For easily specifying remote files for editing with vim or emacs from the shell, I would like to have tab-completion like available for scp.

Completions for scp work well and fast, if your .ssh/config is correctly configured.

So why not for vim, and other ssh-capable editors? I feel, the standard bash-completion package could benefit from a completion function set for ssh-capable editors, which AFAIK does not yet exist publicly.

(In environments, where afuse and sshfs are available to me, I use "as work-around" a user-level afuse sshfs auto-mounter daemon spawned from shell init to on-demand background mount remote file-systems into a tree under ~/scp/.)

2 Answers 2


I played around with your solution. Here is a slightly tweaked version which works better for me on a Mac OSX 10.11 system using homebrew.

First, in a file rvim_fun.sh, I define

vi () {
  local params=();
  while [[ ! -z $1 ]]; do
    # test if arg begins a sequence S of characters
    #    - . A-Z a-z 0-9 @ _
    # followed by a colon,
    # if so, we replace S: by scp://S/ to match vim syntax

    if [[ "$1" =~ ^[-.A-Za-z0-9@_]*:.*$ ]]; then
      params=("scp://${1/://}" "${params[@]}");
  echo vi ${params[@]};
  $HOME/bin/vi ${params[@]};

I found that this somehow works better for me (also, I have a program vi installed in ~/bin that invokes MaxVim).

Now, on my Mac, I installed bash-completion via homebrew. All I had to do was place the following in my .bashrc file:

case "$-" in
*i*)    source rvim_func.sh 
        complete -F _scp -o nospace vi
*)  ;;

So I didn't directly source anything else, except for what one has to do with homebrew:

if [ -f $(brew --prefix)/etc/bash_completion ]; then
  . $(brew --prefix)/etc/bash_completion

That is from the homebrew discussion board...

Anyway, this works pretty well for me now...thanks!


I hacked up something that "misuses" the available standard _scp bash completion function to enable completion of remote hosts/paths/files.

A vim-wrapping function then mangles the returned paths in the form ho.st:/fol/der/fi.le into the vim-expected form scp://ho.st///fol/der/fi.le.

vim () {
  local params=();
  while [[ ! -z $1 ]]; do
    if [[ "$1" =~ ^[a-z0-9-]*:/.*$ ]]; then
      params=("scp://${1/:\//\/\//}" "${params[@]}");
  echo vim ${params[@]};
  /usr/bin/vim ${params[@]};
. /usr/share/bash-completion/completions/scp
complete -F _scp -o nospace vim

For emacs use: params=("/scp:$1" "${params[@]}");

But, this setup could work better. Currently, this approach has the following minor shortcomings:

  • I can't tab-complete vim -o ptions. But I rarely use them anyway.
  • The scp options are still in there (but I never see them)
  • Only works for scp:// paths. But I only rarely use others like rsync or http.
  • The last 2 lines feel sub-optimal, and leave my env cluttered with lots of helper functions.

    I tried using this as second-last line instead, but this does not seem reliable:

    _completion_loader scp

    Sometimes, but not in tmux, spawning a new shell resulted in '_completion_loader not found'-Error. Yet running _completion_loader _scp results in functioning completion without error for this shell.

This works well enough for me, since I can just type the rare -o ption or http:// path.

But I do not consider this a good solution/answer, and won't accept it, because I am hoping for a better one to come up.

Note: I previously tried just using a modified standard supplied _known_hosts_real() function, found a way to run-time patch it to support more options, but then couldn't quickly wrap that into _vim(), so I just ignored the minor inconveniences of using _scp(), and started using that.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .