How do I comment on Emacs Lisp?

2022-07-10 Sun 00:00

The only way I knew how to comment code in Emacs Lisp (elisp) was to insert ; before the code I wanted to comment. This worked but the indentations for the commented sections were all over the place. I knew I was doing something wrong. So I searched up how to comment the right way, the Emacser way.

The proper way to comment

There are three types of comments.

  • ; comments on the same line with code
  • ;; comments that are not on the same line with code
  • ;;; Comment used as headlines in Outline minor mode

This is the complete example of using all types of comments.

;;; My heading
;; A function that greets people
(defun greet (&optional name) 
  "My function"
  (message
   (concat "Hello "
           (if name ; check if nil
               name
             "World"))))

(greet)
;; This prints Hello World

(greet "Gene")
;; This prints Hello Gene

The ; comment

This type of comment is for commenting stuff on the same line with some code. I'll probably use it to describe what the code is doing.

When used in a line where there are code, the comment stays where you put them after reformatting the code. When I use them in a line where there are no code, the comment goes all the way to the right when I reformat the code.

(defun greet (&optional name)
  "My function"
  (message
                                        ; Wrong comment usage
   (concat "Hello "
           (if name ; check if nil
               name ; Print "Hello [name]"
             "World")))) ; Print "Hello World"

                                        ; Wrong comment usage

The ;; comment

This comment keeps the same indentations as with the code. When the indentation of the comment is not the same as the code, reformatting the code indents it the same way as the code. This makes it easy to have clean comments even when the code changes. It can also be used inline with code, like the ; comment. Now I'm confused to why the ; comment exists, because I can replace all the ; comments with ;; and there will be no readability issues. I guess typing one character is better than typing two characters.

;; A function that greets people
(defun greet (&optional name) 
  "My function"
  (message
   (concat "Hello "
           (if name ;; check if nil
               name
             "World"))))

(greet)
;; This prints Hello World

(greet "Gene")
;; This prints Hello Gene

The ;;; comment

This is a special comment that is used by the Outline minor mode. I am not that familiar with the mode, but the comment works kind of like a headline in org mode. In the outline minor mode, I think you can fold the code at the ;;; comment.

Finding an easier way to comment

Whenever I code with something thats not lisp, I usually comment and uncomment with the ⌘/ shortcut. I wanted something similar to this when editing lisp, not typing ;; every time I want to comment.

The comment-line command

This command was pretty simple and useful. Although commenting part of the lisp code was still a chore. In the example below, the (greet) is commented out nicely, but the concat part was commented out disregarding the lisp syntax and now its missing a closing parenthesis. My editor is highlighting the syntax error and making me very uncomfortable.

Before commenting

(defun greet (&optional name) 
  "My function"
  (message
   (concat "Hello "
           (if name 
               name
             "World"))))

(greet)

After commenting

(defun greet (&optional name) 
  "My function"
  (message
   ;; (concat "Hello "
   ;;         (if name
   ;;             name
   ;;           "World"))))

;; (greet)

You can also uncomment using the same comment-line command, when the line is already commented.

The comment-or-uncomment-region command

This command only comments region you highlighted. This can be useful when commenting a section in a lisp code. Using this command, I can now highlight the concat function from the starting parenthesis to the closing parenthesis and run comment-or-uncomment-region. I use vim, so just typing vab highlights everything inside the parenthesis for me :D. You can see below that it extracts the part to comment nicely and adjusts the other parts.

Before commenting

(defun greet (&optional name) 
  "My function"
  (message
   (concat "Hello "
           (if name 
               name
             "World"))))

(greet)

After commenting

(defun greet (&optional name) 
  "My function"
  (message
   ;; (concat "Hello "
   ;;         (if name 
   ;;             name
   ;;           "World"))
   ))

(greet)

As indicated by the command name, you can also uncomment with comment-or-uncomment-region by highlighting lines that are already commented.

Setting up shortcuts

I want to be able to comment with the usual ⌘/ shortcut. I also want to use the comment-line when in normal mode (Vim), and comment-or-uncomment-region when in visual mode (Vim). I'm using Evil Mode, so the key binding only works with Evil mode installed.

;; Key binding in normal, or insert mode
(general-nimap emacs-lisp-mode-map
  "s-/" 'comment-line)

;; Key binding in visual mode
(general-vmap emacs-lisp-mode-map
  "s-/" 'comment-or-uncomment-region)

I tried it out, and it works as intended! Now my elisp life is much more comfortable :D

2022-07-12_22-03-10_Kapture.gif

References

I got all the information from these two pages in the elisp manual. You can check it out if you want further details.

https://www.gnu.org/software/emacs/manual/html_node/elisp/Comment-Tips.html
https://www.gnu.org/software/emacs/manual/html_node/elisp/Comments.html