aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/autoload/netrw.vim23
-rw-r--r--runtime/autoload/zip.vim37
-rw-r--r--runtime/colors/vim.lua154
-rw-r--r--runtime/compiler/javac.vim9
-rw-r--r--runtime/doc/api.txt6
-rw-r--r--runtime/doc/builtin.txt163
-rw-r--r--runtime/doc/diagnostic.txt1
-rw-r--r--runtime/doc/lsp.txt2
-rw-r--r--runtime/doc/lua.txt16
-rw-r--r--runtime/doc/news.txt10
-rw-r--r--runtime/doc/nvim_terminal_emulator.txt17
-rw-r--r--runtime/doc/options.txt13
-rw-r--r--runtime/doc/quickfix.txt7
-rw-r--r--runtime/doc/syntax.txt38
-rw-r--r--runtime/doc/treesitter.txt2
-rw-r--r--runtime/doc/various.txt2
-rw-r--r--runtime/doc/vim_diff.txt21
-rw-r--r--runtime/ftplugin/kdl.vim17
-rw-r--r--runtime/ftplugin/snakemake.vim13
-rw-r--r--runtime/ftplugin/svelte.vim13
-rw-r--r--runtime/indent/kdl.vim30
-rw-r--r--runtime/keymap/georgian-qwerty.vim51
-rw-r--r--runtime/lua/vim/_defaults.lua24
-rw-r--r--runtime/lua/vim/_meta/api.lua6
-rw-r--r--runtime/lua/vim/_meta/builtin.lua1
-rw-r--r--runtime/lua/vim/_meta/builtin_types.lua5
-rw-r--r--runtime/lua/vim/_meta/lpeg.lua4
-rw-r--r--runtime/lua/vim/_meta/options.lua13
-rw-r--r--runtime/lua/vim/_meta/vimfn.lua200
-rw-r--r--runtime/lua/vim/_options.lua11
-rw-r--r--runtime/lua/vim/filetype.lua2
-rw-r--r--runtime/lua/vim/filetype/detect.lua1
-rw-r--r--runtime/lua/vim/iter.lua2
-rw-r--r--runtime/lua/vim/lsp/_dynamic.lua4
-rw-r--r--runtime/lua/vim/lsp/client.lua21
-rw-r--r--runtime/lua/vim/lsp/completion.lua4
-rw-r--r--runtime/lua/vim/lsp/handlers.lua1
-rw-r--r--runtime/lua/vim/lsp/inlay_hint.lua2
-rw-r--r--runtime/lua/vim/lsp/log.lua2
-rw-r--r--runtime/lua/vim/lsp/protocol.lua342
-rw-r--r--runtime/lua/vim/lsp/rpc.lua8
-rw-r--r--runtime/lua/vim/lsp/semantic_tokens.lua3
-rw-r--r--runtime/lua/vim/lsp/util.lua29
-rw-r--r--runtime/lua/vim/text.lua10
-rw-r--r--runtime/lua/vim/treesitter/_fold.lua1
-rw-r--r--runtime/lua/vim/treesitter/_meta.lua2
-rw-r--r--runtime/lua/vim/treesitter/highlighter.lua6
-rw-r--r--runtime/lua/vim/treesitter/languagetree.lua10
-rw-r--r--runtime/pack/dist/opt/termdebug/plugin/termdebug.vim125
-rw-r--r--runtime/syntax/deb822sources.vim2
-rw-r--r--runtime/syntax/html.vim2
-rw-r--r--runtime/syntax/java.vim56
-rw-r--r--runtime/syntax/kdl.vim48
-rw-r--r--runtime/syntax/vim.vim45
-rwxr-xr-xscripts/gen_vimdoc.lua9
-rw-r--r--scripts/luacats_grammar.lua3
-rw-r--r--scripts/luacats_parser.lua2
-rwxr-xr-xsrc/clint.py2
-rw-r--r--src/nvim/api/extmark.c6
-rw-r--r--src/nvim/api/private/helpers.c4
-rw-r--r--src/nvim/autocmd.c2
-rw-r--r--src/nvim/base64.c1
-rw-r--r--src/nvim/change.c4
-rw-r--r--src/nvim/cmdexpand.c2
-rw-r--r--src/nvim/context.c126
-rw-r--r--src/nvim/context.h22
-rw-r--r--src/nvim/diff.c6
-rw-r--r--src/nvim/drawline.c7
-rw-r--r--src/nvim/eval.c4
-rw-r--r--src/nvim/eval.lua195
-rw-r--r--src/nvim/eval/userfunc.c4
-rw-r--r--src/nvim/ex_cmds.c12
-rw-r--r--src/nvim/ex_docmd.c6
-rw-r--r--src/nvim/ex_eval.c4
-rw-r--r--src/nvim/file_search.c10
-rw-r--r--src/nvim/fold.c2
-rw-r--r--src/nvim/highlight.h4
-rw-r--r--src/nvim/highlight_defs.h4
-rw-r--r--src/nvim/highlight_group.c60
-rw-r--r--src/nvim/insexpand.c33
-rw-r--r--src/nvim/memory.h4
-rw-r--r--src/nvim/memory_defs.h2
-rw-r--r--src/nvim/menu.c2
-rw-r--r--src/nvim/msgpack_rpc/channel.c8
-rw-r--r--src/nvim/msgpack_rpc/packer.c27
-rw-r--r--src/nvim/msgpack_rpc/packer.h5
-rw-r--r--src/nvim/msgpack_rpc/packer_defs.h2
-rw-r--r--src/nvim/normal.c2
-rw-r--r--src/nvim/ops.c6
-rw-r--r--src/nvim/option.c6
-rw-r--r--src/nvim/option_vars.h14
-rw-r--r--src/nvim/options.lua13
-rw-r--r--src/nvim/os/fileio.c3
-rw-r--r--src/nvim/os/fileio.h6
-rw-r--r--src/nvim/os/shell.c26
-rw-r--r--src/nvim/path.c4
-rw-r--r--src/nvim/popupmenu.c167
-rw-r--r--src/nvim/popupmenu.h1
-rw-r--r--src/nvim/quickfix.c4
-rw-r--r--src/nvim/regexp.c2
-rw-r--r--src/nvim/runtime.c2
-rw-r--r--src/nvim/search.c33
-rw-r--r--src/nvim/shada.c169
-rw-r--r--src/nvim/shada.h2
-rw-r--r--src/nvim/sign.c4
-rw-r--r--src/nvim/spell.c12
-rw-r--r--src/nvim/spellfile.c20
-rw-r--r--src/nvim/spellsuggest.c4
-rw-r--r--src/nvim/statusline.c84
-rw-r--r--src/nvim/syntax.c2
-rw-r--r--src/nvim/tag.c2
-rw-r--r--src/nvim/terminal.c77
-rw-r--r--src/nvim/ui.c8
-rw-r--r--src/nvim/usercmd.c4
-rw-r--r--test/functional/api/vim_spec.lua6
-rw-r--r--test/functional/core/startup_spec.lua6
-rw-r--r--test/functional/editor/macro_spec.lua17
-rw-r--r--test/functional/lua/vim_spec.lua21
-rw-r--r--test/functional/plugin/lsp/completion_spec.lua17
-rw-r--r--test/functional/plugin/lsp/semantic_tokens_spec.lua24
-rw-r--r--test/functional/plugin/lsp_spec.lua15
-rw-r--r--test/functional/terminal/buffer_spec.lua4
-rw-r--r--test/functional/terminal/clipboard_spec.lua65
-rw-r--r--test/functional/terminal/mouse_spec.lua8
-rw-r--r--test/functional/terminal/testutil.lua4
-rw-r--r--test/functional/terminal/tui_spec.lua38
-rw-r--r--test/functional/terminal/window_spec.lua26
-rw-r--r--test/functional/terminal/window_split_tab_spec.lua8
-rw-r--r--test/functional/testnvim.lua2
-rw-r--r--test/functional/ui/cursor_spec.lua4
-rw-r--r--test/functional/ui/float_spec.lua12
-rw-r--r--test/functional/ui/popupmenu_spec.lua236
-rw-r--r--test/functional/ui/searchhl_spec.lua9
-rw-r--r--test/functional/ui/sign_spec.lua30
-rw-r--r--test/functional/ui/statuscolumn_spec.lua354
-rw-r--r--test/functional/ui/wildmode_spec.lua12
-rw-r--r--test/old/testdir/test_cmdline.vim18
-rw-r--r--test/old/testdir/test_filetype.vim2
-rw-r--r--test/old/testdir/test_functions.vim27
-rw-r--r--test/old/testdir/test_ins_complete.vim41
-rw-r--r--test/old/testdir/test_popup.vim126
-rw-r--r--test/old/testdir/test_signs.vim6
-rw-r--r--test/old/testdir/test_termdebug.vim11
-rw-r--r--test/old/testdir/test_visual.vim9
144 files changed, 2526 insertions, 1530 deletions
diff --git a/runtime/autoload/netrw.vim b/runtime/autoload/netrw.vim
index a1929636e5..7da97c9690 100644
--- a/runtime/autoload/netrw.vim
+++ b/runtime/autoload/netrw.vim
@@ -14,6 +14,7 @@
" 2024 May 10 by Vim Project: recursively delete directories by default
" 2024 May 13 by Vim Project: prefer scp over pscp
" 2024 Jun 04 by Vim Project: set bufhidden if buffer changed, nohidden is set and buffer shall be switched (#14915)
+" 2024 Jun 13 by Vim Project: glob() on Windows fails when a directory name contains [] (#14952)
" Former Maintainer: Charles E Campbell
" GetLatestVimScripts: 1075 1 :AutoInstall: netrw.vim
" Copyright: Copyright (C) 2016 Charles E. Campbell {{{1
@@ -5756,16 +5757,20 @@ fun! s:NetrwGlob(direntry,expr,pare)
let filelist= w:netrw_treedict[a:direntry]
endif
let w:netrw_liststyle= keep_liststyle
- elseif v:version > 704 || (v:version == 704 && has("patch656"))
- let filelist= glob(s:ComposePath(fnameescape(a:direntry),a:expr),0,1,1)
- if a:pare
- let filelist= map(filelist,'substitute(v:val, "^.*/", "", "")')
- endif
else
- let filelist= glob(s:ComposePath(fnameescape(a:direntry),a:expr),0,1)
- if a:pare
- let filelist= map(filelist,'substitute(v:val, "^.*/", "", "")')
- endif
+ let path= s:ComposePath(fnameescape(a:direntry),a:expr)
+ if has("win32")
+ " escape [ so it is not detected as wildcard character, see :h wildcard
+ let path= substitute(path, '[', '[[]', 'g')
+ endif
+ if v:version > 704 || (v:version == 704 && has("patch656"))
+ let filelist= glob(path,0,1,1)
+ else
+ let filelist= glob(path,0,1)
+ endif
+ if a:pare
+ let filelist= map(filelist,'substitute(v:val, "^.*/", "", "")')
+ endif
endif
" call Dret("s:NetrwGlob ".string(filelist))
return filelist
diff --git a/runtime/autoload/zip.vim b/runtime/autoload/zip.vim
index c0034f8a7a..d0e706e83a 100644
--- a/runtime/autoload/zip.vim
+++ b/runtime/autoload/zip.vim
@@ -4,17 +4,18 @@
" Version: 33
" Maintainer: This runtime file is looking for a new maintainer.
" Former Maintainer: Charles E Campbell
+" Last Change:
+" 2024 Jun 16 by Vim Project: handle whitespace on Windows properly (#14998)
" License: Vim License (see vim's :help license)
-" Copyright: Copyright (C) 2005-2019 Charles E. Campbell {{{1
-" Permission is hereby granted to use and distribute this code,
-" with or without modifications, provided that this copyright
-" notice is copied with it. Like anything else that's free,
-" zip.vim and zipPlugin.vim are provided *as is* and comes with
-" no warranty of any kind, either expressed or implied. By using
-" this plugin, you agree that in no event will the copyright
-" holder be liable for any damages resulting from the use
-" of this software.
-"redraw!|call DechoSep()|call inputsave()|call input("Press <cr> to continue")|call inputrestore()
+" Copyright: Copyright (C) 2005-2019 Charles E. Campbell {{{1
+" Permission is hereby granted to use and distribute this code,
+" with or without modifications, provided that this copyright
+" notice is copied with it. Like anything else that's free,
+" zip.vim and zipPlugin.vim are provided *as is* and comes with
+" no warranty of any kind, either expressed or implied. By using
+" this plugin, you agree that in no event will the copyright
+" holder be liable for any damages resulting from the use
+" of this software.
" ---------------------------------------------------------------------
" Load Once: {{{1
@@ -214,7 +215,6 @@ endfun
" ---------------------------------------------------------------------
" zip#Read: {{{2
fun! zip#Read(fname,mode)
-" call Dfunc("zip#Read(fname<".a:fname.">,mode=".a:mode.")")
let repkeep= &report
set report=10
@@ -226,15 +226,12 @@ fun! zip#Read(fname,mode)
let fname = substitute(a:fname,'^.\{-}zipfile://.\{-}::\([^\\].*\)$','\1','')
let fname = substitute(fname, '[', '[[]', 'g')
endif
-" call Decho("zipfile<".zipfile.">")
-" call Decho("fname <".fname.">")
" sanity check
if !executable(substitute(g:zip_unzipcmd,'\s\+.*$','',''))
redraw!
echohl Error | echo "***error*** (zip#Read) sorry, your system doesn't appear to have the ".g:zip_unzipcmd." program" | echohl None
" call inputsave()|call input("Press <cr> to continue")|call inputrestore()
let &report= repkeep
-" call Dret("zip#Write")
return
endif
@@ -242,10 +239,8 @@ fun! zip#Read(fname,mode)
" exe "keepj sil! r! ".g:zip_unzipcmd." -p -- ".s:Escape(zipfile,1)." ".s:Escape(fnameescape(fname),1)
" but allows zipfile://... entries in quickfix lists
let temp = tempname()
-" call Decho("using temp file<".temp.">")
let fn = expand('%:p')
- exe "sil! !".g:zip_unzipcmd." -p -- ".s:Escape(zipfile,1)." ".s:Escape(fnameescape(fname),1).' > '.temp
-" call Decho("exe sil! !".g:zip_unzipcmd." -p -- ".s:Escape(zipfile,1)." ".s:Escape(fnameescape(fname),1).' > '.temp)
+ exe "sil! !".g:zip_unzipcmd." -p -- ".s:Escape(zipfile,1)." ".s:Escape(fname,1).' > '.temp
sil exe 'keepalt file '.temp
sil keepj e!
sil exe 'keepalt file '.fnameescape(fn)
@@ -254,11 +249,9 @@ fun! zip#Read(fname,mode)
filetype detect
" cleanup
- " keepj 0d " used to be needed for the ...r! ... method
set nomod
let &report= repkeep
-" call Dret("zip#Read")
endfun
" ---------------------------------------------------------------------
@@ -422,7 +415,6 @@ endfun
" ---------------------------------------------------------------------
" s:Escape: {{{2
fun! s:Escape(fname,isfilt)
-" call Dfunc("QuoteFileDir(fname<".a:fname."> isfilt=".a:isfilt.")")
if exists("*shellescape")
if a:isfilt
let qnameq= shellescape(a:fname,1)
@@ -432,7 +424,10 @@ fun! s:Escape(fname,isfilt)
else
let qnameq= g:zip_shq.escape(a:fname,g:zip_shq).g:zip_shq
endif
-" call Dret("QuoteFileDir <".qnameq.">")
+ if exists("+shellslash") && &shellslash && &shell =~ "cmd.exe"
+ " renormalize directory separator on Windows
+ let qnameq=substitute(qnameq, '/', '\\', 'g')
+ endif
return qnameq
endfun
diff --git a/runtime/colors/vim.lua b/runtime/colors/vim.lua
index 7231418f5f..5b9309ab38 100644
--- a/runtime/colors/vim.lua
+++ b/runtime/colors/vim.lua
@@ -56,6 +56,8 @@ hi('CursorLineFold', { link = 'FoldColumn' })
hi('CurSearch', { link = 'Search' })
hi('PmenuKind', { link = 'Pmenu' })
hi('PmenuKindSel', { link = 'PmenuSel' })
+hi('PmenuMatch', { link = 'Pmenu' })
+hi('PmenuMatchSel', { link = 'PmenuSel' })
hi('PmenuExtra', { link = 'Pmenu' })
hi('PmenuExtraSel', { link = 'PmenuSel' })
hi('Substitute', { link = 'Search' })
@@ -209,81 +211,85 @@ hi('@lsp.type.variable', { link = 'Identifier' })
if vim.o.background == 'light' then
-- Default colors only used with a light background.
- hi('ColorColumn', { bg = 'LightRed', ctermbg = 'LightRed' })
- hi('CursorColumn', { bg = 'Grey90', ctermbg = 'LightGrey' })
- hi('CursorLine', { bg = 'Grey90', cterm = { underline = true } })
- hi('CursorLineNr', { fg = 'Brown', bold = true, ctermfg = 'Brown', cterm = { underline = true } })
- hi('DiffAdd', { bg = 'LightBlue', ctermbg = 'LightBlue' })
- hi('DiffChange', { bg = 'LightMagenta', ctermbg = 'LightMagenta' })
- hi('DiffDelete', { fg = 'Blue', bg = 'LightCyan', bold = true, ctermfg = 'Blue', ctermbg = 'LightCyan' })
- hi('Directory', { fg = 'Blue', ctermfg = 'DarkBlue' })
- hi('FoldColumn', { fg = 'DarkBlue', bg = 'Grey', ctermfg = 'DarkBlue', ctermbg = 'Grey' })
- hi('Folded', { fg = 'DarkBlue', bg = 'LightGrey', ctermfg = 'DarkBlue', ctermbg = 'Grey' })
- hi('LineNr', { fg = 'Brown', ctermfg = 'Brown' })
- hi('MatchParen', { bg = 'Cyan', ctermbg = 'Cyan' })
- hi('MoreMsg', { fg = 'SeaGreen', bold = true, ctermfg = 'DarkGreen' })
- hi('Pmenu', { bg = 'LightMagenta', ctermfg = 'Black', ctermbg = 'LightMagenta' })
- hi('PmenuSel', { bg = 'Grey', ctermfg = 'Black', ctermbg = 'LightGrey' })
- hi('PmenuThumb', { bg = 'Black', ctermbg = 'Black' })
- hi('Question', { fg = 'SeaGreen', bold = true, ctermfg = 'DarkGreen' })
- hi('Search', { bg = 'Yellow', ctermbg = 'Yellow' })
- hi('SignColumn', { fg = 'DarkBlue', bg = 'Grey', ctermfg = 'DarkBlue', ctermbg = 'Grey' })
- hi('SpecialKey', { fg = 'Blue', ctermfg = 'DarkBlue' })
- hi('SpellBad', { sp = 'Red', undercurl = true, ctermbg = 'LightRed' })
- hi('SpellCap', { sp = 'Blue', undercurl = true, ctermbg = 'LightBlue' })
- hi('SpellLocal', { sp = 'DarkCyan', undercurl = true, ctermbg = 'Cyan' })
- hi('SpellRare', { sp = 'Magenta', undercurl = true, ctermbg = 'LightMagenta' })
- hi('TabLine', { bg = 'LightGrey', underline = true, ctermfg = 'Black', ctermbg = 'LightGrey', cterm = { underline = true } })
- hi('Title', { fg = 'Magenta', bold = true, ctermfg = 'DarkMagenta' })
- hi('Visual', { fg = 'Black', bg = 'LightGrey', ctermfg = 'Black', ctermbg = 'Grey' })
- hi('WarningMsg', { fg = 'Red', ctermfg = 'DarkRed' })
- hi('Comment', { fg = 'Blue', ctermfg = 'DarkBlue' })
- hi('Constant', { fg = 'Magenta', ctermfg = 'DarkRed' })
- hi('Special', { fg = '#6a5acd', ctermfg = 'DarkMagenta' })
- hi('Identifier', { fg = 'DarkCyan', ctermfg = 'DarkCyan' })
- hi('Statement', { fg = 'Brown', bold = true, ctermfg = 'Brown' })
- hi('PreProc', { fg = '#6a0dad', ctermfg = 'DarkMagenta' })
- hi('Type', { fg = 'SeaGreen', bold = true, ctermfg = 'DarkGreen' })
- hi('Underlined', { fg = 'SlateBlue', underline = true, ctermfg = 'DarkMagenta', cterm = { underline = true } })
- hi('Ignore', { ctermfg = 'White' })
+ hi('ColorColumn', { bg = 'LightRed', ctermbg = 'LightRed' })
+ hi('CursorColumn', { bg = 'Grey90', ctermbg = 'LightGrey' })
+ hi('CursorLine', { bg = 'Grey90', cterm = { underline = true } })
+ hi('CursorLineNr', { fg = 'Brown', bold = true, ctermfg = 'Brown', cterm = { underline = true } })
+ hi('DiffAdd', { bg = 'LightBlue', ctermbg = 'LightBlue' })
+ hi('DiffChange', { bg = 'LightMagenta', ctermbg = 'LightMagenta' })
+ hi('DiffDelete', { fg = 'Blue', bg = 'LightCyan', bold = true, ctermfg = 'Blue', ctermbg = 'LightCyan' })
+ hi('Directory', { fg = 'Blue', ctermfg = 'DarkBlue' })
+ hi('FoldColumn', { fg = 'DarkBlue', bg = 'Grey', ctermfg = 'DarkBlue', ctermbg = 'Grey' })
+ hi('Folded', { fg = 'DarkBlue', bg = 'LightGrey', ctermfg = 'DarkBlue', ctermbg = 'Grey' })
+ hi('LineNr', { fg = 'Brown', ctermfg = 'Brown' })
+ hi('MatchParen', { bg = 'Cyan', ctermbg = 'Cyan' })
+ hi('MoreMsg', { fg = 'SeaGreen', bold = true, ctermfg = 'DarkGreen' })
+ hi('Pmenu', { bg = 'LightMagenta', ctermfg = 'Black', ctermbg = 'LightMagenta' })
+ hi('PmenuSel', { bg = 'Grey', ctermfg = 'Black', ctermbg = 'LightGrey' })
+ hi('PmenuThumb', { bg = 'Black', ctermbg = 'Black' })
+ hi('Question', { fg = 'SeaGreen', bold = true, ctermfg = 'DarkGreen' })
+ hi('Search', { bg = 'Yellow', ctermbg = 'Yellow' })
+ hi('SignColumn', { fg = 'DarkBlue', bg = 'Grey', ctermfg = 'DarkBlue', ctermbg = 'Grey' })
+ hi('SpecialKey', { fg = 'Blue', ctermfg = 'DarkBlue' })
+ hi('SpellBad', { sp = 'Red', undercurl = true, ctermbg = 'LightRed' })
+ hi('SpellCap', { sp = 'Blue', undercurl = true, ctermbg = 'LightBlue' })
+ hi('SpellLocal', { sp = 'DarkCyan', undercurl = true, ctermbg = 'Cyan' })
+ hi('SpellRare', { sp = 'Magenta', undercurl = true, ctermbg = 'LightMagenta' })
+ hi('StatusLineTerm', { fg = 'White', bg = 'DarkGreen', bold = true, ctermfg = 'White', ctermbg = 'DarkGreen', cterm = { bold = true } })
+ hi('StatusLineTermNC', { fg = 'White', bg = 'DarkGreen', ctermfg = 'White', ctermbg = 'DarkGreen' })
+ hi('TabLine', { bg = 'LightGrey', underline = true, ctermfg = 'Black', ctermbg = 'LightGrey', cterm = { underline = true } })
+ hi('Title', { fg = 'Magenta', bold = true, ctermfg = 'DarkMagenta' })
+ hi('Visual', { fg = 'Black', bg = 'LightGrey', ctermfg = 'Black', ctermbg = 'Grey' })
+ hi('WarningMsg', { fg = 'Red', ctermfg = 'DarkRed' })
+ hi('Comment', { fg = 'Blue', ctermfg = 'DarkBlue' })
+ hi('Constant', { fg = 'Magenta', ctermfg = 'DarkRed' })
+ hi('Special', { fg = '#6a5acd', ctermfg = 'DarkMagenta' })
+ hi('Identifier', { fg = 'DarkCyan', ctermfg = 'DarkCyan' })
+ hi('Statement', { fg = 'Brown', bold = true, ctermfg = 'Brown' })
+ hi('PreProc', { fg = '#6a0dad', ctermfg = 'DarkMagenta' })
+ hi('Type', { fg = 'SeaGreen', bold = true, ctermfg = 'DarkGreen' })
+ hi('Underlined', { fg = 'SlateBlue', underline = true, ctermfg = 'DarkMagenta', cterm = { underline = true } })
+ hi('Ignore', { ctermfg = 'White' })
else
-- Default colors only used with a dark background.
- hi('ColorColumn', { bg = 'DarkRed', ctermbg = 'DarkRed' })
- hi('CursorColumn', { bg = 'Grey40', ctermbg = 'DarkGrey' })
- hi('CursorLine', { bg = 'Grey40', cterm = { underline = true } })
- hi('CursorLineNr', { fg = 'Yellow', bold = true, ctermfg = 'Yellow', cterm = { underline = true } })
- hi('DiffAdd', { bg = 'DarkBlue', ctermbg = 'DarkBlue' })
- hi('DiffChange', { bg = 'DarkMagenta', ctermbg = 'DarkMagenta' })
- hi('DiffDelete', { fg = 'Blue', bg = 'DarkCyan', bold = true, ctermfg = 'Blue', ctermbg = 'DarkCyan' })
- hi('Directory', { fg = 'Cyan', ctermfg = 'LightCyan' })
- hi('FoldColumn', { fg = 'Cyan', bg = 'Grey', ctermfg = 'Cyan', ctermbg = 'DarkGrey' })
- hi('Folded', { fg = 'Cyan', bg = 'DarkGrey', ctermfg = 'Cyan', ctermbg = 'DarkGrey' })
- hi('LineNr', { fg = 'Yellow', ctermfg = 'Yellow' })
- hi('MatchParen', { bg = 'DarkCyan', ctermbg = 'DarkCyan' })
- hi('MoreMsg', { fg = 'SeaGreen', bold = true, ctermfg = 'LightGreen' })
- hi('Pmenu', { bg = 'Magenta', ctermfg = 'Black', ctermbg = 'Magenta' })
- hi('PmenuSel', { bg = 'DarkGrey', ctermfg = 'DarkGrey', ctermbg = 'Black' })
- hi('PmenuThumb', { bg = 'White', ctermbg = 'White' })
- hi('Question', { fg = 'Green', bold = true, ctermfg = 'LightGreen' })
- hi('Search', { fg = 'Black', bg = 'Yellow', ctermfg = 'Black', ctermbg = 'Yellow' })
- hi('SignColumn', { fg = 'Cyan', bg = 'Grey', ctermfg = 'Cyan', ctermbg = 'DarkGrey' })
- hi('SpecialKey', { fg = 'Cyan', ctermfg = 'LightBlue' })
- hi('SpellBad', { sp = 'Red', undercurl = true, ctermbg = 'Red' })
- hi('SpellCap', { sp = 'Blue', undercurl = true, ctermbg = 'Blue' })
- hi('SpellLocal', { sp = 'Cyan', undercurl = true, ctermbg = 'Cyan' })
- hi('SpellRare', { sp = 'Magenta', undercurl = true, ctermbg = 'Magenta' })
- hi('TabLine', { bg = 'DarkGrey', underline = true, ctermfg = 'White', ctermbg = 'DarkGrey', cterm = { underline = true } })
- hi('Title', { fg = 'Magenta', bold = true, ctermfg = 'LightMagenta' })
- hi('Visual', { fg = 'LightGrey', bg = '#575757', ctermfg = 'Black', ctermbg = 'Grey' })
- hi('WarningMsg', { fg = 'Red', ctermfg = 'LightRed' })
- hi('Comment', { fg = '#80a0ff', ctermfg = 'Cyan' })
- hi('Constant', { fg = '#ffa0a0', ctermfg = 'Magenta' })
- hi('Special', { fg = 'Orange', ctermfg = 'LightRed' })
- hi('Identifier', { fg = '#40ffff', ctermfg = 'Cyan', cterm = { bold = true } })
- hi('Statement', { fg = '#ffff60', bold = true, ctermfg = 'Yellow' })
- hi('PreProc', { fg = '#ff80ff', ctermfg = 'LightBlue' })
- hi('Type', { fg = '#60ff60', bold = true, ctermfg = 'LightGreen' })
- hi('Underlined', { fg = '#80a0ff', underline = true, ctermfg = 'LightBlue', cterm = { underline = true } })
- hi('Ignore', { ctermfg = 'Black' })
+ hi('ColorColumn', { bg = 'DarkRed', ctermbg = 'DarkRed' })
+ hi('CursorColumn', { bg = 'Grey40', ctermbg = 'DarkGrey' })
+ hi('CursorLine', { bg = 'Grey40', cterm = { underline = true } })
+ hi('CursorLineNr', { fg = 'Yellow', bold = true, ctermfg = 'Yellow', cterm = { underline = true } })
+ hi('DiffAdd', { bg = 'DarkBlue', ctermbg = 'DarkBlue' })
+ hi('DiffChange', { bg = 'DarkMagenta', ctermbg = 'DarkMagenta' })
+ hi('DiffDelete', { fg = 'Blue', bg = 'DarkCyan', bold = true, ctermfg = 'Blue', ctermbg = 'DarkCyan' })
+ hi('Directory', { fg = 'Cyan', ctermfg = 'LightCyan' })
+ hi('FoldColumn', { fg = 'Cyan', bg = 'Grey', ctermfg = 'Cyan', ctermbg = 'DarkGrey' })
+ hi('Folded', { fg = 'Cyan', bg = 'DarkGrey', ctermfg = 'Cyan', ctermbg = 'DarkGrey' })
+ hi('LineNr', { fg = 'Yellow', ctermfg = 'Yellow' })
+ hi('MatchParen', { bg = 'DarkCyan', ctermbg = 'DarkCyan' })
+ hi('MoreMsg', { fg = 'SeaGreen', bold = true, ctermfg = 'LightGreen' })
+ hi('Pmenu', { bg = 'Magenta', ctermfg = 'Black', ctermbg = 'Magenta' })
+ hi('PmenuSel', { bg = 'DarkGrey', ctermfg = 'DarkGrey', ctermbg = 'Black' })
+ hi('PmenuThumb', { bg = 'White', ctermbg = 'White' })
+ hi('Question', { fg = 'Green', bold = true, ctermfg = 'LightGreen' })
+ hi('Search', { fg = 'Black', bg = 'Yellow', ctermfg = 'Black', ctermbg = 'Yellow' })
+ hi('SignColumn', { fg = 'Cyan', bg = 'Grey', ctermfg = 'Cyan', ctermbg = 'DarkGrey' })
+ hi('SpecialKey', { fg = 'Cyan', ctermfg = 'LightBlue' })
+ hi('SpellBad', { sp = 'Red', undercurl = true, ctermbg = 'Red' })
+ hi('SpellCap', { sp = 'Blue', undercurl = true, ctermbg = 'Blue' })
+ hi('SpellLocal', { sp = 'Cyan', undercurl = true, ctermbg = 'Cyan' })
+ hi('SpellRare', { sp = 'Magenta', undercurl = true, ctermbg = 'Magenta' })
+ hi('StatusLineTerm', { fg = 'Black', bg = 'LightGreen', bold = true, ctermfg = 'Black', ctermbg = 'LightGreen', cterm = { bold = true } })
+ hi('StatusLineTermNC', { fg = 'Black', bg = 'LightGreen', ctermfg = 'Black', ctermbg = 'LightGreen' })
+ hi('TabLine', { bg = 'DarkGrey', underline = true, ctermfg = 'White', ctermbg = 'DarkGrey', cterm = { underline = true } })
+ hi('Title', { fg = 'Magenta', bold = true, ctermfg = 'LightMagenta' })
+ hi('Visual', { fg = 'LightGrey', bg = '#575757', ctermfg = 'Black', ctermbg = 'Grey' })
+ hi('WarningMsg', { fg = 'Red', ctermfg = 'LightRed' })
+ hi('Comment', { fg = '#80a0ff', ctermfg = 'Cyan' })
+ hi('Constant', { fg = '#ffa0a0', ctermfg = 'Magenta' })
+ hi('Special', { fg = 'Orange', ctermfg = 'LightRed' })
+ hi('Identifier', { fg = '#40ffff', ctermfg = 'Cyan', cterm = { bold = true } })
+ hi('Statement', { fg = '#ffff60', bold = true, ctermfg = 'Yellow' })
+ hi('PreProc', { fg = '#ff80ff', ctermfg = 'LightBlue' })
+ hi('Type', { fg = '#60ff60', bold = true, ctermfg = 'LightGreen' })
+ hi('Underlined', { fg = '#80a0ff', underline = true, ctermfg = 'LightBlue', cterm = { underline = true } })
+ hi('Ignore', { ctermfg = 'Black' })
end
--stylua: ignore end
diff --git a/runtime/compiler/javac.vim b/runtime/compiler/javac.vim
index f5fe84124f..9bd4cdf270 100644
--- a/runtime/compiler/javac.vim
+++ b/runtime/compiler/javac.vim
@@ -1,7 +1,7 @@
" Vim compiler file
" Compiler: Java Development Kit Compiler
" Maintainer: Doug Kearns <dougkearns@gmail.com>
-" Last Change: 2024 Apr 03
+" Last Change: 2024 Jun 14
if exists("current_compiler")
finish
@@ -11,7 +11,12 @@ let current_compiler = "javac"
let s:cpo_save = &cpo
set cpo&vim
-CompilerSet makeprg=javac
+if exists("g:javac_makeprg_params")
+ execute $'CompilerSet makeprg=javac\ {escape(g:javac_makeprg_params, ' \|"')}'
+else
+ CompilerSet makeprg=javac
+endif
+
CompilerSet errorformat=%E%f:%l:\ error:\ %m,
\%W%f:%l:\ warning:\ %m,
\%-Z%p^,
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index f92a69af4e..a7b59f20bc 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -2800,7 +2800,7 @@ nvim_set_decoration_provider({ns_id}, {opts})
Note: this function should not be called often. Rather, the callbacks
themselves can be used to throttle unneeded callbacks. the `on_start`
callback can return `false` to disable the provider until the next redraw.
- Similarly, return `false` in `on_win` will skip the `on_lines` calls for
+ Similarly, return `false` in `on_win` will skip the `on_line` calls for
that window (but any extmarks set in `on_win` will still be used). A
plugin managing multiple sources of decoration should ideally only set one
provider, and merge the sources internally. You can use multiple `ns_id`
@@ -2809,10 +2809,10 @@ nvim_set_decoration_provider({ns_id}, {opts})
Note: doing anything other than setting extmarks is considered
experimental. Doing things like changing options are not explicitly
forbidden, but is likely to have unexpected consequences (such as 100% CPU
- consumption). doing `vim.rpcnotify` should be OK, but `vim.rpcrequest` is
+ consumption). Doing `vim.rpcnotify` should be OK, but `vim.rpcrequest` is
quite dubious for the moment.
- Note: It is not allowed to remove or update extmarks in 'on_line'
+ Note: It is not allowed to remove or update extmarks in `on_line`
callbacks.
Attributes: ~
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index 1a762c6ec0..1e0df1918b 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -701,33 +701,33 @@ clearmatches([{win}]) *clearmatches()*
col({expr} [, {winid}]) *col()*
The result is a Number, which is the byte index of the column
- position given with {expr}. The accepted positions are:
- . the cursor position
- $ the end of the cursor line (the result is the
- number of bytes in the cursor line plus one)
- 'x position of mark x (if the mark is not set, 0 is
- returned)
- v In Visual mode: the start of the Visual area (the
- cursor is the end). When not in Visual mode
- returns the cursor position. Differs from |'<| in
- that it's updated right away.
+ position given with {expr}.
+ For accepted positions see |getpos()|.
+ When {expr} is "$", it means the end of the cursor line, so
+ the result is the number of bytes in the cursor line plus one.
Additionally {expr} can be [lnum, col]: a |List| with the line
and column number. Most useful when the column is "$", to get
the last column of a specific line. When "lnum" or "col" is
out of range then col() returns zero.
+
With the optional {winid} argument the values are obtained for
that window instead of the current window.
+
To get the line number use |line()|. To get both use
|getpos()|.
+
For the screen column position use |virtcol()|. For the
character position use |charcol()|.
+
Note that only marks in the current file can be used.
+
Examples: >vim
echo col(".") " column of cursor
echo col("$") " length of cursor line plus one
echo col("'t") " column of mark t
echo col("'" .. markname) " column of mark markname
-< The first column is 1. Returns 0 if {expr} is invalid or when
+<
+ The first column is 1. Returns 0 if {expr} is invalid or when
the window with ID {winid} is not found.
For an uppercase mark the column may actually be in another
buffer.
@@ -2739,9 +2739,34 @@ getpid() *getpid()*
This is a unique number, until Vim exits.
getpos({expr}) *getpos()*
- Get the position for String {expr}. For possible values of
- {expr} see |line()|. For getting the cursor position see
- |getcurpos()|.
+ Get the position for String {expr}.
+ The accepted values for {expr} are:
+ . The cursor position.
+ $ The last line in the current buffer.
+ 'x Position of mark x (if the mark is not set, 0 is
+ returned for all values).
+ w0 First line visible in current window (one if the
+ display isn't updated, e.g. in silent Ex mode).
+ w$ Last line visible in current window (this is one
+ less than "w0" if no lines are visible).
+ v When not in Visual mode, returns the cursor
+ position. In Visual mode, returns the other end
+ of the Visual area. A good way to think about
+ this is that in Visual mode "v" and "." complement
+ each other. While "." refers to the cursor
+ position, "v" refers to where |v_o| would move the
+ cursor. As a result, you can use "v" and "."
+ together to work on all of a selection in
+ characterwise Visual mode. If the cursor is at
+ the end of a characterwise Visual area, "v" refers
+ to the start of the same Visual area. And if the
+ cursor is at the start of a characterwise Visual
+ area, "v" refers to the end of the same Visual
+ area. "v" differs from |'<| and |'>| in that it's
+ updated right away.
+ Note that a mark in another file can be used. The line number
+ then applies to another buffer.
+
The result is a |List| with four numbers:
[bufnum, lnum, col, off]
"bufnum" is zero, unless a mark like '0 or 'A is used, then it
@@ -2752,20 +2777,25 @@ getpos({expr}) *getpos()*
it is the offset in screen columns from the start of the
character. E.g., a position within a <Tab> or after the last
character.
- Note that for '< and '> Visual mode matters: when it is "V"
- (visual line mode) the column of '< is zero and the column of
- '> is a large number equal to |v:maxcol|.
+
+ For getting the cursor position see |getcurpos()|.
The column number in the returned List is the byte position
within the line. To get the character position in the line,
use |getcharpos()|.
+
+ Note that for '< and '> Visual mode matters: when it is "V"
+ (visual line mode) the column of '< is zero and the column of
+ '> is a large number equal to |v:maxcol|.
A very large column number equal to |v:maxcol| can be returned,
in which case it means "after the end of the line".
If {expr} is invalid, returns a list with all zeros.
+
This can be used to save and restore the position of a mark: >vim
let save_a_mark = getpos("'a")
" ...
call setpos("'a", save_a_mark)
-< Also see |getcharpos()|, |getcurpos()| and |setpos()|.
+<
+ Also see |getcharpos()|, |getcurpos()| and |setpos()|.
getqflist([{what}]) *getqflist()*
Returns a |List| with all the current quickfix errors. Each
@@ -2963,8 +2993,8 @@ getregion({pos1}, {pos2} [, {opts}]) *getregion()*
difference if the buffer is displayed in a window with
different 'virtualedit' or 'list' values.
- Examples: >
- :xnoremap <CR>
+ Examples: >vim
+ xnoremap <CR>
\ <Cmd>echom getregion(
\ getpos('v'), getpos('.'), #{ type: mode() })<CR>
<
@@ -4091,28 +4121,16 @@ libcallnr({libname}, {funcname}, {argument}) *libcallnr()*
<
line({expr} [, {winid}]) *line()*
- The result is a Number, which is the line number of the file
- position given with {expr}. The {expr} argument is a string.
- The accepted positions are:
- . the cursor position
- $ the last line in the current buffer
- 'x position of mark x (if the mark is not set, 0 is
- returned)
- w0 first line visible in current window (one if the
- display isn't updated, e.g. in silent Ex mode)
- w$ last line visible in current window (this is one
- less than "w0" if no lines are visible)
- v In Visual mode: the start of the Visual area (the
- cursor is the end). When not in Visual mode
- returns the cursor position. Differs from |'<| in
- that it's updated right away.
- Note that a mark in another file can be used. The line number
- then applies to another buffer.
+ See |getpos()| for accepted positions.
+
To get the column number use |col()|. To get both use
|getpos()|.
+
With the optional {winid} argument the values are obtained for
that window instead of the current window.
+
Returns 0 for invalid values of {expr} and {winid}.
+
Examples: >vim
echo line(".") " line number of the cursor
echo line(".", winid) " idem, in window "winid"
@@ -4629,19 +4647,19 @@ matchbufline({buf}, {pat}, {lnum}, {end}, [, {dict}]) *matchbufline()*
Examples: >vim
" Assuming line 3 in buffer 5 contains "a"
- :echo matchbufline(5, '\<\k\+\>', 3, 3)
- [{'lnum': 3, 'byteidx': 0, 'text': 'a'}]
+ echo matchbufline(5, '\<\k\+\>', 3, 3)
+< `[{'lnum': 3, 'byteidx': 0, 'text': 'a'}]` >vim
" Assuming line 4 in buffer 10 contains "tik tok"
- :echo matchbufline(10, '\<\k\+\>', 1, 4)
- [{'lnum': 4, 'byteidx': 0, 'text': 'tik'}, {'lnum': 4, 'byteidx': 4, 'text': 'tok'}]
-<
+ echo matchbufline(10, '\<\k\+\>', 1, 4)
+< `[{'lnum': 4, 'byteidx': 0, 'text': 'tik'}, {'lnum': 4, 'byteidx': 4, 'text': 'tok'}]`
+
If {submatch} is present and is v:true, then submatches like
"\1", "\2", etc. are also returned. Example: >vim
" Assuming line 2 in buffer 2 contains "acd"
- :echo matchbufline(2, '\(a\)\?\(b\)\?\(c\)\?\(.*\)', 2, 2
+ echo matchbufline(2, '\(a\)\?\(b\)\?\(c\)\?\(.*\)', 2, 2
\ {'submatches': v:true})
- [{'lnum': 2, 'byteidx': 0, 'text': 'acd', 'submatches': ['a', '', 'c', 'd', '', '', '', '', '']}]
-< The "submatches" List always contains 9 items. If a submatch
+< `[{'lnum': 2, 'byteidx': 0, 'text': 'acd', 'submatches': ['a', '', 'c', 'd', '', '', '', '', '']}]`
+ The "submatches" List always contains 9 items. If a submatch
is not found, then an empty string is returned for that
submatch.
@@ -4801,17 +4819,17 @@ matchstrlist({list}, {pat} [, {dict}]) *matchstrlist()*
option settings on the pattern.
Example: >vim
- :echo matchstrlist(['tik tok'], '\<\k\+\>')
- [{'idx': 0, 'byteidx': 0, 'text': 'tik'}, {'idx': 0, 'byteidx': 4, 'text': 'tok'}]
- :echo matchstrlist(['a', 'b'], '\<\k\+\>')
- [{'idx': 0, 'byteidx': 0, 'text': 'a'}, {'idx': 1, 'byteidx': 0, 'text': 'b'}]
-<
+ echo matchstrlist(['tik tok'], '\<\k\+\>')
+< `[{'idx': 0, 'byteidx': 0, 'text': 'tik'}, {'idx': 0, 'byteidx': 4, 'text': 'tok'}]` >vim
+ echo matchstrlist(['a', 'b'], '\<\k\+\>')
+< `[{'idx': 0, 'byteidx': 0, 'text': 'a'}, {'idx': 1, 'byteidx': 0, 'text': 'b'}]`
+
If "submatches" is present and is v:true, then submatches like
"\1", "\2", etc. are also returned. Example: >vim
- :echo matchstrlist(['acd'], '\(a\)\?\(b\)\?\(c\)\?\(.*\)',
+ echo matchstrlist(['acd'], '\(a\)\?\(b\)\?\(c\)\?\(.*\)',
\ #{submatches: v:true})
- [{'idx': 0, 'byteidx': 0, 'text': 'acd', 'submatches': ['a', '', 'c', 'd', '', '', '', '', '']}]
-< The "submatches" List always contains 9 items. If a submatch
+< `[{'idx': 0, 'byteidx': 0, 'text': 'acd', 'submatches': ['a', '', 'c', 'd', '', '', '', '', '']}]`
+ The "submatches" List always contains 9 items. If a submatch
is not found, then an empty string is returned for that
submatch.
@@ -4976,17 +4994,14 @@ mkdir({name} [, {flags} [, {prot}]]) *mkdir()* *E73
When {flags} is present it must be a string. An empty string
has no effect.
- If {flags} contains "p" then intermediate directories are
- created as necessary.
+ {flags} can contain these character flags:
+ "p" intermediate directories will be created as necessary
+ "D" {name} will be deleted at the end of the current
+ function, but not recursively |:defer|
+ "R" {name} will be deleted recursively at the end of the
+ current function |:defer|
- If {flags} contains "D" then {name} is deleted at the end of
- the current function, as with: >vim
- defer delete({name}, 'd')
-<
- If {flags} contains "R" then {name} is deleted recursively at
- the end of the current function, as with: >vim
- defer delete({name}, 'rf')
-< Note that when {name} has more than one part and "p" is used
+ Note that when {name} has more than one part and "p" is used
some directories may already exist. Only the first one that
is created and what it contains is scheduled to be deleted.
E.g. when using: >vim
@@ -6039,7 +6054,7 @@ screencol() *screencol()*
the following mappings: >vim
nnoremap <expr> GG ":echom " .. screencol() .. "\n"
nnoremap <silent> GG :echom screencol()<CR>
- noremap GG <Cmd>echom screencol()<Cr>
+ noremap GG <Cmd>echom screencol()<CR>
<
screenpos({winid}, {lnum}, {col}) *screenpos()*
@@ -8735,7 +8750,9 @@ virtcol({expr} [, {list} [, {winid}]]) *virtcol()*
set to 8, it returns 8. |conceal| is ignored.
For the byte position use |col()|.
- For the use of {expr} see |col()|.
+ For the use of {expr} see |getpos()| and |col()|.
+ When {expr} is "$", it means the end of the cursor line, so
+ the result is the number of cells in the cursor line plus one.
When 'virtualedit' is used {expr} can be [lnum, col, off],
where "off" is the offset in screen columns from the start of
@@ -8745,18 +8762,6 @@ virtcol({expr} [, {list} [, {winid}]]) *virtcol()*
beyond the end of the line can be returned. Also see
|'virtualedit'|
- The accepted positions are:
- . the cursor position
- $ the end of the cursor line (the result is the
- number of displayed characters in the cursor line
- plus one)
- 'x position of mark x (if the mark is not set, 0 is
- returned)
- v In Visual mode: the start of the Visual area (the
- cursor is the end). When not in Visual mode
- returns the cursor position. Differs from |'<| in
- that it's updated right away.
-
If {list} is present and non-zero then virtcol() returns a
List with the first and last screen position occupied by the
character.
@@ -8775,7 +8780,9 @@ virtcol({expr} [, {list} [, {winid}]]) *virtcol()*
" With text " there", with 't at 'h':
echo virtcol("'t") " returns 6
-< The first column is 1. 0 or [0, 0] is returned for an error.
+<
+ The first column is 1. 0 or [0, 0] is returned for an error.
+
A more advanced example that echoes the maximum length of
all lines: >vim
echo max(map(range(1, line('$')), "virtcol([v:val, '$'])"))
diff --git a/runtime/doc/diagnostic.txt b/runtime/doc/diagnostic.txt
index 68dc9d6549..05af2eddc3 100644
--- a/runtime/doc/diagnostic.txt
+++ b/runtime/doc/diagnostic.txt
@@ -363,7 +363,6 @@ Lua module: vim.diagnostic *diagnostic-api*
• {message} (`string`) The diagnostic text
• {source}? (`string`) The source of the diagnostic
• {code}? (`string|integer`) The diagnostic code
- • {_tags}? (`{ deprecated: boolean, unnecessary: boolean}`)
• {user_data}? (`any`) arbitrary data plugins can add
• {namespace}? (`integer`)
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt
index ca9dfd0350..7b5eee0a14 100644
--- a/runtime/doc/lsp.txt
+++ b/runtime/doc/lsp.txt
@@ -1679,7 +1679,7 @@ is_enabled({filter}) *vim.lsp.inlay_hint.is_enabled()*
Query whether inlay hint is enabled in the {filter}ed scope
Parameters: ~
- • {filter} (`table`) Optional filters |kwargs|, or `nil` for all.
+ • {filter} (`table?`) Optional filters |kwargs|, or `nil` for all.
• {bufnr} (`integer?`) Buffer number, or 0 for current
buffer, or nil for all.
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index e2fcac1bda..3bfd1d1885 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -981,6 +981,9 @@ vim.str_byteindex({str}, {index}, {use_utf16}) *vim.str_byteindex()*
• {index} (`integer`)
• {use_utf16} (`boolean?`)
+ Return: ~
+ (`integer`)
+
vim.str_utf_end({str}, {index}) *vim.str_utf_end()*
Gets the distance (in bytes) from the last byte of the codepoint
(character) that {index} points to.
@@ -4079,10 +4082,10 @@ Iter:map({f}) *Iter:map()*
<
Parameters: ~
- • {f} (`fun(...):any`) Mapping function. Takes all values returned from
- the previous stage in the pipeline as arguments and returns one
- or more new values, which are used in the next pipeline stage.
- Nil return values are filtered from the output.
+ • {f} (`fun(...):...:any`) Mapping function. Takes all values returned
+ from the previous stage in the pipeline as arguments and returns
+ one or more new values, which are used in the next pipeline
+ stage. Nil return values are filtered from the output.
Return: ~
(`Iter`)
@@ -4385,8 +4388,9 @@ vim.text.hexdecode({enc}) *vim.text.hexdecode()*
Parameters: ~
• {enc} (`string`) String to decode
- Return: ~
- (`string`) Decoded string
+ Return (multiple): ~
+ (`string?`) Decoded string
+ (`string?`) Error message, if any
vim.text.hexencode({str}) *vim.text.hexencode()*
Hex encode a string.
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index 2ff6b0302c..848a642774 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -62,7 +62,10 @@ LUA
OPTIONS
-• TODO
+• The 'statuscolumn' `%l` item can now be used as a number column segment that
+ changes according to related options. It takes care of alignment, 'number',
+ 'relativenumber' and 'signcolumn' set to "number". The now redundant `%r` item
+ is no longer treated specially for 'statuscolumn'.
PLUGINS
@@ -138,7 +141,10 @@ STARTUP
TERMINAL
-• TODO
+• The |terminal| now understands the OSC 52 escape sequence to write to the
+ system clipboard (copy). Querying with OSC 52 (paste) is not supported.
+• |hl-StatusLineTerm| and |hl-StatusLineTermNC| define highlights for the
+ status line in |terminal| windows.
TREESITTER
diff --git a/runtime/doc/nvim_terminal_emulator.txt b/runtime/doc/nvim_terminal_emulator.txt
index a6ebc7e958..81bcd89146 100644
--- a/runtime/doc/nvim_terminal_emulator.txt
+++ b/runtime/doc/nvim_terminal_emulator.txt
@@ -164,7 +164,22 @@ directory indicated in the request. >lua
To try it out, select the above code and source it with `:'<,'>lua`, then run
this command in a :terminal buffer: >
- printf "\033]7;file://./foo/bar\033\\"
+ printf "\033]7;file://./foo/bar\033\\"
+
+OSC 52: write to system clipboard *terminal-osc52*
+
+Applications in the :terminal buffer can write to the system clipboard by
+emitting an OSC 52 sequence. Example: >
+
+ printf '\033]52;;%s\033\\' "$(echo -n 'Hello world' | base64)"
+
+Nvim uses the configured |clipboard| provider to write to the system
+clipboard. Reading from the system clipboard with OSC 52 is not supported, as
+this would allow any arbitrary program in the :terminal to read the user's
+clipboard.
+
+OSC 52 sequences sent from the :terminal buffer do not emit a |TermRequest|
+event. The event is handled directly by Nvim and is not forwarded to plugins.
==============================================================================
Status Variables *terminal-status*
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index f02d3c9741..1b71050620 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -3842,6 +3842,9 @@ A jump table for the options with a short description can be found at |Q_op|.
between tabs and spaces and for trailing blanks. Further changed by
the 'listchars' option.
+ When 'listchars' does not contain "tab" field, tabs are shown as "^I"
+ or "<09>", like how unprintable characters are displayed.
+
The cursor is displayed at the start of the space a Tab character
occupies, not at the end as usual in Normal mode. To get this cursor
position while displaying Tabs with spaces, use: >vim
@@ -5951,8 +5954,7 @@ A jump table for the options with a short description can be found at |Q_op|.
Some of the items from the 'statusline' format are different for
'statuscolumn':
- %l line number of currently drawn line
- %r relative line number of currently drawn line
+ %l line number column for currently drawn line
%s sign column for currently drawn line
%C fold column for currently drawn line
@@ -5979,11 +5981,8 @@ A jump table for the options with a short description can be found at |Q_op|.
handler should be written with this in mind.
Examples: >vim
- " Relative number with bar separator and click handlers:
- set statuscolumn=%@SignCb@%s%=%T%@NumCb@%r│%T
-
- " Right aligned relative cursor line number:
- let &stc='%=%{v:relnum?v:relnum:v:lnum} '
+ " Line number with bar separator and click handlers:
+ set statuscolumn=%@SignCb@%s%=%T%@NumCb@%l│%T
" Line numbers in hexadecimal for non wrapped part of lines:
let &stc='%=%{v:virtnum>0?"":printf("%x",v:lnum)} '
diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt
index 897e503fc4..9ac7492b9b 100644
--- a/runtime/doc/quickfix.txt
+++ b/runtime/doc/quickfix.txt
@@ -1288,6 +1288,13 @@ g:compiler_gcc_ignore_unmatched_lines
commands run from make are generating false
positives.
+JAVAC *compiler-javac*
+
+Commonly used compiler options can be added to 'makeprg' by setting the
+g:javac_makeprg_params variable. For example: >
+ let g:javac_makeprg_params = "-Xlint:all -encoding utf-8"
+<
+
PANDOC *quickfix-pandoc* *compiler-pandoc*
The Pandoc compiler plugin expects that an output file type extension is
diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt
index 61028c791d..4a1588a910 100644
--- a/runtime/doc/syntax.txt
+++ b/runtime/doc/syntax.txt
@@ -468,10 +468,10 @@ Configuration
The following variables control certain syntax highlighting features.
You can add them to your .vimrc.
-To enables TypeScript and TSX for ".astro" files (default "disable"): >
+To enable TypeScript and TSX for ".astro" files (default "disable"): >
let g:astro_typescript = "enable"
<
-To enables Stylus for ".astro" files (default "disable"): >
+To enable Stylus for ".astro" files (default "disable"): >
let g:astro_stylus = "enable"
<
NOTE: You need to install an external plugin to support stylus in astro files.
@@ -3327,28 +3327,31 @@ The g:vimsyn_embed option allows users to select what, if any, types of
embedded script highlighting they wish to have. >
g:vimsyn_embed == 0 : disable (don't embed any scripts)
- g:vimsyn_embed == 'lpPr' : support embedded lua, perl, python and ruby
+ g:vimsyn_embed == 'lpPr' : support embedded Lua, Perl, Python and Ruby
<
This option is disabled by default.
*g:vimsyn_folding*
-
Some folding is now supported with when 'foldmethod' is set to "syntax": >
g:vimsyn_folding == 0 or doesn't exist: no syntax-based folding
g:vimsyn_folding =~ 'a' : augroups
g:vimsyn_folding =~ 'f' : fold functions
g:vimsyn_folding =~ 'h' : fold heredocs
- g:vimsyn_folding =~ 'l' : fold lua script
- g:vimsyn_folding =~ 'p' : fold perl script
- g:vimsyn_folding =~ 'P' : fold python script
- g:vimsyn_folding =~ 'r' : fold ruby script
+ g:vimsyn_folding =~ 'l' : fold Lua script
+ g:vimsyn_folding =~ 'p' : fold Perl script
+ g:vimsyn_folding =~ 'P' : fold Python script
+ g:vimsyn_folding =~ 'r' : fold Ruby script
<
By default, g:vimsyn_folding is unset. Concatenate the indicated characters
-to support folding of multiple syntax constructs; i.e.
-g:vimsyn_folding = "fh" will enable folding of both functions and heredocs.
+to support folding of multiple syntax constructs (e.g.,
+g:vimsyn_folding = "fh" will enable folding of both functions and heredocs).
+
+ *g:vimsyn_comment_strings*
+By default, strings are highlighted inside comments. This may be disabled by
+setting g:vimsyn_comment_strings to false.
- *g:vimsyn_noerror*
+ *g:vimsyn_noerror*
Not all error highlighting that syntax/vim.vim does may be correct; Vim script
is a difficult language to highlight correctly. A way to suppress error
highlighting is to put the following line in your |vimrc|: >
@@ -5011,7 +5014,6 @@ IncSearch 'incsearch' highlighting; also used for the text replaced with
":s///c".
*hl-Substitute*
Substitute |:substitute| replacement text highlighting.
-
*hl-LineNr*
LineNr Line number for ":number" and ":#" commands, and when 'number'
or 'relativenumber' option is set.
@@ -5031,7 +5033,6 @@ CursorLineSign Like SignColumn when 'cursorline' is set for the cursor line.
*hl-MatchParen*
MatchParen Character under the cursor or just before it, if it
is a paired bracket, and its match. |pi_paren.txt|
-
*hl-ModeMsg*
ModeMsg 'showmode' message (e.g., "-- INSERT --").
*hl-MsgArea*
@@ -5073,11 +5074,15 @@ PmenuExtraSel Popup menu: Selected item "extra text".
PmenuSbar Popup menu: Scrollbar.
*hl-PmenuThumb*
PmenuThumb Popup menu: Thumb of the scrollbar.
+ *hl-PmenuMatch*
+PmenuMatch Popup menu: Matched text in normal item
+ *hl-PmenuMatchSel*
+PmenuMatchSel Popup menu: Matched text in selected item
*hl-Question*
Question |hit-enter| prompt and yes/no questions.
*hl-QuickFixLine*
QuickFixLine Current |quickfix| item in the quickfix window. Combined with
- |hl-CursorLine| when the cursor is there.
+ |hl-CursorLine| when the cursor is there.
*hl-Search*
Search Last search pattern highlighting (see 'hlsearch').
Also used for similar items that need to stand out.
@@ -5104,6 +5109,11 @@ SpellRare Word that is recognized by the spellchecker as one that is
StatusLine Status line of current window.
*hl-StatusLineNC*
StatusLineNC Status lines of not-current windows.
+ *hl-StatusLineTerm*
+StatusLineTerm Status line of |terminal| window.
+ *hl-StatusLineTermNC*
+StatusLineTermNC
+ Status line of non-current |terminal| windows.
*hl-TabLine*
TabLine Tab pages line, not active tab page label.
*hl-TabLineFill*
diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt
index 25b070b310..ed514cb722 100644
--- a/runtime/doc/treesitter.txt
+++ b/runtime/doc/treesitter.txt
@@ -22,9 +22,11 @@ search for in the `parser` runtime directory.
Nvim includes these parsers:
+- Bash
- C
- Lua
- Markdown
+- Python
- Vimscript
- Vimdoc
- Treesitter query files |ft-query-plugin|
diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt
index 0287271d4c..63fca2c1aa 100644
--- a/runtime/doc/various.txt
+++ b/runtime/doc/various.txt
@@ -140,7 +140,7 @@ gx Opens the current filepath or URL (decided by
:[range]# [count] [flags]
synonym for :number.
- *:#!*
+ *:#!* *vim-shebang*
:#!{anything} Ignored, so that you can start a Vim script with: >
#!vim -S
echo "this is a Vim script"
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index ac20948f14..a6f08402f6 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -166,6 +166,14 @@ nvim_terminal:
when 'background' is "light". While this may not reflect the actual
foreground/background color, it permits 'background' to be retained for a
nested Nvim instance running in the terminal emulator.
+- TermOpen: Sets default options for |terminal| buffers:
+ - 'nomodifiable'
+ - 'undolevels' set to -1
+ - 'textwidth' set to 0
+ - 'nowrap'
+ - 'nolist'
+ - 'winhighlight' uses |hl-StatusLineTerm| and |hl-StatusLineTermNC| in
+ place of |hl-StatusLine| and |hl-StatusLineNC|
nvim_cmdwin:
- CmdwinEnter: Limits syntax sync to maxlines=1 in the |cmdwin|.
@@ -538,6 +546,8 @@ Highlight groups:
- Highlight groups names are allowed to contain `@` characters.
- It is an error to define a highlight group with a name that doesn't match
the regexp `[a-zA-Z0-9_.@-]*` (see |group-name|).
+- |hl-StatusLineTerm| |hl-StatusLineTermNC| are implemented as 'winhighlight'
+ window-local highlights which are set by the default |TermOpen| handler.
Macro (|recording|) behavior:
- Replay of a macro recorded during :lmap produces the same actions as when it
@@ -665,17 +675,6 @@ Events:
- *SafeStateAgain*
- *SigUSR1* Use |Signal| to detect `SIGUSR1` signal instead.
-Highlight groups:
-- *hl-StatusLineTerm* *hl-StatusLineTermNC* are unnecessary because Nvim
- supports 'winhighlight' window-local highlights. For example, to mimic Vim's
- StatusLineTerm: >vim
- hi StatusLineTerm ctermfg=black ctermbg=green
- hi StatusLineTermNC ctermfg=green
- autocmd TermOpen,WinEnter * if &buftype=='terminal'
- \|setlocal winhighlight=StatusLine:StatusLineTerm,StatusLineNC:StatusLineTermNC
- \|else|setlocal winhighlight=|endif
-<
-
Options:
- *'aleph'* *'al'*
- antialias
diff --git a/runtime/ftplugin/kdl.vim b/runtime/ftplugin/kdl.vim
new file mode 100644
index 0000000000..c9a1d8b185
--- /dev/null
+++ b/runtime/ftplugin/kdl.vim
@@ -0,0 +1,17 @@
+" Vim filetype plugin
+" Language: KDL
+" Author: Aram Drevekenin <aram@poor.dev>
+" Maintainer: Yinzuo Jiang <jiangyinzuo@foxmail.com>
+" Last Change: 2024-06-10
+
+if exists("b:did_ftplugin")
+ finish
+endif
+
+let b:did_ftplugin = 1
+
+setlocal comments=://
+setlocal commentstring=//\ %s
+setlocal formatoptions-=t
+
+let b:undo_ftplugin = 'setlocal comments< commentstring< formatoptions<'
diff --git a/runtime/ftplugin/snakemake.vim b/runtime/ftplugin/snakemake.vim
new file mode 100644
index 0000000000..ab90ca10b5
--- /dev/null
+++ b/runtime/ftplugin/snakemake.vim
@@ -0,0 +1,13 @@
+" Vim filetype plugin
+" Language: snakemake
+" Maintainer: Riley Bruins <ribru17@gmail.com>
+" Last Change: 2024 Jun 13
+
+if exists('b:did_ftplugin')
+ finish
+endif
+let b:did_ftplugin = 1
+
+setl comments=:# commentstring=#\ %s
+
+let b:undo_ftplugin = 'setl com< cms<'
diff --git a/runtime/ftplugin/svelte.vim b/runtime/ftplugin/svelte.vim
new file mode 100644
index 0000000000..e0ec4e0ae3
--- /dev/null
+++ b/runtime/ftplugin/svelte.vim
@@ -0,0 +1,13 @@
+" Vim filetype plugin
+" Language: svelte
+" Maintainer: Igor Lacerda <igorlafarsi@gmail.com>
+" Last Change: 2024 Jun 09
+
+if exists('b:did_ftplugin')
+ finish
+endif
+let b:did_ftplugin = 1
+
+setl commentstring=<!--\ %s\ -->
+
+let b:undo_ftplugin = 'setl cms<'
diff --git a/runtime/indent/kdl.vim b/runtime/indent/kdl.vim
new file mode 100644
index 0000000000..b0a6bd90d9
--- /dev/null
+++ b/runtime/indent/kdl.vim
@@ -0,0 +1,30 @@
+" Vim indent file
+" Language: KDL
+" Author: Aram Drevekenin <aram@poor.dev>
+" Maintainer: Yinzuo Jiang <jiangyinzuo@foxmail.com>
+" Last Change: 2024-06-16
+
+" Only load this indent file when no other was loaded.
+if exists("b:did_indent")
+ finish
+endif
+let b:did_indent = 1
+
+setlocal indentexpr=KdlIndent()
+let b:undo_indent = "setlocal indentexpr<"
+
+function! KdlIndent(...)
+ let line = substitute(getline(v:lnum), '//.*$', '', '')
+ let previousNum = prevnonblank(v:lnum - 1)
+ let previous = substitute(getline(previousNum), '//.*$', '', '')
+
+ let l:indent = indent(previousNum)
+ if previous =~ "{" && previous !~ "}"
+ let l:indent += shiftwidth()
+ endif
+ if line =~ "}" && line !~ "{"
+ let l:indent -= shiftwidth()
+ endif
+ return l:indent
+endfunction
+" vim: sw=2 sts=2 et
diff --git a/runtime/keymap/georgian-qwerty.vim b/runtime/keymap/georgian-qwerty.vim
new file mode 100644
index 0000000000..df18729f06
--- /dev/null
+++ b/runtime/keymap/georgian-qwerty.vim
@@ -0,0 +1,51 @@
+" Vim keymap file for Georgian (Mkhedruli) layout
+" Maintainer: Mishiko Okropiridze <misho.okropiridze@gmail.com>
+" Last changed: 2024-06-14
+
+
+let b:keymap_name = "ge"
+
+loadkeymap
+a ა
+A ა
+b ბ
+c ც
+C ჩ
+d დ
+e ე
+E ე
+f ფ
+F ფ
+g გ
+G გ
+h ჰ
+H ჵ
+i ი
+I ი
+j ჯ
+J ჟ
+k კ
+l ლ
+m მ
+n ნ
+o ო
+p პ
+q ქ
+Q ქ
+r რ
+R ღ
+s ს
+S შ
+t ტ
+T თ
+u უ
+v ვ
+V ვ
+w წ
+W ჭ
+x ხ
+X ხ
+y ყ
+Y ყ
+z ზ
+Z ძ
diff --git a/runtime/lua/vim/_defaults.lua b/runtime/lua/vim/_defaults.lua
index 01dcd4bf74..630f2219c7 100644
--- a/runtime/lua/vim/_defaults.lua
+++ b/runtime/lua/vim/_defaults.lua
@@ -85,13 +85,13 @@ do
vim.keymap.set(
'x',
'Q',
- "mode() == 'V' ? ':normal! @<C-R>=reg_recorded()<CR><CR>' : 'Q'",
+ "mode() ==# 'V' ? ':normal! @<C-R>=reg_recorded()<CR><CR>' : 'Q'",
{ silent = true, expr = true, desc = ':help v_Q-default' }
)
vim.keymap.set(
'x',
'@',
- "mode() == 'V' ? ':normal! @'.getcharstr().'<CR>' : '@'",
+ "mode() ==# 'V' ? ':normal! @'.getcharstr().'<CR>' : '@'",
{ silent = true, expr = true, desc = ':help v_@-default' }
)
@@ -282,6 +282,26 @@ do
end,
})
+ vim.api.nvim_create_autocmd('TermOpen', {
+ group = nvim_terminal_augroup,
+ desc = 'Default settings for :terminal buffers',
+ callback = function()
+ vim.bo.modifiable = false
+ vim.bo.undolevels = -1
+ vim.bo.scrollback = vim.o.scrollback < 0 and 10000 or math.max(1, vim.o.scrollback)
+ vim.bo.textwidth = 0
+ vim.wo[0][0].wrap = false
+ vim.wo[0][0].list = false
+
+ -- This is gross. Proper list options support when?
+ local winhl = vim.o.winhighlight
+ if winhl ~= '' then
+ winhl = winhl .. ','
+ end
+ vim.wo[0][0].winhighlight = winhl .. 'StatusLine:StatusLineTerm,StatusLineNC:StatusLineTermNC'
+ end,
+ })
+
vim.api.nvim_create_autocmd('CmdwinEnter', {
pattern = '[:>]',
desc = 'Limit syntax sync to maxlines=1 in the command window',
diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua
index d91b2d08bf..1b70cc275f 100644
--- a/runtime/lua/vim/_meta/api.lua
+++ b/runtime/lua/vim/_meta/api.lua
@@ -1910,7 +1910,7 @@ function vim.api.nvim_set_current_win(window) end
--- Note: this function should not be called often. Rather, the callbacks
--- themselves can be used to throttle unneeded callbacks. the `on_start`
--- callback can return `false` to disable the provider until the next redraw.
---- Similarly, return `false` in `on_win` will skip the `on_lines` calls for
+--- Similarly, return `false` in `on_win` will skip the `on_line` calls for
--- that window (but any extmarks set in `on_win` will still be used). A
--- plugin managing multiple sources of decoration should ideally only set one
--- provider, and merge the sources internally. You can use multiple `ns_id`
@@ -1919,10 +1919,10 @@ function vim.api.nvim_set_current_win(window) end
--- Note: doing anything other than setting extmarks is considered
--- experimental. Doing things like changing options are not explicitly
--- forbidden, but is likely to have unexpected consequences (such as 100% CPU
---- consumption). doing `vim.rpcnotify` should be OK, but `vim.rpcrequest` is
+--- consumption). Doing `vim.rpcnotify` should be OK, but `vim.rpcrequest` is
--- quite dubious for the moment.
---
---- Note: It is not allowed to remove or update extmarks in 'on_line'
+--- Note: It is not allowed to remove or update extmarks in `on_line`
--- callbacks.
---
--- @param ns_id integer Namespace id from `nvim_create_namespace()`
diff --git a/runtime/lua/vim/_meta/builtin.lua b/runtime/lua/vim/_meta/builtin.lua
index 75737bd040..3aca3cdfa5 100644
--- a/runtime/lua/vim/_meta/builtin.lua
+++ b/runtime/lua/vim/_meta/builtin.lua
@@ -121,6 +121,7 @@ function vim.stricmp(a, b) end
--- @param str string
--- @param index integer
--- @param use_utf16? boolean
+--- @return integer
function vim.str_byteindex(str, index, use_utf16) end
--- Gets a list of the starting byte positions of each UTF-8 codepoint in the given string.
diff --git a/runtime/lua/vim/_meta/builtin_types.lua b/runtime/lua/vim/_meta/builtin_types.lua
index 53dd8d95e9..9afb8c84f4 100644
--- a/runtime/lua/vim/_meta/builtin_types.lua
+++ b/runtime/lua/vim/_meta/builtin_types.lua
@@ -34,6 +34,11 @@
--- @field filename? string
--- @field lnum integer
+--- @class vim.fn.getmarklist.ret.item
+--- @field mark string
+--- @field pos [integer, integer, integer, integer]
+--- @field file string
+
--- @class vim.fn.getmousepos.ret
--- @field screenrow integer
--- @field screencol integer
diff --git a/runtime/lua/vim/_meta/lpeg.lua b/runtime/lua/vim/_meta/lpeg.lua
index 73b3375c82..39a894aaeb 100644
--- a/runtime/lua/vim/_meta/lpeg.lua
+++ b/runtime/lua/vim/_meta/lpeg.lua
@@ -2,7 +2,7 @@
error('Cannot require a meta file')
-- These types were taken from https://github.com/LuaCATS/lpeg
--- (based on revision e6789e28e5b91a4a277a2a03081d708c403a3e34)
+-- (based on revision 82c6a8fc676bbc20722026afd952668f3919b11d)
-- with types being renamed to include the vim namespace and with some descriptions made less verbose.
--- @brief <pre>help
@@ -32,7 +32,7 @@ vim.lpeg = {}
--- @operator div(table): vim.lpeg.Capture
--- @operator div(function): vim.lpeg.Capture
--- @operator pow(number): vim.lpeg.Pattern
---- @operator mod(function): nil
+--- @operator mod(function): vim.lpeg.Capture
local Pattern = {}
--- @alias vim.lpeg.Capture vim.lpeg.Pattern
diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua
index 155c93726b..902df8f7d6 100644
--- a/runtime/lua/vim/_meta/options.lua
+++ b/runtime/lua/vim/_meta/options.lua
@@ -3830,6 +3830,9 @@ vim.go.lw = vim.go.lispwords
--- between tabs and spaces and for trailing blanks. Further changed by
--- the 'listchars' option.
---
+--- When 'listchars' does not contain "tab" field, tabs are shown as "^I"
+--- or "<09>", like how unprintable characters are displayed.
+---
--- The cursor is displayed at the start of the space a Tab character
--- occupies, not at the end as usual in Normal mode. To get this cursor
--- position while displaying Tabs with spaces, use:
@@ -6373,8 +6376,7 @@ vim.go.sol = vim.go.startofline
--- Some of the items from the 'statusline' format are different for
--- 'statuscolumn':
---
---- %l line number of currently drawn line
---- %r relative line number of currently drawn line
+--- %l line number column for currently drawn line
--- %s sign column for currently drawn line
--- %C fold column for currently drawn line
---
@@ -6403,11 +6405,8 @@ vim.go.sol = vim.go.startofline
--- Examples:
---
--- ```vim
---- " Relative number with bar separator and click handlers:
---- set statuscolumn=%@SignCb@%s%=%T%@NumCb@%r│%T
----
---- " Right aligned relative cursor line number:
---- let &stc='%=%{v:relnum?v:relnum:v:lnum} '
+--- " Line number with bar separator and click handlers:
+--- set statuscolumn=%@SignCb@%s%=%T%@NumCb@%l│%T
---
--- " Line numbers in hexadecimal for non wrapped part of lines:
--- let &stc='%=%{v:virtnum>0?"":printf("%x",v:lnum)} '
diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua
index a1600e1cb5..11dcbc010b 100644
--- a/runtime/lua/vim/_meta/vimfn.lua
+++ b/runtime/lua/vim/_meta/vimfn.lua
@@ -911,33 +911,33 @@ function vim.fn.cindent(lnum) end
function vim.fn.clearmatches(win) end
--- The result is a Number, which is the byte index of the column
---- position given with {expr}. The accepted positions are:
---- . the cursor position
---- $ the end of the cursor line (the result is the
---- number of bytes in the cursor line plus one)
---- 'x position of mark x (if the mark is not set, 0 is
---- returned)
---- v In Visual mode: the start of the Visual area (the
---- cursor is the end). When not in Visual mode
---- returns the cursor position. Differs from |'<| in
---- that it's updated right away.
+--- position given with {expr}.
+--- For accepted positions see |getpos()|.
+--- When {expr} is "$", it means the end of the cursor line, so
+--- the result is the number of bytes in the cursor line plus one.
--- Additionally {expr} can be [lnum, col]: a |List| with the line
--- and column number. Most useful when the column is "$", to get
--- the last column of a specific line. When "lnum" or "col" is
--- out of range then col() returns zero.
+---
--- With the optional {winid} argument the values are obtained for
--- that window instead of the current window.
+---
--- To get the line number use |line()|. To get both use
--- |getpos()|.
+---
--- For the screen column position use |virtcol()|. For the
--- character position use |charcol()|.
+---
--- Note that only marks in the current file can be used.
+---
--- Examples: >vim
--- echo col(".") " column of cursor
--- echo col("$") " length of cursor line plus one
--- echo col("'t") " column of mark t
--- echo col("'" .. markname) " column of mark markname
---- <The first column is 1. Returns 0 if {expr} is invalid or when
+--- <
+--- The first column is 1. Returns 0 if {expr} is invalid or when
--- the window with ID {winid} is not found.
--- For an uppercase mark the column may actually be in another
--- buffer.
@@ -2766,8 +2766,9 @@ function vim.fn.getchangelist(buf) end
--- endfunction
--- <
---
+--- @param expr? 0|1
--- @return integer
-function vim.fn.getchar() end
+function vim.fn.getchar(expr) end
--- The result is a Number which is the state of the modifiers for
--- the last obtained character with getchar() or in another way.
@@ -2837,8 +2838,9 @@ function vim.fn.getcharsearch() end
--- Otherwise this works like |getchar()|, except that a number
--- result is converted to a string.
---
+--- @param expr? 0|1
--- @return string
-function vim.fn.getcharstr() end
+function vim.fn.getcharstr(expr) end
--- Return the type of the current command-line completion.
--- Only works when the command line is being edited, thus
@@ -3249,8 +3251,8 @@ function vim.fn.getloclist(nr, what) end
--- Refer to |getpos()| for getting information about a specific
--- mark.
---
---- @param buf? any
---- @return any
+--- @param buf? integer?
+--- @return vim.fn.getmarklist.ret.item[]
function vim.fn.getmarklist(buf) end
--- Returns a |List| with all matches previously defined for the
@@ -3327,9 +3329,34 @@ function vim.fn.getmousepos() end
--- @return integer
function vim.fn.getpid() end
---- Get the position for String {expr}. For possible values of
---- {expr} see |line()|. For getting the cursor position see
---- |getcurpos()|.
+--- Get the position for String {expr}.
+--- The accepted values for {expr} are:
+--- . The cursor position.
+--- $ The last line in the current buffer.
+--- 'x Position of mark x (if the mark is not set, 0 is
+--- returned for all values).
+--- w0 First line visible in current window (one if the
+--- display isn't updated, e.g. in silent Ex mode).
+--- w$ Last line visible in current window (this is one
+--- less than "w0" if no lines are visible).
+--- v When not in Visual mode, returns the cursor
+--- position. In Visual mode, returns the other end
+--- of the Visual area. A good way to think about
+--- this is that in Visual mode "v" and "." complement
+--- each other. While "." refers to the cursor
+--- position, "v" refers to where |v_o| would move the
+--- cursor. As a result, you can use "v" and "."
+--- together to work on all of a selection in
+--- characterwise Visual mode. If the cursor is at
+--- the end of a characterwise Visual area, "v" refers
+--- to the start of the same Visual area. And if the
+--- cursor is at the start of a characterwise Visual
+--- area, "v" refers to the end of the same Visual
+--- area. "v" differs from |'<| and |'>| in that it's
+--- updated right away.
+--- Note that a mark in another file can be used. The line number
+--- then applies to another buffer.
+---
--- The result is a |List| with four numbers:
--- [bufnum, lnum, col, off]
--- "bufnum" is zero, unless a mark like '0 or 'A is used, then it
@@ -3340,20 +3367,25 @@ function vim.fn.getpid() end
--- it is the offset in screen columns from the start of the
--- character. E.g., a position within a <Tab> or after the last
--- character.
---- Note that for '< and '> Visual mode matters: when it is "V"
---- (visual line mode) the column of '< is zero and the column of
---- '> is a large number equal to |v:maxcol|.
+---
+--- For getting the cursor position see |getcurpos()|.
--- The column number in the returned List is the byte position
--- within the line. To get the character position in the line,
--- use |getcharpos()|.
+---
+--- Note that for '< and '> Visual mode matters: when it is "V"
+--- (visual line mode) the column of '< is zero and the column of
+--- '> is a large number equal to |v:maxcol|.
--- A very large column number equal to |v:maxcol| can be returned,
--- in which case it means "after the end of the line".
--- If {expr} is invalid, returns a list with all zeros.
+---
--- This can be used to save and restore the position of a mark: >vim
--- let save_a_mark = getpos("'a")
--- " ...
--- call setpos("'a", save_a_mark)
---- <Also see |getcharpos()|, |getcurpos()| and |setpos()|.
+--- <
+--- Also see |getcharpos()|, |getcurpos()| and |setpos()|.
---
--- @param expr string
--- @return integer[]
@@ -3569,8 +3601,8 @@ function vim.fn.getreginfo(regname) end
--- difference if the buffer is displayed in a window with
--- different 'virtualedit' or 'list' values.
---
---- Examples: >
---- :xnoremap <CR>
+--- Examples: >vim
+--- xnoremap <CR>
--- \ <Cmd>echom getregion(
--- \ getpos('v'), getpos('.'), #{ type: mode() })<CR>
--- <
@@ -4958,28 +4990,16 @@ function vim.fn.libcall(libname, funcname, argument) end
--- @return any
function vim.fn.libcallnr(libname, funcname, argument) end
---- The result is a Number, which is the line number of the file
---- position given with {expr}. The {expr} argument is a string.
---- The accepted positions are:
---- . the cursor position
---- $ the last line in the current buffer
---- 'x position of mark x (if the mark is not set, 0 is
---- returned)
---- w0 first line visible in current window (one if the
---- display isn't updated, e.g. in silent Ex mode)
---- w$ last line visible in current window (this is one
---- less than "w0" if no lines are visible)
---- v In Visual mode: the start of the Visual area (the
---- cursor is the end). When not in Visual mode
---- returns the cursor position. Differs from |'<| in
---- that it's updated right away.
---- Note that a mark in another file can be used. The line number
---- then applies to another buffer.
+--- See |getpos()| for accepted positions.
+---
--- To get the column number use |col()|. To get both use
--- |getpos()|.
+---
--- With the optional {winid} argument the values are obtained for
--- that window instead of the current window.
+---
--- Returns 0 for invalid values of {expr} and {winid}.
+---
--- Examples: >vim
--- echo line(".") " line number of the cursor
--- echo line(".", winid) " idem, in window "winid"
@@ -5297,8 +5317,9 @@ function vim.fn.mapcheck(name, mode, abbr) end
--- ounmap xyzzy
--- echo printf("Operator-pending mode bit: 0x%x", op_bit)
---
---- @return any
-function vim.fn.maplist() end
+--- @param abbr? 0|1
+--- @return table[]
+function vim.fn.maplist(abbr) end
--- Like |map()| but instead of replacing items in {expr1} a new
--- List or Dictionary is created and returned. {expr1} remains
@@ -5575,19 +5596,19 @@ function vim.fn.matcharg(nr) end
---
--- Examples: >vim
--- " Assuming line 3 in buffer 5 contains "a"
---- :echo matchbufline(5, '\<\k\+\>', 3, 3)
---- [{'lnum': 3, 'byteidx': 0, 'text': 'a'}]
+--- echo matchbufline(5, '\<\k\+\>', 3, 3)
+--- < `[{'lnum': 3, 'byteidx': 0, 'text': 'a'}]` >vim
--- " Assuming line 4 in buffer 10 contains "tik tok"
---- :echo matchbufline(10, '\<\k\+\>', 1, 4)
---- [{'lnum': 4, 'byteidx': 0, 'text': 'tik'}, {'lnum': 4, 'byteidx': 4, 'text': 'tok'}]
---- <
+--- echo matchbufline(10, '\<\k\+\>', 1, 4)
+--- < `[{'lnum': 4, 'byteidx': 0, 'text': 'tik'}, {'lnum': 4, 'byteidx': 4, 'text': 'tok'}]`
+---
--- If {submatch} is present and is v:true, then submatches like
--- "\1", "\2", etc. are also returned. Example: >vim
--- " Assuming line 2 in buffer 2 contains "acd"
---- :echo matchbufline(2, '\(a\)\?\(b\)\?\(c\)\?\(.*\)', 2, 2
+--- echo matchbufline(2, '\(a\)\?\(b\)\?\(c\)\?\(.*\)', 2, 2
--- \ {'submatches': v:true})
---- [{'lnum': 2, 'byteidx': 0, 'text': 'acd', 'submatches': ['a', '', 'c', 'd', '', '', '', '', '']}]
---- <The "submatches" List always contains 9 items. If a submatch
+--- < `[{'lnum': 2, 'byteidx': 0, 'text': 'acd', 'submatches': ['a', '', 'c', 'd', '', '', '', '', '']}]`
+--- The "submatches" List always contains 9 items. If a submatch
--- is not found, then an empty string is returned for that
--- submatch.
---
@@ -5786,17 +5807,17 @@ function vim.fn.matchstr(expr, pat, start, count) end
--- option settings on the pattern.
---
--- Example: >vim
---- :echo matchstrlist(['tik tok'], '\<\k\+\>')
---- [{'idx': 0, 'byteidx': 0, 'text': 'tik'}, {'idx': 0, 'byteidx': 4, 'text': 'tok'}]
---- :echo matchstrlist(['a', 'b'], '\<\k\+\>')
---- [{'idx': 0, 'byteidx': 0, 'text': 'a'}, {'idx': 1, 'byteidx': 0, 'text': 'b'}]
---- <
+--- echo matchstrlist(['tik tok'], '\<\k\+\>')
+--- < `[{'idx': 0, 'byteidx': 0, 'text': 'tik'}, {'idx': 0, 'byteidx': 4, 'text': 'tok'}]` >vim
+--- echo matchstrlist(['a', 'b'], '\<\k\+\>')
+--- < `[{'idx': 0, 'byteidx': 0, 'text': 'a'}, {'idx': 1, 'byteidx': 0, 'text': 'b'}]`
+---
--- If "submatches" is present and is v:true, then submatches like
--- "\1", "\2", etc. are also returned. Example: >vim
---- :echo matchstrlist(['acd'], '\(a\)\?\(b\)\?\(c\)\?\(.*\)',
+--- echo matchstrlist(['acd'], '\(a\)\?\(b\)\?\(c\)\?\(.*\)',
--- \ #{submatches: v:true})
---- [{'idx': 0, 'byteidx': 0, 'text': 'acd', 'submatches': ['a', '', 'c', 'd', '', '', '', '', '']}]
---- <The "submatches" List always contains 9 items. If a submatch
+--- < `[{'idx': 0, 'byteidx': 0, 'text': 'acd', 'submatches': ['a', '', 'c', 'd', '', '', '', '', '']}]`
+--- The "submatches" List always contains 9 items. If a submatch
--- is not found, then an empty string is returned for that
--- submatch.
---
@@ -5986,17 +6007,14 @@ function vim.fn.min(expr) end
--- When {flags} is present it must be a string. An empty string
--- has no effect.
---
---- If {flags} contains "p" then intermediate directories are
---- created as necessary.
+--- {flags} can contain these character flags:
+--- "p" intermediate directories will be created as necessary
+--- "D" {name} will be deleted at the end of the current
+--- function, but not recursively |:defer|
+--- "R" {name} will be deleted recursively at the end of the
+--- current function |:defer|
---
---- If {flags} contains "D" then {name} is deleted at the end of
---- the current function, as with: >vim
---- defer delete({name}, 'd')
---- <
---- If {flags} contains "R" then {name} is deleted recursively at
---- the end of the current function, as with: >vim
---- defer delete({name}, 'rf')
---- <Note that when {name} has more than one part and "p" is used
+--- Note that when {name} has more than one part and "p" is used
--- some directories may already exist. Only the first one that
--- is created and what it contains is scheduled to be deleted.
--- E.g. when using: >vim
@@ -7236,7 +7254,7 @@ function vim.fn.screenchars(row, col) end
--- the following mappings: >vim
--- nnoremap <expr> GG ":echom " .. screencol() .. "\n"
--- nnoremap <silent> GG :echom screencol()<CR>
---- noremap GG <Cmd>echom screencol()<Cr>
+--- noremap GG <Cmd>echom screencol()<CR>
--- <
---
--- @return any
@@ -7634,8 +7652,15 @@ function vim.fn.searchdecl(name, global, thisblock) end
--- \ 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string"')
--- <
---
---- @return any
-function vim.fn.searchpair() end
+--- @param start any
+--- @param middle any
+--- @param end_ any
+--- @param flags? string
+--- @param skip? any
+--- @param stopline? any
+--- @param timeout? integer
+--- @return integer
+function vim.fn.searchpair(start, middle, end_, flags, skip, stopline, timeout) end
--- Same as |searchpair()|, but returns a |List| with the line and
--- column position of the match. The first element of the |List|
@@ -7647,8 +7672,15 @@ function vim.fn.searchpair() end
--- <
--- See |match-parens| for a bigger and more useful example.
---
---- @return any
-function vim.fn.searchpairpos() end
+--- @param start any
+--- @param middle any
+--- @param end_ any
+--- @param flags? string
+--- @param skip? any
+--- @param stopline? any
+--- @param timeout? integer
+--- @return [integer, integer]
+function vim.fn.searchpairpos(start, middle, end_, flags, skip, stopline, timeout) end
--- Same as |search()|, but returns a |List| with the line and
--- column position of the match. The first element of the |List|
@@ -10382,7 +10414,9 @@ function vim.fn.values(dict) end
--- set to 8, it returns 8. |conceal| is ignored.
--- For the byte position use |col()|.
---
---- For the use of {expr} see |col()|.
+--- For the use of {expr} see |getpos()| and |col()|.
+--- When {expr} is "$", it means the end of the cursor line, so
+--- the result is the number of cells in the cursor line plus one.
---
--- When 'virtualedit' is used {expr} can be [lnum, col, off],
--- where "off" is the offset in screen columns from the start of
@@ -10392,18 +10426,6 @@ function vim.fn.values(dict) end
--- beyond the end of the line can be returned. Also see
--- |'virtualedit'|
---
---- The accepted positions are:
---- . the cursor position
---- $ the end of the cursor line (the result is the
---- number of displayed characters in the cursor line
---- plus one)
---- 'x position of mark x (if the mark is not set, 0 is
---- returned)
---- v In Visual mode: the start of the Visual area (the
---- cursor is the end). When not in Visual mode
---- returns the cursor position. Differs from |'<| in
---- that it's updated right away.
----
--- If {list} is present and non-zero then virtcol() returns a
--- List with the first and last screen position occupied by the
--- character.
@@ -10422,7 +10444,9 @@ function vim.fn.values(dict) end
--- " With text " there", with 't at 'h':
---
--- echo virtcol("'t") " returns 6
---- <The first column is 1. 0 or [0, 0] is returned for an error.
+--- <
+--- The first column is 1. 0 or [0, 0] is returned for an error.
+---
--- A more advanced example that echoes the maximum length of
--- all lines: >vim
--- echo max(map(range(1, line('$')), "virtcol([v:val, '$'])"))
diff --git a/runtime/lua/vim/_options.lua b/runtime/lua/vim/_options.lua
index 4a360c18e4..a61fa61256 100644
--- a/runtime/lua/vim/_options.lua
+++ b/runtime/lua/vim/_options.lua
@@ -174,6 +174,11 @@ local function new_buf_opt_accessor(bufnr)
end
local function new_win_opt_accessor(winid, bufnr)
+ -- TODO(lewis6991): allow passing both buf and win to nvim_get_option_value
+ if bufnr ~= nil and bufnr ~= 0 then
+ error('only bufnr=0 is supported')
+ end
+
return setmetatable({}, {
__index = function(_, k)
if bufnr == nil and type(k) == 'number' then
@@ -184,11 +189,6 @@ local function new_win_opt_accessor(winid, bufnr)
end
end
- if bufnr ~= nil and bufnr ~= 0 then
- error('only bufnr=0 is supported')
- end
-
- -- TODO(lewis6991): allow passing both buf and win to nvim_get_option_value
return api.nvim_get_option_value(k, {
scope = bufnr and 'local' or nil,
win = winid or 0,
@@ -196,7 +196,6 @@ local function new_win_opt_accessor(winid, bufnr)
end,
__newindex = function(_, k, v)
- -- TODO(lewis6991): allow passing both buf and win to nvim_set_option_value
return api.nvim_set_option_value(k, v, {
scope = bufnr and 'local' or nil,
win = winid or 0,
diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua
index cc2fbe0cec..2bb50d8c0b 100644
--- a/runtime/lua/vim/filetype.lua
+++ b/runtime/lua/vim/filetype.lua
@@ -985,6 +985,7 @@ local extension = {
smt = 'smith',
smithy = 'smithy',
sml = 'sml',
+ smk = 'snakemake',
spt = 'snobol4',
sno = 'snobol4',
sln = 'solution',
@@ -1620,6 +1621,7 @@ local filename = {
['/etc/slp.spi'] = 'slpspi',
['.slrnrc'] = 'slrnrc',
['sendmail.cf'] = 'sm',
+ Snakefile = 'snakemake',
['.sqlite_history'] = 'sql',
['squid.conf'] = 'squid',
['ssh_config'] = 'sshconfig',
diff --git a/runtime/lua/vim/filetype/detect.lua b/runtime/lua/vim/filetype/detect.lua
index c56ece6289..fa90c83b81 100644
--- a/runtime/lua/vim/filetype/detect.lua
+++ b/runtime/lua/vim/filetype/detect.lua
@@ -1783,6 +1783,7 @@ local patterns_hashbang = {
['^janet\\>'] = { 'janet', { vim_regex = true } },
['^dart\\>'] = { 'dart', { vim_regex = true } },
['^execlineb\\>'] = { 'execline', { vim_regex = true } },
+ ['^vim\\>'] = { 'vim', { vim_regex = true } },
}
---@private
diff --git a/runtime/lua/vim/iter.lua b/runtime/lua/vim/iter.lua
index 1093759efe..6bddf0bc5e 100644
--- a/runtime/lua/vim/iter.lua
+++ b/runtime/lua/vim/iter.lua
@@ -276,7 +276,7 @@ end
--- -- { 6, 12 }
--- ```
---
----@param f fun(...):any Mapping function. Takes all values returned from
+---@param f fun(...):...:any Mapping function. Takes all values returned from
--- the previous stage in the pipeline as arguments
--- and returns one or more new values, which are used
--- in the next pipeline stage. Nil return values
diff --git a/runtime/lua/vim/lsp/_dynamic.lua b/runtime/lua/vim/lsp/_dynamic.lua
index 819b03a63a..27113c0e74 100644
--- a/runtime/lua/vim/lsp/_dynamic.lua
+++ b/runtime/lua/vim/lsp/_dynamic.lua
@@ -24,7 +24,6 @@ function M:supports_registration(method)
end
--- @param registrations lsp.Registration[]
---- @package
function M:register(registrations)
-- remove duplicates
self:unregister(registrations)
@@ -38,7 +37,6 @@ function M:register(registrations)
end
--- @param unregisterations lsp.Unregistration[]
---- @package
function M:unregister(unregisterations)
for _, unreg in ipairs(unregisterations) do
local method = unreg.method
@@ -58,7 +56,6 @@ end
--- @param method string
--- @param opts? {bufnr: integer?}
--- @return lsp.Registration? (table|nil) the registration if found
---- @package
function M:get(method, opts)
opts = opts or {}
opts.bufnr = opts.bufnr or vim.api.nvim_get_current_buf()
@@ -78,7 +75,6 @@ end
--- @param method string
--- @param opts? {bufnr: integer?}
---- @package
function M:supports(method, opts)
return self:get(method, opts) ~= nil
end
diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua
index 327cd19125..8cdfdd4b90 100644
--- a/runtime/lua/vim/lsp/client.lua
+++ b/runtime/lua/vim/lsp/client.lua
@@ -436,7 +436,7 @@ local function ensure_list(x)
return { x }
end
---- @package
+--- @nodoc
--- @param config vim.lsp.ClientConfig
--- @return vim.lsp.Client?
function Client.create(config)
@@ -535,7 +535,7 @@ function Client:_run_callbacks(cbs, error_id, ...)
end
end
---- @package
+--- @nodoc
function Client:initialize()
local config = self.config
@@ -656,7 +656,7 @@ end
--- @param method string LSP method name.
--- @param params? table LSP request params.
--- @param handler? lsp.Handler Response |lsp-handler| for this method.
---- @param bufnr? integer Buffer handle (0 for current).
+--- @param bufnr integer Buffer handle (0 for current).
--- @return boolean status, integer? request_id {status} is a bool indicating
--- whether the request was successful. If it is `false`, then it will
--- always be `false` (the client has shutdown). If it was
@@ -861,7 +861,6 @@ function Client:_is_stopped()
return self.rpc.is_closing()
end
---- @package
--- Execute a lsp command, either via client command function (if available)
--- or via workspace/executeCommand (if supported by the server)
---
@@ -906,7 +905,6 @@ function Client:_exec_cmd(command, context, handler, on_unsupported)
self.request(ms.workspace_executeCommand, params, handler, context.bufnr)
end
---- @package
--- Default handler for the 'textDocument/didOpen' LSP notification.
---
--- @param bufnr integer Number of the buffer, or 0 for current
@@ -918,18 +916,16 @@ function Client:_text_document_did_open_handler(bufnr)
if not api.nvim_buf_is_loaded(bufnr) then
return
end
- local filetype = vim.bo[bufnr].filetype
- local params = {
+ local filetype = vim.bo[bufnr].filetype
+ self.notify(ms.textDocument_didOpen, {
textDocument = {
- version = 0,
+ version = lsp.util.buf_versions[bufnr],
uri = vim.uri_from_bufnr(bufnr),
languageId = self.get_language_id(bufnr, filetype),
text = lsp._buf_get_full_text(bufnr),
},
- }
- self.notify(ms.textDocument_didOpen, params)
- lsp.util.buf_versions[bufnr] = params.textDocument.version
+ })
-- Next chance we get, we should re-do the diagnostics
vim.schedule(function()
@@ -942,7 +938,6 @@ function Client:_text_document_did_open_handler(bufnr)
end)
end
---- @package
--- Runs the on_attach function from the client's config if it was defined.
--- @param bufnr integer Buffer number
function Client:_on_attach(bufnr)
@@ -1065,7 +1060,6 @@ function Client:_on_exit(code, signal)
)
end
---- @package
--- Add a directory to the workspace folders.
--- @param dir string?
function Client:_add_workspace_folder(dir)
@@ -1088,7 +1082,6 @@ function Client:_add_workspace_folder(dir)
vim.list_extend(self.workspace_folders, wf)
end
---- @package
--- Remove a directory to the workspace folders.
--- @param dir string?
function Client:_remove_workspace_folder(dir)
diff --git a/runtime/lua/vim/lsp/completion.lua b/runtime/lua/vim/lsp/completion.lua
index 4b7deabf41..2e6d82b367 100644
--- a/runtime/lua/vim/lsp/completion.lua
+++ b/runtime/lua/vim/lsp/completion.lua
@@ -145,8 +145,8 @@ local function get_completion_word(item)
-- label: insert
--
-- Typing `i` would remove the candidate because newText starts with `t`.
- local text = item.insertText or item.textEdit.newText
- return #text < #item.label and text or item.label
+ local text = parse_snippet(item.insertText or item.textEdit.newText)
+ return #text < #item.label and vim.fn.matchstr(text, '\\k*') or item.label
elseif item.insertText and item.insertText ~= '' then
return parse_snippet(item.insertText)
else
diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua
index 38c43893eb..44548fec92 100644
--- a/runtime/lua/vim/lsp/handlers.lua
+++ b/runtime/lua/vim/lsp/handlers.lua
@@ -646,6 +646,7 @@ M[ms.window_showMessage] = function(_, result, ctx, _)
if message_type == protocol.MessageType.Error then
err_message('LSP[', client_name, '] ', message)
else
+ --- @type string
local message_type_name = protocol.MessageType[message_type]
api.nvim_out_write(string.format('LSP[%s][%s] %s\n', client_name, message_type_name, message))
end
diff --git a/runtime/lua/vim/lsp/inlay_hint.lua b/runtime/lua/vim/lsp/inlay_hint.lua
index 2d784816cb..aa84294cc4 100644
--- a/runtime/lua/vim/lsp/inlay_hint.lua
+++ b/runtime/lua/vim/lsp/inlay_hint.lua
@@ -370,7 +370,7 @@ api.nvim_set_decoration_provider(namespace, {
})
--- Query whether inlay hint is enabled in the {filter}ed scope
---- @param filter vim.lsp.inlay_hint.enable.Filter
+--- @param filter? vim.lsp.inlay_hint.enable.Filter
--- @return boolean
--- @since 12
function M.is_enabled(filter)
diff --git a/runtime/lua/vim/lsp/log.lua b/runtime/lua/vim/lsp/log.lua
index 9f2bd71158..0438ca84af 100644
--- a/runtime/lua/vim/lsp/log.lua
+++ b/runtime/lua/vim/lsp/log.lua
@@ -9,7 +9,7 @@ local log_levels = vim.log.levels
--- Can be used to lookup the number from the name or the name from the number.
--- Levels by name: "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF"
--- Level numbers begin with "TRACE" at 0
---- @type table<string|integer, string|integer>
+--- @type table<string,integer> | table<integer, string>
--- @nodoc
log.levels = vim.deepcopy(log_levels)
diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua
index 8ac4cc794b..eb18043843 100644
--- a/runtime/lua/vim/lsp/protocol.lua
+++ b/runtime/lua/vim/lsp/protocol.lua
@@ -12,9 +12,6 @@ end
local sysname = vim.uv.os_uname().sysname
--- Protocol for the Microsoft Language Server Protocol (mslsp)
-local protocol = {}
-
local constants = {
--- @enum lsp.DiagnosticSeverity
DiagnosticSeverity = {
@@ -46,6 +43,8 @@ local constants = {
Info = 3,
-- A log message.
Log = 4,
+ -- A debug message.
+ Debug = 5,
},
-- The file event type.
@@ -308,326 +307,18 @@ local constants = {
},
}
-for k1, v1 in pairs(constants) do
- local tbl = vim.deepcopy(v1, true)
- for _, k2 in ipairs(vim.tbl_keys(tbl)) do
- local v2 = tbl[k2]
- tbl[v2] = k2
+-- Protocol for the Microsoft Language Server Protocol (mslsp)
+local protocol = {}
+
+--- @diagnostic disable:no-unknown
+for k1, v1 in pairs(vim.deepcopy(constants, true)) do
+ for _, k2 in ipairs(vim.tbl_keys(v1)) do
+ local v2 = v1[k2]
+ v1[v2] = k2
end
- protocol[k1] = tbl
+ protocol[k1] = v1
end
-
---[=[
---Text document specific client capabilities.
-export interface TextDocumentClientCapabilities {
- synchronization?: {
- --Whether text document synchronization supports dynamic registration.
- dynamicRegistration?: boolean;
- --The client supports sending will save notifications.
- willSave?: boolean;
- --The client supports sending a will save request and
- --waits for a response providing text edits which will
- --be applied to the document before it is saved.
- willSaveWaitUntil?: boolean;
- --The client supports did save notifications.
- didSave?: boolean;
- }
- --Capabilities specific to the `textDocument/completion`
- completion?: {
- --Whether completion supports dynamic registration.
- dynamicRegistration?: boolean;
- --The client supports the following `CompletionItem` specific
- --capabilities.
- completionItem?: {
- --The client supports snippets as insert text.
- --
- --A snippet can define tab stops and placeholders with `$1`, `$2`
- --and `${3:foo}`. `$0` defines the final tab stop, it defaults to
- --the end of the snippet. Placeholders with equal identifiers are linked,
- --that is typing in one will update others too.
- snippetSupport?: boolean;
- --The client supports commit characters on a completion item.
- commitCharactersSupport?: boolean
- --The client supports the following content formats for the documentation
- --property. The order describes the preferred format of the client.
- documentationFormat?: MarkupKind[];
- --The client supports the deprecated property on a completion item.
- deprecatedSupport?: boolean;
- --The client supports the preselect property on a completion item.
- preselectSupport?: boolean;
- }
- completionItemKind?: {
- --The completion item kind values the client supports. When this
- --property exists the client also guarantees that it will
- --handle values outside its set gracefully and falls back
- --to a default value when unknown.
- --
- --If this property is not present the client only supports
- --the completion items kinds from `Text` to `Reference` as defined in
- --the initial version of the protocol.
- valueSet?: CompletionItemKind[];
- },
- --The client supports to send additional context information for a
- --`textDocument/completion` request.
- contextSupport?: boolean;
- };
- --Capabilities specific to the `textDocument/hover`
- hover?: {
- --Whether hover supports dynamic registration.
- dynamicRegistration?: boolean;
- --The client supports the follow content formats for the content
- --property. The order describes the preferred format of the client.
- contentFormat?: MarkupKind[];
- };
- --Capabilities specific to the `textDocument/signatureHelp`
- signatureHelp?: {
- --Whether signature help supports dynamic registration.
- dynamicRegistration?: boolean;
- --The client supports the following `SignatureInformation`
- --specific properties.
- signatureInformation?: {
- --The client supports the follow content formats for the documentation
- --property. The order describes the preferred format of the client.
- documentationFormat?: MarkupKind[];
- --Client capabilities specific to parameter information.
- parameterInformation?: {
- --The client supports processing label offsets instead of a
- --simple label string.
- --
- --Since 3.14.0
- labelOffsetSupport?: boolean;
- }
- };
- };
- --Capabilities specific to the `textDocument/references`
- references?: {
- --Whether references supports dynamic registration.
- dynamicRegistration?: boolean;
- };
- --Capabilities specific to the `textDocument/documentHighlight`
- documentHighlight?: {
- --Whether document highlight supports dynamic registration.
- dynamicRegistration?: boolean;
- };
- --Capabilities specific to the `textDocument/documentSymbol`
- documentSymbol?: {
- --Whether document symbol supports dynamic registration.
- dynamicRegistration?: boolean;
- --Specific capabilities for the `SymbolKind`.
- symbolKind?: {
- --The symbol kind values the client supports. When this
- --property exists the client also guarantees that it will
- --handle values outside its set gracefully and falls back
- --to a default value when unknown.
- --
- --If this property is not present the client only supports
- --the symbol kinds from `File` to `Array` as defined in
- --the initial version of the protocol.
- valueSet?: SymbolKind[];
- }
- --The client supports hierarchical document symbols.
- hierarchicalDocumentSymbolSupport?: boolean;
- };
- --Capabilities specific to the `textDocument/formatting`
- formatting?: {
- --Whether formatting supports dynamic registration.
- dynamicRegistration?: boolean;
- };
- --Capabilities specific to the `textDocument/rangeFormatting`
- rangeFormatting?: {
- --Whether range formatting supports dynamic registration.
- dynamicRegistration?: boolean;
- };
- --Capabilities specific to the `textDocument/onTypeFormatting`
- onTypeFormatting?: {
- --Whether on type formatting supports dynamic registration.
- dynamicRegistration?: boolean;
- };
- --Capabilities specific to the `textDocument/declaration`
- declaration?: {
- --Whether declaration supports dynamic registration. If this is set to `true`
- --the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`
- --return value for the corresponding server capability as well.
- dynamicRegistration?: boolean;
- --The client supports additional metadata in the form of declaration links.
- --
- --Since 3.14.0
- linkSupport?: boolean;
- };
- --Capabilities specific to the `textDocument/definition`.
- --
- --Since 3.14.0
- definition?: {
- --Whether definition supports dynamic registration.
- dynamicRegistration?: boolean;
- --The client supports additional metadata in the form of definition links.
- linkSupport?: boolean;
- };
- --Capabilities specific to the `textDocument/typeDefinition`
- --
- --Since 3.6.0
- typeDefinition?: {
- --Whether typeDefinition supports dynamic registration. If this is set to `true`
- --the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`
- --return value for the corresponding server capability as well.
- dynamicRegistration?: boolean;
- --The client supports additional metadata in the form of definition links.
- --
- --Since 3.14.0
- linkSupport?: boolean;
- };
- --Capabilities specific to the `textDocument/implementation`.
- --
- --Since 3.6.0
- implementation?: {
- --Whether implementation supports dynamic registration. If this is set to `true`
- --the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`
- --return value for the corresponding server capability as well.
- dynamicRegistration?: boolean;
- --The client supports additional metadata in the form of definition links.
- --
- --Since 3.14.0
- linkSupport?: boolean;
- };
- --Capabilities specific to the `textDocument/codeAction`
- codeAction?: {
- --Whether code action supports dynamic registration.
- dynamicRegistration?: boolean;
- --The client support code action literals as a valid
- --response of the `textDocument/codeAction` request.
- --
- --Since 3.8.0
- codeActionLiteralSupport?: {
- --The code action kind is support with the following value
- --set.
- codeActionKind: {
- --The code action kind values the client supports. When this
- --property exists the client also guarantees that it will
- --handle values outside its set gracefully and falls back
- --to a default value when unknown.
- valueSet: CodeActionKind[];
- };
- };
- };
- --Capabilities specific to the `textDocument/codeLens`
- codeLens?: {
- --Whether code lens supports dynamic registration.
- dynamicRegistration?: boolean;
- };
- --Capabilities specific to the `textDocument/documentLink`
- documentLink?: {
- --Whether document link supports dynamic registration.
- dynamicRegistration?: boolean;
- };
- --Capabilities specific to the `textDocument/documentColor` and the
- --`textDocument/colorPresentation` request.
- --
- --Since 3.6.0
- colorProvider?: {
- --Whether colorProvider supports dynamic registration. If this is set to `true`
- --the client supports the new `(ColorProviderOptions & TextDocumentRegistrationOptions & StaticRegistrationOptions)`
- --return value for the corresponding server capability as well.
- dynamicRegistration?: boolean;
- }
- --Capabilities specific to the `textDocument/rename`
- rename?: {
- --Whether rename supports dynamic registration.
- dynamicRegistration?: boolean;
- --The client supports testing for validity of rename operations
- --before execution.
- prepareSupport?: boolean;
- };
- --Capabilities specific to `textDocument/publishDiagnostics`.
- publishDiagnostics?: {
- --Whether the clients accepts diagnostics with related information.
- relatedInformation?: boolean;
- --Client supports the tag property to provide meta data about a diagnostic.
- --Clients supporting tags have to handle unknown tags gracefully.
- --Since 3.15.0
- tagSupport?: {
- --The tags supported by this client
- valueSet: DiagnosticTag[];
- };
- };
- --Capabilities specific to `textDocument/foldingRange` requests.
- --
- --Since 3.10.0
- foldingRange?: {
- --Whether implementation supports dynamic registration for folding range providers. If this is set to `true`
- --the client supports the new `(FoldingRangeProviderOptions & TextDocumentRegistrationOptions & StaticRegistrationOptions)`
- --return value for the corresponding server capability as well.
- dynamicRegistration?: boolean;
- --The maximum number of folding ranges that the client prefers to receive per document. The value serves as a
- --hint, servers are free to follow the limit.
- rangeLimit?: number;
- --If set, the client signals that it only supports folding complete lines. If set, client will
- --ignore specified `startCharacter` and `endCharacter` properties in a FoldingRange.
- lineFoldingOnly?: boolean;
- };
-}
---]=]
-
---[=[
---Workspace specific client capabilities.
-export interface WorkspaceClientCapabilities {
- --The client supports applying batch edits to the workspace by supporting
- --the request 'workspace/applyEdit'
- applyEdit?: boolean;
- --Capabilities specific to `WorkspaceEdit`s
- workspaceEdit?: {
- --The client supports versioned document changes in `WorkspaceEdit`s
- documentChanges?: boolean;
- --The resource operations the client supports. Clients should at least
- --support 'create', 'rename' and 'delete' files and folders.
- resourceOperations?: ResourceOperationKind[];
- --The failure handling strategy of a client if applying the workspace edit
- --fails.
- failureHandling?: FailureHandlingKind;
- };
- --Capabilities specific to the `workspace/didChangeConfiguration` notification.
- didChangeConfiguration?: {
- --Did change configuration notification supports dynamic registration.
- dynamicRegistration?: boolean;
- };
- --Capabilities specific to the `workspace/didChangeWatchedFiles` notification.
- didChangeWatchedFiles?: {
- --Did change watched files notification supports dynamic registration. Please note
- --that the current protocol doesn't support static configuration for file changes
- --from the server side.
- dynamicRegistration?: boolean;
- };
- --Capabilities specific to the `workspace/symbol` request.
- symbol?: {
- --Symbol request supports dynamic registration.
- dynamicRegistration?: boolean;
- --Specific capabilities for the `SymbolKind` in the `workspace/symbol` request.
- symbolKind?: {
- --The symbol kind values the client supports. When this
- --property exists the client also guarantees that it will
- --handle values outside its set gracefully and falls back
- --to a default value when unknown.
- --
- --If this property is not present the client only supports
- --the symbol kinds from `File` to `Array` as defined in
- --the initial version of the protocol.
- valueSet?: SymbolKind[];
- }
- };
- --Capabilities specific to the `workspace/executeCommand` request.
- executeCommand?: {
- --Execute command supports dynamic registration.
- dynamicRegistration?: boolean;
- };
- --The client has support for workspace folders.
- --
- --Since 3.6.0
- workspaceFolders?: boolean;
- --The client supports `workspace/configuration` requests.
- --
- --Since 3.6.0
- configuration?: boolean;
-}
---]=]
+--- @diagnostic enable:no-unknown
--- Gets a new ClientCapabilities object describing the LSP client
--- capabilities.
@@ -1250,14 +941,5 @@ protocol.Methods = {
--- The `workspace/workspaceFolders` is sent from the server to the client to fetch the open workspace folders.
workspace_workspaceFolders = 'workspace/workspaceFolders',
}
-local function freeze(t)
- return setmetatable({}, {
- __index = t,
- __newindex = function()
- error('cannot modify immutable table')
- end,
- })
-end
-protocol.Methods = freeze(protocol.Methods)
return protocol
diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua
index 3c63a12da2..7acb67b25e 100644
--- a/runtime/lua/vim/lsp/rpc.lua
+++ b/runtime/lua/vim/lsp/rpc.lua
@@ -140,7 +140,7 @@ local client_errors = {
SERVER_RESULT_CALLBACK_ERROR = 7,
}
---- @type table<string|integer, string|integer>
+--- @type table<string,integer> | table<integer,string>
--- @nodoc
M.client_errors = vim.deepcopy(client_errors)
for k, v in pairs(client_errors) do
@@ -407,7 +407,9 @@ function Client:handle_body(body)
end
log.debug('rpc.receive', decoded)
- if type(decoded.method) == 'string' and decoded.id then
+ if type(decoded) ~= 'table' then
+ self:on_error(M.client_errors.INVALID_SERVER_MESSAGE, decoded)
+ elseif type(decoded.method) == 'string' and decoded.id then
local err --- @type lsp.ResponseError|nil
-- Schedule here so that the users functions don't trigger an error and
-- we can still use the result.
@@ -502,7 +504,7 @@ function Client:handle_body(body)
if decoded.error then
decoded.error = setmetatable(decoded.error, {
__tostring = M.format_rpc_error,
- }) --- @type table
+ })
end
self:try_call(
M.client_errors.SERVER_RESULT_CALLBACK_ERROR,
diff --git a/runtime/lua/vim/lsp/semantic_tokens.lua b/runtime/lua/vim/lsp/semantic_tokens.lua
index 279956658c..2ae86851d1 100644
--- a/runtime/lua/vim/lsp/semantic_tokens.lua
+++ b/runtime/lua/vim/lsp/semantic_tokens.lua
@@ -412,7 +412,7 @@ end
function STHighlighter:on_win(topline, botline)
for client_id, state in pairs(self.client_state) do
local current_result = state.current_result
- if current_result.version and current_result.version == util.buf_versions[self.bufnr] then
+ if current_result.version == util.buf_versions[self.bufnr] then
if not current_result.namespace_cleared then
api.nvim_buf_clear_namespace(self.bufnr, state.namespace, 0, -1)
current_result.namespace_cleared = true
@@ -773,7 +773,6 @@ function M.highlight_token(token, bufnr, client_id, hl_group, opts)
})
end
---- @package
--- |lsp-handler| for the method `workspace/semanticTokens/refresh`
---
--- Refresh requests are sent by the server to indicate a project-wide change
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index 088d57b6d6..a5cf13ed0f 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -238,6 +238,7 @@ end
---@param rows integer[] zero-indexed line numbers
---@return table<integer, string>|string a table mapping rows to lines
local function get_lines(bufnr, rows)
+ --- @type integer[]
rows = type(rows) == 'table' and rows or { rows }
-- This is needed for bufload and bufloaded
@@ -246,7 +247,7 @@ local function get_lines(bufnr, rows)
end
local function buf_lines()
- local lines = {}
+ local lines = {} --- @type table<integer,string>
for _, row in ipairs(rows) do
lines[row] = (api.nvim_buf_get_lines(bufnr, row, row + 1, false) or { '' })[1]
end
@@ -274,11 +275,11 @@ local function get_lines(bufnr, rows)
if not fd then
return ''
end
- local stat = uv.fs_fstat(fd)
- local data = uv.fs_read(fd, stat.size, 0)
+ local stat = assert(uv.fs_fstat(fd))
+ local data = assert(uv.fs_read(fd, stat.size, 0))
uv.fs_close(fd)
- local lines = {} -- rows we need to retrieve
+ local lines = {} --- @type table<integer,true|string> rows we need to retrieve
local need = 0 -- keep track of how many unique rows we need
for _, row in pairs(rows) do
if not lines[row] then
@@ -307,7 +308,7 @@ local function get_lines(bufnr, rows)
lines[i] = ''
end
end
- return lines
+ return lines --[[@as table<integer,string>]]
end
--- Gets the zero-indexed line from the given buffer.
@@ -322,7 +323,8 @@ local function get_line(bufnr, row)
end
--- Position is a https://microsoft.github.io/language-server-protocol/specifications/specification-current/#position
----@param offset_encoding string|nil utf-8|utf-16|utf-32
+---@param position lsp.Position
+---@param offset_encoding? string utf-8|utf-16|utf-32
---@return integer
local function get_line_byte_from_position(bufnr, position, offset_encoding)
-- LSP's line and characters are 0-indexed
@@ -366,6 +368,7 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding)
-- Fix reversed range and indexing each text_edits
local index = 0
+ --- @param text_edit lsp.TextEdit
text_edits = vim.tbl_map(function(text_edit)
index = index + 1
text_edit._index = index
@@ -383,6 +386,9 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding)
end, text_edits)
-- Sort text_edits
+ ---@param a lsp.TextEdit | { _index: integer }
+ ---@param b lsp.TextEdit | { _index: integer }
+ ---@return boolean
table.sort(text_edits, function(a, b)
if a.range.start.line ~= b.range.start.line then
return a.range.start.line > b.range.start.line
@@ -393,10 +399,11 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding)
if a._index ~= b._index then
return a._index < b._index
end
+ return false
end)
-- save and restore local marks since they get deleted by nvim_buf_set_lines
- local marks = {}
+ local marks = {} --- @type table<string,[integer,integer]>
for _, m in pairs(vim.fn.getmarklist(bufnr)) do
if m.mark:match("^'[a-z]$") then
marks[m.mark:sub(2, 2)] = { m.pos[2], m.pos[3] - 1 } -- api-indexed
@@ -509,7 +516,6 @@ function M.apply_text_document_edit(text_document_edit, index, offset_encoding)
and (
text_document.version
and text_document.version > 0
- and M.buf_versions[bufnr]
and M.buf_versions[bufnr] > text_document.version
)
then
@@ -2215,6 +2221,11 @@ end
M._get_line_byte_from_position = get_line_byte_from_position
---@nodoc
-M.buf_versions = {} ---@type table<integer,integer>
+---@type table<integer,integer>
+M.buf_versions = setmetatable({}, {
+ __index = function(t, bufnr)
+ return rawget(t, bufnr) or 0
+ end,
+})
return M
diff --git a/runtime/lua/vim/text.lua b/runtime/lua/vim/text.lua
index bc90d490aa..0be3396464 100644
--- a/runtime/lua/vim/text.lua
+++ b/runtime/lua/vim/text.lua
@@ -18,15 +18,19 @@ end
--- Hex decode a string.
---
--- @param enc string String to decode
---- @return string : Decoded string
+--- @return string? : Decoded string
+--- @return string? : Error message, if any
function M.hexdecode(enc)
- assert(#enc % 2 == 0, 'string must have an even number of hex characters')
+ if #enc % 2 ~= 0 then
+ return nil, 'string must have an even number of hex characters'
+ end
+
local str = {} ---@type string[]
for i = 1, #enc, 2 do
local n = assert(tonumber(enc:sub(i, i + 1), 16))
str[#str + 1] = string.char(n)
end
- return table.concat(str)
+ return table.concat(str), nil
end
return M
diff --git a/runtime/lua/vim/treesitter/_fold.lua b/runtime/lua/vim/treesitter/_fold.lua
index eecf1ad6b1..04a3c62cf1 100644
--- a/runtime/lua/vim/treesitter/_fold.lua
+++ b/runtime/lua/vim/treesitter/_fold.lua
@@ -383,7 +383,6 @@ local function on_bytes(bufnr, foldinfo, start_row, start_col, old_row, old_col,
end
end
----@package
---@param lnum integer|nil
---@return string
function M.foldexpr(lnum)
diff --git a/runtime/lua/vim/treesitter/_meta.lua b/runtime/lua/vim/treesitter/_meta.lua
index 177699a207..2aedf5754e 100644
--- a/runtime/lua/vim/treesitter/_meta.lua
+++ b/runtime/lua/vim/treesitter/_meta.lua
@@ -33,6 +33,7 @@ error('Cannot require a meta file')
---@field iter_children fun(self: TSNode): fun(): TSNode, string
---@field field fun(self: TSNode, name: string): TSNode[]
---@field byte_length fun(self: TSNode): integer
+---@field __has_ancestor fun(self: TSNode, node_types: string[]): boolean
local TSNode = {}
---@alias TSLoggerCallback fun(logtype: 'parse'|'lex', msg: string)
@@ -62,6 +63,7 @@ local TSNode = {}
---@field patterns table<integer, (integer|string)[][]>
--- @param lang string
+--- @return table
vim._ts_inspect_language = function(lang) end
---@return integer
diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua
index d2f986b874..003f7e0169 100644
--- a/runtime/lua/vim/treesitter/highlighter.lua
+++ b/runtime/lua/vim/treesitter/highlighter.lua
@@ -47,7 +47,7 @@ function TSHighlighterQuery:get_hl_from_capture(capture)
return self.hl_cache[capture]
end
----@package
+---@nodoc
function TSHighlighterQuery:query()
return self._query
end
@@ -75,7 +75,7 @@ local TSHighlighter = {
TSHighlighter.__index = TSHighlighter
----@package
+---@nodoc
---
--- Creates a highlighter for `tree`.
---
@@ -232,7 +232,7 @@ function TSHighlighter:on_changedtree(changes)
end
--- Gets the query used for @param lang
----@package
+---@nodoc
---@param lang string Language used by the highlighter.
---@return vim.treesitter.highlighter.Query
function TSHighlighter:get_query(lang)
diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua
index b0812123b9..3523ea95e0 100644
--- a/runtime/lua/vim/treesitter/languagetree.lua
+++ b/runtime/lua/vim/treesitter/languagetree.lua
@@ -98,9 +98,9 @@ local LanguageTree = {}
LanguageTree.__index = LanguageTree
---- @package
+--- @nodoc
---
---- |LanguageTree| contains a tree of parsers: the root treesitter parser for {lang} and any
+--- LanguageTree contains a tree of parsers: the root treesitter parser for {lang} and any
--- "injected" language parsers, which themselves may inject other languages, recursively.
---
---@param source (integer|string) Buffer or text string to parse
@@ -951,7 +951,7 @@ function LanguageTree:_edit(
end
end
----@package
+---@nodoc
---@param bufnr integer
---@param changed_tick integer
---@param start_row integer
@@ -1023,12 +1023,12 @@ function LanguageTree:_on_bytes(
)
end
----@package
+---@nodoc
function LanguageTree:_on_reload()
self:invalidate(true)
end
----@package
+---@nodoc
function LanguageTree:_on_detach(...)
self:invalidate(true)
self:_do_callback('detach', ...)
diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
index f78a082cb7..9d5d3f5b96 100644
--- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
+++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
@@ -44,8 +44,13 @@
" - job_info && term_getjob -> nvim_get_chan_info
" - balloon -> vim.lsp.util.open_floating_preview
+func s:Echoerr(msg)
+ echohl ErrorMsg | echom '[termdebug] ' .. a:msg | echohl None
+endfunc
+
" In case this gets sourced twice.
if exists(':Termdebug')
+ call s:Echoerr('Termdebug already loaded.')
finish
endif
@@ -67,8 +72,8 @@ command -nargs=+ -complete=file -bang TermdebugCommand call s:StartDebugCommand(
let s:pc_id = 12
let s:asm_id = 13
let s:break_id = 14 " breakpoint number is added to this
-let s:stopped = 1
-let s:running = 0
+let s:stopped = v:true
+let s:running = v:false
let s:parsing_disasm_msg = 0
let s:asm_lines = []
@@ -121,10 +126,6 @@ func s:GetCommand()
return type(cmd) == v:t_list ? copy(cmd) : [cmd]
endfunc
-func s:Echoerr(msg)
- echohl ErrorMsg | echom '[termdebug] ' .. a:msg | echohl None
-endfunc
-
func s:StartDebug(bang, ...)
" First argument is the command to debug, second core file or process ID.
call s:StartDebug_internal({'gdb_args': a:000, 'bang': a:bang})
@@ -149,9 +150,9 @@ func s:StartDebug_internal(dict)
let s:ptywin = 0
let s:pid = 0
let s:asmwin = 0
- let s:asmbuf = 0
+ let s:asmbufnr = 0
let s:varwin = 0
- let s:varbuf = 0
+ let s:varbufnr = 0
if exists('#User#TermdebugStartPre')
doauto <nomodeline> User TermdebugStartPre
@@ -168,7 +169,7 @@ func s:StartDebug_internal(dict)
let s:signcolumn_buflist = [bufnr()]
let s:save_columns = 0
- let s:allleft = 0
+ let s:allleft = v:false
let wide = 0
if exists('g:termdebug_config')
let wide = get(g:termdebug_config, 'wide', 0)
@@ -181,11 +182,11 @@ func s:StartDebug_internal(dict)
let &columns = wide
" If we make the Vim window wider, use the whole left half for the debug
" windows.
- let s:allleft = 1
+ let s:allleft = v:true
endif
- let s:vertical = 1
+ let s:vertical = v:true
else
- let s:vertical = 0
+ let s:vertical = v:false
endif
" Override using a terminal window by setting g:termdebug_use_prompt to 1.
@@ -226,24 +227,24 @@ endfunc
" Use when debugger didn't start or ended.
func s:CloseBuffers()
- exe 'bwipe! ' . s:ptybuf
- if s:asmbuf > 0 && bufexists(s:asmbuf)
- exe 'bwipe! ' . s:asmbuf
+ exe 'bwipe! ' . s:ptybufnr
+ if s:asmbufnr > 0 && bufexists(s:asmbufnr)
+ exe 'bwipe! ' . s:asmbufnr
endif
- if s:varbuf > 0 && bufexists(s:varbuf)
- exe 'bwipe! ' . s:varbuf
+ if s:varbufnr > 0 && bufexists(s:varbufnr)
+ exe 'bwipe! ' . s:varbufnr
endif
- let s:running = 0
+ let s:running = v:false
unlet! s:gdbwin
endfunc
-func s:CheckGdbRunning()
+func s:IsGdbStarted()
if !s:gdb_running
call s:Echoerr(string(s:GetCommand()[0]) . ' exited unexpectedly')
call s:CloseBuffers()
- return ''
+ return v:false
endif
- return 'ok'
+ return v:true
endfunc
" Open a terminal window without a job, to run the debugged program in.
@@ -258,7 +259,7 @@ func s:StartDebug_term(dict)
return
endif
let pty_job_info = nvim_get_chan_info(s:pty_job_id)
- let s:ptybuf = pty_job_info['buffer']
+ let s:ptybufnr = pty_job_info['buffer']
let pty = pty_job_info['pty']
let s:ptywin = win_getid()
if s:vertical
@@ -279,11 +280,11 @@ func s:StartDebug_term(dict)
" hide terminal buffer
if s:comm_job_id == 0
call s:Echoerr('Invalid argument (or job table is full) while opening communication terminal window')
- exe 'bwipe! ' . s:ptybuf
+ exe 'bwipe! ' . s:ptybufnr
return
elseif s:comm_job_id == -1
call s:Echoerr('Failed to open the communication terminal window')
- exe 'bwipe! ' . s:ptybuf
+ exe 'bwipe! ' . s:ptybufnr
return
endif
let comm_job_info = nvim_get_chan_info(s:comm_job_id)
@@ -324,7 +325,7 @@ func s:StartDebug_term(dict)
let s:gdb_job_id = termopen(gdb_cmd, {'on_exit': function('s:EndTermDebug')})
if s:gdb_job_id == 0
call s:Echoerr('Invalid argument (or job table is full) while opening gdb terminal window')
- exe 'bwipe! ' . s:ptybuf
+ exe 'bwipe! ' . s:ptybufnr
return
elseif s:gdb_job_id == -1
call s:Echoerr('Failed to open the gdb terminal window')
@@ -334,18 +335,18 @@ func s:StartDebug_term(dict)
let s:gdb_running = v:true
let s:starting = v:true
let gdb_job_info = nvim_get_chan_info(s:gdb_job_id)
- let s:gdbbuf = gdb_job_info['buffer']
+ let s:gdbbufnr = gdb_job_info['buffer']
let s:gdbwin = win_getid()
" Wait for the "startupdone" message before sending any commands.
let try_count = 0
while 1
- if s:CheckGdbRunning() != 'ok'
+ if !s:IsGdbStarted()
return
endif
for lnum in range(1, 200)
- if get(getbufline(s:gdbbuf, lnum), 0, '') =~ 'startupdone'
+ if get(getbufline(s:gdbbufnr, lnum), 0, '') =~ 'startupdone'
let try_count = 9999
break
endif
@@ -371,14 +372,14 @@ func s:StartDebug_term(dict)
" why the debugger doesn't work.
let try_count = 0
while 1
- if s:CheckGdbRunning() != 'ok'
+ if !s:IsGdbStarted()
return
endif
let response = ''
for lnum in range(1, 200)
- let line1 = get(getbufline(s:gdbbuf, lnum), 0, '')
- let line2 = get(getbufline(s:gdbbuf, lnum + 1), 0, '')
+ let line1 = get(getbufline(s:gdbbufnr, lnum), 0, '')
+ let line2 = get(getbufline(s:gdbbufnr, lnum + 1), 0, '')
if line1 =~ 'new-ui mi '
" response can be in the same line or the next line
let response = line1 . line2
@@ -472,7 +473,7 @@ func s:StartDebug_prompt(dict)
\ })
if s:gdbjob == 0
call s:Echoerr('Invalid argument (or job table is full) while starting gdb job')
- exe 'bwipe! ' . s:ptybuf
+ exe 'bwipe! ' . s:ptybufnr
return
elseif s:gdbjob == -1
call s:Echoerr('Failed to start the gdb job')
@@ -481,7 +482,7 @@ func s:StartDebug_prompt(dict)
endif
exe $'au BufUnload <buffer={s:promptbuf}> ++once call jobstop(s:gdbjob)'
- let s:ptybuf = 0
+ let s:ptybufnr = 0
if has('win32')
" MS-Windows: run in a new console window for maximum compatibility
call s:SendCommand('set new-console on')
@@ -498,7 +499,7 @@ func s:StartDebug_prompt(dict)
return
endif
let pty_job_info = nvim_get_chan_info(s:pty_job_id)
- let s:ptybuf = pty_job_info['buffer']
+ let s:ptybufnr = pty_job_info['buffer']
let pty = pty_job_info['pty']
let s:ptywin = win_getid()
call s:SendCommand('tty ' . pty)
@@ -602,7 +603,7 @@ endfunc
func s:SendResumingCommand(cmd)
if s:stopped
" reset s:stopped here, it may take a bit of time before we get a response
- let s:stopped = 0
+ let s:stopped = v:false
" call ch_log('assume that program is running after this command')
call s:SendCommand(a:cmd)
" else
@@ -776,16 +777,16 @@ endfunc
func s:EndDebugCommon()
let curwinid = win_getid()
- if exists('s:ptybuf') && s:ptybuf
- exe 'bwipe! ' . s:ptybuf
+ if exists('s:ptybufnr') && s:ptybufnr
+ exe 'bwipe! ' . s:ptybufnr
endif
- if s:asmbuf > 0 && bufexists(s:asmbuf)
- exe 'bwipe! ' . s:asmbuf
+ if s:asmbufnr > 0 && bufexists(s:asmbufnr)
+ exe 'bwipe! ' . s:asmbufnr
endif
- if s:varbuf > 0 && bufexists(s:varbuf)
- exe 'bwipe! ' . s:varbuf
+ if s:varbufnr > 0 && bufexists(s:varbufnr)
+ exe 'bwipe! ' . s:varbufnr
endif
- let s:running = 0
+ let s:running = v:false
" Restore 'signcolumn' in all buffers for which it was set.
call win_gotoid(s:sourcewin)
@@ -1186,7 +1187,7 @@ endfunc
func s:Until(at)
if s:stopped
" reset s:stopped here, it may take a bit of time before we get a response
- let s:stopped = 0
+ let s:stopped = v:false
" call ch_log('assume that program is running after this command')
" Use the fname:lnum format
let at = empty(a:at) ?
@@ -1322,9 +1323,9 @@ func s:Evaluate(range, arg)
return
endif
let expr = s:GetEvaluationExpression(a:range, a:arg)
- let s:evalFromBalloonExpr = 1
+ let s:evalFromBalloonExpr = v:true
let s:evalFromBalloonExprResult = ''
- let s:ignoreEvalError = 0
+ let s:ignoreEvalError = v:false
call s:SendEval(expr)
endfunc
@@ -1343,12 +1344,12 @@ func s:GetEvaluationExpression(range, arg)
let expr = s:CleanupExpr(@v)
call setpos('.', pos)
call setreg('v', reg, regt)
- let s:evalFromBalloonExpr = 1
+ let s:evalFromBalloonExpr = v:true
else
" no evaluation provided: get from C-expression under cursor
" TODO: allow filetype specific lookup #9057
let expr = expand('<cexpr>')
- let s:evalFromBalloonExpr = 1
+ let s:evalFromBalloonExpr = v:true
endif
return expr
endfunc
@@ -1376,8 +1377,8 @@ func s:CleanupExpr(expr)
return expr
endfunc
-let s:ignoreEvalError = 0
-let s:evalFromBalloonExpr = 0
+let s:ignoreEvalError = v:false
+let s:evalFromBalloonExpr = v:false
let s:evalFromBalloonExprResult = ''
let s:eval_float_win_id = -1
@@ -1419,7 +1420,7 @@ func s:HandleEvaluate(msg)
if s:evalexpr[0] != '*' && value =~ '^0x' && value != '0x0' && value !~ '"$'
" Looks like a pointer, also display what it points to.
- let s:ignoreEvalError = 1
+ let s:ignoreEvalError = v:true
call s:SendEval('*' . s:evalexpr)
endif
endfunc
@@ -1428,8 +1429,8 @@ endfunc
func s:HandleError(msg)
if s:ignoreEvalError
" Result of s:SendEval() failed, ignore.
- let s:ignoreEvalError = 0
- let s:evalFromBalloonExpr = 0
+ let s:ignoreEvalError = v:false
+ let s:evalFromBalloonExpr = v:false
return
endif
let msgVal = substitute(a:msg, '.*msg="\(.*\)"', '\1', '')
@@ -1489,11 +1490,11 @@ func s:GotoAsmwinOrCreateIt()
setlocal signcolumn=no
setlocal modifiable
- if s:asmbuf > 0 && bufexists(s:asmbuf)
- exe 'buffer' . s:asmbuf
+ if s:asmbufnr > 0 && bufexists(s:asmbufnr)
+ exe 'buffer' . s:asmbufnr
elseif empty(glob('Termdebug-asm-listing'))
silent file Termdebug-asm-listing
- let s:asmbuf = bufnr('Termdebug-asm-listing')
+ let s:asmbufnr = bufnr('Termdebug-asm-listing')
else
call s:Echoerr("You have a file/folder named 'Termdebug-asm-listing'.
\ Please exit and rename it because Termdebug may not work as expected.")
@@ -1561,11 +1562,11 @@ func s:GotoVariableswinOrCreateIt()
setlocal signcolumn=no
setlocal modifiable
- if s:varbuf > 0 && bufexists(s:varbuf)
- exe 'buffer' . s:varbuf
+ if s:varbufnr > 0 && bufexists(s:varbufnr)
+ exe 'buffer' . s:varbufnr
elseif empty(glob('Termdebug-variables-listing'))
silent file Termdebug-variables-listing
- let s:varbuf = bufnr('Termdebug-variables-listing')
+ let s:varbufnr = bufnr('Termdebug-variables-listing')
else
call s:Echoerr("You have a file/folder named 'Termdebug-variables-listing'.
\ Please exit and rename it because Termdebug may not work as expected.")
@@ -1588,14 +1589,14 @@ func s:HandleCursor(msg)
if a:msg =~ '^\*stopped'
"call ch_log('program stopped')
- let s:stopped = 1
+ let s:stopped = v:true
if a:msg =~ '^\*stopped,reason="exited-normally"'
- let s:running = 0
+ let s:running = v:false
endif
elseif a:msg =~ '^\*running'
"call ch_log('program running')
- let s:stopped = 0
- let s:running = 1
+ let s:stopped = v:false
+ let s:running = v:true
endif
if a:msg =~ 'fullname='
diff --git a/runtime/syntax/deb822sources.vim b/runtime/syntax/deb822sources.vim
index f7d337fce9..ec45605905 100644
--- a/runtime/syntax/deb822sources.vim
+++ b/runtime/syntax/deb822sources.vim
@@ -40,7 +40,7 @@ syn match deb822sourcesUri '\(https\?://\|ftp://\|[rs]sh://\|debtorre
syn region deb822sourcesStrictField matchgroup=deb822sourcesEntryField start="^\%(Types\|URIs\|Suites\|Components\): *" end="$" contains=deb822sourcesType,deb822sourcesUri,deb822sourcesSupportedSuites,deb822sourcesUnsupportedSuites,deb822sourcesFreeComponent,deb822sourcesNonFreeComponent oneline
syn region deb822sourcesField matchgroup=deb822sourcesOptionField start="^\%(Signed-By\|Check-Valid-Until\|Valid-Until-Min\|Valid-Until-Max\|Date-Max-Future\|InRelease-Path\): *" end="$" oneline
syn region deb822sourcesField matchgroup=deb822sourcesMultiValueOptionField start="^\%(Architectures\|Languages\|Targets\)\%(-Add\|-Remove\)\?: *" end="$" oneline
-syn region deb822sourcesStrictField matchgroup=deb822sourcesBooleanOptionField start="^\%(PDiffs\|Allow-Insecure\|Allow-Weak\|Allow-Downgrade-To-Insecure\|Trusted\|Check-Date\): *" end="$" contains=deb822sourcesYesNo oneline
+syn region deb822sourcesStrictField matchgroup=deb822sourcesBooleanOptionField start="^\%(PDiffs\|Allow-Insecure\|Allow-Weak\|Allow-Downgrade-To-Insecure\|Trusted\|Check-Date\|Enabled\): *" end="$" contains=deb822sourcesYesNo oneline
syn region deb822sourcesStrictField matchgroup=deb822sourcesForceBooleanOptionField start="^\%(By-Hash\): *" end="$" contains=deb822sourcesForce,deb822sourcesYesNo oneline
hi def link deb822sourcesField Default
diff --git a/runtime/syntax/html.vim b/runtime/syntax/html.vim
index c975ae8620..d067dde83c 100644
--- a/runtime/syntax/html.vim
+++ b/runtime/syntax/html.vim
@@ -191,7 +191,7 @@ syn keyword htmlArg contained step title translate typemustmatch
syn match htmlArg contained "\<data-\h\%(\w\|[-.]\)*\%(\_s*=\)\@="
" special characters
-syn match htmlSpecialChar "&#\=[0-9A-Za-z]\{1,8};"
+syn match htmlSpecialChar "&#\=[0-9A-Za-z]\{1,32};"
" Comments (the real ones or the old netscape ones)
if exists("html_wrong_comments")
diff --git a/runtime/syntax/java.vim b/runtime/syntax/java.vim
index f5910a8557..6f64bdc4ed 100644
--- a/runtime/syntax/java.vim
+++ b/runtime/syntax/java.vim
@@ -3,7 +3,7 @@
" Maintainer: Aliaksei Budavei <0x000c70 AT gmail DOT com>
" Former Maintainer: Claudio Fleiner <claudio@fleiner.com>
" Repository: https://github.com/zzzyxwvut/java-vim.git
-" Last Change: 2024 Jun 08
+" Last Change: 2024 Jun 15
" Please check :help java.vim for comments on some of the options available.
@@ -14,7 +14,6 @@ if !exists("main_syntax")
endif
" we define it here so that included files can test for it
let main_syntax='java'
- syn region javaFold start="{" end="}" transparent fold
endif
let s:cpo_save = &cpo
@@ -40,6 +39,18 @@ else
endfunction
endif
+function! JavaSyntaxFoldTextExpr() abort
+ return getline(v:foldstart) !~ '/\*\+\s*$'
+ \ ? foldtext()
+ \ : printf('+-%s%3d lines: ',
+ \ v:folddashes,
+ \ (v:foldend - v:foldstart + 1)) .
+ \ getline(v:foldstart + 1)
+endfunction
+
+" E120 for "fdt=s:JavaSyntaxFoldTextExpr()" before v8.2.3900.
+setlocal foldtext=JavaSyntaxFoldTextExpr()
+
" Admit the ASCII dollar sign to keyword characters (JLS-17, §3.8):
try
exec 'syntax iskeyword ' . &l:iskeyword . ',$'
@@ -99,6 +110,7 @@ syn match javaClassDecl "\<record\>\%(\s*(\)\@!"
syn match javaClassDecl "^class\>"
syn match javaClassDecl "[^.]\s*\<class\>"ms=s+1
syn match javaAnnotation "@\%(\K\k*\.\)*\K\k*\>"
+syn region javaAnnotation transparent matchgroup=javaAnnotationStart start=/@\%(\K\k*\.\)*\K\k*(/ end=/)/ skip=/\/\*.\{-}\*\/\|\/\/.*$/ contains=javaAnnotation,javaParenT,javaBlock,javaString,javaBoolean,javaNumber,javaTypedef,javaComment,javaLineComment
syn match javaClassDecl "@interface\>"
syn keyword javaBranch break continue nextgroup=javaUserLabelRef skipwhite
syn match javaUserLabelRef "\k\+" contained
@@ -237,7 +249,7 @@ if exists("java_comment_strings")
syn cluster javaCommentSpecial2 add=javaComment2String,javaCommentCharacter,javaNumber,javaStrTempl
endif
-syn region javaComment matchgroup=javaCommentStart start="/\*" end="\*/" contains=@javaCommentSpecial,javaTodo,javaCommentError,javaSpaceError,@Spell
+syn region javaComment matchgroup=javaCommentStart start="/\*" end="\*/" contains=@javaCommentSpecial,javaTodo,javaCommentError,javaSpaceError,@Spell fold
syn match javaCommentStar contained "^\s*\*[^/]"me=e-1
syn match javaCommentStar contained "^\s*\*$"
syn match javaLineComment "//.*" contains=@javaCommentSpecial2,javaTodo,javaCommentMarkupTag,javaSpaceError,@Spell
@@ -268,7 +280,7 @@ if !exists("java_ignore_javadoc") && main_syntax != 'jsp'
call s:ReportOnce(v:exception)
endtry
- syn region javaDocComment start="/\*\*" end="\*/" keepend contains=javaCommentTitle,@javaHtml,javaDocTags,javaDocSeeTag,javaDocCodeTag,javaDocSnippetTag,javaTodo,javaCommentError,javaSpaceError,@Spell
+ syn region javaDocComment start="/\*\*" end="\*/" keepend contains=javaCommentTitle,@javaHtml,javaDocTags,javaDocSeeTag,javaDocCodeTag,javaDocSnippetTag,javaTodo,javaCommentError,javaSpaceError,@Spell fold
exec 'syn region javaCommentTitle contained matchgroup=javaDocComment start="/\*\*" matchgroup=javaCommentTitle end="\.$" end="\.[ \t\r]\@=" end="\%(^\s*\**\s*\)\@' . s:ff.Peek('80', '') . '<=@"me=s-2,he=s-1 end="\*/"me=s-1,he=s-1 contains=@javaHtml,javaCommentStar,javaTodo,javaCommentError,javaSpaceError,@Spell,javaDocTags,javaDocSeeTag,javaDocCodeTag,javaDocSnippetTag'
syn region javaCommentTitle contained matchgroup=javaDocComment start="/\*\*\s*\r\=\n\=\s*\**\s*\%({@return\>\)\@=" matchgroup=javaCommentTitle end="}\%(\s*\.*\)*" contains=@javaHtml,javaCommentStar,javaTodo,javaCommentError,javaSpaceError,@Spell,javaDocTags,javaDocSeeTag,javaDocCodeTag,javaDocSnippetTag
syn region javaDocTags contained start="{@\%(li\%(teral\|nk\%(plain\)\=\)\|inherit[Dd]oc\|doc[rR]oot\|value\)\>" end="}"
@@ -347,8 +359,6 @@ if exists("java_highlight_functions")
" Match: [@ɐ] [abstract] [<α, β>] Τʬ[<γ>][[][]] μʭʭ(/* ... */);
exec 'syn region javaFuncDef start=/' . s:ff.Engine('\%#=2', '') . '^\s\+\%(\%(@\%(\K\k*\.\)*\K\k*\>\)\s\+\)*\%(p\%(ublic\|rotected\|rivate\)\s\+\)\=\%(\%(abstract\|default\)\s\+\|\%(\%(final\|\%(native\|strictfp\)\|s\%(tatic\|ynchronized\)\)\s\+\)*\)\=\%(<.*[[:space:]-]\@' . s:ff.Peek('1', '') . '<!>\s\+\)\=\%(void\|\%(b\%(oolean\|yte\)\|char\|short\|int\|long\|float\|double\|\%(\<\K\k*\>\.\)*\<' . s:ff.UpperCase('[$_[:upper:]]', '[^a-z0-9]') . '\k*\>\%(<[^(){}]*[[:space:]-]\@' . s:ff.Peek('1', '') . '<!>\)\=\)\%(\[\]\)*\)\s\+\<' . s:ff.LowerCase('[$_[:lower:]]', '[^A-Z0-9]') . '\k*\>\s*(/ end=/)/ skip=/\/\*.\{-}\*\/\|\/\/.*$/ contains=@javaFuncParams'
endif
-
- syn match javaBraces "[{}]"
endif
if exists("java_highlight_debug")
@@ -403,14 +413,18 @@ if exists("java_highlight_debug")
endif
if exists("java_mark_braces_in_parens_as_errors")
- syn match javaInParen contained "[{}]"
- hi def link javaInParen javaError
+ syn match javaInParen contained "[{}]"
+ hi def link javaInParen javaError
endif
+" Try not to fold top-level-type bodies under assumption that there is
+" but one such body.
+exec 'syn region javaBlock transparent start="\%(^\|^\S[^:]\+\)\@' . s:ff.Peek('120', '') . '<!{" end="}" fold'
+
" catch errors caused by wrong parenthesis
-syn region javaParenT transparent matchgroup=javaParen start="(" end=")" contains=@javaTop,javaParenT1
-syn region javaParenT1 transparent matchgroup=javaParen1 start="(" end=")" contains=@javaTop,javaParenT2 contained
-syn region javaParenT2 transparent matchgroup=javaParen2 start="(" end=")" contains=@javaTop,javaParenT contained
+syn region javaParenT transparent matchgroup=javaParen start="(" end=")" contains=@javaTop,javaInParen,javaParenT1
+syn region javaParenT1 transparent matchgroup=javaParen1 start="(" end=")" contains=@javaTop,javaInParen,javaParenT2 contained
+syn region javaParenT2 transparent matchgroup=javaParen2 start="(" end=")" contains=@javaTop,javaInParen,javaParenT contained
syn match javaParenError ")"
" catch errors caused by wrong square parenthesis
syn region javaParenT transparent matchgroup=javaParen start="\[" end="\]" contains=@javaTop,javaParenT1
@@ -444,7 +458,7 @@ endif
" The @javaTop cluster comprises non-contained Java syntax groups.
" Note that the syntax file "aidl.vim" relies on its availability.
-syn cluster javaTop contains=TOP,javaDocComment,javaFold,javaParenError,javaParenT
+syn cluster javaTop contains=TOP,javaDocComment,javaBlock,javaParenError,javaParenT
if !exists("java_minlines")
let java_minlines = 10
@@ -462,7 +476,6 @@ exec "syn sync ccomment javaComment minlines=" . java_minlines
hi def link javaLambdaDef Function
hi def link javaFuncDef Function
hi def link javaVarArg Function
-hi def link javaBraces Function
hi def link javaBranch Conditional
hi def link javaUserLabelRef javaUserLabel
hi def link javaLabel Label
@@ -497,6 +510,7 @@ hi def link javaConstant Constant
hi def link javaTypedef Typedef
hi def link javaTodo Todo
hi def link javaAnnotation PreProc
+hi def link javaAnnotationStart javaAnnotation
hi def link javaCommentTitle SpecialComment
hi def link javaDocTags Special
@@ -531,4 +545,20 @@ let b:spell_options = "contained"
let &cpo = s:cpo_save
unlet s:module_info_cur_buf s:ff s:cpo_save
+" See ":help vim9-mix".
+if !has("vim9script")
+ finish
+endif
+
+def! s:JavaSyntaxFoldTextExpr(): string
+ return getline(v:foldstart) !~ '/\*\+\s*$'
+ ? foldtext()
+ : printf('+-%s%3d lines: ',
+ v:folddashes,
+ (v:foldend - v:foldstart + 1)) ..
+ getline(v:foldstart + 1)
+enddef
+
+setlocal foldtext=s:JavaSyntaxFoldTextExpr()
+delfunction! g:JavaSyntaxFoldTextExpr
" vim: sw=2 ts=8 noet sta
diff --git a/runtime/syntax/kdl.vim b/runtime/syntax/kdl.vim
new file mode 100644
index 0000000000..97e8f93b61
--- /dev/null
+++ b/runtime/syntax/kdl.vim
@@ -0,0 +1,48 @@
+" Vim syntax file
+" Language: KDL
+" Maintainer: Aram Drevekenin <aram@poor.dev>
+" Maintainer: Yinzuo Jiang <jiangyinzuo@foxmail.com>
+" Latest Revision: 2024-06-16
+
+" quit when a syntax file was already loaded
+if exists("b:current_syntax")
+ finish
+endif
+
+syn match kdlNode '\v(\w|-|\=)' display
+syn match kdlBool '\v(true|false)' display
+
+syn keyword kdlTodo contained TODO FIXME XXX NOTE
+syn region kdlComment start="//" end="$" contains=kdlTodo,@Spell
+syn region kdlComment start="/\*" end="\*/" contains=kdlTodo,@Spell
+
+" Regular int like number with - + or nothing in front
+syn match kdlNumber '\d\+'
+syn match kdlNumber '[-+]\d\+'
+
+" Floating point number with decimal no E or e (+,-)
+syn match kdlNumber '\d\+\.\d*' contained display
+syn match kdlNumber '[-+]\d\+\.\d*' contained display
+
+" Floating point like number with E and no decimal point (+,-)
+syn match kdlNumber '[-+]\=\d[[:digit:]]*[eE][\-+]\=\d\+' contained display
+syn match kdlNumber '\d[[:digit:]]*[eE][\-+]\=\d\+' contained display
+
+" Floating point like number with E and decimal point (+,-)
+syn match kdlNumber '[-+]\=\d[[:digit:]]*\.\d*[eE][\-+]\=\d\+' contained display
+syn match kdlNumber '\d[[:digit:]]*\.\d*[eE][\-+]\=\d\+' contained display
+
+syn region kdlString start='"' end='"' skip='\\\\\|\\"' display
+
+syn region kdlChildren start="{" end="}" contains=kdlString,kdlNumber,kdlNode,kdlBool,kdlComment
+
+hi def link kdlTodo Todo
+hi def link kdlComment Comment
+hi def link kdlNode Statement
+hi def link kdlBool Boolean
+hi def link kdlString String
+hi def link kdlNumber Number
+
+let b:current_syntax = "kdl"
+
+" vim: sw=2 sts=2 et
diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim
index 6cb75f3af4..a3b0117e9d 100644
--- a/runtime/syntax/vim.vim
+++ b/runtime/syntax/vim.vim
@@ -60,9 +60,9 @@ syn case ignore
syn keyword vimGroup contained Comment Constant String Character Number Boolean Float Identifier Function Statement Conditional Repeat Label Operator Keyword Exception PreProc Include Define Macro PreCondit Type StorageClass Structure Typedef Special SpecialChar Tag Delimiter SpecialComment Debug Underlined Ignore Error Todo
" Default highlighting groups {{{2
-syn keyword vimHLGroup contained ErrorMsg IncSearch ModeMsg NonText StatusLine StatusLineNC EndOfBuffer VertSplit DiffText PmenuSbar TabLineSel TabLineFill Cursor lCursor QuickFixLine CursorLineSign CursorLineFold CurSearch PmenuKind PmenuKindSel PmenuExtra PmenuExtraSel Normal Directory LineNr CursorLineNr MoreMsg Question Search SpellBad SpellCap SpellRare SpellLocal PmenuThumb Pmenu PmenuSel SpecialKey Title WarningMsg WildMenu Folded FoldColumn SignColumn Visual DiffAdd DiffChange DiffDelete TabLine CursorColumn CursorLine ColorColumn MatchParen CursorIM LineNrAbove LineNrBelow
+syn keyword vimHLGroup contained ErrorMsg IncSearch ModeMsg NonText StatusLine StatusLineNC EndOfBuffer VertSplit DiffText PmenuSbar TabLineSel TabLineFill Cursor lCursor QuickFixLine CursorLineSign CursorLineFold CurSearch PmenuKind PmenuKindSel PmenuMatch PmenuMatchSel PmenuExtra PmenuExtraSel Normal Directory LineNr CursorLineNr MoreMsg Question Search SpellBad SpellCap SpellRare SpellLocal PmenuThumb Pmenu PmenuSel SpecialKey Title WarningMsg WildMenu Folded FoldColumn SignColumn Visual DiffAdd DiffChange DiffDelete TabLine CursorColumn CursorLine ColorColumn MatchParen StatusLineTerm StatusLineTermNC CursorIM LineNrAbove LineNrBelow
syn match vimHLGroup contained "\<Conceal\>"
-syn keyword vimOnlyHLGroup contained Menu Scrollbar StatusLineTerm StatusLineTermNC ToolbarButton ToolbarLine Tooltip VisualNOS
+syn keyword vimOnlyHLGroup contained Menu Scrollbar ToolbarButton ToolbarLine Tooltip VisualNOS
syn keyword nvimHLGroup contained FloatBorder FloatFooter FloatTitle MsgSeparator NormalFloat NormalNC Substitute TermCursor TermCursorNC VisualNC Whitespace WinBar WinBarNC WinSeparator
"}}}2
syn case match
@@ -165,7 +165,7 @@ syn match vimNumber '\%(^\|\A\)\zs#\x\{6}' skipwhite nextgroup=vimGlobal,vimSub
syn case match
" All vimCommands are contained by vimIsCommand. {{{2
-syn cluster vimCmdList contains=vimAbb,vimAddress,vimAutoCmd,vimAugroup,vimBehave,vimDef,@vimEcho,vimEnddef,vimEndfunction,vimExecute,vimIsCommand,vimExtCmd,vimFor,vimFunction,vimGlobal,vimHighlight,vimLet,vimMap,vimMark,vimNotFunc,vimNorm,vimSet,vimSyntax,vimUnlet,vimUnmap,vimUserCmd,vimMenu,vimMenutranslate
+syn cluster vimCmdList contains=vimAbb,vimAddress,vimAutoCmd,vimAugroup,vimBehave,vimCatch,vimDef,@vimEcho,vimEnddef,vimEndfunction,vimExecute,vimIsCommand,vimExtCmd,vimFor,vimFunction,vimGlobal,vimHighlight,vimLet,vimMap,vimMark,vimNotFunc,vimNorm,vimSet,vimSleep,vimSyntax,vimThrow,vimUnlet,vimUnmap,vimUserCmd,vimMenu,vimMenutranslate
syn match vimCmdSep "[:|]\+" skipwhite nextgroup=@vimCmdList,vimSubst1
syn match vimIsCommand "\<\%(\h\w*\|[23]mat\%[ch]\)\>" contains=vimCommand
syn match vimVar contained "\<\h[a-zA-Z0-9#_]*\>"
@@ -196,6 +196,11 @@ syn match vimBehave "\<be\%[have]\>" nextgroup=vimBehaveBang,vimBehaveModel,vi
syn match vimBehaveBang contained "\a\@1<=!" nextgroup=vimBehaveModel skipwhite
syn keyword vimBehaveModel contained mswin xterm
+" Exception Handling {{{2
+syn keyword vimThrow th[row] skipwhite nextgroup=@vimExprList
+syn keyword vimCatch cat[ch] skipwhite nextgroup=vimCatchPattern
+syn region vimCatchPattern contained matchgroup=Delimiter start="\z([!#$%&'()*+,-./:;<=>?@[\]^_`{}~]\)" skip="\\\\\|\\\z1" end="\z1" contains=@vimSubstList oneline
+
" Filetypes {{{2
" =========
syn match vimFiletype "\<filet\%[ype]\(\s\+\I\i*\)*" skipwhite contains=vimFTCmd,vimFTOption,vimFTError
@@ -359,7 +364,9 @@ syn region vimUserCmdBlock contained matchgroup=vimSep start="{" end="}" contain
" Lower Priority Comments: after some vim commands... {{{2
" =======================
-syn region vimCommentString contained oneline start='\S\s\+"'ms=e end='"'
+if get(g:, "vimsyn_comment_strings", 1)
+ syn region vimCommentString contained oneline start='\S\s\+"'ms=e end='"'
+endif
if s:vim9script
syn match vimComment excludenl +\s"[^\-:.%#=*].*$+lc=1 contains=@vimCommentGroup,vimCommentString contained
@@ -640,6 +647,12 @@ syn match vimNotFunc "\<if\>\|\<el\%[seif]\>\|\<retu\%[rn]\>\|\<while\>" skipwhi
syn match vimNorm "\<norm\%[al]!\=" skipwhite nextgroup=vimNormCmds
syn match vimNormCmds contained ".*$"
+" Sleep: {{{2
+" =====
+syn keyword vimSleep sl[eep] skipwhite nextgroup=vimSleepBang,vimSleepArg
+syn match vimSleepBang contained "\a\@1<=!" skipwhite nextgroup=vimSleepArg
+syn match vimSleepArg contained "\<\%(\d\+\)\=m\=\>"
+
" Syntax: {{{2
"=======
syn match vimGroupList contained "[^[:space:],]\+\%(\s*,\s*[^[:space:],]\+\)*" contains=vimGroupSpecial
@@ -806,16 +819,23 @@ syn match vimCtrlChar "[- -]"
" Beginners - Patterns that involve ^ {{{2
" =========
if s:vim9script
- syn match vimLineComment +^[ \t:]*".*$+ contains=@vimCommentGroup,vimCommentString,vimCommentTitle contained
- syn match vim9LineComment +^[ \t:]*#.*$+ contains=@vimCommentGroup,vimCommentString,vim9CommentTitle
+ syn region vim9LineComment start=+^[ \t:]*\zs#.*$+ skip=+\n\s*\\\|\n\s*#\\ + end="$" contains=@vimCommentGroup,vimCommentString,vim9CommentTitle
+ syn region vimLineComment start=+^[ \t:]*\zs".*$+ skip=+\n\s*\\\|\n\s*"\\ + end="$" contains=@vimCommentGroup,vimCommentString,vimCommentTitle contained
else
- syn match vimLineComment +^[ \t:]*".*$+ contains=@vimCommentGroup,vimCommentString,vimCommentTitle
- syn match vim9LineComment +^[ \t:]*#.*$+ contains=@vimCommentGroup,vimCommentString,vim9CommentTitle contained
+ syn region vimLineComment start=+^[ \t:]*\zs".*$+ skip=+\n\s*\\\|\n\s*"\\ + end="$" contains=@vimCommentGroup,vimCommentString,vimCommentTitle
+ syn region vim9LineComment start=+^[ \t:]*\zs#.*$+ skip=+\n\s*\\\|\n\s*#\\ + end="$" contains=@vimCommentGroup,vimCommentString,vim9CommentTitle contained
endif
syn match vimCommentTitle '"\s*\%([sS]:\|\h\w*#\)\=\u\w*\(\s\+\u\w*\)*:'hs=s+1 contained contains=vimCommentTitleLeader,vimTodo,@vimCommentGroup
syn match vim9CommentTitle '#\s*\%([sS]:\|\h\w*#\)\=\u\w*\(\s\+\u\w*\)*:'hs=s+1 contained contains=vim9CommentTitleLeader,vimTodo,@vimCommentGroup
+
+" allowed anywhere in the file
+if !s:vim9script
+ syn match vimShebangError "^\s*\zs#!.*" display
+endif
+syn match vimShebang "\%^#!.*" display
+
syn match vimContinue "^\s*\zs\\"
-syn match vimContinueComment '^\s*\zs["#]\\ .*' contained
+syn match vimContinueComment '^\s*\zs["#]\\ .*'
syn cluster vimContinue contains=vimContinue,vimContinueComment
syn region vimString start="^\s*\\\z(['"]\)" skip='\\\\\|\\\z1' end="\z1" oneline keepend contains=@vimStringGroup,vimContinue
syn match vimCommentTitleLeader '"\s\+'ms=s+1 contained
@@ -1044,6 +1064,7 @@ if !exists("skip_vim_syntax_inits")
hi def link vimHiCtermError vimError
hi def link vimHiKeyError vimError
hi def link vimMapModErr vimError
+ hi def link vimShebangError vimError
hi def link vimSubstFlagErr vimError
hi def link vimSynCaseError vimError
hi def link vimSynFoldMethodError vimError
@@ -1064,6 +1085,7 @@ if !exists("skip_vim_syntax_inits")
hi def link vimBehaveModel vimBehave
hi def link vimBehave vimCommand
hi def link vimBracket Delimiter
+ hi def link vimCatch vimCommand
hi def link vimCmplxRepeat SpecialChar
hi def link vimCommand Statement
hi def link vimComment Comment
@@ -1181,6 +1203,10 @@ if !exists("skip_vim_syntax_inits")
hi def link vimSetSep Statement
hi def link vimSetString vimString
hi def link vim9Vim9Script vimCommand
+ hi def link vimShebang PreProc
+ hi def link vimSleep vimCommand
+ hi def link vimSleepArg Constant
+ hi def link vimSleepBang vimBang
hi def link vimSpecFile Identifier
hi def link vimSpecFileMod vimSpecFile
hi def link vimSpecial Type
@@ -1221,6 +1247,7 @@ if !exists("skip_vim_syntax_inits")
hi def link vimSynReg Type
hi def link vimSyntax vimCommand
hi def link vimSynType vimSpecial
+ hi def link vimThrow vimCommand
hi def link vimTodo Todo
hi def link vimType Type
hi def link vimUnlet vimCommand
diff --git a/scripts/gen_vimdoc.lua b/scripts/gen_vimdoc.lua
index 507426c8c0..dc384c12f5 100755
--- a/scripts/gen_vimdoc.lua
+++ b/scripts/gen_vimdoc.lua
@@ -421,8 +421,11 @@ local function render_type(ty, generics, default)
end
--- @param p nvim.luacats.parser.param|nvim.luacats.parser.field
-local function should_render_param(p)
- return not p.access and not contains(p.name, { '_', 'self' })
+local function should_render_field_or_param(p)
+ return not p.nodoc
+ and not p.access
+ and not contains(p.name, { '_', 'self' })
+ and not vim.startswith(p.name, '_')
end
--- @param desc? string
@@ -524,7 +527,7 @@ end
local function render_fields_or_params(xs, generics, classes, exclude_types)
local ret = {} --- @type string[]
- xs = vim.tbl_filter(should_render_param, xs)
+ xs = vim.tbl_filter(should_render_field_or_param, xs)
local indent = 0
for _, p in ipairs(xs) do
diff --git a/scripts/luacats_grammar.lua b/scripts/luacats_grammar.lua
index 9360eb9417..ebb0183fd9 100644
--- a/scripts/luacats_grammar.lua
+++ b/scripts/luacats_grammar.lua
@@ -178,7 +178,8 @@ local grammar = P {
table_elem = v.table_key * colon * v.ltype,
ty_table = Pf('{') * comma1(v.table_elem) * fill * P('}'),
fun_param = lname * opt(colon * v.ltype),
- ty_fun = Pf('fun') * paren(comma(lname * opt(colon * v.ltype))) * opt(colon * comma1(v.ltype)),
+ fun_ret = v.ltype + (ident * colon * v.ltype) + (P('...') * opt(colon * v.ltype)),
+ ty_fun = Pf('fun') * paren(comma(lname * opt(colon * v.ltype))) * opt(colon * comma1(v.fun_ret)),
ty_generic = P('`') * letter * P('`'),
ty_tuple = Pf('[') * comma(v.ltype) * fill * P(']'),
}
diff --git a/scripts/luacats_parser.lua b/scripts/luacats_parser.lua
index 66fe8ed616..e73a42111d 100644
--- a/scripts/luacats_parser.lua
+++ b/scripts/luacats_parser.lua
@@ -46,6 +46,7 @@ local luacats_grammar = require('scripts.luacats_grammar')
--- @field type string
--- @field desc string
--- @field access? 'private'|'package'|'protected'
+--- @field nodoc? true
--- @class nvim.luacats.parser.class
--- @field kind 'class'
@@ -270,6 +271,7 @@ local function fun2field(fun)
type = table.concat(parts, ''),
access = fun.access,
desc = fun.desc,
+ nodoc = fun.nodoc,
}
end
diff --git a/src/clint.py b/src/clint.py
index 41058469b1..051f0e91e5 100755
--- a/src/clint.py
+++ b/src/clint.py
@@ -1995,7 +1995,7 @@ def CheckLanguage(filename, clean_lines, linenum, error):
if match:
error(filename, linenum, 'runtime/printf', 4,
'Use xstrlcpy, xmemcpyz or snprintf instead of %s' % match.group(1))
- match = Search(r'\b(STRNCAT|strncat|strcat|vim_strcat)\b', line)
+ match = Search(r'\b(STRNCAT|strncat|vim_strcat)\b', line)
if match:
error(filename, linenum, 'runtime/printf', 4,
'Use xstrlcat or snprintf instead of %s' % match.group(1))
diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c
index ab6ff5ff1f..e30ec9a2ca 100644
--- a/src/nvim/api/extmark.c
+++ b/src/nvim/api/extmark.c
@@ -1002,7 +1002,7 @@ void nvim_buf_clear_namespace(Buffer buffer, Integer ns_id, Integer line_start,
/// Note: this function should not be called often. Rather, the callbacks
/// themselves can be used to throttle unneeded callbacks. the `on_start`
/// callback can return `false` to disable the provider until the next redraw.
-/// Similarly, return `false` in `on_win` will skip the `on_lines` calls
+/// Similarly, return `false` in `on_win` will skip the `on_line` calls
/// for that window (but any extmarks set in `on_win` will still be used).
/// A plugin managing multiple sources of decoration should ideally only set
/// one provider, and merge the sources internally. You can use multiple `ns_id`
@@ -1011,10 +1011,10 @@ void nvim_buf_clear_namespace(Buffer buffer, Integer ns_id, Integer line_start,
/// Note: doing anything other than setting extmarks is considered experimental.
/// Doing things like changing options are not explicitly forbidden, but is
/// likely to have unexpected consequences (such as 100% CPU consumption).
-/// doing `vim.rpcnotify` should be OK, but `vim.rpcrequest` is quite dubious
+/// Doing `vim.rpcnotify` should be OK, but `vim.rpcrequest` is quite dubious
/// for the moment.
///
-/// Note: It is not allowed to remove or update extmarks in 'on_line' callbacks.
+/// Note: It is not allowed to remove or update extmarks in `on_line` callbacks.
///
/// @param ns_id Namespace id from |nvim_create_namespace()|
/// @param opts Table of callbacks:
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index a17e78cc31..ac621b1486 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -548,10 +548,6 @@ String buf_get_text(buf_T *buf, int64_t lnum, int64_t start_col, int64_t end_col
void api_free_string(String value)
{
- if (!value.data) {
- return;
- }
-
xfree(value.data);
}
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
index e5872fcc76..c32d33080e 100644
--- a/src/nvim/autocmd.c
+++ b/src/nvim/autocmd.c
@@ -711,7 +711,7 @@ char *au_event_disable(char *what)
if (*what == ',' && *p_ei == NUL) {
STRCPY(new_ei, what + 1);
} else {
- STRCAT(new_ei, what);
+ strcat(new_ei, what);
}
set_option_direct(kOptEventignore, CSTR_AS_OPTVAL(new_ei), 0, SID_NONE);
xfree(new_ei);
diff --git a/src/nvim/base64.c b/src/nvim/base64.c
index 39e4ec4872..99d3c5a33e 100644
--- a/src/nvim/base64.c
+++ b/src/nvim/base64.c
@@ -142,6 +142,7 @@ char *base64_encode(const char *src, size_t src_len)
/// @param [out] out_lenp Returns the length of the decoded string
/// @return Decoded string
char *base64_decode(const char *src, size_t src_len, size_t *out_lenp)
+ FUNC_ATTR_NONNULL_ALL
{
assert(src != NULL);
assert(out_lenp != NULL);
diff --git a/src/nvim/change.c b/src/nvim/change.c
index 05772d39e9..6c979df1fe 100644
--- a/src/nvim/change.c
+++ b/src/nvim/change.c
@@ -1723,12 +1723,12 @@ bool open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
// Below, set_indent(newindent, SIN_INSERT) will insert the
// whitespace needed before the comment char.
for (int i = 0; i < padding; i++) {
- STRCAT(leader, " ");
+ strcat(leader, " ");
less_cols--;
newcol++;
}
}
- STRCAT(leader, p_extra);
+ strcat(leader, p_extra);
p_extra = leader;
did_ai = true; // So truncating blanks works with comments
less_cols -= lead_len;
diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c
index 0b88e2be11..f75b84c77b 100644
--- a/src/nvim/cmdexpand.c
+++ b/src/nvim/cmdexpand.c
@@ -3257,7 +3257,7 @@ void globpath(char *path, char *file, garray_T *ga, int expand_options, bool dir
copy_option_part(&path, buf, MAXPATHL, ",");
if (strlen(buf) + strlen(file) + 2 < MAXPATHL) {
add_pathsep(buf);
- STRCAT(buf, file);
+ strcat(buf, file);
char **p;
int num_p = 0;
diff --git a/src/nvim/context.c b/src/nvim/context.c
index 95e2618f62..2e3634329a 100644
--- a/src/nvim/context.c
+++ b/src/nvim/context.c
@@ -66,21 +66,11 @@ Context *ctx_get(size_t index)
void ctx_free(Context *ctx)
FUNC_ATTR_NONNULL_ALL
{
- if (ctx->regs.data) {
- msgpack_sbuffer_destroy(&ctx->regs);
- }
- if (ctx->jumps.data) {
- msgpack_sbuffer_destroy(&ctx->jumps);
- }
- if (ctx->bufs.data) {
- msgpack_sbuffer_destroy(&ctx->bufs);
- }
- if (ctx->gvars.data) {
- msgpack_sbuffer_destroy(&ctx->gvars);
- }
- if (ctx->funcs.items) {
- api_free_array(ctx->funcs);
- }
+ api_free_string(ctx->regs);
+ api_free_string(ctx->jumps);
+ api_free_string(ctx->bufs);
+ api_free_string(ctx->gvars);
+ api_free_array(ctx->funcs);
}
/// Saves the editor state to a context.
@@ -98,19 +88,19 @@ void ctx_save(Context *ctx, const int flags)
}
if (flags & kCtxRegs) {
- ctx_save_regs(ctx);
+ ctx->regs = shada_encode_regs();
}
if (flags & kCtxJumps) {
- ctx_save_jumps(ctx);
+ ctx->jumps = shada_encode_jumps();
}
if (flags & kCtxBufs) {
- ctx_save_bufs(ctx);
+ ctx->bufs = shada_encode_buflist();
}
if (flags & kCtxGVars) {
- ctx_save_gvars(ctx);
+ ctx->gvars = shada_encode_gvars();
}
if (flags & kCtxFuncs) {
@@ -173,33 +163,13 @@ bool ctx_restore(Context *ctx, const int flags)
return true;
}
-/// Saves the global registers to a context.
-///
-/// @param ctx Save to this context.
-static inline void ctx_save_regs(Context *ctx)
- FUNC_ATTR_NONNULL_ALL
-{
- msgpack_sbuffer_init(&ctx->regs);
- shada_encode_regs(&ctx->regs);
-}
-
/// Restores the global registers from a context.
///
/// @param ctx Restore from this context.
static inline void ctx_restore_regs(Context *ctx)
FUNC_ATTR_NONNULL_ALL
{
- shada_read_sbuf(&ctx->regs, kShaDaWantInfo | kShaDaForceit);
-}
-
-/// Saves the jumplist to a context.
-///
-/// @param ctx Save to this context.
-static inline void ctx_save_jumps(Context *ctx)
- FUNC_ATTR_NONNULL_ALL
-{
- msgpack_sbuffer_init(&ctx->jumps);
- shada_encode_jumps(&ctx->jumps);
+ shada_read_string(ctx->regs, kShaDaWantInfo | kShaDaForceit);
}
/// Restores the jumplist from a context.
@@ -208,17 +178,7 @@ static inline void ctx_save_jumps(Context *ctx)
static inline void ctx_restore_jumps(Context *ctx)
FUNC_ATTR_NONNULL_ALL
{
- shada_read_sbuf(&ctx->jumps, kShaDaWantInfo | kShaDaForceit);
-}
-
-/// Saves the buffer list to a context.
-///
-/// @param ctx Save to this context.
-static inline void ctx_save_bufs(Context *ctx)
- FUNC_ATTR_NONNULL_ALL
-{
- msgpack_sbuffer_init(&ctx->bufs);
- shada_encode_buflist(&ctx->bufs);
+ shada_read_string(ctx->jumps, kShaDaWantInfo | kShaDaForceit);
}
/// Restores the buffer list from a context.
@@ -227,17 +187,7 @@ static inline void ctx_save_bufs(Context *ctx)
static inline void ctx_restore_bufs(Context *ctx)
FUNC_ATTR_NONNULL_ALL
{
- shada_read_sbuf(&ctx->bufs, kShaDaWantInfo | kShaDaForceit);
-}
-
-/// Saves global variables to a context.
-///
-/// @param ctx Save to this context.
-static inline void ctx_save_gvars(Context *ctx)
- FUNC_ATTR_NONNULL_ALL
-{
- msgpack_sbuffer_init(&ctx->gvars);
- shada_encode_gvars(&ctx->gvars);
+ shada_read_string(ctx->bufs, kShaDaWantInfo | kShaDaForceit);
}
/// Restores global variables from a context.
@@ -246,7 +196,7 @@ static inline void ctx_save_gvars(Context *ctx)
static inline void ctx_restore_gvars(Context *ctx)
FUNC_ATTR_NONNULL_ALL
{
- shada_read_sbuf(&ctx->gvars, kShaDaWantInfo | kShaDaForceit);
+ shada_read_string(ctx->gvars, kShaDaWantInfo | kShaDaForceit);
}
/// Saves functions to a context.
@@ -291,41 +241,16 @@ static inline void ctx_restore_funcs(Context *ctx)
}
}
-/// Convert msgpack_sbuffer to readfile()-style array.
-///
-/// @param[in] sbuf msgpack_sbuffer to convert.
-///
-/// @return readfile()-style array representation of "sbuf".
-static inline Array sbuf_to_array(msgpack_sbuffer sbuf, Arena *arena)
-{
- list_T *const list = tv_list_alloc(kListLenMayKnow);
- tv_list_append_string(list, "", 0);
- if (sbuf.size > 0) {
- encode_list_write(list, sbuf.data, sbuf.size);
- }
-
- typval_T list_tv = (typval_T) {
- .v_lock = VAR_UNLOCKED,
- .v_type = VAR_LIST,
- .vval.v_list = list
- };
-
- Array array = vim_to_object(&list_tv, arena, false).data.array;
- tv_clear(&list_tv);
- return array;
-}
-
-/// Convert readfile()-style array to msgpack_sbuffer.
+/// Convert readfile()-style array to String
///
/// @param[in] array readfile()-style array to convert.
/// @param[out] err Error object.
///
-/// @return msgpack_sbuffer with conversion result.
-static inline msgpack_sbuffer array_to_sbuf(Array array, Error *err)
+/// @return String with conversion result.
+static inline String array_to_string(Array array, Error *err)
FUNC_ATTR_NONNULL_ALL
{
- msgpack_sbuffer sbuf;
- msgpack_sbuffer_init(&sbuf);
+ String sbuf = STRING_INIT;
typval_T list_tv;
object_to_vim(ARRAY_OBJ(array), &list_tv, err);
@@ -335,7 +260,6 @@ static inline msgpack_sbuffer array_to_sbuf(Array array, Error *err)
api_set_error(err, kErrorTypeException, "%s",
"E474: Failed to convert list to msgpack string buffer");
}
- sbuf.alloc = sbuf.size;
tv_clear(&list_tv);
return sbuf;
@@ -353,10 +277,10 @@ Dictionary ctx_to_dict(Context *ctx, Arena *arena)
Dictionary rv = arena_dict(arena, 5);
- PUT_C(rv, "regs", ARRAY_OBJ(sbuf_to_array(ctx->regs, arena)));
- PUT_C(rv, "jumps", ARRAY_OBJ(sbuf_to_array(ctx->jumps, arena)));
- PUT_C(rv, "bufs", ARRAY_OBJ(sbuf_to_array(ctx->bufs, arena)));
- PUT_C(rv, "gvars", ARRAY_OBJ(sbuf_to_array(ctx->gvars, arena)));
+ PUT_C(rv, "regs", ARRAY_OBJ(string_to_array(ctx->regs, false, arena)));
+ PUT_C(rv, "jumps", ARRAY_OBJ(string_to_array(ctx->jumps, false, arena)));
+ PUT_C(rv, "bufs", ARRAY_OBJ(string_to_array(ctx->bufs, false, arena)));
+ PUT_C(rv, "gvars", ARRAY_OBJ(string_to_array(ctx->gvars, false, arena)));
PUT_C(rv, "funcs", ARRAY_OBJ(copy_array(ctx->funcs, arena)));
return rv;
@@ -382,16 +306,16 @@ int ctx_from_dict(Dictionary dict, Context *ctx, Error *err)
}
if (strequal(item.key.data, "regs")) {
types |= kCtxRegs;
- ctx->regs = array_to_sbuf(item.value.data.array, err);
+ ctx->regs = array_to_string(item.value.data.array, err);
} else if (strequal(item.key.data, "jumps")) {
types |= kCtxJumps;
- ctx->jumps = array_to_sbuf(item.value.data.array, err);
+ ctx->jumps = array_to_string(item.value.data.array, err);
} else if (strequal(item.key.data, "bufs")) {
types |= kCtxBufs;
- ctx->bufs = array_to_sbuf(item.value.data.array, err);
+ ctx->bufs = array_to_string(item.value.data.array, err);
} else if (strequal(item.key.data, "gvars")) {
types |= kCtxGVars;
- ctx->gvars = array_to_sbuf(item.value.data.array, err);
+ ctx->gvars = array_to_string(item.value.data.array, err);
} else if (strequal(item.key.data, "funcs")) {
types |= kCtxFuncs;
ctx->funcs = copy_object(item.value, NULL).data.array;
diff --git a/src/nvim/context.h b/src/nvim/context.h
index 1c18a1af7c..0bb7138b6c 100644
--- a/src/nvim/context.h
+++ b/src/nvim/context.h
@@ -7,25 +7,19 @@
#include "nvim/api/private/defs.h"
typedef struct {
- msgpack_sbuffer regs; ///< Registers.
- msgpack_sbuffer jumps; ///< Jumplist.
- msgpack_sbuffer bufs; ///< Buffer list.
- msgpack_sbuffer gvars; ///< Global variables.
+ String regs; ///< Registers.
+ String jumps; ///< Jumplist.
+ String bufs; ///< Buffer list.
+ String gvars; ///< Global variables.
Array funcs; ///< Functions.
} Context;
typedef kvec_t(Context) ContextVec;
-#define MSGPACK_SBUFFER_INIT (msgpack_sbuffer) { \
- .size = 0, \
- .data = NULL, \
- .alloc = 0, \
-}
-
#define CONTEXT_INIT (Context) { \
- .regs = MSGPACK_SBUFFER_INIT, \
- .jumps = MSGPACK_SBUFFER_INIT, \
- .bufs = MSGPACK_SBUFFER_INIT, \
- .gvars = MSGPACK_SBUFFER_INIT, \
+ .regs = STRING_INIT, \
+ .jumps = STRING_INIT, \
+ .bufs = STRING_INIT, \
+ .gvars = STRING_INIT, \
.funcs = ARRAY_DICT_INIT, \
}
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index 54335fc93e..0fe1729029 100644
--- a/src/nvim/diff.c
+++ b/src/nvim/diff.c
@@ -1273,10 +1273,10 @@ void ex_diffpatch(exarg_T *eap)
// Delete any .orig or .rej file created.
STRCPY(buf, tmp_new);
- STRCAT(buf, ".orig");
+ strcat(buf, ".orig");
os_remove(buf);
STRCPY(buf, tmp_new);
- STRCAT(buf, ".rej");
+ strcat(buf, ".rej");
os_remove(buf);
// Only continue if the output file was created.
@@ -1288,7 +1288,7 @@ void ex_diffpatch(exarg_T *eap)
} else {
if (curbuf->b_fname != NULL) {
newname = xstrnsave(curbuf->b_fname, strlen(curbuf->b_fname) + 4);
- STRCAT(newname, ".new");
+ strcat(newname, ".new");
}
// don't use a new tab page, each tab page has its own diffs
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c
index 4247705896..6109652f7d 100644
--- a/src/nvim/drawline.c
+++ b/src/nvim/drawline.c
@@ -587,12 +587,13 @@ static void draw_statuscol(win_T *wp, winlinevars_T *wlv, linenr_T lnum, int vir
char buf[MAXPATHL];
// When a buffer's line count has changed, make a best estimate for the full
- // width of the status column by building with "w_nrwidth_line_count". Add
- // potentially truncated width and rebuild before drawing anything.
+ // width of the status column by building with the largest possible line number.
+ // Add potentially truncated width and rebuild before drawing anything.
if (wp->w_statuscol_line_count != wp->w_nrwidth_line_count) {
wp->w_statuscol_line_count = wp->w_nrwidth_line_count;
set_vim_var_nr(VV_VIRTNUM, 0);
- int width = build_statuscol_str(wp, wp->w_nrwidth_line_count, 0, buf, stcp);
+ int width = build_statuscol_str(wp, wp->w_nrwidth_line_count,
+ wp->w_nrwidth_line_count, buf, stcp);
if (width > stcp->width) {
int addwidth = MIN(width - stcp->width, MAX_STCWIDTH - stcp->width);
wp->w_nrwidth += addwidth;
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index a4680b62ab..d52e10f61b 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -7154,8 +7154,8 @@ static char *make_expanded_name(const char *in_start, char *expr_start, char *ex
retval = xmalloc(strlen(temp_result) + (size_t)(expr_start - in_start)
+ (size_t)(in_end - expr_end) + 1);
STRCPY(retval, in_start);
- STRCAT(retval, temp_result);
- STRCAT(retval, expr_end + 1);
+ strcat(retval, temp_result);
+ strcat(retval, expr_end + 1);
}
xfree(temp_result);
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index 3c99ba22c2..79a62874a4 100644
--- a/src/nvim/eval.lua
+++ b/src/nvim/eval.lua
@@ -1238,33 +1238,33 @@ M.funcs = {
base = 1,
desc = [=[
The result is a Number, which is the byte index of the column
- position given with {expr}. The accepted positions are:
- . the cursor position
- $ the end of the cursor line (the result is the
- number of bytes in the cursor line plus one)
- 'x position of mark x (if the mark is not set, 0 is
- returned)
- v In Visual mode: the start of the Visual area (the
- cursor is the end). When not in Visual mode
- returns the cursor position. Differs from |'<| in
- that it's updated right away.
+ position given with {expr}.
+ For accepted positions see |getpos()|.
+ When {expr} is "$", it means the end of the cursor line, so
+ the result is the number of bytes in the cursor line plus one.
Additionally {expr} can be [lnum, col]: a |List| with the line
and column number. Most useful when the column is "$", to get
the last column of a specific line. When "lnum" or "col" is
out of range then col() returns zero.
+
With the optional {winid} argument the values are obtained for
that window instead of the current window.
+
To get the line number use |line()|. To get both use
|getpos()|.
+
For the screen column position use |virtcol()|. For the
character position use |charcol()|.
+
Note that only marks in the current file can be used.
+
Examples: >vim
echo col(".") " column of cursor
echo col("$") " length of cursor line plus one
echo col("'t") " column of mark t
echo col("'" .. markname) " column of mark markname
- <The first column is 1. Returns 0 if {expr} is invalid or when
+ <
+ The first column is 1. Returns 0 if {expr} is invalid or when
the window with ID {winid} is not found.
For an uppercase mark the column may actually be in another
buffer.
@@ -3448,7 +3448,7 @@ M.funcs = {
<
]=],
name = 'getchar',
- params = {},
+ params = { { 'expr', '0|1' } },
returns = 'integer',
signature = 'getchar([{expr}])',
},
@@ -3537,7 +3537,7 @@ M.funcs = {
result is converted to a string.
]=],
name = 'getcharstr',
- params = {},
+ params = { { 'expr', '0|1' } },
returns = 'string',
signature = 'getcharstr([{expr}])',
},
@@ -4047,8 +4047,9 @@ M.funcs = {
]=],
name = 'getmarklist',
- params = { { 'buf', 'any' } },
+ params = { { 'buf', 'integer?' } },
signature = 'getmarklist([{buf}])',
+ returns = 'vim.fn.getmarklist.ret.item[]',
},
getmatches = {
args = { 0, 1 },
@@ -4140,9 +4141,34 @@ M.funcs = {
args = 1,
base = 1,
desc = [=[
- Get the position for String {expr}. For possible values of
- {expr} see |line()|. For getting the cursor position see
- |getcurpos()|.
+ Get the position for String {expr}.
+ The accepted values for {expr} are:
+ . The cursor position.
+ $ The last line in the current buffer.
+ 'x Position of mark x (if the mark is not set, 0 is
+ returned for all values).
+ w0 First line visible in current window (one if the
+ display isn't updated, e.g. in silent Ex mode).
+ w$ Last line visible in current window (this is one
+ less than "w0" if no lines are visible).
+ v When not in Visual mode, returns the cursor
+ position. In Visual mode, returns the other end
+ of the Visual area. A good way to think about
+ this is that in Visual mode "v" and "." complement
+ each other. While "." refers to the cursor
+ position, "v" refers to where |v_o| would move the
+ cursor. As a result, you can use "v" and "."
+ together to work on all of a selection in
+ characterwise Visual mode. If the cursor is at
+ the end of a characterwise Visual area, "v" refers
+ to the start of the same Visual area. And if the
+ cursor is at the start of a characterwise Visual
+ area, "v" refers to the end of the same Visual
+ area. "v" differs from |'<| and |'>| in that it's
+ updated right away.
+ Note that a mark in another file can be used. The line number
+ then applies to another buffer.
+
The result is a |List| with four numbers:
[bufnum, lnum, col, off]
"bufnum" is zero, unless a mark like '0 or 'A is used, then it
@@ -4153,20 +4179,25 @@ M.funcs = {
it is the offset in screen columns from the start of the
character. E.g., a position within a <Tab> or after the last
character.
- Note that for '< and '> Visual mode matters: when it is "V"
- (visual line mode) the column of '< is zero and the column of
- '> is a large number equal to |v:maxcol|.
+
+ For getting the cursor position see |getcurpos()|.
The column number in the returned List is the byte position
within the line. To get the character position in the line,
use |getcharpos()|.
+
+ Note that for '< and '> Visual mode matters: when it is "V"
+ (visual line mode) the column of '< is zero and the column of
+ '> is a large number equal to |v:maxcol|.
A very large column number equal to |v:maxcol| can be returned,
in which case it means "after the end of the line".
If {expr} is invalid, returns a list with all zeros.
+
This can be used to save and restore the position of a mark: >vim
let save_a_mark = getpos("'a")
" ...
call setpos("'a", save_a_mark)
- <Also see |getcharpos()|, |getcurpos()| and |setpos()|.
+ <
+ Also see |getcharpos()|, |getcurpos()| and |setpos()|.
]=],
name = 'getpos',
@@ -4404,8 +4435,8 @@ M.funcs = {
difference if the buffer is displayed in a window with
different 'virtualedit' or 'list' values.
- Examples: >
- :xnoremap <CR>
+ Examples: >vim
+ xnoremap <CR>
\ <Cmd>echom getregion(
\ getpos('v'), getpos('.'), #{ type: mode() })<CR>
<
@@ -6069,28 +6100,16 @@ M.funcs = {
args = { 1, 2 },
base = 1,
desc = [=[
- The result is a Number, which is the line number of the file
- position given with {expr}. The {expr} argument is a string.
- The accepted positions are:
- . the cursor position
- $ the last line in the current buffer
- 'x position of mark x (if the mark is not set, 0 is
- returned)
- w0 first line visible in current window (one if the
- display isn't updated, e.g. in silent Ex mode)
- w$ last line visible in current window (this is one
- less than "w0" if no lines are visible)
- v In Visual mode: the start of the Visual area (the
- cursor is the end). When not in Visual mode
- returns the cursor position. Differs from |'<| in
- that it's updated right away.
- Note that a mark in another file can be used. The line number
- then applies to another buffer.
+ See |getpos()| for accepted positions.
+
To get the column number use |col()|. To get both use
|getpos()|.
+
With the optional {winid} argument the values are obtained for
that window instead of the current window.
+
Returns 0 for invalid values of {expr} and {winid}.
+
Examples: >vim
echo line(".") " line number of the cursor
echo line(".", winid) " idem, in window "winid"
@@ -6481,7 +6500,8 @@ M.funcs = {
echo printf("Operator-pending mode bit: 0x%x", op_bit)
]],
name = 'maplist',
- params = {},
+ params = { { 'abbr', '0|1' } },
+ returns = 'table[]',
signature = 'maplist([{abbr}])',
},
mapnew = {
@@ -6793,19 +6813,19 @@ M.funcs = {
Examples: >vim
" Assuming line 3 in buffer 5 contains "a"
- :echo matchbufline(5, '\<\k\+\>', 3, 3)
- [{'lnum': 3, 'byteidx': 0, 'text': 'a'}]
+ echo matchbufline(5, '\<\k\+\>', 3, 3)
+ < `[{'lnum': 3, 'byteidx': 0, 'text': 'a'}]` >vim
" Assuming line 4 in buffer 10 contains "tik tok"
- :echo matchbufline(10, '\<\k\+\>', 1, 4)
- [{'lnum': 4, 'byteidx': 0, 'text': 'tik'}, {'lnum': 4, 'byteidx': 4, 'text': 'tok'}]
- <
+ echo matchbufline(10, '\<\k\+\>', 1, 4)
+ < `[{'lnum': 4, 'byteidx': 0, 'text': 'tik'}, {'lnum': 4, 'byteidx': 4, 'text': 'tok'}]`
+
If {submatch} is present and is v:true, then submatches like
"\1", "\2", etc. are also returned. Example: >vim
" Assuming line 2 in buffer 2 contains "acd"
- :echo matchbufline(2, '\(a\)\?\(b\)\?\(c\)\?\(.*\)', 2, 2
+ echo matchbufline(2, '\(a\)\?\(b\)\?\(c\)\?\(.*\)', 2, 2
\ {'submatches': v:true})
- [{'lnum': 2, 'byteidx': 0, 'text': 'acd', 'submatches': ['a', '', 'c', 'd', '', '', '', '', '']}]
- <The "submatches" List always contains 9 items. If a submatch
+ < `[{'lnum': 2, 'byteidx': 0, 'text': 'acd', 'submatches': ['a', '', 'c', 'd', '', '', '', '', '']}]`
+ The "submatches" List always contains 9 items. If a submatch
is not found, then an empty string is returned for that
submatch.
]=],
@@ -7025,17 +7045,17 @@ M.funcs = {
option settings on the pattern.
Example: >vim
- :echo matchstrlist(['tik tok'], '\<\k\+\>')
- [{'idx': 0, 'byteidx': 0, 'text': 'tik'}, {'idx': 0, 'byteidx': 4, 'text': 'tok'}]
- :echo matchstrlist(['a', 'b'], '\<\k\+\>')
- [{'idx': 0, 'byteidx': 0, 'text': 'a'}, {'idx': 1, 'byteidx': 0, 'text': 'b'}]
- <
+ echo matchstrlist(['tik tok'], '\<\k\+\>')
+ < `[{'idx': 0, 'byteidx': 0, 'text': 'tik'}, {'idx': 0, 'byteidx': 4, 'text': 'tok'}]` >vim
+ echo matchstrlist(['a', 'b'], '\<\k\+\>')
+ < `[{'idx': 0, 'byteidx': 0, 'text': 'a'}, {'idx': 1, 'byteidx': 0, 'text': 'b'}]`
+
If "submatches" is present and is v:true, then submatches like
"\1", "\2", etc. are also returned. Example: >vim
- :echo matchstrlist(['acd'], '\(a\)\?\(b\)\?\(c\)\?\(.*\)',
+ echo matchstrlist(['acd'], '\(a\)\?\(b\)\?\(c\)\?\(.*\)',
\ #{submatches: v:true})
- [{'idx': 0, 'byteidx': 0, 'text': 'acd', 'submatches': ['a', '', 'c', 'd', '', '', '', '', '']}]
- <The "submatches" List always contains 9 items. If a submatch
+ < `[{'idx': 0, 'byteidx': 0, 'text': 'acd', 'submatches': ['a', '', 'c', 'd', '', '', '', '', '']}]`
+ The "submatches" List always contains 9 items. If a submatch
is not found, then an empty string is returned for that
submatch.
]=],
@@ -7244,17 +7264,14 @@ M.funcs = {
When {flags} is present it must be a string. An empty string
has no effect.
- If {flags} contains "p" then intermediate directories are
- created as necessary.
+ {flags} can contain these character flags:
+ "p" intermediate directories will be created as necessary
+ "D" {name} will be deleted at the end of the current
+ function, but not recursively |:defer|
+ "R" {name} will be deleted recursively at the end of the
+ current function |:defer|
- If {flags} contains "D" then {name} is deleted at the end of
- the current function, as with: >vim
- defer delete({name}, 'd')
- <
- If {flags} contains "R" then {name} is deleted recursively at
- the end of the current function, as with: >vim
- defer delete({name}, 'rf')
- <Note that when {name} has more than one part and "p" is used
+ Note that when {name} has more than one part and "p" is used
some directories may already exist. Only the first one that
is created and what it contains is scheduled to be deleted.
E.g. when using: >vim
@@ -8715,7 +8732,7 @@ M.funcs = {
the following mappings: >vim
nnoremap <expr> GG ":echom " .. screencol() .. "\n"
nnoremap <silent> GG :echom screencol()<CR>
- noremap GG <Cmd>echom screencol()<Cr>
+ noremap GG <Cmd>echom screencol()<CR>
<
]=],
name = 'screencol',
@@ -9142,7 +9159,16 @@ M.funcs = {
<
]=],
name = 'searchpair',
- params = {},
+ params = {
+ { 'start', 'any' },
+ { 'middle', 'any' },
+ { 'end', 'any' },
+ { 'flags', 'string' },
+ { 'skip', 'any' },
+ { 'stopline', 'any' },
+ { 'timeout', 'integer' },
+ },
+ returns = 'integer',
signature = 'searchpair({start}, {middle}, {end} [, {flags} [, {skip} [, {stopline} [, {timeout}]]]])',
},
searchpairpos = {
@@ -9159,7 +9185,16 @@ M.funcs = {
See |match-parens| for a bigger and more useful example.
]=],
name = 'searchpairpos',
- params = {},
+ params = {
+ { 'start', 'any' },
+ { 'middle', 'any' },
+ { 'end', 'any' },
+ { 'flags', 'string' },
+ { 'skip', 'any' },
+ { 'stopline', 'any' },
+ { 'timeout', 'integer' },
+ },
+ returns = '[integer, integer]',
signature = 'searchpairpos({start}, {middle}, {end} [, {flags} [, {skip} [, {stopline} [, {timeout}]]]])',
},
searchpos = {
@@ -12428,7 +12463,9 @@ M.funcs = {
set to 8, it returns 8. |conceal| is ignored.
For the byte position use |col()|.
- For the use of {expr} see |col()|.
+ For the use of {expr} see |getpos()| and |col()|.
+ When {expr} is "$", it means the end of the cursor line, so
+ the result is the number of cells in the cursor line plus one.
When 'virtualedit' is used {expr} can be [lnum, col, off],
where "off" is the offset in screen columns from the start of
@@ -12438,18 +12475,6 @@ M.funcs = {
beyond the end of the line can be returned. Also see
|'virtualedit'|
- The accepted positions are:
- . the cursor position
- $ the end of the cursor line (the result is the
- number of displayed characters in the cursor line
- plus one)
- 'x position of mark x (if the mark is not set, 0 is
- returned)
- v In Visual mode: the start of the Visual area (the
- cursor is the end). When not in Visual mode
- returns the cursor position. Differs from |'<| in
- that it's updated right away.
-
If {list} is present and non-zero then virtcol() returns a
List with the first and last screen position occupied by the
character.
@@ -12468,7 +12493,9 @@ M.funcs = {
" With text " there", with 't at 'h':
echo virtcol("'t") " returns 6
- <The first column is 1. 0 or [0, 0] is returned for an error.
+ <
+ The first column is 1. 0 or [0, 0] is returned for an error.
+
A more advanced example that echoes the maximum length of
all lines: >vim
echo max(map(range(1, line('$')), "virtcol([v:val, '$'])"))
diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c
index 00fb896797..122a1ac8ab 100644
--- a/src/nvim/eval/userfunc.c
+++ b/src/nvim/eval/userfunc.c
@@ -265,7 +265,7 @@ static void set_ufunc_name(ufunc_T *fp, char *name)
if ((uint8_t)name[0] == K_SPECIAL) {
fp->uf_name_exp = xmalloc(strlen(name) + 3);
STRCPY(fp->uf_name_exp, "<SNR>");
- STRCAT(fp->uf_name_exp, fp->uf_name + 3);
+ strcat(fp->uf_name_exp, fp->uf_name + 3);
}
}
@@ -2062,7 +2062,7 @@ char *get_scriptlocal_funcname(char *funcname)
const int off = *funcname == 's' ? 2 : 5;
char *newname = xmalloc(strlen(sid_buf) + strlen(funcname + off) + 1);
STRCPY(newname, sid_buf);
- STRCAT(newname, funcname + off);
+ strcat(newname, funcname + off);
return newname;
}
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 2f7673a6f4..0aa897105e 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -970,13 +970,13 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out
char *t = xmalloc(len);
*t = NUL;
if (newcmd != NULL) {
- STRCAT(t, newcmd);
+ strcat(t, newcmd);
}
if (ins_prevcmd) {
- STRCAT(t, prevcmd);
+ strcat(t, prevcmd);
}
char *p = t + strlen(t);
- STRCAT(t, trailarg);
+ strcat(t, trailarg);
xfree(newcmd);
newcmd = t;
@@ -1029,8 +1029,8 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out
}
newcmd = xmalloc(strlen(prevcmd) + 2 * strlen(p_shq) + 1);
STRCPY(newcmd, p_shq);
- STRCAT(newcmd, prevcmd);
- STRCAT(newcmd, p_shq);
+ strcat(newcmd, prevcmd);
+ strcat(newcmd, p_shq);
free_newcmd = true;
}
if (addr_count == 0) { // :!
@@ -4108,7 +4108,7 @@ skip:
// the line as reference, because the substitute may
// have changed the number of characters. Same for
// "prev_matchcol".
- STRCAT(new_start, sub_firstline + copycol);
+ strcat(new_start, sub_firstline + copycol);
matchcol = (colnr_T)strlen(sub_firstline) - matchcol;
prev_matchcol = (colnr_T)strlen(sub_firstline)
- prev_matchcol;
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 1e2c515195..a6246afb41 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -3826,8 +3826,8 @@ char *replace_makeprg(exarg_T *eap, char *arg, char **cmdlinep)
// No $* in arg, build "<makeprg> <arg>" instead
new_cmdline = xmalloc(strlen(program) + strlen(arg) + 2);
STRCPY(new_cmdline, program);
- STRCAT(new_cmdline, " ");
- STRCAT(new_cmdline, arg);
+ strcat(new_cmdline, " ");
+ strcat(new_cmdline, arg);
}
msg_make(arg);
@@ -7236,7 +7236,7 @@ char *expand_sfile(char *arg)
memmove(newres, result, (size_t)(p - result));
STRCPY(newres + (p - result), repl);
len = strlen(newres);
- STRCAT(newres, p + srclen);
+ strcat(newres, p + srclen);
xfree(repl);
xfree(result);
result = newres;
diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c
index 2681beb228..6e7c1ff21c 100644
--- a/src/nvim/ex_eval.c
+++ b/src/nvim/ex_eval.c
@@ -406,7 +406,7 @@ char *get_exception_string(void *value, except_type_T type, char *cmdname, bool
|| (ascii_isdigit(p[3])
&& p[4] == ':')))))) {
if (*p == NUL || p == mesg) {
- STRCAT(val, mesg); // 'E123' missing or at beginning
+ strcat(val, mesg); // 'E123' missing or at beginning
} else {
// '"filename" E123: message text'
if (mesg[0] != '"' || p - 2 < &mesg[1]
@@ -415,7 +415,7 @@ char *get_exception_string(void *value, except_type_T type, char *cmdname, bool
continue;
}
- STRCAT(val, p);
+ strcat(val, p);
p[-2] = NUL;
snprintf(val + strlen(p), strlen(" (%s)"), " (%s)", &mesg[1]);
p[-2] = '"';
diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c
index 30a80773e3..b6a039af5e 100644
--- a/src/nvim/file_search.c
+++ b/src/nvim/file_search.c
@@ -451,7 +451,7 @@ void *vim_findfile_init(char *path, char *filename, char *stopdirs, int level, i
STRCPY(buf, ff_expand_buffer);
STRCPY(buf + eb_len, search_ctx->ffsc_fix_path);
if (os_isdir(buf)) {
- STRCAT(ff_expand_buffer, search_ctx->ffsc_fix_path);
+ strcat(ff_expand_buffer, search_ctx->ffsc_fix_path);
add_pathsep(ff_expand_buffer);
} else {
char *p = path_tail(search_ctx->ffsc_fix_path);
@@ -479,7 +479,7 @@ void *vim_findfile_init(char *path, char *filename, char *stopdirs, int level, i
+ strlen(search_ctx->ffsc_fix_path + len)
+ 1);
STRCPY(temp, search_ctx->ffsc_fix_path + len);
- STRCAT(temp, search_ctx->ffsc_wc_path);
+ strcat(temp, search_ctx->ffsc_wc_path);
xfree(search_ctx->ffsc_wc_path);
xfree(wc_path);
search_ctx->ffsc_wc_path = temp;
@@ -681,7 +681,7 @@ char *vim_findfile(void *search_ctx_arg)
ff_free_stack_element(stackp);
goto fail;
}
- STRCAT(file_path, stackp->ffs_fix_path);
+ strcat(file_path, stackp->ffs_fix_path);
if (!add_pathsep(file_path)) {
ff_free_stack_element(stackp);
goto fail;
@@ -781,7 +781,7 @@ char *vim_findfile(void *search_ctx_arg)
ff_free_stack_element(stackp);
goto fail;
}
- STRCAT(file_path, search_ctx->ffsc_file_to_search);
+ strcat(file_path, search_ctx->ffsc_file_to_search);
// Try without extra suffix and then with suffixes
// from 'suffixesadd'.
@@ -922,7 +922,7 @@ char *vim_findfile(void *search_ctx_arg)
if (!add_pathsep(file_path)) {
goto fail;
}
- STRCAT(file_path, search_ctx->ffsc_fix_path);
+ strcat(file_path, search_ctx->ffsc_fix_path);
// create a new stack entry
sptr = ff_create_stack_element(file_path,
diff --git a/src/nvim/fold.c b/src/nvim/fold.c
index be1b6acf2c..78fe33cc78 100644
--- a/src/nvim/fold.c
+++ b/src/nvim/fold.c
@@ -3315,7 +3315,7 @@ void f_foldtext(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
char *r = xmalloc(len);
snprintf(r, len, txt, dashes, count);
len = strlen(r);
- STRCAT(r, s);
+ strcat(r, s);
// remove 'foldmarker' and 'commentstring'
foldtext_cleanup(r + len);
rettv->vval.v_string = r;
diff --git a/src/nvim/highlight.h b/src/nvim/highlight.h
index cb3a84bcaf..2ba6cf5371 100644
--- a/src/nvim/highlight.h
+++ b/src/nvim/highlight.h
@@ -54,6 +54,8 @@ EXTERN const char *hlf_names[] INIT( = {
[HLF_SPL] = "SpellLocal",
[HLF_PNI] = "Pmenu",
[HLF_PSI] = "PmenuSel",
+ [HLF_PMNI] = "PmenuMatch",
+ [HLF_PMSI] = "PmenuMatchSel",
[HLF_PNK] = "PmenuKind",
[HLF_PSK] = "PmenuKindSel",
[HLF_PNX] = "PmenuExtra",
@@ -78,6 +80,8 @@ EXTERN const char *hlf_names[] INIT( = {
[HLF_CU] = "Cursor",
[HLF_BTITLE] = "FloatTitle",
[HLF_BFOOTER] = "FloatFooter",
+ [HLF_TS] = "StatusLineTerm",
+ [HLF_TSNC] = "StatusLineTermNC",
});
EXTERN int highlight_attr[HLF_COUNT + 1]; // Highl. attr for each context.
diff --git a/src/nvim/highlight_defs.h b/src/nvim/highlight_defs.h
index 25ab9dc2d9..e0cce81166 100644
--- a/src/nvim/highlight_defs.h
+++ b/src/nvim/highlight_defs.h
@@ -101,6 +101,8 @@ typedef enum {
HLF_SPL, ///< SpellLocal
HLF_PNI, ///< popup menu normal item
HLF_PSI, ///< popup menu selected item
+ HLF_PMNI, ///< popup menu matched text in normal item
+ HLF_PMSI, ///< popup menu matched text in selected item
HLF_PNK, ///< popup menu normal item "kind"
HLF_PSK, ///< popup menu selected item "kind"
HLF_PNX, ///< popup menu normal item "menu" (extra text)
@@ -125,6 +127,8 @@ typedef enum {
HLF_CU, ///< Cursor
HLF_BTITLE, ///< Float Border Title
HLF_BFOOTER, ///< Float Border Footer
+ HLF_TS, ///< status line for terminal window
+ HLF_TSNC, ///< status line for non-current terminal window
HLF_COUNT, ///< MUST be the last one
} hlf_T;
diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c
index c32e1f9657..3c777e7c4d 100644
--- a/src/nvim/highlight_group.c
+++ b/src/nvim/highlight_group.c
@@ -151,34 +151,38 @@ static const char *highlight_init_both[] = {
"lCursor guifg=bg guibg=fg",
// UI
- "default link CursorIM Cursor",
- "default link CursorLineFold FoldColumn",
- "default link CursorLineSign SignColumn",
- "default link EndOfBuffer NonText",
- "default link FloatBorder NormalFloat",
- "default link FloatFooter FloatTitle",
- "default link FloatTitle Title",
- "default link FoldColumn SignColumn",
- "default link IncSearch CurSearch",
- "default link LineNrAbove LineNr",
- "default link LineNrBelow LineNr",
- "default link MsgSeparator StatusLine",
- "default link MsgArea NONE",
- "default link NormalNC NONE",
- "default link PmenuExtra Pmenu",
- "default link PmenuExtraSel PmenuSel",
- "default link PmenuKind Pmenu",
- "default link PmenuKindSel PmenuSel",
- "default link PmenuSbar Pmenu",
- "default link Substitute Search",
- "default link TabLine StatusLineNC",
- "default link TabLineFill TabLine",
- "default link TermCursorNC NONE",
- "default link VertSplit WinSeparator",
- "default link VisualNOS Visual",
- "default link Whitespace NonText",
- "default link WildMenu PmenuSel",
- "default link WinSeparator Normal",
+ "default link CursorIM Cursor",
+ "default link CursorLineFold FoldColumn",
+ "default link CursorLineSign SignColumn",
+ "default link EndOfBuffer NonText",
+ "default link FloatBorder NormalFloat",
+ "default link FloatFooter FloatTitle",
+ "default link FloatTitle Title",
+ "default link FoldColumn SignColumn",
+ "default link IncSearch CurSearch",
+ "default link LineNrAbove LineNr",
+ "default link LineNrBelow LineNr",
+ "default link MsgSeparator StatusLine",
+ "default link MsgArea NONE",
+ "default link NormalNC NONE",
+ "default link PmenuExtra Pmenu",
+ "default link PmenuExtraSel PmenuSel",
+ "default link PmenuKind Pmenu",
+ "default link PmenuKindSel PmenuSel",
+ "default link PmenuMatch Pmenu",
+ "default link PmenuMatchSel PmenuSel",
+ "default link PmenuSbar Pmenu",
+ "default link Substitute Search",
+ "default link StatusLineTerm StatusLine",
+ "default link StatusLineTermNC StatusLineNC",
+ "default link TabLine StatusLineNC",
+ "default link TabLineFill TabLine",
+ "default link TermCursorNC NONE",
+ "default link VertSplit WinSeparator",
+ "default link VisualNOS Visual",
+ "default link Whitespace NonText",
+ "default link WildMenu PmenuSel",
+ "default link WinSeparator Normal",
// Syntax
"default link Character Constant",
diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c
index 574c9a9e3a..0a25b72451 100644
--- a/src/nvim/insexpand.c
+++ b/src/nvim/insexpand.c
@@ -1144,11 +1144,13 @@ static void trigger_complete_changed_event(int cur)
}
/// pumitem qsort compare func
-static int ins_compl_fuzzy_sort(const void *a, const void *b)
+static int ins_compl_fuzzy_cmp(const void *a, const void *b)
{
const int sa = (*(pumitem_T *)a).pum_score;
const int sb = (*(pumitem_T *)b).pum_score;
- return sa == sb ? 0 : sa < sb ? 1 : -1;
+ const int ia = (*(pumitem_T *)a).pum_idx;
+ const int ib = (*(pumitem_T *)b).pum_idx;
+ return sa == sb ? (ia == ib ? 0 : (ia < ib ? -1 : 1)) : (sa < sb ? 1 : -1);
}
/// Build a popup menu to show the completion matches.
@@ -1228,6 +1230,9 @@ static int ins_compl_build_pum(void)
}
cur = i;
} else if (compl_fuzzy_match) {
+ if (i == 0) {
+ shown_compl = comp;
+ }
// Update the maximum fuzzy score and the shown match
// if the current item's score is higher
if (comp->cp_score > max_fuzzy_score) {
@@ -1246,6 +1251,9 @@ static int ins_compl_build_pum(void)
|| (compl_leader == NULL || lead_len == 0))) {
shown_match_ok = true;
cur = 0;
+ if (match_at_original_text(compl_shown_match)) {
+ compl_shown_match = shown_compl;
+ }
}
}
@@ -1284,9 +1292,12 @@ static int ins_compl_build_pum(void)
} while (comp != NULL && !is_first_match(comp));
if (compl_fuzzy_match && compl_leader != NULL && lead_len > 0) {
+ for (i = 0; i < compl_match_arraysize; i++) {
+ compl_match_array[i].pum_idx = i;
+ }
// sort by the largest score of fuzzy match
qsort(compl_match_array, (size_t)compl_match_arraysize, sizeof(pumitem_T),
- ins_compl_fuzzy_sort);
+ ins_compl_fuzzy_cmp);
}
if (!shown_match_ok) { // no displayed match at all
@@ -1383,6 +1394,12 @@ bool compl_match_curr_select(int selected)
#define DICT_FIRST (1) ///< use just first element in "dict"
#define DICT_EXACT (2) ///< "dict" is the exact name of a file
+/// Get current completion leader
+char *ins_compl_leader(void)
+{
+ return compl_leader;
+}
+
/// Add any identifiers that match the given pattern "pat" in the list of
/// dictionary files "dict_start" to the list of completions.
///
@@ -3681,16 +3698,16 @@ static int find_next_completion_match(bool allow_get_expansion, int todo, bool a
while (--todo >= 0) {
if (compl_shows_dir_forward() && compl_shown_match->cp_next != NULL) {
- compl_shown_match = !compl_fuzzy_match ? compl_shown_match->cp_next
- : find_comp_when_fuzzy();
+ compl_shown_match = compl_fuzzy_match && compl_match_array != NULL
+ ? find_comp_when_fuzzy() : compl_shown_match->cp_next;
found_end = (compl_first_match != NULL
&& (is_first_match(compl_shown_match->cp_next)
|| is_first_match(compl_shown_match)));
} else if (compl_shows_dir_backward()
&& compl_shown_match->cp_prev != NULL) {
found_end = is_first_match(compl_shown_match);
- compl_shown_match = !compl_fuzzy_match ? compl_shown_match->cp_prev
- : find_comp_when_fuzzy();
+ compl_shown_match = compl_fuzzy_match && compl_match_array != NULL
+ ? find_comp_when_fuzzy() : compl_shown_match->cp_prev;
found_end |= is_first_match(compl_shown_match);
} else {
if (!allow_get_expansion) {
@@ -4059,7 +4076,7 @@ static int get_normal_compl_info(char *line, int startcol, colnr_T curs_col)
compl_pattern = xmalloc(7);
STRCPY(compl_pattern, "\\<");
quote_meta(compl_pattern + 2, line + compl_col, 1);
- STRCAT(compl_pattern, "\\k");
+ strcat(compl_pattern, "\\k");
} else {
compl_pattern = xmalloc(quote_meta(NULL, line + compl_col, compl_length) + 2);
STRCPY(compl_pattern, "\\<");
diff --git a/src/nvim/memory.h b/src/nvim/memory.h
index 0788670142..a6ff82e39d 100644
--- a/src/nvim/memory.h
+++ b/src/nvim/memory.h
@@ -45,8 +45,6 @@ EXTERN size_t arena_alloc_count INIT( = 0);
((v).capacity = (s), \
(v).items = (void *)arena_alloc(a, sizeof((v).items[0]) * (v).capacity, true))
-#define ARENA_BLOCK_SIZE 4096
-
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "memory.h.generated.h"
#endif
@@ -72,5 +70,3 @@ EXTERN size_t arena_alloc_count INIT( = 0);
// Like strcpy() but allows overlapped source and destination.
#define STRMOVE(d, s) memmove((d), (s), strlen(s) + 1)
-
-#define STRCAT(d, s) strcat((char *)(d), (char *)(s)) // NOLINT(runtime/printf)
diff --git a/src/nvim/memory_defs.h b/src/nvim/memory_defs.h
index bde0e54f54..df271ceca5 100644
--- a/src/nvim/memory_defs.h
+++ b/src/nvim/memory_defs.h
@@ -11,5 +11,7 @@ typedef struct {
size_t pos, size;
} Arena;
+#define ARENA_BLOCK_SIZE 4096
+
// inits an empty arena.
#define ARENA_EMPTY { .cur_blk = NULL, .pos = 0, .size = 0 }
diff --git a/src/nvim/menu.c b/src/nvim/menu.c
index a4d49d041e..c33d3cc712 100644
--- a/src/nvim/menu.c
+++ b/src/nvim/menu.c
@@ -1057,7 +1057,7 @@ char *get_menu_names(expand_T *xp, int idx)
}
// hack on menu separators: use a 'magic' char for the separator
// so that '.' in names gets escaped properly
- STRCAT(tbuffer, "\001");
+ strcat(tbuffer, "\001");
str = tbuffer;
} else {
if (should_advance) {
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index 6a0dc10214..0930f0c7b3 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -590,16 +590,16 @@ static void packer_buffer_init_channels(Channel **chans, size_t nchans, PackerBu
packer->endptr = packer->startptr + ARENA_BLOCK_SIZE;
packer->packer_flush = channel_flush_callback;
packer->anydata = chans;
- packer->anylen = nchans;
+ packer->anyint = (int64_t)nchans;
}
static void packer_buffer_finish_channels(PackerBuffer *packer)
{
size_t len = (size_t)(packer->ptr - packer->startptr);
if (len > 0) {
- WBuffer *buf = wstream_new_buffer(packer->startptr, len, packer->anylen, free_block);
+ WBuffer *buf = wstream_new_buffer(packer->startptr, len, (size_t)packer->anyint, free_block);
Channel **chans = packer->anydata;
- for (size_t i = 0; i < packer->anylen; i++) {
+ for (int64_t i = 0; i < packer->anyint; i++) {
channel_write(chans[i], buf);
}
} else {
@@ -610,7 +610,7 @@ static void packer_buffer_finish_channels(PackerBuffer *packer)
static void channel_flush_callback(PackerBuffer *packer)
{
packer_buffer_finish_channels(packer);
- packer_buffer_init_channels(packer->anydata, packer->anylen, packer);
+ packer_buffer_init_channels(packer->anydata, (size_t)packer->anyint, packer);
}
void rpc_set_client_info(uint64_t id, Dictionary info)
diff --git a/src/nvim/msgpack_rpc/packer.c b/src/nvim/msgpack_rpc/packer.c
index 9c0d2910fa..58318b88b0 100644
--- a/src/nvim/msgpack_rpc/packer.c
+++ b/src/nvim/msgpack_rpc/packer.c
@@ -10,8 +10,7 @@
static void check_buffer(PackerBuffer *packer)
{
- ptrdiff_t remaining = packer->endptr - packer->ptr;
- if (remaining < MPACK_ITEM_SIZE) {
+ if (mpack_remaining(packer) < MPACK_ITEM_SIZE) {
packer->packer_flush(packer);
}
}
@@ -28,15 +27,20 @@ static void mpack_w8(char **b, const char *data)
#endif
}
+void mpack_uint64(char **ptr, uint64_t i)
+{
+ if (i > 0xfffffff) {
+ mpack_w(ptr, 0xcf);
+ mpack_w8(ptr, (char *)&i);
+ } else {
+ mpack_uint(ptr, (uint32_t)i);
+ }
+}
+
void mpack_integer(char **ptr, Integer i)
{
if (i >= 0) {
- if (i > 0xfffffff) {
- mpack_w(ptr, 0xcf);
- mpack_w8(ptr, (char *)&i);
- } else {
- mpack_uint(ptr, (uint32_t)i);
- }
+ mpack_uint64(ptr, (uint64_t)i);
} else {
if (i < -0x80000000LL) {
mpack_w(ptr, 0xd3);
@@ -80,11 +84,16 @@ void mpack_str(String str, PackerBuffer *packer)
abort();
}
+ mpack_raw(str.data, len, packer);
+}
+
+void mpack_raw(char *data, size_t len, PackerBuffer *packer)
+{
size_t pos = 0;
while (pos < len) {
ptrdiff_t remaining = packer->endptr - packer->ptr;
size_t to_copy = MIN(len - pos, (size_t)remaining);
- memcpy(packer->ptr, str.data + pos, to_copy);
+ memcpy(packer->ptr, data + pos, to_copy);
packer->ptr += to_copy;
pos += to_copy;
diff --git a/src/nvim/msgpack_rpc/packer.h b/src/nvim/msgpack_rpc/packer.h
index 8117bd09bd..299962bab4 100644
--- a/src/nvim/msgpack_rpc/packer.h
+++ b/src/nvim/msgpack_rpc/packer.h
@@ -71,6 +71,11 @@ static inline void mpack_map(char **buf, uint32_t len)
}
}
+static inline size_t mpack_remaining(PackerBuffer *packer)
+{
+ return (size_t)(packer->endptr - packer->ptr);
+}
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "msgpack_rpc/packer.h.generated.h"
#endif
diff --git a/src/nvim/msgpack_rpc/packer_defs.h b/src/nvim/msgpack_rpc/packer_defs.h
index 420f3dc424..95d86caaab 100644
--- a/src/nvim/msgpack_rpc/packer_defs.h
+++ b/src/nvim/msgpack_rpc/packer_defs.h
@@ -19,6 +19,6 @@ struct packer_buffer_t {
// these are free to be used by packer_flush for any purpose, if want
void *anydata;
- size_t anylen;
+ int64_t anyint;
PackerBufferFlush packer_flush;
};
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 879131c9e8..3343803bb1 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -1987,7 +1987,7 @@ bool add_to_showcmd(int c)
size_t overflow = old_len + extra_len - limit;
memmove(showcmd_buf, showcmd_buf + overflow, old_len - overflow + 1);
}
- STRCAT(showcmd_buf, p);
+ strcat(showcmd_buf, p);
if (char_avail()) {
return false;
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 1448896146..8f8baaf619 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -2666,7 +2666,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
char *pnew = xmalloc(strlen(curr->y_array[curr->y_size - 1])
+ strlen(reg->y_array[0]) + 1);
STRCPY(pnew, curr->y_array[--j]);
- STRCAT(pnew, reg->y_array[0]);
+ strcat(pnew, reg->y_array[0]);
xfree(curr->y_array[j]);
xfree(reg->y_array[0]);
curr->y_array[j++] = pnew;
@@ -3431,7 +3431,7 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
totlen = strlen(y_array[y_size - 1]);
char *newp = xmalloc((size_t)ml_get_len(lnum) - (size_t)col + totlen + 1);
STRCPY(newp, y_array[y_size - 1]);
- STRCAT(newp, ptr);
+ strcat(newp, ptr);
// insert second line
ml_append(lnum, newp, 0, false);
new_lnum++;
@@ -4747,7 +4747,7 @@ bool do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
}
}
*ptr = NUL;
- STRCAT(buf1, buf2);
+ strcat(buf1, buf2);
ins_str(buf1); // insert the new number
endpos = curwin->w_cursor;
if (curwin->w_cursor.col) {
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 301e6e9cea..8fb97ed979 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -236,11 +236,11 @@ static void set_init_default_backupskip(void)
== NULL) {
ga_grow(&ga, (int)len);
if (!GA_EMPTY(&ga)) {
- STRCAT(ga.ga_data, ",");
+ strcat(ga.ga_data, ",");
}
- STRCAT(ga.ga_data, p);
+ strcat(ga.ga_data, p);
add_pathsep(ga.ga_data);
- STRCAT(ga.ga_data, "*");
+ strcat(ga.ga_data, "*");
ga.ga_len += (int)len;
}
xfree(item);
diff --git a/src/nvim/option_vars.h b/src/nvim/option_vars.h
index bd0fe699d9..404e58661c 100644
--- a/src/nvim/option_vars.h
+++ b/src/nvim/option_vars.h
@@ -55,13 +55,13 @@
#define HIGHLIGHT_INIT \
"8:SpecialKey,~:EndOfBuffer,z:TermCursor,Z:TermCursorNC,@:NonText,d:Directory,e:ErrorMsg," \
"i:IncSearch,l:Search,y:CurSearch,m:MoreMsg,M:ModeMsg,n:LineNr,a:LineNrAbove,b:LineNrBelow," \
- "N:CursorLineNr,G:CursorLineSign,O:CursorLineFold" \
- "r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg," \
- "W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,>:SignColumn," \
- "-:Conceal,B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel," \
- "[:PmenuKind,]:PmenuKindSel,{:PmenuExtra,}:PmenuExtraSel,x:PmenuSbar,X:PmenuThumb," \
- "*:TabLine,#:TabLineSel,_:TabLineFill,!:CursorColumn,.:CursorLine,o:ColorColumn," \
- "q:QuickFixLine,g:MsgArea,0:Whitespace,I:NormalNC"
+ "N:CursorLineNr,G:CursorLineSign,O:CursorLineFold,r:Question,s:StatusLine,S:StatusLineNC," \
+ "c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn," \
+ "A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,>:SignColumn,-:Conceal,B:SpellBad,P:SpellCap," \
+ "R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel,k:PmenuMatch,<:PmenuMatchSel,[:PmenuKind," \
+ "]:PmenuKindSel,{:PmenuExtra,}:PmenuExtraSel,x:PmenuSbar,X:PmenuThumb,*:TabLine,#:TabLineSel," \
+ "_:TabLineFill,!:CursorColumn,.:CursorLine,o:ColorColumn,q:QuickFixLine,z:StatusLineTerm," \
+ "Z:StatusLineTermNC,g:MsgArea,0:Whitespace,I:NormalNC"
// Default values for 'errorformat'.
// The "%f|%l| %m" one is used for when the contents of the quickfix window is
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index f323926015..efa2ea7dd9 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -4876,6 +4876,9 @@ return {
between tabs and spaces and for trailing blanks. Further changed by
the 'listchars' option.
+ When 'listchars' does not contain "tab" field, tabs are shown as "^I"
+ or "<09>", like how unprintable characters are displayed.
+
The cursor is displayed at the start of the space a Tab character
occupies, not at the end as usual in Normal mode. To get this cursor
position while displaying Tabs with spaces, use: >vim
@@ -8037,8 +8040,7 @@ return {
Some of the items from the 'statusline' format are different for
'statuscolumn':
- %l line number of currently drawn line
- %r relative line number of currently drawn line
+ %l line number column for currently drawn line
%s sign column for currently drawn line
%C fold column for currently drawn line
@@ -8065,11 +8067,8 @@ return {
handler should be written with this in mind.
Examples: >vim
- " Relative number with bar separator and click handlers:
- set statuscolumn=%@SignCb@%s%=%T%@NumCb@%r│%T
-
- " Right aligned relative cursor line number:
- let &stc='%=%{v:relnum?v:relnum:v:lnum} '
+ " Line number with bar separator and click handlers:
+ set statuscolumn=%@SignCb@%s%=%T%@NumCb@%l│%T
" Line numbers in hexadecimal for non wrapped part of lines:
let &stc='%=%{v:virtnum>0?"":printf("%x",v:lnum)} '
diff --git a/src/nvim/os/fileio.c b/src/nvim/os/fileio.c
index 585c4964e2..89834bed80 100644
--- a/src/nvim/os/fileio.c
+++ b/src/nvim/os/fileio.c
@@ -320,9 +320,8 @@ ptrdiff_t file_write(FileDescriptor *const fp, const char *const buf, const size
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1)
{
assert(fp->wr);
- ptrdiff_t space = (fp->buffer + ARENA_BLOCK_SIZE) - fp->write_pos;
// includes the trivial case of size==0
- if (size < (size_t)space) {
+ if (size < file_space(fp)) {
memcpy(fp->write_pos, buf, size);
fp->write_pos += size;
return (ptrdiff_t)size;
diff --git a/src/nvim/os/fileio.h b/src/nvim/os/fileio.h
index e8fd2209db..523f9657a4 100644
--- a/src/nvim/os/fileio.h
+++ b/src/nvim/os/fileio.h
@@ -2,6 +2,7 @@
#include <stddef.h> // IWYU pragma: keep
+#include "nvim/memory_defs.h"
#include "nvim/os/fileio_defs.h" // IWYU pragma: keep
/// file_open() flags
@@ -32,6 +33,11 @@ enum {
kRWBufferSize = 1024,
};
+static inline size_t file_space(FileDescriptor *fp)
+{
+ return (size_t)((fp->buffer + ARENA_BLOCK_SIZE) - fp->write_pos);
+}
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/fileio.h.generated.h"
#endif
diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c
index b66faa2285..4b34ed1c4e 100644
--- a/src/nvim/os/shell.c
+++ b/src/nvim/os/shell.c
@@ -248,11 +248,11 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in
} else {
STRCPY(command, "(");
}
- STRCAT(command, pat[0] + 1); // exclude first backtick
+ strcat(command, pat[0] + 1); // exclude first backtick
p = command + strlen(command) - 1;
if (is_fish_shell) {
*p-- = ';';
- STRCAT(command, " end");
+ strcat(command, " end");
} else {
*p-- = ')'; // remove last backtick
}
@@ -263,7 +263,7 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in
ampersand = true;
*p = ' ';
}
- STRCAT(command, ">");
+ strcat(command, ">");
} else {
STRCPY(command, "");
if (shell_style == STYLE_GLOB) {
@@ -271,26 +271,26 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in
// otherwise, this may set the positional parameters for the shell,
// e.g. "$*".
if (flags & EW_NOTFOUND) {
- STRCAT(command, "set nonomatch; ");
+ strcat(command, "set nonomatch; ");
} else {
- STRCAT(command, "unset nonomatch; ");
+ strcat(command, "unset nonomatch; ");
}
}
if (shell_style == STYLE_GLOB) {
- STRCAT(command, "glob >");
+ strcat(command, "glob >");
} else if (shell_style == STYLE_PRINT) {
- STRCAT(command, "print -N >");
+ strcat(command, "print -N >");
} else if (shell_style == STYLE_VIMGLOB) {
- STRCAT(command, sh_vimglob_func);
+ strcat(command, sh_vimglob_func);
} else if (shell_style == STYLE_GLOBSTAR) {
- STRCAT(command, sh_globstar_opt);
- STRCAT(command, sh_vimglob_func);
+ strcat(command, sh_globstar_opt);
+ strcat(command, sh_vimglob_func);
} else {
- STRCAT(command, "echo >");
+ strcat(command, "echo >");
}
}
- STRCAT(command, tempname);
+ strcat(command, tempname);
if (shell_style != STYLE_BT) {
for (i = 0; i < num_pat; i++) {
@@ -334,7 +334,7 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in
}
if (ampersand) {
- STRCAT(command, "&"); // put the '&' after the redirection
+ strcat(command, "&"); // put the '&' after the redirection
}
// Using zsh -G: If a pattern has no matches, it is just deleted from
diff --git a/src/nvim/path.c b/src/nvim/path.c
index d782d1a989..aa630038a8 100644
--- a/src/nvim/path.c
+++ b/src/nvim/path.c
@@ -962,7 +962,7 @@ static void uniquefy_paths(garray_T *gap, char *pattern)
char *file_pattern = xmalloc(len + 2);
file_pattern[0] = '*';
file_pattern[1] = NUL;
- STRCAT(file_pattern, pattern);
+ strcat(file_pattern, pattern);
char *pat = file_pat_to_reg_pat(file_pattern, NULL, NULL, true);
xfree(file_pattern);
if (pat == NULL) {
@@ -1065,7 +1065,7 @@ static void uniquefy_paths(garray_T *gap, char *pattern)
rel_path = xmalloc(strlen(short_name) + strlen(PATHSEPSTR) + 2);
STRCPY(rel_path, ".");
add_pathsep(rel_path);
- STRCAT(rel_path, short_name);
+ strcat(rel_path, short_name);
xfree(fnames[i]);
fnames[i] = rel_path;
diff --git a/src/nvim/popupmenu.c b/src/nvim/popupmenu.c
index 324254a188..18446e749b 100644
--- a/src/nvim/popupmenu.c
+++ b/src/nvim/popupmenu.c
@@ -25,6 +25,7 @@
#include "nvim/ex_cmds_defs.h"
#include "nvim/extmark.h"
#include "nvim/extmark_defs.h"
+#include "nvim/garray.h"
#include "nvim/getchar.h"
#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
@@ -48,6 +49,7 @@
#include "nvim/plines.h"
#include "nvim/popupmenu.h"
#include "nvim/pos_defs.h"
+#include "nvim/search.h"
#include "nvim/state_defs.h"
#include "nvim/strings.h"
#include "nvim/types_defs.h"
@@ -141,7 +143,7 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i
|| (State == MODE_CMDLINE && ui_has(kUIWildmenu));
}
- pum_rl = (curwin->w_p_rl && State != MODE_CMDLINE);
+ pum_rl = State != MODE_CMDLINE && curwin->w_p_rl;
do {
// Mark the pum as visible already here,
@@ -435,6 +437,84 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i
pum_redraw();
}
+/// Computes attributes of text on the popup menu.
+/// Returns attributes for every cell, or NULL if all attributes are the same.
+static int *pum_compute_text_attrs(char *text, hlf_T hlf)
+{
+ char *leader = ins_compl_leader();
+
+ if (leader == NULL || *leader == NUL || (hlf != HLF_PSI && hlf != HLF_PNI)
+ || (win_hl_attr(curwin, HLF_PMSI) == win_hl_attr(curwin, HLF_PSI)
+ && win_hl_attr(curwin, HLF_PMNI) == win_hl_attr(curwin, HLF_PNI))) {
+ return NULL;
+ }
+
+ int *attrs = xmalloc(sizeof(int) * (size_t)vim_strsize(text));
+ size_t leader_len = strlen(leader);
+ const bool in_fuzzy = (get_cot_flags() & COT_FUZZY) != 0;
+
+ garray_T *ga = NULL;
+ bool matched_start = false;
+
+ if (in_fuzzy) {
+ ga = fuzzy_match_str_with_pos(text, leader);
+ } else {
+ matched_start = strncmp(text, leader, leader_len) == 0;
+ }
+
+ const char *ptr = text;
+ int cell_idx = 0;
+ uint32_t char_pos = 0;
+
+ while (*ptr != NUL) {
+ int new_attr = win_hl_attr(curwin, (int)hlf);
+
+ if (ga != NULL) {
+ // Handle fuzzy matching
+ for (int i = 0; i < ga->ga_len; i++) {
+ if (char_pos == ((uint32_t *)ga->ga_data)[i]) {
+ new_attr = win_hl_attr(curwin, hlf == HLF_PSI ? HLF_PMSI : HLF_PMNI);
+ break;
+ }
+ }
+ } else if (matched_start && ptr < text + leader_len) {
+ new_attr = win_hl_attr(curwin, hlf == HLF_PSI ? HLF_PMSI : HLF_PMNI);
+ }
+
+ int char_cells = utf_ptr2cells(ptr);
+ for (int i = 0; i < char_cells; i++) {
+ attrs[cell_idx + i] = new_attr;
+ }
+ cell_idx += char_cells;
+
+ MB_PTR_ADV(ptr);
+ char_pos++;
+ }
+
+ if (ga != NULL) {
+ ga_clear(ga);
+ xfree(ga);
+ }
+ return attrs;
+}
+
+/// Displays text on the popup menu with specific attributes.
+static void pum_grid_puts_with_attrs(int col, int cells, const char *text, int textlen,
+ const int *attrs)
+{
+ const int col_start = col;
+ const char *ptr = text;
+
+ // Render text with proper attributes
+ while (*ptr != NUL && (textlen < 0 || ptr < text + textlen)) {
+ int char_len = utfc_ptr2len(ptr);
+ int attr = attrs[pum_rl ? (col_start + cells - col - 1) : (col - col_start)];
+ grid_line_puts(col, ptr, char_len, attr);
+ col += utf_ptr2cells(ptr);
+ ptr += char_len;
+ }
+}
+
/// Redraw the popup menu, using "pum_first" and "pum_selected".
void pum_redraw(void)
{
@@ -446,11 +526,9 @@ void pum_redraw(void)
int thumb_height = 1;
int n;
-#define HA(hlf) (win_hl_attr(curwin, (hlf)))
- // "word" "kind" "extra text"
- const int attrsNorm[3] = { HA(HLF_PNI), HA(HLF_PNK), HA(HLF_PNX) };
- const int attrsSel[3] = { HA(HLF_PSI), HA(HLF_PSK), HA(HLF_PSX) };
-#undef HA
+ // "word" "kind" "extra text"
+ const hlf_T hlfsNorm[3] = { HLF_PNI, HLF_PNK, HLF_PNX };
+ const hlf_T hlfsSel[3] = { HLF_PSI, HLF_PSK, HLF_PSX };
int grid_width = pum_width;
int col_off = 0;
@@ -517,8 +595,9 @@ void pum_redraw(void)
for (int i = 0; i < pum_height; i++) {
int idx = i + pum_first;
- const int *const attrs = (idx == pum_selected) ? attrsSel : attrsNorm;
- int attr = attrs[0]; // start with "word" highlight
+ const hlf_T *const hlfs = (idx == pum_selected) ? hlfsSel : hlfsNorm;
+ hlf_T hlf = hlfs[0]; // start with "word" highlight
+ int attr = win_hl_attr(curwin, (int)hlf);
grid_line_start(&pum_grid, row);
@@ -540,7 +619,8 @@ void pum_redraw(void)
int totwidth = 0;
for (int round = 0; round < 3; round++) {
- attr = attrs[round];
+ hlf = hlfs[round];
+ attr = win_hl_attr(curwin, (int)hlf);
int width = 0;
char *s = NULL;
@@ -574,36 +654,50 @@ void pum_redraw(void)
*p = saved;
}
+ int *attrs = pum_compute_text_attrs(st, hlf);
+
if (pum_rl) {
char *rt = reverse_text(st);
char *rt_start = rt;
- int size = vim_strsize(rt);
+ int cells = vim_strsize(rt);
- if (size > pum_width) {
+ if (cells > pum_width) {
do {
- size -= utf_ptr2cells(rt);
+ cells -= utf_ptr2cells(rt);
MB_PTR_ADV(rt);
- } while (size > pum_width);
+ } while (cells > pum_width);
- if (size < pum_width) {
+ if (cells < pum_width) {
// Most left character requires 2-cells but only 1 cell
// is available on screen. Put a '<' on the left of the
// pum item
*(--rt) = '<';
- size++;
+ cells++;
}
}
- grid_line_puts(grid_col - size + 1, rt, -1, attr);
+
+ if (attrs == NULL) {
+ grid_line_puts(grid_col - cells + 1, rt, -1, attr);
+ } else {
+ pum_grid_puts_with_attrs(grid_col - cells + 1, cells, rt, -1, attrs);
+ }
+
xfree(rt_start);
xfree(st);
grid_col -= width;
} else {
- // use grid_line_puts() to truncate the text
- grid_line_puts(grid_col, st, -1, attr);
+ if (attrs == NULL) {
+ grid_line_puts(grid_col, st, -1, attr);
+ } else {
+ pum_grid_puts_with_attrs(grid_col, vim_strsize(st), st, -1, attrs);
+ }
+
xfree(st);
grid_col += width;
}
+ xfree(attrs);
+
if (*p != TAB) {
break;
}
@@ -645,7 +739,7 @@ void pum_redraw(void)
if (pum_rl) {
grid_line_fill(col_off - pum_base_width - n + 1, grid_col + 1, schar_from_ascii(' '), attr);
- grid_col = col_off - pum_base_width - n + 1;
+ grid_col = col_off - pum_base_width - n;
} else {
grid_line_fill(grid_col, col_off + pum_base_width + n, schar_from_ascii(' '), attr);
grid_col = col_off + pum_base_width + n;
@@ -1144,12 +1238,14 @@ void pum_set_event_info(dict_T *dict)
static void pum_position_at_mouse(int min_width)
{
int min_row = 0;
+ int min_col = 0;
int max_row = Rows;
int max_col = Columns;
if (mouse_grid > 1) {
win_T *wp = get_win_by_grid_handle(mouse_grid);
if (wp != NULL) {
min_row = -wp->w_winrow;
+ min_col = -wp->w_wincol;
max_row = MAX(Rows - wp->w_winrow, wp->w_grid.rows);
max_col = MAX(Columns - wp->w_wincol, wp->w_grid.cols);
}
@@ -1162,6 +1258,7 @@ static void pum_position_at_mouse(int min_width)
} else {
pum_anchor_grid = mouse_grid;
}
+
if (max_row - mouse_row > pum_size) {
// Enough space below the mouse row.
pum_above = false;
@@ -1178,16 +1275,29 @@ static void pum_position_at_mouse(int min_width)
pum_row = min_row;
}
}
- if (max_col - mouse_col >= pum_base_width
- || max_col - mouse_col > min_width) {
- // Enough space to show at mouse column.
- pum_col = mouse_col;
+
+ if (pum_rl) {
+ if (mouse_col - min_col + 1 >= pum_base_width
+ || mouse_col - min_col + 1 > min_width) {
+ // Enough space to show at mouse column.
+ pum_col = mouse_col;
+ } else {
+ // Not enough space, left align with window.
+ pum_col = min_col + MIN(pum_base_width, min_width) - 1;
+ }
+ pum_width = pum_col - min_col + 1;
} else {
- // Not enough space, right align with window.
- pum_col = max_col - (pum_base_width > min_width ? min_width : pum_base_width);
+ if (max_col - mouse_col >= pum_base_width
+ || max_col - mouse_col > min_width) {
+ // Enough space to show at mouse column.
+ pum_col = mouse_col;
+ } else {
+ // Not enough space, right align with window.
+ pum_col = max_col - MIN(pum_base_width, min_width);
+ }
+ pum_width = max_col - pum_col;
}
- pum_width = max_col - pum_col;
if (pum_width > pum_base_width + 1) {
pum_width = pum_base_width + 1;
}
@@ -1269,6 +1379,7 @@ void pum_show_popupmenu(vimmenu_T *menu)
pum_compute_size();
pum_scrollbar = 0;
pum_height = pum_size;
+ pum_rl = curwin->w_p_rl;
pum_position_at_mouse(20);
pum_selected = -1;
@@ -1348,7 +1459,9 @@ void pum_make_popup(const char *path_name, int use_mouse_pos)
// Hack: set mouse position at the cursor so that the menu pops up
// around there.
mouse_row = curwin->w_grid.row_offset + curwin->w_wrow;
- mouse_col = curwin->w_grid.col_offset + curwin->w_wcol;
+ mouse_col = curwin->w_grid.col_offset
+ + (curwin->w_p_rl ? curwin->w_width_inner - curwin->w_wcol - 1
+ : curwin->w_wcol);
if (ui_has(kUIMultigrid)) {
mouse_grid = curwin->w_grid.target->handle;
} else if (curwin->w_grid.target != &default_grid) {
diff --git a/src/nvim/popupmenu.h b/src/nvim/popupmenu.h
index 9e3f8f5a7f..bcf2a14290 100644
--- a/src/nvim/popupmenu.h
+++ b/src/nvim/popupmenu.h
@@ -15,6 +15,7 @@ typedef struct {
char *pum_extra; ///< extra menu text (may be truncated)
char *pum_info; ///< extra info
int pum_score; ///< fuzzy match score
+ int pum_idx; ///< index of item before sorting by score
} pumitem_T;
EXTERN ScreenGrid pum_grid INIT( = SCREEN_GRID_INIT);
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index be2f41da14..ed3fd83fd5 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -4531,7 +4531,7 @@ static char *get_mef_name(void)
name = xmalloc(strlen(p_mef) + 30);
STRCPY(name, p_mef);
snprintf(name + (p - p_mef), strlen(name), "%d%d", start, off);
- STRCAT(name, p + 2);
+ strcat(name, p + 2);
// Don't accept a symbolic link, it's a security risk.
FileInfo file_info;
bool file_or_link_found = os_fileinfo_link(name, &file_info);
@@ -7237,7 +7237,7 @@ static void hgr_search_files_in_dir(qf_list_T *qfl, char *dirname, regmatch_T *p
// Find all "*.txt" and "*.??x" files in the "doc" directory.
add_pathsep(dirname);
- STRCAT(dirname, "doc/*.\\(txt\\|??x\\)"); // NOLINT
+ strcat(dirname, "doc/*.\\(txt\\|??x\\)"); // NOLINT
if (gen_expand_wildcards(1, &dirname, &fcount, &fnames, EW_FILE|EW_SILENT) == OK
&& fcount > 0) {
for (int fi = 0; fi < fcount && !got_int; fi++) {
diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c
index 2ff4dbee70..5a5ba9df07 100644
--- a/src/nvim/regexp.c
+++ b/src/nvim/regexp.c
@@ -11451,7 +11451,7 @@ static void nfa_set_code(int c)
}
if (addnl == true) {
- STRCAT(code, " + NEWLINE ");
+ strcat(code, " + NEWLINE ");
}
}
diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c
index 648e574b97..c479418131 100644
--- a/src/nvim/runtime.c
+++ b/src/nvim/runtime.c
@@ -409,7 +409,7 @@ int do_in_path(const char *path, const char *prefix, char *name, int flags,
did_one = true;
} else if (buflen + 2 + strlen(prefix) + strlen(name) < MAXPATHL) {
add_pathsep(buf);
- STRCAT(buf, prefix);
+ strcat(buf, prefix);
tail = buf + strlen(buf);
// Loop over all patterns in "name"
diff --git a/src/nvim/search.c b/src/nvim/search.c
index bee124e305..994a0794b0 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -21,12 +21,14 @@
#include "nvim/errors.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/ex_cmds.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_getln.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
+#include "nvim/garray.h"
#include "nvim/getchar.h"
#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
@@ -3542,6 +3544,37 @@ int fuzzy_match_str(char *const str, const char *const pat)
return score;
}
+/// Fuzzy match the position of string "pat" in string "str".
+/// @returns a dynamic array of matching positions. If there is no match, returns NULL.
+garray_T *fuzzy_match_str_with_pos(char *const str, const char *const pat)
+{
+ if (str == NULL || pat == NULL) {
+ return NULL;
+ }
+
+ garray_T *match_positions = xmalloc(sizeof(garray_T));
+ ga_init(match_positions, sizeof(uint32_t), 10);
+
+ unsigned matches[MAX_FUZZY_MATCHES];
+ int score = 0;
+ if (!fuzzy_match(str, pat, false, &score, matches, MAX_FUZZY_MATCHES)
+ || score == 0) {
+ ga_clear(match_positions);
+ xfree(match_positions);
+ return NULL;
+ }
+
+ int j = 0;
+ for (const char *p = pat; *p != NUL; MB_PTR_ADV(p)) {
+ if (!ascii_iswhite(utf_ptr2char(p))) {
+ GA_APPEND(uint32_t, match_positions, matches[j]);
+ j++;
+ }
+ }
+
+ return match_positions;
+}
+
/// Copy a list of fuzzy matches into a string list after sorting the matches by
/// the fuzzy score. Frees the memory allocated for "fuzmatch".
void fuzzymatches_to_strmatches(fuzmatch_str_T *const fuzmatch, char ***const matches,
diff --git a/src/nvim/shada.c b/src/nvim/shada.c
index d5655b1754..5736ea0f09 100644
--- a/src/nvim/shada.c
+++ b/src/nvim/shada.c
@@ -42,6 +42,7 @@
#include "nvim/mbyte.h"
#include "nvim/memory.h"
#include "nvim/message.h"
+#include "nvim/msgpack_rpc/packer.h"
#include "nvim/normal_defs.h"
#include "nvim/ops.h"
#include "nvim/option.h"
@@ -602,20 +603,6 @@ static void close_file(FileDescriptor *cookie)
}
}
-/// Msgpack callback for writing to FileDescriptor*
-static int msgpack_sd_writer_write(void *data, const char *buf, size_t len)
-{
- FileDescriptor *const sd_writer = (FileDescriptor *)data;
- const ptrdiff_t ret = file_write(sd_writer, buf, len);
- if (ret < 0) {
- semsg(_(SERR "System error while writing ShaDa file: %s"),
- os_strerror((int)ret));
- return -1;
- }
-
- return 0;
-}
-
/// Check whether writing to shada file was disabled ("-i NONE" or "--clean").
///
/// @return true if it was disabled, false otherwise.
@@ -1365,6 +1352,8 @@ static char *shada_filename(const char *file)
} \
} while (0)
+#define SHADA_MPACK_FREE_SPACE (4 * MPACK_ITEM_SIZE)
+
/// Write single ShaDa entry
///
/// @param[in] packer Packer used to write entry.
@@ -1373,7 +1362,7 @@ static char *shada_filename(const char *file)
/// restrictions.
///
/// @return kSDWriteSuccessful, kSDWriteFailed or kSDWriteIgnError.
-static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, ShadaEntry entry,
+static ShaDaWriteResult shada_pack_entry(PackerBuffer *const packer, ShadaEntry entry,
const size_t max_kbyte)
FUNC_ATTR_NONNULL_ALL
{
@@ -1657,29 +1646,26 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, ShadaEntr
#undef CHECK_DEFAULT
#undef ONE_IF_NOT_DEFAULT
if (!max_kbyte || sbuf.size <= max_kbyte * 1024) {
+ if (mpack_remaining(packer) < SHADA_MPACK_FREE_SPACE) {
+ packer->packer_flush(packer);
+ }
+
if (entry.type == kSDItemUnknown) {
- if (msgpack_pack_uint64(packer, entry.data.unknown_item.type) == -1) {
- goto shada_pack_entry_error;
- }
+ mpack_uint64(&packer->ptr, entry.data.unknown_item.type);
} else {
- if (msgpack_pack_uint64(packer, (uint64_t)entry.type) == -1) {
- goto shada_pack_entry_error;
- }
- }
- if (msgpack_pack_uint64(packer, (uint64_t)entry.timestamp) == -1) {
- goto shada_pack_entry_error;
+ mpack_uint64(&packer->ptr, (uint64_t)entry.type);
}
+ mpack_uint64(&packer->ptr, (uint64_t)entry.timestamp);
if (sbuf.size > 0) {
- if ((msgpack_pack_uint64(packer, (uint64_t)sbuf.size) == -1)
- || (packer->callback(packer->data, sbuf.data,
- (unsigned)sbuf.size) == -1)) {
- goto shada_pack_entry_error;
- }
+ mpack_uint64(&packer->ptr, (uint64_t)sbuf.size);
+ mpack_raw(sbuf.data, sbuf.size, packer);
+ }
+
+ if (packer->anyint != 0) { // error code
+ goto shada_pack_entry_error;
}
}
- msgpack_packer_free(spacker);
- msgpack_sbuffer_destroy(&sbuf);
- return kSDWriteSuccessful;
+ ret = kSDWriteSuccessful;
shada_pack_entry_error:
msgpack_packer_free(spacker);
msgpack_sbuffer_destroy(&sbuf);
@@ -1694,7 +1680,7 @@ shada_pack_entry_error:
/// @param[in] entry Entry written.
/// @param[in] max_kbyte Maximum size of an item in KiB. Zero means no
/// restrictions.
-static inline ShaDaWriteResult shada_pack_pfreed_entry(msgpack_packer *const packer,
+static inline ShaDaWriteResult shada_pack_pfreed_entry(PackerBuffer *const packer,
PossiblyFreedShadaEntry entry,
const size_t max_kbyte)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_ALWAYS_INLINE
@@ -1908,7 +1894,7 @@ static inline ShaDaWriteResult shada_read_when_writing(FileDescriptor *const sd_
const unsigned srni_flags,
const size_t max_kbyte,
WriteMergerState *const wms,
- msgpack_packer *const packer)
+ PackerBuffer *const packer)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
ShaDaWriteResult ret = kSDWriteSuccessful;
@@ -2360,6 +2346,29 @@ static int hist_type2char(const int type)
return NUL;
}
+static PackerBuffer packer_buffer_for_file(FileDescriptor *file)
+{
+ if (file_space(file) < SHADA_MPACK_FREE_SPACE) {
+ file_flush(file);
+ }
+ return (PackerBuffer) {
+ .startptr = file->buffer,
+ .ptr = file->write_pos,
+ .endptr = file->buffer + ARENA_BLOCK_SIZE,
+ .anydata = file,
+ .anyint = 0, // set to nonzero if error
+ .packer_flush = flush_file_buffer,
+ };
+}
+
+static void flush_file_buffer(PackerBuffer *buffer)
+{
+ FileDescriptor *fd = buffer->anydata;
+ fd->write_pos = buffer->ptr;
+ buffer->anyint = file_flush(fd);
+ buffer->ptr = fd->write_pos;
+}
+
/// Write ShaDa file
///
/// @param[in] sd_writer Structure containing file writer definition.
@@ -2408,8 +2417,7 @@ static ShaDaWriteResult shada_write(FileDescriptor *const sd_writer,
}
}
- const unsigned srni_flags = (unsigned)(
- kSDReadUndisableableData
+ const unsigned srni_flags = (unsigned)(kSDReadUndisableableData
| kSDReadUnknown
| (dump_history ? kSDReadHistory : 0)
| (dump_registers ? kSDReadRegisters : 0)
@@ -2418,8 +2426,7 @@ static ShaDaWriteResult shada_write(FileDescriptor *const sd_writer,
| (num_marked_files ? kSDReadLocalMarks |
kSDReadChanges : 0));
- msgpack_packer *const packer = msgpack_packer_new(sd_writer,
- &msgpack_sd_writer_write);
+ PackerBuffer packer = packer_buffer_for_file(sd_writer);
// Set b_last_cursor for all the buffers that have a window.
//
@@ -2433,7 +2440,7 @@ static ShaDaWriteResult shada_write(FileDescriptor *const sd_writer,
find_removable_bufs(&removable_bufs);
// Write header
- if (shada_pack_entry(packer, (ShadaEntry) {
+ if (shada_pack_entry(&packer, (ShadaEntry) {
.type = kSDItemHeader,
.timestamp = os_time(),
.data = {
@@ -2462,7 +2469,7 @@ static ShaDaWriteResult shada_write(FileDescriptor *const sd_writer,
// Write buffer list
if (find_shada_parameter('%') != NULL) {
ShadaEntry buflist_entry = shada_get_buflist(&removable_bufs);
- if (shada_pack_entry(packer, buflist_entry, 0) == kSDWriteFailed) {
+ if (shada_pack_entry(&packer, buflist_entry, 0) == kSDWriteFailed) {
xfree(buflist_entry.data.buffer_list.buffers);
ret = kSDWriteFailed;
goto shada_write_exit;
@@ -2512,7 +2519,7 @@ static ShaDaWriteResult shada_write(FileDescriptor *const sd_writer,
typval_T tgttv;
tv_copy(&vartv, &tgttv);
ShaDaWriteResult spe_ret;
- if ((spe_ret = shada_pack_entry(packer, (ShadaEntry) {
+ if ((spe_ret = shada_pack_entry(&packer, (ShadaEntry) {
.type = kSDItemVariable,
.timestamp = cur_timestamp,
.data = {
@@ -2689,7 +2696,7 @@ static ShaDaWriteResult shada_write(FileDescriptor *const sd_writer,
if (sd_reader != NULL) {
const ShaDaWriteResult srww_ret = shada_read_when_writing(sd_reader, srni_flags, max_kbyte, wms,
- packer);
+ &packer);
if (srww_ret != kSDWriteSuccessful) {
ret = srww_ret;
}
@@ -2720,7 +2727,7 @@ static ShaDaWriteResult shada_write(FileDescriptor *const sd_writer,
do { \
for (size_t i_ = 0; i_ < ARRAY_SIZE(wms_array); i_++) { \
if ((wms_array)[i_].data.type != kSDItemMissing) { \
- if (shada_pack_pfreed_entry(packer, (wms_array)[i_], max_kbyte) \
+ if (shada_pack_pfreed_entry(&packer, (wms_array)[i_], max_kbyte) \
== kSDWriteFailed) { \
ret = kSDWriteFailed; \
goto shada_write_exit; \
@@ -2732,7 +2739,7 @@ static ShaDaWriteResult shada_write(FileDescriptor *const sd_writer,
PACK_WMS_ARRAY(wms->numbered_marks);
PACK_WMS_ARRAY(wms->registers);
for (size_t i = 0; i < wms->jumps_size; i++) {
- if (shada_pack_pfreed_entry(packer, wms->jumps[i], max_kbyte)
+ if (shada_pack_pfreed_entry(&packer, wms->jumps[i], max_kbyte)
== kSDWriteFailed) {
ret = kSDWriteFailed;
goto shada_write_exit;
@@ -2741,7 +2748,7 @@ static ShaDaWriteResult shada_write(FileDescriptor *const sd_writer,
#define PACK_WMS_ENTRY(wms_entry) \
do { \
if ((wms_entry).data.type != kSDItemMissing) { \
- if (shada_pack_pfreed_entry(packer, wms_entry, max_kbyte) \
+ if (shada_pack_pfreed_entry(&packer, wms_entry, max_kbyte) \
== kSDWriteFailed) { \
ret = kSDWriteFailed; \
goto shada_write_exit; \
@@ -2767,14 +2774,14 @@ static ShaDaWriteResult shada_write(FileDescriptor *const sd_writer,
for (size_t i = 0; i < file_markss_to_dump; i++) {
PACK_WMS_ARRAY(all_file_markss[i]->marks);
for (size_t j = 0; j < all_file_markss[i]->changes_size; j++) {
- if (shada_pack_pfreed_entry(packer, all_file_markss[i]->changes[j],
+ if (shada_pack_pfreed_entry(&packer, all_file_markss[i]->changes[j],
max_kbyte) == kSDWriteFailed) {
ret = kSDWriteFailed;
goto shada_write_exit;
}
}
for (size_t j = 0; j < all_file_markss[i]->additional_marks_size; j++) {
- if (shada_pack_entry(packer, all_file_markss[i]->additional_marks[j],
+ if (shada_pack_entry(&packer, all_file_markss[i]->additional_marks[j],
0) == kSDWriteFailed) {
shada_free_shada_entry(&all_file_markss[i]->additional_marks[j]);
ret = kSDWriteFailed;
@@ -2792,7 +2799,7 @@ static ShaDaWriteResult shada_write(FileDescriptor *const sd_writer,
if (dump_one_history[i]) {
hms_insert_whole_neovim_history(&wms->hms[i]);
HMS_ITER(&wms->hms[i], cur_entry, {
- if (shada_pack_pfreed_entry(packer, (PossiblyFreedShadaEntry) {
+ if (shada_pack_pfreed_entry(&packer, (PossiblyFreedShadaEntry) {
.data = cur_entry->data,
.can_free_entry = cur_entry->can_free_entry,
}, max_kbyte) == kSDWriteFailed) {
@@ -2818,7 +2825,7 @@ shada_write_exit:
})
map_destroy(cstr_t, &wms->file_marks);
set_destroy(ptr_t, &removable_bufs);
- msgpack_packer_free(packer);
+ packer.packer_flush(&packer);
set_destroy(cstr_t, &wms->dumped_variables);
xfree(wms);
return ret;
@@ -3953,16 +3960,43 @@ static inline size_t shada_init_jumps(PossiblyFreedShadaEntry *jumps,
return jumps_size;
}
+static PackerBuffer packer_string_buffer(void)
+{
+ const size_t initial_size = 64; // must be larger than SHADA_MPACK_FREE_SPACE
+ char *alloc = xmalloc(initial_size);
+ return (PackerBuffer) {
+ .startptr = alloc,
+ .ptr = alloc,
+ .endptr = alloc + initial_size,
+ .packer_flush = flush_string_buffer,
+ };
+}
+
+static void flush_string_buffer(PackerBuffer *buffer)
+{
+ size_t current_capacity = (size_t)(buffer->endptr - buffer->startptr);
+ size_t new_capacity = 2 * current_capacity;
+ size_t len = (size_t)(buffer->ptr - buffer->startptr);
+
+ buffer->startptr = xrealloc(buffer->startptr, new_capacity);
+ buffer->ptr = buffer->startptr + len;
+ buffer->endptr = buffer->startptr + new_capacity;
+}
+
+static String packer_take_string(PackerBuffer *buffer)
+{
+ return (String){ .data = buffer->startptr, .size = (size_t)(buffer->ptr - buffer->startptr) };
+}
+
/// Write registers ShaDa entries in given msgpack_sbuffer.
///
/// @param[in] sbuf target msgpack_sbuffer to write to.
-void shada_encode_regs(msgpack_sbuffer *const sbuf)
+String shada_encode_regs(void)
FUNC_ATTR_NONNULL_ALL
{
WriteMergerState *const wms = xcalloc(1, sizeof(*wms));
shada_initialize_registers(wms, -1);
- msgpack_packer packer;
- msgpack_packer_init(&packer, sbuf, msgpack_sbuffer_write);
+ PackerBuffer packer = packer_string_buffer();
for (size_t i = 0; i < ARRAY_SIZE(wms->registers); i++) {
if (wms->registers[i].data.type == kSDItemRegister) {
if (kSDWriteFailed
@@ -3972,52 +4006,53 @@ void shada_encode_regs(msgpack_sbuffer *const sbuf)
}
}
xfree(wms);
+ return packer_take_string(&packer);
}
/// Write jumplist ShaDa entries in given msgpack_sbuffer.
///
/// @param[in] sbuf target msgpack_sbuffer to write to.
-void shada_encode_jumps(msgpack_sbuffer *const sbuf)
+String shada_encode_jumps(void)
FUNC_ATTR_NONNULL_ALL
{
Set(ptr_t) removable_bufs = SET_INIT;
find_removable_bufs(&removable_bufs);
PossiblyFreedShadaEntry jumps[JUMPLISTSIZE];
size_t jumps_size = shada_init_jumps(jumps, &removable_bufs);
- msgpack_packer packer;
- msgpack_packer_init(&packer, sbuf, msgpack_sbuffer_write);
+ PackerBuffer packer = packer_string_buffer();
for (size_t i = 0; i < jumps_size; i++) {
if (kSDWriteFailed == shada_pack_pfreed_entry(&packer, jumps[i], 0)) {
abort();
}
}
+ return packer_take_string(&packer);
}
/// Write buffer list ShaDa entry in given msgpack_sbuffer.
///
/// @param[in] sbuf target msgpack_sbuffer to write to.
-void shada_encode_buflist(msgpack_sbuffer *const sbuf)
+String shada_encode_buflist(void)
FUNC_ATTR_NONNULL_ALL
{
Set(ptr_t) removable_bufs = SET_INIT;
find_removable_bufs(&removable_bufs);
ShadaEntry buflist_entry = shada_get_buflist(&removable_bufs);
- msgpack_packer packer;
- msgpack_packer_init(&packer, sbuf, msgpack_sbuffer_write);
+
+ PackerBuffer packer = packer_string_buffer();
if (kSDWriteFailed == shada_pack_entry(&packer, buflist_entry, 0)) {
abort();
}
xfree(buflist_entry.data.buffer_list.buffers);
+ return packer_take_string(&packer);
}
/// Write global variables ShaDa entries in given msgpack_sbuffer.
///
/// @param[in] sbuf target msgpack_sbuffer to write to.
-void shada_encode_gvars(msgpack_sbuffer *const sbuf)
+String shada_encode_gvars(void)
FUNC_ATTR_NONNULL_ALL
{
- msgpack_packer packer;
- msgpack_packer_init(&packer, sbuf, msgpack_sbuffer_write);
+ PackerBuffer packer = packer_string_buffer();
const void *var_iter = NULL;
const Timestamp cur_timestamp = os_time();
do {
@@ -4049,21 +4084,21 @@ void shada_encode_gvars(msgpack_sbuffer *const sbuf)
}
tv_clear(&vartv);
} while (var_iter != NULL);
+ return packer_take_string(&packer);
}
-/// Read ShaDa from msgpack_sbuffer.
+/// Read ShaDa from String.
///
-/// @param[in] file msgpack_sbuffer to read from.
+/// @param[in] string string to read from.
/// @param[in] flags Flags, see ShaDaReadFileFlags enum.
-void shada_read_sbuf(msgpack_sbuffer *const sbuf, const int flags)
+void shada_read_string(String string, const int flags)
FUNC_ATTR_NONNULL_ALL
{
- assert(sbuf != NULL);
- if (sbuf->data == NULL) {
+ if (string.size == 0) {
return;
}
FileDescriptor sd_reader;
- file_open_buffer(&sd_reader, sbuf->data, sbuf->size);
+ file_open_buffer(&sd_reader, string.data, string.size);
shada_read(&sd_reader, flags);
close_file(&sd_reader);
}
diff --git a/src/nvim/shada.h b/src/nvim/shada.h
index d7cac24afc..58689a5bd7 100644
--- a/src/nvim/shada.h
+++ b/src/nvim/shada.h
@@ -2,6 +2,8 @@
#include <msgpack.h> // IWYU pragma: keep
+#include "nvim/api/private/defs.h"
+
/// Flags for shada_read_file and children
typedef enum {
kShaDaWantInfo = 1, ///< Load non-mark information
diff --git a/src/nvim/sign.c b/src/nvim/sign.c
index 1ca0e846a9..605098fb66 100644
--- a/src/nvim/sign.c
+++ b/src/nvim/sign.c
@@ -126,8 +126,8 @@ static void buf_set_sign(buf_T *buf, uint32_t *id, char *group, int prio, linenr
| (has_hl ? MT_FLAG_DECOR_SIGNHL : 0);
DecorInline decor = { .ext = true, .data.ext = { .vt = NULL, .sh_idx = decor_put_sh(sign) } };
- extmark_set(buf, ns, id, lnum - 1, 0, -1, -1, decor, decor_flags, true,
- false, true, true, NULL);
+ extmark_set(buf, ns, id, MIN(buf->b_ml.ml_line_count, lnum) - 1, 0, -1, -1,
+ decor, decor_flags, true, false, true, true, NULL);
}
/// For an existing, placed sign with "id", modify the sign, group or priority.
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index 39145d73ed..8ec28c7f61 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -2092,7 +2092,7 @@ char *parse_spelllang(win_T *wp)
} else {
// One entry in 'spellfile'.
copy_option_part(&spf, spf_name, MAXPATHL - 5, ",");
- STRCAT(spf_name, ".spl");
+ strcat(spf_name, ".spl");
int c;
// If it was already found above then skip it.
@@ -2677,7 +2677,7 @@ void ex_spellrepall(exarg_T *eap)
char *p = xmalloc((size_t)get_cursor_line_len() + (size_t)addlen + 1);
memmove(p, line, (size_t)curwin->w_cursor.col);
STRCPY(p + curwin->w_cursor.col, repl_to);
- STRCAT(p, line + curwin->w_cursor.col + repl_from_len);
+ strcat(p, line + curwin->w_cursor.col + repl_from_len);
ml_replace(curwin->w_cursor.lnum, p, false);
inserted_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col,
(int)repl_from_len, (int)repl_to_len);
@@ -3444,14 +3444,14 @@ static void dump_word(slang_T *slang, char *word, char *pat, Direction *dir, int
// Add flags and regions after a slash.
if ((flags & (WF_BANNED | WF_RARE | WF_REGION)) || keepcap) {
STRCPY(badword, p);
- STRCAT(badword, "/");
+ strcat(badword, "/");
if (keepcap) {
- STRCAT(badword, "=");
+ strcat(badword, "=");
}
if (flags & WF_BANNED) {
- STRCAT(badword, "!");
+ strcat(badword, "!");
} else if (flags & WF_RARE) {
- STRCAT(badword, "?");
+ strcat(badword, "?");
}
if (flags & WF_REGION) {
for (int i = 0; i < 7; i++) {
diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c
index 9746c3df91..ddeab218e1 100644
--- a/src/nvim/spellfile.c
+++ b/src/nvim/spellfile.c
@@ -2140,11 +2140,11 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char *fname)
+ strlen(items[1]) + 3, false);
if (spin->si_info != NULL) {
STRCPY(p, spin->si_info);
- STRCAT(p, "\n");
+ strcat(p, "\n");
}
- STRCAT(p, items[0]);
- STRCAT(p, " ");
- STRCAT(p, items[1]);
+ strcat(p, items[0]);
+ strcat(p, " ");
+ strcat(p, items[1]);
spin->si_info = p;
} else if (is_aff_rule(items, itemcnt, "MIDWORD", 2) && midword == NULL) {
midword = getroom_save(spin, items[1]);
@@ -2200,7 +2200,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char *fname)
// "Na" into "Na+", "1234" into "1234+".
p = getroom(spin, strlen(items[1]) + 2, false);
STRCPY(p, items[1]);
- STRCAT(p, "+");
+ strcat(p, "+");
compflags = p;
} else if (is_aff_rule(items, itemcnt, "COMPOUNDRULES", 2)) {
// We don't use the count, but do check that it's a number and
@@ -2221,9 +2221,9 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char *fname)
p = getroom(spin, (size_t)l, false);
if (compflags != NULL) {
STRCPY(p, compflags);
- STRCAT(p, "/");
+ strcat(p, "/");
}
- STRCAT(p, items[1]);
+ strcat(p, items[1]);
compflags = p;
}
} else if (is_aff_rule(items, itemcnt, "COMPOUNDWORDMAX", 2)
@@ -2844,7 +2844,7 @@ static void process_compflags(spellinfo_T *spin, afffile_T *aff, char *compflags
char *p = getroom(spin, (size_t)len, false);
if (spin->si_compflags != NULL) {
STRCPY(p, spin->si_compflags);
- STRCAT(p, "/");
+ strcat(p, "/");
}
spin->si_compflags = p;
uint8_t *tp = (uint8_t *)p + strlen(p);
@@ -3386,7 +3386,7 @@ static int store_aff_word(spellinfo_T *spin, char *word, char *afflist, afffile_
MB_PTR_ADV(p);
}
}
- STRCAT(newword, p);
+ strcat(newword, p);
} else {
// suffix: chop/add at the end of the word
xstrlcpy(newword, word, MAXWLEN);
@@ -3400,7 +3400,7 @@ static int store_aff_word(spellinfo_T *spin, char *word, char *afflist, afffile_
*p = NUL;
}
if (ae->ae_add != NULL) {
- STRCAT(newword, ae->ae_add);
+ strcat(newword, ae->ae_add);
}
}
diff --git a/src/nvim/spellsuggest.c b/src/nvim/spellsuggest.c
index 0e674c3178..ed1ba972d5 100644
--- a/src/nvim/spellsuggest.c
+++ b/src/nvim/spellsuggest.c
@@ -643,7 +643,7 @@ void spell_suggest(int count)
int c = (int)(sug.su_badptr - line);
memmove(p, line, (size_t)c);
STRCPY(p + c, stp->st_word);
- STRCAT(p, sug.su_badptr + stp->st_orglen);
+ strcat(p, sug.su_badptr + stp->st_orglen);
// For redo we use a change-word command.
ResetRedobuff();
@@ -1638,7 +1638,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
// Append a space to preword when splitting.
if (!try_compound && !fword_ends) {
- STRCAT(preword, " ");
+ strcat(preword, " ");
}
sp->ts_prewordlen = (uint8_t)strlen(preword);
sp->ts_splitoff = sp->ts_twordlen;
diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c
index ca7083a9e3..ad7e4587a9 100644
--- a/src/nvim/statusline.c
+++ b/src/nvim/statusline.c
@@ -1017,7 +1017,6 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op
int evaldepth = 0;
int curitem = 0;
- int foldsignitem = -1;
bool prevchar_isflag = true;
bool prevchar_isitem = false;
@@ -1234,6 +1233,8 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op
}
int minwid = 0;
int maxwid = 9999;
+ int foldsignitem = -1; // Start of fold or sign item
+ bool left_align_num = false; // Number item for should be left-aligned
bool left_align = false;
// Denotes that numbers should be left-padded with zeros
@@ -1505,12 +1506,20 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op
}
case STL_LINE:
- // Overload %l with v:lnum for 'statuscolumn'
- if (stcp != NULL) {
- if (wp->w_p_nu && !get_vim_var_nr(VV_VIRTNUM)) {
- num = (int)get_vim_var_nr(VV_LNUM);
+ // Overload %l with v:(re)lnum for 'statuscolumn'. Place a sign when 'signcolumn'
+ // is set to "number". Take care of alignment for 'number' + 'relativenumber'.
+ if (stcp != NULL && (wp->w_p_nu || wp->w_p_rnu) && get_vim_var_nr(VV_VIRTNUM) == 0) {
+ if (wp->w_maxscwidth == SCL_NUM && stcp->sattrs[0].text[0]) {
+ goto stcsign;
}
- } else {
+ int relnum = (int)get_vim_var_nr(VV_RELNUM);
+ num = (!wp->w_p_rnu || (wp->w_p_nu && relnum == 0)) ? (int)get_vim_var_nr(VV_LNUM) : relnum;
+ left_align_num = wp->w_p_rnu && wp->w_p_nu && relnum == 0;
+ if (!left_align_num) {
+ stl_items[curitem].type = Separate;
+ stl_items[curitem++].start = out_p;
+ }
+ } else if (stcp == NULL) {
num = (wp->w_buffer->b_ml.ml_flags & ML_EMPTY) ? 0 : wp->w_cursor.lnum;
}
break;
@@ -1609,16 +1618,9 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op
case STL_ROFLAG:
case STL_ROFLAG_ALT:
- // Overload %r with v:relnum for 'statuscolumn'
- if (stcp != NULL) {
- if (wp->w_p_rnu && !get_vim_var_nr(VV_VIRTNUM)) {
- num = (int)get_vim_var_nr(VV_RELNUM);
- }
- } else {
- itemisflag = true;
- if (wp->w_buffer->b_p_ro) {
- str = (opt == STL_ROFLAG_ALT) ? ",RO" : _("[RO]");
- }
+ itemisflag = true;
+ if (wp->w_buffer->b_p_ro) {
+ str = (opt == STL_ROFLAG_ALT) ? ",RO" : _("[RO]");
}
break;
@@ -1632,21 +1634,20 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op
case STL_FOLDCOL: // 'C' for 'statuscolumn'
case STL_SIGNCOL: { // 's' for 'statuscolumn'
+stcsign:
if (stcp == NULL) {
break;
}
- bool fold = opt == STL_FOLDCOL;
- int fdc = fold ? compute_foldcolumn(wp, 0) : 0;
- int width = fold ? fdc > 0 : wp->w_scwidth;
+ int fdc = opt == STL_FOLDCOL ? compute_foldcolumn(wp, 0) : 0;
+ int width = opt == STL_FOLDCOL ? fdc > 0 : opt == STL_SIGNCOL ? wp->w_scwidth : 1;
if (width <= 0) {
break;
}
foldsignitem = curitem;
- char *p = NULL;
- if (fold) {
- schar_T fold_buf[10];
+ if (fdc > 0) {
+ schar_T fold_buf[9];
fill_foldcolumn(wp, stcp->foldinfo, (linenr_T)get_vim_var_nr(VV_LNUM),
0, fdc, NULL, fold_buf);
stl_items[curitem].minwid = -((stcp->use_cul ? HLF_CLF : HLF_FC) + 1);
@@ -1654,31 +1655,26 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op
// TODO(bfredl): this is very backwards. we must support schar_T
// being used directly in 'statuscolumn'
for (int i = 0; i < fdc; i++) {
- buflen += schar_get(out_p + buflen, fold_buf[i]);
+ buflen += schar_get(buf_tmp + buflen, fold_buf[i]);
}
- p = out_p;
}
- char buf[SIGN_WIDTH * MAX_SCHAR_SIZE];
- size_t buflen = 0;
- varnumber_T virtnum = get_vim_var_nr(VV_VIRTNUM);
+ size_t signlen = 0;
for (int i = 0; i < width; i++) {
- if (!fold) {
- SignTextAttrs *sattr = virtnum ? NULL : &stcp->sattrs[i];
- p = " ";
- if (sattr && sattr->text[0]) {
- describe_sign_text(buf, sattr->text);
- p = buf;
+ stl_items[curitem].start = out_p + signlen;
+ if (fdc == 0) {
+ if (stcp->sattrs[i].text[0] && get_vim_var_nr(VV_VIRTNUM) == 0) {
+ SignTextAttrs sattrs = stcp->sattrs[i];
+ signlen += describe_sign_text(buf_tmp + signlen, sattrs.text);
+ stl_items[curitem].minwid = -(stcp->sign_cul_id ? stcp->sign_cul_id : sattrs.hl_id);
+ } else {
+ buf_tmp[signlen++] = ' ';
+ buf_tmp[signlen++] = ' ';
+ buf_tmp[signlen] = NUL;
+ stl_items[curitem].minwid = -((stcp->use_cul ? HLF_CLS : HLF_SC) + 1);
}
- stl_items[curitem].minwid = -(sattr && sattr->text[0]
- ? (stcp->sign_cul_id ? stcp->sign_cul_id : sattr->hl_id)
- : (stcp->use_cul ? HLF_CLS : HLF_SC) + 1);
}
- stl_items[curitem].type = Highlight;
- stl_items[curitem].start = out_p + buflen;
- xstrlcpy(buf_tmp + buflen, p, TMPLEN - buflen);
- buflen += strlen(p);
- curitem++;
+ stl_items[curitem++].type = Highlight;
}
str = buf_tmp;
break;
@@ -1851,7 +1847,6 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op
// For a 'statuscolumn' sign or fold item, add an item to reset the highlight group
if (foldsignitem >= 0) {
- foldsignitem = -1;
stl_items[curitem].type = Highlight;
stl_items[curitem].start = out_p;
stl_items[curitem].minwid = 0;
@@ -1956,6 +1951,11 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op
// Item processed, move to the next
curitem++;
+ // For a 'statuscolumn' number item that is left aligned, add a separator item.
+ if (left_align_num) {
+ stl_items[curitem].type = Separate;
+ stl_items[curitem++].start = out_p;
+ }
}
*out_p = NUL;
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index c13619797a..d1af8f304c 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -4992,7 +4992,7 @@ static int get_id_list(char **const arg, const int keylen, int16_t **const list,
} else {
// Handle match of regexp with group names.
*name = '^';
- STRCAT(name, "$");
+ strcat(name, "$");
regmatch.regprog = vim_regcomp(name, RE_MAGIC);
if (regmatch.regprog == NULL) {
failed = true;
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index ca3885b079..8f6342bfcc 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -1060,7 +1060,7 @@ static int add_llist_tags(char *tag, int num_matches, char **matches)
// Precede the tag pattern with \V to make it very
// nomagic.
- STRCAT(cmd, "\\V");
+ strcat(cmd, "\\V");
len += 2;
int cmd_len = (int)(cmd_end - cmd_start + 1);
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 2738eb874d..b16777be8a 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -112,6 +112,9 @@ typedef struct {
// libvterm. Improves performance when receiving large bursts of data.
#define REFRESH_DELAY 10
+#define TEXTBUF_SIZE 0x1fff
+#define SELECTIONBUF_SIZE 0x0400
+
static TimeWatcher refresh_timer;
static bool refresh_pending = false;
@@ -127,7 +130,7 @@ struct terminal {
// buffer used to:
// - convert VTermScreen cell arrays into utf8 strings
// - receive data from libvterm as a result of key presses.
- char textbuf[0x1fff];
+ char textbuf[TEXTBUF_SIZE];
ScrollbackLine **sb_buffer; // Scrollback storage.
size_t sb_current; // Lines stored in sb_buffer.
@@ -166,6 +169,9 @@ struct terminal {
// When there is a pending TermRequest autocommand, block and store input.
StringBuilder *pending_send;
+ char *selection_buffer; /// libvterm selection buffer
+ StringBuilder selection; /// Growable array containing full selection data
+
size_t refcount; // reference count
};
@@ -179,6 +185,12 @@ static VTermScreenCallbacks vterm_screen_callbacks = {
.sb_popline = term_sb_pop,
};
+static VTermSelectionCallbacks vterm_selection_callbacks = {
+ .set = term_selection_set,
+ // For security reasons we don't support querying the system clipboard from the embedded terminal
+ .query = NULL,
+};
+
static Set(ptr_t) invalidated_terminals = SET_INIT;
static void emit_termrequest(void **argv)
@@ -315,6 +327,11 @@ void terminal_open(Terminal **termpp, buf_T *buf, TerminalOptions opts)
vterm_screen_set_damage_merge(term->vts, VTERM_DAMAGE_SCROLL);
vterm_screen_reset(term->vts, 1);
vterm_output_set_callback(term->vt, term_output_callback, term);
+
+ term->selection_buffer = xcalloc(SELECTIONBUF_SIZE, 1);
+ vterm_state_set_selection_callbacks(state, &vterm_selection_callbacks, term,
+ term->selection_buffer, SELECTIONBUF_SIZE);
+
// force a initial refresh of the screen to ensure the buffer will always
// have as many lines as screen rows when refresh_scrollback is called
term->invalid_start = 0;
@@ -326,14 +343,6 @@ void terminal_open(Terminal **termpp, buf_T *buf, TerminalOptions opts)
refresh_screen(term, buf);
set_option_value(kOptBuftype, STATIC_CSTR_AS_OPTVAL("terminal"), OPT_LOCAL);
- // Default settings for terminal buffers
- buf->b_p_ma = false; // 'nomodifiable'
- buf->b_p_ul = -1; // 'undolevels'
- buf->b_p_scbk = // 'scrollback' (initialize local from global)
- (p_scbk < 0) ? 10000 : MAX(1, p_scbk);
- buf->b_p_tw = 0; // 'textwidth'
- set_option_value(kOptWrap, BOOLEAN_OPTVAL(false), OPT_LOCAL);
- set_option_value(kOptList, BOOLEAN_OPTVAL(false), OPT_LOCAL);
if (buf->b_ffname != NULL) {
buf_set_term_title(buf, buf->b_ffname, strlen(buf->b_ffname));
}
@@ -769,6 +778,8 @@ void terminal_destroy(Terminal **termpp)
}
xfree(term->sb_buffer);
xfree(term->title);
+ xfree(term->selection_buffer);
+ kv_destroy(term->selection);
vterm_free(term->vt);
xfree(term);
*termpp = NULL; // coverity[dead-store]
@@ -1198,6 +1209,54 @@ static int term_sb_pop(int cols, VTermScreenCell *cells, void *data)
return 1;
}
+static void term_clipboard_set(void **argv)
+{
+ VTermSelectionMask mask = (VTermSelectionMask)(long)argv[0];
+ char *data = argv[1];
+
+ char regname;
+ switch (mask) {
+ case VTERM_SELECTION_CLIPBOARD:
+ regname = '+';
+ break;
+ case VTERM_SELECTION_PRIMARY:
+ regname = '*';
+ break;
+ default:
+ regname = '+';
+ break;
+ }
+
+ list_T *lines = tv_list_alloc(1);
+ tv_list_append_allocated_string(lines, data);
+
+ list_T *args = tv_list_alloc(3);
+ tv_list_append_list(args, lines);
+
+ const char regtype = 'v';
+ tv_list_append_string(args, &regtype, 1);
+
+ tv_list_append_string(args, &regname, 1);
+ eval_call_provider("clipboard", "set", args, true);
+}
+
+static int term_selection_set(VTermSelectionMask mask, VTermStringFragment frag, void *user)
+{
+ Terminal *term = user;
+ if (frag.initial) {
+ kv_size(term->selection) = 0;
+ }
+
+ kv_concat_len(term->selection, frag.str, frag.len);
+
+ if (frag.final) {
+ char *data = xmemdupz(term->selection.items, kv_size(term->selection));
+ multiqueue_put(main_loop.events, term_clipboard_set, (void *)mask, data);
+ }
+
+ return 1;
+}
+
// }}}
// input handling {{{
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index 9bb66b886e..314d322a68 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -144,11 +144,15 @@ void ui_free_all_mem(void)
/// Returns true if any `rgb=true` UI is attached.
bool ui_rgb_attached(void)
{
- if (!headless_mode && p_tgc) {
+ if (p_tgc) {
return true;
}
for (size_t i = 0; i < ui_count; i++) {
- if (uis[i]->rgb) {
+ // We do not consider the TUI in this loop because we already checked for 'termguicolors' at the
+ // beginning of this function. In this loop, we are checking to see if any _other_ UIs which
+ // support RGB are attached.
+ bool tui = uis[i]->stdin_tty || uis[i]->stdout_tty;
+ if (!tui && uis[i]->rgb) {
return true;
}
}
diff --git a/src/nvim/usercmd.c b/src/nvim/usercmd.c
index 79f897f020..2893c7cf9f 100644
--- a/src/nvim/usercmd.c
+++ b/src/nvim/usercmd.c
@@ -1274,9 +1274,9 @@ static size_t add_cmd_modifier(char *buf, char *mod_str, bool *multi_mods)
if (buf != NULL) {
if (*multi_mods) {
- STRCAT(buf, " ");
+ strcat(buf, " ");
}
- STRCAT(buf, mod_str);
+ strcat(buf, mod_str);
}
*multi_mods = true;
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index b32f2b1cb2..d28064447c 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -3887,11 +3887,11 @@ describe('API', function()
))
eq(
{
- str = '3 ',
- width = 2,
+ str = ' 3 ',
+ width = 9,
highlights = {
{ group = 'LineNr', start = 0 },
- { group = 'ErrorMsg', start = 1 },
+ { group = 'ErrorMsg', start = 8 },
},
},
api.nvim_eval_statusline('%l%#ErrorMsg# ', { use_statuscol_lnum = 3, highlights = true })
diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua
index a53625ab1b..1bb4ce2946 100644
--- a/test/functional/core/startup_spec.lua
+++ b/test/functional/core/startup_spec.lua
@@ -400,9 +400,6 @@ describe('startup', function()
read_file('Xtest_startup_ttyout')
)
end)
- if is_os('win') then
- assert_log('stream write failed. RPC canceled; closing channel', testlog)
- end
end)
it('input from pipe: has("ttyin")==0 has("ttyout")==1', function()
@@ -435,9 +432,6 @@ describe('startup', function()
read_file('Xtest_startup_ttyout')
)
end)
- if is_os('win') then
- assert_log('stream write failed. RPC canceled; closing channel', testlog)
- end
end)
it('input from pipe (implicit) #7679', function()
diff --git a/test/functional/editor/macro_spec.lua b/test/functional/editor/macro_spec.lua
index 27c5eddac8..680a70b78a 100644
--- a/test/functional/editor/macro_spec.lua
+++ b/test/functional/editor/macro_spec.lua
@@ -148,6 +148,23 @@ helloFOO]]
eq({ 0, 1, 1, 0 }, fn.getpos('v'))
end)
+ it('can be recorded and replayed in Visual mode when ignorecase', function()
+ command('set ignorecase')
+ insert('foo BAR BAR foo BAR foo BAR BAR BAR foo BAR BAR')
+ feed('0vqifofRq')
+ eq({ 0, 1, 7, 0 }, fn.getpos('.'))
+ eq({ 0, 1, 1, 0 }, fn.getpos('v'))
+ feed('Q')
+ eq({ 0, 1, 19, 0 }, fn.getpos('.'))
+ eq({ 0, 1, 1, 0 }, fn.getpos('v'))
+ feed('Q')
+ eq({ 0, 1, 27, 0 }, fn.getpos('.'))
+ eq({ 0, 1, 1, 0 }, fn.getpos('v'))
+ feed('@i')
+ eq({ 0, 1, 43, 0 }, fn.getpos('.'))
+ eq({ 0, 1, 1, 0 }, fn.getpos('v'))
+ end)
+
it('can be replayed with @ in blockwise Visual mode', function()
insert [[
hello
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index d50b646085..23bb9f0a2e 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -135,14 +135,15 @@ describe('lua stdlib', function()
-- See MAINTAIN.md for the soft/hard deprecation policy
describe(('vim.deprecate prerel=%s,'):format(prerel or 'nil'), function()
- local curver = exec_lua('return vim.version()') --[[@as {major:number, minor:number}]]
- -- "0.10" or "0.10-dev+xxx"
- local curstr = ('%s.%s%s'):format(curver.major, curver.minor, prerel or '')
- -- "0.10" or "0.11"
- local nextver = ('%s.%s'):format(curver.major, curver.minor + (prerel and 0 or 1))
- local was_removed = prerel and 'was removed' or 'will be removed'
+ local curver --- @type {major:number, minor:number}
+
+ before_each(function()
+ curver = exec_lua('return vim.version()')
+ end)
it('plugin=nil, same message skipped', function()
+ -- "0.10" or "0.10-dev+xxx"
+ local curstr = ('%s.%s%s'):format(curver.major, curver.minor, prerel or '')
eq(
dedent(
[[
@@ -162,6 +163,10 @@ describe('lua stdlib', function()
end)
it('plugin=nil, show error if hard-deprecated', function()
+ -- "0.10" or "0.11"
+ local nextver = ('%s.%s'):format(curver.major, curver.minor + (prerel and 0 or 1))
+
+ local was_removed = prerel and 'was removed' or 'will be removed'
eq(
dedent(
[[
@@ -2023,6 +2028,10 @@ describe('lua stdlib', function()
vim.cmd "enew"
]]
eq(100, fn.luaeval 'vim.wo.scrolloff')
+
+ matches('only bufnr=0 is supported', pcall_err(exec_lua, 'vim.wo[0][10].signcolumn = "no"'))
+
+ matches('only bufnr=0 is supported', pcall_err(exec_lua, 'local a = vim.wo[0][10].signcolumn'))
end)
describe('vim.opt', function()
diff --git a/test/functional/plugin/lsp/completion_spec.lua b/test/functional/plugin/lsp/completion_spec.lua
index 0e81e4fddb..1b56d1740a 100644
--- a/test/functional/plugin/lsp/completion_spec.lua
+++ b/test/functional/plugin/lsp/completion_spec.lua
@@ -81,10 +81,21 @@ describe('vim.lsp.completion: item conversion', function()
-- plain text
{
label = 'foocar',
- sortText = 'k',
+ sortText = 'g',
insertText = 'foodar(${1:var1})',
insertTextFormat = 1,
},
+ {
+ label = '•INT16_C(c)',
+ insertText = 'INT16_C(${1:c})',
+ insertTextFormat = 2,
+ filterText = 'INT16_C',
+ sortText = 'h',
+ textEdit = {
+ newText = 'INT16_C(${1:c})',
+ range = range0,
+ },
+ },
}
local expected = {
{
@@ -115,6 +126,10 @@ describe('vim.lsp.completion: item conversion', function()
abbr = 'foocar',
word = 'foodar(${1:var1})', -- marked as PlainText, text is used as is
},
+ {
+ abbr = '•INT16_C(c)',
+ word = 'INT16_C',
+ },
}
local result = complete('|', completion_list)
result = vim.tbl_map(function(x)
diff --git a/test/functional/plugin/lsp/semantic_tokens_spec.lua b/test/functional/plugin/lsp/semantic_tokens_spec.lua
index 7908c5d2e7..9babb080e7 100644
--- a/test/functional/plugin/lsp/semantic_tokens_spec.lua
+++ b/test/functional/plugin/lsp/semantic_tokens_spec.lua
@@ -111,6 +111,7 @@ describe('semantic token highlighting', function()
end)
it('buffer is highlighted when attached', function()
+ insert(text)
exec_lua([[
bufnr = vim.api.nvim_get_current_buf()
vim.api.nvim_win_set_buf(0, bufnr)
@@ -118,8 +119,6 @@ describe('semantic token highlighting', function()
client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
]])
- insert(text)
-
screen:expect {
grid = [[
#include <iostream> |
@@ -141,6 +140,7 @@ describe('semantic token highlighting', function()
end)
it('use LspTokenUpdate and highlight_token', function()
+ insert(text)
exec_lua([[
vim.api.nvim_create_autocmd("LspTokenUpdate", {
callback = function(args)
@@ -157,8 +157,6 @@ describe('semantic token highlighting', function()
client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
]])
- insert(text)
-
screen:expect {
grid = [[
#include <iostream> |
@@ -180,14 +178,17 @@ describe('semantic token highlighting', function()
end)
it('buffer is unhighlighted when client is detached', function()
+ insert(text)
+
exec_lua([[
bufnr = vim.api.nvim_get_current_buf()
vim.api.nvim_win_set_buf(0, bufnr)
client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
+ vim.wait(1000, function()
+ return #server.messages > 1
+ end)
]])
- insert(text)
-
exec_lua([[
vim.notify = function() end
vim.lsp.buf_detach_client(bufnr, client_id)
@@ -331,14 +332,13 @@ describe('semantic token highlighting', function()
end)
it('buffer is re-highlighted when force refreshed', function()
+ insert(text)
exec_lua([[
bufnr = vim.api.nvim_get_current_buf()
vim.api.nvim_win_set_buf(0, bufnr)
client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
]])
- insert(text)
-
screen:expect {
grid = [[
#include <iostream> |
@@ -412,13 +412,14 @@ describe('semantic token highlighting', function()
end)
it('updates highlights with delta request on buffer change', function()
+ insert(text)
+
exec_lua([[
bufnr = vim.api.nvim_get_current_buf()
vim.api.nvim_win_set_buf(0, bufnr)
client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
]])
- insert(text)
screen:expect {
grid = [[
#include <iostream> |
@@ -597,6 +598,7 @@ describe('semantic token highlighting', function()
end)
it('does not send delta requests if not supported by server', function()
+ insert(text)
exec_lua(
[[
local legend, response, edit_response = ...
@@ -625,7 +627,6 @@ describe('semantic token highlighting', function()
edit_response
)
- insert(text)
screen:expect {
grid = [[
#include <iostream> |
@@ -1449,6 +1450,7 @@ int main()
},
}) do
it(test.it, function()
+ insert(test.text1)
exec_lua(create_server_definition)
exec_lua(
[[
@@ -1485,8 +1487,6 @@ int main()
test.response2
)
- insert(test.text1)
-
test.expected_screen1()
local highlights = exec_lua([[
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index 50e9c0cc0f..b345a3288c 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -255,7 +255,7 @@ describe('LSP', function()
return
end
local expected_handlers = {
- { NIL, {}, { method = 'shutdown', bufnr = 1, client_id = 1 } },
+ { NIL, {}, { method = 'shutdown', bufnr = 1, client_id = 1, version = 0 } },
{ NIL, {}, { method = 'test', client_id = 1 } },
}
test_rpc_server {
@@ -948,7 +948,11 @@ describe('LSP', function()
it('should forward ContentModified to callback', function()
local expected_handlers = {
{ NIL, {}, { method = 'finish', client_id = 1 } },
- { { code = -32801 }, NIL, { method = 'error_code_test', bufnr = 1, client_id = 1 } },
+ {
+ { code = -32801 },
+ NIL,
+ { method = 'error_code_test', bufnr = 1, client_id = 1, version = 0 },
+ },
}
local client --- @type vim.lsp.Client
test_rpc_server {
@@ -978,7 +982,7 @@ describe('LSP', function()
it('should track pending requests to the language server', function()
local expected_handlers = {
{ NIL, {}, { method = 'finish', client_id = 1 } },
- { NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1 } },
+ { NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1, version = 0 } },
}
local client --- @type vim.lsp.Client
test_rpc_server {
@@ -1045,7 +1049,7 @@ describe('LSP', function()
it('should clear pending and cancel requests on reply', function()
local expected_handlers = {
{ NIL, {}, { method = 'finish', client_id = 1 } },
- { NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1 } },
+ { NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1, version = 0 } },
}
local client --- @type vim.lsp.Client
test_rpc_server {
@@ -1084,7 +1088,7 @@ describe('LSP', function()
it('should trigger LspRequest autocmd when requests table changes', function()
local expected_handlers = {
{ NIL, {}, { method = 'finish', client_id = 1 } },
- { NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1 } },
+ { NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1, version = 0 } },
}
local client --- @type vim.lsp.Client
test_rpc_server {
@@ -1364,6 +1368,7 @@ describe('LSP', function()
},
bufnr = 2,
client_id = 1,
+ version = 0,
},
},
{ NIL, {}, { method = 'start', client_id = 1 } },
diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua
index 96abd9f543..365a4f8035 100644
--- a/test/functional/terminal/buffer_spec.lua
+++ b/test/functional/terminal/buffer_spec.lua
@@ -199,7 +199,7 @@ describe(':terminal buffer', function()
{5:========== }|
rows: 2, cols: 50 |
{2: } |
- {1:========== }|
+ {18:========== }|
|
]])
@@ -340,7 +340,7 @@ describe(':terminal buffer', function()
eq(termbuf, eval('g:termbuf'))
end)
- it('TermReqeust synchronization #27572', function()
+ it('TermRequest synchronization #27572', function()
command('autocmd! nvim_terminal TermRequest')
local term = exec_lua([[
_G.input = {}
diff --git a/test/functional/terminal/clipboard_spec.lua b/test/functional/terminal/clipboard_spec.lua
new file mode 100644
index 0000000000..4a1a0e29fd
--- /dev/null
+++ b/test/functional/terminal/clipboard_spec.lua
@@ -0,0 +1,65 @@
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
+local eq = t.eq
+local retry = t.retry
+
+local clear = n.clear
+local fn = n.fn
+local testprg = n.testprg
+local exec_lua = n.exec_lua
+local eval = n.eval
+
+describe(':terminal', function()
+ before_each(function()
+ clear()
+
+ exec_lua([[
+ local function clipboard(reg, type)
+ if type == 'copy' then
+ return function(lines)
+ local data = table.concat(lines, '\n')
+ vim.g.clipboard_data = data
+ end
+ end
+
+ if type == 'paste' then
+ return function()
+ error()
+ end
+ end
+
+ error('invalid type: ' .. type)
+ end
+
+ vim.g.clipboard = {
+ name = 'Test',
+ copy = {
+ ['+'] = clipboard('+', 'copy'),
+ ['*'] = clipboard('*', 'copy'),
+ },
+ paste = {
+ ['+'] = clipboard('+', 'paste'),
+ ['*'] = clipboard('*', 'paste'),
+ },
+ }
+ ]])
+ end)
+
+ it('can write to the system clipboard', function()
+ eq('Test', eval('g:clipboard.name'))
+
+ local text = 'Hello, world! This is some\nexample text\nthat spans multiple\nlines'
+ local encoded = exec_lua('return vim.base64.encode(...)', text)
+
+ local function osc52(arg)
+ return string.format('\027]52;;%s\027\\', arg)
+ end
+
+ fn.termopen({ testprg('shell-test'), '-t', osc52(encoded) })
+
+ retry(nil, 1000, function()
+ eq(text, exec_lua([[ return vim.g.clipboard_data ]]))
+ end)
+ end)
+end)
diff --git a/test/functional/terminal/mouse_spec.lua b/test/functional/terminal/mouse_spec.lua
index ad98dfc6c3..476e2a5fe5 100644
--- a/test/functional/terminal/mouse_spec.lua
+++ b/test/functional/terminal/mouse_spec.lua
@@ -14,10 +14,12 @@ describe(':terminal mouse', function()
before_each(function()
clear()
api.nvim_set_option_value('statusline', '==========', {})
- command('highlight StatusLine cterm=NONE')
- command('highlight StatusLineNC cterm=NONE')
- command('highlight VertSplit cterm=NONE')
screen = tt.screen_setup()
+ command('highlight StatusLine NONE')
+ command('highlight StatusLineNC NONE')
+ command('highlight StatusLineTerm NONE')
+ command('highlight StatusLineTermNC NONE')
+ command('highlight VertSplit NONE')
local lines = {}
for i = 1, 30 do
table.insert(lines, 'line' .. tostring(i))
diff --git a/test/functional/terminal/testutil.lua b/test/functional/terminal/testutil.lua
index f3fc5d3f93..45c73b1dc6 100644
--- a/test/functional/terminal/testutil.lua
+++ b/test/functional/terminal/testutil.lua
@@ -92,6 +92,8 @@ local function screen_setup(extra_rows, command, cols, env, screen_opts)
api.nvim_command('highlight TermCursor cterm=reverse')
api.nvim_command('highlight TermCursorNC ctermbg=11')
+ api.nvim_command('highlight StatusLineTerm ctermbg=2 ctermfg=0')
+ api.nvim_command('highlight StatusLineTermNC ctermbg=2 ctermfg=8')
local screen = Screen.new(cols, 7 + extra_rows)
screen:set_default_attr_ids({
@@ -111,6 +113,8 @@ local function screen_setup(extra_rows, command, cols, env, screen_opts)
[14] = { underline = true, reverse = true, bold = true },
[15] = { underline = true, foreground = 12 },
[16] = { background = 248, foreground = 0 }, -- Visual in :terminal session
+ [17] = { background = 2, foreground = 0 }, -- StatusLineTerm
+ [18] = { background = 2, foreground = 8 }, -- StatusLineTermNC
})
screen:attach(screen_opts or { rgb = false })
diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua
index 80df336cc4..5269af760a 100644
--- a/test/functional/terminal/tui_spec.lua
+++ b/test/functional/terminal/tui_spec.lua
@@ -1056,6 +1056,11 @@ describe('TUI', function()
if is_ci('github') then
pending('tty-test complains about not owning the terminal -- actions/runner#241')
end
+ screen:set_default_attr_ids({
+ [1] = { reverse = true }, -- focused cursor
+ [3] = { bold = true },
+ [19] = { bold = true, background = 121, foreground = 0 }, -- StatusLineTerm
+ })
child_exec_lua('vim.o.statusline="^^^^^^^"')
child_exec_lua('vim.cmd.terminal(...)', testprg('tty-test'))
feed_data('i')
@@ -1063,7 +1068,7 @@ describe('TUI', function()
tty ready |
{1: } |
|*2
- {5:^^^^^^^ }|
+ {19:^^^^^^^ }|
{3:-- TERMINAL --} |*2
]])
feed_data('\027[200~')
@@ -1073,7 +1078,7 @@ describe('TUI', function()
tty ready |
hallo{1: } |
|*2
- {5:^^^^^^^ }|
+ {19:^^^^^^^ }|
{3:-- TERMINAL --} |*2
]])
end)
@@ -1548,10 +1553,32 @@ describe('TUI', function()
screen:set_rgb_cterm(true)
screen:set_default_attr_ids({
[1] = { { reverse = true }, { reverse = true } },
- [2] = { { bold = true, reverse = true }, { bold = true, reverse = true } },
+ [2] = {
+ { bold = true, background = Screen.colors.LightGreen, foreground = Screen.colors.Black },
+ { bold = true },
+ },
[3] = { { bold = true }, { bold = true } },
[4] = { { fg_indexed = true, foreground = tonumber('0xe0e000') }, { foreground = 3 } },
[5] = { { foreground = tonumber('0xff8000') }, {} },
+ [6] = {
+ {
+ fg_indexed = true,
+ bg_indexed = true,
+ bold = true,
+ background = tonumber('0x66ff99'),
+ foreground = Screen.colors.Black,
+ },
+ { bold = true, background = 121, foreground = 0 },
+ },
+ [7] = {
+ {
+ fg_indexed = true,
+ bg_indexed = true,
+ background = tonumber('0x66ff99'),
+ foreground = Screen.colors.Black,
+ },
+ { background = 121, foreground = 0 },
+ },
})
child_exec_lua('vim.o.statusline="^^^^^^^"')
@@ -1586,7 +1613,7 @@ describe('TUI', function()
{1:t}ty ready |
{4:text}colortext |
|*2
- {2:^^^^^^^ }|
+ {6:^^^^^^^}{7: }|
:set notermguicolors |
{3:-- TERMINAL --} |
]],
@@ -1973,6 +2000,7 @@ describe('TUI', function()
[3] = { bold = true },
[4] = { foreground = tonumber('0x4040ff'), fg_indexed = true },
[5] = { bold = true, reverse = true },
+ [6] = { foreground = Screen.colors.White, background = Screen.colors.DarkGreen },
})
screen:attach()
fn.termopen({
@@ -1998,7 +2026,7 @@ describe('TUI', function()
{2:~ }│{4:~ }|*5
{2:~ }│{5:[No Name] 0,0-1 All}|
{2:~ }│ |
- {5:new }{1:{MATCH:<.*[/\]nvim }}|
+ {5:new }{6:{MATCH:<.*[/\]nvim }}|
|
]])
end)
diff --git a/test/functional/terminal/window_spec.lua b/test/functional/terminal/window_spec.lua
index f85e26a66d..64534ca8dc 100644
--- a/test/functional/terminal/window_spec.lua
+++ b/test/functional/terminal/window_spec.lua
@@ -13,6 +13,26 @@ local skip = t.skip
local is_os = t.is_os
describe(':terminal window', function()
+ before_each(clear)
+
+ it('sets local values of window options #29325', function()
+ command('setglobal wrap list')
+ command('terminal')
+ eq({ 0, 0, 1 }, eval('[&l:wrap, &wrap, &g:wrap]'))
+ eq({ 0, 0, 1 }, eval('[&l:list, &list, &g:list]'))
+ command('enew')
+ eq({ 1, 1, 1 }, eval('[&l:wrap, &wrap, &g:wrap]'))
+ eq({ 1, 1, 1 }, eval('[&l:list, &list, &g:list]'))
+ command('buffer #')
+ eq({ 0, 0, 1 }, eval('[&l:wrap, &wrap, &g:wrap]'))
+ eq({ 0, 0, 1 }, eval('[&l:list, &list, &g:list]'))
+ command('new')
+ eq({ 1, 1, 1 }, eval('[&l:wrap, &wrap, &g:wrap]'))
+ eq({ 1, 1, 1 }, eval('[&l:list, &list, &g:list]'))
+ end)
+end)
+
+describe(':terminal window', function()
local screen
before_each(function()
@@ -110,9 +130,9 @@ describe(':terminal window', function()
]])
feed_data('\nabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
screen:expect([[
- {7:++7 } |
- {7:++8 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR|
- {7:++9 }TUVWXYZ |
+ {7:++ 7 } |
+ {7:++ 8 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR|
+ {7:++ 9 }TUVWXYZ |
{7:++10 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR|
{7:++11 }TUVWXYZrows: 6, cols: 44 |
{7:++12 }{1: } |
diff --git a/test/functional/terminal/window_split_tab_spec.lua b/test/functional/terminal/window_split_tab_spec.lua
index 04d2e0bca7..ccd6a5218b 100644
--- a/test/functional/terminal/window_split_tab_spec.lua
+++ b/test/functional/terminal/window_split_tab_spec.lua
@@ -22,10 +22,12 @@ describe(':terminal', function()
-- set the statusline to a constant value because of variables like pid
-- and current directory and to improve visibility of splits
api.nvim_set_option_value('statusline', '==========', {})
- command('highlight StatusLine cterm=NONE')
- command('highlight StatusLineNC cterm=NONE')
- command('highlight VertSplit cterm=NONE')
screen = tt.screen_setup(3)
+ command('highlight StatusLine NONE')
+ command('highlight StatusLineNC NONE')
+ command('highlight StatusLineTerm NONE')
+ command('highlight StatusLineTermNC NONE')
+ command('highlight VertSplit NONE')
end)
after_each(function()
diff --git a/test/functional/testnvim.lua b/test/functional/testnvim.lua
index 746c7290ef..5a9e7f8c29 100644
--- a/test/functional/testnvim.lua
+++ b/test/functional/testnvim.lua
@@ -22,7 +22,7 @@ local runtime_set = 'set runtimepath^=./build/lib/nvim/'
M.nvim_prog = (os.getenv('NVIM_PRG') or t.paths.test_build_dir .. '/bin/nvim')
-- Default settings for the test session.
M.nvim_set = (
- 'set shortmess+=IS background=light termguicolors noswapfile noautoindent startofline'
+ 'set shortmess+=IS background=light noswapfile noautoindent startofline'
.. ' laststatus=1 undodir=. directory=. viewdir=. backupdir=.'
.. ' belloff= wildoptions-=pum joinspaces noshowcmd noruler nomore redrawdebug=invalid'
)
diff --git a/test/functional/ui/cursor_spec.lua b/test/functional/ui/cursor_spec.lua
index 8bfceb8cce..619153724b 100644
--- a/test/functional/ui/cursor_spec.lua
+++ b/test/functional/ui/cursor_spec.lua
@@ -246,11 +246,11 @@ describe('ui/cursor', function()
end
end
if m.hl_id then
- m.hl_id = 64
+ m.hl_id = 66
m.attr = { background = Screen.colors.DarkGray }
end
if m.id_lm then
- m.id_lm = 69
+ m.id_lm = 73
end
end
diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua
index cdaae6cfee..7aff47e50e 100644
--- a/test/functional/ui/float_spec.lua
+++ b/test/functional/ui/float_spec.lua
@@ -1532,9 +1532,9 @@ describe('float window', function()
[2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
- {20:1}{19: }{20: }{22:^x}{21: }|
- {14:2}{19: }{14: }{22:y} |
- {14:3}{19: }{14: }{22: } |
+ {20: 1}{19: }{22:^x}{21: }|
+ {14: 2}{19: }{22:y} |
+ {14: 3}{19: }{22: } |
{0:~ }|*3
## grid 3
|
@@ -1545,9 +1545,9 @@ describe('float window', function()
]], float_pos={[4] = {1001, "NW", 1, 4, 10, true}}}
else
screen:expect{grid=[[
- {20:1}{19: }{20: }{22:^x}{21: }|
- {14:2}{19: }{14: }{22:y} |
- {14:3}{19: }{14: }{22: } {15:x } |
+ {20: 1}{19: }{22:^x}{21: }|
+ {14: 2}{19: }{22:y} |
+ {14: 3}{19: }{22: } {15:x } |
{0:~ }{15:y }{0: }|
{0:~ }{15: }{0: }|*2
|
diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua
index 8f8604eecb..4ea60194c2 100644
--- a/test/functional/ui/popupmenu_spec.lua
+++ b/test/functional/ui/popupmenu_spec.lua
@@ -1129,7 +1129,7 @@ describe("builtin popupmenu 'pumblend'", function()
[10] = { foreground = tonumber('0x000002') },
})
screen:attach({ rgb = false })
- command('set notermguicolors pumblend=10')
+ command('set pumblend=10')
insert([[
Lorem ipsum dolor sit amet, consectetur
adipisicing elit, sed do eiusmod tempor
@@ -1177,6 +1177,8 @@ describe('builtin popupmenu', function()
ks = { foreground = Screen.colors.Red, background = Screen.colors.Grey },
xn = { foreground = Screen.colors.White, background = Screen.colors.Magenta },
xs = { foreground = Screen.colors.Black, background = Screen.colors.Grey },
+ mn = { foreground = Screen.colors.Blue, background = Screen.colors.Magenta },
+ ms = { foreground = Screen.colors.Blue, background = Screen.colors.Grey },
})
screen:attach({ ext_multigrid = multigrid })
end)
@@ -2528,6 +2530,7 @@ describe('builtin popupmenu', function()
]],
}
+ -- oldtest: Test_wildmenu_pum_rightleft()
feed('<tab>')
screen:expect {
grid = [[
@@ -4477,6 +4480,27 @@ describe('builtin popupmenu', function()
feed('<Esc>')
+ command('set rightleft')
+ feed('/X<CR>:popup PopUp<CR>')
+ screen:expect([[
+ evif ruof eerht owt eno|
+ evif ruof eerht{7:^X} owt eno dna|
+ {n: odnU }wt erom eno|
+ {1: }{n: }{1: ~}|
+ {1: }{n: etsaP }{1: ~}|
+ {1: }{n: }{1: ~}|
+ {1: }{n: droW tceleS }{1: ~}|
+ {1: }{n: ecnetneS tceleS }{1: ~}|
+ {1: }{n: hpargaraP tceleS }{1: ~}|
+ {1: }{n: eniL tceleS }{1: ~}|
+ {1: }{n: kcolB tceleS }{1: ~}|
+ {1: }{n: llA tceleS }{1: ~}|
+ {1: ~}|*7
+ :popup PopUp |
+ ]])
+ feed('<Esc>')
+ command('set norightleft')
+
-- Set an <expr> mapping to change a menu entry while it's displayed.
-- The text should not change but the command does.
-- Also verify that "changed" shows up, which means the mapping triggered.
@@ -4533,6 +4557,55 @@ describe('builtin popupmenu', function()
feed('<Esc>')
end)
+ -- oldtest: Test_mouse_popup_position()
+ it('position of right-click menu when clicking near edge', function()
+ screen:try_resize(50, 20)
+ exec([[
+ set mousemodel=popup_setpos
+ aunmenu *
+ source $VIMRUNTIME/menu.vim
+ call setline(1, join(range(20)))
+ ]])
+
+ api.nvim_input_mouse('right', 'press', '', 0, 0, 45 - 1)
+ screen:expect([[
+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ^18 19 |
+ {1:~ }{n: Undo }|
+ {1:~ }{n: }|
+ {1:~ }{n: Paste }|
+ {1:~ }{n: }|
+ {1:~ }{n: Select Word }|
+ {1:~ }{n: Select Sentence }|
+ {1:~ }{n: Select Paragraph}|
+ {1:~ }{n: Select Line }|
+ {1:~ }{n: Select Block }|
+ {1:~ }{n: Select All }|
+ {1:~ }|*8
+ |
+ ]])
+ feed('<Esc>')
+
+ command('set rightleft')
+ api.nvim_input_mouse('right', 'press', '', 0, 0, 50 - 45)
+ screen:expect([[
+ 91 8^1 71 61 51 41 31 21 11 01 9 8 7 6 5 4 3 2 1 0|
+ {n: odnU }{1: ~}|
+ {n: }{1: ~}|
+ {n: etsaP }{1: ~}|
+ {n: }{1: ~}|
+ {n: droW tceleS }{1: ~}|
+ {n: ecnetneS tceleS }{1: ~}|
+ {n:hpargaraP tceleS }{1: ~}|
+ {n: eniL tceleS }{1: ~}|
+ {n: kcolB tceleS }{1: ~}|
+ {n: llA tceleS }{1: ~}|
+ {1: ~}|*8
+ |
+ ]])
+ feed('<Esc>')
+ command('set norightleft')
+ end)
+
describe('"kind" and "menu"', function()
before_each(function()
screen:try_resize(30, 8)
@@ -4585,6 +4658,167 @@ describe('builtin popupmenu', function()
]])
end)
end)
+
+ -- oldtest: Test_pum_highlights_match()
+ it('can highlight matched text', function()
+ exec([[
+ func Omni_test(findstart, base)
+ if a:findstart
+ return col(".")
+ endif
+ return {
+ \ 'words': [
+ \ { 'word': 'foo', 'kind': 'fookind' },
+ \ { 'word': 'foofoo', 'kind': 'fookind' },
+ \ { 'word': 'foobar', 'kind': 'fookind' },
+ \ { 'word': 'fooBaz', 'kind': 'fookind' },
+ \ { 'word': 'foobala', 'kind': 'fookind' },
+ \ { 'word': '你好' },
+ \ { 'word': '你好吗' },
+ \ { 'word': '你不好吗' },
+ \ { 'word': '你可好吗' },
+ \]}
+ endfunc
+ set omnifunc=Omni_test
+ set completeopt=menu,noinsert,fuzzy
+ hi PmenuMatchSel guifg=Blue guibg=Grey
+ hi PmenuMatch guifg=Blue guibg=Magenta
+ ]])
+ feed('i<C-X><C-O>')
+ local pum_start = [[
+ ^ |
+ {s:foo fookind }{1: }|
+ {n:foofoo fookind }{1: }|
+ {n:foobar fookind }{1: }|
+ {n:fooBaz fookind }{1: }|
+ {n:foobala fookind }{1: }|
+ {n:你好 }{1: }|
+ {n:你好吗 }{1: }|
+ {n:你不好吗 }{1: }|
+ {n:你可好吗 }{1: }|
+ {1:~ }|*9
+ {2:-- }{5:match 1 of 9} |
+ ]]
+ screen:expect(pum_start)
+ feed('fo')
+ screen:expect([[
+ fo^ |
+ {ms:fo}{s:o fookind }{1: }|
+ {mn:fo}{n:ofoo fookind }{1: }|
+ {mn:fo}{n:obar fookind }{1: }|
+ {mn:fo}{n:oBaz fookind }{1: }|
+ {mn:fo}{n:obala fookind }{1: }|
+ {1:~ }|*13
+ {2:-- }{5:match 1 of 9} |
+ ]])
+ feed('<Esc>S<C-X><C-O>')
+ screen:expect(pum_start)
+ feed('你')
+ screen:expect([[
+ 你^ |
+ {ms:你}{s:好 }{1: }|
+ {mn:你}{n:好吗 }{1: }|
+ {mn:你}{n:不好吗 }{1: }|
+ {mn:你}{n:可好吗 }{1: }|
+ {1:~ }|*14
+ {2:-- }{5:match 1 of 9} |
+ ]])
+ feed('吗')
+ screen:expect([[
+ 你吗^ |
+ {ms:你}{s:好}{ms:吗}{s: }{1: }|
+ {mn:你}{n:不好}{mn:吗}{n: }{1: }|
+ {mn:你}{n:可好}{mn:吗}{n: }{1: }|
+ {1:~ }|*15
+ {2:-- }{5:match 1 of 9} |
+ ]])
+ feed('<C-E><Esc>')
+
+ command('set rightleft')
+ feed('S<C-X><C-O>')
+ local pum_start_rl = [[
+ ^ |
+ {1: }{s: dnikoof oof}|
+ {1: }{n: dnikoof oofoof}|
+ {1: }{n: dnikoof raboof}|
+ {1: }{n: dnikoof zaBoof}|
+ {1: }{n: dnikoof alaboof}|
+ {1: }{n: 好你}|
+ {1: }{n: 吗好你}|
+ {1: }{n: 吗好不你}|
+ {1: }{n: 吗好可你}|
+ {1: ~}|*9
+ {2:-- }{5:match 1 of 9} |
+ ]]
+ screen:expect(pum_start_rl)
+ feed('fo')
+ screen:expect([[
+ ^ of|
+ {1: }{s: dnikoof o}{ms:of}|
+ {1: }{n: dnikoof oofo}{mn:of}|
+ {1: }{n: dnikoof rabo}{mn:of}|
+ {1: }{n: dnikoof zaBo}{mn:of}|
+ {1: }{n: dnikoof alabo}{mn:of}|
+ {1: ~}|*13
+ {2:-- }{5:match 1 of 9} |
+ ]])
+ feed('<Esc>S<C-X><C-O>')
+ screen:expect(pum_start_rl)
+ feed('你')
+ screen:expect([[
+ ^ 你|
+ {1: }{s: 好}{ms:你}|
+ {1: }{n: 吗好}{mn:你}|
+ {1: }{n: 吗好不}{mn:你}|
+ {1: }{n: 吗好可}{mn:你}|
+ {1: ~}|*14
+ {2:-- }{5:match 1 of 9} |
+ ]])
+ feed('吗')
+ screen:expect([[
+ ^ 吗你|
+ {1: }{s: }{ms:吗}{s:好}{ms:你}|
+ {1: }{n: }{mn:吗}{n:好不}{mn:你}|
+ {1: }{n: }{mn:吗}{n:好可}{mn:你}|
+ {1: ~}|*15
+ {2:-- }{5:match 1 of 9} |
+ ]])
+ feed('<C-E><Esc>')
+ command('set norightleft')
+
+ command('set completeopt-=fuzzy')
+ feed('S<C-X><C-O>')
+ screen:expect(pum_start)
+ feed('fo')
+ screen:expect([[
+ fo^ |
+ {ms:fo}{s:o fookind }{1: }|
+ {mn:fo}{n:ofoo fookind }{1: }|
+ {mn:fo}{n:obar fookind }{1: }|
+ {mn:fo}{n:oBaz fookind }{1: }|
+ {mn:fo}{n:obala fookind }{1: }|
+ {1:~ }|*13
+ {2:-- }{5:match 1 of 9} |
+ ]])
+ feed('<C-E><Esc>')
+
+ command('set rightleft')
+ feed('S<C-X><C-O>')
+ screen:expect(pum_start_rl)
+ feed('fo')
+ screen:expect([[
+ ^ of|
+ {1: }{s: dnikoof o}{ms:of}|
+ {1: }{n: dnikoof oofo}{mn:of}|
+ {1: }{n: dnikoof rabo}{mn:of}|
+ {1: }{n: dnikoof zaBo}{mn:of}|
+ {1: }{n: dnikoof alabo}{mn:of}|
+ {1: ~}|*13
+ {2:-- }{5:match 1 of 9} |
+ ]])
+ feed('<C-E><Esc>')
+ command('set norightleft')
+ end)
end
end
diff --git a/test/functional/ui/searchhl_spec.lua b/test/functional/ui/searchhl_spec.lua
index 8bdf528412..493493da60 100644
--- a/test/functional/ui/searchhl_spec.lua
+++ b/test/functional/ui/searchhl_spec.lua
@@ -345,12 +345,19 @@ describe('search highlighting', function()
bar baz foo
bar foo baz]])
feed('/foo')
+ screen:set_default_attr_ids({
+ [1] = { bold = true, foreground = Screen.colors.Blue },
+ [2] = { background = Screen.colors.Yellow }, -- Search
+ [3] = { reverse = true },
+ [4] = { bold = true, reverse = true },
+ [5] = { foreground = Screen.colors.White, background = Screen.colors.DarkGreen },
+ })
screen:expect([[
{3:foo} bar baz │{MATCH:%d+}: {2:foo}{MATCH:%s+}|
bar baz {2:foo} │{MATCH:%d+}: {2:foo}{MATCH:%s+}|
bar {2:foo} baz │{MATCH:%d+}: {2:foo}{MATCH:%s+}|
{1:~ }│{MATCH:.*}|*2
- {5:[No Name] [+] }{3:term }|
+ {4:[No Name] [+] }{5:term }|
/foo^ |
]])
end)
diff --git a/test/functional/ui/sign_spec.lua b/test/functional/ui/sign_spec.lua
index b353b3738a..6f4bf5695d 100644
--- a/test/functional/ui/sign_spec.lua
+++ b/test/functional/ui/sign_spec.lua
@@ -577,4 +577,34 @@ describe('Signs', function()
]])
eq({}, eval('sign_getdefined()'))
end)
+
+ it('no crash when unplacing signs beyond end of buffer', function()
+ exec([[
+ sign define S1 text=S1
+ sign define S2 text=S2
+ sign place 1 line=8 name=S1
+ sign place 2 line=9 name=S2
+ ]])
+ -- Now placed at end of buffer
+ local s1 = {
+ grid = [[
+ S2^ |
+ {0:~ }|*12
+ |
+ ]],
+ }
+ screen:expect(s1)
+ -- Signcolumn tracking used to not count signs placed beyond end of buffer here
+ exec('set signcolumn=auto:9')
+ screen:expect({
+ grid = [[
+ S2S1^ |
+ {0:~ }|*12
+ |
+ ]],
+ })
+ -- Unplacing the sign does not crash by decrementing tracked signs below zero
+ exec('sign unplace 1')
+ screen:expect(s1)
+ end)
end)
diff --git a/test/functional/ui/statuscolumn_spec.lua b/test/functional/ui/statuscolumn_spec.lua
index faf94bccbe..c388d347e2 100644
--- a/test/functional/ui/statuscolumn_spec.lua
+++ b/test/functional/ui/statuscolumn_spec.lua
@@ -94,46 +94,80 @@ describe('statuscolumn', function()
end)
it("works with 'number' and 'relativenumber'", function()
- command([[set stc=%{&nu?v:lnum:''}%=%{&rnu?'\ '.v:relnum:''}│]])
- screen:expect([[
- {8:4 │}aaaaa |
- {8:5 │}aaaaa |
- {8:6 │}aaaaa |
- {8:7 │}aaaaa |
- {8:8 │}^aaaaa |
- {8:9 │}aaaaa |
- {8:10│}aaaaa |
- {8:11│}aaaaa |
- {8:12│}aaaaa |
- {8:13│}aaaaa |
- {8:14│}aaaaa |
- {8:15│}aaaaa |
- {8:16│}aaaaa |
- |
- ]])
- command([[set stc=%l%=%{&rnu?'\ ':''}%r│]])
+ screen:expect([[
+ {8: 4 }aaaaa |
+ {8: 5 }aaaaa |
+ {8: 6 }aaaaa |
+ {8: 7 }aaaaa |
+ {8: 8 }^aaaaa |
+ {8: 9 }aaaaa |
+ {8:10 }aaaaa |
+ {8:11 }aaaaa |
+ {8:12 }aaaaa |
+ {8:13 }aaaaa |
+ {8:14 }aaaaa |
+ {8:15 }aaaaa |
+ {8:16 }aaaaa |
+ |
+ ]])
+ command([[set stc=%l\ ]])
screen:expect_unchanged()
- command([[set stc=%{&nu?v:lnum:''}%=%{&rnu?'\ '.v:relnum:''}│]])
command('set relativenumber')
screen:expect([[
- {8:4 4│}aaaaa |
- {8:5 3│}aaaaa |
- {8:6 2│}aaaaa |
- {8:7 1│}aaaaa |
- {8:8 0│}^aaaaa |
- {8:9 1│}aaaaa |
- {8:10 2│}aaaaa |
- {8:11 3│}aaaaa |
- {8:12 4│}aaaaa |
- {8:13 5│}aaaaa |
- {8:14 6│}aaaaa |
- {8:15 7│}aaaaa |
- {8:16 8│}aaaaa |
- |
- ]])
- command([[set stc=%l%=%{&rnu?'\ ':''}%r│]])
+ {8: 4 }aaaaa |
+ {8: 3 }aaaaa |
+ {8: 2 }aaaaa |
+ {8: 1 }aaaaa |
+ {8:8 }^aaaaa |
+ {8: 1 }aaaaa |
+ {8: 2 }aaaaa |
+ {8: 3 }aaaaa |
+ {8: 4 }aaaaa |
+ {8: 5 }aaaaa |
+ {8: 6 }aaaaa |
+ {8: 7 }aaaaa |
+ {8: 8 }aaaaa |
+ |
+ ]])
+ command('set stc=')
+ screen:expect_unchanged()
+ command([[set nonu stc=%l\ ]])
+ screen:expect([[
+ {8: 4 }aaaaa |
+ {8: 3 }aaaaa |
+ {8: 2 }aaaaa |
+ {8: 1 }aaaaa |
+ {8: 0 }^aaaaa |
+ {8: 1 }aaaaa |
+ {8: 2 }aaaaa |
+ {8: 3 }aaaaa |
+ {8: 4 }aaaaa |
+ {8: 5 }aaaaa |
+ {8: 6 }aaaaa |
+ {8: 7 }aaaaa |
+ {8: 8 }aaaaa |
+ |
+ ]])
+ command('set nuw=1 stc=')
screen:expect_unchanged()
- command([[set stc=%{&nu?v:lnum:''}%=%{&rnu?'\ '.v:relnum:''}│]])
+ -- Correct alignment with items before and after number column
+ command([[set nu stc=foo\ %l\ bar]])
+ screen:expect([[
+ {8:foo 4 bar}aaaaa |
+ {8:foo 3 bar}aaaaa |
+ {8:foo 2 bar}aaaaa |
+ {8:foo 1 bar}aaaaa |
+ {8:foo 8 bar}^aaaaa |
+ {8:foo 1 bar}aaaaa |
+ {8:foo 2 bar}aaaaa |
+ {8:foo 3 bar}aaaaa |
+ {8:foo 4 bar}aaaaa |
+ {8:foo 5 bar}aaaaa |
+ {8:foo 6 bar}aaaaa |
+ {8:foo 7 bar}aaaaa |
+ {8:foo 8 bar}aaaaa |
+ |
+ ]])
end)
it("works with highlighted 'statuscolumn'", function()
@@ -160,36 +194,36 @@ describe('statuscolumn', function()
]])
command('set relativenumber')
screen:expect([[
- {1:4 }{8: 4│}aaaaa |
- {1:5 3}{8:│}aaaaa |
- {1:6 }{8: 2│}aaaaa |
- {1:7 1}{8:│}aaaaa |
- {1:8 }{8: 0│}^aaaaa |
- {1:9 1}{8:│}aaaaa |
- {1:10}{8: 2│}aaaaa |
- {1:11 3}{8:│}aaaaa |
- {1:12}{8: 4│}aaaaa |
- {1:13 5}{8:│}aaaaa |
- {1:14}{8: 6│}aaaaa |
- {1:15 7}{8:│}aaaaa |
- {1:16}{8: 8│}aaaaa |
+ {1:4 }{8: 4│}aaaaa |
+ {1:5 3}{8:│}aaaaa |
+ {1:6 }{8: 2│}aaaaa |
+ {1:7 1}{8:│}aaaaa |
+ {1:8 }{8: 0│}^aaaaa |
+ {1:9 1}{8:│}aaaaa |
+ {1:10 }{8: 2│}aaaaa |
+ {1:11 3}{8:│}aaaaa |
+ {1:12 }{8: 4│}aaaaa |
+ {1:13 5}{8:│}aaaaa |
+ {1:14 }{8: 6│}aaaaa |
+ {1:15 7}{8:│}aaaaa |
+ {1:16 }{8: 8│}aaaaa |
|
]])
command('set nonumber')
screen:expect([[
- {8:4│}aaaaa |
- {1:3}{8:│}aaaaa |
- {8:2│}aaaaa |
- {1:1}{8:│}aaaaa |
- {8:0│}^aaaaa |
- {1:1}{8:│}aaaaa |
- {8:2│}aaaaa |
- {1:3}{8:│}aaaaa |
- {8:4│}aaaaa |
- {1:5}{8:│}aaaaa |
- {8:6│}aaaaa |
- {1:7}{8:│}aaaaa |
- {8:8│}aaaaa |
+ {1: }{8:4│}aaaaa |
+ {1: 3}{8:│}aaaaa |
+ {1: }{8:2│}aaaaa |
+ {1: 1}{8:│}aaaaa |
+ {1: }{8:0│}^aaaaa |
+ {1: 1}{8:│}aaaaa |
+ {1: }{8:2│}aaaaa |
+ {1: 3}{8:│}aaaaa |
+ {1: }{8:4│}aaaaa |
+ {1: 5}{8:│}aaaaa |
+ {1: }{8:6│}aaaaa |
+ {1: 7}{8:│}aaaaa |
+ {1: }{8:8│}aaaaa |
|
]])
end)
@@ -305,36 +339,36 @@ describe('statuscolumn', function()
-- v:relnum is the same value on wrapped lines
command([[set stc=%C%=\ %{v:relnum}│%s\ ]])
screen:expect([[
- {2: }{1: 4│>>}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: }{1: 4│}{2: }{1: }aaaaaa |
- {2: }{1: 3│}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: }{1: 3│}{2: }{1: }aaaaaa |
- {2: }{1: 2│}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: }{1: 2│}{2: }{1: }aaaaaa |
- {2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: }{1: 1│}{2: }{1: }aaaaaa |
- {2:+}{4: 0│}{2: }{4: }{6:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
- {2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: }{1: 1│}{2: }{1: }aaaaaa |
- {2: }{1: 2│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: }{1: 2│}{2: }{1: }aaaaaa |
+ {2: }{1: 4│>>}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: }{1: 4│}{2: }{1: }aaaaaaa |
+ {2: }{1: 3│}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: }{1: 3│}{2: }{1: }aaaaaaa |
+ {2: }{1: 2│}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: }{1: 2│}{2: }{1: }aaaaaaa |
+ {2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: }{1: 1│}{2: }{1: }aaaaaaa |
+ {2:+}{4: 0│}{2: }{4: }{6:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
+ {2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: }{1: 1│}{2: }{1: }aaaaaaa |
+ {2: }{1: 2│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: }{1: 2│}{2: }{1: }aaaaaaa |
|
]])
command([[set stc=%C%=\ %{v:virtnum?'':v:relnum}│%s\ ]])
screen:expect([[
- {2: }{1: 4│>>}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: }{1: │}{2: }{1: }aaaaaa |
- {2: }{1: 3│}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: }{1: │}{2: }{1: }aaaaaa |
- {2: }{1: 2│}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: }{1: │}{2: }{1: }aaaaaa |
- {2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: }{1: │}{2: }{1: }aaaaaa |
- {2:+}{4: 0│}{2: }{4: }{6:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
- {2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: }{1: │}{2: }{1: }aaaaaa |
- {2: }{1: 2│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: }{1: │}{2: }{1: }aaaaaa |
+ {2: }{1: 4│>>}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: }{1: │}{2: }{1: }aaaaaaa |
+ {2: }{1: 3│}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: }{1: │}{2: }{1: }aaaaaaa |
+ {2: }{1: 2│}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: }{1: │}{2: }{1: }aaaaaaa |
+ {2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: }{1: │}{2: }{1: }aaaaaaa |
+ {2:+}{4: 0│}{2: }{4: }{6:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
+ {2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: }{1: │}{2: }{1: }aaaaaaa |
+ {2: }{1: 2│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: }{1: │}{2: }{1: }aaaaaaa |
|
]])
-- Up to 9 signs in a line
@@ -347,75 +381,75 @@ describe('statuscolumn', function()
command('sign place 10 line=6 name=piet2 buffer=1')
command('sign place 11 line=6 name=piet1 buffer=1')
screen:expect([[
- {2: }{1: 4│>>}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: }{1: │}{2: }{1: }aaaaaaaaaaaaaaaaaaaa |
- {2: }{1: 3│}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: }{1: │}{2: }{1: }aaaaaaaaaaaaaaaaaaaa |
- {2: }{1: 2│>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: }{1: │}{2: }{1: }aaaaaaaaaaaaaaaaaaaa |
- {2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: }{1: │}{2: }{1: }aaaaaaaaaaaaaaaaaaaa |
- {2:+}{4: 0│}{2: }{4: }{6:^+-- 1 line: aaaaaaaaaaaaaaaaa}|
- {2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: }{1: │}{2: }{1: }aaaaaaaaaaaaaaaaaaaa |
- {2: }{1: 2│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: }{1: │}{2: }{1: }aaaaaaaaaaaaaaaaaaaa |
+ {2: }{1: 4│>>}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: }{1: │}{2: }{1: }aaaaaaaaaaaaaaaaaaaaa |
+ {2: }{1: 3│}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: }{1: │}{2: }{1: }aaaaaaaaaaaaaaaaaaaaa |
+ {2: }{1: 2│>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: }{1: │}{2: }{1: }aaaaaaaaaaaaaaaaaaaaa |
+ {2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: }{1: │}{2: }{1: }aaaaaaaaaaaaaaaaaaaaa |
+ {2:+}{4: 0│}{2: }{4: }{6:^+-- 1 line: aaaaaaaaaaaaaaaa}|
+ {2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: }{1: │}{2: }{1: }aaaaaaaaaaaaaaaaaaaaa |
+ {2: }{1: 2│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: }{1: │}{2: }{1: }aaaaaaaaaaaaaaaaaaaaa |
|
]])
-- Also test fold and sign column when 'cpoptions' includes "n"
command('set cpoptions+=n')
feed('Hgjg0')
screen:expect([[
- {2: }{4: 0│}{1:>>}{2: }{4: }{5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
- {2: }{5:^aaaaaaaaaaaaaaaaaaaa }|
- {2: }{1: 3│}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: }aaaaaaaaaaaaaaaaaaaa |
- {2: }{1: 2│>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: }aaaaaaaaaaaaaaaaaaaa |
- {2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: }aaaaaaaaaaaaaaaaaaaa |
- {2:+}{1: 4│}{2: }{1: }{3:+-- 1 line: aaaaaaaaaaaaaaaaa}|
- {2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: }aaaaaaaaaaaaaaaaaaaa |
- {2: }{1: 2│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: }aaaaaaaaaaaaaaaaaaaa |
+ {2: }{4: 0│}{1:>>}{2: }{4: }{5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
+ {2: }{5:^aaaaaaaaaaaaaaaaaaaaa }|
+ {2: }{1: 3│}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: }aaaaaaaaaaaaaaaaaaaaa |
+ {2: }{1: 2│>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: }aaaaaaaaaaaaaaaaaaaaa |
+ {2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: }aaaaaaaaaaaaaaaaaaaaa |
+ {2:+}{1: 4│}{2: }{1: }{3:+-- 1 line: aaaaaaaaaaaaaaaa}|
+ {2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: }aaaaaaaaaaaaaaaaaaaaa |
+ {2: }{1: 2│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: }aaaaaaaaaaaaaaaaaaaaa |
|
]])
command('set breakindent')
command('sign unplace 2')
feed('J2gjg0')
screen:expect([[
- {2: }{4: 0│}{1:>>}{2: }{4: }{5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
- {2: } {5:aaaaaaaaaaaaaaaaaaaa aaaaaaaaa}|
- {2: } {5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
- {2: } {5:^aaaaaaaaaaa }|
- {2: }{1: 1│>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: } aaaaaaaaaaaaaaaaaaaa |
- {2: }{1: 2│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: } aaaaaaaaaaaaaaaaaaaa |
- {2:+}{1: 3│}{2: }{1: }{3:+-- 1 line: aaaaaaaaaaaaaaaaa}|
- {2: }{1: 4│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: } aaaaaaaaaaaaaaaaaaaa |
- {2: }{1: 5│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: } aaaaaaaaaaaaaaaaaaaa |
+ {2: }{4: 0│}{1:>>}{2: }{4: }{5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
+ {2: } {5:aaaaaaaaaaaaaaaaaaaaa aaaaaaa}|
+ {2: } {5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
+ {2: } {5:^aaaaaaaaaaaaaa }|
+ {2: }{1: 1│>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: } aaaaaaaaaaaaaaaaaaaaa |
+ {2: }{1: 2│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: } aaaaaaaaaaaaaaaaaaaaa |
+ {2:+}{1: 3│}{2: }{1: }{3:+-- 1 line: aaaaaaaaaaaaaaaa}|
+ {2: }{1: 4│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: } aaaaaaaaaaaaaaaaaaaaa |
+ {2: }{1: 5│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: } aaaaaaaaaaaaaaaaaaaaa |
|
]])
command('set nobreakindent')
feed('$g0')
screen:expect([[
- {2: }{4: 0│}{1:>>}{2: }{4: }{5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
- {2: }{5:aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaa}|
+ {2: }{4: 0│}{1:>>}{2: }{4: }{5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
+ {2: }{5:aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaa}|
{2: }{5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
- {2: }{5:^aaa }|
- {2: }{1: 1│>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: }aaaaaaaaaaaaaaaaaaaa |
- {2: }{1: 2│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: }aaaaaaaaaaaaaaaaaaaa |
- {2:+}{1: 3│}{2: }{1: }{3:+-- 1 line: aaaaaaaaaaaaaaaaa}|
- {2: }{1: 4│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: }aaaaaaaaaaaaaaaaaaaa |
- {2: }{1: 5│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {2: }aaaaaaaaaaaaaaaaaaaa |
+ {2: }{5:^aaaa }|
+ {2: }{1: 1│>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: }aaaaaaaaaaaaaaaaaaaaa |
+ {2: }{1: 2│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: }aaaaaaaaaaaaaaaaaaaaa |
+ {2:+}{1: 3│}{2: }{1: }{3:+-- 1 line: aaaaaaaaaaaaaaaa}|
+ {2: }{1: 4│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: }aaaaaaaaaaaaaaaaaaaaa |
+ {2: }{1: 5│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {2: }aaaaaaaaaaaaaaaaaaaaa |
|
]])
command('silent undo')
@@ -427,7 +461,23 @@ describe('statuscolumn', function()
virt_lines_above = true, virt_lines = {{{"virt_line above", ""}}} })
vim.api.nvim_buf_set_extmark(0, ns, 4, 0, { virt_lines = {{{"virt_line", ""}}} })
]])
- command('set foldcolumn=0 signcolumn=no')
+ command('set foldcolumn=0 signcolumn=number stc=%l')
+ screen:expect([[
+ {1:>>}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
+ {1: 5}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
+ {1: }virt_line |
+ {1: }virt_line above |
+ {1:>>}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
+ {1: 7}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
+ {4: 8}{6:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
+ {1: 9}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
+ {1:10}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
+ {1:11}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
+ {1:12}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
+ {1:13}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
+ {1:14}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
+ |
+ ]])
command(
[[set stc=%{v:virtnum<0?'virtual':(!v:virtnum?'buffer':'wrapped')}%=%{'\ '.v:virtnum.'\ '.v:lnum}]]
)
@@ -533,8 +583,8 @@ describe('statuscolumn', function()
command([[set stc=%6s\ %l]])
exec_lua('vim.api.nvim_buf_set_extmark(0, ns, 7, 0, {sign_text = "𒀀"})')
screen:expect([[
- {8: 𒀀 8 }^aaaaa |
- {8: }{7: }{8: 9 }aaaaa |
+ {8: 𒀀 8}^aaaaa |
+ {8: }{7: }{8: 9}aaaaa |
|
]])
end)
@@ -644,26 +694,26 @@ describe('statuscolumn', function()
-- clicking an item does not drag mouse
api.nvim_input_mouse('left', 'press', '', 0, 0, 0)
screen:expect([[
- {0:8 }^aaaaa |
+ {0: 8}^aaaaa |
{1: Echo } |
]])
api.nvim_input_mouse('left', 'press', '', 0, 1, 5)
api.nvim_input_mouse('left', 'release', '', 0, 1, 5)
screen:expect([[
- {0:8 }^aaaaa |
+ {0: 8}^aaaaa |
0 1 l 8 |
]])
command('echo')
-- clicking outside to close the menu does not drag mouse
api.nvim_input_mouse('left', 'press', '', 0, 0, 0)
screen:expect([[
- {0:8 }^aaaaa |
+ {0: 8}^aaaaa |
{1: Echo } |
]])
api.nvim_input_mouse('left', 'press', '', 0, 0, 10)
api.nvim_input_mouse('left', 'release', '', 0, 0, 10)
screen:expect([[
- {0:8 }^aaaaa |
+ {0: 8}^aaaaa |
|
]])
end)
@@ -749,9 +799,9 @@ describe('statuscolumn', function()
it('works with cmdwin', function()
feed(':set stc=%l<CR>q:k$')
screen:expect([[
- {8:7 }aaaaa |
- {8:8 }aaaaa |
- {8:9 }aaaaa |
+ {8: 7}aaaaa |
+ {8: 8}aaaaa |
+ {8: 9}aaaaa |
{8:10}aaaaa |
{2:[No Name] [+] }|
{1::}{8:1}set stc=%^l |
@@ -899,16 +949,16 @@ describe('statuscolumn', function()
command([[set spell stc=%l\ ]])
command('call setline(8, "This is a line that contains ᶏ multibyte character.")')
screen:expect([[
- {8:8 }^This is a line that contains {31:ᶏ}|
+ {8: 8 }^This is a line that contains {31:ᶏ}|
{8: } {31:multibyte} character. |
- {8:9 }{31:aaaaa} |
+ {8: 9 }{31:aaaaa} |
|
]])
end)
it('line increase properly redraws buffer text with relativenumber #27709', function()
screen:try_resize(33, 4)
- command([[set rnu nuw=3 stc=%l\ ]])
+ command([[set rnu nuw=3 stc=%{v:lnum}\ ]])
command('call setline(1, range(1, 99))')
feed('Gyyp')
screen:expect([[
diff --git a/test/functional/ui/wildmode_spec.lua b/test/functional/ui/wildmode_spec.lua
index 0feec6bd03..6299852a69 100644
--- a/test/functional/ui/wildmode_spec.lua
+++ b/test/functional/ui/wildmode_spec.lua
@@ -199,9 +199,13 @@ describe("'wildmenu'", function()
feed((':terminal "%s" REP 5000 !terminal_output!<cr>'):format(testprg('shell-test')))
feed('G') -- Follow :terminal output.
feed([[:sign <Tab>]]) -- Invoke wildmenu.
+ screen:set_default_attr_ids {
+ [31] = { foreground = Screen.colors.Black, background = Screen.colors.Yellow },
+ [32] = { bold = true, foreground = Screen.colors.White, background = Screen.colors.DarkGreen },
+ }
-- NB: in earlier versions terminal output was redrawn during cmdline mode.
-- For now just assert that the screen remains unchanged.
- screen:expect { any = '{31:define}{3: jump list > }|\n:sign define^ |' }
+ screen:expect { any = '{31:define}{32: jump list > }|\n:sign define^ |' }
screen:expect_unchanged()
-- cmdline CTRL-D display should also be preserved.
@@ -259,9 +263,13 @@ describe("'wildmenu'", function()
feed([[<C-\><C-N>]])
feed([[:<Tab>]]) -- Invoke wildmenu.
+ screen:set_default_attr_ids {
+ [31] = { foreground = Screen.colors.Black, background = Screen.colors.Yellow },
+ [32] = { bold = true, foreground = Screen.colors.White, background = Screen.colors.DarkGreen },
+ }
-- Check only the last 2 lines, because the shell output is
-- system-dependent.
- screen:expect { any = '{31:!}{3: # & < = > @ > }|\n:!^' }
+ screen:expect { any = '{31:!}{32: # & < = > @ > }|\n:!^' }
-- Because this test verifies a _lack_ of activity, we must wait the full timeout.
-- So make it reasonable.
screen:expect_unchanged(false, 1000)
diff --git a/test/old/testdir/test_cmdline.vim b/test/old/testdir/test_cmdline.vim
index 443539fbfd..f83f782817 100644
--- a/test/old/testdir/test_cmdline.vim
+++ b/test/old/testdir/test_cmdline.vim
@@ -2905,6 +2905,24 @@ func Test_wildmenu_pum_odd_wildchar()
call StopVimInTerminal(buf)
endfunc
+" Test that 'rightleft' should not affect cmdline completion popup menu.
+func Test_wildmenu_pum_rightleft()
+ CheckFeature rightleft
+ CheckScreendump
+
+ let lines =<< trim END
+ set wildoptions=pum
+ set rightleft
+ END
+ call writefile(lines, 'Xwildmenu_pum_rl', 'D')
+ let buf = RunVimInTerminal('-S Xwildmenu_pum_rl', #{rows: 10, cols: 50})
+
+ call term_sendkeys(buf, ":sign \<Tab>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_rl', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
" Test for completion after a :substitute command followed by a pipe (|)
" character
func Test_cmdline_complete_substitute()
diff --git a/test/old/testdir/test_filetype.vim b/test/old/testdir/test_filetype.vim
index fa62765398..ec9d88d3bf 100644
--- a/test/old/testdir/test_filetype.vim
+++ b/test/old/testdir/test_filetype.vim
@@ -670,6 +670,7 @@ func s:GetFilenameChecks() abort
\ 'smith': ['file.smt', 'file.smith'],
\ 'smithy': ['file.smithy'],
\ 'sml': ['file.sml'],
+ \ 'snakemake': ['file.smk', 'Snakefile'],
\ 'snobol4': ['file.sno', 'file.spt'],
\ 'solidity': ['file.sol'],
\ 'solution': ['file.sln'],
@@ -991,6 +992,7 @@ func s:GetScriptChecks() abort
\ ['#!/path/regina']],
\ 'janet': [['#!/path/janet']],
\ 'dart': [['#!/path/dart']],
+ \ 'vim': [['#!/path/vim']],
\ }
endfunc
diff --git a/test/old/testdir/test_functions.vim b/test/old/testdir/test_functions.vim
index fa9ae63381..81e843ba8d 100644
--- a/test/old/testdir/test_functions.vim
+++ b/test/old/testdir/test_functions.vim
@@ -3448,6 +3448,33 @@ func Test_glob()
call assert_fails("call glob('*', 0, {})", 'E728:')
endfunc
+func Test_glob2()
+ call mkdir('[XglobDir]', 'R')
+ call mkdir('abc[glob]def', 'R')
+
+ call writefile(['glob'], '[XglobDir]/Xglob')
+ call writefile(['glob'], 'abc[glob]def/Xglob')
+ if has("unix")
+ call assert_equal([], (glob('[XglobDir]/*', 0, 1)))
+ call assert_equal([], (glob('abc[glob]def/*', 0, 1)))
+ call assert_equal(['[XglobDir]/Xglob'], (glob('\[XglobDir]/*', 0, 1)))
+ call assert_equal(['abc[glob]def/Xglob'], (glob('abc\[glob]def/*', 0, 1)))
+ elseif has("win32")
+ let _sl=&shellslash
+ call assert_equal([], (glob('[XglobDir]\*', 0, 1)))
+ call assert_equal([], (glob('abc[glob]def\*', 0, 1)))
+ call assert_equal([], (glob('\[XglobDir]\*', 0, 1)))
+ call assert_equal([], (glob('abc\[glob]def\*', 0, 1)))
+ set noshellslash
+ call assert_equal(['[XglobDir]\Xglob'], (glob('[[]XglobDir]/*', 0, 1)))
+ call assert_equal(['abc[glob]def\Xglob'], (glob('abc[[]glob]def/*', 0, 1)))
+ set shellslash
+ call assert_equal(['[XglobDir]/Xglob'], (glob('[[]XglobDir]/*', 0, 1)))
+ call assert_equal(['abc[glob]def/Xglob'], (glob('abc[[]glob]def/*', 0, 1)))
+ let &shellslash=_sl
+ endif
+endfunc
+
" Test for browse()
func Test_browse()
CheckFeature browse
diff --git a/test/old/testdir/test_ins_complete.vim b/test/old/testdir/test_ins_complete.vim
index fd77da67f8..0f974ebb5b 100644
--- a/test/old/testdir/test_ins_complete.vim
+++ b/test/old/testdir/test_ins_complete.vim
@@ -2620,6 +2620,13 @@ func Test_complete_fuzzy_match()
call feedkeys("S\<C-x>\<C-o>fb\<C-p>\<C-p>\<C-p>\<C-p>", 'tx')
call assert_equal('fooBaz', g:word)
+ func Comp()
+ call complete(col('.'), ["fooBaz", "foobar", "foobala"])
+ return ''
+ endfunc
+ call feedkeys("i\<C-R>=Comp()\<CR>", 'tx')
+ call assert_equal('fooBaz', g:word)
+
" respect noselect
set completeopt+=noselect
call feedkeys("S\<C-x>\<C-o>fb", 'tx')
@@ -2627,6 +2634,19 @@ func Test_complete_fuzzy_match()
call feedkeys("S\<C-x>\<C-o>fb\<C-n>", 'tx')
call assert_equal('fooBaz', g:word)
+ " avoid breaking default completion behavior
+ set completeopt=fuzzy,menu
+ call setline(1, ['hello help hero h'])
+ " Use "!" flag of feedkeys() so that ex_normal_busy is not set and
+ " ins_compl_check_keys() is not skipped.
+ " Add a "0" after the <Esc> to avoid waiting for an escape sequence.
+ call feedkeys("A\<C-X>\<C-N>\<Esc>0", 'tx!')
+ call assert_equal('hello help hero hello', getline('.'))
+ set completeopt+=noinsert
+ call setline(1, ['hello help hero h'])
+ call feedkeys("A\<C-X>\<C-N>\<Esc>0", 'tx!')
+ call assert_equal('hello help hero h', getline('.'))
+
" clean up
set omnifunc=
bw!
@@ -2635,8 +2655,29 @@ func Test_complete_fuzzy_match()
augroup! AAAAA_Group
delfunc OnPumChange
delfunc Omni_test
+ delfunc Comp
unlet g:item
unlet g:word
endfunc
+" Check that tie breaking is stable for completeopt+=fuzzy (which should
+" behave the same on different platforms).
+func Test_complete_fuzzy_match_tie()
+ new
+ set completeopt+=fuzzy,noselect
+ call setline(1, ['aaabbccc', 'aaabbCCC', 'aaabbcccc', 'aaabbCCCC', ''])
+
+ call feedkeys("Gcc\<C-X>\<C-N>ab\<C-N>\<C-Y>", 'tx')
+ call assert_equal('aaabbccc', getline('.'))
+ call feedkeys("Gcc\<C-X>\<C-N>ab\<C-N>\<C-N>\<C-Y>", 'tx')
+ call assert_equal('aaabbCCC', getline('.'))
+ call feedkeys("Gcc\<C-X>\<C-N>ab\<C-N>\<C-N>\<C-N>\<C-Y>", 'tx')
+ call assert_equal('aaabbcccc', getline('.'))
+ call feedkeys("Gcc\<C-X>\<C-N>ab\<C-N>\<C-N>\<C-N>\<C-N>\<C-Y>", 'tx')
+ call assert_equal('aaabbCCCC', getline('.'))
+
+ bwipe!
+ set completeopt&
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab nofoldenable
diff --git a/test/old/testdir/test_popup.vim b/test/old/testdir/test_popup.vim
index 5ae2ed5ed5..6c14fb3a6e 100644
--- a/test/old/testdir/test_popup.vim
+++ b/test/old/testdir/test_popup.vim
@@ -910,6 +910,13 @@ func Test_popup_command_dump()
call term_sendkeys(buf, "\<Esc>")
+ if has('rightleft')
+ call term_sendkeys(buf, ":set rightleft\<CR>")
+ call term_sendkeys(buf, "/X\<CR>:popup PopUp\<CR>")
+ call VerifyScreenDump(buf, 'Test_popup_command_rl', {})
+ call term_sendkeys(buf, "\<Esc>:set norightleft\<CR>")
+ endif
+
" Set a timer to change a menu entry while it's displayed. The text should
" not change but the command does. Making the screendump also verifies that
" "changed" shows up, which means the timer triggered.
@@ -932,6 +939,37 @@ func Test_popup_command_dump()
call StopVimInTerminal(buf)
endfunc
+" Test position of right-click menu when clicking near window edge.
+func Test_mouse_popup_position()
+ CheckFeature menu
+ CheckScreendump
+
+ let script =<< trim END
+ set mousemodel=popup_setpos
+ source $VIMRUNTIME/menu.vim
+ call setline(1, join(range(20)))
+ func Trigger(col)
+ call test_setmouse(1, a:col)
+ call feedkeys("\<RightMouse>", 't')
+ endfunc
+ END
+ call writefile(script, 'XmousePopupPosition', 'D')
+ let buf = RunVimInTerminal('-S XmousePopupPosition', #{rows: 20, cols: 50})
+
+ call term_sendkeys(buf, ":call Trigger(45)\<CR>")
+ call VerifyScreenDump(buf, 'Test_mouse_popup_position_01', {})
+ call term_sendkeys(buf, "\<Esc>")
+
+ if has('rightleft')
+ call term_sendkeys(buf, ":set rightleft\<CR>")
+ call term_sendkeys(buf, ":call Trigger(50 + 1 - 45)\<CR>")
+ call VerifyScreenDump(buf, 'Test_mouse_popup_position_02', {})
+ call term_sendkeys(buf, "\<Esc>:set norightleft\<CR>")
+ endif
+
+ call StopVimInTerminal(buf)
+endfunc
+
func Test_popup_complete_backwards()
new
call setline(1, ['Post', 'Port', 'Po'])
@@ -1348,4 +1386,92 @@ func Test_pum_highlights_custom()
call StopVimInTerminal(buf)
endfunc
+" Test match relate highlight group in pmenu
+func Test_pum_highlights_match()
+ CheckScreendump
+ let lines =<< trim END
+ func Omni_test(findstart, base)
+ if a:findstart
+ return col(".")
+ endif
+ return {
+ \ 'words': [
+ \ { 'word': 'foo', 'kind': 'fookind' },
+ \ { 'word': 'foofoo', 'kind': 'fookind' },
+ \ { 'word': 'foobar', 'kind': 'fookind' },
+ \ { 'word': 'fooBaz', 'kind': 'fookind' },
+ \ { 'word': 'foobala', 'kind': 'fookind' },
+ \ { 'word': '你好' },
+ \ { 'word': '你好吗' },
+ \ { 'word': '你不好吗' },
+ \ { 'word': '你可好吗' },
+ \]}
+ endfunc
+ set omnifunc=Omni_test
+ set completeopt=menu,noinsert,fuzzy
+ hi PmenuMatchSel ctermfg=6 ctermbg=7
+ hi PmenuMatch ctermfg=4 ctermbg=225
+ END
+ call writefile(lines, 'Xscript', 'D')
+ let buf = RunVimInTerminal('-S Xscript', {})
+ call TermWait(buf)
+ call term_sendkeys(buf, "i\<C-X>\<C-O>")
+ call TermWait(buf, 50)
+ call term_sendkeys(buf, "fo")
+ call TermWait(buf, 50)
+ call VerifyScreenDump(buf, 'Test_pum_highlights_03', {})
+ call term_sendkeys(buf, "\<Esc>S\<C-X>\<C-O>")
+ call TermWait(buf, 50)
+ call term_sendkeys(buf, "你")
+ call TermWait(buf, 50)
+ call VerifyScreenDump(buf, 'Test_pum_highlights_04', {})
+ call term_sendkeys(buf, "吗")
+ call TermWait(buf, 50)
+ call VerifyScreenDump(buf, 'Test_pum_highlights_05', {})
+ call term_sendkeys(buf, "\<C-E>\<Esc>")
+
+ if has('rightleft')
+ call term_sendkeys(buf, ":set rightleft\<CR>")
+ call TermWait(buf, 50)
+ call term_sendkeys(buf, "S\<C-X>\<C-O>")
+ call TermWait(buf, 50)
+ call term_sendkeys(buf, "fo")
+ call TermWait(buf, 50)
+ call VerifyScreenDump(buf, 'Test_pum_highlights_06', {})
+ call term_sendkeys(buf, "\<Esc>S\<C-X>\<C-O>")
+ call TermWait(buf, 50)
+ call term_sendkeys(buf, "你")
+ call VerifyScreenDump(buf, 'Test_pum_highlights_06a', {})
+ call term_sendkeys(buf, "吗")
+ call VerifyScreenDump(buf, 'Test_pum_highlights_06b', {})
+ call term_sendkeys(buf, "\<C-E>\<Esc>")
+ call term_sendkeys(buf, ":set norightleft\<CR>")
+ call TermWait(buf)
+ endif
+
+ call term_sendkeys(buf, ":set completeopt-=fuzzy\<CR>")
+ call TermWait(buf)
+ call term_sendkeys(buf, "S\<C-X>\<C-O>")
+ call TermWait(buf, 50)
+ call term_sendkeys(buf, "fo")
+ call TermWait(buf, 50)
+ call VerifyScreenDump(buf, 'Test_pum_highlights_07', {})
+ call term_sendkeys(buf, "\<C-E>\<Esc>")
+
+ if has('rightleft')
+ call term_sendkeys(buf, ":set rightleft\<CR>")
+ call TermWait(buf, 50)
+ call term_sendkeys(buf, "S\<C-X>\<C-O>")
+ call TermWait(buf, 50)
+ call term_sendkeys(buf, "fo")
+ call TermWait(buf, 50)
+ call VerifyScreenDump(buf, 'Test_pum_highlights_08', {})
+ call term_sendkeys(buf, "\<C-E>\<Esc>")
+ call term_sendkeys(buf, ":set norightleft\<CR>")
+ endif
+
+ call TermWait(buf)
+ call StopVimInTerminal(buf)
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_signs.vim b/test/old/testdir/test_signs.vim
index d7baa7e870..69fefccb3f 100644
--- a/test/old/testdir/test_signs.vim
+++ b/test/old/testdir/test_signs.vim
@@ -89,8 +89,9 @@ func Test_sign()
" Place a sign without specifying the filename or buffer
sign place 77 line=9 name=Sign2
let a=execute('sign place')
+ " Nvim: sign line clamped to buffer length
call assert_equal("\n--- Signs ---\nSigns for [NULL]:\n" .
- \ " line=9 id=77 name=Sign2 priority=10\n", a)
+ \ " line=4 id=77 name=Sign2 priority=10\n", a)
sign unplace *
" Check :jump with file=...
@@ -799,10 +800,11 @@ func Test_sign_group()
set buftype=nofile
sign place 25 line=76 name=sign1 priority=99 file=foo
let a = execute('sign place')
+ " Nvim: sign line clamped to buffer length
call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
\ " line=10 id=5 name=sign1 priority=10\n" .
\ "Signs for foo:\n" .
- \ " line=76 id=25 name=sign1 priority=99\n", a)
+ \ " line=1 id=25 name=sign1 priority=99\n", a)
close
bwipe foo
diff --git a/test/old/testdir/test_termdebug.vim b/test/old/testdir/test_termdebug.vim
index fd0c850577..38278cb326 100644
--- a/test/old/testdir/test_termdebug.vim
+++ b/test/old/testdir/test_termdebug.vim
@@ -340,5 +340,16 @@ func Test_termdebug_bufnames()
unlet g:termdebug_config
endfunc
+function Test_termdebug_save_restore_variables()
+ let &mousemodel=''
+ Termdebug
+ call WaitForAssert({-> assert_equal(3, winnr('$'))})
+ call WaitForAssert({-> assert_match(&mousemodel, 'popup_setpos')})
+ wincmd t
+ quit!
+ call WaitForAssert({-> assert_equal(1, winnr('$'))})
+ call WaitForAssert({-> assert_true(empty(&mousemodel))})
+endfunction
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_visual.vim b/test/old/testdir/test_visual.vim
index 0b840944bf..5307c49012 100644
--- a/test/old/testdir/test_visual.vim
+++ b/test/old/testdir/test_visual.vim
@@ -2709,4 +2709,13 @@ func Test_visual_block_cursor_delete()
bwipe!
endfunc
+func Test_visual_block_cursor_insert_enter()
+ new
+ call setline(1, ['asdf asdf', 'asdf asdf', 'asdf asdf', 'asdf asdf'])
+ call cursor(1, 5)
+ exe ":norm! \<c-v>3jcw\<cr>"
+ call assert_equal(['asdfw', 'asdf', 'asdfasdf', 'asdfasdf', 'asdfasdf'], getline(1, '$'))
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab