tags:

views:

760

answers:

4

When I call find-file to open a new file, it generally happens that the file I'm looking for is in one of the directories I've already loaded from.

Ideally, I'd like to scroll through the history using the up/down arrows.

The problem with this is that if I've already loaded 10 files from a directory, I first have to pass through those ten files, all in the same directory, before I see a new directory where my file might be.

In the end, I often just type in the directory again or cut/paste it from an xterm.

in the find-file command, can I change the behavior of the up/down arrows to iterate over directories instead of files.

Alternatively, can I change the file order to match the order of buffers most recently visited instead of when I loaded the file?

+1  A: 

not what you want, but

have you tried (electric-buffer-list) Ctrl-x Ctrl-b?

or (dired)?

Peter Miehle
+1  A: 

This will use the buffer-list's order for the history, which is what you want.

(setq read-file-name-function 'my-read-file-name)
(defun my-read-file-name (prompt dir default-filename mustmatch initial predicate)
  (let ((default-directory dir)
        (files (directory-files dir))
        (history (delq nil (mapcar 'buffer-file-name (buffer-list)))))
    (completing-read prompt files predicate mustmatch initial 'history)))

Hmmm... This changes the behavior of find-file's TAB completion because the TAB completes over the history (already opened files), and not over the files available in the directory you're specifying.

Getting both to work at the same time is a bit trickier...

Trey Jackson
+3  A: 

My first answer suffered from the behavior that TAB completion no longer worked as expected in 'find-file. But the technique still seems useful (and if you like it, preferable).

However, this solution has the same history behavior, but maintains the TAB completion as expected inside 'find-file.

I'd be interested to know if there were a way to avoid advising find-file, but I couldn't find any introspection that gave me the knowledge that 'find-file was called.

(defadvice find-file (around find-file-set-trigger-variable protect activate)
  "bind a variable so that history command can do special behavior for find-file"
  (interactive (let (inside-find-file-command) (find-file-read-args "Find file: " nil)))
  ad-do-it)

(defadvice next-history-element (around next-history-element-special-behavior-for-find-file protect activate)
  "when doing history for find-file, use the buffer-list as history"
  (if (boundp 'inside-find-file-command)
      (let ((find-file-history (delq nil (mapcar 'buffer-file-name (buffer-list))))
            (minibuffer-history-variable 'find-file-history))
        ad-do-it)
    ad-do-it))
Trey Jackson
This solution has the nasty side effect that the down and uparrows are not complementary, e.g. if you cycle past the file you want using the uparrow, pressing the downarrow does not get go back 1 in the list you have just cycled through!
EoghanM
I don't find that to be the case. When I set a breakpoint in the 'next-history-element advice, I see it gets called when I press either the up or down arrow keys. Perhaps your keys are bound differently?
Trey Jackson
I don't think I've any strange keybindings - when I created another 'previous-history-element' function the up and down arrows seem to be the inverse of eachother
EoghanM
+1  A: 

I suggest IDO. You can search in the buffer list or in find-file. When searching in find-file and it has no matches in the current folder it searches through history.