I'm playing with evil-mode and this is one of the things where evil differs from vim. In vim G
takes you to the last line, but evil uses Emacs end-of-buffer
which for some reason takes me beyond last line to some imaginary line.
-
Emacs and Vim differ in how they deal with the final newline. Evil does not try working around this as it's purely concerned with emulating Vim-style editing. I've found it helpful to visualize it with fringe indicators, you may find another package of that kind useful.– wasamasaCommented Mar 23, 2017 at 17:42
-
I'm sorry, visualise what?– user1685095Commented Mar 23, 2017 at 17:45
-
The final newline.– wasamasaCommented Mar 23, 2017 at 18:06
-
@wasamasa Hmm, I don't see the point of doing that. Can you explain?– user1685095Commented Mar 23, 2017 at 18:08
2 Answers
The command end-of-buffer
uses a variation on (goto-char (point-max))
to go to the last position in the buffer. If the buffer ends with a newline, end-of-buffer
will leave you on the empty line at the end, whereas if you delete this last newline, end-of-buffer
will leave you at the end of the text in the now non-empty last line.
One possible solution is to advise end-of-buffer
to just go up a line if it leaves you on an empty line:
(defun my-end-of-buffer-dwim (&rest _)
"If current line is empty, call `previous-line'."
(when (looking-at-p "^$")
(previous-line)))
(advice-add #'end-of-buffer :after #'my-end-of-buffer-dwim)
If you want end-of-buffer
to always leave you at the beginning of the penultimate line (rather than at the end if the file has no trailing newline), you might want this instead:
(defun my-end-of-buffer-dwim (&rest _)
"Go to beginning of line.
If current line is empty, go to beginning of previous one
instead."
(beginning-of-line (and (looking-at-p "^$") 0)))
(advice-add #'end-of-buffer :after #'my-end-of-buffer-dwim)
And the standard advice disclaimer: You can avoid unanticipated side-effects by just creating your own end-of-buffer command and rebinding the keys, rather than using advice:
(defun my-end-of-buffer ()
"Go to beginning of last line in buffer.
If last line is empty, go to beginning of penultimate one
instead."
(interactive)
(goto-char (point-max))
(beginning-of-line (and (looking-at-p "^$") 0)))
(global-set-key [remap end-of-buffer] #'my-end-of-buffer)
Note that all of the above solutions leave you at most one line away from the end of the buffer - they do not leave you on the last non-empty line.
-
Thanks, your solution works! I'm new to elisp, so I haven't knew about
advice-add
. I didn't want to remap keys, because in evilG
is a motion, so you can delete till the end of file withdG
etc. I don't think tht.his would work if I would just remap key to another function. But maybe I don't know lisp well enough. Commented Mar 23, 2017 at 19:49 -
If you wish to remap
my-end-of-buffer
to the default shortcut (overriding it), use(global-set-key "\M->" #'my-end-of-buffer)
. Commented Jan 4 at 12:09
This probably doesn't answer your question, question about stopping Emacs scrolling past end-of-buffer.
(setq next-line-add-newlines t)
The problem with this though is that mouse scroll is not going paste end-of-buffer, and you will end up with alot of empty lines in your files (pressing down arrows adds newlines, up arrow does not remove them).