branch: elpa/dirvish
commit 8002bb97619fea549d9a74d6a00e1448a1b6b25a
Author: Alex Lu <hellosimon1...@hotmail.com>
Commit: Alex Lu <hellosimon1...@hotmail.com>

    fix(core): rewrite mode line composer (#233)
    
    - ensure the mode-line context buffer is alive, closes #233.
    
    - rename dirvish--mode-line-fmt -> dirvish--mode-line-composer
    
    - dirvish-*-ml no longer takes dv as its argument
      It's unnecessary for most of the segment and may confuse users who need 
define
      their own segments.
    
    - compose mode/header line segments at runtime
      We may allow changing segments on the fly in the future.
    
    - calculate font scale at runtime
      Maybe support text-scale-adjust in the future.
---
 dirvish-widgets.el         |  1 +
 dirvish.el                 | 84 ++++++++++++++++++++++++----------------------
 extensions/dirvish-fd.el   |  6 ++--
 extensions/dirvish-side.el |  4 +--
 4 files changed, 49 insertions(+), 46 deletions(-)

diff --git a/dirvish-widgets.el b/dirvish-widgets.el
index 8672155809..13de8643c5 100644
--- a/dirvish-widgets.el
+++ b/dirvish-widgets.el
@@ -307,6 +307,7 @@ GROUP-TITLES is a list of group titles."
 (dirvish-define-mode-line path
   "Path of file under the cursor."
   (let* ((directory-abbrev-alist nil) ; TODO: support custom 
`directory-abbrev-alist'
+         (dv (dirvish-curr))
          (index (dired-current-directory))
          (face (if (dirvish--window-selected-p dv) 'dired-header 'shadow))
          (rmt (dirvish-prop :remote))
diff --git a/dirvish.el b/dirvish.el
index 926074aaa6..b060ff714a 100644
--- a/dirvish.el
+++ b/dirvish.el
@@ -363,7 +363,7 @@ A dirvish preview dispatcher is a function consumed by
   "Define a mode line segment NAME with BODY and DOCSTRING."
   (declare (indent defun) (doc-string 2))
   (let ((ml-name (intern (format "dirvish-%s-ml" name))))
-    `(defun ,ml-name (dv) ,docstring (ignore dv) ,@body)))
+    `(defun ,ml-name () ,docstring ,@body)))
 
 ;;;; Helpers
 
@@ -565,8 +565,8 @@ ARGS is a list of keyword arguments for `dirvish' struct."
      (when (or m-attr feat-in-lib) (require lib))
      (and m-attr (setq attrs (append attrs m-attr))))
    finally
-   (setf dirvish--mode-line-fmt (dirvish--mode-line-fmt-setter ml-l ml-r))
-   (setf dirvish--header-line-fmt (dirvish--mode-line-fmt-setter hl-l hl-r t))
+   (setf dirvish--mode-line-fmt (dirvish--mode-line-composer ml-l ml-r))
+   (setf dirvish--header-line-fmt (dirvish--mode-line-composer hl-l hl-r t))
    (setf dirvish--working-preview-dispathchers (dirvish--preview-dps-validate))
    (setf dirvish--working-attrs (dirvish--attrs-expand attrs))))
 
@@ -959,52 +959,54 @@ This attribute is enabled when `dirvish-hide-cursor' is 
non-nil."
     (let ((ov (make-overlay f-end l-end)))
       (overlay-put ov 'invisible t) `(ov . ,ov))))
 
