I have written utilities for choosing what information, icons, and faces your eshell prompt presents.
Example eshell prompts:
Eshell prompt customization takes place in
eshell-prompt-regexp. The former determines the content of your prompt
while the latter distinguishes your commands.
I define a macro
esh-section taking a name, an icon, a form or variable to be
evaluated, and optionally face properties. They create anonymous functions which
will be evaluated and concatenated at prompt-time.
(require 'dash) (require 's) (defmacro with-face (STR &rest PROPS) "Return STR propertized with PROPS." `(propertize ,STR 'face (list ,@PROPS))) (defmacro esh-section (NAME ICON FORM &rest PROPS) "Build eshell section NAME with ICON prepended to evaled FORM with PROPS." `(setq ,NAME (lambda () (when ,FORM (-> ,ICON (concat esh-section-delim ,FORM) (with-face ,@PROPS)))))) (defun esh-acc (acc x) "Accumulator for evaluating and concatenating esh-sections." (--if-let (funcall x) (if (s-blank? acc) it (concat acc esh-sep it)) acc)) (defun esh-prompt-func () "Build `eshell-prompt-function'" (concat esh-header (-reduce-from 'esh-acc "" eshell-funcs) "\n" eshell-prompt-string))
Now lets define the needed configuration.
;; Separator between esh-sections (setq esh-sep " ") ; or " | " ;; Separator between an esh-section icon and form (setq esh-section-delim " ") ;; Eshell prompt header (setq esh-header "\n ") ; or "\n┌─" ;; Eshell prompt regexp and string. Unless you are varying the prompt by eg. ;; your login, these can be the same. (setq eshell-prompt-regexp " ") ; or "└─> " (setq eshell-prompt-string " ") ; or "└─> "
Now we are set to build some sections. A note, if a section's form returns nil, then it will be skipped, so the effect of eg. python virtual environments will only appear when you have an active venv.
(esh-section esh-dir "\xf07c" ; (faicon folder) (abbreviate-file-name (eshell/pwd)) '(:foreground "gold" :bold ultra-bold :underline t)) (esh-section esh-git "\xe907" ; (git icon) (magit-get-current-branch) '(:foreground "pink")) (esh-section esh-python "\xe928" ; (python icon) pyvenv-virtual-env-name) (esh-section esh-clock "\xf017" ; (clock icon) (format-time-string "%H:%M" (current-time)) '(:foreground "forest green")) ;; Below I implement a "prompt number" section (setq esh-prompt-num 0) (add-hook 'eshell-exit-hook (lambda () (setq esh-prompt-num 0))) (advice-add 'eshell-send-input :before (lambda (&rest args) (setq esh-prompt-num (incf esh-prompt-num)))) (esh-section esh-num "\xf0c9" ; (list icon) (number-to-string esh-prompt-num) '(:foreground "brown")) ;; Choose which eshell-funcs to enable (setq eshell-funcs (list esh-dir esh-git esh-python esh-clock esh-num)) ;; Enable the new eshell prompt (setq eshell-prompt-function 'esh-prompt-func)
Further extensions to explore are predicate-based face application for eg. distinguishing master and other branches and modeline-like foreground separation.
display/shell in my config will host the most recent iteration and all my other emacs tweaks.