aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clang-tidy10
-rw-r--r--.github/workflows/ci.yml16
-rw-r--r--.github/workflows/stale.yml25
-rw-r--r--runtime/autoload/health.vim26
-rw-r--r--runtime/autoload/provider/clipboard.vim16
-rw-r--r--runtime/autoload/tutor.vim2
-rw-r--r--runtime/doc/api.txt3
-rw-r--r--runtime/doc/autocmd.txt4
-rw-r--r--runtime/doc/builtin.txt26
-rw-r--r--runtime/doc/cmdline.txt44
-rw-r--r--runtime/doc/editing.txt2
-rw-r--r--runtime/doc/eval.txt2
-rw-r--r--runtime/doc/filetype.txt2
-rw-r--r--runtime/doc/lua.txt3
-rw-r--r--runtime/doc/news.txt8
-rw-r--r--runtime/doc/options.txt13
-rw-r--r--runtime/doc/pi_tar.txt4
-rw-r--r--runtime/doc/spell.txt4
-rw-r--r--runtime/doc/syntax.txt4
-rw-r--r--runtime/doc/treesitter.txt5
-rw-r--r--runtime/doc/usr_03.txt2
-rw-r--r--runtime/doc/vim_diff.txt1
-rw-r--r--runtime/doc/visual.txt6
-rw-r--r--runtime/doc/windows.txt4
-rw-r--r--runtime/ftplugin/checkhealth.vim12
-rw-r--r--runtime/lua/man.lua16
-rw-r--r--runtime/lua/nvim/health.lua8
-rw-r--r--runtime/lua/vim/filetype.lua1
-rw-r--r--runtime/lua/vim/treesitter/highlighter.lua19
-rw-r--r--runtime/lua/vim/ui.lua17
-rw-r--r--runtime/syntax/cabal.vim21
-rw-r--r--runtime/syntax/checkhealth.vim21
-rw-r--r--runtime/syntax/debchangelog.vim6
-rw-r--r--runtime/syntax/debsources.vim6
-rw-r--r--runtime/syntax/help.vim4
-rw-r--r--runtime/syntax/hollywood.vim20
-rw-r--r--runtime/syntax/make.vim6
-rw-r--r--runtime/syntax/modula3.vim101
-rw-r--r--runtime/syntax/sshconfig.vim23
-rw-r--r--runtime/syntax/sshdconfig.vim16
-rw-r--r--src/nvim/api/command.c1
-rw-r--r--src/nvim/api/extmark.c11
-rw-r--r--src/nvim/api/options.c2
-rw-r--r--src/nvim/api/tabpage.c13
-rw-r--r--src/nvim/api/vim.c3
-rw-r--r--src/nvim/api/vimscript.c2
-rw-r--r--src/nvim/api/win_config.c4
-rw-r--r--src/nvim/arabic.c130
-rw-r--r--src/nvim/arglist.c13
-rw-r--r--src/nvim/auevents.lua1
-rw-r--r--src/nvim/autocmd.c4
-rw-r--r--src/nvim/buffer.c26
-rw-r--r--src/nvim/buffer.h1
-rw-r--r--src/nvim/buffer_defs.h4
-rw-r--r--src/nvim/change.c2
-rw-r--r--src/nvim/cmdexpand.c243
-rw-r--r--src/nvim/context.c2
-rw-r--r--src/nvim/decoration.c23
-rw-r--r--src/nvim/decoration.h6
-rw-r--r--src/nvim/diff.c59
-rw-r--r--src/nvim/drawline.c5
-rw-r--r--src/nvim/drawscreen.c9
-rw-r--r--src/nvim/edit.c13
-rw-r--r--src/nvim/eval.c63
-rw-r--r--src/nvim/eval.lua4
-rw-r--r--src/nvim/eval/decode.c11
-rw-r--r--src/nvim/eval/executor.c4
-rw-r--r--src/nvim/eval/funcs.c41
-rw-r--r--src/nvim/eval/typval.c16
-rw-r--r--src/nvim/eval/userfunc.c7
-rw-r--r--src/nvim/eval/vars.c29
-rw-r--r--src/nvim/ex_cmds.c18
-rw-r--r--src/nvim/ex_cmds_defs.h1
-rw-r--r--src/nvim/ex_docmd.c23
-rw-r--r--src/nvim/ex_eval.c9
-rw-r--r--src/nvim/extmark.c2
-rw-r--r--src/nvim/fileio.c46
-rw-r--r--src/nvim/fold.c14
-rw-r--r--src/nvim/generators/gen_options.lua5
-rw-r--r--src/nvim/globals.h3
-rw-r--r--src/nvim/grid_defs.h18
-rw-r--r--src/nvim/hardcopy.c134
-rw-r--r--src/nvim/highlight.c14
-rw-r--r--src/nvim/highlight_defs.h2
-rw-r--r--src/nvim/highlight_group.c13
-rw-r--r--src/nvim/indent.c3
-rw-r--r--src/nvim/indent_c.c18
-rw-r--r--src/nvim/insexpand.c55
-rw-r--r--src/nvim/lua/converter.c3
-rw-r--r--src/nvim/lua/executor.c3
-rw-r--r--src/nvim/lua/stdlib.c15
-rw-r--r--src/nvim/main.c21
-rw-r--r--src/nvim/mark.c3
-rw-r--r--src/nvim/match.c18
-rw-r--r--src/nvim/mbyte.c5
-rw-r--r--src/nvim/memfile.c6
-rw-r--r--src/nvim/memline.c66
-rw-r--r--src/nvim/memory.c3
-rw-r--r--src/nvim/message.c12
-rw-r--r--src/nvim/message.h2
-rw-r--r--src/nvim/mouse.c7
-rw-r--r--src/nvim/msgpack_rpc/helpers.c5
-rw-r--r--src/nvim/normal.c6
-rw-r--r--src/nvim/ops.c20
-rw-r--r--src/nvim/option.c39
-rw-r--r--src/nvim/option_defs.h5
-rw-r--r--src/nvim/options.lua11
-rw-r--r--src/nvim/os/env.c12
-rw-r--r--src/nvim/os/fileio.c8
-rw-r--r--src/nvim/os/fileio.h1
-rw-r--r--src/nvim/os/fs.c40
-rw-r--r--src/nvim/os/input.c3
-rw-r--r--src/nvim/path.c6
-rw-r--r--src/nvim/plines.c3
-rw-r--r--src/nvim/popupmenu.c22
-rw-r--r--src/nvim/quickfix.c36
-rw-r--r--src/nvim/regexp.c269
-rw-r--r--src/nvim/regexp_bt.c604
-rw-r--r--src/nvim/regexp_defs.h70
-rw-r--r--src/nvim/regexp_nfa.c414
-rw-r--r--src/nvim/screen.c474
-rw-r--r--src/nvim/screen.h6
-rw-r--r--src/nvim/shada.c33
-rw-r--r--src/nvim/spell.c35
-rw-r--r--src/nvim/spellfile.c76
-rw-r--r--src/nvim/spellsuggest.c108
-rw-r--r--src/nvim/statusline.c643
-rw-r--r--src/nvim/statusline.h5
-rw-r--r--src/nvim/statusline_defs.h26
-rw-r--r--src/nvim/strings.c25
-rw-r--r--src/nvim/syntax.c35
-rw-r--r--src/nvim/tag.c32
-rw-r--r--src/nvim/terminal.c12
-rw-r--r--src/nvim/testdir/test_arglist.vim10
-rw-r--r--src/nvim/testdir/test_autocmd.vim15
-rw-r--r--src/nvim/testdir/test_cmdline.vim47
-rw-r--r--src/nvim/testdir/test_compiler.vim8
-rw-r--r--src/nvim/testdir/test_cursor_func.vim24
-rw-r--r--src/nvim/testdir/test_delete.vim14
-rw-r--r--src/nvim/testdir/test_diffmode.vim4
-rw-r--r--src/nvim/testdir/test_filetype.vim1
-rw-r--r--src/nvim/testdir/test_fold.vim88
-rw-r--r--src/nvim/testdir/test_functions.vim14
-rw-r--r--src/nvim/testdir/test_help_tagjump.vim16
-rw-r--r--src/nvim/testdir/test_ins_complete.vim969
-rw-r--r--src/nvim/testdir/test_mapping.vim2
-rw-r--r--src/nvim/testdir/test_normal.vim241
-rw-r--r--src/nvim/testdir/test_options.vim12
-rw-r--r--src/nvim/testdir/test_popup.vim40
-rw-r--r--src/nvim/testdir/test_quickfix.vim137
-rw-r--r--src/nvim/testdir/test_tagfunc.vim283
-rw-r--r--src/nvim/testdir/test_vimscript.vim20
-rw-r--r--src/nvim/testdir/vim9.vim80
-rw-r--r--src/nvim/testing.c15
-rw-r--r--src/nvim/tui/input.c44
-rw-r--r--src/nvim/tui/tui.c3
-rw-r--r--src/nvim/types.h3
-rw-r--r--src/nvim/ui.c2
-rw-r--r--src/nvim/undo.c3
-rw-r--r--src/nvim/usercmd.c6
-rw-r--r--src/nvim/viml/parser/expressions.c34
-rw-r--r--src/nvim/window.c35
-rw-r--r--test/functional/api/command_spec.lua10
-rw-r--r--test/functional/ex_cmds/map_spec.lua2
-rw-r--r--test/functional/ex_cmds/write_spec.lua27
-rw-r--r--test/functional/legacy/search_stat_spec.lua4
-rw-r--r--test/functional/lua/ffi_spec.lua14
-rw-r--r--test/functional/lua/ui_spec.lua46
-rw-r--r--test/functional/plugin/health_spec.lua175
-rw-r--r--test/functional/terminal/buffer_spec.lua8
-rw-r--r--test/functional/ui/decorations_spec.lua38
-rw-r--r--test/functional/ui/highlight_spec.lua9
-rw-r--r--test/functional/ui/messages_spec.lua41
-rw-r--r--test/functional/ui/popupmenu_spec.lua151
-rw-r--r--test/functional/vimscript/writefile_spec.lua20
-rw-r--r--test/unit/buffer_spec.lua3
176 files changed, 4458 insertions, 3167 deletions
diff --git a/.clang-tidy b/.clang-tidy
index 90d12602d1..1fe87ba501 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -1,5 +1,3 @@
----
-
Checks: >
-*,
@@ -16,8 +14,6 @@ Checks: >
-bugprone-easily-swappable-parameters,
-bugprone-implicit-widening-of-multiplication-result,
-bugprone-macro-parentheses,
- -bugprone-misplaced-widening-cast,
- -bugprone-narrowing-conversions,
-bugprone-narrowing-conversions,
-bugprone-not-null-terminated-result,
-bugprone-reserved-identifier,
@@ -32,6 +28,7 @@ Checks: >
-misc-unused-parameters,
-modernize-macro-to-enum,
-performance-no-int-to-ptr,
+ -readability-avoid-const-params-in-decls,
-readability-braces-around-statements,
-readability-else-after-return,
-readability-function-cognitive-complexity,
@@ -43,8 +40,3 @@ Checks: >
-readability-redundant-declaration,
-readability-redundant-function-ptr-dereference,
-readability-suspicious-call-argument,
-
-WarningsAsErrors: ''
-
-HeaderFilterRegex: "(src/[cjson|klib|mpack|unicode|xdiff]/).*\\.h$"
-...
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index c4f7f9da36..53d52ec55a 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -31,7 +31,6 @@ jobs:
- name: Install apt packages
run: |
- sudo add-apt-repository ppa:neovim-ppa/stable
sudo apt-get update
sudo apt-get install -y \
autoconf \
@@ -39,23 +38,9 @@ jobs:
build-essential \
cmake \
gettext \
- libluajit-5.1-dev \
- libmsgpack-dev \
- libtermkey-dev \
libtool-bin \
- libtree-sitter-dev \
- libunibilium-dev \
- libuv1-dev \
- libvterm-dev \
locales \
- lua-busted \
lua-check \
- lua-filesystem \
- lua-inspect \
- lua-lpeg \
- lua-luv-dev \
- lua-nvim \
- luajit \
ninja-build \
pkg-config
@@ -173,7 +158,6 @@ jobs:
libvterm-dev \
locales \
lua-busted \
- lua-check \
lua-filesystem \
lua-inspect \
lua-lpeg \
diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml
new file mode 100644
index 0000000000..a10f73531d
--- /dev/null
+++ b/.github/workflows/stale.yml
@@ -0,0 +1,25 @@
+name: 'Close stale issues and PRs'
+on:
+ schedule:
+ - cron: '30 1 * * *' # Run every day at 01:30
+ workflow_dispatch:
+
+jobs:
+ stale:
+ runs-on: ubuntu-latest
+ permissions:
+ issues: write
+ pull-requests: write
+ steps:
+ - uses: actions/stale@v6
+ with:
+ days-before-close: 30
+ days-before-stale: -1
+ stale-issue-label: needs:response
+ stale-pr-label: needs:response
+ close-issue-message: "This issue has been closed since a request for
+ information has not been answered for 30 days. It can be reopened
+ when the requested information is provided."
+ close-pr-message: "This PR has been closed since a request for
+ changes has not been answered for 30 days. It can be reopened when
+ the requested changes are provided."
diff --git a/runtime/autoload/health.vim b/runtime/autoload/health.vim
index a693868381..5fd4627b11 100644
--- a/runtime/autoload/health.vim
+++ b/runtime/autoload/health.vim
@@ -5,8 +5,13 @@ function! health#check(plugin_names) abort
\ ? s:discover_healthchecks()
\ : s:get_healthcheck(a:plugin_names)
- " create scratch-buffer
- execute 'tab sbuffer' nvim_create_buf(v:true, v:true)
+ " Create buffer and open in a tab, unless this is the default buffer when Nvim starts.
+ let emptybuf = (bufnr('$') == 1 && empty(getline(1)) && 1 == line('$'))
+ execute (emptybuf ? 'buffer' : 'tab sbuffer') nvim_create_buf(v:true, v:true)
+ if bufexists('health://')
+ bwipe health://
+ endif
+ file health://
setfiletype checkhealth
if empty(healthchecks)
@@ -38,7 +43,7 @@ function! health#check(plugin_names) abort
\ name, v:throwpoint, v:exception))
endif
endtry
- let header = [name. ': ' . func, repeat('=', 72)]
+ let header = [repeat('=', 78), name .. ': ' .. func, '']
" remove empty line after header from report_start
let s:output = s:output[0] == '' ? s:output[1:] : s:output
let s:output = header + s:output + ['']
@@ -47,8 +52,7 @@ function! health#check(plugin_names) abort
endfor
endif
- " needed for plasticboy/vim-markdown, because it uses fdm=expr
- normal! zR
+ " Clear the 'Running healthchecks...' message.
redraw|echo ''
endfunction
@@ -58,7 +62,7 @@ endfunction
" Starts a new report.
function! health#report_start(name) abort
- call s:collect_output("\n## " . a:name)
+ call s:collect_output(printf("\n%s ~", a:name))
endfunction
" Indents lines *except* line 1 of a string if it contains newlines.
@@ -81,7 +85,7 @@ endfunction
" Format a message for a specific report item.
" a:1: Optional advice (string or list)
function! s:format_report_message(status, msg, ...) abort " {{{
- let output = ' - ' . a:status . ': ' . s:indent_after_line1(a:msg, 4)
+ let output = '- ' .. a:status .. (empty(a:status) ? '' : ' ') .. s:indent_after_line1(a:msg, 2)
" Optional parameters
if a:0 > 0
@@ -92,9 +96,9 @@ function! s:format_report_message(status, msg, ...) abort " {{{
" Report each suggestion
if !empty(advice)
- let output .= "\n - ADVICE:"
+ let output .= "\n - ADVICE:"
for suggestion in advice
- let output .= "\n - " . s:indent_after_line1(suggestion, 10)
+ let output .= "\n - " . s:indent_after_line1(suggestion, 6)
endfor
endif
endif
@@ -102,9 +106,9 @@ function! s:format_report_message(status, msg, ...) abort " {{{
return s:help_to_link(output)
endfunction " }}}
-" Use {msg} to report information in the current section
+" Reports a message as a listitem in the current section.
function! health#report_info(msg) abort " {{{
- call s:collect_output(s:format_report_message('INFO', a:msg))
+ call s:collect_output(s:format_report_message('', a:msg))
endfunction " }}}
" Reports a successful healthcheck.
diff --git a/runtime/autoload/provider/clipboard.vim b/runtime/autoload/provider/clipboard.vim
index 026c01bce6..de8f2cbdf2 100644
--- a/runtime/autoload/provider/clipboard.vim
+++ b/runtime/autoload/provider/clipboard.vim
@@ -97,18 +97,18 @@ function! provider#clipboard#Executable() abort
let s:copy['*'] = ['wl-copy', '--foreground', '--primary', '--type', 'text/plain']
let s:paste['*'] = ['wl-paste', '--no-newline', '--primary']
return 'wl-copy'
- elseif !empty($DISPLAY) && executable('xclip')
- let s:copy['+'] = ['xclip', '-quiet', '-i', '-selection', 'clipboard']
- let s:paste['+'] = ['xclip', '-o', '-selection', 'clipboard']
- let s:copy['*'] = ['xclip', '-quiet', '-i', '-selection', 'primary']
- let s:paste['*'] = ['xclip', '-o', '-selection', 'primary']
- return 'xclip'
elseif !empty($DISPLAY) && executable('xsel') && s:cmd_ok('xsel -o -b')
let s:copy['+'] = ['xsel', '--nodetach', '-i', '-b']
let s:paste['+'] = ['xsel', '-o', '-b']
let s:copy['*'] = ['xsel', '--nodetach', '-i', '-p']
let s:paste['*'] = ['xsel', '-o', '-p']
return 'xsel'
+ elseif !empty($DISPLAY) && executable('xclip')
+ let s:copy['+'] = ['xclip', '-quiet', '-i', '-selection', 'clipboard']
+ let s:paste['+'] = ['xclip', '-o', '-selection', 'clipboard']
+ let s:copy['*'] = ['xclip', '-quiet', '-i', '-selection', 'primary']
+ let s:paste['*'] = ['xclip', '-o', '-selection', 'primary']
+ return 'xclip'
elseif executable('lemonade')
let s:copy['+'] = ['lemonade', 'copy']
let s:paste['+'] = ['lemonade', 'paste']
@@ -139,8 +139,8 @@ function! provider#clipboard#Executable() abort
let s:paste['*'] = s:paste['+']
return 'termux-clipboard'
elseif !empty($TMUX) && executable('tmux')
- let [major, minor] = matchlist(systemlist(['tmux', '-V'])[0], 'tmux \(\d\+\)\.\(\d\+\)')[1:2]
- if major > 3 || (major == 3 && minor >= 2)
+ let ver = matchlist(systemlist(['tmux', '-V'])[0], '\vtmux %(next-)?(\d+)\.(\d+)')
+ if len(ver) >= 3 && (ver[1] > 3 || (ver[1] == 3 && ver[2] >= 2))
let s:copy['+'] = ['tmux', 'load-buffer', '-w', '-']
else
let s:copy['+'] = ['tmux', 'load-buffer', '-']
diff --git a/runtime/autoload/tutor.vim b/runtime/autoload/tutor.vim
index abf5c5e2c8..4da4213826 100644
--- a/runtime/autoload/tutor.vim
+++ b/runtime/autoload/tutor.vim
@@ -104,7 +104,7 @@ function! tutor#CheckLine(line)
if exists('b:tutor_metadata') && has_key(b:tutor_metadata, 'expect')
let bufn = bufnr('%')
let ctext = getline(a:line)
- let signs = sign_getplaced('.', {'lnum': a:line})[0].signs
+ let signs = sign_getplaced(bufn, {'lnum': a:line})[0].signs
if !empty(signs)
call sign_unplace('', {'id': signs[0].id})
endif
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index e2a5291f7f..9faff82f06 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -1757,6 +1757,7 @@ nvim_create_user_command({name}, {command}, {*opts})
executed. When called from Lua, the command can also be a
Lua function. The function is called with a single table
argument that contains the following keys:
+ • name: (string) Command name
• args: (string) The args passed to the command, if any
|<args>|
• fargs: (table) The args split by unescaped whitespace
@@ -3070,7 +3071,7 @@ nvim_open_win({buffer}, {enter}, {*config}) *nvim_open_win()*
• title: Title (optional) in window border, String or list.
List is [text, highlight] tuples. if is string the default
- highlight group is `FloatBorderTitle`.
+ highlight group is `FloatTitle`.
• title_pos: Title position must set with title option.
value can be of `left` `center` `right` default is left.
• noautocmd: If true then no buffer-related autocommand
diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt
index da41c92df6..c30c190301 100644
--- a/runtime/doc/autocmd.txt
+++ b/runtime/doc/autocmd.txt
@@ -996,6 +996,10 @@ TextChangedP After a change was made to the text in the
current buffer in Insert mode, only when the
popup menu is visible. Otherwise the same as
TextChanged.
+ *TextChangedT*
+TextChangedT After a change was made to the text in the
+ current buffer in |Terminal-mode|. Otherwise
+ the same as TextChanged.
*TextYankPost*
TextYankPost Just after a |yank| or |deleting| command, but not
if the black hole register |quote_| is used nor
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index 11352bb0c8..fa9fb286ae 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -78,13 +78,13 @@ chanclose({id} [, {stream}]) Number Closes a channel or one of its streams
chansend({id}, {data}) Number Writes {data} to channel
char2nr({expr} [, {utf8}]) Number ASCII/UTF-8 value of first char in {expr}
charclass({string}) Number character class of {string}
-charcol({expr}) Number column number of cursor or mark
+charcol({expr} [, {winid}]) Number column number of cursor or mark
charidx({string}, {idx} [, {countcc}])
Number char index of byte {idx} in {string}
chdir({dir}) String change current working directory
cindent({lnum}) Number C indent for line {lnum}
clearmatches([{win}]) none clear all matches
-col({expr}) Number column byte index of cursor or mark
+col({expr} [, {winid}]) Number column byte index of cursor or mark
complete({startcol}, {matches}) none set Insert mode completion
complete_add({expr}) Number add completion match
complete_check() Number check for key typed during completion
@@ -920,7 +920,8 @@ bufwinid({buf}) *bufwinid()*
echo "A window containing buffer 1 is " .. (bufwinid(1))
<
- Only deals with the current tab page.
+ Only deals with the current tab page. See |win_findbuf()| for
+ finding more.
Can also be used as a |method|: >
FindBuffer()->bufwinid()
@@ -1088,8 +1089,8 @@ charclass({string}) *charclass()*
Returns 0 if {string} is not a |String|.
- *charcol()*
-charcol({expr}) Same as |col()| but returns the character index of the column
+charcol({expr} [, {winid}]) *charcol()*
+ Same as |col()| but returns the character index of the column
position given with {expr} instead of the byte position.
Example:
@@ -1171,8 +1172,8 @@ clearmatches([{win}]) *clearmatches()*
Can also be used as a |method|: >
GetWin()->clearmatches()
<
- *col()*
-col({expr}) The result is a Number, which is the byte index of the column
+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
@@ -1187,6 +1188,8 @@ col({expr}) The result is a Number, which is the byte index of the column
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
@@ -1197,14 +1200,15 @@ col({expr}) The result is a Number, which is the byte index of the column
col("$") length of cursor line plus one
col("'t") column of mark t
col("'" .. markname) column of mark markname
-< The first column is 1. Returns 0 if {expr} is invalid.
+< 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.
For the cursor position, when 'virtualedit' is active, the
column is one higher if the cursor is after the end of the
line. Also, when using a <Cmd> mapping the cursor isn't
moved, this can be used to obtain the column in Insert mode: >
- :imap <F2> <Cmd>echo col(".")<CR>
+ :imap <F2> <Cmd>echo col(".").."\n"<CR>
< Can also be used as a |method|: >
GetPos()->col()
@@ -2291,7 +2295,7 @@ flatten({list} [, {maxdepth}]) *flatten()*
float2nr({expr}) *float2nr()*
Convert {expr} to a Number by omitting the part after the
decimal point.
- {expr} must evaluate to a |Float| or a Number.
+ {expr} must evaluate to a |Float| or a |Number|.
Returns 0 if {expr} is not a |Float| or a |Number|.
When the value of {expr} is out of range for a |Number| the
result is truncated to 0x7fffffff or -0x7fffffff (or when
@@ -9034,6 +9038,7 @@ win_move_separator({nr}, {offset}) *win_move_separator()*
FALSE otherwise.
This will fail for the rightmost window and a full-width
window, since it has no separator on the right.
+ Only works for the current tab page. *E1308*
Can also be used as a |method|: >
GetWinnr()->win_move_separator(offset)
@@ -9048,6 +9053,7 @@ win_move_statusline({nr}, {offset}) *win_move_statusline()*
movement may be smaller than specified (e.g., as a consequence
of maintaining 'winminheight'). Returns TRUE if the window can
be found and FALSE otherwise.
+ Only works for the current tab page.
Can also be used as a |method|: >
GetWinnr()->win_move_statusline(offset)
diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt
index a6458adb77..b4923b0d70 100644
--- a/runtime/doc/cmdline.txt
+++ b/runtime/doc/cmdline.txt
@@ -690,7 +690,9 @@ Line numbers may be specified with: *:range* *{address}*
'T position of mark T (uppercase); when the mark is in
another file it cannot be used in a range
/{pattern}[/] the next line where {pattern} matches *:/*
+ also see |:range-pattern| below
?{pattern}[?] the previous line where {pattern} matches *:?*
+ also see |:range-pattern| below
\/ the next line where the previously used search
pattern matches
\? the previous line where the previously used search
@@ -698,11 +700,49 @@ Line numbers may be specified with: *:range* *{address}*
\& the next line where the previously used substitute
pattern matches
+ *:range-offset*
Each may be followed (several times) by '+' or '-' and an optional number.
This number is added or subtracted from the preceding line number. If the
number is omitted, 1 is used. If there is nothing before the '+' or '-' then
the current line is used.
-
+ *:range-closed-fold*
+When a line number after the comma is in a closed fold it is adjusted to the
+last line of the fold, thus the whole fold is included.
+
+When a number is added this is done after the adjustment to the last line of
+the fold. This means these lines are additionally included in the range. For
+example: >
+ :3,4+2print
+On this text:
+ 1 one ~
+ 2 two ~
+ 3 three ~
+ 4 four FOLDED ~
+ 5 five FOLDED ~
+ 6 six ~
+ 7 seven ~
+ 8 eight ~
+Where lines four and five are a closed fold, ends up printing lines 3 to 7.
+The 7 comes from the "4" in the range, which is adjusted to the end of the
+closed fold, which is 5, and then the offset 2 is added.
+
+An example for subtracting (which isn't very useful): >
+ :2,4-1print
+On this text:
+ 1 one ~
+ 2 two ~
+ 3 three FOLDED~
+ 4 four FOLDED ~
+ 5 five FOLDED ~
+ 6 six FOLDED ~
+ 7 seven ~
+ 8 eight ~
+Where lines three to six are a closed fold, ends up printing lines 2 to 6.
+The 6 comes from the "4" in the range, which is adjusted to the end of the
+closed fold, which is 6, and then 1 is subtracted, then this is still in the
+closed fold and the last line of that fold is used, which is 6.
+
+ *:range-pattern*
The "/" and "?" after {pattern} are required to separate the pattern from
anything that follows.
@@ -758,7 +798,7 @@ always be swapped then.
Count and Range *N:*
-When giving a count before entering ":", this is translated into:
+When giving a count before entering ":", this is translated into: >
:.,.+(count - 1)
In words: The "count" lines at and after the cursor. Example: To delete
three lines: >
diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt
index 58a5cbc60c..76c528ef3c 100644
--- a/runtime/doc/editing.txt
+++ b/runtime/doc/editing.txt
@@ -438,6 +438,8 @@ Where {optname} is one of: *++ff* *++enc* *++bin* *++nobin* *++edit*
bad specifies behavior for bad characters
edit for |:read| only: keep option values as if editing
a file
+ p creates the parent directory (or directories) of
+ a filename if they do not exist
{value} cannot contain white space. It can be any valid value for these
options. Examples: >
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index a28fa529b9..4446598a2e 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -3177,7 +3177,7 @@ this pending exception or command is discarded.
For examples see |throw-catch| and |try-finally|.
-NESTING OF TRY CONDITIONALS *try-nesting*
+NESTING OF TRY CONDITIONALS *try-nesting*
Try conditionals can be nested arbitrarily. That is, a complete try
conditional can be put into the try block, a catch clause, or the finally
diff --git a/runtime/doc/filetype.txt b/runtime/doc/filetype.txt
index 8de91ed3ae..a53c287d48 100644
--- a/runtime/doc/filetype.txt
+++ b/runtime/doc/filetype.txt
@@ -534,7 +534,7 @@ used.
For example, to set the dialect to a default of "fblite" but still allow for
any #lang directive overrides, use the following command: >
- let g:freebasic_lang = "fblite"
+ let g:freebasic_lang = "fblite"
GIT COMMIT *ft-gitcommit-plugin*
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index c4e139bca7..cab2f49d94 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -1979,7 +1979,8 @@ input({opts}, {on_confirm}) *vim.ui.input()*
highlighting user inputs.
• {on_confirm} (function) ((input|nil) -> ()) Called once the user
confirms or abort the input. `input` is what the user
- typed. `nil` if the user aborted the dialog.
+ typed (it might be an empty string if nothing was
+ entered), or `nil` if the user aborted the dialog.
select({items}, {opts}, {on_choice}) *vim.ui.select()*
Prompts the user to pick a single item from a collection of entries
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index 5f29fa8da9..d339df8479 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -41,9 +41,17 @@ The following new APIs or features were added.
• When using Nvim inside tmux 3.2 or later, the default clipboard provider
will now copy to the system clipboard. |provider-clipboard|
+
• 'splitkeep' option to control the scroll behavior of horizontal splits.
+
• |nvim_select_popupmenu_item()| now supports |cmdline-completion| popup menu.
+• |'diffopt'| now includes a `linematch` option to enable a second-stage diff
+ on individual hunks to provide much more accurate diffs. This option is also
+ available to |vim.diff()|
+
+ See https://github.com/neovim/neovim/pull/14537.
+
==============================================================================
CHANGED FEATURES *news-changes*
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 37f8ea4b20..fd76f11046 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -313,9 +313,10 @@ Note: In the future more global options can be made |global-local|. Using
*option-value-function*
-Some options ('completefunc', 'imactivatefunc', 'imstatusfunc', 'omnifunc',
-'operatorfunc', 'quickfixtextfunc', 'tagfunc' and 'thesaurusfunc') are set to
-a function name or a function reference or a lambda function. Examples:
+Some options ('completefunc', 'omnifunc', 'operatorfunc', 'quickfixtextfunc',
+'tagfunc' and 'thesaurusfunc') are set to a function name or a function
+reference or a lambda function. When using a lambda it will be converted to
+the name, e.g. "<lambda>123". Examples:
>
set opfunc=MyOpFunc
set opfunc=function('MyOpFunc')
@@ -325,10 +326,10 @@ a function name or a function reference or a lambda function. Examples:
let Fn = function('MyTagFunc')
let &tagfunc = string(Fn)
" set using a lambda expression
- let &tagfunc = "{t -> MyTagFunc(t)}"
+ let &tagfunc = {t -> MyTagFunc(t)}
" set using a variable with lambda expression
let L = {a, b, c -> MyTagFunc(a, b , c)}
- let &tagfunc = string(L)
+ let &tagfunc = L
<
Setting the filetype
@@ -2163,7 +2164,7 @@ A jump table for the options with a short description can be found at |Q_op|.
See 'fileencoding' to control file-content encoding.
*'endoffile'* *'eof'* *'noendoffile'* *'noeof'*
-'endoffile' 'eof' boolean (default on)
+'endoffile' 'eof' boolean (default off)
local to buffer
Indicates that a CTRL-Z character was found at the end of the file
when reading it. Normally only happens when 'fileformat' is "dos".
diff --git a/runtime/doc/pi_tar.txt b/runtime/doc/pi_tar.txt
index 0b2ab1690b..2230b82dec 100644
--- a/runtime/doc/pi_tar.txt
+++ b/runtime/doc/pi_tar.txt
@@ -82,7 +82,7 @@ Copyright 2005-2017: *tar-copyright*
<.vimrc> file.
Default
Variable Value Explanation
- *g:tar_browseoptions* "Ptf" used to get a list of contents
+ *g:tar_browseoptions* "Ptf" used to get a list of contents
*g:tar_readoptions* "OPxf" used to extract a file from a tarball
*g:tar_cmd* "tar" the name of the tar program
*g:tar_nomax* 0 if true, file window will not be maximized
@@ -98,7 +98,7 @@ Copyright 2005-2017: *tar-copyright*
"-"
Not all tar's support the "--" which is why
it isn't default.
- *g:tar_writeoptions* "uf" used to update/replace a file
+ *g:tar_writeoptions* "uf" used to update/replace a file
==============================================================================
diff --git a/runtime/doc/spell.txt b/runtime/doc/spell.txt
index 74ec035316..98a6af1b8b 100644
--- a/runtime/doc/spell.txt
+++ b/runtime/doc/spell.txt
@@ -992,8 +992,8 @@ Note: even when using "num" or "long" the number of flags available to
compounding and prefixes is limited to about 250.
-AFFIXES
- *spell-PFX* *spell-SFX*
+AFFIXES *spell-PFX* *spell-SFX*
+
The usual PFX (prefix) and SFX (suffix) lines are supported (see the Myspell
documentation or the Aspell manual:
http://aspell.net/man-html/Affix-Compression.html).
diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt
index 693e78cf9c..033a01ac98 100644
--- a/runtime/doc/syntax.txt
+++ b/runtime/doc/syntax.txt
@@ -5201,10 +5201,10 @@ LineNrBelow Line number for when the 'relativenumber'
*hl-CursorLineNr*
CursorLineNr Like LineNr when 'cursorline' is set and 'cursorlineopt'
contains "number" or is "both", for the cursor line.
- *hl-CursorLineSign*
-CursorLineSign Like SignColumn when 'cursorline' is set for the cursor line.
*hl-CursorLineFold*
CursorLineFold Like FoldColumn when 'cursorline' is set for the cursor line.
+ *hl-CursorLineSign*
+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|
diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt
index 31ee7c31c8..d6cd370ec7 100644
--- a/runtime/doc/treesitter.txt
+++ b/runtime/doc/treesitter.txt
@@ -239,7 +239,7 @@ The following predicates are built in:
`contains?` *treesitter-predicate-contains?*
Match a string against parts of the text corresponding to a node: >
((identifier) @foo (#contains? @foo "foo"))
- ((identifier) @foo-bar (#contains @foo-bar "foo" "bar"))
+ ((identifier) @foo-bar (#contains? @foo-bar "foo" "bar"))
<
`any-of?` *treesitter-predicate-any-of?*
Match any of the given strings against the text corresponding to
@@ -432,6 +432,9 @@ capture marks comments as to be checked: >
(comment) @spell
<
+
+There is also `@nospell` which disables spellchecking regions with `@spell`.
+
*treesitter-highlight-conceal*
Treesitter highlighting supports |conceal| via the `conceal` metadata. By
convention, nodes to be concealed are captured as `@conceal`, but any capture
diff --git a/runtime/doc/usr_03.txt b/runtime/doc/usr_03.txt
index 74674fdb42..2b0d40ba32 100644
--- a/runtime/doc/usr_03.txt
+++ b/runtime/doc/usr_03.txt
@@ -224,7 +224,7 @@ you can see? This figure shows the three commands you can use:
+---------------------------+
Hints: "H" stands for Home, "M" for Middle and "L" for Last. Alternatively,
-"H" for high, "M" for Middle and "L" for low.
+"H" for High, "M" for Middle and "L" for Low.
==============================================================================
*03.6* Telling where you are
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index da2b5e2466..fe6c28c809 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -267,6 +267,7 @@ Options:
'tabline' %@Func@foo%X can call any function on mouse-click
'winblend' pseudo-transparency in floating windows |api-floatwin|
'winhighlight' window-local highlights
+ 'diffopt' has the option `linematch`.
Signs:
Signs are removed if the associated line is deleted.
diff --git a/runtime/doc/visual.txt b/runtime/doc/visual.txt
index 5383ea4f72..0c6bd4f3a1 100644
--- a/runtime/doc/visual.txt
+++ b/runtime/doc/visual.txt
@@ -103,7 +103,7 @@ gn Search forward for the last used search pattern, like
E.g., "dgn" deletes the text of the next match.
If Visual mode is active, extends the selection
until the end of the next match.
- 'wrapscan' applies
+ 'wrapscan' applies.
Note: Unlike `n` the search direction does not depend
on the previous search command.
@@ -501,11 +501,11 @@ mode Vim automatically switches to Visual mode, so that the same behavior as
in Visual mode is effective. If you don't want this use |:xmap| or |:smap|.
One particular edge case: >
- :vnoremap <C-K> <Esc>
+ :vnoremap <C-K> <Esc>
This ends Visual mode when in Visual mode, but in Select mode it does not
work, because Select mode is restored after executing the mapped keys. You
need to use: >
- :snoremap <C-K> <Esc>
+ :snoremap <C-K> <Esc>
<
Users will expect printable characters to replace the selected area.
Therefore avoid mapping printable characters in Select mode. Or use
diff --git a/runtime/doc/windows.txt b/runtime/doc/windows.txt
index 45cedd2cd8..dfc2fb5abf 100644
--- a/runtime/doc/windows.txt
+++ b/runtime/doc/windows.txt
@@ -537,9 +537,9 @@ CTRL-W = Make all windows (almost) equally high and wide, but use
Windows with 'winfixheight' set keep their height and windows
with 'winfixwidth' set keep their width.
To equalize only vertically (make window equally high) use
- `vertical wincmd =`
+ `vertical wincmd =` .
To equalize only horizontally (make window equally wide) use
- `horizontal wincmd =`
+ `horizontal wincmd =` .
:res[ize] -N *:res* *:resize* *CTRL-W_-*
CTRL-W - Decrease current window height by N (default 1).
diff --git a/runtime/ftplugin/checkhealth.vim b/runtime/ftplugin/checkhealth.vim
index 3d8e9ace1a..62a1970b4a 100644
--- a/runtime/ftplugin/checkhealth.vim
+++ b/runtime/ftplugin/checkhealth.vim
@@ -1,20 +1,18 @@
" Vim filetype plugin
-" Language: Neovim checkhealth buffer
-" Last Change: 2021 Dec 15
+" Language: Nvim :checkhealth buffer
+" Last Change: 2022 Nov 10
if exists("b:did_ftplugin")
finish
endif
-runtime! ftplugin/markdown.vim ftplugin/markdown_*.vim ftplugin/markdown/*.vim
+runtime! ftplugin/help.vim
setlocal wrap breakindent linebreak
-setlocal conceallevel=2 concealcursor=nc
-setlocal keywordprg=:help
let &l:iskeyword='!-~,^*,^|,^",192-255'
if exists("b:undo_ftplugin")
- let b:undo_ftplugin .= "|setl wrap< bri< lbr< cole< cocu< kp< isk<"
+ let b:undo_ftplugin .= "|setl wrap< bri< lbr< kp< isk<"
else
- let b:undo_ftplugin = "setl wrap< bri< lbr< cole< cocu< kp< isk<"
+ let b:undo_ftplugin = "setl wrap< bri< lbr< kp< isk<"
endif
diff --git a/runtime/lua/man.lua b/runtime/lua/man.lua
index 5951884e07..a644dd68b8 100644
--- a/runtime/lua/man.lua
+++ b/runtime/lua/man.lua
@@ -12,7 +12,7 @@ local function man_error(msg)
end
-- Run a system command and timeout after 30 seconds.
-local function system(cmd, silent, env)
+local function system(cmd_, silent, env)
local stdout_data = {}
local stderr_data = {}
local stdout = vim.loop.new_pipe(false)
@@ -21,11 +21,23 @@ local function system(cmd, silent, env)
local done = false
local exit_code
+ -- We use the `env` command here rather than the env option to vim.loop.spawn since spawn will
+ -- completely overwrite the environment when we just want to modify the existing one.
+ --
+ -- Overwriting mainly causes problems NixOS which relies heavily on a non-standard environment.
+ local cmd
+ if env then
+ cmd = { 'env' }
+ vim.list_extend(cmd, env)
+ vim.list_extend(cmd, cmd_)
+ else
+ cmd = cmd_
+ end
+
local handle
handle = vim.loop.spawn(cmd[1], {
args = vim.list_slice(cmd, 2),
stdio = { nil, stdout, stderr },
- env = env,
}, function(code)
exit_code = code
stdout:close()
diff --git a/runtime/lua/nvim/health.lua b/runtime/lua/nvim/health.lua
index 413eae0bf9..0dd32ddc0b 100644
--- a/runtime/lua/nvim/health.lua
+++ b/runtime/lua/nvim/health.lua
@@ -359,14 +359,12 @@ local function check_terminal()
\ ..'\%(conemu\|vtpcon\|win32con\)')))
call health#report_error('command failed: '.cmd."\n".out)
else
- call health#report_info('key_backspace (kbs) terminfo entry: '
- \ .(empty(kbs_entry) ? '? (not found)' : kbs_entry))
- call health#report_info('key_dc (kdch1) terminfo entry: '
- \ .(empty(kbs_entry) ? '? (not found)' : kdch1_entry))
+ call health#report_info(printf('key_backspace (kbs) terminfo entry: `%s`', (empty(kbs_entry) ? '? (not found)' : kbs_entry)))
+ call health#report_info(printf('key_dc (kdch1) terminfo entry: `%s`', (empty(kbs_entry) ? '? (not found)' : kdch1_entry)))
endif
for env_var in ['XTERM_VERSION', 'VTE_VERSION', 'TERM_PROGRAM', 'COLORTERM', 'SSH_TTY']
if exists('$'.env_var)
- call health#report_info(printf("$%s='%s'", env_var, eval('$'.env_var)))
+ call health#report_info(printf('$%s="%s"', env_var, eval('$'.env_var)))
endif
endfor
endf
diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua
index 56659eff04..5aa968e211 100644
--- a/runtime/lua/vim/filetype.lua
+++ b/runtime/lua/vim/filetype.lua
@@ -1057,6 +1057,7 @@ local extension = {
hdl = 'vhdl',
vho = 'vhdl',
vbe = 'vhdl',
+ tape = 'vhs',
vim = 'vim',
vba = 'vim',
mar = 'vmasm',
diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua
index 83a26aff13..f5e5ca1988 100644
--- a/runtime/lua/vim/treesitter/highlighter.lua
+++ b/runtime/lua/vim/treesitter/highlighter.lua
@@ -164,7 +164,7 @@ function TSHighlighter:get_query(lang)
end
---@private
-local function on_line_impl(self, buf, line, spell)
+local function on_line_impl(self, buf, line, is_spell_nav)
self.tree:for_each_tree(function(tstree, tree)
if not tstree then
return
@@ -201,17 +201,26 @@ local function on_line_impl(self, buf, line, spell)
local start_row, start_col, end_row, end_col = node:range()
local hl = highlighter_query.hl_cache[capture]
- local is_spell = highlighter_query:query().captures[capture] == 'spell'
+ local capture_name = highlighter_query:query().captures[capture]
+ local spell = nil
+ if capture_name == 'spell' then
+ spell = true
+ elseif capture_name == 'nospell' then
+ spell = false
+ end
+
+ -- Give nospell a higher priority so it always overrides spell captures.
+ local spell_pri_offset = capture_name == 'nospell' and 1 or 0
- if hl and end_row >= line and (not spell or is_spell) then
+ if hl and end_row >= line and (not is_spell_nav or spell ~= nil) then
a.nvim_buf_set_extmark(buf, ns, start_row, start_col, {
end_line = end_row,
end_col = end_col,
hl_group = hl,
ephemeral = true,
- priority = tonumber(metadata.priority) or 100, -- Low but leaves room below
+ priority = (tonumber(metadata.priority) or 100) + spell_pri_offset, -- Low but leaves room below
conceal = metadata.conceal,
- spell = is_spell,
+ spell = spell,
})
end
if start_row > line then
diff --git a/runtime/lua/vim/ui.lua b/runtime/lua/vim/ui.lua
index 6f1ce3089d..97dccd83ab 100644
--- a/runtime/lua/vim/ui.lua
+++ b/runtime/lua/vim/ui.lua
@@ -73,7 +73,8 @@ end
--- user inputs.
---@param on_confirm function ((input|nil) -> ())
--- Called once the user confirms or abort the input.
---- `input` is what the user typed.
+--- `input` is what the user typed (it might be
+--- an empty string if nothing was entered), or
--- `nil` if the user aborted the dialog.
---
--- Example:
@@ -88,11 +89,17 @@ function M.input(opts, on_confirm)
})
opts = (opts and not vim.tbl_isempty(opts)) and opts or vim.empty_dict()
- local input = vim.fn.input(opts)
- if #input > 0 then
- on_confirm(input)
- else
+
+ -- Note that vim.fn.input({}) returns an empty string when cancelled.
+ -- vim.ui.input() should distinguish aborting from entering an empty string.
+ local _canceled = vim.NIL
+ opts = vim.tbl_extend('keep', opts, { cancelreturn = _canceled })
+
+ local ok, input = pcall(vim.fn.input, opts)
+ if not ok or input == _canceled then
on_confirm(nil)
+ else
+ on_confirm(input)
end
end
diff --git a/runtime/syntax/cabal.vim b/runtime/syntax/cabal.vim
index 92e6b8331e..74cda51266 100644
--- a/runtime/syntax/cabal.vim
+++ b/runtime/syntax/cabal.vim
@@ -4,7 +4,9 @@
" Maintainer: Marcin Szamotulski <profunctor@pm.me>
" Previous Maintainer: Vincent Berthoux <twinside@gmail.com>
" File Types: .cabal
-" Last Change: 21 Nov 2020
+" Last Change: 22 Oct 2022
+" v1.6: Added support for foreign-libraries
+" Added highlighting for various fields
" v1.5: Incorporated changes from
" https://github.com/sdiehl/haskell-vim-proto/blob/master/vim/syntax/cabal.vim
" Use `syn keyword` instead of `syn match`.
@@ -61,13 +63,14 @@ syn keyword cabalCategory contained
\ test-suite
\ source-repository
\ flag
+ \ foreign-library
\ custom-setup
\ common
syn match cabalCategoryTitle contained /[^{]*\ze{\?/
syn match cabalCategoryRegion
\ contains=cabalCategory,cabalCategoryTitle
\ nextgroup=cabalCategory skipwhite
- \ /^\c\s*\(contained\|executable\|library\|benchmark\|test-suite\|source-repository\|flag\|custom-setup\|common\)\+\s*\%(.*$\|$\)/
+ \ /^\c\s*\(contained\|executable\|library\|benchmark\|test-suite\|source-repository\|flag\|foreign-library\|custom-setup\|common\)\+\s*\%(.*$\|$\)/
syn keyword cabalTruth true false
" cabalStatementRegion which limits the scope of cabalStatement keywords, this
@@ -77,6 +80,7 @@ syn keyword cabalStatement contained containedin=cabalStatementRegion
\ default-language
\ default-extensions
\ author
+ \ autogen-includes
\ autogen-modules
\ asm-sources
\ asm-options
@@ -84,7 +88,7 @@ syn keyword cabalStatement contained containedin=cabalStatementRegion
\ bug-reports
\ build-depends
\ build-tools
- \ build-tools-depends
+ \ build-tool-depends
\ build-type
\ buildable
\ c-sources
@@ -95,6 +99,7 @@ syn keyword cabalStatement contained containedin=cabalStatementRegion
\ cmm-sources
\ cmm-options
\ cpp-options
+ \ cxx-options
\ cxx-sources
\ data-dir
\ data-files
@@ -111,7 +116,9 @@ syn keyword cabalStatement contained containedin=cabalStatementRegion
\ extra-framework-dirs
\ extra-ghci-libraries
\ extra-lib-dirs
+ \ extra-lib-dirs-static
\ extra-libraries
+ \ extra-libraries-static
\ extra-library-flavours
\ extra-source-files
\ extra-tmp-files
@@ -133,6 +140,8 @@ syn keyword cabalStatement contained containedin=cabalStatementRegion
\ install-includes
\ js-sources
\ ld-options
+ \ lib-version-info
+ \ lib-version-linux
\ license
\ license-file
\ location
@@ -141,20 +150,26 @@ syn keyword cabalStatement contained containedin=cabalStatementRegion
\ manual
\ mixins
\ module
+ \ mod-def-file
\ name
\ nhc98-options
+ \ options
\ other-extensions
\ other-language
\ other-languages
\ other-modules
\ package-url
\ pkgconfig-depends
+ \ scope
\ setup-depends
+ \ signatures
\ stability
\ subdir
\ synopsis
+ \ reexported-modules
\ tag
\ tested-with
+ \ test-module
\ type
\ version
\ virtual-modules
diff --git a/runtime/syntax/checkhealth.vim b/runtime/syntax/checkhealth.vim
index 37f1822740..4b0ce75a54 100644
--- a/runtime/syntax/checkhealth.vim
+++ b/runtime/syntax/checkhealth.vim
@@ -1,26 +1,21 @@
" Vim syntax file
-" Language: Neovim checkhealth buffer
-" Last Change: 2021 Dec 15
+" Language: Nvim :checkhealth buffer
+" Last Change: 2022 Nov 10
if exists("b:current_syntax")
finish
endif
-runtime! syntax/markdown.vim
+runtime! syntax/help.vim
unlet! b:current_syntax
syn case match
-" We do not care about markdown syntax errors
-if hlexists('markdownError')
- syn clear markdownError
-endif
-
-syn keyword healthError ERROR[:] containedin=markdownCodeBlock,mkdListItemLine
-syn keyword healthWarning WARNING[:] containedin=markdownCodeBlock,mkdListItemLine
-syn keyword healthSuccess OK[:] containedin=markdownCodeBlock,mkdListItemLine
-syn match healthHelp "|.\{-}|" containedin=markdownCodeBlock,mkdListItemLine contains=healthBar
-syn match healthBar "|" contained conceal
+syn keyword healthError ERROR[:]
+syn keyword healthWarning WARNING[:]
+syn keyword healthSuccess OK[:]
+syn match helpSectionDelim "^======*\n.*$"
+syn match healthHeadingChar "=" conceal cchar=─ contained containedin=helpSectionDelim
hi def link healthError Error
hi def link healthWarning WarningMsg
diff --git a/runtime/syntax/debchangelog.vim b/runtime/syntax/debchangelog.vim
index 9bd836801e..691c3778c1 100644
--- a/runtime/syntax/debchangelog.vim
+++ b/runtime/syntax/debchangelog.vim
@@ -3,7 +3,7 @@
" Maintainer: Debian Vim Maintainers
" Former Maintainers: Gerfried Fuchs <alfie@ist.org>
" Wichert Akkerman <wakkerma@debian.org>
-" Last Change: 2022 Jul 25
+" Last Change: 2022 Oct 29
" URL: https://salsa.debian.org/vim-team/vim-debian/blob/master/syntax/debchangelog.vim
" Standard syntax initialization
@@ -21,9 +21,9 @@ let s:cpo = &cpo
set cpo-=C
let s:supported = [
\ 'oldstable', 'stable', 'testing', 'unstable', 'experimental', 'sid', 'rc-buggy',
- \ 'buster', 'bullseye', 'bookworm', 'trixie',
+ \ 'buster', 'bullseye', 'bookworm', 'trixie', 'forky',
\
- \ 'trusty', 'xenial', 'bionic', 'focal', 'jammy', 'kinetic',
+ \ 'trusty', 'xenial', 'bionic', 'focal', 'jammy', 'kinetic', 'lunar',
\ 'devel'
\ ]
let s:unsupported = [
diff --git a/runtime/syntax/debsources.vim b/runtime/syntax/debsources.vim
index ea9e59ea8e..9b75797b54 100644
--- a/runtime/syntax/debsources.vim
+++ b/runtime/syntax/debsources.vim
@@ -2,7 +2,7 @@
" Language: Debian sources.list
" Maintainer: Debian Vim Maintainers
" Former Maintainer: Matthijs Mohlmann <matthijs@cacholong.nl>
-" Last Change: 2022 Jul 25
+" Last Change: 2022 Oct 29
" URL: https://salsa.debian.org/vim-team/vim-debian/blob/master/syntax/debsources.vim
" Standard syntax initialization
@@ -23,9 +23,9 @@ let s:cpo = &cpo
set cpo-=C
let s:supported = [
\ 'oldstable', 'stable', 'testing', 'unstable', 'experimental', 'sid', 'rc-buggy',
- \ 'buster', 'bullseye', 'bookworm', 'trixie',
+ \ 'buster', 'bullseye', 'bookworm', 'trixie', 'forky',
\
- \ 'trusty', 'xenial', 'bionic', 'focal', 'jammy', 'kinetic',
+ \ 'trusty', 'xenial', 'bionic', 'focal', 'jammy', 'kinetic', 'lunar',
\ 'devel'
\ ]
let s:unsupported = [
diff --git a/runtime/syntax/help.vim b/runtime/syntax/help.vim
index 1882fe8d67..82add63482 100644
--- a/runtime/syntax/help.vim
+++ b/runtime/syntax/help.vim
@@ -1,7 +1,7 @@
" Vim syntax file
" Language: Vim help file
" Maintainer: Bram Moolenaar (Bram@vim.org)
-" Last Change: 2022 Oct 17
+" Last Change: 2022 Nov 09
" Quit when a (custom) syntax file was already loaded
if exists("b:current_syntax")
@@ -11,7 +11,7 @@ endif
let s:cpo_save = &cpo
set cpo&vim
-syn match helpHeadline "^ *[-A-Z.][-A-Z0-9 .()_]*?\=\ze\(\s\+\*\|$\)"
+syn match helpHeadline "^[A-Z.][-A-Z0-9 .,()_]*?\=\ze\(\s\+\*\|$\)"
syn match helpSectionDelim "^===.*===$"
syn match helpSectionDelim "^---.*--$"
if has("conceal")
diff --git a/runtime/syntax/hollywood.vim b/runtime/syntax/hollywood.vim
index ce5ba29553..fcd03a68f0 100644
--- a/runtime/syntax/hollywood.vim
+++ b/runtime/syntax/hollywood.vim
@@ -1,14 +1,14 @@
" Vim syntax file
-" Language: Hollywood 9.0
-" Maintainer: Tom Crecelius <holly@net-eclipse.net>
-" First Author: Tom Crecelius <holly@net-eclipse.net>
-" Last Change: 2021 April 13
-" Highlighting Issues:
+" Language: Hollywood 9.1
+" Maintainer: Ola Söder <rolfkopman@gmail.com>
+" First Author: Tom Crecelius <holly@net-eclipse.net>
+" Last Change: 2022 Nov 09
+" Highlighting Issues:
" Depending on your colour schema, Strings or Comments might be highlighted in
" a way, you don't like. If so, try one of the following settings after
" opening a hollywood script:
"
-" :hi link hwString MoreMsg
+" :hi link hwString MoreMsg
" :hi link hwString NonText
" :hi link hwString String
"
@@ -60,10 +60,10 @@ syn region hwThenElse transparent matchgroup=hwCond start="\<Then\>" end="$" end
" If .. EndIf
syn region hwIfEndIf transparent matchgroup=hwCond start="\<If\>\(\(.\{-}Then.\{-}\)\@!\)" end="\<EndIf\>" contains=ALLBUT,hwTodo,hwSpecial,hwIn,hwStep,hwLineStatement skipwhite skipempty
-" Else ... EndIf
+" Else ... EndIf
syn region hwElseEndIf contained transparent matchgroup=hwCond start="\<Else\>" end="\<EndIf\>"me=e-5 contains=ALLBUT,hwTodo,hwSpecial,hwElseIf,hwElseEndIf,hwIn,hwStep,hwFallThrough,hwLineStatement
-" Then
+" Then
"syn keyword hwLineStatement Then contained
" Forever
syn keyword hwLineStatement Forever contained
@@ -92,7 +92,7 @@ syn region hwLoopBlock transparent matchgroup=hwRepeat start="\<Repeat\>" end="\
" While ... Wend/Do
syn region hwLoopBlock transparent matchgroup=hwRepeat start="\<While\>" end="\<Do\>" end="\<Wend\>" contains=ALLBUT,hwTodo,hwSpecial,hwElseIf,hwElse,hwIn,hwStep,hwLineStatement skipwhite skipempty
-" For .. To
+" For .. To
syn region hwForTo transparent matchgroup=hwRepeat start="\<For\>" end="\<To\>"me=e-2 skipwhite skipempty nextgroup=hwToNext
" To .. Next
@@ -113,7 +113,7 @@ syn match hwPreProcessor "@\<\%(ANIM\|APPAUTHOR\|APPCOPYRIGHT\|APPDESCRIPTION\|A
" predefined constants
syn match hwConstant "#\<\%(ACTIVEWINDOW\|ADF_ANIM\|ADF_FX\|ADF_MOVEOBJECT\|ALL\|ALPHABETICAL\|ALPHACHANNEL\|ALPHANUMERICAL\|AMIGAICON_DEVICE\|AMIGAICON_DISK\|AMIGAICON_DRAWER\|AMIGAICON_GARBAGE\|AMIGAICON_HIDE\|AMIGAICON_KICKSTART\|AMIGAICON_NONE\|AMIGAICON_PROJECT\|AMIGAICON_SETPOSITION\|AMIGAICON_SETTITLE\|AMIGAICON_SHOW\|AMIGAICON_TOOL\|ANIM\|ANIMSTREAM\|ANIMTYPE_RASTER\|ANIMTYPE_VECTOR\|ANMFMT_GIF\|ANMFMT_IFF\|ANMFMT_MJPEG\|ANTIALIAS\|AQUA\|ARC\|ASYNCDRAW\|ASYNCOBJ\|ATTRACTIVE\|ATTRADAPTER\|ATTRALPHAINTENSITY\|ATTRBGPIC\|ATTRBITRATE\|ATTRBORDERBOTTOM\|ATTRBORDERLEFT\|ATTRBORDERLESS\|ATTRBORDERPEN\|ATTRBORDERRIGHT\|ATTRBORDERTOP\|ATTRBULLETPEN\|ATTRCANSEEK\|ATTRCLIPREGION\|ATTRCOUNT\|ATTRCURFRAME\|ATTRCURSORX\|ATTRCURSORY\|ATTRCURSUBSONG\|ATTRCYCLE\|ATTRDENSITY\|ATTRDEPTH\|ATTRDISPLAY\|ATTRDITHERMODE\|ATTRDOUBLEBUFFER\|ATTRDRIVER\|ATTRDURATION\|ATTRELAPSE\|ATTRENCODING\|ATTRFIXED\|ATTRFONTAA\|ATTRFONTASCENDER\|ATTRFONTCHARMAP\|ATTRFONTDEPTH\|ATTRFONTDESCENDER\|ATTRFONTENGINE\|ATTRFONTNAME\|ATTRFONTPALETTE\|ATTRFONTSCALABLE\|ATTRFONTSIZE\|ATTRFONTTRANSPARENTPEN\|ATTRFONTTYPE\|ATTRFORMAT\|ATTRFRAMEDELAY\|ATTRFUNCTION\|ATTRGROUP\|ATTRHARDWARE\|ATTRHASALPHA\|ATTRHASMASK\|ATTRHEIGHT\|ATTRHOSTDEPTH\|ATTRHOSTHEIGHT\|ATTRHOSTMONITORS\|ATTRHOSTSCALE\|ATTRHOSTSCALEX\|ATTRHOSTSCALEY\|ATTRHOSTTASKBAR\|ATTRHOSTTITLEBARHEIGHT\|ATTRHOSTWIDTH\|ATTRID\|ATTRIMMERSIVEMODE\|ATTRINTERPOLATE\|ATTRKEYBOARD\|ATTRLAYERID\|ATTRLAYERS\|ATTRLAYERSON\|ATTRLOADER\|ATTRMARGINLEFT\|ATTRMARGINRIGHT\|ATTRMASKMODE\|ATTRMAXHEIGHT\|ATTRMAXIMIZED\|ATTRMAXWIDTH\|ATTRMENU\|ATTRMODE\|ATTRMONITOR\|ATTRNOCLOSE\|ATTRNOHIDE\|ATTRNOMODESWITCH\|ATTRNUMENTRIES\|ATTRNUMFRAMES\|ATTRNUMSUBSONGS\|ATTRONSCREEN\|ATTRORIENTATION\|ATTROUTPUTDEVICE\|ATTRPALETTE\|ATTRPALETTEMODE\|ATTRPAUSED\|ATTRPEN\|ATTRPITCH\|ATTRPLAYING\|ATTRPOINTER\|ATTRPOSITION\|ATTRPUBSCREEN\|ATTRRAWHEIGHT\|ATTRRAWWIDTH\|ATTRRAWXPOS\|ATTRRAWYPOS\|ATTRSCALEHEIGHT\|ATTRSCALEMODE\|ATTRSCALESWITCH\|ATTRSCALEWIDTH\|ATTRSHADOWPEN\|ATTRSIZE\|ATTRSIZEABLE\|ATTRSPRITES\|ATTRSTANDARD\|ATTRSTATE\|ATTRSYSTEMBARS\|ATTRTEXT\|ATTRTITLE\|ATTRTRANSPARENTCOLOR\|ATTRTRANSPARENTPEN\|ATTRTYPE\|ATTRUSERDATA\|ATTRVISIBLE\|ATTRWIDTH\|ATTRXDPI\|ATTRXPOS\|ATTRXSERVER\|ATTRYDPI\|ATTRYPOS\|ATTRZPOS\|BARS\|BAUD_115200\|BAUD_1200\|BAUD_19200\|BAUD_2400\|BAUD_300\|BAUD_38400\|BAUD_460800\|BAUD_4800\|BAUD_57600\|BAUD_600\|BAUD_9600\|BEEPERROR\|BEEPINFORMATION\|BEEPQUESTION\|BEEPSYSTEM\|BEEPWARNING\|BGPIC\|BGPICPART\|BIGENDIAN\|BIGSINE\|BITMAP_DEFAULT\|BLACK\|BLEND\|BLUE\|BOLD\|BOOLEAN\|BORDER\|BOTTOM\|BOTTOMOUT\|BOUNCE\|BOX\|BRUSH\|BRUSH_VS_BOX\|BRUSHPART\|BULLET_ARROW\|BULLET_BOX\|BULLET_CHECKMARK\|BULLET_CIRCLE\|BULLET_CROSS\|BULLET_DASH\|BULLET_DIAMOND\|BULLET_LALPHA\|BULLET_LALPHADOUBLE\|BULLET_LALPHASINGLE\|BULLET_LROMAN\|BULLET_LROMANDOUBLE\|BULLET_LROMANSINGLE\|BULLET_NONE\|BULLET_NUMERIC\|BULLET_NUMERICDOUBLE\|BULLET_NUMERICSINGLE\|BULLET_UALPHA\|BULLET_UALPHADOUBLE\|BULLET_UALPHASINGLE\|BULLET_UROMAN\|BULLET_UROMANDOUBLE\|BULLET_UROMANSINGLE\|BYTE\|CAPBUTT\|CAPROUND\|CAPSQUARE\|CARDBOTTOM\|CARDTOP\|CENTER\|CHARMAP_ADOBECUSTOM\|CHARMAP_ADOBEEXPERT\|CHARMAP_ADOBELATIN1\|CHARMAP_ADOBESTANDARD\|CHARMAP_APPLEROMAN\|CHARMAP_BIG5\|CHARMAP_DEFAULT\|CHARMAP_JOHAB\|CHARMAP_MSSYMBOL\|CHARMAP_OLDLATIN2\|CHARMAP_SJIS\|CHARMAP_UNICODE\|CHARMAP_WANSUNG\|CHIPMEMORY\|CIRCLE\|CLIENT\|CLIPBOARD_EMPTY\|CLIPBOARD_IMAGE\|CLIPBOARD_SOUND\|CLIPBOARD_TEXT\|CLIPBOARD_UNKNOWN\|CLIPREGION\|CLOCKWIPE\|CLOSEWINDOW\|CONICAL\|COPYFILE_FAILED\|COPYFILE_OVERWRITE\|COPYFILE_STATUS\|COPYFILE_UNPROTECT\|COUNTBOTH\|COUNTDIRECTORIES\|COUNTFILES\|COUNTRY_AFGHANISTAN\|COUNTRY_ALANDISLANDS\|COUNTRY_ALBANIA\|COUNTRY_ALGERIA\|COUNTRY_AMERICANSAMOA\|COUNTRY_ANDORRA\|COUNTRY_ANGOLA\|COUNTRY_ANGUILLA\|COUNTRY_ANTARCTICA\|COUNTRY_ANTIGUAANDBARBUDA\|COUNTRY_ARGENTINA\|COUNTRY_ARMENIA\|COUNTRY_ARUBA\|COUNTRY_AUSTRALIA\|COUNTRY_AUSTRIA\|COUNTRY_AZERBAIJAN\|COUNTRY_BAHAMAS\|COUNTRY_BAHRAIN\|COUNTRY_BANGLADESH\|COUNTRY_BARBADOS\|COUNTRY_BELARUS\|COUNTRY_BELGIUM\|COUNTRY_BELIZE\|COUNTRY_BENIN\|COUNTRY_BERMUDA\|COUNTRY_BESISLANDS\|COUNTRY_BHUTAN\|COUNTRY_BOLIVIA\|COUNTRY_BOSNIAANDHERZEGOVINA\|COUNTRY_BOTSWANA\|COUNTRY_BOUVETISLAND\|COUNTRY_BRAZIL\|COUNTRY_BRUNEI\|COUNTRY_BULGARIA\|COUNTRY_BURKINAFASO\|COUNTRY_BURUNDI\|COUNTRY_CAMBODIA\|COUNTRY_CAMEROON\|COUNTRY_CANADA\|COUNTRY_CAPEVERDE\|COUNTRY_CAYMANISLANDS\|COUNTRY_CENTRALAFRICANREPUBLIC\|COUNTRY_CHAD\|COUNTRY_CHILE\|COUNTRY_CHINA\|COUNTRY_CHRISTMASISLAND\|COUNTRY_COCOSISLANDS\|COUNTRY_COLOMBIA\|COUNTRY_COMOROS\|COUNTRY_CONGO\|COUNTRY_COOKISLANDS\|COUNTRY_COSTARICA\|COUNTRY_CROATIA\|COUNTRY_CUBA\|COUNTRY_CURACAO\|COUNTRY_CYPRUS\|COUNTRY_CZECHREPUBLIC\|COUNTRY_DENMARK\|COUNTRY_DJIBOUTI\|COUNTRY_DOMINICA\|COUNTRY_DOMINICANREPUBLIC\|COUNTRY_DRCONGO\|COUNTRY_ECUADOR\|COUNTRY_EGYPT\|COUNTRY_ELSALVADOR\|COUNTRY_EQUATORIALGUINEA\|COUNTRY_ERITREA\|COUNTRY_ESTONIA\|COUNTRY_ETHIOPIA\|COUNTRY_FALKLANDISLANDS\|COUNTRY_FAROEISLANDS\|COUNTRY_FIJI\|COUNTRY_FINLAND\|COUNTRY_FRANCE\|COUNTRY_FRENCHGUIANA\|COUNTRY_FRENCHPOLYNESIA\|COUNTRY_GABON\|COUNTRY_GAMBIA\|COUNTRY_GEORGIA\|COUNTRY_GERMANY\|COUNTRY_GHANA\|COUNTRY_GIBRALTAR\|COUNTRY_GREECE\|COUNTRY_GREENLAND\|COUNTRY_GRENADA\|COUNTRY_GUADELOUPE\|COUNTRY_GUAM\|COUNTRY_GUATEMALA\|COUNTRY_GUERNSEY\|COUNTRY_GUINEA\|COUNTRY_GUINEABISSAU\|COUNTRY_GUYANA\|COUNTRY_HAITI\|COUNTRY_HOLYSEE\|COUNTRY_HONDURAS\|COUNTRY_HONGKONG\|COUNTRY_HUNGARY\|COUNTRY_ICELAND\|COUNTRY_INDIA\|COUNTRY_INDONESIA\|COUNTRY_IRAN\|COUNTRY_IRAQ\|COUNTRY_IRELAND\|COUNTRY_ISLEOFMAN\|COUNTRY_ISRAEL\|COUNTRY_ITALY\|COUNTRY_IVORYCOAST\|COUNTRY_JAMAICA\|COUNTRY_JAPAN\|COUNTRY_JERSEY\|COUNTRY_JORDAN\|COUNTRY_KAZAKHSTAN\|COUNTRY_KENYA\|COUNTRY_KIRIBATI\|COUNTRY_KUWAIT\|COUNTRY_KYRGYZSTAN\|COUNTRY_LAOS\|COUNTRY_LATVIA\|COUNTRY_LEBANON\|COUNTRY_LESOTHO\|COUNTRY_LIBERIA\|COUNTRY_LIBYA\|COUNTRY_LIECHTENSTEIN\|COUNTRY_LITHUANIA\|COUNTRY_LUXEMBOURG\|COUNTRY_MACAO\|COUNTRY_MACEDONIA\|COUNTRY_MADAGASCAR\|COUNTRY_MALAWI\|COUNTRY_MALAYSIA\|COUNTRY_MALDIVES\|COUNTRY_MALI\|COUNTRY_MALTA\|COUNTRY_MARSHALLISLANDS\|COUNTRY_MARTINIQUE\|COUNTRY_MAURITANIA\|COUNTRY_MAURITIUS\|COUNTRY_MAYOTTE\|COUNTRY_MEXICO\|COUNTRY_MICRONESIA\|COUNTRY_MOLDOVA\|COUNTRY_MONACO\|COUNTRY_MONGOLIA\|COUNTRY_MONTENEGRO\|COUNTRY_MONTSERRAT\|COUNTRY_MOROCCO\|COUNTRY_MOZAMBIQUE\|COUNTRY_MYANMAR\|COUNTRY_NAMIBIA\|COUNTRY_NAURU\|COUNTRY_NEPAL\|COUNTRY_NETHERLANDS\|COUNTRY_NEWCALEDONIA\|COUNTRY_NEWZEALAND\|COUNTRY_NICARAGUA\|COUNTRY_NIGER\|COUNTRY_NIGERIA\|COUNTRY_NIUE\|COUNTRY_NORFOLKISLAND\|COUNTRY_NORTHKOREA\|COUNTRY_NORWAY\|COUNTRY_OMAN\|COUNTRY_PAKISTAN\|COUNTRY_PALAU\|COUNTRY_PALESTINE\|COUNTRY_PANAMA\|COUNTRY_PAPUANEWGUINEA\|COUNTRY_PARAGUAY\|COUNTRY_PERU\|COUNTRY_PHILIPPINES\|COUNTRY_PITCAIRN\|COUNTRY_POLAND\|COUNTRY_PORTUGAL\|COUNTRY_PUERTORICO\|COUNTRY_QATAR\|COUNTRY_REUNION\|COUNTRY_ROMANIA\|COUNTRY_RUSSIA\|COUNTRY_RWANDA\|COUNTRY_SAINTBARTHELEMY\|COUNTRY_SAINTHELENA\|COUNTRY_SAINTKITTSANDNEVIS\|COUNTRY_SAINTLUCIA\|COUNTRY_SAINTVINCENT\|COUNTRY_SAMOA\|COUNTRY_SANMARINO\|COUNTRY_SAOTOMEANDPRINCIPE\|COUNTRY_SAUDIARABIA\|COUNTRY_SENEGAL\|COUNTRY_SERBIA\|COUNTRY_SEYCHELLES\|COUNTRY_SIERRALEONE\|COUNTRY_SINGAPORE\|COUNTRY_SLOVAKIA\|COUNTRY_SLOVENIA\|COUNTRY_SOLOMONISLANDS\|COUNTRY_SOMALIA\|COUNTRY_SOUTHAFRICA\|COUNTRY_SOUTHKOREA\|COUNTRY_SOUTHSUDAN\|COUNTRY_SPAIN\|COUNTRY_SRILANKA\|COUNTRY_SUDAN\|COUNTRY_SURINAME\|COUNTRY_SWAZILAND\|COUNTRY_SWEDEN\|COUNTRY_SWITZERLAND\|COUNTRY_SYRIA\|COUNTRY_TAIWAN\|COUNTRY_TAJIKISTAN\|COUNTRY_TANZANIA\|COUNTRY_THAILAND\|COUNTRY_TIMOR\|COUNTRY_TOGO\|COUNTRY_TONGA\|COUNTRY_TRINIDADANDTOBAGO\|COUNTRY_TUNISIA\|COUNTRY_TURKEY\|COUNTRY_TURKMENISTAN\|COUNTRY_TUVALU\|COUNTRY_UAE\|COUNTRY_UGANDA\|COUNTRY_UK\|COUNTRY_UKRAINE\|COUNTRY_UNKNOWN\|COUNTRY_URUGUAY\|COUNTRY_USA\|COUNTRY_UZBEKISTAN\|COUNTRY_VANUATU\|COUNTRY_VENEZUELA\|COUNTRY_VIETNAM\|COUNTRY_YEMEN\|COUNTRY_ZAMBIA\|COUNTSEPARATE\|CR_DEAD\|CR_RUNNING\|CR_SUSPENDED\|CROSSFADE\|CRUSHBOTTOM\|CRUSHLEFT\|CRUSHRIGHT\|CRUSHTOP\|DAMPED\|DATA_5\|DATA_6\|DATA_7\|DATA_8\|DATEDAY\|DATELOCAL\|DATELOCALNATIVE\|DATEMONTH\|DATETIME\|DATEUTC\|DATEYEAR\|DEFAULTICON\|DEFAULTSPEED\|DEINTERLACE_DEFAULT\|DEINTERLACE_DOUBLE\|DELETEFILE_FAILED\|DELETEFILE_STATUS\|DELETEFILE_UNPROTECT\|DENSITY_HIGH\|DENSITY_LOW\|DENSITY_MEDIUM\|DENSITY_NONE\|DIAGONAL\|DIRECTORY\|DIRMONITOR_ADD\|DIRMONITOR_CHANGE\|DIRMONITOR_REMOVE\|DISPLAY\|DISPMODE_ASK\|DISPMODE_FAKEFULLSCREEN\|DISPMODE_FULLSCREEN\|DISPMODE_FULLSCREENSCALE\|DISPMODE_MODEREQUESTER\|DISPMODE_MODESWITCH\|DISPMODE_SYSTEMSCALE\|DISPMODE_WINDOWED\|DISPSTATE_CLOSED\|DISPSTATE_MINIMIZED\|DISPSTATE_OPEN\|DISSOLVE\|DITHERMODE_FLOYDSTEINBERG\|DITHERMODE_NONE\|DOSTYPE_DIRECTORY\|DOSTYPE_FILE\|DOUBLE\|DOUBLEBUFFER\|DOWNLOADFILE_STATUS\|DTR_OFF\|DTR_ON\|DURATION_LONG\|DURATION_SHORT\|EDGE\|ELLIPSE\|ENCODING_AMIGA\|ENCODING_ISO8859_1\|ENCODING_RAW\|ENCODING_UTF8\|EOF\|ERR_8OR16BITONLY\|ERR_ACCELERATOR\|ERR_ADDAPPICON\|ERR_ADDAPPWIN\|ERR_ADDSYSEVENT\|ERR_ADDTASK\|ERR_ADFFREEDISP\|ERR_ADFWRONGDISP\|ERR_AFILEPROP\|ERR_AHI\|ERR_ALLOCALPHA\|ERR_ALLOCCHANNEL\|ERR_ALLOCCHUNKY\|ERR_ALLOCMASK\|ERR_ALRDYDECLRD\|ERR_ALREADYASYNC\|ERR_ALSAPCM\|ERR_AMIGAGUIDE\|ERR_ANIMDISK\|ERR_ANIMFRAME\|ERR_ANTIALIAS\|ERR_APPLET\|ERR_APPLETVERSION\|ERR_APPLICATION\|ERR_ARGS\|ERR_ARRAYDECLA\|ERR_ASSERTFAILED\|ERR_ATSUI\|ERR_AUDIOCONVERTER\|ERR_BACKFILL\|ERR_BAD8SVX\|ERR_BADBASE64\|ERR_BADBYTECODE\|ERR_BADCALLBACKRET\|ERR_BADCONSTANT\|ERR_BADDIMENSIONS\|ERR_BADENCODING\|ERR_BADINTEGER\|ERR_BADIP\|ERR_BADLAYERTYPE\|ERR_BADPLATFORM\|ERR_BADSIGNATURE\|ERR_BADUPVALUES\|ERR_BADURL\|ERR_BADWAVE\|ERR_BADYIELD\|ERR_BEGINREFRESH\|ERR_BGPICBUTTON\|ERR_BGPICPALETTE\|ERR_BGPICTYPE\|ERR_BITMAP\|ERR_BLKWOENDBLK\|ERR_BRACECLOSE\|ERR_BRACEOPEN\|ERR_BRACKETCLOSE\|ERR_BRACKETOPEN\|ERR_BRUSHLINK\|ERR_BRUSHSIZE\|ERR_BRUSHTYPE\|ERR_CACHEERROR\|ERR_CASECST\|ERR_CHANGEDIR\|ERR_CHANNELRANGE\|ERR_CHRCSTEMPTY\|ERR_CHRCSTLEN\|ERR_CLIPFORMAT\|ERR_CLIPOPEN\|ERR_CLIPREAD\|ERR_CLIPWRITE\|ERR_CLOSEDDISPLAY\|ERR_CLOSEFILE\|ERR_CMDASVAR\|ERR_CMPUNSUPPORTED\|ERR_COLORSPACE\|ERR_COMMENTSTRUCT\|ERR_COMMODITY\|ERR_COMPLEXEXPR\|ERR_COMPLEXPATTERN\|ERR_COMPLEXWHILE\|ERR_CONCAT\|ERR_CONFIG\|ERR_CONFIG2\|ERR_CONITEMS\|ERR_CONSOLEARG\|ERR_CONTEXTMENU\|ERR_COORDSRANGE\|ERR_COREFOUNDATION\|ERR_CORETEXT\|ERR_CREATEDIR\|ERR_CREATEDOCKY\|ERR_CREATEEVENT\|ERR_CREATEGC\|ERR_CREATEICON\|ERR_CREATEMENU\|ERR_CREATEPORT\|ERR_CREATESHORTCUT\|ERR_CSTDOUBLEDEF\|ERR_CTRLSTRUCT\|ERR_CYIELD\|ERR_DATATYPEALPHA\|ERR_DATATYPESAVE\|ERR_DATATYPESAVE2\|ERR_DBLENCODING\|ERR_DBPALETTE\|ERR_DBTRANSWIN\|ERR_DBVIDEOLAYER\|ERR_DDAUTOSCALE\|ERR_DDMOBILE\|ERR_DDRECVIDEO\|ERR_DEADRESUME\|ERR_DEFFONT\|ERR_DELETEFILE\|ERR_DEMO\|ERR_DEMO2\|ERR_DEMO3\|ERR_DEPTHMISMATCH\|ERR_DEPTHRANGE\|ERR_DESERIALIZE\|ERR_DIFFDEPTH\|ERR_DIFFENCODING\|ERR_DINPUT\|ERR_DIRECTSHOW\|ERR_DIRLOCK\|ERR_DISPLAYADAPTERSUPPORT\|ERR_DISPLAYDESKTOP\|ERR_DISPLAYDESKTOPPAL\|ERR_DISPLAYSIZE\|ERR_DISPMINIMIZED\|ERR_DLOPEN\|ERR_DOUBLEDECLA\|ERR_DOUBLEMENU\|ERR_DRAWPATH\|ERR_DSOUNDNOTIFY\|ERR_DSOUNDNOTIPOS\|ERR_DSOUNDPLAY\|ERR_ELSEIFAFTERELSE\|ERR_ELSETWICE\|ERR_ELSEWOIF\|ERR_EMPTYMENUTREE\|ERR_EMPTYOBJ\|ERR_EMPTYPATH\|ERR_EMPTYSCRIPT\|ERR_EMPTYTABLE\|ERR_ENDBLKWOBLK\|ERR_ENDDOUBLEBUFFER\|ERR_ENDFUNCWOFUNC\|ERR_ENDIFWOIF\|ERR_ENDSWCHWOSWCH\|ERR_ENDWITHWOWITH\|ERR_EQUALEXPECTED\|ERR_ERRORCALLED\|ERR_ESCREPLACE\|ERR_EVNTEXPCTED\|ERR_EXAMINE\|ERR_EXECUTE\|ERR_EXETYPE\|ERR_FGRABVIDSTATE\|ERR_FIELDINIT\|ERR_FILEEXIST\|ERR_FILEFORMAT\|ERR_FILENOTFOUND\|ERR_FILESIZE\|ERR_FINDACTIVITY\|ERR_FINDANIM\|ERR_FINDANIMSTREAM\|ERR_FINDAPPLICATION\|ERR_FINDARRAY\|ERR_FINDASYNCDRAW\|ERR_FINDASYNCOBJ\|ERR_FINDBGPIC\|ERR_FINDBRUSH\|ERR_FINDBUTTON\|ERR_FINDCLIENT\|ERR_FINDCLIPREGION\|ERR_FINDCST\|ERR_FINDDIR\|ERR_FINDDISPLAY\|ERR_FINDFILE\|ERR_FINDFONT\|ERR_FINDFONT2\|ERR_FINDICON\|ERR_FINDINTERVAL\|ERR_FINDLAYER\|ERR_FINDLAYERDATA\|ERR_FINDMEMBLK\|ERR_FINDMENU\|ERR_FINDMENUITEM\|ERR_FINDMONITOR\|ERR_FINDMOVE\|ERR_FINDMUSIC\|ERR_FINDOBJECTDATA\|ERR_FINDPALETTE\|ERR_FINDPATH\|ERR_FINDPLUGIN\|ERR_FINDPOINTER\|ERR_FINDPORT\|ERR_FINDSAMPLE\|ERR_FINDSELECTOR\|ERR_FINDSERIAL\|ERR_FINDSERVER\|ERR_FINDSPRITE\|ERR_FINDTEXTOBJECT\|ERR_FINDTIMEOUT\|ERR_FINDTIMER\|ERR_FINDUDPOBJECT\|ERR_FINDVIDEO\|ERR_FIRSTPREPROC\|ERR_FONTFORMAT\|ERR_FONTPATH\|ERR_FONTPATH2\|ERR_FORBIDMODAL\|ERR_FOREVERWOREPEAT\|ERR_FORWONEXT\|ERR_FRAMEGRABBER\|ERR_FREEABGPIC\|ERR_FREEADISPLAY\|ERR_FREECURPOINTER\|ERR_FT2\|ERR_FTPAUTH\|ERR_FTPERROR\|ERR_FULLSCREEN\|ERR_FUNCARGS\|ERR_FUNCDECLA\|ERR_FUNCEXPECTED\|ERR_FUNCJMP\|ERR_FUNCREMOVED\|ERR_FUNCTABLEARG\|ERR_FUNCWOENDFUNC\|ERR_GETDISKOBJ\|ERR_GETIFADDRS\|ERR_GETMONITORINFO\|ERR_GETSHORTCUT\|ERR_GRABSCREEN\|ERR_GROUPNAMEUSED\|ERR_GTK\|ERR_GUIGFX\|ERR_HEXPOINT\|ERR_HOSTNAME\|ERR_HTTPERROR\|ERR_HTTPTE\|ERR_HWBMCLOSEDISP\|ERR_HWBRUSH\|ERR_HWBRUSHFUNC\|ERR_HWDBFREEDISP\|ERR_ICONDIMS\|ERR_ICONENTRY\|ERR_ICONPARMS\|ERR_ICONSIZE\|ERR_ICONSTANDARD\|ERR_ICONVECTOR\|ERR_IFWOENDIF\|ERR_IMAGEERROR\|ERR_INCOMPATBRUSH\|ERR_INISYNTAX\|ERR_INITSERIAL\|ERR_INTERNAL\|ERR_INTERNAL1\|ERR_INTEXPECTED\|ERR_INVALIDDATE\|ERR_INVALIDUTF8\|ERR_INVALIDUTF8ARG\|ERR_INVCAPIDX\|ERR_INVINSERT\|ERR_INVNEXTKEY\|ERR_INVPATCAP\|ERR_INVREPLACE\|ERR_JAVA\|ERR_JAVAMETHOD\|ERR_JOYSTICK\|ERR_KEYFILE\|ERR_KEYNOTFOUND\|ERR_KEYWORD\|ERR_KICKSTART\|ERR_LABELDECLA\|ERR_LABELDOUBLE\|ERR_LABINFOR\|ERR_LABINFUNC\|ERR_LABINIF\|ERR_LABINWHILE\|ERR_LABMAINBLK\|ERR_LAYERRANGE\|ERR_LAYERSOFF\|ERR_LAYERSON\|ERR_LAYERSUPPORT\|ERR_LAYERSUPPORT2\|ERR_LAYERSWITCH\|ERR_LEGACYPTMOD\|ERR_LFSYNTAX\|ERR_LINKFONT\|ERR_LINKPLUGIN\|ERR_LOADFRAME\|ERR_LOADICON\|ERR_LOADPICTURE\|ERR_LOADPICTURE2\|ERR_LOADPLUGIN\|ERR_LOADSOUND\|ERR_LOADVIDEO\|ERR_LOCK\|ERR_LOCK2\|ERR_LOCKBMAP\|ERR_LOCKEDOBJ\|ERR_LOOPRANGE\|ERR_LOWFREQ\|ERR_MAGICKEY\|ERR_MALFORMPAT1\|ERR_MALFORMPAT2\|ERR_MASKNALPHA\|ERR_MAXLINES\|ERR_MAXLOCALS\|ERR_MAXPARAMS\|ERR_MAXUPVALS\|ERR_MEDIAFOUNDATION\|ERR_MEM\|ERR_MEMCODE\|ERR_MEMCST\|ERR_MEMRANGE\|ERR_MENUATTACHED\|ERR_MENUCOMPLEXITY\|ERR_MISSINGBRACKET\|ERR_MISSINGFIELD\|ERR_MISSINGOPBRACK\|ERR_MISSINGPARAMTR\|ERR_MISSINGSEPARTR\|ERR_MIXMUSMOD\|ERR_MOBILE\|ERR_MODIFYAANIM\|ERR_MODIFYABG\|ERR_MODIFYABGPIC\|ERR_MODIFYABR\|ERR_MODIFYPSMP\|ERR_MODIFYSPRITE\|ERR_MODIFYSPRITE2\|ERR_MONITORDIR\|ERR_MONITORFULLSCREEN\|ERR_MONITORRANGE\|ERR_MOVEFILE\|ERR_MSGPORT\|ERR_MULDISMOBILE\|ERR_MULTIBGPIC\|ERR_MULTIDISPLAYS\|ERR_MUSFMTSUPPORT\|ERR_MUSNOTPAUSED\|ERR_MUSNOTPLYNG\|ERR_MUSNOTPLYNG2\|ERR_MUSPAUSED\|ERR_MUSPLAYING\|ERR_NAMETOOLONG\|ERR_NAMEUSED\|ERR_NEEDAPPLICATION\|ERR_NEEDCOMPOSITE\|ERR_NEEDMORPHOS2\|ERR_NEEDOS41\|ERR_NEEDPALETTEIMAGE\|ERR_NEGCOORDS\|ERR_NEWHWPLUGIN\|ERR_NEXTWOFOR\|ERR_NOABSPATH\|ERR_NOACCESS\|ERR_NOALPHA\|ERR_NOANMLAYER\|ERR_NOAPPLET\|ERR_NOARGBVISUAL\|ERR_NOBLOCKBREAK\|ERR_NOCALLBACK\|ERR_NOCHANNEL\|ERR_NOCHAR\|ERR_NOCLIPREG\|ERR_NOCOLON\|ERR_NOCOMMA\|ERR_NOCOMPRESS\|ERR_NOCONSTANTS\|ERR_NOCONTEXTMENU\|ERR_NOCOORDCST\|ERR_NODIRPATTERN\|ERR_NODISLAYERS\|ERR_NODISPMODES\|ERR_NODOUBLEBUFFER\|ERR_NOFALLTHROUGH\|ERR_NOFILTERNAME\|ERR_NOFMBHANDLER\|ERR_NOFUNCTION\|ERR_NOHWFUNC\|ERR_NOJOYATPORT\|ERR_NOKEYWORDS\|ERR_NOLAYERS\|ERR_NOLOOP\|ERR_NOLOOPCONT\|ERR_NOMASKBRUSH\|ERR_NOMENU\|ERR_NOMIMEVIEWER\|ERR_NOMUSICCB\|ERR_NONE\|ERR_NONSUSPENDEDRESUME\|ERR_NOPALETTE\|ERR_NOPALETTEIMAGE\|ERR_NOPALETTEMODE\|ERR_NORETVAL\|ERR_NOREXX\|ERR_NOSPRITES\|ERR_NOTADIR\|ERR_NOTENOUGHPIXELS\|ERR_NOTIGER\|ERR_NOTPROTRACKER\|ERR_NOTRANSPARENCY\|ERR_NOTXTLAYER\|ERR_NUMBEREXPECTED\|ERR_NUMCALLBACK\|ERR_NUMCONCAT\|ERR_NUMEXPECTED\|ERR_NUMSTRCMP\|ERR_NUMTABLEARG\|ERR_OLDAPPLET\|ERR_OPENANIM\|ERR_OPENANIM2\|ERR_OPENAUDIO\|ERR_OPENFONT\|ERR_OPENLIB\|ERR_OPENSERIAL\|ERR_OPENSOCKET\|ERR_OPENSOUND\|ERR_OPENSOUND2\|ERR_OUTOFRANGE\|ERR_PAKFORMAT\|ERR_PALETTEFILL\|ERR_PALETTEMODE\|ERR_PALSCREEN\|ERR_PEERNAME\|ERR_PENRANGE\|ERR_PERCENTFORMAT\|ERR_PERCENTFORMATSTR\|ERR_PIPE\|ERR_PIXELFORMAT\|ERR_PIXELRANGE\|ERR_PLAYERCOMP\|ERR_PLAYVIDEO\|ERR_PLUGINARCH\|ERR_PLUGINDOUBLET\|ERR_PLUGINSUPPORT\|ERR_PLUGINSYMBOL\|ERR_PLUGINTYPE\|ERR_PLUGINVER\|ERR_POINTERFORMAT\|ERR_POINTERIMG\|ERR_PORTNOTAVAIL\|ERR_PREPROCSYM\|ERR_PROTMETATABLE\|ERR_PUBSCREEN\|ERR_QUICKTIME\|ERR_RADIOTOGGLEMENU\|ERR_RANDOMIZE\|ERR_READ\|ERR_READFILE\|ERR_READFUNC\|ERR_READONLY\|ERR_READRANGE\|ERR_READTABLE\|ERR_READVIDEOPIXELS\|ERR_RECVCLOSED\|ERR_RECVTIMEOUT\|ERR_RECVUNKNOWN\|ERR_REGCLASS\|ERR_REGISTRYREAD\|ERR_REGISTRYWRITE\|ERR_REMADLAYER\|ERR_RENAME\|ERR_RENDER\|ERR_RENDERADLAYER\|ERR_RENDERCALLBACK\|ERR_RENDERER\|ERR_REPEATWOUNTIL\|ERR_REQAUTH\|ERR_REQUIREFIELD\|ERR_REQUIREPLUGIN\|ERR_REQUIRETAGFMT\|ERR_RETWOGOSUB\|ERR_REVDWORD\|ERR_REWINDDIR\|ERR_REXXERR\|ERR_SATELLITE\|ERR_SATFREEDISP\|ERR_SAVEANIM\|ERR_SAVEICON\|ERR_SAVEIMAGE\|ERR_SAVEPNG\|ERR_SAVERALPHA\|ERR_SAVESAMPLE\|ERR_SCALEBGPIC\|ERR_SCREEN\|ERR_SCREENMODE\|ERR_SCREENSIZE\|ERR_SCRPIXFMT\|ERR_SEEK\|ERR_SEEKFILE\|ERR_SEEKFORMAT\|ERR_SEEKRANGE\|ERR_SELECTALPHACHANNEL\|ERR_SELECTANIM\|ERR_SELECTBG\|ERR_SELECTBGPIC\|ERR_SELECTBGPIC2\|ERR_SELECTBRUSH\|ERR_SELECTMASK\|ERR_SEMAPHORE\|ERR_SENDDATA\|ERR_SENDMESSAGE\|ERR_SENDTIMEOUT\|ERR_SENDUNKNOWN\|ERR_SERIALIO\|ERR_SERIALIZE\|ERR_SERIALIZETYPE\|ERR_SETADAPTER\|ERR_SETENV\|ERR_SETFILEATTR\|ERR_SETFILECOMMENT\|ERR_SETFILEDATE\|ERR_SETMENU\|ERR_SHORTIF\|ERR_SIGNAL\|ERR_SMODEALPHA\|ERR_SMPRANGE\|ERR_SOCKET\|ERR_SOCKNAME\|ERR_SOCKOPT\|ERR_SORTFUNC\|ERR_SPRITELINK\|ERR_SPRITEONSCREEN\|ERR_SPRITEONSCREEN2\|ERR_SQBRACKETCLOSE\|ERR_SQBRACKETOPEN\|ERR_STACK\|ERR_STAT\|ERR_STRCALLBACK\|ERR_STREAMASSAMPLE\|ERR_STREXPECTED\|ERR_STRINGCST\|ERR_STRINGEXPECTED\|ERR_STRORNUM\|ERR_STRTABLEARG\|ERR_STRTOOSHORT\|ERR_SURFACE\|ERR_SWCHWOENDSWCH\|ERR_SYNTAXERROR\|ERR_SYNTAXLEVELS\|ERR_SYSBUTTON\|ERR_SYSIMAGE\|ERR_SYSTOOOLD\|ERR_TABCALLBACK\|ERR_TABEXPECTED\|ERR_TABEXPECTED2\|ERR_TABEXPECTED3\|ERR_TABLEDECLA\|ERR_TABLEINDEX\|ERR_TABLEORNIL\|ERR_TABLEOVERFLOW\|ERR_TAGEXPECTED\|ERR_TASKSETUP\|ERR_TEXTARG\|ERR_TEXTCONVERT\|ERR_TEXTCONVERT2\|ERR_TEXTSYNTAX\|ERR_TEXTURE\|ERR_TFIMAGE\|ERR_TFVANIM\|ERR_TFVBGPICBRUSH\|ERR_TFVBRUSH\|ERR_TFVBRUSHBGPIC\|ERR_THREAD\|ERR_THREADEXPECTED\|ERR_TIMER\|ERR_TOKENEXPECTED\|ERR_TOOMANYARGS\|ERR_TOOMANYCAPTURES\|ERR_TOOSMALL2\|ERR_TRANSBGMOBILE\|ERR_TRANSBRUSH\|ERR_TRAYICON\|ERR_TRIALCOMPILE\|ERR_TRIALINCLUDE\|ERR_TRIALLIMIT\|ERR_TRIALSAVEVID\|ERR_UDEXPECTED\|ERR_UNBALANCEDPAT\|ERR_UNEXPECTEDEOF\|ERR_UNEXPECTEDSYM\|ERR_UNFINISHEDCAPTURE\|ERR_UNIMPLCMD\|ERR_UNKNOWN\|ERR_UNKNOWNANMOUT\|ERR_UNKNOWNATTR\|ERR_UNKNOWNCMD\|ERR_UNKNOWNCOND\|ERR_UNKNOWNFILTER\|ERR_UNKNOWNICNOUT\|ERR_UNKNOWNIMGOUT\|ERR_UNKNOWNMIMETYPE\|ERR_UNKNOWNMUSFMT\|ERR_UNKNOWNPALETTE\|ERR_UNKNOWNSEC\|ERR_UNKNOWNSEQ\|ERR_UNKNOWNSMPOUT\|ERR_UNKNOWNTAG\|ERR_UNKNUMFMT\|ERR_UNKPROTOCOL\|ERR_UNKTEXTFMT\|ERR_UNMPARENTHESES\|ERR_UNSETENV\|ERR_UNSUPPORTEDFEAT\|ERR_UNTERMINTDSTR\|ERR_UNTILWOREPEAT\|ERR_UPDATEICON\|ERR_UPLOADFORBIDDEN\|ERR_USERABORT\|ERR_VALUEEXPECTED\|ERR_VAREXPECTED\|ERR_VARLENGTH\|ERR_VARSYNTAX\|ERR_VECGFXPLUGIN\|ERR_VECTORANIM\|ERR_VECTORBRUSH\|ERR_VERSION\|ERR_VFONT\|ERR_VFONTTYPE\|ERR_VIDATTACHED\|ERR_VIDEOFRAME\|ERR_VIDEOINIT\|ERR_VIDEOLAYER\|ERR_VIDEOLAYERDRV\|ERR_VIDEOSTRATEGY\|ERR_VIDEOTRANS\|ERR_VIDLAYERFUNC\|ERR_VIDNOTPAUSED\|ERR_VIDNOTPLAYING\|ERR_VIDPAUSED\|ERR_VIDPLAYING\|ERR_VIDRECMULTI\|ERR_VIDRECTRANS\|ERR_VIDSTOPPED\|ERR_VISUALINFO\|ERR_VMMISMATCH\|ERR_WARPOS\|ERR_WENDWOWHILE\|ERR_WHILEWOWEND\|ERR_WINDOW\|ERR_WITHWOENDWITH\|ERR_WRITE\|ERR_WRITEFILE\|ERR_WRITEJPEG\|ERR_WRITEONLY\|ERR_WRONGCLIPREG\|ERR_WRONGCMDRECVIDEO\|ERR_WRONGDTYPE\|ERR_WRONGFLOAT\|ERR_WRONGHEX\|ERR_WRONGID\|ERR_WRONGOP\|ERR_WRONGOPCST\|ERR_WRONGSPRITESIZE\|ERR_WRONGUSAGE\|ERR_WRONGVSTRATEGY\|ERR_XCURSOR\|ERR_XDISPLAY\|ERR_XF86VIDMODEEXT\|ERR_XFIXES\|ERR_YIELD\|ERR_ZERODIVISION\|ERR_ZLIBDATA\|ERR_ZLIBIO\|ERR_ZLIBSTREAM\|ERR_ZLIBVERSION\|EVENTHANDLER\|FADE\|FASTMEMORY\|FASTSPEED\|FILE\|FILEATTR_ARCHIVE\|FILEATTR_DELETE_USR\|FILEATTR_EXECUTE_GRP\|FILEATTR_EXECUTE_OTH\|FILEATTR_EXECUTE_USR\|FILEATTR_HIDDEN\|FILEATTR_NORMAL\|FILEATTR_PURE\|FILEATTR_READ_GRP\|FILEATTR_READ_OTH\|FILEATTR_READ_USR\|FILEATTR_READONLY\|FILEATTR_SCRIPT\|FILEATTR_SYSTEM\|FILEATTR_WRITE_GRP\|FILEATTR_WRITE_OTH\|FILEATTR_WRITE_USR\|FILETYPE_ANIM\|FILETYPE_ICON\|FILETYPE_IMAGE\|FILETYPE_SOUND\|FILETYPE_VIDEO\|FILETYPEFLAGS_ALPHA\|FILETYPEFLAGS_FPS\|FILETYPEFLAGS_QUALITY\|FILETYPEFLAGS_SAVE\|FILLCOLOR\|FILLGRADIENT\|FILLNONE\|FILLRULEEVENODD\|FILLRULEWINDING\|FILLTEXTURE\|FLOAT\|FLOW_HARDWARE\|FLOW_OFF\|FLOW_XON_XOFF\|FONT\|FONTENGINE_INBUILT\|FONTENGINE_NATIVE\|FONTSLANT_ITALIC\|FONTSLANT_OBLIQUE\|FONTSLANT_ROMAN\|FONTTYPE_BITMAP\|FONTTYPE_COLOR\|FONTTYPE_VECTOR\|FONTWEIGHT_BLACK\|FONTWEIGHT_BOLD\|FONTWEIGHT_BOOK\|FONTWEIGHT_DEMIBOLD\|FONTWEIGHT_EXTRABLACK\|FONTWEIGHT_EXTRABOLD\|FONTWEIGHT_EXTRALIGHT\|FONTWEIGHT_HEAVY\|FONTWEIGHT_LIGHT\|FONTWEIGHT_MEDIUM\|FONTWEIGHT_NORMAL\|FONTWEIGHT_REGULAR\|FONTWEIGHT_SEMIBOLD\|FONTWEIGHT_THIN\|FONTWEIGHT_ULTRABLACK\|FONTWEIGHT_ULTRABOLD\|FONTWEIGHT_ULTRALIGHT\|FRAMEMODE_FULL\|FRAMEMODE_SINGLE\|FREESPACE\|FTPASCII\|FTPBINARY\|FUCHSIA\|FUNCTION\|GRAY\|GREEN\|HBLINDS128\|HBLINDS16\|HBLINDS32\|HBLINDS64\|HBLINDS8\|HCLOSECURTAIN\|HCLOSEGATE\|HEXNUMERICAL\|HFLIPCOIN\|HFLOWBOTTOM\|HFLOWTOP\|HIDEBRUSH\|HIDELAYER\|HKEY_CLASSES_ROOT\|HKEY_CURRENT_CONFIG\|HKEY_CURRENT_USER\|HKEY_LOCAL_MACHINE\|HKEY_USERS\|HLINES\|HLINES2\|HLOWFLIPCOIN\|HOLLYWOOD\|HOPENCURTAIN\|HOPENGATE\|HSPLIT\|HSTRANGEPUSH\|HSTRETCHCENTER\|HSTRIPES\|HSTRIPES16\|HSTRIPES2\|HSTRIPES32\|HSTRIPES4\|HSTRIPES64\|HSTRIPES8\|HW_64BIT\|HW_AMIGA\|HW_AMIGAOS3\|HW_AMIGAOS4\|HW_ANDROID\|HW_AROS\|HW_IOS\|HW_LINUX\|HW_LITTLE_ENDIAN\|HW_MACOS\|HW_MORPHOS\|HW_REVISION\|HW_VERSION\|HW_WARPOS\|HW_WINDOWS\|ICNFMT_HOLLYWOOD\|ICON\|IMAGETYPE_RASTER\|IMAGETYPE_VECTOR\|IMGFMT_BMP\|IMGFMT_GIF\|IMGFMT_ILBM\|IMGFMT_JPEG\|IMGFMT_NATIVE\|IMGFMT_PLUGIN\|IMGFMT_PNG\|IMGFMT_TIFF\|IMGFMT_UNKNOWN\|IMMERSIVE_LEANBACK\|IMMERSIVE_NONE\|IMMERSIVE_NORMAL\|IMMERSIVE_STICKY\|INACTIVEWINDOW\|INF\|INSERTBRUSH\|INTEGER\|INTERVAL\|IO_BUFFERED\|IO_FAKE64\|IO_LITTLEENDIAN\|IO_SIGNED\|IO_UNBUFFERED\|IO_UNSIGNED\|IPAUTO\|IPUNKNOWN\|IPV4\|IPV6\|ITALIC\|JOINBEVEL\|JOINMITER\|JOINROUND\|JOYDOWN\|JOYDOWNLEFT\|JOYDOWNRIGHT\|JOYLEFT\|JOYNODIR\|JOYRIGHT\|JOYUP\|JOYUPLEFT\|JOYUPRIGHT\|JUSTIFIED\|KEEPASPRAT\|KEEPPOSITION\|LANGUAGE_ABKHAZIAN\|LANGUAGE_AFAR\|LANGUAGE_AFRIKAANS\|LANGUAGE_AKAN\|LANGUAGE_ALBANIAN\|LANGUAGE_AMHARIC\|LANGUAGE_ARABIC\|LANGUAGE_ARAGONESE\|LANGUAGE_ARMENIAN\|LANGUAGE_ASSAMESE\|LANGUAGE_AVARIC\|LANGUAGE_AVESTAN\|LANGUAGE_AYMARA\|LANGUAGE_AZERBAIJANI\|LANGUAGE_BAMBARA\|LANGUAGE_BASHKIR\|LANGUAGE_BASQUE\|LANGUAGE_BELARUSIAN\|LANGUAGE_BENGALI\|LANGUAGE_BIHARI\|LANGUAGE_BISLAMA\|LANGUAGE_BOSNIAN\|LANGUAGE_BRETON\|LANGUAGE_BULGARIAN\|LANGUAGE_BURMESE\|LANGUAGE_CATALAN\|LANGUAGE_CENTRALKHMER\|LANGUAGE_CHAMORRO\|LANGUAGE_CHECHEN\|LANGUAGE_CHICHEWA\|LANGUAGE_CHINESE\|LANGUAGE_CHURCHSLAVIC\|LANGUAGE_CHUVASH\|LANGUAGE_CORNISH\|LANGUAGE_CORSICAN\|LANGUAGE_CREE\|LANGUAGE_CROATIAN\|LANGUAGE_CZECH\|LANGUAGE_DANISH\|LANGUAGE_DIVEHI\|LANGUAGE_DUTCH\|LANGUAGE_DZONGKHA\|LANGUAGE_ENGLISH\|LANGUAGE_ESPERANTO\|LANGUAGE_ESTONIAN\|LANGUAGE_EWE\|LANGUAGE_FAROESE\|LANGUAGE_FIJIAN\|LANGUAGE_FINNISH\|LANGUAGE_FRENCH\|LANGUAGE_FULAH\|LANGUAGE_GAELIC\|LANGUAGE_GALICIAN\|LANGUAGE_GANDA\|LANGUAGE_GEORGIAN\|LANGUAGE_GERMAN\|LANGUAGE_GREEK\|LANGUAGE_GREENLANDIC\|LANGUAGE_GUARANI\|LANGUAGE_GUJARATI\|LANGUAGE_HAITIAN\|LANGUAGE_HAUSA\|LANGUAGE_HEBREW\|LANGUAGE_HERERO\|LANGUAGE_HINDI\|LANGUAGE_HIRIMOTU\|LANGUAGE_HUNGARIAN\|LANGUAGE_ICELANDIC\|LANGUAGE_IDO\|LANGUAGE_IGBO\|LANGUAGE_INDONESIAN\|LANGUAGE_INTERLINGUA\|LANGUAGE_INTERLINGUE\|LANGUAGE_INUKTITUT\|LANGUAGE_INUPIAQ\|LANGUAGE_IRISH\|LANGUAGE_ITALIAN\|LANGUAGE_JAPANESE\|LANGUAGE_JAVANESE\|LANGUAGE_KANNADA\|LANGUAGE_KANURI\|LANGUAGE_KASHMIRI\|LANGUAGE_KAZAKH\|LANGUAGE_KIKUYU\|LANGUAGE_KINYARWANDA\|LANGUAGE_KIRGHIZ\|LANGUAGE_KOMI\|LANGUAGE_KONGO\|LANGUAGE_KOREAN\|LANGUAGE_KUANYAMA\|LANGUAGE_KURDISH\|LANGUAGE_LAO\|LANGUAGE_LATIN\|LANGUAGE_LATVIAN\|LANGUAGE_LIMBURGAN\|LANGUAGE_LINGALA\|LANGUAGE_LITHUANIAN\|LANGUAGE_LUBAKATANGA\|LANGUAGE_LUXEMBOURGISH\|LANGUAGE_MACEDONIAN\|LANGUAGE_MALAGASY\|LANGUAGE_MALAY\|LANGUAGE_MALAYALAM\|LANGUAGE_MALTESE\|LANGUAGE_MANX\|LANGUAGE_MAORI\|LANGUAGE_MARATHI\|LANGUAGE_MARSHALLESE\|LANGUAGE_MONGOLIAN\|LANGUAGE_NAURU\|LANGUAGE_NAVAJO\|LANGUAGE_NDONGA\|LANGUAGE_NEPALI\|LANGUAGE_NORTHERNSAMI\|LANGUAGE_NORTHNDEBELE\|LANGUAGE_NORWEGIAN\|LANGUAGE_NORWEGIANBOKMAL\|LANGUAGE_NORWEGIANNYNORSK\|LANGUAGE_OCCITAN\|LANGUAGE_OJIBWA\|LANGUAGE_ORIYA\|LANGUAGE_OROMO\|LANGUAGE_OSSETIAN\|LANGUAGE_PALI\|LANGUAGE_PANJABI\|LANGUAGE_PASHTO\|LANGUAGE_PERSIAN\|LANGUAGE_POLISH\|LANGUAGE_PORTUGUESE\|LANGUAGE_QUECHUA\|LANGUAGE_ROMANIAN\|LANGUAGE_ROMANSH\|LANGUAGE_RUNDI\|LANGUAGE_RUSSIAN\|LANGUAGE_SAMOAN\|LANGUAGE_SANGO\|LANGUAGE_SANSKRIT\|LANGUAGE_SARDINIAN\|LANGUAGE_SERBIAN\|LANGUAGE_SHONA\|LANGUAGE_SICHUANYI\|LANGUAGE_SINDHI\|LANGUAGE_SINHALA\|LANGUAGE_SLOVAK\|LANGUAGE_SLOVENIAN\|LANGUAGE_SOMALI\|LANGUAGE_SOUTHERNSOTHO\|LANGUAGE_SOUTHNDEBELE\|LANGUAGE_SPANISH\|LANGUAGE_SUNDANESE\|LANGUAGE_SWAHILI\|LANGUAGE_SWATI\|LANGUAGE_SWEDISH\|LANGUAGE_TAGALOG\|LANGUAGE_TAHITIAN\|LANGUAGE_TAJIK\|LANGUAGE_TAMIL\|LANGUAGE_TATAR\|LANGUAGE_TELUGU\|LANGUAGE_THAI\|LANGUAGE_TIBETAN\|LANGUAGE_TIGRINYA\|LANGUAGE_TONGA\|LANGUAGE_TSONGA\|LANGUAGE_TSWANA\|LANGUAGE_TURKISH\|LANGUAGE_TURKMEN\|LANGUAGE_TWI\|LANGUAGE_UIGHUR\|LANGUAGE_UKRAINIAN\|LANGUAGE_UNKNOWN\|LANGUAGE_URDU\|LANGUAGE_UZBEK\|LANGUAGE_VENDA\|LANGUAGE_VIETNAMESE\|LANGUAGE_WALLOON\|LANGUAGE_WELSH\|LANGUAGE_WESTERNFRISIAN\|LANGUAGE_WOLOF\|LANGUAGE_XHOSA\|LANGUAGE_YIDDISH\|LANGUAGE_YORUBA\|LANGUAGE_ZHUANG\|LANGUAGE_ZULU\|LAYER\|LAYER_VS_BOX\|LAYERBUTTON\|LEFT\|LEFTOUT\|LIGHTUSERDATA\|LIME\|LINE\|LINEAR\|LITTLEENDIAN\|LONG\|LOWERCURVE\|MAROON\|MASK\|MASKAND\|MASKINVISIBLE\|MASKOR\|MASKVANILLACOPY\|MASKVISIBLE\|MASKXOR\|MEMORY\|MENU\|MENUITEM_DISABLED\|MENUITEM_RADIO\|MENUITEM_SELECTED\|MENUITEM_TOGGLE\|MILLISECONDS\|MODE_READ\|MODE_READWRITE\|MODE_WRITE\|MODLALT\|MODLCOMMAND\|MODLCONTROL\|MODLSHIFT\|MODRALT\|MODRCOMMAND\|MODRCONTROL\|MODRSHIFT\|MONO16\|MONO8\|MONOSPACE\|MOVEFILE_COPY\|MOVEFILE_COPYFAILED\|MOVEFILE_DELETE\|MOVEFILE_DELETEFAILED\|MOVEFILE_UNPROTECT\|MOVELIST\|MOVEWINDOW\|MUSIC\|NAN\|NATIVE\|NATIVEENDIAN\|NAVY\|NETWORKCONNECTION\|NETWORKSERVER\|NETWORKUDP\|NEXTFRAME\|NEXTFRAME2\|NIL\|NOCOLOR\|NONE\|NOPEN\|NORMAL\|NORMALSPEED\|NOTRANSPARENCY\|NUMBER\|NUMERICAL\|OLIVE\|ONBUTTONCLICK\|ONBUTTONCLICKALL\|ONBUTTONOVER\|ONBUTTONOVERALL\|ONBUTTONRIGHTCLICK\|ONBUTTONRIGHTCLICKALL\|ONKEYDOWN\|ONKEYDOWNALL\|ORIENTATION_LANDSCAPE\|ORIENTATION_LANDSCAPEREV\|ORIENTATION_NONE\|ORIENTATION_PORTRAIT\|ORIENTATION_PORTRAITREV\|PALETTE\|PALETTE_AGA\|PALETTE_CGA\|PALETTE_DEFAULT\|PALETTE_EGA\|PALETTE_GRAY128\|PALETTE_GRAY16\|PALETTE_GRAY256\|PALETTE_GRAY32\|PALETTE_GRAY4\|PALETTE_GRAY64\|PALETTE_GRAY8\|PALETTE_MACINTOSH\|PALETTE_MONOCHROME\|PALETTE_OCS\|PALETTE_WINDOWS\|PALETTE_WORKBENCH\|PALETTEMODE_PEN\|PALETTEMODE_REMAP\|PARITY_EVEN\|PARITY_NONE\|PARITY_ODD\|PERMREQ_READEXTERNAL\|PERMREQ_WRITEEXTERNAL\|PI\|PIXELZOOM1\|PIXELZOOM2\|PLOT\|PLUGINCAPS_ANIM\|PLUGINCAPS_AUDIOADAPTER\|PLUGINCAPS_CONVERT\|PLUGINCAPS_DIRADAPTER\|PLUGINCAPS_DISPLAYADAPTER\|PLUGINCAPS_EXTENSION\|PLUGINCAPS_FILEADAPTER\|PLUGINCAPS_ICON\|PLUGINCAPS_IMAGE\|PLUGINCAPS_IPCADAPTER\|PLUGINCAPS_LIBRARY\|PLUGINCAPS_NETWORKADAPTER\|PLUGINCAPS_REQUESTERADAPTER\|PLUGINCAPS_REQUIRE\|PLUGINCAPS_SAVEANIM\|PLUGINCAPS_SAVEICON\|PLUGINCAPS_SAVEIMAGE\|PLUGINCAPS_SAVESAMPLE\|PLUGINCAPS_SERIALIZE\|PLUGINCAPS_SOUND\|PLUGINCAPS_TIMERADAPTER\|PLUGINCAPS_VECTOR\|PLUGINCAPS_VIDEO\|POINTER\|POLYGON\|PRGTYPE_APPLET\|PRGTYPE_PROGRAM\|PRGTYPE_SCRIPT\|PRINT\|PURPLE\|PUSHBOTTOM\|PUSHLEFT\|PUSHRIGHT\|PUSHTOP\|PUZZLE\|QUADRECT\|QUARTERS\|RADIAL\|RANDOMEFFECT\|RANDOMPARAMETER\|RECEIVEALL\|RECEIVEBYTES\|RECEIVEDATA_PACKET\|RECEIVELINE\|RECTBACKCENTER\|RECTBACKEAST\|RECTBACKNORTH\|RECTBACKNORTHEAST\|RECTBACKNORTHWEST\|RECTBACKSOUTH\|RECTBACKSOUTHEAST\|RECTBACKSOUTHWEST\|RECTBACKWEST\|RECTCENTER\|RECTEAST\|RECTNORTH\|RECTNORTHEAST\|RECTNORTHWEST\|RECTSOUTH\|RECTSOUTHEAST\|RECTSOUTHWEST\|RECTWEST\|RED\|REMOVELAYER\|REQ_CAMERA\|REQ_GALLERY\|REQ_HIDEICONS\|REQ_MULTISELECT\|REQ_NORMAL\|REQ_SAVEMODE\|REQICON_ERROR\|REQICON_INFORMATION\|REQICON_NONE\|REQICON_QUESTION\|REQICON_WARNING\|REVEALBOTTOM\|REVEALLEFT\|REVEALRIGHT\|REVEALTOP\|RIGHT\|RIGHTOUT\|ROLLLEFT\|ROLLTOP\|RTS_OFF\|RTS_ON\|SAMPLE\|SANS\|SCALEMODE_AUTO\|SCALEMODE_LAYER\|SCALEMODE_NONE\|SCROLLBOTTOM\|SCROLLEAST\|SCROLLLEFT\|SCROLLNORTH\|SCROLLNORTHEAST\|SCROLLNORTHWEST\|SCROLLRIGHT\|SCROLLSOUTH\|SCROLLSOUTHEAST\|SCROLLSOUTHWEST\|SCROLLTOP\|SCROLLWEST\|SECONDS\|SEEK_BEGINNING\|SEEK_CURRENT\|SEEK_END\|SELMODE_COMBO\|SELMODE_LAYERS\|SELMODE_NORMAL\|SERIAL\|SERIF\|SERVER\|SHADOW\|SHAPE\|SHDWEAST\|SHDWNORTH\|SHDWNORTHEAST\|SHDWNORTHWEST\|SHDWSOUTH\|SHDWSOUTHEAST\|SHDWSOUTHWEST\|SHDWWEST\|SHORT\|SILVER\|SIMPLEBUTTON\|SINE\|SIZEWINDOW\|SLIDEBOTTOM\|SLIDELEFT\|SLIDERIGHT\|SLIDETOP\|SLOWSPEED\|SMOOTHOUT\|SMPFMT_WAVE\|SNAPDESKTOP\|SNAPDISPLAY\|SNAPWINDOW\|SPIRAL\|SPRITE\|SPRITE_VS_BOX\|SPRITE_VS_BRUSH\|STAR\|STDERR\|STDIN\|STDOUT\|STDPTR_BUSY\|STDPTR_CUSTOM\|STDPTR_SYSTEM\|STEREO16\|STEREO8\|STOP_1\|STOP_2\|STRETCHBOTTOM\|STRETCHLEFT\|STRETCHRIGHT\|STRETCHTOP\|STRING\|STRUDEL\|SUN\|SWISS\|TABLE\|TEAL\|TEXTOBJECT\|TEXTOUT\|THREAD\|TICKS\|TIMEOUT\|TIMER\|TOP\|TOPOUT\|TRUETYPE_DEFAULT\|TURNDOWNBOTTOM\|TURNDOWNLEFT\|TURNDOWNRIGHT\|TURNDOWNTOP\|UDPCLIENT\|UDPNONE\|UDPOBJECT\|UDPSERVER\|UNDERLINED\|UNDO\|UPLOADFILE_RESPONSE\|UPLOADFILE_STATUS\|UPNDOWN\|UPPERCURVE\|USEDSPACE\|USELAYERPOSITION\|USERDATA\|VANILLACOPY\|VBLINDS128\|VBLINDS16\|VBLINDS32\|VBLINDS64\|VBLINDS8\|VCLOSECURTAIN\|VCLOSEGATE\|VECTORPATH\|VFLIPCOIN\|VFLOWLEFT\|VFLOWRIGHT\|VIDDRV_HOLLYWOOD\|VIDDRV_OS\|VIDEO\|VIEWMODE_DATE\|VIEWMODE_ICONS\|VIEWMODE_NAME\|VIEWMODE_NONE\|VIEWMODE_SIZE\|VIEWMODE_TYPE\|VLINES\|VLINES2\|VLOWFLIPCOIN\|VOID\|VOPENCURTAIN\|VOPENGATE\|VSPLIT\|VSTRANGEPUSH\|VSTRETCHCENTER\|VSTRIPES\|VSTRIPES16\|VSTRIPES2\|VSTRIPES32\|VSTRIPES4\|VSTRIPES64\|VSTRIPES8\|WALLPAPERLEFT\|WALLPAPERTOP\|WATER1\|WATER2\|WATER3\|WATER4\|WHITE\|WORD\|YELLOW\|ZOOMCENTER\|ZOOMEAST\|ZOOMIN\|ZOOMNORTH\|ZOOMNORTHEAST\|ZOOMNORTHWEST\|ZOOMOUT\|ZOOMSOUTH\|ZOOMSOUTHEAST\|ZOOMSOUTHWEST\|ZOOMWEST\)\>"
" Hollywood Functions
-syn keyword hwFunction ACos ARGB ASin ATan ATan2 Abs ActivateDisplay Add AddArcToPath AddBoxToPath AddCircleToPath AddEllipseToPath AddFontPath AddIconImage AddMove AddStr AddTab AddTextToPath AllocMem AllocMemFromPointer AllocMemFromVirtualFile AppendPath ApplyPatch Arc ArcDistortBrush ArrayToStr Asc Assert AsyncDrawFrame BGPicToBrush BarrelDistortBrush Base64Str Beep BeginAnimStream BeginDoubleBuffer BeginRefresh BinStr BitClear BitComplement BitSet BitTest BitXor Blue BlurBrush Box BreakEventHandler BreakWhileMouseOn BrushToBGPic BrushToGray BrushToMonochrome BrushToPenArray BrushToRGBArray ByteAsc ByteChr ByteLen ByteOffset ByteStrStr ByteVal CRC32 CRC32Str CallJavaMethod CancelAsyncDraw CancelAsyncOperation CanonizePath Cast Ceil ChangeApplicationIcon ChangeBrushTransparency ChangeDirectory ChangeDisplayMode ChangeDisplaySize ChangeInterval CharOffset CharWidth CharcoalBrush CheckEvent CheckEvents Chr Circle ClearClipboard ClearEvents ClearInterval ClearMove ClearObjectData ClearPath ClearScreen ClearSerialQueue ClearTimeout CloseAmigaGuide CloseAnim CloseAudio CloseCatalog CloseConnection CloseDirectory CloseDisplay CloseFile CloseFont CloseMusic ClosePath CloseResourceMonitor CloseSerialPort CloseServer CloseUDPObject CloseVideo Cls CollectGarbage Collision ColorRequest CompareDates CompareStr CompressFile Concat ConsolePrint ConsolePrintNR ConsolePrompt ContinueAsyncOperation ContrastBrush ContrastPalette ConvertStr ConvertToBrush CopyAnim CopyBGPic CopyBrush CopyFile CopyMem CopyObjectData CopyPalette CopyPath CopyPens CopySample CopySprite CopyTable CopyTextObject Cos CountDirectoryEntries CountJoysticks CountStr CreateAnim CreateBGPic CreateBorderBrush CreateBrush CreateButton CreateClipRegion CreateCoroutine CreateDisplay CreateGradientBGPic CreateGradientBrush CreateIcon CreateKeyDown CreateLayer CreateList CreateMenu CreateMusic CreatePalette CreatePointer CreatePort CreateRainbowBGPic CreateRexxPort CreateSample CreateServer CreateShadowBrush CreateShortcut CreateSprite CreateTextObject CreateTexturedBGPic CreateTexturedBrush CreateUDPObject CropBrush CtrlCQuit CurveTo CyclePalette DateToTimestamp DateToUTC DebugOutput DebugPrint DebugPrintNR DebugPrompt DebugStr DebugVal DecompressFile DecreasePointer DefineVirtualFile DefineVirtualFileFromString Deg DeleteAlphaChannel DeleteButton DeleteFile DeleteMask DeletePrefs DeselectMenuItem DeserializeTable DirectoryItems DisableButton DisableEvent DisableLayers DisableLineHook DisableMenuItem DisablePlugin DisableVWait DisplayAnimFrame DisplayBGPic DisplayBGPicPart DisplayBGPicPartFX DisplayBrush DisplayBrushFX DisplayBrushPart DisplaySprite DisplayTextObject DisplayTextObjectFX DisplayTransitionFX DisplayVideoFrame Div DoMove DownloadFile DrawPath DumpButtons DumpLayers DumpMem DumpVideo DumpVideoTime EdgeBrush Ellipse EmbossBrush EmptyStr EnableButton EnableEvent EnableLayers EnableLineHook EnableMenuItem EnablePlugin EnableVWait End EndDoubleBuffer EndRefresh EndSelect EndianSwap EndsWith Eof Error EscapeQuit Eval Execute Exists ExitOnError Exp ExtractPalette FileAttributes FileLength FileLines FilePart FilePos FileRequest FileSize FileToString FillMem FillMusicBuffer FindStr FinishAnimStream FinishAsyncDraw Flip FlipBrush FlipSprite FloodFill Floor FlushFile FlushMusicBuffer FlushSerialPort FontRequest ForEach ForEachI ForcePathUse ForceSound ForceVideoDriver ForceVideoMode FormatStr FrExp Frac FreeAnim FreeBGPic FreeBrush FreeClipRegion FreeDisplay FreeEventCache FreeGlyphCache FreeIcon FreeLayers FreeMem FreeMenu FreeModule FreePalette FreePath FreePointer FreeSample FreeSprite FreeTextObject FullPath GCInfo GammaBrush GammaPalette GetAnimFrame GetApplicationInfo GetApplicationList GetAsset GetAttribute GetAvailableFonts GetBaudRate GetBestPen GetBrushLink GetBrushPen GetBulletColor GetCatalogString GetChannels GetCharMaps GetClipboard GetCommandLine GetConnectionIP GetConnectionPort GetConnectionProtocol GetConstant GetCoroutineStatus GetCountryInfo GetCurrentDirectory GetCurrentPoint GetDTR GetDash GetDataBits GetDate GetDateNum GetDefaultEncoding GetDirectoryEntry GetDisplayModes GetEnv GetErrorName GetEventCode GetFPSLimit GetFileArgument GetFileAttributes GetFillRule GetFillStyle GetFlowControl GetFontColor GetFontStyle GetFormStyle GetFrontScreen GetHostName GetIconProperties GetItem GetKerningPair GetLanguageInfo GetLastError GetLayerAtPos GetLayerPen GetLayerStyle GetLineCap GetLineJoin GetLineWidth GetLocalIP GetLocalInterfaces GetLocalPort GetLocalProtocol GetMACAddress GetMemPointer GetMemString GetMemoryInfo GetMetaTable GetMiterLimit GetMonitors GetObjectData GetObjectType GetObjects GetPalettePen GetParity GetPathExtents GetPatternPosition GetPen GetPlugins GetProgramDirectory GetProgramInfo GetPubScreens GetRTS GetRandomColor GetRandomFX GetRealColor GetSampleData GetShortcutPath GetSongPosition GetStartDirectory GetStopBits GetSystemCountry GetSystemInfo GetSystemLanguage GetTempFileName GetTime GetTimeZone GetTimer GetTimestamp GetType GetVersion GetVideoFrame GetVolumeInfo GetVolumeName GetWeekday GrabDesktop Green HaveFreeChannel HaveItem HaveObject HaveObjectData HavePlugin HaveVolume HexStr HideDisplay HideKeyboard HideLayer HideLayerFX HidePointer HideScreen Hypot IIf IPairs IgnoreCase ImageRequest InKeyStr IncreasePointer InsertItem InsertLayer InsertSample InsertStr InstallEventHandler Int Intersection InvertAlphaChannel InvertBrush InvertMask InvertPalette IsAbsolutePath IsAlNum IsAlpha IsAnim IsBrushEmpty IsChannelPlaying IsCntrl IsDigit IsDirectory IsFinite IsGraph IsInf IsKeyDown IsLeftMouse IsLower IsMenuItemDisabled IsMenuItemSelected IsMidMouse IsModule IsMusic IsMusicPlaying IsNan IsNil IsOnline IsPathEmpty IsPicture IsPrint IsPunct IsRightMouse IsSample IsSamplePlaying IsSound IsSpace IsTableEmpty IsUnicode IsUpper IsVideo IsVideoPlaying IsXDigit JoyDir JoyFire LayerExists LayerToBack LayerToFront Ld LdExp LeftMouseQuit LeftStr LegacyControl Limit Line LineTo ListItems ListRequest Ln LoadAnim LoadAnimFrame LoadBGPic LoadBrush LoadIcon LoadModule LoadPalette LoadPlugin LoadPrefs LoadSample LoadSprite Locate Log LowerStr MD5 MD5Str MakeButton MakeDate MakeDirectory MakeHostPath MatchPattern Max MemToTable MidStr Min MixBrush MixRGB MixSample Mod ModifyAnimFrames ModifyButton ModifyKeyDown ModifyLayerFrames ModulateBrush ModulatePalette MonitorDirectory MouseX MouseY MoveAnim MoveBrush MoveDisplay MoveFile MoveLayer MovePointer MoveSprite MoveTextObject MoveTo Mul NPrint NextDirectoryEntry NextFrame NextItem NormalizePath OilPaintBrush OpenAmigaGuide OpenAnim OpenAudio OpenCatalog OpenConnection OpenDirectory OpenDisplay OpenFile OpenFont OpenMusic OpenResourceMonitor OpenSerialPort OpenURL OpenVideo Pack PadNum Pairs PaletteToGray ParseDate PathItems PathPart PathRequest PathToBrush PatternFindStr PatternFindStrDirect PatternFindStrShort PatternReplaceStr PauseLayer PauseModule PauseMusic PauseTimer PauseVideo Peek PeekClipboard PenArrayToBrush PerformSelector PermissionRequest PerspectiveDistortBrush Pi PixelateBrush PlayAnim PlayAnimDisk PlayLayer PlayModule PlayMusic PlaySample PlaySubsong PlayVideo Plot Poke PolarDistortBrush PollSerialQueue Polygon Pow Print QuantizeBrush RGB RGBArrayToBrush Rad RaiseOnError RasterizeBrush RawDiv RawEqual RawGet RawSet ReadBrushPixel ReadByte ReadBytes ReadChr ReadDirectory ReadFloat ReadFunction ReadInt ReadLine ReadMem ReadPen ReadPixel ReadRegistryKey ReadSerialData ReadShort ReadString ReadTable ReceiveData ReceiveUDPData Red ReduceAlphaChannel RefreshDisplay RelCurveTo RelLineTo RelMoveTo RemapBrush RemoveBrushPalette RemoveButton RemoveIconImage RemoveItem RemoveKeyDown RemoveLayer RemoveLayerFX RemoveLayers RemoveSprite RemoveSprites Rename RepeatStr ReplaceColors ReplaceStr ResetKeyStates ResetTabs ResetTimer ResolveHostName ResumeCoroutine ResumeLayer ResumeModule ResumeMusic ResumeTimer ResumeVideo ReverseFindStr ReverseStr RewindDirectory RightStr Rnd RndF RndStrong Rol Ror RotateBrush RotateLayer RotateTextObject Round Rt Run RunCallback RunRexxScript Sar SaveAnim SaveBrush SaveIcon SavePalette SavePrefs SaveSample SaveSnapshot ScaleAnim ScaleBGPic ScaleBrush ScaleLayer ScaleSprite ScaleTextObject Seek SeekLayer SeekMusic SeekVideo SelectAlphaChannel SelectAnim SelectBGPic SelectBrush SelectDisplay SelectLayer SelectMask SelectMenuItem SelectPalette SendApplicationMessage SendData SendMessage SendRexxCommand SendUDPData SepiaToneBrush SerializeTable SetAlphaIntensity SetAnimFrameDelay SetBaudRate SetBorderPen SetBrushDepth SetBrushPalette SetBrushPen SetBrushTransparency SetBrushTransparentPen SetBulletColor SetBulletPen SetChannelVolume SetClipRegion SetClipboard SetCycleTable SetDTR SetDash SetDataBits SetDefaultEncoding SetDepth SetDisplayAttributes SetDitherMode SetDrawPen SetDrawTagsDefault SetEnv SetEventTimeout SetFPSLimit SetFileAttributes SetFileEncoding SetFillRule SetFillStyle SetFlowControl SetFont SetFontColor SetFontStyle SetFormStyle SetGradientPalette SetIOMode SetIconProperties SetInterval SetLayerAnchor SetLayerBorder SetLayerDepth SetLayerFilter SetLayerLight SetLayerName SetLayerPalette SetLayerPen SetLayerShadow SetLayerStyle SetLayerTint SetLayerTransparency SetLayerTransparentPen SetLayerVolume SetLayerZPos SetLineCap SetLineJoin SetLineWidth SetListItems SetMargins SetMaskMode SetMasterVolume SetMetaTable SetMiterLimit SetMusicVolume SetNetworkProtocol SetNetworkTimeout SetObjectData SetPalette SetPaletteDepth SetPaletteMode SetPalettePen SetPaletteTransparentPen SetPanning SetParity SetPen SetPitch SetPointer SetRTS SetScreenTitle SetShadowPen SetSpriteZPos SetStandardIconImage SetStandardPalette SetStopBits SetSubtitle SetTimeout SetTimerElapse SetTitle SetTransparentPen SetTransparentThreshold SetTrayIcon SetVectorEngine SetVideoPosition SetVideoSize SetVideoVolume SetVolume SetWBIcon Sgn SharpenBrush Shl ShowDisplay ShowKeyboard ShowLayer ShowLayerFX ShowNotification ShowPointer ShowRinghioMessage ShowScreen ShowToast Shr Sin SolarizeBrush SolarizePalette Sort SplitStr Sqrt StartPath StartSubPath StartTimer StartsWith StopChannel StopLayer StopModule StopMusic StopSample StopTimer StopVideo StrLen StrStr StrToArray StringRequest StringToFile StripStr Sub SwapLayers SwirlBrush SystemRequest TableItems TableToMem Tan TextExtent TextHeight TextOut TextWidth TimerElapsed TimestampToDate TintBrush TintPalette ToHostName ToIP ToNumber ToString ToUserData TransformBrush TransformLayer TranslateLayer TranslatePath TrimBrush TrimStr UTCToDate UndefineVirtualStringFile Undo UndoFX UnleftStr UnmidStr Unpack UnrightStr UnsetEnv UploadFile UpperStr UseCarriageReturn UseFont VWait Val ValidateDate ValidateStr Vibrate Wait WaitEvent WaitKeyDown WaitLeftMouse WaitMidMouse WaitPatternPosition WaitRightMouse WaitSampleEnd WaitSongPosition WaitTimer WaterRippleBrush WhileKeyDown WhileMouseDown WhileMouseOn WhileRightMouseDown Wrap WriteAnimFrame WriteBrushPixel WriteByte WriteBytes WriteChr WriteFloat WriteFunction WriteInt WriteLine WriteMem WritePen WriteRegistryKey WriteSerialData WriteShort WriteString WriteTable YieldCoroutine
+syn keyword hwFunction Abs ACos ARGB ActivateDisplay Add AddArcToPath AddBoxToPath AddCircleToPath AddEllipseToPath AddFontPath AddIconImage AddMove AddStr AddTab AddTextToPath AllocMem AllocMemFromPointer AllocMemFromVirtualFile AppendPath ApplyPatch Arc ArcDistortBrush ArrayToStr Asc ASin Assert AsyncDrawFrame ATan ATan2 BarrelDistortBrush Base64Str Beep BeginAnimStream BeginDoubleBuffer BeginRefresh BGPicToBrush BinStr BitClear BitComplement BitSet BitTest BitXor Blue BlurBrush Box BreakEventHandler BreakWhileMouseOn BrushToBGPic BrushToGray BrushToMonochrome BrushToPenArray BrushToRGBArray ByteAsc ByteChr ByteLen ByteOffset ByteStrStr ByteVal CRC32 CRC32Str CallJavaMethod CancelAsyncDraw CancelAsyncOperation CanonizePath Cast Ceil ChangeApplicationIcon ChangeBrushTransparency ChangeDirectory ChangeDisplayMode ChangeDisplaySize ChangeInterval CharcoalBrush CharOffset CharWidth CheckEvent CheckEvents Chr Circle ClearClipboard ClearEvents ClearInterval ClearMove ClearObjectData ClearPath ClearScreen ClearSerialQueue ClearTimeout CloseAmigaGuide CloseAnim CloseAudio CloseCatalog CloseConnection CloseDirectory CloseDisplay CloseFile CloseFont CloseMusic ClosePath CloseResourceMonitor CloseSerialPort CloseServer CloseUDPObject CloseVideo Cls CollectGarbage Collision ColorRequest CompareDates CompareStr CompressFile Concat ConsolePrint ConsolePrintNR ConsolePrompt ContinueAsyncOperation ContrastBrush ContrastPalette ConvertStr ConvertToBrush CopyAnim CopyBGPic CopyBrush CopyFile CopyLayer CopyMem CopyObjectData CopyPalette CopyPath CopyPens CopySample CopySprite CopyTable CopyTextObject Cos CountDirectoryEntries CountJoysticks CountStr CreateAnim CreateBGPic CreateBorderBrush CreateBrush CreateButton CreateClipRegion CreateCoroutine CreateDisplay CreateGradientBGPic CreateGradientBrush CreateIcon CreateKeyDown CreateLayer CreateList CreateMenu CreateMusic CreatePalette CreatePointer CreatePort CreateRainbowBGPic CreateRexxPort CreateSample CreateServer CreateShadowBrush CreateShortcut CreateSprite CreateTextObject CreateTexturedBGPic CreateTexturedBrush CreateUDPObject CropBrush CtrlCQuit CurveTo CyclePalette DateToTimestamp DateToUTC DebugOutput DebugPrint DebugPrintNR DebugPrompt DebugStr DebugVal DecompressFile DecreasePointer DefineVirtualFile DefineVirtualFileFromString Deg DeleteAlphaChannel DeleteButton DeleteFile DeleteMask DeletePrefs DeselectMenuItem DeserializeTable DirectoryItems DisableButton DisableEvent DisableEventHandler DisableLayers DisableLineHook DisableMenuItem DisablePlugin DisablePrecalculation DisableVWait DisplayAnimFrame DisplayBGPic DisplayBGPicPart DisplayBGPicPartFX DisplayBrush DisplayBrushFX DisplayBrushPart DisplaySprite DisplayTextObject DisplayTextObjectFX DisplayTransitionFX DisplayVideoFrame Div DoMove DownloadFile DrawPath DumpButtons DumpLayers DumpMem DumpVideo DumpVideoTime EdgeBrush Ellipse EmbossBrush EmptyStr EnableButton EnableEventHandler EnableEvent EnableLayers EnableLineHook EnableMenuItem EnablePlugin EnablePrecalculation EnableVWait End EndDoubleBuffer EndianSwap EndRefresh EndSelect EndsWith Eof Error EscapeQuit Eval Execute Exists ExitOnError Exp ExtractPalette FileAttributes FileLength FileLines FilePart FilePos FileRequest FileSize FileToString FillMem FillMusicBuffer FindStr FinishAnimStream FinishAsyncDraw Flip FlipBrush FlipSprite FloodFill Floor FlushFile FlushMusicBuffer FlushSerialPort FontRequest ForcePathUse ForceSound ForceVideoDriver ForceVideoMode ForEach ForEachI FormatStr Frac FreeAnim FreeBGPic FreeBrush FreeClipRegion FreeDisplay FreeEventCache FreeGlyphCache FreeIcon FreeLayers FreeMem FreeMenu FreeModule FreePalette FreePath FreePointer FreeSample FreeSprite FreeTextObject FrExp FullPath GammaBrush GammaPalette GCInfo GetAnimFrame GetApplicationInfo GetApplicationList GetAsset GetAttribute GetAvailableFonts GetBaudRate GetBestPen GetBrushLink GetBrushPen GetBulletColor GetCatalogString GetChannels GetCharMaps GetClipboard GetCommandLine GetConnectionIP GetConnectionPort GetConnectionProtocol GetConstant GetCoroutineStatus GetCountryInfo GetCurrentDirectory GetCurrentPoint GetDash GetDataBits GetDate GetDateNum GetDefaultEncoding GetDirectoryEntry GetDisplayModes GetDTR GetEnv GetErrorName GetEventCode GetFileArgument GetFileAttributes GetFillRule GetFillStyle GetFlowControl GetFontColor GetFontStyle GetFormStyle GetFPSLimit GetFrontScreen GetHostName GetIconProperties GetItem GetKerningPair GetLanguageInfo GetLastError GetLayerAtPos GetLayerPen GetLayerStyle GetLineCap GetLineJoin GetLineWidth GetLocalInterfaces GetLocalIP GetLocalPort GetLocalProtocol GetMACAddress GetMemoryInfo GetMemPointer GetMemString GetMetaTable GetMiterLimit GetMonitors GetObjectData GetObjects GetObjectType GetPalettePen GetParity GetPathExtents GetPatternPosition GetPen GetPlugins GetProgramDirectory GetProgramInfo GetPubScreens GetRandomColor GetRandomFX GetRealColor GetRTS GetSampleData GetShortcutPath GetSongPosition GetStartDirectory GetStopBits GetSystemCountry GetSystemInfo GetSystemLanguage GetTempFileName GetTime GetTimer GetTimestamp GetTimeZone GetType GetVersion GetVideoFrame GetVolumeInfo GetVolumeName GetWeekday Gosub Goto GrabDesktop Green HaveFreeChannel HaveItem HaveObject HaveObjectData HavePlugin HaveVolume HexStr HideDisplay HideKeyboard HideLayer HideLayerFX HidePointer HideScreen Hypot IgnoreCase IIf ImageRequest IncreasePointer InKeyStr InsertItem InsertLayer InsertSample InsertStr InstallEventHandler Intersection Int InvertAlphaChannel InvertBrush InvertMask InvertPalette IPairs IsAbsolutePath IsAlNum IsAlpha IsAnim IsAnimPlaying IsBrushEmpty IsChannelPlaying IsCntrl IsDigit IsDirectory IsFinite IsGraph IsInf IsKeyDown IsLeftMouse IsLower IsMenuItemDisabled IsMenuItemSelected IsMidMouse IsModule IsMusicPlaying IsMusic IsNan IsNil IsOnline IsPathEmpty IsPicture IsPrint IsPunct IsRightMouse IsSamplePlaying IsSample IsSound IsSpace IsTableEmpty IsUnicode IsUpper IsVideo IsVideoPlaying IsXDigit JoyDir JoyFire Label LayerExists LayerToBack LayerToFront Ld LdExp LeftMouseQuit LeftStr LegacyControl Limit Line LineTo ListItems ListRequest Ln LoadAnim LoadAnimFrame LoadBGPic LoadBrush LoadIcon LoadModule LoadPalette LoadPlugin LoadPrefs LoadSample LoadSprite Locate Log LowerStr MakeButton MakeDate MakeDirectory MakeHostPath MatchPattern Max MD5 MD5Str MemToTable MidStr Min MixBrush MixRGB MixSample ModifyAnimFrames ModifyButton ModifyKeyDown ModifyLayerFrames ModulateBrush Mod ModulatePalette MonitorDirectory MouseX MouseY MoveAnim MoveBrush MoveDisplay MoveFile MoveLayer MovePointer MoveSprite MoveTextObject MoveTo Mul NextDirectoryEntry NextFrame NextItem NormalizePath NPrint OilPaintBrush OpenAmigaGuide OpenAnim OpenAudio OpenCatalog OpenConnection OpenDirectory OpenDisplay OpenFile OpenFont OpenMusic OpenResourceMonitor OpenSerialPort OpenURL OpenVideo Pack PadNum Pairs PaletteToGray ParseDate PathItems PathPart PathRequest PathToBrush PatternFindStr PatternFindStrDirect PatternFindStrShort PatternReplaceStr PauseLayer PauseModule PauseMusic PauseTimer PauseVideo PeekClipboard Peek PenArrayToBrush PerformSelector PermissionRequest PerspectiveDistortBrush Pi PixelateBrush PlayAnim PlayAnimDisk PlayLayer PlayModule PlayMusic PlaySample PlaySubsong PlayVideo Plot Poke PolarDistortBrush PollSerialQueue Polygon Pow Print QuantizeBrush Rad RaiseOnError RasterizeBrush RawDiv RawEqual RawGet RawSet ReadBrushPixel ReadByte ReadBytes ReadChr ReadDirectory ReadFloat ReadFunction ReadInt ReadLine ReadMem ReadPen ReadPixel ReadRegistryKey ReadSerialData ReadShort ReadString ReadTable ReceiveData ReceiveUDPData Red ReduceAlphaChannel RefreshDisplay RelCurveTo RelLineTo RelMoveTo RemapBrush RemoveBrushPalette RemoveButton RemoveIconImage RemoveItem RemoveKeyDown RemoveLayer RemoveLayerFX RemoveLayers RemoveSprite RemoveSprites Rename RepeatStr ReplaceColors ReplaceStr ResetKeyStates ResetTabs ResetTimer ResolveHostName ResumeCoroutine ResumeLayer ResumeModule ResumeMusic ResumeTimer ResumeVideo ReverseFindStr ReverseStr RewindDirectory RGB RGBArrayToBrush RightStr Rnd RndF RndStrong Rol Ror RotateBrush RotateLayer RotateTextObject Round Rt Run RunCallback RunRexxScript Sar SaveAnim SaveBrush SaveIcon SavePalette SavePrefs SaveSample SaveSnapshot ScaleAnim ScaleBGPic ScaleBrush ScaleLayer ScaleSprite ScaleTextObject Seek SeekLayer SeekMusic SeekVideo SelectAlphaChannel SelectAnim SelectBGPic SelectBrush SelectDisplay SelectLayer SelectMask SelectMenuItem SelectPalette SendApplicationMessage SendData SendMessage SendRexxCommand SendUDPData SepiaToneBrush SerializeTable SetAlphaIntensity SetAnimFrameDelay SetBaudRate SetBorderPen SetBrushDepth SetBrushPalette SetBrushPen SetBrushTransparency SetBrushTransparentPen SetBulletColor SetBulletPen SetChannelVolume SetClipboard SetClipRegion SetCycleTable SetDash SetDataBits SetDefaultEncoding SetDepth SetDisplayAttributes SetDitherMode SetDrawPen SetDrawTagsDefault SetDTR SetEnv SetEventTimeout SetFileAttributes SetFileEncoding SetFillRule SetFillStyle SetFlowControl SetFont SetFontColor SetFontStyle SetFormStyle SetFPSLimit SetGradientPalette SetIconProperties SetInterval SetIOMode SetLayerAnchor SetLayerBorder SetLayerDepth SetLayerFilter SetLayerLight SetLayerName SetLayerPalette SetLayerPen SetLayerShadow SetLayerStyle SetLayerTint SetLayerTransparency SetLayerTransparentPen SetLayerVolume SetLayerZPos SetLineCap SetLineJoin SetLineWidth SetListItems SetMargins SetMaskMode SetMasterVolume SetMetaTable SetMiterLimit SetMusicVolume SetNetworkProtocol SetNetworkTimeout SetObjectData SetPalette SetPaletteDepth SetPaletteMode SetPalettePen SetPaletteTransparentPen SetPanning SetParity SetPen SetPitch SetPointer SetRTS SetScreenTitle SetShadowPen SetSpriteZPos SetStandardIconImage SetStandardPalette SetStopBits SetSubtitle SetTimeout SetTimerElapse SetTitle SetTransparentPen SetTransparentThreshold SetTrayIcon SetVarType SetVectorEngine SetVideoPosition SetVideoSize SetVideoVolume SetVolume SetWBIcon Sgn SharpenBrush Shl ShowDisplay ShowKeyboard ShowLayer ShowLayerFX ShowNotification ShowPointer ShowRinghioMessage ShowScreen ShowToast Shr Sin SolarizeBrush SolarizePalette Sort SplitStr Sqrt StartPath StartSubPath StartTimer StartsWith StopAnim StopChannel StopLayer StopModule StopMusic StopSample StopTimer StopVideo StringRequest StringToFile StripStr StrLen StrStr StrToArray Sub SwapLayers SwirlBrush SystemRequest TableItems TableToMem Tan TextExtent TextHeight TextOut TextWidth TimerElapsed TimestampToDate TintBrush TintPalette ToHostName ToIP ToNumber ToString ToUserData TransformBrush TransformLayer TranslateLayer TranslatePath TrimBrush TrimStr UndefineVirtualStringFile Undo UndoFX UnleftStr UnmidStr Unpack UnrightStr UnsetEnv UploadFile UpperStr Usage UseCarriageReturn UseFont UTCToDate Val ValidateDate ValidateStr Vibrate VWait Wait WaitAnimEnd WaitEvent WaitKeyDown WaitLeftMouse WaitMidMouse WaitPatternPosition WaitRightMouse WaitSampleEnd WaitSongPosition WaitTimer WaterRippleBrush WhileKeyDown WhileMouseDown WhileMouseOn WhileRightMouseDown Wrap WriteAnimFrame WriteBrushPixel WriteByte WriteBytes WriteChr WriteFloat WriteFunction WriteInt WriteLine WriteMem WritePen WriteRegistryKey WriteSerialData WriteShort WriteString WriteTable YieldCoroutine
" user-defined constants
syn match hwUserConstant "#\<\u\+\>"
diff --git a/runtime/syntax/make.vim b/runtime/syntax/make.vim
index 68f7ee21ea..b4573044ca 100644
--- a/runtime/syntax/make.vim
+++ b/runtime/syntax/make.vim
@@ -3,7 +3,7 @@
" Maintainer: Roland Hieber <rohieb+vim-iR0jGdkV@rohieb.name>, <https://github.com/rohieb>
" Previous Maintainer: Claudio Fleiner <claudio@fleiner.com>
" URL: https://github.com/vim/vim/blob/master/runtime/syntax/make.vim
-" Last Change: 2020 Oct 16
+" Last Change: 2022 Nov 06
" quit when a syntax file was already loaded
if exists("b:current_syntax")
@@ -45,11 +45,11 @@ syn match makeImplicit "^\.[A-Za-z0-9_./\t -]\+\s*:$"me=e-1
syn match makeImplicit "^\.[A-Za-z0-9_./\t -]\+\s*:[^=]"me=e-2
syn region makeTarget transparent matchgroup=makeTarget
- \ start="^[~A-Za-z0-9_./$()%-][A-Za-z0-9_./\t $()%-]*&\?:\?:\{1,2}[^:=]"rs=e-1
+ \ start="^[~A-Za-z0-9_./$(){}%-][A-Za-z0-9_./\t ${}()%-]*&\?:\?:\{1,2}[^:=]"rs=e-1
\ end="[^\\]$"
\ keepend contains=makeIdent,makeSpecTarget,makeNextLine,makeComment,makeDString
\ skipnl nextGroup=makeCommands
-syn match makeTarget "^[~A-Za-z0-9_./$()%*@-][A-Za-z0-9_./\t $()%*@-]*&\?::\=\s*$"
+syn match makeTarget "^[~A-Za-z0-9_./$(){}%*@-][A-Za-z0-9_./\t $(){}%*@-]*&\?::\=\s*$"
\ contains=makeIdent,makeSpecTarget,makeComment
\ skipnl nextgroup=makeCommands,makeCommandError
diff --git a/runtime/syntax/modula3.vim b/runtime/syntax/modula3.vim
index b179303799..390a1a90ff 100644
--- a/runtime/syntax/modula3.vim
+++ b/runtime/syntax/modula3.vim
@@ -2,18 +2,29 @@
" Language: Modula-3
" Maintainer: Doug Kearns <dougkearns@gmail.com>
" Previous Maintainer: Timo Pedersen <dat97tpe@ludat.lth.se>
-" Last Change: 2021 Apr 08
+" Last Change: 2022 Oct 31
if exists("b:current_syntax")
finish
endif
-" Modula-3 keywords
-syn keyword modula3Keyword ANY ARRAY AS BITS BRANDED BY CASE CONST DEFINITION
-syn keyword modula3Keyword EVAL EXIT EXCEPT EXCEPTION EXIT EXPORTS FINALLY
-syn keyword modula3Keyword FROM GENERIC IMPORT LOCK METHOD OF RAISE RAISES
-syn keyword modula3Keyword READONLY RECORD REF RETURN SET TRY TYPE TYPECASE
-syn keyword modula3Keyword UNSAFE VALUE VAR WITH
+" Whitespace errors {{{1
+if exists("modula3_space_errors")
+ if !exists("modula3_no_trail_space_error")
+ syn match modula3SpaceError display excludenl "\s\+$"
+ endif
+ if !exists("modula3_no_tab_space_error")
+ syn match modula3SpaceError display " \+\t"me=e-1
+ endif
+endif
+
+" Keywords {{{1
+syn keyword modula3Keyword ANY ARRAY AS BITS BRANDED BY CASE CONST
+syn keyword modula3Keyword DEFINITION EVAL EXIT EXCEPT EXCEPTION EXIT
+syn keyword modula3Keyword EXPORTS FINALLY FROM GENERIC IMPORT LOCK METHOD
+syn keyword modula3Keyword OF RAISE RAISES READONLY RECORD REF
+syn keyword modula3Keyword RETURN SET TRY TYPE TYPECASE UNSAFE
+syn keyword modula3Keyword VALUE VAR WITH
syn match modula3keyword "\<UNTRACED\>"
@@ -22,44 +33,73 @@ syn keyword modula3Block PROCEDURE FUNCTION MODULE INTERFACE REPEAT THEN
syn keyword modula3Block BEGIN END OBJECT METHODS OVERRIDES RECORD REVEAL
syn keyword modula3Block WHILE UNTIL DO TO IF FOR ELSIF ELSE LOOP
-" Reserved identifiers
+" Reserved identifiers {{{1
syn keyword modula3Identifier ABS ADR ADRSIZE BITSIZE BYTESIZE CEILING DEC
syn keyword modula3Identifier DISPOSE FIRST FLOAT FLOOR INC ISTYPE LAST
syn keyword modula3Identifier LOOPHOLE MAX MIN NARROW NEW NUMBER ORD ROUND
syn keyword modula3Identifier SUBARRAY TRUNC TYPECODE VAL
-" Predefined types
+" Predefined types {{{1
syn keyword modula3Type ADDRESS BOOLEAN CARDINAL CHAR EXTENDED INTEGER
syn keyword modula3Type LONGCARD LONGINT LONGREAL MUTEX NULL REAL REFANY TEXT
syn keyword modula3Type WIDECHAR
syn match modula3Type "\<\%(UNTRACED\s\+\)\=ROOT\>"
-" Operators
-syn keyword modulaOperator DIV MOD IN AND OR NOT
+" Operators {{{1
+syn keyword modula3Operator DIV MOD
+syn keyword modula3Operator IN
+syn keyword modula3Operator NOT AND OR
+" TODO: exclude = from declarations
if exists("modula3_operators")
syn match modula3Operator "\^"
- syn match modula3Operator "+\|-\|\*\|/\|&"
- " TODO: need to exclude = in procedure definitions
- syn match modula3Operator "<=\|<\|>=\|>\|:\@<!=\|#"
+ syn match modula3Operator "[-+/*]"
+ syn match modula3Operator "&"
+ syn match modula3Operator "<=\|<:\@!\|>=\|>"
+ syn match modula3Operator ":\@<!=\|#"
endif
+" Literals {{{1
+
" Booleans
syn keyword modula3Boolean TRUE FALSE
" Nil
syn keyword modula3Nil NIL
-" Integers
-syn match modula3Integer "\<\d\+L\=\>"
-syn match modula3Integer "\<\d\d\=_\x\+L\=\>"
+" Numbers {{{2
+
+" NOTE: Negated numbers are constant expressions not literals
+
+syn case ignore
+
+ " Integers
+
+ syn match modula3Integer "\<\d\+L\=\>"
-" Reals
-syn match modula3Real "\c\<\d\+\.\d\+\%([EDX][+-]\=\d\+\)\=\>"
+ if exists("modula3_number_errors")
+ syn match modula3IntegerError "\<\d\d\=_\x\+L\=\>"
+ endif
+
+ let s:digits = "0123456789ABCDEF"
+ for s:radix in range(2, 16)
+ " Nvim does not support interpolated strings yet.
+ " exe $'syn match modula3Integer "\<{s:radix}_[{s:digits[:s:radix - 1]}]\+L\=\>"'
+ exe 'syn match modula3Integer "\<' .. s:radix .. '_[' .. s:digits[:s:radix - 1] .. ']\+L\=\>"'
+ endfor
+ unlet s:digits s:radix
+
+ " Reals
+ syn match modula3Real "\<\d\+\.\d\+\%([EDX][+-]\=\d\+\)\=\>"
+
+syn case match
+
+" Strings and characters {{{2
" String escape sequences
syn match modula3Escape "\\['"ntrf]" contained display
+" TODO: limit to <= 377 (255)
syn match modula3Escape "\\\o\{3}" contained display
syn match modula3Escape "\\\\" contained display
@@ -69,13 +109,23 @@ syn match modula3Character "'\%([^']\|\\.\|\\\o\{3}\)'" contains=modula3Escape
" Strings
syn region modula3String start=+"+ end=+"+ contains=modula3Escape
-" Pragmas
+" Pragmas {{{1
+" EXTERNAL INLINE ASSERT TRACE FATAL UNUSED OBSOLETE CALLBACK EXPORTED PRAGMA NOWARN LINE LL LL.sup SPEC
+" Documented: INLINE ASSERT TRACE FATAL UNUSED OBSOLETE NOWARN
syn region modula3Pragma start="<\*" end="\*>"
-" Comments
-syn region modula3Comment start="(\*" end="\*)" contains=modula3Comment,@Spell
+" Comments {{{1
+if !exists("modula3_no_comment_fold")
+ syn region modula3Comment start="(\*" end="\*)" contains=modula3Comment,@Spell fold
+ syn region modula3LineCommentBlock start="^\s*(\*.*\*)\s*\n\%(^\s*(\*.*\*)\s*$\)\@=" end="^\s*(\*.*\*)\s*\n\%(^\s*(\*.*\*)\s*$\)\@!" contains=modula3Comment transparent fold keepend
+else
+ syn region modula3Comment start="(\*" end="\*)" contains=modula3Comment,@Spell
+endif
+
+" Syncing "{{{1
+syn sync minlines=100
-" Default highlighting
+" Default highlighting {{{1
hi def link modula3Block Statement
hi def link modula3Boolean Boolean
hi def link modula3Character Character
@@ -85,12 +135,13 @@ hi def link modula3Identifier Keyword
hi def link modula3Integer Number
hi def link modula3Keyword Statement
hi def link modula3Nil Constant
+hi def link modula3IntegerError Error
hi def link modula3Operator Operator
hi def link modula3Pragma PreProc
hi def link modula3Real Float
hi def link modula3String String
-hi def link modula3Type Type
+hi def link modula3Type Type "}}}
let b:current_syntax = "modula3"
-" vim: nowrap sw=2 sts=2 ts=8 noet:
+" vim: nowrap sw=2 sts=2 ts=8 noet fdm=marker:
diff --git a/runtime/syntax/sshconfig.vim b/runtime/syntax/sshconfig.vim
index ae3c7dd8cc..88665e5f6d 100644
--- a/runtime/syntax/sshconfig.vim
+++ b/runtime/syntax/sshconfig.vim
@@ -6,9 +6,10 @@
" Contributor: Leonard Ehrenfried <leonard.ehrenfried@web.de>
" Contributor: Karsten Hopp <karsten@redhat.com>
" Contributor: Dean, Adam Kenneth <adam.ken.dean@hpe.com>
-" Last Change: 2021 Mar 29
+" Last Change: 2022 Nov 09
" Added RemoteCommand from pull request #4809
" Included additional keywords from Martin.
+" Included PR #5753
" SSH Version: 8.5p1
"
@@ -57,12 +58,12 @@ syn match sshconfigCiphers "\<aes256-gcm@openssh\.com\>"
syn match sshconfigCiphers "\<chacha20-poly1305@openssh\.com\>"
syn keyword sshconfigMAC hmac-sha1
-syn keyword sshconfigMAC mac-sha1-96
-syn keyword sshconfigMAC mac-sha2-256
-syn keyword sshconfigMAC mac-sha2-512
-syn keyword sshconfigMAC mac-md5
-syn keyword sshconfigMAC mac-md5-96
-syn keyword sshconfigMAC mac-ripemd160
+syn keyword sshconfigMAC hmac-sha1-96
+syn keyword sshconfigMAC hmac-sha2-256
+syn keyword sshconfigMAC hmac-sha2-512
+syn keyword sshconfigMAC hmac-md5
+syn keyword sshconfigMAC hmac-md5-96
+syn keyword sshconfigMAC hmac-ripemd160
syn match sshconfigMAC "\<hmac-ripemd160@openssh\.com\>"
syn match sshconfigMAC "\<umac-64@openssh\.com\>"
syn match sshconfigMAC "\<umac-128@openssh\.com\>"
@@ -78,16 +79,24 @@ syn match sshconfigMAC "\<umac-128-etm@openssh\.com\>"
syn keyword sshconfigHostKeyAlgo ssh-ed25519
syn match sshconfigHostKeyAlgo "\<ssh-ed25519-cert-v01@openssh\.com\>"
+syn match sshconfigHostKeyAlgo "\<sk-ssh-ed25519@openssh\.com\>"
+syn match sshconfigHostKeyAlgo "\<sk-ssh-ed25519-cert-v01@openssh\.com\>"
syn keyword sshconfigHostKeyAlgo ssh-rsa
+syn keyword sshconfigHostKeyAlgo rsa-sha2-256
+syn keyword sshconfigHostKeyAlgo rsa-sha2-512
syn keyword sshconfigHostKeyAlgo ssh-dss
syn keyword sshconfigHostKeyAlgo ecdsa-sha2-nistp256
syn keyword sshconfigHostKeyAlgo ecdsa-sha2-nistp384
syn keyword sshconfigHostKeyAlgo ecdsa-sha2-nistp521
+syn match sshconfigHostKeyAlgo "\<sk-ecdsa-sha2-nistp256@openssh\.com\>"
syn match sshconfigHostKeyAlgo "\<ssh-rsa-cert-v01@openssh\.com\>"
+syn match sshconfigHostKeyAlgo "\<rsa-sha2-256-cert-v01@openssh\.com\>"
+syn match sshconfigHostKeyAlgo "\<rsa-sha2-512-cert-v01@openssh\.com\>"
syn match sshconfigHostKeyAlgo "\<ssh-dss-cert-v01@openssh\.com\>"
syn match sshconfigHostKeyAlgo "\<ecdsa-sha2-nistp256-cert-v01@openssh\.com\>"
syn match sshconfigHostKeyAlgo "\<ecdsa-sha2-nistp384-cert-v01@openssh\.com\>"
syn match sshconfigHostKeyAlgo "\<ecdsa-sha2-nistp521-cert-v01@openssh\.com\>"
+syn match sshconfigHostKeyAlgo "\<sk-ecdsa-sha2-nistp256-cert-v01@openssh\.com\>"
syn keyword sshconfigPreferredAuth hostbased publickey password gssapi-with-mic
syn keyword sshconfigPreferredAuth keyboard-interactive
diff --git a/runtime/syntax/sshdconfig.vim b/runtime/syntax/sshdconfig.vim
index 6b0d2af4d1..d8e12047e0 100644
--- a/runtime/syntax/sshdconfig.vim
+++ b/runtime/syntax/sshdconfig.vim
@@ -7,7 +7,7 @@
" Contributor: Leonard Ehrenfried <leonard.ehrenfried@web.de>
" Contributor: Karsten Hopp <karsten@redhat.com>
" Originally: 2009-07-09
-" Last Change: 2021-03-29
+" Last Change: 2022 Nov 09
" SSH Version: 8.5p1
"
@@ -59,12 +59,12 @@ syn match sshdconfigCiphers "\<aes256-gcm@openssh\.com\>"
syn match sshdconfigCiphers "\<chacha20-poly1305@openssh\.com\>"
syn keyword sshdconfigMAC hmac-sha1
-syn keyword sshdconfigMAC mac-sha1-96
-syn keyword sshdconfigMAC mac-sha2-256
-syn keyword sshdconfigMAC mac-sha2-512
-syn keyword sshdconfigMAC mac-md5
-syn keyword sshdconfigMAC mac-md5-96
-syn keyword sshdconfigMAC mac-ripemd160
+syn keyword sshdconfigMAC hmac-sha1-96
+syn keyword sshdconfigMAC hmac-sha2-256
+syn keyword sshdconfigMAC hmac-sha2-512
+syn keyword sshdconfigMAC hmac-md5
+syn keyword sshdconfigMAC hmac-md5-96
+syn keyword sshdconfigMAC hmac-ripemd160
syn match sshdconfigMAC "\<hmac-ripemd160@openssh\.com\>"
syn match sshdconfigMAC "\<umac-64@openssh\.com\>"
syn match sshdconfigMAC "\<umac-128@openssh\.com\>"
@@ -258,6 +258,8 @@ syn keyword sshdconfigKeyword Subsystem
syn keyword sshdconfigKeyword SyslogFacility
syn keyword sshdconfigKeyword TCPKeepAlive
syn keyword sshdconfigKeyword TrustedUserCAKeys
+syn keyword sshdconfigKeyword UseBlacklist
+syn keyword sshdconfigKeyword UseBlocklist
syn keyword sshdconfigKeyword UseDNS
syn keyword sshdconfigKeyword UseLogin
syn keyword sshdconfigKeyword UsePAM
diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c
index 8cd2c0f8b8..752d3868d5 100644
--- a/src/nvim/api/command.c
+++ b/src/nvim/api/command.c
@@ -884,6 +884,7 @@ static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdin
/// @param command Replacement command to execute when this user command is executed. When called
/// from Lua, the command can also be a Lua function. The function is called with a
/// single table argument that contains the following keys:
+/// - name: (string) Command name
/// - args: (string) The args passed to the command, if any |<args>|
/// - fargs: (table) The args split by unescaped whitespace (when more than one
/// argument is allowed), if any |<f-args>|
diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c
index 3b1b470629..54eb7d9b6b 100644
--- a/src/nvim/api/extmark.c
+++ b/src/nvim/api/extmark.c
@@ -721,8 +721,12 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
bool ephemeral = false;
OPTION_TO_BOOL(ephemeral, ephemeral, false);
- OPTION_TO_BOOL(decor.spell, spell, false);
- if (decor.spell) {
+ if (opts->spell.type == kObjectTypeNil) {
+ decor.spell = kNone;
+ } else {
+ bool spell = false;
+ OPTION_TO_BOOL(spell, spell, false);
+ decor.spell = spell ? kTrue : kFalse;
has_decor = true;
}
@@ -833,9 +837,8 @@ uint32_t src2ns(Integer *src_id)
}
if (*src_id < 0) {
return (((uint32_t)1) << 31) - 1;
- } else {
- return (uint32_t)(*src_id);
}
+ return (uint32_t)(*src_id);
}
/// Adds a highlight to buffer.
diff --git a/src/nvim/api/options.c b/src/nvim/api/options.c
index ec1f19cf6a..92f20fff48 100644
--- a/src/nvim/api/options.c
+++ b/src/nvim/api/options.c
@@ -487,7 +487,7 @@ static getoption_T access_option_value(char *key, long *numval, char **stringval
bool get, Error *err)
{
if (get) {
- return get_option_value(key, numval, stringval, opt_flags);
+ return get_option_value(key, numval, stringval, NULL, opt_flags);
} else {
char *errmsg;
if ((errmsg = set_option_value(key, *numval, *stringval, opt_flags))) {
diff --git a/src/nvim/api/tabpage.c b/src/nvim/api/tabpage.c
index b81fc3b7d7..31f9fab82a 100644
--- a/src/nvim/api/tabpage.c
+++ b/src/nvim/api/tabpage.c
@@ -110,15 +110,14 @@ Window nvim_tabpage_get_win(Tabpage tabpage, Error *err)
if (tab == curtab) {
return nvim_get_current_win();
- } else {
- FOR_ALL_WINDOWS_IN_TAB(wp, tab) {
- if (wp == tab->tp_curwin) {
- return wp->handle;
- }
+ }
+ FOR_ALL_WINDOWS_IN_TAB(wp, tab) {
+ if (wp == tab->tp_curwin) {
+ return wp->handle;
}
- // There should always be a current window for a tabpage
- abort();
}
+ // There should always be a current window for a tabpage
+ abort();
}
/// Gets the tabpage number
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index beb48b8d7d..d3f8c768a0 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -2223,7 +2223,8 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
buf,
sizeof(buf),
str.data,
- false,
+ NULL,
+ 0,
fillchar,
maxwidth,
hltab_ptr,
diff --git a/src/nvim/api/vimscript.c b/src/nvim/api/vimscript.c
index 71209c9ab6..dccc2d42d8 100644
--- a/src/nvim/api/vimscript.c
+++ b/src/nvim/api/vimscript.c
@@ -532,7 +532,7 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, E
kv_drop(ast_conv_stack, 1);
} else {
if (cur_item.ret_node_p->type == kObjectTypeNil) {
- size_t items_size = (size_t)(3 // "type", "start" and "len"
+ size_t items_size = (size_t)(3 // "type", "start" and "len" // NOLINT(bugprone-misplaced-widening-cast)
+ (node->children != NULL) // "children"
+ (node->type == kExprNodeOption
|| node->type == kExprNodePlainIdentifier) // "scope"
diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c
index 9f15e5a85b..648048e970 100644
--- a/src/nvim/api/win_config.c
+++ b/src/nvim/api/win_config.c
@@ -139,7 +139,7 @@
/// [ {"+", "MyCorner"}, {"x", "MyBorder"} ].
/// - title: Title (optional) in window border, String or list.
/// List is [text, highlight] tuples. if is string the default
-/// highlight group is `FloatBorderTitle`.
+/// highlight group is `FloatTitle`.
/// - title_pos: Title position must set with title option.
/// value can be of `left` `center` `right` default is left.
/// - noautocmd: If true then no buffer-related autocommand events such as
@@ -364,7 +364,7 @@ static void parse_border_title(Object title, Object title_pos, FloatConfig *fcon
fconfig->title = false;
return;
}
- int hl_id = syn_check_group(S_LEN("FloatBorderTitle"));
+ int hl_id = syn_check_group(S_LEN("FloatTitle"));
kv_push(fconfig->title_chunks, ((VirtTextChunk){ .text = xstrdup(title.data.string.data),
.hl_id = hl_id }));
fconfig->title_width = (int)mb_string2cells(title.data.string.data);
diff --git a/src/nvim/arabic.c b/src/nvim/arabic.c
index b57019286f..ac6269493d 100644
--- a/src/nvim/arabic.c
+++ b/src/nvim/arabic.c
@@ -27,70 +27,72 @@
#include "nvim/vim.h"
// Unicode values for Arabic characters.
-#define a_HAMZA 0x0621
-#define a_ALEF_MADDA 0x0622
-#define a_ALEF_HAMZA_ABOVE 0x0623
-#define a_WAW_HAMZA 0x0624
-#define a_ALEF_HAMZA_BELOW 0x0625
-#define a_YEH_HAMZA 0x0626
-#define a_ALEF 0x0627
-#define a_BEH 0x0628
-#define a_TEH_MARBUTA 0x0629
-#define a_TEH 0x062a
-#define a_THEH 0x062b
-#define a_JEEM 0x062c
-#define a_HAH 0x062d
-#define a_KHAH 0x062e
-#define a_DAL 0x062f
-#define a_THAL 0x0630
-#define a_REH 0x0631
-#define a_ZAIN 0x0632
-#define a_SEEN 0x0633
-#define a_SHEEN 0x0634
-#define a_SAD 0x0635
-#define a_DAD 0x0636
-#define a_TAH 0x0637
-#define a_ZAH 0x0638
-#define a_AIN 0x0639
-#define a_GHAIN 0x063a
-#define a_TATWEEL 0x0640
-#define a_FEH 0x0641
-#define a_QAF 0x0642
-#define a_KAF 0x0643
-#define a_LAM 0x0644
-#define a_MEEM 0x0645
-#define a_NOON 0x0646
-#define a_HEH 0x0647
-#define a_WAW 0x0648
-#define a_ALEF_MAKSURA 0x0649
-#define a_YEH 0x064a
-#define a_FATHATAN 0x064b
-#define a_DAMMATAN 0x064c
-#define a_KASRATAN 0x064d
-#define a_FATHA 0x064e
-#define a_DAMMA 0x064f
-#define a_KASRA 0x0650
-#define a_SHADDA 0x0651
-#define a_SUKUN 0x0652
-#define a_MADDA_ABOVE 0x0653
-#define a_HAMZA_ABOVE 0x0654
-#define a_HAMZA_BELOW 0x0655
-
-#define a_PEH 0x067e
-#define a_TCHEH 0x0686
-#define a_JEH 0x0698
-#define a_FKAF 0x06a9
-#define a_GAF 0x06af
-#define a_FYEH 0x06cc
-
-#define a_s_LAM_ALEF_MADDA_ABOVE 0xfef5
-#define a_f_LAM_ALEF_MADDA_ABOVE 0xfef6
-#define a_s_LAM_ALEF_HAMZA_ABOVE 0xfef7
-#define a_f_LAM_ALEF_HAMZA_ABOVE 0xfef8
-#define a_s_LAM_ALEF_HAMZA_BELOW 0xfef9
-#define a_f_LAM_ALEF_HAMZA_BELOW 0xfefa
-#define a_s_LAM_ALEF 0xfefb
-#define a_f_LAM_ALEF 0xfefc
+enum {
+ a_HAMZA = 0x0621,
+ a_ALEF_MADDA = 0x0622,
+ a_ALEF_HAMZA_ABOVE = 0x0623,
+ a_WAW_HAMZA = 0x0624,
+ a_ALEF_HAMZA_BELOW = 0x0625,
+ a_YEH_HAMZA = 0x0626,
+ a_ALEF = 0x0627,
+ a_BEH = 0x0628,
+ a_TEH_MARBUTA = 0x0629,
+ a_TEH = 0x062a,
+ a_THEH = 0x062b,
+ a_JEEM = 0x062c,
+ a_HAH = 0x062d,
+ a_KHAH = 0x062e,
+ a_DAL = 0x062f,
+ a_THAL = 0x0630,
+ a_REH = 0x0631,
+ a_ZAIN = 0x0632,
+ a_SEEN = 0x0633,
+ a_SHEEN = 0x0634,
+ a_SAD = 0x0635,
+ a_DAD = 0x0636,
+ a_TAH = 0x0637,
+ a_ZAH = 0x0638,
+ a_AIN = 0x0639,
+ a_GHAIN = 0x063a,
+ a_TATWEEL = 0x0640,
+ a_FEH = 0x0641,
+ a_QAF = 0x0642,
+ a_KAF = 0x0643,
+ a_LAM = 0x0644,
+ a_MEEM = 0x0645,
+ a_NOON = 0x0646,
+ a_HEH = 0x0647,
+ a_WAW = 0x0648,
+ a_ALEF_MAKSURA = 0x0649,
+ a_YEH = 0x064a,
+ a_FATHATAN = 0x064b,
+ a_DAMMATAN = 0x064c,
+ a_KASRATAN = 0x064d,
+ a_FATHA = 0x064e,
+ a_DAMMA = 0x064f,
+ a_KASRA = 0x0650,
+ a_SHADDA = 0x0651,
+ a_SUKUN = 0x0652,
+ a_MADDA_ABOVE = 0x0653,
+ a_HAMZA_ABOVE = 0x0654,
+ a_HAMZA_BELOW = 0x0655,
+
+ a_PEH = 0x067e,
+ a_TCHEH = 0x0686,
+ a_JEH = 0x0698,
+ a_FKAF = 0x06a9,
+ a_GAF = 0x06af,
+ a_FYEH = 0x06cc,
+
+ a_s_LAM_ALEF_MADDA_ABOVE = 0xfef5,
+ a_f_LAM_ALEF_MADDA_ABOVE = 0xfef6,
+ a_s_LAM_ALEF_HAMZA_ABOVE = 0xfef7,
+ a_f_LAM_ALEF_HAMZA_ABOVE = 0xfef8,
+ a_s_LAM_ALEF_HAMZA_BELOW = 0xfef9,
+ a_f_LAM_ALEF_HAMZA_BELOW = 0xfefa,
+ a_s_LAM_ALEF = 0xfefb,
+ a_f_LAM_ALEF = 0xfefc,
+};
static struct achar {
unsigned c;
diff --git a/src/nvim/arglist.c b/src/nvim/arglist.c
index c7af1a71be..bd49bc8a36 100644
--- a/src/nvim/arglist.c
+++ b/src/nvim/arglist.c
@@ -693,8 +693,17 @@ void ex_next(exarg_T *eap)
void ex_argdedupe(exarg_T *eap FUNC_ATTR_UNUSED)
{
for (int i = 0; i < ARGCOUNT; i++) {
+ // Expand each argument to a full path to catch different paths leading
+ // to the same file.
+ char *firstFullname = FullName_save(ARGLIST[i].ae_fname, false);
+
for (int j = i + 1; j < ARGCOUNT; j++) {
- if (path_fnamecmp(ARGLIST[i].ae_fname, ARGLIST[j].ae_fname) == 0) {
+ char *secondFullname = FullName_save(ARGLIST[j].ae_fname, false);
+ bool areNamesDuplicate = path_fnamecmp(firstFullname, secondFullname) == 0;
+ xfree(secondFullname);
+
+ if (areNamesDuplicate) {
+ // remove one duplicate argument
xfree(ARGLIST[j].ae_fname);
memmove(ARGLIST + j, ARGLIST + j + 1,
(size_t)(ARGCOUNT - j - 1) * sizeof(aentry_T));
@@ -709,6 +718,8 @@ void ex_argdedupe(exarg_T *eap FUNC_ATTR_UNUSED)
j--;
}
}
+
+ xfree(firstFullname);
}
}
diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua
index 93a870fe04..65c22c922a 100644
--- a/src/nvim/auevents.lua
+++ b/src/nvim/auevents.lua
@@ -108,6 +108,7 @@ return {
'TextChanged', -- text was modified
'TextChangedI', -- text was modified in Insert mode(no popup)
'TextChangedP', -- text was modified in Insert mode(popup)
+ 'TextChangedT', -- text was modified in Terminal mode
'TextYankPost', -- after a yank or delete was done (y, d, c)
'UIEnter', -- after UI attaches
'UILeave', -- after UI detaches
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
index 5b5ea43d86..9845e6be13 100644
--- a/src/nvim/autocmd.c
+++ b/src/nvim/autocmd.c
@@ -779,7 +779,7 @@ void au_event_restore(char *old_ei)
// :autocmd * *.c show all autocommands for *.c files.
//
// Mostly a {group} argument can optionally appear before <event>.
-void do_autocmd(char *arg_in, int forceit)
+void do_autocmd(exarg_T *eap, char *arg_in, int forceit)
{
char *arg = arg_in;
char *envpat = NULL;
@@ -790,6 +790,7 @@ void do_autocmd(char *arg_in, int forceit)
int group;
if (*arg == '|') {
+ eap->nextcmd = arg + 1;
arg = "";
group = AUGROUP_ALL; // no argument, use all groups
} else {
@@ -806,6 +807,7 @@ void do_autocmd(char *arg_in, int forceit)
pat = skipwhite(pat);
if (*pat == '|') {
+ eap->nextcmd = pat + 1;
pat = "";
cmd = "";
} else {
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 2c87677925..78b058ea9a 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -1842,7 +1842,7 @@ buf_T *buflist_new(char *ffname_arg, char *sfname_arg, linenr_T lnum, int flags)
pmap_put(handle_T)(&buffer_handles, buf->b_fnum, buf);
if (top_file_num < 0) { // wrap around (may cause duplicates)
emsg(_("W14: Warning: List of file names overflow"));
- if (emsg_silent == 0) {
+ if (emsg_silent == 0 && !in_assert_fails) {
ui_flush();
os_delay(3001L, true); // make sure it is noticed
}
@@ -3203,17 +3203,9 @@ void maketitle(void)
if (*p_titlestring != NUL) {
if (stl_syntax & STL_IN_TITLE) {
- int use_sandbox = false;
- const int called_emsg_before = called_emsg;
-
- use_sandbox = was_set_insecurely(curwin, "titlestring", 0);
- build_stl_str_hl(curwin, buf, sizeof(buf),
- p_titlestring, use_sandbox,
- 0, maxlen, NULL, NULL);
+ build_stl_str_hl(curwin, buf, sizeof(buf), p_titlestring,
+ "titlestring", 0, 0, maxlen, NULL, NULL);
title_str = buf;
- if (called_emsg > called_emsg_before) {
- set_string_option_direct("titlestring", -1, "", OPT_FREE, SID_ERROR);
- }
} else {
title_str = p_titlestring;
}
@@ -3317,16 +3309,8 @@ void maketitle(void)
icon_str = buf;
if (*p_iconstring != NUL) {
if (stl_syntax & STL_IN_ICON) {
- int use_sandbox = false;
- const int called_emsg_before = called_emsg;
-
- use_sandbox = was_set_insecurely(curwin, "iconstring", 0);
- build_stl_str_hl(curwin, icon_str, sizeof(buf),
- p_iconstring, use_sandbox,
- 0, 0, NULL, NULL);
- if (called_emsg > called_emsg_before) {
- set_string_option_direct("iconstring", -1, "", OPT_FREE, SID_ERROR);
- }
+ build_stl_str_hl(curwin, icon_str, sizeof(buf), p_iconstring,
+ "iconstring", 0, 0, 0, NULL, NULL);
} else {
icon_str = p_iconstring;
}
diff --git a/src/nvim/buffer.h b/src/nvim/buffer.h
index 7380bb045a..84c402d782 100644
--- a/src/nvim/buffer.h
+++ b/src/nvim/buffer.h
@@ -4,7 +4,6 @@
#include "nvim/eval/typval.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/func_attr.h"
-#include "nvim/grid_defs.h" // for StlClickRecord
#include "nvim/macros.h"
#include "nvim/memline.h"
#include "nvim/pos.h" // for linenr_T
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 6448c6b6f6..96cf352067 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -6,8 +6,6 @@
// for FILE
#include <stdio.h>
-#include "grid_defs.h"
-
typedef struct file_buffer buf_T; // Forward declaration
// Reference to a buffer that stores the value of buf_free_count.
@@ -46,6 +44,8 @@ typedef struct {
#include "nvim/marktree.h"
// for float window title
#include "nvim/extmark_defs.h"
+// for click definitions
+#include "nvim/statusline_defs.h"
#define GETFILE_SUCCESS(x) ((x) <= 0)
#define MODIFIABLE(buf) (buf->b_p_ma)
diff --git a/src/nvim/change.c b/src/nvim/change.c
index c6df98651d..a62880dfc1 100644
--- a/src/nvim/change.c
+++ b/src/nvim/change.c
@@ -107,7 +107,7 @@ void changed(void)
// Wait two seconds, to make sure the user reads this unexpected
// message. Since we could be anywhere, call wait_return() now,
// and don't let the emsg() set msg_scroll.
- if (need_wait_return && emsg_silent == 0) {
+ if (need_wait_return && emsg_silent == 0 && !in_assert_fails) {
ui_flush();
os_delay(2002L, true);
wait_return(true);
diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c
index 480f3aa18c..ef742525da 100644
--- a/src/nvim/cmdexpand.c
+++ b/src/nvim/cmdexpand.c
@@ -20,6 +20,7 @@
#include "nvim/ex_getln.h"
#include "nvim/garray.h"
#include "nvim/getchar.h"
+#include "nvim/grid.h"
#include "nvim/help.h"
#include "nvim/highlight_group.h"
#include "nvim/locale.h"
@@ -34,6 +35,7 @@
#include "nvim/screen.h"
#include "nvim/search.h"
#include "nvim/sign.h"
+#include "nvim/statusline.h"
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/tag.h"
@@ -275,6 +277,236 @@ void cmdline_pum_cleanup(CmdlineInfo *cclp)
wildmenu_cleanup(cclp);
}
+/// Return the number of characters that should be skipped in the wildmenu
+/// These are backslashes used for escaping. Do show backslashes in help tags.
+static int skip_wildmenu_char(expand_T *xp, char_u *s)
+{
+ if ((rem_backslash((char *)s) && xp->xp_context != EXPAND_HELP)
+ || ((xp->xp_context == EXPAND_MENUS || xp->xp_context == EXPAND_MENUNAMES)
+ && (s[0] == '\t' || (s[0] == '\\' && s[1] != NUL)))) {
+#ifndef BACKSLASH_IN_FILENAME
+ // TODO(bfredl): Why in the actual fuck are we special casing the
+ // shell variety deep in the redraw logic? Shell special snowflakiness
+ // should already be eliminated multiple layers before reaching the
+ // screen infracstructure.
+ if (xp->xp_shell && csh_like_shell() && s[1] == '\\' && s[2] == '!') {
+ return 2;
+ }
+#endif
+ return 1;
+ }
+ return 0;
+}
+
+/// Get the length of an item as it will be shown in the status line.
+static int wildmenu_match_len(expand_T *xp, char_u *s)
+{
+ int len = 0;
+
+ int emenu = (xp->xp_context == EXPAND_MENUS
+ || xp->xp_context == EXPAND_MENUNAMES);
+
+ // Check for menu separators - replace with '|'.
+ if (emenu && menu_is_separator((char *)s)) {
+ return 1;
+ }
+
+ while (*s != NUL) {
+ s += skip_wildmenu_char(xp, s);
+ len += ptr2cells((char *)s);
+ MB_PTR_ADV(s);
+ }
+
+ return len;
+}
+
+/// Show wildchar matches in the status line.
+/// Show at least the "match" item.
+/// We start at item "first_match" in the list and show all matches that fit.
+///
+/// If inversion is possible we use it. Else '=' characters are used.
+///
+/// @param matches list of matches
+static void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int match, int showtail)
+{
+#define L_MATCH(m) (showtail ? showmatches_gettail(matches[m], false) : matches[m])
+ int row;
+ char_u *buf;
+ int len;
+ int clen; // length in screen cells
+ int fillchar;
+ int attr;
+ int i;
+ bool highlight = true;
+ char_u *selstart = NULL;
+ int selstart_col = 0;
+ char_u *selend = NULL;
+ static int first_match = 0;
+ bool add_left = false;
+ char_u *s;
+ int emenu;
+ int l;
+
+ if (matches == NULL) { // interrupted completion?
+ return;
+ }
+
+ buf = xmalloc((size_t)Columns * MB_MAXBYTES + 1);
+
+ if (match == -1) { // don't show match but original text
+ match = 0;
+ highlight = false;
+ }
+ // count 1 for the ending ">"
+ clen = wildmenu_match_len(xp, (char_u *)L_MATCH(match)) + 3;
+ if (match == 0) {
+ first_match = 0;
+ } else if (match < first_match) {
+ // jumping left, as far as we can go
+ first_match = match;
+ add_left = true;
+ } else {
+ // check if match fits on the screen
+ for (i = first_match; i < match; i++) {
+ clen += wildmenu_match_len(xp, (char_u *)L_MATCH(i)) + 2;
+ }
+ if (first_match > 0) {
+ clen += 2;
+ }
+ // jumping right, put match at the left
+ if ((long)clen > Columns) {
+ first_match = match;
+ // if showing the last match, we can add some on the left
+ clen = 2;
+ for (i = match; i < num_matches; i++) {
+ clen += wildmenu_match_len(xp, (char_u *)L_MATCH(i)) + 2;
+ if ((long)clen >= Columns) {
+ break;
+ }
+ }
+ if (i == num_matches) {
+ add_left = true;
+ }
+ }
+ }
+ if (add_left) {
+ while (first_match > 0) {
+ clen += wildmenu_match_len(xp, (char_u *)L_MATCH(first_match - 1)) + 2;
+ if ((long)clen >= Columns) {
+ break;
+ }
+ first_match--;
+ }
+ }
+
+ fillchar = fillchar_status(&attr, curwin);
+
+ if (first_match == 0) {
+ *buf = NUL;
+ len = 0;
+ } else {
+ STRCPY(buf, "< ");
+ len = 2;
+ }
+ clen = len;
+
+ i = first_match;
+ while (clen + wildmenu_match_len(xp, (char_u *)L_MATCH(i)) + 2 < Columns) {
+ if (i == match) {
+ selstart = buf + len;
+ selstart_col = clen;
+ }
+
+ s = (char_u *)L_MATCH(i);
+ // Check for menu separators - replace with '|'
+ emenu = (xp->xp_context == EXPAND_MENUS
+ || xp->xp_context == EXPAND_MENUNAMES);
+ if (emenu && menu_is_separator((char *)s)) {
+ STRCPY(buf + len, transchar('|'));
+ l = (int)STRLEN(buf + len);
+ len += l;
+ clen += l;
+ } else {
+ for (; *s != NUL; s++) {
+ s += skip_wildmenu_char(xp, s);
+ clen += ptr2cells((char *)s);
+ if ((l = utfc_ptr2len((char *)s)) > 1) {
+ STRNCPY(buf + len, s, l); // NOLINT(runtime/printf)
+ s += l - 1;
+ len += l;
+ } else {
+ STRCPY(buf + len, transchar_byte(*s));
+ len += (int)STRLEN(buf + len);
+ }
+ }
+ }
+ if (i == match) {
+ selend = buf + len;
+ }
+
+ *(buf + len++) = ' ';
+ *(buf + len++) = ' ';
+ clen += 2;
+ if (++i == num_matches) {
+ break;
+ }
+ }
+
+ if (i != num_matches) {
+ *(buf + len++) = '>';
+ clen++;
+ }
+
+ buf[len] = NUL;
+
+ row = cmdline_row - 1;
+ if (row >= 0) {
+ if (wild_menu_showing == 0 || wild_menu_showing == WM_LIST) {
+ if (msg_scrolled > 0) {
+ // Put the wildmenu just above the command line. If there is
+ // no room, scroll the screen one line up.
+ if (cmdline_row == Rows - 1) {
+ msg_scroll_up(false, false);
+ msg_scrolled++;
+ } else {
+ cmdline_row++;
+ row++;
+ }
+ wild_menu_showing = WM_SCROLLED;
+ } else {
+ // Create status line if needed by setting 'laststatus' to 2.
+ // Set 'winminheight' to zero to avoid that the window is
+ // resized.
+ if (lastwin->w_status_height == 0 && global_stl_height() == 0) {
+ save_p_ls = (int)p_ls;
+ save_p_wmh = (int)p_wmh;
+ p_ls = 2;
+ p_wmh = 0;
+ last_status(false);
+ }
+ wild_menu_showing = WM_SHOWN;
+ }
+ }
+
+ // Tricky: wildmenu can be drawn either over a status line, or at empty
+ // scrolled space in the message output
+ ScreenGrid *grid = (wild_menu_showing == WM_SCROLLED)
+ ? &msg_grid_adj : &default_grid;
+
+ grid_puts(grid, (char *)buf, row, 0, attr);
+ if (selstart != NULL && highlight) {
+ *selend = NUL;
+ grid_puts(grid, (char *)selstart, row, selstart_col, HL_ATTR(HLF_WM));
+ }
+
+ grid_fill(grid, row, row + 1, clen, Columns,
+ fillchar, fillchar, attr);
+ }
+
+ win_redraw_last_status(topframe);
+ xfree(buf);
+}
+
/// Get the next or prev cmdline completion match. The index of the match is set
/// in "p_findex"
static char *get_next_or_prev_match(int mode, expand_T *xp, int *p_findex, char *orig_save)
@@ -563,7 +795,8 @@ int showmatches(expand_T *xp, int wildmenu)
{
CmdlineInfo *const ccline = get_cmdline_info();
#define L_SHOWFILE(m) (showtail \
- ? sm_gettail(files_found[m], false) : files_found[m])
+ ? showmatches_gettail(files_found[m], false) \
+ : files_found[m])
int num_files;
char **files_found;
int i, j, k;
@@ -606,7 +839,7 @@ int showmatches(expand_T *xp, int wildmenu)
.pum_kind = NULL,
};
}
- char *endpos = (showtail ? sm_gettail(xp->xp_pattern, true) : xp->xp_pattern);
+ char *endpos = showtail ? showmatches_gettail(xp->xp_pattern, true) : xp->xp_pattern;
if (ui_has(kUICmdline)) {
compl_startcol = (int)(endpos - ccline->cmdbuff);
} else {
@@ -739,9 +972,9 @@ int showmatches(expand_T *xp, int wildmenu)
return EXPAND_OK;
}
-/// Private path_tail for showmatches() (and redraw_wildmenu()):
-/// Find tail of file name path, but ignore trailing "/".
-char *sm_gettail(char *s, bool eager)
+/// path_tail() version for showmatches() and redraw_wildmenu():
+/// Return the tail of file name path "s", ignoring a trailing "/".
+static char *showmatches_gettail(char *s, bool eager)
{
char_u *p;
char_u *t = (char_u *)s;
diff --git a/src/nvim/context.c b/src/nvim/context.c
index 34692cdf64..c765b95733 100644
--- a/src/nvim/context.c
+++ b/src/nvim/context.c
@@ -131,7 +131,7 @@ bool ctx_restore(Context *ctx, const int flags)
}
char *op_shada;
- get_option_value("shada", NULL, &op_shada, OPT_GLOBAL);
+ get_option_value("shada", NULL, &op_shada, NULL, OPT_GLOBAL);
set_option_value("shada", 0L, "!,'100,%", OPT_GLOBAL);
if (flags & kCtxRegs) {
diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c
index 5a1708a57c..230d96a15f 100644
--- a/src/nvim/decoration.c
+++ b/src/nvim/decoration.c
@@ -69,7 +69,11 @@ void bufhl_add_hl_pos_offset(buf_T *buf, int src_id, int hl_id, lpos_T pos_start
void decor_redraw(buf_T *buf, int row1, int row2, Decoration *decor)
{
if (row2 >= row1) {
- if (!decor || decor->hl_id || decor_has_sign(decor) || decor->conceal || decor->spell) {
+ if (!decor
+ || decor->hl_id
+ || decor_has_sign(decor)
+ || decor->conceal
+ || decor->spell != kNone) {
redraw_buf_range_later(buf, row1 + 1, row2 + 1);
}
}
@@ -169,13 +173,12 @@ Decoration get_decor(mtkey_t mark)
{
if (mark.decor_full) {
return *mark.decor_full;
- } else {
- Decoration fake = DECORATION_INIT;
- fake.hl_id = mark.hl_id;
- fake.priority = mark.priority;
- fake.hl_eol = (mark.flags & MT_FLAG_HL_EOL);
- return fake;
}
+ Decoration fake = DECORATION_INIT;
+ fake.hl_id = mark.hl_id;
+ fake.priority = mark.priority;
+ fake.hl_eol = (mark.flags & MT_FLAG_HL_EOL);
+ return fake;
}
/// @return true if decor has a virtual position (virtual text or ui_watched)
@@ -310,7 +313,7 @@ next_mark:
bool conceal = 0;
int conceal_char = 0;
int conceal_attr = 0;
- bool spell = false;
+ TriState spell = kNone;
for (size_t i = 0; i < kv_size(state->active); i++) {
DecorRange item = kv_A(state->active, i);
@@ -344,8 +347,8 @@ next_mark:
conceal_attr = item.attr_id;
}
}
- if (active && item.decor.spell) {
- spell = true;
+ if (active && item.decor.spell != kNone) {
+ spell = item.decor.spell;
}
if ((item.start_row == state->row && item.start_col <= col)
&& decor_virt_pos(item.decor)
diff --git a/src/nvim/decoration.h b/src/nvim/decoration.h
index 9ba621d7a4..8f016c103b 100644
--- a/src/nvim/decoration.h
+++ b/src/nvim/decoration.h
@@ -45,7 +45,7 @@ struct Decoration {
bool hl_eol;
bool virt_lines_above;
bool conceal;
- bool spell;
+ TriState spell;
// TODO(bfredl): style, etc
DecorPriority priority;
int col; // fixed col value, like win_col
@@ -61,7 +61,7 @@ struct Decoration {
bool ui_watched; // watched for win_extmark
};
#define DECORATION_INIT { KV_INITIAL_VALUE, KV_INITIAL_VALUE, 0, kVTEndOfLine, \
- kHlModeUnknown, false, false, false, false, false, \
+ kHlModeUnknown, false, false, false, false, kNone, \
DECOR_PRIORITY_BASE, 0, 0, NULL, 0, 0, 0, 0, 0, false }
typedef struct {
@@ -91,7 +91,7 @@ typedef struct {
int conceal_char;
int conceal_attr;
- bool spell;
+ TriState spell;
} DecorState;
EXTERN DecorState decor_state INIT(= { 0 });
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index 503e546562..b20d0976e4 100644
--- a/src/nvim/diff.c
+++ b/src/nvim/diff.c
@@ -1133,37 +1133,36 @@ static int diff_file(diffio_T *dio)
// Use xdiff for generating the diff.
if (dio->dio_internal) {
return diff_file_internal(dio);
- } else {
- const size_t len = (strlen(tmp_orig) + strlen(tmp_new) + strlen(tmp_diff)
- + strlen(p_srr) + 27);
- char *const cmd = xmalloc(len);
-
- // We don't want $DIFF_OPTIONS to get in the way.
- if (os_getenv("DIFF_OPTIONS")) {
- os_unsetenv("DIFF_OPTIONS");
- }
-
- // Build the diff command and execute it. Always use -a, binary
- // differences are of no use. Ignore errors, diff returns
- // non-zero when differences have been found.
- vim_snprintf(cmd, len, "diff %s%s%s%s%s%s%s%s %s",
- diff_a_works == kFalse ? "" : "-a ",
- "",
- (diff_flags & DIFF_IWHITE) ? "-b " : "",
- (diff_flags & DIFF_IWHITEALL) ? "-w " : "",
- (diff_flags & DIFF_IWHITEEOL) ? "-Z " : "",
- (diff_flags & DIFF_IBLANK) ? "-B " : "",
- (diff_flags & DIFF_ICASE) ? "-i " : "",
- tmp_orig, tmp_new);
- append_redir(cmd, len, p_srr, tmp_diff);
- block_autocmds(); // Avoid ShellCmdPost stuff
- (void)call_shell((char_u *)cmd,
- kShellOptFilter | kShellOptSilent | kShellOptDoOut,
- NULL);
- unblock_autocmds();
- xfree(cmd);
- return OK;
}
+ const size_t len = (strlen(tmp_orig) + strlen(tmp_new) + strlen(tmp_diff)
+ + strlen(p_srr) + 27);
+ char *const cmd = xmalloc(len);
+
+ // We don't want $DIFF_OPTIONS to get in the way.
+ if (os_getenv("DIFF_OPTIONS")) {
+ os_unsetenv("DIFF_OPTIONS");
+ }
+
+ // Build the diff command and execute it. Always use -a, binary
+ // differences are of no use. Ignore errors, diff returns
+ // non-zero when differences have been found.
+ vim_snprintf(cmd, len, "diff %s%s%s%s%s%s%s%s %s",
+ diff_a_works == kFalse ? "" : "-a ",
+ "",
+ (diff_flags & DIFF_IWHITE) ? "-b " : "",
+ (diff_flags & DIFF_IWHITEALL) ? "-w " : "",
+ (diff_flags & DIFF_IWHITEEOL) ? "-Z " : "",
+ (diff_flags & DIFF_IBLANK) ? "-B " : "",
+ (diff_flags & DIFF_ICASE) ? "-i " : "",
+ tmp_orig, tmp_new);
+ append_redir(cmd, len, p_srr, tmp_diff);
+ block_autocmds(); // Avoid ShellCmdPost stuff
+ (void)call_shell((char_u *)cmd,
+ kShellOptFilter | kShellOptSilent | kShellOptDoOut,
+ NULL);
+ unblock_autocmds();
+ xfree(cmd);
+ return OK;
}
/// Create a new version of a file from the current buffer and a diff file.
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c
index cb7d85a467..6d42b91507 100644
--- a/src/nvim/drawline.c
+++ b/src/nvim/drawline.c
@@ -33,6 +33,7 @@
#include "nvim/spell.h"
#include "nvim/state.h"
#include "nvim/syntax.h"
+#include "nvim/types.h"
#include "nvim/undo.h"
#include "nvim/window.h"
@@ -1722,9 +1723,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
decor_conceal = 2; // really??
}
- if (decor_state.spell) {
- can_spell = true;
- }
+ can_spell = TRISTATE_TO_BOOL(decor_state.spell, can_spell);
}
// Check spelling (unless at the end of the line).
diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c
index 30abcd1a31..fe2c9c3801 100644
--- a/src/nvim/drawscreen.c
+++ b/src/nvim/drawscreen.c
@@ -165,14 +165,10 @@ bool default_grid_alloc(void)
// size is wrong.
grid_alloc(&default_grid, Rows, Columns, true, true);
- StlClickDefinition *new_tab_page_click_defs =
- xcalloc((size_t)Columns, sizeof(*new_tab_page_click_defs));
stl_clear_click_defs(tab_page_click_defs, tab_page_click_defs_size);
- xfree(tab_page_click_defs);
-
- tab_page_click_defs = new_tab_page_click_defs;
- tab_page_click_defs_size = Columns;
+ tab_page_click_defs = stl_alloc_click_defs(tab_page_click_defs, Columns,
+ &tab_page_click_defs_size);
default_grid.comp_height = Rows;
default_grid.comp_width = Columns;
@@ -455,6 +451,7 @@ int update_screen(void)
}
msg_scrolled = 0;
msg_scrolled_at_flush = 0;
+ msg_grid_scroll_discount = 0;
need_wait_return = false;
}
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index c99449e0f3..4540ddf4fe 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -87,10 +87,12 @@ typedef struct insert_state {
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "edit.c.generated.h"
#endif
-#define BACKSPACE_CHAR 1
-#define BACKSPACE_WORD 2
-#define BACKSPACE_WORD_NOT_SPACE 3
-#define BACKSPACE_LINE 4
+enum {
+ BACKSPACE_CHAR = 1,
+ BACKSPACE_WORD = 2,
+ BACKSPACE_WORD_NOT_SPACE = 3,
+ BACKSPACE_LINE = 4,
+};
/// Set when doing something for completion that may call edit() recursively,
/// which is not allowed.
@@ -1227,9 +1229,8 @@ bool edit(int cmdchar, bool startln, long count)
restart_edit = 'i';
force_restart_edit = true;
return false;
- } else {
- return terminal_enter();
}
+ return terminal_enter();
}
// Don't allow inserting in the sandbox.
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index c578d9fd39..f5f8840350 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -30,6 +30,7 @@
#include "nvim/ex_session.h"
#include "nvim/getchar.h"
#include "nvim/highlight_group.h"
+#include "nvim/insexpand.h"
#include "nvim/locale.h"
#include "nvim/lua/executor.h"
#include "nvim/mark.h"
@@ -49,6 +50,7 @@
#include "nvim/search.h"
#include "nvim/sign.h"
#include "nvim/syntax.h"
+#include "nvim/tag.h"
#include "nvim/ui.h"
#include "nvim/ui_compositor.h"
#include "nvim/undo.h"
@@ -1925,11 +1927,10 @@ bool next_for_item(void *fi_void, char *arg)
listitem_T *item = fi->fi_lw.lw_item;
if (item == NULL) {
return false;
- } else {
- fi->fi_lw.lw_item = TV_LIST_ITEM_NEXT(fi->fi_list, item);
- return (ex_let_vars(arg, TV_LIST_ITEM_TV(item), true,
- fi->fi_semicolon, fi->fi_varcount, false, NULL) == OK);
}
+ fi->fi_lw.lw_item = TV_LIST_ITEM_NEXT(fi->fi_list, item);
+ return (ex_let_vars(arg, TV_LIST_ITEM_TV(item), true,
+ fi->fi_semicolon, fi->fi_varcount, false, NULL) == OK);
}
// TODO(ZyX-I): move to eval/ex_cmds
@@ -3689,10 +3690,10 @@ static int eval_index(char **arg, typval_T *rettv, int evaluate, int verbose)
int get_option_tv(const char **const arg, typval_T *const rettv, const bool evaluate)
FUNC_ATTR_NONNULL_ARG(1)
{
- int opt_flags;
+ int scope;
// Isolate the option name and find its value.
- char *option_end = (char *)find_option_end(arg, &opt_flags);
+ char *option_end = (char *)find_option_end(arg, &scope);
if (option_end == NULL) {
if (rettv != NULL) {
semsg(_("E112: Option name missing: %s"), *arg);
@@ -3712,7 +3713,7 @@ int get_option_tv(const char **const arg, typval_T *const rettv, const bool eval
char c = *option_end;
*option_end = NUL;
getoption_T opt_type = get_option_value(*arg, &numval,
- rettv == NULL ? NULL : &stringval, opt_flags);
+ rettv == NULL ? NULL : &stringval, NULL, scope);
if (opt_type == gov_unknown) {
if (rettv != NULL) {
@@ -4168,10 +4169,23 @@ bool garbage_collect(bool testing)
ABORTING(set_ref_dict)(buf->additional_data, copyID);
// buffer callback functions
- set_ref_in_callback(&buf->b_prompt_callback, copyID, NULL, NULL);
- set_ref_in_callback(&buf->b_prompt_interrupt, copyID, NULL, NULL);
+ ABORTING(set_ref_in_callback)(&buf->b_prompt_callback, copyID, NULL, NULL);
+ ABORTING(set_ref_in_callback)(&buf->b_prompt_interrupt, copyID, NULL, NULL);
+ ABORTING(set_ref_in_callback)(&buf->b_cfu_cb, copyID, NULL, NULL);
+ ABORTING(set_ref_in_callback)(&buf->b_ofu_cb, copyID, NULL, NULL);
+ ABORTING(set_ref_in_callback)(&buf->b_tsrfu_cb, copyID, NULL, NULL);
+ ABORTING(set_ref_in_callback)(&buf->b_tfu_cb, copyID, NULL, NULL);
}
+ // 'completefunc', 'omnifunc' and 'thesaurusfunc' callbacks
+ ABORTING(set_ref_in_insexpand_funcs)(copyID);
+
+ // 'operatorfunc' callback
+ ABORTING(set_ref_in_opfunc)(copyID);
+
+ // 'tagfunc' callback
+ ABORTING(set_ref_in_tagfunc)(copyID);
+
FOR_ALL_TAB_WINDOWS(tp, wp) {
// window-local variables
ABORTING(set_ref_in_item)(&wp->w_winvar.di_tv, copyID, NULL, NULL);
@@ -5860,6 +5874,7 @@ bool callback_from_typval(Callback *const callback, typval_T *const arg)
return true;
}
+/// @return whether the callback could be called.
bool callback_call(Callback *const callback, const int argcount_in, typval_T *const argvars_in,
typval_T *const rettv)
FUNC_ATTR_NONNULL_ALL
@@ -5909,8 +5924,8 @@ bool callback_call(Callback *const callback, const int argcount_in, typval_T *co
return call_func(name, -1, rettv, argcount_in, argvars_in, &funcexe);
}
-static bool set_ref_in_callback(Callback *callback, int copyID, ht_stack_T **ht_stack,
- list_stack_T **list_stack)
+bool set_ref_in_callback(Callback *callback, int copyID, ht_stack_T **ht_stack,
+ list_stack_T **list_stack)
{
typval_T tv;
switch (callback->type) {
@@ -7067,6 +7082,9 @@ char *set_cmdarg(exarg_T *eap, char *oldarg)
if (eap->bad_char != 0) {
len += 7 + 4; // " ++bad=" + "keep" or "drop"
}
+ if (eap->mkdir_p != 0) {
+ len += 4;
+ }
const size_t newval_len = len + 1;
char *newval = xmalloc(newval_len);
@@ -7100,6 +7118,11 @@ char *set_cmdarg(exarg_T *eap, char *oldarg)
snprintf(newval + strlen(newval), newval_len, " ++bad=%c",
eap->bad_char);
}
+
+ if (eap->mkdir_p) {
+ snprintf(newval, newval_len, " ++p");
+ }
+
vimvars[VV_CMDARG].vv_str = newval;
return oldval;
}
@@ -7154,9 +7177,8 @@ int check_luafunc_name(const char *const str, const bool paren)
const char *const p = skip_luafunc_name(str);
if (*p != (paren ? '(' : NUL)) {
return 0;
- } else {
- return (int)(p - str);
}
+ return (int)(p - str);
}
/// Handle:
@@ -7786,19 +7808,19 @@ void ex_execute(exarg_T *eap)
///
/// @return NULL when no option name found. Otherwise pointer to the char
/// after the option name.
-const char *find_option_end(const char **const arg, int *const opt_flags)
+const char *find_option_end(const char **const arg, int *const scope)
{
const char *p = *arg;
p++;
if (*p == 'g' && p[1] == ':') {
- *opt_flags = OPT_GLOBAL;
+ *scope = OPT_GLOBAL;
p += 2;
} else if (*p == 'l' && p[1] == ':') {
- *opt_flags = OPT_LOCAL;
+ *scope = OPT_LOCAL;
p += 2;
} else {
- *opt_flags = 0;
+ *scope = 0;
}
if (!ASCII_ISALPHA(*p)) {
@@ -7902,9 +7924,8 @@ static var_flavour_T var_flavour(char *varname)
}
}
return VAR_FLAVOUR_SHADA;
- } else {
- return VAR_FLAVOUR_DEFAULT;
}
+ return VAR_FLAVOUR_DEFAULT;
}
/// Iterate over global variables
@@ -8697,9 +8718,9 @@ bool invoke_prompt_interrupt(void)
argv[0].v_type = VAR_UNKNOWN;
got_int = false; // don't skip executing commands
- callback_call(&curbuf->b_prompt_interrupt, 0, argv, &rettv);
+ int ret = callback_call(&curbuf->b_prompt_interrupt, 0, argv, &rettv);
tv_clear(&rettv);
- return true;
+ return ret != FAIL;
}
/// Compare "typ1" and "typ2". Put the result in "typ1".
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index 8bfa6797d0..dd30f51eb4 100644
--- a/src/nvim/eval.lua
+++ b/src/nvim/eval.lua
@@ -73,12 +73,12 @@ return {
chansend={args=2},
char2nr={args={1, 2}, base=1},
charclass={args=1, base=1},
- charcol={args=1, base=1},
+ charcol={args={1, 2}, base=1},
charidx={args={2, 3}, base=1},
chdir={args=1, base=1},
cindent={args=1, base=1},
clearmatches={args={0, 1}, base=1},
- col={args=1, base=1},
+ col={args={1, 2}, base=1},
complete={args=2, base=2},
complete_add={args=1, base=1},
complete_check={},
diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c
index 6b7eb2f8f8..f677148e08 100644
--- a/src/nvim/eval/decode.c
+++ b/src/nvim/eval/decode.c
@@ -284,13 +284,12 @@ typval_T decode_string(const char *const s, const size_t len, const TriState has
}
}
return tv;
- } else {
- return (typval_T) {
- .v_type = VAR_STRING,
- .v_lock = VAR_UNLOCKED,
- .vval = { .v_string = ((s == NULL || s_allocated) ? (char *)s : xmemdupz(s, len)) },
- };
}
+ return (typval_T) {
+ .v_type = VAR_STRING,
+ .v_lock = VAR_UNLOCKED,
+ .vval = { .v_string = ((s == NULL || s_allocated) ? (char *)s : xmemdupz(s, len)) },
+ };
}
/// Parse JSON double-quoted string
diff --git a/src/nvim/eval/executor.c b/src/nvim/eval/executor.c
index 0e0d0fe696..e253098df5 100644
--- a/src/nvim/eval/executor.c
+++ b/src/nvim/eval/executor.c
@@ -122,8 +122,8 @@ int eexe_mod_op(typval_T *const tv1, const typval_T *const tv2, const char *cons
break;
}
const float_T f = (tv2->v_type == VAR_FLOAT
- ? tv2->vval.v_float
- : (float_T)tv_get_number(tv2));
+ ? tv2->vval.v_float
+ : (float_T)tv_get_number(tv2));
switch (*op) {
case '+':
tv1->vval.v_float += f; break;
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 1492a2d30d..8acdc3256c 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -846,9 +846,32 @@ static void f_char2nr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
/// otherwise the byte index of the column.
static void get_col(typval_T *argvars, typval_T *rettv, bool charcol)
{
+ if (tv_check_for_string_or_list_arg(argvars, 0) == FAIL
+ || tv_check_for_opt_number_arg(argvars, 1) == FAIL) {
+ return;
+ }
+
+ switchwin_T switchwin;
+ bool winchanged = false;
+
+ if (argvars[1].v_type != VAR_UNKNOWN) {
+ // use the window specified in the second argument
+ tabpage_T *tp;
+ win_T *wp = win_id2wp_tp((int)tv_get_number(&argvars[1]), &tp);
+ if (wp == NULL || tp == NULL) {
+ return;
+ }
+
+ if (switch_win_noblock(&switchwin, wp, tp, true) != OK) {
+ return;
+ }
+
+ check_cursor();
+ winchanged = true;
+ }
+
colnr_T col = 0;
int fnum = curbuf->b_fnum;
-
pos_T *fp = var2fpos(&argvars[0], false, &fnum, charcol);
if (fp != NULL && fnum == curbuf->b_fnum) {
if (fp->col == MAXCOL) {
@@ -876,6 +899,10 @@ static void get_col(typval_T *argvars, typval_T *rettv, bool charcol)
}
}
rettv->vval.v_number = col;
+
+ if (winchanged) {
+ restore_win_noblock(&switchwin, true);
+ }
}
/// "charcol()" function
@@ -5240,10 +5267,9 @@ static void f_mkdir(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
xfree(failed_dir);
rettv->vval.v_number = FAIL;
return;
- } else {
- rettv->vval.v_number = OK;
- return;
}
+ rettv->vval.v_number = OK;
+ return;
}
}
rettv->vval.v_number = vim_mkdir_emsg(dir, prot);
@@ -7485,9 +7511,8 @@ static void f_serverstart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (argvars[0].v_type != VAR_STRING) {
emsg(_(e_invarg));
return;
- } else {
- address = xstrdup(tv_get_string(argvars));
}
+ address = xstrdup(tv_get_string(argvars));
} else {
address = server_address_new(NULL);
}
@@ -9970,6 +9995,7 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
bool binary = false;
bool append = false;
bool do_fsync = !!p_fs;
+ bool mkdir_p = false;
if (argvars[2].v_type != VAR_UNKNOWN) {
const char *const flags = tv_get_string_chk(&argvars[2]);
if (flags == NULL) {
@@ -9985,6 +10011,8 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
do_fsync = true; break;
case 'S':
do_fsync = false; break;
+ case 'p':
+ mkdir_p = true; break;
default:
// Using %s, p and not %c, *p to preserve multibyte characters
semsg(_("E5060: Unknown flag: %s"), p);
@@ -10004,6 +10032,7 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
emsg(_("E482: Can't open file with an empty name"));
} else if ((error = file_open(&fp, fname,
((append ? kFileAppend : kFileTruncate)
+ | (mkdir_p ? kFileMkDir : kFileCreate)
| kFileCreate), 0666)) != 0) {
semsg(_("E482: Can't open file %s for writing: %s"),
fname, os_strerror(error));
diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c
index 13d836071d..7e4066adb7 100644
--- a/src/nvim/eval/typval.c
+++ b/src/nvim/eval/typval.c
@@ -46,6 +46,8 @@ static char e_non_empty_string_required_for_argument_nr[]
= N_("E1175: Non-empty string required for argument %d");
static char e_number_required_for_argument_nr[]
= N_("E1210: Number required for argument %d");
+static char e_string_or_list_required_for_argument_nr[]
+ = N_("E1222: String or List required for argument %d");
bool tv_in_free_unref_items = false;
@@ -1747,9 +1749,8 @@ static bool tv_dict_watcher_matches(DictWatcher *watcher, const char *const key)
const size_t len = watcher->key_pattern_len;
if (len && watcher->key_pattern[len - 1] == '*') {
return strncmp(key, watcher->key_pattern, len - 1) == 0;
- } else {
- return strcmp(key, watcher->key_pattern) == 0;
}
+ return strcmp(key, watcher->key_pattern) == 0;
}
/// Send a change notification to all dictionary watchers that match given key
@@ -3881,6 +3882,17 @@ int tv_check_for_opt_number_arg(const typval_T *const args, const int idx)
|| tv_check_for_number_arg(args, idx) != FAIL) ? OK : FAIL;
}
+/// Give an error and return FAIL unless "args[idx]" is a string or a list.
+int tv_check_for_string_or_list_arg(const typval_T *const args, const int idx)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
+{
+ if (args[idx].v_type != VAR_STRING && args[idx].v_type != VAR_LIST) {
+ semsg(_(e_string_or_list_required_for_argument_nr), idx + 1);
+ return FAIL;
+ }
+ return OK;
+}
+
/// Get the string value of a "stringish" VimL object.
///
/// @param[in] tv Object to get value of.
diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c
index d07cfe0bd9..c01bd1e3df 100644
--- a/src/nvim/eval/userfunc.c
+++ b/src/nvim/eval/userfunc.c
@@ -1394,7 +1394,7 @@ func_call_skip_call:
}
/// call the 'callback' function and return the result as a number.
-/// Returns -1 when calling the function fails. Uses argv[0] to argv[argc - 1]
+/// Returns -2 when calling the function fails. Uses argv[0] to argv[argc - 1]
/// for the function arguments. argv[argc] should have type VAR_UNKNOWN.
///
/// @param argcount number of "argvars"
@@ -1403,7 +1403,7 @@ varnumber_T callback_call_retnr(Callback *callback, int argcount, typval_T *argv
{
typval_T rettv;
if (!callback_call(callback, argcount, argvars, &rettv)) {
- return -1;
+ return -2;
}
varnumber_T retval = tv_get_number_chk(&rettv, NULL);
@@ -2051,9 +2051,8 @@ void ex_function(exarg_T *eap)
}
xfree(fudi.fd_newkey);
return;
- } else {
- eap->skip = true;
}
+ eap->skip = true;
}
// An error in a function call during evaluation of an expression in magic
diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c
index 139e7ed66b..3a625df988 100644
--- a/src/nvim/eval/vars.c
+++ b/src/nvim/eval/vars.c
@@ -380,9 +380,8 @@ const char *skip_var_list(const char *arg, int *var_count, int *semicolon)
}
}
return p + 1;
- } else {
- return skip_var_one((char *)arg);
}
+ return skip_var_one((char *)arg);
}
/// Skip one (assignable) variable name, including @r, $VAR, &option, d.key,
@@ -560,8 +559,6 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
{
char *arg_end = NULL;
int len;
- int opt_flags;
- char *tofree = NULL;
// ":let $VAR = expr": Set environment variable.
if (*arg == '$') {
@@ -582,12 +579,12 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
&& vim_strchr(endchars, *skipwhite(arg)) == NULL) {
emsg(_(e_letunexp));
} else if (!check_secure()) {
+ char *tofree = NULL;
const char c1 = name[len];
name[len] = NUL;
const char *p = tv_get_string_chk(tv);
if (p != NULL && op != NULL && *op == '.') {
char *s = vim_getenv(name);
-
if (s != NULL) {
tofree = concat_str(s, p);
p = (const char *)tofree;
@@ -611,7 +608,8 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
return NULL;
}
// Find the end of the name.
- char *const p = (char *)find_option_end((const char **)&arg, &opt_flags);
+ int scope;
+ char *const p = (char *)find_option_end((const char **)&arg, &scope);
if (p == NULL
|| (endchars != NULL
&& vim_strchr(endchars, *skipwhite(p)) == NULL)) {
@@ -623,11 +621,13 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
char *stringval = NULL;
const char *s = NULL;
bool failed = false;
+ uint32_t opt_p_flags;
+ char *tofree = NULL;
const char c1 = *p;
*p = NUL;
- opt_type = get_option_value(arg, &numval, &stringval, opt_flags);
+ opt_type = get_option_value(arg, &numval, &stringval, &opt_p_flags, scope);
if (opt_type == gov_bool
|| opt_type == gov_number
|| opt_type == gov_hidden_bool
@@ -636,8 +636,13 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
n = (long)tv_get_number(tv);
}
- // Avoid setting a string option to the text "v:false" or similar.
- if (tv->v_type != VAR_BOOL && tv->v_type != VAR_SPECIAL) {
+ if ((opt_p_flags & P_FUNC) && tv_is_func(*tv)) {
+ // If the option can be set to a function reference or a lambda
+ // and the passed value is a function reference, then convert it to
+ // the name (string) of the function reference.
+ s = tofree = encode_tv2string(tv, NULL);
+ } else if (tv->v_type != VAR_BOOL && tv->v_type != VAR_SPECIAL) {
+ // Avoid setting a string option to the text "v:false" or similar.
s = tv_get_string_chk(tv);
}
@@ -674,7 +679,7 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
if (!failed) {
if (opt_type != gov_string || s != NULL) {
- char *err = set_option_value(arg, n, s, opt_flags);
+ char *err = set_option_value(arg, n, s, scope);
arg_end = p;
if (err != NULL) {
emsg(_(err));
@@ -685,6 +690,7 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
}
*p = c1;
xfree(stringval);
+ xfree(tofree);
}
// ":let @r = expr": Set register contents.
} else if (*arg == '@') {
@@ -884,9 +890,8 @@ static int do_unlet_var(lval_T *lp, char *name_end, exarg_T *eap, int deep FUNC_
lp->ll_n1++;
if (lp->ll_li == NULL || (!lp->ll_empty2 && lp->ll_n2 < lp->ll_n1)) {
break;
- } else {
- last_li = lp->ll_li;
}
+ last_li = lp->ll_li;
}
tv_list_remove_items(lp->ll_list, first_li, last_li);
} else {
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index d3a4b6c282..c22f22366a 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -1135,10 +1135,12 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out
msg_scroll = scroll_save;
}
- // Try to find an embedded bang, like in :!<cmd> ! [args]
- // (:!! is indicated by the 'forceit' variable)
+ // Try to find an embedded bang, like in ":!<cmd> ! [args]"
+ // ":!!" is indicated by the 'forceit' variable.
bool ins_prevcmd = forceit;
- trailarg = arg;
+
+ // Skip leading white space to avoid a strange error with some shells.
+ trailarg = skipwhite(arg);
do {
len = strlen(trailarg) + 1;
if (newcmd != NULL) {
@@ -1922,6 +1924,13 @@ int do_write(exarg_T *eap)
fname = curbuf->b_sfname;
}
+ if (eap->mkdir_p) {
+ if (os_file_mkdir(fname, 0755) < 0) {
+ retval = FAIL;
+ goto theend;
+ }
+ }
+
name_was_missing = curbuf->b_ffname == NULL;
retval = buf_write(curbuf, ffname, fname, eap->line1, eap->line2,
eap, eap->append, eap->forceit, true, false);
@@ -2152,9 +2161,8 @@ static int check_readonly(int *forceit, buf_T *buf)
// Set forceit, to force the writing of a readonly file
*forceit = true;
return false;
- } else {
- return true;
}
+ return true;
} else if (buf->b_p_ro) {
emsg(_(e_readonly));
} else {
diff --git a/src/nvim/ex_cmds_defs.h b/src/nvim/ex_cmds_defs.h
index 0015a82880..378271c107 100644
--- a/src/nvim/ex_cmds_defs.h
+++ b/src/nvim/ex_cmds_defs.h
@@ -202,6 +202,7 @@ struct exarg {
int regname; ///< register name (NUL if none)
int force_bin; ///< 0, FORCE_BIN or FORCE_NOBIN
int read_edit; ///< ++edit argument
+ int mkdir_p; ///< ++p argument
int force_ff; ///< ++ff= argument (first char of argument)
int force_enc; ///< ++enc= argument (index in cmd[])
int bad_char; ///< BAD_KEEP, BAD_DROP or replacement byte
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index dc2b7247f1..b875aafaad 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -78,6 +78,7 @@
#include "nvim/spell.h"
#include "nvim/spellfile.h"
#include "nvim/state.h"
+#include "nvim/statusline.h"
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/tag.h"
@@ -3481,9 +3482,10 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, int
} else {
i = (char_u)(*cmd++);
}
- if (!ascii_isdigit(*cmd)) { // '+' is '+1', but '+0' is not '+1'
+ if (!ascii_isdigit(*cmd)) { // '+' is '+1'
n = 1;
} else {
+ // "number", "+number" or "-number"
n = getdigits_int32(&cmd, false, MAXLNUM);
if (n == MAXLNUM) {
emsg(_(e_line_number_out_of_range));
@@ -3498,8 +3500,8 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, int
} else if (addr_type == ADDR_LOADED_BUFFERS || addr_type == ADDR_BUFFERS) {
lnum = compute_buffer_local_count(addr_type, lnum, (i == '-') ? -1 * n : n);
} else {
- // Relative line addressing, need to adjust for folded lines
- // now, but only do it after the first address.
+ // Relative line addressing: need to adjust for lines in a
+ // closed fold after the first address.
if (addr_type == ADDR_LINES && (i == '-' || i == '+')
&& address_count >= 2) {
(void)hasFolding(lnum, NULL, &lnum);
@@ -4074,6 +4076,13 @@ static int getargopt(exarg_T *eap)
return OK;
}
+ // ":write ++p foo/bar/file
+ if (strncmp(arg, "p", 1) == 0) {
+ eap->mkdir_p = true;
+ eap->arg = skipwhite(arg + 1);
+ return OK;
+ }
+
if (STRNCMP(arg, "ff", 2) == 0) {
arg += 2;
pp = &eap->force_ff;
@@ -4224,7 +4233,7 @@ static void ex_autocmd(exarg_T *eap)
secure = 2;
eap->errmsg = _(e_curdir);
} else if (eap->cmdidx == CMD_autocmd) {
- do_autocmd(eap->arg, eap->forceit);
+ do_autocmd(eap, eap->arg, eap->forceit);
} else {
do_augroup(eap->arg, eap->forceit);
}
@@ -4357,9 +4366,8 @@ char *check_nextcmd(char *p)
if (*s == '|' || *s == '\n') {
return s + 1;
- } else {
- return NULL;
}
+ return NULL;
}
/// - if there are more files to edit
@@ -4758,9 +4766,8 @@ static void ex_only(exarg_T *eap)
for (wp = firstwin; --wnr > 0;) {
if (wp->w_next == NULL) {
break;
- } else {
- wp = wp->w_next;
}
+ wp = wp->w_next;
}
} else {
wp = curwin;
diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c
index 8c2ac895cb..bde2f3c801 100644
--- a/src/nvim/ex_eval.c
+++ b/src/nvim/ex_eval.c
@@ -899,7 +899,14 @@ void ex_else(exarg_T *eap)
if (eap->cmdidx == CMD_elseif) {
bool error;
- result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip);
+ // When skipping we ignore most errors, but a missing expression is
+ // wrong, perhaps it should have been "else".
+ // A double quote here is the start of a string, not a comment.
+ if (skip && *eap->arg != '"' && ends_excmd(*eap->arg)) {
+ semsg(_(e_invexpr2), eap->arg);
+ } else {
+ result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip);
+ }
// When throwing error exceptions, we want to throw always the first
// of several errors in a row. This is what actually happens when
diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c
index df87cc8ab6..015799be06 100644
--- a/src/nvim/extmark.c
+++ b/src/nvim/extmark.c
@@ -71,7 +71,7 @@ void extmark_set(buf_T *buf, uint32_t ns_id, uint32_t *idp, int row, colnr_T col
|| decor->conceal
|| decor_has_sign(decor)
|| decor->ui_watched
- || decor->spell) {
+ || decor->spell != kNone) {
decor_full = true;
decor = xmemdup(decor, sizeof *decor);
}
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index c780f64a7a..e1ffc27d5b 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -72,15 +72,17 @@
#endif
#define HAS_BW_FLAGS
-#define FIO_LATIN1 0x01 // convert Latin1
-#define FIO_UTF8 0x02 // convert UTF-8
-#define FIO_UCS2 0x04 // convert UCS-2
-#define FIO_UCS4 0x08 // convert UCS-4
-#define FIO_UTF16 0x10 // convert UTF-16
-#define FIO_ENDIAN_L 0x80 // little endian
-#define FIO_NOCONVERT 0x2000 // skip encoding conversion
-#define FIO_UCSBOM 0x4000 // check for BOM at start of file
-#define FIO_ALL (-1) // allow all formats
+enum {
+ FIO_LATIN1 = 0x01, // convert Latin1
+ FIO_UTF8 = 0x02, // convert UTF-8
+ FIO_UCS2 = 0x04, // convert UCS-2
+ FIO_UCS4 = 0x08, // convert UCS-4
+ FIO_UTF16 = 0x10, // convert UTF-16
+ FIO_ENDIAN_L = 0x80, // little endian
+ FIO_NOCONVERT = 0x2000, // skip encoding conversion
+ FIO_UCSBOM = 0x4000, // check for BOM at start of file
+ FIO_ALL = -1, // allow all formats
+};
// When converting, a read() or write() may leave some bytes to be converted
// for the next call. The value is guessed...
@@ -498,18 +500,17 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
return FAIL;
}
return OK; // a new file is not an error
- } else {
- filemess(curbuf, sfname, ((fd == UV_EFBIG) ? _("[File too big]") :
+ }
+ filemess(curbuf, sfname, ((fd == UV_EFBIG) ? _("[File too big]") :
#if defined(UNIX) && defined(EOVERFLOW)
- // libuv only returns -errno
- // in Unix and in Windows
- // open() does not set
- // EOVERFLOW
- (fd == -EOVERFLOW) ? _("[File too big]") :
+ // libuv only returns -errno
+ // in Unix and in Windows
+ // open() does not set
+ // EOVERFLOW
+ (fd == -EOVERFLOW) ? _("[File too big]") :
#endif
- _("[Permission Denied]")), 0);
- curbuf->b_p_ro = true; // must use "w!" now
- }
+ _("[Permission Denied]")), 0);
+ curbuf->b_p_ro = true; // must use "w!" now
return FAIL;
}
@@ -4945,7 +4946,7 @@ int buf_check_timestamp(buf_T *buf)
}
msg_clr_eos();
(void)msg_end();
- if (emsg_silent == 0) {
+ if (emsg_silent == 0 && !in_assert_fails) {
ui_flush();
// give the user some time to think about it
os_delay(1004L, true);
@@ -5232,10 +5233,9 @@ static void vim_mktempdir(void)
if (vim_settempdir(path)) {
// Successfully created and set temporary directory so stop trying.
break;
- } else {
- // Couldn't set `vim_tempdir` to `path` so remove created directory.
- os_rmdir(path);
}
+ // Couldn't set `vim_tempdir` to `path` so remove created directory.
+ os_rmdir(path);
}
(void)umask(umask_save);
}
diff --git a/src/nvim/fold.c b/src/nvim/fold.c
index 02fbbc20db..dd74971ab5 100644
--- a/src/nvim/fold.c
+++ b/src/nvim/fold.c
@@ -57,9 +57,11 @@ typedef struct {
// folds too
} fold_T;
-#define FD_OPEN 0 // fold is open (nested ones can be closed)
-#define FD_CLOSED 1 // fold is closed
-#define FD_LEVEL 2 // depends on 'foldlevel' (nested folds too)
+enum {
+ FD_OPEN = 0, // fold is open (nested ones can be closed)
+ FD_CLOSED = 1, // fold is closed
+ FD_LEVEL = 2, // depends on 'foldlevel' (nested folds too)
+};
#define MAX_LEVEL 20 // maximum fold depth
@@ -1772,7 +1774,7 @@ char *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume, foldinfo_T foldinfo
}
}
if (text == NULL) {
- unsigned long count = (unsigned long)(lnume - lnum + 1);
+ unsigned long count = (unsigned long)(lnume - lnum + 1); // NOLINT(bugprone-misplaced-widening-cast)
vim_snprintf(buf, FOLD_TEXT_LEN,
NGETTEXT("+--%3ld line folded",
@@ -3115,7 +3117,7 @@ static int put_folds_recurse(FILE *fd, garray_T *gap, linenr_T off)
return FAIL;
}
if (fprintf(fd, "%" PRId64 ",%" PRId64 "fold",
- (int64_t)(fp->fd_top + off),
+ (int64_t)fp->fd_top + off,
(int64_t)(fp->fd_top + off + fp->fd_len - 1)) < 0
|| put_eol(fd) == FAIL) {
return FAIL;
@@ -3136,7 +3138,7 @@ static int put_foldopen_recurse(FILE *fd, win_T *wp, garray_T *gap, linenr_T off
if (fp->fd_flags != FD_LEVEL) {
if (!GA_EMPTY(&fp->fd_nested)) {
// open nested folds while this fold is open
- if (fprintf(fd, "%" PRId64, (int64_t)(fp->fd_top + off)) < 0
+ if (fprintf(fd, "%" PRId64, (int64_t)fp->fd_top + off) < 0
|| put_eol(fd) == FAIL
|| put_line(fd, "normal! zo") == FAIL) {
return FAIL;
diff --git a/src/nvim/generators/gen_options.lua b/src/nvim/generators/gen_options.lua
index 4e4dd83367..af21d44eaf 100644
--- a/src/nvim/generators/gen_options.lua
+++ b/src/nvim/generators/gen_options.lua
@@ -29,14 +29,14 @@ local type_flags={
}
local redraw_flags={
+ ui_option='P_UI_OPTION',
+ tabline='P_RTABL',
statuslines='P_RSTAT',
- tabline = 'P_RTABL',
current_window='P_RWIN',
current_window_only='P_RWINONLY',
current_buffer='P_RBUF',
all_windows='P_RALL',
curswant='P_CURSWANT',
- ui_option='P_UI_OPTION',
}
local list_flags={
@@ -78,6 +78,7 @@ local get_flags = function(o)
{'deny_in_modelines', 'P_NO_ML'},
{'deny_duplicates', 'P_NODUP'},
{'modelineexpr', 'P_MLE'},
+ {'func'}
}) do
local key_name = flag_desc[1]
local def_name = flag_desc[2] or ('P_' .. key_name:upper())
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 14266fc859..76f62fe267 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -195,7 +195,6 @@ EXTERN int emsg_skip INIT(= 0); // don't display errors for
EXTERN bool emsg_severe INIT(= false); // use message of next of several
// emsg() calls for throw
// used by assert_fails()
-EXTERN bool emsg_assert_fails_used INIT(= false);
EXTERN char *emsg_assert_fails_msg INIT(= NULL);
EXTERN long emsg_assert_fails_lnum INIT(= 0);
EXTERN char *emsg_assert_fails_context INIT(= NULL);
@@ -667,6 +666,8 @@ EXTERN int emsg_silent INIT(= 0); // don't print error messages
EXTERN bool emsg_noredir INIT(= false); // don't redirect error messages
EXTERN bool cmd_silent INIT(= false); // don't echo the command line
+EXTERN bool in_assert_fails INIT(= false); // assert_fails() active
+
// Values for swap_exists_action: what to do when swap file already exists
#define SEA_NONE 0 // don't use dialog
#define SEA_DIALOG 1 // use dialog when possible
diff --git a/src/nvim/grid_defs.h b/src/nvim/grid_defs.h
index 57b3817bc6..db31f7b984 100644
--- a/src/nvim/grid_defs.h
+++ b/src/nvim/grid_defs.h
@@ -110,24 +110,6 @@ struct ScreenGrid {
false, 0, 0, NULL, false, true, 0, \
0, 0, 0, 0, 0, false }
-/// Status line click definition
-typedef struct {
- enum {
- kStlClickDisabled = 0, ///< Clicks to this area are ignored.
- kStlClickTabSwitch, ///< Switch to the given tab.
- kStlClickTabClose, ///< Close given tab.
- kStlClickFuncRun, ///< Run user function.
- } type; ///< Type of the click.
- int tabnr; ///< Tab page number.
- char *func; ///< Function to run.
-} StlClickDefinition;
-
-/// Used for tabline clicks
-typedef struct {
- StlClickDefinition def; ///< Click definition.
- const char *start; ///< Location where region starts.
-} StlClickRecord;
-
typedef struct {
int args[3];
int icell;
diff --git a/src/nvim/hardcopy.c b/src/nvim/hardcopy.c
index 7345e9cc35..b769f6215c 100644
--- a/src/nvim/hardcopy.c
+++ b/src/nvim/hardcopy.c
@@ -122,8 +122,10 @@ static const uint32_t cterm_color_16[16] = {
static int current_syn_id;
-#define PRCOLOR_BLACK 0
-#define PRCOLOR_WHITE 0xffffff
+enum {
+ PRCOLOR_BLACK = 0,
+ PRCOLOR_WHITE = 0xffffff,
+};
static TriState curr_italic;
static TriState curr_bold;
@@ -132,13 +134,15 @@ static uint32_t curr_bg;
static uint32_t curr_fg;
static int page_count;
-#define OPT_MBFONT_USECOURIER 0
-#define OPT_MBFONT_ASCII 1
-#define OPT_MBFONT_REGULAR 2
-#define OPT_MBFONT_BOLD 3
-#define OPT_MBFONT_OBLIQUE 4
-#define OPT_MBFONT_BOLDOBLIQUE 5
-#define OPT_MBFONT_NUM_OPTIONS 6
+enum {
+ OPT_MBFONT_USECOURIER = 0,
+ OPT_MBFONT_ASCII = 1,
+ OPT_MBFONT_REGULAR = 2,
+ OPT_MBFONT_BOLD = 3,
+ OPT_MBFONT_OBLIQUE = 4,
+ OPT_MBFONT_BOLDOBLIQUE = 5,
+ OPT_MBFONT_NUM_OPTIONS = 6,
+};
static option_table_T mbfont_opts[OPT_MBFONT_NUM_OPTIONS] = {
{ "c", false, 0, NULL, 0, false },
@@ -522,7 +526,6 @@ static void prt_header(prt_settings_T *const psettings, const int pagenum, const
if (*p_header != NUL) {
linenr_T tmp_lnum, tmp_topline, tmp_botline;
- int use_sandbox = false;
// Need to (temporarily) set current line number and first/last line
// number on the 'window'. Since we don't know how long the page is,
@@ -536,9 +539,8 @@ static void prt_header(prt_settings_T *const psettings, const int pagenum, const
curwin->w_botline = lnum + 63;
printer_page_num = pagenum;
- use_sandbox = was_set_insecurely(curwin, "printheader", 0);
build_stl_str_hl(curwin, (char *)tbuf, (size_t)width + IOSIZE,
- (char *)p_header, use_sandbox,
+ (char *)p_header, "printheader", 0,
' ', width, NULL, NULL);
// Reset line numbers
@@ -729,7 +731,7 @@ void ex_hardcopy(exarg_T *eap)
}
assert(prtpos.bytes_printed <= SIZE_MAX / 100);
- sprintf((char *)IObuff, _("Printing page %d (%zu%%)"),
+ sprintf((char *)IObuff, _("Printing page %d (%zu%%)"), // NOLINT(runtime/printf)
page_count + 1 + side,
prtpos.bytes_printed * 100 / bytes_to_print);
if (!mch_print_begin_page((char_u *)IObuff)) {
@@ -750,8 +752,7 @@ void ex_hardcopy(exarg_T *eap)
prtpos.file_line);
}
- for (page_line = 0; page_line < settings.lines_per_page;
- ++page_line) {
+ for (page_line = 0; page_line < settings.lines_per_page; page_line++) {
prtpos.column = hardcopy_line(&settings,
page_line, &prtpos);
if (prtpos.column == 0) {
@@ -938,8 +939,10 @@ static colnr_T hardcopy_line(prt_settings_T *psettings, int page_line, prt_pos_T
// Some of these documents can be found in PDF form on Adobe's web site -
// http://www.adobe.com
-#define PRT_PS_DEFAULT_DPI (72) // Default user space resolution
-#define PRT_PS_DEFAULT_FONTSIZE (10)
+enum {
+ PRT_PS_DEFAULT_DPI = 72, // Default user space resolution
+ PRT_PS_DEFAULT_FONTSIZE = 10,
+};
#define PRT_MEDIASIZE_LEN ARRAY_SIZE(prt_mediasize)
@@ -960,10 +963,12 @@ static struct prt_mediasize_S prt_mediasize[] = {
{ "tabloid", 792.0, 1224.0 }
};
-#define PRT_PS_FONT_ROMAN (0)
-#define PRT_PS_FONT_BOLD (1)
-#define PRT_PS_FONT_OBLIQUE (2)
-#define PRT_PS_FONT_BOLDOBLIQUE (3)
+enum {
+ PRT_PS_FONT_ROMAN = 0,
+ PRT_PS_FONT_BOLD = 1,
+ PRT_PS_FONT_OBLIQUE = 2,
+ PRT_PS_FONT_BOLDOBLIQUE = 3,
+};
// Standard font metrics for Courier family
static struct prt_ps_font_S prt_ps_courier_font = {
@@ -984,14 +989,16 @@ static struct prt_ps_font_S prt_ps_mb_font = {
// Pointer to current font set being used
static struct prt_ps_font_S *prt_ps_font;
-#define CS_JIS_C_1978 (0x01)
-#define CS_JIS_X_1983 (0x02)
-#define CS_JIS_X_1990 (0x04)
-#define CS_NEC (0x08)
-#define CS_MSWINDOWS (0x10)
-#define CS_CP932 (0x20)
-#define CS_KANJITALK6 (0x40)
-#define CS_KANJITALK7 (0x80)
+enum {
+ CS_JIS_C_1978 = 0x01,
+ CS_JIS_X_1983 = 0x02,
+ CS_JIS_X_1990 = 0x04,
+ CS_NEC = 0x08,
+ CS_MSWINDOWS = 0x10,
+ CS_CP932 = 0x20,
+ CS_KANJITALK6 = 0x40,
+ CS_KANJITALK7 = 0x80,
+};
// Japanese encodings and charsets
static struct prt_ps_encoding_S j_encodings[] = {
@@ -1015,13 +1022,15 @@ static struct prt_ps_charset_S j_charsets[] = {
{ "KANJITALK7", "90pv", CS_KANJITALK7 }
};
-#define CS_GB_2312_80 (0x01)
-#define CS_GBT_12345_90 (0x02)
-#define CS_GBK2K (0x04)
-#define CS_SC_MAC (0x08)
-#define CS_GBT_90_MAC (0x10)
-#define CS_GBK (0x20)
-#define CS_SC_ISO10646 (0x40)
+enum {
+ CS_GB_2312_80 = 0x01,
+ CS_GBT_12345_90 = 0x02,
+ CS_GBK2K = 0x04,
+ CS_SC_MAC = 0x08,
+ CS_GBT_90_MAC = 0x10,
+ CS_GBK = 0x20,
+ CS_SC_ISO10646 = 0x40,
+};
// Simplified Chinese encodings and charsets
static struct prt_ps_encoding_S sc_encodings[] = {
@@ -1043,19 +1052,21 @@ static struct prt_ps_charset_S sc_charsets[] = {
{ "ISO10646", "UniGB", CS_SC_ISO10646 }
};
-#define CS_CNS_PLANE_1 (0x01)
-#define CS_CNS_PLANE_2 (0x02)
-#define CS_CNS_PLANE_1_2 (0x04)
-#define CS_B5 (0x08)
-#define CS_ETEN (0x10)
-#define CS_HK_GCCS (0x20)
-#define CS_HK_SCS (0x40)
-#define CS_HK_SCS_ETEN (0x80)
-#define CS_MTHKL (0x100)
-#define CS_MTHKS (0x200)
-#define CS_DLHKL (0x400)
-#define CS_DLHKS (0x800)
-#define CS_TC_ISO10646 (0x1000)
+enum {
+ CS_CNS_PLANE_1 = 0x01,
+ CS_CNS_PLANE_2 = 0x02,
+ CS_CNS_PLANE_1_2 = 0x04,
+ CS_B5 = 0x08,
+ CS_ETEN = 0x10,
+ CS_HK_GCCS = 0x20,
+ CS_HK_SCS = 0x40,
+ CS_HK_SCS_ETEN = 0x80,
+ CS_MTHKL = 0x100,
+ CS_MTHKS = 0x200,
+ CS_DLHKL = 0x400,
+ CS_DLHKS = 0x800,
+ CS_TC_ISO10646 = 0x1000,
+};
// Traditional Chinese encodings and charsets
static struct prt_ps_encoding_S tc_encodings[] = {
@@ -1087,10 +1098,12 @@ static struct prt_ps_charset_S tc_charsets[] = {
{ "ISO10646", "UniCNS", CS_TC_ISO10646 }
};
-#define CS_KR_X_1992 (0x01)
-#define CS_KR_MAC (0x02)
-#define CS_KR_X_1992_MS (0x04)
-#define CS_KR_ISO10646 (0x08)
+enum {
+ CS_KR_X_1992 = 0x01,
+ CS_KR_MAC = 0x02,
+ CS_KR_X_1992_MS = 0x04,
+ CS_KR_ISO10646 = 0x08,
+};
// Korean encodings and charsets
static struct prt_ps_encoding_S k_encodings[] = {
@@ -1169,10 +1182,12 @@ static struct prt_ps_mbfont_S prt_ps_mbfonts[] = {
// Data for table based DSC comment recognition, easy to extend if VIM needs to
// read more comments.
-#define PRT_DSC_MISC_TYPE (-1)
-#define PRT_DSC_TITLE_TYPE (1)
-#define PRT_DSC_VERSION_TYPE (2)
-#define PRT_DSC_ENDCOMMENTS_TYPE (3)
+enum {
+ PRT_DSC_MISC_TYPE = -1,
+ PRT_DSC_TITLE_TYPE = 1,
+ PRT_DSC_VERSION_TYPE = 2,
+ PRT_DSC_ENDCOMMENTS_TYPE = 3,
+};
#define PRT_DSC_TITLE "%%Title:"
#define PRT_DSC_VERSION "%%Version:"
@@ -2440,8 +2455,7 @@ bool mch_print_begin(prt_settings_T *psettings)
prt_dsc_font_resource("DocumentNeededResources", &prt_ps_courier_font);
}
if (prt_out_mbyte) {
- prt_dsc_font_resource((prt_use_courier ? NULL
- : "DocumentNeededResources"), &prt_ps_mb_font);
+ prt_dsc_font_resource((prt_use_courier ? NULL : "DocumentNeededResources"), &prt_ps_mb_font);
if (!prt_custom_cmap) {
prt_dsc_resources(NULL, "cmap", prt_cmap);
}
@@ -2990,7 +3004,7 @@ int mch_print_text_out(char_u *const textp, size_t len)
ga_append(&prt_ps_buffer, '\\'); break;
default:
- sprintf((char *)ch_buff, "%03o", (unsigned int)ch);
+ sprintf((char *)ch_buff, "%03o", (unsigned int)ch); // NOLINT(runtime/printf)
ga_append(&prt_ps_buffer, (char)ch_buff[0]);
ga_append(&prt_ps_buffer, (char)ch_buff[1]);
ga_append(&prt_ps_buffer, (char)ch_buff[2]);
diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c
index d507f07bca..c992731ee3 100644
--- a/src/nvim/highlight.c
+++ b/src/nvim/highlight.c
@@ -141,10 +141,9 @@ int hl_get_syn_attr(int ns_id, int idx, HlAttrs at_en)
|| at_en.rgb_ae_attr != 0 || ns_id != 0) {
return get_attr_entry((HlEntry){ .attr = at_en, .kind = kHlSyntax,
.id1 = idx, .id2 = ns_id });
- } else {
- // If all the fields are cleared, clear the attr field back to default value
- return 0;
}
+ // If all the fields are cleared, clear the attr field back to default value
+ return 0;
}
void ns_hl_def(NS ns_id, int hl_id, HlAttrs attrs, int link_id, Dict(highlight) *dict)
@@ -238,12 +237,11 @@ int ns_get_hl(NS *ns_hl, int hl_id, bool link, bool nodefault)
if (link) {
if (it.attr_id >= 0) {
return 0;
- } else {
- if (it.link_global) {
- *ns_hl = 0;
- }
- return it.link_id;
}
+ if (it.link_global) {
+ *ns_hl = 0;
+ }
+ return it.link_id;
} else {
return it.attr_id;
}
diff --git a/src/nvim/highlight_defs.h b/src/nvim/highlight_defs.h
index d66bcca57f..2557a248c3 100644
--- a/src/nvim/highlight_defs.h
+++ b/src/nvim/highlight_defs.h
@@ -179,7 +179,7 @@ EXTERN const char *hlf_names[] INIT(= {
[HLF_WBR] = "WinBar",
[HLF_WBRNC] = "WinBarNC",
[HLF_CU] = "Cursor",
- [HLF_BTITLE] = "FloatBorderTitle",
+ [HLF_BTITLE] = "FloatTitle",
});
EXTERN int highlight_attr[HLF_COUNT + 1]; // Highl. attr for each context.
diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c
index a83f4ea969..3c3c834c6c 100644
--- a/src/nvim/highlight_group.c
+++ b/src/nvim/highlight_group.c
@@ -23,9 +23,11 @@
/// \addtogroup SG_SET
/// @{
-#define SG_CTERM 2 // cterm has been set
-#define SG_GUI 4 // gui has been set
-#define SG_LINK 8 // link has been set
+enum {
+ SG_CTERM = 2, // cterm has been set
+ SG_GUI = 4, // gui has been set
+ SG_LINK = 8, // link has been set
+};
/// @}
#define MAX_SYN_NAME 200
@@ -131,7 +133,7 @@ static const char *highlight_init_both[] = {
"default link MsgSeparator StatusLine",
"default link NormalFloat Pmenu",
"default link FloatBorder WinSeparator",
- "default link FloatBorderTitle Title",
+ "default link FloatTitle Title",
"default FloatShadow blend=80 guibg=Black",
"default FloatShadowThrough blend=100 guibg=Black",
"RedrawDebugNormal cterm=reverse gui=reverse",
@@ -1730,9 +1732,8 @@ int syn_name2id(const char *name)
if (name[0] == '@') {
// if we look up @aaa.bbb, we have to consider @aaa as well
return syn_check_group(name, strlen(name));
- } else {
- return syn_name2id_len(name, strlen(name));
}
+ return syn_name2id_len(name, strlen(name));
}
/// Lookup a highlight group name and return its ID.
diff --git a/src/nvim/indent.c b/src/nvim/indent.c
index d372e41459..0bf36c42f4 100644
--- a/src/nvim/indent.c
+++ b/src/nvim/indent.c
@@ -896,9 +896,8 @@ int inindent(int extra)
if (col >= curwin->w_cursor.col + extra) {
return true;
- } else {
- return false;
}
+ return false;
}
/// @return true if the conditions are OK for smart indenting.
diff --git a/src/nvim/indent_c.c b/src/nvim/indent_c.c
index 5eed2601d5..5a38fb5aae 100644
--- a/src/nvim/indent_c.c
+++ b/src/nvim/indent_c.c
@@ -458,9 +458,8 @@ bool cin_iscase(const char_u *s, bool strict)
// JS etc.
if (strict) {
return false; // stop at string
- } else {
- return true;
}
+ return true;
}
}
return false;
@@ -2877,14 +2876,13 @@ int get_c_indent(void)
// Line below current line is the one that starts a
// (possibly broken) line ending in a comma.
break;
- } else {
- amount = get_indent();
- if (curwin->w_cursor.lnum - 1 == ourscope) {
- // line above is start of the scope, thus current
- // line is the one that stars a (possibly broken)
- // line ending in a comma.
- break;
- }
+ }
+ amount = get_indent();
+ if (curwin->w_cursor.lnum - 1 == ourscope) {
+ // line above is start of the scope, thus current
+ // line is the one that stars a (possibly broken)
+ // line ending in a comma.
+ break;
}
}
diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c
index 1acdddedef..91ac1d5e8c 100644
--- a/src/nvim/insexpand.c
+++ b/src/nvim/insexpand.c
@@ -56,24 +56,26 @@
#define CTRL_X_WANT_IDENT 0x100
-#define CTRL_X_NORMAL 0 ///< CTRL-N CTRL-P completion, default
-#define CTRL_X_NOT_DEFINED_YET 1
-#define CTRL_X_SCROLL 2
-#define CTRL_X_WHOLE_LINE 3
-#define CTRL_X_FILES 4
-#define CTRL_X_TAGS (5 + CTRL_X_WANT_IDENT)
-#define CTRL_X_PATH_PATTERNS (6 + CTRL_X_WANT_IDENT)
-#define CTRL_X_PATH_DEFINES (7 + CTRL_X_WANT_IDENT)
-#define CTRL_X_FINISHED 8
-#define CTRL_X_DICTIONARY (9 + CTRL_X_WANT_IDENT)
-#define CTRL_X_THESAURUS (10 + CTRL_X_WANT_IDENT)
-#define CTRL_X_CMDLINE 11
-#define CTRL_X_FUNCTION 12
-#define CTRL_X_OMNI 13
-#define CTRL_X_SPELL 14
-#define CTRL_X_LOCAL_MSG 15 ///< only used in "ctrl_x_msgs"
-#define CTRL_X_EVAL 16 ///< for builtin function complete()
-#define CTRL_X_CMDLINE_CTRL_X 17 ///< CTRL-X typed in CTRL_X_CMDLINE
+enum {
+ CTRL_X_NORMAL = 0, ///< CTRL-N CTRL-P completion, default
+ CTRL_X_NOT_DEFINED_YET = 1,
+ CTRL_X_SCROLL = 2,
+ CTRL_X_WHOLE_LINE = 3,
+ CTRL_X_FILES = 4,
+ CTRL_X_TAGS = (5 + CTRL_X_WANT_IDENT),
+ CTRL_X_PATH_PATTERNS = (6 + CTRL_X_WANT_IDENT),
+ CTRL_X_PATH_DEFINES = (7 + CTRL_X_WANT_IDENT),
+ CTRL_X_FINISHED = 8,
+ CTRL_X_DICTIONARY = (9 + CTRL_X_WANT_IDENT),
+ CTRL_X_THESAURUS = (10 + CTRL_X_WANT_IDENT),
+ CTRL_X_CMDLINE = 11,
+ CTRL_X_FUNCTION = 12,
+ CTRL_X_OMNI = 13,
+ CTRL_X_SPELL = 14,
+ CTRL_X_LOCAL_MSG = 15, ///< only used in "ctrl_x_msgs"
+ CTRL_X_EVAL = 16, ///< for builtin function complete()
+ CTRL_X_CMDLINE_CTRL_X = 17, ///< CTRL-X typed in CTRL_X_CMDLINE
+};
#define CTRL_X_MSG(i) ctrl_x_msgs[(i) & ~CTRL_X_WANT_IDENT]
@@ -452,7 +454,7 @@ bool check_compl_option(bool dict_opt)
msg_attr((dict_opt
? _("'dictionary' option is empty")
: _("'thesaurus' option is empty")), HL_ATTR(HLF_E));
- if (emsg_silent == 0) {
+ if (emsg_silent == 0 && !in_assert_fails) {
vim_beep(BO_COMPL);
setcursor();
ui_flush();
@@ -2233,7 +2235,7 @@ static Callback tsrfu_cb; ///< 'thesaurusfunc' callback function
static void copy_global_to_buflocal_cb(Callback *globcb, Callback *bufcb)
{
callback_free(bufcb);
- if (globcb->data.funcref != NULL && *globcb->data.funcref != NUL) {
+ if (globcb->type != kCallbackNone) {
callback_copy(bufcb, globcb);
}
}
@@ -2290,17 +2292,26 @@ int set_thesaurusfunc_option(void)
if (*curbuf->b_p_tsrfu != NUL) {
// buffer-local option set
- callback_free(&curbuf->b_tsrfu_cb);
retval = option_set_callback_func(curbuf->b_p_tsrfu, &curbuf->b_tsrfu_cb);
} else {
// global option set
- callback_free(&tsrfu_cb);
retval = option_set_callback_func(p_tsrfu, &tsrfu_cb);
}
return retval;
}
+/// Mark the global 'completefunc' 'omnifunc' and 'thesaurusfunc' callbacks with
+/// "copyID" so that they are not garbage collected.
+bool set_ref_in_insexpand_funcs(int copyID)
+{
+ bool abort = set_ref_in_callback(&cfu_cb, copyID, NULL, NULL);
+ abort = abort || set_ref_in_callback(&ofu_cb, copyID, NULL, NULL);
+ abort = abort || set_ref_in_callback(&tsrfu_cb, copyID, NULL, NULL);
+
+ return abort;
+}
+
/// Get the user-defined completion function name for completion "type"
static char_u *get_complete_funcname(int type)
{
diff --git a/src/nvim/lua/converter.c b/src/nvim/lua/converter.c
index bdb0719809..d7881350aa 100644
--- a/src/nvim/lua/converter.c
+++ b/src/nvim/lua/converter.c
@@ -906,9 +906,8 @@ Float nlua_pop_Float(lua_State *lstate, Error *err)
lua_pop(lstate, 1);
if (table_props.type != kObjectTypeFloat) {
return 0;
- } else {
- return (Float)table_props.val;
}
+ return (Float)table_props.val;
}
/// Convert lua table to array without determining whether it is array
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index 9d63fe55f9..9cb42a81d3 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -1985,6 +1985,9 @@ int nlua_do_ucmd(ucmd_T *cmd, exarg_T *eap, bool preview)
nlua_pushref(lstate, preview ? cmd->uc_preview_luaref : cmd->uc_luaref);
lua_newtable(lstate);
+ lua_pushstring(lstate, cmd->uc_name);
+ lua_setfield(lstate, -2, "name");
+
lua_pushboolean(lstate, eap->forceit == 1);
lua_setfield(lstate, -2, "bang");
diff --git a/src/nvim/lua/stdlib.c b/src/nvim/lua/stdlib.c
index 6974c6181c..54e2c24523 100644
--- a/src/nvim/lua/stdlib.c
+++ b/src/nvim/lua/stdlib.c
@@ -378,15 +378,14 @@ int nlua_setvar(lua_State *lstate)
if (di == NULL) {
// Doesn't exist, nothing to do
return 0;
- } else {
- // Notify watchers
- if (watched) {
- tv_dict_watcher_notify(dict, key.data, NULL, &di->di_tv);
- }
-
- // Delete the entry
- tv_dict_item_remove(dict, di);
}
+ // Notify watchers
+ if (watched) {
+ tv_dict_watcher_notify(dict, key.data, NULL, &di->di_tv);
+ }
+
+ // Delete the entry
+ tv_dict_item_remove(dict, di);
} else {
// Update the key
typval_T tv;
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 07be01da3a..e395f8dc78 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -61,6 +61,7 @@
#include "nvim/shada.h"
#include "nvim/sign.h"
#include "nvim/state.h"
+#include "nvim/statusline.h"
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/ui.h"
@@ -88,16 +89,20 @@
#include "nvim/api/extmark.h"
// values for "window_layout"
-#define WIN_HOR 1 // "-o" horizontally split windows
-#define WIN_VER 2 // "-O" vertically split windows
-#define WIN_TABS 3 // "-p" windows on tab pages
+enum {
+ WIN_HOR = 1, // "-o" horizontally split windows
+ WIN_VER = 2, // "-O" vertically split windows
+ WIN_TABS = 3, // "-p" windows on tab pages
+};
// Values for edit_type.
-#define EDIT_NONE 0 // no edit type yet
-#define EDIT_FILE 1 // file name argument[s] given, use argument list
-#define EDIT_STDIN 2 // read file from stdin
-#define EDIT_TAG 3 // tag name argument given, use tagname
-#define EDIT_QF 4 // start in quickfix mode
+enum {
+ EDIT_NONE = 0, // no edit type yet
+ EDIT_FILE = 1, // file name argument[s] given, use argument list
+ EDIT_STDIN = 2, // read file from stdin
+ EDIT_TAG = 3, // tag name argument given, use tagname
+ EDIT_QF = 4, // start in quickfix mode
+};
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "main.c.generated.h"
diff --git a/src/nvim/mark.c b/src/nvim/mark.c
index 8172aec543..f9ed80e3ce 100644
--- a/src/nvim/mark.c
+++ b/src/nvim/mark.c
@@ -1479,9 +1479,8 @@ const void *mark_jumplist_iter(const void *const iter, const win_T *const win, x
*fm = *iter_mark;
if (iter_mark == &(win->w_jumplist[win->w_jumplistlen - 1])) {
return NULL;
- } else {
- return iter_mark + 1;
}
+ return iter_mark + 1;
}
/// Iterate over global marks
diff --git a/src/nvim/match.c b/src/nvim/match.c
index 916bb44d8c..1e77dc3e91 100644
--- a/src/nvim/match.c
+++ b/src/nvim/match.c
@@ -805,17 +805,17 @@ bool get_prevcol_hl_flag(win_T *wp, match_T *search_hl, long curcol)
|| (prevcol > (long)search_hl->startcol
&& search_hl->endcol == MAXCOL))) {
return true;
- } else {
- cur = wp->w_match_head;
- while (cur != NULL) {
- if (!cur->mit_hl.is_addpos && (prevcol == (long)cur->mit_hl.startcol
- || (prevcol > (long)cur->mit_hl.startcol
- && cur->mit_hl.endcol == MAXCOL))) {
- return true;
- }
- cur = cur->mit_next;
+ }
+ cur = wp->w_match_head;
+ while (cur != NULL) {
+ if (!cur->mit_hl.is_addpos && (prevcol == (long)cur->mit_hl.startcol
+ || (prevcol > (long)cur->mit_hl.startcol
+ && cur->mit_hl.endcol == MAXCOL))) {
+ return true;
}
+ cur = cur->mit_next;
}
+
return false;
}
diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c
index 9e34c7e413..848b0f29d0 100644
--- a/src/nvim/mbyte.c
+++ b/src/nvim/mbyte.c
@@ -1186,9 +1186,8 @@ static int utf_convert(int a, const convertStruct *const table, size_t n_items)
&& a <= table[start].rangeEnd
&& (a - table[start].rangeStart) % table[start].step == 0) {
return a + table[start].offset;
- } else {
- return a;
}
+ return a;
}
// Return the folded-case equivalent of "a", which is a UCS-4 character. Uses
@@ -1550,7 +1549,7 @@ void show_utf8(void)
}
clen = utf_ptr2len((char *)line + i);
}
- sprintf((char *)IObuff + rlen, "%02x ",
+ sprintf((char *)IObuff + rlen, "%02x ", // NOLINT(runtime/printf)
(line[i] == NL) ? NUL : line[i]); // NUL is stored as NL
clen--;
rlen += (int)strlen(IObuff + rlen);
diff --git a/src/nvim/memfile.c b/src/nvim/memfile.c
index bb9be0766e..608d194cad 100644
--- a/src/nvim/memfile.c
+++ b/src/nvim/memfile.c
@@ -815,8 +815,10 @@ static bool mf_do_open(memfile_T *mfp, char *fname, int flags)
/// The number of buckets in the hashtable is increased by a factor of
/// MHT_GROWTH_FACTOR when the average number of items per bucket
/// exceeds 2 ^ MHT_LOG_LOAD_FACTOR.
-#define MHT_LOG_LOAD_FACTOR 6
-#define MHT_GROWTH_FACTOR 2 // must be a power of two
+enum {
+ MHT_LOG_LOAD_FACTOR = 6,
+ MHT_GROWTH_FACTOR = 2, // must be a power of two
+};
/// Initialize an empty hash table.
static void mf_hash_init(mf_hashtab_T *mht)
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index 225e2aeab1..1826e5935e 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -83,10 +83,12 @@ typedef struct pointer_block PTR_BL; // contents of a pointer block
typedef struct data_block DATA_BL; // contents of a data block
typedef struct pointer_entry PTR_EN; // block/line-count pair
-#define DATA_ID (('d' << 8) + 'a') // data block id
-#define PTR_ID (('p' << 8) + 't') // pointer block id
-#define BLOCK0_ID0 'b' // block 0 id 0
-#define BLOCK0_ID1 '0' // block 0 id 1
+enum {
+ DATA_ID = (('d' << 8) + 'a'), // data block id
+ PTR_ID = (('p' << 8) + 't'), // pointer block id
+ BLOCK0_ID0 = 'b', // block 0 id 0
+ BLOCK0_ID1 = '0', // block 0 id 1
+};
// pointer to a block, used in a pointer block
struct pointer_entry {
@@ -134,18 +136,22 @@ struct data_block {
#define INDEX_SIZE (sizeof(unsigned)) // size of one db_index entry
#define HEADER_SIZE (sizeof(DATA_BL) - INDEX_SIZE) // size of data block header
-#define B0_FNAME_SIZE_ORG 900 // what it was in older versions
-#define B0_FNAME_SIZE_NOCRYPT 898 // 2 bytes used for other things
-#define B0_FNAME_SIZE_CRYPT 890 // 10 bytes used for other things
-#define B0_UNAME_SIZE 40
-#define B0_HNAME_SIZE 40
+enum {
+ B0_FNAME_SIZE_ORG = 900, // what it was in older versions
+ B0_FNAME_SIZE_NOCRYPT = 898, // 2 bytes used for other things
+ B0_FNAME_SIZE_CRYPT = 890, // 10 bytes used for other things
+ B0_UNAME_SIZE = 40,
+ B0_HNAME_SIZE = 40,
+};
// Restrict the numbers to 32 bits, otherwise most compilers will complain.
// This won't detect a 64 bit machine that only swaps a byte in the top 32
// bits, but that is crazy anyway.
-#define B0_MAGIC_LONG 0x30313233L
-#define B0_MAGIC_INT 0x20212223L
-#define B0_MAGIC_SHORT 0x10111213L
-#define B0_MAGIC_CHAR 0x55
+enum {
+ B0_MAGIC_LONG = 0x30313233L,
+ B0_MAGIC_INT = 0x20212223L,
+ B0_MAGIC_SHORT = 0x10111213L,
+ B0_MAGIC_CHAR = 0x55,
+};
// Block zero holds all info about the swap file.
//
@@ -205,10 +211,12 @@ struct block0 {
static linenr_T lowest_marked = 0;
// arguments for ml_find_line()
-#define ML_DELETE 0x11 // delete line
-#define ML_INSERT 0x12 // insert line
-#define ML_FIND 0x13 // just find the line
-#define ML_FLUSH 0x02 // flush locked block
+enum {
+ ML_DELETE = 0x11, // delete line
+ ML_INSERT = 0x12, // insert line
+ ML_FIND = 0x13, // just find the line
+ ML_FLUSH = 0x02, // flush locked block
+};
#define ML_SIMPLE(x) ((x) & 0x10) // DEL, INS or FIND
// argument for ml_upd_block0()
@@ -271,7 +279,7 @@ int ml_open(buf_T *buf)
b0p->b0_id[0] = BLOCK0_ID0;
b0p->b0_id[1] = BLOCK0_ID1;
b0p->b0_magic_long = B0_MAGIC_LONG;
- b0p->b0_magic_int = (int)B0_MAGIC_INT;
+ b0p->b0_magic_int = B0_MAGIC_INT;
b0p->b0_magic_short = (int16_t)B0_MAGIC_SHORT;
b0p->b0_magic_char = B0_MAGIC_CHAR;
xstrlcpy(xstpcpy((char *)b0p->b0_version, "VIM "), Version, 6);
@@ -2135,13 +2143,13 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b
buf->b_ml.ml_stack_top = stack_idx + 1; // truncate stack
if (lineadd) {
- --(buf->b_ml.ml_stack_top);
+ (buf->b_ml.ml_stack_top)--;
// fix line count for rest of blocks in the stack
ml_lineadd(buf, lineadd);
// fix stack itself
buf->b_ml.ml_stack[buf->b_ml.ml_stack_top].ip_high +=
lineadd;
- ++(buf->b_ml.ml_stack_top);
+ (buf->b_ml.ml_stack_top)++;
}
// We are finished, break the loop here.
@@ -2428,7 +2436,7 @@ static int ml_delete_int(buf_T *buf, linenr_T lnum, bool message)
buf->b_ml.ml_stack[buf->b_ml.ml_stack_top].ip_high +=
buf->b_ml.ml_locked_lineadd;
}
- ++(buf->b_ml.ml_stack_top);
+ (buf->b_ml.ml_stack_top)++;
break;
}
@@ -2698,11 +2706,11 @@ static bhdr_T *ml_find_line(buf_T *buf, linenr_T lnum, int action)
&& buf->b_ml.ml_locked_high >= lnum) {
// remember to update pointer blocks and stack later
if (action == ML_INSERT) {
- ++(buf->b_ml.ml_locked_lineadd);
- ++(buf->b_ml.ml_locked_high);
+ (buf->b_ml.ml_locked_lineadd)++;
+ (buf->b_ml.ml_locked_high)++;
} else if (action == ML_DELETE) {
- --(buf->b_ml.ml_locked_lineadd);
- --(buf->b_ml.ml_locked_high);
+ (buf->b_ml.ml_locked_lineadd)--;
+ (buf->b_ml.ml_locked_high)--;
}
return buf->b_ml.ml_locked;
}
@@ -3375,7 +3383,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
static int b0_magic_wrong(ZERO_BL *b0p)
{
return b0p->b0_magic_long != B0_MAGIC_LONG
- || b0p->b0_magic_int != (int)B0_MAGIC_INT
+ || b0p->b0_magic_int != B0_MAGIC_INT
|| b0p->b0_magic_short != (int16_t)B0_MAGIC_SHORT
|| b0p->b0_magic_char != B0_MAGIC_CHAR;
}
@@ -3525,8 +3533,10 @@ void ml_setflags(buf_T *buf)
}
}
-#define MLCS_MAXL 800 // max no of lines in chunk
-#define MLCS_MINL 400 // should be half of MLCS_MAXL
+enum {
+ MLCS_MAXL = 800, // max no of lines in chunk
+ MLCS_MINL = 400, // should be half of MLCS_MAXL
+};
/// Keep information for finding byte offset of a line
///
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index 16033e9c63..81299d3e25 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -439,9 +439,8 @@ char *xstrdupnul(const char *const str)
{
if (str == NULL) {
return xmallocz(0);
- } else {
- return xstrdup(str);
}
+ return xstrdup(str);
}
/// A version of memchr that starts the search at `src + len`.
diff --git a/src/nvim/message.c b/src/nvim/message.c
index e42fd42d46..538bcde6a5 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -59,8 +59,10 @@ struct msgchunk_S {
};
// Magic chars used in confirm dialog strings
-#define DLG_BUTTON_SEP '\n'
-#define DLG_HOTKEY_CHAR '&'
+enum {
+ DLG_BUTTON_SEP = '\n',
+ DLG_HOTKEY_CHAR = '&',
+};
static int confirm_msg_used = false; // displaying confirm_msg
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -128,7 +130,6 @@ static bool msg_ext_history_visible = false;
static bool msg_ext_keep_after_cmdline = false;
static int msg_grid_pos_at_flush = 0;
-static int msg_grid_scroll_discount = 0;
static void ui_ext_msg_set_pos(int row, bool scrolled)
{
@@ -195,7 +196,7 @@ void msg_grid_validate(void)
msg_grid_set_pos(max_rows, false);
}
- if (msg_grid.chars && cmdline_row < msg_grid_pos) {
+ if (msg_grid.chars && !msg_scrolled && cmdline_row < msg_grid_pos) {
// TODO(bfredl): this should already be the case, but fails in some
// "batched" executions where compute_cmdrow() use stale positions or
// something.
@@ -663,7 +664,7 @@ static bool emsg_multiline(const char *s, bool multiline)
return true;
}
- if (emsg_assert_fails_used && emsg_assert_fails_msg == NULL) {
+ if (in_assert_fails && emsg_assert_fails_msg == NULL) {
emsg_assert_fails_msg = xstrdup(s);
emsg_assert_fails_lnum = SOURCING_LNUM;
xfree(emsg_assert_fails_context);
@@ -2443,6 +2444,7 @@ void msg_reset_scroll(void)
}
msg_scrolled = 0;
msg_scrolled_at_flush = 0;
+ msg_grid_scroll_discount = 0;
}
/// Increment "msg_scrolled".
diff --git a/src/nvim/message.h b/src/nvim/message.h
index 31cd54f18c..191d3b8da7 100644
--- a/src/nvim/message.h
+++ b/src/nvim/message.h
@@ -66,6 +66,8 @@ EXTERN ScreenGrid msg_grid_adj INIT(= SCREEN_GRID_INIT);
// value of msg_scrolled at latest msg_scroll_flush.
EXTERN int msg_scrolled_at_flush INIT(= 0);
+EXTERN int msg_grid_scroll_discount INIT(= 0);
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "message.h.generated.h"
#endif
diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c
index 53431187af..fd1eec692a 100644
--- a/src/nvim/mouse.c
+++ b/src/nvim/mouse.c
@@ -25,6 +25,7 @@
#include "nvim/plines.h"
#include "nvim/search.h"
#include "nvim/state.h"
+#include "nvim/statusline.h"
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/ui.h"
@@ -1179,17 +1180,15 @@ retnomove:
// Don't use start_arrow() if we're in the same window
if (curwin == old_curwin) {
return IN_STATUS_LINE;
- } else {
- return IN_STATUS_LINE | CURSOR_MOVED;
}
+ return IN_STATUS_LINE | CURSOR_MOVED;
}
if (sep_line_offset) { // In (or below) status line
// Don't use start_arrow() if we're in the same window
if (curwin == old_curwin) {
return IN_SEP_LINE;
- } else {
- return IN_SEP_LINE | CURSOR_MOVED;
}
+ return IN_SEP_LINE | CURSOR_MOVED;
}
curwin->w_cursor.lnum = curwin->w_topline;
diff --git a/src/nvim/msgpack_rpc/helpers.c b/src/nvim/msgpack_rpc/helpers.c
index ddca9afad0..86babd1c36 100644
--- a/src/nvim/msgpack_rpc/helpers.c
+++ b/src/nvim/msgpack_rpc/helpers.c
@@ -95,9 +95,8 @@ bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg)
dest = conv(((String) { \
.size = obj->via.attr.size, \
.data = (obj->via.attr.ptr == NULL || obj->via.attr.size == 0 \
- ? xmemdupz("", 0) \
- : xmemdupz(obj->via.attr.ptr, obj->via.attr.size)), \
- })); \
+ ? xmemdupz("", 0) \
+ : xmemdupz(obj->via.attr.ptr, obj->via.attr.size)), })); \
break; \
}
STR_CASE(MSGPACK_OBJECT_STR, str, cur.mobj, *cur.aobj, STRING_OBJ)
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index d142af555a..27a7b1ae04 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -611,6 +611,7 @@ static bool normal_need_redraw_mode_message(NormalState *s)
&& stuff_empty()
&& typebuf_typed()
&& emsg_silent == 0
+ && !in_assert_fails
&& !did_wait_return
&& s->oa.op_type == OP_NOP);
}
@@ -2266,7 +2267,7 @@ bool find_decl(char_u *ptr, size_t len, bool locally, bool thisblock, int flags_
// Put "\V" before the pattern to avoid that the special meaning of "."
// and "~" causes trouble.
assert(len <= INT_MAX);
- sprintf((char *)pat, vim_iswordp(ptr) ? "\\V\\<%.*s\\>" : "\\V%.*s",
+ sprintf((char *)pat, vim_iswordp(ptr) ? "\\V\\<%.*s\\>" : "\\V%.*s", // NOLINT(runtime/printf)
(int)len, ptr);
old_pos = curwin->w_cursor;
save_p_ws = p_ws;
@@ -4299,9 +4300,8 @@ static void nv_brackets(cmdarg_T *cap)
cap->nchar == 's', false, NULL) == 0) {
clearopbeep(cap->oap);
break;
- } else {
- curwin->w_set_curswant = true;
}
+ curwin->w_set_curswant = true;
}
if (cap->oap->op_type == OP_NOP && (fdo_flags & FDO_SEARCH) && KeyTyped) {
foldOpenCursor();
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 2d53918ded..8656b4265d 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -5555,13 +5555,22 @@ static void op_colon(oparg_T *oap)
} else {
stuffnumReadbuff((long)oap->start.lnum);
}
- if (oap->end.lnum != oap->start.lnum) {
+
+ // When using !! on a closed fold the range ".!" works best to operate
+ // on, it will be made the whole closed fold later.
+ linenr_T endOfStartFold = oap->start.lnum;
+ (void)hasFolding(oap->start.lnum, NULL, &endOfStartFold);
+ if (oap->end.lnum != oap->start.lnum && oap->end.lnum != endOfStartFold) {
+ // Make it a range with the end line.
stuffcharReadbuff(',');
if (oap->end.lnum == curwin->w_cursor.lnum) {
stuffcharReadbuff('.');
} else if (oap->end.lnum == curbuf->b_ml.ml_line_count) {
stuffcharReadbuff('$');
- } else if (oap->start.lnum == curwin->w_cursor.lnum) {
+ } else if (oap->start.lnum == curwin->w_cursor.lnum
+ // do not use ".+number" for a closed fold, it would count
+ // folded lines twice
+ && !hasFolding(oap->end.lnum, NULL, NULL)) {
stuffReadbuff(".+");
stuffnumReadbuff(oap->line_count - 1);
} else {
@@ -5606,6 +5615,13 @@ void free_operatorfunc_option(void)
}
#endif
+/// Mark the global 'operatorfunc' callback with "copyID" so that it is not
+/// garbage collected.
+bool set_ref_in_opfunc(int copyID)
+{
+ return set_ref_in_callback(&opfunc_cb, copyID, NULL, NULL);
+}
+
/// Handle the "g@" operator: call 'operatorfunc'.
static void op_function(const oparg_T *oap)
FUNC_ATTR_NONNULL_ALL
diff --git a/src/nvim/option.c b/src/nvim/option.c
index da3fad0d61..23c4a1ccf3 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -2842,6 +2842,7 @@ int findoption(const char *const arg)
/// Gets the value for an option.
///
/// @param stringval NULL when only checking existence
+/// @param flagsp set to the option flags (P_xxxx) (if not NULL)
///
/// @returns:
/// Number option: gov_number, *numval gets value.
@@ -2851,7 +2852,8 @@ int findoption(const char *const arg)
/// Hidden Toggle option: gov_hidden_bool.
/// Hidden String option: gov_hidden_string.
/// Unknown option: gov_unknown.
-getoption_T get_option_value(const char *name, long *numval, char **stringval, int opt_flags)
+getoption_T get_option_value(const char *name, long *numval, char **stringval, uint32_t *flagsp,
+ int scope)
{
if (get_tty_option(name, stringval)) {
return gov_string;
@@ -2862,7 +2864,12 @@ getoption_T get_option_value(const char *name, long *numval, char **stringval, i
return gov_unknown;
}
- char_u *varp = (char_u *)get_varp_scope(&(options[opt_idx]), opt_flags);
+ char_u *varp = (char_u *)get_varp_scope(&(options[opt_idx]), scope);
+
+ if (flagsp != NULL) {
+ // Return the P_xxxx option flags.
+ *flagsp = options[opt_idx].flags;
+ }
if (options[opt_idx].flags & P_STRING) {
if (varp == NULL) { // hidden option
@@ -2953,15 +2960,13 @@ int get_option_value_strict(char *name, int64_t *numval, char **stringval, int o
if (p->indir & PV_WIN) {
if (opt_type == SREQ_BUF) {
return 0; // Requested buffer-local, not window-local option
- } else {
- rv |= SOPT_WIN;
}
+ rv |= SOPT_WIN;
} else if (p->indir & PV_BUF) {
if (opt_type == SREQ_WIN) {
return 0; // Requested window-local, not buffer-local option
- } else {
- rv |= SOPT_BUF;
}
+ rv |= SOPT_BUF;
}
}
@@ -2972,9 +2977,8 @@ int get_option_value_strict(char *name, int64_t *numval, char **stringval, int o
if (opt_type == SREQ_GLOBAL) {
if (p->var == VAR_WIN) {
return 0;
- } else {
- varp = p->var;
}
+ varp = p->var;
} else {
if (opt_type == SREQ_BUF) {
// Special case: 'modified' is b_changed, but we also want to
@@ -3092,14 +3096,13 @@ char *set_option_value(const char *const name, const long number, const char *co
numval = -1;
} else {
char *s = NULL;
- (void)get_option_value(name, &numval, &s, OPT_GLOBAL);
+ (void)get_option_value(name, &numval, &s, NULL, OPT_GLOBAL);
}
}
if (flags & P_NUM) {
return set_num_option(opt_idx, varp, numval, NULL, 0, opt_flags);
- } else {
- return set_bool_option(opt_idx, varp, (int)numval, opt_flags);
}
+ return set_bool_option(opt_idx, varp, (int)numval, opt_flags);
}
}
return NULL;
@@ -3701,15 +3704,17 @@ void unset_global_local_option(char *name, void *from)
}
/// Get pointer to option variable, depending on local or global scope.
-char *get_varp_scope(vimoption_T *p, int opt_flags)
+///
+/// @param scope can be OPT_LOCAL, OPT_GLOBAL or a combination.
+char *get_varp_scope(vimoption_T *p, int scope)
{
- if ((opt_flags & OPT_GLOBAL) && p->indir != PV_NONE) {
+ if ((scope & OPT_GLOBAL) && p->indir != PV_NONE) {
if (p->var == VAR_WIN) {
return GLOBAL_WO(get_varp(p));
}
return (char *)p->var;
}
- if ((opt_flags & OPT_LOCAL) && ((int)p->indir & PV_BOTH)) {
+ if ((scope & OPT_LOCAL) && ((int)p->indir & PV_BOTH)) {
switch ((int)p->indir) {
case PV_FP:
return (char *)&(curbuf->b_p_fp);
@@ -4863,9 +4868,9 @@ void ExpandOldSetting(int *num_file, char ***file)
/// NameBuff[]. Must not be called with a hidden option!
///
/// @param opt_flags OPT_GLOBAL and/or OPT_LOCAL
-static void option_value2string(vimoption_T *opp, int opt_flags)
+static void option_value2string(vimoption_T *opp, int scope)
{
- char_u *varp = (char_u *)get_varp_scope(opp, opt_flags);
+ char_u *varp = (char_u *)get_varp_scope(opp, scope);
if (opp->flags & P_NUM) {
long wc = 0;
@@ -5184,7 +5189,7 @@ int option_set_callback_func(char *optval, Callback *optcb)
}
Callback cb;
- if (!callback_from_typval(&cb, tv)) {
+ if (!callback_from_typval(&cb, tv) || cb.type == kCallbackNone) {
tv_free(tv);
return FAIL;
}
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index 7c33773e41..d505e75be4 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -24,6 +24,7 @@
#define P_NO_MKRC 0x200U ///< don't include in :mkvimrc output
// when option changed, what to display:
+#define P_UI_OPTION 0x400U ///< send option to remote UI
#define P_RTABL 0x800U ///< redraw tabline
#define P_RSTAT 0x1000U ///< redraw status lines
#define P_RWIN 0x2000U ///< redraw current window and recompute text
@@ -50,9 +51,9 @@
#define P_NDNAME 0x8000000U ///< only normal dir name chars allowed
#define P_RWINONLY 0x10000000U ///< only redraw current window
#define P_MLE 0x20000000U ///< under control of 'modelineexpr'
+#define P_FUNC 0x40000000U ///< accept a function reference or a lambda
-#define P_NO_DEF_EXP 0x40000000U ///< Do not expand default value.
-#define P_UI_OPTION 0x80000000U ///< send option to remote ui
+#define P_NO_DEF_EXP 0x80000000U ///< Do not expand default value.
/// Flags for option-setting functions
///
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index 3a59becb33..dc0561d560 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -10,6 +10,7 @@
-- secure=nil, gettext=nil, noglob=nil, normal_fname_chars=nil,
-- pri_mkrc=nil, deny_in_modelines=nil, normal_dname_chars=nil,
-- modelineexpr=nil,
+-- func=nil,
-- expand=nil, nodefault=nil, no_mkrc=nil,
-- alloced=nil,
-- save_pv_indir=nil,
@@ -455,6 +456,7 @@ return {
type='string', scope={'buffer'},
secure=true,
alloced=true,
+ func=true,
varname='p_cfu',
defaults={if_true=""}
},
@@ -647,7 +649,7 @@ return {
no_mkrc=true,
redraw={'statuslines'},
varname='p_eof',
- defaults={if_true=true}
+ defaults={if_true=false}
},
{
full_name='endofline', abbreviation='eol',
@@ -1638,6 +1640,7 @@ return {
type='string', scope={'buffer'},
secure=true,
alloced=true,
+ func=true,
varname='p_ofu',
defaults={if_true=""}
},
@@ -1653,6 +1656,7 @@ return {
short_desc=N_("function to be called for |g@| operator"),
type='string', scope={'global'},
secure=true,
+ func=true,
varname='p_opfunc',
defaults={if_true=""}
},
@@ -1835,6 +1839,8 @@ return {
full_name='quickfixtextfunc', abbreviation='qftf',
short_desc=N_("customize the quickfix window"),
type='string', scope={'global'},
+ secure=true,
+ func=true,
varname='p_qftf',
defaults={if_true=""}
},
@@ -2408,6 +2414,8 @@ return {
full_name='tagfunc', abbreviation='tfu',
short_desc=N_("function used to perform tag searches"),
type='string', scope={'buffer'},
+ secure=true,
+ func=true,
varname='p_tfu',
defaults={if_true=""}
},
@@ -2538,6 +2546,7 @@ return {
type='string', scope={'global', 'buffer'},
secure=true,
alloced=true,
+ func=true,
varname='p_tsrfu',
defaults={if_true=""}
},
diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c
index faafc546a4..ca6bff662d 100644
--- a/src/nvim/os/env.c
+++ b/src/nvim/os/env.c
@@ -837,10 +837,9 @@ const void *vim_env_iter(const char delim, const char *const val, const void *co
if (dirend == NULL) {
*len = strlen(varval);
return NULL;
- } else {
- *len = (size_t)(dirend - varval);
- return dirend + 1;
}
+ *len = (size_t)(dirend - varval);
+ return dirend + 1;
}
/// Iterates $PATH-like delimited list `val` in reverse order.
@@ -870,11 +869,10 @@ const void *vim_env_iter_rev(const char delim, const char *const val, const void
*len = varlen;
*dir = val;
return NULL;
- } else {
- *dir = colon + 1;
- *len = (size_t)(varend - colon);
- return colon - 1;
}
+ *dir = colon + 1;
+ *len = (size_t)(varend - colon);
+ return colon - 1;
}
/// @param[out] exe_name should be at least MAXPATHL in size
diff --git a/src/nvim/os/fileio.c b/src/nvim/os/fileio.c
index b1710737d0..280a9c2bee 100644
--- a/src/nvim/os/fileio.c
+++ b/src/nvim/os/fileio.c
@@ -71,6 +71,7 @@ int file_open(FileDescriptor *const ret_fp, const char *const fname, const int f
FLAG(flags, kFileReadOnly, O_RDONLY, kFalse, wr != kTrue);
#ifdef O_NOFOLLOW
FLAG(flags, kFileNoSymlink, O_NOFOLLOW, kNone, true);
+ FLAG(flags, kFileMkDir, O_CREAT|O_WRONLY, kTrue, !(flags & kFileCreateOnly));
#endif
#undef FLAG
// wr is used for kFileReadOnly flag, but on
@@ -78,6 +79,13 @@ int file_open(FileDescriptor *const ret_fp, const char *const fname, const int f
// `error: variable ‘wr’ set but not used [-Werror=unused-but-set-variable]`
(void)wr;
+ if (flags & kFileMkDir) {
+ int mkdir_ret = os_file_mkdir((char *)fname, 0755);
+ if (mkdir_ret < 0) {
+ return mkdir_ret;
+ }
+ }
+
const int fd = os_open(fname, os_open_flags, mode);
if (fd < 0) {
diff --git a/src/nvim/os/fileio.h b/src/nvim/os/fileio.h
index da23a54c4e..5e47bbf921 100644
--- a/src/nvim/os/fileio.h
+++ b/src/nvim/os/fileio.h
@@ -35,6 +35,7 @@ typedef enum {
///< be used with kFileCreateOnly.
kFileNonBlocking = 128, ///< Do not restart read() or write() syscall if
///< EAGAIN was encountered.
+ kFileMkDir = 256,
} FileOpenFlags;
static inline bool file_eof(const FileDescriptor *fp)
diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c
index 68e96eea6e..0cadabbb47 100644
--- a/src/nvim/os/fs.c
+++ b/src/nvim/os/fs.c
@@ -121,9 +121,8 @@ bool os_isrealdir(const char *name)
fs_loop_unlock();
if (S_ISLNK(request.statbuf.st_mode)) {
return false;
- } else {
- return S_ISDIR(request.statbuf.st_mode);
}
+ return S_ISDIR(request.statbuf.st_mode);
}
/// Check if the given path exists and is a directory.
@@ -249,9 +248,8 @@ bool os_can_exe(const char *name, char **abspath, bool use_path)
&& is_executable(name, abspath)) {
#endif
return true;
- } else {
- return false;
}
+ return false;
}
return is_executable_in_path(name, abspath);
@@ -756,9 +754,8 @@ int32_t os_getperm(const char *name)
int stat_result = os_stat(name, &statbuf);
if (stat_result == kLibuvSuccess) {
return (int32_t)statbuf.st_mode;
- } else {
- return stat_result;
}
+ return stat_result;
}
/// Set the permission of a file.
@@ -946,6 +943,37 @@ int os_mkdir_recurse(const char *const dir, int32_t mode, char **const failed_di
return 0;
}
+/// Create the parent directory of a file if it does not exist
+///
+/// @param[in] fname Full path of the file name whose parent directories
+/// we want to create
+/// @param[in] mode Permissions for the newly-created directory.
+///
+/// @return `0` for success, libuv error code for failure.
+int os_file_mkdir(char *fname, int32_t mode)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ if (!dir_of_file_exists((char_u *)fname)) {
+ char *tail = path_tail_with_sep(fname);
+ char *last_char = tail + strlen(tail) - 1;
+ if (vim_ispathsep(*last_char)) {
+ emsg(_(e_noname));
+ return -1;
+ }
+ char c = *tail;
+ *tail = NUL;
+ int r;
+ char *failed_dir;
+ if ((r = os_mkdir_recurse(fname, mode, &failed_dir) < 0)) {
+ semsg(_(e_mkdir), failed_dir, os_strerror(r));
+ xfree(failed_dir);
+ }
+ *tail = c;
+ return r;
+ }
+ return 0;
+}
+
/// Create a unique temporary directory.
///
/// @param[in] template Template of the path to the directory with XXXXXX
diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c
index cb0dba8cac..f8c1ee57ea 100644
--- a/src/nvim/os/input.c
+++ b/src/nvim/os/input.c
@@ -469,9 +469,8 @@ static InbufPollResult inbuf_poll(int ms, MultiQueue *events)
if (input_ready(events)) {
return kInputAvail;
- } else {
- return input_eof ? kInputEof : kInputNone;
}
+ return input_eof ? kInputEof : kInputNone;
}
void input_done(void)
diff --git a/src/nvim/path.c b/src/nvim/path.c
index f568ba8854..1413000680 100644
--- a/src/nvim/path.c
+++ b/src/nvim/path.c
@@ -33,8 +33,10 @@
#include "nvim/vim.h"
#include "nvim/window.h"
-#define URL_SLASH 1 // path_is_url() has found ":/"
-#define URL_BACKSLASH 2 // path_is_url() has found ":\\"
+enum {
+ URL_SLASH = 1, // path_is_url() has found ":/"
+ URL_BACKSLASH = 2, // path_is_url() has found ":\\"
+};
#ifdef gen_expand_wildcards
# undef gen_expand_wildcards
diff --git a/src/nvim/plines.c b/src/nvim/plines.c
index bed15f9e36..268e57927b 100644
--- a/src/nvim/plines.c
+++ b/src/nvim/plines.c
@@ -238,9 +238,8 @@ int win_chartabsize(win_T *wp, char *p, colnr_T col)
buf_T *buf = wp->w_buffer;
if (*p == TAB && (!wp->w_p_list || wp->w_p_lcs_chars.tab1)) {
return tabstop_padding(col, buf->b_p_ts, buf->b_p_vts_array);
- } else {
- return ptr2cells(p);
}
+ return ptr2cells(p);
}
/// Return the number of characters the string 's' will take on the screen,
diff --git a/src/nvim/popupmenu.c b/src/nvim/popupmenu.c
index 893ed38e25..234ce5fcba 100644
--- a/src/nvim/popupmenu.c
+++ b/src/nvim/popupmenu.c
@@ -762,12 +762,11 @@ static bool pum_set_selected(int n, int repeat)
if (e == NULL) {
ml_append(lnum++, (char *)p, 0, false);
break;
- } else {
- *e = NUL;
- ml_append(lnum++, (char *)p, (int)(e - p + 1), false);
- *e = '\n';
- p = e + 1;
}
+ *e = NUL;
+ ml_append(lnum++, (char *)p, (int)(e - p + 1), false);
+ *e = '\n';
+ p = e + 1;
}
// Increase the height of the preview window to show the
@@ -1044,10 +1043,16 @@ void pum_show_popupmenu(vimmenu_T *menu)
pumitem_T *array = (pumitem_T *)xcalloc((size_t)pum_size, sizeof(pumitem_T));
for (vimmenu_T *mp = menu->children; mp != NULL; mp = mp->next) {
+ char *s = NULL;
+ // Make a copy of the text, the menu may be redefined in a callback.
if (menu_is_separator(mp->dname)) {
- array[idx++].pum_text = (char_u *)"";
+ s = "";
} else if (mp->modes & mp->enabled & mode) {
- array[idx++].pum_text = (char_u *)mp->dname;
+ s = mp->dname;
+ }
+ if (s != NULL) {
+ s = xstrdup(s);
+ array[idx++].pum_text = (char_u *)s;
}
}
@@ -1118,6 +1123,9 @@ void pum_show_popupmenu(vimmenu_T *menu)
}
}
+ for (idx = 0; idx < pum_size; idx++) {
+ xfree(array[idx].pum_text);
+ }
xfree(array);
pum_undisplay(true);
if (!p_mousemev) {
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index 5d101ee415..9fdf7b348c 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -2153,12 +2153,11 @@ static char *qf_push_dir(char *dirbuf, struct dir_stack_T **stackptr, bool is_fi
if ((*stackptr)->dirname != NULL) {
return (*stackptr)->dirname;
- } else {
- ds_ptr = *stackptr;
- *stackptr = (*stackptr)->next;
- xfree(ds_ptr);
- return NULL;
}
+ ds_ptr = *stackptr;
+ *stackptr = (*stackptr)->next;
+ xfree(ds_ptr);
+ return NULL;
}
// pop dirbuf from the directory stack and return previous directory or NULL if
@@ -2706,11 +2705,10 @@ static int qf_jump_edit_buffer(qf_info_T *qi, qfline_T *qf_ptr, int forceit, int
if (!can_abandon(curbuf, forceit)) {
no_write_message();
return FAIL;
- } else {
- retval = do_ecmd(qf_ptr->qf_fnum, NULL, NULL, NULL, (linenr_T)1,
- ECMD_HIDE + ECMD_SET_HELP,
- prev_winid == curwin->handle ? curwin : NULL);
}
+ retval = do_ecmd(qf_ptr->qf_fnum, NULL, NULL, NULL, (linenr_T)1,
+ ECMD_HIDE + ECMD_SET_HELP,
+ prev_winid == curwin->handle ? curwin : NULL);
} else {
retval = buflist_getfile(qf_ptr->qf_fnum, (linenr_T)1,
GETF_SETMARK | GETF_SWITCH, forceit);
@@ -5140,11 +5138,10 @@ static bool vgr_qflist_valid(win_T *wp, qf_info_T *qi, unsigned qfid, char *titl
// An autocmd has freed the location list
emsg(_(e_current_location_list_was_changed));
return false;
- } else {
- // Quickfix list is not found, create a new one.
- qf_new_list(qi, title);
- return true;
}
+ // Quickfix list is not found, create a new one.
+ qf_new_list(qi, title);
+ return true;
}
if (qf_restore_list(qi, qfid) == FAIL) {
return false;
@@ -6686,7 +6683,8 @@ int set_errorlist(win_T *wp, list_T *list, int action, char *title, dict_T *what
return retval;
}
-/// Mark the context as in use for all the lists in a quickfix stack.
+/// Mark the quickfix context and callback function as in use for all the lists
+/// in a quickfix stack.
static bool mark_quickfix_ctx(qf_info_T *qi, int copyID)
{
bool abort = false;
@@ -6695,8 +6693,11 @@ static bool mark_quickfix_ctx(qf_info_T *qi, int copyID)
typval_T *ctx = qi->qf_lists[i].qf_ctx;
if (ctx != NULL && ctx->v_type != VAR_NUMBER
&& ctx->v_type != VAR_STRING && ctx->v_type != VAR_FLOAT) {
- abort = set_ref_in_item(ctx, copyID, NULL, NULL);
+ abort = abort || set_ref_in_item(ctx, copyID, NULL, NULL);
}
+
+ Callback *cb = &qi->qf_lists[i].qf_qftf_cb;
+ abort = abort || set_ref_in_callback(cb, copyID, NULL, NULL);
}
return abort;
@@ -6711,6 +6712,11 @@ bool set_ref_in_quickfix(int copyID)
return abort;
}
+ abort = set_ref_in_callback(&qftf_cb, copyID, NULL, NULL);
+ if (abort) {
+ return abort;
+ }
+
FOR_ALL_TAB_WINDOWS(tp, win) {
if (win->w_llist != NULL) {
abort = mark_quickfix_ctx(win->w_llist, copyID);
diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c
index 7a96889f22..27b5d198ac 100644
--- a/src/nvim/regexp.c
+++ b/src/nvim/regexp.c
@@ -1,9 +1,7 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-/*
- * Handling of regular expressions: vim_regcomp(), vim_regexec(), vim_regsub()
- */
+// Handling of regular expressions: vim_regcomp(), vim_regexec(), vim_regsub()
// By default: do not create debugging logs or files related to regular
// expressions, even when compiling with -DDEBUG.
@@ -41,21 +39,17 @@
# define BT_REGEXP_DEBUG_LOG_NAME "bt_regexp_debug.log"
#endif
-/*
- * Magic characters have a special meaning, they don't match literally.
- * Magic characters are negative. This separates them from literal characters
- * (possibly multi-byte). Only ASCII characters can be Magic.
- */
+// Magic characters have a special meaning, they don't match literally.
+// Magic characters are negative. This separates them from literal characters
+// (possibly multi-byte). Only ASCII characters can be Magic.
#define Magic(x) ((int)(x) - 256)
#define un_Magic(x) ((x) + 256)
#define is_Magic(x) ((x) < 0)
-/*
- * We should define ftpr as a pointer to a function returning a pointer to
- * a function returning a pointer to a function ...
- * This is impossible, so we declare a pointer to a function returning a
- * pointer to a function returning void. This should work for all compilers.
- */
+// We should define ftpr as a pointer to a function returning a pointer to
+// a function returning a pointer to a function ...
+// This is impossible, so we declare a pointer to a function returning a
+// pointer to a function returning void. This should work for all compilers.
typedef void (*(*fptr_T)(int *, int))(void);
static int no_Magic(int x)
@@ -143,28 +137,24 @@ static int re_multi_type(int c)
static char *reg_prev_sub = NULL;
-/*
- * REGEXP_INRANGE contains all characters which are always special in a []
- * range after '\'.
- * REGEXP_ABBR contains all characters which act as abbreviations after '\'.
- * These are:
- * \n - New line (NL).
- * \r - Carriage Return (CR).
- * \t - Tab (TAB).
- * \e - Escape (ESC).
- * \b - Backspace (Ctrl_H).
- * \d - Character code in decimal, eg \d123
- * \o - Character code in octal, eg \o80
- * \x - Character code in hex, eg \x4a
- * \u - Multibyte character code, eg \u20ac
- * \U - Long multibyte character code, eg \U12345678
- */
+// REGEXP_INRANGE contains all characters which are always special in a []
+// range after '\'.
+// REGEXP_ABBR contains all characters which act as abbreviations after '\'.
+// These are:
+// \n - New line (NL).
+// \r - Carriage Return (CR).
+// \t - Tab (TAB).
+// \e - Escape (ESC).
+// \b - Backspace (Ctrl_H).
+// \d - Character code in decimal, eg \d123
+// \o - Character code in octal, eg \o80
+// \x - Character code in hex, eg \x4a
+// \u - Multibyte character code, eg \u20ac
+// \U - Long multibyte character code, eg \U12345678
static char REGEXP_INRANGE[] = "]^-n\\";
static char REGEXP_ABBR[] = "nrtebdoxuU";
-/*
- * Translate '\x' to its control character, except "\n", which is Magic.
- */
+// Translate '\x' to its control character, except "\n", which is Magic.
static int backslash_trans(int c)
{
switch (c) {
@@ -239,10 +229,8 @@ static int get_char_class(char **pp)
return CLASS_NONE;
}
-/*
- * Specific version of character class functions.
- * Using a table to keep this fast.
- */
+// Specific version of character class functions.
+// Using a table to keep this fast.
static int16_t class_tab[256];
#define RI_DIGIT 0x01
@@ -325,9 +313,7 @@ static int reg_string; // matching with a string instead of a buffer
// line
static int reg_strict; // "[abc" is illegal
-/*
- * META contains all characters that may be magic, except '^' and '$'.
- */
+// META contains all characters that may be magic, except '^' and '$'.
// uncrustify:off
@@ -391,11 +377,9 @@ int re_multiline(const regprog_T *prog)
return prog->regflags & RF_HASNL;
}
-/*
- * Check for an equivalence class name "[=a=]". "pp" points to the '['.
- * Returns a character representing the class. Zero means that no item was
- * recognized. Otherwise "pp" is advanced to after the item.
- */
+// Check for an equivalence class name "[=a=]". "pp" points to the '['.
+// Returns a character representing the class. Zero means that no item was
+// recognized. Otherwise "pp" is advanced to after the item.
static int get_equi_class(char **pp)
{
int c;
@@ -413,12 +397,10 @@ static int get_equi_class(char **pp)
return 0;
}
-/*
- * Check for a collating element "[.a.]". "pp" points to the '['.
- * Returns a character. Zero means that no item was recognized. Otherwise
- * "pp" is advanced to after the item.
- * Currently only single characters are recognized!
- */
+// Check for a collating element "[.a.]". "pp" points to the '['.
+// Returns a character. Zero means that no item was recognized. Otherwise
+// "pp" is advanced to after the item.
+// Currently only single characters are recognized!
static int get_coll_element(char **pp)
{
int c;
@@ -562,9 +544,7 @@ static int prevchr_len; // byte length of previous char
static int at_start; // True when on the first character
static int prev_at_start; // True when on the second character
-/*
- * Start parsing at "str".
- */
+// Start parsing at "str".
static void initchr(char_u *str)
{
regparse = (char *)str;
@@ -574,10 +554,8 @@ static void initchr(char_u *str)
prev_at_start = false;
}
-/*
- * Save the current parse state, so that it can be restored and parsing
- * starts in the same state again.
- */
+// Save the current parse state, so that it can be restored and parsing
+// starts in the same state again.
static void save_parse_state(parse_state_T *ps)
{
ps->regparse = (char_u *)regparse;
@@ -591,9 +569,7 @@ static void save_parse_state(parse_state_T *ps)
ps->regnpar = regnpar;
}
-/*
- * Restore a previously saved parse state.
- */
+// Restore a previously saved parse state.
static void restore_parse_state(parse_state_T *ps)
{
regparse = (char *)ps->regparse;
@@ -607,9 +583,7 @@ static void restore_parse_state(parse_state_T *ps)
regnpar = ps->regnpar;
}
-/*
- * Get the next character without advancing.
- */
+// Get the next character without advancing.
static int peekchr(void)
{
static int after_slash = false;
@@ -736,9 +710,7 @@ static int peekchr(void)
after_slash--;
curchr = toggle_Magic(curchr);
} else if (vim_strchr(REGEXP_ABBR, c)) {
- /*
- * Handle abbreviations, like "\t" for TAB -- webb
- */
+ // Handle abbreviations, like "\t" for TAB -- webb
curchr = backslash_trans(c);
} else if (reg_magic == MAGIC_NONE && (c == '$' || c == '^')) {
curchr = toggle_Magic(c);
@@ -757,9 +729,7 @@ static int peekchr(void)
return curchr;
}
-/*
- * Eat one lexed character. Do this in a way that we can undo it.
- */
+// Eat one lexed character. Do this in a way that we can undo it.
static void skipchr(void)
{
// peekchr() eats a backslash, do the same here
@@ -781,10 +751,8 @@ static void skipchr(void)
nextchr = -1;
}
-/*
- * Skip a character while keeping the value of prev_at_start for at_start.
- * prevchr and prevprevchr are also kept.
- */
+// Skip a character while keeping the value of prev_at_start for at_start.
+// prevchr and prevprevchr are also kept.
static void skipchr_keepstart(void)
{
int as = prev_at_start;
@@ -797,10 +765,8 @@ static void skipchr_keepstart(void)
prevprevchr = prpr;
}
-/*
- * Get the next character from the pattern. We know about magic and such, so
- * therefore we need a lexical analyzer.
- */
+// Get the next character from the pattern. We know about magic and such, so
+// therefore we need a lexical analyzer.
static int getchr(void)
{
int chr = peekchr();
@@ -809,9 +775,7 @@ static int getchr(void)
return chr;
}
-/*
- * put character back. Works only once!
- */
+// put character back. Works only once!
static void ungetchr(void)
{
nextchr = curchr;
@@ -825,15 +789,13 @@ static void ungetchr(void)
regparse -= prevchr_len;
}
-/*
- * Get and return the value of the hex string at the current position.
- * Return -1 if there is no valid hex number.
- * The position is updated:
- * blahblah\%x20asdf
- * before-^ ^-after
- * The parameter controls the maximum number of input characters. This will be
- * 2 when reading a \%x20 sequence and 4 when reading a \%u20AC sequence.
- */
+// Get and return the value of the hex string at the current position.
+// Return -1 if there is no valid hex number.
+// The position is updated:
+// blahblah\%x20asdf
+// before-^ ^-after
+// The parameter controls the maximum number of input characters. This will be
+// 2 when reading a \%x20 sequence and 4 when reading a \%u20AC sequence.
static int64_t gethexchrs(int maxinputlen)
{
int64_t nr = 0;
@@ -856,10 +818,8 @@ static int64_t gethexchrs(int maxinputlen)
return nr;
}
-/*
- * Get and return the value of the decimal string immediately after the
- * current position. Return -1 for invalid. Consumes all digits.
- */
+// Get and return the value of the decimal string immediately after the
+// current position. Return -1 for invalid. Consumes all digits.
static int64_t getdecchrs(void)
{
int64_t nr = 0;
@@ -883,14 +843,12 @@ static int64_t getdecchrs(void)
return nr;
}
-/*
- * get and return the value of the octal string immediately after the current
- * position. Return -1 for invalid, or 0-255 for valid. Smart enough to handle
- * numbers > 377 correctly (for example, 400 is treated as 40) and doesn't
- * treat 8 or 9 as recognised characters. Position is updated:
- * blahblah\%o210asdf
- * before-^ ^-after
- */
+// get and return the value of the octal string immediately after the current
+// position. Return -1 for invalid, or 0-255 for valid. Smart enough to handle
+// numbers > 377 correctly (for example, 400 is treated as 40) and doesn't
+// treat 8 or 9 as recognised characters. Position is updated:
+// blahblah\%o210asdf
+// before-^ ^-after
static int64_t getoctchrs(void)
{
int64_t nr = 0;
@@ -913,12 +871,10 @@ static int64_t getoctchrs(void)
return nr;
}
-/*
- * read_limits - Read two integers to be taken as a minimum and maximum.
- * If the first character is '-', then the range is reversed.
- * Should end with 'end'. If minval is missing, zero is default, if maxval is
- * missing, a very big number is the default.
- */
+// read_limits - Read two integers to be taken as a minimum and maximum.
+// If the first character is '-', then the range is reversed.
+// Should end with 'end'. If minval is missing, zero is default, if maxval is
+// missing, a very big number is the default.
static int read_limits(long *minval, long *maxval)
{
int reverse = false;
@@ -950,10 +906,8 @@ static int read_limits(long *minval, long *maxval)
EMSG2_RET_FAIL(_("E554: Syntax error in %s{...}"), reg_magic == MAGIC_ALL);
}
- /*
- * Reverse the range if there was a '-', or make sure it is in the right
- * order otherwise.
- */
+ // Reverse the range if there was a '-', or make sure it is in the right
+ // order otherwise.
if ((!reverse && *minval > *maxval) || (reverse && *minval < *maxval)) {
tmp = *minval;
*minval = *maxval;
@@ -963,13 +917,9 @@ static int read_limits(long *minval, long *maxval)
return OK;
}
-/*
- * vim_regexec and friends
- */
+// vim_regexec and friends
-/*
- * Global work variables for vim_regexec().
- */
+// Global work variables for vim_regexec().
// Sometimes need to save a copy of a line. Since alloc()/free() is very
// slow, we keep one allocated piece of memory and only re-allocate it when
@@ -1052,9 +1002,7 @@ static bool reg_iswordc(int c)
return vim_iswordc_buf(c, rex.reg_buf);
}
-/*
- * Get pointer to the line "lnum", which is relative to "reg_firstlnum".
- */
+// Get pointer to the line "lnum", which is relative to "reg_firstlnum".
static char_u *reg_getline(linenr_T lnum)
{
// when looking behind for a match/no-match lnum is negative. But we
@@ -1077,9 +1025,7 @@ static lpos_T reg_endzpos[NSUBEXP]; // idem, end pos
// true if using multi-line regexp.
#define REG_MULTI (rex.reg_match == NULL)
-/*
- * Create a new extmatch and mark it as referenced once.
- */
+// Create a new extmatch and mark it as referenced once.
static reg_extmatch_T *make_extmatch(void)
FUNC_ATTR_NONNULL_RET
{
@@ -1088,9 +1034,7 @@ static reg_extmatch_T *make_extmatch(void)
return em;
}
-/*
- * Add a reference to an extmatch.
- */
+// Add a reference to an extmatch.
reg_extmatch_T *ref_extmatch(reg_extmatch_T *em)
{
if (em != NULL) {
@@ -1099,10 +1043,8 @@ reg_extmatch_T *ref_extmatch(reg_extmatch_T *em)
return em;
}
-/*
- * Remove a reference to an extmatch. If there are no references left, free
- * the info.
- */
+// Remove a reference to an extmatch. If there are no references left, free
+// the info.
void unref_extmatch(reg_extmatch_T *em)
{
int i;
@@ -1201,10 +1143,8 @@ static bool reg_match_visual(void)
return true;
}
-/*
- * Check the regexp program for its magic number.
- * Return true if it's wrong.
- */
+// Check the regexp program for its magic number.
+// Return true if it's wrong.
static int prog_magic_wrong(void)
{
regprog_T *prog;
@@ -1222,11 +1162,9 @@ static int prog_magic_wrong(void)
return false;
}
-/*
- * Cleanup the subexpressions, if this wasn't done yet.
- * This construction is used to clear the subexpressions only when they are
- * used (to increase speed).
- */
+// Cleanup the subexpressions, if this wasn't done yet.
+// This construction is used to clear the subexpressions only when they are
+// used (to increase speed).
static void cleanup_subexpr(void)
{
if (rex.need_clear_subexpr) {
@@ -1265,12 +1203,10 @@ static void reg_nextline(void)
fast_breakcheck();
}
-/*
- * Check whether a backreference matches.
- * Returns RA_FAIL, RA_NOMATCH or RA_MATCH.
- * If "bytelen" is not NULL, it is set to the byte length of the match in the
- * last line.
- */
+// Check whether a backreference matches.
+// Returns RA_FAIL, RA_NOMATCH or RA_MATCH.
+// If "bytelen" is not NULL, it is set to the byte length of the match in the
+// last line.
static int match_with_backref(linenr_T start_lnum, colnr_T start_col, linenr_T end_lnum,
colnr_T end_col, int *bytelen)
{
@@ -1449,9 +1385,9 @@ static int cstrncmp(char *s1, char *s2, int *n)
c1 = mb_ptr2char_adv((const char_u **)&str1);
c2 = mb_ptr2char_adv((const char_u **)&str2);
- /* decompose the character if necessary, into 'base' characters
- * because I don't care about Arabic, I will hard-code the Hebrew
- * which I *do* care about! So sue me... */
+ // decompose the character if necessary, into 'base' characters
+ // because I don't care about Arabic, I will hard-code the Hebrew
+ // which I *do* care about! So sue me...
if (c1 != c2 && (!rex.reg_ic || utf_fold(c1) != utf_fold(c2))) {
// decomposition necessary?
mb_decompose(c1, &c11, &junk, &junk);
@@ -1566,7 +1502,7 @@ char *regtilde(char *source, int magic, bool preview)
int len;
int prevlen;
- for (p = newsub; *p; ++p) {
+ for (p = newsub; *p; p++) {
if ((*p == '~' && magic) || (*p == '\\' && *(p + 1) == '~' && !magic)) {
if (reg_prev_sub != NULL) {
// length = len(newsub) - 1 + len(prev_sub) + 1
@@ -1871,12 +1807,11 @@ static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest, int des
*s = CAR;
} else if (*s == '\\' && s[1] != NUL) {
s++;
- /* Change NL to CR here too, so that this works:
- * :s/abc\\\ndef/\="aaa\\\nbbb"/ on text:
- * abc\
- * def
- * Not when called from vim_regexec_nl().
- */
+ // Change NL to CR here too, so that this works:
+ // :s/abc\\\ndef/\="aaa\\\nbbb"/ on text:
+ // abc{backslash}
+ // def
+ // Not when called from vim_regexec_nl().
if (*s == NL && !rsm.sm_line_lbr) {
*s = CAR;
}
@@ -2172,10 +2107,8 @@ char *reg_submatch(int no)
if (rsm.sm_match == NULL) {
ssize_t len;
- /*
- * First round: compute the length and allocate memory.
- * Second round: copy the text.
- */
+ // First round: compute the length and allocate memory.
+ // Second round: copy the text.
for (round = 1; round <= 2; round++) {
lnum = rsm.sm_mmatch->startpos[no].lnum;
if (lnum < 0 || rsm.sm_mmatch->endpos[no].lnum < 0) {
@@ -2216,7 +2149,7 @@ char *reg_submatch(int no)
len++;
}
if (round == 2) {
- STRNCPY(retval + len, reg_getline_submatch(lnum),
+ STRNCPY(retval + len, reg_getline_submatch(lnum), // NOLINT(runtime/printf)
rsm.sm_mmatch->endpos[no].col);
}
len += rsm.sm_mmatch->endpos[no].col;
@@ -2327,12 +2260,10 @@ static char_u regname[][30] = {
};
#endif
-/*
- * Compile a regular expression into internal code.
- * Returns the program in allocated memory.
- * Use vim_regfree() to free the memory.
- * Returns NULL for an error.
- */
+// Compile a regular expression into internal code.
+// Returns the program in allocated memory.
+// Use vim_regfree() to free the memory.
+// Returns NULL for an error.
regprog_T *vim_regcomp(char *expr_arg, int re_flags)
{
regprog_T *prog = NULL;
@@ -2413,9 +2344,7 @@ regprog_T *vim_regcomp(char *expr_arg, int re_flags)
return prog;
}
-/*
- * Free a compiled regexp program, returned by vim_regcomp().
- */
+// Free a compiled regexp program, returned by vim_regcomp().
void vim_regfree(regprog_T *prog)
{
if (prog != NULL) {
diff --git a/src/nvim/regexp_bt.c b/src/nvim/regexp_bt.c
index 6f63b38a90..7b5f4cd12a 100644
--- a/src/nvim/regexp_bt.c
+++ b/src/nvim/regexp_bt.c
@@ -1,137 +1,130 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-/*
- *
- * Backtracking regular expression implementation.
- *
- * This file is included in "regexp.c".
- *
- * NOTICE:
- *
- * This is NOT the original regular expression code as written by Henry
- * Spencer. This code has been modified specifically for use with the VIM
- * editor, and should not be used separately from Vim. If you want a good
- * regular expression library, get the original code. The copyright notice
- * that follows is from the original.
- *
- * END NOTICE
- *
- * Copyright (c) 1986 by University of Toronto.
- * Written by Henry Spencer. Not derived from licensed software.
- *
- * Permission is granted to anyone to use this software for any
- * purpose on any computer system, and to redistribute it freely,
- * subject to the following restrictions:
- *
- * 1. The author is not responsible for the consequences of use of
- * this software, no matter how awful, even if they arise
- * from defects in it.
- *
- * 2. The origin of this software must not be misrepresented, either
- * by explicit claim or by omission.
- *
- * 3. Altered versions must be plainly marked as such, and must not
- * be misrepresented as being the original software.
- *
- * Beware that some of this code is subtly aware of the way operator
- * precedence is structured in regular expressions. Serious changes in
- * regular-expression syntax might require a total rethink.
- *
- * Changes have been made by Tony Andrews, Olaf 'Rhialto' Seibert, Robert
- * Webb, Ciaran McCreesh and Bram Moolenaar.
- * Named character class support added by Walter Briscoe (1998 Jul 01)
- */
-
-/*
- * The "internal use only" fields in regexp_defs.h are present to pass info from
- * compile to execute that permits the execute phase to run lots faster on
- * simple cases. They are:
- *
- * regstart char that must begin a match; NUL if none obvious; Can be a
- * multi-byte character.
- * reganch is the match anchored (at beginning-of-line only)?
- * regmust string (pointer into program) that match must include, or NULL
- * regmlen length of regmust string
- * regflags RF_ values or'ed together
- *
- * Regstart and reganch permit very fast decisions on suitable starting points
- * for a match, cutting down the work a lot. Regmust permits fast rejection
- * of lines that cannot possibly match. The regmust tests are costly enough
- * that vim_regcomp() supplies a regmust only if the r.e. contains something
- * potentially expensive (at present, the only such thing detected is * or +
- * at the start of the r.e., which can involve a lot of backup). Regmlen is
- * supplied because the test in vim_regexec() needs it and vim_regcomp() is
- * computing it anyway.
- */
-
-/*
- * Structure for regexp "program". This is essentially a linear encoding
- * of a nondeterministic finite-state machine (aka syntax charts or
- * "railroad normal form" in parsing technology). Each node is an opcode
- * plus a "next" pointer, possibly plus an operand. "Next" pointers of
- * all nodes except BRANCH and BRACES_COMPLEX implement concatenation; a "next"
- * pointer with a BRANCH on both ends of it is connecting two alternatives.
- * (Here we have one of the subtle syntax dependencies: an individual BRANCH
- * (as opposed to a collection of them) is never concatenated with anything
- * because of operator precedence). The "next" pointer of a BRACES_COMPLEX
- * node points to the node after the stuff to be repeated.
- * The operand of some types of node is a literal string; for others, it is a
- * node leading into a sub-FSM. In particular, the operand of a BRANCH node
- * is the first node of the branch.
- * (NB this is *not* a tree structure: the tail of the branch connects to the
- * thing following the set of BRANCHes.)
- *
- * pattern is coded like:
- *
- * +-----------------+
- * | V
- * <aa>\|<bb> BRANCH <aa> BRANCH <bb> --> END
- * | ^ | ^
- * +------+ +----------+
- *
- *
- * +------------------+
- * V |
- * <aa>* BRANCH BRANCH <aa> --> BACK BRANCH --> NOTHING --> END
- * | | ^ ^
- * | +---------------+ |
- * +---------------------------------------------+
- *
- *
- * +----------------------+
- * V |
- * <aa>\+ BRANCH <aa> --> BRANCH --> BACK BRANCH --> NOTHING --> END
- * | | ^ ^
- * | +-----------+ |
- * +--------------------------------------------------+
- *
- *
- * +-------------------------+
- * V |
- * <aa>\{} BRANCH BRACE_LIMITS --> BRACE_COMPLEX <aa> --> BACK END
- * | | ^
- * | +----------------+
- * +-----------------------------------------------+
- *
- *
- * <aa>\@!<bb> BRANCH NOMATCH <aa> --> END <bb> --> END
- * | | ^ ^
- * | +----------------+ |
- * +--------------------------------+
- *
- * +---------+
- * | V
- * \z[abc] BRANCH BRANCH a BRANCH b BRANCH c BRANCH NOTHING --> END
- * | | | | ^ ^
- * | | | +-----+ |
- * | | +----------------+ |
- * | +---------------------------+ |
- * +------------------------------------------------------+
- *
- * They all start with a BRANCH for "\|" alternatives, even when there is only
- * one alternative.
- */
+// Backtracking regular expression implementation.
+//
+// This file is included in "regexp.c".
+//
+// NOTICE:
+//
+// This is NOT the original regular expression code as written by Henry
+// Spencer. This code has been modified specifically for use with the VIM
+// editor, and should not be used separately from Vim. If you want a good
+// regular expression library, get the original code. The copyright notice
+// that follows is from the original.
+//
+// END NOTICE
+//
+// Copyright (c) 1986 by University of Toronto.
+// Written by Henry Spencer. Not derived from licensed software.
+//
+// Permission is granted to anyone to use this software for any
+// purpose on any computer system, and to redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. The author is not responsible for the consequences of use of
+// this software, no matter how awful, even if they arise
+// from defects in it.
+//
+// 2. The origin of this software must not be misrepresented, either
+// by explicit claim or by omission.
+//
+// 3. Altered versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// Beware that some of this code is subtly aware of the way operator
+// precedence is structured in regular expressions. Serious changes in
+// regular-expression syntax might require a total rethink.
+//
+// Changes have been made by Tony Andrews, Olaf 'Rhialto' Seibert, Robert
+// Webb, Ciaran McCreesh and Bram Moolenaar.
+// Named character class support added by Walter Briscoe (1998 Jul 01)
+
+// The "internal use only" fields in regexp_defs.h are present to pass info from
+// compile to execute that permits the execute phase to run lots faster on
+// simple cases. They are:
+//
+// regstart char that must begin a match; NUL if none obvious; Can be a
+// multi-byte character.
+// reganch is the match anchored (at beginning-of-line only)?
+// regmust string (pointer into program) that match must include, or NULL
+// regmlen length of regmust string
+// regflags RF_ values or'ed together
+//
+// Regstart and reganch permit very fast decisions on suitable starting points
+// for a match, cutting down the work a lot. Regmust permits fast rejection
+// of lines that cannot possibly match. The regmust tests are costly enough
+// that vim_regcomp() supplies a regmust only if the r.e. contains something
+// potentially expensive (at present, the only such thing detected is * or +
+// at the start of the r.e., which can involve a lot of backup). Regmlen is
+// supplied because the test in vim_regexec() needs it and vim_regcomp() is
+// computing it anyway.
+
+// Structure for regexp "program". This is essentially a linear encoding
+// of a nondeterministic finite-state machine (aka syntax charts or
+// "railroad normal form" in parsing technology). Each node is an opcode
+// plus a "next" pointer, possibly plus an operand. "Next" pointers of
+// all nodes except BRANCH and BRACES_COMPLEX implement concatenation; a "next"
+// pointer with a BRANCH on both ends of it is connecting two alternatives.
+// (Here we have one of the subtle syntax dependencies: an individual BRANCH
+// (as opposed to a collection of them) is never concatenated with anything
+// because of operator precedence). The "next" pointer of a BRACES_COMPLEX
+// node points to the node after the stuff to be repeated.
+// The operand of some types of node is a literal string; for others, it is a
+// node leading into a sub-FSM. In particular, the operand of a BRANCH node
+// is the first node of the branch.
+// (NB this is *not* a tree structure: the tail of the branch connects to the
+// thing following the set of BRANCHes.)
+//
+// pattern is coded like:
+//
+// +-----------------+
+// | V
+// <aa>\|<bb> BRANCH <aa> BRANCH <bb> --> END
+// | ^ | ^
+// +------+ +----------+
+//
+//
+// +------------------+
+// V |
+// <aa>* BRANCH BRANCH <aa> --> BACK BRANCH --> NOTHING --> END
+// | | ^ ^
+// | +---------------+ |
+// +---------------------------------------------+
+//
+//
+// +----------------------+
+// V |
+// <aa>\+ BRANCH <aa> --> BRANCH --> BACK BRANCH --> NOTHING --> END
+// | | ^ ^
+// | +-----------+ |
+// +--------------------------------------------------+
+//
+//
+// +-------------------------+
+// V |
+// <aa>\{} BRANCH BRACE_LIMITS --> BRACE_COMPLEX <aa> --> BACK END
+// | | ^
+// | +----------------+
+// +-----------------------------------------------+
+//
+//
+// <aa>\@!<bb> BRANCH NOMATCH <aa> --> END <bb> --> END
+// | | ^ ^
+// | +----------------+ |
+// +--------------------------------+
+//
+// +---------+
+// | V
+// \z[abc] BRANCH BRANCH a BRANCH b BRANCH c BRANCH NOTHING --> END
+// | | | | ^ ^
+// | | | +-----+ |
+// | | +----------------+ |
+// | +---------------------------+ |
+// +------------------------------------------------------+
+//
+// They all start with a BRANCH for "\|" alternatives, even when there is only
+// one alternative.
#include <assert.h>
#include <inttypes.h>
@@ -141,9 +134,7 @@
#include "nvim/garray.h"
#include "nvim/regexp.h"
-/*
- * The opcodes are:
- */
+// The opcodes are:
// definition number opnd? meaning
#define END 0 // End of program or NOMATCH operand.
@@ -240,9 +231,7 @@
#define RE_VISUAL 208 // Match Visual area
#define RE_COMPOSING 209 // any composing characters
-/*
- * Flags to be passed up and down.
- */
+// Flags to be passed up and down.
#define HASWIDTH 0x1 // Known never to match null string.
#define SIMPLE 0x2 // Simple enough to be STAR/PLUS operand.
#define SPSTART 0x4 // Starts with * or +.
@@ -273,10 +262,8 @@ static int classcodes[] = {
UPPER, NUPPER
};
-/*
- * When regcode is set to this value, code is not emitted and size is computed
- * instead.
- */
+// When regcode is set to this value, code is not emitted and size is computed
+// instead.
#define JUST_CALC_SIZE ((char_u *)-1)
// Values for rs_state in regitem_T.
@@ -297,11 +284,9 @@ typedef enum regstate_E {
RS_STAR_SHORT, // STAR/PLUS/BRACE_SIMPLE shortest match
} regstate_T;
-/*
- * Structure used to save the current input state, when it needs to be
- * restored after trying a match. Used by reg_save() and reg_restore().
- * Also stores the length of "backpos".
- */
+// Structure used to save the current input state, when it needs to be
+// restored after trying a match. Used by reg_save() and reg_restore().
+// Also stores the length of "backpos".
typedef struct {
union {
char_u *ptr; // rex.input pointer, for single-line regexp
@@ -327,12 +312,10 @@ typedef struct regbehind_S {
save_se_T save_end[NSUBEXP];
} regbehind_T;
-/*
- * When there are alternatives a regstate_T is put on the regstack to remember
- * what we are doing.
- * Before it may be another type of item, depending on rs_state, to remember
- * more things.
- */
+// When there are alternatives a regstate_T is put on the regstack to remember
+// what we are doing.
+// Before it may be another type of item, depending on rs_state, to remember
+// more things.
typedef struct regitem_S {
regstate_T rs_state; // what we are doing, one of RS_ above
int16_t rs_no; // submatch nr or BEHIND/NOBEHIND
@@ -359,69 +342,63 @@ typedef struct backpos_S {
regsave_T bp_pos; // last input position
} backpos_T;
-/*
- * "regstack" and "backpos" are used by regmatch(). They are kept over calls
- * to avoid invoking malloc() and free() often.
- * "regstack" is a stack with regitem_T items, sometimes preceded by regstar_T
- * or regbehind_T.
- * "backpos_T" is a table with backpos_T for BACK
- */
+// "regstack" and "backpos" are used by regmatch(). They are kept over calls
+// to avoid invoking malloc() and free() often.
+// "regstack" is a stack with regitem_T items, sometimes preceded by regstar_T
+// or regbehind_T.
+// "backpos_T" is a table with backpos_T for BACK
static garray_T regstack = GA_EMPTY_INIT_VALUE;
static garray_T backpos = GA_EMPTY_INIT_VALUE;
static regsave_T behind_pos;
-/*
- * Both for regstack and backpos tables we use the following strategy of
- * allocation (to reduce malloc/free calls):
- * - Initial size is fairly small.
- * - When needed, the tables are grown bigger (8 times at first, double after
- * that).
- * - After executing the match we free the memory only if the array has grown.
- * Thus the memory is kept allocated when it's at the initial size.
- * This makes it fast while not keeping a lot of memory allocated.
- * A three times speed increase was observed when using many simple patterns.
- */
+// Both for regstack and backpos tables we use the following strategy of
+// allocation (to reduce malloc/free calls):
+// - Initial size is fairly small.
+// - When needed, the tables are grown bigger (8 times at first, double after
+// that).
+// - After executing the match we free the memory only if the array has grown.
+// Thus the memory is kept allocated when it's at the initial size.
+// This makes it fast while not keeping a lot of memory allocated.
+// A three times speed increase was observed when using many simple patterns.
#define REGSTACK_INITIAL 2048
#define BACKPOS_INITIAL 64
-/*
- * Opcode notes:
- *
- * BRANCH The set of branches constituting a single choice are hooked
- * together with their "next" pointers, since precedence prevents
- * anything being concatenated to any individual branch. The
- * "next" pointer of the last BRANCH in a choice points to the
- * thing following the whole choice. This is also where the
- * final "next" pointer of each individual branch points; each
- * branch starts with the operand node of a BRANCH node.
- *
- * BACK Normal "next" pointers all implicitly point forward; BACK
- * exists to make loop structures possible.
- *
- * STAR,PLUS '=', and complex '*' and '+', are implemented as circular
- * BRANCH structures using BACK. Simple cases (one character
- * per match) are implemented with STAR and PLUS for speed
- * and to minimize recursive plunges.
- *
- * BRACE_LIMITS This is always followed by a BRACE_SIMPLE or BRACE_COMPLEX
- * node, and defines the min and max limits to be used for that
- * node.
- *
- * MOPEN,MCLOSE ...are numbered at compile time.
- * ZOPEN,ZCLOSE ...ditto
- */
-
-/*
- * A node is one char of opcode followed by two chars of "next" pointer.
- * "Next" pointers are stored as two 8-bit bytes, high order first. The
- * value is a positive offset from the opcode of the node containing it.
- * An operand, if any, simply follows the node. (Note that much of the
- * code generation knows about this implicit relationship.)
- *
- * Using two bytes for the "next" pointer is vast overkill for most things,
- * but allows patterns to get big without disasters.
- */
+// Opcode notes:
+//
+// BRANCH The set of branches constituting a single choice are hooked
+// together with their "next" pointers, since precedence prevents
+// anything being concatenated to any individual branch. The
+// "next" pointer of the last BRANCH in a choice points to the
+// thing following the whole choice. This is also where the
+// final "next" pointer of each individual branch points; each
+// branch starts with the operand node of a BRANCH node.
+//
+// BACK Normal "next" pointers all implicitly point forward; BACK
+// exists to make loop structures possible.
+//
+// STAR,PLUS '=', and complex '*' and '+', are implemented as circular
+// BRANCH structures using BACK. Simple cases (one character
+// per match) are implemented with STAR and PLUS for speed
+// and to minimize recursive plunges.
+//
+// BRACE_LIMITS This is always followed by a BRACE_SIMPLE or BRACE_COMPLEX
+// node, and defines the min and max limits to be used for that
+// node.
+//
+// MOPEN,MCLOSE ...are numbered at compile time.
+// ZOPEN,ZCLOSE ...ditto
+///
+//
+//
+// A node is one char of opcode followed by two chars of "next" pointer.
+// "Next" pointers are stored as two 8-bit bytes, high order first. The
+// value is a positive offset from the opcode of the node containing it.
+// An operand, if any, simply follows the node. (Note that much of the
+// code generation knows about this implicit relationship.)
+//
+// Using two bytes for the "next" pointer is vast overkill for most things,
+// but allows patterns to get big without disasters.
#define OP(p) ((int)(*(p)))
#define NEXT(p) (((*((p) + 1) & 0377) << 8) + (*((p) + 2) & 0377))
#define OPERAND(p) ((p) + 3)
@@ -449,9 +426,7 @@ static int regnarrate = 0;
# include "regexp_bt.c.generated.h"
#endif
-/*
- * Setup to parse the regexp. Used once to get the length and once to do it.
- */
+// Setup to parse the regexp. Used once to get the length and once to do it.
static void regcomp_start(char_u *expr, int re_flags) // see vim_regcomp()
{
initchr(expr);
@@ -484,9 +459,7 @@ static bool use_multibytecode(int c)
|| utf_iscomposing(c));
}
-/*
- * Emit (if appropriate) a byte of code
- */
+// Emit (if appropriate) a byte of code
static void regc(int b)
{
if (regcode == JUST_CALC_SIZE) {
@@ -496,9 +469,7 @@ static void regc(int b)
}
}
-/*
- * Emit (if appropriate) a multi-byte character of code
- */
+// Emit (if appropriate) a multi-byte character of code
static void regmbc(int c)
{
if (regcode == JUST_CALC_SIZE) {
@@ -508,11 +479,9 @@ static void regmbc(int c)
}
}
-/*
- * Produce the bytes for equivalence class "c".
- * Currently only handles latin1, latin9 and utf-8.
- * NOTE: When changing this function, also change nfa_emit_equi_class()
- */
+// Produce the bytes for equivalence class "c".
+// Currently only handles latin1, latin9 and utf-8.
+// NOTE: When changing this function, also change nfa_emit_equi_class()
static void reg_equi_class(int c)
{
{
@@ -1481,10 +1450,8 @@ static void reg_equi_class(int c)
regmbc(c);
}
-/*
- * Emit a node.
- * Return pointer to generated code.
- */
+// Emit a node.
+// Return pointer to generated code.
static char_u *regnode(int op)
{
char_u *ret;
@@ -1500,9 +1467,7 @@ static char_u *regnode(int op)
return ret;
}
-/*
- * Write a four bytes number at "p" and return pointer to the next char.
- */
+// Write a four bytes number at "p" and return pointer to the next char.
static char_u *re_put_uint32(char_u *p, uint32_t val)
{
*p++ = (char_u)((val >> 24) & 0377);
@@ -1512,11 +1477,9 @@ static char_u *re_put_uint32(char_u *p, uint32_t val)
return p;
}
-/*
- * regnext - dig the "next" pointer out of a node
- * Returns NULL when calculating size, when there is no next item and when
- * there is an error.
- */
+// regnext - dig the "next" pointer out of a node
+// Returns NULL when calculating size, when there is no next item and when
+// there is an error.
static char_u *regnext(char_u *p)
FUNC_ATTR_NONNULL_ALL
{
@@ -1573,9 +1536,7 @@ static void regtail(char_u *p, char_u *val)
}
}
-/*
- * Like regtail, on item after a BRANCH; nop if none.
- */
+// Like regtail, on item after a BRANCH; nop if none.
static void regoptail(char_u *p, char_u *val)
{
// When op is neither BRANCH nor BRACE_COMPLEX0-9, it is "operandless"
@@ -1587,11 +1548,9 @@ static void regoptail(char_u *p, char_u *val)
regtail(OPERAND(p), val);
}
-/*
- * Insert an operator in front of already-emitted operand
- *
- * Means relocating the operand.
- */
+// Insert an operator in front of already-emitted operand
+//
+// Means relocating the operand.
static void reginsert(int op, char_u *opnd)
{
char_u *src;
@@ -1615,10 +1574,8 @@ static void reginsert(int op, char_u *opnd)
*place = NUL;
}
-/*
- * Insert an operator in front of already-emitted operand.
- * Add a number to the operator.
- */
+// Insert an operator in front of already-emitted operand.
+// Add a number to the operator.
static void reginsert_nr(int op, long val, char_u *opnd)
{
char_u *src;
@@ -1644,12 +1601,10 @@ static void reginsert_nr(int op, long val, char_u *opnd)
re_put_uint32(place, (uint32_t)val);
}
-/*
- * Insert an operator in front of already-emitted operand.
- * The operator has the given limit values as operands. Also set next pointer.
- *
- * Means relocating the operand.
- */
+// Insert an operator in front of already-emitted operand.
+// The operator has the given limit values as operands. Also set next pointer.
+//
+// Means relocating the operand.
static void reginsert_limits(int op, long minval, long maxval, char_u *opnd)
{
char_u *src;
@@ -1704,13 +1659,11 @@ static int seen_endbrace(int refnum)
return true;
}
-/*
- * Parse the lowest level.
- *
- * Optimization: gobbles an entire sequence of ordinary characters so that
- * it can turn them into a single node, which is smaller to store and
- * faster to run. Don't do this when one_exactly is set.
- */
+// Parse the lowest level.
+//
+// Optimization: gobbles an entire sequence of ordinary characters so that
+// it can turn them into a single node, which is smaller to store and
+// faster to run. Don't do this when one_exactly is set.
static char_u *regatom(int *flagp)
{
char_u *ret;
@@ -2289,8 +2242,7 @@ collection:
if (c_class != 0) {
// produce equivalence class
reg_equi_class(c_class);
- } else if ((c_class =
- get_coll_element(&regparse)) != 0) {
+ } else if ((c_class = get_coll_element(&regparse)) != 0) {
// produce a collating element
regmbc(c_class);
} else {
@@ -2466,7 +2418,7 @@ do_multibyte:
for (len = 0; c != NUL && (len == 0
|| (re_multi_type(peekchr()) == NOT_MULTI
&& !one_exactly
- && !is_Magic(c))); ++len) {
+ && !is_Magic(c))); len++) {
c = no_Magic(c);
{
regmbc(c);
@@ -2500,15 +2452,13 @@ do_multibyte:
return ret;
}
-/*
- * Parse something followed by possible [*+=].
- *
- * Note that the branching code sequences used for = and the general cases
- * of * and + are somewhat optimized: they use the same NOTHING node as
- * both the endmarker for their branch list and the body of the last branch.
- * It might seem that this node could be dispensed with entirely, but the
- * endmarker role is not redundant.
- */
+// Parse something followed by possible [*+=].
+//
+// Note that the branching code sequences used for = and the general cases
+// of * and + are somewhat optimized: they use the same NOTHING node as
+// both the endmarker for their branch list and the body of the last branch.
+// It might seem that this node could be dispensed with entirely, but the
+// endmarker role is not redundant.
static char_u *regpiece(int *flagp)
{
char_u *ret;
@@ -2644,10 +2594,8 @@ static char_u *regpiece(int *flagp)
return ret;
}
-/*
- * Parse one alternative of an | or & operator.
- * Implements the concatenation operator.
- */
+// Parse one alternative of an | or & operator.
+// Implements the concatenation operator.
static char_u *regconcat(int *flagp)
{
char_u *first = NULL;
@@ -2722,10 +2670,8 @@ static char_u *regconcat(int *flagp)
return first;
}
-/*
- * Parse one alternative of an | operator.
- * Implements the & operator.
- */
+// Parse one alternative of an | operator.
+// Implements the & operator.
static char_u *regbranch(int *flagp)
{
char_u *ret;
@@ -2874,27 +2820,25 @@ static char_u *reg(int paren, int *flagp)
return ret;
}
-/*
- * bt_regcomp() - compile a regular expression into internal code for the
- * traditional back track matcher.
- * Returns the program in allocated space. Returns NULL for an error.
- *
- * We can't allocate space until we know how big the compiled form will be,
- * but we can't compile it (and thus know how big it is) until we've got a
- * place to put the code. So we cheat: we compile it twice, once with code
- * generation turned off and size counting turned on, and once "for real".
- * This also means that we don't allocate space until we are sure that the
- * thing really will compile successfully, and we never have to move the
- * code and thus invalidate pointers into it. (Note that it has to be in
- * one piece because free() must be able to free it all.)
- *
- * Whether upper/lower case is to be ignored is decided when executing the
- * program, it does not matter here.
- *
- * Beware that the optimization-preparation code in here knows about some
- * of the structure of the compiled regexp.
- * "re_flags": RE_MAGIC and/or RE_STRING.
- */
+// bt_regcomp() - compile a regular expression into internal code for the
+// traditional back track matcher.
+// Returns the program in allocated space. Returns NULL for an error.
+//
+// We can't allocate space until we know how big the compiled form will be,
+// but we can't compile it (and thus know how big it is) until we've got a
+// place to put the code. So we cheat: we compile it twice, once with code
+// generation turned off and size counting turned on, and once "for real".
+// This also means that we don't allocate space until we are sure that the
+// thing really will compile successfully, and we never have to move the
+// code and thus invalidate pointers into it. (Note that it has to be in
+// one piece because free() must be able to free it all.)
+//
+// Whether upper/lower case is to be ignored is decided when executing the
+// program, it does not matter here.
+//
+// Beware that the optimization-preparation code in here knows about some
+// of the structure of the compiled regexp.
+// "re_flags": RE_MAGIC and/or RE_STRING.
static regprog_T *bt_regcomp(char_u *expr, int re_flags)
{
char_u *scan;
@@ -2999,19 +2943,15 @@ static regprog_T *bt_regcomp(char_u *expr, int re_flags)
return (regprog_T *)r;
}
-/*
- * Check if during the previous call to vim_regcomp the EOL item "$" has been
- * found. This is messy, but it works fine.
- */
+// Check if during the previous call to vim_regcomp the EOL item "$" has been
+// found. This is messy, but it works fine.
int vim_regcomp_had_eol(void)
{
return had_eol;
}
-/*
- * Get a number after a backslash that is inside [].
- * When nothing is recognized return a backslash.
- */
+// Get a number after a backslash that is inside [].
+// When nothing is recognized return a backslash.
static int coll_get_char(void)
{
int64_t nr = -1;
@@ -3037,9 +2977,7 @@ static int coll_get_char(void)
return (int)nr;
}
-/*
- * Free a compiled regexp program, returned by bt_regcomp().
- */
+// Free a compiled regexp program, returned by bt_regcomp().
static void bt_regfree(regprog_T *prog)
{
xfree(prog);
@@ -3047,11 +2985,9 @@ static void bt_regfree(regprog_T *prog)
#define ADVANCE_REGINPUT() MB_PTR_ADV(rex.input)
-/*
- * The arguments from BRACE_LIMITS are stored here. They are actually local
- * to regmatch(), but they are here to reduce the amount of stack space used
- * (it can be called recursively many times).
- */
+// The arguments from BRACE_LIMITS are stored here. They are actually local
+// to regmatch(), but they are here to reduce the amount of stack space used
+// (it can be called recursively many times).
static long bl_minval;
static long bl_maxval;
@@ -3108,13 +3044,11 @@ static bool reg_save_equal(const regsave_T *save)
else /* NOLINT */ \
*(pp) = (savep)->se_u.ptr; }
-/*
- * Tentatively set the sub-expression start to the current position (after
- * calling regmatch() they will have changed). Need to save the existing
- * values for when there is no match.
- * Use se_save() to use pointer (save_se_multi()) or position (save_se_one()),
- * depending on REG_MULTI.
- */
+// Tentatively set the sub-expression start to the current position (after
+// calling regmatch() they will have changed). Need to save the existing
+// values for when there is no match.
+// Use se_save() to use pointer (save_se_multi()) or position (save_se_one()),
+// depending on REG_MULTI.
static void save_se_multi(save_se_T *savep, lpos_T *posp)
{
savep->se_u.pos = *posp;
@@ -3494,10 +3428,8 @@ do_class:
return (int)count;
}
-/*
- * Push an item onto the regstack.
- * Returns pointer to new item. Returns NULL when out of memory.
- */
+// Push an item onto the regstack.
+// Returns pointer to new item. Returns NULL when out of memory.
static regitem_T *regstack_push(regstate_T state, char_u *scan)
{
regitem_T *rp;
@@ -3516,9 +3448,7 @@ static regitem_T *regstack_push(regstate_T state, char_u *scan)
return rp;
}
-/*
- * Pop an item from the regstack.
- */
+// Pop an item from the regstack.
static void regstack_pop(char_u **scan)
{
regitem_T *rp;
@@ -4643,7 +4573,7 @@ static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out)
// Pop the state. Restore pointers when there is no match.
if (status == RA_NOMATCH) {
reg_restore(&rp->rs_un.regsave, &backpos);
- --brace_count[rp->rs_no]; // decrement match count
+ brace_count[rp->rs_no]--; // decrement match count
}
regstack_pop(&scan);
break;
@@ -4653,7 +4583,7 @@ static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out)
if (status == RA_NOMATCH) {
// There was no match, but we did find enough matches.
reg_restore(&rp->rs_un.regsave, &backpos);
- --brace_count[rp->rs_no];
+ brace_count[rp->rs_no]--;
// continue with the items after "\{}"
status = RA_CONT;
}
@@ -5247,9 +5177,7 @@ static long bt_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T
return bt_regexec_both(NULL, col, tm, timed_out);
}
-/*
- * Compare a number with the operand of RE_LNUM, RE_COL or RE_VCOL.
- */
+// Compare a number with the operand of RE_LNUM, RE_COL or RE_VCOL.
static int re_num_cmp(uint32_t val, char_u *scan)
{
uint32_t n = (uint32_t)OPERAND_MIN(scan);
@@ -5265,9 +5193,7 @@ static int re_num_cmp(uint32_t val, char_u *scan)
#ifdef BT_REGEXP_DUMP
-/*
- * regdump - dump a regexp onto stdout in vaguely comprehensible form
- */
+// regdump - dump a regexp onto stdout in vaguely comprehensible form
static void regdump(char_u *pattern, bt_regprog_T *r)
{
char_u *s;
@@ -5353,9 +5279,7 @@ static void regdump(char_u *pattern, bt_regprog_T *r)
#ifdef REGEXP_DEBUG
-/*
- * regprop - printable representation of opcode
- */
+// regprop - printable representation of opcode
static char_u *regprop(char_u *op)
{
char *p;
diff --git a/src/nvim/regexp_defs.h b/src/nvim/regexp_defs.h
index b24ed350e8..ee32b8d13a 100644
--- a/src/nvim/regexp_defs.h
+++ b/src/nvim/regexp_defs.h
@@ -1,13 +1,11 @@
-/*
- * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
- *
- * This is NOT the original regular expression code as written by Henry
- * Spencer. This code has been modified specifically for use with Vim, and
- * should not be used apart from compiling Vim. If you want a good regular
- * expression library, get the original code.
- *
- * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
- */
+// NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
+//
+// This is NOT the original regular expression code as written by Henry
+// Spencer. This code has been modified specifically for use with Vim, and
+// should not be used apart from compiling Vim. If you want a good regular
+// expression library, get the original code.
+//
+// NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
#ifndef NVIM_REGEXP_DEFS_H
#define NVIM_REGEXP_DEFS_H
@@ -17,18 +15,14 @@
#include "nvim/pos.h"
#include "nvim/types.h"
-/*
- * The number of sub-matches is limited to 10.
- * The first one (index 0) is the whole match, referenced with "\0".
- * The second one (index 1) is the first sub-match, referenced with "\1".
- * This goes up to the tenth (index 9), referenced with "\9".
- */
+// The number of sub-matches is limited to 10.
+// The first one (index 0) is the whole match, referenced with "\0".
+// The second one (index 1) is the first sub-match, referenced with "\1".
+// This goes up to the tenth (index 9), referenced with "\9".
#define NSUBEXP 10
-/*
- * In the NFA engine: how many braces are allowed.
- * TODO(RE): Use dynamic memory allocation instead of static, like here
- */
+// In the NFA engine: how many braces are allowed.
+// TODO(RE): Use dynamic memory allocation instead of static, like here
#define NFA_MAX_BRACES 20
// In the NFA engine: how many states are allowed.
@@ -61,11 +55,9 @@ typedef struct {
#include "nvim/buffer_defs.h"
-/*
- * Structure returned by vim_regcomp() to pass on to vim_regexec().
- * This is the general structure. For the actual matcher, two specific
- * structures are used. See code below.
- */
+// Structure returned by vim_regcomp() to pass on to vim_regexec().
+// This is the general structure. For the actual matcher, two specific
+// structures are used. See code below.
struct regprog {
regengine_T *engine;
unsigned regflags;
@@ -74,11 +66,9 @@ struct regprog {
bool re_in_use; ///< prog is being executed
};
-/*
- * Structure used by the back track matcher.
- * These fields are only to be used in regexp.c!
- * See regexp.c for an explanation.
- */
+// Structure used by the back track matcher.
+// These fields are only to be used in regexp.c!
+// See regexp.c for an explanation.
typedef struct {
// These four members implement regprog_T.
regengine_T *engine;
@@ -107,9 +97,7 @@ struct nfa_state {
int val;
};
-/*
- * Structure used by the NFA matcher.
- */
+// Structure used by the NFA matcher.
typedef struct {
// These four members implement regprog_T.
regengine_T *engine;
@@ -133,11 +121,9 @@ typedef struct {
nfa_state_T state[1]; // actually longer..
} nfa_regprog_T;
-/*
- * Structure to be used for single-line matching.
- * Sub-match "no" starts at "startp[no]" and ends just before "endp[no]".
- * When there is no match, the pointer is NULL.
- */
+// Structure to be used for single-line matching.
+// Sub-match "no" starts at "startp[no]" and ends just before "endp[no]".
+// When there is no match, the pointer is NULL.
typedef struct {
regprog_T *regprog;
char *startp[NSUBEXP];
@@ -145,11 +131,9 @@ typedef struct {
bool rm_ic;
} regmatch_T;
-/*
- * Structure used to store external references: "\z\(\)" to "\z\1".
- * Use a reference count to avoid the need to copy this around. When it goes
- * from 1 to zero the matches need to be freed.
- */
+// Structure used to store external references: "\z\(\)" to "\z\1".
+// Use a reference count to avoid the need to copy this around. When it goes
+// from 1 to zero the matches need to be freed.
struct reg_extmatch {
int16_t refcnt;
char_u *matches[NSUBEXP];
diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c
index d4d2ed28cc..c4102c40ec 100644
--- a/src/nvim/regexp_nfa.c
+++ b/src/nvim/regexp_nfa.c
@@ -1,11 +1,9 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-/*
- * NFA regular expression implementation.
- *
- * This file is included in "regexp.c".
- */
+// NFA regular expression implementation.
+//
+// This file is included in "regexp.c".
#include <assert.h>
#include <inttypes.h>
@@ -383,10 +381,8 @@ static void nfa_regcomp_start(char_u *expr, int re_flags)
regcomp_start(expr, re_flags);
}
-/*
- * Figure out if the NFA state list starts with an anchor, must match at start
- * of the line.
- */
+// Figure out if the NFA state list starts with an anchor, must match at start
+// of the line.
static int nfa_get_reganch(nfa_state_T *start, int depth)
{
nfa_state_T *p = start;
@@ -441,10 +437,8 @@ static int nfa_get_reganch(nfa_state_T *start, int depth)
return 0;
}
-/*
- * Figure out if the NFA state list starts with a character which must match
- * at start of the match.
- */
+// Figure out if the NFA state list starts with a character which must match
+// at start of the match.
static int nfa_get_regstart(nfa_state_T *start, int depth)
{
nfa_state_T *p = start;
@@ -521,11 +515,9 @@ static int nfa_get_regstart(nfa_state_T *start, int depth)
return 0;
}
-/*
- * Figure out if the NFA state list contains just literal text and nothing
- * else. If so return a string in allocated memory with what must match after
- * regstart. Otherwise return NULL.
- */
+// Figure out if the NFA state list contains just literal text and nothing
+// else. If so return a string in allocated memory with what must match after
+// regstart. Otherwise return NULL.
static char_u *nfa_get_match_text(nfa_state_T *start)
{
nfa_state_T *p = start;
@@ -557,10 +549,8 @@ static char_u *nfa_get_match_text(nfa_state_T *start)
return ret;
}
-/*
- * Allocate more space for post_start. Called when
- * running above the estimated number of states.
- */
+// Allocate more space for post_start. Called when
+// running above the estimated number of states.
static void realloc_post_list(void)
{
// For weird patterns the number of states can be very high. Increasing by
@@ -572,16 +562,14 @@ static void realloc_post_list(void)
post_start = new_start;
}
-/*
- * Search between "start" and "end" and try to recognize a
- * character class in expanded form. For example [0-9].
- * On success, return the id the character class to be emitted.
- * On failure, return 0 (=FAIL)
- * Start points to the first char of the range, while end should point
- * to the closing brace.
- * Keep in mind that 'ignorecase' applies at execution time, thus [a-z] may
- * need to be interpreted as [a-zA-Z].
- */
+// Search between "start" and "end" and try to recognize a
+// character class in expanded form. For example [0-9].
+// On success, return the id the character class to be emitted.
+// On failure, return 0 (=FAIL)
+// Start points to the first char of the range, while end should point
+// to the closing brace.
+// Keep in mind that 'ignorecase' applies at execution time, thus [a-z] may
+// need to be interpreted as [a-zA-Z].
static int nfa_recognize_char_class(char_u *start, char_u *end, int extra_newl)
{
#define CLASS_not 0x80
@@ -700,14 +688,12 @@ static int nfa_recognize_char_class(char_u *start, char_u *end, int extra_newl)
return FAIL;
}
-/*
- * Produce the bytes for equivalence class "c".
- * Currently only handles latin1, latin9 and utf-8.
- * Emits bytes in postfix notation: 'a,b,NFA_OR,c,NFA_OR' is
- * equivalent to 'a OR b OR c'
- *
- * NOTE! When changing this function, also update reg_equi_class()
- */
+// Produce the bytes for equivalence class "c".
+// Currently only handles latin1, latin9 and utf-8.
+// Emits bytes in postfix notation: 'a,b,NFA_OR,c,NFA_OR' is
+// equivalent to 'a OR b OR c'
+//
+// NOTE! When changing this function, also update reg_equi_class()
static void nfa_emit_equi_class(int c)
{
#define EMIT2(c) EMIT(c); EMIT(NFA_CONCAT);
@@ -1778,26 +1764,22 @@ static void nfa_emit_equi_class(int c)
#undef EMIT2
}
-/*
- * Code to parse regular expression.
- *
- * We try to reuse parsing functions in regexp.c to
- * minimize surprise and keep the syntax consistent.
- */
-
-/*
- * Parse the lowest level.
- *
- * An atom can be one of a long list of items. Many atoms match one character
- * in the text. It is often an ordinary character or a character class.
- * Braces can be used to make a pattern into an atom. The "\z(\)" construct
- * is only for syntax highlighting.
- *
- * atom ::= ordinary-atom
- * or \( pattern \)
- * or \%( pattern \)
- * or \z( pattern \)
- */
+// Code to parse regular expression.
+//
+// We try to reuse parsing functions in regexp.c to
+// minimize surprise and keep the syntax consistent.
+
+// Parse the lowest level.
+//
+// An atom can be one of a long list of items. Many atoms match one character
+// in the text. It is often an ordinary character or a character class.
+// Braces can be used to make a pattern into an atom. The "\z(\)" construct
+// is only for syntax highlighting.
+//
+// atom ::= ordinary-atom
+// or \( pattern \)
+// or \%( pattern \)
+// or \z( pattern \)
static int nfa_regatom(void)
{
int c;
@@ -1862,9 +1844,7 @@ static int nfa_regatom(void)
// "\_x" is character class plus newline
FALLTHROUGH;
- /*
- * Character classes.
- */
+ // Character classes.
case Magic('.'):
case Magic('i'):
case Magic('I'):
@@ -2228,24 +2208,20 @@ static int nfa_regatom(void)
case Magic('['):
collection:
- /*
- * [abc] uses NFA_START_COLL - NFA_END_COLL
- * [^abc] uses NFA_START_NEG_COLL - NFA_END_NEG_COLL
- * Each character is produced as a regular state, using
- * NFA_CONCAT to bind them together.
- * Besides normal characters there can be:
- * - character classes NFA_CLASS_*
- * - ranges, two characters followed by NFA_RANGE.
- */
+ // [abc] uses NFA_START_COLL - NFA_END_COLL
+ // [^abc] uses NFA_START_NEG_COLL - NFA_END_NEG_COLL
+ // Each character is produced as a regular state, using
+ // NFA_CONCAT to bind them together.
+ // Besides normal characters there can be:
+ // - character classes NFA_CLASS_*
+ // - ranges, two characters followed by NFA_RANGE.
p = (char_u *)regparse;
endp = skip_anyof((char *)p);
if (*endp == ']') {
- /*
- * Try to reverse engineer character classes. For example,
- * recognize that [0-9] stands for \d and [A-Za-z_] for \h,
- * and perform the necessary substitutions in the NFA.
- */
+ // Try to reverse engineer character classes. For example,
+ // recognize that [0-9] stands for \d and [A-Za-z_] for \h,
+ // and perform the necessary substitutions in the NFA.
int result = nfa_recognize_char_class((char_u *)regparse, endp, extra == NFA_ADD_NL);
if (result != FAIL) {
if (result >= NFA_FIRST_NL && result <= NFA_LAST_NL) {
@@ -2259,10 +2235,8 @@ collection:
MB_PTR_ADV(regparse);
return OK;
}
- /*
- * Failed to recognize a character class. Use the simple
- * version that turns [abc] into 'a' OR 'b' OR 'c'
- */
+ // Failed to recognize a character class. Use the simple
+ // version that turns [abc] into 'a' OR 'b' OR 'c'
startc = -1;
negated = false;
if (*regparse == '^') { // negated range
@@ -2554,16 +2528,14 @@ nfa_do_multibyte:
return OK;
}
-/*
- * Parse something followed by possible [*+=].
- *
- * A piece is an atom, possibly followed by a multi, an indication of how many
- * times the atom can be matched. Example: "a*" matches any sequence of "a"
- * characters: "", "a", "aa", etc.
- *
- * piece ::= atom
- * or atom multi
- */
+// Parse something followed by possible [*+=].
+//
+// A piece is an atom, possibly followed by a multi, an indication of how many
+// times the atom can be matched. Example: "a*" matches any sequence of "a"
+// characters: "", "a", "aa", etc.
+//
+// piece ::= atom
+// or atom multi
static int nfa_regpiece(void)
{
int i;
@@ -2601,17 +2573,15 @@ static int nfa_regpiece(void)
break;
case Magic('+'):
- /*
- * Trick: Normally, (a*)\+ would match the whole input "aaa". The
- * first and only submatch would be "aaa". But the backtracking
- * engine interprets the plus as "try matching one more time", and
- * a* matches a second time at the end of the input, the empty
- * string.
- * The submatch will be the empty string.
- *
- * In order to be consistent with the old engine, we replace
- * <atom>+ with <atom><atom>*
- */
+ // Trick: Normally, (a*)\+ would match the whole input "aaa". The
+ // first and only submatch would be "aaa". But the backtracking
+ // engine interprets the plus as "try matching one more time", and
+ // a* matches a second time at the end of the input, the empty
+ // string.
+ // The submatch will be the empty string.
+ //
+ // In order to be consistent with the old engine, we replace
+ // <atom>+ with <atom><atom>*
restore_parse_state(&old_state);
curchr = -1;
if (nfa_regatom() == FAIL) {
@@ -2770,16 +2740,14 @@ static int nfa_regpiece(void)
return OK;
}
-/*
- * Parse one or more pieces, concatenated. It matches a match for the
- * first piece, followed by a match for the second piece, etc. Example:
- * "f[0-9]b", first matches "f", then a digit and then "b".
- *
- * concat ::= piece
- * or piece piece
- * or piece piece piece
- * etc.
- */
+// Parse one or more pieces, concatenated. It matches a match for the
+// first piece, followed by a match for the second piece, etc. Example:
+// "f[0-9]b", first matches "f", then a digit and then "b".
+//
+// concat ::= piece
+// or piece piece
+// or piece piece piece
+// etc.
static int nfa_regconcat(void)
{
bool cont = true;
@@ -2843,18 +2811,16 @@ static int nfa_regconcat(void)
return OK;
}
-/*
- * Parse a branch, one or more concats, separated by "\&". It matches the
- * last concat, but only if all the preceding concats also match at the same
- * position. Examples:
- * "foobeep\&..." matches "foo" in "foobeep".
- * ".*Peter\&.*Bob" matches in a line containing both "Peter" and "Bob"
- *
- * branch ::= concat
- * or concat \& concat
- * or concat \& concat \& concat
- * etc.
- */
+// Parse a branch, one or more concats, separated by "\&". It matches the
+// last concat, but only if all the preceding concats also match at the same
+// position. Examples:
+// "foobeep\&..." matches "foo" in "foobeep".
+// ".*Peter\&.*Bob" matches in a line containing both "Peter" and "Bob"
+//
+// branch ::= concat
+// or concat \& concat
+// or concat \& concat \& concat
+// etc.
static int nfa_regbranch(void)
{
int old_post_pos;
@@ -3311,9 +3277,7 @@ static FILE *log_fd;
static char_u e_log_open_failed[] =
N_("Could not open temporary log file for writing, displaying on stderr... ");
-/*
- * Print the postfix notation of the current regexp.
- */
+// Print the postfix notation of the current regexp.
static void nfa_postfix_dump(char_u *expr, int retval)
{
int *p;
@@ -3341,9 +3305,7 @@ static void nfa_postfix_dump(char_u *expr, int retval)
}
}
-/*
- * Print the NFA starting with a root node "state".
- */
+// Print the NFA starting with a root node "state".
static void nfa_print_state(FILE *debugf, nfa_state_T *state)
{
garray_T indent;
@@ -3413,9 +3375,7 @@ static void nfa_print_state2(FILE *debugf, nfa_state_T *state, garray_T *indent)
ga_append(indent, NUL);
}
-/*
- * Print the NFA state machine.
- */
+// Print the NFA state machine.
static void nfa_dump(nfa_regprog_T *prog)
{
FILE *debugf = fopen(NFA_REGEXP_DUMP_LOG, "a");
@@ -3437,12 +3397,10 @@ static void nfa_dump(nfa_regprog_T *prog)
fclose(debugf);
}
}
-#endif /* REGEXP_DEBUG */
+#endif // REGEXP_DEBUG
-/*
- * Parse r.e. @expr and convert it into postfix form.
- * Return the postfix string on success, NULL otherwise.
- */
+// Parse r.e. @expr and convert it into postfix form.
+// Return the postfix string on success, NULL otherwise.
static int *re2post(void)
{
if (nfa_reg(REG_NOPAREN) == FAIL) {
@@ -3454,18 +3412,14 @@ static int *re2post(void)
// NB. Some of the code below is inspired by Russ's.
-/*
- * Represents an NFA state plus zero or one or two arrows exiting.
- * if c == MATCH, no arrows out; matching state.
- * If c == SPLIT, unlabeled arrows to out and out1 (if != NULL).
- * If c < 256, labeled arrow with character c to out.
- */
+// Represents an NFA state plus zero or one or two arrows exiting.
+// if c == MATCH, no arrows out; matching state.
+// If c == SPLIT, unlabeled arrows to out and out1 (if != NULL).
+// If c < 256, labeled arrow with character c to out.
static nfa_state_T *state_ptr; // points to nfa_prog->state
-/*
- * Allocate and initialize nfa_state_T.
- */
+// Allocate and initialize nfa_state_T.
static nfa_state_T *alloc_state(int c, nfa_state_T *out, nfa_state_T *out1)
{
nfa_state_T *s;
@@ -3488,16 +3442,12 @@ static nfa_state_T *alloc_state(int c, nfa_state_T *out, nfa_state_T *out1)
return s;
}
-/*
- * A partially built NFA without the matching state filled in.
- * Frag_T.start points at the start state.
- * Frag_T.out is a list of places that need to be set to the
- * next state for this fragment.
- */
+// A partially built NFA without the matching state filled in.
+// Frag_T.start points at the start state.
+// Frag_T.out is a list of places that need to be set to the
+// next state for this fragment.
-/*
- * Initialize a Frag_T struct and return it.
- */
+// Initialize a Frag_T struct and return it.
static Frag_T frag(nfa_state_T *start, Ptrlist *out)
{
Frag_T n;
@@ -3507,9 +3457,7 @@ static Frag_T frag(nfa_state_T *start, Ptrlist *out)
return n;
}
-/*
- * Create singleton list containing just outp.
- */
+// Create singleton list containing just outp.
static Ptrlist *list1(nfa_state_T **outp)
{
Ptrlist *l;
@@ -3519,9 +3467,7 @@ static Ptrlist *list1(nfa_state_T **outp)
return l;
}
-/*
- * Patch the list of states at out to point to start.
- */
+// Patch the list of states at out to point to start.
static void patch(Ptrlist *l, nfa_state_T *s)
{
Ptrlist *next;
@@ -3532,9 +3478,7 @@ static void patch(Ptrlist *l, nfa_state_T *s)
}
}
-/*
- * Join the two lists l1 and l2, returning the combination.
- */
+// Join the two lists l1 and l2, returning the combination.
static Ptrlist *append(Ptrlist *l1, Ptrlist *l2)
{
Ptrlist *oldl1;
@@ -3547,9 +3491,7 @@ static Ptrlist *append(Ptrlist *l1, Ptrlist *l2)
return oldl1;
}
-/*
- * Stack used for transforming postfix form into NFA.
- */
+// Stack used for transforming postfix form into NFA.
static Frag_T empty;
static void st_error(int *postfix, int *end, int *p)
@@ -3592,9 +3534,7 @@ static void st_error(int *postfix, int *end, int *p)
emsg(_("E874: (NFA) Could not pop the stack!"));
}
-/*
- * Push an item onto the stack.
- */
+// Push an item onto the stack.
static void st_push(Frag_T s, Frag_T **p, Frag_T *stack_end)
{
Frag_T *stackp = *p;
@@ -3606,9 +3546,7 @@ static void st_push(Frag_T s, Frag_T **p, Frag_T *stack_end)
*p = *p + 1;
}
-/*
- * Pop an item from the stack.
- */
+// Pop an item from the stack.
static Frag_T st_pop(Frag_T **p, Frag_T *stack)
{
Frag_T *stackp;
@@ -3621,10 +3559,8 @@ static Frag_T st_pop(Frag_T **p, Frag_T *stack)
return **p;
}
-/*
- * Estimate the maximum byte length of anything matching "state".
- * When unknown or unlimited return -1.
- */
+// Estimate the maximum byte length of anything matching "state".
+// When unknown or unlimited return -1.
static int nfa_max_width(nfa_state_T *startstate, int depth)
{
int l, r;
@@ -3827,10 +3763,8 @@ static int nfa_max_width(nfa_state_T *startstate, int depth)
return -1;
}
-/*
- * Convert a postfix form into its equivalent NFA.
- * Return the NFA start state on success, NULL otherwise.
- */
+// Convert a postfix form into its equivalent NFA.
+// Return the NFA start state on success, NULL otherwise.
static nfa_state_T *post2nfa(int *postfix, int *end, int nfa_calc_size)
{
int *p;
@@ -3866,7 +3800,7 @@ static nfa_state_T *post2nfa(int *postfix, int *end, int nfa_calc_size)
stack_end = stack + (nstate + 1);
}
- for (p = postfix; p < end; ++p) {
+ for (p = postfix; p < end; p++) {
switch (*p) {
case NFA_CONCAT:
// Concatenation.
@@ -4350,15 +4284,13 @@ theend:
#undef PUSH
}
-/*
- * After building the NFA program, inspect it to add optimization hints.
- */
+// After building the NFA program, inspect it to add optimization hints.
static void nfa_postprocess(nfa_regprog_T *prog)
{
int i;
int c;
- for (i = 0; i < prog->nstate; ++i) {
+ for (i = 0; i < prog->nstate; i++) {
c = prog->state[i].c;
if (c == NFA_START_INVISIBLE
|| c == NFA_START_INVISIBLE_NEG
@@ -4490,9 +4422,7 @@ static void clear_sub(regsub_T *sub)
sub->in_use = 0;
}
-/*
- * Copy the submatches from "from" to "to".
- */
+// Copy the submatches from "from" to "to".
static void copy_sub(regsub_T *to, regsub_T *from)
{
to->in_use = from->in_use;
@@ -4508,9 +4438,7 @@ static void copy_sub(regsub_T *to, regsub_T *from)
}
}
-/*
- * Like copy_sub() but exclude the main match.
- */
+// Like copy_sub() but exclude the main match.
static void copy_sub_off(regsub_T *to, regsub_T *from)
{
if (to->in_use < from->in_use) {
@@ -4528,9 +4456,7 @@ static void copy_sub_off(regsub_T *to, regsub_T *from)
}
}
-/*
- * Like copy_sub() but only do the end of the main match if \ze is present.
- */
+// Like copy_sub() but only do the end of the main match if \ze is present.
static void copy_ze_off(regsub_T *to, regsub_T *from)
{
if (rex.nfa_has_zend) {
@@ -4954,7 +4880,7 @@ static regsubs_T *addstate(nfa_list_T *l, nfa_state_T *state, regsubs_T *subs_ar
// When called from addstate_here() do insert before
// existing states.
if (add_here) {
- for (k = 0; k < l->n && k < listindex; ++k) {
+ for (k = 0; k < l->n && k < listindex; k++) {
if (l->t[k].state->id == state->id) {
found = true;
break;
@@ -5094,7 +5020,7 @@ skip_add:
save_in_use = -1;
} else {
save_in_use = sub->in_use;
- for (i = sub->in_use; i < subidx; ++i) {
+ for (i = sub->in_use; i < subidx; i++) {
sub->list.multi[i].start_lnum = -1;
sub->list.multi[i].end_lnum = -1;
}
@@ -5115,7 +5041,7 @@ skip_add:
save_in_use = -1;
} else {
save_in_use = sub->in_use;
- for (i = sub->in_use; i < subidx; ++i) {
+ for (i = sub->in_use; i < subidx; i++) {
sub->list.line[i].start = NULL;
sub->list.line[i].end = NULL;
}
@@ -5314,9 +5240,7 @@ static regsubs_T *addstate_here(nfa_list_T *l, nfa_state_T *state, regsubs_T *su
return r;
}
-/*
- * Check character class "class" against current character c.
- */
+// Check character class "class" against current character c.
static int check_char_class(int class, int c)
{
switch (class) {
@@ -5502,11 +5426,9 @@ static int match_zref(int subidx, int *bytelen)
return false;
}
-/*
- * Save list IDs for all NFA states of "prog" into "list".
- * Also reset the IDs to zero.
- * Only used for the recursive value lastlist[1].
- */
+// Save list IDs for all NFA states of "prog" into "list".
+// Also reset the IDs to zero.
+// Only used for the recursive value lastlist[1].
static void nfa_save_listids(nfa_regprog_T *prog, int *list)
{
int i;
@@ -5521,9 +5443,7 @@ static void nfa_save_listids(nfa_regprog_T *prog, int *list)
}
}
-/*
- * Restore list IDs from "list" to all NFA states.
- */
+// Restore list IDs from "list" to all NFA states.
static void nfa_restore_listids(nfa_regprog_T *prog, int *list)
{
int i;
@@ -5547,11 +5467,9 @@ static bool nfa_re_num_cmp(uintmax_t val, int op, uintmax_t pos)
return val == pos;
}
-/*
- * Recursively call nfa_regmatch()
- * "pim" is NULL or contains info about a Postponed Invisible Match (start
- * position).
- */
+// Recursively call nfa_regmatch()
+// "pim" is NULL or contains info about a Postponed Invisible Match (start
+// position).
static int recursive_regmatch(nfa_state_T *state, nfa_pim_T *pim, nfa_regprog_T *prog,
regsubs_T *submatch, regsubs_T *m, int **listids, int *listids_len)
FUNC_ATTR_NONNULL_ARG(1, 3, 5, 6, 7)
@@ -5691,12 +5609,10 @@ static int recursive_regmatch(nfa_state_T *state, nfa_pim_T *pim, nfa_regprog_T
return result;
}
-/*
- * Estimate the chance of a match with "state" failing.
- * empty match: 0
- * NFA_ANY: 1
- * specific character: 99
- */
+// Estimate the chance of a match with "state" failing.
+// empty match: 0
+// NFA_ANY: 1
+// specific character: 99
static int failure_chance(nfa_state_T *state, int depth)
{
int c = state->c;
@@ -5851,9 +5767,7 @@ static int failure_chance(nfa_state_T *state, int depth)
return 50;
}
-/*
- * Skip until the char "c" we know a match must start with.
- */
+// Skip until the char "c" we know a match must start with.
static int skip_to_start(int c, colnr_T *colp)
{
const char_u *const s = cstrchr(rex.line + *colp, c);
@@ -5864,11 +5778,9 @@ static int skip_to_start(int c, colnr_T *colp)
return OK;
}
-/*
- * Check for a match with match_text.
- * Called after skip_to_start() has found regstart.
- * Returns zero for no match, 1 for a match.
- */
+// Check for a match with match_text.
+// Called after skip_to_start() has found regstart.
+// Returns zero for no match, 1 for a match.
static long find_match_text(colnr_T startcol, int regstart, char_u *match_text)
{
#define PTR2LEN(x) utf_ptr2len(x)
@@ -6038,9 +5950,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
add_off = clen; \
}
- /*
- * Run for each character.
- */
+ // Run for each character.
for (;;) {
int curc = utf_ptr2char((char *)rex.input);
int clen = utfc_ptr2len((char *)rex.input);
@@ -6086,9 +5996,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
#ifdef NFA_REGEXP_DEBUG_LOG
fprintf(debug, "\n-------------------\n");
#endif
- /*
- * If the state lists are empty we can stop.
- */
+ // If the state lists are empty we can stop.
if (thislist->n == 0) {
break;
}
@@ -6131,10 +6039,8 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
}
#endif
- /*
- * Handle the possible codes of the current state.
- * The most important is NFA_MATCH.
- */
+ // Handle the possible codes of the current state.
+ // The most important is NFA_MATCH.
add_state = NULL;
add_here = false;
add_count = 0;
@@ -7525,10 +7431,8 @@ theend:
return retval;
}
-/*
- * Compile a regular expression into internal code for the NFA matcher.
- * Returns the program in allocated space. Returns NULL for an error.
- */
+// Compile a regular expression into internal code for the NFA matcher.
+// Returns the program in allocated space. Returns NULL for an error.
static regprog_T *nfa_regcomp(char_u *expr, int re_flags)
{
nfa_regprog_T *prog = NULL;
@@ -7554,11 +7458,9 @@ static regprog_T *nfa_regcomp(char_u *expr, int re_flags)
goto fail; // Cascaded (syntax?) error
}
- /*
- * In order to build the NFA, we parse the input regexp twice:
- * 1. first pass to count size (so we can allocate space)
- * 2. second to emit code
- */
+ // In order to build the NFA, we parse the input regexp twice:
+ // 1. first pass to count size (so we can allocate space)
+ // 2. second to emit code
#ifdef REGEXP_DEBUG
{
FILE *f = fopen(NFA_REGEXP_RUN_LOG, "a");
@@ -7573,10 +7475,8 @@ static regprog_T *nfa_regcomp(char_u *expr, int re_flags)
}
#endif
- /*
- * PASS 1
- * Count number of NFA states in "nstate". Do not build the NFA.
- */
+ // PASS 1
+ // Count number of NFA states in "nstate". Do not build the NFA.
post2nfa(postfix, post_ptr, true);
// allocate the regprog with space for the compiled regexp
@@ -7585,10 +7485,8 @@ static regprog_T *nfa_regcomp(char_u *expr, int re_flags)
state_ptr = prog->state;
prog->re_in_use = false;
- /*
- * PASS 2
- * Build the NFA
- */
+ // PASS 2
+ // Build the NFA
prog->start = post2nfa(postfix, post_ptr, false);
if (prog->start == NULL) {
goto fail;
@@ -7632,9 +7530,7 @@ fail:
goto out;
}
-/*
- * Free a compiled regexp program, returned by nfa_regcomp().
- */
+// Free a compiled regexp program, returned by nfa_regcomp().
static void nfa_regfree(regprog_T *prog)
{
if (prog != NULL) {
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index cd1d6553cb..cbd5b96bef 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -15,9 +15,7 @@
#include "nvim/buffer.h"
#include "nvim/charset.h"
-#include "nvim/cmdexpand.h"
#include "nvim/cursor.h"
-#include "nvim/drawscreen.h"
#include "nvim/eval.h"
#include "nvim/extmark.h"
#include "nvim/fileio.h"
@@ -27,7 +25,6 @@
#include "nvim/grid.h"
#include "nvim/highlight.h"
#include "nvim/highlight_group.h"
-#include "nvim/menu.h"
#include "nvim/move.h"
#include "nvim/option.h"
#include "nvim/optionstr.h"
@@ -249,238 +246,6 @@ void rl_mirror(char *str)
}
}
-/// Get the length of an item as it will be shown in the status line.
-static int wildmenu_match_len(expand_T *xp, char_u *s)
-{
- int len = 0;
-
- int emenu = (xp->xp_context == EXPAND_MENUS
- || xp->xp_context == EXPAND_MENUNAMES);
-
- // Check for menu separators - replace with '|'.
- if (emenu && menu_is_separator((char *)s)) {
- return 1;
- }
-
- while (*s != NUL) {
- s += skip_wildmenu_char(xp, s);
- len += ptr2cells((char *)s);
- MB_PTR_ADV(s);
- }
-
- return len;
-}
-
-/// Return the number of characters that should be skipped in the wildmenu
-/// These are backslashes used for escaping. Do show backslashes in help tags.
-static int skip_wildmenu_char(expand_T *xp, char_u *s)
-{
- if ((rem_backslash((char *)s) && xp->xp_context != EXPAND_HELP)
- || ((xp->xp_context == EXPAND_MENUS
- || xp->xp_context == EXPAND_MENUNAMES)
- && (s[0] == '\t'
- || (s[0] == '\\' && s[1] != NUL)))) {
-#ifndef BACKSLASH_IN_FILENAME
- // TODO(bfredl): Why in the actual fuck are we special casing the
- // shell variety deep in the redraw logic? Shell special snowflakiness
- // should already be eliminated multiple layers before reaching the
- // screen infracstructure.
- if (xp->xp_shell && csh_like_shell() && s[1] == '\\' && s[2] == '!') {
- return 2;
- }
-#endif
- return 1;
- }
- return 0;
-}
-
-/// Show wildchar matches in the status line.
-/// Show at least the "match" item.
-/// We start at item 'first_match' in the list and show all matches that fit.
-///
-/// If inversion is possible we use it. Else '=' characters are used.
-///
-/// @param matches list of matches
-void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int match, int showtail)
-{
-#define L_MATCH(m) (showtail ? sm_gettail(matches[m], false) : matches[m])
- int row;
- char_u *buf;
- int len;
- int clen; // length in screen cells
- int fillchar;
- int attr;
- int i;
- bool highlight = true;
- char_u *selstart = NULL;
- int selstart_col = 0;
- char_u *selend = NULL;
- static int first_match = 0;
- bool add_left = false;
- char_u *s;
- int emenu;
- int l;
-
- if (matches == NULL) { // interrupted completion?
- return;
- }
-
- buf = xmalloc((size_t)Columns * MB_MAXBYTES + 1);
-
- if (match == -1) { // don't show match but original text
- match = 0;
- highlight = false;
- }
- // count 1 for the ending ">"
- clen = wildmenu_match_len(xp, (char_u *)L_MATCH(match)) + 3;
- if (match == 0) {
- first_match = 0;
- } else if (match < first_match) {
- // jumping left, as far as we can go
- first_match = match;
- add_left = true;
- } else {
- // check if match fits on the screen
- for (i = first_match; i < match; i++) {
- clen += wildmenu_match_len(xp, (char_u *)L_MATCH(i)) + 2;
- }
- if (first_match > 0) {
- clen += 2;
- }
- // jumping right, put match at the left
- if ((long)clen > Columns) {
- first_match = match;
- // if showing the last match, we can add some on the left
- clen = 2;
- for (i = match; i < num_matches; i++) {
- clen += wildmenu_match_len(xp, (char_u *)L_MATCH(i)) + 2;
- if ((long)clen >= Columns) {
- break;
- }
- }
- if (i == num_matches) {
- add_left = true;
- }
- }
- }
- if (add_left) {
- while (first_match > 0) {
- clen += wildmenu_match_len(xp, (char_u *)L_MATCH(first_match - 1)) + 2;
- if ((long)clen >= Columns) {
- break;
- }
- first_match--;
- }
- }
-
- fillchar = fillchar_status(&attr, curwin);
-
- if (first_match == 0) {
- *buf = NUL;
- len = 0;
- } else {
- STRCPY(buf, "< ");
- len = 2;
- }
- clen = len;
-
- i = first_match;
- while (clen + wildmenu_match_len(xp, (char_u *)L_MATCH(i)) + 2 < Columns) {
- if (i == match) {
- selstart = buf + len;
- selstart_col = clen;
- }
-
- s = (char_u *)L_MATCH(i);
- // Check for menu separators - replace with '|'
- emenu = (xp->xp_context == EXPAND_MENUS
- || xp->xp_context == EXPAND_MENUNAMES);
- if (emenu && menu_is_separator((char *)s)) {
- STRCPY(buf + len, transchar('|'));
- l = (int)STRLEN(buf + len);
- len += l;
- clen += l;
- } else {
- for (; *s != NUL; s++) {
- s += skip_wildmenu_char(xp, s);
- clen += ptr2cells((char *)s);
- if ((l = utfc_ptr2len((char *)s)) > 1) {
- STRNCPY(buf + len, s, l); // NOLINT(runtime/printf)
- s += l - 1;
- len += l;
- } else {
- STRCPY(buf + len, transchar_byte(*s));
- len += (int)STRLEN(buf + len);
- }
- }
- }
- if (i == match) {
- selend = buf + len;
- }
-
- *(buf + len++) = ' ';
- *(buf + len++) = ' ';
- clen += 2;
- if (++i == num_matches) {
- break;
- }
- }
-
- if (i != num_matches) {
- *(buf + len++) = '>';
- clen++;
- }
-
- buf[len] = NUL;
-
- row = cmdline_row - 1;
- if (row >= 0) {
- if (wild_menu_showing == 0 || wild_menu_showing == WM_LIST) {
- if (msg_scrolled > 0) {
- // Put the wildmenu just above the command line. If there is
- // no room, scroll the screen one line up.
- if (cmdline_row == Rows - 1) {
- msg_scroll_up(false, false);
- msg_scrolled++;
- } else {
- cmdline_row++;
- row++;
- }
- wild_menu_showing = WM_SCROLLED;
- } else {
- // Create status line if needed by setting 'laststatus' to 2.
- // Set 'winminheight' to zero to avoid that the window is
- // resized.
- if (lastwin->w_status_height == 0 && global_stl_height() == 0) {
- save_p_ls = (int)p_ls;
- save_p_wmh = (int)p_wmh;
- p_ls = 2;
- p_wmh = 0;
- last_status(false);
- }
- wild_menu_showing = WM_SHOWN;
- }
- }
-
- // Tricky: wildmenu can be drawn either over a status line, or at empty
- // scrolled space in the message output
- ScreenGrid *grid = (wild_menu_showing == WM_SCROLLED)
- ? &msg_grid_adj : &default_grid;
-
- grid_puts(grid, (char *)buf, row, 0, attr);
- if (selstart != NULL && highlight) {
- *selend = NUL;
- grid_puts(grid, (char *)selstart, row, selstart_col, HL_ATTR(HLF_WM));
- }
-
- grid_fill(grid, row, row + 1, clen, Columns,
- fillchar, fillchar, attr);
- }
-
- win_redraw_last_status(topframe);
- xfree(buf);
-}
-
/// Only call if (wp->w_vsep_width != 0).
///
/// @return true if the status line of window "wp" is connected to the status
@@ -572,7 +337,8 @@ void check_for_delay(bool check_msg_scroll)
{
if ((emsg_on_display || (check_msg_scroll && msg_scroll))
&& !did_wait_return
- && emsg_silent == 0) {
+ && emsg_silent == 0
+ && !in_assert_fails) {
ui_flush();
os_delay(1006L, true);
emsg_on_display = false;
@@ -582,22 +348,6 @@ void check_for_delay(bool check_msg_scroll)
}
}
-/// Clear status line, window bar or tab page line click definition table
-///
-/// @param[out] tpcd Table to clear.
-/// @param[in] tpcd_size Size of the table.
-void stl_clear_click_defs(StlClickDefinition *const click_defs, const long click_defs_size)
-{
- if (click_defs != NULL) {
- for (long i = 0; i < click_defs_size; i++) {
- if (i == 0 || click_defs[i].func != click_defs[i - 1].func) {
- xfree(click_defs[i].func);
- }
- }
- memset(click_defs, 0, (size_t)click_defs_size * sizeof(click_defs[0]));
- }
-}
-
/// Set cursor to its position in the current window.
void setcursor(void)
{
@@ -916,226 +666,6 @@ static void recording_mode(int attr)
}
}
-/// Draw the tab pages line at the top of the Vim window.
-void draw_tabline(void)
-{
- int tabcount = 0;
- int tabwidth = 0;
- int col = 0;
- int scol = 0;
- int attr;
- win_T *wp;
- win_T *cwp;
- int wincount;
- int modified;
- int c;
- int len;
- int attr_nosel = HL_ATTR(HLF_TP);
- int attr_fill = HL_ATTR(HLF_TPF);
- char_u *p;
- int room;
- int use_sep_chars = (t_colors < 8);
-
- if (default_grid.chars == NULL) {
- return;
- }
- redraw_tabline = false;
-
- if (ui_has(kUITabline)) {
- ui_ext_tabline_update();
- return;
- }
-
- if (tabline_height() < 1) {
- return;
- }
-
- // Init TabPageIdxs[] to zero: Clicking outside of tabs has no effect.
- assert(Columns == tab_page_click_defs_size);
- stl_clear_click_defs(tab_page_click_defs, tab_page_click_defs_size);
-
- // Use the 'tabline' option if it's set.
- if (*p_tal != NUL) {
- int saved_did_emsg = did_emsg;
-
- // Check for an error. If there is one we would loop in redrawing the
- // screen. Avoid that by making 'tabline' empty.
- did_emsg = false;
- win_redr_custom(NULL, false, false);
- if (did_emsg) {
- set_string_option_direct("tabline", -1, "", OPT_FREE, SID_ERROR);
- }
- did_emsg |= saved_did_emsg;
- } else {
- FOR_ALL_TABS(tp) {
- tabcount++;
- }
-
- if (tabcount > 0) {
- tabwidth = (Columns - 1 + tabcount / 2) / tabcount;
- }
-
- if (tabwidth < 6) {
- tabwidth = 6;
- }
-
- attr = attr_nosel;
- tabcount = 0;
-
- FOR_ALL_TABS(tp) {
- if (col >= Columns - 4) {
- break;
- }
-
- scol = col;
-
- if (tp == curtab) {
- cwp = curwin;
- wp = firstwin;
- } else {
- cwp = tp->tp_curwin;
- wp = tp->tp_firstwin;
- }
-
- if (tp->tp_topframe == topframe) {
- attr = win_hl_attr(cwp, HLF_TPS);
- }
- if (use_sep_chars && col > 0) {
- grid_putchar(&default_grid, '|', 0, col++, attr);
- }
-
- if (tp->tp_topframe != topframe) {
- attr = win_hl_attr(cwp, HLF_TP);
- }
-
- grid_putchar(&default_grid, ' ', 0, col++, attr);
-
- modified = false;
-
- for (wincount = 0; wp != NULL; wp = wp->w_next, wincount++) {
- if (bufIsChanged(wp->w_buffer)) {
- modified = true;
- }
- }
-
- if (modified || wincount > 1) {
- if (wincount > 1) {
- vim_snprintf((char *)NameBuff, MAXPATHL, "%d", wincount);
- len = (int)strlen(NameBuff);
- if (col + len >= Columns - 3) {
- break;
- }
- grid_puts_len(&default_grid, NameBuff, len, 0, col,
- hl_combine_attr(attr, win_hl_attr(cwp, HLF_T)));
- col += len;
- }
- if (modified) {
- grid_puts_len(&default_grid, "+", 1, 0, col++, attr);
- }
- grid_putchar(&default_grid, ' ', 0, col++, attr);
- }
-
- room = scol - col + tabwidth - 1;
- if (room > 0) {
- // Get buffer name in NameBuff[]
- get_trans_bufname(cwp->w_buffer);
- shorten_dir(NameBuff);
- len = vim_strsize((char *)NameBuff);
- p = (char_u *)NameBuff;
- while (len > room) {
- len -= ptr2cells((char *)p);
- MB_PTR_ADV(p);
- }
- if (len > Columns - col - 1) {
- len = Columns - col - 1;
- }
-
- grid_puts_len(&default_grid, (char *)p, (int)STRLEN(p), 0, col, attr);
- col += len;
- }
- grid_putchar(&default_grid, ' ', 0, col++, attr);
-
- // Store the tab page number in tab_page_click_defs[], so that
- // jump_to_mouse() knows where each one is.
- tabcount++;
- while (scol < col) {
- tab_page_click_defs[scol++] = (StlClickDefinition) {
- .type = kStlClickTabSwitch,
- .tabnr = tabcount,
- .func = NULL,
- };
- }
- }
-
- if (use_sep_chars) {
- c = '_';
- } else {
- c = ' ';
- }
- grid_fill(&default_grid, 0, 1, col, Columns, c, c, attr_fill);
-
- // Put an "X" for closing the current tab if there are several.
- if (first_tabpage->tp_next != NULL) {
- grid_putchar(&default_grid, 'X', 0, Columns - 1, attr_nosel);
- tab_page_click_defs[Columns - 1] = (StlClickDefinition) {
- .type = kStlClickTabClose,
- .tabnr = 999,
- .func = NULL,
- };
- }
- }
-
- // Reset the flag here again, in case evaluating 'tabline' causes it to be
- // set.
- redraw_tabline = false;
-}
-
-static void ui_ext_tabline_update(void)
-{
- Arena arena = ARENA_EMPTY;
-
- size_t n_tabs = 0;
- FOR_ALL_TABS(tp) {
- n_tabs++;
- }
-
- Array tabs = arena_array(&arena, n_tabs);
- FOR_ALL_TABS(tp) {
- Dictionary tab_info = arena_dict(&arena, 2);
- PUT_C(tab_info, "tab", TABPAGE_OBJ(tp->handle));
-
- win_T *cwp = (tp == curtab) ? curwin : tp->tp_curwin;
- get_trans_bufname(cwp->w_buffer);
- PUT_C(tab_info, "name", STRING_OBJ(arena_string(&arena, cstr_as_string((char *)NameBuff))));
-
- ADD_C(tabs, DICTIONARY_OBJ(tab_info));
- }
-
- size_t n_buffers = 0;
- FOR_ALL_BUFFERS(buf) {
- n_buffers += buf->b_p_bl ? 1 : 0;
- }
-
- Array buffers = arena_array(&arena, n_buffers);
- FOR_ALL_BUFFERS(buf) {
- // Do not include unlisted buffers
- if (!buf->b_p_bl) {
- continue;
- }
-
- Dictionary buffer_info = arena_dict(&arena, 2);
- PUT_C(buffer_info, "buffer", BUFFER_OBJ(buf->handle));
-
- get_trans_bufname(buf);
- PUT_C(buffer_info, "name", STRING_OBJ(arena_string(&arena, cstr_as_string((char *)NameBuff))));
-
- ADD_C(buffers, DICTIONARY_OBJ(buffer_info));
- }
-
- ui_call_tabline_update(curtab->handle, tabs, curbuf->handle, buffers);
- arena_mem_free(arena_finish(&arena));
-}
-
void get_trans_bufname(buf_T *buf)
{
if (buf_spname(buf) != NULL) {
diff --git a/src/nvim/screen.h b/src/nvim/screen.h
index ea1c58cd80..5cee708bd1 100644
--- a/src/nvim/screen.h
+++ b/src/nvim/screen.h
@@ -9,12 +9,6 @@
EXTERN match_T screen_search_hl; // used for 'hlsearch' highlight matching
-/// Array defining what should be done when tabline is clicked
-EXTERN StlClickDefinition *tab_page_click_defs INIT(= NULL);
-
-/// Size of the tab_page_click_defs array
-EXTERN long tab_page_click_defs_size INIT(= 0);
-
#define W_ENDCOL(wp) ((wp)->w_wincol + (wp)->w_width)
#define W_ENDROW(wp) ((wp)->w_winrow + (wp)->w_height)
diff --git a/src/nvim/shada.c b/src/nvim/shada.c
index d5676e9d70..64029e0799 100644
--- a/src/nvim/shada.c
+++ b/src/nvim/shada.c
@@ -3017,10 +3017,9 @@ shada_write_file_open: {}
assert(sd_reader.close != NULL);
sd_reader.close(&sd_reader);
return FAIL;
- } else {
- (*wp)++;
- goto shada_write_file_open;
}
+ (*wp)++;
+ goto shada_write_file_open;
} else {
semsg(_(SERR "System error while opening temporary ShaDa file %s "
"for writing: %s"), tempname, os_strerror(error));
@@ -3260,13 +3259,12 @@ static ShaDaReadResult fread_len(ShaDaReadDef *const sd_reader, char *const buff
semsg(_(SERR "System error while reading ShaDa file: %s"),
sd_reader->error);
return kSDReadStatusReadError;
- } else {
- semsg(_(RCERR "Error while reading ShaDa file: "
- "last entry specified that it occupies %" PRIu64 " bytes, "
- "but file ended earlier"),
- (uint64_t)length);
- return kSDReadStatusNotShaDa;
}
+ semsg(_(RCERR "Error while reading ShaDa file: "
+ "last entry specified that it occupies %" PRIu64 " bytes, "
+ "but file ended earlier"),
+ (uint64_t)length);
+ return kSDReadStatusNotShaDa;
}
return kSDReadStatusSuccess;
}
@@ -3579,16 +3577,15 @@ shada_read_next_item_start:
entry->type = kSDItemMissing;
}
return spm_ret;
- } else {
- entry->data.unknown_item.contents = xmalloc(length);
- const ShaDaReadResult fl_ret =
- fread_len(sd_reader, entry->data.unknown_item.contents, length);
- if (fl_ret != kSDReadStatusSuccess) {
- shada_free_shada_entry(entry);
- entry->type = kSDItemMissing;
- }
- return fl_ret;
}
+ entry->data.unknown_item.contents = xmalloc(length);
+ const ShaDaReadResult fl_ret =
+ fread_len(sd_reader, entry->data.unknown_item.contents, length);
+ if (fl_ret != kSDReadStatusSuccess) {
+ shada_free_shada_entry(entry);
+ entry->type = kSDItemMissing;
+ }
+ return fl_ret;
}
msgpack_unpacked unpacked;
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index e76ac49b5d..b1daf4ed23 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -112,11 +112,13 @@
#include "nvim/vim.h" // for curwin, strlen, STRLCPY, STRNCMP
// Result values. Lower number is accepted over higher one.
-#define SP_BANNED (-1)
-#define SP_RARE 0
-#define SP_OK 1
-#define SP_LOCAL 2
-#define SP_BAD 3
+enum {
+ SP_BANNED = -1,
+ SP_RARE = 0,
+ SP_OK = 1,
+ SP_LOCAL = 2,
+ SP_BAD = 3,
+};
// First language that is loaded, start of the linked list of loaded
// languages.
@@ -1214,7 +1216,14 @@ static bool decor_spell_nav_col(win_T *wp, linenr_T lnum, linenr_T *decor_lnum,
*decor_lnum = lnum;
}
decor_redraw_col(wp->w_buffer, col, col, false, &decor_state);
- return decor_state.spell;
+ return decor_state.spell == kTrue;
+}
+
+static inline bool can_syn_spell(win_T *wp, linenr_T lnum, int col)
+{
+ bool can_spell;
+ (void)syn_get_id(wp, lnum, col, false, &can_spell, false);
+ return can_spell;
}
/// Moves to the next spell error.
@@ -1344,15 +1353,9 @@ size_t spell_move_to(win_T *wp, int dir, bool allwords, bool curline, hlf_T *att
: p - buf) > wp->w_cursor.col)) {
col = (colnr_T)(p - buf);
- bool can_spell = decor_spell_nav_col(wp, lnum, &decor_lnum, col, &decor_error);
-
- if (!can_spell) {
- if (has_syntax) {
- (void)syn_get_id(wp, lnum, col, false, &can_spell, false);
- } else {
- can_spell = (wp->w_s->b_p_spo_flags & SPO_NPBUFFER) == 0;
- }
- }
+ bool can_spell = (!has_syntax && (wp->w_s->b_p_spo_flags & SPO_NPBUFFER) == 0)
+ || decor_spell_nav_col(wp, lnum, &decor_lnum, col, &decor_error)
+ || (has_syntax && can_syn_spell(wp, lnum, col));
if (!can_spell) {
attr = HLF_COUNT;
@@ -3145,7 +3148,7 @@ void ex_spelldump(exarg_T *eap)
}
char *spl;
long dummy;
- (void)get_option_value("spl", &dummy, &spl, OPT_LOCAL);
+ (void)get_option_value("spl", &dummy, &spl, NULL, OPT_LOCAL);
// Create a new empty buffer in a new window.
do_cmdline_cmd("new");
diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c
index 7837f242b5..d483863fa8 100644
--- a/src/nvim/spellfile.c
+++ b/src/nvim/spellfile.c
@@ -258,50 +258,55 @@
// Special byte values for <byte>. Some are only used in the tree for
// postponed prefixes, some only in the other trees. This is a bit messy...
-#define BY_NOFLAGS 0 // end of word without flags or region; for
- // postponed prefix: no <pflags>
-#define BY_INDEX 1 // child is shared, index follows
-#define BY_FLAGS 2 // end of word, <flags> byte follows; for
- // postponed prefix: <pflags> follows
-#define BY_FLAGS2 3 // end of word, <flags> and <flags2> bytes
- // follow; never used in prefix tree
-#define BY_SPECIAL BY_FLAGS2 // highest special byte value
+enum {
+ BY_NOFLAGS = 0, // end of word without flags or region; for postponed prefix: no <pflags>
+ BY_INDEX = 1, // child is shared, index follows
+ BY_FLAGS = 2, // end of word, <flags> byte follows; for postponed prefix: <pflags> follows
+ BY_FLAGS2 = 3, // end of word, <flags> and <flags2> bytes follow; never used in prefix tree
+ BY_SPECIAL = BY_FLAGS2, // highest special byte value
+};
#define ZERO_FLAG 65009 // used when flag is zero: "0"
// Flags used in .spl file for soundsalike flags.
-#define SAL_F0LLOWUP 1
-#define SAL_COLLAPSE 2
-#define SAL_REM_ACCENTS 4
+enum {
+ SAL_F0LLOWUP = 1,
+ SAL_COLLAPSE = 2,
+ SAL_REM_ACCENTS = 4,
+};
#define VIMSPELLMAGIC "VIMspell" // string at start of Vim spell file
#define VIMSPELLMAGICL (sizeof(VIMSPELLMAGIC) - 1)
#define VIMSPELLVERSION 50
// Section IDs. Only renumber them when VIMSPELLVERSION changes!
-#define SN_REGION 0 // <regionname> section
-#define SN_CHARFLAGS 1 // charflags section
-#define SN_MIDWORD 2 // <midword> section
-#define SN_PREFCOND 3 // <prefcond> section
-#define SN_REP 4 // REP items section
-#define SN_SAL 5 // SAL items section
-#define SN_SOFO 6 // soundfolding section
-#define SN_MAP 7 // MAP items section
-#define SN_COMPOUND 8 // compound words section
-#define SN_SYLLABLE 9 // syllable section
-#define SN_NOBREAK 10 // NOBREAK section
-#define SN_SUGFILE 11 // timestamp for .sug file
-#define SN_REPSAL 12 // REPSAL items section
-#define SN_WORDS 13 // common words
-#define SN_NOSPLITSUGS 14 // don't split word for suggestions
-#define SN_INFO 15 // info section
-#define SN_NOCOMPOUNDSUGS 16 // don't compound for suggestions
-#define SN_END 255 // end of sections
+enum {
+ SN_REGION = 0, // <regionname> section
+ SN_CHARFLAGS = 1, // charflags section
+ SN_MIDWORD = 2, // <midword> section
+ SN_PREFCOND = 3, // <prefcond> section
+ SN_REP = 4, // REP items section
+ SN_SAL = 5, // SAL items section
+ SN_SOFO = 6, // soundfolding section
+ SN_MAP = 7, // MAP items section
+ SN_COMPOUND = 8, // compound words section
+ SN_SYLLABLE = 9, // syllable section
+ SN_NOBREAK = 10, // NOBREAK section
+ SN_SUGFILE = 11, // timestamp for .sug file
+ SN_REPSAL = 12, // REPSAL items section
+ SN_WORDS = 13, // common words
+ SN_NOSPLITSUGS = 14, // don't split word for suggestions
+ SN_INFO = 15, // info section
+ SN_NOCOMPOUNDSUGS = 16, // don't compound for suggestions
+ SN_END = 255, // end of sections
+};
#define SNF_REQUIRED 1 // <sectionflags>: required section
-#define CF_WORD 0x01
-#define CF_UPPER 0x02
+enum {
+ CF_WORD = 0x01,
+ CF_UPPER = 0x02,
+};
static char *e_spell_trunc = N_("E758: Truncated spell file");
static char *e_illegal_character_in_word = N_("E1280: Illegal character in word");
@@ -2465,9 +2470,9 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
aff_entry->ae_cond = (char_u *)getroom_save(spin, (char_u *)items[4]);
if (*items[0] == 'P') {
- sprintf((char *)buf, "^%s", items[4]);
+ sprintf((char *)buf, "^%s", items[4]); // NOLINT(runtime/printf)
} else {
- sprintf((char *)buf, "%s$", items[4]);
+ sprintf((char *)buf, "%s$", items[4]); // NOLINT(runtime/printf)
}
aff_entry->ae_prog = vim_regcomp((char *)buf, RE_MAGIC + RE_STRING + RE_STRICT);
if (aff_entry->ae_prog == NULL) {
@@ -2514,8 +2519,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
onecap_copy((char_u *)items[4], buf, true);
aff_entry->ae_cond = (char_u *)getroom_save(spin, buf);
if (aff_entry->ae_cond != NULL) {
- sprintf((char *)buf, "^%s",
- aff_entry->ae_cond);
+ sprintf((char *)buf, "^%s", aff_entry->ae_cond); // NOLINT(runtime/printf)
vim_regfree(aff_entry->ae_prog);
aff_entry->ae_prog = vim_regcomp((char *)buf, RE_MAGIC + RE_STRING);
}
@@ -3614,7 +3618,7 @@ static int store_aff_word(spellinfo_T *spin, char_u *word, char_u *afflist, afff
if (store_aff_word(spin, newword, ae->ae_flags,
affile, &affile->af_suff, xht,
use_condit & (xht == NULL
- ? ~0 : ~CONDIT_SUF),
+ ? ~0 : ~CONDIT_SUF),
use_flags, use_pfxlist, pfxlen) == FAIL) {
retval = FAIL;
}
diff --git a/src/nvim/spellsuggest.c b/src/nvim/spellsuggest.c
index 400579a233..28bc77c1e5 100644
--- a/src/nvim/spellsuggest.c
+++ b/src/nvim/spellsuggest.c
@@ -91,45 +91,55 @@ typedef struct {
#define SUG_MAX_COUNT(su) (SUG_CLEAN_COUNT(su) + 50)
// score for various changes
-#define SCORE_SPLIT 149 // split bad word
-#define SCORE_SPLIT_NO 249 // split bad word with NOSPLITSUGS
-#define SCORE_ICASE 52 // slightly different case
-#define SCORE_REGION 200 // word is for different region
-#define SCORE_RARE 180 // rare word
-#define SCORE_SWAP 75 // swap two characters
-#define SCORE_SWAP3 110 // swap two characters in three
-#define SCORE_REP 65 // REP replacement
-#define SCORE_SUBST 93 // substitute a character
-#define SCORE_SIMILAR 33 // substitute a similar character
-#define SCORE_SUBCOMP 33 // substitute a composing character
-#define SCORE_DEL 94 // delete a character
-#define SCORE_DELDUP 66 // delete a duplicated character
-#define SCORE_DELCOMP 28 // delete a composing character
-#define SCORE_INS 96 // insert a character
-#define SCORE_INSDUP 67 // insert a duplicate character
-#define SCORE_INSCOMP 30 // insert a composing character
-#define SCORE_NONWORD 103 // change non-word to word char
-
-#define SCORE_FILE 30 // suggestion from a file
-#define SCORE_MAXINIT 350 // Initial maximum score: higher == slower.
- // 350 allows for about three changes.
-
-#define SCORE_COMMON1 30 // subtracted for words seen before
-#define SCORE_COMMON2 40 // subtracted for words often seen
-#define SCORE_COMMON3 50 // subtracted for words very often seen
-#define SCORE_THRES2 10 // word count threshold for COMMON2
-#define SCORE_THRES3 100 // word count threshold for COMMON3
+enum {
+ SCORE_SPLIT = 149, // split bad word
+ SCORE_SPLIT_NO = 249, // split bad word with NOSPLITSUGS
+ SCORE_ICASE = 52, // slightly different case
+ SCORE_REGION = 200, // word is for different region
+ SCORE_RARE = 180, // rare word
+ SCORE_SWAP = 75, // swap two characters
+ SCORE_SWAP3 = 110, // swap two characters in three
+ SCORE_REP = 65, // REP replacement
+ SCORE_SUBST = 93, // substitute a character
+ SCORE_SIMILAR = 33, // substitute a similar character
+ SCORE_SUBCOMP = 33, // substitute a composing character
+ SCORE_DEL = 94, // delete a character
+ SCORE_DELDUP = 66, // delete a duplicated character
+ SCORE_DELCOMP = 28, // delete a composing character
+ SCORE_INS = 96, // insert a character
+ SCORE_INSDUP = 67, // insert a duplicate character
+ SCORE_INSCOMP = 30, // insert a composing character
+ SCORE_NONWORD = 103, // change non-word to word char
+};
+
+enum {
+ SCORE_FILE = 30, // suggestion from a file
+ SCORE_MAXINIT = 350, // Initial maximum score: higher == slower.
+ // 350 allows for about three changes.
+};
+
+enum {
+ SCORE_COMMON1 = 30, // subtracted for words seen before
+ SCORE_COMMON2 = 40, // subtracted for words often seen
+ SCORE_COMMON3 = 50, // subtracted for words very often seen
+ SCORE_THRES2 = 10, // word count threshold for COMMON2
+ SCORE_THRES3 = 100, // word count threshold for COMMON3
+};
// When trying changed soundfold words it becomes slow when trying more than
// two changes. With less than two changes it's slightly faster but we miss a
// few good suggestions. In rare cases we need to try three of four changes.
-#define SCORE_SFMAX1 200 // maximum score for first try
-#define SCORE_SFMAX2 300 // maximum score for second try
-#define SCORE_SFMAX3 400 // maximum score for third try
+enum {
+ SCORE_SFMAX1 = 200, // maximum score for first try
+ SCORE_SFMAX2 = 300, // maximum score for second try
+ SCORE_SFMAX3 = 400, // maximum score for third try
+};
#define SCORE_BIG (SCORE_INS * 3) // big difference
-#define SCORE_MAXMAX 999999 // accept any score
-#define SCORE_LIMITMAX 350 // for spell_edit_score_limit()
+enum {
+ SCORE_MAXMAX = 999999, // accept any score
+ SCORE_LIMITMAX = 350, // for spell_edit_score_limit()
+};
// for spell_edit_score_limit() we need to know the minimum value of
// SCORE_ICASE, SCORE_SWAP, SCORE_DEL, SCORE_SIMILAR and SCORE_INS
@@ -186,19 +196,25 @@ typedef struct trystate_S {
} trystate_T;
// values for ts_isdiff
-#define DIFF_NONE 0 // no different byte (yet)
-#define DIFF_YES 1 // different byte found
-#define DIFF_INSERT 2 // inserting character
+enum {
+ DIFF_NONE = 0, // no different byte (yet)
+ DIFF_YES = 1, // different byte found
+ DIFF_INSERT = 2, // inserting character
+};
// values for ts_flags
-#define TSF_PREFIXOK 1 // already checked that prefix is OK
-#define TSF_DIDSPLIT 2 // tried split at this point
-#define TSF_DIDDEL 4 // did a delete, "ts_delidx" has index
+enum {
+ TSF_PREFIXOK = 1, // already checked that prefix is OK
+ TSF_DIDSPLIT = 2, // tried split at this point
+ TSF_DIDDEL = 4, // did a delete, "ts_delidx" has index
+};
// special values ts_prefixdepth
-#define PFD_NOPREFIX 0xff // not using prefixes
-#define PFD_PREFIXTREE 0xfe // walking through the prefix tree
-#define PFD_NOTSPECIAL 0xfd // highest value that's not special
+enum {
+ PFD_NOPREFIX = 0xff, // not using prefixes
+ PFD_PREFIXTREE = 0xfe, // walking through the prefix tree
+ PFD_NOTSPECIAL = 0xfd, // highest value that's not special
+};
static long spell_suggest_timeout = 5000;
@@ -341,9 +357,11 @@ static int bytes2offset(char_u **pp)
}
// values for sps_flags
-#define SPS_BEST 1
-#define SPS_FAST 2
-#define SPS_DOUBLE 4
+enum {
+ SPS_BEST = 1,
+ SPS_FAST = 2,
+ SPS_DOUBLE = 4,
+};
static int sps_flags = SPS_BEST; ///< flags from 'spellsuggest'
static int sps_limit = 9999; ///< max nr of suggestions given
diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c
index fb49a1b6a7..93334a1d75 100644
--- a/src/nvim/statusline.c
+++ b/src/nvim/statusline.c
@@ -158,6 +158,243 @@ void win_redr_status(win_T *wp)
busy = false;
}
+/// Clear status line, window bar or tab page line click definition table
+///
+/// @param[out] tpcd Table to clear.
+/// @param[in] tpcd_size Size of the table.
+void stl_clear_click_defs(StlClickDefinition *const click_defs, const size_t click_defs_size)
+{
+ if (click_defs != NULL) {
+ for (size_t i = 0; i < click_defs_size; i++) {
+ if (i == 0 || click_defs[i].func != click_defs[i - 1].func) {
+ xfree(click_defs[i].func);
+ }
+ }
+ memset(click_defs, 0, click_defs_size * sizeof(click_defs[0]));
+ }
+}
+
+/// Allocate or resize the click definitions array if needed.
+StlClickDefinition *stl_alloc_click_defs(StlClickDefinition *cdp, long width, size_t *size)
+{
+ if (*size < (size_t)width) {
+ xfree(cdp);
+ *size = (size_t)width;
+ cdp = xcalloc(*size, sizeof(StlClickDefinition));
+ }
+ return cdp;
+}
+
+/// Fill the click definitions array if needed.
+void stl_fill_click_defs(StlClickDefinition *click_defs, StlClickRecord *click_recs, char *buf,
+ int width, bool tabline)
+{
+ if (click_defs == NULL) {
+ return;
+ }
+
+ int col = 0;
+ int len = 0;
+
+ StlClickDefinition cur_click_def = {
+ .type = kStlClickDisabled,
+ };
+ for (int i = 0; click_recs[i].start != NULL; i++) {
+ len += vim_strnsize(buf, (int)(click_recs[i].start - buf));
+ while (col < len) {
+ click_defs[col++] = cur_click_def;
+ }
+ buf = (char *)click_recs[i].start;
+ cur_click_def = click_recs[i].def;
+ if (!tabline && !(cur_click_def.type == kStlClickDisabled
+ || cur_click_def.type == kStlClickFuncRun)) {
+ // window bar and status line only support click functions
+ cur_click_def.type = kStlClickDisabled;
+ }
+ }
+ while (col < width) {
+ click_defs[col++] = cur_click_def;
+ }
+}
+
+/// Redraw the status line, window bar or ruler of window "wp".
+/// When "wp" is NULL redraw the tab pages line from 'tabline'.
+static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
+{
+ static bool entered = false;
+ int attr;
+ int curattr;
+ int row;
+ int col = 0;
+ int maxwidth;
+ int width;
+ int n;
+ int len;
+ int fillchar;
+ char buf[MAXPATHL];
+ char *stl;
+ char *p;
+ char *opt_name;
+ int opt_scope = 0;
+ stl_hlrec_t *hltab;
+ StlClickRecord *tabtab;
+ win_T *ewp;
+ int p_crb_save;
+ bool is_stl_global = global_stl_height() > 0;
+
+ ScreenGrid *grid = &default_grid;
+
+ // There is a tiny chance that this gets called recursively: When
+ // redrawing a status line triggers redrawing the ruler or tabline.
+ // Avoid trouble by not allowing recursion.
+ if (entered) {
+ return;
+ }
+ entered = true;
+
+ // setup environment for the task at hand
+ if (wp == NULL) {
+ // Use 'tabline'. Always at the first line of the screen.
+ stl = p_tal;
+ row = 0;
+ fillchar = ' ';
+ attr = HL_ATTR(HLF_TPF);
+ maxwidth = Columns;
+ opt_name = "tabline";
+ } else if (draw_winbar) {
+ opt_name = "winbar";
+ stl = ((*wp->w_p_wbr != NUL) ? wp->w_p_wbr : p_wbr);
+ opt_scope = ((*wp->w_p_wbr != NUL) ? OPT_LOCAL : 0);
+ row = -1; // row zero is first row of text
+ col = 0;
+ grid = &wp->w_grid;
+ grid_adjust(&grid, &row, &col);
+
+ if (row < 0) {
+ return;
+ }
+
+ fillchar = wp->w_p_fcs_chars.wbr;
+ attr = (wp == curwin) ? win_hl_attr(wp, HLF_WBR) : win_hl_attr(wp, HLF_WBRNC);
+ maxwidth = wp->w_width_inner;
+ stl_clear_click_defs(wp->w_winbar_click_defs, wp->w_winbar_click_defs_size);
+ wp->w_winbar_click_defs = stl_alloc_click_defs(wp->w_winbar_click_defs, maxwidth,
+ &wp->w_winbar_click_defs_size);
+ } else {
+ row = is_stl_global ? (Rows - (int)p_ch - 1) : W_ENDROW(wp);
+ fillchar = fillchar_status(&attr, wp);
+ maxwidth = is_stl_global ? Columns : wp->w_width;
+ stl_clear_click_defs(wp->w_status_click_defs, wp->w_status_click_defs_size);
+ wp->w_status_click_defs = stl_alloc_click_defs(wp->w_status_click_defs, maxwidth,
+ &wp->w_status_click_defs_size);
+
+ if (draw_ruler) {
+ stl = p_ruf;
+ opt_name = "rulerformat";
+ // advance past any leading group spec - implicit in ru_col
+ if (*stl == '%') {
+ if (*++stl == '-') {
+ stl++;
+ }
+ if (atoi(stl)) {
+ while (ascii_isdigit(*stl)) {
+ stl++;
+ }
+ }
+ if (*stl++ != '(') {
+ stl = p_ruf;
+ }
+ }
+ col = ru_col - (Columns - maxwidth);
+ if (col < (maxwidth + 1) / 2) {
+ col = (maxwidth + 1) / 2;
+ }
+ maxwidth = maxwidth - col;
+ if (!wp->w_status_height && !is_stl_global) {
+ grid = &msg_grid_adj;
+ row = Rows - 1;
+ maxwidth--; // writing in last column may cause scrolling
+ fillchar = ' ';
+ attr = HL_ATTR(HLF_MSG);
+ }
+ } else {
+ opt_name = "statusline";
+ stl = ((*wp->w_p_stl != NUL) ? wp->w_p_stl : p_stl);
+ opt_scope = ((*wp->w_p_stl != NUL) ? OPT_LOCAL : 0);
+ }
+
+ col += is_stl_global ? 0 : wp->w_wincol;
+ }
+
+ if (maxwidth <= 0) {
+ goto theend;
+ }
+
+ // Temporarily reset 'cursorbind', we don't want a side effect from moving
+ // the cursor away and back.
+ ewp = wp == NULL ? curwin : wp;
+ p_crb_save = ewp->w_p_crb;
+ ewp->w_p_crb = false;
+
+ // Make a copy, because the statusline may include a function call that
+ // might change the option value and free the memory.
+ stl = xstrdup(stl);
+ width = build_stl_str_hl(ewp, buf, sizeof(buf), stl, opt_name,
+ opt_scope, fillchar, maxwidth, &hltab, &tabtab);
+ xfree(stl);
+ ewp->w_p_crb = p_crb_save;
+
+ // Make all characters printable.
+ p = transstr(buf, true);
+ len = (int)STRLCPY(buf, p, sizeof(buf));
+ len = (size_t)len < sizeof(buf) ? len : (int)sizeof(buf) - 1;
+ xfree(p);
+
+ // fill up with "fillchar"
+ while (width < maxwidth && len < (int)sizeof(buf) - 1) {
+ len += utf_char2bytes(fillchar, buf + len);
+ width++;
+ }
+ buf[len] = NUL;
+
+ // Draw each snippet with the specified highlighting.
+ grid_puts_line_start(grid, row);
+
+ curattr = attr;
+ p = buf;
+ for (n = 0; hltab[n].start != NULL; n++) {
+ int textlen = (int)(hltab[n].start - p);
+ grid_puts_len(grid, p, textlen, row, col, curattr);
+ col += vim_strnsize(p, textlen);
+ p = hltab[n].start;
+
+ if (hltab[n].userhl == 0) {
+ curattr = attr;
+ } else if (hltab[n].userhl < 0) {
+ curattr = syn_id2attr(-hltab[n].userhl);
+ } else if (wp != NULL && wp != curwin && wp->w_status_height != 0) {
+ curattr = highlight_stlnc[hltab[n].userhl - 1];
+ } else {
+ curattr = highlight_user[hltab[n].userhl - 1];
+ }
+ }
+ // Make sure to use an empty string instead of p, if p is beyond buf + len.
+ grid_puts(grid, p >= buf + len ? "" : p, row, col, curattr);
+
+ grid_puts_line_flush(false);
+
+ // Fill the tab_page_click_defs, w_status_click_defs or w_winbar_click_defs array for clicking
+ // in the tab page line, status line or window bar
+ StlClickDefinition *click_defs = (wp == NULL) ? tab_page_click_defs
+ : draw_winbar ? wp->w_winbar_click_defs
+ : wp->w_status_click_defs;
+
+ stl_fill_click_defs(click_defs, tabtab, buf, maxwidth, wp == NULL);
+
+theend:
+ entered = false;
+}
+
void win_redr_winbar(win_T *wp)
{
static bool entered = false;
@@ -172,19 +409,7 @@ void win_redr_winbar(win_T *wp)
if (wp->w_winbar_height == 0 || !redrawing()) {
// Do nothing.
} else if (*p_wbr != NUL || *wp->w_p_wbr != NUL) {
- int saved_did_emsg = did_emsg;
-
- did_emsg = false;
win_redr_custom(wp, true, false);
- if (did_emsg) {
- // When there is an error disable the winbar, otherwise the
- // display is messed up with errors and a redraw triggers the problem
- // again and again.
- set_string_option_direct("winbar", -1, "",
- OPT_FREE | (*wp->w_p_stl != NUL
- ? OPT_LOCAL : OPT_GLOBAL), SID_ERROR);
- }
- did_emsg |= saved_did_emsg;
}
entered = false;
}
@@ -214,11 +439,7 @@ void win_redr_ruler(win_T *wp, bool always)
}
if (*p_ruf && p_ch > 0 && !ui_has(kUIMessages)) {
- const int called_emsg_before = called_emsg;
win_redr_custom(wp, false, true);
- if (called_emsg > called_emsg_before) {
- set_string_option_direct("rulerformat", -1, "", OPT_FREE, SID_ERROR);
- }
return;
}
@@ -389,7 +610,6 @@ int fillchar_status(int *attr, win_T *wp)
void redraw_custom_statusline(win_T *wp)
{
static bool entered = false;
- int saved_did_emsg = did_emsg;
// When called recursively return. This can happen when the statusline
// contains an expression that triggers a redraw.
@@ -398,234 +618,215 @@ void redraw_custom_statusline(win_T *wp)
}
entered = true;
- did_emsg = false;
win_redr_custom(wp, false, false);
- if (did_emsg) {
- // When there is an error disable the statusline, otherwise the
- // display is messed up with errors and a redraw triggers the problem
- // again and again.
- set_string_option_direct("statusline", -1, "",
- OPT_FREE | (*wp->w_p_stl != NUL
- ? OPT_LOCAL : OPT_GLOBAL), SID_ERROR);
- }
- did_emsg |= saved_did_emsg;
entered = false;
}
-/// Redraw the status line, window bar or ruler of window "wp".
-/// When "wp" is NULL redraw the tab pages line from 'tabline'.
-void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
+static void ui_ext_tabline_update(void)
{
- static bool entered = false;
- int attr;
- int curattr;
- int row;
+ Arena arena = ARENA_EMPTY;
+
+ size_t n_tabs = 0;
+ FOR_ALL_TABS(tp) {
+ n_tabs++;
+ }
+
+ Array tabs = arena_array(&arena, n_tabs);
+ FOR_ALL_TABS(tp) {
+ Dictionary tab_info = arena_dict(&arena, 2);
+ PUT_C(tab_info, "tab", TABPAGE_OBJ(tp->handle));
+
+ win_T *cwp = (tp == curtab) ? curwin : tp->tp_curwin;
+ get_trans_bufname(cwp->w_buffer);
+ PUT_C(tab_info, "name", STRING_OBJ(arena_string(&arena, cstr_as_string((char *)NameBuff))));
+
+ ADD_C(tabs, DICTIONARY_OBJ(tab_info));
+ }
+
+ size_t n_buffers = 0;
+ FOR_ALL_BUFFERS(buf) {
+ n_buffers += buf->b_p_bl ? 1 : 0;
+ }
+
+ Array buffers = arena_array(&arena, n_buffers);
+ FOR_ALL_BUFFERS(buf) {
+ // Do not include unlisted buffers
+ if (!buf->b_p_bl) {
+ continue;
+ }
+
+ Dictionary buffer_info = arena_dict(&arena, 2);
+ PUT_C(buffer_info, "buffer", BUFFER_OBJ(buf->handle));
+
+ get_trans_bufname(buf);
+ PUT_C(buffer_info, "name", STRING_OBJ(arena_string(&arena, cstr_as_string((char *)NameBuff))));
+
+ ADD_C(buffers, DICTIONARY_OBJ(buffer_info));
+ }
+
+ ui_call_tabline_update(curtab->handle, tabs, curbuf->handle, buffers);
+ arena_mem_free(arena_finish(&arena));
+}
+
+/// Draw the tab pages line at the top of the Vim window.
+void draw_tabline(void)
+{
+ int tabcount = 0;
+ int tabwidth = 0;
int col = 0;
- int maxwidth;
- int width;
- int n;
+ int scol = 0;
+ int attr;
+ win_T *wp;
+ win_T *cwp;
+ int wincount;
+ int modified;
+ int c;
int len;
- int fillchar;
- char buf[MAXPATHL];
- char *stl;
- char *p;
- stl_hlrec_t *hltab;
- StlClickRecord *tabtab;
- int use_sandbox = false;
- win_T *ewp;
- int p_crb_save;
- bool is_stl_global = global_stl_height() > 0;
+ int attr_nosel = HL_ATTR(HLF_TP);
+ int attr_fill = HL_ATTR(HLF_TPF);
+ char_u *p;
+ int room;
+ int use_sep_chars = (t_colors < 8);
- ScreenGrid *grid = &default_grid;
+ if (default_grid.chars == NULL) {
+ return;
+ }
+ redraw_tabline = false;
- // There is a tiny chance that this gets called recursively: When
- // redrawing a status line triggers redrawing the ruler or tabline.
- // Avoid trouble by not allowing recursion.
- if (entered) {
+ if (ui_has(kUITabline)) {
+ ui_ext_tabline_update();
return;
}
- entered = true;
- // setup environment for the task at hand
- if (wp == NULL) {
- // Use 'tabline'. Always at the first line of the screen.
- stl = p_tal;
- row = 0;
- fillchar = ' ';
- attr = HL_ATTR(HLF_TPF);
- maxwidth = Columns;
- use_sandbox = was_set_insecurely(wp, "tabline", 0);
- } else if (draw_winbar) {
- stl = ((*wp->w_p_wbr != NUL) ? wp->w_p_wbr : p_wbr);
- row = -1; // row zero is first row of text
- col = 0;
- grid = &wp->w_grid;
- grid_adjust(&grid, &row, &col);
+ if (tabline_height() < 1) {
+ return;
+ }
- if (row < 0) {
- return;
+ // Use the 'tabline' option if it's set.
+ if (*p_tal != NUL) {
+ win_redr_custom(NULL, false, false);
+ } else {
+ FOR_ALL_TABS(tp) {
+ tabcount++;
}
- fillchar = wp->w_p_fcs_chars.wbr;
- attr = (wp == curwin) ? win_hl_attr(wp, HLF_WBR) : win_hl_attr(wp, HLF_WBRNC);
- maxwidth = wp->w_width_inner;
- use_sandbox = was_set_insecurely(wp, "winbar", 0);
-
- stl_clear_click_defs(wp->w_winbar_click_defs, (long)wp->w_winbar_click_defs_size);
- // Allocate / resize the click definitions array for winbar if needed.
- if (wp->w_winbar_height && wp->w_winbar_click_defs_size < (size_t)maxwidth) {
- xfree(wp->w_winbar_click_defs);
- wp->w_winbar_click_defs_size = (size_t)maxwidth;
- wp->w_winbar_click_defs = xcalloc(wp->w_winbar_click_defs_size, sizeof(StlClickRecord));
+ if (tabcount > 0) {
+ tabwidth = (Columns - 1 + tabcount / 2) / tabcount;
}
- } else {
- row = is_stl_global ? (Rows - (int)p_ch - 1) : W_ENDROW(wp);
- fillchar = fillchar_status(&attr, wp);
- maxwidth = is_stl_global ? Columns : wp->w_width;
- stl_clear_click_defs(wp->w_status_click_defs, (long)wp->w_status_click_defs_size);
- // Allocate / resize the click definitions array for statusline if needed.
- if (wp->w_status_click_defs_size < (size_t)maxwidth) {
- xfree(wp->w_status_click_defs);
- wp->w_status_click_defs_size = (size_t)maxwidth;
- wp->w_status_click_defs = xcalloc(wp->w_status_click_defs_size, sizeof(StlClickRecord));
+ if (tabwidth < 6) {
+ tabwidth = 6;
}
- if (draw_ruler) {
- stl = p_ruf;
- // advance past any leading group spec - implicit in ru_col
- if (*stl == '%') {
- if (*++stl == '-') {
- stl++;
- }
- if (atoi(stl)) {
- while (ascii_isdigit(*stl)) {
- stl++;
- }
- }
- if (*stl++ != '(') {
- stl = p_ruf;
- }
- }
- col = ru_col - (Columns - maxwidth);
- if (col < (maxwidth + 1) / 2) {
- col = (maxwidth + 1) / 2;
- }
- maxwidth = maxwidth - col;
- if (!wp->w_status_height && !is_stl_global) {
- grid = &msg_grid_adj;
- row = Rows - 1;
- maxwidth--; // writing in last column may cause scrolling
- fillchar = ' ';
- attr = HL_ATTR(HLF_MSG);
+ attr = attr_nosel;
+ tabcount = 0;
+
+ FOR_ALL_TABS(tp) {
+ if (col >= Columns - 4) {
+ break;
}
- use_sandbox = was_set_insecurely(wp, "rulerformat", 0);
- } else {
- if (*wp->w_p_stl != NUL) {
- stl = wp->w_p_stl;
+ scol = col;
+
+ if (tp == curtab) {
+ cwp = curwin;
+ wp = firstwin;
} else {
- stl = p_stl;
+ cwp = tp->tp_curwin;
+ wp = tp->tp_firstwin;
}
- use_sandbox = was_set_insecurely(wp, "statusline", *wp->w_p_stl == NUL ? 0 : OPT_LOCAL);
- }
- col += is_stl_global ? 0 : wp->w_wincol;
- }
+ if (tp->tp_topframe == topframe) {
+ attr = win_hl_attr(cwp, HLF_TPS);
+ }
+ if (use_sep_chars && col > 0) {
+ grid_putchar(&default_grid, '|', 0, col++, attr);
+ }
- if (maxwidth <= 0) {
- goto theend;
- }
+ if (tp->tp_topframe != topframe) {
+ attr = win_hl_attr(cwp, HLF_TP);
+ }
- // Temporarily reset 'cursorbind', we don't want a side effect from moving
- // the cursor away and back.
- ewp = wp == NULL ? curwin : wp;
- p_crb_save = ewp->w_p_crb;
- ewp->w_p_crb = false;
+ grid_putchar(&default_grid, ' ', 0, col++, attr);
- // Make a copy, because the statusline may include a function call that
- // might change the option value and free the memory.
- stl = xstrdup(stl);
- width =
- build_stl_str_hl(ewp, buf, sizeof(buf), stl, use_sandbox,
- fillchar, maxwidth, &hltab, &tabtab);
- xfree(stl);
- ewp->w_p_crb = p_crb_save;
-
- // Make all characters printable.
- p = transstr(buf, true);
- len = (int)STRLCPY(buf, p, sizeof(buf));
- len = (size_t)len < sizeof(buf) ? len : (int)sizeof(buf) - 1;
- xfree(p);
+ modified = false;
- // fill up with "fillchar"
- while (width < maxwidth && len < (int)sizeof(buf) - 1) {
- len += utf_char2bytes(fillchar, buf + len);
- width++;
- }
- buf[len] = NUL;
+ for (wincount = 0; wp != NULL; wp = wp->w_next, wincount++) {
+ if (bufIsChanged(wp->w_buffer)) {
+ modified = true;
+ }
+ }
- // Draw each snippet with the specified highlighting.
- grid_puts_line_start(grid, row);
+ if (modified || wincount > 1) {
+ if (wincount > 1) {
+ vim_snprintf((char *)NameBuff, MAXPATHL, "%d", wincount);
+ len = (int)strlen(NameBuff);
+ if (col + len >= Columns - 3) {
+ break;
+ }
+ grid_puts_len(&default_grid, NameBuff, len, 0, col,
+ hl_combine_attr(attr, win_hl_attr(cwp, HLF_T)));
+ col += len;
+ }
+ if (modified) {
+ grid_puts_len(&default_grid, "+", 1, 0, col++, attr);
+ }
+ grid_putchar(&default_grid, ' ', 0, col++, attr);
+ }
- curattr = attr;
- p = buf;
- for (n = 0; hltab[n].start != NULL; n++) {
- int textlen = (int)(hltab[n].start - p);
- grid_puts_len(grid, p, textlen, row, col, curattr);
- col += vim_strnsize(p, textlen);
- p = hltab[n].start;
+ room = scol - col + tabwidth - 1;
+ if (room > 0) {
+ // Get buffer name in NameBuff[]
+ get_trans_bufname(cwp->w_buffer);
+ shorten_dir(NameBuff);
+ len = vim_strsize((char *)NameBuff);
+ p = (char_u *)NameBuff;
+ while (len > room) {
+ len -= ptr2cells((char *)p);
+ MB_PTR_ADV(p);
+ }
+ if (len > Columns - col - 1) {
+ len = Columns - col - 1;
+ }
- if (hltab[n].userhl == 0) {
- curattr = attr;
- } else if (hltab[n].userhl < 0) {
- curattr = syn_id2attr(-hltab[n].userhl);
- } else if (wp != NULL && wp != curwin && wp->w_status_height != 0) {
- curattr = highlight_stlnc[hltab[n].userhl - 1];
- } else {
- curattr = highlight_user[hltab[n].userhl - 1];
+ grid_puts_len(&default_grid, (char *)p, (int)STRLEN(p), 0, col, attr);
+ col += len;
+ }
+ grid_putchar(&default_grid, ' ', 0, col++, attr);
+
+ // Store the tab page number in tab_page_click_defs[], so that
+ // jump_to_mouse() knows where each one is.
+ tabcount++;
+ while (scol < col) {
+ tab_page_click_defs[scol++] = (StlClickDefinition) {
+ .type = kStlClickTabSwitch,
+ .tabnr = tabcount,
+ .func = NULL,
+ };
+ }
}
- }
- // Make sure to use an empty string instead of p, if p is beyond buf + len.
- grid_puts(grid, p >= buf + len ? "" : p, row, col, curattr);
-
- grid_puts_line_flush(false);
-
- // Fill the tab_page_click_defs, w_status_click_defs or w_winbar_click_defs array for clicking
- // in the tab page line, status line or window bar
- StlClickDefinition *click_defs = (wp == NULL) ? tab_page_click_defs
- : draw_winbar ? wp->w_winbar_click_defs
- : wp->w_status_click_defs;
-
- if (click_defs == NULL) {
- goto theend;
- }
- col = 0;
- len = 0;
- p = buf;
- StlClickDefinition cur_click_def = {
- .type = kStlClickDisabled,
- };
- for (n = 0; tabtab[n].start != NULL; n++) {
- len += vim_strnsize(p, (int)(tabtab[n].start - p));
- while (col < len) {
- click_defs[col++] = cur_click_def;
+ if (use_sep_chars) {
+ c = '_';
+ } else {
+ c = ' ';
}
- p = (char *)tabtab[n].start;
- cur_click_def = tabtab[n].def;
- if ((wp != NULL) && !(cur_click_def.type == kStlClickDisabled
- || cur_click_def.type == kStlClickFuncRun)) {
- // window bar and status line only support click functions
- cur_click_def.type = kStlClickDisabled;
+ grid_fill(&default_grid, 0, 1, col, Columns, c, c, attr_fill);
+
+ // Put an "X" for closing the current tab if there are several.
+ if (first_tabpage->tp_next != NULL) {
+ grid_putchar(&default_grid, 'X', 0, Columns - 1, attr_nosel);
+ tab_page_click_defs[Columns - 1] = (StlClickDefinition) {
+ .type = kStlClickTabClose,
+ .tabnr = 999,
+ .func = NULL,
+ };
}
}
- while (col < maxwidth) {
- click_defs[col++] = cur_click_def;
- }
-theend:
- entered = false;
+ // Reset the flag here again, in case evaluating 'tabline' causes it to be
+ // set.
+ redraw_tabline = false;
}
/// Build a string from the status line items in "fmt".
@@ -646,15 +847,16 @@ theend:
/// Note: This should not be NameBuff
/// @param outlen The length of the output buffer
/// @param fmt The statusline format string
-/// @param use_sandbox Use a sandboxed environment when evaluating fmt
+/// @param opt_name The option name corresponding to "fmt"
+/// @param opt_scope The scope corresponding to "opt_name"
/// @param fillchar Character to use when filling empty space in the statusline
/// @param maxwidth The maximum width to make the statusline
/// @param hltab HL attributes (can be NULL)
/// @param tabtab Tab clicks definition (can be NULL).
///
/// @return The final width of the statusline
-int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, int use_sandbox, int fillchar,
- int maxwidth, stl_hlrec_t **hltab, StlClickRecord **tabtab)
+int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_name, int opt_scope,
+ int fillchar, int maxwidth, stl_hlrec_t **hltab, StlClickRecord **tabtab)
{
static size_t stl_items_len = 20; // Initial value, grows as needed.
static stl_item_t *stl_items = NULL;
@@ -669,6 +871,10 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, int use_san
char *usefmt = fmt;
const int save_must_redraw = must_redraw;
const int save_redr_type = curwin->w_redr_type;
+ // TODO(Bram): find out why using called_emsg_before makes tests fail, does it
+ // matter?
+ // const int called_emsg_before = called_emsg;
+ const int did_emsg_before = did_emsg;
if (stl_items == NULL) {
stl_items = xmalloc(sizeof(stl_item_t) * stl_items_len);
@@ -682,6 +888,11 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, int use_san
stl_separator_locations = xmalloc(sizeof(int) * stl_items_len);
}
+ // if "fmt" was set insecurely it needs to be evaluated in the sandbox
+ // "opt_name" will be NULL when caller is nvim_eval_statusline()
+ const int use_sandbox = opt_name ? was_set_insecurely(wp, opt_name, opt_scope)
+ : false;
+
// When the format starts with "%!" then evaluate it as an expression and
// use the result as the actual format string.
if (fmt[0] == '%' && fmt[1] == '!') {
@@ -1804,5 +2015,15 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, int use_san
curwin->w_redr_type = save_redr_type;
}
+ // Check for an error. If there is one the display will be messed up and
+ // might loop redrawing. Avoid that by making the corresponding option
+ // empty.
+ // TODO(Bram): find out why using called_emsg_before makes tests fail, does it
+ // matter?
+ // if (called_emsg > called_emsg_before)
+ if (opt_name && did_emsg > did_emsg_before) {
+ set_string_option_direct(opt_name, -1, "", OPT_FREE | opt_scope, SID_ERROR);
+ }
+
return width;
}
diff --git a/src/nvim/statusline.h b/src/nvim/statusline.h
index 357a9a821f..dc25dd5e67 100644
--- a/src/nvim/statusline.h
+++ b/src/nvim/statusline.h
@@ -3,6 +3,11 @@
#include "nvim/buffer_defs.h"
+/// Array defining what should be done when tabline is clicked
+EXTERN StlClickDefinition *tab_page_click_defs INIT(= NULL);
+/// Size of the tab_page_click_defs array
+EXTERN size_t tab_page_click_defs_size INIT(= 0);
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "statusline.h.generated.h"
#endif
diff --git a/src/nvim/statusline_defs.h b/src/nvim/statusline_defs.h
new file mode 100644
index 0000000000..eac9dfd690
--- /dev/null
+++ b/src/nvim/statusline_defs.h
@@ -0,0 +1,26 @@
+#ifndef NVIM_STATUSLINE_DEFS_H
+#define NVIM_STATUSLINE_DEFS_H
+
+#include <stddef.h>
+
+#include "nvim/macros.h"
+
+/// Status line click definition
+typedef struct {
+ enum {
+ kStlClickDisabled = 0, ///< Clicks to this area are ignored.
+ kStlClickTabSwitch, ///< Switch to the given tab.
+ kStlClickTabClose, ///< Close given tab.
+ kStlClickFuncRun, ///< Run user function.
+ } type; ///< Type of the click.
+ int tabnr; ///< Tab page number.
+ char *func; ///< Function to run.
+} StlClickDefinition;
+
+/// Used for tabline clicks
+typedef struct {
+ StlClickDefinition def; ///< Click definition.
+ const char *start; ///< Location where region starts.
+} StlClickRecord;
+
+#endif // NVIM_STATUSLINE_DEFS_H
diff --git a/src/nvim/strings.c b/src/nvim/strings.c
index 4d1401293b..dc48273c8e 100644
--- a/src/nvim/strings.c
+++ b/src/nvim/strings.c
@@ -604,10 +604,9 @@ static const void *tv_ptr(const typval_T *const tvs, int *const idxp)
if (tvs[idx].v_type == VAR_UNKNOWN) {
emsg(_(e_printf));
return NULL;
- } else {
- (*idxp)++;
- return tvs[idx].vval.v_string;
}
+ (*idxp)++;
+ return tvs[idx].vval.v_string;
}
/// Get float argument from idxp entry in tvs
@@ -1035,9 +1034,7 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap, t
: va_arg(ap, long long)); // NOLINT (runtime/int)
break;
case 'z':
- arg = (tvs
- ? (ptrdiff_t)tv_nr(tvs, &arg_idx)
- : va_arg(ap, ptrdiff_t));
+ arg = (tvs ? (ptrdiff_t)tv_nr(tvs, &arg_idx) : va_arg(ap, ptrdiff_t));
break;
}
if (arg > 0) {
@@ -1049,19 +1046,13 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap, t
// unsigned
switch (length_modifier) {
case '\0':
- uarg = (unsigned int)(tvs
- ? tv_nr(tvs, &arg_idx)
- : va_arg(ap, unsigned int));
+ uarg = (unsigned int)(tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, unsigned int));
break;
case 'h':
- uarg = (uint16_t)(tvs
- ? tv_nr(tvs, &arg_idx)
- : va_arg(ap, unsigned int));
+ uarg = (uint16_t)(tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, unsigned int));
break;
case 'l':
- uarg = (tvs
- ? (unsigned long)tv_nr(tvs, &arg_idx)
- : va_arg(ap, unsigned long));
+ uarg = (tvs ? (unsigned long)tv_nr(tvs, &arg_idx) : va_arg(ap, unsigned long));
break;
case '2':
uarg = (uintmax_t)(unsigned long long)( // NOLINT (runtime/int)
@@ -1071,9 +1062,7 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap, t
: va_arg(ap, unsigned long long)); // NOLINT (runtime/int)
break;
case 'z':
- uarg = (tvs
- ? (size_t)tv_nr(tvs, &arg_idx)
- : va_arg(ap, size_t));
+ uarg = (tvs ? (size_t)tv_nr(tvs, &arg_idx) : va_arg(ap, size_t));
break;
}
arg_sign = (uarg != 0);
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index fb82df4fe9..fe1bdf12b1 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -1655,13 +1655,12 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
&& (spp->sp_type == SPTYPE_MATCH
|| spp->sp_type == SPTYPE_START)
&& (current_next_list != NULL
- ? in_id_list(NULL, current_next_list,
- &spp->sp_syn, 0)
- : (cur_si == NULL
- ? !(spp->sp_flags & HL_CONTAINED)
- : in_id_list(cur_si,
- cur_si->si_cont_list, &spp->sp_syn,
- spp->sp_flags & HL_CONTAINED)))) {
+ ? in_id_list(NULL, current_next_list, &spp->sp_syn, 0)
+ : (cur_si == NULL
+ ? !(spp->sp_flags & HL_CONTAINED)
+ : in_id_list(cur_si,
+ cur_si->si_cont_list, &spp->sp_syn,
+ spp->sp_flags & HL_CONTAINED)))) {
// If we already tried matching in this line, and
// there isn't a match before next_match_col, skip
// this item.
@@ -2788,9 +2787,9 @@ static keyentry_T *match_keyword(char *keyword, hashtab_T *ht, stateitem_T *cur_
if (current_next_list != 0
? in_id_list(NULL, current_next_list, &kp->k_syn, 0)
: (cur_si == NULL
- ? !(kp->flags & HL_CONTAINED)
- : in_id_list(cur_si, cur_si->si_cont_list,
- &kp->k_syn, kp->flags & HL_CONTAINED))) {
+ ? !(kp->flags & HL_CONTAINED)
+ : in_id_list(cur_si, cur_si->si_cont_list,
+ &kp->k_syn, kp->flags & HL_CONTAINED))) {
return kp;
}
}
@@ -3123,22 +3122,20 @@ static void syn_cmd_clear(exarg_T *eap, int syncing)
if (id == 0) {
semsg(_("E391: No such syntax cluster: %s"), arg);
break;
- } else {
- // We can't physically delete a cluster without changing
- // the IDs of other clusters, so we do the next best thing
- // and make it empty.
- int scl_id = id - SYNID_CLUSTER;
-
- XFREE_CLEAR(SYN_CLSTR(curwin->w_s)[scl_id].scl_list);
}
+ // We can't physically delete a cluster without changing
+ // the IDs of other clusters, so we do the next best thing
+ // and make it empty.
+ int scl_id = id - SYNID_CLUSTER;
+
+ XFREE_CLEAR(SYN_CLSTR(curwin->w_s)[scl_id].scl_list);
} else {
id = syn_name2id_len(arg, (size_t)(arg_end - arg));
if (id == 0) {
semsg(_(e_nogroup), arg);
break;
- } else {
- syn_clear_one(id, syncing);
}
+ syn_clear_one(id, syncing);
}
arg = skipwhite(arg_end);
}
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index 16d6629c2e..b6b8f5c959 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -81,14 +81,16 @@ typedef struct {
// ht_match[] is used to find duplicates, ga_match[] to keep them in sequence.
// At the end, the matches from ga_match[] are concatenated, to make a list
// sorted on priority.
-#define MT_ST_CUR 0 // static match in current file
-#define MT_GL_CUR 1 // global match in current file
-#define MT_GL_OTH 2 // global match in other file
-#define MT_ST_OTH 3 // static match in other file
-#define MT_IC_OFF 4 // add for icase match
-#define MT_RE_OFF 8 // add for regexp match
-#define MT_MASK 7 // mask for printing priority
-#define MT_COUNT 16
+enum {
+ MT_ST_CUR = 0, // static match in current file
+ MT_GL_CUR = 1, // global match in current file
+ MT_GL_OTH = 2, // global match in other file
+ MT_ST_OTH = 3, // static match in other file
+ MT_IC_OFF = 4, // add for icase match
+ MT_RE_OFF = 8, // add for regexp match
+ MT_MASK = 7, // mask for printing priority
+ MT_COUNT = 16,
+};
static char *mt_names[MT_COUNT/2] =
{ "FSC", "F C", "F ", "FS ", " SC", " C", " ", " S " };
@@ -149,12 +151,19 @@ void free_tagfunc_option(void)
}
#endif
+/// Mark the global 'tagfunc' callback with "copyID" so that it is not garbage
+/// collected.
+bool set_ref_in_tagfunc(int copyID)
+{
+ return set_ref_in_callback(&tfu_cb, copyID, NULL, NULL);
+}
+
/// Copy the global 'tagfunc' callback function to the buffer-local 'tagfunc'
/// callback for 'buf'.
void set_buflocal_tfu_callback(buf_T *buf)
{
callback_free(&buf->b_tfu_cb);
- if (tfu_cb.data.funcref != NULL && *tfu_cb.data.funcref != NUL) {
+ if (tfu_cb.type != kCallbackNone) {
callback_copy(&buf->b_tfu_cb, &tfu_cb);
}
}
@@ -1153,7 +1162,7 @@ static int find_tagfunc_tags(char_u *pat, garray_T *ga, int *match_count, int fl
}
}
- if (*curbuf->b_p_tfu == NUL) {
+ if (*curbuf->b_p_tfu == NUL || curbuf->b_tfu_cb.type == kCallbackNone) {
return FAIL;
}
@@ -1650,9 +1659,8 @@ int find_tags(char *pat, int *num_matches, char ***matchesp, int flags, int minc
- search_info.low_offset) / 2);
if (offset == search_info.curr_offset) {
break; // End the binary search without a match.
- } else {
- search_info.curr_offset = offset;
}
+ search_info.curr_offset = offset;
} else if (state == TS_SKIP_BACK) {
// Skipping back (after a match during binary search).
search_info.curr_offset -= lbuf_size * 2;
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 5e221e13df..890b04a614 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -523,6 +523,18 @@ static int terminal_check(VimState *state)
if (must_redraw) {
update_screen();
+
+ // Make sure an invoked autocmd doesn't delete the buffer (and the
+ // terminal) under our fingers.
+ curbuf->b_locked++;
+
+ // save and restore curwin and curbuf, in case the autocmd changes them
+ aco_save_T aco;
+ aucmd_prepbuf(&aco, curbuf);
+ apply_autocmds(EVENT_TEXTCHANGEDT, NULL, NULL, false, curbuf);
+ aucmd_restbuf(&aco);
+
+ curbuf->b_locked--;
}
if (need_maketitle) { // Update title in terminal-mode. #7248
diff --git a/src/nvim/testdir/test_arglist.vim b/src/nvim/testdir/test_arglist.vim
index cae71e10f3..fb8b17cd16 100644
--- a/src/nvim/testdir/test_arglist.vim
+++ b/src/nvim/testdir/test_arglist.vim
@@ -418,15 +418,19 @@ func Test_argdedupe()
call Reset_arglist()
argdedupe
call assert_equal([], argv())
+
args a a a aa b b a b aa
argdedupe
call assert_equal(['a', 'aa', 'b'], argv())
+
args a b c
argdedupe
call assert_equal(['a', 'b', 'c'], argv())
+
args a
argdedupe
call assert_equal(['a'], argv())
+
args a A b B
argdedupe
if has('fname_case')
@@ -434,11 +438,17 @@ func Test_argdedupe()
else
call assert_equal(['a', 'b'], argv())
endif
+
args a b a c a b
last
argdedupe
next
call assert_equal('c', expand('%:t'))
+
+ args a ./a
+ argdedupe
+ call assert_equal(['a'], argv())
+
%argd
endfunc
diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim
index 1488fe8431..f4c32599f1 100644
--- a/src/nvim/testdir/test_autocmd.vim
+++ b/src/nvim/testdir/test_autocmd.vim
@@ -175,7 +175,7 @@ func Test_autocmd_bufunload_avoiding_SEGV_01()
exe 'autocmd BufUnload <buffer> ' . (lastbuf + 1) . 'bwipeout!'
augroup END
- call assert_fails('edit bb.txt', ['E937:', 'E517:'])
+ call assert_fails('edit bb.txt', 'E937:')
autocmd! test_autocmd_bufunload
augroup! test_autocmd_bufunload
@@ -481,17 +481,20 @@ endfunc
func Test_early_bar()
" test that a bar is recognized before the {event}
call s:AddAnAutocmd()
- augroup vimBarTest | au! | augroup END
+ augroup vimBarTest | au! | let done = 77 | augroup END
call assert_equal(1, len(split(execute('au vimBarTest'), "\n")))
+ call assert_equal(77, done)
call s:AddAnAutocmd()
- augroup vimBarTest| au!| augroup END
+ augroup vimBarTest| au!| let done = 88 | augroup END
call assert_equal(1, len(split(execute('au vimBarTest'), "\n")))
+ call assert_equal(88, done)
" test that a bar is recognized after the {event}
call s:AddAnAutocmd()
- augroup vimBarTest| au!BufReadCmd| augroup END
+ augroup vimBarTest| au!BufReadCmd| let done = 99 | augroup END
call assert_equal(1, len(split(execute('au vimBarTest'), "\n")))
+ call assert_equal(99, done)
" test that a bar is recognized after the {group}
call s:AddAnAutocmd()
@@ -1975,9 +1978,7 @@ func Test_change_mark_in_autocmds()
endfunc
func Test_Filter_noshelltemp()
- if !executable('cat')
- return
- endif
+ CheckExecutable cat
enew!
call setline(1, ['a', 'b', 'c', 'd'])
diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim
index b0be7ab396..2921c8b41a 100644
--- a/src/nvim/testdir/test_cmdline.vim
+++ b/src/nvim/testdir/test_cmdline.vim
@@ -1628,6 +1628,53 @@ func Test_cmd_bang_E135()
%bwipe!
endfunc
+func Test_cmd_bang_args()
+ new
+ :.!
+ call assert_equal(0, v:shell_error)
+
+ " Note that below there is one space char after the '!'. This caused a
+ " shell error in the past, see https://github.com/vim/vim/issues/11495.
+ :.!
+ call assert_equal(0, v:shell_error)
+ bwipe!
+
+ CheckUnix
+ :.!pwd
+ call assert_equal(0, v:shell_error)
+ :.! pwd
+ call assert_equal(0, v:shell_error)
+
+ " Note there is one space after 'pwd'.
+ :.! pwd
+ call assert_equal(0, v:shell_error)
+
+ " Note there are two spaces after 'pwd'.
+ :.! pwd
+ call assert_equal(0, v:shell_error)
+ :.!ls ~
+ call assert_equal(0, v:shell_error)
+
+ " Note there is one space char after '~'.
+ :.!ls ~
+ call assert_equal(0, v:shell_error)
+
+ " Note there are two spaces after '~'.
+ :.!ls ~
+ call assert_equal(0, v:shell_error)
+
+ :.!echo "foo"
+ call assert_equal(getline('.'), "foo")
+ :.!echo "foo "
+ call assert_equal(getline('.'), "foo ")
+ :.!echo " foo "
+ call assert_equal(getline('.'), " foo ")
+ :.!echo " foo "
+ call assert_equal(getline('.'), " foo ")
+
+ %bwipe!
+endfunc
+
" Test for using ~ for home directory in cmdline completion matches
func Test_cmdline_expand_home()
call mkdir('Xdir')
diff --git a/src/nvim/testdir/test_compiler.vim b/src/nvim/testdir/test_compiler.vim
index 3dc8710d63..ec7d143030 100644
--- a/src/nvim/testdir/test_compiler.vim
+++ b/src/nvim/testdir/test_compiler.vim
@@ -1,9 +1,11 @@
" Test the :compiler command
+source check.vim
+source shared.vim
+
func Test_compiler()
- if !executable('perl')
- return
- endif
+ CheckExecutable perl
+ CheckFeature quickfix
" $LANG changes the output of Perl.
if $LANG != ''
diff --git a/src/nvim/testdir/test_cursor_func.vim b/src/nvim/testdir/test_cursor_func.vim
index 9801a45915..7f9e74e94b 100644
--- a/src/nvim/testdir/test_cursor_func.vim
+++ b/src/nvim/testdir/test_cursor_func.vim
@@ -241,8 +241,9 @@ endfunc
" Test for the charcol() function
func Test_charcol()
- call assert_fails('call charcol({})', 'E731:')
- call assert_equal(0, charcol(0))
+ call assert_fails('call charcol({})', 'E1222:')
+ call assert_fails('call charcol(".", [])', 'E1210:')
+ call assert_fails('call charcol(0)', 'E1222:')
new
call setline(1, ['', "01\tà4è678", 'Ⅵ', '012345678'])
@@ -298,6 +299,25 @@ func Test_charcol()
call assert_equal([1, 10, 2, 10, 7], g:InsertCurrentCol)
iunmap <F3>
+ " Test for getting the column number in another window.
+ let winid = win_getid()
+ new
+ call win_execute(winid, 'normal 1G')
+ call assert_equal(1, charcol('.', winid))
+ call assert_equal(1, charcol('$', winid))
+ call win_execute(winid, 'normal 2G6l')
+ call assert_equal(7, charcol('.', winid))
+ call assert_equal(10, charcol('$', winid))
+
+ " calling from another tab page also works
+ tabnew
+ call assert_equal(7, charcol('.', winid))
+ call assert_equal(10, charcol('$', winid))
+ tabclose
+
+ " unknown window ID
+ call assert_equal(0, charcol('.', 10001))
+
%bw!
endfunc
diff --git a/src/nvim/testdir/test_delete.vim b/src/nvim/testdir/test_delete.vim
index b23a3bd025..6b49f153c6 100644
--- a/src/nvim/testdir/test_delete.vim
+++ b/src/nvim/testdir/test_delete.vim
@@ -1,5 +1,7 @@
" Test for delete().
+source check.vim
+
func Test_file_delete()
split Xfile
call setline(1, ['a', 'b'])
@@ -41,9 +43,7 @@ func Test_recursive_delete()
endfunc
func Test_symlink_delete()
- if !has('unix')
- return
- endif
+ CheckUnix
split Xfile
call setline(1, ['a', 'b'])
wq
@@ -56,9 +56,7 @@ func Test_symlink_delete()
endfunc
func Test_symlink_dir_delete()
- if !has('unix')
- return
- endif
+ CheckUnix
call mkdir('Xdir1')
silent !ln -s Xdir1 Xlink
call assert_true(isdirectory('Xdir1'))
@@ -70,9 +68,7 @@ func Test_symlink_dir_delete()
endfunc
func Test_symlink_recursive_delete()
- if !has('unix')
- return
- endif
+ CheckUnix
call mkdir('Xdir3')
call mkdir('Xdir3/subdir')
call mkdir('Xdir4')
diff --git a/src/nvim/testdir/test_diffmode.vim b/src/nvim/testdir/test_diffmode.vim
index 831efdbfc2..0de5310735 100644
--- a/src/nvim/testdir/test_diffmode.vim
+++ b/src/nvim/testdir/test_diffmode.vim
@@ -621,9 +621,7 @@ func Test_diff_move_to()
endfunc
func Test_diffexpr()
- if !executable('diff')
- return
- endif
+ CheckExecutable diff
func DiffExpr()
" Prepend some text to check diff type detection
diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim
index c6f90604e5..69508cb19e 100644
--- a/src/nvim/testdir/test_filetype.vim
+++ b/src/nvim/testdir/test_filetype.vim
@@ -612,6 +612,7 @@ let s:filename_checks = {
\ 'verilogams': ['file.va', 'file.vams'],
\ 'vgrindefs': ['vgrindefs'],
\ 'vhdl': ['file.hdl', 'file.vhd', 'file.vhdl', 'file.vbe', 'file.vst', 'file.vhdl_123', 'file.vho', 'some.vhdl_1', 'some.vhdl_1-file'],
+ \ 'vhs': ['file.tape'],
\ 'vim': ['file.vim', 'file.vba', '.exrc', '_exrc', 'some-vimrc', 'some-vimrc-file', 'vimrc', 'vimrc-file'],
\ 'viminfo': ['.viminfo', '_viminfo'],
\ 'vmasm': ['file.mar'],
diff --git a/src/nvim/testdir/test_fold.vim b/src/nvim/testdir/test_fold.vim
index 0a9be310ff..1b979dbc03 100644
--- a/src/nvim/testdir/test_fold.vim
+++ b/src/nvim/testdir/test_fold.vim
@@ -72,6 +72,54 @@ func Test_address_fold()
quit!
endfunc
+func Test_address_offsets()
+ " check the help for :range-closed-fold
+ enew
+ call setline(1, [
+ \ '1 one',
+ \ '2 two',
+ \ '3 three',
+ \ '4 four FOLDED',
+ \ '5 five FOLDED',
+ \ '6 six',
+ \ '7 seven',
+ \ '8 eight',
+ \])
+ set foldmethod=manual
+ normal 4Gvjzf
+ 3,4+2yank
+ call assert_equal([
+ \ '3 three',
+ \ '4 four FOLDED',
+ \ '5 five FOLDED',
+ \ '6 six',
+ \ '7 seven',
+ \ ], getreg(0,1,1))
+
+ enew!
+ call setline(1, [
+ \ '1 one',
+ \ '2 two',
+ \ '3 three FOLDED',
+ \ '4 four FOLDED',
+ \ '5 five FOLDED',
+ \ '6 six FOLDED',
+ \ '7 seven',
+ \ '8 eight',
+ \])
+ normal 3Gv3jzf
+ 2,4-1yank
+ call assert_equal([
+ \ '2 two',
+ \ '3 three FOLDED',
+ \ '4 four FOLDED',
+ \ '5 five FOLDED',
+ \ '6 six FOLDED',
+ \ ], getreg(0,1,1))
+
+ bwipe!
+endfunc
+
func Test_indent_fold()
new
call setline(1, ['', 'a', ' b', ' c'])
@@ -95,9 +143,7 @@ func Test_indent_fold2()
endfunc
func Test_manual_fold_with_filter()
- if !executable('cat')
- return
- endif
+ CheckExecutable cat
for type in ['manual', 'marker']
exe 'set foldmethod=' . type
new
@@ -988,4 +1034,40 @@ func Test_indent_append_blank_small_fold_close()
bw!
endfunc
+func Test_sort_closed_fold()
+ CheckExecutable sort
+
+ call setline(1, [
+ \ 'Section 1',
+ \ ' how',
+ \ ' now',
+ \ ' brown',
+ \ ' cow',
+ \ 'Section 2',
+ \ ' how',
+ \ ' now',
+ \ ' brown',
+ \ ' cow',
+ \])
+ setlocal foldmethod=indent sw=3
+ normal 2G
+
+ " The "!!" expands to ".,.+3" and must only sort four lines
+ call feedkeys("!!sort\<CR>", 'xt')
+ call assert_equal([
+ \ 'Section 1',
+ \ ' brown',
+ \ ' cow',
+ \ ' how',
+ \ ' now',
+ \ 'Section 2',
+ \ ' how',
+ \ ' now',
+ \ ' brown',
+ \ ' cow',
+ \ ], getline(1, 10))
+
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim
index 0f2066b7c1..5ff544ab55 100644
--- a/src/nvim/testdir/test_functions.vim
+++ b/src/nvim/testdir/test_functions.vim
@@ -813,6 +813,8 @@ func Test_append()
" Using $ instead of '$' must give an error
call assert_fails("call append($, 'foobar')", 'E116:')
+
+ call assert_fails("call append({}, '')", ['E728:', 'E728:'])
endfunc
" Test for setline()
@@ -1286,6 +1288,9 @@ func Test_col()
call assert_equal(0, col([2, '$']))
call assert_equal(0, col([1, 100]))
call assert_equal(0, col([1]))
+ call assert_equal(0, col(v:_null_list))
+ call assert_fails('let c = col({})', 'E1222:')
+ call assert_fails('let c = col(".", [])', 'E1210:')
" test for getting the visual start column
func T()
@@ -1315,6 +1320,15 @@ func Test_col()
call assert_equal(4, col('.'))
set virtualedit&
+ " Test for getting the column number in another window
+ let winid = win_getid()
+ new
+ call win_execute(winid, 'normal 1G$')
+ call assert_equal(3, col('.', winid))
+ call win_execute(winid, 'normal 2G')
+ call assert_equal(8, col('$', winid))
+ call assert_equal(0, col('.', 5001))
+
bw!
endfunc
diff --git a/src/nvim/testdir/test_help_tagjump.vim b/src/nvim/testdir/test_help_tagjump.vim
index e84726bbfc..f81e4fb1ef 100644
--- a/src/nvim/testdir/test_help_tagjump.vim
+++ b/src/nvim/testdir/test_help_tagjump.vim
@@ -38,18 +38,18 @@ func Test_help_tagjump()
call assert_true(getline('.') =~ '\*quotestar\*')
helpclose
- " The test result is different in vim. There ":help ??" will jump to the
- " falsy operator ??, which hasn't been ported to neovim yet. Instead, neovim
- " jumps to the tag "g??". This test result needs to be changed if neovim
- " ports the falsy operator.
- help ??
+ " help sm?le
+ help ch?ckhealth
call assert_equal("help", &filetype)
- call assert_true(getline('.') =~ '\*g??\*')
+ " call assert_true(getline('.') =~ '\*:smile\*')
+ call assert_true(getline('.') =~ '\*:checkhealth\*')
helpclose
- help ch?ckhealth
+ help ??
call assert_equal("help", &filetype)
- call assert_true(getline('.') =~ '\*:checkhealth\*')
+ " *??* tag needs patch 8.2.1794
+ " call assert_true(getline('.') =~ '\*??\*')
+ call assert_true(getline('.') =~ '\*g??\*')
helpclose
help :?
diff --git a/src/nvim/testdir/test_ins_complete.vim b/src/nvim/testdir/test_ins_complete.vim
index fc612dcbe2..d788841833 100644
--- a/src/nvim/testdir/test_ins_complete.vim
+++ b/src/nvim/testdir/test_ins_complete.vim
@@ -1,5 +1,8 @@
+" Test for insert completion
+
source screendump.vim
source check.vim
+source vim9.vim
" Test for insert expansion
func Test_ins_complete()
@@ -1287,500 +1290,670 @@ endfunc
" Test for different ways of setting the 'completefunc' option
func Test_completefunc_callback()
- " Test for using a function()
- func MycompleteFunc1(findstart, base)
- call add(g:MycompleteFunc1_args, [a:findstart, a:base])
+ func CompleteFunc1(callnr, findstart, base)
+ call add(g:CompleteFunc1Args, [a:callnr, a:findstart, a:base])
return a:findstart ? 0 : []
endfunc
- set completefunc=function('MycompleteFunc1')
- new | only
- call setline(1, 'one')
- let g:MycompleteFunc1_args = []
- call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
- call assert_equal([[1, ''], [0, 'one']], g:MycompleteFunc1_args)
- bw!
-
- " Using a funcref variable to set 'completefunc'
- let Fn = function('MycompleteFunc1')
- let &completefunc = string(Fn)
- new | only
- call setline(1, 'two')
- let g:MycompleteFunc1_args = []
- call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
- call assert_equal([[1, ''], [0, 'two']], g:MycompleteFunc1_args)
- call assert_fails('let &completefunc = Fn', 'E729:')
- bw!
-
- " Test for using a funcref()
- func MycompleteFunc2(findstart, base)
- call add(g:MycompleteFunc2_args, [a:findstart, a:base])
+ func CompleteFunc2(findstart, base)
+ call add(g:CompleteFunc2Args, [a:findstart, a:base])
return a:findstart ? 0 : []
endfunc
- set completefunc=funcref('MycompleteFunc2')
- new | only
- call setline(1, 'three')
- let g:MycompleteFunc2_args = []
- call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
- call assert_equal([[1, ''], [0, 'three']], g:MycompleteFunc2_args)
- bw!
- " Using a funcref variable to set 'completefunc'
- let Fn = funcref('MycompleteFunc2')
- let &completefunc = string(Fn)
- new | only
- call setline(1, 'four')
- let g:MycompleteFunc2_args = []
- call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
- call assert_equal([[1, ''], [0, 'four']], g:MycompleteFunc2_args)
- call assert_fails('let &completefunc = Fn', 'E729:')
- bw!
+ let lines =<< trim END
+ #" Test for using a function name
+ LET &completefunc = 'g:CompleteFunc2'
+ new
+ call setline(1, 'zero')
+ LET g:CompleteFunc2Args = []
+ call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
+ call assert_equal([[1, ''], [0, 'zero']], g:CompleteFunc2Args)
+ bw!
- " Test for using a lambda function
- func MycompleteFunc3(findstart, base)
- call add(g:MycompleteFunc3_args, [a:findstart, a:base])
- return a:findstart ? 0 : []
- endfunc
- set completefunc={a,\ b,\ ->\ MycompleteFunc3(a,\ b,)}
- new | only
- call setline(1, 'five')
- let g:MycompleteFunc3_args = []
- call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
- call assert_equal([[1, ''], [0, 'five']], g:MycompleteFunc3_args)
- bw!
+ #" Test for using a function()
+ set completefunc=function('g:CompleteFunc1',\ [10])
+ new
+ call setline(1, 'one')
+ LET g:CompleteFunc1Args = []
+ call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
+ call assert_equal([[10, 1, ''], [10, 0, 'one']], g:CompleteFunc1Args)
+ bw!
- " Set 'completefunc' to a lambda expression
- let &completefunc = '{a, b -> MycompleteFunc3(a, b)}'
- new | only
- call setline(1, 'six')
- let g:MycompleteFunc3_args = []
- call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
- call assert_equal([[1, ''], [0, 'six']], g:MycompleteFunc3_args)
- bw!
+ #" Using a funcref variable to set 'completefunc'
+ VAR Fn = function('g:CompleteFunc1', [11])
+ LET &completefunc = Fn
+ new
+ call setline(1, 'two')
+ LET g:CompleteFunc1Args = []
+ call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
+ call assert_equal([[11, 1, ''], [11, 0, 'two']], g:CompleteFunc1Args)
+ bw!
- " Set 'completefunc' to a variable with a lambda expression
- let Lambda = {a, b -> MycompleteFunc3(a, b)}
- let &completefunc = string(Lambda)
- new | only
- call setline(1, 'seven')
- let g:MycompleteFunc3_args = []
- call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
- call assert_equal([[1, ''], [0, 'seven']], g:MycompleteFunc3_args)
- call assert_fails('let &completefunc = Lambda', 'E729:')
- bw!
+ #" Using string(funcref_variable) to set 'completefunc'
+ LET Fn = function('g:CompleteFunc1', [12])
+ LET &completefunc = string(Fn)
+ new
+ call setline(1, 'two')
+ LET g:CompleteFunc1Args = []
+ call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
+ call assert_equal([[12, 1, ''], [12, 0, 'two']], g:CompleteFunc1Args)
+ bw!
- " Test for using a lambda function with incorrect return value
- let Lambda = {s -> strlen(s)}
- let &completefunc = string(Lambda)
- new | only
- call setline(1, 'eight')
- call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
- bw!
+ #" Test for using a funcref()
+ set completefunc=funcref('g:CompleteFunc1',\ [13])
+ new
+ call setline(1, 'three')
+ LET g:CompleteFunc1Args = []
+ call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
+ call assert_equal([[13, 1, ''], [13, 0, 'three']], g:CompleteFunc1Args)
+ bw!
- " Test for clearing the 'completefunc' option
- set completefunc=''
- set completefunc&
+ #" Using a funcref variable to set 'completefunc'
+ LET Fn = funcref('g:CompleteFunc1', [14])
+ LET &completefunc = Fn
+ new
+ call setline(1, 'four')
+ LET g:CompleteFunc1Args = []
+ call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
+ call assert_equal([[14, 1, ''], [14, 0, 'four']], g:CompleteFunc1Args)
+ bw!
+
+ #" Using a string(funcref_variable) to set 'completefunc'
+ LET Fn = funcref('g:CompleteFunc1', [15])
+ LET &completefunc = string(Fn)
+ new
+ call setline(1, 'four')
+ LET g:CompleteFunc1Args = []
+ call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
+ call assert_equal([[15, 1, ''], [15, 0, 'four']], g:CompleteFunc1Args)
+ bw!
+
+ #" Test for using a lambda function with set
+ VAR optval = "LSTART a, b LMIDDLE CompleteFunc1(16, a, b) LEND"
+ LET optval = substitute(optval, ' ', '\\ ', 'g')
+ exe "set completefunc=" .. optval
+ new
+ call setline(1, 'five')
+ LET g:CompleteFunc1Args = []
+ call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
+ call assert_equal([[16, 1, ''], [16, 0, 'five']], g:CompleteFunc1Args)
+ bw!
+
+ #" Set 'completefunc' to a lambda expression
+ LET &completefunc = LSTART a, b LMIDDLE CompleteFunc1(17, a, b) LEND
+ new
+ call setline(1, 'six')
+ LET g:CompleteFunc1Args = []
+ call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
+ call assert_equal([[17, 1, ''], [17, 0, 'six']], g:CompleteFunc1Args)
+ bw!
+
+ #" Set 'completefunc' to string(lambda_expression)
+ LET &completefunc = 'LSTART a, b LMIDDLE CompleteFunc1(18, a, b) LEND'
+ new
+ call setline(1, 'six')
+ LET g:CompleteFunc1Args = []
+ call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
+ call assert_equal([[18, 1, ''], [18, 0, 'six']], g:CompleteFunc1Args)
+ bw!
+
+ #" Set 'completefunc' to a variable with a lambda expression
+ VAR Lambda = LSTART a, b LMIDDLE CompleteFunc1(19, a, b) LEND
+ LET &completefunc = Lambda
+ new
+ call setline(1, 'seven')
+ LET g:CompleteFunc1Args = []
+ call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
+ call assert_equal([[19, 1, ''], [19, 0, 'seven']], g:CompleteFunc1Args)
+ bw!
+
+ #" Set 'completefunc' to a string(variable with a lambda expression)
+ LET Lambda = LSTART a, b LMIDDLE CompleteFunc1(20, a, b) LEND
+ LET &completefunc = string(Lambda)
+ new
+ call setline(1, 'seven')
+ LET g:CompleteFunc1Args = []
+ call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
+ call assert_equal([[20, 1, ''], [20, 0, 'seven']], g:CompleteFunc1Args)
+ bw!
+
+ #" Test for using a lambda function with incorrect return value
+ LET Lambda = LSTART a, b LMIDDLE strlen(a) LEND
+ LET &completefunc = Lambda
+ new
+ call setline(1, 'eight')
+ call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
+ bw!
+
+ #" Test for clearing the 'completefunc' option
+ set completefunc=''
+ set completefunc&
+ call assert_fails("set completefunc=function('abc')", "E700:")
+ call assert_fails("set completefunc=funcref('abc')", "E700:")
+
+ #" set 'completefunc' to a non-existing function
+ set completefunc=CompleteFunc2
+ call setline(1, 'five')
+ call assert_fails("set completefunc=function('NonExistingFunc')", 'E700:')
+ call assert_fails("LET &completefunc = function('NonExistingFunc')", 'E700:')
+ LET g:CompleteFunc2Args = []
+ call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
+ call assert_equal([[1, ''], [0, 'five']], g:CompleteFunc2Args)
+ bw!
+ END
+ call CheckLegacyAndVim9Success(lines)
- call assert_fails("set completefunc=function('abc')", "E700:")
- call assert_fails("set completefunc=funcref('abc')", "E700:")
- let &completefunc = "{a -> 'abc'}"
+ let &completefunc = {a -> 'abc'}
call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
+ " Using Vim9 lambda expression in legacy context should fail
+ " set completefunc=(a,\ b)\ =>\ CompleteFunc1(21,\ a,\ b)
+ new | only
+ let g:CompleteFunc1Args = []
+ " call assert_fails('call feedkeys("A\<C-X>\<C-U>\<Esc>", "x")', 'E117:')
+ call assert_equal([], g:CompleteFunc1Args)
+
+ " set 'completefunc' to a partial with dict. This used to cause a crash.
+ func SetCompleteFunc()
+ let params = {'complete': function('g:DictCompleteFunc')}
+ let &completefunc = params.complete
+ endfunc
+ func g:DictCompleteFunc(_) dict
+ endfunc
+ call SetCompleteFunc()
+ new
+ call SetCompleteFunc()
+ bw
+ call test_garbagecollect_now()
+ new
+ set completefunc=
+ wincmd w
+ set completefunc=
+ %bw!
+ delfunc g:DictCompleteFunc
+ delfunc SetCompleteFunc
+
" Vim9 tests
let lines =<< trim END
vim9script
- # Test for using function()
- def MycompleteFunc1(findstart: number, base: string): any
- add(g:MycompleteFunc1_args, [findstart, base])
+ # Test for using a def function with completefunc
+ def Vim9CompleteFunc(val: number, findstart: number, base: string): any
+ add(g:Vim9completeFuncArgs, [val, findstart, base])
return findstart ? 0 : []
enddef
- set completefunc=function('MycompleteFunc1')
+ set completefunc=function('Vim9CompleteFunc',\ [60])
new | only
setline(1, 'one')
- g:MycompleteFunc1_args = []
- feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
- assert_equal([[1, ''], [0, 'one']], g:MycompleteFunc1_args)
- bw!
-
- # Test for using a lambda
- def MycompleteFunc2(findstart: number, base: string): any
- add(g:MycompleteFunc2_args, [findstart, base])
- return findstart ? 0 : []
- enddef
- &completefunc = '(a, b) => MycompleteFunc2(a, b)'
- new | only
- setline(1, 'two')
- g:MycompleteFunc2_args = []
- feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
- assert_equal([[1, ''], [0, 'two']], g:MycompleteFunc2_args)
- bw!
-
- # Test for using a variable with a lambda expression
- var Fn: func = (a, b) => MycompleteFunc2(a, b)
- &completefunc = string(Fn)
- new | only
- setline(1, 'three')
- g:MycompleteFunc2_args = []
+ g:Vim9completeFuncArgs = []
feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
- assert_equal([[1, ''], [0, 'three']], g:MycompleteFunc2_args)
+ assert_equal([[60, 1, ''], [60, 0, 'one']], g:Vim9completeFuncArgs)
bw!
END
" call CheckScriptSuccess(lines)
- " Using Vim9 lambda expression in legacy context should fail
- " set completefunc=(a,\ b)\ =>\ g:MycompleteFunc2(a,\ b)
- " new | only
- " let g:MycompleteFunc2_args = []
- " call assert_fails('call feedkeys("A\<C-X>\<C-U>\<Esc>", "x")', 'E117:')
- " call assert_equal([], g:MycompleteFunc2_args)
-
" cleanup
- delfunc MycompleteFunc1
- delfunc MycompleteFunc2
- delfunc MycompleteFunc3
set completefunc&
+ delfunc CompleteFunc1
+ delfunc CompleteFunc2
+ unlet g:CompleteFunc1Args g:CompleteFunc2Args
%bw!
endfunc
" Test for different ways of setting the 'omnifunc' option
func Test_omnifunc_callback()
- " Test for using a function()
- func MyomniFunc1(findstart, base)
- call add(g:MyomniFunc1_args, [a:findstart, a:base])
+ func OmniFunc1(callnr, findstart, base)
+ call add(g:OmniFunc1Args, [a:callnr, a:findstart, a:base])
return a:findstart ? 0 : []
endfunc
- set omnifunc=function('MyomniFunc1')
- new | only
- call setline(1, 'one')
- let g:MyomniFunc1_args = []
- call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
- call assert_equal([[1, ''], [0, 'one']], g:MyomniFunc1_args)
- bw!
-
- " Using a funcref variable to set 'omnifunc'
- let Fn = function('MyomniFunc1')
- let &omnifunc = string(Fn)
- new | only
- call setline(1, 'two')
- let g:MyomniFunc1_args = []
- call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
- call assert_equal([[1, ''], [0, 'two']], g:MyomniFunc1_args)
- call assert_fails('let &omnifunc = Fn', 'E729:')
- bw!
-
- " Test for using a funcref()
- func MyomniFunc2(findstart, base)
- call add(g:MyomniFunc2_args, [a:findstart, a:base])
+ func OmniFunc2(findstart, base)
+ call add(g:OmniFunc2Args, [a:findstart, a:base])
return a:findstart ? 0 : []
endfunc
- set omnifunc=funcref('MyomniFunc2')
- new | only
- call setline(1, 'three')
- let g:MyomniFunc2_args = []
- call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
- call assert_equal([[1, ''], [0, 'three']], g:MyomniFunc2_args)
- bw!
- " Using a funcref variable to set 'omnifunc'
- let Fn = funcref('MyomniFunc2')
- let &omnifunc = string(Fn)
- new | only
- call setline(1, 'four')
- let g:MyomniFunc2_args = []
- call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
- call assert_equal([[1, ''], [0, 'four']], g:MyomniFunc2_args)
- call assert_fails('let &omnifunc = Fn', 'E729:')
- bw!
+ let lines =<< trim END
+ #" Test for using a function name
+ LET &omnifunc = 'g:OmniFunc2'
+ new
+ call setline(1, 'zero')
+ LET g:OmniFunc2Args = []
+ call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
+ call assert_equal([[1, ''], [0, 'zero']], g:OmniFunc2Args)
+ bw!
- " Test for using a lambda function
- func MyomniFunc3(findstart, base)
- call add(g:MyomniFunc3_args, [a:findstart, a:base])
- return a:findstart ? 0 : []
- endfunc
- set omnifunc={a,\ b,\ ->\ MyomniFunc3(a,\ b,)}
- new | only
- call setline(1, 'five')
- let g:MyomniFunc3_args = []
- call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
- call assert_equal([[1, ''], [0, 'five']], g:MyomniFunc3_args)
- bw!
+ #" Test for using a function()
+ set omnifunc=function('g:OmniFunc1',\ [10])
+ new
+ call setline(1, 'one')
+ LET g:OmniFunc1Args = []
+ call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
+ call assert_equal([[10, 1, ''], [10, 0, 'one']], g:OmniFunc1Args)
+ bw!
- " Set 'omnifunc' to a lambda expression
- let &omnifunc = '{a, b -> MyomniFunc3(a, b)}'
- new | only
- call setline(1, 'six')
- let g:MyomniFunc3_args = []
- call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
- call assert_equal([[1, ''], [0, 'six']], g:MyomniFunc3_args)
- bw!
+ #" Using a funcref variable to set 'omnifunc'
+ VAR Fn = function('g:OmniFunc1', [11])
+ LET &omnifunc = Fn
+ new
+ call setline(1, 'two')
+ LET g:OmniFunc1Args = []
+ call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
+ call assert_equal([[11, 1, ''], [11, 0, 'two']], g:OmniFunc1Args)
+ bw!
- " Set 'omnifunc' to a variable with a lambda expression
- let Lambda = {a, b -> MyomniFunc3(a, b)}
- let &omnifunc = string(Lambda)
- new | only
- call setline(1, 'seven')
- let g:MyomniFunc3_args = []
- call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
- call assert_equal([[1, ''], [0, 'seven']], g:MyomniFunc3_args)
- call assert_fails('let &omnifunc = Lambda', 'E729:')
- bw!
+ #" Using a string(funcref_variable) to set 'omnifunc'
+ LET Fn = function('g:OmniFunc1', [12])
+ LET &omnifunc = string(Fn)
+ new
+ call setline(1, 'two')
+ LET g:OmniFunc1Args = []
+ call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
+ call assert_equal([[12, 1, ''], [12, 0, 'two']], g:OmniFunc1Args)
+ bw!
- " Test for using a lambda function with incorrect return value
- let Lambda = {s -> strlen(s)}
- let &omnifunc = string(Lambda)
- new | only
- call setline(1, 'eight')
- call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
- bw!
+ #" Test for using a funcref()
+ set omnifunc=funcref('g:OmniFunc1',\ [13])
+ new
+ call setline(1, 'three')
+ LET g:OmniFunc1Args = []
+ call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
+ call assert_equal([[13, 1, ''], [13, 0, 'three']], g:OmniFunc1Args)
+ bw!
- " Test for clearing the 'omnifunc' option
- set omnifunc=''
- set omnifunc&
+ #" Use let to set 'omnifunc' to a funcref
+ LET Fn = funcref('g:OmniFunc1', [14])
+ LET &omnifunc = Fn
+ new
+ call setline(1, 'four')
+ LET g:OmniFunc1Args = []
+ call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
+ call assert_equal([[14, 1, ''], [14, 0, 'four']], g:OmniFunc1Args)
+ bw!
+
+ #" Using a string(funcref) to set 'omnifunc'
+ LET Fn = funcref("g:OmniFunc1", [15])
+ LET &omnifunc = string(Fn)
+ new
+ call setline(1, 'four')
+ LET g:OmniFunc1Args = []
+ call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
+ call assert_equal([[15, 1, ''], [15, 0, 'four']], g:OmniFunc1Args)
+ bw!
+
+ #" Test for using a lambda function with set
+ VAR optval = "LSTART a, b LMIDDLE OmniFunc1(16, a, b) LEND"
+ LET optval = substitute(optval, ' ', '\\ ', 'g')
+ exe "set omnifunc=" .. optval
+ new
+ call setline(1, 'five')
+ LET g:OmniFunc1Args = []
+ call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
+ call assert_equal([[16, 1, ''], [16, 0, 'five']], g:OmniFunc1Args)
+ bw!
- call assert_fails("set omnifunc=function('abc')", "E700:")
- call assert_fails("set omnifunc=funcref('abc')", "E700:")
- let &omnifunc = "{a -> 'abc'}"
+ #" Set 'omnifunc' to a lambda expression
+ LET &omnifunc = LSTART a, b LMIDDLE OmniFunc1(17, a, b) LEND
+ new
+ call setline(1, 'six')
+ LET g:OmniFunc1Args = []
+ call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
+ call assert_equal([[17, 1, ''], [17, 0, 'six']], g:OmniFunc1Args)
+ bw!
+
+ #" Set 'omnifunc' to a string(lambda_expression)
+ LET &omnifunc = 'LSTART a, b LMIDDLE OmniFunc1(18, a, b) LEND'
+ new
+ call setline(1, 'six')
+ LET g:OmniFunc1Args = []
+ call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
+ call assert_equal([[18, 1, ''], [18, 0, 'six']], g:OmniFunc1Args)
+ bw!
+
+ #" Set 'omnifunc' to a variable with a lambda expression
+ VAR Lambda = LSTART a, b LMIDDLE OmniFunc1(19, a, b) LEND
+ LET &omnifunc = Lambda
+ new
+ call setline(1, 'seven')
+ LET g:OmniFunc1Args = []
+ call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
+ call assert_equal([[19, 1, ''], [19, 0, 'seven']], g:OmniFunc1Args)
+ bw!
+
+ #" Set 'omnifunc' to a string(variable with a lambda expression)
+ LET Lambda = LSTART a, b LMIDDLE OmniFunc1(20, a, b) LEND
+ LET &omnifunc = string(Lambda)
+ new
+ call setline(1, 'seven')
+ LET g:OmniFunc1Args = []
+ call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
+ call assert_equal([[20, 1, ''], [20, 0, 'seven']], g:OmniFunc1Args)
+ bw!
+
+ #" Test for using a lambda function with incorrect return value
+ LET Lambda = LSTART a, b LMIDDLE strlen(a) LEND
+ LET &omnifunc = Lambda
+ new
+ call setline(1, 'eight')
+ call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
+ bw!
+
+ #" Test for clearing the 'omnifunc' option
+ set omnifunc=''
+ set omnifunc&
+ call assert_fails("set omnifunc=function('abc')", "E700:")
+ call assert_fails("set omnifunc=funcref('abc')", "E700:")
+
+ #" set 'omnifunc' to a non-existing function
+ set omnifunc=OmniFunc2
+ call setline(1, 'nine')
+ call assert_fails("set omnifunc=function('NonExistingFunc')", 'E700:')
+ call assert_fails("LET &omnifunc = function('NonExistingFunc')", 'E700:')
+ LET g:OmniFunc2Args = []
+ call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
+ call assert_equal([[1, ''], [0, 'nine']], g:OmniFunc2Args)
+ bw!
+ END
+ call CheckLegacyAndVim9Success(lines)
+
+ let &omnifunc = {a -> 'abc'}
call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
+ " Using Vim9 lambda expression in legacy context should fail
+ " set omnifunc=(a,\ b)\ =>\ OmniFunc1(21,\ a,\ b)
+ new | only
+ let g:OmniFunc1Args = []
+ " call assert_fails('call feedkeys("A\<C-X>\<C-O>\<Esc>", "x")', 'E117:')
+ call assert_equal([], g:OmniFunc1Args)
+
+ " set 'omnifunc' to a partial with dict. This used to cause a crash.
+ func SetOmniFunc()
+ let params = {'omni': function('g:DictOmniFunc')}
+ let &omnifunc = params.omni
+ endfunc
+ func g:DictOmniFunc(_) dict
+ endfunc
+ call SetOmniFunc()
+ new
+ call SetOmniFunc()
+ bw
+ call test_garbagecollect_now()
+ new
+ set omnifunc=
+ wincmd w
+ set omnifunc=
+ %bw!
+ delfunc g:DictOmniFunc
+ delfunc SetOmniFunc
+
" Vim9 tests
let lines =<< trim END
vim9script
- # Test for using function()
- def MyomniFunc1(findstart: number, base: string): any
- add(g:MyomniFunc1_args, [findstart, base])
+ # Test for using a def function with omnifunc
+ def Vim9omniFunc(val: number, findstart: number, base: string): any
+ add(g:Vim9omniFunc_Args, [val, findstart, base])
return findstart ? 0 : []
enddef
- set omnifunc=function('MyomniFunc1')
+ set omnifunc=function('Vim9omniFunc',\ [60])
new | only
setline(1, 'one')
- g:MyomniFunc1_args = []
+ g:Vim9omniFunc_Args = []
feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
- assert_equal([[1, ''], [0, 'one']], g:MyomniFunc1_args)
- bw!
-
- # Test for using a lambda
- def MyomniFunc2(findstart: number, base: string): any
- add(g:MyomniFunc2_args, [findstart, base])
- return findstart ? 0 : []
- enddef
- &omnifunc = '(a, b) => MyomniFunc2(a, b)'
- new | only
- setline(1, 'two')
- g:MyomniFunc2_args = []
- feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
- assert_equal([[1, ''], [0, 'two']], g:MyomniFunc2_args)
- bw!
-
- # Test for using a variable with a lambda expression
- var Fn: func = (a, b) => MyomniFunc2(a, b)
- &omnifunc = string(Fn)
- new | only
- setline(1, 'three')
- g:MyomniFunc2_args = []
- feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
- assert_equal([[1, ''], [0, 'three']], g:MyomniFunc2_args)
+ assert_equal([[60, 1, ''], [60, 0, 'one']], g:Vim9omniFunc_Args)
bw!
END
" call CheckScriptSuccess(lines)
- " Using Vim9 lambda expression in legacy context should fail
- " set omnifunc=(a,\ b)\ =>\ g:MyomniFunc2(a,\ b)
- " new | only
- " let g:MyomniFunc2_args = []
- " call assert_fails('call feedkeys("A\<C-X>\<C-O>\<Esc>", "x")', 'E117:')
- " call assert_equal([], g:MyomniFunc2_args)
-
" cleanup
- delfunc MyomniFunc1
- delfunc MyomniFunc2
- delfunc MyomniFunc3
set omnifunc&
+ delfunc OmniFunc1
+ delfunc OmniFunc2
+ unlet g:OmniFunc1Args g:OmniFunc2Args
%bw!
endfunc
" Test for different ways of setting the 'thesaurusfunc' option
func Test_thesaurusfunc_callback()
- " Test for using a function()
- func MytsrFunc1(findstart, base)
- call add(g:MytsrFunc1_args, [a:findstart, a:base])
+ func TsrFunc1(callnr, findstart, base)
+ call add(g:TsrFunc1Args, [a:callnr, a:findstart, a:base])
return a:findstart ? 0 : []
endfunc
- set thesaurusfunc=function('MytsrFunc1')
- new | only
- call setline(1, 'one')
- let g:MytsrFunc1_args = []
- call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
- call assert_equal([[1, ''], [0, 'one']], g:MytsrFunc1_args)
- bw!
+ func TsrFunc2(findstart, base)
+ call add(g:TsrFunc2Args, [a:findstart, a:base])
+ return a:findstart ? 0 : ['sunday']
+ endfunc
- " Using a funcref variable to set 'thesaurusfunc'
- let Fn = function('MytsrFunc1')
- let &thesaurusfunc = string(Fn)
- new | only
- call setline(1, 'two')
- let g:MytsrFunc1_args = []
- call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
- call assert_equal([[1, ''], [0, 'two']], g:MytsrFunc1_args)
- call assert_fails('let &thesaurusfunc = Fn', 'E729:')
- bw!
+ let lines =<< trim END
+ #" Test for using a function name
+ LET &thesaurusfunc = 'g:TsrFunc2'
+ new
+ call setline(1, 'zero')
+ LET g:TsrFunc2Args = []
+ call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
+ call assert_equal([[1, ''], [0, 'zero']], g:TsrFunc2Args)
+ bw!
- " Test for using a funcref()
- func MytsrFunc2(findstart, base)
- call add(g:MytsrFunc2_args, [a:findstart, a:base])
- return a:findstart ? 0 : []
- endfunc
- set thesaurusfunc=funcref('MytsrFunc2')
- new | only
- call setline(1, 'three')
- let g:MytsrFunc2_args = []
- call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
- call assert_equal([[1, ''], [0, 'three']], g:MytsrFunc2_args)
- bw!
+ #" Test for using a function()
+ set thesaurusfunc=function('g:TsrFunc1',\ [10])
+ new
+ call setline(1, 'one')
+ LET g:TsrFunc1Args = []
+ call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
+ call assert_equal([[10, 1, ''], [10, 0, 'one']], g:TsrFunc1Args)
+ bw!
- " Using a funcref variable to set 'thesaurusfunc'
- let Fn = funcref('MytsrFunc2')
- let &thesaurusfunc = string(Fn)
- new | only
- call setline(1, 'four')
- let g:MytsrFunc2_args = []
- call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
- call assert_equal([[1, ''], [0, 'four']], g:MytsrFunc2_args)
- call assert_fails('let &thesaurusfunc = Fn', 'E729:')
- bw!
+ #" Using a funcref variable to set 'thesaurusfunc'
+ VAR Fn = function('g:TsrFunc1', [11])
+ LET &thesaurusfunc = Fn
+ new
+ call setline(1, 'two')
+ LET g:TsrFunc1Args = []
+ call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
+ call assert_equal([[11, 1, ''], [11, 0, 'two']], g:TsrFunc1Args)
+ bw!
- " Test for using a lambda function
- func MytsrFunc3(findstart, base)
- call add(g:MytsrFunc3_args, [a:findstart, a:base])
- return a:findstart ? 0 : []
- endfunc
- set thesaurusfunc={a,\ b,\ ->\ MytsrFunc3(a,\ b,)}
- new | only
- call setline(1, 'five')
- let g:MytsrFunc3_args = []
- call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
- call assert_equal([[1, ''], [0, 'five']], g:MytsrFunc3_args)
- bw!
+ #" Using a string(funcref_variable) to set 'thesaurusfunc'
+ LET Fn = function('g:TsrFunc1', [12])
+ LET &thesaurusfunc = string(Fn)
+ new
+ call setline(1, 'two')
+ LET g:TsrFunc1Args = []
+ call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
+ call assert_equal([[12, 1, ''], [12, 0, 'two']], g:TsrFunc1Args)
+ bw!
- " Set 'thesaurusfunc' to a lambda expression
- let &thesaurusfunc = '{a, b -> MytsrFunc3(a, b)}'
- new | only
- call setline(1, 'six')
- let g:MytsrFunc3_args = []
- call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
- call assert_equal([[1, ''], [0, 'six']], g:MytsrFunc3_args)
- bw!
+ #" Test for using a funcref()
+ set thesaurusfunc=funcref('g:TsrFunc1',\ [13])
+ new
+ call setline(1, 'three')
+ LET g:TsrFunc1Args = []
+ call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
+ call assert_equal([[13, 1, ''], [13, 0, 'three']], g:TsrFunc1Args)
+ bw!
- " Set 'thesaurusfunc' to a variable with a lambda expression
- let Lambda = {a, b -> MytsrFunc3(a, b)}
- let &thesaurusfunc = string(Lambda)
- new | only
- call setline(1, 'seven')
- let g:MytsrFunc3_args = []
+ #" Using a funcref variable to set 'thesaurusfunc'
+ LET Fn = funcref('g:TsrFunc1', [14])
+ LET &thesaurusfunc = Fn
+ new
+ call setline(1, 'four')
+ LET g:TsrFunc1Args = []
+ call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
+ call assert_equal([[14, 1, ''], [14, 0, 'four']], g:TsrFunc1Args)
+ bw!
+
+ #" Using a string(funcref_variable) to set 'thesaurusfunc'
+ LET Fn = funcref('g:TsrFunc1', [15])
+ LET &thesaurusfunc = string(Fn)
+ new
+ call setline(1, 'four')
+ LET g:TsrFunc1Args = []
+ call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
+ call assert_equal([[15, 1, ''], [15, 0, 'four']], g:TsrFunc1Args)
+ bw!
+
+ #" Test for using a lambda function
+ VAR optval = "LSTART a, b LMIDDLE TsrFunc1(16, a, b) LEND"
+ LET optval = substitute(optval, ' ', '\\ ', 'g')
+ exe "set thesaurusfunc=" .. optval
+ new
+ call setline(1, 'five')
+ LET g:TsrFunc1Args = []
+ call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
+ call assert_equal([[16, 1, ''], [16, 0, 'five']], g:TsrFunc1Args)
+ bw!
+
+ #" Test for using a lambda function with set
+ LET &thesaurusfunc = LSTART a, b LMIDDLE TsrFunc1(17, a, b) LEND
+ new
+ call setline(1, 'six')
+ LET g:TsrFunc1Args = []
+ call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
+ call assert_equal([[17, 1, ''], [17, 0, 'six']], g:TsrFunc1Args)
+ bw!
+
+ #" Set 'thesaurusfunc' to a string(lambda expression)
+ LET &thesaurusfunc = 'LSTART a, b LMIDDLE TsrFunc1(18, a, b) LEND'
+ new
+ call setline(1, 'six')
+ LET g:TsrFunc1Args = []
+ call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
+ call assert_equal([[18, 1, ''], [18, 0, 'six']], g:TsrFunc1Args)
+ bw!
+
+ #" Set 'thesaurusfunc' to a variable with a lambda expression
+ VAR Lambda = LSTART a, b LMIDDLE TsrFunc1(19, a, b) LEND
+ LET &thesaurusfunc = Lambda
+ new
+ call setline(1, 'seven')
+ LET g:TsrFunc1Args = []
+ call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
+ call assert_equal([[19, 1, ''], [19, 0, 'seven']], g:TsrFunc1Args)
+ bw!
+
+ #" Set 'thesaurusfunc' to a string(variable with a lambda expression)
+ LET Lambda = LSTART a, b LMIDDLE TsrFunc1(20, a, b) LEND
+ LET &thesaurusfunc = string(Lambda)
+ new
+ call setline(1, 'seven')
+ LET g:TsrFunc1Args = []
+ call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
+ call assert_equal([[20, 1, ''], [20, 0, 'seven']], g:TsrFunc1Args)
+ bw!
+
+ #" Test for using a lambda function with incorrect return value
+ LET Lambda = LSTART a, b LMIDDLE strlen(a) LEND
+ LET &thesaurusfunc = Lambda
+ new
+ call setline(1, 'eight')
+ call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
+ bw!
+
+ #" Test for clearing the 'thesaurusfunc' option
+ set thesaurusfunc=''
+ set thesaurusfunc&
+ call assert_fails("set thesaurusfunc=function('abc')", "E700:")
+ call assert_fails("set thesaurusfunc=funcref('abc')", "E700:")
+
+ #" set 'thesaurusfunc' to a non-existing function
+ set thesaurusfunc=TsrFunc2
+ call setline(1, 'ten')
+ call assert_fails("set thesaurusfunc=function('NonExistingFunc')", 'E700:')
+ call assert_fails("LET &thesaurusfunc = function('NonExistingFunc')", 'E700:')
+ LET g:TsrFunc2Args = []
+ call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
+ call assert_equal([[1, ''], [0, 'ten']], g:TsrFunc2Args)
+ bw!
+
+ #" Use a buffer-local value and a global value
+ set thesaurusfunc&
+ setlocal thesaurusfunc=function('g:TsrFunc1',\ [22])
+ call setline(1, 'sun')
+ LET g:TsrFunc1Args = []
+ call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")
+ call assert_equal('sun', getline(1))
+ call assert_equal([[22, 1, ''], [22, 0, 'sun']], g:TsrFunc1Args)
+ new
+ call setline(1, 'sun')
+ LET g:TsrFunc1Args = []
+ call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")
+ call assert_equal('sun', getline(1))
+ call assert_equal([], g:TsrFunc1Args)
+ set thesaurusfunc=function('g:TsrFunc1',\ [23])
+ wincmd w
+ call setline(1, 'sun')
+ LET g:TsrFunc1Args = []
+ call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")
+ call assert_equal('sun', getline(1))
+ call assert_equal([[22, 1, ''], [22, 0, 'sun']], g:TsrFunc1Args)
+ :%bw!
+ END
+ call CheckLegacyAndVim9Success(lines)
+
+ let &thesaurusfunc = {a -> 'abc'}
call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
- call assert_equal([[1, ''], [0, 'seven']], g:MytsrFunc3_args)
- call assert_fails('let &thesaurusfunc = Lambda', 'E729:')
- bw!
- " Test for using a lambda function with incorrect return value
- let Lambda = {s -> strlen(s)}
- let &thesaurusfunc = string(Lambda)
+ " Using Vim9 lambda expression in legacy context should fail
+ " set thesaurusfunc=(a,\ b)\ =>\ TsrFunc1(21,\ a,\ b)
new | only
- call setline(1, 'eight')
- call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
+ let g:TsrFunc1Args = []
+ " call assert_fails('call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")', 'E117:')
+ call assert_equal([], g:TsrFunc1Args)
bw!
- " Test for clearing the 'thesaurusfunc' option
- set thesaurusfunc=''
- set thesaurusfunc&
+ " set 'thesaurusfunc' to a partial with dict. This used to cause a crash.
+ func SetTsrFunc()
+ let params = {'thesaurus': function('g:DictTsrFunc')}
+ let &thesaurusfunc = params.thesaurus
+ endfunc
+ func g:DictTsrFunc(_) dict
+ endfunc
+ call SetTsrFunc()
+ new
+ call SetTsrFunc()
+ bw
+ call test_garbagecollect_now()
+ new
+ set thesaurusfunc=
+ wincmd w
+ %bw!
+ delfunc SetTsrFunc
- call assert_fails("set thesaurusfunc=function('abc')", "E700:")
- call assert_fails("set thesaurusfunc=funcref('abc')", "E700:")
- let &thesaurusfunc = "{a -> 'abc'}"
- call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
+ " set buffer-local 'thesaurusfunc' to a partial with dict. This used to
+ " cause a crash.
+ func SetLocalTsrFunc()
+ let params = {'thesaurus': function('g:DictTsrFunc')}
+ let &l:thesaurusfunc = params.thesaurus
+ endfunc
+ call SetLocalTsrFunc()
+ call test_garbagecollect_now()
+ call SetLocalTsrFunc()
+ set thesaurusfunc=
+ bw!
+ delfunc g:DictTsrFunc
+ delfunc SetLocalTsrFunc
" Vim9 tests
let lines =<< trim END
vim9script
- # Test for using function()
- def MytsrFunc1(findstart: number, base: string): any
- add(g:MytsrFunc1_args, [findstart, base])
+ # Test for using a def function with thesaurusfunc
+ def Vim9tsrFunc(val: number, findstart: number, base: string): any
+ add(g:Vim9tsrFunc_Args, [val, findstart, base])
return findstart ? 0 : []
enddef
- set thesaurusfunc=function('MytsrFunc1')
+ set thesaurusfunc=function('Vim9tsrFunc',\ [60])
new | only
setline(1, 'one')
- g:MytsrFunc1_args = []
+ g:Vim9tsrFunc_Args = []
feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
- assert_equal([[1, ''], [0, 'one']], g:MytsrFunc1_args)
- bw!
-
- # Test for using a lambda
- def MytsrFunc2(findstart: number, base: string): any
- add(g:MytsrFunc2_args, [findstart, base])
- return findstart ? 0 : []
- enddef
- &thesaurusfunc = '(a, b) => MytsrFunc2(a, b)'
- new | only
- setline(1, 'two')
- g:MytsrFunc2_args = []
- feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
- assert_equal([[1, ''], [0, 'two']], g:MytsrFunc2_args)
- bw!
-
- # Test for using a variable with a lambda expression
- var Fn: func = (a, b) => MytsrFunc2(a, b)
- &thesaurusfunc = string(Fn)
- new | only
- setline(1, 'three')
- g:MytsrFunc2_args = []
- feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
- assert_equal([[1, ''], [0, 'three']], g:MytsrFunc2_args)
+ assert_equal([[60, 1, ''], [60, 0, 'one']], g:Vim9tsrFunc_Args)
bw!
END
" call CheckScriptSuccess(lines)
- " Using Vim9 lambda expression in legacy context should fail
- " set thesaurusfunc=(a,\ b)\ =>\ g:MytsrFunc2(a,\ b)
- " new | only
- " let g:MytsrFunc2_args = []
- " call assert_fails('call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")', 'E117:')
- " call assert_equal([], g:MytsrFunc2_args)
- " bw!
-
- " Use a buffer-local value and a global value
- func MytsrFunc4(findstart, base)
- call add(g:MytsrFunc4_args, [a:findstart, a:base])
- return a:findstart ? 0 : ['sunday']
- endfunc
- set thesaurusfunc&
- setlocal thesaurusfunc=function('MytsrFunc4')
- call setline(1, 'sun')
- let g:MytsrFunc4_args = []
- call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")
- call assert_equal('sunday', getline(1))
- call assert_equal([[1, ''], [0, 'sun']], g:MytsrFunc4_args)
- new
- call setline(1, 'sun')
- let g:MytsrFunc4_args = []
- call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")
- call assert_equal('sun', getline(1))
- call assert_equal([], g:MytsrFunc4_args)
- set thesaurusfunc=function('MytsrFunc1')
- wincmd w
- call setline(1, 'sun')
- let g:MytsrFunc4_args = []
- call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")
- call assert_equal('sunday', getline(1))
- call assert_equal([[1, ''], [0, 'sun']], g:MytsrFunc4_args)
-
" cleanup
set thesaurusfunc&
- delfunc MytsrFunc1
- delfunc MytsrFunc2
- delfunc MytsrFunc3
- delfunc MytsrFunc4
+ delfunc TsrFunc1
+ delfunc TsrFunc2
+ unlet g:TsrFunc1Args g:TsrFunc2Args
%bw!
endfunc
diff --git a/src/nvim/testdir/test_mapping.vim b/src/nvim/testdir/test_mapping.vim
index 560883ba5d..522a51589f 100644
--- a/src/nvim/testdir/test_mapping.vim
+++ b/src/nvim/testdir/test_mapping.vim
@@ -779,7 +779,7 @@ func Test_expr_abbr()
" invalid <expr> abbreviation
abbr <expr> hte GetAbbr()
call assert_fails('normal ihte ', 'E117:')
- call assert_equal(' ', getline(1))
+ call assert_equal('', getline(1))
unabbr <expr> hte
close!
diff --git a/src/nvim/testdir/test_normal.vim b/src/nvim/testdir/test_normal.vim
index 6160352052..0d75644920 100644
--- a/src/nvim/testdir/test_normal.vim
+++ b/src/nvim/testdir/test_normal.vim
@@ -3,6 +3,7 @@
source shared.vim
source check.vim
source view_util.vim
+source vim9.vim
source screendump.vim
func Setup_NewWindow()
@@ -388,70 +389,6 @@ func Test_normal09a_operatorfunc()
norm V10j,,
call assert_equal(22, g:a)
- " Use a lambda function for 'opfunc'
- unmap <buffer> ,,
- call cursor(1, 1)
- let g:a=0
- nmap <buffer><silent> ,, :set opfunc={type\ ->\ CountSpaces(type)}<CR>g@
- vmap <buffer><silent> ,, :<C-U>call CountSpaces(visualmode(), 1)<CR>
- 50
- norm V2j,,
- call assert_equal(6, g:a)
- norm V,,
- call assert_equal(2, g:a)
- norm ,,l
- call assert_equal(0, g:a)
- 50
- exe "norm 0\<c-v>10j2l,,"
- call assert_equal(11, g:a)
- 50
- norm V10j,,
- call assert_equal(22, g:a)
-
- " use a partial function for 'opfunc'
- let g:OpVal = 0
- func! Test_opfunc1(x, y, type)
- let g:OpVal = a:x + a:y
- endfunc
- set opfunc=function('Test_opfunc1',\ [5,\ 7])
- normal! g@l
- call assert_equal(12, g:OpVal)
- " delete the function and try to use g@
- delfunc Test_opfunc1
- call test_garbagecollect_now()
- call assert_fails('normal! g@l', 'E117:')
- set opfunc=
-
- " use a funcref for 'opfunc'
- let g:OpVal = 0
- func! Test_opfunc2(x, y, type)
- let g:OpVal = a:x + a:y
- endfunc
- set opfunc=funcref('Test_opfunc2',\ [4,\ 3])
- normal! g@l
- call assert_equal(7, g:OpVal)
- " delete the function and try to use g@
- delfunc Test_opfunc2
- call test_garbagecollect_now()
- call assert_fails('normal! g@l', 'E933:')
- set opfunc=
-
- " Try to use a function with two arguments for 'operatorfunc'
- let g:OpVal = 0
- func! Test_opfunc3(x, y)
- let g:OpVal = 4
- endfunc
- set opfunc=Test_opfunc3
- call assert_fails('normal! g@l', 'E119:')
- call assert_equal(0, g:OpVal)
- set opfunc=
- delfunc Test_opfunc3
- unlet g:OpVal
-
- " Try to use a lambda function with two arguments for 'operatorfunc'
- set opfunc={x,\ y\ ->\ 'done'}
- call assert_fails('normal! g@l', 'E119:')
-
" clean up
unmap <buffer> ,,
set opfunc=
@@ -520,6 +457,182 @@ func Test_normal09c_operatorfunc()
set operatorfunc=
endfunc
+" Test for different ways of setting the 'operatorfunc' option
+func Test_opfunc_callback()
+ new
+ func OpFunc1(callnr, type)
+ let g:OpFunc1Args = [a:callnr, a:type]
+ endfunc
+ func OpFunc2(type)
+ let g:OpFunc2Args = [a:type]
+ endfunc
+
+ let lines =<< trim END
+ #" Test for using a function name
+ LET &opfunc = 'g:OpFunc2'
+ LET g:OpFunc2Args = []
+ normal! g@l
+ call assert_equal(['char'], g:OpFunc2Args)
+
+ #" Test for using a function()
+ set opfunc=function('g:OpFunc1',\ [10])
+ LET g:OpFunc1Args = []
+ normal! g@l
+ call assert_equal([10, 'char'], g:OpFunc1Args)
+
+ #" Using a funcref variable to set 'operatorfunc'
+ VAR Fn = function('g:OpFunc1', [11])
+ LET &opfunc = Fn
+ LET g:OpFunc1Args = []
+ normal! g@l
+ call assert_equal([11, 'char'], g:OpFunc1Args)
+
+ #" Using a string(funcref_variable) to set 'operatorfunc'
+ LET Fn = function('g:OpFunc1', [12])
+ LET &operatorfunc = string(Fn)
+ LET g:OpFunc1Args = []
+ normal! g@l
+ call assert_equal([12, 'char'], g:OpFunc1Args)
+
+ #" Test for using a funcref()
+ set operatorfunc=funcref('g:OpFunc1',\ [13])
+ LET g:OpFunc1Args = []
+ normal! g@l
+ call assert_equal([13, 'char'], g:OpFunc1Args)
+
+ #" Using a funcref variable to set 'operatorfunc'
+ LET Fn = funcref('g:OpFunc1', [14])
+ LET &opfunc = Fn
+ LET g:OpFunc1Args = []
+ normal! g@l
+ call assert_equal([14, 'char'], g:OpFunc1Args)
+
+ #" Using a string(funcref_variable) to set 'operatorfunc'
+ LET Fn = funcref('g:OpFunc1', [15])
+ LET &opfunc = string(Fn)
+ LET g:OpFunc1Args = []
+ normal! g@l
+ call assert_equal([15, 'char'], g:OpFunc1Args)
+
+ #" Test for using a lambda function using set
+ VAR optval = "LSTART a LMIDDLE OpFunc1(16, a) LEND"
+ LET optval = substitute(optval, ' ', '\\ ', 'g')
+ exe "set opfunc=" .. optval
+ LET g:OpFunc1Args = []
+ normal! g@l
+ call assert_equal([16, 'char'], g:OpFunc1Args)
+
+ #" Test for using a lambda function using LET
+ LET &opfunc = LSTART a LMIDDLE OpFunc1(17, a) LEND
+ LET g:OpFunc1Args = []
+ normal! g@l
+ call assert_equal([17, 'char'], g:OpFunc1Args)
+
+ #" Set 'operatorfunc' to a string(lambda expression)
+ LET &opfunc = 'LSTART a LMIDDLE OpFunc1(18, a) LEND'
+ LET g:OpFunc1Args = []
+ normal! g@l
+ call assert_equal([18, 'char'], g:OpFunc1Args)
+
+ #" Set 'operatorfunc' to a variable with a lambda expression
+ VAR Lambda = LSTART a LMIDDLE OpFunc1(19, a) LEND
+ LET &opfunc = Lambda
+ LET g:OpFunc1Args = []
+ normal! g@l
+ call assert_equal([19, 'char'], g:OpFunc1Args)
+
+ #" Set 'operatorfunc' to a string(variable with a lambda expression)
+ LET Lambda = LSTART a LMIDDLE OpFunc1(20, a) LEND
+ LET &opfunc = string(Lambda)
+ LET g:OpFunc1Args = []
+ normal! g@l
+ call assert_equal([20, 'char'], g:OpFunc1Args)
+
+ #" Try to use 'operatorfunc' after the function is deleted
+ func g:TmpOpFunc1(type)
+ let g:TmpOpFunc1Args = [21, a:type]
+ endfunc
+ LET &opfunc = function('g:TmpOpFunc1')
+ delfunc g:TmpOpFunc1
+ call test_garbagecollect_now()
+ LET g:TmpOpFunc1Args = []
+ call assert_fails('normal! g@l', 'E117:')
+ call assert_equal([], g:TmpOpFunc1Args)
+
+ #" Try to use a function with two arguments for 'operatorfunc'
+ func g:TmpOpFunc2(x, y)
+ let g:TmpOpFunc2Args = [a:x, a:y]
+ endfunc
+ set opfunc=TmpOpFunc2
+ LET g:TmpOpFunc2Args = []
+ call assert_fails('normal! g@l', 'E119:')
+ call assert_equal([], g:TmpOpFunc2Args)
+ delfunc TmpOpFunc2
+
+ #" Try to use a lambda function with two arguments for 'operatorfunc'
+ LET &opfunc = LSTART a, b LMIDDLE OpFunc1(22, b) LEND
+ LET g:OpFunc1Args = []
+ call assert_fails('normal! g@l', 'E119:')
+ call assert_equal([], g:OpFunc1Args)
+
+ #" Test for clearing the 'operatorfunc' option
+ set opfunc=''
+ set opfunc&
+ call assert_fails("set opfunc=function('abc')", "E700:")
+ call assert_fails("set opfunc=funcref('abc')", "E700:")
+
+ #" set 'operatorfunc' to a non-existing function
+ LET &opfunc = function('g:OpFunc1', [23])
+ call assert_fails("set opfunc=function('NonExistingFunc')", 'E700:')
+ call assert_fails("LET &opfunc = function('NonExistingFunc')", 'E700:')
+ LET g:OpFunc1Args = []
+ normal! g@l
+ call assert_equal([23, 'char'], g:OpFunc1Args)
+ END
+ call CheckTransLegacySuccess(lines)
+
+ " Using Vim9 lambda expression in legacy context should fail
+ " set opfunc=(a)\ =>\ OpFunc1(24,\ a)
+ let g:OpFunc1Args = []
+ " call assert_fails('normal! g@l', 'E117:')
+ call assert_equal([], g:OpFunc1Args)
+
+ " set 'operatorfunc' to a partial with dict. This used to cause a crash.
+ func SetOpFunc()
+ let operator = {'execute': function('OperatorExecute')}
+ let &opfunc = operator.execute
+ endfunc
+ func OperatorExecute(_) dict
+ endfunc
+ call SetOpFunc()
+ call test_garbagecollect_now()
+ set operatorfunc=
+ delfunc SetOpFunc
+ delfunc OperatorExecute
+
+ " Vim9 tests
+ let lines =<< trim END
+ vim9script
+
+ # Test for using a def function with opfunc
+ def g:Vim9opFunc(val: number, type: string): void
+ g:OpFunc1Args = [val, type]
+ enddef
+ set opfunc=function('g:Vim9opFunc',\ [60])
+ g:OpFunc1Args = []
+ normal! g@l
+ assert_equal([60, 'char'], g:OpFunc1Args)
+ END
+ " call CheckScriptSuccess(lines)
+
+ " cleanup
+ set opfunc&
+ delfunc OpFunc1
+ delfunc OpFunc2
+ unlet g:OpFunc1Args g:OpFunc2Args
+ %bw!
+endfunc
+
func Test_normal10_expand()
" Test for expand()
10new
diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim
index db544e47b8..11c2977a4e 100644
--- a/src/nvim/testdir/test_options.vim
+++ b/src/nvim/testdir/test_options.vim
@@ -1264,5 +1264,17 @@ func Test_keywordprg_empty()
let &keywordprg = k
endfunc
+" check that the very first buffer created does not have 'endoffile' set
+func Test_endoffile_default()
+ let after =<< trim [CODE]
+ call writefile([execute('set eof?')], 'Xtestout')
+ qall!
+ [CODE]
+ if RunVim([], after, '')
+ call assert_equal(["\nnoendoffile"], readfile('Xtestout'))
+ endif
+ call delete('Xtestout')
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_popup.vim b/src/nvim/testdir/test_popup.vim
index 7f183f0849..791cce4431 100644
--- a/src/nvim/testdir/test_popup.vim
+++ b/src/nvim/testdir/test_popup.vim
@@ -359,7 +359,7 @@ func Test_completefunc_opens_new_window_one()
/^one
call assert_fails('call feedkeys("A\<C-X>\<C-U>\<C-N>\<Esc>", "x")', 'E565:')
call assert_equal(winid, win_getid())
- call assert_equal('oneDEF', getline(1))
+ call assert_equal('onedef', getline(1))
q!
endfunc
@@ -384,9 +384,7 @@ func Test_completefunc_opens_new_window_two()
/^two
call assert_fails('call feedkeys("A\<C-X>\<C-U>\<C-N>\<Esc>", "x")', 'E565:')
call assert_equal(winid, win_getid())
- " v8.2.1919 hasn't been ported yet
- " call assert_equal('twodef', getline(1))
- call assert_equal('twoDEF', getline(1))
+ call assert_equal('twodef', getline(1))
q!
endfunc
@@ -864,7 +862,6 @@ func Test_popup_position()
endfunc
func Test_popup_command()
- CheckScreendump
CheckFeature menu
menu Test.Foo Foo
@@ -872,6 +869,23 @@ func Test_popup_command()
call assert_fails('popup Test.Foo.X', 'E327:')
call assert_fails('popup Foo', 'E337:')
unmenu Test.Foo
+endfunc
+
+func Test_popup_command_dump()
+ CheckFeature menu
+ CheckScreendump
+
+ let script =<< trim END
+ func StartTimer()
+ call timer_start(100, {-> ChangeMenu()})
+ endfunc
+ func ChangeMenu()
+ aunmenu PopUp.&Paste
+ nnoremenu 1.40 PopUp.&Paste :echomsg "pasted"<CR>
+ echomsg 'changed'
+ endfunc
+ END
+ call writefile(script, 'XtimerScript')
let lines =<< trim END
one two three four five
@@ -879,12 +893,12 @@ func Test_popup_command()
one more two three four five
END
call writefile(lines, 'Xtest')
- let buf = RunVimInTerminal('Xtest', {})
+ let buf = RunVimInTerminal('-S XtimerScript Xtest', {})
call term_sendkeys(buf, ":source $VIMRUNTIME/menu.vim\<CR>")
call term_sendkeys(buf, "/X\<CR>:popup PopUp\<CR>")
call VerifyScreenDump(buf, 'Test_popup_command_01', {})
- " Select a word
+ " go to the Paste entry in the menu
call term_sendkeys(buf, "jj")
call VerifyScreenDump(buf, 'Test_popup_command_02', {})
@@ -893,8 +907,20 @@ func Test_popup_command()
call VerifyScreenDump(buf, 'Test_popup_command_03', {})
call term_sendkeys(buf, "\<Esc>")
+
+ " 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
+ call term_sendkeys(buf, "/X\<CR>:call StartTimer() | popup PopUp\<CR>")
+ call VerifyScreenDump(buf, 'Test_popup_command_04', {})
+
+ " Select the Paste entry, executes the changed menu item.
+ call term_sendkeys(buf, "jj\<CR>")
+ call VerifyScreenDump(buf, 'Test_popup_command_05', {})
+
call StopVimInTerminal(buf)
call delete('Xtest')
+ call delete('XtimerScript')
endfunc
func Test_popup_complete_backwards()
diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim
index 9d9fc5e77b..5edcf9ce0e 100644
--- a/src/nvim/testdir/test_quickfix.vim
+++ b/src/nvim/testdir/test_quickfix.vim
@@ -1,6 +1,7 @@
" Test for the quickfix feature.
source check.vim
+source vim9.vim
CheckFeature quickfix
source screendump.vim
@@ -3440,9 +3441,9 @@ func Xmultidirstack_tests(cchar)
let l1 = g:Xgetlist({'nr':1, 'items':1})
let l2 = g:Xgetlist({'nr':2, 'items':1})
- call assert_equal(expand('Xone/a/one.txt'), bufname(l1.items[1].bufnr))
+ call assert_equal('Xone/a/one.txt', bufname(l1.items[1].bufnr))
call assert_equal(3, l1.items[1].lnum)
- call assert_equal(expand('Xtwo/a/two.txt'), bufname(l2.items[1].bufnr))
+ call assert_equal('Xtwo/a/two.txt', bufname(l2.items[1].bufnr))
call assert_equal(5, l2.items[1].lnum)
endfunc
@@ -5690,6 +5691,138 @@ func Test_qftextfunc()
call Xtest_qftextfunc('l')
endfunc
+func Test_qftextfunc_callback()
+ let lines =<< trim END
+ set efm=%f:%l:%c:%m
+
+ #" Test for using a function name
+ LET &qftf = 'g:Tqfexpr'
+ cexpr "F0:0:0:L0"
+ copen
+ call assert_equal('F0-L0C0-L0', getline(1))
+ cclose
+
+ #" Test for using a function()
+ set qftf=function('g:Tqfexpr')
+ cexpr "F1:1:1:L1"
+ copen
+ call assert_equal('F1-L1C1-L1', getline(1))
+ cclose
+
+ #" Using a funcref variable to set 'quickfixtextfunc'
+ VAR Fn = function('g:Tqfexpr')
+ LET &qftf = Fn
+ cexpr "F2:2:2:L2"
+ copen
+ call assert_equal('F2-L2C2-L2', getline(1))
+ cclose
+
+ #" Using string(funcref_variable) to set 'quickfixtextfunc'
+ LET Fn = function('g:Tqfexpr')
+ LET &qftf = string(Fn)
+ cexpr "F3:3:3:L3"
+ copen
+ call assert_equal('F3-L3C3-L3', getline(1))
+ cclose
+
+ #" Test for using a funcref()
+ set qftf=funcref('g:Tqfexpr')
+ cexpr "F4:4:4:L4"
+ copen
+ call assert_equal('F4-L4C4-L4', getline(1))
+ cclose
+
+ #" Using a funcref variable to set 'quickfixtextfunc'
+ LET Fn = funcref('g:Tqfexpr')
+ LET &qftf = Fn
+ cexpr "F5:5:5:L5"
+ copen
+ call assert_equal('F5-L5C5-L5', getline(1))
+ cclose
+
+ #" Using a string(funcref_variable) to set 'quickfixtextfunc'
+ LET Fn = funcref('g:Tqfexpr')
+ LET &qftf = string(Fn)
+ cexpr "F5:5:5:L5"
+ copen
+ call assert_equal('F5-L5C5-L5', getline(1))
+ cclose
+
+ #" Test for using a lambda function with set
+ VAR optval = "LSTART a LMIDDLE Tqfexpr(a) LEND"
+ LET optval = substitute(optval, ' ', '\\ ', 'g')
+ exe "set qftf=" .. optval
+ cexpr "F6:6:6:L6"
+ copen
+ call assert_equal('F6-L6C6-L6', getline(1))
+ cclose
+
+ #" Set 'quickfixtextfunc' to a lambda expression
+ LET &qftf = LSTART a LMIDDLE Tqfexpr(a) LEND
+ cexpr "F7:7:7:L7"
+ copen
+ call assert_equal('F7-L7C7-L7', getline(1))
+ cclose
+
+ #" Set 'quickfixtextfunc' to string(lambda_expression)
+ LET &qftf = "LSTART a LMIDDLE Tqfexpr(a) LEND"
+ cexpr "F8:8:8:L8"
+ copen
+ call assert_equal('F8-L8C8-L8', getline(1))
+ cclose
+
+ #" Set 'quickfixtextfunc' to a variable with a lambda expression
+ VAR Lambda = LSTART a LMIDDLE Tqfexpr(a) LEND
+ LET &qftf = Lambda
+ cexpr "F9:9:9:L9"
+ copen
+ call assert_equal('F9-L9C9-L9', getline(1))
+ cclose
+
+ #" Set 'quickfixtextfunc' to a string(variable with a lambda expression)
+ LET Lambda = LSTART a LMIDDLE Tqfexpr(a) LEND
+ LET &qftf = string(Lambda)
+ cexpr "F9:9:9:L9"
+ copen
+ call assert_equal('F9-L9C9-L9', getline(1))
+ cclose
+ END
+ call CheckLegacyAndVim9Success(lines)
+
+ " set 'quickfixtextfunc' to a partial with dict. This used to cause a crash.
+ func SetQftfFunc()
+ let params = {'qftf': function('g:DictQftfFunc')}
+ let &quickfixtextfunc = params.qftf
+ endfunc
+ func g:DictQftfFunc(_) dict
+ endfunc
+ call SetQftfFunc()
+ new
+ call SetQftfFunc()
+ bw
+ call test_garbagecollect_now()
+ new
+ set qftf=
+ wincmd w
+ set qftf=
+ :%bw!
+
+ " set per-quickfix list 'quickfixtextfunc' to a partial with dict. This used
+ " to cause a crash.
+ let &qftf = ''
+ func SetLocalQftfFunc()
+ let params = {'qftf': function('g:DictQftfFunc')}
+ call setqflist([], 'a', {'quickfixtextfunc' : params.qftf})
+ endfunc
+ call SetLocalQftfFunc()
+ call test_garbagecollect_now()
+ call setqflist([], 'a', {'quickfixtextfunc' : ''})
+ delfunc g:DictQftfFunc
+ delfunc SetQftfFunc
+ delfunc SetLocalQftfFunc
+ set efm&
+endfunc
+
" Test for updating a location list for some other window and check that
" 'qftextfunc' uses the correct location list.
func Test_qftextfunc_other_loclist()
diff --git a/src/nvim/testdir/test_tagfunc.vim b/src/nvim/testdir/test_tagfunc.vim
index 8690e30e77..7a88723bc0 100644
--- a/src/nvim/testdir/test_tagfunc.vim
+++ b/src/nvim/testdir/test_tagfunc.vim
@@ -1,5 +1,7 @@
" Test 'tagfunc'
+source vim9.vim
+
func TagFunc(pat, flag, info)
let g:tagfunc_args = [a:pat, a:flag, a:info]
let tags = []
@@ -125,45 +127,153 @@ endfunc
" Test for different ways of setting the 'tagfunc' option
func Test_tagfunc_callback()
- " Test for using a function()
- func MytagFunc1(pat, flags, info)
- let g:MytagFunc1_args = [a:pat, a:flags, a:info]
+ func TagFunc1(callnr, pat, flags, info)
+ let g:TagFunc1Args = [a:callnr, a:pat, a:flags, a:info]
return v:null
endfunc
- set tagfunc=function('MytagFunc1')
- new | only
- let g:MytagFunc1_args = []
- call assert_fails('tag a11', 'E433:')
- call assert_equal(['a11', '', {}], g:MytagFunc1_args)
-
- " Using a funcref variable to set 'tagfunc'
- let Fn = function('MytagFunc1')
- let &tagfunc = string(Fn)
- new | only
- let g:MytagFunc1_args = []
- call assert_fails('tag a12', 'E433:')
- call assert_equal(['a12', '', {}], g:MytagFunc1_args)
- call assert_fails('let &tagfunc = Fn', 'E729:')
-
- " Test for using a funcref()
- func MytagFunc2(pat, flags, info)
- let g:MytagFunc2_args = [a:pat, a:flags, a:info]
+ func TagFunc2(pat, flags, info)
+ let g:TagFunc2Args = [a:pat, a:flags, a:info]
return v:null
endfunc
- set tagfunc=funcref('MytagFunc2')
- new | only
- let g:MytagFunc2_args = []
- call assert_fails('tag a13', 'E433:')
- call assert_equal(['a13', '', {}], g:MytagFunc2_args)
- " Using a funcref variable to set 'tagfunc'
- let Fn = funcref('MytagFunc2')
- let &tagfunc = string(Fn)
+ let lines =<< trim END
+ #" Test for using a function name
+ LET &tagfunc = 'g:TagFunc2'
+ new
+ LET g:TagFunc2Args = []
+ call assert_fails('tag a10', 'E433:')
+ call assert_equal(['a10', '', {}], g:TagFunc2Args)
+ bw!
+
+ #" Test for using a function()
+ set tagfunc=function('g:TagFunc1',\ [10])
+ new
+ LET g:TagFunc1Args = []
+ call assert_fails('tag a11', 'E433:')
+ call assert_equal([10, 'a11', '', {}], g:TagFunc1Args)
+ bw!
+
+ #" Using a funcref variable to set 'tagfunc'
+ VAR Fn = function('g:TagFunc1', [11])
+ LET &tagfunc = Fn
+ new
+ LET g:TagFunc1Args = []
+ call assert_fails('tag a12', 'E433:')
+ call assert_equal([11, 'a12', '', {}], g:TagFunc1Args)
+ bw!
+
+ #" Using a string(funcref_variable) to set 'tagfunc'
+ LET Fn = function('g:TagFunc1', [12])
+ LET &tagfunc = string(Fn)
+ new
+ LET g:TagFunc1Args = []
+ call assert_fails('tag a12', 'E433:')
+ call assert_equal([12, 'a12', '', {}], g:TagFunc1Args)
+ bw!
+
+ #" Test for using a funcref()
+ set tagfunc=funcref('g:TagFunc1',\ [13])
+ new
+ LET g:TagFunc1Args = []
+ call assert_fails('tag a13', 'E433:')
+ call assert_equal([13, 'a13', '', {}], g:TagFunc1Args)
+ bw!
+
+ #" Using a funcref variable to set 'tagfunc'
+ LET Fn = funcref('g:TagFunc1', [14])
+ LET &tagfunc = Fn
+ new
+ LET g:TagFunc1Args = []
+ call assert_fails('tag a14', 'E433:')
+ call assert_equal([14, 'a14', '', {}], g:TagFunc1Args)
+ bw!
+
+ #" Using a string(funcref_variable) to set 'tagfunc'
+ LET Fn = funcref('g:TagFunc1', [15])
+ LET &tagfunc = string(Fn)
+ new
+ LET g:TagFunc1Args = []
+ call assert_fails('tag a14', 'E433:')
+ call assert_equal([15, 'a14', '', {}], g:TagFunc1Args)
+ bw!
+
+ #" Test for using a lambda function
+ VAR optval = "LSTART a, b, c LMIDDLE TagFunc1(16, a, b, c) LEND"
+ LET optval = substitute(optval, ' ', '\\ ', 'g')
+ exe "set tagfunc=" .. optval
+ new
+ LET g:TagFunc1Args = []
+ call assert_fails('tag a17', 'E433:')
+ call assert_equal([16, 'a17', '', {}], g:TagFunc1Args)
+ bw!
+
+ #" Set 'tagfunc' to a lambda expression
+ LET &tagfunc = LSTART a, b, c LMIDDLE TagFunc1(17, a, b, c) LEND
+ new
+ LET g:TagFunc1Args = []
+ call assert_fails('tag a18', 'E433:')
+ call assert_equal([17, 'a18', '', {}], g:TagFunc1Args)
+ bw!
+
+ #" Set 'tagfunc' to a string(lambda expression)
+ LET &tagfunc = 'LSTART a, b, c LMIDDLE TagFunc1(18, a, b, c) LEND'
+ new
+ LET g:TagFunc1Args = []
+ call assert_fails('tag a18', 'E433:')
+ call assert_equal([18, 'a18', '', {}], g:TagFunc1Args)
+ bw!
+
+ #" Set 'tagfunc' to a variable with a lambda expression
+ VAR Lambda = LSTART a, b, c LMIDDLE TagFunc1(19, a, b, c) LEND
+ LET &tagfunc = Lambda
+ new
+ LET g:TagFunc1Args = []
+ call assert_fails("tag a19", "E433:")
+ call assert_equal([19, 'a19', '', {}], g:TagFunc1Args)
+ bw!
+
+ #" Set 'tagfunc' to a string(variable with a lambda expression)
+ LET Lambda = LSTART a, b, c LMIDDLE TagFunc1(20, a, b, c) LEND
+ LET &tagfunc = string(Lambda)
+ new
+ LET g:TagFunc1Args = []
+ call assert_fails("tag a19", "E433:")
+ call assert_equal([20, 'a19', '', {}], g:TagFunc1Args)
+ bw!
+
+ #" Test for using a lambda function with incorrect return value
+ LET Lambda = LSTART a, b, c LMIDDLE strlen(a) LEND
+ LET &tagfunc = string(Lambda)
+ new
+ call assert_fails("tag a20", "E987:")
+ bw!
+
+ #" Test for clearing the 'tagfunc' option
+ set tagfunc=''
+ set tagfunc&
+ call assert_fails("set tagfunc=function('abc')", "E700:")
+ call assert_fails("set tagfunc=funcref('abc')", "E700:")
+
+ #" set 'tagfunc' to a non-existing function
+ LET &tagfunc = function('g:TagFunc2', [21])
+ LET g:TagFunc2Args = []
+ call assert_fails("set tagfunc=function('NonExistingFunc')", 'E700:')
+ call assert_fails("LET &tagfunc = function('NonExistingFunc')", 'E700:')
+ call assert_fails("tag axb123", 'E426:')
+ call assert_equal([], g:TagFunc2Args)
+ bw!
+ END
+ call CheckLegacyAndVim9Success(lines)
+
+ let &tagfunc = "{a -> 'abc'}"
+ call assert_fails("echo taglist('a')", "E987:")
+
+ " Using Vim9 lambda expression in legacy context should fail
+ " set tagfunc=(a,\ b,\ c)\ =>\ g:TagFunc1(21,\ a,\ b,\ c)
new | only
- let g:MytagFunc2_args = []
- call assert_fails('tag a14', 'E433:')
- call assert_equal(['a14', '', {}], g:MytagFunc2_args)
- call assert_fails('let &tagfunc = Fn', 'E729:')
+ let g:TagFunc1Args = []
+ " call assert_fails("tag a17", "E117:")
+ call assert_equal([], g:TagFunc1Args)
" Test for using a script local function
set tagfunc=<SID>ScriptLocalTagFunc
@@ -174,101 +284,60 @@ func Test_tagfunc_callback()
" Test for using a script local funcref variable
let Fn = function("s:ScriptLocalTagFunc")
- let &tagfunc= string(Fn)
+ let &tagfunc= Fn
new | only
let g:ScriptLocalFuncArgs = []
call assert_fails('tag a16', 'E433:')
call assert_equal(['a16', '', {}], g:ScriptLocalFuncArgs)
- " Test for using a lambda function
- func MytagFunc3(pat, flags, info)
- let g:MytagFunc3_args = [a:pat, a:flags, a:info]
- return v:null
- endfunc
- set tagfunc={a,\ b,\ c\ ->\ MytagFunc3(a,\ b,\ c)}
- new | only
- let g:MytagFunc3_args = []
- call assert_fails('tag a17', 'E433:')
- call assert_equal(['a17', '', {}], g:MytagFunc3_args)
-
- " Set 'tagfunc' to a lambda expression
- let &tagfunc = '{a, b, c -> MytagFunc3(a, b, c)}'
- new | only
- let g:MytagFunc3_args = []
- call assert_fails('tag a18', 'E433:')
- call assert_equal(['a18', '', {}], g:MytagFunc3_args)
-
- " Set 'tagfunc' to a variable with a lambda expression
- let Lambda = {a, b, c -> MytagFunc3(a, b, c)}
- let &tagfunc = string(Lambda)
- new | only
- let g:MytagFunc3_args = []
- call assert_fails("tag a19", "E433:")
- call assert_equal(['a19', '', {}], g:MytagFunc3_args)
- call assert_fails('let &tagfunc = Lambda', 'E729:')
-
- " Test for using a lambda function with incorrect return value
- let Lambda = {s -> strlen(s)}
- let &tagfunc = string(Lambda)
+ " Test for using a string(script local funcref variable)
+ let Fn = function("s:ScriptLocalTagFunc")
+ let &tagfunc= string(Fn)
new | only
- call assert_fails("tag a20", "E987:")
-
- " Test for clearing the 'tagfunc' option
- set tagfunc=''
- set tagfunc&
+ let g:ScriptLocalFuncArgs = []
+ call assert_fails('tag a16', 'E433:')
+ call assert_equal(['a16', '', {}], g:ScriptLocalFuncArgs)
- call assert_fails("set tagfunc=function('abc')", "E700:")
- call assert_fails("set tagfunc=funcref('abc')", "E700:")
- let &tagfunc = "{a -> 'abc'}"
- call assert_fails("echo taglist('a')", "E987:")
+ " set 'tagfunc' to a partial with dict. This used to cause a crash.
+ func SetTagFunc()
+ let params = {'tagfn': function('g:DictTagFunc')}
+ let &tagfunc = params.tagfn
+ endfunc
+ func g:DictTagFunc(_) dict
+ endfunc
+ call SetTagFunc()
+ new
+ call SetTagFunc()
+ bw
+ call test_garbagecollect_now()
+ new
+ set tagfunc=
+ wincmd w
+ set tagfunc=
+ :%bw!
+ delfunc g:DictTagFunc
+ delfunc SetTagFunc
" Vim9 tests
let lines =<< trim END
vim9script
# Test for using function()
- def MytagFunc1(pat: string, flags: string, info: dict<any>): any
- g:MytagFunc1_args = [pat, flags, info]
+ def Vim9tagFunc(val: number, pat: string, flags: string, info: dict<any>): any
+ g:Vim9tagFuncArgs = [val, pat, flags, info]
return null
enddef
- set tagfunc=function('MytagFunc1')
+ set tagfunc=function('Vim9tagFunc',\ [60])
new | only
- g:MytagFunc1_args = []
+ g:Vim9tagFuncArgs = []
assert_fails('tag a10', 'E433:')
- assert_equal(['a10', '', {}], g:MytagFunc1_args)
-
- # Test for using a lambda
- def MytagFunc2(pat: string, flags: string, info: dict<any>): any
- g:MytagFunc2_args = [pat, flags, info]
- return null
- enddef
- &tagfunc = '(a, b, c) => MytagFunc2(a, b, c)'
- new | only
- g:MytagFunc2_args = []
- assert_fails('tag a20', 'E433:')
- assert_equal(['a20', '', {}], g:MytagFunc2_args)
-
- # Test for using a variable with a lambda expression
- var Fn: func = (a, b, c) => MytagFunc2(a, b, c)
- &tagfunc = string(Fn)
- new | only
- g:MytagFunc2_args = []
- assert_fails('tag a30', 'E433:')
- assert_equal(['a30', '', {}], g:MytagFunc2_args)
+ assert_equal([60, 'a10', '', {}], g:Vim9tagFuncArgs)
END
" call CheckScriptSuccess(lines)
- " Using Vim9 lambda expression in legacy context should fail
- " set tagfunc=(a,\ b,\ c)\ =>\ g:MytagFunc2(a,\ b,\ c)
- " new | only
- " let g:MytagFunc3_args = []
- " call assert_fails("tag a17", "E117:")
- " call assert_equal([], g:MytagFunc3_args)
-
" cleanup
- delfunc MytagFunc1
- delfunc MytagFunc2
- delfunc MytagFunc3
+ delfunc TagFunc1
+ delfunc TagFunc2
set tagfunc&
%bw!
endfunc
diff --git a/src/nvim/testdir/test_vimscript.vim b/src/nvim/testdir/test_vimscript.vim
index 44904af160..c93ba9dcfc 100644
--- a/src/nvim/testdir/test_vimscript.vim
+++ b/src/nvim/testdir/test_vimscript.vim
@@ -193,6 +193,16 @@ func Test_if_while()
call assert_equal('ab3j3b2c2b1f1h1km', g:Xpath)
endfunc
+" Check double quote after skipped "elseif" does not give error E15
+func Test_skipped_elseif()
+ if "foo" ==? "foo"
+ let result = "first"
+ elseif "foo" ==? "foo"
+ let result = "second"
+ endif
+ call assert_equal('first', result)
+endfunc
+
"-------------------------------------------------------------------------------
" Test 4: :return {{{1
"-------------------------------------------------------------------------------
@@ -3024,7 +3034,7 @@ func Test_nested_if_else_errors()
" :elseif without :if
let code =<< trim END
- elseif
+ elseif 1
END
call writefile(code, 'Xtest')
call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if')
@@ -3032,7 +3042,7 @@ func Test_nested_if_else_errors()
" :elseif without :if
let code =<< trim END
while 1
- elseif
+ elseif 1
endwhile
END
call writefile(code, 'Xtest')
@@ -3042,7 +3052,7 @@ func Test_nested_if_else_errors()
let code =<< trim END
try
finally
- elseif
+ elseif 1
endtry
END
call writefile(code, 'Xtest')
@@ -3051,7 +3061,7 @@ func Test_nested_if_else_errors()
" :elseif without :if
let code =<< trim END
try
- elseif
+ elseif 1
endtry
END
call writefile(code, 'Xtest')
@@ -3062,7 +3072,7 @@ func Test_nested_if_else_errors()
try
throw "a"
catch /a/
- elseif
+ elseif 1
endtry
END
call writefile(code, 'Xtest')
diff --git a/src/nvim/testdir/vim9.vim b/src/nvim/testdir/vim9.vim
new file mode 100644
index 0000000000..db74ce3b11
--- /dev/null
+++ b/src/nvim/testdir/vim9.vim
@@ -0,0 +1,80 @@
+
+" Use a different file name for each run.
+let s:sequence = 1
+
+" Check that "lines" inside a legacy function has no error.
+func CheckLegacySuccess(lines)
+ let cwd = getcwd()
+ let fname = 'XlegacySuccess' .. s:sequence
+ let s:sequence += 1
+ call writefile(['func Func()'] + a:lines + ['endfunc'], fname)
+ try
+ exe 'so ' .. fname
+ call Func()
+ finally
+ delfunc! Func
+ call chdir(cwd)
+ call delete(fname)
+ endtry
+endfunc
+
+" Check that "lines" inside a legacy function results in the expected error
+func CheckLegacyFailure(lines, error)
+ let cwd = getcwd()
+ let fname = 'XlegacyFails' .. s:sequence
+ let s:sequence += 1
+ call writefile(['func Func()'] + a:lines + ['endfunc', 'call Func()'], fname)
+ try
+ call assert_fails('so ' .. fname, a:error)
+ finally
+ delfunc! Func
+ call chdir(cwd)
+ call delete(fname)
+ endtry
+endfunc
+
+" Execute "lines" in a legacy function, translated as in
+" CheckLegacyAndVim9Success()
+func CheckTransLegacySuccess(lines)
+ let legacylines = a:lines->deepcopy()->map({_, v ->
+ \ v->substitute('\<VAR\>', 'let', 'g')
+ \ ->substitute('\<LET\>', 'let', 'g')
+ \ ->substitute('\<LSTART\>', '{', 'g')
+ \ ->substitute('\<LMIDDLE\>', '->', 'g')
+ \ ->substitute('\<LEND\>', '}', 'g')
+ \ ->substitute('\<TRUE\>', '1', 'g')
+ \ ->substitute('\<FALSE\>', '0', 'g')
+ \ ->substitute('#"', ' "', 'g')
+ \ })
+ call CheckLegacySuccess(legacylines)
+endfunc
+
+" Execute "lines" in a legacy function
+" Use 'VAR' for a declaration.
+" Use 'LET' for an assignment
+" Use ' #"' for a comment
+" Use LSTART arg LMIDDLE expr LEND for lambda
+" Use 'TRUE' for 1
+" Use 'FALSE' for 0
+func CheckLegacyAndVim9Success(lines)
+ call CheckTransLegacySuccess(a:lines)
+endfunc
+
+" Execute "lines" in a legacy function
+" Use 'VAR' for a declaration.
+" Use 'LET' for an assignment
+" Use ' #"' for a comment
+func CheckLegacyAndVim9Failure(lines, error)
+ if type(a:error) == type('string')
+ let legacyError = error
+ else
+ let legacyError = error[0]
+ endif
+
+ let legacylines = a:lines->deepcopy()->map({_, v ->
+ \ v->substitute('\<VAR\>', 'let', 'g')
+ \ ->substitute('\<LET\>', 'let', 'g')
+ \ ->substitute('#"', ' "', 'g')
+ \ })
+ call CheckLegacyFailure(legacylines, legacyError)
+endfunc
diff --git a/src/nvim/testing.c b/src/nvim/testing.c
index 9dd41224da..a37ceeb86b 100644
--- a/src/nvim/testing.c
+++ b/src/nvim/testing.c
@@ -6,6 +6,8 @@
#include "nvim/eval.h"
#include "nvim/eval/encode.h"
#include "nvim/ex_docmd.h"
+#include "nvim/globals.h"
+#include "nvim/message.h"
#include "nvim/os/os.h"
#include "nvim/runtime.h"
#include "nvim/testing.h"
@@ -491,8 +493,8 @@ void f_assert_fails(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
// trylevel must be zero for a ":throw" command to be considered failed
trylevel = 0;
suppress_errthrow = true;
- emsg_silent = true;
- emsg_assert_fails_used = true;
+ in_assert_fails = true;
+ no_wait_return++;
do_cmdline_cmd(cmd);
if (called_emsg == called_emsg_before) {
@@ -584,9 +586,14 @@ void f_assert_fails(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
theend:
trylevel = save_trylevel;
suppress_errthrow = false;
- emsg_silent = false;
+ in_assert_fails = false;
+ did_emsg = false;
+ msg_col = 0;
+ no_wait_return--;
+ need_wait_return = false;
emsg_on_display = false;
- emsg_assert_fails_used = false;
+ msg_reset_scroll();
+ lines_left = Rows;
XFREE_CLEAR(emsg_assert_fails_msg);
set_vim_var_string(VV_ERRMSG, NULL, 0);
if (wrong_arg_msg != NULL) {
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c
index fbeca26274..2089686e5e 100644
--- a/src/nvim/tui/input.c
+++ b/src/nvim/tui/input.c
@@ -324,15 +324,14 @@ static void forward_simple_utf8(TermInput *input, TermKeyKey *key)
&& map_has(KittyKey, cstr_t)(&kitty_key_map, (KittyKey)key->code.codepoint)) {
handle_kitty_key_protocol(input, key);
return;
- } else {
- while (*ptr) {
- if (*ptr == '<') {
- len += (size_t)snprintf(buf + len, sizeof(buf) - len, "<lt>");
- } else {
- buf[len++] = *ptr;
- }
- ptr++;
+ }
+ while (*ptr) {
+ if (*ptr == '<') {
+ len += (size_t)snprintf(buf + len, sizeof(buf) - len, "<lt>");
+ } else {
+ buf[len++] = *ptr;
}
+ ptr++;
}
tinput_enqueue(input, buf, len);
@@ -355,21 +354,20 @@ static void forward_modified_utf8(TermInput *input, TermKeyKey *key)
(KittyKey)key->code.codepoint)) {
handle_kitty_key_protocol(input, key);
return;
- } else {
- // Termkey doesn't include the S- modifier for ASCII characters (e.g.,
- // ctrl-shift-l is <C-L> instead of <C-S-L>. Vim, on the other hand,
- // treats <C-L> and <C-l> the same, requiring the S- modifier.
- len = termkey_strfkey(input->tk, buf, sizeof(buf), key, TERMKEY_FORMAT_VIM);
- if ((key->modifiers & TERMKEY_KEYMOD_CTRL)
- && !(key->modifiers & TERMKEY_KEYMOD_SHIFT)
- && ASCII_ISUPPER(key->code.codepoint)) {
- assert(len <= 62);
- // Make room for the S-
- memmove(buf + 3, buf + 1, len - 1);
- buf[1] = 'S';
- buf[2] = '-';
- len += 2;
- }
+ }
+ // Termkey doesn't include the S- modifier for ASCII characters (e.g.,
+ // ctrl-shift-l is <C-L> instead of <C-S-L>. Vim, on the other hand,
+ // treats <C-L> and <C-l> the same, requiring the S- modifier.
+ len = termkey_strfkey(input->tk, buf, sizeof(buf), key, TERMKEY_FORMAT_VIM);
+ if ((key->modifiers & TERMKEY_KEYMOD_CTRL)
+ && !(key->modifiers & TERMKEY_KEYMOD_SHIFT)
+ && ASCII_ISUPPER(key->code.codepoint)) {
+ assert(len <= 62);
+ // Make room for the S-
+ memmove(buf + 3, buf + 1, len - 1);
+ buf[1] = 'S';
+ buf[2] = '-';
+ len += 2;
}
}
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index 083677a58e..e2d37860c4 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -1651,9 +1651,8 @@ static void out(void *ctx, const char *str, size_t len)
// Called by unibi_format(): avoid flush_buf() halfway an escape sequence.
data->overflow = true;
return;
- } else {
- flush_buf(ui);
}
+ flush_buf(ui);
}
memcpy(data->buf + data->bufpos, str, len);
diff --git a/src/nvim/types.h b/src/nvim/types.h
index fb10bf21d9..d90c623955 100644
--- a/src/nvim/types.h
+++ b/src/nvim/types.h
@@ -45,6 +45,9 @@ typedef enum {
kTrue = 1,
} TriState;
+#define TRISTATE_TO_BOOL(val, \
+ default) ((val) == kTrue ? true : ((val) == kFalse ? false : (default)))
+
typedef struct Decoration Decoration;
#endif // NVIM_TYPES_H
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index eb59d72e43..bee8d461a7 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -315,7 +315,7 @@ void vim_beep(unsigned val)
{
called_vim_beep = true;
- if (emsg_silent == 0) {
+ if (emsg_silent == 0 && !in_assert_fails) {
if (!((bo_flags & val) || (bo_flags & BO_ALL))) {
static int beeps = 0;
static uint64_t start_time = 0;
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index ef8dc0775b..d450043d2a 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -2713,9 +2713,8 @@ void ex_undojoin(exarg_T *eap)
}
if (get_undolevel(curbuf) < 0) {
return; // no entries, nothing to do
- } else {
- curbuf->b_u_synced = false; // Append next change to last entry
}
+ curbuf->b_u_synced = false; // Append next change to last entry
}
/// Called after writing or reloading the file and setting b_changed to false.
diff --git a/src/nvim/usercmd.c b/src/nvim/usercmd.c
index bed4d55d4e..21a433d855 100644
--- a/src/nvim/usercmd.c
+++ b/src/nvim/usercmd.c
@@ -343,9 +343,8 @@ static char *get_command_complete(int arg)
{
if (arg >= (int)(ARRAY_SIZE(command_complete))) {
return NULL;
- } else {
- return (char *)command_complete[arg];
}
+ return (char *)command_complete[arg];
}
/// Function given to ExpandGeneric() to obtain the list of values for -complete.
@@ -357,9 +356,8 @@ char *get_user_cmd_complete(expand_T *xp, int idx)
char *cmd_compl = get_command_complete(idx);
if (cmd_compl == NULL) {
return "";
- } else {
- return cmd_compl;
}
+ return cmd_compl;
}
int cmdcomplete_str_to_type(const char *complete_str)
diff --git a/src/nvim/viml/parser/expressions.c b/src/nvim/viml/parser/expressions.c
index 8028950c07..77f85b5d2d 100644
--- a/src/nvim/viml/parser/expressions.c
+++ b/src/nvim/viml/parser/expressions.c
@@ -628,8 +628,8 @@ LexExprToken viml_pexpr_next_token(ParserState *const pstate, const int flags)
GET_CCS(ret, pline);
ret.data.cmp.inv = (schar == '<');
ret.data.cmp.type = ((ret.data.cmp.inv ^ haseqsign)
- ? kExprCmpGreaterOrEqual
- : kExprCmpGreater);
+ ? kExprCmpGreaterOrEqual
+ : kExprCmpGreater);
break;
}
@@ -1963,8 +1963,8 @@ ExprAST viml_pexpr_parse(ParserState *const pstate, const int flags)
|| ((*kv_Z(ast_stack, 1))->type != kExprNodeConcat
&& ((*kv_Z(ast_stack, 1))->type
!= kExprNodeConcatOrSubscript))))
- ? kELFlagAllowFloat
- : 0));
+ ? kELFlagAllowFloat
+ : 0));
LexExprToken cur_token = viml_pexpr_next_token(pstate,
want_node_to_lexer_flags[want_node] |
lexer_additional_flags);
@@ -2031,9 +2031,9 @@ viml_pexpr_parse_process_token:
const bool node_is_key = (
is_concat_or_subscript
&& (cur_token.type == kExprLexPlainIdentifier
- ? (!cur_token.data.var.autoload
- && cur_token.data.var.scope == kExprVarScopeMissing)
- : (cur_token.type == kExprLexNumber))
+ ? (!cur_token.data.var.autoload
+ && cur_token.data.var.scope == kExprVarScopeMissing)
+ : (cur_token.type == kExprLexNumber))
&& prev_token.type != kExprLexSpacing);
if (is_concat_or_subscript && !node_is_key) {
// Note: in Vim "d. a" (this is the reason behind `prev_token.type !=
@@ -2707,14 +2707,14 @@ viml_pexpr_parse_figure_brace_closing_error:
break;
case kExprLexPlainIdentifier: {
const ExprVarScope scope = (cur_token.type == kExprLexInvalid
- ? kExprVarScopeMissing
- : cur_token.data.var.scope);
+ ? kExprVarScopeMissing
+ : cur_token.data.var.scope);
if (want_node == kENodeValue) {
want_node = kENodeOperator;
NEW_NODE_WITH_CUR_POS(cur_node,
(node_is_key
- ? kExprNodePlainKey
- : kExprNodePlainIdentifier));
+ ? kExprNodePlainKey
+ : kExprNodePlainIdentifier));
cur_node->data.var.scope = scope;
const size_t scope_shift = (scope == kExprVarScopeMissing ? 0 : 2);
cur_node->data.var.ident = (pline.data + cur_token.start.col
@@ -2732,8 +2732,8 @@ viml_pexpr_parse_figure_brace_closing_error:
scope_shift),
cur_token.len - scope_shift,
(node_is_key
- ? HL(IdentifierKey)
- : HL(IdentifierName)));
+ ? HL(IdentifierKey)
+ : HL(IdentifierName)));
} else {
if (scope == kExprVarScopeMissing) {
// uncrustify:off
@@ -2902,15 +2902,15 @@ viml_pexpr_parse_no_paren_closing_error: {}
// different error numbers: "E114: Missing quote" and
// "E115: Missing quote".
ERROR_FROM_TOKEN_AND_MSG(cur_token, (is_double
- ? _("E114: Missing double quote: %.*s")
- : _("E115: Missing single quote: %.*s")));
+ ? _("E114: Missing double quote: %.*s")
+ : _("E115: Missing single quote: %.*s")));
}
if (want_node == kENodeOperator) {
OP_MISSING;
}
NEW_NODE_WITH_CUR_POS(cur_node, (is_double
- ? kExprNodeDoubleQuotedString
- : kExprNodeSingleQuotedString));
+ ? kExprNodeDoubleQuotedString
+ : kExprNodeSingleQuotedString));
*top_node_p = cur_node;
parse_quoted_string(pstate, cur_node, cur_token, &ast_stack, is_invalid);
want_node = kENodeOperator;
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 1cde433b0a..de5bcb40ea 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -52,6 +52,7 @@
#include "nvim/regexp.h"
#include "nvim/search.h"
#include "nvim/state.h"
+#include "nvim/statusline.h"
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/terminal.h"
@@ -271,9 +272,8 @@ newwindow:
for (wp = firstwin; --Prenum > 0;) {
if (wp->w_next == NULL) {
break;
- } else {
- wp = wp->w_next;
}
+ wp = wp->w_next;
}
} else {
if (nchar == 'W') { // go to previous window
@@ -873,9 +873,8 @@ int win_fdccol_count(win_T *wp)
const int fdccol = fdc[4] == ':' ? fdc[5] - '0' : 1;
int needed_fdccols = getDeepestNesting(wp);
return MIN(fdccol, needed_fdccols);
- } else {
- return fdc[0] - '0';
}
+ return fdc[0] - '0';
}
void ui_ext_win_position(win_T *wp, bool validate)
@@ -4870,12 +4869,11 @@ win_T *buf_jump_open_win(buf_T *buf)
if (curwin->w_buffer == buf) {
win_enter(curwin, false);
return curwin;
- } else {
- FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if (wp->w_buffer == buf) {
- win_enter(wp, false);
- return wp;
- }
+ }
+ FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
+ if (wp->w_buffer == buf) {
+ win_enter(wp, false);
+ return wp;
}
}
@@ -5030,10 +5028,10 @@ static void win_free(win_T *wp, tabpage_T *tp)
xfree(wp->w_localdir);
xfree(wp->w_prevdir);
- stl_clear_click_defs(wp->w_status_click_defs, (long)wp->w_status_click_defs_size);
+ stl_clear_click_defs(wp->w_status_click_defs, wp->w_status_click_defs_size);
xfree(wp->w_status_click_defs);
- stl_clear_click_defs(wp->w_winbar_click_defs, (long)wp->w_winbar_click_defs_size);
+ stl_clear_click_defs(wp->w_winbar_click_defs, wp->w_winbar_click_defs_size);
xfree(wp->w_winbar_click_defs);
// Remove the window from the b_wininfo lists, it may happen that the
@@ -6587,7 +6585,7 @@ static void win_remove_status_line(win_T *wp, bool add_hsep)
}
comp_col();
- stl_clear_click_defs(wp->w_status_click_defs, (long)wp->w_status_click_defs_size);
+ stl_clear_click_defs(wp->w_status_click_defs, wp->w_status_click_defs_size);
xfree(wp->w_status_click_defs);
wp->w_status_click_defs_size = 0;
wp->w_status_click_defs = NULL;
@@ -6646,12 +6644,11 @@ static bool resize_frame_for_winbar(frame_T *fr)
if (fp == NULL || fp == fr) {
emsg(_(e_noroom));
return false;
- } else {
- frame_new_height(fp, fp->fr_height - 1, false, false);
- win_new_height(wp, wp->w_height + 1);
- frame_fix_height(wp);
- (void)win_comp_pos();
}
+ frame_new_height(fp, fp->fr_height - 1, false, false);
+ win_new_height(wp, wp->w_height + 1);
+ frame_fix_height(wp);
+ (void)win_comp_pos();
return true;
}
@@ -6724,7 +6721,7 @@ int set_winbar_win(win_T *wp, bool make_room, bool valid_cursor)
if (winbar_height == 0) {
// When removing winbar, deallocate the w_winbar_click_defs array
- stl_clear_click_defs(wp->w_winbar_click_defs, (long)wp->w_winbar_click_defs_size);
+ stl_clear_click_defs(wp->w_winbar_click_defs, wp->w_winbar_click_defs_size);
xfree(wp->w_winbar_click_defs);
wp->w_winbar_click_defs_size = 0;
wp->w_winbar_click_defs = NULL;
diff --git a/test/functional/api/command_spec.lua b/test/functional/api/command_spec.lua
index f19d7a362b..d0fb26edc7 100644
--- a/test/functional/api/command_spec.lua
+++ b/test/functional/api/command_spec.lua
@@ -114,6 +114,7 @@ describe('nvim_create_user_command', function()
]]
eq({
+ name = "CommandWithLuaCallback",
args = [[this\ is a\ test]],
fargs = {"this ", "is", "a test"},
bang = false,
@@ -150,6 +151,7 @@ describe('nvim_create_user_command', function()
]=])
eq({
+ name = "CommandWithLuaCallback",
args = [[this includes\ a backslash: \\]],
fargs = {"this", "includes a", "backslash:", "\\"},
bang = false,
@@ -186,6 +188,7 @@ describe('nvim_create_user_command', function()
]=])
eq({
+ name = "CommandWithLuaCallback",
args = "a\\b",
fargs = {"a\\b"},
bang = false,
@@ -222,6 +225,7 @@ describe('nvim_create_user_command', function()
]=])
eq({
+ name = "CommandWithLuaCallback",
args = 'h\tey ',
fargs = {[[h]], [[ey]]},
bang = true,
@@ -258,6 +262,7 @@ describe('nvim_create_user_command', function()
]=])
eq({
+ name = "CommandWithLuaCallback",
args = "h",
fargs = {"h"},
bang = false,
@@ -294,6 +299,7 @@ describe('nvim_create_user_command', function()
]])
eq({
+ name = "CommandWithLuaCallback",
args = "",
fargs = {}, -- fargs works without args
bang = false,
@@ -342,6 +348,7 @@ describe('nvim_create_user_command', function()
]]
eq({
+ name = "CommandWithOneOrNoArg",
args = "hello I'm one argument",
fargs = {"hello I'm one argument"}, -- Doesn't split args
bang = false,
@@ -379,6 +386,7 @@ describe('nvim_create_user_command', function()
-- f-args is an empty table if no args were passed
eq({
+ name = "CommandWithOneOrNoArg",
args = "",
fargs = {},
bang = false,
@@ -427,6 +435,7 @@ describe('nvim_create_user_command', function()
})
]]
eq({
+ name = "CommandWithNoArgs",
args = "",
fargs = {},
bang = false,
@@ -463,6 +472,7 @@ describe('nvim_create_user_command', function()
]])
-- register can be specified
eq({
+ name = "CommandWithNoArgs",
args = "",
fargs = {},
bang = false,
diff --git a/test/functional/ex_cmds/map_spec.lua b/test/functional/ex_cmds/map_spec.lua
index c6bdd017bd..dd9f7027cf 100644
--- a/test/functional/ex_cmds/map_spec.lua
+++ b/test/functional/ex_cmds/map_spec.lua
@@ -161,6 +161,7 @@ describe('Screen', function()
]])
end)
+ -- oldtest: Test_expr_map_restore_cursor()
it('cursor is restored after :map <expr> which redraws statusline vim-patch:8.1.2336', function()
exec([[
call setline(1, ['one', 'two', 'three'])
@@ -246,6 +247,7 @@ describe('Screen', function()
]])
end)
+ -- oldtest: Test_map_listing()
it('listing mappings clears command line vim-patch:8.2.4401', function()
screen:try_resize(40, 5)
command('nmap a b')
diff --git a/test/functional/ex_cmds/write_spec.lua b/test/functional/ex_cmds/write_spec.lua
index 4045d13153..d6b5c54de9 100644
--- a/test/functional/ex_cmds/write_spec.lua
+++ b/test/functional/ex_cmds/write_spec.lua
@@ -20,6 +20,9 @@ describe(':write', function()
os.remove('test_bkc_file.txt')
os.remove('test_bkc_link.txt')
os.remove('test_fifo')
+ os.remove('test/write/p_opt.txt')
+ os.remove('test/write')
+ os.remove('test')
os.remove(fname)
os.remove(fname_bak)
os.remove(fname_broken)
@@ -94,6 +97,30 @@ describe(':write', function()
fifo:close()
end)
+ it("++p creates missing parent directories", function()
+ eq(0, eval("filereadable('p_opt.txt')"))
+ command("write ++p p_opt.txt")
+ eq(1, eval("filereadable('p_opt.txt')"))
+ os.remove("p_opt.txt")
+
+ eq(0, eval("filereadable('p_opt.txt')"))
+ command("write ++p ./p_opt.txt")
+ eq(1, eval("filereadable('p_opt.txt')"))
+ os.remove("p_opt.txt")
+
+ eq(0, eval("filereadable('test/write/p_opt.txt')"))
+ command("write ++p test/write/p_opt.txt")
+ eq(1, eval("filereadable('test/write/p_opt.txt')"))
+
+ eq(('Vim(write):E32: No file name'), pcall_err(command, 'write ++p test_write/'))
+ if not iswin() then
+ eq(('Vim(write):E17: "'..funcs.fnamemodify('.', ':p:h')..'" is a directory'),
+ pcall_err(command, 'write ++p .'))
+ eq(('Vim(write):E17: "'..funcs.fnamemodify('.', ':p:h')..'" is a directory'),
+ pcall_err(command, 'write ++p ./'))
+ end
+ end)
+
it('errors out correctly', function()
if isCI('cirrus') then
pending('FIXME: cirrus')
diff --git a/test/functional/legacy/search_stat_spec.lua b/test/functional/legacy/search_stat_spec.lua
index c2ca393a56..9fcf798836 100644
--- a/test/functional/legacy/search_stat_spec.lua
+++ b/test/functional/legacy/search_stat_spec.lua
@@ -17,6 +17,7 @@ describe('search stat', function()
screen:attach()
end)
+ -- oldtest: Test_search_stat_screendump()
it('right spacing with silent mapping vim-patch:8.1.1970', function()
exec([[
set shortmess-=S
@@ -57,6 +58,7 @@ describe('search stat', function()
]])
end)
+ -- oldtest: Test_search_stat_foldopen()
it('when only match is in fold vim-patch:8.2.0840', function()
exec([[
set shortmess-=S
@@ -86,6 +88,7 @@ describe('search stat', function()
screen:expect_unchanged()
end)
+ -- oldtest: Test_search_stat_then_gd()
it('is cleared by gd and gD vim-patch:8.2.3583', function()
exec([[
call setline(1, ['int cat;', 'int dog;', 'cat = dog;'])
@@ -120,6 +123,7 @@ describe('search stat', function()
]])
end)
+ -- oldtest: Test_search_stat_and_incsearch()
it('is not broken by calling searchcount() in tabline vim-patch:8.2.4378', function()
exec([[
call setline(1, ['abc--c', '--------abc', '--abc'])
diff --git a/test/functional/lua/ffi_spec.lua b/test/functional/lua/ffi_spec.lua
index 80c01a2b8c..3969a7a478 100644
--- a/test/functional/lua/ffi_spec.lua
+++ b/test/functional/lua/ffi_spec.lua
@@ -35,11 +35,12 @@ describe('ffi.cdef', function()
int build_stl_str_hl(
win_T *wp,
- char_u *out,
+ char *out,
size_t outlen,
- char_u *fmt,
- int use_sandbox,
- char_u fillchar,
+ char *fmt,
+ char *opt_name,
+ int opt_scope,
+ int fillchar,
int maxwidth,
stl_hlrec_t **hltab,
StlClickRecord **tabtab
@@ -48,9 +49,10 @@ describe('ffi.cdef', function()
return ffi.C.build_stl_str_hl(
ffi.C.find_window_by_handle(0, ffi.new('Error')),
- ffi.new('char_u[1024]'),
+ ffi.new('char[1024]'),
1024,
- ffi.cast('char_u*', 'StatusLineOfLength20'),
+ ffi.cast('char*', 'StatusLineOfLength20'),
+ nil,
0,
0,
0,
diff --git a/test/functional/lua/ui_spec.lua b/test/functional/lua/ui_spec.lua
index 3fcb2dec8d..9ee99b4905 100644
--- a/test/functional/lua/ui_spec.lua
+++ b/test/functional/lua/ui_spec.lua
@@ -4,6 +4,7 @@ local exec_lua = helpers.exec_lua
local clear = helpers.clear
local feed = helpers.feed
local eval = helpers.eval
+local poke_eventloop = helpers.poke_eventloop
describe('vim.ui', function()
before_each(function()
@@ -83,5 +84,50 @@ describe('vim.ui', function()
feed('abcdefg<cr>')
eq('abcdefg', exec_lua('return result'))
end)
+
+ it('can input empty text #18144', function()
+ feed(':lua vim.ui.input({}, function(input) result = input end)<cr>')
+ feed('<cr>')
+ eq('', exec_lua('return result'))
+ end)
+
+ it('can input empty text with cancelreturn opt #18144', function()
+ feed(':lua vim.ui.input({ cancelreturn = "CANCEL" }, function(input) result = input end)<cr>')
+ feed('<cr>')
+ eq('', exec_lua('return result'))
+ end)
+
+ it('can return nil when aborted with ESC #18144', function()
+ feed(':lua result = "on_confirm not called"<cr>')
+ feed(':lua vim.ui.input({}, function(input) result = input end)<cr>')
+ feed('Inputted Text<esc>')
+ -- Note: When `result == nil`, exec_lua('returns result') returns vim.NIL
+ eq(true, exec_lua('return (nil == result)'))
+ end)
+
+ it('can return opts.cacelreturn when aborted with ESC with cancelreturn opt #18144', function()
+ feed(':lua result = "on_confirm not called"<cr>')
+ feed(':lua vim.ui.input({ cancelreturn = "CANCEL" }, function(input) result = input end)<cr>')
+ feed('Inputted Text<esc>')
+ eq('CANCEL', exec_lua('return result'))
+ end)
+
+ it('can return nil when interrupted with Ctrl-C #18144', function()
+ feed(':lua result = "on_confirm not called"<cr>')
+ feed(':lua vim.ui.input({}, function(input) result = input end)<cr>')
+ poke_eventloop() -- This is needed because Ctrl-C flushes input
+ feed('Inputted Text<c-c>')
+ eq(true, exec_lua('return (nil == result)'))
+ end)
+
+ it('can return the identical object when an arbitrary opts.cancelreturn object is given', function()
+ feed(':lua fn = function() return 42 end<CR>')
+ eq(42, exec_lua('return fn()'))
+ feed(':lua vim.ui.input({ cancelreturn = fn }, function(input) result = input end)<cr>')
+ feed('cancel<esc>')
+ eq(true, exec_lua('return (result == fn)'))
+ eq(42, exec_lua('return result()'))
+ end)
+
end)
end)
diff --git a/test/functional/plugin/health_spec.lua b/test/functional/plugin/health_spec.lua
index c970a03fcf..97d32313e5 100644
--- a/test/functional/plugin/health_spec.lua
+++ b/test/functional/plugin/health_spec.lua
@@ -29,7 +29,7 @@ describe(':checkhealth', function()
-- Do this after startup, otherwise it just breaks $VIMRUNTIME.
command("let $VIM='zub'")
command("checkhealth nvim")
- matches('ERROR: $VIM .* zub', curbuf_contents())
+ matches('ERROR $VIM .* zub', curbuf_contents())
end)
it('completions can be listed via getcompletion()', function()
clear()
@@ -55,21 +55,22 @@ describe('health.vim', function()
command("checkhealth full_render")
helpers.expect([[
+ ==============================================================================
full_render: health#full_render#check
- ========================================================================
- ## report 1
- - OK: life is fine
- - WARNING: no what installed
- - ADVICE:
- - pip what
- - make what
-
- ## report 2
- - INFO: stuff is stable
- - ERROR: why no hardcopy
- - ADVICE:
- - :help |:hardcopy|
- - :help |:TOhtml|
+
+ report 1 ~
+ - OK life is fine
+ - WARNING no what installed
+ - ADVICE:
+ - pip what
+ - make what
+
+ report 2 ~
+ - stuff is stable
+ - ERROR why no hardcopy
+ - ADVICE:
+ - :help |:hardcopy|
+ - :help |:TOhtml|
]])
end)
@@ -77,26 +78,29 @@ describe('health.vim', function()
command("checkhealth success1 success2 test_plug")
helpers.expect([[
+ ==============================================================================
success1: health#success1#check
- ========================================================================
- ## report 1
- - OK: everything is fine
- ## report 2
- - OK: nothing to see here
+ report 1 ~
+ - OK everything is fine
+
+ report 2 ~
+ - OK nothing to see here
+ ==============================================================================
success2: health#success2#check
- ========================================================================
- ## another 1
- - OK: ok
+ another 1 ~
+ - OK ok
+
+ ==============================================================================
test_plug: require("test_plug.health").check()
- ========================================================================
- ## report 1
- - OK: everything is fine
- ## report 2
- - OK: nothing to see here
+ report 1 ~
+ - OK everything is fine
+
+ report 2 ~
+ - OK nothing to see here
]])
end)
@@ -106,13 +110,14 @@ describe('health.vim', function()
-- and the Lua healthcheck is used instead.
helpers.expect([[
+ ==============================================================================
test_plug: require("test_plug.health").check()
- ========================================================================
- ## report 1
- - OK: everything is fine
- ## report 2
- - OK: nothing to see here
+ report 1 ~
+ - OK everything is fine
+
+ report 2 ~
+ - OK nothing to see here
]])
end)
@@ -120,13 +125,14 @@ describe('health.vim', function()
command("checkhealth test_plug.submodule")
helpers.expect([[
+ ==============================================================================
test_plug.submodule: require("test_plug.submodule.health").check()
- ========================================================================
- ## report 1
- - OK: everything is fine
- ## report 2
- - OK: nothing to see here
+ report 1 ~
+ - OK everything is fine
+
+ report 2 ~
+ - OK nothing to see here
]])
end)
@@ -137,30 +143,34 @@ describe('health.vim', function()
local received = table.concat(buf_lines, '\n', 1, #buf_lines - 5)
local expected = helpers.dedent([[
+ ==============================================================================
test_plug: require("test_plug.health").check()
- ========================================================================
- ## report 1
- - OK: everything is fine
- ## report 2
- - OK: nothing to see here
+ report 1 ~
+ - OK everything is fine
+
+ report 2 ~
+ - OK nothing to see here
+ ==============================================================================
test_plug.submodule: require("test_plug.submodule.health").check()
- ========================================================================
- ## report 1
- - OK: everything is fine
- ## report 2
- - OK: nothing to see here
+ report 1 ~
+ - OK everything is fine
+ report 2 ~
+ - OK nothing to see here
+
+ ==============================================================================
test_plug.submodule_empty: require("test_plug.submodule_empty.health").check()
- ========================================================================
- - ERROR: The healthcheck report for "test_plug.submodule_empty" plugin is empty.
+ - ERROR The healthcheck report for "test_plug.submodule_empty" plugin is empty.
+
+ ==============================================================================
test_plug.submodule_failed: require("test_plug.submodule_failed.health").check()
- ========================================================================
- - ERROR: Failed to run healthcheck for "test_plug.submodule_failed" plugin. Exception:
- function health#check, line 20]])
+
+ - ERROR Failed to run healthcheck for "test_plug.submodule_failed" plugin. Exception:
+ function health#check, line 25]])
eq(expected, received)
end)
@@ -168,11 +178,12 @@ describe('health.vim', function()
command("checkhealth broken")
helpers.expect([[
+ ==============================================================================
broken: health#broken#check
- ========================================================================
- - ERROR: Failed to run healthcheck for "broken" plugin. Exception:
- function health#check[20]..health#broken#check, line 1
- caused an error
+
+ - ERROR Failed to run healthcheck for "broken" plugin. Exception:
+ function health#check[25]..health#broken#check, line 1
+ caused an error
]])
end)
@@ -180,9 +191,10 @@ describe('health.vim', function()
command("checkhealth test_plug.submodule_empty")
helpers.expect([[
+ ==============================================================================
test_plug.submodule_empty: require("test_plug.submodule_empty.health").check()
- ========================================================================
- - ERROR: The healthcheck report for "test_plug.submodule_empty" plugin is empty.
+
+ - ERROR The healthcheck report for "test_plug.submodule_empty" plugin is empty.
]])
end)
@@ -197,38 +209,38 @@ describe('health.vim', function()
local expected = global_helpers.dedent([[
+ ==============================================================================
test_plug.submodule_failed: require("test_plug.submodule_failed.health").check()
- ========================================================================
- - ERROR: Failed to run healthcheck for "test_plug.submodule_failed" plugin. Exception:
- function health#check, line 20]])
+
+ - ERROR Failed to run healthcheck for "test_plug.submodule_failed" plugin. Exception:
+ function health#check, line 25]])
eq(expected, received)
end)
it("highlights OK, ERROR", function()
- local screen = Screen.new(72, 10)
+ local screen = Screen.new(50, 12)
screen:attach()
screen:set_default_attr_ids({
Ok = { foreground = Screen.colors.Grey3, background = 6291200 },
Error = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
- Heading = { bold=true, foreground=Screen.colors.Magenta },
- Heading2 = { foreground = Screen.colors.SlateBlue },
- Bar = { foreground = 0x6a0dad },
- Bullet = { bold=true, foreground=Screen.colors.Brown },
+ Heading = { foreground = tonumber('0x6a0dad') },
+ Bar = { foreground = Screen.colors.LightGrey, background = Screen.colors.DarkGrey },
})
command("checkhealth foo success1")
- command("1tabclose")
- command("set laststatus=0")
+ command("set nowrap laststatus=0")
screen:expect{grid=[[
- ^ |
- {Heading:foo: } |
- {Bar:========================================================================}|
- {Bullet: -} {Error:ERROR}: No healthcheck found for "foo" plugin. |
- |
- {Heading:success1: health#success1#check} |
- {Bar:========================================================================}|
- {Heading2:## }{Heading:report 1} |
- {Bullet: -} {Ok:OK}: everything is fine |
- |
+ ^ |
+ {Bar:──────────────────────────────────────────────────}|
+ {Heading:foo: } |
+ |
+ - {Error:ERROR} No healthcheck found for "foo" plugin. |
+ |
+ {Bar:──────────────────────────────────────────────────}|
+ {Heading:success1: health#success1#check} |
+ |
+ {Heading:report 1} |
+ - {Ok:OK} everything is fine |
+ |
]]}
end)
@@ -237,9 +249,10 @@ describe('health.vim', function()
-- luacheck: ignore 613
helpers.expect([[
+ ==============================================================================
non_existent_healthcheck:
- ========================================================================
- - ERROR: No healthcheck found for "non_existent_healthcheck" plugin.
+
+ - ERROR No healthcheck found for "non_existent_healthcheck" plugin.
]])
end)
diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua
index 9d10f43ec6..46d08897e0 100644
--- a/test/functional/terminal/buffer_spec.lua
+++ b/test/functional/terminal/buffer_spec.lua
@@ -410,6 +410,14 @@ describe('on_lines does not emit out-of-bounds line indexes when', function()
feed_command('bdelete!')
eq('', exec_lua([[return _G.cb_error]]))
end)
+
+ it('runs TextChangedT event', function()
+ meths.set_var('called', 0)
+ command('autocmd TextChangedT * ++once let g:called = 1')
+ feed_command('terminal')
+ feed('iaa')
+ eq(1, meths.get_var('called'))
+ end)
end)
it('terminal truncates number of composing characters to 5', function()
diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua
index 5b62f5b3e1..489c33d8b1 100644
--- a/test/functional/ui/decorations_spec.lua
+++ b/test/functional/ui/decorations_spec.lua
@@ -176,7 +176,13 @@ describe('decorations providers', function()
beamtrace = {}
local function on_do(kind, ...)
if kind == 'win' or kind == 'spell' then
- a.nvim_buf_set_extmark(0, ns, 0, 0, { end_row = 2, end_col = 23, spell = true, ephemeral = true })
+ a.nvim_buf_set_extmark(0, ns, 0, 0, {
+ end_row = 2,
+ end_col = 23,
+ spell = true,
+ priority = 20,
+ ephemeral = true
+ })
end
table.insert(beamtrace, {kind, ...})
end
@@ -234,6 +240,36 @@ describe('decorations providers', function()
{1:~ }|
|
]]}
+
+ -- spell=false with lower priority doesn't disable spell
+ local ns = meths.create_namespace "spell"
+ local id = helpers.curbufmeths.set_extmark(ns, 0, 0, { priority = 30, end_row = 2, end_col = 23, spell = false })
+
+ screen:expect{grid=[[
+ I am well written text. |
+ i am not capitalized. |
+ I am a ^speling mistakke. |
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ -- spell=false with higher priority does disable spell
+ helpers.curbufmeths.set_extmark(ns, 0, 0, { id = id, priority = 10, end_row = 2, end_col = 23, spell = false })
+
+ screen:expect{grid=[[
+ I am well written text. |
+ {15:i} am not capitalized. |
+ I am a {16:^speling} {16:mistakke}. |
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
end)
it('can predefine highlights', function()
diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua
index 504a38d591..173d422334 100644
--- a/test/functional/ui/highlight_spec.lua
+++ b/test/functional/ui/highlight_spec.lua
@@ -1048,6 +1048,7 @@ describe('CursorLine and CursorLineNr highlights', function()
]])
end)
+ -- oldtest: Test_cursorline_after_yank()
it('always updated. vim-patch:8.1.0849', function()
local screen = Screen.new(50,5)
screen:set_default_attr_ids({
@@ -1081,6 +1082,7 @@ describe('CursorLine and CursorLineNr highlights', function()
]])
end)
+ -- oldtest: Test_cursorline_with_visualmode()
it('with visual area. vim-patch:8.1.1001', function()
local screen = Screen.new(50,5)
screen:set_default_attr_ids({
@@ -1108,6 +1110,7 @@ describe('CursorLine and CursorLineNr highlights', function()
]])
end)
+ -- oldtest: Test_cursorline_callback()
it('is updated if cursor is moved up from timer vim-patch:8.2.4591', function()
local screen = Screen.new(50, 8)
screen:set_default_attr_ids({
@@ -1237,6 +1240,7 @@ describe('CursorLine and CursorLineNr highlights', function()
})
end)
+ -- oldtest: Test_diff_with_cursorline_number()
it('CursorLineNr shows correctly just below filler lines', function()
local screen = Screen.new(50,12)
screen:set_default_attr_ids({
@@ -1357,6 +1361,7 @@ describe('CursorColumn highlight', function()
]])
end)
+ -- oldtest: Test_cursorcolumn_callback()
it('is updated if cursor is moved from timer', function()
exec([[
call setline(1, ['aaaaa', 'bbbbb', 'ccccc', 'ddddd'])
@@ -1412,6 +1417,7 @@ describe('ColorColumn highlight', function()
screen:attach()
end)
+ -- oldtest: Test_colorcolumn()
it('when entering a buffer vim-patch:8.1.2073', function()
exec([[
set nohidden
@@ -1443,6 +1449,7 @@ describe('ColorColumn highlight', function()
]])
end)
+ -- oldtest: Test_colorcolumn_bri()
it("in 'breakindent' vim-patch:8.2.1689", function()
exec([[
call setline(1, 'The quick brown fox jumped over the lazy dogs')
@@ -1467,6 +1474,7 @@ describe('ColorColumn highlight', function()
]])
end)
+ -- oldtest: Test_colorcolumn_sbr()
it("in 'showbreak' vim-patch:8.2.1689", function()
exec([[
call setline(1, 'The quick brown fox jumped over the lazy dogs')
@@ -1686,6 +1694,7 @@ describe("'number' and 'relativenumber' highlight", function()
]])
end)
+ -- oldtest: Test_relativenumber_callback()
it('relative number highlight is updated if cursor is moved from timer', function()
local screen = Screen.new(50, 8)
screen:set_default_attr_ids({
diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua
index a042291b54..60b538eee5 100644
--- a/test/functional/ui/messages_spec.lua
+++ b/test/functional/ui/messages_spec.lua
@@ -10,9 +10,11 @@ local async_meths = helpers.async_meths
local test_build_dir = helpers.test_build_dir
local nvim_prog = helpers.nvim_prog
local iswin = helpers.iswin
+local exec = helpers.exec
local exc_exec = helpers.exc_exec
local exec_lua = helpers.exec_lua
local poke_eventloop = helpers.poke_eventloop
+local assert_alive = helpers.assert_alive
describe('ui/ext_messages', function()
local screen
@@ -1234,6 +1236,45 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim
bar^ |
]])
end)
+
+ it('consecutive calls to win_move_statusline() work after multiline message #21014',function()
+ async_meths.exec([[
+ echo "\n"
+ call win_move_statusline(0, -4)
+ call win_move_statusline(0, 4)
+ ]], false)
+ screen:expect([[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {3: }|
+ |
+ {4:Press ENTER or type command to continue}^ |
+ ]])
+ feed('<CR>')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]])
+ eq(1, meths.get_option('cmdheight'))
+ end)
+end)
+
+it('calling screenstring() after redrawing between messages without UI #20999', function()
+ clear()
+ exec([[
+ echo repeat('a', 100)
+ redraw
+ echo "\n"
+ call screenstring(1, 1)
+ ]])
+ assert_alive()
end)
describe('ui/ext_messages', function()
diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua
index 33e201eb68..7e81d1a577 100644
--- a/test/functional/ui/popupmenu_spec.lua
+++ b/test/functional/ui/popupmenu_spec.lua
@@ -967,6 +967,7 @@ describe('builtin popupmenu', function()
[4] = {bold = true, reverse = true},
[5] = {bold = true, foreground = Screen.colors.SeaGreen},
[6] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
+ [7] = {background = Screen.colors.Yellow}, -- Search
})
end)
@@ -3037,6 +3038,156 @@ describe('builtin popupmenu', function()
eq(false, screen.options.mousemoveevent)
eq('bar', meths.get_var('menustr'))
end)
+
+ -- oldtest: Test_popup_command_dump()
+ it(':popup command', function()
+ exec([[
+ func ChangeMenu()
+ aunmenu PopUp.&Paste
+ nnoremenu 1.40 PopUp.&Paste :echomsg "pasted"<CR>
+ echomsg 'changed'
+ return "\<Ignore>"
+ endfunc
+
+ let lines =<< trim END
+ one two three four five
+ and one two Xthree four five
+ one more two three four five
+ END
+ call setline(1, lines)
+
+ aunmenu *
+ source $VIMRUNTIME/menu.vim
+ ]])
+ feed('/X<CR>:popup PopUp<CR>')
+ screen:expect([[
+ one two three four five |
+ and one two {7:^X}three four five |
+ one more tw{n: Undo } |
+ {1:~ }{n: }{1: }|
+ {1:~ }{n: Paste }{1: }|
+ {1:~ }{n: }{1: }|
+ {1:~ }{n: Select Word }{1: }|
+ {1:~ }{n: Select Sentence }{1: }|
+ {1:~ }{n: Select Paragraph }{1: }|
+ {1:~ }{n: Select Line }{1: }|
+ {1:~ }{n: Select Block }{1: }|
+ {1:~ }{n: Select All }{1: }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ :popup PopUp |
+ ]])
+
+ -- go to the Paste entry in the menu
+ feed('jj')
+ screen:expect([[
+ one two three four five |
+ and one two {7:^X}three four five |
+ one more tw{n: Undo } |
+ {1:~ }{n: }{1: }|
+ {1:~ }{s: Paste }{1: }|
+ {1:~ }{n: }{1: }|
+ {1:~ }{n: Select Word }{1: }|
+ {1:~ }{n: Select Sentence }{1: }|
+ {1:~ }{n: Select Paragraph }{1: }|
+ {1:~ }{n: Select Line }{1: }|
+ {1:~ }{n: Select Block }{1: }|
+ {1:~ }{n: Select All }{1: }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ :popup PopUp |
+ ]])
+
+ -- Select a word
+ feed('j')
+ screen:expect([[
+ one two three four five |
+ and one two {7:^X}three four five |
+ one more tw{n: Undo } |
+ {1:~ }{n: }{1: }|
+ {1:~ }{n: Paste }{1: }|
+ {1:~ }{n: }{1: }|
+ {1:~ }{s: Select Word }{1: }|
+ {1:~ }{n: Select Sentence }{1: }|
+ {1:~ }{n: Select Paragraph }{1: }|
+ {1:~ }{n: Select Line }{1: }|
+ {1:~ }{n: Select Block }{1: }|
+ {1:~ }{n: Select All }{1: }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ :popup PopUp |
+ ]])
+
+ feed('<Esc>')
+
+ -- 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.
+ command('nnoremap <expr> <F2> ChangeMenu()')
+ feed('/X<CR>:popup PopUp<CR><F2>')
+ screen:expect([[
+ one two three four five |
+ and one two {7:^X}three four five |
+ one more tw{n: Undo } |
+ {1:~ }{n: }{1: }|
+ {1:~ }{n: Paste }{1: }|
+ {1:~ }{n: }{1: }|
+ {1:~ }{n: Select Word }{1: }|
+ {1:~ }{n: Select Sentence }{1: }|
+ {1:~ }{n: Select Paragraph }{1: }|
+ {1:~ }{n: Select Line }{1: }|
+ {1:~ }{n: Select Block }{1: }|
+ {1:~ }{n: Select All }{1: }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ changed |
+ ]])
+
+ -- Select the Paste entry, executes the changed menu item.
+ feed('jj<CR>')
+ screen:expect([[
+ one two three four five |
+ and one two {7:^X}three four five |
+ one more two three four five |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ pasted |
+ ]])
+ end)
end)
describe('builtin popupmenu with ui/ext_multigrid', function()
diff --git a/test/functional/vimscript/writefile_spec.lua b/test/functional/vimscript/writefile_spec.lua
index 5f693249a9..8c8da9dc88 100644
--- a/test/functional/vimscript/writefile_spec.lua
+++ b/test/functional/vimscript/writefile_spec.lua
@@ -111,6 +111,26 @@ describe('writefile()', function()
pcall_err(command, ('call writefile([42], %s)'):format(ddname_tail)))
end)
+ it('writefile(..., "p") creates missing parent directories', function()
+ os.remove(dname)
+ eq(nil, read_file(dfname))
+ eq(0, funcs.writefile({'abc', 'def', 'ghi'}, dfname, 'p'))
+ eq('abc\ndef\nghi\n', read_file(dfname))
+ os.remove(dfname)
+ os.remove(dname)
+ eq(nil, read_file(dfname))
+ eq(0, funcs.writefile({'\na\nb\n'}, dfname, 'pb'))
+ eq('\0a\0b\0', read_file(dfname))
+ os.remove(dfname)
+ os.remove(dname)
+ eq('Vim(call):E32: No file name',
+ pcall_err(command, ('call writefile([], "%s", "p")'):format(dfname .. '.d/')))
+ eq(('Vim(call):E482: Can\'t open file ./ for writing: illegal operation on a directory'),
+ pcall_err(command, 'call writefile([], "./", "p")'))
+ eq(('Vim(call):E482: Can\'t open file . for writing: illegal operation on a directory'),
+ pcall_err(command, 'call writefile([], ".", "p")'))
+ end)
+
it('errors out with invalid arguments', function()
write_file(fname, 'TEST')
eq('Vim(call):E119: Not enough arguments for function: writefile',
diff --git a/test/unit/buffer_spec.lua b/test/unit/buffer_spec.lua
index 5dccc2f5a2..2611e7ca7c 100644
--- a/test/unit/buffer_spec.lua
+++ b/test/unit/buffer_spec.lua
@@ -233,7 +233,8 @@ describe('buffer functions', function()
output_buffer,
buffer_byte_size,
to_cstr(pat),
- false,
+ NULL,
+ 0,
fillchar,
maximum_cell_count,
NULL,