Search code examples
emacsformattingelispkey-bindingsauto-indent

(ELisp) automatically nesting next line using brace return


I'm completely new to both Lisp and Emacs. In Emacs, when coding in Java for example, I want to be able to type "{" then hit "ENTER" and have the next line be ready for whatever is nested in the braces. For example, if I have the following line:

public void method()

and I type "{" then hit return I should get this:

public void method() {
    // indentation applied, no additional tabbing necessary
}

I'm already able to insert by pairs, for example, typing "{" gives "{}" with my cursor between the braces. I did this by adding these lines to the emacs init file:

;; insert by pairs (parens, quotes, brackets, braces)
(defun insert-pair (leftChar rightChar)
  (if (region-active-p)
      (let (
        (p1 (region-beginning))
        (p2 (region-end))
        )
    (goto-char p2)
    (insert rightChar)
    (goto-char p1)
    (insert leftChar)
    (goto-char (+ p2 2))
    )
(progn
  (insert leftChar rightChar)
  (backward-char 1) ) )
  )
(defun insert-pair-brace () (interactive) (insert-pair "{" "}") )
(global-set-key (kbd "{") 'insert-pair-brace)

To get the auto-nesting I described above, I added these lines:

;; automatically nest next line
(defun auto-nest ()
  (insert "\n\n")
  (backward-char 1)
  (insert "\t")
)
(defun auto-nest-brace () (interactive) (auto-nest) )
(global-set-key (kbd "{ RET") 'auto-nest-brace)

When I start up Emacs, however, I get this message:

error: Key sequence { RET starts with non-prefix key {

What am I doing wrong, and what can I do to fix it? I don't want to use a different key combination to do this. There are a lot of text editors in which this auto-nesting is standard, and it should be easy enough to code up in ELisp.


Solution

  • It's great that you are trying to add this functionality to Emacs yourself, but there's no need to reinvent the wheel here. Emacs already has a command for the purpose of auto-indenting; it's called newline-and-indent. It is bound to C-j by default, but you can rebind it to RET

    1. globally:

      (global-set-key (kbd "RET") 'newline-and-indent)
      
    2. for a specific mode only:

      (require 'cc-mode)
      (define-key java-mode-map (kbd "RET") 'newline-and-indent)
      

      java-mode-map is defined in cc-mode.el and not available by default, that's why you have to require cc-mode before you can modify java-mode-map.


    Note that newline-and-indent indents according to major mode. That is, if you're e.g. in java-mode and press RET in some random location that's not meaningful w/r/t Java syntax, it won't insert additional whitespace at the beginning of the new line.

    To read all there is to know about newline-and-indent do

    C-h f newline-and-indent RET