From f19db1b9ba864e4e57cc9ee29763ae5f74bcb415 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 10 Apr 2018 23:24:46 +0200 Subject: [PATCH 1/7] remove scripts/run-api-tests.exp Usage of this script was removed 0c2ec77ae0c0. --- scripts/run-api-tests.exp | 50 --------------------------------------- 1 file changed, 50 deletions(-) delete mode 100755 scripts/run-api-tests.exp diff --git a/scripts/run-api-tests.exp b/scripts/run-api-tests.exp deleted file mode 100755 index 27c9c963e5..0000000000 --- a/scripts/run-api-tests.exp +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env expect - -if {$argc < 2} { - puts "Need commands for running the tests and for starting nvim" - exit 1 -} - -set timeout 60 -set run_tests [split [lindex $argv 0] " "] -set run_nvim [split [lindex $argv 1] " "] - -# don't echo to stdout -log_user 0 -# set NVIM_LISTEN_ADDRESS, so nvim will listen on a known socket -set env(NVIM_LISTEN_ADDRESS) "/tmp/nvim-[exec date +%s%N].sock" -# start nvim -spawn {*}$run_nvim -# save the job descriptor -set nvim_id $spawn_id -# Reset function that can be invoked by test runners to put nvim in a cleaner -# state -send { -:echo "read"."y" -} -# wait until nvim is ready -expect "ready" -# run tests -spawn {*}$run_tests -set tests_id $spawn_id -set status 1 -# listen for test output in the background -expect_background { - * { - # show test output to the user - send_user -- $expect_out(buffer) - } - eof { - # collect the exit status code - set spawn_id $tests_id - catch wait result - set status [lindex $result 3] - set spawn_id $nvim_id - # quit nvim - send ":qa!\r" - } -} -# switch back nvim and wait until it exits -set spawn_id $nvim_id -expect eof -exit $status From b11b681289582472340e3af72ea116c4ba354066 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Wed, 11 Apr 2018 01:43:15 +0200 Subject: [PATCH 2/7] test/util: matches() --- test/functional/helpers.lua | 2 ++ test/helpers.lua | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index b8d912114d..84ba6b6853 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -16,6 +16,7 @@ local neq = global_helpers.neq local eq = global_helpers.eq local ok = global_helpers.ok local map = global_helpers.map +local matches = global_helpers.matches local filter = global_helpers.filter local dedent = global_helpers.dedent local table_flatten = global_helpers.table_flatten @@ -747,6 +748,7 @@ local module = { insert = insert, iswin = iswin, map = map, + matches = matches, merge_args = merge_args, meth_pcall = meth_pcall, meths = meths, diff --git a/test/helpers.lua b/test/helpers.lua index 7cce6d8c55..0b6a10a29a 100644 --- a/test/helpers.lua +++ b/test/helpers.lua @@ -16,6 +16,12 @@ end local function ok(res) return assert.is_true(res) end +local function matches(pat, actual) + if nil ~= string.match(actual, pat) then + return true + end + error(string.format('Pattern does not match.\nPattern:\n%s\nActual:\n%s', pat, actual)) +end -- initial_path: directory to recurse into -- re: include pattern (string) @@ -572,6 +578,7 @@ return { hasenv = hasenv, intchar2lua = intchar2lua, map = map, + matches = matches, mergedicts_copy = mergedicts_copy, neq = neq, ok = ok, From 9f598e57656fe072114b9f1e73d3051423e13234 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 8 Apr 2018 13:06:26 +0200 Subject: [PATCH 3/7] serverstop(): return FALSE for invalid address --- man/nvim.1 | 37 +++++++++++----------------- runtime/doc/eval.txt | 24 +++++++----------- src/nvim/eval.c | 5 +++- src/nvim/msgpack_rpc/server.c | 8 +++--- test/functional/eval/server_spec.lua | 20 +++++++-------- 5 files changed, 42 insertions(+), 52 deletions(-) diff --git a/man/nvim.1 b/man/nvim.1 index d2a3ea5c43..809e7e047e 100644 --- a/man/nvim.1 +++ b/man/nvim.1 @@ -25,7 +25,7 @@ To enter commands in type a colon .Pq Sq \&: which is also used in this manual to denote commands. -For more information, consult the on-line help system with the +For more information, consult the online help system with the .Ic :help command. .Bl -tag -width Fl @@ -337,12 +337,12 @@ Print version information and exit. .Sh ENVIRONMENT .Bl -tag -width Fl .It Ev VIM -Used to locate various user files, such as the user's init.vim. +Used to locate various user files, such as init.vim. .It Ev VIMRUNTIME -Used to locate run time files, such as on-line documentation and +Used to locate runtime files, such as online documentation and syntax highlighting definitions. .It Ev XDG_CONFIG_HOME -Path to use for the user-local configuration directory, see +Path to the user-local configuration directory, see .Sx FILES . Defaults to .Pa ~/.config @@ -356,7 +356,7 @@ Defaults to .Pa ~/.local/share if not set. .It Ev VIMINIT -A string of Ex commands to be executed at startup. +Ex commands to be executed at startup. For example, the command to quit is .Ic :q , so to have @@ -375,41 +375,32 @@ command. .Sh FILES .Bl -tag -width "~/.config/nvim/init.vim" .It Pa ~/.config/nvim/init.vim -The user-local +User-local .Nm configuration file. -See -.Ev XDG_CONFIG_HOME -above. .It Pa ~/.config/nvim -The user-local +User-local .Nm configuration directory. -See -.Ev XDG_CONFIG_HOME -above. +See also +.Ev XDG_CONFIG_HOME . .It Pa $VIM/sysinit.vim -The system-global +System-global .Nm configuration file. .It Pa /usr/local/share/nvim -The system-global +System-global .Nm runtime directory. .El .Sh AUTHORS -.Nm -was started by -.An Thiago de Arruda , -with a lot of help from others. -.Pp +Nvim was started by +.An Thiago de Arruda . Most of Vim was written by .An -nosplit -.An Bram Moolenaar , -with a lot of help from others. +.An Bram Moolenaar . See .Ic :help credits . -.Pp Vim is based on Stevie, worked on by .An Tim Thompson , .An Tony Andrews , diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 767fc133d8..084936e9d2 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1789,8 +1789,10 @@ v:scrollstart String describing the script or function that caused the *v:servername* *servername-variable* *$NVIM_LISTEN_ADDRESS* -v:servername Default Nvim server address. Equivalent to - |$NVIM_LISTEN_ADDRESS| on startup. |serverstop()| +v:servername Primary listen address of the current Nvim instance, the first + item returned by |serverlist()|. Can be set by + |--listen| or |$NVIM_LISTEN_ADDRESS| on startup. + See also |serverstart()| and |serverstop()|. Read-only. @@ -6638,15 +6640,11 @@ server2client({clientid}, {string}) *server2client()* :echo server2client(expand(""), "HELLO") < serverlist() *serverlist()* - Returns a list of available server names in a list. - When there are no servers an empty string is returned. + Returns a list of server addresses, or empty if all servers + were stopped. |serverstart()| |serverstop()| Example: > :echo serverlist() -< {Nvim} *--serverlist* - The Vim command-line option `--serverlist` was removed from - Nvim, but it can be imitated: > - nvim --cmd "echo serverlist()" --cmd "q" -< + serverstart([{address}]) *serverstart()* Opens a socket or named pipe at {address} and listens for |RPC| messages. Clients can send |API| commands to the address @@ -6674,13 +6672,9 @@ serverstart([{address}]) *serverstart()* < |$NVIM_LISTEN_ADDRESS| is set to {address} if not already set. - *--servername* - The Vim command-line option `--servername` can be imitated: > - nvim --cmd "let g:server_addr = serverstart('foo')" -< serverstop({address}) *serverstop()* - Closes the pipe or socket at {address}. Does nothing if - {address} is empty or invalid. + Closes the pipe or socket at {address}. + Returns TRUE if {address} is valid, else FALSE. If |$NVIM_LISTEN_ADDRESS| is stopped it is unset. If |v:servername| is stopped it is set to the next available address returned by |serverlist()|. diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 7bdfe7c9ee..284185083e 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -14403,8 +14403,11 @@ static void f_serverstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = 0; if (argvars[0].vval.v_string) { - server_stop((char *) argvars[0].vval.v_string); + bool rv = server_stop((char *)argvars[0].vval.v_string); + rettv->vval.v_number = (rv ? 1 : 0); } } diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c index 9bf122f4db..4d0e6b07a0 100644 --- a/src/nvim/msgpack_rpc/server.c +++ b/src/nvim/msgpack_rpc/server.c @@ -177,7 +177,7 @@ int server_start(const char *endpoint) /// Stops listening on the address specified by `endpoint`. /// /// @param endpoint Address of the server. -void server_stop(char *endpoint) +bool server_stop(char *endpoint) { SocketWatcher *watcher; bool watcher_found = false; @@ -196,8 +196,8 @@ void server_stop(char *endpoint) } if (!watcher_found) { - ELOG("Not listening on %s", addr); - return; + WLOG("Not listening on %s", addr); + return false; } // Unset $NVIM_LISTEN_ADDRESS if it is the stopped address. @@ -219,6 +219,8 @@ void server_stop(char *endpoint) if (STRCMP(addr, get_vim_var_str(VV_SEND_SERVER)) == 0) { set_vservername(&watchers); } + + return true; } /// Returns an allocated array of server addresses. diff --git a/test/functional/eval/server_spec.lua b/test/functional/eval/server_spec.lua index 393616838e..edd63fe83c 100644 --- a/test/functional/eval/server_spec.lua +++ b/test/functional/eval/server_spec.lua @@ -11,21 +11,21 @@ local function clear_serverlist() end end -describe('serverstart(), serverstop()', function() +describe('server', function() before_each(clear) - it('sets $NVIM_LISTEN_ADDRESS on first invocation', function() + it('serverstart() sets $NVIM_LISTEN_ADDRESS on first invocation', function() -- Unset $NVIM_LISTEN_ADDRESS command('let $NVIM_LISTEN_ADDRESS = ""') local s = eval('serverstart()') assert(s ~= nil and s:len() > 0, "serverstart() returned empty") eq(s, eval('$NVIM_LISTEN_ADDRESS')) - command("call serverstop('"..s.."')") + eq(1, eval("serverstop('"..s.."')")) eq('', eval('$NVIM_LISTEN_ADDRESS')) end) - it('sets v:servername _only_ on nvim startup unless all servers are stopped', + it('serverstart() sets v:servername at startup or if all servers were stopped', function() local initial_server = meths.get_vvar('servername') assert(initial_server ~= nil and initial_server:len() > 0, @@ -38,11 +38,11 @@ describe('serverstart(), serverstop()', function() neq(initial_server, s) -- serverstop() does _not_ modify v:servername... - funcs.serverstop(s) + eq(1, funcs.serverstop(s)) eq(initial_server, meths.get_vvar('servername')) -- ...unless we stop _all_ servers. - funcs.serverstop(funcs.serverlist()[1]) + eq(1, funcs.serverstop(funcs.serverlist()[1])) eq('', meths.get_vvar('servername')) -- v:servername will take the next available server. @@ -53,9 +53,9 @@ describe('serverstart(), serverstop()', function() eq(servername, meths.get_vvar('servername')) end) - it('serverstop() ignores invalid input', function() - command("call serverstop('')") - command("call serverstop('bogus-socket-name')") + it('serverstop() returns false for invalid input', function() + eq(0, eval("serverstop('')")) + eq(0, eval("serverstop('bogus-socket-name')")) end) it('parses endpoints correctly', function() @@ -120,7 +120,7 @@ describe('serverlist()', function() -- The new servers should be at the end of the list. for i = 1, #servs do eq(servs[i], new_servs[i + n]) - command("call serverstop('"..servs[i].."')") + eq(1, eval("serverstop('"..servs[i].."')")) end -- After serverstop() the servers should NOT be in the list. eq(n, eval('len(serverlist())')) From 7362ca44305d11c41d0dee14f49d0ac248abacf8 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 8 Apr 2018 14:04:58 +0200 Subject: [PATCH 4/7] cleanup: remove main_start_gui() --- src/nvim/ex_docmd.c | 6 ++---- src/nvim/globals.h | 1 - src/nvim/main.c | 29 ++--------------------------- 3 files changed, 4 insertions(+), 32 deletions(-) diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 4b37abab9e..93cb0e50fa 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -6975,12 +6975,10 @@ do_exedit ( ex_no_reprint = TRUE; } -/* - * ":gui" and ":gvim" when there is no GUI. - */ +/// ":gui" and ":gvim" when there is no GUI. static void ex_nogui(exarg_T *eap) { - eap->errmsg = e_nogvim; + eap->errmsg = (char_u *)N_("E25: Nvim does not have a built-in GUI"); } diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 776f131437..89d93310a6 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -1070,7 +1070,6 @@ EXTERN char_u e_nesting[] INIT(= N_("E22: Scripts nested too deep")); EXTERN char_u e_noalt[] INIT(= N_("E23: No alternate file")); EXTERN char_u e_noabbr[] INIT(= N_("E24: No such abbreviation")); EXTERN char_u e_nobang[] INIT(= N_("E477: No ! allowed")); -EXTERN char_u e_nogvim[] INIT(= N_("E25: Nvim does not have a built-in GUI")); EXTERN char_u e_nogroup[] INIT(= N_("E28: No such highlight group name: %s")); EXTERN char_u e_noinstext[] INIT(= N_("E29: No inserted text yet")); EXTERN char_u e_nolastcmd[] INIT(= N_("E30: No previous command line")); diff --git a/src/nvim/main.c b/src/nvim/main.c index 4288d7f9d7..cd7c13ae9a 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -864,10 +864,6 @@ static void command_line_scan(mparm_T *parmp) case 'f': /* "-f" GUI: run in foreground. */ break; - case 'g': /* "-g" start GUI */ - main_start_gui(); - break; - case 'F': { // "-F" start in Farsi mode: rl + fkmap set. p_fkmap = true; set_option_value("rl", 1L, NULL, 0); @@ -906,18 +902,8 @@ static void command_line_scan(mparm_T *parmp) parmp->no_swap_file = TRUE; break; - case 'p': /* "-p[N]" open N tab pages */ -#ifdef TARGET_API_MAC_OSX - /* For some reason on MacOS X, an argument like: - -psn_0_10223617 is passed in when invoke from Finder - or with the 'open' command */ - if (argv[0][argv_idx] == 's') { - argv_idx = -1; /* bypass full -psn */ - main_start_gui(); - break; - } -#endif - /* default is 0: open window for each file */ + case 'p': // "-p[N]" open N tab pages + // default is 0: open window for each file parmp->window_count = get_number_arg(argv[0], &argv_idx, 0); parmp->window_layout = WIN_TABS; break; @@ -1834,17 +1820,6 @@ static void source_startup_scripts(const mparm_T *const parmp) TIME_MSG("sourcing vimrc file(s)"); } -/* - * Setup to start using the GUI. Exit with an error when not available. - */ -static void main_start_gui(void) -{ - mch_errmsg(_(e_nogvim)); - mch_errmsg("\n"); - mch_exit(2); -} - - /// Get an environment variable, and execute it as Ex commands. /// /// @param env environment variable to execute From 507bda1c95cdac2886f64e59aa6bbf85c3fac389 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 8 Apr 2018 17:20:25 +0200 Subject: [PATCH 5/7] server: introduce --listen, deprecate $NVIM_LISTEN_ADDRESS --- man/nvim.1 | 3 ++ runtime/doc/deprecated.txt | 4 +++ runtime/doc/eval.txt | 8 ++--- runtime/doc/msgpack_rpc.txt | 5 ++- runtime/doc/starting.txt | 4 +++ src/nvim/main.c | 47 +++++++++++++++------------- src/nvim/msgpack_rpc/server.c | 20 ++++++------ test/functional/eval/server_spec.lua | 38 ++++++++++++++++------ 8 files changed, 80 insertions(+), 49 deletions(-) diff --git a/man/nvim.1 b/man/nvim.1 index 809e7e047e..61dbb13748 100644 --- a/man/nvim.1 +++ b/man/nvim.1 @@ -329,6 +329,9 @@ Implies .Fl -headless . .It Fl -headless Do not start a user interface. +.Fl -listen . +.It Fl -listen Ar address +Start RPC server on this pipe or TCP socket. .It Fl h , -help Print usage information and exit. .It Fl v , -version diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt index ea61e847c7..03699b3dfb 100644 --- a/runtime/doc/deprecated.txt +++ b/runtime/doc/deprecated.txt @@ -22,6 +22,10 @@ Commands ~ *:wv* *:wviminfo* Deprecated alias to |:wshada| command. +Environment Variables ~ +*$NVIM_LISTEN_ADDRESS* Deprecated in favor of |--listen|. If both are given, + $NVIM_LISTEN_ADDRESS is ignored. + Events ~ *EncodingChanged* Never fired; 'encoding' is always "utf-8". *FileEncoding* Never fired; equivalent to |EncodingChanged|. diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 084936e9d2..11c4b62403 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1788,11 +1788,9 @@ v:scrollstart String describing the script or function that caused the hit-enter prompt. *v:servername* *servername-variable* - *$NVIM_LISTEN_ADDRESS* -v:servername Primary listen address of the current Nvim instance, the first - item returned by |serverlist()|. Can be set by - |--listen| or |$NVIM_LISTEN_ADDRESS| on startup. - See also |serverstart()| and |serverstop()|. +v:servername Primary listen-address of the current Nvim instance, the first + item returned by |serverlist()|. Can be set by |--listen| or + |$NVIM_LISTEN_ADDRESS| at startup. |serverstart()| |serverstop()| Read-only. diff --git a/runtime/doc/msgpack_rpc.txt b/runtime/doc/msgpack_rpc.txt index 11fad105b5..01d4e10cea 100644 --- a/runtime/doc/msgpack_rpc.txt +++ b/runtime/doc/msgpack_rpc.txt @@ -70,9 +70,8 @@ An rpc socket is automatically created with each instance. The socket location is stored in |v:servername|. By default this is a named pipe with an automatically generated address. See |XXX|. -To make Nvim listen on a TCP/IP socket instead, set the - |$NVIM_LISTEN_ADDRESS| environment variable before starting Nvim: > - NVIM_LISTEN_ADDRESS=127.0.0.1:6666 nvim +To make Nvim listen on a TCP/IP socket instead, specify |--listen|: > + nvim --listen 127.0.0.1:6666 0) { fname = get_fname(¶ms, cwd); @@ -819,6 +818,9 @@ static void command_line_scan(mparm_T *parmp) if (!channel_from_stdio(true, CALLBACK_READER_INIT, &err)) { abort(); } + } else if (STRNICMP(argv[0] + argv_idx, "listen", 6) == 0) { + want_argument = true; + argv_idx += 6; } else if (STRNICMP(argv[0] + argv_idx, "literal", 7) == 0) { #if !defined(UNIX) parmp->literal = TRUE; @@ -1016,15 +1018,12 @@ static void command_line_scan(mparm_T *parmp) mainerr(err_opt_unknown, argv[0]); } - /* - * Handle option arguments with argument. - */ + // Handle option arguments with argument. if (want_argument) { - /* - * Check for garbage immediately after the option letter. - */ - if (argv[0][argv_idx] != NUL) + // Check for garbage immediately after the option letter. + if (argv[0][argv_idx] != NUL) { mainerr(err_opt_garbage, argv[0]); + } --argc; if (argc < 1 && c != 'S') /* -S has an optional argument */ @@ -1063,13 +1062,17 @@ static void command_line_scan(mparm_T *parmp) break; case '-': - if (argv[-1][2] == 'c') { - /* "--cmd {command}" execute command */ - if (parmp->n_pre_commands >= MAX_ARG_CMDS) + if (strequal(argv[-1], "--cmd")) { + // "--cmd {command}" execute command + if (parmp->n_pre_commands >= MAX_ARG_CMDS) { mainerr(err_extra_cmd, NULL); + } parmp->pre_commands[parmp->n_pre_commands++] = argv[0]; + } else if (strequal(argv[-1], "--listen")) { + // "--listen {address}" + parmp->listen_addr = argv[0]; } - /* "--startuptime " already handled */ + // "--startuptime " already handled break; case 'q': /* "-q {errorfile}" QuickFix mode */ @@ -1210,11 +1213,10 @@ static void init_params(mparm_T *paramp, int argc, char **argv) paramp->want_full_screen = true; paramp->use_debug_break_level = -1; paramp->window_count = -1; + paramp->listen_addr = NULL; } -/* - * Initialize global startuptime file if "--startuptime" passed as an argument. - */ +/// Initialize global startuptime file if "--startuptime" passed as an argument. static void init_startuptime(mparm_T *paramp) { for (int i = 1; i < paramp->argc; i++) { @@ -1943,6 +1945,7 @@ static void usage(void) mch_msg(_(" --api-info Write msgpack-encoded API metadata to stdout\n")); mch_msg(_(" --embed Use stdin/stdout as a msgpack-rpc channel\n")); mch_msg(_(" --headless Don't start a user interface\n")); + mch_msg(_(" --listen
Start RPC server on this socket or TCP address\n")); #if !defined(UNIX) mch_msg(_(" --literal Don't expand wildcards\n")); #endif diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c index 4d0e6b07a0..abff5cfe4f 100644 --- a/src/nvim/msgpack_rpc/server.c +++ b/src/nvim/msgpack_rpc/server.c @@ -32,24 +32,26 @@ static garray_T watchers = GA_EMPTY_INIT_VALUE; #endif /// Initializes the module -bool server_init(void) +bool server_init(const char *listen_address) { ga_init(&watchers, sizeof(SocketWatcher *), 1); bool must_free = false; - const char *listen_address = os_getenv(LISTEN_ADDRESS_ENV_VAR); if (listen_address == NULL) { - must_free = true; - listen_address = server_address_new(); - } - - if (!listen_address) { - return false; + // Deprecated: $NVIM_LISTEN_ADDRESS + listen_address = os_getenv(LISTEN_ADDRESS_ENV_VAR); + if (listen_address == NULL) { + must_free = true; + listen_address = server_address_new(); + if (listen_address == NULL) { + return false; + } + } } bool ok = (server_start(listen_address) == 0); if (must_free) { - xfree((char *) listen_address); + xfree((char *)listen_address); } return ok; } diff --git a/test/functional/eval/server_spec.lua b/test/functional/eval/server_spec.lua index edd63fe83c..a2644498f2 100644 --- a/test/functional/eval/server_spec.lua +++ b/test/functional/eval/server_spec.lua @@ -1,14 +1,14 @@ - local helpers = require('test.functional.helpers')(after_each) local eq, neq, eval = helpers.eq, helpers.neq, helpers.eval local command = helpers.command local clear, funcs, meths = helpers.clear, helpers.funcs, helpers.meths +local ok = helpers.ok local os_name = helpers.os_name local function clear_serverlist() - for _, server in pairs(funcs.serverlist()) do - funcs.serverstop(server) - end + for _, server in pairs(funcs.serverlist()) do + funcs.serverstop(server) + end end describe('server', function() @@ -96,16 +96,12 @@ describe('server', function() funcs.serverstart('127.0.0.1:65536') -- invalid port eq({}, funcs.serverlist()) end) -end) -describe('serverlist()', function() - before_each(clear) - - it('returns the list of servers', function() + it('serverlist() returns the list of servers', function() -- There should already be at least one server. local n = eval('len(serverlist())') - -- Add a few + -- Add some servers. local servs = (os_name() == 'windows' and { [[\\.\pipe\Xtest-pipe0934]], [[\\.\pipe\Xtest-pipe4324]] } or { [[Xtest-pipe0934]], [[Xtest-pipe4324]] }) @@ -126,3 +122,25 @@ describe('serverlist()', function() eq(n, eval('len(serverlist())')) end) end) + +describe('startup --listen', function() + it('validates', function() + clear() + + local cmd = { unpack(helpers.nvim_argv) } + table.insert(cmd, '--listen') + eq('nvim: Argument missing after: "--listen"', + string.match(funcs.system(cmd), '.-n"')) + + cmd = { unpack(helpers.nvim_argv) } + table.insert(cmd, '--listen2') + eq('nvim: Garbage after option argument: "--listen2"', + string.match(funcs.system(cmd), '.-2"')) + end) + + it('sets v:servername, overrides $NVIM_LISTEN_ADDRESS', function() + clear({ env={ NVIM_LISTEN_ADDRESS='Xtest-env-pipe' }, + args={ '--listen', 'Xtest-listen-pipe' } }) + eq('Xtest-listen-pipe', meths.get_vvar('servername')) + end) +end) From 704ba4151e7f67999510ee0ac19fdabb595d530c Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Wed, 11 Apr 2018 00:01:43 +0200 Subject: [PATCH 6/7] server: init v:servername if $NVIM_LISTEN_ADDRESS is invalid Before this change, if $NVIM_LISTEN_ADDRESS was invalid, v:servername was left empty. --- src/nvim/msgpack_rpc/server.c | 33 ++++++++++++++-------------- test/functional/eval/server_spec.lua | 32 +++++++++++++++++---------- 2 files changed, 36 insertions(+), 29 deletions(-) diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c index abff5cfe4f..e5d80aea1d 100644 --- a/src/nvim/msgpack_rpc/server.c +++ b/src/nvim/msgpack_rpc/server.c @@ -32,28 +32,27 @@ static garray_T watchers = GA_EMPTY_INIT_VALUE; #endif /// Initializes the module -bool server_init(const char *listen_address) +bool server_init(const char *listen_addr) { ga_init(&watchers, sizeof(SocketWatcher *), 1); - bool must_free = false; - if (listen_address == NULL) { - // Deprecated: $NVIM_LISTEN_ADDRESS - listen_address = os_getenv(LISTEN_ADDRESS_ENV_VAR); - if (listen_address == NULL) { - must_free = true; - listen_address = server_address_new(); - if (listen_address == NULL) { + // $NVIM_LISTEN_ADDRESS + const char *env_addr = os_getenv(LISTEN_ADDRESS_ENV_VAR); + int rv = listen_addr == NULL ? 1 : server_start(listen_addr); + + if (0 != rv) { + rv = env_addr == NULL ? 1 : server_start(env_addr); + if (0 != rv) { + listen_addr = server_address_new(); + if (listen_addr == NULL) { return false; } + rv = server_start(listen_addr); + xfree((char *)listen_addr); } } - bool ok = (server_start(listen_address) == 0); - if (must_free) { - xfree((char *)listen_address); - } - return ok; + return rv == 0; } /// Teardown a single server @@ -122,8 +121,8 @@ bool server_owns_pipe_address(const char *path) /// @param endpoint Address of the server. Either a 'ip:[port]' string or an /// arbitrary identifier (trimmed to 256 bytes) for the Unix /// socket or named pipe. -/// @returns 0 on success, 1 on a regular error, and negative errno -/// on failure to bind or listen. +/// @returns 0: success, 1: validation error, 2: already listening, +/// -errno: failed to bind or listen. int server_start(const char *endpoint) { if (endpoint == NULL || endpoint[0] == '\0') { @@ -147,7 +146,7 @@ int server_start(const char *endpoint) uv_freeaddrinfo(watcher->uv.tcp.addrinfo); } socket_watcher_close(watcher, free_server); - return 1; + return 2; } } diff --git a/test/functional/eval/server_spec.lua b/test/functional/eval/server_spec.lua index a2644498f2..4e4aed864b 100644 --- a/test/functional/eval/server_spec.lua +++ b/test/functional/eval/server_spec.lua @@ -2,8 +2,9 @@ local helpers = require('test.functional.helpers')(after_each) local eq, neq, eval = helpers.eq, helpers.neq, helpers.eval local command = helpers.command local clear, funcs, meths = helpers.clear, helpers.funcs, helpers.meths +local iswin = helpers.iswin local ok = helpers.ok -local os_name = helpers.os_name +local matches = helpers.matches local function clear_serverlist() for _, server in pairs(funcs.serverlist()) do @@ -25,7 +26,15 @@ describe('server', function() eq('', eval('$NVIM_LISTEN_ADDRESS')) end) - it('serverstart() sets v:servername at startup or if all servers were stopped', + it('sets new v:servername if $NVIM_LISTEN_ADDRESS is invalid', function() + clear({env={NVIM_LISTEN_ADDRESS='.'}}) + eq('.', eval('$NVIM_LISTEN_ADDRESS')) + local servers = funcs.serverlist() + eq(1, #servers) + ok(string.len(servers[1]) > 4) -- Like /tmp/nvim…/… or \\.\pipe\… + end) + + it('sets v:servername at startup or if all servers were stopped', function() local initial_server = meths.get_vvar('servername') assert(initial_server ~= nil and initial_server:len() > 0, @@ -46,9 +55,8 @@ describe('server', function() eq('', meths.get_vvar('servername')) -- v:servername will take the next available server. - local servername = (os_name() == 'windows' - and [[\\.\pipe\Xtest-functional-server-pipe]] - or 'Xtest-functional-server-socket') + local servername = (iswin() and [[\\.\pipe\Xtest-functional-server-pipe]] + or 'Xtest-functional-server-socket') funcs.serverstart(servername) eq(servername, meths.get_vvar('servername')) end) @@ -102,7 +110,7 @@ describe('server', function() local n = eval('len(serverlist())') -- Add some servers. - local servs = (os_name() == 'windows' + local servs = (iswin() and { [[\\.\pipe\Xtest-pipe0934]], [[\\.\pipe\Xtest-pipe4324]] } or { [[Xtest-pipe0934]], [[Xtest-pipe4324]] }) for _, s in ipairs(servs) do @@ -129,18 +137,18 @@ describe('startup --listen', function() local cmd = { unpack(helpers.nvim_argv) } table.insert(cmd, '--listen') - eq('nvim: Argument missing after: "--listen"', - string.match(funcs.system(cmd), '.-n"')) + matches('nvim.*: Argument missing after: "%-%-listen"', funcs.system(cmd)) cmd = { unpack(helpers.nvim_argv) } table.insert(cmd, '--listen2') - eq('nvim: Garbage after option argument: "--listen2"', - string.match(funcs.system(cmd), '.-2"')) + matches('nvim.*: Garbage after option argument: "%-%-listen2"', funcs.system(cmd)) end) it('sets v:servername, overrides $NVIM_LISTEN_ADDRESS', function() + local addr = (iswin() and [[\\.\pipe\Xtest-listen-pipe]] + or 'Xtest-listen-pipe') clear({ env={ NVIM_LISTEN_ADDRESS='Xtest-env-pipe' }, - args={ '--listen', 'Xtest-listen-pipe' } }) - eq('Xtest-listen-pipe', meths.get_vvar('servername')) + args={ '--listen', addr } }) + eq(addr, meths.get_vvar('servername')) end) end) From 777d34ec376ee8706a80d4f1f44fb83397753116 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Wed, 11 Apr 2018 01:28:33 +0200 Subject: [PATCH 7/7] lint --- src/nvim/main.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/nvim/main.c b/src/nvim/main.c index 0d7187fb71..ce9feedd16 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -72,30 +72,30 @@ # include "nvim/os/pty_process_unix.h" #endif -/* Maximum number of commands from + or -c arguments. */ +// Maximum number of commands from + or -c arguments. #define MAX_ARG_CMDS 10 -/* values for "window_layout" */ -#define WIN_HOR 1 /* "-o" horizontally split windows */ -#define WIN_VER 2 /* "-O" vertically split windows */ -#define WIN_TABS 3 /* "-p" windows on tab pages */ +// values for "window_layout" +#define WIN_HOR 1 // "-o" horizontally split windows +#define WIN_VER 2 // "-O" vertically split windows +#define WIN_TABS 3 // "-p" windows on tab pages -/* Struct for various parameters passed between main() and other functions. */ +// Struct for various parameters passed between main() and other functions. typedef struct { int argc; char **argv; char *use_vimrc; // vimrc from -u argument - int n_commands; /* no. of commands from + or -c */ + int n_commands; // no. of commands from + or -c char *commands[MAX_ARG_CMDS]; // commands from + or -c arg - char_u cmds_tofree[MAX_ARG_CMDS]; /* commands that need free() */ - int n_pre_commands; /* no. of commands from --cmd */ + char_u cmds_tofree[MAX_ARG_CMDS]; // commands that need free() + int n_pre_commands; // no. of commands from --cmd char *pre_commands[MAX_ARG_CMDS]; // commands from --cmd argument - int edit_type; /* type of editing to do */ - char_u *tagname; /* tag from -t argument */ - char_u *use_ef; /* 'errorfile' from -q argument */ + int edit_type; // type of editing to do + char_u *tagname; // tag from -t argument + char_u *use_ef; // 'errorfile' from -q argument int want_full_screen; bool input_isatty; // stdin is a terminal @@ -103,13 +103,13 @@ typedef struct { bool err_isatty; // stderr is a terminal int no_swap_file; // "-n" argument used int use_debug_break_level; - int window_count; /* number of windows to use */ - int window_layout; /* 0, WIN_HOR, WIN_VER or WIN_TABS */ + int window_count; // number of windows to use + int window_layout; // 0, WIN_HOR, WIN_VER or WIN_TABS #if !defined(UNIX) - int literal; /* don't expand file names */ + int literal; // don't expand file names #endif - int diff_mode; /* start with 'diff' set */ + int diff_mode; // start with 'diff' set char *listen_addr; // --listen {address} } mparm_T; @@ -1945,7 +1945,7 @@ static void usage(void) mch_msg(_(" --api-info Write msgpack-encoded API metadata to stdout\n")); mch_msg(_(" --embed Use stdin/stdout as a msgpack-rpc channel\n")); mch_msg(_(" --headless Don't start a user interface\n")); - mch_msg(_(" --listen
Start RPC server on this socket or TCP address\n")); + mch_msg(_(" --listen
Start RPC server at this address\n")); #if !defined(UNIX) mch_msg(_(" --literal Don't expand wildcards\n")); #endif