3

I would like to type source code comments of the form:

{-                                                                                                                                                                                   
 - Hello World                                                                                                                                                                       
 -                                                                                                                                                                                   
 - This program prints "Hello World".                                                                                                                                                
 -}  

where I would like emacs to automatically insert the leading - for each line. Is there any way to teach emacs to do this?

rityzmon
  • 181
  • 3
  • 1
    This should be put in comment, but I don't have reputation enough :p You may find some insight from this QA: http://emacs.stackexchange.com/questions/14563/how-to-automatically-create-neat-c-comment-blocks-while-typing It describes same functionality for c-mode, so you need to arrange to meet your comment style. – lurdan Jun 21 '16 at 10:15

2 Answers2

2

Emacs has supported various styles of multi-line comments since at least as far back as version 23. :)

The variables of interest are listed below (see their documentation with C-h v). It is up to the major mode to set them to a sensible default, but you can customise them in a mode hook.

  • comment-start - String that begins a comment. For haskell this is usually set to "-- ".
  • comment-end - String that ends a comment. For haskell this is usually set to "", which means comments continue until the end of the line.
  • comment-multi-line - Affects comment indentation when auto-filling.
  • comment-padding - String placed between comment characters and the comment text.
  • comment-style - Determines behaviour and formatting of comment-region.
  • comment-styles - List of available comment-styles along with their description.
  • comment-continue - Leading string for continuation lines of multiline comments.
  • comment-empty-lines - Whether to comment empty lines.

So, to achieve the commenting style in your example you could do something like

(defun my-haskell-comment-setup ()
  "Configure multi-line comments for haskell."
  ;; You may want to use `setq-local' instead.
  (setq comment-start       "{-"
        comment-end         "-}"
        comment-multi-line  t
        comment-padding     nil
        comment-style       'extra-line
        comment-continue    " - "
        comment-empty-lines t))

(add-hook 'haskell-mode-hook #'my-haskell-comment-setup)

The only problem I see with this is that empty lines get commented with a trailing space. You may want to play around with these settings and arrange for delete-trailing-whitespace or similar to run after commenting.

See also command indent-new-comment-line (M-j/C-M-j) for starting a new and indented comment line when point is within a comment, as opposed to when you are commenting a whole region.

Basil
  • 12,019
  • 43
  • 69
  • This doesn't work. I tried [this](https://ptpb.pw/gqGK) and when I press `RET` after a `/*` line, I don't get a `*` line. Did I misunderstand the question and answer? (edit: disregard the typo 'multi'->'mutli'... fixing it doesn't solve the problem) – itdoesntwork Apr 06 '18 at 01:15
  • Thanks, pressing `M-j` instead of `RET` solved my issue. – hraban Jan 26 '21 at 09:38
0

This is only a quick hack, but it works well enough to show you how you might accomplish your goal. Hopefully the code is enough to get you started.

I'm guessing that you're new to Emacs, and I don't recognize the language comment style. So you might start by switching the suffixes in the example code below to the suffixes for the languages that you want the commenting action to work on.

(defvar comment-prefix-start "{- "
  "The start of the comment.")

(defvar comment-prefix-continue " - "
  "The continuation of the comment.")

(defun my-return-key ()
  "Return as usual, and then insert the comment-prefix."
  (interactive)
  (newline)
  (let (curpos (incomment nil))
    (cond 
     ((equal ".el" (substring (buffer-name) -3))
      (save-excursion
        (forward-line -1)
        (goto-char (line-beginning-position))
        (if (or (looking-at comment-prefix-start)
                (looking-at comment-prefix-continue))
            (setq incomment t)))
      (if incomment
          (insert comment-prefix-continue)))

     ;; repeat that block of code for other languages

     )))

(global-set-key (kbd "C-m") 'my-return-key)

;; Test this in the *scratch* buffer by pasting this code.
;; Start a comment the normal way, and
;; including the trailing spaces, if any.
;; Type return to see a new prefix inserted.
;;
;; To stop entering prefixes, backspace to remove a trailing
;; space, so emacs is not "looking-at" a full prefix string.
;;
;; Put this code into your Emacs startup file, or into a 
;; separate file, and load that file, to load it each time.
Kevin
  • 1,308
  • 8
  • 20