How can I do multiline / block comments in Lisp code - e.g. in the init.el.

In Python I would do it like this


In C/C++ like this


The use case is to out-comment some code blocks for debugging and error diagnosis.

  • Emacs Lisp has no multi-line comments, but Common Lisp does.
    – sds
    Nov 7, 2021 at 10:45

4 Answers 4


Emacs Lisp doesn't have multiline comments. Neither does Python, for that matter. """…""" in Python delimit a multiline string. Emacs has multiline string literals, but they're delimited simply by "…", so you can't use them to make a block of code inert if that block contains ordinary string literals.

You can just select the block and use M-; or M-x comment-region. This will comment out all the selected lines.

Assuming what you want to comment out is a syntactically correct block of code with balanced parentheses, you can put (when nil before it and ) after it, or even shorter, [ before and ] after. (when nil …) doesn't execute any of the code in and evaluates to nil. '(…) doesn't evaluate any of the code in and evaluates to a list object. […] doesn't evaluate any of the code in and evaluates to a vector object. This doesn't require any change to intermediate lines, and nests. This is similar to using #if 0#endif in C or C++, although the requirement on having a syntactically well-formed block is higher since this Emacs Lisp equivalent requires the parentheses in the block to be balanced.

  • M-; is it! Great! Is there an opposite of comment-region? Can't find one with my way to search the docs.
    – buhtz
    Nov 8, 2021 at 8:23
  • 3
    @buhtz uncomment-region is the opposite of comment-region. M-; uncomments if the region is fully commented out, so a second M-; will undo the previous one. Nov 8, 2021 at 9:47
  • And here I was writing out my own (defmacro greater-comment (&rest _)) like a newb, haha.
    – mtraceur
    Apr 13 at 2:31

There is no syntax for multi-line comments (AFAIK). Just select the target code blocks and do comment-dwim which will comment/uncomment each line.

  • 1
    I'd add that comment-dwim is bound to M-; by default. Nov 7, 2021 at 10:17

First, yes, it's true that Emacs Lisp does not have a real block-comment syntax. This is different from Common Lisp, which has #| ... |#.

That said, you can use ;-style comments to get much of the effect of #|...|# commenting, if not quite the same flexibility or appearance.

My answer is to use comment-region, not comment-dwim. IMO, the former is much more useful when you want to, for example, nest blocks of comments and, in particular, unnest a given level of nesting. I use comment-dwim (M-;) only for single-semicolon comments after a line of code.

For comment-region:

  • A plain C-u unnests a full level of comments, for the region.

  • A negative prefix arg removes that many comment chars. E.g., M- - 2 removes two ; chars.

However, I actually prefer the following, comment-region-lines from library misc-cmds.el, because I typically want to comment/uncomment full lines as a block comment. I bind it to C-x C-;.

(defun comment-region-lines (beg end &optional arg)
  "Like `comment-region' (which see), but comment or uncomment whole lines."
  (interactive "*r\nP")
  (when (> beg end) (setq beg  (prog1 end (setq end  beg))))
  (let ((bol  (save-excursion (goto-char beg) (line-beginning-position)))
        (eol  (save-excursion (goto-char end) (if (bolp) (point) (line-end-position)))))
    (comment-region bol eol arg)))

Here's the doc string of comment-region, which the doc of comment-region-lines refers to:

comment-region is an interactive compiled Lisp function in newcomment.el.

(comment-region BEG END &optional ARG)

Comment or uncomment each line in the region.

With just C-u prefix arg, uncomment each line in region BEG .. END.

Numeric prefix ARG means use ARG comment characters. If ARG is negative, delete that many comment characters instead.

The strings used as comment starts are built from comment-start and comment-padding; the strings used as comment ends are built from comment-end and comment-padding.

By default, the comment-start markers are inserted at the current indentation of the region, and comments are terminated on each line (even for syntaxes in which newline does not end the comment and blank lines do not get comments). This can be changed with comment-style.


If you mean commenting for functions/variables docs, then let's look at this example, taken at random:

(defun centaur-tabs-current-tabset (&optional update)
  "Return the tab set currently displayed on the tab bar.
If optional argument UPDATE is non-nil, call the user defined function
`centaur-tabs-current-tabset-function' to obtain it.  Otherwise return the
current cached copy."
  (and update centaur-tabs-current-tabset-function
       (setq centaur-tabs-current-tabset
         (funcall centaur-tabs-current-tabset-function)))

It is self-explaining: start with " and when finished close also with ".

  • 1
    That is the "documentation string" of the function or variable. It is not a comment as the language defines comments (anything from a semicolon to the end of the line).
    – NickD
    Nov 7, 2021 at 17:14

Your Answer

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

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