aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/lua/vim/lsp.lua39
-rw-r--r--runtime/lua/vim/lsp/util.lua7
-rw-r--r--src/nvim/eval/funcs.c2
-rw-r--r--src/nvim/ex_docmd.c1
-rw-r--r--src/nvim/testdir/test_cmdline.vim15
5 files changed, 56 insertions, 8 deletions
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
index 9a008ac965..56ac1cbc66 100644
--- a/runtime/lua/vim/lsp.lua
+++ b/runtime/lua/vim/lsp.lua
@@ -644,7 +644,9 @@ end
--- - debounce_text_changes (number, default nil): Debounce didChange
--- notifications to the server by the given number in milliseconds. No debounce
--- occurs if nil
----
+--- - exit_timeout (number, default 500): Milliseconds to wait for server to
+-- exit cleanly after sending the 'shutdown' request before sending kill -15.
+-- If set to false, nvim exits immediately after sending the 'shutdown' request to the server.
---@returns Client id. |vim.lsp.get_client_by_id()| Note: client may not be
--- fully initialized. Use `on_init` to do any actions once
--- the client has been initialized.
@@ -1226,9 +1228,38 @@ function lsp._vim_exit_handler()
client.stop()
end
- if not vim.wait(500, function() return tbl_isempty(active_clients) end, 50) then
- for _, client in pairs(active_clients) do
- client.stop(true)
+ local timeouts = {}
+ local max_timeout = 0
+ local send_kill = false
+
+ for client_id, client in pairs(active_clients) do
+ local timeout = if_nil(client.config.flags.exit_timeout, 500)
+ if timeout then
+ send_kill = true
+ timeouts[client_id] = timeout
+ max_timeout = math.max(timeout, max_timeout)
+ else
+ active_clients[client_id] = nil
+ end
+ end
+
+ local poll_time = 50
+
+ local function check_clients_closed()
+ for client_id, _ in pairs(active_clients) do
+ timeouts[client_id] = timeouts[client_id] - poll_time
+ if timeouts[client_id] < 0 then
+ active_clients[client_id] = nil
+ end
+ end
+ return tbl_isempty(active_clients)
+ end
+
+ if send_kill then
+ if not vim.wait(max_timeout, check_clients_closed, poll_time) then
+ for _, client in pairs(active_clients) do
+ client.stop(true)
+ end
end
end
end
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index 952926b67e..7a0ac458f3 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -226,9 +226,10 @@ function M.get_progress_messages()
table.remove(client.messages, item.idx)
end
- for _, item in ipairs(progress_remove) do
- client.messages.progress[item.token] = nil
- end
+ end
+
+ for _, item in ipairs(progress_remove) do
+ item.client.messages.progress[item.token] = nil
end
return new_messages
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 946bde060d..1c78e25639 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -3359,7 +3359,7 @@ static void f_getcompletion(typval_T *argvars, typval_T *rettv, FunPtr fptr)
expand_T xpc;
bool filtered = false;
int options = WILD_SILENT | WILD_USE_NL | WILD_ADD_SLASH
- | WILD_NO_BEEP;
+ | WILD_NO_BEEP | WILD_HOME_REPLACE;
if (argvars[1].v_type != VAR_STRING) {
EMSG2(_(e_invarg2), "type must be a string");
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 4524026e3f..68dd4a22ff 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -2915,6 +2915,7 @@ const char *set_one_cmd_context(expand_T *xp, const char *buff)
ExpandInit(xp);
xp->xp_pattern = (char_u *)buff;
+ xp->xp_line = (char_u *)buff;
xp->xp_context = EXPAND_COMMANDS; // Default until we get past command
ea.argt = 0;
diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim
index ffca415282..98340d0ac6 100644
--- a/src/nvim/testdir/test_cmdline.vim
+++ b/src/nvim/testdir/test_cmdline.vim
@@ -309,6 +309,11 @@ func Test_getcompletion()
let l = getcompletion('NoMatch', 'dir')
call assert_equal([], l)
+ if glob('~/*') !=# ''
+ let l = getcompletion('~/', 'dir')
+ call assert_true(l[0][0] ==# '~')
+ endif
+
let l = getcompletion('exe', 'expression')
call assert_true(index(l, 'executable(') >= 0)
let l = getcompletion('kill', 'expression')
@@ -422,6 +427,16 @@ func Test_getcompletion()
let l = getcompletion('call paint', 'cmdline')
call assert_equal([], l)
+ func T(a, c, p)
+ return "oneA\noneB\noneC"
+ endfunc
+ command -nargs=1 -complete=custom,T MyCmd
+ let l = getcompletion('MyCmd ', 'cmdline')
+ call assert_equal(['oneA', 'oneB', 'oneC'], l)
+
+ delcommand MyCmd
+ delfunc T
+
" For others test if the name is recognized.
let names = ['buffer', 'environment', 'file_in_path', 'mapping', 'tag', 'tag_listfiles', 'user']
if has('cmdline_hist')