Kind Stranger
Kind Stranger

Reputation: 1761

Different comment-start for end of line comments for custom major-mode

When I type M-;, this invokes comment-dwim which, on a line containing text and with no active region, I believe ultimately invokes comment-indent to add an in-line or end-of-line comment.

In this custom major-mode, comment-start is set to "# " (and comment-style is 'plain) but this should only apply at the very start of a line. How do I get an in-line comment to start with ";; "?

Example of current behaviour:

# Whole line comment
SOME CODE HERE # in-line comment

Example of required behaviour:

# Whole line comment
SOME CODE HERE ;; in-line comment

Additionally, comment-region works perfectly when region starts at the beginning of a line and comment-start is always left-aligned for this. However, halfway through a line, it will begin the comment with comment-start (#).

Upvotes: 0

Views: 589

Answers (2)

Kind Stranger
Kind Stranger

Reputation: 1761

I've managed to write a solution to this:

I noted that comment-indent-function is a variable which holds (from emacs describe-variable):

Function to compute desired indentation for a comment. This function is called with no args with point at the beginning of the comment's starting delimiter and should return either the desired column indentation or nil. If nil is returned, indentation is delegated to `indent-according-to-mode'.

This allows creation of a custom function which can replace comment-start and return nil to allow default indentation, noting that when this function is called, point will be "at the beginning of the comment's starting delimiter" (i.e. at the beginning of comment-start). The following is now included in my custom major mode comment-indent (through comment-dwim) now behaves as required:

;;
(defun my-major-mode ()
  (interactive)
  (kill-all-local-variables)
  ...
  (make-local-variable 'comment-start)
  (make-local-variable 'comment-indent-function)
  (make-local-variable 'comment-indent-start)
  ...
  (setq major-mode 'my-major-mode
    ...
    comment-start "# "
    comment-indent-function 'my-comment-indent
    comment-indent-start ";; "
    )
  ...
)

(defun my-comment-indent ()
  "Replace indented '#' with ';;'"
  (interactive)
  (if (not (looking-back ".\\{1\\}")) ;; if comment is left aligned
      0                               ;; leave it left aligned (return 0)
    (progn                        ;; else: don't return until we're ready
      (looking-at comment-start)            ;; find "#"
      (replace-match comment-indent-start)) ;; replace with ";;"
      nil)))                      ;; return `nil' for default indentation

Upvotes: 0

Alex Ott
Alex Ott

Reputation: 87269

You may need to make custom syntax table as described at Emacs Wiki and ErgoEmacs:

For example, for my cql-mode I use following to distinguish between /* .. */ for block comments, and -- or // for single-line/end-of line comments.

(defvar cql-mode-syntax-table
  (let ((st (make-syntax-table)))
    (modify-syntax-entry ?/ ". 124b" st)
    (modify-syntax-entry ?* ". 23" st)
    ;; double-dash starts comments
    (modify-syntax-entry ?- ". 12b" st)
    ;; newline and formfeed end comments
    (modify-syntax-entry ?\n "> b" st)
    (modify-syntax-entry ?\f "> b" st)
    st)
  "Syntax table for CQL mode")

and in declaration of derived mode I specify:

(set-syntax-table cql-mode-syntax-table)

And meaning is described in documentation for function modify-syntax-entry: for / - 1 means that character can start comment, 2 means that it could be also 2nd character in sequence, 4 - that it finishes comment, b is that it could be comment type b. for * it says that it could be second or second to last character of comment type a (default type).

Similarly, for - it declares that it could be first & second characters in comment type b.

In your case it could look following way (not tested):

(defvar some-mode-syntax-table
  (let ((st (make-syntax-table)))
    (modify-syntax-entry ?# ". 1b" st)
    ;; double-; starts comments
    (modify-syntax-entry ?; ". 12b" st)
    ;; newline and formfeed end comments
    (modify-syntax-entry ?\n "> b" st)
    (modify-syntax-entry ?\f "> b" st)
    st)
  "Syntax table for some mode")

Upvotes: 1

Related Questions