* paren-close-dwim: elisp function of a newbie; feedback welcome
@ 2013-09-25 11:46 Florian
2013-09-25 12:18 ` Andreas Röhler
2013-09-25 17:32 ` Davis Herring
0 siblings, 2 replies; 11+ messages in thread
From: Florian @ 2013-09-25 11:46 UTC (permalink / raw)
To: emacs-devel
Hi,
here is my first elisp function 'paren-close-dwim' and I would be glad
to get some feedback on it (whether its done to complicated, in an
unusual way, or whether this functionality is already available in
some emacs extension which I have not found).
The function allows to close braces/brackets/paranthesis without the
user to care which kind of brace actually has to be closed next. For
me this is much handier than using paren-mode or auto-pair etc,
especially when modifying existing code. Automatic paren modes came in
the way and did the wrong thing from time to time for me and I had to
delete automatically inserted closing paranthesis which was hindering
my workflow. So, to be honest, I were not able to master them
appropriately enough with my muscle memory.
I work with a German keyboard layout where braces are not that easily
reachable as on the Englisch layout, but I want to stick with this and
just want to avoid some uncomfortable key-strokes for closing braces.
So, here is my function paren-close-dwim, which you can freely pick
and use for your own configuration. Maybe it is a bit
'over-commented', which only represents my still lacking elisp
fluency.
(defun paren-close-dwim ()
"Insert the next missing closing paranthesis based on the syntax table.
Otherwise insert a normal closing ?\)"
(interactive)
(save-excursion
(setq fallback-char ?\))
;; go backward up a level in the parenthesis hierarchy (which
;; jumps to the next not yet closed (seen from point) open
;; parenthesis). Catch unbalanced paranthesis error etc.
(setq closing-paren
(condition-case nil
(progn (backward-up-list)
;; get character at point
(setq open-paren (point))
;; get corresponding closing character from the
;; syntax table. (syntax-after open-paren)
;; delivers a cons cell with (OPEN . CLOSE), so
;; we need the cdr to match open-paren.
(setq syntax-cons (syntax-after open-paren))
(if (cdr syntax-cons)
(cdr syntax-cons)
;; if cdr is nil use the fallback-char
fallback-char))
(error fallback-char))))
;; insert dwim parenthesis
(insert closing-paren))
;; I bind this to the normal closing paranthesis key and am quite happy
;; with its behaviour in several different modes since a few weeks now.
(global-set-key (kbd ")") 'paren-close-dwim)
Thanks for your feedback,
Florian
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: paren-close-dwim: elisp function of a newbie; feedback welcome
2013-09-25 11:46 paren-close-dwim: elisp function of a newbie; feedback welcome Florian
@ 2013-09-25 12:18 ` Andreas Röhler
2013-09-25 17:32 ` Davis Herring
1 sibling, 0 replies; 11+ messages in thread
From: Andreas Röhler @ 2013-09-25 12:18 UTC (permalink / raw)
To: emacs-devel
Am 25.09.2013 13:46, schrieb Florian:
> Hi,
>
> here is my first elisp function 'paren-close-dwim' and I would be glad
> to get some feedback on it (whether its done to complicated, in an
> unusual way, or whether this functionality is already available in
> some emacs extension which I have not found).
>
> The function allows to close braces/brackets/paranthesis without the
> user to care which kind of brace actually has to be closed next. For
> me this is much handier than using paren-mode or auto-pair etc,
> especially when modifying existing code. Automatic paren modes came in
> the way and did the wrong thing from time to time for me and I had to
> delete automatically inserted closing paranthesis which was hindering
> my workflow. So, to be honest, I were not able to master them
> appropriately enough with my muscle memory.
>
> I work with a German keyboard layout where braces are not that easily
> reachable as on the Englisch layout, but I want to stick with this and
> just want to avoid some uncomfortable key-strokes for closing braces.
>
> So, here is my function paren-close-dwim, which you can freely pick
> and use for your own configuration. Maybe it is a bit
> 'over-commented', which only represents my still lacking elisp
> fluency.
>
> (defun paren-close-dwim ()
> "Insert the next missing closing paranthesis based on the syntax table.
> Otherwise insert a normal closing ?\)"
> (interactive)
> (save-excursion
> (setq fallback-char ?\))
> ;; go backward up a level in the parenthesis hierarchy (which
> ;; jumps to the next not yet closed (seen from point) open
> ;; parenthesis). Catch unbalanced paranthesis error etc.
> (setq closing-paren
> (condition-case nil
> (progn (backward-up-list)
> ;; get character at point
> (setq open-paren (point))
> ;; get corresponding closing character from the
> ;; syntax table. (syntax-after open-paren)
> ;; delivers a cons cell with (OPEN . CLOSE), so
> ;; we need the cdr to match open-paren.
> (setq syntax-cons (syntax-after open-paren))
> (if (cdr syntax-cons)
> (cdr syntax-cons)
> ;; if cdr is nil use the fallback-char
> fallback-char))
> (error fallback-char))))
> ;; insert dwim parenthesis
> (insert closing-paren))
>
> ;; I bind this to the normal closing paranthesis key and am quite happy
> ;; with its behaviour in several different modes since a few weeks now.
> (global-set-key (kbd ")") 'paren-close-dwim)
>
> Thanks for your feedback,
> Florian
>
>
Hi Florian,
IMO that's quite interesting, thanks.
In detail some design suggestions:
- use let-bound variables instead of setq closing-paren
- don't rely on syntax-table (xclusively), rather make it an universal command, relying on chars
that would permit also to close "}" for example, being usable in text-modes.
skip-chars-backward MY-DELIMITER_CHARS seems an option.
Andreas
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: paren-close-dwim: elisp function of a newbie; feedback welcome
2013-09-25 11:46 paren-close-dwim: elisp function of a newbie; feedback welcome Florian
2013-09-25 12:18 ` Andreas Röhler
@ 2013-09-25 17:32 ` Davis Herring
2013-09-26 19:54 ` Harry Putnam
1 sibling, 1 reply; 11+ messages in thread
From: Davis Herring @ 2013-09-25 17:32 UTC (permalink / raw)
To: Florian; +Cc: emacs-devel
> (defun paren-close-dwim ()
> "Insert the next missing closing paranthesis based on the syntax table.
Typo: "parenthesis".
> Otherwise insert a normal closing ?\)"
Don't indent docstring lines.
> (interactive)
Use "*" to get an immediate error if read-only. You might also consider
allowing a prefix count like `self-insert-command'.
> (save-excursion
> (setq fallback-char ?\))
Use `let' to introduce local variables. However, here you'll be able to
do without any...
> ;; go backward up a level in the parenthesis hierarchy (which
> ;; jumps to the next not yet closed (seen from point) open
> ;; parenthesis). Catch unbalanced paranthesis error etc.
> (setq closing-paren
> (condition-case nil
> (progn (backward-up-list)
> ;; get character at point
> (setq open-paren (point))
> ;; get corresponding closing character from the
> ;; syntax table. (syntax-after open-paren)
> ;; delivers a cons cell with (OPEN . CLOSE), so
> ;; we need the cdr to match open-paren.
> (setq syntax-cons (syntax-after open-paren))
Since you only assign and use `open-paren' once, just insert the
expression for it in place of the variable.
> (if (cdr syntax-cons)
> (cdr syntax-cons)
> ;; if cdr is nil use the fallback-char
> fallback-char))
(or (cdr syntax-cons) fallback-char)
This then allows you to drop the `syntax-cons' variable.
> (error fallback-char))))
Use `ignore-errors' and promote the `or`:
(or (ignore-errors (backward-up-list) (cdr (syntax-after (point))))
fallback-char)
Then you can get rid of `fallback-char' too.
> ;; insert dwim parenthesis
> (insert closing-paren))
Similarly, you can do without the `closing-paren' variable.
Indentation error: the `insert' is not inside the `save-excursion'.
The final version I get (narrowly wrapped for email):
(defun paren-close-dwim ()
"Insert closing parenthesis from syntax table.
Use a normal parenthesis if not inside any."
(interactive "*")
(insert (or (ignore-errors
(save-excursion (backward-up-list)
(cdr (syntax-after (point)))))
?\))))
Davis
--
This product is sold by volume, not by mass. If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: paren-close-dwim: elisp function of a newbie; feedback welcome
2013-09-25 17:32 ` Davis Herring
@ 2013-09-26 19:54 ` Harry Putnam
2013-09-26 20:38 ` Davis Herring
0 siblings, 1 reply; 11+ messages in thread
From: Harry Putnam @ 2013-09-26 19:54 UTC (permalink / raw)
To: emacs-devel
Davis Herring <herring@lanl.gov> writes:
> (defun paren-close-dwim ()
> "Insert closing parenthesis from syntax table.
> Use a normal parenthesis if not inside any."
> (interactive "*")
> (insert (or (ignore-errors
> (save-excursion (backward-up-list)
> (cdr (syntax-after (point)))))
> ?\))))
I'm a total illiterate in elisp but the narrative so far sounds like a
this code might do something really useful.
Can someone describe briefly how this would work, maybe with a small
example, when repairing my own perl code?
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: paren-close-dwim: elisp function of a newbie; feedback welcome
2013-09-26 19:54 ` Harry Putnam
@ 2013-09-26 20:38 ` Davis Herring
2013-09-26 20:44 ` Florian
2013-09-27 21:30 ` Harry Putnam
0 siblings, 2 replies; 11+ messages in thread
From: Davis Herring @ 2013-09-26 20:38 UTC (permalink / raw)
To: Harry Putnam; +Cc: emacs-devel
>> (defun paren-close-dwim ()
>> "Insert closing parenthesis from syntax table.
>> Use a normal parenthesis if not inside any."
>> (interactive "*")
>> (insert (or (ignore-errors
>> (save-excursion (backward-up-list)
>> (cdr (syntax-after (point)))))
>> ?\))))
>
> I'm a total illiterate in elisp but the narrative so far sounds like a
> this code might do something really useful.
>
> Can someone describe briefly how this would work, maybe with a small
> example, when repairing my own perl code?
I'm not sure what you mean about "repairing ... code". This command
simply inserts ')', ']', or '}' (and perhaps '>' or so) to match the
most recent unclosed ([{<.
(If it is "really useful", know that it's not my idea; you just quoted
my reimplementation of Florian's code.)
Davis
--
This product is sold by volume, not by mass. If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: paren-close-dwim: elisp function of a newbie; feedback welcome
2013-09-26 20:38 ` Davis Herring
@ 2013-09-26 20:44 ` Florian
2013-09-27 5:51 ` Andreas Röhler
` (2 more replies)
2013-09-27 21:30 ` Harry Putnam
1 sibling, 3 replies; 11+ messages in thread
From: Florian @ 2013-09-26 20:44 UTC (permalink / raw)
To: emacs-devel
> I'm not sure what you mean about "repairing ... code". This command
> simply inserts ')', ']', or '}' (and perhaps '>' or so) to match the
> most recent unclosed ([{<.
>
> (If it is "really useful", know that it's not my idea; you just quoted
> my reimplementation of Florian's code.)
But yours is much cleaner, I like it. Thanks for that.
Here is a small example to illustrate what it does:
If you are writing a nested expression, like the following, and '_' is
your cursor,
{ (a * [(b) - (c) _
and you have bound ')' to paren-close-dwim (dwim = do what I mean),
three succeeding presses of ')' will produce the sequence: ])}. Or in
other words: ')' will produce the correct next matching closing
bracket regarding the position of your cursor.
Florian
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: paren-close-dwim: elisp function of a newbie; feedback welcome
2013-09-26 20:44 ` Florian
@ 2013-09-27 5:51 ` Andreas Röhler
2013-09-29 9:36 ` Ted Zlatanov
2013-09-27 21:33 ` Harry Putnam
2013-09-29 10:11 ` Óscar Fuentes
2 siblings, 1 reply; 11+ messages in thread
From: Andreas Röhler @ 2013-09-27 5:51 UTC (permalink / raw)
To: emacs-devel
Am 26.09.2013 22:44, schrieb Florian:
>
>> I'm not sure what you mean about "repairing ... code". This command
>> simply inserts ')', ']', or '}' (and perhaps '>' or so) to match the
>> most recent unclosed ([{<.
>>
>> (If it is "really useful", know that it's not my idea; you just quoted
>> my reimplementation of Florian's code.)
>
> But yours is much cleaner, I like it. Thanks for that.
>
> Here is a small example to illustrate what it does:
>
> If you are writing a nested expression, like the following, and '_' is
> your cursor,
>
> { (a * [(b) - (c) _
>
> and you have bound ')' to paren-close-dwim (dwim = do what I mean),
> three succeeding presses of ')' will produce the sequence: ])}. Or in
> other words: ')' will produce the correct next matching closing
> bracket regarding the position of your cursor.
>
> Florian
>
>
>
Really great. So we may have an electric-close, where C-j does all remaining before reaching the next line.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: paren-close-dwim: elisp function of a newbie; feedback welcome
2013-09-27 5:51 ` Andreas Röhler
@ 2013-09-29 9:36 ` Ted Zlatanov
0 siblings, 0 replies; 11+ messages in thread
From: Ted Zlatanov @ 2013-09-29 9:36 UTC (permalink / raw)
To: emacs-devel
On Fri, 27 Sep 2013 07:51:11 +0200 Andreas Röhler <andreas.roehler@online.de> wrote:
AR> Am 26.09.2013 22:44, schrieb Florian:
>>
>> If you are writing a nested expression, like the following, and '_' is
>> your cursor,
>>
>> { (a * [(b) - (c) _
>>
>> and you have bound ')' to paren-close-dwim (dwim = do what I mean),
>> three succeeding presses of ')' will produce the sequence: ])}. Or in
>> other words: ')' will produce the correct next matching closing
>> bracket regarding the position of your cursor.
AR> Really great. So we may have an electric-close, where C-j does all remaining before reaching the next line.
This is a great idea (both `paren-close-dwim' and the electric version
of it). IMHO `paren-close-dwim' should go into Emacs, not an external
package, and have first-class key bindings. It's really helpful.
Ted
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: paren-close-dwim: elisp function of a newbie; feedback welcome
2013-09-26 20:44 ` Florian
2013-09-27 5:51 ` Andreas Röhler
@ 2013-09-27 21:33 ` Harry Putnam
2013-09-29 10:11 ` Óscar Fuentes
2 siblings, 0 replies; 11+ messages in thread
From: Harry Putnam @ 2013-09-27 21:33 UTC (permalink / raw)
To: emacs-devel
Florian <floriansbriefe@gmail.com> writes:
> Here is a small example to illustrate what it does:
[...] snipped example.
Thank you, that was exactly what I needed to understand its working.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: paren-close-dwim: elisp function of a newbie; feedback welcome
2013-09-26 20:44 ` Florian
2013-09-27 5:51 ` Andreas Röhler
2013-09-27 21:33 ` Harry Putnam
@ 2013-09-29 10:11 ` Óscar Fuentes
2 siblings, 0 replies; 11+ messages in thread
From: Óscar Fuentes @ 2013-09-29 10:11 UTC (permalink / raw)
To: emacs-devel
Florian <floriansbriefe@gmail.com> writes:
[snip]
> If you are writing a nested expression, like the following, and '_' is
> your cursor,
>
> { (a * [(b) - (c) _
>
> and you have bound ')' to paren-close-dwim (dwim = do what I mean),
> three succeeding presses of ')' will produce the sequence: ])}. Or in
> other words: ')' will produce the correct next matching closing
> bracket regarding the position of your cursor.
I'll like to match the space separators too. With your example, pressing
`)' thrice would result in:
{ (a * [(b) - (c)]) }_
Note how the space between `(c) _' disappeared and how an space was
inserted before `}'.
Without this sub-feature, the user would be forced to edit after
pressing `)'.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: paren-close-dwim: elisp function of a newbie; feedback welcome
2013-09-26 20:38 ` Davis Herring
2013-09-26 20:44 ` Florian
@ 2013-09-27 21:30 ` Harry Putnam
1 sibling, 0 replies; 11+ messages in thread
From: Harry Putnam @ 2013-09-27 21:30 UTC (permalink / raw)
To: emacs-devel
Davis Herring <herring@lanl.gov> writes:
>>> (defun paren-close-dwim ()
>>> "Insert closing parenthesis from syntax table.
>>> Use a normal parenthesis if not inside any."
>>> (interactive "*")
>>> (insert (or (ignore-errors
>>> (save-excursion (backward-up-list)
>>> (cdr (syntax-after (point)))))
>>> ?\))))
>>
>> I'm a total illiterate in elisp but the narrative so far sounds like a
>> this code might do something really useful.
>>
>> Can someone describe briefly how this would work, maybe with a small
>> example, when repairing my own perl code?
>
> I'm not sure what you mean about "repairing ... code". This command
> simply inserts ')', ']', or '}' (and perhaps '>' or so) to match the
> most recent unclosed ([{<.
It was actually a reference to something Florian said in OP:
Florian wrote:
>> . . . . . . . . . . . . For me this is much handier
>> than using paren-mode or auto-pair etc, especially when modifying
>> existing code."
In my mind that registered as `repairing code'.
> (If it is "really useful", know that it's not my idea; you just quoted
> my reimplementation of Florian's code.)
Thanks, yes, sorry... I actually meant to be replying to Florian's OP.
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2013-09-29 10:11 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-09-25 11:46 paren-close-dwim: elisp function of a newbie; feedback welcome Florian
2013-09-25 12:18 ` Andreas Röhler
2013-09-25 17:32 ` Davis Herring
2013-09-26 19:54 ` Harry Putnam
2013-09-26 20:38 ` Davis Herring
2013-09-26 20:44 ` Florian
2013-09-27 5:51 ` Andreas Röhler
2013-09-29 9:36 ` Ted Zlatanov
2013-09-27 21:33 ` Harry Putnam
2013-09-29 10:11 ` Óscar Fuentes
2013-09-27 21:30 ` Harry Putnam
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.