Neovim: restore --remote (+clientserver)

Created on 28 Dec 2014  Â·  58Comments  Â·  Source: neovim/neovim

AFAICT there is no reason we should not restore these Vim command line options:

   --remote <files>â–¸    Edit <files> in a Vim server if possible
   --remote-silent <files>  Same, don't complain if there is no server
   --remote-wait <files>  As --remote but wait for files to have been edited
   --remote-wait-silent <files>  Same, don't complain if there is no server
   --remote-tab[-wait][-silent] <files>  As --remote but use tab page per file
   --remote-send <keys>â–¸Send <keys> to a Vim server and exit
   --remote-expr <expr>â–¸Evaluate <expr> in a Vim server and print result 

What is the equivalent of these options in the current state of Neovim? cc @tarruda

api compatibility non-trivial good first issue help wanted

Most helpful comment

I'm curious: Is there any work on this yet? I am very much looking forward to neovim getting support for the --remote commands again!

All 58 comments

:+1: I really need this for synctex.

What is the equivalent of these options in the current state of Neovim? cc @tarruda

Any of vim remote-* commands can be easily emulated via msgpack-rpc, here's a quick and dirty python implementation:

#!/usr/bin/env python
import click, re, sys
from neovim import attach


IP_ADDR = re.compile(r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(?:\:\d{1,5})?$')


@click.command(context_settings=dict(allow_extra_args=True))
@click.option('--address')
@click.option('--send', default=None)
@click.option('--expr', default=None)
@click.option('--tab/--no-tab', default=False)
@click.option('--silent/--no-silent', default=False)
@click.pass_context
def main(ctx, address, send, expr, tab, silent):
    if IP_ADDR.match(address):
        args = ('tcp',)
        kwargs = {'address': address}
    else:
        args = ('socket',)
        kwargs = {'path': address}
    try:
        nvim = attach(*args, **kwargs)
    except Exception as e:
        if not silent:
            print >> sys.stderr, e.message
        sys.exit(1)

    if send:
        nvim.input(send)
    elif expr:
        print nvim.eval(expr)
    else:
        files = ctx.args
        if not files:
            print >> sys.stderr, 'Need at least one file to edit'
            sys.exit(1)
        cmd = 'tabedit' if tab else 'edit'
        for f in files:
            nvim.command('{0} {1}'.format(cmd, f))


if __name__ == '__main__':
    main()

The question is, do we need to bundle this functionality in the nvim executable? IMO it would be better to have a general purpose shell utility and distribute it with nvim.

With something like https://github.com/neovim/neovim/pull/1446 we wouldn't need python. I would say it should be bundled

With something like #1446 we wouldn't need python. I would say it should be bundled

Yea, ideally it should just work without fussing and (as has been recently shown by @justinmk) getting python to work is not always fuss-free. So a VimL implementation of this functionality would, in my mind, show the true power of nvim.

Just an idea: Perhaps Neovim could ship with a small application written in C called nvimclient that would do only one thing: get the environment variable NVIM_LISTEN_ADDRESS and send a message to that address. Then, it would be easy to implement SyncTeX backward with PDF viewers like Zathura and Sumatra which accept a command line argument to setup the backward search. If the pdf viewers are started by nvim, they will inherit its environment variables. The nvimclient could also accept the --servername argument for compatibility with Vim plugins that use the 'clientserver' feature.

Why a separate program?

The main reason to have a separate program is because it would be quicker to launch, but I am not sure if this is necessary since nvim is already lightweight. Another reason is that when nvim finds the environment variable NVIM_LISTEN_ADDRESS it listens on the address while the nvimclient would write to it. But this is not a good reason too because the arguments --remote-expr etc will turn nvim into a client. One third reason is that the command line to call nvimclient would be simpler than calling nvim. For example, it could be

nvimclient 'call MyFunction("text here", 0)'

instead of

nvim --servername /tmp/nvimCg4gH/0 --remote-expr 'MyFunction("text here", 0)'

But, at the end, I am sure that any implementation will be good and plugin developers will adapt to whatever decision Neovim developers make.

The main reason to have a separate program is because it would be quicker to launch, but I am not sure if this is necessary since nvim is already lightweight.

@jalvesaq as long as we only run the code necessary to connect and send the message(no need to source vimrc or any other scripts), the startup would already be fast since it's very likely that the code is already cached by the operating system.

Another reason is that when nvim finds the environment variable NVIM_LISTEN_ADDRESS it listens on the address while the nvimclient would write to it.

We need to change that, now that we have a serverlisten function, it would be better to only listen on a socket when explicitly started by the user or a plugin.

Honestly, I don't think we need to reimplement the --remote-* flags from vim, there's no need to maintain compatibility with command line options. With the changes introduced by @splinterofchaos in #1446, rpcrequest/rpcnotify can already control remote nvim instances in any way imaginable. We just need a rpcconnect function to connect to an already running instance(rpcstart will spawn a new instance).

With a vimscript command library wrapping rpcrequest/rpcconnect, sending a command to another nvim would be as simple:

nvim -u NONE +'RemoteSend /path/to/socket command'

It's good to know that only rpcconnect is missing!

As you guys are talking about, is there a way to make neovim + Skim backward search working?

I don't know what Skim is.

Skim is a PDF viewer (Mac OS X) with SyncTeX support. For those who don't know, SyncTeX is a system of synchronization between a LaTeX text editor (which might be Vim or Neovim) and the PDF viewer. We can both click in the PDF to jump to the corresponding line in the text editor and issue a command in the text editor to jump to the corresponding place in the PDF. That is, we need a way of sending a message from the PDF editor to Neovim. In Vim, the 'clientserver' is used for SyncTeX.

I implemented SyncTeX support for Rnoweb (LaTeX + R) files in Neovim (Nvim-R), but in order to do this, I created a C application that runs a TCP server (run as a Neovim job) and another C application that I called nvimrclient which sends messages to the server. The PDF viewer must be configured to run the nvimrclient.

I created a C application that runs a TCP server (run as a Neovim job) and another C application that I called nvimrclient which sends messages to the server.

A very urgent goal for us is to make nvim serve this purpose out of the box, i.e., it should be a client of itself. https://github.com/neovim/neovim/issues/3119

The legacy --remote feature would be implemented as a special case of this general capability.

It would be great if --remote works out of the box.

"It would be great if --remote works out of the box." +1 :)

