ambevar-dotfiles/.emacs.d/lisp/init-eshell.el

111 lines
4.3 KiB
EmacsLisp

;;; Eshell
;;; Eshell gets initialized differently. When eshell.el first gets loaded, only
;;; the core is defined and `eshell-load-hook' is called. For every Eshell
;;; session, `eshell-mode' is run: it resets `eshell-mode-map', it loads
;;; modules, runs their hooks and concludes with `eshell-first-time-mode-hook'
;;; (for the first session only) and `eshell-mode-hook'.
(setq eshell-directory-name (concat emacs-cache-folder "eshell"))
;;; Use native 'sudo', system sudo asks for password every time.
(require 'em-tramp)
(with-eval-after-load "esh-module" ; Need a file name because `provide' is before the definition of `eshell-modules-list.
;; Don't print the banner.
(delq 'eshell-banner eshell-modules-list)
(push 'eshell-tramp eshell-modules-list))
(setq
eshell-ls-use-colors t
;; ffap-shell-prompt-regexp changes the behaviour of `helm-find-files' when
;; point is on prompt. I find this disturbing.
ffap-shell-prompt-regexp nil
eshell-destroy-buffer-when-process-dies t)
;; TODO: Hour is printed twice. We don't need to set this?
;; (setq eshell-ls-date-format (replace-regexp-in-string "^\\+*" "" (getenv "TIME_STYLE")))
;;; Leave `eshell-highlight-prompt' to t as it sets the read-only property.
(setq eshell-prompt-function
(lambda nil
(let ((path (abbreviate-file-name (eshell/pwd))))
(concat
(format
(propertize "(%s@%s)[%s]\n>" 'face '(:weight bold))
(propertize (user-login-name) 'face '(:foreground "cyan"))
(propertize (system-name) 'face '(:foreground "cyan"))
(propertize path 'face `(:foreground ,(if (= (user-uid) 0) "red" "green") :weight bold)))
" "))))
;;; If the prompt spans over multiple lines, the regexp should match
;;; last line only.
(setq-default eshell-prompt-regexp "^> ")
(with-eval-after-load 'em-term
(nconc eshell-visual-commands
'("abook" "alsamixer" "cmus" "fzf" "htop" "mpsyt" "mpv" "mutt" "ncdu" "newsbeuter" "pinentry-curses" "ranger" "watch"))
(setq eshell-visual-subcommands
'(("git" "log" "l" "lol" "diff" "d" "dc" "show")
("sudo" "vi"))))
;;; Support for Emacs' pinentry
(setq epa-pinentry-mode 'loopback)
(pinentry-start)
;;; Alias management possibilities:
;;; - Version eshell-alias and store it in user-emacs-directory. Simplest and
;;; fastest, but aliases cannot be included conditionnaly, e.g. depending on the
;;; existence of a program.
;;; - Store eshell-alias in cache and populate it dynamically on startup.
;; (setq eshell-aliases-file (concat user-emacs-directory "eshell-alias"))
;;;
;;; `eshell/alias' is too slow as it reads and write the file on each definition.
;;; Let's write manually instead.
(with-eval-after-load 'em-alias
;;; TODO: This conflicts with `evil-define-key' during the initialization of
;;; the first eshell session: the map in insert-mode will not take the changes
;;; into account. Going to normal mode and back to insert mode works.
(eshell-read-aliases-list)
(dolist
(alias
'(("l" "ls -1 $*")
("la" "ls -lAh $*")
("ll" "ls -lh $*")
;; ("ls" "ls -F $*")
;; ("emacs" "find-file $1")
;; ("em" "find-file $*")
("cp" "*cp -i $*")
("mv" "*mv -i $*")
("mkdir" "*mkdir -p $*")
("mkcd" "*mkdir -p $* && cd $1")))
(add-to-list 'eshell-command-aliases-list alias))
(eshell-write-aliases-list))
;;; Hooks
;;; `nobreak-char-display' makes some output look weird, e.g. with 'tree'.
(add-hook 'eshell-mode-hook 'turn-off-nobreak-char-display)
(add-hook 'eshell-mode-hook 'eshell-cmpl-initialize)
;;; REVIEW: Emacs' standard functions fail when output has empty lines.
;;; This implementation is more reliable.
;;; Reported at https://debbugs.gnu.org/cgi/bugreport.cgi?bug=27405.
(with-eval-after-load 'em-prompt
(defun eshell-next-prompt (n)
"Move to end of Nth next prompt in the buffer.
See `eshell-prompt-regexp'."
(interactive "p")
(re-search-forward eshell-prompt-regexp nil t n)
(when eshell-highlight-prompt
(while (not (get-text-property (line-beginning-position) 'read-only) )
(re-search-forward eshell-prompt-regexp nil t n)))
(eshell-skip-prompt))
(defun eshell-previous-prompt (n)
"Move to end of Nth previous prompt in the buffer.
See `eshell-prompt-regexp'."
(interactive "p")
(backward-char)
(eshell-next-prompt (- n))))
(provide 'init-eshell)