Yevgnen/ivy-rich

ivy-rich-switch-buffer-path not shown when switching buffers

Closed this issue · 4 comments

Even on a fresh emacs install, switching buffers with C-x b does not show the path and project columns with ivy-switch-buffer. The space for the data seems to be reserved but blank. Changing themes or ivy-rich variables (like switching column order, width, path abbreviation, etc) does not seem to have an effect. Ivy-rich-mode was cycled after changes when testing.

What does your config look like? Can you provide a reproducing script?

Sorry for the delay. The most minimal setup I can get is:

  1. Start emacs with "env HOME=~/test emacs"
  2. Evaluate to add Melpa
(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
(package-initialize)
  1. M-x package-install ivy, counsel, ivy-rich
  2. M-x ivy-mode, ivy-rich-mode
  3. C-x b

At which point I'd expect to see paths in the blank spaces.
Screenshot_20210515_104502

avexs commented

I ran into a similar issue (not sure if its the same). If I remember correctly, my issue was that ivy-rich--switch-buffer-root-and-filename can potentially return nil values for root and or dir; specifically when not using projectile. And the caller ivy-rich-switch-buffer-path will stop execution on the first if-let and return an empty string.

(defun ivy-rich--switch-buffer-root-and-filename (candidate)
  (when-let ((root (ivy-rich-switch-buffer-root candidate))
             (dir (ivy-rich--switch-buffer-directory candidate)))
    (when (bound-and-true-p projectile-mode)
      (setq dir (or (file-name-directory
                     (or (ivy-rich--local-values
                          candidate 'buffer-file-truename)
                         ""))
                    (file-truename dir))))
    (cons (expand-file-name root) (expand-file-name dir))))

(defun ivy-rich-switch-buffer-path (candidate)
  (if-let ((result (ivy-rich--switch-buffer-root-and-filename candidate)))
      (cl-destructuring-bind (root . filename) result
        (cond
         ;; Case: absolute
         ((or (memq ivy-rich-path-style '(full absolute))
              (and (null ivy-rich-parse-remote-file-path)
                   (or (file-remote-p root))))
          (or filename root))
         ;; Case: abbreviate
         ((memq ivy-rich-path-style '(abbreviate abbrev))
          (abbreviate-file-name (or filename root)))
         ;; Case: relative
         ((or (eq ivy-rich-path-style 'relative)
              t)	    ; make 'relative default
          (if (and filename root)
              (let ((relative-path (string-remove-prefix root filename)))
                (if (string= relative-path candidate)
                    (file-name-as-directory
                     (file-name-nondirectory
                      (directory-file-name (file-name-directory filename))))
                  relative-path))
            ""))))
    ""))

I fixed the problem in my case by overriding ivy-rich--switch-buffer-root-and-filename

  ;; overwrite the ivy-rich function
  ;; since it breaks when a project root is not defined
  (defun ivy-rich--switch-buffer-root-and-filename (candidate)
    (let* ((root (ivy-rich-switch-buffer-root candidate))
           (dir (ivy-rich--switch-buffer-directory candidate)))
      (when (bound-and-true-p projectile-mode)
        (setq dir (or (file-name-directory
                       (or (ivy-rich--local-values
                            candidate 'buffer-file-truename)
                           ""))
                      (file-truename dir))))
      (let ((return-root (if root (expand-file-name root) ""))
            (return-dir (if dir (expand-file-name dir) "")))
        (cons return-root return-dir))))

Hope this helps.

That is an excellent catch @avexs. Hope a variation gets merged, until then using your override.
Thank you!