Emacs navigation between files with same names

2020-04-06 12:40发布

I've long been a fan of GNU Emacs' file navigation model. I've been switching buffers with C-x C-f ..., C-x b; C-mouse-1 occasionally.

However, recently I've been finding myself programming on projects that have sets of several files with the same names, but in different directories, along these lines:

package/message.py
package/message.zcml
package/ui/message.py
package/ui/message.zcml
package/ui2/message.py
package/ui2/message.zcml

In these circumstances my usual buffer switching tools are not very efficient. It's hard to remember whether the file I want is in the buffer message.py<2> or message.py<3>, and it's pretty fussy to switch between them with C-x b. What I would like, perhaps, is something like tab bar or a menu where I could arrange the files I'm working on and have them maintain their spatial arrangement, so that I could quickly switch beetween them. I briefly looked at speedbar and tabbar-mode, but didn't find much help. Any suggestions?

3条回答
家丑人穷心不美
2楼-- · 2020-04-06 13:35

Along with using uniquify to obtain more helpful buffer names, you might want to look into using ibuffer groups for your "spatial arrangement" needs. You can create named groups based on sets of filters, and you can filter on file path(*), so you could easily have separate groups for each of those directories.

I highly recommend binding C-xC-b to ibuffer as a replacement for the default.

Aside from that, if you use ido-mode in conjunction with the uniquify config, then when you type C-xb to switch buffers, you can type and match against any part of the (uniquified) buffer name. If you enable ido-enable-flex-matching (or alternatively, use something like LustyExplorer instead) then you can type unconnected parts of that buffer name, and the fuzzy matching will narrow the list intelligently (e.g. typing "mez2" might be enough to isolate "message.zcml|ui2").

(*) Personally I prefer ibuffer to match dired buffers as well as file buffers when I make a filename filter, so I redefine that filter accordingly:

;; Enable ibuffer-filter-by-filename to filter on directory names too.
(eval-after-load "ibuf-ext"
  '(define-ibuffer-filter filename
     "Toggle current view to buffers with file or directory name matching QUALIFIER."
     (:description "filename"
      :reader (read-from-minibuffer "Filter by file/directory name (regexp): "))
     (ibuffer-awhen (or (buffer-local-value 'buffer-file-name buf)
                        (buffer-local-value 'dired-directory buf))
       (string-match qualifier it))))
查看更多
ゆ 、 Hurt°
3楼-- · 2020-04-06 13:36

I found this solution from Borbus: https://stackoverflow.com/a/845311/552421

;; uniquify changes conflicting buffer names from file<2> etc
(require 'uniquify)
(setq uniquify-buffer-name-style 'reverse)
(setq uniquify-separator "/")
(setq uniquify-after-kill-buffer-p t) ; rename after killing uniquified
(setq uniquify-ignore-buffers-re "^\\*") ; don't muck with special buffers

From your example, your buffers would be named "message.py|ui", "message.py|ui2", etc...

查看更多
再贱就再见
4楼-- · 2020-04-06 13:46

You can rename the buffer without changing the file it is attached to. M-x rename-buffer <ret> new-buffer-name <ret>. After that, you can bounce back and forth using the more convenient buffer names, but when you save any changes they go to the actual files associated with each buffer.

In your case, you might rename your message.py<n> files to ui-message, ui2-message and base-message. Those will be easier to navigate to (and remember which files they belong to) with C-x b.

查看更多
登录 后发表回答