Agreed, I also would very much like this feature in neovim. I'm developing vimtex, and I am using callbacks with the following syntax in vim:

vim --servername NAME --remote-expr "function-name()"

I both know and understand that I can utilize external scripts through python and ruby (and I guess other languages), but I think the "old" method is very convenient for my particular need.

I am currently working on neovim support, see #262, and if the legacy feature was added to neovim, then the changes required in vimtex would be minimal.

I would love to see this implemented.

In the meantime @lervag this is the easiest way I found to sort it out.
It's in Scala, but it should be easy to translate to vimscript.

Cheers.

Thanks, @ktonga.

+1 to seeing this implemented in neovim, or a closely comparable and compatible alternative.

As long as there's no other solution, here a wrapper script that handles --remote and friends: https://github.com/mhinz/neovim-remote

Awesome. That makes it straightforward for someone to use as a reference for implementing in C.

Thanks, @mhinz!

Doing

nvr --servername $TMPDIR/nvim --remote-tab /tmp

or

nvr --servername $TMPDIR/nvim -c 'tabedit /tmp'

given that /tmp is real directory tab is not opened. I can see the buffer listed though. I know that directories are treated specially, and in this case I've disabled netrw but just for sake of consistency it should behave the same as when doing :tabedit /tmp from inside nvim when actually new tab is created. Could this be related to the fact that autocommands are not triggered (as I've learned from nvim-remote README)?

What's the status on this bug exactly? Are we going to stick with the status quo or bundle a client program for compatiblity with vim?

I'm curious because I'm considering packaging https://github.com/mhinz/neovim-remote, and if it's only a temporary solution, there's not much point.

Are we going to stick with the status quo or bundle a client program for compatiblity with vim?

Neither. https://github.com/mhinz/neovim-remote is a temporary solution.

I'm curious: Is there any work on this yet? I am very much looking forward to neovim getting support for the --remote commands again!

I make heavy use of the --remote option but in my workflow (which is quite specific I must admit) those options are useless without the --servername option. I heard neovim could be a drop in replacement to vim but without those options I can't give neovim a try.

