When working on my web projects I often have same the same filename in different folders, such as projectname/index.html and anotherproject/index.html.

When opening files in Emacs, I might have to open index.html if I'm already in projectname/ or type ../anotherproject/index.html to open from another folder. I switch folders enough that I wanted to have a more consistent way to open things. I now use a global find-file that lets me match on the complete pathname. I can open projectname/index from anywhere, without having to type something different based on which folder I'm in.

When switching buffers, either with the built-in function or with consult-buffer from consult.el, I can type index.html if I only have one index.html file open. If I have more than one open, Emacs will rename them index.html<projectname>, index.html<anotherproject>, etc., and then I would type index projectname. But if I have only one open, then typing index projectname will fail. I wanted to make it more consistent so that I could always type index projectname whether there's only one index.html buffer open or multiple. I implemented this by putting the full filename instead of the buffer name into consult's buffer list:

(defun my/consult--source-buffer ()
  "Make consult-buffer match the entire filename of a buffer"
  ;; items is a list of (name . buffer)
  (let ((items (consult--buffer-query :sort 'visibility
                                      :as #'consult--buffer-pair)))
    ;; TODO: sort these so the current project is first?
    (--map
     (let* ((label (car it))
            (buffer (cdr it))
            (filename (buffer-file-name buffer)))
       (if filename
           (progn
             (setq filename (abbreviate-file-name filename))
             (setq label
                   (concat (file-name-directory filename)
                           (propertize (file-name-nondirectory filename) 'face 'consult-file))))
         (setq label (propertize label 'face 'consult-buffer)))
       (cons label buffer))
     items)))

(defvar my/consult--source-buffer
  `(:name     "Open file"
              :narrow   ?o
              :category buffer
              :history  buffer-name-history
              :state    ,#'consult--buffer-state
              :default  t
              :items    ,#'my/consult--source-buffer)
  "Buffer with filename matching for `consult-buffer'.")

and then I put that in consult-buffer-sources:

(setq consult-buffer-sources
   '(consult--source-hidden-buffer       ;; use SPC to see list
     consult--source-modified-buffer     ;; use * SPC to see list
     my/consult--source-buffer           ;; buffers, with folder names
     consult--source-bookmark            ;; use m SPC to see list
     consult--source-file-register       ;; use r SPC to see list
     consult--source-project-recent-file ;; use f SPC to see list
     consult--source-recent-file         ;; use f SPC to see list
     ))

Now consult-buffer shows the filename instead of the buffer name, and I can match on any part of it. I think this has downsides too, as switching buffers takes more keystrokes, but it's also more consistent across different buffer configurations. I've only been using it a few days so far and don't yet know whether I'll keep it.

Labels:

0 comments: