diff --git a/modules/ui/modeline/config.el b/modules/ui/modeline/config.el index d90c39e84..9306ea66e 100644 --- a/modules/ui/modeline/config.el +++ b/modules/ui/modeline/config.el @@ -27,9 +27,22 @@ modeline.") "If non-nil, the bar is transparent, and only used to police the height of the mode-line.") -(defvar +modeline-buffer-path-function #'+modeline-file-path - "The function that returns the buffer name display for file-visiting -buffers.") +(defvar +modeline-buffer-path-function #'+modeline-file-path-with-project + "A function that returns, in list form, components of the buffer file name +display in the mode-line. + +Each item should either be a string or a a cons cell whose CAR is the path +component and CDR is the name of a face. + +Currently available functions: + ++ `+modeline-file-path-with-project': project/src/lib/file.c ++ `+modeline-file-path-from-project': src/lib/file.c ++ `+modeline-file-path-truncated-with-project': project/s/l/file.c ++ `+modeline-file-path-truncated-upto-project': ~/w/project/src/lib/file.c ++ `+modeline-file-path-truncated-upto-project-root': ~/w/p/s/lib/file.c ++ `+modeline-file-path-truncated': ~/w/p/s/l/file.c ++ `+modeline-file-name': file.c") ;; Convenience aliases (defvaralias 'mode-line-format-left '+modeline-format-left) @@ -236,27 +249,109 @@ buffers.") concat (if (eq idx len) "\"};" "\",\n"))) 'xpm t :ascent 'center))))) -(defun +modeline-file-path (&optional path) - (let ((buffer-file-name (or path buffer-file-name)) - (root (doom-project-root))) - (cond ((null root) - (propertize "%b" 'face 'doom-modeline-buffer-file)) - ((or (null buffer-file-name) - (directory-name-p buffer-file-name)) - (propertize (abbreviate-file-name (or buffer-file-name default-directory)) - 'face 'doom-modeline-buffer-path)) - ((let* ((true-filename (file-truename buffer-file-name)) - (relative-dirs (file-relative-name (file-name-directory true-filename) - root))) - (if (equal "./" relative-dirs) (setq relative-dirs "")) - (concat (propertize (concat (doom-project-name) "/") - 'face 'doom-modeline-buffer-project-root) - (propertize relative-dirs - 'face 'doom-modeline-buffer-path) - (propertize (file-name-nondirectory true-filename) - 'face 'doom-modeline-buffer-file))))))) +(defun +modeline-build-path (&optional path) + "Construct the file path for the `+modeline-buffer-id' segment using +`+mdoeline-buffer-path-function'. If the buffer has no `buffer-file-name', just +use `buffer-name'." + (let ((buffer-file-name (or path buffer-file-name))) + (if (or (eq major-mode 'dired-mode) + (null buffer-file-name)) + (propertize "%s" 'face 'doom-modeline-buffer-path) + (cl-loop for spec in (funcall +modeline-buffer-path-function) + if (stringp spec) concat spec + else concat (propertize (car spec) 'face (cdr spec)))))) -;; TODO Add shrink-path alternatives + +;; +;; Buffer file path styles +;; + +(defun +modeline-file-path-with-project () + "Returns the unaltered buffer file path relative to the project root's +parent. + +e.g. project/src/lib/file.c" + (let* ((project-root (doom-project-root)) + (true-filename (file-truename buffer-file-name)) + (relative-dirs (file-relative-name (file-name-directory true-filename) + project-root))) + (list (cons (concat (doom-project-name) "/") + 'doom-modeline-buffer-project-root) + (cons (if (equal "./" relative-dirs) "" relative-dirs) + 'doom-modeline-buffer-path) + (cons (file-name-nondirectory true-filename) + 'doom-modeline-buffer-file)))) + +(defun +modeline-file-path-from-project () + "Returns file path relative to the project root. + +e.g. src/lib/file.c + +Meant for `+modeline-buffer-path-function'." + (cdr (+modeline-file-path-with-project))) + +(defun +modeline-file-path-truncated-with-project () + "Returns file path relative to (and including) project root, with descendent +folders truncated. + +e.g. project/s/l/file.c + +Meant for `+modeline-buffer-path-function'." + (let* ((parts (+modeline-file-path-with-project)) + (dirs (car (nth 1 parts)))) + (setcar (nth 1 parts) + (shrink-path--dirs-internal dirs t)) + parts)) + +(defun +modeline-file-path-truncated-upto-project () + "Returns file path, truncating segments prior to the project. + +e.g. ~/w/project/src/lib/file.c + +Meant for `+modeline-buffer-path-function'." + (pcase-let + ((`(,root-parent ,root ,dir, file) + (shrink-path-file-mixed (doom-project-root) + (file-name-directory buffer-file-name) + buffer-file-name))) + (list (cons root-parent 'font-lock-comment-face) + (cons root 'doom-modeline-buffer-project-root) + (cons (concat "/" dir) 'doom-modeline-buffer-path) + (cons file 'doom-modeline-buffer-file)))) + +(defun +modeline-file-path-truncated-upto-project-root () + "Return file path, truncating segemnts prior to (and including) the project +root. + +e.g. ~/w/p/src/lib/file.c + +Meant for `+modeline-buffer-path-function'." + (let* ((parts (+modeline-file-path-truncated-upto-project)) + (root (car (nth 1 parts)))) + (setcar (nth 1 parts) + (let ((first (substring root 0 1))) + (if (equal first ".") + (substring root 0 2) + first))) + parts)) + +(defun +modeline-file-path-truncated () + "Return absolute file path with all directories truncated. + +e.g. ~/w/p/s/l/file.c + +Meant for `+modeline-buffer-path-function'." + (pcase-let ((`(,dir . ,file) (shrink-path-prompt buffer-file-name))) + (list (cons dir 'doom-modeline-buffer-path) + (cons file 'doom-modeline-buffer-file)))) + +(defun +modeline-file-name () + "Return buffer name. + +e.g. file.c + +Meant for `+modeline-buffer-path-function'." + (list (cons "%b" 'doom-modeline-buffer-path))) ;; @@ -339,7 +434,7 @@ buffers.") :init "%b" :faces t (if buffer-file-name - (funcall +modeline-buffer-path-function buffer-file-name) + (+modeline-build-path buffer-file-name) "%b")) (def-modeline-segment! +modeline-buffer-directory