Three questions anyways:

  1. how can I start a nvim instance from command line in a way that I can find it later (by name, id or whatever) in the opened sockets ? (... so read: "how can I emulate --servername with neovim" ?)
  2. when connected to a neovim instance, how can I get the directory from where neovim was initially run in ? So I don't mean the current directory [neovim.eval('getcwd()')] but the initial directory
  3. what is the preferred/fastest way to get a list of the currently opened neovim file sockets on the local machine ? If globing /tmp/nvim* is the way to go then I suggest to use $XDG_RUNTIME_DIR/neovim/* instead.

1+3) Set $NVIM_LISTEN_ADDRESS to a path of your choice.

$ NVIM_LISTEN_ADDRESS=~/servers/foo nvim
$ NIVM_LISTEN_ADDRESS=~/servers/bar nvim
$ ls -1 ~/servers

2) I don't think Vim keeps that information.

autocmd VimEnter * let g:init_dir = getcwd()
$ nvr --remote-expr g:init_dir
/etc/manpaths.d

@mhinz Excellent ! After all I've got all I need to try neovim in my workflow.

Thanks a lot !

I'm curious: Is there any progress or work on this?

Any progress on supporting this legacy capability will be noted in this issue, or in backreferences to this issue. So it's not necessary to ask about progress, and definitely not necessary to ask more than once.

In the meantime Nvim has a robust API, which can be used to achieve anything that --remote-* can be used for. Help is also welcome: core developers are focused on the 0.2 milestone, but anyone is welcome to work on things they consider more important...

Just to be clear: I have deep respect for your work with neovim, and I acknowledge and appreciate the major effort involved! I also understand your reply that progress will be visible in the thread. The reason I asked a second time was more to stress that I think this is an important issue, and I think it would have been better if I just said that directly.

Unfortunately, I do not have the necessary skills to work on this issue myself. If I did, I would definately consider to help!

So: Sorry for being rude, and thank you for the already very impressive effort and work on neovim!

But what exactly is the issue? Neovim remote seems to work perfectly at the
moment, I have been using without any problems.

On Nov 13, 2016 1:21 AM, "Karl Yngve LervÃ¥g" [email protected]
wrote:

Just to be clear: I have deep respect for your work with neovim, and I
acknowledge and appreciate the major effort involved! I also understand
your reply that progress will be visible in the thread. The reason I asked
a second time was more to stress that I think this is an important issue,
and I think it would have been better if I just said that directly.

Unfortunately, I do not have the necessary skills to work on this issue
myself. If I did, I would definately consider to help!

So: Sorry for being rude, and thank you for the already very impressive
effort and work on neovim!

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/neovim/neovim/issues/1750#issuecomment-260171062, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AGBkZj5Aak0TEIj_EDBeLOGMORtUNa4yks5q9rqFgaJpZM4DMvFw
.

On Nov 13, 2016 9:09 AM, "yashamon" [email protected] wrote:

But what exactly is the issue? Neovim remote seems to work perfectly at
the
moment, I have been using without any problems.

Same here.

The authors of Neovim remote already did the work of using Neovim's API to
implement the --remote flags.

@lervag I believe the last two comments are referring to https://github.com/mhinz/neovim-remote. It's a good option, but we do plan to build this into nvim itself at some point.

Thanks for the info. I knew about neovim-remote, and I understand that it works well. I'll consider to try it myself while waiting for this to be built into nvim.

@justinmk hi, I use neovim with more than 200+ plugins, so the startup time is too long, and I want to use nvim as a server, and Keeping the server alive all the time, everytime when I start nvim, just check if the server is alive, if the server is exist, just connect to the server, and stop loadding the init.vim.
with this feature, we can change ~/.config/nvim/init.vim to

if {server exist}
          " then just connect to the exist server
          " stop loadding init.vim
          finish
endif

" if server does not exist, load the init.vim, and make current nvim server as a detach process

" set options
set nu

" defind mapping

" load plugins


NVR works. But I would like to end that as a long term solution it is
unacceptable. For instance, there is currently a bug affecting nvr usage
with the simple plugin goyo, but I have been lazy about filling it, because
it is not even clear where, goyo developer, neovim, NVR developer? Which
one?

On Oct 4, 2017 12:45 AM, "Wang Shidong" notifications@github.com wrote:

@justinmk https://github.com/justinmk hi, I use neovim with more than
200+ plugins, so the startup time is too long, and I want to use nvim as a
server, and Keeping the server alive all the time, everytime when I start
nvim, just check if the server is alive, if the server is exist, just
connect to the server, and stop loadding the init.vim.
with this feature, we can change ~/.config/nvim/init.vim to

if {server exist} " then just connect to the exist server " stop loadding init.vim
finishendif
" if server does not exist, load the init.vim, and make current nvim server as a detach process
" set optionsset nu
" defind mapping
" load plugins

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/neovim/neovim/issues/1750#issuecomment-334055629, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AGBkZh_jsGRKLNmkmutuLueUyW8ZTNTVks5soxuMgaJpZM4DMvFw
.

Well, we can't possibly answer that without details of the bug.

Even this bug in nvr will be fixed finally, NVR does not support windows and it won't. https://github.com/mhinz/neovim-remote/issues/53

This feature is planned, note the 0.3. milestone tag.

That's good news. Sorry I was not aware.

On Thu, Oct 5, 2017 at 2:30 AM, Justin M. Keyes notifications@github.com
wrote:

This feature is planned, note the 0.3. milestone tag.

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/neovim/neovim/issues/1750#issuecomment-334382051, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AGBkZpf3kRQhohr1FMC2d1xp0o1kSmRZks5spIV_gaJpZM4DMvFw
.

@justinmk it looks like the milestone tag says 0.4, can you clarify if that is correct or if it's still planned for 0.3?

@catskul it's planned for 0.4

NVIM_LISTEN_ADDRESS=servername nvim filename.tex works to do forward synctex at least.

@justinmk this seems similar to the proposal i was working on..
This will require connecting to NVIM_LISTEN_ADDRESS from nvim and then just using rpc_send_call to send commands right?

@geekodour rpc_send_call certainly will be involved.

This issue could also potentially involve "discovery" of existing Nvim servers, so the user could say "connect to the first server that you find", or "connect to a server named foo". Though we could leave that as a TODO.

@justinmk I tried implementing --remote it seems to work fine so far. please suggest changes/improvements, I'll create a PR with the other options then. Also about the discovery of servers,

"connect to the first server that you find"

how can we find the nvim instances, lookup processes? I am new to this.

$  NVIM_LISTEN_ADDRESS=/tmp/nvimFapyty/0 ./nvim --remote file1.txt file2.txt file3.txt
diff --git a/src/nvim/main.c b/src/nvim/main.c
index a4ed868af..d8b12d68f 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -112,6 +112,7 @@ typedef struct {
   int diff_mode;                        // start with 'diff' set

   char *listen_addr;                    // --listen {address}
+  bool cs_remote;                       // --remote {file1} {file2}
 } mparm_T;

 /* Values for edit_type. */
