-
Notifications
You must be signed in to change notification settings - Fork 275
/
Copy pathevil-collection-eshell.el
144 lines (126 loc) · 5.58 KB
/
evil-collection-eshell.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
;;; evil-collection-eshell.el --- Evil bindings for Eshell -*- lexical-binding: t -*-
;; Copyright (C) 2017 Pierre Neidhardt
;; Author: Pierre Neidhardt <[email protected]>
;; Maintainer: James Nguyen <[email protected]>
;; Pierre Neidhardt <[email protected]>
;; URL: https://github.com/emacs-evil/evil-collection
;; Version: 0.0.1
;; Package-Requires: ((emacs "25.1"))
;; Keywords: evil, eshell, tools
;; This file is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published
;; by the Free Software Foundation; either version 3, or (at your
;; option) any later version.
;;
;; This file is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; For a full copy of the GNU General Public License
;; see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; Evil bindings for Eshell.
;;; Code:
(require 'em-prompt)
(require 'eshell)
(require 'evil-collection)
(defconst evil-collection-eshell-maps '(eshell-mode-map))
(defun evil-collection-eshell-next-prompt ()
"`evil' wrapper around `eshell-next-prompt'."
(when (get-text-property (point) 'read-only)
;; If at end of prompt, `eshell-next-prompt' will not move, so go backward.
(beginning-of-line)
(eshell-next-prompt 1)))
(defun evil-collection-eshell-next-prompt-on-insert ()
"Go to next prompt on `evil' replace/insert enter."
(dolist (hook '(evil-replace-state-entry-hook evil-insert-state-entry-hook))
(add-hook hook 'evil-collection-eshell-next-prompt nil t)))
(defun evil-collection-eshell-interrupt-process ()
"Interupt `eshell' process and enter insert state."
(interactive)
(eshell-interrupt-process)
(evil-insert 1))
;; Taken from Doom Emacs
(evil-define-operator evil-collection-eshell-evil-change (beg end type register yank-handler delete-func)
"Like `evil-change' but will not delete/copy the prompt."
(interactive "<R><x><y>")
(save-restriction
(narrow-to-region eshell-last-output-end (point-max))
(evil-change (max beg (point-min))
(if (eq type 'line) (point-max) (min (or end (point-max)) (point-max)))
type register yank-handler delete-func)))
;; Taken from Doom Emacs
(evil-define-operator evil-collection-eshell-evil-change-line (beg end type register yank-handler)
"Change to end of line."
:motion evil-end-of-line
(interactive "<R><x><y>")
(evil-collection-eshell-evil-change beg end type register yank-handler #'evil-delete-line))
;; Taken from Doom Emacs
(evil-define-operator evil-collection-eshell-evil-delete (beg end type register yank-handler)
"Like `evil-delete' but will not delete/copy the prompt."
(interactive "<R><x><y>")
(save-restriction
(narrow-to-region eshell-last-output-end (point-max))
(evil-delete (if beg (max beg (point-min)) (point-min))
(if (eq type 'line) (point-max) (min (or end (point-max)) (point-max)))
type register yank-handler)))
;; Taken from Doom Emacs
;; Although the BEG argument doesn't get used in any meaningful way, `evil-define-operator' must access it nonetheless, so putting an underscore in front will make the CI fail.
(evil-define-operator evil-collection-eshell-evil-delete-line (beg end type register yank-handler)
"Change to end of line."
:motion nil
:keep-visual t
(interactive "<R><x>")
(evil-collection-eshell-evil-delete (point) end type register yank-handler))
;;; `eshell-mode-map' is reset when Eshell is initialized in `eshell-mode'. We
;;; need to add bindings to `eshell-first-time-mode-hook'.
(defun evil-collection-eshell-setup-keys ()
"Set up `evil' bindings for `eshell'."
(evil-collection-define-key 'normal 'eshell-mode-map
;; motion
"[[" 'eshell-previous-prompt
"]]" 'eshell-next-prompt
(kbd "C-k") 'eshell-previous-prompt
(kbd "C-j") 'eshell-next-prompt
"gk" 'eshell-previous-prompt
"gj" 'eshell-next-prompt
"0" 'eshell-bol
"^" 'eshell-bol
(kbd "M-h") 'eshell-backward-argument
(kbd "M-l") 'eshell-forward-argument
(kbd "C-n") 'eshell-next-matching-input-from-input
(kbd "C-p") 'eshell-previous-matching-input-from-input
(kbd "RET") 'eshell-send-input
(kbd "C-c C-c") 'evil-collection-eshell-interrupt-process
"c" 'evil-collection-eshell-evil-change
"C" 'evil-collection-eshell-evil-change-line
"d" 'evil-collection-eshell-evil-delete
"D" 'evil-collection-eshell-evil-delete-line)
(evil-collection-define-key 'insert 'eshell-mode-map
;; motion
(kbd "M-h") 'eshell-backward-argument
(kbd "M-l") 'eshell-forward-argument)
;; TODO: What if the user changes `evil-want-C-u-delete' after this is run?
(when evil-want-C-u-delete
(evil-collection-define-key 'insert 'eshell-mode-map
(kbd "C-u") 'eshell-kill-input))
(evil-collection-define-key 'visual 'eshell-mode-map
;; motion
;; TODO: This does not work with `evil-visual-line'.
"[[" 'eshell-previous-prompt
"]]" 'eshell-next-prompt
(kbd "C-k") 'eshell-previous-prompt
(kbd "C-j") 'eshell-next-prompt
"gk" 'eshell-previous-prompt
"gj" 'eshell-next-prompt
"0" 'eshell-bol
"^" 'eshell-bol))
;; TODO: Compare this setup procedure with evil-ediff.
;;;###autoload
(defun evil-collection-eshell-setup ()
"Set up `evil' bindings for `eshell'."
(add-hook 'eshell-mode-hook 'evil-collection-eshell-next-prompt-on-insert)
(add-hook 'eshell-first-time-mode-hook 'evil-collection-eshell-setup-keys))
(provide 'evil-collection-eshell)
;;; evil-collection-eshell.el ends here