Better distrobox and sudo tramp support
This commit is contained in:
@ -5,6 +5,8 @@
|
||||
(require 'vc-git)
|
||||
(require 'eshell)
|
||||
(require 'cl-lib)
|
||||
(require 'tramp)
|
||||
(eval-when-compile (require 'rx))
|
||||
|
||||
;;; Configuration options
|
||||
(defgroup eshell-starship nil
|
||||
@ -35,7 +37,7 @@ This will also update all eshell-starship explain buffers that need updating."
|
||||
(revert-buffer)))))))
|
||||
|
||||
(defcustom eshell-starship-module-order
|
||||
'("remote" "cwd" "git" "vc" t "cmd-time" "arrow")
|
||||
'("remote" "root" "cwd" "git" "vc" t "cmd-time" "newline" "container" "arrow")
|
||||
"The order of modules for eshell-starship.
|
||||
This is a list with each element being a module name. The special value t can
|
||||
appear at most once to denote \"all remaining modules\"."
|
||||
@ -58,6 +60,22 @@ appear at most once to denote \"all remaining modules\"."
|
||||
:tag "Suppress eshell-starship explore refresh messages"
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom eshell-starship-overridden-remote-methods
|
||||
'("docker" "podman" "kubernetes" "doas" "su" "sudo" "sudoedit")
|
||||
"List of `file-remote-p' mwthods that should NOT be considered remote.
|
||||
Any eshell buffer with a `default-directory' managed by one of these methods
|
||||
will not be considered remote and all modules that would be disabled because of
|
||||
the remote directory will work as usual."
|
||||
:group 'eshell-starship
|
||||
:tag "Overridden Remote Methods"
|
||||
:type '(repeat (string :tag "Method")))
|
||||
|
||||
(defcustom eshell-starship-verbose-tramp 1
|
||||
"Tramp verbosity level when rendering the prompt."
|
||||
:group 'eshell-starship
|
||||
:tag "Tramp Verbosity Level"
|
||||
:type 'integer)
|
||||
|
||||
(defface eshell-starship-icon-face '((t :inherit default))
|
||||
"Face to use when drawing module icons.
|
||||
Note that the foreground color will be overridden by the module."
|
||||
@ -162,7 +180,7 @@ be nil.")
|
||||
:documentation "Weather the module should be run if
|
||||
`default-directory' is a `file-remote-p'.")
|
||||
(action :initarg :action
|
||||
:initform 'ignore
|
||||
:initform 'string
|
||||
:accessor eshell-starship-module-action
|
||||
:type function
|
||||
:documentation "A function that produces the main text for the
|
||||
@ -304,12 +322,16 @@ Example:
|
||||
(defun eshell-starship--get-current-dir ()
|
||||
"Get dir for `eshell-starship--prompt-function'."
|
||||
(concat
|
||||
(propertize (eshell-starship--limit-path-parts
|
||||
3 (if-let ((worktree (vc-root-dir))
|
||||
(parent (file-name-parent-directory worktree)))
|
||||
(file-relative-name default-directory parent)
|
||||
(eshell-starship--replace-home-with-tilda default-directory)))
|
||||
'face '(:foreground "dark turquoise"))
|
||||
(propertize
|
||||
(eshell-starship--limit-path-parts
|
||||
3 (let ((cwd (or (file-remote-p default-directory 'localname)
|
||||
default-directory)))
|
||||
(if-let ((worktree (vc-root-dir))
|
||||
(parent (file-name-parent-directory worktree)))
|
||||
(file-relative-name cwd (or (file-remote-p parent 'localname)
|
||||
parent))
|
||||
(eshell-starship--replace-home-with-tilda cwd))))
|
||||
'face '(:foreground "dark turquoise"))
|
||||
(unless (file-writable-p default-directory)
|
||||
" ")))
|
||||
|
||||
@ -721,24 +743,56 @@ This does not mean anything if pyenv-mode is not installed.")
|
||||
|
||||
;;; Misc modules
|
||||
(eshell-starship-defmodule remote
|
||||
:icon "🌐"
|
||||
:icon "🌐 "
|
||||
:color "light blue"
|
||||
:predicate (lambda ()
|
||||
(file-remote-p default-directory))
|
||||
:predicate
|
||||
(lambda ()
|
||||
(eshell-starship--remote-for-modules-p default-directory))
|
||||
:action
|
||||
(lambda ()
|
||||
(or (file-remote-p default-directory 'host) ""))
|
||||
:reload-on 'cwd
|
||||
:doc "A small icon if the working directory is remote.")
|
||||
|
||||
(eshell-starship-defmodule root
|
||||
:predicate
|
||||
(lambda ()
|
||||
(member (file-remote-p default-directory 'method)
|
||||
'("doas" "sudo" "su" "sudoedit")))
|
||||
:action
|
||||
(lambda ()
|
||||
(format "%s in"
|
||||
(propertize (file-remote-p default-directory 'user)
|
||||
'face '(:weight bold :foreground "red"))))
|
||||
:reload-on 'cwd
|
||||
:doc "Show the current sudo or doas user.")
|
||||
|
||||
(eshell-starship-defmodule newline
|
||||
:predicate 'always
|
||||
:action (lambda () (propertize "\n" 'read-only t 'rear-nonsticky t))
|
||||
:doc "A newline in the prompt.")
|
||||
|
||||
(eshell-starship-defmodule container
|
||||
:icon "⬢ "
|
||||
:color "firebrick"
|
||||
:predicate (lambda ()
|
||||
(member (file-remote-p default-directory 'method)
|
||||
'("docker" "podman" "kubernetes")))
|
||||
:action (lambda ()
|
||||
(format "[%s]" (file-remote-p default-directory 'host)))
|
||||
:reload-on 'cwd
|
||||
:doc "The name of the current container.")
|
||||
|
||||
(eshell-starship-defmodule arrow
|
||||
:predicate 'always
|
||||
:reload-on 'always
|
||||
:action (lambda ()
|
||||
(concat
|
||||
(propertize "\n" 'read-only t 'rear-nonsticky t)
|
||||
(propertize
|
||||
"❯ " 'face `(:foreground
|
||||
,(if (= eshell-last-command-status 0)
|
||||
"lime green"
|
||||
"red"))
|
||||
'rear-nonsticky t)))
|
||||
(propertize
|
||||
"❯ " 'face `(:foreground
|
||||
,(if (= eshell-last-command-status 0)
|
||||
"lime green"
|
||||
"red"))
|
||||
'rear-nonsticky t))
|
||||
:doc "An arrow that appears next to where you type.")
|
||||
|
||||
|
||||
@ -773,36 +827,52 @@ That is, if EXT is \"pkg.tar.gz\", this will return
|
||||
(substring name (1+ idx))
|
||||
""))
|
||||
|
||||
(defun eshell-starship--remote-for-modules-p (file)
|
||||
"Return non-nil if FILE is remote for the purpose of running modules."
|
||||
(let ((method (file-remote-p file 'method)))
|
||||
(and method
|
||||
(not (member method eshell-starship-overridden-remote-methods)))))
|
||||
|
||||
(defun eshell-starship--modules-for-dir (dir)
|
||||
"Return a list of modules that are applicable to DIR."
|
||||
(seq-uniq
|
||||
(nconc
|
||||
(mapcan
|
||||
(lambda (entry)
|
||||
(let ((name (car entry))
|
||||
(is-dir (eq t (file-attribute-type (cdr entry)))))
|
||||
(if is-dir
|
||||
(copy-sequence (eshell-starship--module-by :dirs name))
|
||||
(apply 'nconc
|
||||
(eshell-starship--module-by :files name)
|
||||
(mapcar (lambda (ext)
|
||||
(copy-sequence (eshell-starship--module-by
|
||||
:extensions ext)))
|
||||
(eshell-starship--permute-extension
|
||||
(eshell-starship--file-name-extension name)))))))
|
||||
(directory-files-and-attributes dir nil nil t))
|
||||
(let ((default-directory dir))
|
||||
(cl-loop for (name is-dir module) in eshell-starship--extra-module-files
|
||||
when (and is-dir (file-directory-p name))
|
||||
collect module
|
||||
when (and (not is-dir) (file-exists-p name))
|
||||
collect module))
|
||||
(let ((default-directory dir))
|
||||
(cl-loop for module being the hash-values of eshell-starship-modules
|
||||
for predicate = (eshell-starship-module-predicate module)
|
||||
when (funcall predicate)
|
||||
collect module)))
|
||||
'eq))
|
||||
(let ((is-remote (eshell-starship--remote-for-modules-p dir)))
|
||||
(seq-uniq
|
||||
(nconc
|
||||
(cl-delete-if
|
||||
(lambda (module)
|
||||
(and is-remote (not (eshell-starship-module-allow-remote-p module))))
|
||||
(mapcan
|
||||
(lambda (entry)
|
||||
(let ((name (car entry))
|
||||
(is-dir (eq t (file-attribute-type (cdr entry)))))
|
||||
(if is-dir
|
||||
(copy-sequence (eshell-starship--module-by :dirs name))
|
||||
(apply 'nconc
|
||||
(eshell-starship--module-by :files name)
|
||||
(mapcar (lambda (ext)
|
||||
(copy-sequence (eshell-starship--module-by
|
||||
:extensions ext)))
|
||||
(eshell-starship--permute-extension
|
||||
(eshell-starship--file-name-extension name)))))))
|
||||
(directory-files-and-attributes dir nil nil t)))
|
||||
(let ((default-directory dir))
|
||||
(cl-loop for (name is-dir module) in eshell-starship--extra-module-files
|
||||
when (and (or (not is-remote)
|
||||
(eshell-starship-module-allow-remote-p module))
|
||||
is-dir (file-directory-p name))
|
||||
collect module
|
||||
when (and (or (not is-remote)
|
||||
(eshell-starship-module-allow-remote-p module))
|
||||
(not is-dir) (file-exists-p name))
|
||||
collect module))
|
||||
(let ((default-directory dir))
|
||||
(cl-loop for module being the hash-values of eshell-starship-modules
|
||||
for predicate = (eshell-starship-module-predicate module)
|
||||
when (and (or (not is-remote)
|
||||
(eshell-starship-module-allow-remote-p module))
|
||||
(funcall predicate))
|
||||
collect module)))
|
||||
'eq)))
|
||||
|
||||
(defun eshell-starship--propertize-face (str append &rest faces)
|
||||
"Copy STR and add FACES to its text properties.
|
||||
@ -902,9 +972,17 @@ Return a hash table mapping module names to their output."
|
||||
(t
|
||||
(push (gethash cur-name output) pre)
|
||||
(remhash cur-name output))))
|
||||
(mapconcat 'identity
|
||||
(nconc (nreverse pre) (hash-table-values output) (nreverse post))
|
||||
" ")))
|
||||
(cl-loop for (part . rest) = (nconc (nreverse pre)
|
||||
(hash-table-values output)
|
||||
(nreverse post))
|
||||
then rest
|
||||
while part
|
||||
concat part
|
||||
unless (or (string-suffix-p "\n" part)
|
||||
(string-empty-p part)
|
||||
(not (car rest))
|
||||
(string-prefix-p "\n" (car rest)))
|
||||
concat " ")))
|
||||
|
||||
(defun eshell-starship--render-prompt ()
|
||||
"Actually produce the prompt."
|
||||
@ -918,7 +996,8 @@ Return a hash table mapping module names to their output."
|
||||
|
||||
(defun eshell-starship--prompt-function ()
|
||||
"Function for `eshell-prompt-function'."
|
||||
(let (start-time prompt end-time)
|
||||
(let ((tramp-verbose eshell-starship-verbose-tramp)
|
||||
start-time prompt end-time)
|
||||
(setq start-time (float-time)
|
||||
prompt (eshell-starship--render-prompt)
|
||||
end-time (float-time)
|
||||
@ -940,10 +1019,12 @@ Return a hash table mapping module names to their output."
|
||||
(defun eshell-starship--enable ()
|
||||
"Enable eshell-starship."
|
||||
(setq-local eshell-starship--restore-state
|
||||
(buffer-local-set-state eshell-prompt-function
|
||||
'eshell-starship--prompt-function
|
||||
eshell-prompt-regexp "^❯ "
|
||||
eshell-highlight-prompt nil)
|
||||
(buffer-local-set-state
|
||||
eshell-prompt-function
|
||||
'eshell-starship--prompt-function
|
||||
;; temporary fix until the next version where eshell uses fields
|
||||
eshell-prompt-regexp (rx bol (? "⬢ [" (+ any) "] ") "❯ ")
|
||||
eshell-highlight-prompt nil)
|
||||
eshell-starship--module-cache (make-hash-table :test 'equal))
|
||||
(add-hook 'eshell-pre-command-hook
|
||||
#'eshell-starship--run-module-precmd-actions nil t)
|
||||
|
Reference in New Issue
Block a user