unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* New comment-sexp command and key bind
@ 2015-08-21 11:11 Artur Malabarba
  2015-08-21 11:31 ` João Távora
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Artur Malabarba @ 2015-08-21 11:11 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 3307 bytes --]

I'd like to add the following command that comments and uncomments
sexps. I'm attacking a gif to show its behavior, but it is pretty much
the same as our current comment-line, except it acts on sexps.

Furthermore, I'd like to bind it to `C-M-;' since C-M- is a relatively
common modifier for sexp-stuff.

-----
(defun uncomment-sexp (&optional n)
  "Uncomment a sexp around point."
  (interactive "P")
  (let* ((initial-point (point-marker))
         (p)
         (end (save-excursion
                (when (elt (syntax-ppss) 4)
                  (re-search-backward comment-start-skip
                                      (line-beginning-position)
                                      t))
                (setq p (point-marker))
                (comment-forward (point-max))
                (point-marker)))
         (beg (save-excursion
                (forward-line 0)
                (while (= end (save-excursion
                                (comment-forward (point-max))
                                (point)))
                  (forward-line -1))
                (goto-char (line-end-position))
                (re-search-backward comment-start-skip
                                    (line-beginning-position)
                                    t)
                (while (looking-at-p comment-start-skip)
                  (forward-char -1))
                (point-marker))))
    (unless (= beg end)
      (uncomment-region beg end)
      (goto-char p)
      ;; Indentify the "top-level" sexp inside the comment.
      (while (and (ignore-errors (backward-up-list) t)
                  (>= (point) beg))
        (skip-chars-backward (rx (syntax expression-prefix)))
        (setq p (point-marker)))
      ;; Re-comment everything before it.
      (ignore-errors
        (comment-region beg p))
      ;; And everything after it.
      (goto-char p)
      (forward-sexp (or n 1))
      (skip-chars-forward "\r\n[:blank:]")
      (if (< (point) end)
          (ignore-errors
            (comment-region (point) end))
        ;; If this is a closing delimiter, pull it up.
        (goto-char end)
        (skip-chars-forward "\r\n[:blank:]")
        (when (= 5 (car (syntax-after (point))))
          (delete-indentation))))
    ;; Without a prefix, it's more useful to leave point where
    ;; it was.
    (unless n
      (goto-char initial-point))))

