4

Often I find myself in the shell, wanting to insert a filename into a lengthy command.

I'd like to hit a shortcut, and use Netrw or Nerdtree to browse for a file or directory, and have it pasted in place into the command I’m building.

So if I was in a folder, and wanted to compare 2 files:

  • I'd type diff
  • then I'd like to hit my shortcut, and visually browse using Netrw or Nerdtree, and select a file.
  • That filename is now added to my diff command... e.g. diff /tmp/file1.txt
  • I hit the shortcut again, and browse for the second file, /super/ez/another/file/somewhere/else/compare.txt
  • this then adds the second file to my diff command, so I now have:

    diff /tmp/file1.txt /super/ez/another/file/somewhere/else/compare.txt
    

Is this possible using any tool? I like Netrw in Vim, but am willing to try new things!

Note that I'm not interested in Tab completion of filenames using globbing. That works sometimes, but not all the time. I like Netrw and would love to figure out how to use it to select a filename by browsing.

3
+100

You basically already know the answer from here. It's quite easy to put this all together like this:

function insert_files() {
    vifm -f < /dev/tty > /dev/tty

    while read l; do
        LBUFFER+="'$l' "
    done < ~/.vifm/vimfiles

    zle reset-prompt
}
zle -N insert_files
bindkey '^t' insert_files

I'm not a zsh-user, so I stole structure of the code from answer by Lucas. As for bash, I was looking once for a way to process output of external command inside shortcut, but didn't find one.

Demonstration

P.S. My code contains quite primitive escaping, you might want to improve that and maybe change the way spacing is added between arguments.

4

Zsh allows you to bind a shell function to a key and also has a builtin to put text into your command line. So you can do something like this (in zsh):

# define a function that does the work
function my_browser_function () {
  local result
  result=$( some command that returns the filename )
  # print -z $result (see comments)
  LBUFFER+=$result
}
# turn the function into a widget
zle -N my_browser_function
# bind it to some key ("CTRL-X I" for example)
bindkey '\Cxi' my_browser_function

Now you just have to get a command working that lets you browse the filesystem in the way you want and prints the result on stdout.

EDIT: Here is a very basic version of the above function that uses vim:

function my_browser_function () {
  local file=$(mktemp)
  vim -c "map <C-A> :cal system('echo '.expand('%').'/'.getline('.').'>$file')<bar>q<cr>" .
  LBUFFER+=$(<$file)
  rm $file
}

You can navigate in vim/netrw as usual and then use <C-A> (Ctrl-A) to Accept the file/directory name.

Obviously this is only a very basic function. If you want more functionallity you also might write a vim autoload function and call that from the vim command line with -c.

  • 2
    You don't want to use print -z here (stricktly speaking print -rz --) which is more to simulate key presses (might call other zle widgets for instance). Use LBUFFER+=$result (or LBUFFER+=${(qqq)result} to insert it quoted). – Stéphane Chazelas Dec 8 '14 at 11:30
  • cool! this is definitely half of it... now to figure out a way to get Netrw to select a file and output it to stdout.... I can go vi . and browse using Netrw to the file. But then I have to edit it and hit a keystroke to copy the name to the clipboard. Must... eliminate... these... extra... keystrokes! – Brad Parks Dec 8 '14 at 12:49
  • I've found vifm, which seems to do the "browsing" part - super nice... but when I try and run it using a shortcut via zsh or tmux, I get a screen dump of what appears to be escape characters... any ideas on what this would happen? – Brad Parks Dec 9 '14 at 20:39
  • Another file manager which might be interesting for this (like vimfm) is ranger. I also added a better shell function that really uses vim above. – Lucas Dec 10 '14 at 23:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.