unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* auto indenting code blocks
@ 2015-06-13 10:40 Sam Halliday
  2015-06-13 11:25 ` Yuri Khan
  0 siblings, 1 reply; 8+ messages in thread
From: Sam Halliday @ 2015-06-13 10:40 UTC (permalink / raw)
  To: help-gnu-emacs

Hi all,

I find it extremely convenient when writing Scala code (and this may be relevant in all c-mode derivations) to be able to have my code blocks automatically expanded.

I have smart-parens installed, so when I type `{' the closing brace is placed after point.

But often I intend to write a multi-line block of code (this may well be the norm in C and C++) and when I type newline I expect the second brace to be moved down a line, indented, and the point placed, indented, in the middle.

For example, let's say we start with this (point denoted by pipe)

  blah |

Type `{' and smart-parens will insert the closing brace

  blah {|}

I'd actually prefer it to be, so if anybody knows how to do that I'd be greatly appreciative of their advice.

  blah { | }

Then I hit newline and this happens

  blah {
  |}

But I *actually* want

  blah {
    |
  }


I have cooked up a little post-self-insert-hook (see bottom of mail) but it feels like I'm inventing some form of wheel.

  1. is there an existing preferred way to do what my scala-block-indent is trying to do?
  2. is there an easier way (perhaps via smart-parens) to achieve what my scala-block-pad is doing, but at the point when the closing brace is inserted?



(defun scala-block-indent ()
  "It is convenient for newlines that follow a curly bracket to be indented."
  (when (and (eq major-mode 'scala-mode)
             ;; ordered for performance
             (looking-at "}") (looking-back "{[[:space:]]*\n"))
    (indent-according-to-mode)
    (forward-line -1)
    (move-end-of-line nil)
    (newline-and-indent)))
(add-hook 'post-self-insert-hook 'scala-block-indent)

(defun scala-block-pad ()
  "It is convenient for spaces following a brace to be space padded."
  (when (and (eq major-mode 'scala-mode)
             ;; ordered for performance
             (looking-at "}") (looking-back "{[[:space:]]"))
    (insert-char ?\s)
    (backward-char)))
(add-hook 'post-self-insert-hook 'scala-block-pad)

Best regards,
Sam


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

* Re: auto indenting code blocks
  2015-06-13 10:40 auto indenting code blocks Sam Halliday
@ 2015-06-13 11:25 ` Yuri Khan
  2015-06-13 11:55   ` Michael Heerdegen
  0 siblings, 1 reply; 8+ messages in thread
From: Yuri Khan @ 2015-06-13 11:25 UTC (permalink / raw)
  To: Sam Halliday; +Cc: help-gnu-emacs@gnu.org

On Sat, Jun 13, 2015 at 4:40 PM, Sam Halliday <sam.halliday@gmail.com> wrote:

> I find it extremely convenient when writing Scala code (and this may be relevant in all c-mode derivations) to be able to have my code blocks automatically expanded.
>
> I have smart-parens installed, so when I type `{' the closing brace is placed after point.
>
> But often I intend to write a multi-line block of code (this may well be the norm in C and C++) and when I type newline I expect the second brace to be moved down a line, indented, and the point placed, indented, in the middle.

I am solving this for C++ with the following ugly hack (BTW thanks for
pointing out “looking-back”):

===
(defun yk-electric-ret ()
  (interactive)
  (if (and (looking-at "\}") (looking-back "\{")))
      (progn
        (newline-and-indent)
        (save-excursion
          (newline-and-indent))
        (indent-according-to-mode))
    (newline-and-indent)))

(defun yk-braces-keys ()
  (local-set-key (kbd "RET") 'yk-electric-ret))
(add-hook 'c-mode-common-hook 'yk-braces-keys)
===

It is essentially equivalent to yours except that I prefer rebinding a
single key to watching for all buffer changes.

> I have cooked up a little post-self-insert-hook (see bottom of mail) but it feels like I'm inventing some form of wheel.
>
>   1. is there an existing preferred way to do what my scala-block-indent is trying to do?
>   2. is there an easier way (perhaps via smart-parens) to achieve what my scala-block-pad is doing, but at the point when the closing brace is inserted?

I am also interested in answers to the above.

Additionally, it would be nice to be able to select a multi-line
region (def: a region that contains at least one line break), press
“{” and have it automatically enclose the region in a pair of braces,
add a line break immediately after the opening brace and another one
before the closing brace, and re-indent all affected lines according
to mode and style. (I could probably compose a function to that effect
and bind it to “{” instead of c-electric-brace or self-insert-command,
but that looks boring :])



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

* Re: auto indenting code blocks
  2015-06-13 11:25 ` Yuri Khan
@ 2015-06-13 11:55   ` Michael Heerdegen
  2015-06-13 13:14     ` Yuri Khan
  0 siblings, 1 reply; 8+ messages in thread
From: Michael Heerdegen @ 2015-06-13 11:55 UTC (permalink / raw)
  To: help-gnu-emacs

Yuri Khan <yuri.v.khan@gmail.com> writes:

> (defun yk-electric-ret ()
>   (interactive)
>   (if (and (looking-at "\}") (looking-back "\{")))
>       (progn
>         (newline-and-indent)
>         (save-excursion
>           (newline-and-indent))
>         (indent-according-to-mode))
>     (newline-and-indent)))
>
> (defun yk-braces-keys ()
>   (local-set-key (kbd "RET") 'yk-electric-ret))
> (add-hook 'c-mode-common-hook 'yk-braces-keys)


Shouldn't `electric-indent-mode' be able to do this?

Michael.




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

* Re: auto indenting code blocks
  2015-06-13 11:55   ` Michael Heerdegen
@ 2015-06-13 13:14     ` Yuri Khan
  2015-06-13 23:30       ` Michael Heerdegen
  0 siblings, 1 reply; 8+ messages in thread
From: Yuri Khan @ 2015-06-13 13:14 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: help-gnu-emacs@gnu.org

On Sat, Jun 13, 2015 at 5:55 PM, Michael Heerdegen
<michael_heerdegen@web.de> wrote:

> Shouldn't `electric-indent-mode' be able to do this?

Maybe it should, but it does not for me.

$ emacs --version
GNU Emacs 24.4.1
[…]

$ emacs -Q

M-: (add-to-list 'load-path "~/.emacs.d/dash.el")
;; as of github:magnars/dash.el tag 2.10.0

M-: (add-to-list 'load-path "~/.emacs.d/smartparens")
;; as of github:Fuco1/smartparens.git commit 8d22a6b

M-x load-library
smartparens-config

M-x smartparens-global-mode

M-x load-library
cc-mode

M-: (setq c-default-style '((java-mode . "java") (awk-mode . "awk")
(other . "stroustrup")))

C-x C-f ~/test.cpp
;; where the file does not exist

Now I start typing:

===
int main(|
===

As soon as I type the opening parenthesis, smartparens adds a matching
closing parenthesis after the point:

===
int main(|)
===

I press End to get out of parentheses and then press Enter to start a new line:

===
int main()
    |
===

I press “{”. smartparens adds a matching closing brace.
electric-indent-mode unindents the newly inserted pair of braces to
the level of “int”:

===
int main()
{|}
===

(1)

I press Enter. Nothing special happens:

===
int main()
{
|}
===

(2)

I press Enter again. Nothing special happens again:

===
int main()
{

|}
===

The behavior does not change if I use Ctrl+J instead of Enter.

If at point (2) I go to the end of the line with the opening brace and
press Enter, or if at point (1) I press Ctrl+O and then Enter, then I
get the desired function skeleton:

===
int main()
{
    |
}
===

But those are not key sequences I’d like to repeat every time.

If I forgo smartparens, then electric-indent-mode does indeed yield
the desired sequence:

===
int main()|
===

Enter

===
int main()
    |
===

Opening brace

===
int main()
{|
===

Enter

===
int main()
{
    |
===

Some text

===
int main()
{
    std::cout << "Hello World\n";|
===

Enter

===
int main()
{
    std::cout << "Hello World\n";
    |
===

Closing brace

===
int main()
{
    std::cout << "Hello World\n";
}|
===

However, smartparens is too convenient to give up.



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

* Re: auto indenting code blocks
  2015-06-13 13:14     ` Yuri Khan
@ 2015-06-13 23:30       ` Michael Heerdegen
  2015-06-14  5:24         ` Yuri Khan
       [not found]         ` <mailman.4973.1434259496.904.help-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 8+ messages in thread
From: Michael Heerdegen @ 2015-06-13 23:30 UTC (permalink / raw)
  To: help-gnu-emacs

Yuri Khan <yuri.v.khan@gmail.com> writes:

> > Shouldn't `electric-indent-mode' be able to do this?
> Maybe it should, but it does not for me.

> If I forgo smartparens, then electric-indent-mode does indeed yield
> the desired sequence:

Then I think someone should make a bug report at the smartparens site
please:

  https://github.com/Fuco1/smartparens

A related report doesn't seem to exist yet.  Contacting the author by
email is surely ok if you don't have a github account.


Regards,

Michael.




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

* Re: auto indenting code blocks
  2015-06-13 23:30       ` Michael Heerdegen
@ 2015-06-14  5:24         ` Yuri Khan
       [not found]         ` <mailman.4973.1434259496.904.help-gnu-emacs@gnu.org>
  1 sibling, 0 replies; 8+ messages in thread
From: Yuri Khan @ 2015-06-14  5:24 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: help-gnu-emacs@gnu.org

On Sun, Jun 14, 2015 at 5:30 AM, Michael Heerdegen
<michael_heerdegen@web.de> wrote:
> Yuri Khan <yuri.v.khan@gmail.com> writes:
>
>> > Shouldn't `electric-indent-mode' be able to do this?
>> Maybe it should, but it does not for me.
>
>> If I forgo smartparens, then electric-indent-mode does indeed yield
>> the desired sequence:
>
> Then I think someone should make a bug report at the smartparens site
> please:
>
>   https://github.com/Fuco1/smartparens

I do not believe it’s a smartparens bug. Its job in this context is to
add a matching closing brace as soon as an opening brace is inserted.

It’s not an electric-indent-mode bug, either. When a line break is
inserted immediately before a closing brace, it reindents the closing
brace according to the mode and style.

What Sam and I want, however, is, with a single Enter keypress, to
insert *two* line breaks, position the point between them, and indent
everything nicely. This is just a piece of unimplemented
functionality, and we implement it in slightly different but similar
ways. It’s possible we are overlooking some part of smartparens’
functionality, hence this thread.

Actually, the smartparens documentation mentions a facility for adding
hooks on pair insertion:

https://github.com/Fuco1/smartparens/wiki/Permissions#pre-and-post-action-hooks

One of its examples specifically adds two line breaks, positions point
in between, and reindents, but this happens immediately after
inserting a brace, making it inconvenient to insert one-liners.

The final example in the same section adds a hook that runs after a
pair of braces is inserted *and* RET is pressed as the immediate next
action. Which is pretty close to what I want but I think I prefer that
it happen every time I press Enter while in an empty pair of braces,
not only when said pair is newly inserted.

The next section describes a more concise syntax for such insertions:

https://github.com/Fuco1/smartparens/wiki/Permissions#pre-and-post-action-hooks

===
(sp-local-pair 'c++-mode "{" nil :post-handlers '(("||\n[i]" "RET")))
===

Sam, you might also like this:

===
(sp-local-pair 'c++-mode "{" nil :post-handlers '(("||\n[i]" "RET")
("| " "SPC")))
===

(substitute your major mode).


I think I’ll take it for a drive. Michael, thank you for encouraging
me to figure this out.



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

* Re: auto indenting code blocks
       [not found]         ` <mailman.4973.1434259496.904.help-gnu-emacs@gnu.org>
@ 2015-06-14 19:54           ` Sam Halliday
  2015-06-14 19:59           ` Stefan Monnier
  1 sibling, 0 replies; 8+ messages in thread
From: Sam Halliday @ 2015-06-14 19:54 UTC (permalink / raw)
  To: help-gnu-emacs

Yuri, this is *exactly* what I wanted... thank you so much for figuring it out :-D

On Sunday, 14 June 2015 06:24:58 UTC+1, Yuri Khan  wrote:
> On Sun, Jun 14, 2015 at 5:30 AM, Michael Heerdegen
> <michael_heerdegen@web.de> wrote:
> > Yuri Khan <yuri.v.khan@gmail.com> writes:
> >
> >> > Shouldn't `electric-indent-mode' be able to do this?
> >> Maybe it should, but it does not for me.
> >
> >> If I forgo smartparens, then electric-indent-mode does indeed yield
> >> the desired sequence:
> >
> > Then I think someone should make a bug report at the smartparens site
> > please:
> >
> >   https://github.com/Fuco1/smartparens
> 
> I do not believe it's a smartparens bug. Its job in this context is to
> add a matching closing brace as soon as an opening brace is inserted.
> 
> It's not an electric-indent-mode bug, either. When a line break is
> inserted immediately before a closing brace, it reindents the closing
> brace according to the mode and style.
> 
> What Sam and I want, however, is, with a single Enter keypress, to
> insert *two* line breaks, position the point between them, and indent
> everything nicely. This is just a piece of unimplemented
> functionality, and we implement it in slightly different but similar
> ways. It's possible we are overlooking some part of smartparens'
> functionality, hence this thread.
> 
> Actually, the smartparens documentation mentions a facility for adding
> hooks on pair insertion:
> 
> https://github.com/Fuco1/smartparens/wiki/Permissions#pre-and-post-action-hooks
> 
> One of its examples specifically adds two line breaks, positions point
> in between, and reindents, but this happens immediately after
> inserting a brace, making it inconvenient to insert one-liners.
> 
> The final example in the same section adds a hook that runs after a
> pair of braces is inserted *and* RET is pressed as the immediate next
> action. Which is pretty close to what I want but I think I prefer that
> it happen every time I press Enter while in an empty pair of braces,
> not only when said pair is newly inserted.
> 
> The next section describes a more concise syntax for such insertions:
> 
> https://github.com/Fuco1/smartparens/wiki/Permissions#pre-and-post-action-hooks
> 
> ===
> (sp-local-pair 'c++-mode "{" nil :post-handlers '(("||\n[i]" "RET")))
> ===
> 
> Sam, you might also like this:
> 
> ===
> (sp-local-pair 'c++-mode "{" nil :post-handlers '(("||\n[i]" "RET")
> ("| " "SPC")))
> ===
> 
> (substitute your major mode).
> 
> 
> I think I'll take it for a drive. Michael, thank you for encouraging
> me to figure this out.



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

* Re: auto indenting code blocks
       [not found]         ` <mailman.4973.1434259496.904.help-gnu-emacs@gnu.org>
  2015-06-14 19:54           ` Sam Halliday
@ 2015-06-14 19:59           ` Stefan Monnier
  1 sibling, 0 replies; 8+ messages in thread
From: Stefan Monnier @ 2015-06-14 19:59 UTC (permalink / raw)
  To: help-gnu-emacs

> I do not believe it’s a smartparens bug. Its job in this context is to
> add a matching closing brace as soon as an opening brace is inserted.

> It’s not an electric-indent-mode bug, either. When a line break is
> inserted immediately before a closing brace, it reindents the closing
> brace according to the mode and style.

> What Sam and I want, however, is, with a single Enter keypress, to
> insert *two* line breaks, position the point between them, and indent
> everything nicely.

Indeed.  IIRC electric-pair-mode offers such a feature, and during its
implementation we considered other alternatives, including adding it via
electric-layout-mode which is arguably conceptually closer.


        Stefan


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

end of thread, other threads:[~2015-06-14 19:59 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-06-13 10:40 auto indenting code blocks Sam Halliday
2015-06-13 11:25 ` Yuri Khan
2015-06-13 11:55   ` Michael Heerdegen
2015-06-13 13:14     ` Yuri Khan
2015-06-13 23:30       ` Michael Heerdegen
2015-06-14  5:24         ` Yuri Khan
     [not found]         ` <mailman.4973.1434259496.904.help-gnu-emacs@gnu.org>
2015-06-14 19:54           ` Sam Halliday
2015-06-14 19:59           ` Stefan Monnier

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).