How to open files in specific Vim instance

From Vifm Wiki
Revision as of 16:16, 8 March 2021 by Xaizek (talk | contribs) (<source> -> <syntaxhighlight>)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

There are some usage scenarios in which one might want to open all/some files in specific Vim instance. This can be done via Vim client-server facilities which include means to send file for opening in specific instance. Vim must be compiled with +clientserver feature.

Here only single example is described, one can think of something better/different (binding to process id, terminal multiplexer session, etc.).

How files are opened[edit]

Say you have a mapping to open file in Vim which looks like this:

nnoremap o :!gvim --remote-tab-silent %f &<cr>

Same should be applicable to 'vicmd'/'vixcmd' options. Here you see mapping, because it is handy to have different ways to open files (in the same terminal, separate terminal multiplexer window/split, gVim instance).

Amending Vim run command[edit]

To bind the command we need to pass --servername option to Vim. Let's use environment variable $VIMARGS for this and put it into Vim invocation command:

nnoremap o :!gvim $VIMARGS --remote-tab-silent %f &<cr>

Here $VIMARGS can include anything and we want to put --servername argument there.

Picking target instance[edit]

By default $VIMARGS is empty, so first found server is used by remote commands (just as usual). Setting $VIMARGS to --servername name makes all consecutive file opens to use Vim with that server name (if there is none yet, it will be created).

Setting environment variable looks like this:

let $VIMARGS='--servername work'

Command to pick target[edit]

Having to type something like let $VIMARGS='--servername project' each time one wants to change target instance is not very good idea. It's better to add a command which would set target. Here it is:

command! target :let $VIMARGS = '--servername "%a"'

That's it, now simply running :target project1 will cause all files to be sent to project1 instance and after :target project2 all files will be sent to project2.

Integration with shell[edit]

There are many ways to open files without using Vifm, but quite popular one is probably opening files from shell. In this case, one might want to have the same functionality there. Lets assume there is an alias or a function that opens a file in gVim and teach it to make use of $VIMARGS in two steps.

Shell configuration update[edit]

Obviously, one needs to add the variable to shell configuration file (e.g. to ~/.bashrc), for example:

function g()
    gvim $VIMARGS --remote-tab-silent "$@"

No need for double quotes around $VIMARGS because we don't want to pass argument with empty value to Vim (it works as if it were . and starts browsing in current directory).

Communicating $VIMARGS to the shell[edit]

If terminal multiplexer is not used, nothing special needs to be done because environment variables set in Vifm are visible in all child processes.

In case tmux is used, our :target command could be updated in the following manner:

command! target : let $VIMARGS = '--servername "%a"'
               \| execute "!tmux %%i set-environment VIMARGS '".$VIMARGS."'"

Here we set $VIMARGS variable for all new panes/windows of the current tmux session. Note %%i, percent sign must be duplicated to survive first command substitution, which turns it into %i macro in the second one.