3

I'm trying to setup a simple environment which would allow me to work on a local file and it's remote counterpart.

Both files are accessible on my filesystem. So let's say I have :

File 1 : /home/john/petshop/categories/animals/fluffy/cats.txt

and

File 2 : /mnt/sshfs/petshop/categories/animals/fluffy/cats.txt

Once I have File 1 opened in vim, how can I quickly open file 2 without having to type out the whole path ? I'd prefer an answer that doesn't involve a fuzzy finder.

5

Some characters are special on Vim's command-line (see :h cmdline-special), including % which is automatically replaced by the path to the current file relative to the current working directory.

Some of them may be followed by filename-modifiers (see :h filename-modifiers). Those can be combined, and among them are :p which makes Vim expands % into an absolute file path instead of a relative one, and :s?pat?rep? which allows you to replace a pattern with an arbitrary replacement string.

This could be useful in your case to make Vim replace /home/john with /mnt/sshfs:

:e %:p:s?/home/john?/mnt/sshfs?

Note that if the pattern or the replacement contains a question mark, you can use another delimiter between the fields of the substitution command, like ; for example:

:e %:p:s;/home/john;/mnt/sshfs;

Also, the substitution will only affect the first occurrence of the pattern. If you need to replace all of them, use gs (the g is for Global) instead of s:

:e %:p:gs?/home/john?/mnt/sshfs?
  • 1
    I went from there and added a remap to my vimrc in order to open the file in a vertical split, like so : nnoremap ,p :vsp %:p:s?/home/john?/mnt/sshfs?<CR> – mike23 Oct 22 '18 at 14:28
3

You can get the full path of the file you're editing with expand('%:p'). Unfortunately, we need to edit the path slightly, so this isn't enough on its own, but it gets us closer to where we're going. We need to evaluate that vimscript and put it into the command line as text so we could edit it. Thankfully, we have the expression register.

Here's what I would do:

  1. Open up the command line, and start off your command with :e<space>. Now press ctrl-r = to open up the expression register. You should see an = where you normally see the colon.

  2. Type expand('%:p') and press Enter. You should now see

    :e /home/john/petshop/categories/animals/fluffy/cats.txt
    

    in your command line.

  3. Use the arrow keys (or ctrl+left) to navigate to the beginning of the path, and edit it to the path you want, then press enter.


EDIT

I decided that this is something really useful, so I'd like to have it in my config as well. While creating a mapping for it, I realized you could do something much simpler if you use an <expr> mapping. I did this:

nnoremap <expr> <leader>F ":e ".expand('%:p')

(Of course, you can pick whatever you want in place of <leader>F) This works be evaluating everything after the mapping as a string, and returning those keystrokes as if you typed them.

":e " Obviously corresponds to :e<space> since that's the beginning of the command you'll use.

. is the string concatenation operator

expand('%:p') evaluates to the full path like before.

This is overall simpler since it doesn't require the "= register.

  • Neat, now I'm trying to turn that into a remap, with nnoremap <C-tab> :e<Space><C-r>= expand('%:p')<CR> but that doesn't seem to work. – mike23 Oct 20 '18 at 18:43
  • @mike23 That's because <C-tab> isn't something that you can map to. You'll have to find some other mapping. I also added some information specific to mapping this in an edit to the answer. – DJMcMayhem Oct 20 '18 at 19:13

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.