3

It is possible and relatively easy to create a new major mode, deriving from c-mode, and just add two dashes '--' to work as comments too? I have checked many resources, but couldn't find anything similar. I tried some approaches, but I'm pretty novice with emacs-lisp programming, and c-mode seemed overwhelming for my knowledge.

Any hints will be appreciated.

3 Answers 3

3

I asked this question in Xah Lee emacs blog entry, and he gave me these suggestions:

i think it can be done, without much trouble. Read the elisp chapter on syntax table. basically, add the -- to the syntax table as comment. Note: syntax table is hard to work with, especially when specifying comment chars. Also, by default it only supports a few. I'm not sure you can have -- // /* */ all together. See my tutorial about comment linked on this page. But, if it can be done, then that's all you need to do. But if it cannot be done, you can still do so by trying to add the syntax for comment as text properties. (you'll need to learn about text properties)

I went through the elisp syntax table chapter, that I found pretty hard to grasp, and through Xah Lee comments tutorial and tried these lines, just like his lines for regular // c++ style comment.

    (define-derived-mode my-mode c-mode
      "my mode"
      (modify-syntax-entry ?- ". 12b" c-mode-syntax-table)
      (modify-syntax-entry ?\n "> b" c-mode-syntax-table)
      )
    (provide 'my-mode)

It seems that this was enough for what I needed.

2
  • 2
    Note that you are actually changing the the syntax table for c-mode as well.
    – nispio
    Jun 8, 2016 at 22:02
  • Note too that my-mode “has its own syntax table” predefined as my-mode-syntax-table. Therefore you could simply replace c-mode-syntax-table with my-mode-syntax-table in your code, and that way avoid changing c-mode’s syntax (@nispio), which might have unwanted effects. Jul 7, 2019 at 11:29
1

In order for your derived mode to not modify the c-mode syntax table directly, you should define your own syntax table which is based on the c-mode syntax table. Also, it is often helpful to modify the comment-start and comment-end variables to match the preferred comment style for the mode:

(require 'cc-langs)

(defvar c-like-syntax-table
  (let ((table (make-syntax-table)))
    (c-populate-syntax-table table)
    (modify-syntax-entry ?- ". 12b" table)
    table)
  "The syntax table for my mode called `c-like-mode'")

(define-derived-mode c-like-mode c-mode "C-Like"
  "Major mode that is like `c-mode' but with \"--\" as a comment"
  :syntax-table c-like-syntax-table
  (setq comment-start "-- ")
  (setq comment-end ""))

(provide 'c-like-mode)

It is worth noting that, given this syntax table, comments that start with -- are of the same comment style as comments that start with //. A side effect of this is that any combination of those characters will result in a comment. In other words, //, --, /-, and -/ will all mark the beginning of a comment.

1

To expand on the answers above, this link explains why we need to add ". 12b". In summary, . means that your symbol is punctuation (note that if you instead put < the character becomes a single comment delimiter), whereas the integer flags act as follows (copied from the link):

The flags for a character c are:

`1' means c is the start of a two-character comment start sequence.
`2' means c is the second character of such a sequence.
`3' means c is the start of a two-character comment end sequence.
`4' means c is the second character of such a sequence.
`b' means that c as a comment delimiter belongs to the alternative "b" comment style. 
    Emacs supports two comment styles simultaneously in any one syntax table. This is 
    for the sake of C++. Each style of comment syntax has its own comment-start sequence 
    and its own comment-end sequence. Each comment must stick to one style or the other; 
    thus, if it starts with the comment-start sequence of style "b", it must also end 
    with the comment-end sequence of style "b". The two comment-start sequences must begin 
    with the same character; only the second character may differ. Mark the second
    character of the "b"-style comment start sequence with the `b' flag. A comment-end 
    sequence (one or two characters) applies to the "b" style if its first character has
    the `b' flag set; otherwise, it applies to the "a" style. The appropriate comment 
    syntax settings for C++ are as follows:

`/'  `124b' 
`*'  `23' 
`\n' `>b' 

Thus `/*' is a comment-start sequence for "a" style, `//' is a comment-start 
sequence for "b" style, `*/' is a comment-end sequence for "a" style, and newline is
a comment-end sequence for "b" style.
`p' identifies an additional "prefix character" for Lisp syntax. These characters are 
treated as whitespace when they appear between expressions. When they appear within an 
expression, they are handled according to their usual syntax codes. The function 
backward-prefix-chars moves back over these characters, as well as over characters whose
primary syntax class is prefix (`'').

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.