I use evil-mode
on emacs, and recently I started using eshell
, I really like how I can leave insert mode and move on the eshell
buffer to copy content or other goodies, but when entering insert mode again it does it in the cursor current position, what I would like is that when I enter insert mode automatically move the currsor to the prompt line (last line, end of line).
What I did was:
(add-hook 'eshell-mode-hook
(lambda()
(define-key evil-normal-state-map (kbd "i") (lambda () (interactive) (evil-goto-line) (evil-append-line nil)))))
However it applies this mapping in all other buffers, I just want to make it active on an eshell buffer.
How to define a key binding that works differently in eshell?
The current accepted answer satisfies the stated requirements, but has two major limitations:
point
is already on the last line (e.g., when editing the current command), there is no way to enter insert mode at the current position;
i is effectively rebound to A.The first limitation can be eliminated by hooking first on eshell-mode
then second on evil-insert-state-entry
.
The second limitation can be addressed by setting point
's position based first on the line number and second on the read-only text-property:
point
is not already on the last line, then it is moved to point-max
(which is always read-write).point
is read-only, point
is moved to the position in the current line where the read-only text-property changes.The following code negates the limitations of the accepted answer.
(defun move-point-to-writeable-last-line ()
"Move the point to a non-read-only part of the last line.
If point is not on the last line, move point to the maximum position
in the buffer. Otherwise if the point is in read-only text, move the
point forward out of the read-only sections."
(interactive)
(let* ((curline (line-number-at-pos))
(endline (line-number-at-pos (point-max))))
(if (= curline endline)
(if (not (eobp))
(let (
;; Get text-properties at the current location
(plist (text-properties-at (point)))
;; Record next change in text-properties
(next-change
(or (next-property-change (point) (current-buffer))
(point-max))))
;; If current text is read-only, go to where that property changes
(if (plist-get plist 'read-only)
(goto-char next-change))))
(goto-char (point-max)))))
(defun move-point-on-insert-to-writeable-last-line ()
"Only edit the current command in insert mode."
(add-hook 'evil-insert-state-entry-hook
'move-point-to-writeable-last-line
nil
t))
(add-hook 'eshell-mode-hook
'move-point-on-insert-to-writeable-last-line)