-(defun dirvish--mode-line-fmt-setter (left right &optional header)
-  "Set the `dirvish--mode-line-fmt'.
+(defun dirvish--mode-line-composer (left right &optional header)
+  "Set `dirvish--mode-line-fmt'.
 LEFT and RIGHT are segments aligned to left/right respectively.
 If HEADER, set the `dirvish--header-line-fmt' instead."
-  (cl-labels ((expand (segments)
-                (cl-loop for s in segments collect
-                         (if (stringp s) s
-                           `(:eval (,(intern (format "dirvish-%s-ml" s)) 
(dirvish-curr))))))
-              (get-font-scale ()
-                (let* ((face (if header 'header-line 'mode-line-inactive))
-                       (default (face-attribute 'default :height))
-                       (ml-height (face-attribute face :height)))
-                  (cond ((floatp ml-height) ml-height)
-                        ((integerp ml-height) (/ (float ml-height) default))
-                        (t 1)))))
-    `((:eval
-       (let* ((dv (dirvish-curr))
-              (buf (and (car (dv-layout dv)) (cdr (dv-index dv))))
-              (scale ,(get-font-scale))
-              (win-width (floor (/ (window-width) scale)))
-              (str-l (format-mode-line
-                      ',(or (expand left) mode-line-format) nil nil buf))
-              (str-r (format-mode-line ',(expand right) nil nil buf))
-              (len-r (string-width str-r)))
-         (concat
-          (dirvish--bar-image (car (dv-layout dv)) ,header)
-          (if (< (+ (string-width str-l) len-r) win-width)
-              str-l
-            (let ((trim (1- (- win-width len-r))))
-              (if (>= trim 0)
-                  (substring str-l 0 (min trim (1- (length str-l))))
-                "")))
-          (propertize
-           " " 'display
-           `((space :align-to (- (+ right right-fringe right-margin)
-                                 ,(ceiling (* scale (string-width str-r)))))))
-          str-r))))))
+  `((:eval
+     (let* ((dv (dirvish-curr))
+            (buf (and (car (dv-layout dv)) (cdr (dv-index dv))))
+            (expand
+             (lambda (segs)
+               (cl-loop for s in segs collect
+                        (if (stringp s) s
+                          `(:eval (,(intern (format "dirvish-%s-ml" s))))))))
+            (face ',(if header 'header-line 'mode-line-inactive))
+            (default (face-attribute 'default :height))
+            (ml-height (face-attribute face :height))
+            (scale (cond ((floatp ml-height) ml-height)
+                         ((integerp ml-height) (/ (float ml-height) default))
+                         (t 1)))
+            (win-width (floor (/ (window-width) scale)))
+            (str-l "DIRVISH: Context buffer is not a live buffer")
+            (str-r (propertize "WARNING" 'face 'dired-warning))
+            (len-r 7))
+       (when (buffer-live-p buf)
+         (setq str-l (format-mode-line (funcall expand ',left) nil nil buf))
+         (setq str-r (format-mode-line (funcall expand ',right) nil nil buf))
+         (setq len-r (string-width str-r)))
+       (concat
+        (dirvish--bar-image fullframe-p ,header)
+        (if (< (+ (string-width str-l) len-r) win-width)
+            str-l
+          (let ((trim (1- (- win-width len-r))))
+            (if (>= trim 0)
+                (substring str-l 0 (min trim (1- (length str-l))))
+              "")))
+        (propertize
+         " " 'display
+         `((space :align-to (- (+ right right-fringe right-margin)
+                               ,(ceiling (* scale (string-width str-r)))))))
+        str-r)))))
 
 ;; Thanks to `doom-modeline'.
-(defun dirvish--bar-image (fullscreenp header)
+(defun dirvish--bar-image (fullframe-p header)
   "Create a bar image with height of `dirvish-mode-line-height'.
-If FULLSCREENP, use the `cdr' of the value as height, otherwise
+If FULLFRAME-P, use the `cdr' of the value as height, otherwise
 use `car'.  If HEADER, use `dirvish-header-line-height' instead."
   (when (and (display-graphic-p) (image-type-available-p 'pbm))
     (let* ((hv (if header dirvish-header-line-height dirvish-mode-line-height))
-           (ht (cond ((numberp hv) hv) (fullscreenp (cdr hv)) (t (car hv)))))
+           (ht (cond ((numberp hv) hv) (fullframe-p (cdr hv)) (t (car hv)))))
       (propertize
        " " 'display
        (ignore-errors
diff --git a/extensions/dirvish-fd.el b/extensions/dirvish-fd.el
index 2c5b617efd..933a5a3374 100644
--- a/extensions/dirvish-fd.el
+++ b/extensions/dirvish-fd.el
@@ -75,7 +75,7 @@ should return a list of regular expressions."
 
 (defconst dirvish-fd-bufname "🔍%s📁%s📁%s")
 (defconst dirvish-fd-header
-  (dirvish--mode-line-fmt-setter '(fd-switches) '(fd-timestamp fd-pwd " ") t))
+  (dirvish--mode-line-composer '(fd-switches) '(fd-timestamp fd-pwd " ") t))
 (defvar dirvish-fd-input-history nil "History list of fd input in the 
minibuffer.")
 (defvar dirvish-fd-debounce-timer nil)
 (defvar-local dirvish-fd--output "")
@@ -218,7 +218,7 @@ Raise an error if fd executable is not available."
   "Return a formatted string showing the DIRVISH-FD-ACTUAL-SWITCHES."
   (pcase-let ((`(,globp ,casep ,ign-range ,types ,exts ,excludes)
                (dirvish-prop :fd-arglist))
-              (face (if (dirvish--window-selected-p dv)
+              (face (if (dirvish--window-selected-p (dirvish-curr))
                         'dired-header 'shadow)))
     (format "  %s | %s"
             (propertize "FD" 'face face)
@@ -246,7 +246,7 @@ Raise an error if fd executable is not available."
 
 (dirvish-define-mode-line fd-timestamp
   "Timestamp of search finished."
-  (when (car (dv-layout dv)) (dirvish-prop :fd-time)))
+  (when (car (dv-layout (dirvish-curr))) (dirvish-prop :fd-time)))
 
 (dirvish-define-mode-line fd-pwd
   "Current working directory."
diff --git a/extensions/dirvish-side.el b/extensions/dirvish-side.el
index 024c6f5aa7..96699d9660 100644
--- a/extensions/dirvish-side.el
+++ b/extensions/dirvish-side.el
@@ -56,7 +56,7 @@ If non-nil, expand all the parent directories of current 
buffer's
 filename until the project root when opening a side session."
   :group 'dirvish :type 'boolean)
 
-(defconst dirvish-side-header (dirvish--mode-line-fmt-setter '(project) nil t))
+(defconst dirvish-side-header (dirvish--mode-line-composer '(project) nil t))
 
 (defun dirvish-side-file-open-fn ()
   "Called before opening a file in side sessions."
@@ -145,7 +145,7 @@ filename until the project root when opening a side 
session."
 (dirvish-define-mode-line project
   "Return a string showing current project."
   (let ((project (dirvish--get-project-root))
-        (face (if (dirvish--window-selected-p dv) 'dired-header 'shadow)))
+        (face (if (dirvish--window-selected-p (dirvish-curr)) 'dired-header 
'shadow)))
     (if project
         (setq project (file-name-base (directory-file-name project)))
       (setq project "-"))

Reply via email to