@@ -259,6 +260,31 @@ int main(int argc, char **argv)
   command_line_scan(&params);
   server_init(params.listen_addr);

+  if (params.cs_remote) {
+    const char *env_addr = os_getenv("NVIM_LISTEN_ADDRESS");
+    CallbackReader on_data = CALLBACK_READER_INIT;
+    const char *error = NULL;
+    uint64_t rc_id = channel_connect(false, env_addr, true,
+                                     on_data, 50, &error);
+    if (!rc_id) {
+      exit(0);
+    }
+    uint64_t command_len = GARGCOUNT * global_alist.al_ga.ga_itemsize * 2;
+    char_u * command = xmalloc(command_len);
+    xstrlcpy(command, "args ", sizeof(command));
+    for (uint8_t i = 0; i < GARGCOUNT; i++) {
+      char_u * filename = ((aentry_T *)global_alist.al_ga.ga_data+i)->ae_fname;
+      xstrlcat(command, filename, command_len);
+      xstrlcat(command, " ", command_len);
+    }
+    Array args = ARRAY_DICT_INIT;
+    Error err = ERROR_INIT;
+    String s = { .data = command, .size = strlen(command) * sizeof(char) };
+    ADD(args, STRING_OBJ(s));
+    rpc_send_call(rc_id, "nvim_command", args, &err);
+    exit(0);
+  }
+
   if (GARGCOUNT > 0) {
     fname = get_fname(&params, cwd);
   }
@@ -779,6 +805,7 @@ static void command_line_scan(mparm_T *parmp)
           /* "--literal" take files literally */
           /* "--noplugin[s]" skip plugins */
           /* "--cmd <cmd>" execute cmd before vimrc */
