;;; syd-eshell.el -*- lexical-binding: t; -*- (require 'ring) (require 'cl-lib) (defvar eshell-buffer-name "*eshell*") (defvar syd-eshell-buffers (make-ring 25) "List of open eshell buffers.") (defun syd-eshell-buffers () "TODO" (ring-elements syd-eshell-buffers)) ;;;###autoload (defun syd-eshell-run-command (command &optional buffer) "TODO" (let ((buffer (or buffer (if (eq major-mode 'eshell-mode) (current-buffer) (cl-find-if #'buffer-live-p (syd-eshell-buffers)))))) (unless buffer (user-error "No living eshell buffers available")) (unless (buffer-live-p buffer) (user-error "Cannot operate on a dead buffer")) (with-current-buffer buffer (goto-char eshell-last-output-end) (goto-char (line-end-position)) (insert command) (eshell-send-input nil t)))) ;;;###autoload (defun syd-eshell/toggle (arg &optional command) "Toggle eshell popup window." (interactive "P") (let ((eshell-buffer (get-buffer-create (format "*eshell-popup:%s*" (if (bound-and-true-p persp-mode) (safe-persp-name (get-current-persp)) "main")))) confirm-kill-processes current-prefix-arg) (when arg (when-let* ((win (get-buffer-window eshell-buffer))) (delete-window win)) (when (buffer-live-p eshell-buffer) (with-current-buffer eshell-buffer (fundamental-mode) (erase-buffer)))) (if-let* ((win (get-buffer-window eshell-buffer))) (let (confirm-kill-processes) (delete-window win) (ignore-errors (kill-buffer eshell-buffer))) (with-current-buffer eshell-buffer (syd-mark-buffer-as-real) (if (eq major-mode 'eshell-mode) (run-hooks 'eshell-mode-hook) (eshell-mode)) (when command (syd-eshell-run-command command eshell-buffer))) (pop-to-buffer eshell-buffer)))) (use-package eshell :custom ((eshell-banner-message '(format "🦌 %s %s }:3\n" (propertize (format " %s " (string-trim (buffer-name))) 'face 'mode-line-highlight) (propertize (current-time-string) 'face 'font-lock-keyword-face))) (eshell-scroll-to-bottom-on-input 'all) (eshell-scroll-to-bottom-on-output 'all) (eshell-kill-processes-on-exit t) (eshell-hist-ignoredups t) (eshell-glob-case-insensitive t) (eshell-error-if-no-glob t) (eshell-history-file-name (file-name-concat syd-data-dir "eshell" "history")) (eshell-last-dir-ring-file-name (file-name-concat syd-data-dir "eshell" "lastdir"))) :general (:keymaps 'syd-leader-open-map "e" #'syd-eshell/toggle) (:keymaps 'eshell-mode-map :states '(normal insert) "C-j" #'eshell-next-matching-input-from-input "C-k" #'eshell-previous-matching-input-from-input) :config (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) (provide 'syd-eshell)