| Commit message (Collapse) | Author | Age |
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Problem:
'isident' decides how env var names are parsed, which is more
"confusing" than "useful":
- Changing 'isident' (for 'define' or "\i") can break `$NAME` expansion.
- Its default byte ranges let multibyte names work on Windows (`$aあ`)
but not Unix (`$é`).
Solution:
Ignore 'isident' when parsing env var names.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Problem: Repeated default fields and field-by-field assertions obscure
the values that each functional test is meant to check.
Solution: Add eq_partial() to check selected record fields while
preserving list length and order. Use local helpers to fill fixed
expected defaults where tests need full equality. Keep explicit absence
checks and test-specific values at the call sites.
AI-assisted
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
'isident' is checked per byte (inherited from Vim), so a name can end
in the middle of a multibyte char: with "192-255", `$é` (C3 A9) looks
up "\xC3".
- Unix: expands an env var named "\xC3", plus a stray "\xA9".
- Windows: uv_os_getenv() rejects the name (invalid UTF-8), and
os_getenv() logs an error.
`$VAR` in expressions (get_env_len()) and cmdline completion have the
same scan.
Solution:
`vim_isIDp()`: a multibyte char is an identifier char only if it is valid
UTF-8 and 'isident' has all its bytes. Use it in expand_env_esc(),
get_env_len() and cmdline completion. Names whose bytes are all in
'isident' still work, e.g. `$aあ` with the Windows default.
Assert UV_EINVAL in os_getenv() and os_getenv_buf() (like
os_env_exists() and os_setenv() already do): Nvim no longer passes
invalid UTF-8.
|
| |
|
|
|
|
|
|
|
|
| |
Problem:
API contract was relaxed by 25439dad7e2ba21ff2f78759c68be888a217342c40581
to treat `opts` params as optional. However, when called from Vimscript,
omitting the `opts` arg `E119: Not enough arguments for function` error.
Solution:
Add a min/max argument range in the Vimscript generator if the function
has an `opts_idx` field.
|
| |
|
|
| |
Fix has_spec.lua for v9.1.0000
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
In the `enc=utf-8` only world, the 'isprint' option is quite obsolete.
The function is only consulted for decoded U+0080 to U+00FF chars
whose printability is defined by the unicode charset, just like
higher codepoints. Meanwhile, invalid `\x80` to `\xFF` bytes are always
unprintable.
Disentangle 'iskeyword', 'isfname' and 'isident' from each other by
giving them all separate bitsets. Now these can be updated individually.
These updaters can back out of errors gracefully, no need for extra
panic logic in option[str].c to restore partially updated chartabs.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem: Option validators and setters repeatedly pass error buffers and
their sizes separately. Some setters return messages in static storage.
Solution:
- Add CharBuf for borrowed writable storage, with its length including
space for a terminating NUL.
- Move option error buffers to the callers that report errors. Preserve
existing buffer sizes, truncation, and calls that do not need a
message.
- Consolidate option error formatting and the duplicated code that lists
valid option values.
- Return error messages directly from do_one_set_option().
- Remove unused arguments from get_option_newval() and
set_option_value_for().
- Handle legacy TTY assignments in the existing callers and remove the
redundant compatibility wrapper.
- Reuse CharBuf for Tree-sitter query errors.
- Pass CharBuf through the statusline and statuscolumn builders,
retaining the buffer sizes provided by their callers, including title
formatting.
AI-assisted
|
| | |
|
| |
|
|
|
|
|
|
|
|
| |
Problem:
`inputlist()` advertises "click with the mouse" purely because it
implements click selection, so under the default `'mouse'` of "nvi" it
offers a click that command-line mode never receives.
Solution:
Only offer the mouse when `'mouse'` covers command-line mode, the same
condition `:help inputlist()` already documents.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
Redudant code
Solution:
Add `path_fold_char()` to normalize path sep.
Refactor `pathcmp()` and `path_fnamencmp()` into `path_cmp`.
| feature | pathcmp | path_fnamencmp | path_cmp(now) |
| ------------------------ | -------------- | -------------- | ------------- |
| case folding | `mb_toupper()` | `utf_fold()` | `utf_fold()` |
| consults fileignorecase | ✅ | ✅ | `ic` param |
| `maxlen` | ✅ | ✅ | ✅ |
| `/` == `\` | ✅ | ✅ | ✅ |
| MSWIN drive letter | ❌ | ✅ | ✅ |
| sep affects sorting | ✅ | ❌ | ✅ |
| ignores a trailing slash | ✅ | ❌ | ✅ |
Refactor `path_fnamecmp` and `path_full_compare` into `path_equal`,
with flags controlling "no filesystem" comparison (i.e. `path_cmp`), env
variables expansion, absolute path resolution and filesystem access.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
Assigning to the local value of a global-local boolean option
('autoread', 'autocomplete', 'fsync') aborts:
Assertion failed: (curval.type == newval.type), function
ex_let_option, file vars.c, line 1408.
ex_let_one
ex_let_vars
ex_let
execute_cmd0
do_cmdline
call_user_func
...
eval_map_expr
vgetorpeek
vgetc
state_enter
main
A global-local option may have local value `kObjectTypeUnset`, but
`ex_let_option()` guards only `kObjectTypeNil`.
Solution:
When curval is Unset, resolve it to the inherited global value.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
Assigning a Boolean or special value (v:true/v:false/v:null/v:none) to a TTY
option aborts:
Assertion failed: (curval.type == newval.type), function ex_let_option, file vars.c, line 1408.
3 libsystem_c.dylib __assert_rtn + 284
4 nvim ex_let_one + 3308
5 nvim ex_let_vars + 112
6 nvim ex_let + 2356
7 nvim execute_cmd0 + 252
8 nvim do_cmdline + 9076
9 nvim call_user_func + 3320
10 nvim call_func + 2076
11 nvim get_func_tv + 696
12 nvim eval_func + 380
20 nvim eval_to_string_eap + 276
21 nvim eval_map_expr + 444
22 nvim vgetorpeek + 3172
23 nvim vgetc + 764
Solution:
Apply the string-type check to TTY options too, so a Boolean/special value
gives "E928: String required" instead of aborting. Valid string/number
assignments to `t_*` pseudo-options still silently no-op.
|
| |
|
|
|
| |
It's necessary to copy the global 'fileencoding' to the buffer-local
value before entering the buffer, otherwise 'fileencoding' is changed
when reading the file, which will mark the file as modified.
|
| |
|
|
|
|
|
|
|
|
|
| |
Problem:
The current check is intended to match DOS device paths starting with
`\\?` or `\\.` but will match any path starting with `?` or `.`,
including relative paths such as `.\`.
This is because the leading slashes are removed before the comparison.
Solution:
Changes the check to include the path's prefix, assuring the path has
the correct amount of separators for a DOS device path.
|
| |
|
|
| |
Co-authored-by: Barrett Ruth <br@barrettruth.com>
Co-authored-by: Nathan Zeng <nathan.j.zeng@gmail.com>
|
| |
|
|
|
|
|
|
|
|
|
| |
Problem:
Redundant code.
Solution:
Combine path_has_wildcard() and path_has_exp_wildcard(). They have similar logic.
Also, the latter operates on whatever wildcards remain after shell/env/backtick
expansion, so the two felt somewhat related.
Also drop some unnecessary MB_PTR_ADV calls.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
The magic globals `it`, `describe`, etc., are more trouble than they are
worth.
- Hooking into `after_each` requires `getfenv()` hacks.
- They confuse luals/emmylua, because the top-level `.luarc.json` isn't
merged with `test/.luarc.json` (apparently a luals limitation?)
- They totally defeat discoverability because the user just has to
"know" about the various magic symbols.
So they harm DX, which means they serve no purpose at all.
Solution:
- Expose the test API from `testutil`, so tests can call `t.it()`,
`t.describe()`, etc., in the conventional way.
- Drop `getfenv()` hacks.
- Drop the `setfenv()` injection in `load_chunk`.
- Drop `test/_meta.lua`.
|
| |
|
|
|
|
|
|
|
|
| |
- Remove old help tags: they add noise to cmdline completion.
Co-authored-by: acehinnnqru <acehinnnqru@gmail.com>
Co-authored-by: KangaZero <samuelyongw@gmail.com>
Co-authored-by: Simone Ragusa <hi@interrato.dev>
Co-authored-by: Chinmay Dalal <~chinmay/public-inbox@lists.sr.ht>
Co-authored-by: coyaSONG <66289470+coyaSONG@users.noreply.github.com>
Co-authored-by: Olivia Kinnear <git@superatomic.dev>
|
| |
|
|
|
|
|
|
| |
Problem:
Expanding an unknown ~user path falls back to the shell. In a fast event,
this re-enters the event loop and aborts Nvim.
Solution:
Leave unknown users unexpanded when the system account lookup fails.
|
| |
|
|
|
|
|
|
|
|
| |
Problem:
This functions are most likely never used in the wild.
- They are redundant with `nvim_get_context` + `nvim_load_context`.
- The "context" concept was never fully developed and hasn't gained
traction.
Solution:
Drop these vimscript aliases, they are just extra cruft.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
/src/nvim/ex_docmd.c: 5033 in ex_restart()
5027 // The address after --listen may be in use by the current server.
5028 if (i > 0 && strequal(arg, "--listen")) {
5029 const listitem_T *next_li = li->li_next;
5030 if (next_li != NULL) {
5031 const char *addr = tv_get_string(TV_LIST_ITEM_TV(next_li));
5032 if (strstr(addr, ":") || strstr(addr, "/") || strstr(addr, "\\")) {
>>> CID 649201: Resource leaks (RESOURCE_LEAK)
>>> Overwriting "listen_arg" in "listen_arg = xstrdup(addr)" leaks the storage that "listen_arg" points to.
5033 listen_arg = TO_SLASH_SAVE(addr);
5034 #ifdef MSWIN
5035 // On Windows, don't pass --listen to new server (named pipe can't be reused immediately).
5036 // Instead pass the address via RPC; new server rebinds after startup.
5037 li = next_li;
5038 continue;
*** CID 649200: Memory - illegal accesses (USE_AFTER_FREE)
/src/nvim/eval/fs.c: 228 in modify_fname()
222
223 // ":h" - head, remove "/file_name", can be repeated
224 // Don't remove the logical root, see `FileInfo`.
225 while (src[*usedlen] == ':' && src[*usedlen + 1] == 'h') {
226 valid |= VALID_HEAD;
227 *usedlen += 2;
>>> CID 649200: Memory - illegal accesses (USE_AFTER_FREE)
>>> Using freed pointer "s".
228 while (tail > s && after_pathsep(s, tail)) {
229 MB_PTR_BACK(*fnamep, tail);
230 }
231 *fnamelen = tail <= s ? (size_t)(s - *fnamep) : (size_t)(tail - *fnamep);
232 if (*fnamelen == 0) {
233 // Result is empty. Turn it into "." to make ":cd %:h" work.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
Continue separators normalization, and try to keep it at the
nvim <-> external boundary, e.g., `fn.xxx`, `api.xxx`, `:xxx`
Solution:
some key changes
- normalize `$HOME-windows`
- normalize entry points of changing directory
- `nvim_set_current_dir()`, `chdir()`
- normalize the named pipe
- `--listen` arg, `--server` arg, `:restart`
- `serverstart()`, `sockconnect()`, `serverstop()`
- make `expand()` respect 'shellslash' again
- clean up `did_set_shellslash`
- replace `forward_slash` with `TO_SLASH`
- remove obsolete `TMP_PATHSEPSTR`
- remove `slash_adjust` in `do_autocmd_dirchanged`?
- make `fnamemodify()` always return `/` (except when substituting
separators via `:s`, `:gs` ?)
Note:
- these funcs still apply `slash_adjust` on return, as before:
`:pwd`, `chdir()`, `exepath()`, `getcwd()`
- these funcs alwarys return `/`, unlike before the normalization PRs
- `getcompletion()`, `finddir()`, `findfile()`
Also
- clean up code, comments, formatting and tests
- move `TO_SLASH` from `f_chdir` to `changedir_func`
- move `TO_SLASH` from `f_bufadd` to `buflist_new`
Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
|
| |
|
|
| |
related: fb6aeaba2d3a
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
On Windows, `fnamemodify('//foo/C$', ':h')` incorrectly removes `C$`
as a regular file name and returns `//foo`. However, this is a valid
UNC path, `foo` is a server name and `C$` is a share name.
The correct result should be `//foo/C$`.
Solution:
Extend `os_fileinfo2` and `FileInfo` with `prefix_off`, `rest_off` to
identify path types and logical root boundaries. ':h' can use this info
to prevent traversing past the logical root.
Examples:
/foo => /
//foo => // (POSIX)
//foo/bar => //foo (POSIX)
//server/share/foo => //server/share/ (Windows)
C:/foo => C:/
//?/C:/foo => //?/C:/
Co-authored-by: Barrett Ruth <br@barrettruth.com>
|
| |
|
|
| |
Allow window navigation/creation even while cmdwin is alive! 😱
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
cmdwin (the `:q` cmdline buffer) has various limitations which require
special-casing all over the codebase.
Besides complicating the code, it also breaks async plugins if they try
to create buffers/windows after some work is done, if the user happens
to open cmdwin at the wrong the moment:
Lua callback: …/guh.nvim/lua/guh/util.lua:531:
E11: Invalid in command-line window; <CR> executes, CTRL-C quits
stack traceback:
[C]: in function 'nvim_buf_delete'
…/guh.nvim/lua/guh/util.lua:531: in function <…/guh.nvim/lua/guh/util.lua:526>
Solution:
Just say no to "inception". Reimplement cmdwin as a normal buffer+window.
All of the cmdwin contortions (in both core, and innocent plugins) exist
literally only to support "inception": recursive
cmdwin-in-cmdline-things, like `<c-r>=`, `/`, search-during-substitute,
`:input()`, etc. So we just won't support that (though I have
a potential plan for that later, which I call "modal parking lot").
The benefit is that plugins, and core, no longer have to care about
cmdwin.
BONUS:
- mouse-drag on vertical separators works (it only worked for
horizontal/statusline before)
- inccommand-in-cmdwin now works correctly, for free (thus don't need
#40077).
POTENTIAL FOLLOWUPS
- Drop `CHECK_CMDWIN` ("E11: Invalid in command-line window"), allow chaos.
- Unify `BUFLOCK_OK` / `LOCK_OK` ?
DESIGN:
- Eliminate lots of C globals, `EX_CMDWIN`, etc.
- `text_locked()` no longer reports true for cmdwin.
- cmdwin = a normal window with 'winfixbuf', 'bufhidden=wipe',
'buftype=nofile'. Invariants come from those options rather than
special cases throughout the codebase.
- `nv_record` for q:/q//q? calls Lua
`nlua_call_vimfn("vim._core.cmdwin", …)`. No `K_CMDWIN`
/ cmdline-reader detour.
- `cedit_key` (`c_CTRL-F`) schedules a deferred event that calls
`vim._core.cmdwin.open(type, content, pos)` and returns `Ctrl_C` so
the in-flight cmdline cancels. Reader state is not serialized; instead
the captured `(type, line, col)` is replayed via
`nvim_feedkeys(type..line.."<CR>", "nt", …)` after user confirms.
- On confirm/cancel: `<CR>` / `<C-C>` calls into Lua which closes the
window and re-feeds the cmdline.
BREAKING CHANGES:
- Expression-register cmdline (`<C-R>=` from insert-mode) no longer
supports cmdwin. Same applies to `input()` / `inputlist()` (already
covered by `text_locked`).
- Usage of cmdwin in macros/mappings will probably break (assuming they
ever worked).
|
| |
|
|
|
|
|
|
|
| |
Problem: Vim9: Getbufline(-1, 1, '$') gives an error.
Solution: Return an empty list. (closes vim/vim#7180)
https://github.com/vim/vim/commit/e6e70a10f118ecfa9df2425e8724bc009bd09929
Co-authored-by: Bram Moolenaar <Bram@vim.org>
|
| |
|
|
|
|
|
|
| |
Problem:
It's clumsy for scripts to handle a "restart", without custom mappings or
global vars.
Solution:
Introduce `v:startreason`
|
| |
|
|
|
|
|
|
|
|
| |
Problem:
Listing individual "skipped" notices for each non-actionable or
NVIM_TEST_INTEG test is noisy and makes the "skipped" list overwhelming
and less meaningful.
Solution:
- Mark non-actionable tests with "N/A".
- Report NVIM_TEST_INTEG tests as a separate 1-line summary.
|
| |
|
|
|
|
|
|
|
|
| |
Builds with -DNDEBUG do not contain the compilation string, so the test
will fail even if nvim is built with unibilium.
Similarly, zig builds only report "Compilation: TODO", so they also fail
the test even when build with unibilium
Detect both scenarios and skip the test, rather than failing it.
|
| |
|
|
|
| |
Problem: `fnamemodify(..., ':h')` mishandles POSIX leading slash runs longer than `//`.
Solution: Collapse those slash runs to `/` before computing the head.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
When `:!` writes shell output to a buffer, write_output() splits on `\r`, `\n`,
and `\r\n`, replacing the terminator byte with NUL. For a binary-mode buffer
this is wrong: `\r` should be preserved verbatim, not treated as a line
terminator. This wrong behavior causes a file like `\r\n` round-trips through
`:%!cat` to `\n`.
This was masked when 'shelltemp' was enabled, because output went through a temp
file and the regular file I/O path handled binary-mode correctly. Switching the
default to 'noshelltemp' exposed the bug, since output is now piped directly
into write_output().
Solution:
In `write_output()`, skip the `\r` and `\r\n` splits for a binary-mode buffer;
only split on `\n`.
|
| |
|
|
|
|
|
|
| |
Problem:
`gx` relies on `exepath` to get the fullpath of `cmd.exe`,
and that path must use `\`; otherwise, luv's spawn will fail.
Solution:
Revert `slash_adjust` in `exepath`, so that it still respects 'shellslash'
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
1. `vim_getenv` is followed by `TO_SLASH` when getting
path-related variables.
2. cmd exits when launched with forward slash.
Solution:
1. try calling `TO_SLASH` in `vim_getenv`.
2. pass fullpath via `lpApplicationName`, only include `cmd.exe`
in cmdline.
Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
|
| |
|
|
|
|
|
|
|
|
|
| |
Problem:
- write_blob, write_string dereference args which may be NULL.
- `writefile(v:_null_blob, …)` fails.
Solution:
- Fix the annotation.
- Handle null blob.
Co-authored-by: zeertzjq <zeertzjq@outlook.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
On Windows, path separators may become inconsistent for various reasons,
which makes normalization quite painful.
Solution:
Normalize paths to `/` at the entry boundaries and always use it
internally, converting back only in rare cases where `\` is really
needed (e.g. cmd.exe/bat scripts?).
This is the first commit in a series of incremental steps.
Note:
* some funcs won't respect shellslash. e.g. `expand/fnamemodify`
* some funcs still respect shellslash, but will be updated in a follow
PR. e.g. `ex_pwd/f_chdir/f_getcwd`
* uv's built-in funcs always return `\`. e.g. `uv.cwd/uv.exepath`
Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
|
| |
|
|
|
|
|
| |
Problem:
vim.fn.writefile() treats Lua strings as Vimscript strings instead of a "binary clean" string.
Solution:
Treat Lua-originated strings as blob data.
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
- Builtin "Vimscript" functions (f_xx) are mostly implemented in C.
Partly that's because there is some boilerplate required to call out
to Lua.
- Calls to `vim.fn.foo()` always marshall over the Lua <=> Vimscript
("typval") bridge, even if `fn.foo()` is implemented entirely in Lua:
```
Lua => typval => Object => Lua => Object => typval => Lua.
```
Solution:
Functions declared in eval.lua with `func_lua` are implemented in
entirely in Lua (`_core/vimfn.lua`).
- `gen_eval.lua` wires `func_lua` entries to `lua_wrapper`, which handles
the typval conversion for Vimscript callers (slow path).
- `nlua_call()` detects `func_lua` functions and calls the Lua
implementation directly. This eliminates all conversion overhead for
Lua callers (fast path).
- Validate at build-time that `func`, `func_float`, and `func_lua` are
mutually exclusive.
- Migrate `hostname()` as a toy example, to show the idea.
|
| |
|
|
|
|
|
| |
Problem:
On Windows, `:!echo тест` shows `????` because the console code page defaults to a legacy ANSI encoding (e.g. CP1252) instead of `UTF-8`
Solution:
Call `SetConsoleOutputCP(CP_UTF8)` and `SetConsoleCP(CP_UTF8)` in `do_os_system()` before spawning child processes, and restore the original values after. It covers both `:!` and `system()` since they both go through `do_os_system()`
|
| |
|
|
|
|
|
|
|
|
|
| |
Problem:
On windows, if a drive-relative path doesn't contain a slash,
`path_to_absolute` can't split out the relative component, causing
expansion to fails. e.g., `c:` `c:.` `c:..` `c:foo.md`
Solution:
For these cases, we can pass letter and colon to `path_full_dir_name`.
Notably, `..` is included as well.
if that relative path exists, it can be expanded correctly.
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
This is a better way to prevent parallel tests from interfering with
each other, as there are many ways files can be created and deleted in
tests, so enforcing different file names is hard.
Using $TMPDIR can also work in most cases, but 'backipskip' etc. have
special defaults for $TMPDIR.
Symlink runtime/, src/, test/ and README.md to Xtest_xdg dir to make
tests more convenient (and symlinking test/ is required for busted).
Also, use README.md instead of test/README.md in the Ex mode inccommand
test, as test/README.md no longer contains 'N' char.
|