aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTING.md2
-rw-r--r--runtime/autoload/health/nvim.vim2
-rw-r--r--runtime/doc/api.txt17
-rw-r--r--runtime/doc/lua.txt5
-rw-r--r--runtime/lua/vim/_editor.lua1
-rw-r--r--runtime/lua/vim/filetype.lua100
-rw-r--r--runtime/lua/vim/filetype/detect.lua573
-rw-r--r--runtime/lua/vim/lsp/health.lua3
-rw-r--r--scripts/lintcommit.lua8
-rw-r--r--src/nvim/api/vimscript.c12
-rw-r--r--src/nvim/change.c4
-rw-r--r--src/nvim/cursor.c18
-rw-r--r--src/nvim/edit.c9
-rw-r--r--src/nvim/event/loop.c2
-rw-r--r--src/nvim/ex_docmd.c15
-rw-r--r--src/nvim/ex_getln.c11
-rw-r--r--src/nvim/globals.h3
-rw-r--r--src/nvim/grid.c2
-rw-r--r--src/nvim/indent_c.c2
-rw-r--r--src/nvim/strings.c8
-rw-r--r--src/nvim/terminal.c17
-rw-r--r--src/nvim/testdir/test_cindent.vim7
-rw-r--r--src/nvim/testdir/test_cmdline.vim12
-rw-r--r--src/nvim/testdir/test_visual.vim12
-rw-r--r--test/functional/api/buffer_updates_spec.lua4
-rw-r--r--test/functional/core/startup_spec.lua8
-rw-r--r--test/functional/ex_cmds/mksession_spec.lua9
-rw-r--r--test/functional/terminal/cursor_spec.lua57
-rw-r--r--test/functional/terminal/highlight_spec.lua1
-rw-r--r--test/functional/terminal/scrollback_spec.lua5
-rw-r--r--test/functional/ui/messages_spec.lua1
-rw-r--r--test/functional/ui/output_spec.lua1
-rw-r--r--test/unit/fixtures/rbuffer.c2
-rw-r--r--third-party/CMakeLists.txt4
34 files changed, 748 insertions, 189 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 078377dcc2..e26d0d63c5 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -92,7 +92,7 @@ the VCS/git logs more valuable. The general structure of a commit message is:
```
- Prefix the commit subject with one of these [_types_](https://github.com/commitizen/conventional-commit-types/blob/master/index.json):
- - `build`, `ci`, `docs`, `feat`, `fix`, `perf`, `refactor`, `revert`, `test`, `vim-patch`, `chore`
+ - `build`, `ci`, `docs`, `feat`, `fix`, `perf`, `refactor`, `revert`, `test`, `vim-patch`, `dist`
- You can **ignore this for "fixup" commits** or any commits you expect to be squashed.
- Append optional scope to _type_ such as `(lsp)`, `(treesitter)`, `(float)`, …
- _Description_ shouldn't start with a capital letter or end in a period.
diff --git a/runtime/autoload/health/nvim.vim b/runtime/autoload/health/nvim.vim
index f3732e012f..9b387095ee 100644
--- a/runtime/autoload/health/nvim.vim
+++ b/runtime/autoload/health/nvim.vim
@@ -45,7 +45,7 @@ function! s:check_config() abort
let shadafile = empty(&shada) ? &shada : substitute(matchstr(
\ split(&shada, ',')[-1], '^n.\+'), '^n', '', '')
let shadafile = empty(&shadafile) ? empty(shadafile) ?
- \ stdpath('data').'/shada/main.shada' : expand(shadafile)
+ \ stdpath('state').'/shada/main.shada' : expand(shadafile)
\ : &shadafile ==# 'NONE' ? '' : &shadafile
if !empty(shadafile) && empty(glob(shadafile))
" Since this may be the first time neovim has been run, we will try to
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index 820eaad99a..86ec05417c 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -1728,8 +1728,7 @@ Vimscript Functions *api-vimscript*
nvim_call_dict_function({dict}, {fn}, {args})
Calls a VimL |Dictionary-function| with the given arguments.
- On execution error: fails with VimL error, does not update
- v:errmsg.
+ On execution error: fails with VimL error, updates v:errmsg.
Parameters: ~
{dict} Dictionary, or String evaluating to a VimL |self|
@@ -1743,8 +1742,7 @@ nvim_call_dict_function({dict}, {fn}, {args})
nvim_call_function({fn}, {args}) *nvim_call_function()*
Calls a VimL function with the given arguments.
- On execution error: fails with VimL error, does not update
- v:errmsg.
+ On execution error: fails with VimL error, updates v:errmsg.
Parameters: ~
{fn} Function to call
@@ -1763,6 +1761,8 @@ nvim_cmd({*cmd}, {*opts}) *nvim_cmd()*
argument, expanding filenames in a command that otherwise
doesn't expand filenames, etc.
+ On execution error: fails with VimL error, updates v:errmsg.
+
Parameters: ~
{cmd} Command to execute. Must be a Dictionary that can
contain the same values as the return value of
@@ -1784,8 +1784,7 @@ nvim_cmd({*cmd}, {*opts}) *nvim_cmd()*
nvim_command({command}) *nvim_command()*
Executes an Ex command.
- On execution error: fails with VimL error, does not update
- v:errmsg.
+ On execution error: fails with VimL error, updates v:errmsg.
Prefer using |nvim_cmd()| or |nvim_exec()| over this. To
evaluate multiple lines of Vim script or an Ex command
@@ -1801,8 +1800,7 @@ nvim_eval({expr}) *nvim_eval()*
Evaluates a VimL |expression|. Dictionaries and Lists are
recursively expanded.
- On execution error: fails with VimL error, does not update
- v:errmsg.
+ On execution error: fails with VimL error, updates v:errmsg.
Parameters: ~
{expr} VimL expression string
@@ -1817,8 +1815,7 @@ nvim_exec({src}, {output}) *nvim_exec()*
Unlike |nvim_command()| this function supports heredocs,
script-scope (s:), etc.
- On execution error: fails with VimL error, does not update
- v:errmsg.
+ On execution error: fails with VimL error, updates v:errmsg.
Parameters: ~
{src} Vimscript code
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index 0b6b8d05ed..b551552c03 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -690,8 +690,9 @@ matching within a single line.
vim.regex({re}) *vim.regex()*
Parse the Vim regex {re} and return a regex object. Regexes are
- "magic" and case-insensitive by default, regardless of 'magic' and
- 'ignorecase'. They can be controlled with flags, see |/magic|.
+ "magic" and case-sensitive by default, regardless of 'magic' and
+ 'ignorecase'. They can be controlled with flags, see |/magic| and
+ |/ignorecase|.
Methods on the regex object:
diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua
index dc25d68f61..e6ab48f30d 100644
--- a/runtime/lua/vim/_editor.lua
+++ b/runtime/lua/vim/_editor.lua
@@ -406,7 +406,6 @@ function vim.defer_fn(fn, timeout)
timeout,
0,
vim.schedule_wrap(function()
- timer:stop()
timer:close()
fn()
diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua
index fed0231ae9..8321e0b11e 100644
--- a/runtime/lua/vim/filetype.lua
+++ b/runtime/lua/vim/filetype.lua
@@ -810,11 +810,11 @@ local extension = {
R = function(path, bufnr)
require('vim.filetype.detect').r(bufnr)
end,
- asm = function()
- vim.fn['dist#ft#FTasm']()
+ asm = function(path, bufnr)
+ require('vim.filetype.detect').asm(bufnr)
end,
- bas = function()
- vim.fn['dist#ft#FTbas']()
+ bas = function(path, bufnr)
+ require('vim.filetype.detect').bas(bufnr)
end,
bi = function()
vim.fn['dist#ft#FTbas']()
@@ -828,11 +828,11 @@ local extension = {
btm = function(path, bufnr)
return require('vim.filetype.detect').btm(bufnr)
end,
- c = function()
- vim.fn['dist#ft#FTlpc']()
+ c = function(path, bufnr)
+ return require('vim.filetype.detect').lpc(bufnr)
end,
- ch = function()
- vim.fn['dist#ft#FTchange']()
+ ch = function(path, bufnr)
+ return require('vim.filetype.detect').change(bufnr)
end,
com = function()
vim.fn['dist#ft#BindzoneCheck']('dcl')
@@ -843,8 +843,8 @@ local extension = {
csh = function()
vim.fn['dist#ft#CSH']()
end,
- d = function()
- vim.fn['dist#ft#DtraceCheck']()
+ d = function(path, bufnr)
+ return require('vim.filetype.detect').dtrace(bufnr)
end,
db = function()
vim.fn['dist#ft#BindzoneCheck']('')
@@ -862,30 +862,30 @@ local extension = {
vim.fn['dist#ft#SetFileTypeSH']('bash')
end,
ent = function(path, bufnr)
- return require('vim.filetype.detect').ent(bufnr)
+ require('vim.filetype.detect').ent(bufnr)
end,
env = function()
vim.fn['dist#ft#SetFileTypeSH'](vim.fn.getline(1))
end,
eu = function(path, bufnr)
- return require('vim.filetype.detect').euphoria(bufnr)
+ require('vim.filetype.detect').euphoria(bufnr)
end,
ew = function(path, bufnr)
- return require('vim.filetype.detect').euphoria(bufnr)
+ require('vim.filetype.detect').euphoria(bufnr)
end,
ex = function(path, bufnr)
- return require('vim.filetype.detect').ex(bufnr)
+ require('vim.filetype.detect').ex(bufnr)
end,
exu = function(path, bufnr)
- return require('vim.filetype.detect').euphoria(bufnr)
+ require('vim.filetype.detect').euphoria(bufnr)
end,
exw = function(path, bufnr)
- return require('vim.filetype.detect').euphoria(bufnr)
+ require('vim.filetype.detect').euphoria(bufnr)
end,
frm = function(path, bufnr)
require('vim.filetype.detect').frm(bufnr)
end,
- fs = function()
+ fs = function(path, bufnr)
vim.fn['dist#ft#FTfs']()
end,
h = function(path, bufnr)
@@ -897,8 +897,8 @@ local extension = {
html = function()
vim.fn['dist#ft#FThtml']()
end,
- i = function()
- vim.fn['dist#ft#FTprogress_asm']()
+ i = function(path, bufnr)
+ require('vim.filetype.detect').progress_asm(bufnr)
end,
idl = function(path, bufnr)
require('vim.filetype.detect').idl(bufnr)
@@ -912,26 +912,26 @@ local extension = {
ksh = function()
vim.fn['dist#ft#SetFileTypeSH']('ksh')
end,
- lst = function()
- vim.fn['dist#ft#FTasm']()
+ lst = function(path, bufnr)
+ require('vim.filetype.detect').asm(bufnr)
end,
- m = function()
- vim.fn['dist#ft#FTm']()
+ m = function(path, bufnr)
+ require('vim.filetype.detect').m(bufnr)
end,
- mac = function()
- vim.fn['dist#ft#FTasm']()
+ mac = function(path, bufnr)
+ require('vim.filetype.detect').asm(bufnr)
end,
mc = function(path, bufnr)
require('vim.filetype.detect').mc(bufnr)
end,
- mm = function()
- vim.fn['dist#ft#FTmm']()
+ mm = function(path, bufnr)
+ require('vim.filetype.detect').mm(bufnr)
end,
mms = function(path, bufnr)
require('vim.filetype.detect').mms(bufnr)
end,
- p = function()
- vim.fn['dist#ft#FTprogress_pascal']()
+ p = function(path, bufnr)
+ require('vim.filetype.detect').progress_pascal(bufnr)
end,
patch = function(path, bufnr)
local firstline = getline(bufnr, 1)
@@ -959,8 +959,8 @@ local extension = {
rdf = function(path, bufnr)
require('vim.filetype.detect').redif(bufnr)
end,
- rules = function()
- vim.fn['dist#ft#FTRules']()
+ rules = function(path, bufnr)
+ require('vim.filetype.detect').rules(path, bufnr)
end,
sc = function(path, bufnr)
require('vim.filetype.detect').sc(bufnr)
@@ -1559,13 +1559,13 @@ local pattern = {
['%.zlog.*'] = starsetf('zsh'),
['%.zsh.*'] = starsetf('zsh'),
['.*%.[1-9]'] = function(path, bufnr)
- return require('vim.filetype.detect').nroff(bufnr)
+ require('vim.filetype.detect').nroff(bufnr)
end,
- ['.*%.[aA]'] = function()
- vim.fn['dist#ft#FTasm']()
+ ['.*%.[aA]'] = function(path, bufnr)
+ require('vim.filetype.detect').asm(bufnr)
end,
- ['.*%.[sS]'] = function()
- vim.fn['dist#ft#FTasm']()
+ ['.*%.[sS]'] = function(path, bufnr)
+ require('vim.filetype.detect').asm(bufnr)
end,
['.*%.properties_.._.._.*'] = starsetf('jproperties'),
['.*%.vhdl_[0-9].*'] = starsetf('vhdl'),
@@ -1575,8 +1575,8 @@ local pattern = {
['.*/Xresources/.*'] = starsetf('xdefaults'),
['.*/app%-defaults/.*'] = starsetf('xdefaults'),
['.*/bind/db%..*'] = starsetf('bindzone'),
- ['.*/debian/patches/.*'] = function()
- vim.fn['dist#ft#Dep3patch']()
+ ['.*/debian/patches/.*'] = function(path, bufnr)
+ require('vim.filetype.detect').dep3patch(path, bufnr)
end,
['.*/etc/Muttrc%.d/.*'] = starsetf('muttrc'),
['.*/etc/apache2/.*%.conf.*'] = starsetf('apache'),
@@ -1680,24 +1680,24 @@ local pattern = {
return 'git'
end
end,
- ['.*%.[Cc][Ff][Gg]'] = function()
- vim.fn['dist#ft#FTcfg']()
+ ['.*%.[Cc][Ff][Gg]'] = function(path, bufnr)
+ require('vim.filetype.detect').cfg(bufnr)
end,
- ['.*%.[Dd][Aa][Tt]'] = function()
- vim.fn['dist#ft#FTdat']()
+ ['.*%.[Dd][Aa][Tt]'] = function(path, bufnr)
+ require('vim.filetype.detect').dat(bufnr)
end,
- ['.*%.[Mm][Oo][Dd]'] = function()
- vim.fn['dist#ft#FTmod']()
+ ['.*%.[Mm][Oo][Dd]'] = function(path, bufnr)
+ require('vim.filetype.detect').mod(path, bufnr)
end,
- ['.*%.[Ss][Rr][Cc]'] = function()
- vim.fn['dist#ft#FTsrc']()
+ ['.*%.[Ss][Rr][Cc]'] = function(path, bufnr)
+ require('vim.filetype.detect').src(bufnr)
end,
['.*%.[Ss][Uu][Bb]'] = 'krl',
- ['.*%.[Pp][Rr][Gg]'] = function()
- vim.fn['dist#ft#FTprg']()
+ ['.*%.[Pp][Rr][Gg]'] = function(path, bufnr)
+ require('vim.filetype.detect').prg(bufnr)
end,
- ['.*%.[Ss][Yy][Ss]'] = function()
- vim.fn['dist#ft#FTsys']()
+ ['.*%.[Ss][Yy][Ss]'] = function(path, bufnr)
+ require('vim.filetype.detect').sys(bufnr)
end,
-- Neovim only
['.*/queries/.*%.scm'] = 'query', -- tree-sitter queries
diff --git a/runtime/lua/vim/filetype/detect.lua b/runtime/lua/vim/filetype/detect.lua
index 4c363e7403..da59625353 100644
--- a/runtime/lua/vim/filetype/detect.lua
+++ b/runtime/lua/vim/filetype/detect.lua
@@ -1,15 +1,28 @@
+-- Contains filetype detection functions converted to Lua from Vim's autoload/runtime/dist/ft.vim file.
+
+-- Here are a few guidelines to follow when porting a new function:
+-- * Sort the function alphabetically and omit 'ft' or 'check' from the new function name.
+-- * Use ':find' instead of ':match' / ':sub' if possible.
+-- * When '=~' is used to match a pattern, there are two possibilities:
+-- - If the pattern only contains lowercase characters, treat the comparison as case-insensitive.
+-- - Otherwise, treat it as case-sensitive.
+-- (Basically, we apply 'smartcase': if upper case characters are used in the original pattern, then
+-- it's likely that case does matter).
+-- * When '\k', '\<' or '\>' is used in a pattern, use the 'matchregex' function.
+-- Note that vim.regex is case-sensitive by default, so add the '\c' flag if only lowercase letters
+-- are present in the pattern:
+-- Example:
+-- `if line =~ '^\s*unwind_protect\>'` => `if matchregex(line, [[\c^\s*unwind_protect\>]])`
+
local M = {}
---@private
-local function getlines(bufnr, start_lnum, end_lnum, opts)
+local function getlines(bufnr, start_lnum, end_lnum)
if not end_lnum then
-- Return a single line as a string
return vim.api.nvim_buf_get_lines(bufnr, start_lnum - 1, start_lnum, false)[1]
end
-
- local lines = vim.api.nvim_buf_get_lines(bufnr, start_lnum - 1, end_lnum, false)
- opts = opts or {}
- return opts.concat and (table.concat(lines) or '') or lines
+ return vim.api.nvim_buf_get_lines(bufnr, start_lnum - 1, end_lnum, false)
end
---@private
@@ -22,16 +35,103 @@ local function findany(s, patterns)
return false
end
+---@private
+local function nextnonblank(bufnr, start_lnum)
+ for _, line in ipairs(getlines(bufnr, start_lnum, -1)) do
+ if not line:find('^%s*$') then
+ return line
+ end
+ end
+ return nil
+end
+
+---@private
+local matchregex = (function()
+ local cache = {}
+ return function(line, pattern)
+ if line == nil then
+ return nil
+ end
+ if not cache[pattern] then
+ cache[pattern] = vim.regex(pattern)
+ end
+ return cache[pattern]:match_str(line)
+ end
+end)()
+
-- luacheck: push no unused args
-- luacheck: push ignore 122
-function M.asm(path, bufnr) end
+-- This function checks for the kind of assembly that is wanted by the user, or
+-- can be detected from the first five lines of the file.
+function M.asm(bufnr)
+ -- Make sure b:asmsyntax exists
+ if not vim.b[bufnr].asmsyntax then
+ vim.b[bufnr].asmsyntax = ''
+ end
-function M.asm_syntax(path, bufnr) end
+ if vim.b[bufnr].asmsyntax == '' then
+ M.asm_syntax(bufnr)
+ end
-function M.bas(path, bufnr) end
+ -- If b:asmsyntax still isn't set, default to asmsyntax or GNU
+ if vim.b[bufnr].asmsyntax == '' then
+ if vim.g.asmsyntax and vim.g.asmsyntax ~= 0 then
+ vim.b[bufnr].asmsyntax = vim.g.asmsyntax
+ else
+ vim.b[bufnr].asmsyntax = 'asm'
+ end
+ end
+ vim.bo[bufnr].filetype = vim.fn.fnameescape(vim.b[bufnr].asmsyntax)
+end
+
+-- Checks the first 5 lines for a asmsyntax=foo override.
+-- Only whitespace characters can be present immediately before or after this statement.
+function M.asm_syntax(bufnr)
+ local lines = table.concat(getlines(bufnr, 1, 5), ' '):lower()
+ local match = lines:match('%sasmsyntax=([a-zA-Z0-9]+)%s')
+ if match then
+ vim.b['asmsyntax'] = match
+ elseif findany(lines, { '%.title', '%.ident', '%.macro', '%.subtitle', '%.library' }) then
+ vim.b['asmsyntax'] = 'vmasm'
+ end
+end
-function M.bindzone(path, bufnr) end
+local visual_basic_content = { 'vb_name', 'begin vb%.form', 'begin vb%.mdiform', 'begin vb%.usercontrol' }
+
+-- See frm() for Visual Basic form file detection
+function M.bas(bufnr)
+ if vim.g.filetype_bas then
+ vim.bo[bufnr].filetype = vim.g.filetype_bas
+ return
+ end
+
+ -- Most frequent FreeBASIC-specific keywords in distro files
+ local fb_keywords =
+ [[\c^\s*\%(extern\|var\|enum\|private\|scope\|union\|byref\|operator\|constructor\|delete\|namespace\|public\|property\|with\|destructor\|using\)\>\%(\s*[:=(]\)\@!]]
+ local fb_preproc =
+ [[\c^\s*\%(#\a\+\|option\s\+\%(byval\|dynamic\|escape\|\%(no\)\=gosub\|nokeyword\|private\|static\)\>\)]]
+
+ local fb_comment = "^%s*/'"
+ -- OPTION EXPLICIT, without the leading underscore, is common to many dialects
+ local qb64_preproc = [[\c^\s*\%($\a\+\|option\s\+\%(_explicit\|_\=explicitarray\)\>\)]]
+
+ for _, line in ipairs(getlines(bufnr, 1, 100)) do
+ if line:find(fb_comment) or matchregex(line, fb_preproc) or matchregex(line, fb_keywords) then
+ vim.bo[bufnr].filetype = 'freebasic'
+ return
+ elseif matchregex(line, qb64_preproc) then
+ vim.bo[bufnr].filetype = 'qb64'
+ return
+ elseif findany(line:lower(), visual_basic_content) then
+ vim.bo[bufnr].filetype = 'vb'
+ return
+ end
+ end
+ vim.bo[bufnr].filetype = 'basic'
+end
+
+function M.bindzone(bufnr, default_ft) end
function M.btm(bufnr)
if vim.g.dosbatch_syntax_for_btm and vim.g.dosbatch_syntax_for_btm ~= 0 then
@@ -47,14 +147,11 @@ local function is_rapid(bufnr, extension)
local line = getlines(bufnr, 1):lower()
return findany(line, { 'eio:cfg', 'mmc:cfg', 'moc:cfg', 'proc:cfg', 'sio:cfg', 'sys:cfg' })
end
- local first = '^%s*module%s+%S+%s*'
- -- Called from mod, prg or sys functions
- for _, line in ipairs(getlines(bufnr, 1, -1)) do
- if not line:find('^%s*$') then
- return findany(line:lower(), { '^%s*%%%%%%', first .. '(', first .. '$' })
- end
+ local line = nextnonblank(bufnr, 1)
+ if line then
+ -- Called from mod, prg or sys functions
+ return matchregex(line:lower(), [[\c\v^\s*%(\%{3}|module\s+\k+\s*%(\(|$))]])
end
- -- Only found blank lines
return false
end
@@ -68,17 +165,110 @@ function M.cfg(bufnr)
end
end
-function M.change(path, bufnr) end
+-- This function checks if one of the first ten lines start with a '@'. In
+-- that case it is probably a change file.
+-- If the first line starts with # or ! it's probably a ch file.
+-- If a line has "main", "include", "//" or "/*" it's probably ch.
+-- Otherwise CHILL is assumed.
+function M.change(bufnr)
+ local first_line = getlines(bufnr, 1)
+ if findany(first_line, { '^#', '^!' }) then
+ vim.bo[bufnr].filetype = 'ch'
+ return
+ end
+ for _, line in ipairs(getlines(bufnr, 1, 10)) do
+ if line:find('^@') then
+ vim.bo[bufnr].filetype = 'change'
+ return
+ end
+ if line:find('MODULE') then
+ vim.bo[bufnr].filetype = 'chill'
+ return
+ elseif findany(line:lower(), { 'main%s*%(', '#%s*include', '//' }) then
+ vim.bo[bufnr].filetype = 'ch'
+ return
+ end
+ end
+ vim.bo[bufnr].filetype = 'chill'
+end
function M.csh(path, bufnr) end
-function M.dat(path, bufnr) end
+-- Determine if a *.dat file is Kuka Robot Language
+-- TODO: this one fails for some reason, so I omitted it. #18219 should be merged first.
+function M.dat(bufnr)
+ -- if vim.g.filetype_dat then
+ -- vim.bo[bufnr].filetype = vim.g.filetype_dat
+ -- return
+ -- end
+ -- local line = nextnonblank(bufnr, 1):lower()
+ -- if findany(line, { "^%s*&%w+", "^%s*defdat" }) then
+ -- vim.bo[bufnr].filetype = "krl"
+ -- end
+end
-function M.dep3patch(path, bufnr) end
+-- This function is called for all files under */debian/patches/*, make sure not
+-- to non-dep3patch files, such as README and other text files.
+function M.dep3patch(path, bufnr)
+ local file_name = vim.fn.fnamemodify(path, ':t')
+ if file_name == 'series' then
+ return
+ end
-function M.dtrace(path, bufnr) end
+ for _, line in ipairs(getlines(bufnr, 1, 100)) do
+ if
+ findany(line, {
+ '^Description:',
+ '^Subject:',
+ '^Origin:',
+ '^Bug:',
+ '^Forwarded:',
+ '^Author:',
+ '^From:',
+ '^Reviewed%-by:',
+ '^Acked%-by:',
+ '^Last%-Updated:',
+ '^Applied%-Upstream:',
+ })
+ then
+ vim.bo[bufnr].filetype = 'dep3patch'
+ return
+ elseif line:find('^%-%-%-') then
+ -- End of headers found. stop processing
+ return
+ end
+ end
+end
-function M.e(path, bufnr) end
+function M.dtrace(bufnr)
+ local did_filetype = vim.fn.did_filetype()
+ if did_filetype and did_filetype ~= 0 then
+ -- Filetype was already detected
+ return
+ end
+ for _, line in ipairs(getlines(bufnr, 1, 100)) do
+ if matchregex(line, [[\c^module\>\|^import\>]]) then
+ -- D files often start with a module and/or import statement.
+ vim.bo[bufnr].filetype = 'd'
+ return
+ elseif findany(line, { '^#!%S+dtrace', '#pragma%s+D%s+option', ':%S-:%S-:' }) then
+ vim.bo[bufnr].filetype = 'dtrace'
+ return
+ end
+ end
+ vim.bo[bufnr].filetype = 'd'
+end
+
+function M.e(path, bufnr)
+ if vim.g.filetype_euphoria then
+ vim.bo[bufnr].filetype = vim.g.filetype_euphoria
+ return
+ end
+ -- TODO: WIP
+ -- for _, line in ipairs(getlines(bufnr, 1, 100)) do
+ -- if line:find("^$")
+ -- end
+end
-- This function checks for valid cl syntax in the first five lines.
-- Look for either an opening comment, '#', or a block start, '{'.
@@ -110,8 +300,7 @@ function M.ex(bufnr)
vim.bo[bufnr].filetype = vim.g.filetype_euphoria
else
for _, line in ipairs(getlines(bufnr, 1, 100)) do
- -- TODO: in the Vim regex, \> is used to match the end of the word, can this be omitted?
- if findany(line, { '^%-%-', '^ifdef', '^include' }) then
+ if matchregex(line, [[\c^--\|^ifdef\>\|^include\>]]) then
vim.bo[bufnr].filetype = 'euphoria3'
return
end
@@ -138,22 +327,34 @@ end
function M.frm(bufnr)
if vim.g.filetype_frm then
vim.bo[bufnr].filetype = vim.g.filetype_frm
+ return
+ end
+ local lines = table.concat(getlines(bufnr, 1, 5)):lower()
+ if findany(lines, visual_basic_content) then
+ vim.bo[bufnr].filetype = 'vb'
else
- -- Always ignore case
- local lines = getlines(bufnr, 1, 5, { concat = true }):lower()
- if findany(lines, { 'vb_name', 'begin vb%.form', 'begin vb%.mdiform' }) then
- vim.bo[bufnr].filetype = 'vb'
- else
- vim.bo[bufnr].filetype = 'form'
- end
+ vim.bo[bufnr].filetype = 'form'
end
end
-function M.fs(path, bufnr) end
+-- Distinguish between Forth and F#.
+function M.fs(bufnr)
+ -- TODO: WIP
+ -- if vim.g.filetype_fs then
+ -- vim.bo[bufnr].filetype = vim.g.filetype_fs
+ -- return
+ -- end
+ -- local line = nextnonblank(bufnr, 1)
+ -- if findany(line, { '^%s*.?%( ', '^%s*\\G? ', '^\\$', '^%s*: %S' }) then
+ -- vim.bo[bufnr].filetype = 'forth'
+ -- else
+ -- vim.bo[bufnr].filetype = 'fsharp'
+ -- end
+end
function M.header(bufnr)
for _, line in ipairs(getlines(bufnr, 1, 200)) do
- if findany(line, { '^@interface', '^@end', '^@class' }) then
+ if findany(line:lower(), { '^@interface', '^@end', '^@class' }) then
if vim.g.c_syntax_for_h then
vim.bo[bufnr].filetype = 'objc'
else
@@ -171,11 +372,22 @@ function M.header(bufnr)
end
end
+function M.html(bufnr)
+ for _, line in ipairs(getlines(bufnr, 1, 10)) do
+ if matchregex(line, [[\<DTD\s\+XHTML\s]]) then
+ vim.bo[bufnr].filetype = 'xhtml'
+ return
+ elseif matchregex(line, [[\c{%\s*\(extends\|block\|load\)\>\|{#\s\+]]) then
+ vim.bo[bufnr].filetype = 'htmldjango'
+ return
+ end
+ end
+ vim.bo[bufnr].filetype = 'html'
+end
+
function M.idl(bufnr)
for _, line in ipairs(getlines(bufnr, 1, 50)) do
- -- Always ignore case
- line = line:lower()
- if findany(line, { '^%s*import%s+"unknwn"%.idl', '^%s*import%s+"objidl"%.idl' }) then
+ if findany(line:lower(), { '^%s*import%s+"unknwn"%.idl', '^%s*import%s+"objidl"%.idl' }) then
vim.bo[bufnr].filetype = 'msidl'
return
end
@@ -198,11 +410,83 @@ function M.inp(bufnr)
end
end
-function M.lpc(path, bufnr) end
+function M.lpc(bufnr)
+ if vim.g.lpc_syntax_for_c then
+ for _, line in ipairs(getlines(bufnr, 1, 12)) do
+ if
+ findany(line, {
+ '^//',
+ '^inherit',
+ '^private',
+ '^protected',
+ '^nosave',
+ '^string',
+ '^object',
+ '^mapping',
+ '^mixed',
+ })
+ then
+ vim.bo[bufnr].filetype = 'lpc'
+ return
+ end
+ end
+ end
+ vim.bo[bufnr].filetype = 'c'
+end
-function M.lprolog(path, bufnr) end
+function M.m(bufnr)
+ if vim.g.filetype_m then
+ vim.bo[bufnr].filetype = vim.g.filetype_m
+ return
+ end
-function M.m(path, bufnr) end
+ -- Excluding end(for|function|if|switch|while) common to Murphi
+ local octave_block_terminators =
+ [[\<end\%(_try_catch\|classdef\|enumeration\|events\|methods\|parfor\|properties\)\>]]
+ local objc_preprocessor = [[\c^\s*#\s*\%(import\|include\|define\|if\|ifn\=def\|undef\|line\|error\|pragma\)\>]]
+
+ -- Whether we've seen a multiline comment leader
+ local saw_comment = false
+ for _, line in ipairs(getlines(bufnr, 1, 100)) do
+ if line:find('^%s*/%*') then
+ -- /* ... */ is a comment in Objective C and Murphi, so we can't conclude
+ -- it's either of them yet, but track this as a hint in case we don't see
+ -- anything more definitive.
+ saw_comment = true
+ end
+ if line:find('^%s*//') or matchregex(line, [[\c^\s*@import\>]]) or matchregex(line, objc_preprocessor) then
+ vim.bo[bufnr].filetype = 'objc'
+ return
+ end
+ if
+ findany(line, { '^%s*#', '^%s*%%!' })
+ or matchregex(line, [[\c^\s*unwind_protect\>]])
+ or matchregex(line, [[\c\%(^\|;\)\s*]] .. octave_block_terminators)
+ then
+ vim.bo[bufnr].filetype = 'octave'
+ return
+ elseif line:find('^%s*%%') then
+ vim.bo[bufnr].filetype = 'matlab'
+ return
+ elseif line:find('^%s*%(%*') then
+ vim.bo[bufnr].filetype = 'mma'
+ return
+ elseif matchregex(line, [[\c^\s*\(\(type\|var\)\>\|--\)]]) then
+ vim.bo[bufnr].filetype = 'murphi'
+ return
+ end
+ end
+
+ if saw_comment then
+ -- We didn't see anything definitive, but this looks like either Objective C
+ -- or Murphi based on the comment leader. Assume the former as it is more
+ -- common.
+ vim.bo[bufnr].filetype = 'objc'
+ else
+ -- Default is Matlab
+ vim.bo[bufnr].filetype = 'matlab'
+ end
+end
-- Rely on the file to start with a comment.
-- MS message text files use ';', Sendmail files use '#' or 'dnl'
@@ -221,7 +505,15 @@ function M.mc(bufnr)
vim.bo[bufnr].filetype = 'm4'
end
-function M.mm(path, bufnr) end
+function M.mm(bufnr)
+ for _, line in ipairs(getlines(bufnr, 1, 20)) do
+ if matchregex(line, [[\c^\s*\(#\s*\(include\|import\)\>\|@import\>\|/\*\)]]) then
+ vim.bo[bufnr].filetype = 'objcpp'
+ return
+ end
+ end
+ vim.bo[bufnr].filetype = 'nroff'
+end
function M.mms(bufnr)
for _, line in ipairs(getlines(bufnr, 1, 20)) do
@@ -236,35 +528,129 @@ function M.mms(bufnr)
vim.bo[bufnr].filetype = 'mmix'
end
-function M.mod(path, bufnr) end
+-- Returns true if file content looks like LambdaProlog
+local function is_lprolog(bufnr)
+ -- Skip apparent comments and blank lines, what looks like
+ -- LambdaProlog comment may be RAPID header
+ for _, line in ipairs(getlines(bufnr, 1, -1)) do
+ -- The second pattern matches a LambdaProlog comment
+ if not findany(line, { '^%s*$', '^%s*%%' }) then
+ -- The pattern must not catch a go.mod file
+ return matchregex(line, [[\c\<module\s\+\w\+\s*\.\s*\(%\|$\)]]) ~= nil
+ end
+ end
+end
+
+-- Determine if *.mod is ABB RAPID, LambdaProlog, Modula-2, Modsim III or go.mod
+function M.mod(path, bufnr)
+ if vim.g.filetype_mod then
+ vim.bo[bufnr].filetype = vim.g.filetype_mod
+ elseif is_lprolog(bufnr) then
+ vim.bo[bufnr].filetype = 'lprolog'
+ elseif matchregex(nextnonblank(bufnr, 1), [[\%(\<MODULE\s\+\w\+\s*;\|^\s*(\*\)]]) then
+ vim.bo[bufnr].filetype = 'modula2'
+ elseif is_rapid(bufnr) then
+ vim.bo[bufnr].filetype = 'rapid'
+ elseif matchregex(path, [[\c\<go\.mod$]]) then
+ vim.bo[bufnr].filetype = 'gomod'
+ else
+ -- Nothing recognized, assume modsim3
+ vim.bo[bufnr].filetype = 'modsim3'
+ end
+end
-- This function checks if one of the first five lines start with a dot. In
--- that case it is probably an nroff file: 'filetype' is set and 1 is returned.
+-- that case it is probably an nroff file: 'filetype' is set and true is returned.
function M.nroff(bufnr)
for _, line in ipairs(getlines(bufnr, 1, 5)) do
if line:find('^%.') then
vim.bo[bufnr].filetype = 'nroff'
- return 1
+ return true
end
end
- return 0
+ return false
end
-function M.perl(path, bufnr) end
+-- If the file has an extension of 't' and is in a directory 't' or 'xt' then
+-- it is almost certainly a Perl test file.
+-- If the first line starts with '#' and contains 'perl' it's probably a Perl file.
+-- (Slow test) If a file contains a 'use' statement then it is almost certainly a Perl file.
+function M.perl(path, bufnr)
+ local dirname = vim.fn.expand(path, '%:p:h:t')
+ if vim.fn.expand(dirname, '%:e') == 't' and (dirname == 't' or dirname == 'xt') then
+ vim.bo[bufnr].filetype = 'perl'
+ return true
+ end
+ local first_line = getlines(bufnr, 1)
+ if first_line:find('^#') and first_line:lower():find('perl') then
+ vim.bo[bufnr].filetype = 'perl'
+ return true
+ end
+ for _, line in ipairs(getlines(bufnr, 1, 30)) do
+ if matchregex(line, [[\c^use\s\s*\k]]) then
+ vim.bo[bufnr].filetype = 'perl'
+ return true
+ end
+ end
+ return false
+end
function M.pl(path, bufnr) end
-function M.pp(path, bufnr) end
+local pascal_comments = { '^%s*{', '^%s*%(*', '^%s*//' }
+local pascal_keywords = [[\c^\s*\%(program\|unit\|library\|uses\|begin\|procedure\|function\|const\|type\|var\)\>]]
+
+function M.pp(bufnr)
+ -- TODO: WIP
+
+ -- if vim.g.filetype_pp then
+ -- vim.bo[bufnr].filetype = vim.g.filetype_pp
+ -- return
+ -- end
+ -- local first_line = nextnonblank(bufnr, 1):lower()
+ -- if findany(first_line, { pascal_comments, pascal_keywords }) then
+ -- vim.bo[bufnr].filetype = "pascal"
+ -- else
+ -- vim.bo[bufnr].filetype = "puppet"
+ -- end
+end
+
+function M.prg(bufnr)
+ if vim.g.filetype_prg then
+ vim.bo[bufnr].filetype = vim.g.filetype_prg
+ elseif is_rapid(bufnr) then
+ vim.bo[bufnr].filetype = 'rapid'
+ else
+ -- Nothing recognized, assume Clipper
+ vim.bo[bufnr].filetype = 'clipper'
+ end
+end
-function M.prg(path, bufnr) end
+-- This function checks for an assembly comment in the first ten lines.
+-- If not found, assume Progress.
+function M.progress_asm(bufnr)
+ if vim.g.filetype_i then
+ vim.bo[bufnr].filetype = vim.g.filetype_i
+ return
+ end
-function M.progress_asm(path, bufnr) end
+ for _, line in ipairs(getlines(bufnr, 1, 10)) do
+ if line:find('^%s*;') or line:find('^/%*') then
+ return M.asm(bufnr)
+ elseif not line:find('^%s*$') or line:find('^/%*') then
+ -- Not an empty line: doesn't look like valid assembly code
+ -- or it looks like a Progress /* comment.
+ break
+ end
+ end
+ vim.bo[bufnr].filetype = 'progress'
+end
function M.progress_cweb(bufnr)
if vim.g.filetype_w then
vim.bo[bufnr].filetype = vim.g.filetype_w
else
- if getlines(bufnr, 1):find('^&ANALYZE') or getlines(bufnr, 3):find('^&GLOBAL%-DEFINE') then
+ if getlines(bufnr, 1):lower():find('^&analyze') or getlines(bufnr, 3):lower():find('^&global%-define') then
vim.bo[bufnr].filetype = 'progress'
else
vim.bo[bufnr].filetype = 'cweb'
@@ -272,15 +658,33 @@ function M.progress_cweb(bufnr)
end
end
-function M.progress_pascal(path, bufnr) end
+-- This function checks for valid Pascal syntax in the first 10 lines.
+-- Look for either an opening comment or a program start.
+-- If not found, assume Progress.
+function M.progress_pascal(bufnr)
+ if vim.g.filetype_p then
+ vim.bo[bufnr].filetype = vim.g.filetype_p
+ return
+ end
+ for _, line in ipairs(getlines(bufnr, 1, 10)) do
+ if findany(line, pascal_comments) or matchregex(line, pascal_keywords) then
+ vim.bo[bufnr].filetype = 'pascal'
+ return
+ elseif not line:find('^%s*$') or line:find('^/%*') then
+ -- Not an empty line: Doesn't look like valid Pascal code.
+ -- Or it looks like a Progress /* comment
+ break
+ end
+ end
+ vim.bo[bufnr].filetype = 'progress'
+end
function M.proto(path, bufnr) end
function M.r(bufnr)
local lines = getlines(bufnr, 1, 50)
- -- TODO: \< / \> which match the beginning / end of a word
-- Rebol is easy to recognize, check for that first
- if table.concat(lines):lower():find('rebol') then
+ if matchregex(table.concat(lines), [[\c\<rebol\>]]) then
vim.bo[bufnr].filetype = 'rebol'
return
end
@@ -315,7 +719,43 @@ function M.redif(bufnr)
end
end
-function M.rules(path, bufnr) end
+local udev_rules_pattern = '^%s*udev_rules%s*=%s*"([%^"]+)/*".*'
+function M.rules(path, bufnr)
+ path = path:lower()
+ if
+ findany(path, {
+ '/etc/udev/.*%.rules$',
+ '/etc/udev/rules%.d/.*$.rules$',
+ '/usr/lib/udev/.*%.rules$',
+ '/usr/lib/udev/rules%.d/.*%.rules$',
+ '/lib/udev/.*%.rules$',
+ '/lib/udev/rules%.d/.*%.rules$',
+ })
+ then
+ vim.bo[bufnr].filetype = 'udevrules'
+ elseif path:find('^/etc/ufw/') then
+ -- Better than hog
+ vim.bo[bufnr].filetype = 'conf'
+ elseif findany(path, { '^/etc/polkit%-1/rules%.d', '/usr/share/polkit%-1/rules%.d' }) then
+ vim.bo[bufnr].filetype = 'javascript'
+ else
+ local ok, config_lines = pcall(vim.fn.readfile, '/etc/udev/udev.conf')
+ if not ok then
+ vim.bo[bufnr].filetype = 'hog'
+ return
+ end
+ local dir = vim.fn.expand(path, ':h')
+ for _, line in ipairs(config_lines) do
+ local match = line:match(udev_rules_pattern)
+ local udev_rules = line:gsub(udev_rules_pattern, match, 1)
+ if dir == udev_rules then
+ vim.bo[bufnr].filetype = 'udevrules'
+ return
+ end
+ end
+ vim.bo[bufnr].filetype = 'hog'
+ end
+end
-- This function checks the first 25 lines of file extension "sc" to resolve
-- detection between scala and SuperCollider
@@ -359,9 +799,27 @@ function M.sql(bufnr)
end
end
-function M.src(path, bufnr) end
+-- Determine if a *.src file is Kuka Robot Language
+function M.src(bufnr)
+ if vim.g.filetype_src then
+ vim.bo[bufnr].filetype = vim.g.filetype_src
+ return
+ end
+ local line = nextnonblank(bufnr, 1)
+ if matchregex(line, [[\c\v^\s*%(\&\w+|%(global\s+)?def%(fct)?>)]]) then
+ vim.bo[bufnr].filetype = 'krl'
+ end
+end
-function M.sys(path, bufnr) end
+function M.sys(bufnr)
+ if vim.g.filetype_sys then
+ vim.bo[bufnr].filetype = vim.g.filetype_sys
+ elseif is_rapid(bufnr) then
+ vim.bo[bufnr].filetype = 'rapid'
+ else
+ vim.bo[bufnr].filetype = 'bat'
+ end
+end
function M.tex(path, bufnr) end
@@ -380,8 +838,8 @@ end
function M.xml(bufnr)
for _, line in ipairs(getlines(bufnr, 1, 100)) do
+ local is_docbook4 = line:find('<!DOCTYPE.*DocBook')
line = line:lower()
- local is_docbook4 = line:find('<!doctype.*docbook')
local is_docbook5 = line:find([[ xmlns="http://docbook.org/ns/docbook"]])
if is_docbook4 or is_docbook5 then
vim.b[bufnr].docbk_type = 'xml'
@@ -403,10 +861,9 @@ function M.y(bufnr)
vim.bo[bufnr].filetype = 'yacc'
return
end
- -- TODO: in the Vim regex, \> is used to match the end of the word after "class",
- -- can this be omitted?
- if findany(line, { '^%s*#', '^%class', '^%s*#%s*include' }) then
+ if matchregex(line, [[\c^\s*\(#\|class\>\)]]) and not line:lower():find('^%s*#%s*include') then
vim.bo[bufnr].filetype = 'racc'
+ return
end
end
vim.bo[bufnr].filetype = 'yacc'
diff --git a/runtime/lua/vim/lsp/health.lua b/runtime/lua/vim/lsp/health.lua
index 74714ebc6b..bf8fe0932e 100644
--- a/runtime/lua/vim/lsp/health.lua
+++ b/runtime/lua/vim/lsp/health.lua
@@ -17,7 +17,8 @@ function M.check()
local log_path = vim.lsp.get_log_path()
report_info(string.format('Log path: %s', log_path))
- local log_size = vim.loop.fs_stat(log_path).size
+ local log_file = vim.loop.fs_stat(log_path)
+ local log_size = log_file and log_file.size or 0
local report_fn = (log_size / 1000000 > 100 and report_warn or report_info)
report_fn(string.format('Log size: %d KB', log_size / 1000))
diff --git a/scripts/lintcommit.lua b/scripts/lintcommit.lua
index 34d1263ff4..16326cfe66 100644
--- a/scripts/lintcommit.lua
+++ b/scripts/lintcommit.lua
@@ -78,7 +78,7 @@ local function validate_commit(commit_message)
-- Check if type is correct
local type = vim.split(before_colon, "%(")[1]
- local allowed_types = {'build', 'ci', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'test', 'chore', 'vim-patch'}
+ local allowed_types = {'build', 'ci', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'test', 'dist', 'vim-patch'}
if not vim.tbl_contains(allowed_types, type) then
return string.format(
'Invalid commit type "%s". Allowed types are:\n %s',
@@ -181,7 +181,7 @@ function M._test()
['refactor: normal message'] = true,
['revert: normal message'] = true,
['test: normal message'] = true,
- ['chore: normal message'] = true,
+ ['dist: normal message'] = true,
['ci(window): message with scope'] = true,
['ci!: message with breaking change'] = true,
['ci(tui)!: message with scope and breaking change'] = true,
@@ -205,10 +205,10 @@ function M._test()
['ci :extra space before colon'] = false,
['refactor(): empty scope'] = false,
['ci( ): whitespace as scope'] = false,
- ['chore: period at end of sentence.'] = false,
+ ['ci: period at end of sentence.'] = false,
['ci: Starting sentence capitalized'] = false,
['unknown: using unknown type'] = false,
- ['chore: you\'re saying this commit message just goes on and on and on and on and on and on for way too long?'] = false,
+ ['ci: you\'re saying this commit message just goes on and on and on and on and on and on for way too long?'] = false,
}
local failed = 0
diff --git a/src/nvim/api/vimscript.c b/src/nvim/api/vimscript.c
index 42101af7f0..b8f7b33cd5 100644
--- a/src/nvim/api/vimscript.c
+++ b/src/nvim/api/vimscript.c
@@ -34,7 +34,7 @@
/// Unlike |nvim_command()| this function supports heredocs, script-scope (s:),
/// etc.
///
-/// On execution error: fails with VimL error, does not update v:errmsg.
+/// On execution error: fails with VimL error, updates v:errmsg.
///
/// @see |execute()|
/// @see |nvim_command()|
@@ -98,7 +98,7 @@ theend:
/// Executes an Ex command.
///
-/// On execution error: fails with VimL error, does not update v:errmsg.
+/// On execution error: fails with VimL error, updates v:errmsg.
///
/// Prefer using |nvim_cmd()| or |nvim_exec()| over this. To evaluate multiple lines of Vim script
/// or an Ex command directly, use |nvim_exec()|. To construct an Ex command using a structured
@@ -118,7 +118,7 @@ void nvim_command(String command, Error *err)
/// Evaluates a VimL |expression|.
/// Dictionaries and Lists are recursively expanded.
///
-/// On execution error: fails with VimL error, does not update v:errmsg.
+/// On execution error: fails with VimL error, updates v:errmsg.
///
/// @param expr VimL expression string
/// @param[out] err Error details, if any
@@ -226,7 +226,7 @@ free_vim_args:
/// Calls a VimL function with the given arguments.
///
-/// On execution error: fails with VimL error, does not update v:errmsg.
+/// On execution error: fails with VimL error, updates v:errmsg.
///
/// @param fn Function to call
/// @param args Function arguments packed in an Array
@@ -240,7 +240,7 @@ Object nvim_call_function(String fn, Array args, Error *err)
/// Calls a VimL |Dictionary-function| with the given arguments.
///
-/// On execution error: fails with VimL error, does not update v:errmsg.
+/// On execution error: fails with VimL error, updates v:errmsg.
///
/// @param dict Dictionary, or String evaluating to a VimL |self| dict
/// @param fn Name of the function defined on the VimL dict
@@ -996,6 +996,8 @@ end:
/// such as having spaces inside a command argument, expanding filenames in a command that otherwise
/// doesn't expand filenames, etc.
///
+/// On execution error: fails with VimL error, updates v:errmsg.
+///
/// @see |nvim_exec()|
/// @see |nvim_command()|
///
diff --git a/src/nvim/change.c b/src/nvim/change.c
index a21665dc23..94e5a19edc 100644
--- a/src/nvim/change.c
+++ b/src/nvim/change.c
@@ -209,6 +209,10 @@ static void changed_common(linenr_T lnum, colnr_T col, linenr_T lnume, long xtra
curwin->w_changelistidx = curbuf->b_changelistlen;
}
+ if (VIsual_active) {
+ check_visual_pos();
+ }
+
FOR_ALL_TAB_WINDOWS(tp, wp) {
if (wp->w_buffer == curbuf) {
// Mark this window to be redrawn later.
diff --git a/src/nvim/cursor.c b/src/nvim/cursor.c
index 11c734479c..1446257f7e 100644
--- a/src/nvim/cursor.c
+++ b/src/nvim/cursor.c
@@ -399,6 +399,24 @@ void check_cursor(void)
check_cursor_col();
}
+/// Check if VIsual position is valid, correct it if not.
+/// Can be called when in Visual mode and a change has been made.
+void check_visual_pos(void)
+{
+ if (VIsual.lnum > curbuf->b_ml.ml_line_count) {
+ VIsual.lnum = curbuf->b_ml.ml_line_count;
+ VIsual.col = 0;
+ VIsual.coladd = 0;
+ } else {
+ int len = (int)STRLEN(ml_get(VIsual.lnum));
+
+ if (VIsual.col > len) {
+ VIsual.col = len;
+ VIsual.coladd = 0;
+ }
+ }
+}
+
/// Make sure curwin->w_cursor is not on the NUL at the end of the line.
/// Allow it when in Visual mode and 'selection' is not "old".
void adjust_cursor_col(void)
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 357e9184d7..aa77c03b48 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -6770,13 +6770,8 @@ static void stop_insert(pos_T *end_insert_pos, int esc, int nomove)
// <C-S-Right> may have started Visual mode, adjust the position for
// deleted characters.
- if (VIsual_active && VIsual.lnum == curwin->w_cursor.lnum) {
- int len = (int)STRLEN(get_cursor_line_ptr());
-
- if (VIsual.col > len) {
- VIsual.col = len;
- VIsual.coladd = 0;
- }
+ if (VIsual_active) {
+ check_visual_pos();
}
}
}
diff --git a/src/nvim/event/loop.c b/src/nvim/event/loop.c
index 89fced59c5..d4e20e2f66 100644
--- a/src/nvim/event/loop.c
+++ b/src/nvim/event/loop.c
@@ -143,7 +143,7 @@ bool loop_close(Loop *loop, bool wait)
while (true) {
// Run the loop to tickle close-callbacks (which should then free memory).
// Use UV_RUN_NOWAIT to avoid a hang. #11820
- uv_run(&loop->uv, didstop ? UV_RUN_DEFAULT : UV_RUN_NOWAIT);
+ uv_run(&loop->uv, didstop ? UV_RUN_DEFAULT : UV_RUN_NOWAIT); // -V547
if ((uv_loop_close(&loop->uv) != UV_EBUSY) || !wait) {
break;
}
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 0510faa57d..7506c353dd 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -345,7 +345,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
// here. The value of 200 allows nested function calls, ":source", etc.
// Allow 200 or 'maxfuncdepth', whatever is larger.
if (call_depth >= 200 && call_depth >= p_mfd) {
- emsg(_("E169: Command too recursive"));
+ emsg(_(e_command_too_recursive));
// When converting to an exception, we do not include the command name
// since this is not an error of the specific command.
do_errthrow((cstack_T *)NULL, NULL);
@@ -1683,14 +1683,13 @@ void execute_cmd(exarg_T *eap, CmdParseInfo *cmdinfo)
(eap->argt & EX_BUFUNL) != 0, false, false);
eap->addr_count = 1;
// Shift each argument by 1
- if (eap->args != NULL) {
- for (size_t i = 0; i < eap->argc - 1; i++) {
- eap->args[i] = eap->args[i + 1];
- }
- // Make the last argument point to the NUL terminator at the end of string
- eap->args[eap->argc - 1] = eap->args[eap->argc - 1] + eap->arglens[eap->argc - 1];
- eap->argc -= 1;
+ for (size_t i = 0; i < eap->argc - 1; i++) {
+ eap->args[i] = eap->args[i + 1];
}
+ // Make the last argument point to the NUL terminator at the end of string
+ eap->args[eap->argc - 1] = eap->args[eap->argc - 1] + eap->arglens[eap->argc - 1];
+ eap->argc -= 1;
+
eap->arg = eap->args[0];
}
if (eap->line2 < 0) { // failed
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 114f1e2ae5..1d496cbf25 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -804,6 +804,12 @@ static uint8_t *command_line_enter(int firstc, long count, int indent, bool init
ccline.cmdlen = s->indent;
}
+ if (cmdline_level == 50) {
+ // Somehow got into a loop recursively calling getcmdline(), bail out.
+ emsg(_(e_command_too_recursive));
+ goto theend;
+ }
+
ExpandInit(&s->xpc);
ccline.xpc = &s->xpc;
@@ -995,12 +1001,13 @@ static uint8_t *command_line_enter(int firstc, long count, int indent, bool init
State = s->save_State;
setmouse();
ui_cursor_shape(); // may show different cursor shape
+ sb_text_end_cmdline();
+
+theend:
xfree(s->save_p_icm);
xfree(ccline.last_colors.cmdbuff);
kv_destroy(ccline.last_colors.colors);
- sb_text_end_cmdline();
-
char_u *p = ccline.cmdbuff;
if (ui_has(kUICmdline)) {
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index e34e3983db..3231ac011a 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -877,7 +877,8 @@ EXTERN char e_api_spawn_failed[] INIT(= N_("E903: Could not spawn API job"));
EXTERN char e_argreq[] INIT(= N_("E471: Argument required"));
EXTERN char e_backslash[] INIT(= N_("E10: \\ should be followed by /, ? or &"));
EXTERN char e_cmdwin[] INIT(= N_("E11: Invalid in command-line window; <CR> executes, CTRL-C quits"));
-EXTERN char e_curdir[] INIT(= N_( "E12: Command not allowed from exrc/vimrc in current dir or tag search"));
+EXTERN char e_curdir[] INIT(= N_("E12: Command not allowed from exrc/vimrc in current dir or tag search"));
+EXTERN char e_command_too_recursive[] INIT(= N_("E169: Command too recursive"));
EXTERN char e_endif[] INIT(= N_("E171: Missing :endif"));
EXTERN char e_endtry[] INIT(= N_("E600: Missing :endtry"));
EXTERN char e_endwhile[] INIT(= N_("E170: Missing :endwhile"));
diff --git a/src/nvim/grid.c b/src/nvim/grid.c
index 8a5d8081c0..13429994de 100644
--- a/src/nvim/grid.c
+++ b/src/nvim/grid.c
@@ -63,7 +63,7 @@ void grid_clear_line(ScreenGrid *grid, size_t off, int width, bool valid)
void grid_invalidate(ScreenGrid *grid)
{
- (void)memset(grid->attrs, -1, sizeof(sattr_T) * (size_t)(grid->Rows * grid->Columns));
+ (void)memset(grid->attrs, -1, sizeof(sattr_T) * (size_t)grid->Rows * (size_t)grid->Columns);
}
bool grid_invalid_row(ScreenGrid *grid, int row)
diff --git a/src/nvim/indent_c.c b/src/nvim/indent_c.c
index 6f75183a5a..e6dc985726 100644
--- a/src/nvim/indent_c.c
+++ b/src/nvim/indent_c.c
@@ -150,7 +150,7 @@ static const char_u *skip_string(const char_u *p)
i++;
}
}
- if (p[i] == '\'') { // check for trailing '
+ if (p[i - 1] != NUL && p[i] == '\'') { // check for trailing '
p += i;
continue;
}
diff --git a/src/nvim/strings.c b/src/nvim/strings.c
index c0c942ffd2..cde2059a9d 100644
--- a/src/nvim/strings.c
+++ b/src/nvim/strings.c
@@ -634,12 +634,12 @@ static const void *tv_ptr(const typval_T *const tvs, int *const idxp)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
#define OFF(attr) offsetof(union typval_vval_union, attr)
- STATIC_ASSERT(OFF(v_string) == OFF(v_list)
+ STATIC_ASSERT(OFF(v_string) == OFF(v_list) // -V568
&& OFF(v_string) == OFF(v_dict)
&& OFF(v_string) == OFF(v_partial)
- && sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_list) // -V568
- && sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_dict) // -V568
- && sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_partial), // -V568
+ && sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_list)
+ && sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_dict)
+ && sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_partial),
"Strings, dictionaries, lists and partials are expected to be pointers, "
"so that all three of them can be accessed via v_string");
#undef OFF
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 2d3102707c..c8f70d4afd 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -1374,26 +1374,21 @@ static void fetch_row(Terminal *term, int row, int end_col)
while (col < end_col) {
VTermScreenCell cell;
fetch_cell(term, row, col, &cell);
- int cell_len = 0;
if (cell.chars[0]) {
+ int cell_len = 0;
for (int i = 0; cell.chars[i]; i++) {
cell_len += utf_char2bytes((int)cell.chars[i], ptr + cell_len);
}
- } else {
- *ptr = ' ';
- cell_len = 1;
- }
- char c = *ptr;
- ptr += cell_len;
- if (c != ' ') {
- // only increase the line length if the last character is not whitespace
+ ptr += cell_len;
line_len = (size_t)(ptr - term->textbuf);
+ } else {
+ *ptr++ = ' ';
}
col += cell.width;
}
- // trim trailing whitespace
- term->textbuf[line_len] = 0;
+ // end of line
+ term->textbuf[line_len] = NUL;
}
static bool fetch_cell(Terminal *term, int row, int col, VTermScreenCell *cell)
diff --git a/src/nvim/testdir/test_cindent.vim b/src/nvim/testdir/test_cindent.vim
index 4d69aed96c..7ba8ef3397 100644
--- a/src/nvim/testdir/test_cindent.vim
+++ b/src/nvim/testdir/test_cindent.vim
@@ -5311,6 +5311,13 @@ func Test_cindent_case()
bwipe!
endfunc
+" This was reading past the end of the line
+func Test_cindent_check_funcdecl()
+ new
+ sil norm o0('\0=L
+ bwipe!
+endfunc
+
func Test_cindent_scopedecls()
new
setl cindent ts=4 sw=4
diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim
index 759caac878..b2c752376f 100644
--- a/src/nvim/testdir/test_cmdline.vim
+++ b/src/nvim/testdir/test_cmdline.vim
@@ -1224,4 +1224,16 @@ func Test_screenpos_and_completion()
call feedkeys(":let a\<C-R>=Check_completion()\<CR>\<Esc>", "xt")
endfunc
+func Test_recursive_register()
+ let @= = ''
+ silent! ?e/
+ let caught = 'no'
+ try
+ normal //
+ catch /E169:/
+ let caught = 'yes'
+ endtry
+ call assert_equal('yes', caught)
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_visual.vim b/src/nvim/testdir/test_visual.vim
index 2b88deb813..41c29c5bb0 100644
--- a/src/nvim/testdir/test_visual.vim
+++ b/src/nvim/testdir/test_visual.vim
@@ -1249,11 +1249,23 @@ endfunc
func Test_visual_block_append_invalid_char()
" this was going over the end of the line
+ set isprint=@,161-255
new
call setline(1, [' let xxx', 'xxxxxˆ', 'xxxxxxxxxxx'])
exe "normal 0\<C-V>jjA-\<Esc>"
call assert_equal([' - let xxx', 'xxxxx -ˆ', 'xxxxxxxx-xxx'], getline(1, 3))
bwipe!
+ set isprint&
+endfunc
+
+func Test_visual_block_with_substitute()
+ " this was reading beyond the end of the line
+ new
+ norm a0)
+ sil! norm  O
+ s/)
+ sil! norm 
+ bwipe!
endfunc
func Test_visual_reselect_with_count()
diff --git a/test/functional/api/buffer_updates_spec.lua b/test/functional/api/buffer_updates_spec.lua
index fc09e4cde0..2728dcf74c 100644
--- a/test/functional/api/buffer_updates_spec.lua
+++ b/test/functional/api/buffer_updates_spec.lua
@@ -785,7 +785,8 @@ describe('API: buffer events:', function()
local function lines_subset(first, second)
for i = 1,#first do
- if first[i] ~= second[i] then
+ -- need to ignore trailing spaces
+ if first[i]:gsub(' +$', '') ~= second[i]:gsub(' +$', '') then
return false
end
end
@@ -827,7 +828,6 @@ describe('API: buffer events:', function()
end
it('when :terminal lines change', function()
- if helpers.pending_win32(pending) then return end
local buffer_lines = {}
local expected_lines = {}
command('terminal "'..nvim_prog..'" -u NONE -i NONE -n -c "set shortmess+=A"')
diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua
index 20ea3621f0..f87fd8e951 100644
--- a/test/functional/core/startup_spec.lua
+++ b/test/functional/core/startup_spec.lua
@@ -53,7 +53,6 @@ describe('startup', function()
]])
end)
it('in a TTY: has("ttyin")==1 has("ttyout")==1', function()
- if helpers.pending_win32(pending) then return end
local screen = Screen.new(25, 4)
screen:attach()
if iswin() then
@@ -105,7 +104,6 @@ describe('startup', function()
end)
end)
it('input from pipe (implicit) #7679', function()
- if helpers.pending_win32(pending) then return end
local screen = Screen.new(25, 4)
screen:attach()
if iswin() then
@@ -261,7 +259,6 @@ describe('startup', function()
end)
it('ENTER dismisses early message #7967', function()
- if helpers.pending_win32(pending) then return end
local screen
screen = Screen.new(60, 6)
screen:attach()
@@ -494,14 +491,14 @@ describe('sysinit', function()
end)
it('fixed hang issue with -D (#12647)', function()
- if helpers.pending_win32(pending) then return end
local screen
- screen = Screen.new(60, 6)
+ screen = Screen.new(60, 7)
screen:attach()
command([[let g:id = termopen('"]]..nvim_prog..
[[" -u NONE -i NONE --cmd "set noruler" -D')]])
screen:expect([[
^ |
+ |
Entering Debug mode. Type "cont" to continue. |
cmd: augroup nvim_terminal |
> |
@@ -512,6 +509,7 @@ describe('sysinit', function()
screen:expect([[
^ |
~ |
+ ~ |
[No Name] |
|
<" -u NONE -i NONE --cmd "set noruler" -D 1,0-1 All|
diff --git a/test/functional/ex_cmds/mksession_spec.lua b/test/functional/ex_cmds/mksession_spec.lua
index 2702fb196f..97e41bbe83 100644
--- a/test/functional/ex_cmds/mksession_spec.lua
+++ b/test/functional/ex_cmds/mksession_spec.lua
@@ -10,11 +10,11 @@ local funcs = helpers.funcs
local matches = helpers.matches
local pesc = helpers.pesc
local rmdir = helpers.rmdir
+local sleep = helpers.sleep
local file_prefix = 'Xtest-functional-ex_cmds-mksession_spec'
describe(':mksession', function()
- if helpers.pending_win32(pending) then return end
local session_file = file_prefix .. '.vim'
local tab_dir = file_prefix .. '.d'
@@ -103,9 +103,11 @@ describe(':mksession', function()
local session_path = cwd_dir..'/'..session_file
command('cd '..tab_dir)
- command('terminal echo $PWD')
+ command('terminal')
command('cd '..cwd_dir)
command('mksession '..session_path)
+ command('bd!')
+ sleep(100) -- Make sure the process exits.
command('qall!')
-- Create a new test instance of Nvim.
@@ -114,6 +116,7 @@ describe(':mksession', function()
local expected_cwd = cwd_dir..'/'..tab_dir
matches('^term://'..pesc(expected_cwd)..'//%d+:', funcs.expand('%'))
- command('qall!')
+ command('bd!')
+ sleep(100) -- Make sure the process exits.
end)
end)
diff --git a/test/functional/terminal/cursor_spec.lua b/test/functional/terminal/cursor_spec.lua
index 3b905f1f56..6e06304acd 100644
--- a/test/functional/terminal/cursor_spec.lua
+++ b/test/functional/terminal/cursor_spec.lua
@@ -5,6 +5,7 @@ local feed, clear, nvim = helpers.feed, helpers.clear, helpers.nvim
local nvim_dir, command = helpers.nvim_dir, helpers.command
local nvim_prog = helpers.nvim_prog
local eq, eval = helpers.eq, helpers.eval
+local matches = helpers.matches
local feed_command = helpers.feed_command
local hide_cursor = thelpers.hide_cursor
local show_cursor = thelpers.show_cursor
@@ -177,7 +178,6 @@ describe('cursor with customized highlighting', function()
end)
describe('buffer cursor position is correct in terminal without number column', function()
- if helpers.pending_win32(pending) then return end
local screen
local function setup_ex_register(str)
@@ -525,10 +525,36 @@ describe('buffer cursor position is correct in terminal without number column',
eq({6, 1}, eval('nvim_win_get_cursor(0)'))
end)
end)
+
+ it('at the end of a line with trailing spaces #16234', function()
+ setup_ex_register('aaaaaaaa ')
+ feed('<C-R>r')
+ screen:expect([[
+ |
+ |
+ |
+ |
+ Entering Ex mode. Type "visual" to go to Normal mode. |
+ :aaaaaaaa {1: } |
+ {3:-- TERMINAL --} |
+ ]])
+ matches('^:aaaaaaaa [ ]*$', eval('nvim_get_current_line()'))
+ eq({6, 13}, eval('nvim_win_get_cursor(0)'))
+ feed([[<C-\><C-N>]])
+ screen:expect([[
+ |
+ |
+ |
+ |
+ Entering Ex mode. Type "visual" to go to Normal mode. |
+ :aaaaaaaa ^ {2: } |
+ |
+ ]])
+ eq({6, 12}, eval('nvim_win_get_cursor(0)'))
+ end)
end)
describe('buffer cursor position is correct in terminal with number column', function()
- if helpers.pending_win32(pending) then return end
local screen
local function setup_ex_register(str)
@@ -879,4 +905,31 @@ describe('buffer cursor position is correct in terminal with number column', fun
eq({6, 1}, eval('nvim_win_get_cursor(0)'))
end)
end)
+
+ it('at the end of a line with trailing spaces #16234', function()
+ setup_ex_register('aaaaaaaa ')
+ feed('<C-R>r')
+ screen:expect([[
+ {7: 1 } |
+ {7: 2 } |
+ {7: 3 } |
+ {7: 4 } |
+ {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
+ {7: 6 }:aaaaaaaa {1: } |
+ {3:-- TERMINAL --} |
+ ]])
+ matches('^:aaaaaaaa [ ]*$', eval('nvim_get_current_line()'))
+ eq({6, 13}, eval('nvim_win_get_cursor(0)'))
+ feed([[<C-\><C-N>]])
+ screen:expect([[
+ {7: 1 } |
+ {7: 2 } |
+ {7: 3 } |
+ {7: 4 } |
+ {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
+ {7: 6 }:aaaaaaaa ^ {2: } |
+ |
+ ]])
+ eq({6, 12}, eval('nvim_win_get_cursor(0)'))
+ end)
end)
diff --git a/test/functional/terminal/highlight_spec.lua b/test/functional/terminal/highlight_spec.lua
index 32c911a5e8..2a63971d48 100644
--- a/test/functional/terminal/highlight_spec.lua
+++ b/test/functional/terminal/highlight_spec.lua
@@ -117,7 +117,6 @@ describe(':terminal highlight', function()
end)
it(':terminal highlight has lower precedence than editor #9964', function()
- if helpers.pending_win32(pending) then return end
clear()
local screen = Screen.new(30, 4)
screen:set_default_attr_ids({
diff --git a/test/functional/terminal/scrollback_spec.lua b/test/functional/terminal/scrollback_spec.lua
index d1cfc7e91b..34fcb6cab9 100644
--- a/test/functional/terminal/scrollback_spec.lua
+++ b/test/functional/terminal/scrollback_spec.lua
@@ -6,6 +6,7 @@ local feed, nvim_dir, feed_command = helpers.feed, helpers.nvim_dir, helpers.fee
local iswin = helpers.iswin
local eval = helpers.eval
local command = helpers.command
+local matches = helpers.matches
local poke_eventloop = helpers.poke_eventloop
local retry = helpers.retry
local curbufmeths = helpers.curbufmeths
@@ -460,8 +461,8 @@ describe("'scrollback' option", function()
expect_lines(58)
-- Verify off-screen state
- eq((iswin() and '36: line' or '35: line'), eval("getline(line('w0') - 1)"))
- eq((iswin() and '27: line' or '26: line'), eval("getline(line('w0') - 10)"))
+ matches((iswin() and '^36: line[ ]*$' or '^35: line[ ]*$'), eval("getline(line('w0') - 1)"))
+ matches((iswin() and '^27: line[ ]*$' or '^26: line[ ]*$'), eval("getline(line('w0') - 10)"))
end)
it('defaults to 10000 in :terminal buffers', function()
diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua
index 041337df8a..ee1e37c675 100644
--- a/test/functional/ui/messages_spec.lua
+++ b/test/functional/ui/messages_spec.lua
@@ -1312,7 +1312,6 @@ end)
describe('ui/msg_puts_printf', function()
it('output multibyte characters correctly', function()
- if helpers.pending_win32(pending) then return end
local screen
local cmd = ''
local locale_dir = test_build_dir..'/share/locale/ja/LC_MESSAGES'
diff --git a/test/functional/ui/output_spec.lua b/test/functional/ui/output_spec.lua
index 7305baa761..50e5dfac84 100644
--- a/test/functional/ui/output_spec.lua
+++ b/test/functional/ui/output_spec.lua
@@ -14,7 +14,6 @@ local has_powershell = helpers.has_powershell
local set_shell_powershell = helpers.set_shell_powershell
describe("shell command :!", function()
- if helpers.pending_win32(pending) then return end
local screen
before_each(function()
clear()
diff --git a/test/unit/fixtures/rbuffer.c b/test/unit/fixtures/rbuffer.c
index 3f4062fa18..efa7ab1986 100644
--- a/test/unit/fixtures/rbuffer.c
+++ b/test/unit/fixtures/rbuffer.c
@@ -15,7 +15,7 @@ void ut_rbuffer_each_read_chunk(RBuffer *buf, each_ptr_cb cb)
void ut_rbuffer_each_write_chunk(RBuffer *buf, each_ptr_cb cb)
{
- RBUFFER_UNTIL_FULL(buf, wptr, wcnt) {
+ RBUFFER_UNTIL_FULL(buf, wptr, wcnt) { // -V1044
cb(wptr, wcnt);
rbuffer_produced(buf, wcnt);
}
diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt
index 36965a2e98..0464f90734 100644
--- a/third-party/CMakeLists.txt
+++ b/third-party/CMakeLists.txt
@@ -130,8 +130,8 @@ endif()
include(ExternalProject)
-set(LIBUV_URL https://github.com/libuv/libuv/archive/v1.44.1.tar.gz)
-set(LIBUV_SHA256 e91614e6dc2dd0bfdd140ceace49438882206b7a6fb00b8750914e67a9ed6d6b)
+set(LIBUV_URL https://github.com/libuv/libuv/archive/730e07e2f77a4001bdf6894112271c926399f5a8.tar.gz)
+set(LIBUV_SHA256 271869759a7dbdaf1d1bf75f1ec388a7307592153b34ebb52d3934715cbaac8a)
set(MSGPACK_URL https://github.com/msgpack/msgpack-c/releases/download/c-4.0.0/msgpack-c-4.0.0.tar.gz)
set(MSGPACK_SHA256 420fe35e7572f2a168d17e660ef981a589c9cbe77faa25eb34a520e1fcc032c8)