Recently, as I replaced more of my Emacs-helm configuration with counsel and
ivy, I noticed that ivy-switch-buffer, when augmented by ivy-rich, was not
showing the directories of the buffers it was listing.
After some Lisp spelunking, I discovered that it was because ivy-rich relies on
the presence of either the projectile package, something I do not wish to have
in my Emacs configuration, or on project.el, which I also do not use.
In this post, I show how you can get full buffer filenames and project names
with the lighter-than-projectile and more-robust-than-project.el
find-file-in-project, or how you can bypass the project name functionality
completely and just get buffer filenames with no extra packages.
(There are a number of long-standing PRs on ivy-rich, so I decided against
investing my time there, instead making the fix available directly on this
blog.)
Updates
Wednesday 2020-11-18
Indeed Yevgnen (ivy-rich’s author) merged my PR, so everything in this post
should be fixed if you update your ivy-rich from melpa.
(use-packageivy-rich:ensuret:config(ivy-rich-mode1);; abbreviate turns home into ~ (for example);; buffers still only get the buffer basename(setqivy-virtual-abbreviate'abbreviateivy-rich-path-style'abbrev);; use buffer-file-name and list-buffers-directory instead of default-directory;; so that special buffers, e.g. *scratch* don't get a directory (we return nil in those cases)(defunivy-rich--switch-buffer-directory(candidate)"Return directory of file visited by buffer named CANDIDATE, or nil if no file."(let*((buffer(get-buffercandidate))(fn(buffer-file-namebuffer)));; if valid filename, i.e. buffer visiting file:(iffn;; return containing directory(directory-file-namefn);; else if mode explicitly offering list-buffers-directory, return that; else nil.;; buffers that don't explicitly visit files, but would like to show a filename,;; e.g. magit or dired, set the list-buffers-directory variable(buffer-local-value'list-buffers-directorybuffer))));; override ivy-rich project root finding to use FFIP or to skip completely(defunivy-rich-switch-buffer-root(candidate);; 1. changed let* to when-let*; if our directory func above returns nil,;; we don't want to try and find project root(when-let*((dir(ivy-rich--switch-buffer-directorycandidate)))(unless(or(and(file-remote-pdir)(notivy-rich-parse-remote-buffer));; Workaround for `browse-url-emacs' buffers , it changes;; `default-directory' to "http://" (#25)(string-match"https?://"dir))(cond;; 2. replace the project-root-finding;; a. add FFIP for projectile-less project-root finding (on my setup much faster) ...((require'find-file-in-projectnilt)(let((default-directorydir))(ffip-project-root)));; b. OR disable project-root-finding altogether(t"")((bound-and-true-pprojectile-mode)(let((project(or(ivy-rich--local-valuescandidate'projectile-project-root)(projectile-project-rootdir))))(unless(string=project"-")project)))((require'projectnilt)(when-let((project(project-currentnildir)))(car(project-rootsproject)))))))))