rust-lang / rust-mode

Emacs configuration for Rust
Apache License 2.0
1.1k stars 178 forks source link

Add the possibility to bind keys to functions for doc comments #385

Open mattiasdrp opened 4 years ago

mattiasdrp commented 4 years ago

As of now using comment-line or comment-dwim will always open a comment with //.

I needed some doc comments (/// or //!) so I implemented mine (inspired by http://ergoemacs.org/emacs/elisp_comment_command.html, thanks a lot!) hoping it would help:

(defun rust-doc-comment-dwim (c)
  "Comment or uncomment the current line or text selection."
  (interactive)

  ;; If there's no text selection, comment or uncomment the line
  ;; depending whether the WHOLE line is a comment. If there is a text
  ;; selection, using the first line to determine whether to
  ;; comment/uncomment.
  (let (p1 p2)
    (if (use-region-p)
        (save-excursion
          (setq p1 (region-beginning) p2 (region-end))
          (goto-char p1)
          (if (wholeLineIsCmt-p c)
              (my-uncomment-region p1 p2 c)
            (my-comment-region p1 p2 c)
            ))
      (progn
        (if (wholeLineIsCmt-p c)
            (my-uncomment-current-line c)
          (my-comment-current-line c)
          )) )))

(defun wholeLineIsCmt-p (c)
  (save-excursion
    (beginning-of-line 1)
    (looking-at (concat "[ \t]*//" c))
    ))

(defun my-comment-current-line (c)
  (interactive)
  (beginning-of-line 1)
  (insert (concat "//" c))
  )

(defun my-uncomment-current-line (c)
  "Remove “//c” (if any) in the beginning of current line."
  (interactive)
  (when (wholeLineIsCmt-p c)
    (beginning-of-line 1)
    (search-forward (concat "//" c))
    (delete-backward-char 3)
    ))

(defun my-comment-region (p1 p2 c)
  "Add “//c” to the beginning of each line of selected text."
  (interactive "r")
  (let ((deactivate-mark nil))
    (save-excursion
      (goto-char p2)
      (while (>= (point) p1)
        (my-comment-current-line c)
        (previous-line)
        ))))

(defun my-uncomment-region (p1 p2 c)
  "Remove “//c” (if any) in the beginning of each line of selected text."
  (interactive "r")
  (let ((deactivate-mark nil))
    (save-excursion
      (goto-char p2)
      (while (>= (point) p1)
        (my-uncomment-current-line c)
        (previous-line) )) ))

(use-package rust-mode
  :mode "\\.rs'"
  :bind ("C-M-;" . rust-doc-comment-dwim-following)
  :bind ("C-M-," . rust-doc-comment-dwim-enclosing)
  (defun rust-doc-comment-dwim-following ()
    (interactive)
    (rust-doc-comment-dwim "/"))
  (defun rust-doc-comment-dwim-enclosing ()
    (interactive)
    (rust-doc-comment-dwim "!"))
  )

Which allows to comment as /// when pressing Ctrl-Alt-; and //! when pressing Ctrl-Alt-,

It would actually be better to have these two functions available in the mode to bind them to some keys but I'm actually really bad at writing Lisp to do it

mookid commented 4 years ago

I think that the proper way to do something like this would be customizing comment-start. See newcomment.el for more information about that.

However, I don't have a reference for similar features of major modes concerning doc comments, so I am unlikely to work on that myself. I unually just do the markup myself by hand when needed (like one does for doxygen-style comment.

Concerning existing integration, notice that default-indent-new-line allows you to keep markup from line to line, so all you need to do is to choose the markup for the first doc line.

mattiasdrp commented 4 years ago

I think that the proper way to do something like this would be customizing comment-start. See newcomment.el for more information about that.

Problem with comment-start is that modifying it would change the behaviour of comment-dwim, from what I understood, no?

Concerning existing integration, notice that default-indent-new-line allows you to keep markup from line to line, so all you need to do is to choose the markup for the first doc line.

Ah, thanks for the default-indent-new-line, will definitely use it :-)