diff options
-rw-r--r-- | runtime/lua/vim/_editor.lua | 72 | ||||
-rw-r--r-- | src/nvim/api/vim.c | 2 | ||||
-rw-r--r-- | src/nvim/main.c | 79 | ||||
-rw-r--r-- | src/nvim/main.h | 2 |
4 files changed, 154 insertions, 1 deletions
diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 3136e36043..5f3d66e108 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -636,6 +636,78 @@ function vim.pretty_print(...) return ... end +local function __rpcrequest(...) + return vim.api.nvim_call_function("rpcrequest", {...}) +end + +function vim._cs_remote(rcid, args) + + local f_silent = false + local f_wait = false + local f_tab = false + local should_exit = true + local command = 'edit ' + + local subcmd = string.sub(args[1],10) + + if subcmd == '' then + -- no flags to set + elseif subcmd == 'tab' then + f_tab = true + elseif subcmd == 'silent' then + f_silent = true + elseif subcmd == 'wait' then + f_wait = true + elseif subcmd == 'wait-silent' then + f_wait = true + f_silent = true + elseif subcmd == 'tab-wait' then + f_tab = true + f_wait = true + elseif subcmd == 'tab-silent' then + f_tab = true + f_silent = true + elseif subcmd == 'tab-wait-silent' then + f_tab = true + f_wait = true + f_silent = true + elseif subcmd == 'send' then + __rpcrequest(rcid, 'nvim_input', args[2]) + return { should_exit = should_exit, tabbed = f_tab, files = 0 } + -- should we show warning if --server doesn't exist in --send and --expr? + elseif subcmd == 'expr' then + local res = __rpcrequest(rcid, 'vim_eval', args[2]) + print(res) + return { should_exit = should_exit, tabbed = f_tab, files = 0 } + else + print('--remote subcommand not found') + end + + table.remove(args,1) + + if not f_silent and rcid == 0 then + print('Remote server does not exist.') + end + + if f_silent and rcid == 0 then + print('Remote server does not exist. starting new server') + should_exit = false + end + + if f_tab then command = 'tabedit ' end + + if rcid ~= 0 then + for _, key in ipairs(args) do + __rpcrequest(rcid, 'nvim_command', command .. key) + end + end + + return { + should_exit = should_exit, + tabbed = f_tab, + files = table.getn(args) + } +end require('vim._meta') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index ebf4f65c91..b82a7553cb 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1997,7 +1997,7 @@ Array nvim_get_proc_children(Integer pid, Error *err) DLOG("fallback to vim._os_proc_children()"); Array a = ARRAY_DICT_INIT; ADD(a, INTEGER_OBJ(pid)); - String s = cstr_to_string("return vim._os_proc_children(select(1, ...))"); + String s = cstr_to_string("return vim._os_proc_children(select(...))"); Object o = nlua_exec(s, a, err); api_free_string(s); api_free_array(a); diff --git a/src/nvim/main.c b/src/nvim/main.c index a575aba50a..3a1ca2988a 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -268,6 +268,10 @@ int main(int argc, char **argv) } server_init(params.listen_addr); + if (params.remote) { + handle_remote_client(¶ms, params.remote, + params.server_addr, argc, argv); + } if (GARGCOUNT > 0) { fname = get_fname(¶ms, cwd); @@ -803,6 +807,67 @@ static void init_locale(void) } #endif +/// Handle remote subcommands +static void handle_remote_client(mparm_T *params, int remote_args, + char *server_addr, int argc, char **argv) +{ + Object rvobj = OBJECT_INIT; + rvobj.data.dictionary = (Dictionary)ARRAY_DICT_INIT; + rvobj.type = kObjectTypeDictionary; + CallbackReader on_data = CALLBACK_READER_INIT; + const char *error = NULL; + uint64_t rc_id = server_addr == NULL ? 0 : channel_connect(false, + server_addr, true, on_data, 50, &error); + + Boolean should_exit = true; + Boolean tabbed; + int files; + + int t_argc = remote_args; + Array args = ARRAY_DICT_INIT; + String arg_s; + for (; t_argc < argc; t_argc++) { + arg_s = cstr_to_string(argv[t_argc]); + ADD(args, STRING_OBJ(arg_s)); + } + + Error err = ERROR_INIT; + Array a = ARRAY_DICT_INIT; + ADD(a, INTEGER_OBJ((int)rc_id)); + ADD(a, ARRAY_OBJ(args)); + String s = cstr_to_string("return vim._cs_remote(...)"); + Object o = executor_exec_lua_api(s, a, &err); + api_free_string(s); + api_free_array(a); + + if (o.type == kObjectTypeDictionary) { + rvobj.data.dictionary = o.data.dictionary; + } else if (!ERROR_SET(&err)) { + api_set_error(&err, kErrorTypeException, + "Function returned unexpected value"); + } + + for (size_t i = 0; i < rvobj.data.dictionary.size ; i++) { + if (strcmp(rvobj.data.dictionary.items[i].key.data, "tabbed") == 0) { + // should we check items[i].value.type here? + tabbed = rvobj.data.dictionary.items[i].value.data.boolean; + } else if (strcmp(rvobj.data.dictionary.items[i].key.data, "should_exit") == 0) { + should_exit = rvobj.data.dictionary.items[i].value.data.boolean; + } else if (strcmp(rvobj.data.dictionary.items[i].key.data, "files") == 0) { + files = (int)rvobj.data.dictionary.items[i].value.data.integer; + } + } + + if (should_exit) { + mch_exit(0); + } else { + if (tabbed) { + params->window_count = files; + params->window_layout = WIN_TABS; + } + } +} + /// Decides whether text (as opposed to commands) will be read from stdin. /// @see EDIT_STDIN static bool edit_stdin(bool explicit, mparm_T *parmp) @@ -868,6 +933,8 @@ static void command_line_scan(mparm_T *parmp) // "--version" give version message // "--noplugin[s]" skip plugins // "--cmd <cmd>" execute cmd before vimrc + // "--remote" execute commands remotey on a server + // "--server" name of vim server to send remote commands to if (STRICMP(argv[0] + argv_idx, "help") == 0) { usage(); os_exit(0); @@ -906,6 +973,11 @@ static void command_line_scan(mparm_T *parmp) argv_idx += 6; } else if (STRNICMP(argv[0] + argv_idx, "literal", 7) == 0) { // Do nothing: file args are always literal. #7679 + } else if (STRNICMP(argv[0] + argv_idx, "remote", 6) == 0) { + parmp->remote = parmp->argc - argc; + } else if (STRNICMP(argv[0] + argv_idx, "server", 6) == 0) { + want_argument = true; + argv_idx += 6; } else if (STRNICMP(argv[0] + argv_idx, "noplugin", 8) == 0) { p_lpl = false; } else if (STRNICMP(argv[0] + argv_idx, "cmd", 3) == 0) { @@ -1137,6 +1209,9 @@ static void command_line_scan(mparm_T *parmp) } else if (strequal(argv[-1], "--listen")) { // "--listen {address}" parmp->listen_addr = argv[0]; + } else if (strequal(argv[-1], "--server")) { + // "--server {address}" + parmp->server_addr = argv[0]; } // "--startuptime <file>" already handled break; @@ -1291,6 +1366,8 @@ static void init_params(mparm_T *paramp, int argc, char **argv) paramp->use_debug_break_level = -1; paramp->window_count = -1; paramp->listen_addr = NULL; + paramp->server_addr = NULL; + paramp->remote = 0; } /// Initialize global startuptime file if "--startuptime" passed as an argument. @@ -2041,6 +2118,8 @@ static void usage(void) mch_msg(_(" --headless Don't start a user interface\n")); mch_msg(_(" --listen <address> Serve RPC API from this address\n")); mch_msg(_(" --noplugin Don't load plugins\n")); + mch_msg(_(" --remote[-subcommand] Execute commands remotely on a server\n")); + mch_msg(_(" --server <address> Specify RPC server to send commands to\n")); mch_msg(_(" --startuptime <file> Write startup timing messages to <file>\n")); mch_msg(_("\nSee \":help startup-options\" for all options.\n")); } diff --git a/src/nvim/main.h b/src/nvim/main.h index f73af5c288..e55bef6e33 100644 --- a/src/nvim/main.h +++ b/src/nvim/main.h @@ -39,6 +39,8 @@ typedef struct { int diff_mode; // start with 'diff' set char *listen_addr; // --listen {address} + int remote; // --remote-[subcmd] {file1} {file2} + char *server_addr; // --server {address} } mparm_T; #ifdef INCLUDE_GENERATED_DECLARATIONS |