blob: 6bcef86521d72b5ec041d0370499672ace87c518 (
plain) (
tree)
|
|
(require 'eshell)
(require 'esh-mode)
(require 'esh-module)
(setq eshell-modules-list
'(eshell-alias
eshell-basic
eshell-cmpl
eshell-dirs
eshell-glob
eshell-hist
eshell-ls
eshell-pred
eshell-prompt
eshell-script
eshell-term
eshell-tramp
eshell-unix))
(require 'em-alias)
(require 'em-basic)
(require 'em-dirs)
(require 'em-glob)
(require 'em-hist)
(require 'em-smart)
(require 'em-term)
(require 'em-tramp)
(require 'em-prompt)
(defun fcuny/eshell-mode-setup ()
(eshell/alias "e" "find-file $1")
(eshell/alias "emacs" "find-file $1")
(eshell/alias "ee" "find-file-other-window $1")
(eshell/alias "ll" "ls -l")
(eshell/alias "d" "dired $1")
(eshell/alias "gs" "magit-status")
(eshell/alias "gd" "magit-diff-unstaged")
(eshell/alias "gds" "magit-diff-staged")
(eshell/alias "rg" "counsel-rg")
(eshell/alias "cal" "calendar")
(eshell/alias "agenda" "org-agenda")
;; Disable current line highlighting.
(setq-local global-hl-line-mode nil))
(defun eshell/gst (&rest args)
(magit-status (pop args) nil)
(eshell/echo)) ;; The echo command suppresses output
(defun fcuny/eshell--open-or-cd (path)
"Cd to PATH if path is a directory ((file-name-directory path) => t), otherwise open PATH via `find-file'."
(interactive)
(if (file-directory-p path)
(progn
(goto-char (point-max))
(insert (concat "cd " path))
(eshell-send-input))
(find-file path)))
(defun fcuny/eshell-open-file-at-point ()
(interactive)
(let ((filename (symbol-name (symbol-at-point))))
(cond
((file-readable-p filename)
(fcuny/eshell--open-or-cd filename))
((file-readable-p (expand-file-name filename))
(fcuny/eshell--open-or-cd (expand-file-name filename))))))
(defun fcuny/shorten-path (path &optional max-len)
"Return a potentially trimmed-down version of the directory PATH, replacing
parent directories with their initial characters to try to get the character
length of PATH (sans directory slashes) down to MAX-LEN."
(let* ((components (split-string (abbreviate-file-name path) "/"))
(host (propertize (system-name) 'face `(:background "#4ba9aa")))
(max-len (or max-len 30))
(len (+ (1- (length components))
(cl-reduce '+ components :key 'length)))
(str ""))
(while (and (> len max-len)
(cdr components))
(setq str (concat str
(cond ((= 0 (length (car components))) "/")
((= 1 (length (car components)))
(concat (car components) "/"))
(t
(if (string= "."
(string (elt (car components) 0)))
(concat (substring (car components) 0 2)
"/")
(string (elt (car components) 0) ?/)))))
len (- len (1- (length (car components))))
components (cdr components)))
(concat host " " str (cl-reduce (lambda (a b) (concat a "/" b)) components))))
(defun fcuny/eshell-prompt ()
"Sets the prompt for eshell. If the current path is on a remote
host and starts with `ssh:', then we replace the prompt with
`@<hostname>' to indicate we're on a remote host."
(concat
(let ((absolute-path (eshell/pwd)))
(if (string-match "/ssh:\\(.+\\):" absolute-path)
(replace-match (propertize (concat "@" (match-string 1 absolute-path) " ") 'face `(:background "#4ba9aa")) nil nil absolute-path)
(fcuny/shorten-path absolute-path)))
(if (= (user-uid) 0) " # " " $ ")))
(defun fcuny/eshell-here ()
"Opens up a new shell in the directory associated with the current
buffer's file. The eshell is renamed to match that directory to make
multiple eshell windows easier."
(interactive)
(let* ((parent (if (buffer-file-name)
(file-name-directory (buffer-file-name))
default-directory))
(name (car (last (split-string parent "/" t)))))
(split-window-horizontally)
(other-window 1)
(eshell "new")
(rename-buffer (concat "*eshell: " name "*"))
(insert (concat "ls " "-lh"))
(eshell-send-input)))
(defun fcuny/eshell-main ()
(eshell "new")
(rename-buffer "*eshell: main session*")
(insert "ls -l")
(eshell-send-input))
(defvar-local fcuny/eshell-output-buffer "*Exported eshell output*"
"Name of buffer with the last output of Eshell command.")
(defvar-local fcuny/eshell-output-delimiter "---"
"Delimiter for successive `prot-eshell-export' outputs.")
(defun fcuny/eshell--command-prompt-output ()
"Capture last command prompt and its output."
(let ((beg (save-excursion
(goto-char (eshell-beginning-of-input))
(goto-char (point-at-bol)))))
(when (derived-mode-p 'eshell-mode)
(buffer-substring-no-properties beg (eshell-end-of-output)))))
;; https://gitlab.com/protesilaos/dotfiles/-/blob/master/emacs/.emacs.d/prot-lisp/prot-eshell.el#L114
(defun fcuny/eshell-export ()
"Produce a buffer with output of the last Eshell command.
If `fcuny/eshell-output-buffer' does not exist, create it. Else
append to it, while separating multiple outputs with
`fcuny/eshell-output-delimiter'."
(interactive)
(let ((eshell-output (fcuny/eshell--command-prompt-output)))
(with-current-buffer (get-buffer-create fcuny/eshell-output-buffer)
(goto-char (point-max))
(unless (eq (point-min) (point-max))
(insert (format "\n%s\n\n" fcuny/eshell-output-delimiter)))
(goto-char (point-at-bol))
(insert eshell-output)
(switch-to-buffer-other-window (current-buffer)))))
;; eshell time and notification
(defvar-local eshell-current-command-start-time nil)
;; https://www.birkey.co/2021-06-20-why-eshell-part-1.html
(defun fcuny/eshell-current-command-start ()
(setq eshell-current-command-start-time (current-time)))
(defun fcuny/eshell-current-command-stop ()
(when eshell-current-command-start-time
(let ((elapsed-time (float-time
(time-subtract (current-time)
eshell-current-command-start-time))))
(if (> elapsed-time 5)
(eshell-interactive-print
(format "Finished in: %.0fs\n" elapsed-time)))))
(setq eshell-current-command-start-time nil))
(defun fcuny/eshell-current-command-time-track ()
(add-hook 'eshell-pre-command-hook #'fcuny/eshell-current-command-start nil t)
(add-hook 'eshell-post-command-hook #'fcuny/eshell-current-command-stop nil t))
(use-package eshell
:hook ((eshell-mode . fcuny/eshell-mode-setup)
(eshell-mode . fcuny/eshell-current-command-time-track)
(eshell-mode . eshell-smart-initialize))
:commands (eshell eshell-command)
:bind (("C-c e h" . fcuny/eshell-here)
("C-c e e" . fcuny/eshell-export)
("C-c r" . counsel-esh-history)
:map eshell-mode-map
("C-o" . fcuny/eshell-open-file-at-point))
:custom
(eshell-scroll-to-bottom-on-input 'all)
(eshell-error-if-no-glob t)
(eshell-hist-ignoredups t)
(eshell-save-history-on-exit t)
(eshell-cd-on-directory t)
(eshell-prefer-lisp-functions nil)
(eshell-where-to-jump 'begin)
(eshell-review-quick-commands nil)
(eshell-smart-space-goes-to-end t)
(eshell-prompt-function 'fcuny/eshell-prompt)
(tramp-shell-prompt-pattern "^[^$>\n]*[#$%>] *\\(\[[0-9;]*[a-zA-Z] *\\)*")
(eshell-destroy-buffer-when-process-dies t))
(use-package eshell-bookmark
:ensure t
:hook (eshell-mode . eshell-bookmark-setup))
(provide 'fcuny-eshell)
|