Fuco1 / smartparens

Minor mode for Emacs that deals with parens pairs and tries to be smart about it.
GNU General Public License v3.0
1.81k stars 193 forks source link

How to comment out sexps and stay balanced? #942

Open TLINDEN opened 5 years ago

TLINDEN commented 5 years ago

Expected behavior

With paredit I could enter a ; in front of a sexp which then commented out the whole sexp not just the line, it even inserted newlines if needed to keep parantheses balanced.

Example (Cursor is |):

|(defun blah()
   (message "blah"))

After entering ;

;|(defun blah()
;   (message "blah"))

Actual behavior

I get this after entering ;

;|(defun blah()
   (message "blah"))

Now I have unbalanced parentheses in my code.

Steps to reproduce the problem

Pretty default config, strict mode disabled.

Environment & version information

Update

I tried to revert my config to a pre-smartparens version but I am still unable to reproduce the old behavoir. So it might be that this was no paredit feature but something else I had enabled previously and lost when switching to smartparens. However, I would love it, if there were a feature like this in smartparens.

TLINDEN commented 5 years ago

I wrote a little function which demonstrates it:

(defun tvd-lisp-comment ()
  (interactive)
  (if (not (looking-at "\("))
      (self-insert-command 1)
    (let ((beg (point)))
      (forward-list 1)
      (when (looking-at "\(")
        (insert "\n"))
      (comment-region beg (point))
      (indent-for-tab-command)
      (goto-char beg))))

(define-key smartparens-mode-map (kbd ";") 'tvd-lisp-comment)
Fuco1 commented 5 years ago

There is sp-comment, but it behaves a little bit differently. You can try it out and see if it works for you

I think the paredit behaviour might make a bit more sense, but it is what it is. What I use is I select the sexp and then I call comment-dwim.

We can add a variant that behaves closer than paredit.

TLINDEN commented 5 years ago

Hm, sp-comment doesn't do this, it only seems to insert a ; wherever I am.

The other way you described seems to work very good but it requires the additional step of marking and hitting M-;.

andreyorst commented 3 years ago

I think that it is safe to map ; to sp-comment in all Lisp related modes in default Smartparens config. Paredit does this, and I think most users actually expect it to work this way as well. And it seems that sp-comment works the same as paredit-semicolon in all cases defined in Paredit documentation:

|(frob grovel)
  ->
;|(frob grovel)

(frob |grovel)
  ->
(frob ;|grovel
 )

(frob |grovel (bloit
               zargh))
  ->
(frob ;|grovel
 (bloit
  zargh))

(frob grovel)          |
  ->
(frob grovel)          ;|
Fuco1 commented 3 years ago

Personally I'm not a huge fan, I never got used to it. The function only exists because some users asked for it as we didn't aim to emulate paredit completely from the start and the default settings are somewhat more "mainstream".

So I'm not sure if making this default after 8+ years is a good idea :blush:.

andreyorst commented 3 years ago

Hmm, maybe there's a way of doing this for all lisp modes and other related modes, like REPL modes without breaking Smartparens?

Currently I bind this key in smartparens-strict-mode-map because I only use strict mode in Lisp related modes, including: clojure-mode, emacs-lisp-mode, common-lisp-mode, scheme-mode, lisp-mode, racket-mode, fennel-mode, cider-repl-mode, racket-repl-mode, and geiser-repl-mode. Not all of these modes have a *-mode-map, so I'm unsure how would I approach such thing without binding strict mode map, which makes it impossible for me to use strict mode in non Lisp modes, and as a consequence in lisps that use something other then a semicolon as a comment char (although I've never seen one).

Fuco1 commented 3 years ago

Well, it's the same issue. You can bind to a minor mode map but not based on a major mode. So even if we bind ; to sp-comment in smartparens-mode-map it will affect also c-mode which we definitely don't want.

As you mention with the strict mode map, it's the same issue.

Paredit was from the start ment only for lisp and so they just went ahead and did it. But we can't.

What we can do is create another minor mode, something like smartparens-lisp-minor-mode where we would bind some additional keys and enable it for the list of lisp modes (either as a global minor mode or each user can do it themselves by iterating over that variable).