Yevgnen/ivy-rich

ivy-rich--switch-buffer-root-and-filename is broken (report with probable fix)

bymoz089 opened this issue · 6 comments

function ivy-rich--switch-buffer-root-and-filename is broken. It returns always nil if the file is not part of a project (or projectile is not installed).

How to reproduce: open a file like "/tmp/foo.txt" and then switch buffers with ivy-switch-buffer, while ivy-rich is activated. You will see, that there is no path listed at candidate foo.txt.

Folowing code is a try to fix this function:

(defun ivy-rich--switch-buffer-root-and-filename (candidate)
  (let* ((buffer (get-buffer candidate))
	 (truenamep t))
    (cl-destructuring-bind
	(filename directory mode)
	(ivy-rich--local-values buffer '(buffer-file-name default-directory major-mode))
      ;; Only make sense when `filename' and `root' are both not `nil'
      (unless (and filename
		   directory
		   (if (file-remote-p filename) ivy-rich-parse-remote-buffer t)
		   (not (eq mode 'dired-mode)))
	(setq truenamep nil))
      (when (and truenamep
		 (ivy-rich-switch-buffer-in-project-p candidate))
	;; Find the project root directory or `default-directory'
	(setq directory (cond ((bound-and-true-p projectile-mode)
			       (or (ivy-rich--local-values buffer 'projectile-project-root)
				   (with-current-buffer buffer
				     (projectile-project-root))))
			      ((require 'project nil t)
			       (with-current-buffer buffer
				 (setq truenamep nil)
				 (car (project-roots (project-current))))))))
      (if truenamep
	  (progn
	    (setq filename (or (ivy-rich--local-values buffer 'buffer-file-truename)
			       (file-truename filename)))
	    (cons (expand-file-name directory)
		  (expand-file-name filename)))))))

I have the same issue, I've tried your code but it shows only the last directory instead of the entire path. Additionally, I can't increase the width of the column which shows the major modes...any suggestions?

Screenshot from 2019-04-12 02-01-48

Hi, sorry for the late reply. I'm not sure whether the original purpose of ivy-rich--switch-buffer-root-and-filename is to only work with project.el or projectile.el. Please give me some time to read the logs...

@styx00 About the columns widths, I personally prefer percentages like

            ivy-switch-buffer
            (:columns ((ivy-rich-switch-buffer-candidate (:width 0.25))
                       (ivy-rich-switch-buffer-size (:width 0.05))
                       (ivy-rich-switch-buffer-indicators (:width 0.05 :face error :align right))
                       (ivy-rich-switch-buffer-major-mode (:width 0.1 :face warning))
                       (ivy-rich-switch-buffer-project (:width 0.15 :face success))
                       (ivy-rich-switch-buffer-path (:width (lambda (x)
                                                              (ivy-rich-switch-buffer-shorten-path x (ivy-rich-minibuffer-width 0.4))))))
                      :predicate
                      (lambda (cand)
                        (get-buffer cand)))

I'm not a user of projectile.el. The following is an ad-hoc fix to show the path up to dirname.
In order to show the path, some lines are commented out.

(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))))

My home-baked fallback when there's no project root.

(defadvice! ivy-rich-no-project-fallback (orig-fn candidate)
    :around #'ivy-rich--switch-buffer-root-and-filename
    (if-let ((result (funcall orig-fn candidate)))
        result
      (cons ""
            (expand-file-name (ivy-rich--switch-buffer-directory candidate)))))

Or like this ?

(defun ivy-rich-no-project-fallback (orig-fn candidate)
  (if-let ((result (funcall orig-fn candidate)))
      result
    (cons ""
          (expand-file-name (ivy-rich--switch-buffer-directory candidate)))))
(advice-add #'ivy-rich--switch-buffer-root-and-filename
            :around #'ivy-rich-no-project-fallback)

Or like this ?

(defun ivy-rich-no-project-fallback (orig-fn candidate)
  (if-let ((result (funcall orig-fn candidate)))
      result
    (cons ""
          (expand-file-name (ivy-rich--switch-buffer-directory candidate)))))
(advice-add #'ivy-rich--switch-buffer-root-and-filename
            :around #'ivy-rich-no-project-fallback)

Oh yes indeed. I am using doom emacs and defadvice! is a doom macro. Basically the same as what you wrote there.