aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/lua/vim/filetype.lua1
-rw-r--r--src/nvim/channel.c8
-rw-r--r--src/nvim/insexpand.c4
-rw-r--r--src/nvim/move.c4
-rw-r--r--src/nvim/normal.c7
-rw-r--r--src/nvim/os/stdpaths.c47
-rw-r--r--test/functional/options/defaults_spec.lua16
-rw-r--r--test/functional/ui/cmdline_spec.lua10
-rw-r--r--test/functional/ui/popupmenu_spec.lua2
-rw-r--r--test/functional/ui/searchhl_spec.lua2
-rw-r--r--test/old/testdir/test_filetype.vim1
-rw-r--r--test/old/testdir/test_ins_complete.vim22
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