From 5296e74f6ad4d5001553fd6b4a71f1a475e16409 Mon Sep 17 00:00:00 2001 From: Alexander Rosenberg Date: Wed, 31 Jan 2024 00:50:08 -0800 Subject: [PATCH] Add module stuff --- elisp/eshell-starship.el | 140 +++++++++++++++++++++++++-------------- 1 file changed, 90 insertions(+), 50 deletions(-) diff --git a/elisp/eshell-starship.el b/elisp/eshell-starship.el index 16976f3..6447341 100644 --- a/elisp/eshell-starship.el +++ b/elisp/eshell-starship.el @@ -7,60 +7,98 @@ (require 'eshell) (require 'cl-lib) -(defun eshell-starship--file-names-present-p (&rest names) - "Test if any of NAMES (wildcards supported) exist in default directory." - (catch 'found - (dolist (name names) - (when (seq-filter #'(lambda (name) - (not (string-prefix-p "." name))) - (file-expand-wildcards name)) - (throw 'found t))))) +(defvar eshell-starship-modules nil + "List of modules used by eshell-starship. +This should be an alist of (name function). The macro +`eshell-starship-defmodule' can help modify this list.") -(cl-defmacro eshell-starship-defmodule (name &body body - &key files - icon color allow-remote) - "Define a starship module called NAME. -FILES s used to detect weather to call the module. It is a list of wildcard -expressions. SYMBOL and COLOR control the output of the module. BODY should -return the string for the module, or nil if it could not be found." +(cl-defmacro eshell-starship-defmodule (name &key pred files dirs exts icon color + allow-remote action) + "Define an eshell-starship module called NAME. +The module will be added to `eshell-starship-modules'. + :PRED - a function that should return t if the module should be run + :FILES - a list of file names and wildcard expansions that will be used to + determine if the module should be run + :EXTS - save as FILES but mach any file with the given extensions + :DIRS - same as FILES, but for directories + :ICON - this is the string to print before the modules text + :COLOR - the color to print the modules text in + :ALLOW-REMOTE - weather to allow the module to run on remote machines + :ACTION - a function that will return the module text, or nil" (declare (indent defun)) - `(defun ,(intern (format "eshell-starship--module-%s-func" - name)) () - ,(format "Module function for eshell-starship module %s." name) - (or (when (and ,(if allow-remote t - '(not (file-remote-p default-directory))) - (eshell-starship--file-names-present-p ,files)) - (if-let (res (progn ,body)) - (concat " via " (propertize (concat ,icon " " res) - 'face (:foreground - ,color))))) - ""))) + `(setf (alist-get ',name eshell-starship-modules) + ,(list 'list pred files dirs exts icon color allow-remote action))) + +(cl-defmacro eshell-starship-find-version-function (command pattern + &rest format) + "Return a lambda that calls COMMAND. +COMMAND is in the form of (exec args...). The temp buffer that was used to run +COMMAND will then have `re-search-forward' run with PATTERN and FORMAT should +arguments to pass to `concat' to format the output." + (declare (indent defun)) + `(lambda () + (with-temp-buffer + (when (zerop (process-file ,(car command) nil t nil ,@(cdr command))) + (goto-char (point-min)) + (when (re-search-forward ,pattern nil t) + (concat ,@format)))))) (eshell-starship-defmodule cc - :files '("*.c" "*.h") + :exts '("c" "h") :icon "C" - :color "green yellow") + :color "green yellow" + :allow-remote nil + :action (eshell-starship-find-version-function + ("cc" "-v") + "^\\([-a-zA-Z]+\\) version \\([0-9]+\\.[0-9]+\\.[0-9]+\\)" + "v" (match-string 2) "-" (match-string 1))) -(defun eshell-starship--cc-status () - "Return the current CC version if C files exist in `default-directory'. -Returns an empty string if no C .c or .h files exist or if current dir is -remote." - (or (unless (file-remote-p default-directory) - (when (eshell-starship--file-names-exist-p "*.h" "*.c") - (with-temp-buffer - (when (zerop (process-file "cc" nil t nil "-v")) - (goto-char (point-min)) - (when (re-search-forward - "^\\([-a-zA-Z]+\\) version \\([0-9]+\\.[0-9]+\\.[0-9]+\\)" - nil t) - (concat " via " - (propertize (concat "C v" - (match-string 2) - "-" - (match-string 1)) - 'face - '(:foreground "green yellow"))) - ))))) "")) +(eshell-starship-defmodule cmake + :files '("CMakeLists.txt" "CMakeCache.txt") + :icon "󰔶" + :color "blue" + :allow-remote nil + :action (eshell-starship-find-version-function + ("cmake" "--version") + "cmake version \\([0-9]+\\.[0-9]+\\.[0-9]+\\)" + "v" (match-string 1))) + +(defun eshell-starship--exts-exist-p (&rest exts) + "Test if any files with EXTS at the end of their name exist in default dir." + (catch 'found + (dolist (ext exts) + (when (seq-filter #'(lambda (name) + (not (string-prefix-p "." name))) + (file-expand-wildcards (concat "*." ext))) + (throw 'found t))))) + +(defun eshell-starship--files-exist-p (&rest names) + "Test if any of NAMES exists and are files in default directory." + (catch 'found + (dolist (name names) + (when (file-exists-p name) + (throw 'found t))))) + +(defun eshell-starship--dirs-exist-p (&rest names) + "Test if any of NAMES exists and are files in default directory." + (catch 'found + (dolist (name names) + (when (file-directory-p name) + (throw 'found t))))) + +(defun eshell-starship--execute-modules () + "Execute all the modules in `eshell-starship-modules'." + (cl-loop + for (_ pred files dirs exts icon color allow-remote action) + in eshell-starship-modules + when (and (or allow-remote (not (file-remote-p default-directory))) + (or (and files (apply 'eshell-starship--files-exist-p files)) + (and dirs (apply' eshell-starship--dirs-exist-p dirs)) + (and exts (apply' eshell-starship--exts-exist-p exts)) + (and pred (funcall pred)))) + concat (if-let (result (funcall action)) + (concat " via " (propertize (concat icon " " result) + 'face `(:foreground ,color)))))) (defun eshell-starship--replace-home-with-tilda (path) "If PATH beings with $HOME (the environment variable), replace it with ~." @@ -210,7 +248,7 @@ For example, a revert. If there is no current operation, return nil." (when (zerop (vc-git-command t nil nil "status" "--porcelain=v2" "--branch" "--show-stash")) (goto-char (point-min)) - (cl-destructuring-bind (oid head upstream ahead behind stash) + (cl-destructuring-bind (oid head _upstream ahead behind stash) (eshell-starship--git-parse-status-headers) (let ((file-status (eshell-starship--git-file-status stash ahead behind)) @@ -277,11 +315,13 @@ END-TIME is the time when the command finished executing." (dir (eshell-starship--get-current-dir)) (prompt (concat "\n" + (if (file-remote-p default-directory) + (propertize "🌐 " 'face '(:foreground "light blue"))) (propertize dir 'face '(:foreground "dark turquoise")) (unless (file-writable-p dir) " ") (eshell-starship--vc-status) - (eshell-starship--cc-status) + (eshell-starship--execute-modules) (eshell-starship--last-command-time end-time) (propertize "\n" 'read-only t 'rear-nonsticky t) (propertize