feat(emacs): Eshell stuff

- Fancify prompt
  - Shows success of last command.
  - TRAMP prefix is made distinct.
  - CWD is abbreviated.
- cd to project root (`cdp`).
- Imitate using `C-d` / send-EOF to exit.
- Opening popup shell puts user in insert state.
- Fixes TRAMP customisation.

Nicely done! }:3
This commit is contained in:
Madeleine Sydney
2025-02-16 18:50:00 -07:00
parent a0495c6df3
commit 6c9213d532
8 changed files with 182 additions and 44 deletions

View File

@@ -60,9 +60,103 @@
(eshell-mode))
(when command
(syd-eshell-run-command command eshell-buffer)))
(pop-to-buffer eshell-buffer))))
(pop-to-buffer eshell-buffer)
(when (bound-and-true-p evil-mode)
(call-interactively #'evil-append-line)))))
(defun syd-eshell-adapt-bash-aliases ()
"Very sloppily convert aliases defined in Bash to an Eshell alias file."
(interactive)
(save-window-excursion
(let ((err-buf (generate-new-buffer "*adapt-bash-aliases-err*"))
(result-buf (generate-new-buffer "*adapted-bash-aliases*")))
(with-current-buffer result-buf
(insert "# Automatically generated by syd-eshell-adapt-bash-aliases\n"))
(with-temp-buffer
;; Aliases are only loaded when bash is in interactive mode.
(shell-command "bash -ic alias" (current-buffer) err-buf)
(goto-char (point-min))
(while (re-search-forward
(rx bol "alias " (group (+ alphanumeric)) "='"
(group (* (not ?\'))) "'")
nil t)
(let ((eshell-alias (format "alias %s %s $*\n"
(match-string 1)
(match-string 2))))
(with-current-buffer result-buf
(insert eshell-alias)))))
(unless (= 0 (buffer-size err-buf))
(message "Some errors occured whilst fetching Bash's aliases:")
(message (with-current-buffer err-buf (buffer-string))))
(kill-buffer err-buf)
result-buf)))
(defun syd-eshell-C-d ()
"Imitate the typical 'C-d' behaviour in other shells. Quits Eshell when the input is empty."
(interactive)
(when (and (eolp) (looking-back eshell-prompt-regexp nil))
(eshell-life-is-too-much)))
(defun syd-eshell--init-ui-hacks ()
(defun syd-eshell-remove-fringes-h ()
(set-window-fringes nil 0 0)
(set-window-margins nil 1 nil))
(defun syd-eshell-enable-text-wrapping-h ()
(visual-line-mode +1)
(set-display-table-slot standard-display-table 0 ?\ ))
(add-hook 'eshell-mode-hook #'syd-eshell-remove-fringes-h)
(add-hook 'eshell-mode-hook #'syd-eshell-enable-text-wrapping-h)
(with-eval-after-load 'hide-mode-line
(add-hook 'eshell-mode-hook #'hide-mode-line-mode))
;; Remove hscroll-margin in shells, otherwise you get jumpiness when the
;; cursor comes close to the left/right edges of the window.
(defun syd-eshell-disable-hscroll-margin ()
(setq hscroll-margin 0))
(add-hook 'eshell-mode-hook #'syd-eshell-disable-hscroll-margin))
(use-package shrink-path
:defer t)
(defface syd-eshell-local-name '((t (:inherit font-lock-constant-face)))
"Face used by the Eshell prompt for the CWD's non-TRAMP part. See
`syd-eshell--prompt-fn'"
:group 'eshell)
(defface syd-eshell-tramp-prefix '((t (:inherit font-lock-comment-face)))
"Face used by the Eshell prompt for the CWD's TRAMP prefix. See
`syd-eshell--prompt-fn'."
:group 'eshell)
(defun syd-eshell--prompt-fn ()
"See `eshell-prompt-function'."
(require 'shrink-path)
(require 'syd-file)
(-let (((tramp-prefix . local-name) (syd-split-tramp-file-name (eshell/pwd))))
(concat (unless (bobp) "\n")
(when tramp-prefix
(propertize tramp-prefix 'face 'syd-eshell-tramp-prefix))
(propertize (if (equal local-name "~")
local-name
(abbreviate-file-name (shrink-path-file local-name)))
'face 'syd-eshell-local-name)
(propertize " $"
'face (if (zerop eshell-last-command-status)
'success
'error))
" ")))
(defvar syd-eshell--prompt-regexp (rx bol (* (not (any "\n$"))) " $ "))
(set-popup-rule! "^\\*eshell-popup"
:vslot -5 :size 13 :select t :modeline nil :quit nil :ttl nil)
(use-package eshell
:init
(defvar syd-eshell-data-dir (file-name-concat syd-data-dir
"eshell"))
(make-directory syd-eshell-data-dir t)
:custom
((eshell-banner-message
'(format "🦌 %s %s }:3\n"
@@ -77,42 +171,32 @@
(eshell-glob-case-insensitive t)
(eshell-error-if-no-glob t)
(eshell-history-file-name (file-name-concat
syd-data-dir "eshell" "history"))
syd-eshell-data-dir "history"))
(eshell-last-dir-ring-file-name (file-name-concat
syd-data-dir "eshell" "lastdir")))
syd-eshell-data-dir "lastdir"))
(eshell-prompt-function #'syd-eshell--prompt-fn)
(eshell-prompt-regexp syd-eshell--prompt-regexp))
:general
(:keymaps 'syd-leader-open-map
"e" #'syd-eshell/toggle)
(:keymaps 'eshell-mode-map
:states 'insert
"C-d" #'syd-eshell-C-d)
(:keymaps 'eshell-mode-map
:states '(normal insert)
"C-j" #'eshell-next-matching-input-from-input
"C-k" #'eshell-previous-matching-input-from-input)
:config
;; When cd'd into a TRAMP remote, automatically expand '/' to the TRAMP
;; notation referring to the remote's root.
(add-to-list 'eshell-modules-list 'eshell-elecslash)
(require 'syd-buffers)
(add-hook 'eshell-mode-hook #'syd-mark-buffer-as-real)
;; UI enhancements.
(defun syd-eshell-remove-fringes-h ()
(set-window-fringes nil 0 0)
(set-window-margins nil 1 nil))
(defun syd-eshell-enable-text-wrapping-h ()
(visual-line-mode +1)
(set-display-table-slot standard-display-table 0 ?\ ))
(add-hook 'eshell-mode-hook #'syd-eshell-remove-fringes-h)
(add-hook 'eshell-mode-hook #'syd-eshell-enable-text-wrapping-h)
(with-eval-after-load 'hide-mode-line
(add-hook 'eshell-mode-hook #'hide-mode-line-mode))
;; Remove hscroll-margin in shells, otherwise you get jumpiness when the
;; cursor comes close to the left/right edges of the window.
(defun syd-eshell-disable-hscroll-margin ()
(setq hscroll-margin 0))
(add-hook 'eshell-mode-hook #'syd-eshell-disable-hscroll-margin))
(set-popup-rule! "^\\*eshell-popup"
:vslot -5 :size 0.35 :select t :modeline nil :quit nil :ttl nil)
(syd-eshell--init-ui-hacks))
(provide 'syd-eshell)