Search code examples
emacsindentationmakofont-lockcc-mode

Custom C preprocessor format in Emacs cc-mode


I'm generating a C source file from a Mako template. Mako templates have directives similar to C preprocessor directives, except that they start with % instead of #. For example:

%if some_condition:
   /* Condition is true */
%else:
   /* Condition is false */
%endif

When editing the template source, those directives play havoc with cc-mode's font locking and automatic indentation.

Is there a way to tell cc-mode that it should handle lines that start with a % in the same way as preprocessor lines (that start with a #)?


Solution

  • There is probably a simpler way, but since cc-mode prepares the fontification stuff at compile time, I'm not sure how you would get the fontification without declaring a derived cc-mode (without simply adding them all via font-lock-add-keywords).

    The indentation could be modified alone by just setting the c-opt-* variables below in your c-mode-hook, I believe, and not bothering with the rest. But, here is an example derived mode that will fontify your preprocessor statements and provide the proper indentation (hopefully), after calling mako-mode from your buffer.

    (eval-when-compile
      (require 'cc-langs)
      (require 'cc-fonts))
    (require 'cc-mode)
    
    ;;; create inherited mako-mode from c-mode
    (eval-and-compile (c-add-language 'mako-mode 'c-mode))
    
    ;;; variables to control font-locking preprocessor stuff
    (c-lang-defconst c-cpp-expr-intro-re mako
                     (concat "\\s *%\\s*" (regexp-opt '("if" "else" "endif")) ":?"))
    (c-lang-defconst c-opt-cpp-prefix mako "\\s *%")
    (c-lang-defconst c-opt-cpp-symbol mako "%")
    (c-lang-defconst c-opt-cpp-start mako "\\s *%\\s *\\([[:alnum:]:]+\\)")
    
    (defconst mako-font-lock-keywords-1 (c-lang-const c-matchers-1 mako))
    (defconst mako-font-lock-keywords-2 (c-lang-const c-matchers-2 mako))
    (defconst mako-font-lock-keywords-3 (c-lang-const c-matchers-3 mako))
    (defvar mako-font-lock-keywords (c-lang-const c-matchers-3 mako))
    (defun mako-font-lock-keywords ()
      (c-compose-keywords-list mako-font-lock-keywords))
    
    (defvar mako-mode-syntax-table nil)
    (define-derived-mode mako-mode prog-mode "Mako"
      :after-hook (c-update-modeline)
      :syntax-table c-mode-syntax-table
    
      ;; initialize cc-mode stuff
      (c-initialize-cc-mode t)
      (c-init-language-vars mako-mode)
      (c-common-init 'mako-mode))