Can you have smart behavior for the home key in Emacs? By smart I mean that instead of going to the character number 0, it should go to the first non-blank character, and go to 0 on a second pressing, and back to the first non-blank in a third and so on. Having smart end would be nice as well.
7 Answers
(defun smart-beginning-of-line ()
"Move point to first non-whitespace character or beginning-of-line.
Move point to the first non-whitespace character on this line.
If point was already at that position, move point to beginning of line."
(interactive "^") ; Use (interactive) in Emacs 22 or older
(let ((oldpos (point)))
(back-to-indentation)
(and (= oldpos (point))
(beginning-of-line))))
(global-set-key [home] 'smart-beginning-of-line)
I'm not quite sure what smart end would do. Do you normally have a lot of trailing whitespace?
Note: The major difference between this function and Robert Vuković's is that his always moves to the first non-blank character on the first keypress, even if the cursor was already there. Mine would move to column 0 in that case.
Also, he used (beginning-of-line-text)
where I used (back-to-indentation)
. Those are very similar, but there are some differences between them. (back-to-indentation)
always moves to the first non-whitespace character on a line. (beginning-of-line-text)
sometimes moves past non-whitespace characters that it considers insignificant. For instance, on a comment-only line, it moves to the first character of the comment's text, not the comment marker. But either function could be used in either of our answers, depending on which behavior you prefer.

- 61,471
- 9
- 126
- 175
-
1Unfortunately it doesn't work with cua enabled, in which case shift for selection doesn't work, shift home for selecting the complete line doesn't work. Any suggestions? – Alexander Stolz May 27 '10 at 08:40
-
@Alexander Stolz, I never use cua-mode, but try adding `(put 'smart-beginning-of-line 'CUA 'move)` after the `defun` (i.e., right before the `global-set-key` line). – cjm May 27 '10 at 09:18
-
2Is there a way to make shift-selection work without toggling shift-select-mode on? – gorlum0 Sep 03 '11 at 04:35
-
2Since Emacs version is now 24, I suggest to write the sample code with `(interactive "^")` by default and add `; Use (interactive) with Emacs 22 or older`. Gorlum0 (comment above) is probably not the only one struggling to have the sample code working with shift selection. – Mathieu Apr 04 '13 at 03:27
-
I'm relatively new to emacs. I was trying to modify this to be more portable, so I added this line: `(if (version< "22" emacs-version) (interactive "^") (interactive))`. But this gives me the error: `Wrong type argument: commandp, smart-beginning-of-line`. Does someone mind explaining why with doesn't work? – Thomas Apr 22 '18 at 16:18
-
Nevermind. I found some reading on `(interactive)` and realized it's not a normal function call. – Thomas Apr 22 '18 at 16:21
This works with GNU Emacs, I didn't tried it with XEmacs.
(defun My-smart-home () "Odd home to beginning of line, even home to beginning of text/code."
(interactive)
(if (and (eq last-command 'My-smart-home)
(/= (line-beginning-position) (point)))
(beginning-of-line)
(beginning-of-line-text))
)
(global-set-key [home] 'My-smart-home)

- 4,677
- 6
- 31
- 47
Thanks for this handy function. I use it all the time now and love it. I've made just one small change: (interactive) becomes: (interactive "^")
From emacs help:
If the string begins with ^' and
shift-select-mode' is non-nil, Emacs first calls the function `handle-shift-select'.
Basically this makes shift-home select from the current position to the start of the line if you use shift-select-mode. It's especially useful in the minibuffer.

- 61
- 1
- 1
Note that there is already a back-to-indentation function which does what you want the first smart-home function to do, i.e. go to the first non-whitespace character on the line. It is bound by default to M-m.

- 68,681
- 4
- 36
- 40
-
Yes, if you read the accepted answer you'll notice a discussion of some of the differences between back-to-indentation and beginning-of-line-text. – cjm Sep 29 '08 at 04:20
-
for me what would be more useful than a smart home key would be making M-m smart on subsequent presses, similar to how C-l is overloaded. – willwillis Apr 25 '11 at 15:58
My version: move to begining of visual line, first non-whitespace, or beginning of line.
(defun smart-beginning-of-line ()
"Move point to beginning-of-line or first non-whitespace character"
(interactive "^")
(let ((p (point)))
(beginning-of-visual-line)
(if (= p (point)) (back-to-indentation))
(if (= p (point)) (beginning-of-line))))
(global-set-key [home] 'smart-beginning-of-line)
(global-set-key "\C-a" 'smart-beginning-of-line)
The [home]
and "\C-a"
(control+a) keys:
- Move the cursor (point) the the beginning of the visual line.
- If it is already at the beginnng of the visual line, then move it to first non-whitespace character of the line.
- If it is already there, then move it to the beginning of the line.
- While moving, keep the region (
interactive "^"
).
This is taken from @cjm and @thomas; then I add the visual line stuff. (Sorry for my broken English).

- 1,030
- 6
- 7
I adapt @Vucovic code to jump to beggining-of-line
first:
(defun my-smart-beginning-of-line ()
"Move point to beginning-of-line. If repeat command it cycle
position between `back-to-indentation' and `beginning-of-line'."
(interactive "^")
(if (and (eq last-command 'my-smart-beginning-of-line)
(= (line-beginning-position) (point)))
(back-to-indentation)
(beginning-of-line)))
(global-set-key [home] 'my-smart-beginning-of-line)

- 45,285
- 19
- 251
- 303