Problem
As we all know programmers are lazy, repetition is the evil, we want to type as fast as possible.
Using C-like languages you always need to put the comma in the end.
Normally after the comma you also want to go to newline and indent, so why not put together those two things and automate it?
If you also like yasnippet then you’ll find this feature even nicer.
I took from this feature textmate , a wonderful text editor which comes with this setting by default.
As we’ll see we don’t need many lines of elisp code to end up with a much more powerful and flexible version of this nice feature.
Solution
newline-force
We first define a first function newline-force
Here it is:
(defun newline-force()
"Goes to newline leaving untouched the rest of the line"
(interactive)
(progn
(end-of-line)
(newline-and-indent)))
This function goes to end of line and calls the predefined function newline-and-indent, which goes to newline and indent according to mode
In more detail:
- interactive: function is available for user
- progn: executes a sequence of disjointed operations
newline-force-close
The newline-force-close function before going to newline adds a closing char at the end.
We have to consider some more cases:
- we are in the beginning of the buffer
- we already have the closing char inserted
(defun newline-force-close()
(interactive)
(end-of-line)
(let ((closing-way (assoc major-mode newline-force-close-alist2))
closing-char)
;; Setting the user defined or the constant if not found
(if (not closing-way)
(progn
(message "closing char not defined for this mode, using default")
(setq closing-char default-closing-char))
(setq closing-char (cdr closing-way)))
(when (not (bobp))
;; if we're at beginning of buffer, the backward-char will beep
;; :( This works even in the case of narrowing (e.g. we don't
;; look outside of the narrowed area.
(when (not (looking-at closing-char))
(insert closing-char))
(newline-force))))
Using the variable major mode we do a lookup in the association list newline-force-close-alist.
If nothing is found we use the default closing char.
Here below there are the two variables needed.
When defining some default values which shouldn’t change usign defconst is better than setting the symbol with setq.
Using defconst, defvar, defun or defcustom allows you to add a docstring to your symbols.
This is very useful and that’s why emacs is also called the “self documenting editor”.
Here below is the association list, which is simply it’s a list of conses.
(defconst default-closing-char ";" "default closing char, change in newline-force-close-alist if needed") (setq newline-force-close-alist '((python-mode . ":") (html-mode . " <br>")))
Now last step, we bind the two defined functions to a pair of key
(global-set-key (kbd "M-RET") 'newline-force) (global-set-key [M-S-return] 'newline-force-close)
In this way we bind globally the two functions o Meta-Return and Meta-Shift-Return.
If you instead prefer to add it only for certain modes than you need to add hooks to your modes, and use local-set-key.
See also this discussion, which is where this code comes from.