neovim-remote

:ok_hand: Support for --remote and friends.

Github stars Tracking Chart

Build status
Supported Python versions

This package provides an executable called nvr which solves these cases:

  • Controlling nvim processes from the shell. E.g. opening files in another
    terminal window.
  • Opening files from within :terminal without starting a nested nvim process.


Installation

pip3 install neovim-remote

If you encounter any issues, e.g. permission denied errors or you can't find the
nvr executable, read INSTALLATION.md.

Theory

Nvim always starts a server. Get its address via :echo $NVIM_LISTEN_ADDRESS or
:echo v:servername. Or specify an address at startup:
NVIM_LISTEN_ADDRESS=/tmp/nvimsocket nvim.

nvr will use $NVIM_LISTEN_ADDRESS or any address given to it via
--servername.

If the targeted address does not exist, nvr starts a new process by running
"nvim". You can change the command by setting $NVR_CMD. (This requires
forking, so it won't work on Windows.)

First steps

Start a nvim process (which acts as a server) in one shell:

NVIM_LISTEN_ADDRESS=/tmp/nvimsocket nvim

And do this in another shell:

# nvr uses /tmp/nvimsocket by default, so we're good.

# Open two files:
nvr --remote file1 file2

# Send keys to the current buffer:
nvr --remote-send 'iabc<esc>'
# Enter insert mode, insert 'abc', and go back to normal mode again.

# Evaluate any VimL expression, e.g. get the current buffer:
nvr --remote-expr 'bufname("")'
README.md
$ nvr -h
usage: nvr [arguments]

Remote control Neovim processes.

If no process is found, a new one will be started.

    $ nvr --remote-send 'iabc<cr><esc>'
    $ nvr --remote-expr 'map([1,2,3], "v:val + 1")'

Any arguments not consumed by options will be fed to --remote-silent:

    $ nvr --remote-silent file1 file2
    $ nvr file1 file2

All --remote options take optional commands.
Exception: --remote-expr, --remote-send.

    $ nvr +10 file
    $ nvr +'echomsg "foo", echomsg "bar"' file
    $ nvr --remote-tab-wait +'set bufhidden=delete' file

Open files in a new window from a terminal buffer:

    $ nvr -cc split file1 file2

Use nvr from git to edit commit messages:

    $ git config --global core.editor 'nvr --remote-wait-silent'

optional arguments:
  -h, --help            show this help message and exit
  --remote [<file> [<file> ...]]
                        Use :edit to open files. If no process is found, throw
                        an error and start a new one.
  --remote-wait [<file> [<file> ...]]
                        Like --remote, but block until all buffers opened by
                        this option get deleted or the process exits.
  --remote-silent [<file> [<file> ...]]
                        Like --remote, but throw no error if no process is
                        found.
  --remote-wait-silent [<file> [<file> ...]]
                        Combines --remote-wait and --remote-silent.
  --remote-tab [<file> [<file> ...]]
                        Like --remote, but use :tabedit.
  --remote-tab-wait [<file> [<file> ...]]
                        Like --remote-wait, but use :tabedit.
  --remote-tab-silent [<file> [<file> ...]]
                        Like --remote-silent, but use :tabedit.
  --remote-tab-wait-silent [<file> [<file> ...]]
                        Like --remote-wait-silent, but use :tabedit.
  --remote-send <keys>  Send key presses.
  --remote-expr <expr>  Evaluate expression and print result in shell.
  --servername <addr>   Set the address to be used. This overrides the default
                        "/tmp/nvimsocket" and $NVIM_LISTEN_ADDRESS.
  --serverlist          Print the TCPv4 and Unix domain socket addresses of
                        all nvim processes.
  -cc <cmd>             Execute a command before every other option.
  -c <cmd>              Execute a command after every other option.
  -d                    Diff mode. Use :diffthis on all to be opened buffers.
  -l                    Change to previous window via ":wincmd p".
  -o <file> [<file> ...]
                        Open files via ":split".
  -O <file> [<file> ...]
                        Open files via ":vsplit".
  -p <file> [<file> ...]
                        Open files via ":tabedit".
  -q <errorfile>        Read errorfile into quickfix list and display first
                        error.
  -s                    Silence "no server found" message.
  -t <tag>              Jump to file and position of given tag.
  --nostart             If no process is found, do not start a new one.
  --version             Show the nvr version.

Development: https://github.com/mhinz/neovim-remote

Happy hacking!

Typical use cases

  • Open files from within :terminal without starting a nested nvim process.

    Easy-peasy! Just nvr file.

    This works without any prior setup, because $NVIM_LISTEN_ADDRESS is always
    set within Nvim. And nvr will default to that address.

    I often work with two windows next to each other. If one contains the
    terminal, I can use nvr -l foo to open the file in the other window.

  • Open files always in the same nvim process no matter which terminal you're in.

    If you just run nvr -s, a new nvim process will start and set its address
    to /tmp/nvimsocket automatically.

    Now, no matter in which terminal you are, nvr file will always work on
    that nvim process. That is akin to emacsclient from Emacs.

  • Use nvr in plugins.

    Some plugins rely on the --remote family of options from Vim. Nvim had to
    remove those when they switched to outsource a lot of manual code to libuv.
    These options are planned to be added back, though.

    In these cases nvr can be used as a drop-in replacement. E.g.
    vimtex can be configured to use nvr to
    jump to a certain file and line: read.

  • Use nvr as git editor.

    Imagine Neovim is set as your default editor via $VISUAL or $EDITOR.

    Running git commit in a regular shell starts a nvim process. But in a
    terminal buffer (:terminal), a new nvim process starts as well. Now you
    have one nvim nested within another.

    If you do not want this, put this in your vimrc:

    if has('nvim')
      let $GIT_EDITOR = 'nvr -cc split --remote-wait'
    endif
    

    That way, you get a new window for inserting the commit message instead of a
    nested nvim process. But git still waits for nvr to finish, so make sure to
    delete the buffer after saving the commit message: :w, bd.

    If you don't like using :w, bd and prefer the good old :wq (or :x),
    put the following in your vimrc:

    autocmd FileType gitcommit,gitrebase,gitconfig set bufhidden=delete
    

    To use nvr from a regular shell as well:

      $ git config --global core.editor 'nvr --remote-wait-silent'
    
  • Use nvr as git mergetool.

    If you want to use nvr for git difftool and git mergetool, put this in
    your gitconfig:

    [diff]
        tool = nvr
    [difftool "nvr"]
        cmd = nvr -s -d $LOCAL $REMOTE
    [merge]
        tool = nvr
    [mergetool "nvr"]
        cmd = nvr -s -d $LOCAL $BASE $REMOTE $MERGED -c 'wincmd J, wincmd ='
    

    nvr -d is a shortcut for nvr -d -O and acts like vim -d, thus it uses
    :vsplit to open the buffers. If you want them to be opened via :split
    instead, use nvr -d -o.

    When used as mergetool and all four buffers got opened, the cursor is in the
    window containing the $MERGED buffer. We move it to the bottom via :wincmd J and then equalize the size of all windows via :wincmd =.

  • Use nvr for scripting.

    You might draw some inspiration from this Reddit
    thread
    .

Demos

(Click on the GIFs to watch them full-size.)

Using nvr from another shell: Demo 1

Using nvr from within :terminal: Demo 2

FAQ

  • How to open directories?

    :e /tmp opens a directory view via netrw. Netrw works by hooking into certain
    events, BufEnter in this case (see :au FileExplorer for all of them).

    Unfortunately Neovim's API doesn't trigger any autocmds on its own, so simply
    nvr /tmp won't work. Meanwhile you can work around it like this:

      $ nvr /tmp -c 'doautocmd BufEnter'
    
  • Reading from stdin?

    Yes! E.g. echo "foo\nbar", nvr -o - and cat file, nvr --remote - work just
    as you would expect them to work.

  • Exit code?

    If you use a recent enough
    Neovim
    , nvr will use the same exit code as the linked nvim.

    E.g. nvr --remote-wait <file> and then :cquit in the linked nvim will make
    nvr return with 1.

  • How to send a message to all waiting clients?

    If you open a buffer with any of the wait options, that buffer will get a
    variable b:nvr. The variable contains a list of channels wheres each
    channel is a waiting nvr client.

    Currently nvr only understands the Exit message. You could use it to
    disconnect all waiting nvr clients at once:

    command! DisconnectClients
        \  if exists('b:nvr')
        \, for client in b:nvr
        \, silent! call rpcnotify(client, 'Exit', 1)
        \, endfor
        \, endif
    
  • Can I have auto-completion for bash?

    If you want basic auto-completion for bash, you can source this
    script
    in your .bashrc.

    This also completes server names with the --servername option.

Main metrics

Overview
Name With Ownermhinz/neovim-remote
Primary LanguagePython
Program languagePython (Language Count: 3)
Platform
License:MIT License
所有者活动
Created At2015-12-04 15:26:32
Pushed At2023-09-29 19:22:47
Last Commit At2022-05-19 17:48:29
Release Count81
Last Release Namev2.5.1 (Posted on )
First Release Namev1.0 (Posted on 2015-12-16 14:16:13)
用户参与
Stargazers Count1.8k
Watchers Count17
Fork Count84
Commits Count318
Has Issues Enabled
Issues Count146
Issue Open Count26
Pull Requests Count17
Pull Requests Open Count5
Pull Requests Close Count29
项目设置
Has Wiki Enabled
Is Archived
Is Fork
Is Locked
Is Mirror
Is Private