diff --git a/modules/defuns/defuns-eshell.el b/modules/defuns/defuns-eshell.el index eca96d3ae..1ec2e5970 100644 --- a/modules/defuns/defuns-eshell.el +++ b/modules/defuns/defuns-eshell.el @@ -3,8 +3,22 @@ (require 'eshell) (defvar doom-eshell-buffers '() "") -(defvar doom-eshell-height 16 "") -(defvar-local doom-eshell-direction nil "") + +;;;###autoload +(defun doom|eshell-cleanup () + (when (eq major-mode 'eshell-mode) + (setq doom-eshell-buffers (delete (current-buffer) doom-eshell-buffers)) + (cond ((doom/popup-p) + (delete-window)) + ((string= "eshell" (wg-workgroup-name (wg-current-workgroup t))) + (if (one-window-p) + (doom:workgroup-delete) + (delete-window)))))) + +;;;###autoload +(defun doom|eshell-init () + (when (eq major-mode 'eshell-mode) + (add-to-list 'doom-eshell-buffers (current-buffer)))) (defun doom--eshell-outside-prompt-p (&optional offset) (< (point) eshell-last-output-end)) @@ -20,39 +34,14 @@ ;;;###autoload (defun doom/eshell-split () (interactive) - (select-window (split-window-vertically doom-eshell-height)) - (setq-local doom-eshell-direction 'below) - (doom--eshell-init t)) + (select-window (split-window-vertically)) + (doom:eshell)) ;;;###autoload (defun doom/eshell-vsplit () (interactive) (select-window (split-window-horizontally)) - (setq-local doom-eshell-direction 'right) - (doom--eshell-init t)) - -;;;###autoload -(defun doom/eshell (&optional same &rest _) - (interactive) - (doom--eshell-init same) - ;; (if doom-eshell-buffers - ;; (let* ((buf (car (reverse doom-eshell-buffers))) - ;; (win (get-buffer-window buf))) - ;; (if (and win (window-live-p win)) - ;; (select-window win) - ;; (select-window (split-window-vertically doom-eshell-height)) - ;; (evil-window-move-very-bottom) - ;; (switch-to-buffer buf t t))) - ;; (doom--eshell-init same)) - ) - -(defun doom--eshell-init (&optional same) - (unless same (select-window (split-window))) - (eshell (max 0 (1- (length doom-eshell-buffers)))) - (unless same - (evil-window-move-very-bottom) - (evil-window-set-height doom-eshell-height)) - (set-window-dedicated-p (selected-window) t)) + (doom:eshell)) ;;;###autoload (defun doom/eshell-prompt () @@ -60,6 +49,39 @@ (propertize (doom--eshell-current-git-branch) 'face 'font-lock-function-name-face) (propertize " λ " 'face 'font-lock-constant-face))) +;;;###autoload (autoload 'doom:eshell "defuns-eshell" nil t) +(evil-define-command doom:eshell (&optional bang) + "Create a shell in the current buffer. If BANG, use a popup buffer." + (interactive "") + (let ((buf (if bang + (get-buffer-create "*eshell:popup*") + (generate-new-buffer eshell-buffer-name)))) + (with-current-buffer buf + (unless (eq major-mode 'eshell-mode) (eshell-mode))) + (if bang + (doom/popup-buffer buf) + (pop-to-buffer-same-window buf)))) + +;;;###autoload +(defun doom/eshell-tab () + "Create a separate tab for the shell." + (interactive) + (unless (wg-switch-to-workgroup (wg-get-workgroup "eshell" t) t) + (doom:tab-create nil "eshell")) + (let ((buf (--find (string-match-p "^\\*eshell" (buffer-name (window-buffer it))) + (doom/get-visible-windows)))) + (if buf + (select-window (get-buffer-window buf)) + (doom:eshell)) + (doom/workgroup-display))) + +;;;###autoload +(defun doom/eshell-frame () + "Create a separate frame for the shell." + (interactive) + (doom/new-frame) + (doom:eshell)) + ;;;###autoload (defun doom/eshell-evil-append () (interactive) @@ -100,5 +122,19 @@ (user-error "Cannot edit read-only region") (call-interactively 'evil-replace-state))) +;;;###autoload +(defun doom/eshell-evil-change () + (interactive) + (when (doom--eshell-outside-prompt-p) + (goto-char eshell-last-output-end)) + (call-interactively 'evil-change)) + +;;;###autoload +(defun doom/eshell-evil-change-line () + (interactive) + (when (doom--eshell-outside-prompt-p) + (goto-char eshell-last-output-end)) + (call-interactively 'evil-change-line)) + (provide 'defuns-eshell) ;;; defuns-eshell.el ends here diff --git a/modules/module-eshell.el b/modules/module-eshell.el index 3d045ad04..3a92ca806 100644 --- a/modules/module-eshell.el +++ b/modules/module-eshell.el @@ -1,5 +1,10 @@ ;;; module-eshell.el --- -*- no-byte-compile: t; -*- +;; see: +;; + `doom:eshell' (open in current buffer or popup) +;; + `doom/eshell-tab' (open in separate tab) +;; + `doom/eshell-frame' (open in separate frame) + (use-package eshell :init (setq eshell-directory-name (concat doom-temp-dir "/eshell") @@ -16,8 +21,11 @@ :config (evil-set-initial-state 'eshell-mode 'insert) + (def-popup! "^\\*eshell:popup\\*$" :regexp t :align below :size 25 :select t) (defun doom|eshell-keymap-setup () + "Setup eshell keybindings. This must be done in a hook because eshell +redefines its keys every time `eshell-mode' is enabled." (map! :map eshell-mode-map :n "i" 'doom/eshell-evil-prepend-maybe :n "I" 'doom/eshell-evil-prepend @@ -25,20 +33,16 @@ :n "A" 'doom/eshell-evil-append :n "r" 'doom/eshell-evil-replace-maybe :n "R" 'doom/eshell-evil-replace-state-maybe + :n "c" 'doom/eshell-evil-change + :n "C" 'doom/eshell-evil-change-line + :i "" 'eshell-pcomplete :i "C-u" 'eshell-kill-input :i "SPC" 'self-insert-command :m "" 'doom/eshell-evil-append - :n [remap doom/evil-window-split] 'doom/eshell-split - :n [remap doom/evil-window-vsplit] 'doom/eshell-vsplit)) - - (defun doom|eshell-init () - (when (eq major-mode 'eshell-mode) - (add-to-list 'doom-eshell-buffers (current-buffer)))) - - (defun doom|eshell-cleanup () - (when (eq major-mode 'eshell-mode) - (setq doom-eshell-buffers (delete (current-buffer) doom-eshell-buffers)) - (delete-window))) + :n [remap evil-window-split] 'doom/eshell-split + :n [remap evil-window-vsplit] 'doom/eshell-vsplit + :n [remap evil-record-macro] 'eshell-life-is-too-much + [remap doom/close-window-or-tab] 'eshell-life-is-too-much)) ;; Close window on exit (add-hook 'eshell-exit-hook 'doom|eshell-cleanup) @@ -46,7 +50,28 @@ (add-hook 'eshell-mode-hook 'doom|eshell-keymap-setup) (add-hook 'eshell-mode-hook 'doom-hide-mode-line-mode) - (add-hook 'eshell-mode-hook 'hl-line-mode)) + + (add-hook! eshell-mode + (add-hook 'evil-insert-state-exit-hook 'hl-line-mode nil t) + (add-hook 'evil-insert-state-entry-hook (lambda () (hl-line-mode -1)) nil t)) + + ;; Aliases + (setq eshell-command-aliases-list + '(("q" "exit") + ("l" "ls -1") + ("ll" "ls -l") + ("la" "ls -la") + ("g" "hub") + ("gs" "hub status --oneline .") + ("gss" "hub status --oneline"))) + + ;; Custom commands + (defun eshell/e (file) + (eshell-eval (cond ((doom/popup-p) + (doom/popup-save (find-file file)) + 0) + (t (find-file file) + 0))))) (provide 'module-eshell) ;;; module-eshell.el ends here diff --git a/private/my-bindings.el b/private/my-bindings.el index 7e7d378ef..42c195995 100644 --- a/private/my-bindings.el +++ b/private/my-bindings.el @@ -24,7 +24,7 @@ "A-/" 'evil-commentary-line "M-b" 'doom:build "C-`" 'doom/popup-last-buffer - "M-~" 'doom/eshell + "C-~" (λ! (doom:eshell t)) ;; Text-scaling "M-0" (λ! (text-scale-set 0)) "M-=" 'text-scale-increase diff --git a/private/my-commands.el b/private/my-commands.el index 7554856fa..b0c80492b 100644 --- a/private/my-commands.el +++ b/private/my-commands.el @@ -45,7 +45,7 @@ (ex! "http" 'httpd-start) ; start http server (ex! "rx" 'doom:regex) ; open re-builder (ex! "repl" 'doom:repl) ; invoke or send to repl -(ex! "sh[ell]" 'doom/eshell) +(ex! "sh[ell]" 'doom:eshell) (ex! "t[mux]" 'doom:tmux) ; send to tmux (ex! "tcd" 'doom:tmux-cd) ; cd to default-directory in tmux (ex! "x" 'doom:scratch-buffer)