+          /* "--remote" open file on remote instance */
           if (STRICMP(argv[0] + argv_idx, "help") == 0) {
             usage();
             mch_exit(0);
@@ -824,9 +851,11 @@ static void command_line_scan(mparm_T *parmp)
 #if !defined(UNIX)
             parmp->literal = TRUE;
 #endif
-          } else if (STRNICMP(argv[0] + argv_idx, "noplugin", 8) == 0)
+          } else if (STRNICMP(argv[0] + argv_idx, "noplugin", 8) == 0){
             p_lpl = FALSE;
-          else if (STRNICMP(argv[0] + argv_idx, "cmd", 3) == 0) {
+          } else if (STRNICMP(argv[0] + argv_idx, "remote", 6) == 0) {
+            parmp->cs_remote = true;
+          } else if (STRNICMP(argv[0] + argv_idx, "cmd", 3) == 0) {
             want_argument = TRUE;
             argv_idx += 3;
           } else if (STRNICMP(argv[0] + argv_idx, "startuptime", 11) == 0) {
@@ -1969,6 +1998,7 @@ static void usage(void)
   mch_msg(_("  --literal             Don't expand wildcards\n"));
 #endif
   mch_msg(_("  --noplugin            Don't load plugins\n"));
+  mch_msg(_("  --remote              Open file remotely\n"));
   mch_msg(_("  --startuptime <file>  Write startup timing messages to <file>\n"));
   mch_msg(_("\nSee \":help startup-options\" for all options.\n"));
 }

@geekodour Very interesting, why not create a PR directly, which allows easier discussion on the diff?

neovim-remote plugin doesn't work on windows, so #8326 would be very helpful.

In particular, this would enable a neovim-based LaTeX workflow using vimtex and including its backward-search functionality (ability to jump from a line in pdf file back to the corresponding LaTeX source line in neovim).

@nadya-p this would enable a lot of stuff. including but not limited to the case you sounded and also using neovim as git editor

I have just tried neovim and almost everything works nice, except the vimtex plugin.

Since neovim-remote doesnt solve all problems maybe someone could solve this issue.

Just to reinforce the importance: vimtex plugin depends on this issue to have full functionality and it is to the best of my knowledge the best plugin for latex by far. For those who possibly doesnt know what latex is, it is very nice high quality typesetting system to produce documents. It is widelly used in science, to write academic papers in the most respected journals and congresses.

I tried neovim and it is really nice, faster than vim, the only thing keeping me from using is that vimtex does not work very well. @tarruda, for neovim to be the future of vim, shouldn't it be compatible with the past?

The link you gave mentions neovim-remote, did you try that? I find it pretty even though I don't use vimtex. Ok, you did, but you don't mention what doesn't work, the link states that everything should work, so lervag might be open to bug report if something's amiss with nvr.

As a side note, tarruda isn't active in the project anymore, so no need to ping him on this.

@iurobpn This is actively worked on in https://github.com/neovim/neovim/pull/8326

@bfredl , its great that there are people working on it.

@KillTheMule, the so called 'backward search' doesnt work for me in neovim. But the 'forward search' started working on my last test, so I'm not sure if the problem is with neovim-remote, neovim or vimtex anymore.

The issue on vimtex states that on the vimtex part it is all ok, but neovim had some work on the clientserver to do solve this problems.

Thank you for your fast answers.

@iurobpn @KillTheMule I've been using vimtex + neovim 0.3.1 (via pynvim) for months and both backward and forward search work fine for me.

Pierre, is this still via nvr, or does pynvim have its own remote setup?
Would you mind sharing how this works?

On Thu, Dec 13, 2018 at 5:15 PM Pierre Ganty notifications@github.com
wrote:

@iurobpn https://github.com/iurobpn @KillTheMule
https://github.com/KillTheMule I've been using vimtex + neovim 0.3.1
(via pynvim) for months and both backward and forward search work fine for
me.

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/neovim/neovim/issues/1750#issuecomment-447155960, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AGBkZiUIXkgiuNMQ7OWCBJGPxfbf9KQsks5u4t-vgaJpZM4DMvFw
.

If anyone run into the same problem, this vimura script solved this for me. There are more steps in the link, but I just used the vimura to substitute my configuration of the zathura 'backward search'.

@yashamon , I used the nvr.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

bedge picture bedge  Â·  3Comments

gnujeremie picture gnujeremie  Â·  3Comments

andreicristianpetcu picture andreicristianpetcu  Â·  3Comments

nhooyr picture nhooyr  Â·  3Comments

nhooyr picture nhooyr  Â·  3Comments