diff options
-rw-r--r-- | runtime/lua/vim/filetype.lua | 1 | ||||
-rw-r--r-- | src/nvim/channel.c | 8 | ||||
-rw-r--r-- | src/nvim/insexpand.c | 4 | ||||
-rw-r--r-- | src/nvim/move.c | 4 | ||||
-rw-r--r-- | src/nvim/normal.c | 7 | ||||
-rw-r--r-- | src/nvim/os/stdpaths.c | 47 | ||||
-rw-r--r-- | test/functional/options/defaults_spec.lua | 16 | ||||
-rw-r--r-- | test/functional/ui/cmdline_spec.lua | 10 | ||||
-rw-r--r-- | test/functional/ui/popupmenu_spec.lua | 2 | ||||
-rw-r--r-- | test/functional/ui/searchhl_spec.lua | 2 | ||||
-rw-r--r-- | test/old/testdir/test_filetype.vim | 1 | ||||
-rw-r--r-- | test/old/testdir/test_ins_complete.vim | 22 |
12 files changed, 104 insertions, 20 deletions
diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index 190071bbc7..1198a9972f 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -1052,6 +1052,7 @@ local extension = { mts = 'typescript', cts = 'typescript', tsx = 'typescriptreact', + tsp = 'typespec', uc = 'uc', uit = 'uil', uil = 'uil', diff --git a/src/nvim/channel.c b/src/nvim/channel.c index 0222a134a7..b64edae2bf 100644 --- a/src/nvim/channel.c +++ b/src/nvim/channel.c @@ -544,8 +544,12 @@ uint64_t channel_from_stdio(bool rpc, CallbackReader on_output, const char **err } #else if (embedded_mode) { - stdin_dup_fd = dup(STDIN_FILENO); - stdout_dup_fd = dup(STDOUT_FILENO); + // In embedded mode redirect stdout and stdin to stderr, since they are used for the UI channel. + // NOTE: fnctl with F_DUPFD_CLOEXEC is used instead of dup to prevent child processes from + // inheriting the file descriptors, which make it impossible for UIs to detect when nvim exits + // while one or more of its child processes are still running. + stdin_dup_fd = fcntl(STDIN_FILENO, F_DUPFD_CLOEXEC, STDERR_FILENO + 1); + stdout_dup_fd = fcntl(STDOUT_FILENO, F_DUPFD_CLOEXEC, STDERR_FILENO + 1); dup2(STDERR_FILENO, STDOUT_FILENO); dup2(STDERR_FILENO, STDIN_FILENO); } diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c index fe5faf8c10..7feb4f6661 100644 --- a/src/nvim/insexpand.c +++ b/src/nvim/insexpand.c @@ -2435,7 +2435,8 @@ static void expand_by_function(int type, char *base) } textlock--; - curwin->w_cursor = pos; // restore the cursor position + curwin->w_cursor = pos; // restore the cursor position + check_cursor(curwin); // make sure cursor position is valid, just in case validate_cursor(curwin); if (!equalpos(curwin->w_cursor, pos)) { emsg(_(e_compldel)); @@ -4059,6 +4060,7 @@ static int get_userdefined_compl_info(colnr_T curs_col) State = save_State; curwin->w_cursor = pos; // restore the cursor position + check_cursor(curwin); // make sure cursor position is valid, just in case validate_cursor(curwin); if (!equalpos(curwin->w_cursor, pos)) { emsg(_(e_compldel)); diff --git a/src/nvim/move.c b/src/nvim/move.c index 52b65c0fef..e7416549f5 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -196,7 +196,7 @@ static void redraw_for_cursorcolumn(win_T *wp) int sms_marker_overlap(win_T *wp, int extra2) { // There is no marker overlap when in showbreak mode, thus no need to - // account for it. See grid_put_linebuf(). + // account for it. See wlv_put_linebuf(). if (*get_showbreak_value(wp) != NUL) { return 0; } @@ -621,7 +621,7 @@ int cursor_valid(win_T *wp) // w_topline must be valid, you may need to call update_topline() first! void validate_cursor(win_T *wp) { - check_cursor(wp); + check_cursor_lnum(wp); check_cursor_moved(wp); if ((wp->w_valid & (VALID_WCOL|VALID_WROW)) != (VALID_WCOL|VALID_WROW)) { curs_columns(wp, true); diff --git a/src/nvim/normal.c b/src/nvim/normal.c index c7eb5c5793..2eb247a47e 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -32,6 +32,7 @@ #include "nvim/ex_cmds.h" #include "nvim/ex_cmds2.h" #include "nvim/ex_docmd.h" +#include "nvim/ex_eval.h" #include "nvim/ex_getln.h" #include "nvim/fileio.h" #include "nvim/fold.h" @@ -1403,6 +1404,12 @@ static int normal_check(VimState *state) normal_check_stuff_buffer(s); normal_check_interrupt(s); + // At the toplevel there is no exception handling. Discard any that + // may be hanging around (e.g. from "interrupt" at the debug prompt). + if (did_throw && !ex_normal_busy) { + discard_current_exception(); + } + if (!exmode_active) { msg_scroll = false; } diff --git a/src/nvim/os/stdpaths.c b/src/nvim/os/stdpaths.c index ede17bc7c8..187a0e0674 100644 --- a/src/nvim/os/stdpaths.c +++ b/src/nvim/os/stdpaths.c @@ -2,13 +2,16 @@ #include <stdbool.h> #include <string.h> +#include "klib/kvec.h" #include "nvim/ascii_defs.h" #include "nvim/fileio.h" #include "nvim/globals.h" #include "nvim/memory.h" #include "nvim/os/os.h" +#include "nvim/os/os_defs.h" #include "nvim/os/stdpaths_defs.h" #include "nvim/path.h" +#include "nvim/strings.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/stdpaths.c.generated.h" @@ -93,6 +96,46 @@ bool appname_is_valid(void) return true; } +/// Remove duplicate directories in the given XDG directory. +/// @param[in] List of directories possibly with duplicates +/// @param[out] List of directories without duplicates +static char *xdg_remove_duplicate(char *ret, const char *sep) +{ + kvec_t(char *) data = KV_INITIAL_VALUE; + char *saveptr; + + char *token = os_strtok(ret, sep, &saveptr); + while (token != NULL) { + // Check if the directory is not already in the list + bool is_duplicate = false; + for (size_t i = 0; i < data.size; i++) { + if (path_fnamecmp(kv_A(data, i), token) == 0) { + is_duplicate = true; + break; + } + } + // If it's not a duplicate, add it to the list + if (!is_duplicate) { + kv_push(data, token); + } + token = os_strtok(NULL, sep, &saveptr); + } + + StringBuilder result = KV_INITIAL_VALUE; + + for (size_t i = 0; i < data.size; i++) { + if (i == 0) { + kv_printf(result, "%s", kv_A(data, i)); + } else { + kv_printf(result, "%s%s", sep, kv_A(data, i)); + } + } + + kv_destroy(data); + xfree(ret); + return result.items; +} + /// Return XDG variable value /// /// @param[in] idx XDG variable to use. @@ -131,6 +174,10 @@ char *stdpaths_get_xdg_var(const XDGVarType idx) ret = xmemdupz(ret, len >= 2 ? len - 1 : 0); // Trim trailing slash. } + if ((idx == kXDGDataDirs || idx == kXDGConfigDirs) && ret != NULL) { + ret = xdg_remove_duplicate(ret, ENV_SEPSTR); + } + return ret; } diff --git a/test/functional/options/defaults_spec.lua b/test/functional/options/defaults_spec.lua index 2d3d827619..5e98453565 100644 --- a/test/functional/options/defaults_spec.lua +++ b/test/functional/options/defaults_spec.lua @@ -378,7 +378,7 @@ describe('XDG defaults', function() .. root_path .. ('/b'):rep(2048) .. '/nvim' - .. (',' .. root_path .. '/c/nvim'):rep(512) + .. (',' .. root_path .. '/c/nvim') .. ',' .. root_path .. ('/X'):rep(4096) @@ -393,12 +393,12 @@ describe('XDG defaults', function() .. root_path .. ('/B'):rep(2048) .. '/nvim/site' - .. (',' .. root_path .. '/C/nvim/site'):rep(512) + .. (',' .. root_path .. '/C/nvim/site') .. ',' .. vimruntime .. ',' .. libdir - .. (',' .. root_path .. '/C/nvim/site/after'):rep(512) + .. (',' .. root_path .. '/C/nvim/site/after') .. ',' .. root_path .. ('/B'):rep(2048) @@ -413,7 +413,7 @@ describe('XDG defaults', function() .. '/' .. data_dir .. '/site/after' - .. (',' .. root_path .. '/c/nvim/after'):rep(512) + .. (',' .. root_path .. '/c/nvim/after') .. ',' .. root_path .. ('/b'):rep(2048) @@ -449,7 +449,7 @@ describe('XDG defaults', function() .. root_path .. ('/b'):rep(2048) .. '/nvim' - .. (',' .. root_path .. '/c/nvim'):rep(512) + .. (',' .. root_path .. '/c/nvim') .. ',' .. root_path .. ('/X'):rep(4096) @@ -464,12 +464,12 @@ describe('XDG defaults', function() .. root_path .. ('/B'):rep(2048) .. '/nvim/site' - .. (',' .. root_path .. '/C/nvim/site'):rep(512) + .. (',' .. root_path .. '/C/nvim/site') .. ',' .. vimruntime .. ',' .. libdir - .. (',' .. root_path .. '/C/nvim/site/after'):rep(512) + .. (',' .. root_path .. '/C/nvim/site/after') .. ',' .. root_path .. ('/B'):rep(2048) @@ -484,7 +484,7 @@ describe('XDG defaults', function() .. '/' .. data_dir .. '/site/after' - .. (',' .. root_path .. '/c/nvim/after'):rep(512) + .. (',' .. root_path .. '/c/nvim/after') .. ',' .. root_path .. ('/b'):rep(2048) diff --git a/test/functional/ui/cmdline_spec.lua b/test/functional/ui/cmdline_spec.lua index d38cb395e2..0b2c0af66b 100644 --- a/test/functional/ui/cmdline_spec.lua +++ b/test/functional/ui/cmdline_spec.lua @@ -365,7 +365,7 @@ local function test_cmdline(linegrid) grid = [[ | {2:[No Name] }| - {1::}mak^e | + {1::}make^ | {3:[Command Line] }| | ]], @@ -377,7 +377,7 @@ local function test_cmdline(linegrid) grid = [[ | {2:[No Name] }| - {1::}mak^e | + {1::}make^ | {3:[Command Line] }| | ]], @@ -396,7 +396,7 @@ local function test_cmdline(linegrid) grid = [[ | {2:[No Name] }| - {1::}mak^e | + {1::}make^ | {3:[Command Line] }| | ]], @@ -416,7 +416,7 @@ local function test_cmdline(linegrid) grid = [[ | {2:[No Name] }| - {1::}mak^e | + {1::}make^ | {3:[Command Line] }| | ]], @@ -1586,7 +1586,7 @@ describe('cmdheight=0', function() topline = 0, botline = 2, curline = 0, - curcol = 0, + curcol = 1, linecount = 1, sum_scroll_delta = 0, }, diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua index 10d933f00a..c1cb2b62be 100644 --- a/test/functional/ui/popupmenu_spec.lua +++ b/test/functional/ui/popupmenu_spec.lua @@ -2946,7 +2946,7 @@ describe('builtin popupmenu', function() | {3:[No Name] }| {1::}sign define | - {1::}sign defin^e | + {1::}sign define^ | {1:~ }|*4 {4:[Command Line] }| :sign define | diff --git a/test/functional/ui/searchhl_spec.lua b/test/functional/ui/searchhl_spec.lua index a702de5dc7..cfc0f2f6de 100644 --- a/test/functional/ui/searchhl_spec.lua +++ b/test/functional/ui/searchhl_spec.lua @@ -53,7 +53,7 @@ describe('search highlighting', function() topline = 0, botline = 3, curline = 0, - curcol = 8, + curcol = 9, linecount = 2, sum_scroll_delta = 0, }, diff --git a/test/old/testdir/test_filetype.vim b/test/old/testdir/test_filetype.vim index a51cf4eef0..1039f4d5df 100644 --- a/test/old/testdir/test_filetype.vim +++ b/test/old/testdir/test_filetype.vim @@ -689,6 +689,7 @@ func s:GetFilenameChecks() abort \ 'typescript': ['file.mts', 'file.cts'], \ 'typescript.glimmer': ['file.gts'], \ 'typescriptreact': ['file.tsx'], + \ 'typespec': ['file.tsp'], \ 'ungrammar': ['file.ungram'], \ 'uc': ['file.uc'], \ 'udevconf': ['/etc/udev/udev.conf', 'any/etc/udev/udev.conf'], diff --git a/test/old/testdir/test_ins_complete.vim b/test/old/testdir/test_ins_complete.vim index ac04187a7b..3f67a06999 100644 --- a/test/old/testdir/test_ins_complete.vim +++ b/test/old/testdir/test_ins_complete.vim @@ -2490,4 +2490,26 @@ func Test_complete_changed_complete_info() call StopVimInTerminal(buf) endfunc +func Test_completefunc_first_call_complete_add() + new + + func Complete(findstart, base) abort + if a:findstart + let col = col('.') + call complete_add('#') + return col - 1 + else + return [] + endif + endfunc + + set completeopt=longest completefunc=Complete + " This used to cause heap-buffer-overflow + call assert_fails('call feedkeys("ifoo#\<C-X>\<C-U>", "xt")', 'E840:') + + delfunc Complete + set completeopt& completefunc& + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab nofoldenable |