2017-09-29 14:36:44 +00:00
|
|
|
[![Build status](https://travis-ci.org/mhinz/neovim-remote.svg?branch=master)](https://travis-ci.org/mhinz/neovim-remote)
|
|
|
|
[![Supported Python versions](https://img.shields.io/pypi/pyversions/neovim-remote.svg)](https://pypi.python.org/pypi/neovim-remote)
|
2018-02-28 19:32:38 +00:00
|
|
|
|
2018-02-28 20:14:58 +00:00
|
|
|
<div align='center'>
|
|
|
|
<h1>neovim-remote</h1><br>
|
|
|
|
</div>
|
2018-02-28 19:32:38 +00:00
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
---
|
2017-09-29 14:36:44 +00:00
|
|
|
|
|
|
|
- [Installation](#installation)
|
2018-02-28 19:28:48 +00:00
|
|
|
- [Theory](#theory)
|
|
|
|
- [First steps](#first-steps)
|
2018-02-28 20:07:18 +00:00
|
|
|
- [Typical use cases](#typical-use-cases)
|
2017-09-29 14:36:44 +00:00
|
|
|
- [Demos](#demos)
|
|
|
|
- [FAQ](#faq)
|
|
|
|
|
2018-02-28 19:32:38 +00:00
|
|
|
---
|
2017-09-29 14:36:44 +00:00
|
|
|
|
2018-02-28 19:28:48 +00:00
|
|
|
## 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](INSTALLATION.md).
|
|
|
|
|
|
|
|
## Theory
|
2017-09-29 14:36:44 +00:00
|
|
|
|
2018-02-28 18:56:38 +00:00
|
|
|
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`.
|
2017-09-29 14:36:44 +00:00
|
|
|
|
2018-02-28 18:56:38 +00:00
|
|
|
**nvr** will use `$NVIM_LISTEN_ADDRESS` or any address given to it via
|
|
|
|
`--servername`.
|
2017-09-29 14:36:44 +00:00
|
|
|
|
2018-02-28 18:56:38 +00:00
|
|
|
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.)_
|
2017-09-29 14:36:44 +00:00
|
|
|
|
2018-02-28 19:28:48 +00:00
|
|
|
## First steps
|
|
|
|
|
|
|
|
Start a nvim process (which acts as a server) in one shell:
|
2018-02-28 19:11:16 +00:00
|
|
|
|
2018-02-28 19:28:48 +00:00
|
|
|
NVIM_LISTEN_ADDRESS=/tmp/nvimsocket nvim
|
2018-02-28 19:11:16 +00:00
|
|
|
|
2018-02-28 19:28:48 +00:00
|
|
|
And do this in another shell:
|
|
|
|
|
|
|
|
```sh
|
|
|
|
# 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
|
|
|
|
```
|
|
|
|
|
|
|
|
<details>
|
2018-02-28 19:32:38 +00:00
|
|
|
<summary>click here to see all nvr options</summary>
|
|
|
|
|
2018-02-28 19:28:48 +00:00
|
|
|
```
|
2018-02-28 19:32:38 +00:00
|
|
|
$ nvr -h
|
|
|
|
usage: nvr [arguments]
|
2018-02-28 19:28:48 +00:00
|
|
|
|
|
|
|
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.
|
|
|
|
-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.
|
|
|
|
|
|
|
|
Happy hacking!
|
|
|
|
```
|
|
|
|
</details>
|
2018-02-28 19:11:16 +00:00
|
|
|
|
2018-02-28 20:07:18 +00:00
|
|
|
## Typcial use cases
|
2017-09-29 14:36:44 +00:00
|
|
|
|
2018-02-28 20:07:18 +00:00
|
|
|
- **Open files from within `:terminal` without starting a nested nvim.**
|
2017-09-29 14:36:44 +00:00
|
|
|
|
2018-02-28 20:07:18 +00:00
|
|
|
Easy-peasy! Just `nvr file`.
|
2017-09-29 14:36:44 +00:00
|
|
|
|
2018-02-28 20:07:18 +00:00
|
|
|
This works without any prior setup, because `$NVIM_LISTEN_ADDRESS` is always
|
|
|
|
set within Nvim. And `nvr` will default to that address.
|
2017-09-29 14:36:44 +00:00
|
|
|
|
2018-02-28 20:07:18 +00:00
|
|
|
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.
|
2017-09-29 14:36:44 +00:00
|
|
|
|
2018-02-28 20:07:18 +00:00
|
|
|
- **Open files always in the same nvim no matter which terminal you're in.**
|
2017-09-29 14:36:44 +00:00
|
|
|
|
2018-02-28 20:07:18 +00:00
|
|
|
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 as temporary editor.**
|
|
|
|
|
|
|
|
Imagine Neovim is set as your default editor: `VISUAL=nvim`.
|
|
|
|
|
|
|
|
Now run `git commit`. In a regular shell, a new nvim process starts. That's
|
|
|
|
exactly what you want.
|
|
|
|
|
|
|
|
But in a terminal buffer (`:terminal`), a new nvim process starts as well. Now
|
|
|
|
you have one nvim nested within another. You don't want that. Put this in your
|
|
|
|
vimrc:
|
|
|
|
|
|
|
|
```vim
|
|
|
|
if has('nvim')
|
|
|
|
let $VISUAL = 'nvr -cc split --remote-wait'
|
|
|
|
endif
|
|
|
|
```
|
|
|
|
|
|
|
|
That way, you get a new window for entering the commit message instead of a
|
|
|
|
nested nvim process.
|
|
|
|
|
|
|
|
Alternatively, you can make git always using nvr. In a regular shell, nvr will
|
|
|
|
create a new nvim process. In a terminal buffer, nvr will open a new buffer.
|
|
|
|
|
|
|
|
$ git config --global core.editor 'nvr --remote-wait-silent'
|
|
|
|
|
|
|
|
- **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](https://github.com/neovim/neovim/issues/1750), though.
|
|
|
|
|
|
|
|
In these cases nvr can be used as a drop-in replacement. E.g.
|
|
|
|
[vimtex](https://github.com/lervag/vimtex) can be configured to use nvr to
|
|
|
|
jump to a certain file and line: [read](https://github.com/lervag/vimtex/blob/80b96c13fe9edc5261e9be104fe15cf3bdc3173d/doc/vimtex.txt#L1702-L1708).
|
2017-09-29 14:36:44 +00:00
|
|
|
|
|
|
|
## Demos
|
|
|
|
|
|
|
|
_(Click on the GIFs to watch them full-size.)_
|
|
|
|
|
|
|
|
Using nvr from another shell: ![Demo 1](https://github.com/mhinz/neovim-remote/raw/master/images/demo1.gif)
|
|
|
|
|
|
|
|
Using nvr from within `:terminal`: ![Demo 2](https://github.com/mhinz/neovim-remote/raw/master/images/demo2.gif)
|
|
|
|
|
|
|
|
## FAQ
|
|
|
|
|
2018-02-28 16:34:21 +00:00
|
|
|
- **How to open directories?**
|
2017-09-29 14:36:44 +00:00
|
|
|
|
2018-02-28 16:34:21 +00:00
|
|
|
`: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).
|
2017-09-29 14:36:44 +00:00
|
|
|
|
2018-02-28 16:34:21 +00:00
|
|
|
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:
|
2017-09-29 14:36:44 +00:00
|
|
|
|
2018-02-28 16:34:21 +00:00
|
|
|
$ nvr /tmp -c 'doautocmd BufEnter'
|
2017-09-29 14:36:44 +00:00
|
|
|
|
2018-02-28 16:34:21 +00:00
|
|
|
- **Reading from stdin?**
|
2017-09-29 14:36:44 +00:00
|
|
|
|
2018-02-28 16:34:21 +00:00
|
|
|
Yes! E.g. `echo "foo\nbar" | nvr -o -` and `cat file | nvr --remote -` work just
|
|
|
|
as you would expect them to work.
|
2017-09-29 14:36:44 +00:00
|
|
|
|
2018-02-28 16:34:21 +00:00
|
|
|
- **Exit code?**
|
2017-09-29 14:36:44 +00:00
|
|
|
|
2018-02-28 16:34:21 +00:00
|
|
|
If you use a [recent enough
|
|
|
|
Neovim](https://github.com/neovim/neovim/commit/d2e8c76dc22460ddfde80477dd93aab3d5866506), nvr will use the same exit code as the linked nvim.
|
2017-09-29 14:36:44 +00:00
|
|
|
|
2018-02-28 16:34:21 +00:00
|
|
|
E.g. `nvr --remote-wait <file>` and then `:cquit` in the linked nvim will make
|
|
|
|
nvr return with 1.
|
2017-09-29 14:36:44 +00:00
|
|
|
|
2018-02-28 16:34:21 +00:00
|
|
|
- **How to send a message to all waiting clients?**
|
2017-09-29 14:36:44 +00:00
|
|
|
|
2018-02-28 16:34:21 +00:00
|
|
|
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.
|
2017-09-29 14:36:44 +00:00
|
|
|
|
2018-02-28 16:34:21 +00:00
|
|
|
Currently nvr only understands the `Exit` message. You could use it to
|
|
|
|
disconnect all waiting nvr clients at once:
|
2017-09-29 14:36:44 +00:00
|
|
|
|
2018-02-28 16:34:21 +00:00
|
|
|
```vim
|
|
|
|
command! DisconnectClients
|
|
|
|
\ if exists('b:nvr')
|
|
|
|
\| for client in b:nvr
|
|
|
|
\| silent! call rpcnotify(client, 'Exit', 1)
|
|
|
|
\| endfor
|
|
|
|
\| endif
|
|
|
|
```
|
2017-09-29 14:36:44 +00:00
|
|
|
|