(defun comment-sexp--raw ()
  "Comment the sexp at point or ahead of point."
  (pcase (or (bounds-of-thing-at-point 'sexp)
             (save-excursion
               (skip-chars-forward "\r\n[:blank:]")
               (bounds-of-thing-at-point 'sexp)))
    (`(,l . ,r)
     (goto-char r)
     (skip-chars-forward "\r\n[:blank:]")
     (comment-region l r)
     (skip-chars-forward "\r\n[:blank:]"))))

(defun comment-or-uncomment-sexp (&optional n)
  "Comment the sexp at point and move past it.
If already inside (or before) a comment, uncomment instead.
With a prefix argument N, (un)comment that many sexps."
  (interactive "P")
  (if (or (elt (syntax-ppss) 4)
          (< (save-excursion
               (skip-chars-forward "\r\n[:blank:]")
               (point))
             (save-excursion
               (comment-forward 1)
               (point))))
      (uncomment-sexp n)
    (dotimes (_ (or n 1))
      (comment-sexp--raw))))

[-- Attachment #2: comment-or-uncomment-sexp.gif --]
[-- Type: image/gif, Size: 83211 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: New comment-sexp command and key bind
  2015-08-21 11:11 New comment-sexp command and key bind Artur Malabarba
@ 2015-08-21 11:31 ` João Távora
  2015-08-21 12:24   ` Artur Malabarba
  2015-08-21 12:15 ` Andreas Schwab
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 9+ messages in thread
From: João Távora @ 2015-08-21 11:31 UTC (permalink / raw)
  To: Artur Malabarba; +Cc: emacs-devel

This is interesting, I just tried it.

Was it your intention to make the uncommenting behaviour for
consecutive sexps different from the commenting behaviour? The former
keeps point at the beginning of the sexp, while the latter advances
one sexp. I thing they should be uniform.

I would prefer to *not* advance sexps. But I realize that that has the
drawback that it is difficult to advance one recently commented sexp.

For now I'll stick to C-M-SPC M-;

João

On Fri, Aug 21, 2015 at 12:11 PM, Artur Malabarba
<bruce.connor.am@gmail.com> wrote:
> I'd like to add the following command that comments and uncomments
> sexps. I'm attacking a gif to show its behavior, but it is pretty much
> the same as our current comment-line, except it acts on sexps.
>
> Furthermore, I'd like to bind it to `C-M-;' since C-M- is a relatively
> common modifier for sexp-stuff.
>
> -----
> (defun uncomment-sexp (&optional n)
>   "Uncomment a sexp around point."
>   (interactive "P")
>   (let* ((initial-point (point-marker))
>          (p)
>          (end (save-excursion
>                 (when (elt (syntax-ppss) 4)
>                   (re-search-backward comment-start-skip
>                                       (line-beginning-position)
>                                       t))
>                 (setq p (point-marker))
>                 (comment-forward (point-max))
>                 (point-marker)))
>          (beg (save-excursion
>                 (forward-line 0)
>                 (while (= end (save-excursion
>                                 (comment-forward (point-max))
>                                 (point)))
>                   (forward-line -1))
>                 (goto-char (line-end-position))
>                 (re-search-backward comment-start-skip
>                                     (line-beginning-position)
>                                     t)
>                 (while (looking-at-p comment-start-skip)
>                   (forward-char -1))
>                 (point-marker))))
>     (unless (= beg end)
>       (uncomment-region beg end)
>       (goto-char p)
>       ;; Indentify the "top-level" sexp inside the comment.
>       (while (and (ignore-errors (backward-up-list) t)
>                   (>= (point) beg))
>         (skip-chars-backward (rx (syntax expression-prefix)))
>         (setq p (point-marker)))
>       ;; Re-comment everything before it.
>       (ignore-errors
>         (comment-region beg p))
>       ;; And everything after it.
>       (goto-char p)
>       (forward-sexp (or n 1))
>       (skip-chars-forward "\r\n[:blank:]")
>       (if (< (point) end)
>           (ignore-errors
>             (comment-region (point) end))
>         ;; If this is a closing delimiter, pull it up.
>         (goto-char end)
>         (skip-chars-forward "\r\n[:blank:]")
>         (when (= 5 (car (syntax-after (point))))
>           (delete-indentation))))
>     ;; Without a prefix, it's more useful to leave point where
>     ;; it was.
>     (unless n
>       (goto-char initial-point))))
>
> (defun comment-sexp--raw ()
>   "Comment the sexp at point or ahead of point."
>   (pcase (or (bounds-of-thing-at-point 'sexp)
>              (save-excursion
>                (skip-chars-forward "\r\n[:blank:]")
>                (bounds-of-thing-at-point 'sexp)))
>     (`(,l . ,r)
>      (goto-char r)
>      (skip-chars-forward "\r\n[:blank:]")
>      (comment-region l r)
>      (skip-chars-forward "\r\n[:blank:]"))))
>
> (defun comment-or-uncomment-sexp (&optional n)
>   "Comment the sexp at point and move past it.
> If already inside (or before) a comment, uncomment instead.
> With a prefix argument N, (un)comment that many sexps."
>   (interactive "P")
>   (if (or (elt (syntax-ppss) 4)
>           (< (save-excursion
>                (skip-chars-forward "\r\n[:blank:]")
>                (point))
>              (save-excursion
>                (comment-forward 1)
>                (point))))
>       (uncomment-sexp n)
>     (dotimes (_ (or n 1))
>       (comment-sexp--raw))))



-- 
João Távora



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: New comment-sexp command and key bind
  2015-08-21 11:11 New comment-sexp command and key bind Artur Malabarba
  2015-08-21 11:31 ` João Távora
@ 2015-08-21 12:15 ` Andreas Schwab
  2015-08-21 12:50 ` Óscar Fuentes
  2015-08-21 13:31 ` Stefan Monnier
  3 siblings, 0 replies; 9+ messages in thread
From: Andreas Schwab @ 2015-08-21 12:15 UTC (permalink / raw)
  To: Artur Malabarba; +Cc: emacs-devel

Artur Malabarba <bruce.connor.am@gmail.com> writes:

> Furthermore, I'd like to bind it to `C-M-;' since C-M- is a relatively
> common modifier for sexp-stuff.

The downside is that C-; isn't a character, so it won't work on a tty
frame.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: New comment-sexp command and key bind
  2015-08-21 11:31 ` João Távora
@ 2015-08-21 12:24   ` Artur Malabarba
  0 siblings, 0 replies; 9+ messages in thread
From: Artur Malabarba @ 2015-08-21 12:24 UTC (permalink / raw)
  To: João Távora; +Cc: emacs-devel

2015-08-21 12:31 GMT+01:00 João Távora <joaotavora@gmail.com>:
> This is interesting, I just tried it.
>
> Was it your intention to make the uncommenting behaviour for
> consecutive sexps different from the commenting behaviour? The former
> keeps point at the beginning of the sexp, while the latter advances
> one sexp. I thing they should be uniform.

Yes, it was intentional, though I'm still experimenting with the
command so that's up for discussion.

- When uncommenting, it leaves point exactly where it was unless you
provide a prefix argument. With a prefix argument, it uncomments that
many sexps and moves point after them.

- When commenting, we always move point after the commented region
(the prefix argument still specifies a number of sexps to comment).

The only reason for this is that it's what seemed most useful to me. I
never want point to be inside a sexp I just commented out (what could
I possibly want to do with it?). OTOH, when I UNcomment something, I
sometimes want to edit it afterwards (sometimes I don't, like I said,
up for discussion).

> I would prefer to *not* advance sexps. But I realize that that has the
> drawback that it is difficult to advance one recently commented sexp.

I really like advancing when commenting.
It lets me comment a series of sexps by just holding down C-M- and
then repeatedly hitting ; (of course, I can use the prefix arg for
this, but sometimes I'm deciding which sexps to comment on the fly).
Like you mention, it's also hard to manually forward-sexp after having
commented it.



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: New comment-sexp command and key bind
  2015-08-21 11:11 New comment-sexp command and key bind Artur Malabarba
  2015-08-21 11:31 ` João Távora
  2015-08-21 12:15 ` Andreas Schwab
@ 2015-08-21 12:50 ` Óscar Fuentes
  2015-08-21 13:44   ` Artur Malabarba
  2015-08-21 13:31 ` Stefan Monnier
  3 siblings, 1 reply; 9+ messages in thread
From: Óscar Fuentes @ 2015-08-21 12:50 UTC (permalink / raw)
  To: emacs-devel

Artur Malabarba <bruce.connor.am@gmail.com> writes:

> I'd like to add the following command that comments and uncomments
> sexps. I'm attacking a gif to show its behavior, but it is pretty much
> the same as our current comment-line, except it acts on sexps.

Cool.

Some quick testing shows a problem with a common pattern of mine. See:

(if something
    foo
  blah)

Now comment the sexp and then uncomment the second line:

;; (if something
     foo
;;   bar)

Go to the first line and M-x comment-or-uncomment-sexp :

(if something
     foo
;;   bar)

And the minibuffer shows:

forward-sexp: Scan error: "Unbalanced parentheses", 3189, 3221

This is with emacs -Q, GNU Emacs 25.0.50.1 (x86_64-unknown-linux-gnu, X
toolkit)





^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: New comment-sexp command and key bind
  2015-08-21 11:11 New comment-sexp command and key bind Artur Malabarba
                   ` (2 preceding siblings ...)
  2015-08-21 12:50 ` Óscar Fuentes
@ 2015-08-21 13:31 ` Stefan Monnier
  2015-08-21 14:21   ` Artur Malabarba
  3 siblings, 1 reply; 9+ messages in thread
From: Stefan Monnier @ 2015-08-21 13:31 UTC (permalink / raw)
  To: Artur Malabarba; +Cc: emacs-devel

> (defun uncomment-sexp (&optional n)

Clearly, this is the more important part, since C-M-SPC M-; does the
trick for the commenting part.

I think I like part of the idea, but being limited to uncommenting is
rather frustrating.  It's reasonably frequent to want to
navigate/manipulate a sexp that spans several comments, and uncommenting
it is not even the most common operation for me.

So I'd be more interested in a way to make C-M-SPC, C-M-f and friends
deal "correctly" with such "sexps that span several comments".


        Stefan



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: New comment-sexp command and key bind
  2015-08-21 12:50 ` Óscar Fuentes
@ 2015-08-21 13:44   ` Artur Malabarba
  0 siblings, 0 replies; 9+ messages in thread
From: Artur Malabarba @ 2015-08-21 13:44 UTC (permalink / raw)
  To: Óscar Fuentes; +Cc: emacs-devel

> Go to the first line and M-x comment-or-uncomment-sexp :
>
> ;; (if something
>      foo
> ;;   bar)
>
> And the minibuffer shows:
>
> forward-sexp: Scan error: "Unbalanced parentheses", 3189, 3221

Yes, the command can't uncomment that because that's not a commented
sexp. It's like calling `mark-sexp' with half the sexp commented out.
I make it a better error message, though.



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: New comment-sexp command and key bind
  2015-08-21 13:31 ` Stefan Monnier
@ 2015-08-21 14:21   ` Artur Malabarba
  2015-08-21 15:16     ` Óscar Fuentes
  0 siblings, 1 reply; 9+ messages in thread
From: Artur Malabarba @ 2015-08-21 14:21 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

2015-08-21 14:31 GMT+01:00 Stefan Monnier <monnier@iro.umontreal.ca>:
>> (defun uncomment-sexp (&optional n)
>
> Clearly, this is the more important part, since C-M-SPC M-; does the
> trick for the commenting part.
>
> I think I like part of the idea, but being limited to uncommenting is
> rather frustrating.

Just to be clear. It's fine if the commented has multiple line even
with empty lines in the middle. The only problem is if there's
uncommented code in between some of the commented lines. In that case
I'm unsure what the sane behavior would even be.

> It's reasonably frequent to want to
> navigate/manipulate a sexp that spans several comments, and uncommenting
> it is not even the most common operation for me.
>
> So I'd be more interested in a way to make C-M-SPC, C-M-f and friends
> deal "correctly" with such "sexps that span several comments".

I think I've heard that smartparens does that. That is, if point is
inside a comment it deals with commented sexps as if they were
uncommented for all intents and purposes. But don't quote me on that.
=P



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: New comment-sexp command and key bind
  2015-08-21 14:21   ` Artur Malabarba
@ 2015-08-21 15:16     ` Óscar Fuentes
  0 siblings, 0 replies; 9+ messages in thread
From: Óscar Fuentes @ 2015-08-21 15:16 UTC (permalink / raw)
  To: emacs-devel

Artur Malabarba <bruce.connor.am@gmail.com> writes:

> Just to be clear. It's fine if the commented has multiple line even
> with empty lines in the middle. The only problem is if there's
> uncommented code in between some of the commented lines. In that case
> I'm unsure what the sane behavior would even be.

Keep uncommenting until the parens are balanced?




^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2015-08-21 15:16 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-08-21 11:11 New comment-sexp command and key bind Artur Malabarba
2015-08-21 11:31 ` João Távora
2015-08-21 12:24   ` Artur Malabarba
2015-08-21 12:15 ` Andreas Schwab
2015-08-21 12:50 ` Óscar Fuentes
2015-08-21 13:44   ` Artur Malabarba
2015-08-21 13:31 ` Stefan Monnier
2015-08-21 14:21   ` Artur Malabarba
2015-08-21 15:16     ` Óscar Fuentes

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).