aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.gitattributes1
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.yml6
-rw-r--r--CONTRIBUTING.md10
-rw-r--r--ci/build.ps12
-rw-r--r--runtime/autoload/health.vim125
-rw-r--r--runtime/autoload/health/lsp.vim5
-rw-r--r--runtime/autoload/health/treesitter.vim5
-rw-r--r--runtime/autoload/netrw.vim3
-rw-r--r--runtime/doc/api.txt574
-rw-r--r--runtime/doc/autocmd.txt7
-rw-r--r--runtime/doc/develop.txt2
-rw-r--r--runtime/doc/diagnostic.txt60
-rw-r--r--runtime/doc/editing.txt3
-rw-r--r--runtime/doc/eval.txt41
-rw-r--r--runtime/doc/filetype.txt2
-rw-r--r--runtime/doc/helphelp.txt12
-rw-r--r--runtime/doc/intro.txt3
-rw-r--r--runtime/doc/lsp.txt36
-rw-r--r--runtime/doc/lua.txt68
-rw-r--r--runtime/doc/mbyte.txt30
-rw-r--r--runtime/doc/nvim_terminal_emulator.txt6
-rw-r--r--runtime/doc/options.txt4
-rw-r--r--runtime/doc/pi_health.txt153
-rw-r--r--runtime/doc/print.txt2
-rw-r--r--runtime/doc/starting.txt3
-rw-r--r--runtime/doc/treesitter.txt8
-rw-r--r--runtime/doc/usr_41.txt2
-rw-r--r--runtime/filetype.vim20
-rw-r--r--runtime/ftplugin/nginx.vim6
-rw-r--r--runtime/ftplugin/spec.vim4
-rw-r--r--runtime/indent/cdl.vim3
-rw-r--r--runtime/indent/cobol.vim3
-rw-r--r--runtime/indent/config.vim13
-rw-r--r--runtime/indent/css.vim12
-rw-r--r--runtime/indent/d.vim4
-rw-r--r--runtime/indent/dtd.vim9
-rw-r--r--runtime/indent/dylan.vim3
-rw-r--r--runtime/indent/elm.vim4
-rw-r--r--runtime/indent/eterm.vim9
-rw-r--r--runtime/indent/framescript.vim9
-rw-r--r--runtime/indent/idlang.vim5
-rw-r--r--runtime/indent/ld.vim9
-rw-r--r--runtime/indent/mail.vim4
-rw-r--r--runtime/indent/make.vim9
-rw-r--r--runtime/indent/matlab.vim2
-rw-r--r--runtime/indent/mma.vim11
-rw-r--r--runtime/indent/nginx.vim17
-rw-r--r--runtime/indent/occam.vim3
-rw-r--r--runtime/indent/pascal.vim15
-rw-r--r--runtime/indent/postscr.vim7
-rw-r--r--runtime/indent/prolog.vim7
-rw-r--r--runtime/indent/python.vim4
-rw-r--r--runtime/indent/readline.vim9
-rw-r--r--runtime/indent/sdl.vim4
-rw-r--r--runtime/indent/tcl.vim8
-rw-r--r--runtime/indent/tcsh.vim5
-rw-r--r--runtime/indent/zimbu.vim4
-rw-r--r--runtime/lua/health.lua23
-rw-r--r--runtime/lua/vim/diagnostic.lua39
-rw-r--r--runtime/lua/vim/lsp/health.lua2
-rw-r--r--runtime/lua/vim/lsp/rpc.lua38
-rw-r--r--runtime/lua/vim/lsp/util.lua11
-rw-r--r--runtime/lua/vim/shared.lua46
-rw-r--r--runtime/lua/vim/treesitter/health.lua2
-rw-r--r--runtime/plugin/diagnostic.vim26
-rw-r--r--runtime/syntax/8th.vim535
-rw-r--r--runtime/syntax/chicken.vim4
-rw-r--r--runtime/syntax/nginx.vim2307
-rw-r--r--runtime/syntax/sml.vim7
-rw-r--r--runtime/syntax/tcl.vim4
-rw-r--r--runtime/syntax/tcsh.vim5
-rw-r--r--runtime/syntax/typescriptcommon.vim5
-rw-r--r--runtime/syntax/xpm.vim7
-rwxr-xr-xscripts/gen_vimdoc.py1
-rwxr-xr-xscripts/pvscheck.sh1
-rwxr-xr-xscripts/release.sh4
-rwxr-xr-xscripts/vim-patch.sh43
-rw-r--r--src/cjson/lua_cjson.c60
-rwxr-xr-xsrc/clint.py1
-rw-r--r--src/mpack/conv.c1
-rw-r--r--src/mpack/lmpack.c2
-rw-r--r--src/nvim/CMakeLists.txt13
-rw-r--r--src/nvim/api/buffer.c458
-rw-r--r--src/nvim/api/deprecated.c14
-rw-r--r--src/nvim/api/keysets.lua52
-rw-r--r--src/nvim/api/private/defs.h10
-rw-r--r--src/nvim/api/private/dispatch.c1
-rw-r--r--src/nvim/api/private/helpers.c504
-rw-r--r--src/nvim/api/private/helpers.h6
-rw-r--r--src/nvim/api/ui.c3
-rw-r--r--src/nvim/api/vim.c281
-rw-r--r--src/nvim/api/win_config.c639
-rw-r--r--src/nvim/api/win_config.h11
-rw-r--r--src/nvim/api/window.c111
-rw-r--r--src/nvim/autocmd.c10
-rw-r--r--src/nvim/buffer.c2
-rw-r--r--src/nvim/charset.c2
-rw-r--r--src/nvim/debugger.c2
-rw-r--r--src/nvim/decoration.c10
-rw-r--r--src/nvim/diff.c2
-rw-r--r--src/nvim/edit.c4
-rw-r--r--src/nvim/eval.c30
-rw-r--r--src/nvim/eval/encode.c5
-rw-r--r--src/nvim/eval/funcs.c6
-rw-r--r--src/nvim/eval/typval.c2
-rw-r--r--src/nvim/ex_getln.c86
-rw-r--r--src/nvim/generators/c_grammar.lua2
-rw-r--r--src/nvim/generators/gen_api_dispatch.lua63
-rwxr-xr-xsrc/nvim/generators/gen_declarations.lua2
-rw-r--r--src/nvim/generators/gen_keysets.lua67
-rw-r--r--src/nvim/generators/hashy.lua122
-rw-r--r--src/nvim/getchar.c28
-rw-r--r--src/nvim/getchar.h2
-rw-r--r--src/nvim/hardcopy.c8
-rw-r--r--src/nvim/if_cscope.c447
-rw-r--r--src/nvim/lua/converter.c22
-rw-r--r--src/nvim/lua/executor.c2
-rw-r--r--src/nvim/lua/vim.lua1
-rw-r--r--src/nvim/lua/xdiff.c8
-rw-r--r--src/nvim/main.c32
-rw-r--r--src/nvim/mark.c9
-rw-r--r--src/nvim/menu.c46
-rw-r--r--src/nvim/message.c2
-rw-r--r--src/nvim/mouse.c19
-rw-r--r--src/nvim/move.c2
-rw-r--r--src/nvim/msgpack_rpc/helpers.c1
-rw-r--r--src/nvim/os/fs.c2
-rw-r--r--src/nvim/os/os_win_console.c26
-rw-r--r--src/nvim/quickfix.c2
-rw-r--r--src/nvim/runtime.c184
-rw-r--r--src/nvim/screen.c4
-rw-r--r--src/nvim/shada.c89
-rw-r--r--src/nvim/spell.c2
-rw-r--r--src/nvim/state.c5
-rw-r--r--src/nvim/strings.c916
-rw-r--r--src/nvim/syntax.c20
-rw-r--r--src/nvim/tag.c1559
-rw-r--r--src/nvim/terminal.c687
-rw-r--r--src/nvim/testdir/test_filetype.vim5
-rw-r--r--src/nvim/testdir/test_functions.vim38
-rw-r--r--src/nvim/testdir/test_method.vim3
-rw-r--r--src/nvim/testdir/test_popup.vim4
-rw-r--r--src/nvim/tui/tui.c28
-rw-r--r--src/nvim/ugrid.c9
-rw-r--r--src/nvim/ui.c72
-rw-r--r--src/nvim/ui_bridge.c25
-rw-r--r--src/nvim/ui_compositor.c61
-rw-r--r--src/nvim/undo.c630
-rw-r--r--src/nvim/version.c34
-rw-r--r--src/nvim/window.c8
-rw-r--r--src/uncrustify.cfg15
-rw-r--r--src/xdiff/xdiffi.c3
-rw-r--r--src/xdiff/xemit.c3
-rw-r--r--src/xdiff/xhistogram.c3
-rw-r--r--src/xdiff/xpatience.c3
-rw-r--r--src/xdiff/xprepare.c3
-rw-r--r--src/xdiff/xutils.c3
-rw-r--r--test/config/paths.lua.in1
-rw-r--r--test/functional/api/buffer_spec.lua55
-rw-r--r--test/functional/api/command_spec.lua2
-rw-r--r--test/functional/api/keymap_spec.lua12
-rw-r--r--test/functional/api/vim_spec.lua74
-rw-r--r--test/functional/core/startup_spec.lua40
-rw-r--r--test/functional/editor/meta_key_spec.lua15
-rw-r--r--test/functional/fixtures/autoload/health/full_render.vim8
-rw-r--r--test/functional/fixtures/lua/test_plug/autoload/health/test_plug.vim3
-rw-r--r--test/functional/fixtures/lua/test_plug/health/init.lua11
-rw-r--r--test/functional/fixtures/lua/test_plug/submodule/health.lua11
-rw-r--r--test/functional/fixtures/lua/test_plug/submodule_failed/health.lua12
-rw-r--r--test/functional/lua/buffer_updates_spec.lua13
-rw-r--r--test/functional/lua/diagnostic_spec.lua51
-rw-r--r--test/functional/lua/vim_spec.lua38
-rw-r--r--test/functional/plugin/health_spec.lua153
-rw-r--r--test/functional/plugin/lsp_spec.lua137
-rw-r--r--test/functional/terminal/buffer_spec.lua20
-rw-r--r--test/functional/ui/float_spec.lua443
-rw-r--r--test/functional/ui/mouse_spec.lua63
-rw-r--r--third-party/CMakeLists.txt10
178 files changed, 8890 insertions, 4446 deletions
diff --git a/.gitattributes b/.gitattributes
index 1deb4dea49..e09a918303 100755
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,7 +1,6 @@
*.h linguist-language=C
src/nvim/testdir/test42.in diff
.github/ export-ignore
-ci/ export-ignore
.travis.yml export-ignore
codecov.yml export-ignore
.builds/ export-ignore
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index fa8d05f6b5..11f27dde21 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -36,7 +36,7 @@ body:
- type: input
attributes:
label: "$TERM environment variable"
- placeholder: "echo $TERM"
+ placeholder: "xterm-256color"
validations:
required: true
@@ -52,11 +52,11 @@ body:
attributes:
label: "How to reproduce the issue"
description: |
- - Steps to reproduce using `nvim -u NORC` or `nvim -u NONE` (try both).
+ - Steps to reproduce using `nvim --clean` ("factory defaults").
- For build failures: list the exact steps including CMake flags (if any).
- For shell-related problems: try `env -i TERM=ansi-256color "$(which nvim)"`.
placeholder: |
- nvim -u NONE
+ nvim --clean
:edit foo
yiwp
validations:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 88d2989f13..e9c1173007 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -19,6 +19,7 @@ Reporting problems
- [Check the FAQ][wiki-faq].
- [Search existing issues][github-issues] (including closed!)
- Update Neovim to the latest version to see if your problem persists.
+- Try to reproduce with `nvim --clean` ("factory defaults").
- [Bisect](https://neovim.io/doc/user/starting.html#bisect) your config: disable plugins incrementally, to narrow down the cause of the issue.
- [Bisect][git-bisect] Neovim's source code to find the cause of a regression, if you can. This is _extremely_ helpful.
- When reporting a crash, [include a stacktrace](https://github.com/neovim/neovim/wiki/FAQ#backtrace-linux).
@@ -161,7 +162,7 @@ see potential bugs found by [PVS Studio](https://www.viva64.com/en/pvs-studio/).
- Use this format for commit messages (where `{id}` is the PVS warning-id)):
```
- PVS/V{id}: {description}
+ fix(PVS/V{id}): {description}
```
- Search the Neovim commit history to find examples:
```
@@ -177,7 +178,7 @@ master build. To view the defects, just request access; you will be approved.
- Use this format for commit messages (where `{id}` is the CID (Coverity ID);
([example](https://github.com/neovim/neovim/pull/804))):
```
- coverity/{id}: {description}
+ fix(coverity/{id}): {description}
```
- Search the Neovim commit history to find examples:
```
@@ -220,10 +221,11 @@ You can lint a single file (but this will _not_ exclude legacy errors):
- Style rules are (mostly) defined by `src/uncrustify.cfg` which tries to match
the [style-guide]. To use the Nvim `gq` command with `uncrustify`:
```
- if !empty(findfile('src/.uncrustify', ';'))
- setlocal formatprg=uncrustify\ -q\ -c\ src/uncrustify.cfg\ --replace\ --no-backup
+ if !empty(findfile('src/uncrustify.cfg', ';'))
+ setlocal formatprg=uncrustify\ -q\ -l\ C\ -c\ src/uncrustify.cfg\ --no-backup
endif
```
+ The required version of `uncrustify` is specified in `uncrustify.cfg`.
- There is also `.clang-format` which has drifted from the [style-guide], but
is available for reference. To use the Nvim `gq` command with `clang-format`:
```
diff --git a/ci/build.ps1 b/ci/build.ps1
index 53e4328e02..8876ac31ef 100644
--- a/ci/build.ps1
+++ b/ci/build.ps1
@@ -72,7 +72,7 @@ if ($compiler -eq 'MINGW') {
& C:\msys64\usr\bin\mkdir -p /var/cache/pacman/pkg
# Build third-party dependencies
- C:\msys64\usr\bin\bash -lc "pacman --verbose --noconfirm -Su" ; exitIfFailed
+ C:\msys64\usr\bin\bash -lc "pacman --verbose --noconfirm -Syu" ; exitIfFailed
C:\msys64\usr\bin\bash -lc "pacman --verbose --noconfirm --needed -S $mingwPackages" ; exitIfFailed
}
elseif ($compiler -eq 'MSVC') {
diff --git a/runtime/autoload/health.vim b/runtime/autoload/health.vim
index 0f7983f175..579db62cb8 100644
--- a/runtime/autoload/health.vim
+++ b/runtime/autoload/health.vim
@@ -26,8 +26,8 @@ endfunction
" Runs all discovered healthchecks if a:plugin_names is empty.
function! health#check(plugin_names) abort
let healthchecks = empty(a:plugin_names)
- \ ? s:discover_health_checks()
- \ : s:to_fn_names(a:plugin_names)
+ \ ? s:discover_healthchecks()
+ \ : s:get_healthcheck(a:plugin_names)
tabnew
setlocal wrap breakindent linebreak
@@ -41,25 +41,29 @@ function! health#check(plugin_names) abort
call setline(1, 'ERROR: No healthchecks found.')
else
redraw|echo 'Running healthchecks...'
- for c in healthchecks
- let output = ''
- call append('$', split(printf("\n%s\n%s", c, repeat('=',72)), "\n"))
+ for name in sort(keys(healthchecks))
+ let [func, type] = healthchecks[name]
+ let s:output = []
try
- let output = "\n\n".execute('call '.c.'()')
+ if func == ''
+ throw 'healthcheck_not_found'
+ endif
+ eval type == 'v' ? call(func, []) : luaeval(func)
catch
- if v:exception =~# '^Vim\%((\a\+)\)\=:E117.*\V'.c
- let output = execute(
- \ 'call health#report_error(''No healthcheck found for "'
- \ .s:to_plugin_name(c)
- \ .'" plugin.'')')
+ let s:output = [] " Clear the output
+ if v:exception =~# 'healthcheck_not_found'
+ call health#report_error('No healthcheck found for "'.name.'" plugin.')
else
- let output = execute(
- \ 'call health#report_error(''Failed to run healthcheck for "'
- \ .s:to_plugin_name(c)
- \ .'" plugin. Exception:''."\n".v:throwpoint."\n".v:exception)')
+ call health#report_error(printf(
+ \ "Failed to run healthcheck for \"%s\" plugin. Exception:\n%s\n%s",
+ \ name, v:throwpoint, v:exception))
endif
endtry
- call append('$', split(output, "\n") + [''])
+ let header = [name. ': ' . func, repeat('=', 72)]
+ " 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 + ['']
+ call append('$', s:output)
redraw
endfor
endif
@@ -71,9 +75,13 @@ function! health#check(plugin_names) abort
redraw|echo ''
endfunction
+function! s:collect_output(output)
+ let s:output += split(a:output, "\n", 1)
+endfunction
+
" Starts a new report.
function! health#report_start(name) abort
- echo "\n## " . a:name
+ call s:collect_output("\n## " . a:name)
endfunction
" Indents lines *except* line 1 of a string if it contains newlines.
@@ -119,21 +127,21 @@ endfunction " }}}
" Use {msg} to report information in the current section
function! health#report_info(msg) abort " {{{
- echo s:format_report_message('INFO', a:msg)
+ call s:collect_output(s:format_report_message('INFO', a:msg))
endfunction " }}}
" Reports a successful healthcheck.
function! health#report_ok(msg) abort " {{{
- echo s:format_report_message('OK', a:msg)
+ call s:collect_output(s:format_report_message('OK', a:msg))
endfunction " }}}
" Reports a health warning.
" a:1: Optional advice (string or list)
function! health#report_warn(msg, ...) abort " {{{
if a:0 > 0
- echo s:format_report_message('WARNING', a:msg, a:1)
+ call s:collect_output(s:format_report_message('WARNING', a:msg, a:1))
else
- echo s:format_report_message('WARNING', a:msg)
+ call s:collect_output(s:format_report_message('WARNING', a:msg))
endif
endfunction " }}}
@@ -141,37 +149,74 @@ endfunction " }}}
" a:1: Optional advice (string or list)
function! health#report_error(msg, ...) abort " {{{
if a:0 > 0
- echo s:format_report_message('ERROR', a:msg, a:1)
+ call s:collect_output(s:format_report_message('ERROR', a:msg, a:1))
else
- echo s:format_report_message('ERROR', a:msg)
+ call s:collect_output(s:format_report_message('ERROR', a:msg))
endif
endfunction " }}}
-function! s:filepath_to_function(name) abort
- return substitute(substitute(substitute(a:name, '.*autoload[\/]', '', ''),
- \ '\.vim', '#check', ''), '[\/]', '#', 'g')
+" From a path return a list [{name}, {func}, {type}] representing a healthcheck
+function! s:filepath_to_healthcheck(path) abort
+ if a:path =~# 'vim$'
+ let name = matchstr(a:path, '\zs[^\/]*\ze\.vim$')
+ let func = 'health#'.name.'#check'
+ let type = 'v'
+ else
+ let base_path = substitute(a:path,
+ \ '.*lua[\/]\(.\{-}\)[\/]health\([\/]init\)\?\.lua$',
+ \ '\1', '')
+ let name = substitute(base_path, '[\/]', '.', 'g')
+ let func = 'require("'.name.'.health").check()'
+ let type = 'l'
+ endif
+ return [name, func, type]
+endfunction
+
+function! s:discover_healthchecks() abort
+ return s:get_healthcheck('*')
endfunction
-function! s:discover_health_checks() abort
- let healthchecks = globpath(&runtimepath, 'autoload/health/*.vim', 1, 1)
- let healthchecks = map(healthchecks, '<SID>filepath_to_function(v:val)')
+" Returns Dictionary {name: [func, type], ..} representing healthchecks
+function! s:get_healthcheck(plugin_names) abort
+ let health_list = s:get_healthcheck_list(a:plugin_names)
+ let healthchecks = {}
+ for c in health_list
+ let name = c[0]
+ let existent = get(healthchecks, name, [])
+ " If an entry with the same name exists and is from vim, prefer Lua so
+ " overwrite it.
+ if existent != []
+ if existent[1] == "v"
+ let healthchecks[name] = c[1:]
+ else
+ continue
+ endif
+ else
+ let healthchecks[name] = c[1:]
+ endif
+ endfor
return healthchecks
endfunction
-" Translates a list of plugin names to healthcheck function names.
-function! s:to_fn_names(plugin_names) abort
+" Returns list of lists [ [{name}, {func}, {type}] ] representing healthchecks
+function! s:get_healthcheck_list(plugin_names) abort
let healthchecks = []
- let plugin_names = type('') ==# type(a:plugin_names)
- \ ? split(a:plugin_names, '', v:false)
+ let plugin_names = type('') == type(a:plugin_names)
+ \ ? split(a:plugin_names, ' ', v:false)
\ : a:plugin_names
for p in plugin_names
- call add(healthchecks, 'health#'.p.'#check')
+ " support vim/lsp/health{/init/}.lua as :checkhealth vim.lsp
+ let p = substitute(p, '\.', '/', 'g')
+ let p = substitute(p, '*$', '**', 'g') " find all submodule e.g vim*
+ let paths = nvim_get_runtime_file('autoload/health/'.p.'.vim', v:true)
+ \ + nvim_get_runtime_file('lua/**/'.p.'/health/init.lua', v:true)
+ \ + nvim_get_runtime_file('lua/**/'.p.'/health.lua', v:true)
+ if len(paths) == 0
+ let healthchecks += [[p, '', '']] " healthchek not found
+ else
+ let healthchecks += map(uniq(sort(paths)),
+ \'<SID>filepath_to_healthcheck(v:val)')
+ end
endfor
return healthchecks
endfunction
-
-" Extracts 'foo' from 'health#foo#check'.
-function! s:to_plugin_name(fn_name) abort
- return substitute(a:fn_name,
- \ '\v.*health\#(.+)\#check.*', '\1', '')
-endfunction
diff --git a/runtime/autoload/health/lsp.vim b/runtime/autoload/health/lsp.vim
deleted file mode 100644
index 2d2ba91cdf..0000000000
--- a/runtime/autoload/health/lsp.vim
+++ /dev/null
@@ -1,5 +0,0 @@
-function! health#lsp#check() abort
- call health#report_start('Checking language server client configuration')
- lua require 'vim.lsp.health'.check_health()
-endfunction
-
diff --git a/runtime/autoload/health/treesitter.vim b/runtime/autoload/health/treesitter.vim
deleted file mode 100644
index 5f167310ce..0000000000
--- a/runtime/autoload/health/treesitter.vim
+++ /dev/null
@@ -1,5 +0,0 @@
-function! health#treesitter#check() abort
- call health#report_start('Checking treesitter configuration')
- lua require 'vim.treesitter.health'.check_health()
-endfunction
-
diff --git a/runtime/autoload/netrw.vim b/runtime/autoload/netrw.vim
index b6edc4c4d8..ef0282848f 100644
--- a/runtime/autoload/netrw.vim
+++ b/runtime/autoload/netrw.vim
@@ -1711,7 +1711,8 @@ fun! s:NetrwOptionsSafe(islocal)
if &cpo =~ 'a' | call s:NetrwSetSafeSetting("&cpo",substitute(&cpo,'a','','g')) | endif
if &cpo =~ 'A' | call s:NetrwSetSafeSetting("&cpo",substitute(&cpo,'A','','g')) | endif
setl fo=nroql2
- call s:NetrwSetSafeSetting("&go","begmr")
+ " call s:NetrwSetSafeSetting("&go","begmr")
+ if &go =~ '\ca' | call s:NetrwSetSafeSetting("&go",substitute(&go,'\ca','','g')) | endif
call s:NetrwSetSafeSetting("&l:hid",0)
call s:NetrwSetSafeSetting("&l:im",0)
setl isk+=@ isk+=* isk+=/
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index df345e4981..1ad0a6883e 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -130,7 +130,9 @@ end of a range, -1 denotes the last line/column.
Exception: the following API functions use "mark-like" indexing (1-based
lines, 0-based columns):
+ |nvim_get_mark()|
|nvim_buf_get_mark()|
+ |nvim_buf_set_mark()|
|nvim_win_get_cursor()|
|nvim_win_set_cursor()|
@@ -706,7 +708,7 @@ nvim_create_buf({listed}, {scratch}) *nvim_create_buf()*
buf_open_scratch
nvim_create_namespace({name}) *nvim_create_namespace()*
- Creates a new namespace, or gets an existing one.
+ Creates a new *namespace* or gets an existing one.
Namespaces are used for buffer highlights and virtual text,
see |nvim_buf_add_highlight()| and |nvim_buf_set_extmark()|.
@@ -735,6 +737,23 @@ nvim_del_keymap({mode}, {lhs}) *nvim_del_keymap()*
See also: ~
|nvim_set_keymap()|
+nvim_del_mark({name}) *nvim_del_mark()*
+ Deletes a uppercase/file named mark. See |mark-motions|.
+
+ Note:
+ fails with error if a lowercase or buffer local named mark
+ is used.
+
+ Parameters: ~
+ {name} Mark name
+
+ Return: ~
+ true if the mark was deleted, else false.
+
+ See also: ~
+ |nvim_buf_del_mark()|
+ |nvim_get_mark()|
+
nvim_del_var({name}) *nvim_del_var()*
Removes a global (g:) variable.
@@ -828,7 +847,7 @@ nvim_feedkeys({keys}, {mode}, {escape_csi}) *nvim_feedkeys()*
On execution error: does not fail, but updates v:errmsg.
To input sequences like <C-o> use |nvim_replace_termcodes()|
- (typically with escape_csi=true) to replace the keycodes. Then
+ (typically with escape_csi=true) to replace |keycodes|, then
pass the result to nvim_feedkeys().
Example: >
@@ -866,32 +885,33 @@ nvim_get_api_info() *nvim_get_api_info()*
{fast}
nvim_get_chan_info({chan}) *nvim_get_chan_info()*
- Get information about a channel.
+ Gets information about a channel.
Return: ~
Dictionary describing a channel, with these keys:
- • "stream" the stream underlying the channel
+ • "id" Channel id.
+ • "argv" (optional) Job arguments list.
+ • "stream" Stream underlying the channel.
• "stdio" stdin and stdout of this Nvim instance
• "stderr" stderr of this Nvim instance
• "socket" TCP/IP socket or named pipe
- • "job" job with communication over its stdio
-
- • "mode" how data received on the channel is interpreted
- • "bytes" send and receive raw bytes
- • "terminal" a |terminal| instance interprets ASCII
- sequences
- • "rpc" |RPC| communication on the channel is active
-
- • "pty" Name of pseudoterminal, if one is used (optional).
- On a POSIX system, this will be a device path like
- /dev/pts/1. Even if the name is unknown, the key will
- still be present to indicate a pty is used. This is
- currently the case when using winpty on windows.
- • "buffer" buffer with connected |terminal| instance
- (optional)
- • "client" information about the client on the other end
- of the RPC channel, if it has added it using
- |nvim_set_client_info()|. (optional)
+ • "job" Job with communication over its stdio.
+
+ • "mode" How data received on the channel is interpreted.
+ • "bytes" Send and receive raw bytes.
+ • "terminal" |terminal| instance interprets ASCII
+ sequences.
+ • "rpc" |RPC| communication on the channel is active.
+
+ • "pty" (optional) Name of pseudoterminal. On a POSIX
+ system this is a device path like "/dev/pts/1". If the
+ name is unknown, the key will still be present if a pty
+ is used (e.g. for winpty on Windows).
+ • "buffer" (optional) Buffer with connected |terminal|
+ instance.
+ • "client" (optional) Info about the peer (client on the
+ other end of the RPC channel), if provided by it via
+ |nvim_set_client_info()|.
nvim_get_color_by_name({name}) *nvim_get_color_by_name()*
Returns the 24-bit RGB value of a |nvim_get_color_map()| color
@@ -917,7 +937,7 @@ nvim_get_color_map() *nvim_get_color_map()*
Return: ~
Map of color names and RGB values.
-nvim_get_commands({opts}) *nvim_get_commands()*
+nvim_get_commands({*opts}) *nvim_get_commands()*
Gets a map of global (non-buffer-local) Ex commands.
Currently only |user-commands| are supported, not builtin Ex
@@ -930,7 +950,7 @@ nvim_get_commands({opts}) *nvim_get_commands()*
Return: ~
Map of maps describing commands.
-nvim_get_context({opts}) *nvim_get_context()*
+nvim_get_context({*opts}) *nvim_get_context()*
Gets a map of the current editor state.
Parameters: ~
@@ -1008,6 +1028,27 @@ nvim_get_keymap({mode}) *nvim_get_keymap()*
Array of maparg()-like dictionaries describing mappings.
The "buffer" key is always zero.
+nvim_get_mark({name}) *nvim_get_mark()*
+ Return a tuple (row, col, buffer, buffername) representing the
+ position of the uppercase/file named mark. See |mark-motions|.
+
+ Marks are (1,0)-indexed. |api-indexing|
+
+ Note:
+ fails with error if a lowercase or buffer local named mark
+ is used.
+
+ Parameters: ~
+ {name} Mark name
+
+ Return: ~
+ 4-tuple (row, col, buffer, buffername), (0, 0, 0, '') if
+ the mark is not set.
+
+ See also: ~
+ |nvim_buf_set_mark()|
+ |nvim_del_mark()|
+
nvim_get_mode() *nvim_get_mode()*
Gets the current mode. |mode()| "blocking" is true if Nvim is
waiting for input.
@@ -1079,10 +1120,6 @@ nvim_get_runtime_file({name}, {all}) *nvim_get_runtime_file()*
It is not an error to not find any files. An empty array is
returned then.
- To find a directory, `name` must end with a forward slash,
- like "rplugin/python/". Without the slash it would instead
- look for an ordinary file called "rplugin/python".
-
Attributes: ~
{fast}
@@ -1251,7 +1288,7 @@ nvim_open_term({buffer}, {opts}) *nvim_open_term()*
For instance, for a floating display, first create an empty
buffer using |nvim_create_buf()|, then display it using
|nvim_open_win()|, and then call this function. Then
- |nvim_chan_send()| cal be called immediately to process
+ |nvim_chan_send()| can be called immediately to process
sequences in a virtual terminal having the intended size.
Parameters: ~
@@ -1261,156 +1298,6 @@ nvim_open_term({buffer}, {opts}) *nvim_open_term()*
Return: ~
Channel id, or 0 on error
-nvim_open_win({buffer}, {enter}, {config}) *nvim_open_win()*
- Open a new window.
-
- Currently this is used to open floating and external windows.
- Floats are windows that are drawn above the split layout, at
- some anchor position in some other window. Floats can be drawn
- internally or by external GUI with the |ui-multigrid|
- extension. External windows are only supported with multigrid
- GUIs, and are displayed as separate top-level windows.
-
- For a general overview of floats, see |api-floatwin|.
-
- Exactly one of `external` and `relative` must be specified.
- The `width` and `height` of the new window must be specified.
-
- With relative=editor (row=0,col=0) refers to the top-left
- corner of the screen-grid and (row=Lines-1,col=Columns-1)
- refers to the bottom-right corner. Fractional values are
- allowed, but the builtin implementation (used by non-multigrid
- UIs) will always round down to nearest integer.
-
- Out-of-bounds values, and configurations that make the float
- not fit inside the main editor, are allowed. The builtin
- implementation truncates values so floats are fully within the
- main screen grid. External GUIs could let floats hover outside
- of the main window like a tooltip, but this should not be used
- to specify arbitrary WM screen positions.
-
- Example (Lua): window-relative float >
- vim.api.nvim_open_win(0, false,
- {relative='win', row=3, col=3, width=12, height=3})
-<
-
- Example (Lua): buffer-relative float (travels as buffer is
- scrolled) >
- vim.api.nvim_open_win(0, false,
- {relative='win', width=12, height=3, bufpos={100,10}})
-<
-
- Attributes: ~
- not allowed when |textlock| is active
-
- Parameters: ~
- {buffer} Buffer to display, or 0 for current buffer
- {enter} Enter the window (make it the current window)
- {config} Map defining the window configuration. Keys:
- • `relative`: Sets the window layout to "floating", placed
- at (row,col) coordinates relative to:
- • "editor" The global editor grid
- • "win" Window given by the `win` field, or
- current window.
- • "cursor" Cursor position in current window.
-
- • `win` : |window-ID| for relative="win".
- • `anchor`: Decides which corner of the float to place
- at (row,col):
- • "NW" northwest (default)
- • "NE" northeast
- • "SW" southwest
- • "SE" southeast
-
- • `width` : Window width (in character cells).
- Minimum of 1.
- • `height` : Window height (in character cells).
- Minimum of 1.
- • `bufpos` : Places float relative to buffer
- text (only when relative="win"). Takes a tuple
- of zero-indexed [line, column]. `row` and
- `col` if given are applied relative to this
- position, else they default to `row=1` and
- `col=0` (thus like a tooltip near the buffer
- text).
- • `row` : Row position in units of "screen cell
- height", may be fractional.
- • `col` : Column position in units of "screen
- cell width", may be fractional.
- • `focusable` : Enable focus by user actions
- (wincmds, mouse events). Defaults to true.
- Non-focusable windows can be entered by
- |nvim_set_current_win()|.
- • `external` : GUI should display the window as
- an external top-level window. Currently
- accepts no other positioning configuration
- together with this.
- • `zindex`: Stacking order. floats with higher`zindex`go on top on floats with lower indices. Must
- be larger than zero. The following screen
- elements have hard-coded z-indices:
- • 100: insert completion popupmenu
- • 200: message scrollback
- • 250: cmdline completion popupmenu (when
- wildoptions+=pum) The default value for
- floats are 50. In general, values below 100
- are recommended, unless there is a good
- reason to overshadow builtin elements.
-
- • `style`: Configure the appearance of the window.
- Currently only takes one non-empty value:
- • "minimal" Nvim will display the window with
- many UI options disabled. This is useful
- when displaying a temporary float where the
- text should not be edited. Disables
- 'number', 'relativenumber', 'cursorline',
- 'cursorcolumn', 'foldcolumn', 'spell' and
- 'list' options. 'signcolumn' is changed to
- `auto` and 'colorcolumn' is cleared. The
- end-of-buffer region is hidden by setting
- `eob` flag of 'fillchars' to a space char,
- and clearing the |EndOfBuffer| region in
- 'winhighlight'.
-
- • `border`: Style of (optional) window border. This can
- either be a string or an array. The string
- values are
- • "none": No border (default).
- • "single": A single line box.
- • "double": A double line box.
- • "rounded": Like "single", but with rounded
- corners ("╭" etc.).
- • "solid": Adds padding by a single whitespace
- cell.
- • "shadow": A drop shadow effect by blending
- with the background.
- • If it is an array, it should have a length
- of eight or any divisor of eight. The array
- will specifify the eight chars building up
- the border in a clockwise fashion starting
- with the top-left corner. As an example, the
- double box style could be specified as [
- "╔", "═" ,"╗", "║", "╝", "═", "╚", "║" ]. If
- the number of chars are less than eight,
- they will be repeated. Thus an ASCII border
- could be specified as [ "/", "-", "\\", "|"
- ], or all chars the same as [ "x" ]. An
- empty string can be used to turn off a
- specific border, for instance, [ "", "", "",
- ">", "", "", "", "<" ] will only make
- vertical borders but not horizontal ones. By
- default, `FloatBorder` highlight is used,
- which links to `VertSplit` when not defined.
- It could also be specified by character: [
- {"+", "MyCorner"}, {"x", "MyBorder"} ].
-
- • `noautocmd` : If true then no buffer-related
- autocommand events such as |BufEnter|,
- |BufLeave| or |BufWinEnter| may fire from
- calling this function.
-
- Return: ~
- Window handle, or 0 on error
-
nvim_out_write({str}) *nvim_out_write()*
Writes a message to the Vim output buffer. Does not append
"\n", the message is buffered (won't display) until a linefeed
@@ -1779,7 +1666,7 @@ nvim_set_hl({ns_id}, {name}, {val}) *nvim_set_hl()*
default cterm attributes are same as attributes
of gui color
-nvim_set_keymap({mode}, {lhs}, {rhs}, {opts}) *nvim_set_keymap()*
+nvim_set_keymap({mode}, {lhs}, {rhs}, {*opts}) *nvim_set_keymap()*
Sets a global |mapping| for the given mode.
To set a buffer-local mapping, use |nvim_buf_set_keymap()|.
@@ -2063,6 +1950,24 @@ nvim_buf_del_keymap({buffer}, {mode}, {lhs}) *nvim_buf_del_keymap()*
See also: ~
|nvim_del_keymap()|
+nvim_buf_del_mark({buffer}, {name}) *nvim_buf_del_mark()*
+ Deletes a named mark in the buffer. See |mark-motions|.
+
+ Note:
+ only deletes marks set in the buffer, if the mark is not
+ set in the buffer it will return false.
+
+ Parameters: ~
+ {buffer} Buffer to set the mark on
+ {name} Mark name
+
+ Return: ~
+ true if the mark was deleted, else false.
+
+ See also: ~
+ |nvim_buf_set_mark()|
+ |nvim_del_mark()|
+
nvim_buf_del_var({buffer}, {name}) *nvim_buf_del_var()*
Removes a buffer-scoped (b:) variable
@@ -2107,7 +2012,7 @@ nvim_buf_get_changedtick({buffer}) *nvim_buf_get_changedtick()*
Return: ~
`b:changedtick` value.
-nvim_buf_get_commands({buffer}, {opts}) *nvim_buf_get_commands()*
+nvim_buf_get_commands({buffer}, {*opts}) *nvim_buf_get_commands()*
Gets a map of buffer-local |user-commands|.
Parameters: ~
@@ -2119,7 +2024,7 @@ nvim_buf_get_commands({buffer}, {opts}) *nvim_buf_get_commands()*
*nvim_buf_get_extmark_by_id()*
nvim_buf_get_extmark_by_id({buffer}, {ns_id}, {id}, {opts})
- Gets the position (0-indexed) of an extmark {id}.
+ Gets the position (0-indexed) of an extmark.
Parameters: ~
{buffer} Buffer handle, or 0 for current buffer
@@ -2170,12 +2075,12 @@ nvim_buf_get_extmarks({buffer}, {ns_id}, {start}, {end}, {opts})
Parameters: ~
{buffer} Buffer handle, or 0 for current buffer
{ns_id} Namespace id from |nvim_create_namespace()|
- {start} Start of range, given as 0-indexed (row, col) or
- valid extmark id (whose position defines the
- bound)
- {end} End of range (inclusive), given as 0-indexed
- (row, col) or valid extmark id (whose position
- defines the bound)
+ {start} Start of range: a 0-indexed (row, col) or valid
+ extmark id (whose position defines the bound).
+ |api-indexing|
+ {end} End of range (inclusive): a 0-indexed (row, col)
+ or valid extmark id (whose position defines the
+ bound). |api-indexing|
{opts} Optional parameters. Keys:
• limit: Maximum number of marks to return
• details Whether to include the details dict
@@ -2217,8 +2122,8 @@ nvim_buf_get_lines({buffer}, {start}, {end}, {strict_indexing})
Array of lines, or empty array for unloaded buffer.
nvim_buf_get_mark({buffer}, {name}) *nvim_buf_get_mark()*
- Return a tuple (row,col) representing the position of the
- named mark.
+ Returns a tuple (row,col) representing the position of the
+ named mark. See |mark-motions|.
Marks are (1,0)-indexed. |api-indexing|
@@ -2227,7 +2132,12 @@ nvim_buf_get_mark({buffer}, {name}) *nvim_buf_get_mark()*
{name} Mark name
Return: ~
- (row, col) tuple
+ (row, col) tuple, (0, 0) if the mark is not set, or is an
+ uppercase/file mark set in another buffer.
+
+ See also: ~
+ |nvim_buf_set_mark()|
+ |nvim_buf_del_mark()|
nvim_buf_get_name({buffer}) *nvim_buf_get_name()*
Gets the full file name for the buffer
@@ -2310,7 +2220,7 @@ nvim_buf_line_count({buffer}) *nvim_buf_line_count()*
Line count, or 0 for unloaded buffer. |api-buffer|
*nvim_buf_set_extmark()*
-nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {opts})
+nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts})
Creates or updates an extmark.
To create a new extmark, pass id=0. The extmark id will be
@@ -2328,8 +2238,10 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {opts})
Parameters: ~
{buffer} Buffer handle, or 0 for current buffer
{ns_id} Namespace id from |nvim_create_namespace()|
- {line} Line where to place the mark, 0-based
- {col} Column where to place the mark, 0-based
+ {line} Line where to place the mark, 0-based.
+ |api-indexing|
+ {col} Column where to place the mark, 0-based.
+ |api-indexing|
{opts} Optional parameters.
• id : id of the extmark to edit.
• end_line : ending line of the mark, 0-based
@@ -2338,6 +2250,10 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {opts})
exclusive.
• hl_group : name of the highlight group used to
highlight this mark.
+ • hl_eol : when true, for a multiline highlight
+ covering the EOL of a line, continue the
+ highlight for the rest of the screen line
+ (just like for diff and cursorline highlight).
• virt_text : virtual text to link to this mark.
A list of [text, highlight] tuples, each
representing a text chunk with specified
@@ -2373,10 +2289,28 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {opts})
color
• "blend": blend with background text color.
- • hl_eol : when true, for a multiline highlight
- covering the EOL of a line, continue the
- highlight for the rest of the screen line
- (just like for diff and cursorline highlight).
+ • virt_lines : virtual lines to add next to this
+ mark This should be an array over lines, where
+ each line in turn is an array over [text,
+ highlight] tuples. In general, buffer and
+ window options do not affect the display of
+ the text. In particular 'wrap' and 'linebreak'
+ options do not take effect, so the number of
+ extra screen lines will always match the size
+ of the array. However the 'tabstop' buffer
+ option is still used for hard tabs. By default
+ lines are placed below the buffer line
+ containing the mark. • Note: currently virtual lines are limited to
+ one block per buffer. Thus setting a new mark
+ disables any previous `virt_lines` decoration.
+ However plugins should not rely on this
+ behaviour, as this limitation is planned to be
+ removed.
+ • virt_lines_above: place virtual lines above
+ instead.
+ • virt_lines_leftcol: Place extmarks in the
+ leftmost column of the window, bypassing sign
+ and number columns.
• ephemeral : for use with
|nvim_set_decoration_provider| callbacks. The
mark will only be used for the current redraw
@@ -2399,7 +2333,7 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {opts})
Id of the created/updated extmark
*nvim_buf_set_keymap()*
-nvim_buf_set_keymap({buffer}, {mode}, {lhs}, {rhs}, {opts})
+nvim_buf_set_keymap({buffer}, {mode}, {lhs}, {rhs}, {*opts})
Sets a buffer-local |mapping| for the given mode.
Parameters: ~
@@ -2435,6 +2369,29 @@ nvim_buf_set_lines({buffer}, {start}, {end}, {strict_indexing}, {replacement})
error.
{replacement} Array of lines to use as replacement
+ *nvim_buf_set_mark()*
+nvim_buf_set_mark({buffer}, {name}, {line}, {col})
+ Sets a named mark in the given buffer, all marks are allowed
+ file/uppercase, visual, last change, etc. See |mark-motions|.
+
+ Marks are (1,0)-indexed. |api-indexing|
+
+ Note:
+ Passing 0 as line deletes the mark
+
+ Parameters: ~
+ {buffer} Buffer to set the mark on
+ {name} Mark name
+ {line} Line number
+ {col} Column/row number
+
+ Return: ~
+ true if the mark was set, else false.
+
+ See also: ~
+ |nvim_buf_del_mark()|
+ |nvim_buf_get_mark()|
+
nvim_buf_set_name({buffer}, {name}) *nvim_buf_set_name()*
Sets the full file name for a buffer
@@ -2534,20 +2491,6 @@ nvim_win_get_buf({window}) *nvim_win_get_buf()*
Return: ~
Buffer handle
-nvim_win_get_config({window}) *nvim_win_get_config()*
- Gets window configuration.
-
- The returned value may be given to |nvim_open_win()|.
-
- `relative` is empty for normal windows.
-
- Parameters: ~
- {window} Window handle, or 0 for current window
-
- Return: ~
- Map defining the window configuration, see
- |nvim_open_win()|
-
nvim_win_get_cursor({window}) *nvim_win_get_cursor()*
Gets the (1,0)-indexed cursor position in the window.
|api-indexing|
@@ -2658,23 +2601,6 @@ nvim_win_set_buf({window}, {buffer}) *nvim_win_set_buf()*
{window} Window handle, or 0 for current window
{buffer} Buffer handle
-nvim_win_set_config({window}, {config}) *nvim_win_set_config()*
- Configures window layout. Currently only for floating and
- external windows (including changing a split window to those
- layouts).
-
- When reconfiguring a floating window, absent option keys will
- not be changed. `row` / `col` and `relative` must be
- reconfigured together.
-
- Parameters: ~
- {window} Window handle, or 0 for current window
- {config} Map defining the window configuration, see
- |nvim_open_win()|
-
- See also: ~
- |nvim_open_win()|
-
nvim_win_set_cursor({window}, {pos}) *nvim_win_set_cursor()*
Sets the (1,0)-indexed cursor position in the window.
|api-indexing|
@@ -2718,6 +2644,194 @@ nvim_win_set_width({window}, {width}) *nvim_win_set_width()*
==============================================================================
+Win_Config Functions *api-win_config*
+
+nvim_open_win({buffer}, {enter}, {*config}) *nvim_open_win()*
+ Open a new window.
+
+ Currently this is used to open floating and external windows.
+ Floats are windows that are drawn above the split layout, at
+ some anchor position in some other window. Floats can be drawn
+ internally or by external GUI with the |ui-multigrid|
+ extension. External windows are only supported with multigrid
+ GUIs, and are displayed as separate top-level windows.
+
+ For a general overview of floats, see |api-floatwin|.
+
+ Exactly one of `external` and `relative` must be specified.
+ The `width` and `height` of the new window must be specified.
+
+ With relative=editor (row=0,col=0) refers to the top-left
+ corner of the screen-grid and (row=Lines-1,col=Columns-1)
+ refers to the bottom-right corner. Fractional values are
+ allowed, but the builtin implementation (used by non-multigrid
+ UIs) will always round down to nearest integer.
+
+ Out-of-bounds values, and configurations that make the float
+ not fit inside the main editor, are allowed. The builtin
+ implementation truncates values so floats are fully within the
+ main screen grid. External GUIs could let floats hover outside
+ of the main window like a tooltip, but this should not be used
+ to specify arbitrary WM screen positions.
+
+ Example (Lua): window-relative float >
+ vim.api.nvim_open_win(0, false,
+ {relative='win', row=3, col=3, width=12, height=3})
+<
+
+ Example (Lua): buffer-relative float (travels as buffer is
+ scrolled) >
+ vim.api.nvim_open_win(0, false,
+ {relative='win', width=12, height=3, bufpos={100,10}})
+<
+
+ Attributes: ~
+ not allowed when |textlock| is active
+
+ Parameters: ~
+ {buffer} Buffer to display, or 0 for current buffer
+ {enter} Enter the window (make it the current window)
+ {config} Map defining the window configuration. Keys:
+ • `relative`: Sets the window layout to "floating", placed
+ at (row,col) coordinates relative to:
+ • "editor" The global editor grid
+ • "win" Window given by the `win` field, or
+ current window.
+ • "cursor" Cursor position in current window.
+
+ • `win` : |window-ID| for relative="win".
+ • `anchor`: Decides which corner of the float to place
+ at (row,col):
+ • "NW" northwest (default)
+ • "NE" northeast
+ • "SW" southwest
+ • "SE" southeast
+
+ • `width` : Window width (in character cells).
+ Minimum of 1.
+ • `height` : Window height (in character cells).
+ Minimum of 1.
+ • `bufpos`: Places float relative to buffer text (only
+ when relative="win"). Takes a tuple of
+ zero-indexed [line, column].`row`and`col`if given are applied relative to this
+ position, else they default to:
+ • `row=1` and `col=0` if `anchor` is "NW" or
+ "NE"
+ • `row=0` and `col=0` if `anchor` is "SW" or
+ "SE" (thus like a tooltip near the buffer
+ text).
+
+ • `row` : Row position in units of "screen cell
+ height", may be fractional.
+ • `col` : Column position in units of "screen
+ cell width", may be fractional.
+ • `focusable` : Enable focus by user actions
+ (wincmds, mouse events). Defaults to true.
+ Non-focusable windows can be entered by
+ |nvim_set_current_win()|.
+ • `external` : GUI should display the window as
+ an external top-level window. Currently
+ accepts no other positioning configuration
+ together with this.
+ • `zindex`: Stacking order. floats with higher`zindex`go on top on floats with lower indices. Must
+ be larger than zero. The following screen
+ elements have hard-coded z-indices:
+ • 100: insert completion popupmenu
+ • 200: message scrollback
+ • 250: cmdline completion popupmenu (when
+ wildoptions+=pum) The default value for
+ floats are 50. In general, values below 100
+ are recommended, unless there is a good
+ reason to overshadow builtin elements.
+
+ • `style`: Configure the appearance of the window.
+ Currently only takes one non-empty value:
+ • "minimal" Nvim will display the window with
+ many UI options disabled. This is useful
+ when displaying a temporary float where the
+ text should not be edited. Disables
+ 'number', 'relativenumber', 'cursorline',
+ 'cursorcolumn', 'foldcolumn', 'spell' and
+ 'list' options. 'signcolumn' is changed to
+ `auto` and 'colorcolumn' is cleared. The
+ end-of-buffer region is hidden by setting
+ `eob` flag of 'fillchars' to a space char,
+ and clearing the |EndOfBuffer| region in
+ 'winhighlight'.
+
+ • `border`: Style of (optional) window border. This can
+ either be a string or an array. The string
+ values are
+ • "none": No border (default).
+ • "single": A single line box.
+ • "double": A double line box.
+ • "rounded": Like "single", but with rounded
+ corners ("╭" etc.).
+ • "solid": Adds padding by a single whitespace
+ cell.
+ • "shadow": A drop shadow effect by blending
+ with the background.
+ • If it is an array, it should have a length
+ of eight or any divisor of eight. The array
+ will specifify the eight chars building up
+ the border in a clockwise fashion starting
+ with the top-left corner. As an example, the
+ double box style could be specified as [
+ "╔", "═" ,"╗", "║", "╝", "═", "╚", "║" ]. If
+ the number of chars are less than eight,
+ they will be repeated. Thus an ASCII border
+ could be specified as [ "/", "-", "\\", "|"
+ ], or all chars the same as [ "x" ]. An
+ empty string can be used to turn off a
+ specific border, for instance, [ "", "", "",
+ ">", "", "", "", "<" ] will only make
+ vertical borders but not horizontal ones. By
+ default, `FloatBorder` highlight is used,
+ which links to `VertSplit` when not defined.
+ It could also be specified by character: [
+ {"+", "MyCorner"}, {"x", "MyBorder"} ].
+
+ • `noautocmd` : If true then no buffer-related
+ autocommand events such as |BufEnter|,
+ |BufLeave| or |BufWinEnter| may fire from
+ calling this function.
+
+ Return: ~
+ Window handle, or 0 on error
+
+nvim_win_get_config({window}) *nvim_win_get_config()*
+ Gets window configuration.
+
+ The returned value may be given to |nvim_open_win()|.
+
+ `relative` is empty for normal windows.
+
+ Parameters: ~
+ {window} Window handle, or 0 for current window
+
+ Return: ~
+ Map defining the window configuration, see
+ |nvim_open_win()|
+
+nvim_win_set_config({window}, {*config}) *nvim_win_set_config()*
+ Configures window layout. Currently only for floating and
+ external windows (including changing a split window to those
+ layouts).
+
+ When reconfiguring a floating window, absent option keys will
+ not be changed. `row` / `col` and `relative` must be
+ reconfigured together.
+
+ Parameters: ~
+ {window} Window handle, or 0 for current window
+ {config} Map defining the window configuration, see
+ |nvim_open_win()|
+
+ See also: ~
+ |nvim_open_win()|
+
+
+==============================================================================
Tabpage Functions *api-tabpage*
nvim_tabpage_del_var({tabpage}, {name}) *nvim_tabpage_del_var()*
diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt
index 7a53f17a78..de74ee891e 100644
--- a/runtime/doc/autocmd.txt
+++ b/runtime/doc/autocmd.txt
@@ -1232,6 +1232,13 @@ Example: >
This prevents having the autocommands defined twice (e.g., after sourcing the
vimrc file again).
+ *FileExplorer*
+There is one group that is recognized by Vim: FileExplorer. If this group
+exists Vim assumes that editing a directory is possible and will trigger a
+plugin that lists the files in that directory. This is used by the |netrw|
+plugin. This allows you to do: >
+ browse edit
+
==============================================================================
9. Executing autocommands *autocmd-execute*
diff --git a/runtime/doc/develop.txt b/runtime/doc/develop.txt
index 14f35acce3..7127c74134 100644
--- a/runtime/doc/develop.txt
+++ b/runtime/doc/develop.txt
@@ -166,7 +166,7 @@ Docstring format:
- Use `<pre>` for code samples.
Example: the help for |nvim_open_win()| is generated from a docstring defined
-in src/nvim/api/vim.c like this: >
+in src/nvim/api/win_config.c like this: >
/// Opens a new window.
/// ...
diff --git a/runtime/doc/diagnostic.txt b/runtime/doc/diagnostic.txt
index 679bb2f7ff..75c8a2ad6f 100644
--- a/runtime/doc/diagnostic.txt
+++ b/runtime/doc/diagnostic.txt
@@ -201,7 +201,52 @@ DiagnosticsChanged After diagnostics have changed.
Example: >
autocmd User DiagnosticsChanged lua vim.diagnostic.setqflist({open = false })
<
-
+==============================================================================
+CUSTOMIZATION *diagnostic-config*
+
+If you need more customization over the way diagnostics are displayed than the
+built-in configuration options provide, you can override the display handler
+explicitly. For example, use the following to only show a sign for the highest
+severity diagnostic on a given line: >
+
+ -- Disable the default signs handler
+ vim.diagnostic.config({signs = false})
+
+ -- Create a namespace. This won't be used to add any diagnostics,
+ -- only to display them.
+ local ns = vim.api.nvim_create_namespace("my_namespace")
+
+ -- Create a reference to the original function
+ local orig_show = vim.diagnostic.show
+
+ local function set_signs(bufnr)
+ -- Get all diagnostics from the current buffer
+ local diagnostics = vim.diagnostic.get(bufnr)
+
+ -- Find the "worst" diagnostic per line
+ local max_severity_per_line = {}
+ for _, d in pairs(diagnostics) do
+ local m = max_severity_per_line[d.lnum]
+ if not m or d.severity < m.severity then
+ max_severity_per_line[d.lnum] = d
+ end
+ end
+
+ -- Show the filtered diagnostics using the custom namespace. Use the
+ -- reference to the original function to avoid a loop.
+ local filtered_diagnostics = vim.tbl_values(max_severity_per_line)
+ orig_show(ns, bufnr, filtered_diagnostics, {
+ virtual_text=false,
+ underline=false,
+ signs=true
+ })
+ end
+
+ function vim.diagnostic.show(namespace, bufnr, ...)
+ orig_show(namespace, bufnr, ...)
+ set_signs(bufnr)
+ end
+<
==============================================================================
Lua module: vim.diagnostic *diagnostic-api*
@@ -253,6 +298,12 @@ config({opts}, {namespace}) *vim.diagnostic.config()*
• severity: Only show signs for diagnostics
matching the given severity
|diagnostic-severity|
+ • priority: (number, default 10) Base
+ priority to use for signs. When
+ {severity_sort} is used, the priority of
+ a sign is adjusted based on its severity.
+ Otherwise, all signs use the same
+ priority.
• update_in_insert: (default false) Update
diagnostics in Insert mode (if false,
@@ -312,6 +363,13 @@ get({bufnr}, {opts}) *vim.diagnostic.get()*
Return: ~
table A list of diagnostic items |diagnostic-structure|.
+get_namespaces() *vim.diagnostic.get_namespaces()*
+ Get current diagnostic namespaces.
+
+ Return: ~
+ table A list of active diagnostic namespaces
+ |vim.diagnostic|.
+
get_next({opts}) *vim.diagnostic.get_next()*
Get the next diagnostic closest to the cursor position.
diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt
index 4700af41b7..0e7e461a61 100644
--- a/runtime/doc/editing.txt
+++ b/runtime/doc/editing.txt
@@ -1183,7 +1183,8 @@ If you want to always use ":confirm", set the 'confirm' option.
|:diffsplit|, |:diffpatch|, |:pedit|, |:redir|,
|:source|, |:update|, |:visual|, |:vsplit|,
and |:qall| if 'confirm' is set.
- {only in Win32 GUI}
+ {only in Win32 GUI, in console `browse edit` works
+ if the FileExplorer autocommand group exists}
When ":browse" is not possible you get an error
message. If {command} doesn't support browsing, the
{command} is executed without a dialog.
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index d6f72b68f7..fe19bb3134 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1307,7 +1307,7 @@ A string constant accepts these special characters:
\U.... same as \u but allows up to 8 hex numbers.
\b backspace <BS>
\e escape <Esc>
-\f formfeed <FF>
+\f formfeed 0x0C
\n newline <NL>
\r return <CR>
\t tab <Tab>
@@ -1316,7 +1316,7 @@ A string constant accepts these special characters:
\<xxx> Special key named "xxx". e.g. "\<C-W>" for CTRL-W. This is for use
in mappings, the 0x80 byte is escaped.
To use the double quote character it must be escaped: "<M-\">".
- Don't use <Char-xxxx> to get a utf-8 character, use \uxxxx as
+ Don't use <Char-xxxx> to get a UTF-8 character, use \uxxxx as
mentioned above.
Note that "\xff" is stored as the byte 255, which may be invalid in some
@@ -2313,7 +2313,7 @@ ceil({expr}) Float round {expr} up
changenr() Number current change number
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/UTF8 value of first char in {expr}
+char2nr({expr}[, {utf8}]) Number ASCII/UTF-8 value of first char in {expr}
charidx({string}, {idx} [, {countcc}])
Number char index of byte {idx} in {string}
cindent({lnum}) Number C indent for line {lnum}
@@ -2544,7 +2544,7 @@ mode([expr]) String current editing mode
msgpackdump({list} [, {type}]) List/Blob dump objects to msgpack
msgpackparse({data}) List parse msgpack to a list of objects
nextnonblank({lnum}) Number line nr of non-blank line >= {lnum}
-nr2char({expr}[, {utf8}]) String single char with ASCII/UTF8 value {expr}
+nr2char({expr}[, {utf8}]) String single char with ASCII/UTF-8 value {expr}
nvim_...({args}...) any call nvim |api| functions
or({expr}, {expr}) Number bitwise OR
pathshorten({expr}) String shorten directory names in a path
@@ -2680,7 +2680,7 @@ stdioopen({dict}) Number open stdio in a headless instance.
stdpath({what}) String/List returns the standard path(s) for {what}
str2float({expr} [, {quoted}]) Float convert String to Float
str2list({expr} [, {utf8}]) List convert each character of {expr} to
- ASCII/UTF8 value
+ ASCII/UTF-8 value
str2nr({expr} [, {base} [, {quoted}]])
Number convert String to Number
strchars({expr} [, {skipcc}]) Number character length of the String {expr}
@@ -3419,6 +3419,8 @@ complete_info([{what}]) *complete_info()*
"" Not in completion mode
"keyword" Keyword completion |i_CTRL-X_CTRL-N|
"ctrl_x" Just pressed CTRL-X |i_CTRL-X|
+ "scroll" Scrolling with |i_CTRL-X_CTRL-E| or
+ |i_CTRL-X_CTRL-Y|
"whole_line" Whole lines |i_CTRL-X_CTRL-L|
"files" File names |i_CTRL-X_CTRL-F|
"tags" Tags |i_CTRL-X_CTRL-]|
@@ -6342,9 +6344,9 @@ list2str({list} [, {utf8}]) *list2str()*
join(map(list, {nr, val -> nr2char(val)}), '')
< |str2list()| does the opposite.
- When {utf8} is omitted or zero, the current 'encoding' is used.
- With {utf8} is 1, always return utf-8 characters.
- With utf-8 composing characters work as expected: >
+ UTF-8 encoding is always used, {utf8} option has no effect,
+ and exists only for backwards-compatibility.
+ With UTF-8 composing characters work as expected: >
list2str([97, 769]) returns "á"
<
localtime() *localtime()*
@@ -6863,29 +6865,31 @@ mode([expr]) Return a string that indicates the current mode.
niR Normal using |i_CTRL-O| in |Replace-mode|
niV Normal using |i_CTRL-O| in |Virtual-Replace-mode|
v Visual by character
+ vs Visual by character using |v_CTRL-O| in Select mode
V Visual by line
+ Vs Visual by line using |v_CTRL-O| in Select mode
CTRL-V Visual blockwise
+ CTRL-Vs Visual blockwise using |v_CTRL-O| in Select mode
s Select by character
S Select by line
CTRL-S Select blockwise
- vs Visual by character using |v_CTRL-O| from
- Select mode
- Vs Visual by line using |v_CTRL-O| from Select mode
- CTRL-Vs Visual blockwise using |v_CTRL-O| from Select mode
i Insert
ic Insert mode completion |compl-generic|
ix Insert mode |i_CTRL-X| completion
R Replace |R|
Rc Replace mode completion |compl-generic|
- Rv Virtual Replace |gR|
Rx Replace mode |i_CTRL-X| completion
+ Rv Virtual Replace |gR|
+ Rvc Virtual Replace mode completion |compl-generic|
+ Rvx Virtual Replace mode |i_CTRL-X| completion
c Command-line editing
cv Vim Ex mode |Q| or |gQ|
r Hit-enter prompt
rm The -- more -- prompt
- r? |:confirm| query of some sort
+ r? A |:confirm| query of some sort
! Shell or external command is executing
t Terminal mode: keys go to the job
+
This is useful in the 'statusline' option or when used
with |remote_expr()| In most other places it always returns
"c" or "n".
@@ -8968,10 +8972,9 @@ str2list({string} [, {utf8}]) *str2list()*
str2list("ABC") returns [65, 66, 67]
< |list2str()| does the opposite.
- When {utf8} is omitted or zero, the current 'encoding' is used.
- With {utf8} set to TRUE, always treat the String as utf-8
- characters. With utf-8 composing characters are handled
- properly: >
+ UTF-8 encoding is always used, {utf8} option has no effect,
+ and exists only for backwards-compatibility.
+ With UTF-8 composing characters are handled properly: >
str2list("á") returns [97, 769]
< Can also be used as a |method|: >
@@ -10983,7 +10986,7 @@ text...
literal then the items also cannot be changed: >
const ll = [1, 2, 3]
let ll[1] = 5 " Error!
-< Nested references are not locked: >
+< Nested references are not locked: >
let lvar = ['a']
const lconst = [0, lvar]
let lconst[0] = 2 " Error!
diff --git a/runtime/doc/filetype.txt b/runtime/doc/filetype.txt
index a23ae3fb76..42a9993c8c 100644
--- a/runtime/doc/filetype.txt
+++ b/runtime/doc/filetype.txt
@@ -501,7 +501,7 @@ One command, :DiffGitCached, is provided to show a diff of the current commit
in the preview window. It is equivalent to calling "git diff --cached" plus
any arguments given to the command.
-GPROF
+GPROF *ft-gprof-plugin*
The gprof filetype plugin defines a mapping <C-]> to jump from a function
entry in the gprof flat profile or from a function entry in the call graph
diff --git a/runtime/doc/helphelp.txt b/runtime/doc/helphelp.txt
index 4a94701b2e..aaa2a35fe1 100644
--- a/runtime/doc/helphelp.txt
+++ b/runtime/doc/helphelp.txt
@@ -389,17 +389,5 @@ highlighting. So do these:
You can find the details in $VIMRUNTIME/syntax/help.vim
- *inclusion*
-Vim is for everybody, no matter race, gender or anything. Some people make a
-big deal about using "he" or "his" when referring to the user, thinking it
-means we assume the user is male. That is not the case, it's just a habit of
-writing help text, which quite often is many years old. Also, a lot of the
-text is written by contributors for whom English is not their first language.
-We do not make any assumptions about the gender of the user, no matter how the
-text is phrased. Some people have suggested using "they", but that is not
-regular English. We do not want to spend much time on this discussion. The
-goal is that the reader understands how Vim works, the exact wording is
-secondary.
-
vim:tw=78:ts=8:noet:ft=help:norl:
diff --git a/runtime/doc/intro.txt b/runtime/doc/intro.txt
index 2baf3a247f..a89263861b 100644
--- a/runtime/doc/intro.txt
+++ b/runtime/doc/intro.txt
@@ -55,7 +55,7 @@ Nvim on the interwebs *internet*
Nvim home page: https://neovim.io/
Nvim FAQ: https://github.com/neovim/neovim/wiki/FAQ
Downloads: https://github.com/neovim/neovim/releases
- Vim FAQ: https://vimhelp.appspot.com/vim_faq.txt.html
+ Vim FAQ: https://vimhelp.org/vim_faq.txt.html
*bugs* *bug-report*
@@ -312,7 +312,6 @@ notation meaning equivalent decimal value(s) ~
<Tab> tab CTRL-I 9 *tab* *Tab*
*linefeed*
<NL> linefeed CTRL-J 10 (used for <Nul>)
-<FF> formfeed CTRL-L 12 *formfeed*
<CR> carriage return CTRL-M 13 *carriage-return*
<Return> same as <CR> *<Return>*
<Enter> same as <CR> *<Enter>*
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt
index 5b2a8d68b4..ac797de92d 100644
--- a/runtime/doc/lsp.txt
+++ b/runtime/doc/lsp.txt
@@ -1015,6 +1015,9 @@ outgoing_calls() *vim.lsp.buf.outgoing_calls()*
cursor in the |quickfix| window. If the symbol can resolve to
multiple items, the user can pick one in the |inputlist|.
+prepare_rename({err}, {result}) *vim.lsp.buf.prepare_rename()*
+ TODO: Documentation
+
*vim.lsp.buf.range_code_action()*
range_code_action({context}, {start_pos}, {end_pos})
Performs |vim.lsp.buf.code_action()| for a given range.
@@ -1251,8 +1254,8 @@ apply_text_edits({text_edits}, {bufnr})
Applies a list of text edits to a buffer.
Parameters: ~
- {text_edits} (table) list of `TextEdit` objects
- {buf_nr} (number) Buffer id
+ {text_edits} table list of `TextEdit` objects
+ {bufnr} number Buffer id
See also: ~
https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textEdit
@@ -1472,6 +1475,13 @@ make_floating_popup_options({width}, {height}, {opts})
{width} (number) window width (in character cells)
{height} (number) window height (in character cells)
{opts} (table, optional)
+ • offset_x (number) offset to add to `col`
+ • offset_y (number) offset to add to `row`
+ • border (string or table) override `border`
+ • focusable (string or table) override
+ `focusable`
+ • zindex (string or table) override `zindex` ,
+ defaults to 50
Return: ~
(table) Options
@@ -1562,10 +1572,6 @@ open_floating_preview({contents}, {syntax}, {opts})
height when wrap is enabled
• max_width maximal width of floating window
• max_height maximal height of floating window
- • pad_left number of columns to pad contents
- at left
- • pad_right number of columns to pad contents
- at right
• pad_top number of lines to pad contents at
top
• pad_bottom number of lines to pad contents
@@ -1585,10 +1591,10 @@ parse_snippet({input}) *vim.lsp.util.parse_snippet()*
Parses snippets in a completion entry.
Parameters: ~
- {input} (string) unparsed snippet
+ {input} string unparsed snippet
Return: ~
- (string) parsed snippet
+ string parsed snippet
preview_location({location}, {opts}) *vim.lsp.util.preview_location()*
Previews a location in a floating window
@@ -1649,10 +1655,6 @@ stylize_markdown({bufnr}, {contents}, {opts})
height
• max_width maximal width of floating window
• max_height maximal height of floating window
- • pad_left number of columns to pad contents
- at left
- • pad_right number of columns to pad contents
- at right
• pad_top number of lines to pad contents at
top
• pad_bottom number of lines to pad contents
@@ -1719,6 +1721,16 @@ get_filename() *vim.lsp.log.get_filename()*
Return: ~
(string) log filename
+get_level() *vim.lsp.log.get_level()*
+ TODO: Documentation
+
+set_format_func({handle}) *vim.lsp.log.set_format_func()*
+ Sets formatting function used to format logs
+
+ Parameters: ~
+ {handle} function function to apply to logging arguments,
+ pass vim.inspect for multi-line formatting
+
set_level({level}) *vim.lsp.log.set_level()*
Sets the current log level.
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index 22e323baa7..a6ccf9f35c 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -1206,6 +1206,36 @@ notify({msg}, {log_level}, {_opts}) *vim.notify()*
See also: ~
:help nvim_notify
+on_key({fn}, {ns_id}) *vim.on_key()*
+ Adds Lua function {fn} with namespace id {ns_id} as a listener
+ to every, yes every, input key.
+
+ The Nvim command-line option |-w| is related but does not
+ support callbacks and cannot be toggled dynamically.
+
+ Note:
+ {fn} will not be cleared by |nvim_buf_clear_namespace()|
+
+ Note:
+ {fn} will receive the keys after mappings have been
+ evaluated
+
+ Parameters: ~
+ {fn} function: Callback function. It should take one
+ string argument. On each key press, Nvim passes
+ the key char to fn(). |i_CTRL-V| If {fn} is nil,
+ it removes the callback for the associated
+ {ns_id}
+ {ns_id} number? Namespace ID. If nil or 0, generates and
+ returns a new |nvim_create_namesapce()| id.
+
+ Return: ~
+ number Namespace id associated with {fn}. Or count of all
+ callbacks if on_key() is called without arguments.
+
+ Note:
+ {fn} will be removed if an error occurs while calling.
+
paste({lines}, {phase}) *vim.paste()*
Paste handler, invoked by |nvim_paste()| when a conforming UI
(such as the |TUI|) pastes text into the editor.
@@ -1268,8 +1298,7 @@ schedule_wrap({cb}) *vim.schedule_wrap()*
deep_equal({a}, {b}) *vim.deep_equal()*
Deep compare values for equality
- Tables are compared recursively unless they both provide the `eq` methamethod.
- All other types are compared using the equality `==` operator.
+ Tables are compared recursively unless they both provide the `eq` methamethod. All other types are compared using the equality `==` operator.
Parameters: ~
{a} first value
@@ -1373,20 +1402,25 @@ pesc({s}) *vim.pesc()*
See also: ~
https://github.com/rxi/lume
-split({s}, {sep}, {plain}) *vim.split()*
+split({s}, {sep}, {kwargs}) *vim.split()*
Splits a string at each instance of a separator.
Examples: >
- split(":aa::b:", ":") --> {'','aa','','b',''}
- split("axaby", "ab?") --> {'','x','y'}
- split(x*yz*o, "*", true) --> {'x','yz','o'}
+
+ split(":aa::b:", ":") --> {'','aa','','b',''}
+ split("axaby", "ab?") --> {'','x','y'}
+ split("x*yz*o", "*", {plain=true}) --> {'x','yz','o'}
+ split("|x|y|z|", "|", {trimempty=true}) --> {'x', 'y', 'z'}
<
Parameters: ~
- {s} String to split
- {sep} Separator string or pattern
- {plain} If `true` use `sep` literally (passed to
- String.find)
+ {s} String to split
+ {sep} Separator string or pattern
+ {kwargs} Keyword arguments:
+ • plain: (boolean) If `true` use `sep` literally
+ (passed to string.find)
+ • trimempty: (boolean) If `true` remove empty
+ items from the front and back of the list
Return: ~
List-like table of the split components.
@@ -1571,12 +1605,14 @@ validate({opt}) *vim.validate()*
vim.validate{arg1={{'foo'}, 'table'}, arg2={'foo', 'string'}}
=> NOP (success)
-
- vim.validate{arg1={1, 'table'}}
- => error('arg1: expected table, got number')
-
- vim.validate{arg1={3, function(a) return (a % 2) == 0 end, 'even number'}}
- => error('arg1: expected even number, got 3')
+<
+>
+ vim.validate{arg1={1, 'table'}}
+ => error('arg1: expected table, got number')
+<
+>
+ vim.validate{arg1={3, function(a) return (a % 2) == 0 end, 'even number'}}
+ => error('arg1: expected even number, got 3')
<
Parameters: ~
diff --git a/runtime/doc/mbyte.txt b/runtime/doc/mbyte.txt
index a6c797a860..3bbf36c642 100644
--- a/runtime/doc/mbyte.txt
+++ b/runtime/doc/mbyte.txt
@@ -663,7 +663,7 @@ This file explains what characters are available in UTF-8 and CP1255 encodings,
and what the keymaps are to get those characters:
glyph encoding keymap ~
-Char utf-8 cp1255 hebrew hebrewp name ~
+Char UTF-8 cp1255 hebrew hebrewp name ~
א 0x5d0 0xe0 t a 'alef
ב 0x5d1 0xe1 c b bet
ג 0x5d2 0xe2 d g gimel
@@ -716,11 +716,11 @@ Vowel marks and special punctuation:
ױ 0x5f1 0xd5 VY VY vav-yod
ײ 0x5f2 0xd6 YY YY yod-yod
-The following are only available in utf-8
+The following are only available in UTF-8
Cantillation marks:
glyph
-Char utf-8 hebrew name
+Char UTF-8 hebrew name
ב֑ 0x591 C: etnahta
ב֒ 0x592 Cs segol
ב֓ 0x593 CS shalshelet
@@ -803,7 +803,7 @@ ASCII. On MS-Windows UTF-16 is also used (previously UCS-2), which uses
internally.
Vim has comprehensive UTF-8 support. It works well in:
-- xterm with utf-8 support enabled
+- xterm with UTF-8 support enabled
- MS-Windows GUI
- several other platforms
@@ -814,14 +814,14 @@ a space to fill the gap.
*bom-bytes*
When reading a file a BOM (Byte Order Mark) can be used to recognize the
Unicode encoding:
- EF BB BF utf-8
- FE FF utf-16 big endian
- FF FE utf-16 little endian
- 00 00 FE FF utf-32 big endian
- FF FE 00 00 utf-32 little endian
-
-Utf-8 is the recommended encoding. Note that it's difficult to tell utf-16
-and utf-32 apart. Utf-16 is often used on MS-Windows, utf-32 is not
+ EF BB BF UTF-8
+ FE FF UTF-16 big endian
+ FF FE UTF-16 little endian
+ 00 00 FE FF UTF-32 big endian
+ FF FE 00 00 UTF-32 little endian
+
+UTF-8 is the recommended encoding. Note that it's difficult to tell UTF-16
+and UTF-32 apart. UTF-16 is often used on MS-Windows, UTF-32 is not
widespread as file format.
@@ -888,10 +888,10 @@ Motif. Use the ":hi Menu font={fontname}" command for this. |:highlight|
TYPING UTF-8 *utf-8-typing*
If you are using X-Windows, you should find an input method that supports
-utf-8.
+UTF-8.
-If your system does not provide support for typing utf-8, you can use the
-'keymap' feature. This allows writing a keymap file, which defines a utf-8
+If your system does not provide support for typing UTF-8, you can use the
+'keymap' feature. This allows writing a keymap file, which defines a UTF-8
character as a sequence of ASCII characters. See |mbyte-keymap|.
If everything else fails, you can type any character as four hex bytes: >
diff --git a/runtime/doc/nvim_terminal_emulator.txt b/runtime/doc/nvim_terminal_emulator.txt
index 5ad69d1122..e83b17f9a0 100644
--- a/runtime/doc/nvim_terminal_emulator.txt
+++ b/runtime/doc/nvim_terminal_emulator.txt
@@ -53,7 +53,7 @@ next key is sent unless it is <C-N>. Use <C-\><C-N> to return to normal-mode.
Terminal-mode forces these local options:
- 'nocursorline'
+ 'cursorlineopt' = number
'nocursorcolumn'
'scrolloff' = 0
'sidescrolloff' = 0
@@ -171,7 +171,7 @@ program window A terminal window for the executed program. When "run" is
The current window is used to show the source code. When gdb pauses the
source file location will be displayed, if possible. A sign is used to
-highlight the current position, using highlight group debugPC.
+highlight the current position, using highlight group debugPC.
If the buffer in the current window is modified, another window will be opened
to display the current gdb position.
@@ -222,7 +222,7 @@ Put focus on the gdb window and type: >
run
Vim will start running in the program window. Put focus there and type: >
:help gui
-Gdb will run into the ex_help breakpoint. The source window now shows the
+Gdb will run into the ex_help breakpoint. The source window now shows the
ex_cmds.c file. A red "1 " marker will appear in the signcolumn where the
breakpoint was set. The line where the debugger stopped is highlighted. You
can now step through the program. You will see the highlighting move as the
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 85be6eddaa..981bdd09fc 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -1409,9 +1409,9 @@ A jump table for the options with a short description can be found at |Q_op|.
When this option is set it overrules 'shellslash' for completion:
- When this option is set to "slash", a forward slash is used for path
completion in insert mode. This is useful when editing HTML tag, or
- Makefile with 'noshellslash' on Windows.
+ Makefile with 'noshellslash' on MS-Windows.
- When this option is set to "backslash", backslash is used. This is
- useful when editing a batch file with 'shellslash' set on Windows.
+ useful when editing a batch file with 'shellslash' set on MS-Windows.
- When this option is empty, same character is used as for
'shellslash'.
For Insert mode completion the buffer-local value is used. For
diff --git a/runtime/doc/pi_health.txt b/runtime/doc/pi_health.txt
index bb688770fc..179c1066cd 100644
--- a/runtime/doc/pi_health.txt
+++ b/runtime/doc/pi_health.txt
@@ -5,7 +5,7 @@ Author: TJ DeVries <devries.timothyj@gmail.com>
Type |gO| to see the table of contents.
==============================================================================
-Introduction *health*
+Introduction *health*
health.vim is a minimal framework to help with troubleshooting user
configuration. Nvim ships with healthchecks for configuration, performance,
@@ -18,65 +18,136 @@ To run the healthchecks, use this command: >
Plugin authors are encouraged to write new healthchecks. |health-dev|
==============================================================================
-Commands *health-commands*
+Commands *health-commands*
- *:checkhealth* *:CheckHealth*
+ *:checkhealth* *:CheckHealth*
:checkhealth Run all healthchecks.
- *E5009*
- Nvim depends on |$VIMRUNTIME| and 'runtimepath' to find
- the standard "runtime files" for syntax highlighting,
- filetype-specific behavior, and standard plugins
- (including :checkhealth). If the runtime files cannot
- be found then those features will not work.
+ *E5009*
+ Nvim depends on |$VIMRUNTIME|, 'runtimepath' and 'packpath' to
+ find the standard "runtime files" for syntax highlighting,
+ filetype-specific behavior, and standard plugins (including
+ :checkhealth). If the runtime files cannot be found then
+ those features will not work.
:checkhealth {plugins}
- Run healthcheck(s) for one or more plugins. E.g. to run
- only the standard Nvim healthcheck: >
+ Run healthcheck(s) for one or more plugins. E.g. to run only
+ the standard Nvim healthcheck: >
:checkhealth nvim
-< To run the healthchecks for the "foo" and "bar" plugins
- (assuming these plugins are on your 'runtimepath' and
- they have implemented health#foo#check() and
- health#bar#check(), respectively): >
+<
+ To run the healthchecks for the "foo" and "bar" plugins
+ (assuming these plugins are on 'runtimepath' or 'packpath' and
+ they have implemented the Lua or Vimscript interface
+ require("foo.health").check() and health#bar#check(),
+ respectively): >
:checkhealth foo bar
<
+ To run healthchecks for lua submodules, use dot notation or
+ "*" to refer to all submodules. For example nvim provides
+ `vim.lsp` and `vim.treesitter` >
+ :checkhealth vim.lsp vim.treesitter
+ :checkhealth vim*
+<
==============================================================================
-Functions *health-functions*
+Lua Functions *health-functions-lua* *health-lua*
+
+The Lua "health" module can be used to create new healthchecks (see also
+|health-functions-vim|). To get started, simply use: >
+ local health = require('health')
+<
+health.report_start({name}) *health.report_start()*
+ Starts a new report. Most plugins should call this only once, but if
+ you want different sections to appear in your report, call this once
+ per section.
+
+health.report_info({msg}) *health.report_info()*
+ Reports an informational message.
+
+health.report_ok({msg}) *health.report_ok()*
+ Reports a "success" message.
+
+health.report_warn({msg} [, {advice}]) *health.report_warn()*
+ Reports a warning. {advice} is an optional List of suggestions.
+
+health.report_error({msg} [, {advice}]) *health.report_error()*
+ Reports an error. {advice} is an optional List of suggestions.
+
+==============================================================================
+Create a Lua healthcheck *health-dev-lua*
+
+Healthchecks are functions that check the user environment, configuration,
+etc. Nvim has built-in healthchecks in $VIMRUNTIME/autoload/health/.
-health.vim functions are for creating new healthchecks. They mostly just do
-some layout and formatting, to give users a consistent presentation.
+To add a new healthcheck for your own plugin, simply define a Lua module in
+your plugin that returns a table with a "check()" function. |:checkhealth|
+will automatically find and invoke this function.
-health#report_start({name}) *health#report_start*
- Starts a new report. Most plugins should call this only once, but if
+If your plugin is named "foo", then its healthcheck module should be a file in
+one of these locations on 'runtimepath' or 'packpath':
+ - lua/foo/health/init.lua
+ - lua/foo/health.lua
+
+If your plugin provides a submodule named "bar" for which you want a separate
+healthcheck, define the healthcheck at one of these locations on 'runtimepath'
+or 'packpath':
+ - lua/foo/bar/health/init.lua
+ - lua/foo/bar/health.lua
+
+All submodules should return a Lua table containing the method `check()`.
+
+Copy this sample code into `lua/foo/health/init.lua` or `lua/foo/health.lua`,
+replacing "foo" in the path with your plugin name: >
+
+ local M = {}
+ local health = require("health")
+
+ M.check = function()
+ health.report_start("my_plugin report")
+ -- make sure setup function parameters are ok
+ if check_setup() then
+ health.report_ok("Setup function is correct")
+ else
+ health.report_error("Setup function is incorrect")
+ end
+ -- do some more checking
+ -- ...
+ end
+
+ return M
+
+==============================================================================
+Vimscript Functions *health-functions-vimscript* *health-vimscript*
+
+health.vim functions are for creating new healthchecks. (See also
+|health-functions-lua|)
+
+health#report_start({name}) *health#report_start*
+ Starts a new report. Most plugins should call this only once, but if
you want different sections to appear in your report, call this once
per section.
-health#report_info({msg}) *health#report_info*
- Reports an informational message.
+health#report_info({msg}) *health#report_info*
+ Reports an informational message.
-health#report_ok({msg}) *health#report_ok*
- Reports a "success" message.
+health#report_ok({msg}) *health#report_ok*
+ Reports a "success" message.
-health#report_warn({msg}, [{advice}]) *health#report_warn*
+health#report_warn({msg} [, {advice}]) *health#report_warn*
Reports a warning. {advice} is an optional List of suggestions.
-health#report_error({msg}, [{advice}]) *health#report_error*
+health#report_error({msg} [, {advice}]) *health#report_error*
Reports an error. {advice} is an optional List of suggestions.
-health#{plugin}#check() *health.user_checker*
+health#{plugin}#check() *health.user_checker*
Healthcheck function for {plugin}. Called by |:checkhealth|
automatically. Example: >
- function! health#my_plug#check() abort
- silent call s:check_environment_vars()
- silent call s:check_python_configuration()
- endfunction
+ function! health#my_plug#check() abort
+ silent call s:check_environment_vars()
+ silent call s:check_python_configuration()
+ endfunction
<
- All output will be captured from the healthcheck. Use the
- health#report_* functions so that your healthcheck has a format
- consistent with the standard healthchecks.
-
==============================================================================
-Create a healthcheck *health-dev*
+Create a healthcheck *health-dev-vim*
Healthchecks are functions that check the user environment, configuration,
etc. Nvim has built-in healthchecks in $VIMRUNTIME/autoload/health/.
@@ -88,8 +159,8 @@ health#{plugin}#check() function in autoload/health/{plugin}.vim.
If your plugin is named "foo", then its healthcheck function must be >
health#foo#check()
-defined in this file on 'runtimepath': >
- autoload/health/foo.vim
+defined in this file on 'runtimepath' or 'packpath':
+ - autoload/health/foo.vim
Copy this sample code into autoload/health/foo.vim and replace "foo" with your
plugin name: >
@@ -97,7 +168,7 @@ plugin name: >
call health#report_start('sanity checks')
" perform arbitrary checks
" ...
-
+
if looks_good
call health#report_ok('found required dependencies')
else
@@ -106,6 +177,4 @@ plugin name: >
endif
endfunction
-==============================================================================
-
-vim:tw=78:ts=8:ft=help:fdm=marker
+vim:et:tw=78:ts=8:ft=help:fdm=marker
diff --git a/runtime/doc/print.txt b/runtime/doc/print.txt
index d9320ad315..f54d0429a6 100644
--- a/runtime/doc/print.txt
+++ b/runtime/doc/print.txt
@@ -690,7 +690,7 @@ There are a couple of points to bear in mind:
==============================================================================
8. Formfeed Characters *printing-formfeed*
-By default Vim does not do any special processing of |formfeed| control
+By default Vim does not do any special processing of formfeed control
characters. Setting the 'printoptions' formfeed item will make Vim recognize
formfeed characters and continue printing the current line at the beginning
of the first line on a new page. The use of formfeed characters provides
diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt
index 87a48e6d2a..bb775ec884 100644
--- a/runtime/doc/starting.txt
+++ b/runtime/doc/starting.txt
@@ -90,10 +90,11 @@ argument.
See |info-message| about capturing the text.
*--clean*
---clean Equivalent to "-u NONE -i NONE":
+--clean Mimics a fresh install of Nvim:
- Skips initializations from files and environment variables.
- No 'shada' file is read or written.
- Excludes user directories from 'runtimepath'
+ - Loads builtin plugins, unlike "-u NONE -i NONE".
*--noplugin*
--noplugin Skip loading plugins. Resets the 'loadplugins' option.
diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt
index ac10aeec88..441ae13df4 100644
--- a/runtime/doc/treesitter.txt
+++ b/runtime/doc/treesitter.txt
@@ -531,9 +531,11 @@ Query:iter_matches({self}, {node}, {source}, {start}, {stop})
for id, node in pairs(match) do
local name = query.captures[id]
-- `node` was captured by the `name` capture in the match
-
- local node_data = metadata[id] -- Node level metadata
-
+<
+>
+ local node_data = metadata[id] -- Node level metadata
+<
+>
... use the info here ...
end
end
diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt
index 5d70834ddc..c575dd9fd8 100644
--- a/runtime/doc/usr_41.txt
+++ b/runtime/doc/usr_41.txt
@@ -1804,7 +1804,7 @@ First of all you must choose a name for your plugin. The features provided
by the plugin should be clear from its name. And it should be unlikely that
someone else writes a plugin with the same name but which does something
different. And please limit the name to 8 characters, to avoid problems on
-old Windows systems.
+old MS-Windows systems.
A script that corrects typing mistakes could be called "typecorr.vim". We
will use it here as an example.
diff --git a/runtime/filetype.vim b/runtime/filetype.vim
index bc3965d4b6..c86ca9646b 100644
--- a/runtime/filetype.vim
+++ b/runtime/filetype.vim
@@ -1,7 +1,7 @@
" Vim support file to detect file types
"
" Maintainer: Bram Moolenaar <Bram@vim.org>
-" Last Change: 2021 Sep 21
+" Last Change: 2021 Oct 03
" Listen very carefully, I will say this only once
if exists("did_load_filetypes")
@@ -872,6 +872,9 @@ au BufNewFile,BufRead *.json-patch setf json
" Jupyter Notebook is also json
au BufNewFile,BufRead *.ipynb setf json
+" Other files that look like json
+au BufNewFile,BufRead .babelrc,.eslintrc,.prettierrc,.firebaserc setf json
+
" JSONC
au BufNewFile,BufRead *.jsonc setf jsonc
@@ -1106,6 +1109,9 @@ au BufNewFile,BufRead *.mysql setf mysql
" Mutt setup files (must be before catch *.rc)
au BufNewFile,BufRead */etc/Muttrc.d/* call s:StarSetf('muttrc')
+" Tcl Shell RC file
+au BufNewFile,BufRead tclsh.rc setf tcl
+
" M$ Resource files
au BufNewFile,BufRead *.rc,*.rch setf rc
@@ -1136,6 +1142,9 @@ au BufNewFile,BufRead Neomuttrc setf neomuttrc
" Netrc
au BufNewFile,BufRead .netrc setf netrc
+" Nginx
+au BufNewFile,BufRead *.nginx,nginx*.conf,*nginx.conf,*/etc/nginx/*,*/usr/local/nginx/conf/*,*/nginx/*.conf setf nginx
+
" Ninja file
au BufNewFile,BufRead *.ninja setf ninja
@@ -1798,7 +1807,7 @@ au BufRead,BufNewFile {pending,completed,undo}.data setf taskdata
au BufRead,BufNewFile *.task setf taskedit
" Tcl (JACL too)
-au BufNewFile,BufRead *.tcl,*.tk,*.itcl,*.itk,*.jacl setf tcl
+au BufNewFile,BufRead *.tcl,*.tm,*.tk,*.itcl,*.itk,*.jacl,.tclshrc,.wishrc setf tcl
" TealInfo
au BufNewFile,BufRead *.tli setf tli
@@ -1995,14 +2004,15 @@ au BufNewFile,BufRead *.ws[fc] setf wsh
" XHTML
au BufNewFile,BufRead *.xhtml,*.xht setf xhtml
-" X Pixmap (dynamically sets colors, use BufEnter to make it work better)
-au BufEnter *.xpm
+" X Pixmap (dynamically sets colors, this used to trigger on BufEnter to make
+" it work better, but that breaks setting 'filetype' manually)
+au BufNewFile,BufRead *.xpm
\ if getline(1) =~ "XPM2" |
\ setf xpm2 |
\ else |
\ setf xpm |
\ endif
-au BufEnter *.xpm2 setf xpm2
+au BufNewFile,BufRead *.xpm2 setf xpm2
" XFree86 config
au BufNewFile,BufRead XF86Config
diff --git a/runtime/ftplugin/nginx.vim b/runtime/ftplugin/nginx.vim
new file mode 100644
index 0000000000..e808db1277
--- /dev/null
+++ b/runtime/ftplugin/nginx.vim
@@ -0,0 +1,6 @@
+" Vim filetype plugin
+" Language: nginx.conf
+" Maintainer: Chris Aumann <me@chr4.org>
+" Last Change: Apr 15, 2017
+
+setlocal commentstring=#\ %s
diff --git a/runtime/ftplugin/spec.vim b/runtime/ftplugin/spec.vim
index ce00021a69..75eebec56a 100644
--- a/runtime/ftplugin/spec.vim
+++ b/runtime/ftplugin/spec.vim
@@ -18,8 +18,8 @@ if !exists("no_plugin_maps") && !exists("no_spec_maps")
endif
endif
-if !hasmapto("call <SID>SpecChangelog(\"\")<CR>")
- noremap <buffer> <unique> <script> <Plug>SpecChangelog :call <SID>SpecChangelog("")<CR>
+if !hasmapto("call SpecChangelog(\"\")<CR>")
+ noremap <buffer> <unique> <script> <Plug>SpecChangelog :call SpecChangelog("")<CR>
endif
if !exists("*s:GetRelVer")
diff --git a/runtime/indent/cdl.vim b/runtime/indent/cdl.vim
index fb4fe27310..0e3c6152b0 100644
--- a/runtime/indent/cdl.vim
+++ b/runtime/indent/cdl.vim
@@ -1,5 +1,6 @@
" Description: Comshare Dimension Definition Language (CDL)
-" Author: Raul Segura Acevedo <raulseguraaceved@netscape.net>
+" Maintainer: Raul Segura Acevedo <raulseguraaceved@netscape.net> (Invalid email address)
+" Doug Kearns <dougkearns@gmail.com>
" Last Change: Fri Nov 30 13:35:48 2001 CST
if exists("b:did_indent")
diff --git a/runtime/indent/cobol.vim b/runtime/indent/cobol.vim
index 590a729df4..01f7212602 100644
--- a/runtime/indent/cobol.vim
+++ b/runtime/indent/cobol.vim
@@ -7,6 +7,7 @@
" Ankit Jain 22.03.2019 Changes & fixes:
" Allow chars in 1st 6 columns
" #C22032019
+" Ankit Jain 24.09.2021 add b:undo_indent (request by tpope)
if exists("b:did_indent")
finish
@@ -18,6 +19,8 @@ setlocal indentexpr=GetCobolIndent(v:lnum)
setlocal indentkeys&
setlocal indentkeys+=0<*>,0/,0$,0=01,=~division,=~section,0=~end,0=~then,0=~else,0=~when,*<Return>,.
+let b:undo_indent = "setlocal expandtab< indentexpr< indentkeys<"
+
" Only define the function once.
if exists("*GetCobolIndent")
finish
diff --git a/runtime/indent/config.vim b/runtime/indent/config.vim
index c987a78d64..b840b1e391 100644
--- a/runtime/indent/config.vim
+++ b/runtime/indent/config.vim
@@ -1,9 +1,10 @@
" Vim indent file
-" Language: Autoconf configure.{ac,in} file
-" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
-" Latest Revision: 2006-12-20
-" TODO: how about nested [()]'s in one line
-" what's wrong with '\\\@!'?
+" Language: Autoconf configure.{ac,in} file
+" Maintainer: Doug Kearns <dougkearns@gmail.com>
+" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
+" Last Change: 24 Sep 2021
+
+" TODO: how about nested [()]'s in one line what's wrong with '\\\@!'?
" Only load this indent file when no other was loaded.
if exists("b:did_indent")
@@ -16,6 +17,8 @@ setlocal indentexpr=GetConfigIndent()
setlocal indentkeys=!^F,o,O,=then,=do,=else,=elif,=esac,=fi,=fin,=fil,=done
setlocal nosmartindent
+let b:undo_indent = "setl inde< indk< si<"
+
" Only define the function once.
if exists("*GetConfigIndent")
finish
diff --git a/runtime/indent/css.vim b/runtime/indent/css.vim
index 4d15b8d2dc..793f05820f 100644
--- a/runtime/indent/css.vim
+++ b/runtime/indent/css.vim
@@ -1,8 +1,10 @@
" Vim indent file
-" Language: CSS
-" Maintainer: Nikolai Weibull <now@bitwi.se>
-" Latest Revision: 2012-05-30
-" Use of shiftwidth() added by Oleg Zubchenko.
+" Language: CSS
+" Maintainer: Doug Kearns <dougkearns@gmail.com>
+" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
+" Last Change: 24 Sep 2021
+
+" Use of shiftwidth() added by Oleg Zubchenko.
if exists("b:did_indent")
finish
@@ -13,7 +15,7 @@ setlocal indentexpr=GetCSSIndent()
setlocal indentkeys=0{,0},!^F,o,O
setlocal nosmartindent
-let b:undo_indent = "setl smartindent< indentkeys< indentexpr<"
+let b:undo_indent = "setl inde< indk< si<"
if exists("*GetCSSIndent")
finish
diff --git a/runtime/indent/d.vim b/runtime/indent/d.vim
index b5dd5e8fa7..57f9125890 100644
--- a/runtime/indent/d.vim
+++ b/runtime/indent/d.vim
@@ -1,7 +1,7 @@
" Vim indent file for the D programming language (version 0.137).
-"
" Language: D
-" Maintainer: Jason Mills<jmills@cs.mun.ca>
+" Maintainer: Jason Mills <jmills@cs.mun.ca> (Invalid email address)
+" Doug Kearns <dougkearns@gmail.com>
" Last Change: 2005 Nov 22
" Version: 0.1
"
diff --git a/runtime/indent/dtd.vim b/runtime/indent/dtd.vim
index 30c06aa8b2..c2b3c0c58e 100644
--- a/runtime/indent/dtd.vim
+++ b/runtime/indent/dtd.vim
@@ -1,12 +1,15 @@
" Vim indent file
-" Language: DTD (Document Type Definition for XML)
-" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
-" Latest Revision: 2011-07-08
+" Language: DTD (Document Type Definition for XML)
+" Maintainer: Doug Kearns <dougkearns@gmail.com>
+" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
+" Last Change: 24 Sep 2021
setlocal indentexpr=GetDTDIndent()
setlocal indentkeys=!^F,o,O,>
setlocal nosmartindent
+let b:undo_indent = "setl inde< indk< si<"
+
if exists("*GetDTDIndent")
finish
endif
diff --git a/runtime/indent/dylan.vim b/runtime/indent/dylan.vim
index 6811ec4af5..55255ddfa9 100644
--- a/runtime/indent/dylan.vim
+++ b/runtime/indent/dylan.vim
@@ -1,8 +1,9 @@
" Vim indent file
" Language: Dylan
+" Maintainer: Brent A. Fulgham <bfulgham@debian.org> (Invalid email address)
+" Doug Kearns <dougkearns@gmail.com>
" Version: 0.01
" Last Change: 2017 Jun 13
-" Maintainer: Brent A. Fulgham <bfulgham@debian.org>
" Only load this indent file when no other was loaded.
if exists("b:did_indent")
diff --git a/runtime/indent/elm.vim b/runtime/indent/elm.vim
index 232c347c66..7b08de7126 100644
--- a/runtime/indent/elm.vim
+++ b/runtime/indent/elm.vim
@@ -4,7 +4,7 @@
" Original Author: Joseph Hager <ajhager@gmail.com>
" Copyright: Joseph Hager <ajhager@gmail.com>
" License: BSD3
-" Latest Revision: 2020-05-29
+" Latest Revision: 2021-09-29
" Only load this indent file when no other was loaded.
if exists('b:did_indent')
@@ -19,6 +19,8 @@ setlocal indentkeys+=0=else,0=if,0=of,0=import,0=then,0=type,0\|,0},0\],0),=-},0
setlocal nolisp
setlocal nosmartindent
+let b:undo_indent = "setl et< inde< indk< lisp< si<"
+
" Only define the function once.
if exists('*GetElmIndent')
finish
diff --git a/runtime/indent/eterm.vim b/runtime/indent/eterm.vim
index 8ee342fcfa..3accf9bff1 100644
--- a/runtime/indent/eterm.vim
+++ b/runtime/indent/eterm.vim
@@ -1,7 +1,8 @@
" Vim indent file
-" Language: Eterm configuration file
-" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
-" Latest Revision: 2006-12-20
+" Language: Eterm configuration file
+" Maintainer: Doug Kearns <dougkearns@gmail.com>
+" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
+" Last Change: 24 Sep 2021
if exists("b:did_indent")
finish
@@ -12,6 +13,8 @@ setlocal indentexpr=GetEtermIndent()
setlocal indentkeys=!^F,o,O,=end
setlocal nosmartindent
+let b:undo_indent = "setl inde< indk< si<"
+
if exists("*GetEtermIndent")
finish
endif
diff --git a/runtime/indent/framescript.vim b/runtime/indent/framescript.vim
index f9a274eab6..4611d34e85 100644
--- a/runtime/indent/framescript.vim
+++ b/runtime/indent/framescript.vim
@@ -1,7 +1,8 @@
" Vim indent file
-" Language: FrameScript
-" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
-" Latest Revision: 2008-07-19
+" Language: FrameScript
+" Maintainer: Doug Kearns <dougkearns@gmail.com>
+" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
+" Last Change: 24 Sep 2021
if exists("b:did_indent")
finish
@@ -12,6 +13,8 @@ setlocal indentexpr=GetFrameScriptIndent()
setlocal indentkeys=!^F,o,O,0=~Else,0=~EndIf,0=~EndLoop,0=~EndSub
setlocal nosmartindent
+let b:undo_indent = "setl inde< indk< si<"
+
if exists("*GetFrameScriptIndent")
finish
endif
diff --git a/runtime/indent/idlang.vim b/runtime/indent/idlang.vim
index 7402e8688e..e6a1d73775 100644
--- a/runtime/indent/idlang.vim
+++ b/runtime/indent/idlang.vim
@@ -1,7 +1,8 @@
" IDL (Interactive Data Language) indent file.
-" Language: IDL (ft=idlang)
+" Language: IDL (ft=idlang)
+" Maintainer: Aleksandar Jelenak <ajelenak AT yahoo.com> (Invalid email address)
+" Doug Kearns <dougkearns@gmail.com>
" Last change: 2017 Jun 13
-" Maintainer: Aleksandar Jelenak <ajelenak AT yahoo.com>
" Only load this indent file when no other was loaded.
if exists("b:did_indent")
diff --git a/runtime/indent/ld.vim b/runtime/indent/ld.vim
index a72a3a9548..ddf003e2de 100644
--- a/runtime/indent/ld.vim
+++ b/runtime/indent/ld.vim
@@ -1,7 +1,8 @@
" Vim indent file
-" Language: ld(1) script
-" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
-" Latest Revision: 2006-12-20
+" Language: ld(1) script
+" Maintainer: Doug Kearns <dougkearns@gmail.com>
+" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
+" Last Change: 24 Sep 2021
if exists("b:did_indent")
finish
@@ -12,6 +13,8 @@ setlocal indentexpr=GetLDIndent()
setlocal indentkeys=0{,0},!^F,o,O
setlocal nosmartindent
+let b:undo_indent = "setl inde< indk< si<"
+
if exists("*GetLDIndent")
finish
endif
diff --git a/runtime/indent/mail.vim b/runtime/indent/mail.vim
index 6246b407e9..22bb0f7e12 100644
--- a/runtime/indent/mail.vim
+++ b/runtime/indent/mail.vim
@@ -1,7 +1,7 @@
" Vim indent file
" Language: Mail
" Maintainer: Bram Moolenaar
-" Last Change: 2009 Jun 03
+" Last Change: 2021 Sep 26
if exists("b:did_indent")
finish
@@ -11,3 +11,5 @@ let b:did_indent = 1
" What works best is auto-indenting, disable other indenting.
" For formatting see the ftplugin.
setlocal autoindent nosmartindent nocindent indentexpr=
+
+let b:undo_indent = "setl ai< cin< inde< si<"
diff --git a/runtime/indent/make.vim b/runtime/indent/make.vim
index 4483efdbd8..76c8f83399 100644
--- a/runtime/indent/make.vim
+++ b/runtime/indent/make.vim
@@ -1,7 +1,8 @@
" Vim indent file
-" Language: Makefile
-" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
-" Latest Revision: 2007-05-07
+" Language: Makefile
+" Maintainer: Doug Kearns <dougkearns@gmail.com>
+" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
+" Last Change: 24 Sep 2021
if exists("b:did_indent")
finish
@@ -12,6 +13,8 @@ setlocal indentexpr=GetMakeIndent()
setlocal indentkeys=!^F,o,O,<:>,=else,=endif
setlocal nosmartindent
+let b:undo_indent = "setl ai< inde< indk<"
+
if exists("*GetMakeIndent")
finish
endif
diff --git a/runtime/indent/matlab.vim b/runtime/indent/matlab.vim
index 6390445c60..10d84602af 100644
--- a/runtime/indent/matlab.vim
+++ b/runtime/indent/matlab.vim
@@ -2,6 +2,7 @@
" Language: MATLAB
" Maintainer: Axel Forsman <axelsfor@gmail.com>
" Previous maintainer: Christophe Poucet <christophe.poucet@pandora.be>
+" Last Update: 2021-10-01
" Only load if no other indent file is loaded
if exists('b:did_indent') | finish | endif
@@ -9,6 +10,7 @@ let b:did_indent = 1
setlocal indentexpr=GetMatlabIndent()
setlocal indentkeys=!,o,O,e,0=end,0=elseif,0=case,0=otherwise,0=catch,0=function,0=elsei
+let b:undo_indent = "setlocal indentexpr< indentkeys<"
" The value of the Function indenting format in
" MATLAB Editor/Debugger Language Preferences.
diff --git a/runtime/indent/mma.vim b/runtime/indent/mma.vim
index a76fa8ede0..ebf98b9a38 100644
--- a/runtime/indent/mma.vim
+++ b/runtime/indent/mma.vim
@@ -1,9 +1,10 @@
" Vim indent file
-" Language: Mathematica
-" Author: steve layland <layland@wolfram.com>
-" Last Change: Sat May 10 18:56:22 CDT 2005
-" Source: http://vim.sourceforge.net/scripts/script.php?script_id=1274
-" http://members.wolfram.com/layland/vim/indent/mma.vim
+" Language: Mathematica
+" Maintainer: Steve Layland <layland@wolfram.com> (Invalid email address)
+" Doug Kearns <dougkearns@gmail.com>
+" Last Change: Sat May 10 18:56:22 CDT 2005
+" Source: http://vim.sourceforge.net/scripts/script.php?script_id=1274
+" http://members.wolfram.com/layland/vim/indent/mma.vim
"
" NOTE:
" Empty .m files will automatically be presumed to be Matlab files
diff --git a/runtime/indent/nginx.vim b/runtime/indent/nginx.vim
new file mode 100644
index 0000000000..d4afec1c11
--- /dev/null
+++ b/runtime/indent/nginx.vim
@@ -0,0 +1,17 @@
+" Vim indent file
+" Language: nginx.conf
+" Maintainer: Chris Aumann <me@chr4.org>
+" Last Change: Apr 15, 2017
+
+if exists("b:did_indent")
+ finish
+endif
+let b:did_indent = 1
+
+setlocal indentexpr=
+
+" cindent actually works for nginx' simple file structure
+setlocal cindent
+
+" Just make sure that the comments are not reset as defs would be.
+setlocal cinkeys-=0#
diff --git a/runtime/indent/occam.vim b/runtime/indent/occam.vim
index 4acd42e3c8..2979ac16ac 100644
--- a/runtime/indent/occam.vim
+++ b/runtime/indent/occam.vim
@@ -1,6 +1,7 @@
" Vim indent file
" Language: occam
-" Maintainer: Mario Schweigler <ms44@kent.ac.uk>
+" Maintainer: Mario Schweigler <ms44@kent.ac.uk> (Invalid email address)
+" Doug Kearns <dougkearns@gmail.com>
" Last Change: 23 April 2003
" Only load this indent file when no other was loaded.
diff --git a/runtime/indent/pascal.vim b/runtime/indent/pascal.vim
index 1f39fd1cad..b21b7256b2 100644
--- a/runtime/indent/pascal.vim
+++ b/runtime/indent/pascal.vim
@@ -2,11 +2,9 @@
" Language: Pascal
" Maintainer: Neil Carter <n.carter@swansea.ac.uk>
" Created: 2004 Jul 13
-" Last Change: 2021 Jul 01
+" Last Change: 2021 Sep 22
"
-" This is version 2.0, a complete rewrite.
-"
-" For further documentation, see http://psy.swansea.ac.uk/staff/carter/vim/
+" For further documentation, see https://psy.swansea.ac.uk/staff/carter/vim/
if exists("b:did_indent")
@@ -20,13 +18,14 @@ setlocal indentkeys+==end;,==const,==type,==var,==begin,==repeat,==until,==for
setlocal indentkeys+==program,==function,==procedure,==object,==private
setlocal indentkeys+==record,==if,==else,==case
-let b:undo_indent = "setl indentkeys< indentexpr<"
+let b:undo_indent = 'setlocal indentexpr< indentkeys<'
if exists("*GetPascalIndent")
finish
endif
+" ________________________________________________________________
function! s:GetPrevNonCommentLineNum( line_num )
" Skip lines starting with a comment
@@ -44,6 +43,7 @@ function! s:GetPrevNonCommentLineNum( line_num )
endfunction
+" ________________________________________________________________
function! s:PurifyCode( line_num )
" Strip any trailing comments and whitespace
let pureline = 'TODO'
@@ -51,6 +51,7 @@ function! s:PurifyCode( line_num )
endfunction
+" ________________________________________________________________
function! GetPascalIndent( line_num )
" Line 0 always goes at column 0
@@ -184,7 +185,7 @@ function! GetPascalIndent( line_num )
endif
-" ____________________________________________________________________
+" ________________________________________________________________
" Object/Borland Pascal/Delphi Extensions
"
" Note that extended-pascal is handled here, unless it is simpler to
@@ -222,8 +223,6 @@ function! GetPascalIndent( line_num )
endif
-" ____________________________________________________________________
-
" If nothing changed, return same indent.
return indnt
endfunction
diff --git a/runtime/indent/postscr.vim b/runtime/indent/postscr.vim
index 2592bcf62f..0691cd237c 100644
--- a/runtime/indent/postscr.vim
+++ b/runtime/indent/postscr.vim
@@ -1,7 +1,8 @@
" PostScript indent file
-" Language: PostScript
-" Maintainer: Mike Williams <mrw@netcomuk.co.uk>
-" Last Change: 2nd July 2001
+" Language: PostScript
+" Maintainer: Mike Williams <mrw@netcomuk.co.uk> (Invalid email address)
+" Doug Kearns <dougkearns@gmail.com>
+" Last Change: 2nd July 2001
"
" Only load this indent file when no other was loaded.
diff --git a/runtime/indent/prolog.vim b/runtime/indent/prolog.vim
index ecd0894166..ac03c28064 100644
--- a/runtime/indent/prolog.vim
+++ b/runtime/indent/prolog.vim
@@ -1,7 +1,8 @@
" vim: set sw=4 sts=4:
-" Maintainer : Gergely Kontra <kgergely@mcl.hu>
-" Revised on : 2002.02.18. 23:34:05
-" Language : Prolog
+" Language: Prolog
+" Maintainer: Gergely Kontra <kgergely@mcl.hu> (Invalid email address)
+" Doug Kearns <dougkearns@gmail.com>
+" Revised on: 2002.02.18. 23:34:05
" Last change by: Takuya Fujiwara, 2018 Sep 23
" TODO:
diff --git a/runtime/indent/python.vim b/runtime/indent/python.vim
index 307b7f656b..668122993e 100644
--- a/runtime/indent/python.vim
+++ b/runtime/indent/python.vim
@@ -2,7 +2,7 @@
" Language: Python
" Maintainer: Bram Moolenaar <Bram@vim.org>
" Original Author: David Bustos <bustos@caltech.edu>
-" Last Change: 2021 May 26
+" Last Change: 2021 Sep 26
" Only load this indent file when no other was loaded.
if exists("b:did_indent")
@@ -17,6 +17,8 @@ setlocal autoindent " indentexpr isn't much help otherwise
setlocal indentexpr=GetPythonIndent(v:lnum)
setlocal indentkeys+=<:>,=elif,=except
+let b:undo_indent = "setl ai< inde< indk< lisp<"
+
" Only define the function once.
if exists("*GetPythonIndent")
finish
diff --git a/runtime/indent/readline.vim b/runtime/indent/readline.vim
index e202ddfd89..0ab0f822c3 100644
--- a/runtime/indent/readline.vim
+++ b/runtime/indent/readline.vim
@@ -1,7 +1,8 @@
" Vim indent file
-" Language: readline configuration file
-" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
-" Latest Revision: 2006-12-20
+" Language: readline configuration file
+" Maintainer: Doug Kearns <dougkearns@gmail.com>
+" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
+" Last Change: 24 Sep 2021
if exists("b:did_indent")
finish
@@ -12,6 +13,8 @@ setlocal indentexpr=GetReadlineIndent()
setlocal indentkeys=!^F,o,O,=$else,=$endif
setlocal nosmartindent
+let b:undo_indent = "setl inde< indk< si<"
+
if exists("*GetReadlineIndent")
finish
endif
diff --git a/runtime/indent/sdl.vim b/runtime/indent/sdl.vim
index 6ce30b6797..40fe63fa7c 100644
--- a/runtime/indent/sdl.vim
+++ b/runtime/indent/sdl.vim
@@ -1,7 +1,7 @@
" Vim indent file
" Language: SDL
" Maintainer: Michael Piefel <entwurf@piefel.de>
-" Last Change: 10 December 2011
+" Last Change: 2021 Oct 03
" Shamelessly stolen from the Vim-Script indent file
@@ -14,6 +14,8 @@ let b:did_indent = 1
setlocal indentexpr=GetSDLIndent()
setlocal indentkeys+==~end,=~state,*<Return>
+let b:undo_indent = "setl inde< indk<"
+
" Only define the function once.
if exists("*GetSDLIndent")
" finish
diff --git a/runtime/indent/tcl.vim b/runtime/indent/tcl.vim
index eafb8dd568..c35150d0e0 100644
--- a/runtime/indent/tcl.vim
+++ b/runtime/indent/tcl.vim
@@ -1,8 +1,8 @@
" Vim indent file
-" Language: Tcl
-" Latest Update: Chris Heithoff <chrisheithoff@gmail.com>
+" Language: Tcl
+" Maintainer: Chris Heithoff <chrisheithoff@gmail.com>
" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
-" Latest Revision: 2018-12-05
+" Last Change: 24 Sep 2021
if exists("b:did_indent")
finish
@@ -13,6 +13,8 @@ setlocal indentexpr=GetTclIndent()
setlocal indentkeys=0{,0},!^F,o,O,0]
setlocal nosmartindent
+let b:undo_indent = "setl inde< indk< si<"
+
if exists("*GetTclIndent")
finish
endif
diff --git a/runtime/indent/tcsh.vim b/runtime/indent/tcsh.vim
index ed08e6c6e2..025d9c805d 100644
--- a/runtime/indent/tcsh.vim
+++ b/runtime/indent/tcsh.vim
@@ -1,7 +1,7 @@
" Vim indent file
" Language: C-shell (tcsh)
-" Maintainer: GI <a@b.c>, where a='gi1242+vim', b='gmail', c='com'
-" Last Modified: Sat 10 Dec 2011 09:23:00 AM EST
+" Maintainer: Doug Kearns <a@b.com> where a=dougkearns, b=gmail
+" Last Modified: Sun 26 Sep 2021 12:38:38 PM EDT
" Only load this indent file when no other was loaded.
if exists("b:did_indent")
@@ -12,6 +12,7 @@ let b:did_indent = 1
setlocal indentexpr=TcshGetIndent()
setlocal indentkeys+=e,0=end,0=endsw indentkeys-=0{,0},0),:,0#
+let b:undo_indent = "setl inde< indk<"
" Only define the function once.
if exists("*TcshGetIndent")
diff --git a/runtime/indent/zimbu.vim b/runtime/indent/zimbu.vim
index 5451877ea7..0e6e2ab1d1 100644
--- a/runtime/indent/zimbu.vim
+++ b/runtime/indent/zimbu.vim
@@ -1,7 +1,7 @@
" Vim indent file
" Language: Zimbu
" Maintainer: Bram Moolenaar <Bram@vim.org>
-" Last Change: 2016 Jan 25
+" Last Change: 2021 Sep 26
" Only load this indent file when no other was loaded.
if exists("b:did_indent")
@@ -16,7 +16,7 @@ setlocal indentkeys=0{,0},!^F,o,O,0=ELSE,0=ELSEIF,0=CASE,0=DEFAULT,0=FINALLY
" We impose recommended defaults: no Tabs, 'shiftwidth' = 2
setlocal sw=2 et
-let b:undo_indent = "setl et< sw< ai< indentkeys< indentexpr="
+let b:undo_indent = "setl ai< cin< et< indentkeys< indentexpr< lisp< sw<"
" Only define the function once.
if exists("*GetZimbuIndent")
diff --git a/runtime/lua/health.lua b/runtime/lua/health.lua
new file mode 100644
index 0000000000..142a353bf2
--- /dev/null
+++ b/runtime/lua/health.lua
@@ -0,0 +1,23 @@
+local M = {}
+
+function M.report_start(msg)
+ vim.fn['health#report_start'](msg)
+end
+
+function M.report_info(msg)
+ vim.fn['health#report_info'](msg)
+end
+
+function M.report_ok(msg)
+ vim.fn['health#report_ok'](msg)
+end
+
+function M.report_warn(msg, ...)
+ vim.fn['health#report_warn'](msg, ...)
+end
+
+function M.report_error(msg, ...)
+ vim.fn['health#report_error'](msg, ...)
+end
+
+return M
diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua
index 00945a7fb3..c7c8c1878e 100644
--- a/runtime/lua/vim/diagnostic.lua
+++ b/runtime/lua/vim/diagnostic.lua
@@ -556,6 +556,9 @@ end
--- - signs: (default true) Use signs for diagnostics. Options:
--- * severity: Only show signs for diagnostics matching the given severity
--- |diagnostic-severity|
+--- * priority: (number, default 10) Base priority to use for signs. When
+--- {severity_sort} is used, the priority of a sign is adjusted based on
+--- its severity. Otherwise, all signs use the same priority.
--- - update_in_insert: (default false) Update diagnostics in Insert mode (if false,
--- diagnostics are updated on InsertLeave)
--- - severity_sort: (default false) Sort diagnostics by severity. This affects the order in
@@ -617,23 +620,22 @@ function M.set(namespace, bufnr, diagnostics, opts)
}
if vim.tbl_isempty(diagnostics) then
- return M.reset(namespace, bufnr)
- end
-
- if not diagnostic_cleanup[bufnr][namespace] then
- diagnostic_cleanup[bufnr][namespace] = true
-
- -- Clean up our data when the buffer unloads.
- vim.api.nvim_buf_attach(bufnr, false, {
- on_detach = function(_, b)
- clear_diagnostic_cache(b, namespace)
- diagnostic_cleanup[b][namespace] = nil
- end
- })
+ clear_diagnostic_cache(namespace, bufnr)
+ else
+ if not diagnostic_cleanup[bufnr][namespace] then
+ diagnostic_cleanup[bufnr][namespace] = true
+
+ -- Clean up our data when the buffer unloads.
+ vim.api.nvim_buf_attach(bufnr, false, {
+ on_detach = function(_, b)
+ clear_diagnostic_cache(b, namespace)
+ diagnostic_cleanup[b][namespace] = nil
+ end
+ })
+ end
+ set_diagnostic_cache(namespace, bufnr, diagnostics)
end
- set_diagnostic_cache(namespace, bufnr, diagnostics)
-
if vim.api.nvim_buf_is_loaded(bufnr) then
M.show(namespace, bufnr, diagnostics, opts)
elseif opts then
@@ -643,6 +645,13 @@ function M.set(namespace, bufnr, diagnostics, opts)
vim.api.nvim_command("doautocmd <nomodeline> User DiagnosticsChanged")
end
+--- Get current diagnostic namespaces.
+---
+---@return table A list of active diagnostic namespaces |vim.diagnostic|.
+function M.get_namespaces()
+ return vim.deepcopy(all_namespaces)
+end
+
--- Get current diagnostics.
---
---@param bufnr number|nil Buffer number to get diagnostics from. Use 0 for
diff --git a/runtime/lua/vim/lsp/health.lua b/runtime/lua/vim/lsp/health.lua
index 855679a2df..ed3eea59df 100644
--- a/runtime/lua/vim/lsp/health.lua
+++ b/runtime/lua/vim/lsp/health.lua
@@ -1,7 +1,7 @@
local M = {}
--- Performs a healthcheck for LSP
-function M.check_health()
+function M.check()
local report_info = vim.fn['health#report_info']
local report_warn = vim.fn['health#report_warn']
diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua
index 255eb65dfe..b1bdb24def 100644
--- a/runtime/lua/vim/lsp/rpc.lua
+++ b/runtime/lua/vim/lsp/rpc.lua
@@ -13,36 +13,6 @@ local function is_dir(filename)
return stat and stat.type == 'directory' or false
end
-local NIL = vim.NIL
-
----@private
-local recursive_convert_NIL
-recursive_convert_NIL = function(v, tbl_processed)
- if v == NIL then
- return nil
- elseif not tbl_processed[v] and type(v) == 'table' then
- tbl_processed[v] = true
- local inside_list = vim.tbl_islist(v)
- return vim.tbl_map(function(x)
- if not inside_list or (inside_list and type(x) == "table") then
- return recursive_convert_NIL(x, tbl_processed)
- else
- return x
- end
- end, v)
- end
-
- return v
-end
-
----@private
---- Returns its argument, but converts `vim.NIL` to Lua `nil`.
----@param v (any) Argument
----@returns (any)
-local function convert_NIL(v)
- return recursive_convert_NIL(v, {})
-end
-
---@private
--- Merges current process env with the given env and returns the result as
--- a list of "k=v" strings.
@@ -457,7 +427,7 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
---@private
local function handle_body(body)
- local ok, decoded = pcall(vim.json.decode, body)
+ local ok, decoded = pcall(vim.json.decode, body, { luanil = { object = true } })
if not ok then
on_error(client_errors.INVALID_SERVER_JSON, decoded)
return
@@ -466,8 +436,6 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
if type(decoded.method) == 'string' and decoded.id then
local err
- -- Server Request
- decoded.params = convert_NIL(decoded.params)
-- Schedule here so that the users functions don't trigger an error and
-- we can still use the result.
schedule(function()
@@ -494,9 +462,6 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
end)
-- This works because we are expecting vim.NIL here
elseif decoded.id and (decoded.result ~= vim.NIL or decoded.error ~= vim.NIL) then
- -- Server Result
- decoded.error = convert_NIL(decoded.error)
- decoded.result = convert_NIL(decoded.result)
-- We sent a number, so we expect a number.
local result_id = tonumber(decoded.id)
@@ -544,7 +509,6 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
end
elseif type(decoded.method) == 'string' then
-- Notification
- decoded.params = convert_NIL(decoded.params)
try_call(client_errors.NOTIFICATION_HANDLER_ERROR,
dispatchers.notification, decoded.method, decoded.params)
else
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index e95f170427..fca956fb57 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -951,6 +951,11 @@ end
---@param width (number) window width (in character cells)
---@param height (number) window height (in character cells)
---@param opts (table, optional)
+--- - offset_x (number) offset to add to `col`
+--- - offset_y (number) offset to add to `row`
+--- - border (string or table) override `border`
+--- - focusable (string or table) override `focusable`
+--- - zindex (string or table) override `zindex`, defaults to 50
---@returns (table) Options
function M.make_floating_popup_options(width, height, opts)
validate {
@@ -975,7 +980,7 @@ function M.make_floating_popup_options(width, height, opts)
else
anchor = anchor..'S'
height = math.min(lines_above, height)
- row = -get_border_size(opts).height
+ row = 0
end
if vim.fn.wincol() + width + (opts.offset_x or 0) <= api.nvim_get_option('columns') then
@@ -1124,8 +1129,6 @@ end
--- - wrap_at character to wrap at for computing height
--- - max_width maximal width of floating window
--- - max_height maximal height of floating window
---- - pad_left number of columns to pad contents at left
---- - pad_right number of columns to pad contents at right
--- - pad_top number of lines to pad contents at top
--- - pad_bottom number of lines to pad contents at bottom
--- - separator insert separator after code block
@@ -1376,8 +1379,6 @@ end
--- - wrap_at character to wrap at for computing height when wrap is enabled
--- - max_width maximal width of floating window
--- - max_height maximal height of floating window
---- - pad_left number of columns to pad contents at left
---- - pad_right number of columns to pad contents at right
--- - pad_top number of lines to pad contents at top
--- - pad_bottom number of lines to pad contents at bottom
--- - focus_id if a popup with this id is opened, then focus it
diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua
index 18c1e21049..b57b7ad4ad 100644
--- a/runtime/lua/vim/shared.lua
+++ b/runtime/lua/vim/shared.lua
@@ -98,17 +98,53 @@ end
--- <pre>
--- split(":aa::b:", ":") --> {'','aa','','b',''}
--- split("axaby", "ab?") --> {'','x','y'}
---- split(x*yz*o, "*", true) --> {'x','yz','o'}
+--- split("x*yz*o", "*", {plain=true}) --> {'x','yz','o'}
+--- split("|x|y|z|", "|", {trimempty=true}) --> {'x', 'y', 'z'}
--- </pre>
---
+---
---@see |vim.gsplit()|
---
---@param s String to split
---@param sep Separator string or pattern
----@param plain If `true` use `sep` literally (passed to String.find)
+---@param kwargs Keyword arguments:
+--- - plain: (boolean) If `true` use `sep` literally (passed to string.find)
+--- - trimempty: (boolean) If `true` remove empty items from the front
+--- and back of the list
---@returns List-like table of the split components.
-function vim.split(s,sep,plain)
- local t={} for c in vim.gsplit(s, sep, plain) do table.insert(t,c) end
+function vim.split(s, sep, kwargs)
+ local plain
+ local trimempty = false
+ if type(kwargs) == 'boolean' then
+ -- Support old signature for backward compatibility
+ plain = kwargs
+ else
+ vim.validate { kwargs = {kwargs, 't', true} }
+ kwargs = kwargs or {}
+ plain = kwargs.plain
+ trimempty = kwargs.trimempty
+ end
+
+ local t = {}
+ local skip = trimempty
+ for c in vim.gsplit(s, sep, plain) do
+ if c ~= "" then
+ skip = false
+ end
+
+ if not skip then
+ table.insert(t, c)
+ end
+ end
+
+ if trimempty then
+ for i = #t, 1, -1 do
+ if t[i] ~= "" then
+ break
+ end
+ table.remove(t, i)
+ end
+ end
+
return t
end
diff --git a/runtime/lua/vim/treesitter/health.lua b/runtime/lua/vim/treesitter/health.lua
index e031ba1bd6..53ccc6e88d 100644
--- a/runtime/lua/vim/treesitter/health.lua
+++ b/runtime/lua/vim/treesitter/health.lua
@@ -9,7 +9,7 @@ function M.list_parsers()
end
--- Performs a healthcheck for treesitter integration
-function M.check_health()
+function M.check()
local report_info = vim.fn['health#report_info']
local report_ok = vim.fn['health#report_ok']
local report_error = vim.fn['health#report_error']
diff --git a/runtime/plugin/diagnostic.vim b/runtime/plugin/diagnostic.vim
deleted file mode 100644
index 2183623ac8..0000000000
--- a/runtime/plugin/diagnostic.vim
+++ /dev/null
@@ -1,26 +0,0 @@
-" :help vim.diagnostic
-
-hi default DiagnosticError ctermfg=1 guifg=Red
-hi default DiagnosticWarn ctermfg=3 guifg=Orange
-hi default DiagnosticInfo ctermfg=4 guifg=LightBlue
-hi default DiagnosticHint ctermfg=7 guifg=LightGrey
-
-hi default DiagnosticUnderlineError cterm=underline gui=underline guisp=Red
-hi default DiagnosticUnderlineWarn cterm=underline gui=underline guisp=Orange
-hi default DiagnosticUnderlineInfo cterm=underline gui=underline guisp=LightBlue
-hi default DiagnosticUnderlineHint cterm=underline gui=underline guisp=LightGrey
-
-hi default link DiagnosticVirtualTextError DiagnosticError
-hi default link DiagnosticVirtualTextWarn DiagnosticWarn
-hi default link DiagnosticVirtualTextInfo DiagnosticInfo
-hi default link DiagnosticVirtualTextHint DiagnosticHint
-
-hi default link DiagnosticFloatingError DiagnosticError
-hi default link DiagnosticFloatingWarn DiagnosticWarn
-hi default link DiagnosticFloatingInfo DiagnosticInfo
-hi default link DiagnosticFloatingHint DiagnosticHint
-
-hi default link DiagnosticSignError DiagnosticError
-hi default link DiagnosticSignWarn DiagnosticWarn
-hi default link DiagnosticSignInfo DiagnosticInfo
-hi default link DiagnosticSignHint DiagnosticHint
diff --git a/runtime/syntax/8th.vim b/runtime/syntax/8th.vim
index d543489b72..ce27d10a44 100644
--- a/runtime/syntax/8th.vim
+++ b/runtime/syntax/8th.vim
@@ -1,6 +1,7 @@
" Vim syntax file
" Language: 8th
-" Version: 19.01d
+" Version: 21.08
+" Last Change: 2021 Sep 20
" Maintainer: Ron Aaron <ron@aaron-tech.com>
" URL: https://8th-dev.com/
" Filetypes: *.8th
@@ -30,246 +31,318 @@ syn match eighthClassWord "\<\S\+:.\+" contains=eighthClasses
syn keyword eighthEndOfColonDef ; i;
syn keyword eighthDefine var var,
-" Built in words
+" Built in words:
com! -nargs=+ Builtin syn keyword eighthBuiltin <args>
-"Builtin ^ < <# <#> = > - -- ,# ; ;; ! ??? / . .# ' () @ * */ \
-Builtin ! G:! #! G:#! ## G:## #> G:#> #if G:#if ' G:' ( G:( (* G:(* (:) G:(:) (code) G:(code) (getc) G:(getc)
-Builtin (gets) G:(gets) (interp) G:(interp) (needs) G:(needs) (putc) G:(putc) (puts) G:(puts) (putslim) G:(putslim)
-Builtin (say) G:(say) (stat) G:(stat) ) G:) +listener G:+listener +ref G:+ref ,# G:,# -- G:-- -----BEGIN G:-----BEGIN
-Builtin -Inf G:-Inf -Inf? G:-Inf? -listener G:-listener -ref G:-ref -rot G:-rot . G:. .# G:.# .needs G:.needs
-Builtin .r G:.r .s G:.s .stats G:.stats .ver G:.ver .with G:.with 0; G:0; 2dip G:2dip 2drop G:2drop
-Builtin 2dup G:2dup 2over G:2over 2swap G:2swap 3drop G:3drop 4drop G:4drop 8thdt? G:8thdt? 8thver? G:8thver?
-Builtin : G:: ; G:; ;; G:;; ;;; G:;;; ;then G:;then ;with G:;with <# G:<# <#> G:<#> >clip G:>clip >json G:>json
-Builtin >kind G:>kind >n G:>n >r G:>r >s G:>s ?: G:?: ??? G:??? @ G:@ Inf G:Inf Inf? G:Inf? NaN G:NaN
-Builtin NaN? G:NaN? SED-CHECK G:SED-CHECK SED: G:SED: SED: G:SED: \ G:\ ` G:` `` G:`` actor: G:actor:
-Builtin again G:again ahead G:ahead and G:and appname G:appname apropos G:apropos argc G:argc args G:args
-Builtin array? G:array? assert G:assert base G:base bi G:bi bits G:bits break G:break break? G:break?
-Builtin build? G:build? buildver? G:buildver? bye G:bye c# G:c# c/does G:c/does case G:case caseof G:caseof
-Builtin chdir G:chdir clip> G:clip> clone G:clone clone-shallow G:clone-shallow cold G:cold compat-level G:compat-level
-Builtin compile G:compile compile? G:compile? conflict G:conflict const G:const container? G:container?
-Builtin cr G:cr curlang G:curlang curry G:curry curry: G:curry: decimal G:decimal defer: G:defer: deg>rad G:deg>rad
-Builtin depth G:depth die G:die dip G:dip drop G:drop dstack G:dstack dump G:dump dup G:dup dup? G:dup?
-Builtin else G:else enum: G:enum: eval G:eval eval! G:eval! eval0 G:eval0 execnull G:execnull expect G:expect
-Builtin extra! G:extra! extra@ G:extra@ false G:false fnv G:fnv fourth G:fourth free G:free func: G:func:
-Builtin getc G:getc getcwd G:getcwd getenv G:getenv gets G:gets handler G:handler header G:header help G:help
-Builtin hex G:hex i: G:i: i; G:i; if G:if if; G:if; isa? G:isa? items-used G:items-used jcall G:jcall
-Builtin jclass G:jclass jmethod G:jmethod json-nesting G:json-nesting json-pretty G:json-pretty json-throw G:json-throw
-Builtin json> G:json> k32 G:k32 keep G:keep l: G:l: last G:last lib G:lib libbin G:libbin libc G:libc
+Builtin args #:args b #:b dhm #:dhm exec# #:exec# id2ns #:id2ns id? #:id? idd #:idd key #:key oa #:oa
+Builtin oid #:oid okey #:okey with #:with with! #:with! zip #:zip gen-secret 2fa:gen-secret gen-url 2fa:gen-url
+Builtin validate-code 2fa:validate-code ! G:! #! G:#! ## G:## #> G:#> #if G:#if ' G:' ( G:( (* G:(*
+Builtin (:) G:(:) (code) G:(code) (defer) G:(defer) (dump) G:(dump) (getc) G:(getc) (gets) G:(gets)
+Builtin (interp) G:(interp) (log) G:(log) (needs) G:(needs) (parseln) G:(parseln) (putc) G:(putc) (puts) G:(puts)
+Builtin (putslim) G:(putslim) (stat) G:(stat) (with) G:(with) ) G:) +hook G:+hook +listener G:+listener
+Builtin +ref G:+ref ,# G:,# -- G:-- -----BEGIN G:-----BEGIN -Inf G:-Inf -Inf? G:-Inf? -hook G:-hook
+Builtin -listener G:-listener -ref G:-ref -rot G:-rot . G:. .# G:.# .hook G:.hook .needs G:.needs .r G:.r
+Builtin .s G:.s .s-truncate G:.s-truncate .stats G:.stats .ver G:.ver .with G:.with 0; G:0; 2dip G:2dip
+Builtin 2drop G:2drop 2dup G:2dup 2over G:2over 2swap G:2swap 3drop G:3drop 3rev G:3rev 4drop G:4drop
+Builtin 8thdt? G:8thdt? 8thsku G:8thsku 8thver? G:8thver? 8thvernum? G:8thvernum? : G:: ; G:; ;; G:;;
+Builtin ;;; G:;;; ;with G:;with <# G:<# <#> G:<#> >clip G:>clip >json G:>json >kind G:>kind >n G:>n
+Builtin >r G:>r >s G:>s ?: G:?: @ G:@ BITMAP: G:BITMAP: ENUM: G:ENUM: FLAG: G:FLAG: Inf G:Inf Inf? G:Inf?
+Builtin NaN G:NaN NaN? G:NaN? SED-CHECK G:SED-CHECK SED: G:SED: SED: G:SED: \ G:\ _dup G:_dup _swap G:_swap
+Builtin actor: G:actor: again G:again ahead G:ahead and G:and appname G:appname apropos G:apropos argc G:argc
+Builtin args G:args array? G:array? assert G:assert base G:base bi G:bi bits G:bits break G:break break? G:break?
+Builtin breakif G:breakif build? G:build? buildver? G:buildver? bye G:bye c# G:c# c/does G:c/does case: G:case:
+Builtin catch G:catch chdir G:chdir clip> G:clip> clone G:clone clone-shallow G:clone-shallow cold G:cold
+Builtin compile G:compile compile? G:compile? compiling? G:compiling? conflict G:conflict const G:const
+Builtin container? G:container? counting-allocations G:counting-allocations cr G:cr curlang G:curlang
+Builtin curry G:curry curry: G:curry: decimal G:decimal default: G:default: defer: G:defer: deferred: G:deferred:
+Builtin deg>rad G:deg>rad depth G:depth die G:die dip G:dip drop G:drop dstack G:dstack dump G:dump
+Builtin dup G:dup dup>r G:dup>r dup? G:dup? e# G:e# enum: G:enum: error? G:error? eval G:eval eval! G:eval!
+Builtin eval0 G:eval0 execnull G:execnull expect G:expect extra! G:extra! extra@ G:extra@ false G:false
+Builtin fnv G:fnv fourth G:fourth free G:free func: G:func: getc G:getc getcwd G:getcwd getenv G:getenv
+Builtin gets G:gets handler G:handler header G:header help G:help hex G:hex i: G:i: i; G:i; isa? G:isa?
+Builtin items-used G:items-used jcall G:jcall jclass G:jclass jmethod G:jmethod json! G:json! json-8th> G:json-8th>
+Builtin json-nesting G:json-nesting json-pretty G:json-pretty json-throw G:json-throw json> G:json>
+Builtin json@ G:json@ k32 G:k32 keep G:keep l: G:l: last G:last lib G:lib libbin G:libbin libc G:libc
Builtin listener@ G:listener@ literal G:literal locals: G:locals: lock G:lock lock-to G:lock-to locked? G:locked?
-Builtin log G:log log-async G:log-async log-task G:log-task log-time G:log-time log-time-local G:log-time-local
-Builtin long-days G:long-days long-months G:long-months loop G:loop loop- G:loop- map? G:map? mark G:mark
-Builtin mark? G:mark? memfree G:memfree mobile? G:mobile? n# G:n# name>os G:name>os name>sem G:name>sem
-Builtin ndrop G:ndrop needs G:needs new G:new next-arg G:next-arg nip G:nip noop G:noop not G:not ns G:ns
-Builtin ns: G:ns: ns>ls G:ns>ls ns>s G:ns>s ns? G:ns? null G:null null; G:null; null? G:null? number? G:number?
-Builtin off G:off on G:on onexit G:onexit only G:only op! G:op! or G:or os G:os os-names G:os-names
-Builtin os>long-name G:os>long-name os>name G:os>name over G:over p: G:p: pack G:pack parse G:parse
-Builtin parsech G:parsech parseln G:parseln parsews G:parsews pick G:pick poke G:poke pool-clear G:pool-clear
-Builtin prior G:prior private G:private process-args G:process-args prompt G:prompt public G:public
-Builtin putc G:putc puts G:puts putslim G:putslim quote G:quote r! G:r! r> G:r> r@ G:r@ rad>deg G:rad>deg
-Builtin rand G:rand rand-pcg G:rand-pcg rand-pcg-seed G:rand-pcg-seed randbuf G:randbuf randbuf-pcg G:randbuf-pcg
-Builtin rdrop G:rdrop recurse G:recurse recurse-stack G:recurse-stack ref@ G:ref@ reg! G:reg! reg@ G:reg@
-Builtin regbin@ G:regbin@ remaining-args G:remaining-args repeat G:repeat reset G:reset roll G:roll
-Builtin rop! G:rop! rot G:rot rpick G:rpick rroll G:rroll rstack G:rstack rswap G:rswap rusage G:rusage
-Builtin s>ns G:s>ns same? G:same? scriptdir G:scriptdir scriptfile G:scriptfile sem G:sem sem-post G:sem-post
-Builtin sem-rm G:sem-rm sem-wait G:sem-wait sem-wait? G:sem-wait? sem>name G:sem>name semi-throw G:semi-throw
-Builtin set-wipe G:set-wipe setenv G:setenv settings! G:settings! settings![] G:settings![] settings@ G:settings@
-Builtin settings@? G:settings@? settings@[] G:settings@[] sh G:sh sh$ G:sh$ short-days G:short-days
-Builtin short-months G:short-months sleep G:sleep space G:space stack-check G:stack-check stack-size G:stack-size
-Builtin step G:step string? G:string? struct: G:struct: swap G:swap syslang G:syslang sysregion G:sysregion
+Builtin log G:log log-syslog G:log-syslog log-task G:log-task log-time G:log-time log-time-local G:log-time-local
+Builtin long-days G:long-days long-months G:long-months longjmp G:longjmp lookup G:lookup loop G:loop
+Builtin loop- G:loop- map? G:map? mark G:mark mark? G:mark? memfree G:memfree mobile? G:mobile? n# G:n#
+Builtin name>os G:name>os name>sem G:name>sem ndrop G:ndrop needs G:needs new G:new next-arg G:next-arg
+Builtin nip G:nip noop G:noop not G:not nothrow G:nothrow ns G:ns ns: G:ns: ns>ls G:ns>ls ns>s G:ns>s
+Builtin ns? G:ns? null G:null null; G:null; null? G:null? number? G:number? of: G:of: off G:off on G:on
+Builtin onexit G:onexit only G:only op! G:op! or G:or os G:os os-names G:os-names os>long-name G:os>long-name
+Builtin os>name G:os>name over G:over p: G:p: pack G:pack parse G:parse parse-csv G:parse-csv parsech G:parsech
+Builtin parseln G:parseln parsews G:parsews pick G:pick poke G:poke pool-clear G:pool-clear pool-clear-all G:pool-clear-all
+Builtin prior G:prior private G:private process-args G:process-args process-args-fancy G:process-args-fancy
+Builtin process-args-help G:process-args-help process-args-vars G:process-args-vars prompt G:prompt
+Builtin public G:public putc G:putc puts G:puts putslim G:putslim quote G:quote r! G:r! r> G:r> r@ G:r@
+Builtin rad>deg G:rad>deg rand-jit G:rand-jit rand-jsf G:rand-jsf rand-native G:rand-native rand-normal G:rand-normal
+Builtin rand-pcg G:rand-pcg rand-pcg-seed G:rand-pcg-seed rand-range G:rand-range rand-select G:rand-select
+Builtin randbuf-pcg G:randbuf-pcg random G:random rdrop G:rdrop recurse G:recurse recurse-stack G:recurse-stack
+Builtin ref@ G:ref@ reg! G:reg! reg@ G:reg@ regbin@ G:regbin@ remaining-args G:remaining-args repeat G:repeat
+Builtin required? G:required? requires G:requires reset G:reset roll G:roll rop! G:rop! rot G:rot rpick G:rpick
+Builtin rroll G:rroll rstack G:rstack rswap G:rswap rusage G:rusage s>ns G:s>ns same? G:same? scriptdir G:scriptdir
+Builtin scriptfile G:scriptfile sem G:sem sem-post G:sem-post sem-rm G:sem-rm sem-wait G:sem-wait sem-wait? G:sem-wait?
+Builtin sem>name G:sem>name semi-throw G:semi-throw set-wipe G:set-wipe setenv G:setenv setjmp G:setjmp
+Builtin settings! G:settings! settings![] G:settings![] settings@ G:settings@ settings@? G:settings@?
+Builtin settings@[] G:settings@[] sh G:sh sh$ G:sh$ short-days G:short-days short-months G:short-months
+Builtin sleep G:sleep sleep-until G:sleep-until slog G:slog space G:space stack-check G:stack-check
+Builtin stack-size G:stack-size step G:step sthrow G:sthrow string? G:string? struct: G:struct: swap G:swap
Builtin tab-hook G:tab-hook tell-conflict G:tell-conflict tempdir G:tempdir tempfilename G:tempfilename
-Builtin then G:then third G:third throw G:throw thrownull G:thrownull times G:times tlog G:tlog tri G:tri
-Builtin true G:true tuck G:tuck type-check G:type-check typeassert G:typeassert unlock G:unlock unpack G:unpack
-Builtin until G:until until! G:until! var G:var var, G:var, while G:while while! G:while! with: G:with:
+Builtin third G:third throw G:throw thrownull G:thrownull times G:times tlog G:tlog tri G:tri true G:true
+Builtin tuck G:tuck type-check G:type-check typeassert G:typeassert uid G:uid uname G:uname unlock G:unlock
+Builtin unpack G:unpack until G:until until! G:until! while G:while while! G:while! with: G:with: word? G:word?
Builtin words G:words words-like G:words-like words/ G:words/ xchg G:xchg xor G:xor >auth HTTP:>auth
-Builtin sh I:sh tpush I:tpush trace-word I:trace-word call JSONRPC:call auth-string OAuth:auth-string
-Builtin gen-nonce OAuth:gen-nonce params OAuth:params call SOAP:call ! a:! + a:+ - a:- 2each a:2each
-Builtin 2map a:2map 2map+ a:2map+ 2map= a:2map= = a:= >map a:>map @ a:@ @@ a:@@ bsearch a:bsearch clear a:clear
-Builtin close a:close diff a:diff dot a:dot each a:each each-slice a:each-slice exists? a:exists? filter a:filter
-Builtin generate a:generate group a:group indexof a:indexof insert a:insert intersect a:intersect join a:join
-Builtin len a:len map a:map map+ a:map+ map= a:map= mean a:mean mean&variance a:mean&variance new a:new
-Builtin op a:op op! a:op! op= a:op= open a:open pop a:pop push a:push qsort a:qsort randeach a:randeach
-Builtin reduce a:reduce reduce+ a:reduce+ rev a:rev shift a:shift shuffle a:shuffle slice a:slice slice+ a:slice+
-Builtin slide a:slide sort a:sort union a:union when a:when when! a:when! x a:x x-each a:x-each xchg a:xchg
-Builtin y a:y zip a:zip 8thdir app:8thdir asset app:asset atrun app:atrun atrun app:atrun atrun app:atrun
-Builtin basedir app:basedir current app:current datadir app:datadir exename app:exename isgui app:isgui
-Builtin main app:main oncrash app:oncrash orientation app:orientation pid app:pid restart app:restart
-Builtin resumed app:resumed shared? app:shared? standalone app:standalone subdir app:subdir suspended app:suspended
-Builtin sysquit app:sysquit (here) asm:(here) >n asm:>n avail asm:avail c, asm:c, here! asm:here! n> asm:n>
-Builtin used asm:used w, asm:w, ! b:! + b:+ / b:/ = b:= >base64 b:>base64 >hex b:>hex >mpack b:>mpack
-Builtin @ b:@ append b:append base64> b:base64> bit! b:bit! bit@ b:bit@ clear b:clear compress b:compress
-Builtin conv b:conv each b:each each-slice b:each-slice expand b:expand fill b:fill getb b:getb hex> b:hex>
-Builtin len b:len mem> b:mem> move b:move mpack-date b:mpack-date mpack-ignore b:mpack-ignore mpack> b:mpack>
-Builtin new b:new op b:op rev b:rev search b:search shmem b:shmem slice b:slice splice b:splice ungetb b:ungetb
-Builtin writable b:writable xor b:xor +block bc:+block .blocks bc:.blocks add-block bc:add-block block-hash bc:block-hash
+Builtin (curry) I:(curry) notimpl I:notimpl sh I:sh trace-word I:trace-word call JSONRPC:call auth-string OAuth:auth-string
+Builtin gen-nonce OAuth:gen-nonce params OAuth:params call SOAP:call ! a:! + a:+ - a:- / a:/ 2each a:2each
+Builtin 2map a:2map 2map+ a:2map+ 2map= a:2map= = a:= @ a:@ @? a:@? _@ a:_@ all a:all any a:any bsearch a:bsearch
+Builtin centroid a:centroid clear a:clear close a:close diff a:diff dot a:dot each a:each each! a:each!
+Builtin each-slice a:each-slice exists? a:exists? filter a:filter generate a:generate group a:group
+Builtin indexof a:indexof insert a:insert intersect a:intersect join a:join len a:len map a:map map+ a:map+
+Builtin map= a:map= mean a:mean mean&variance a:mean&variance merge a:merge new a:new op! a:op! open a:open
+Builtin pop a:pop push a:push qsort a:qsort randeach a:randeach reduce a:reduce reduce+ a:reduce+ remove a:remove
+Builtin rev a:rev shift a:shift shuffle a:shuffle slice a:slice slice+ a:slice+ slide a:slide smear a:smear
+Builtin sort a:sort union a:union x a:x x-each a:x-each xchg a:xchg y a:y zip a:zip 8thdir app:8thdir
+Builtin asset app:asset atrun app:atrun atrun app:atrun atrun app:atrun basedir app:basedir current app:current
+Builtin datadir app:datadir exename app:exename lowmem app:lowmem main app:main name app:name oncrash app:oncrash
+Builtin opts! app:opts! opts@ app:opts@ orientation app:orientation orientation! app:orientation! pid app:pid
+Builtin post-main app:post-main pre-main app:pre-main raise app:raise request-perm app:request-perm
+Builtin restart app:restart resumed app:resumed signal app:signal standalone app:standalone subdir app:subdir
+Builtin suspended app:suspended sysquit app:sysquit terminated app:terminated trap app:trap (here) asm:(here)
+Builtin >n asm:>n avail asm:avail c, asm:c, here! asm:here! n> asm:n> used asm:used w, asm:w, ! b:!
+Builtin + b:+ / b:/ 1+ b:1+ 1- b:1- = b:= >base16 b:>base16 >base32 b:>base32 >base64 b:>base64 >base85 b:>base85
+Builtin >hex b:>hex >mpack b:>mpack @ b:@ append b:append base16> b:base16> base32> b:base32> base64> b:base64>
+Builtin base85> b:base85> bit! b:bit! bit@ b:bit@ clear b:clear compress b:compress conv b:conv each b:each
+Builtin each! b:each! each-slice b:each-slice expand b:expand fill b:fill getb b:getb hex> b:hex> len b:len
+Builtin mem> b:mem> move b:move mpack-compat b:mpack-compat mpack-date b:mpack-date mpack-ignore b:mpack-ignore
+Builtin mpack> b:mpack> n! b:n! n+ b:n+ n@ b:n@ new b:new op b:op pad b:pad rev b:rev search b:search
+Builtin shmem b:shmem slice b:slice splice b:splice ungetb b:ungetb unpad b:unpad writable b:writable
+Builtin xor b:xor +block bc:+block .blocks bc:.blocks add-block bc:add-block block-hash bc:block-hash
Builtin block@ bc:block@ first-block bc:first-block hash bc:hash last-block bc:last-block load bc:load
Builtin new bc:new save bc:save set-sql bc:set-sql validate bc:validate validate-block bc:validate-block
Builtin add bloom:add filter bloom:filter in? bloom:in? accept bt:accept ch! bt:ch! ch@ bt:ch@ connect bt:connect
-Builtin disconnect bt:disconnect err? bt:err? leconnect bt:leconnect lescan bt:lescan listen bt:listen
+Builtin disconnect bt:disconnect init bt:init leconnect bt:leconnect lescan bt:lescan listen bt:listen
Builtin on? bt:on? read bt:read scan bt:scan service? bt:service? services? bt:services? write bt:write
Builtin * c:* * c:* + c:+ + c:+ = c:= = c:= >ri c:>ri >ri c:>ri abs c:abs abs c:abs arg c:arg arg c:arg
-Builtin conj c:conj conj c:conj im c:im n> c:n> new c:new new c:new re c:re >aes128gcm cr:>aes128gcm
-Builtin >aes256gcm cr:>aes256gcm >cp cr:>cp >cpe cr:>cpe >decrypt cr:>decrypt >edbox cr:>edbox >encrypt cr:>encrypt
-Builtin >nbuf cr:>nbuf >rsabox cr:>rsabox >uuid cr:>uuid CBC cr:CBC CFB cr:CFB CTR cr:CTR ECB cr:ECB
-Builtin GCM cr:GCM OFB cr:OFB aad? cr:aad? aes128box-sig cr:aes128box-sig aes128gcm> cr:aes128gcm>
-Builtin aes256box-sig cr:aes256box-sig aes256gcm> cr:aes256gcm> aesgcm cr:aesgcm blakehash cr:blakehash
-Builtin chacha20box-sig cr:chacha20box-sig chachapoly cr:chachapoly cipher! cr:cipher! cipher@ cr:cipher@
-Builtin cp> cr:cp> cpe> cr:cpe> decrypt cr:decrypt decrypt+ cr:decrypt+ decrypt> cr:decrypt> dh-genkey cr:dh-genkey
-Builtin dh-secret cr:dh-secret dh-sign cr:dh-sign dh-verify cr:dh-verify ebox-sig cr:ebox-sig ecc-genkey cr:ecc-genkey
-Builtin ecc-secret cr:ecc-secret ecc-sign cr:ecc-sign ecc-verify cr:ecc-verify edbox-sig cr:edbox-sig
-Builtin edbox> cr:edbox> encrypt cr:encrypt encrypt+ cr:encrypt+ encrypt> cr:encrypt> ensurekey cr:ensurekey
-Builtin err? cr:err? gcm-tag-size cr:gcm-tag-size genkey cr:genkey hash cr:hash hash! cr:hash! hash+ cr:hash+
-Builtin hash>b cr:hash>b hash>s cr:hash>s hash@ cr:hash@ hmac cr:hmac hotp cr:hotp iv? cr:iv? mode cr:mode
-Builtin mode@ cr:mode@ randkey cr:randkey restore cr:restore root-certs cr:root-certs rsa_decrypt cr:rsa_decrypt
-Builtin rsa_encrypt cr:rsa_encrypt rsa_sign cr:rsa_sign rsa_verify cr:rsa_verify rsabox-sig cr:rsabox-sig
-Builtin rsabox> cr:rsabox> rsagenkey cr:rsagenkey save cr:save sbox-sig cr:sbox-sig sha1-hmac cr:sha1-hmac
-Builtin shard cr:shard tag? cr:tag? totp cr:totp totp-epoch cr:totp-epoch totp-time-step cr:totp-time-step
-Builtin unshard cr:unshard uuid cr:uuid uuid> cr:uuid> validate-pgp-sig cr:validate-pgp-sig (.hebrew) d:(.hebrew)
-Builtin (.islamic) d:(.islamic) + d:+ +day d:+day +hour d:+hour +min d:+min +msec d:+msec - d:- .hebrew d:.hebrew
-Builtin .islamic d:.islamic .time d:.time / d:/ = d:= >fixed d:>fixed >hebepoch d:>hebepoch >msec d:>msec
-Builtin >unix d:>unix >ymd d:>ymd Adar d:Adar Adar2 d:Adar2 Adar2 d:Adar2 Av d:Av Elul d:Elul Fri d:Fri
-Builtin Heshvan d:Heshvan Iyar d:Iyar Kislev d:Kislev Mon d:Mon Nissan d:Nissan Sat d:Sat Shevat d:Shevat
-Builtin Sivan d:Sivan Sun d:Sun Tammuz d:Tammuz Tevet d:Tevet Thu d:Thu Tishrei d:Tishrei Tue d:Tue
-Builtin Wed d:Wed adjust-dst d:adjust-dst between d:between d. d:d. dawn d:dawn days-in-hebrew-year d:days-in-hebrew-year
-Builtin displaying-hebrew d:displaying-hebrew do-dawn d:do-dawn do-dusk d:do-dusk do-rise d:do-rise
-Builtin doy d:doy dst? d:dst? dstquery d:dstquery dstzones? d:dstzones? dusk d:dusk elapsed-timer d:elapsed-timer
-Builtin elapsed-timer-seconds d:elapsed-timer-seconds first-dow d:first-dow fixed> d:fixed> fixed>dow d:fixed>dow
-Builtin fixed>hebrew d:fixed>hebrew fixed>islamic d:fixed>islamic format d:format hanukkah d:hanukkah
-Builtin hebrew-epoch d:hebrew-epoch hebrew>fixed d:hebrew>fixed hebrewtoday d:hebrewtoday hmonth-name d:hmonth-name
-Builtin islamic.epoch d:islamic.epoch islamic>fixed d:islamic>fixed islamictoday d:islamictoday join d:join
-Builtin last-day-of-hebrew-month d:last-day-of-hebrew-month last-dow d:last-dow last-month d:last-month
-Builtin last-week d:last-week last-year d:last-year latitude d:latitude longitude d:longitude longitude d:longitude
-Builtin msec d:msec msec> d:msec> new d:new next-dow d:next-dow next-month d:next-month next-week d:next-week
-Builtin next-year d:next-year number>hebrew d:number>hebrew omer d:omer parse d:parse pesach d:pesach
+Builtin conj c:conj conj c:conj im c:im n> c:n> new c:new new c:new re c:re >redir con:>redir accept con:accept
+Builtin accept-pwd con:accept-pwd ansi? con:ansi? black con:black blue con:blue clreol con:clreol cls con:cls
+Builtin cyan con:cyan down con:down free con:free getxy con:getxy gotoxy con:gotoxy green con:green
+Builtin key con:key key? con:key? left con:left load-history con:load-history magenta con:magenta onBlack con:onBlack
+Builtin onBlue con:onBlue onCyan con:onCyan onGreen con:onGreen onMagenta con:onMagenta onRed con:onRed
+Builtin onWhite con:onWhite onYellow con:onYellow print con:print red con:red redir> con:redir> redir? con:redir?
+Builtin right con:right save-history con:save-history size? con:size? up con:up white con:white yellow con:yellow
+Builtin >aes128gcm cr:>aes128gcm >aes256gcm cr:>aes256gcm >cp cr:>cp >cpe cr:>cpe >decrypt cr:>decrypt
+Builtin >edbox cr:>edbox >encrypt cr:>encrypt >nbuf cr:>nbuf >rsabox cr:>rsabox >uuid cr:>uuid CBC cr:CBC
+Builtin CFB cr:CFB CTR cr:CTR ECB cr:ECB GCM cr:GCM OFB cr:OFB aad? cr:aad? aes128box-sig cr:aes128box-sig
+Builtin aes128gcm> cr:aes128gcm> aes256box-sig cr:aes256box-sig aes256gcm> cr:aes256gcm> aesgcm cr:aesgcm
+Builtin blakehash cr:blakehash chacha20box-sig cr:chacha20box-sig chachapoly cr:chachapoly cipher! cr:cipher!
+Builtin cipher@ cr:cipher@ cp> cr:cp> cpe> cr:cpe> decrypt cr:decrypt decrypt+ cr:decrypt+ decrypt> cr:decrypt>
+Builtin dh-genkey cr:dh-genkey dh-secret cr:dh-secret dh-sign cr:dh-sign dh-verify cr:dh-verify ebox-sig cr:ebox-sig
+Builtin ecc-genkey cr:ecc-genkey ecc-secret cr:ecc-secret ecc-sign cr:ecc-sign ecc-verify cr:ecc-verify
+Builtin edbox-sig cr:edbox-sig edbox> cr:edbox> encrypt cr:encrypt encrypt+ cr:encrypt+ encrypt> cr:encrypt>
+Builtin ensurekey cr:ensurekey gcm-tag-size cr:gcm-tag-size genkey cr:genkey hash cr:hash hash! cr:hash!
+Builtin hash+ cr:hash+ hash>b cr:hash>b hash>s cr:hash>s hash@ cr:hash@ hmac cr:hmac hotp cr:hotp iv? cr:iv?
+Builtin mode cr:mode mode@ cr:mode@ rand cr:rand randbuf cr:randbuf randkey cr:randkey restore cr:restore
+Builtin root-certs cr:root-certs rsa_decrypt cr:rsa_decrypt rsa_encrypt cr:rsa_encrypt rsa_sign cr:rsa_sign
+Builtin rsa_verify cr:rsa_verify rsabox-sig cr:rsabox-sig rsabox> cr:rsabox> rsagenkey cr:rsagenkey
+Builtin save cr:save sbox-sig cr:sbox-sig sha1-hmac cr:sha1-hmac shard cr:shard tag? cr:tag? totp cr:totp
+Builtin totp-epoch cr:totp-epoch totp-time-step cr:totp-time-step unshard cr:unshard uuid cr:uuid uuid> cr:uuid>
+Builtin validate-pgp-sig cr:validate-pgp-sig (.hebrew) d:(.hebrew) (.islamic) d:(.islamic) + d:+ +day d:+day
+Builtin +hour d:+hour +min d:+min +msec d:+msec - d:- .hebrew d:.hebrew .islamic d:.islamic .time d:.time
+Builtin / d:/ = d:= >fixed d:>fixed >hebepoch d:>hebepoch >jdn d:>jdn >msec d:>msec >unix d:>unix >ymd d:>ymd
+Builtin ?= d:?= Adar d:Adar Adar2 d:Adar2 Adar2 d:Adar2 Av d:Av Elul d:Elul Fri d:Fri Heshvan d:Heshvan
+Builtin Iyar d:Iyar Kislev d:Kislev Mon d:Mon Nissan d:Nissan Sat d:Sat Shevat d:Shevat Sivan d:Sivan
+Builtin Sun d:Sun Tammuz d:Tammuz Tevet d:Tevet Thu d:Thu Tishrei d:Tishrei Tue d:Tue Wed d:Wed adjust-dst d:adjust-dst
+Builtin approx! d:approx! approx? d:approx? approximates! d:approximates! between d:between d. d:d.
+Builtin dawn d:dawn days-in-hebrew-year d:days-in-hebrew-year displaying-hebrew d:displaying-hebrew
+Builtin do-dawn d:do-dawn do-dusk d:do-dusk do-rise d:do-rise doy d:doy dst? d:dst? dstquery d:dstquery
+Builtin dstzones? d:dstzones? dusk d:dusk elapsed-timer d:elapsed-timer elapsed-timer-seconds d:elapsed-timer-seconds
+Builtin first-dow d:first-dow fixed> d:fixed> fixed>dow d:fixed>dow fixed>hebrew d:fixed>hebrew fixed>islamic d:fixed>islamic
+Builtin format d:format hanukkah d:hanukkah hebrew-epoch d:hebrew-epoch hebrew>fixed d:hebrew>fixed
+Builtin hebrewtoday d:hebrewtoday hmonth-name d:hmonth-name islamic.epoch d:islamic.epoch islamic>fixed d:islamic>fixed
+Builtin islamictoday d:islamictoday jdn> d:jdn> join d:join last-day-of-hebrew-month d:last-day-of-hebrew-month
+Builtin last-dow d:last-dow last-month d:last-month last-week d:last-week last-year d:last-year latitude d:latitude
+Builtin longitude d:longitude longitude d:longitude msec d:msec msec> d:msec> new d:new next-dow d:next-dow
+Builtin next-month d:next-month next-week d:next-week next-year d:next-year number>hebrew d:number>hebrew
+Builtin omer d:omer parse d:parse parse-approx d:parse-approx parse-range d:parse-range pesach d:pesach
Builtin prev-dow d:prev-dow purim d:purim rosh-chodesh? d:rosh-chodesh? rosh-hashanah d:rosh-hashanah
Builtin shavuot d:shavuot start-timer d:start-timer sunrise d:sunrise taanit-esther d:taanit-esther
-Builtin ticks d:ticks ticks/sec d:ticks/sec timer d:timer tisha-beav d:tisha-beav tzadjust d:tzadjust
-Builtin unix> d:unix> updatetz d:updatetz year@ d:year@ ymd d:ymd ymd> d:ymd> yom-haatsmaut d:yom-haatsmaut
-Builtin yom-kippur d:yom-kippur add-func db:add-func bind db:bind close db:close col db:col col[] db:col[]
-Builtin col{} db:col{} err? db:err? errmsg db:errmsg exec db:exec exec-cb db:exec-cb key db:key mysql? db:mysql?
-Builtin odbc? db:odbc? open db:open open? db:open? prepare db:prepare query db:query query-all db:query-all
-Builtin rekey db:rekey sqlerrmsg db:sqlerrmsg bp dbg:bp except-task@ dbg:except-task@ go dbg:go line-info dbg:line-info
-Builtin prompt dbg:prompt stop dbg:stop trace dbg:trace trace-enter dbg:trace-enter trace-leave dbg:trace-leave
-Builtin abspath f:abspath append f:append associate f:associate atime f:atime canwrite? f:canwrite?
-Builtin chmod f:chmod close f:close copy f:copy copydir f:copydir create f:create ctime f:ctime dir? f:dir?
-Builtin dname f:dname eachbuf f:eachbuf eachline f:eachline enssep f:enssep eof? f:eof? err? f:err?
-Builtin exists? f:exists? flush f:flush fname f:fname getb f:getb getc f:getc getline f:getline getmod f:getmod
-Builtin glob f:glob glob-nocase f:glob-nocase include f:include launch f:launch link f:link link> f:link>
-Builtin link? f:link? mkdir f:mkdir mmap f:mmap mmap-range f:mmap-range mmap-range? f:mmap-range? mtime f:mtime
-Builtin mv f:mv open f:open open-ro f:open-ro popen f:popen print f:print read f:read relpath f:relpath
-Builtin rglob f:rglob rm f:rm rmdir f:rmdir seek f:seek sep f:sep show f:show size f:size slurp f:slurp
-Builtin stderr f:stderr stdin f:stdin stdout f:stdout tell f:tell times f:times trash f:trash ungetb f:ungetb
-Builtin ungetc f:ungetc unzip f:unzip unzip-entry f:unzip-entry watch f:watch write f:write writen f:writen
-Builtin zip+ f:zip+ zip@ f:zip@ zipentry f:zipentry zipnew f:zipnew zipopen f:zipopen zipsave f:zipsave
-Builtin bold font:bold face? font:face? glyph-path font:glyph-path glyph-pos font:glyph-pos info font:info
-Builtin italic font:italic ls font:ls measure font:measure new font:new pixels font:pixels pixels? font:pixels?
-Builtin points font:points points? font:points? styles font:styles styles? font:styles? underline font:underline
-Builtin +child g:+child +kind g:+kind +path g:+path -child g:-child /path g:/path >img g:>img >progress g:>progress
-Builtin add-items g:add-items adjustwidth g:adjustwidth allow-orient g:allow-orient arc g:arc arc2 g:arc2
-Builtin autohide g:autohide back g:back bezier g:bezier bg g:bg bg? g:bg? bounds g:bounds bounds? g:bounds?
-Builtin box-label g:box-label btn-font g:btn-font bubble g:bubble button-size g:button-size buttons-visible g:buttons-visible
-Builtin c-text g:c-text callout g:callout center g:center child g:child clear g:clear clearpath g:clearpath
-Builtin clr>n g:clr>n coleven g:coleven colordlg g:colordlg colwidth g:colwidth connectededges g:connectededges
-Builtin contrasting g:contrasting cp g:cp curmouse? g:curmouse? default-font g:default-font deselect-row g:deselect-row
-Builtin dismiss g:dismiss do g:do draw-fitted-text g:draw-fitted-text draw-text g:draw-text draw-text-at g:draw-text-at
-Builtin each g:each edit-on-double-click g:edit-on-double-click editable g:editable editdlg g:editdlg
-Builtin empty-text g:empty-text enable g:enable enabled? g:enabled? fade g:fade fb-files g:fb-files
-Builtin fcolor g:fcolor fg g:fg fg? g:fg? file-filter g:file-filter file-name g:file-name filedlg g:filedlg
-Builtin fill g:fill fillall g:fillall fit-text g:fit-text flex! g:flex! focus g:focus fontdlg g:fontdlg
-Builtin forward g:forward fullscreen g:fullscreen get-lasso-items g:get-lasso-items get-tab g:get-tab
-Builtin getclr g:getclr getfont g:getfont getimage g:getimage getpath g:getpath getroot g:getroot gradient g:gradient
-Builtin gui? g:gui? handle g:handle headerheight g:headerheight hide g:hide image g:image image-at g:image-at
-Builtin invalidate g:invalidate ix? g:ix? justify g:justify keyinfo g:keyinfo l-text g:l-text laf g:laf
-Builtin laf! g:laf! laf? g:laf? len g:len line-width g:line-width lineto g:lineto list+ g:list+ list- g:list-
-Builtin loadcontent g:loadcontent localize g:localize m! g:m! m@ g:m@ menu-font g:menu-font menu-update g:menu-update
-Builtin menuenabled g:menuenabled mouse? g:mouse? mousepos? g:mousepos? moveto g:moveto msgdlg g:msgdlg
-Builtin multi g:multi name g:name named-skin g:named-skin new g:new new-laf g:new-laf next g:next obj g:obj
-Builtin on g:on on? g:on? ontop g:ontop oshandle g:oshandle outlinethickness g:outlinethickness panel-size g:panel-size
-Builtin panel-size? g:panel-size? parent g:parent path g:path path>s g:path>s pie g:pie pix! g:pix!
-Builtin pop g:pop popmenu g:popmenu pos? g:pos? prev g:prev propval! g:propval! propval@ g:propval@
-Builtin push g:push qbezier g:qbezier quit g:quit r-text g:r-text readonly g:readonly rect g:rect refresh g:refresh
-Builtin restore g:restore root g:root root-item-visible g:root-item-visible rotate g:rotate rowheight g:rowheight
-Builtin rrect g:rrect s>path g:s>path save g:save say g:say scale g:scale scolor g:scolor scrollthickness g:scrollthickness
-Builtin sectionenable g:sectionenable select! g:select! select@ g:select@ selected-rows g:selected-rows
-Builtin set-lasso g:set-lasso set-long-press g:set-long-press set-popup-font g:set-popup-font set-range g:set-range
-Builtin set-swipe g:set-swipe set-value g:set-value setcursor g:setcursor setfont g:setfont setheader g:setheader
-Builtin sethtml g:sethtml setimage g:setimage setname g:setname setroot g:setroot settab g:settab show g:show
-Builtin show-line-numbers g:show-line-numbers show-pct g:show-pct showmenu g:showmenu showtooltip g:showtooltip
-Builtin size g:size size? g:size? skin g:skin skin-class g:skin-class stackix g:stackix state g:state
-Builtin state? g:state? stepsize g:stepsize stroke g:stroke stroke-fill g:stroke-fill style g:style
-Builtin tabname g:tabname text g:text text-box-style g:text-box-style text? g:text? textcolor g:textcolor
-Builtin textsize g:textsize timer! g:timer! timer@ g:timer@ toback g:toback tofront g:tofront toggle-row g:toggle-row
-Builtin tooltip g:tooltip top g:top transition g:transition translate g:translate tree-open g:tree-open
-Builtin triangle g:triangle update g:update updateitems g:updateitems url g:url user g:user user! g:user!
-Builtin vertical g:vertical view g:view visible? g:visible? vpos! g:vpos! vpos@ g:vpos@ waitcursor g:waitcursor
-Builtin winding g:winding xy g:xy xy? g:xy? +edge gr:+edge +edge+w gr:+edge+w +node gr:+node connect gr:connect
-Builtin edges gr:edges m! gr:m! m@ gr:m@ neighbors gr:neighbors new gr:new node-edges gr:node-edges
-Builtin nodes gr:nodes traverse gr:traverse + h:+ clear h:clear len h:len new h:new peek h:peek pop h:pop
-Builtin push h:push unique h:unique arm? hw:arm? camera hw:camera camera-fmt hw:camera-fmt camera-img hw:camera-img
-Builtin camera? hw:camera? cpu? hw:cpu? device? hw:device? displays? hw:displays? displaysize? hw:displaysize?
-Builtin err? hw:err? gpio hw:gpio gpio! hw:gpio! gpio-mmap hw:gpio-mmap gpio@ hw:gpio@ i2c hw:i2c i2c! hw:i2c!
-Builtin i2c!reg hw:i2c!reg i2c@ hw:i2c@ i2c@reg hw:i2c@reg isround? hw:isround? iswatch? hw:iswatch?
-Builtin mac? hw:mac? mem? hw:mem? poll hw:poll sensor hw:sensor start hw:start stop hw:stop fetch-full imap:fetch-full
-Builtin fetch-uid-mail imap:fetch-uid-mail login imap:login new imap:new select-inbox imap:select-inbox
-Builtin >file img:>file copy img:copy crop img:crop data img:data desat img:desat fill img:fill filter img:filter
-Builtin flip img:flip from-svg img:from-svg new img:new pix! img:pix! pix@ img:pix@ qr-gen img:qr-gen
-Builtin qr-parse img:qr-parse rotate img:rotate scale img:scale scroll img:scroll size img:size countries iso:countries
-Builtin find loc:find sort loc:sort ! m:! !? m:!? + m:+ +? m:+? - m:- @ m:@ @? m:@? @@ m:@@ clear m:clear
-Builtin data m:data each m:each exists? m:exists? iter m:iter iter-all m:iter-all keys m:keys len m:len
-Builtin map m:map new m:new op! m:op! open m:open vals m:vals xchg m:xchg ! mat:! * mat:* + mat:+ = mat:=
-Builtin @ mat:@ col mat:col data mat:data det mat:det dim? mat:dim? get-n mat:get-n ident mat:ident
-Builtin m. mat:m. minor mat:minor n* mat:n* new mat:new row mat:row same-size? mat:same-size? trans mat:trans
-Builtin ! n:! * n:* */ n:*/ + n:+ +! n:+! - n:- / n:/ /mod n:/mod 1+ n:1+ 1- n:1- < n:< = n:= > n:>
-Builtin BIGE n:BIGE BIGPI n:BIGPI E n:E PI n:PI ^ n:^ abs n:abs acos n:acos acos n:acos asin n:asin
-Builtin asin n:asin atan n:atan atan n:atan atan2 n:atan2 band n:band between n:between bfloat n:bfloat
-Builtin bic n:bic bint n:bint binv n:binv bnot n:bnot bor n:bor bxor n:bxor ceil n:ceil clamp n:clamp
-Builtin cmp n:cmp comb n:comb cos n:cos cosd n:cosd exp n:exp expmod n:expmod float n:float floor n:floor
+Builtin ticks d:ticks ticks/sec d:ticks/sec timer d:timer timer-ctrl d:timer-ctrl tisha-beav d:tisha-beav
+Builtin tzadjust d:tzadjust unix> d:unix> unknown d:unknown unknown? d:unknown? updatetz d:updatetz
+Builtin year@ d:year@ ymd d:ymd ymd> d:ymd> yom-haatsmaut d:yom-haatsmaut yom-kippur d:yom-kippur add-func db:add-func
+Builtin aes! db:aes! begin db:begin bind db:bind bind-exec db:bind-exec bind-exec[] db:bind-exec[]
+Builtin close db:close col db:col col[] db:col[] col{} db:col{} commit db:commit each db:each exec db:exec
+Builtin exec-cb db:exec-cb exec-name db:exec-name get db:get get-sub db:get-sub key db:key kind? db:kind?
+Builtin last-rowid db:last-rowid mysql? db:mysql? odbc? db:odbc? open db:open open? db:open? prep-name db:prep-name
+Builtin prepare db:prepare query db:query query-all db:query-all rekey db:rekey rollback db:rollback
+Builtin set db:set set-sub db:set-sub sql@ db:sql@ bp dbg:bp except-task@ dbg:except-task@ go dbg:go
+Builtin line-info dbg:line-info prompt dbg:prompt stop dbg:stop trace dbg:trace trace-enter dbg:trace-enter
+Builtin trace-leave dbg:trace-leave / f:/ abspath f:abspath absrel f:absrel append f:append associate f:associate
+Builtin atime f:atime canwrite? f:canwrite? chmod f:chmod close f:close copy f:copy copydir f:copydir
+Builtin create f:create ctime f:ctime dir? f:dir? dname f:dname eachbuf f:eachbuf eachline f:eachline
+Builtin enssep f:enssep eof? f:eof? exists? f:exists? flush f:flush fname f:fname getb f:getb getc f:getc
+Builtin getline f:getline getmod f:getmod glob f:glob glob-nocase f:glob-nocase homedir f:homedir homedir! f:homedir!
+Builtin include f:include ioctl f:ioctl join f:join launch f:launch link f:link link> f:link> link? f:link?
+Builtin mkdir f:mkdir mmap f:mmap mmap-range f:mmap-range mmap-range? f:mmap-range? mtime f:mtime mv f:mv
+Builtin name@ f:name@ open f:open open-ro f:open-ro popen f:popen print f:print read f:read read? f:read?
+Builtin relpath f:relpath rglob f:rglob rm f:rm rmdir f:rmdir seek f:seek sep f:sep size f:size slurp f:slurp
+Builtin sparse? f:sparse? spit f:spit stderr f:stderr stdin f:stdin stdout f:stdout tell f:tell times f:times
+Builtin tmpspit f:tmpspit trash f:trash truncate f:truncate ungetb f:ungetb ungetc f:ungetc unzip f:unzip
+Builtin unzip-entry f:unzip-entry watch f:watch write f:write writen f:writen zip+ f:zip+ zip@ f:zip@
+Builtin zipentry f:zipentry zipnew f:zipnew zipopen f:zipopen zipsave f:zipsave atlas! font:atlas!
+Builtin atlas@ font:atlas@ default-size font:default-size info font:info ls font:ls measure font:measure
+Builtin new font:new oversample font:oversample pixels font:pixels pixels? font:pixels? +edge gr:+edge
+Builtin +edge+w gr:+edge+w +node gr:+node connect gr:connect edges gr:edges edges! gr:edges! m! gr:m!
+Builtin m@ gr:m@ neighbors gr:neighbors new gr:new node-edges gr:node-edges nodes gr:nodes traverse gr:traverse
+Builtin weight! gr:weight! + h:+ clear h:clear cmp! h:cmp! len h:len max! h:max! new h:new peek h:peek
+Builtin pop h:pop push h:push unique h:unique arm? hw:arm? camera hw:camera camera-img hw:camera-img
+Builtin camera-limits hw:camera-limits camera? hw:camera? cpu? hw:cpu? device? hw:device? displays? hw:displays?
+Builtin displaysize? hw:displaysize? finger-match hw:finger-match finger-support hw:finger-support
+Builtin gpio hw:gpio gpio! hw:gpio! gpio-mmap hw:gpio-mmap gpio@ hw:gpio@ i2c hw:i2c i2c! hw:i2c! i2c!reg hw:i2c!reg
+Builtin i2c@ hw:i2c@ i2c@reg hw:i2c@reg isround? hw:isround? iswatch? hw:iswatch? mac? hw:mac? mem? hw:mem?
+Builtin model? hw:model? poll hw:poll sensor hw:sensor start hw:start stop hw:stop uid? hw:uid? fetch-full imap:fetch-full
+Builtin fetch-uid-mail imap:fetch-uid-mail login imap:login logout imap:logout new imap:new search imap:search
+Builtin select-inbox imap:select-inbox >file img:>file >fmt img:>fmt copy img:copy crop img:crop data img:data
+Builtin desat img:desat fill img:fill fillrect img:fillrect filter img:filter flip img:flip from-svg img:from-svg
+Builtin new img:new pix! img:pix! pix@ img:pix@ qr-gen img:qr-gen qr-parse img:qr-parse rotate img:rotate
+Builtin scale img:scale scroll img:scroll size img:size countries iso:countries find loc:find sort loc:sort
+Builtin ! m:! !? m:!? + m:+ +? m:+? - m:- >arr m:>arr @ m:@ @? m:@? _! m:_! _@ m:_@ arr> m:arr> bitmap m:bitmap
+Builtin clear m:clear data m:data each m:each exists? m:exists? filter m:filter iter m:iter iter-all m:iter-all
+Builtin keys m:keys len m:len map m:map merge m:merge new m:new op! m:op! open m:open slice m:slice
+Builtin vals m:vals xchg m:xchg zip m:zip ! mat:! * mat:* + mat:+ = mat:= @ mat:@ affine mat:affine
+Builtin col mat:col data mat:data det mat:det dim? mat:dim? get-n mat:get-n ident mat:ident inv mat:inv
+Builtin m. mat:m. minor mat:minor n* mat:n* new mat:new new-minor mat:new-minor rotate mat:rotate row mat:row
+Builtin same-size? mat:same-size? scale mat:scale shear mat:shear trans mat:trans translate mat:translate
+Builtin xform mat:xform 2console md:2console 2html md:2html 2nk md:2nk bounds meta:bounds color meta:color
+Builtin console meta:console end meta:end ffi meta:ffi ! n:! * n:* */ n:*/ + n:+ +! n:+! - n:- / n:/
+Builtin /mod n:/mod 1+ n:1+ 1- n:1- < n:< = n:= > n:> BIGE n:BIGE BIGPI n:BIGPI E n:E PI n:PI ^ n:^
+Builtin _mod n:_mod abs n:abs acos n:acos acos n:acos asin n:asin asin n:asin atan n:atan atan n:atan
+Builtin atan2 n:atan2 band n:band between n:between bfloat n:bfloat bic n:bic bint n:bint binv n:binv
+Builtin bnot n:bnot bor n:bor bxor n:bxor cast n:cast ceil n:ceil clamp n:clamp cmp n:cmp comb n:comb
+Builtin cos n:cos cosd n:cosd emod n:emod exp n:exp expm1 n:expm1 expmod n:expmod float n:float floor n:floor
Builtin fmod n:fmod frac n:frac gcd n:gcd int n:int invmod n:invmod kind? n:kind? lcm n:lcm ln n:ln
-Builtin max n:max median n:median min n:min mod n:mod neg n:neg odd? n:odd? perm n:perm prime? n:prime?
-Builtin quantize n:quantize quantize! n:quantize! r+ n:r+ range n:range rot32l n:rot32l rot32r n:rot32r
-Builtin round n:round round2 n:round2 running-variance n:running-variance running-variance-finalize n:running-variance-finalize
-Builtin sgn n:sgn shl n:shl shr n:shr sin n:sin sind n:sind sqr n:sqr sqrt n:sqrt tan n:tan tand n:tand
-Builtin trunc n:trunc ~= n:~= ! net:! >url net:>url @ net:@ DGRAM net:DGRAM INET4 net:INET4 INET6 net:INET6
-Builtin PROTO_TCP net:PROTO_TCP PROTO_UDP net:PROTO_UDP STREAM net:STREAM accept net:accept addrinfo>o net:addrinfo>o
-Builtin again? net:again? alloc-and-read net:alloc-and-read alloc-buf net:alloc-buf bind net:bind browse net:browse
-Builtin close net:close connect net:connect err>s net:err>s err? net:err? get net:get getaddrinfo net:getaddrinfo
-Builtin getpeername net:getpeername head net:head ifaces? net:ifaces? listen net:listen net-socket net:net-socket
-Builtin opts net:opts port-is-ssl? net:port-is-ssl? post net:post proxy! net:proxy! read net:read recvfrom net:recvfrom
-Builtin s>url net:s>url sendto net:sendto server net:server setsockopt net:setsockopt socket net:socket
-Builtin tlshello net:tlshello url> net:url> user-agent net:user-agent wait net:wait write net:write
-Builtin MAX ns:MAX cast ptr:cast len ptr:len pack ptr:pack unpack ptr:unpack unpack_orig ptr:unpack_orig
+Builtin ln1p n:ln1p max n:max median n:median min n:min mod n:mod neg n:neg odd? n:odd? perm n:perm
+Builtin prime? n:prime? quantize n:quantize quantize! n:quantize! r+ n:r+ range n:range rot32l n:rot32l
+Builtin rot32r n:rot32r round n:round round2 n:round2 rounding n:rounding running-variance n:running-variance
+Builtin running-variance-finalize n:running-variance-finalize sgn n:sgn shl n:shl shr n:shr sin n:sin
+Builtin sind n:sind sqr n:sqr sqrt n:sqrt tan n:tan tand n:tand trunc n:trunc ~= n:~= ! net:! !? net:!?
+Builtin - net:- >url net:>url @ net:@ @? net:@? DGRAM net:DGRAM INET4 net:INET4 INET6 net:INET6 PROTO_TCP net:PROTO_TCP
+Builtin PROTO_UDP net:PROTO_UDP STREAM net:STREAM accept net:accept addrinfo>o net:addrinfo>o again? net:again?
+Builtin alloc-and-read net:alloc-and-read alloc-buf net:alloc-buf bind net:bind close net:close closed? net:closed?
+Builtin connect net:connect debug? net:debug? delete net:delete get net:get getaddrinfo net:getaddrinfo
+Builtin getpeername net:getpeername head net:head ifaces? net:ifaces? listen net:listen map>url net:map>url
+Builtin net-socket net:net-socket opts net:opts port-is-ssl? net:port-is-ssl? post net:post proxy! net:proxy!
+Builtin put net:put read net:read read-all net:read-all recvfrom net:recvfrom s>url net:s>url sendto net:sendto
+Builtin server net:server setsockopt net:setsockopt socket net:socket tlshello net:tlshello url> net:url>
+Builtin user-agent net:user-agent wait net:wait write net:write (begin) nk:(begin) (chart-begin) nk:(chart-begin)
+Builtin (chart-begin-colored) nk:(chart-begin-colored) (chart-end) nk:(chart-end) (end) nk:(end) (group-begin) nk:(group-begin)
+Builtin (group-end) nk:(group-end) (property) nk:(property) >img nk:>img addfont nk:addfont anti-alias nk:anti-alias
+Builtin any-clicked? nk:any-clicked? bounds nk:bounds bounds! nk:bounds! button nk:button button-color nk:button-color
+Builtin button-label nk:button-label button-set-behavior nk:button-set-behavior button-symbol nk:button-symbol
+Builtin button-symbol-label nk:button-symbol-label chart-add-slot nk:chart-add-slot chart-add-slot-colored nk:chart-add-slot-colored
+Builtin chart-push nk:chart-push chart-push-slot nk:chart-push-slot checkbox nk:checkbox clicked? nk:clicked?
+Builtin close-this! nk:close-this! close-this? nk:close-this? close? nk:close? color-picker nk:color-picker
+Builtin combo nk:combo combo-begin-color nk:combo-begin-color combo-begin-label nk:combo-begin-label
+Builtin combo-cb nk:combo-cb combo-end nk:combo-end contextual-begin nk:contextual-begin contextual-close nk:contextual-close
+Builtin contextual-end nk:contextual-end contextual-item-image-text nk:contextual-item-image-text contextual-item-symbol-text nk:contextual-item-symbol-text
+Builtin contextual-item-text nk:contextual-item-text cp! nk:cp! cp@ nk:cp@ display-info nk:display-info
+Builtin display@ nk:display@ do nk:do down? nk:down? draw-image nk:draw-image draw-image-at nk:draw-image-at
+Builtin draw-image-centered nk:draw-image-centered draw-sub-image nk:draw-sub-image draw-text nk:draw-text
+Builtin draw-text-high nk:draw-text-high draw-text-wrap nk:draw-text-wrap edit-focus nk:edit-focus
+Builtin edit-string nk:edit-string event nk:event event-boost nk:event-boost event-msec nk:event-msec
+Builtin event-wait nk:event-wait fill-arc nk:fill-arc fill-circle nk:fill-circle fill-poly nk:fill-poly
+Builtin fill-rect nk:fill-rect fill-rect-color nk:fill-rect-color fill-triangle nk:fill-triangle flags! nk:flags!
+Builtin flags@ nk:flags@ fullscreen nk:fullscreen get nk:get get-row-height nk:get-row-height getfont nk:getfont
+Builtin getmap nk:getmap gl? nk:gl? grid nk:grid grid-push nk:grid-push group-scroll-ofs nk:group-scroll-ofs
+Builtin group-scroll-ofs! nk:group-scroll-ofs! hovered? nk:hovered? image nk:image init nk:init input-button nk:input-button
+Builtin input-key nk:input-key input-motion nk:input-motion input-scroll nk:input-scroll input-string nk:input-string
+Builtin key-down? nk:key-down? key-pressed? nk:key-pressed? key-released? nk:key-released? label nk:label
+Builtin label-colored nk:label-colored label-wrap nk:label-wrap label-wrap-colored nk:label-wrap-colored
+Builtin layout-bounds nk:layout-bounds layout-grid-begin nk:layout-grid-begin layout-grid-end nk:layout-grid-end
+Builtin layout-push-dynamic nk:layout-push-dynamic layout-push-static nk:layout-push-static layout-push-variable nk:layout-push-variable
+Builtin layout-ratio-from-pixel nk:layout-ratio-from-pixel layout-reset-row-height nk:layout-reset-row-height
+Builtin layout-row nk:layout-row layout-row-begin nk:layout-row-begin layout-row-dynamic nk:layout-row-dynamic
+Builtin layout-row-end nk:layout-row-end layout-row-height nk:layout-row-height layout-row-push nk:layout-row-push
+Builtin layout-row-static nk:layout-row-static layout-row-template-begin nk:layout-row-template-begin
+Builtin layout-row-template-end nk:layout-row-template-end layout-space-begin nk:layout-space-begin
+Builtin layout-space-end nk:layout-space-end layout-space-push nk:layout-space-push layout-widget-bounds nk:layout-widget-bounds
+Builtin list-begin nk:list-begin list-end nk:list-end list-new nk:list-new list-range nk:list-range
+Builtin m! nk:m! m@ nk:m@ make-style nk:make-style max-vertex-element nk:max-vertex-element measure nk:measure
+Builtin measure-font nk:measure-font menu-begin nk:menu-begin menu-close nk:menu-close menu-end nk:menu-end
+Builtin menu-item-image nk:menu-item-image menu-item-label nk:menu-item-label menu-item-symbol nk:menu-item-symbol
+Builtin menubar-begin nk:menubar-begin menubar-end nk:menubar-end mouse-pos nk:mouse-pos msgdlg nk:msgdlg
+Builtin option nk:option plot nk:plot plot-fn nk:plot-fn pop-font nk:pop-font popup-begin nk:popup-begin
+Builtin popup-close nk:popup-close popup-end nk:popup-end popup-scroll-ofs nk:popup-scroll-ofs popup-scroll-ofs! nk:popup-scroll-ofs!
+Builtin progress nk:progress prop-int nk:prop-int pt>local nk:pt>local pt>screen nk:pt>screen pts>rect nk:pts>rect
+Builtin push-font nk:push-font rect-center nk:rect-center rect-intersect nk:rect-intersect rect-ofs nk:rect-ofs
+Builtin rect-pad nk:rect-pad rect-shrink nk:rect-shrink rect-union nk:rect-union rect/high nk:rect/high
+Builtin rect/wide nk:rect/wide rect>center nk:rect>center rect>local nk:rect>local rect>pos nk:rect>pos
+Builtin rect>pts nk:rect>pts rect>screen nk:rect>screen rect>size nk:rect>size released? nk:released?
+Builtin render nk:render restore nk:restore rotate nk:rotate save nk:save scale nk:scale scancode? nk:scancode?
+Builtin screen-saver nk:screen-saver screen-size nk:screen-size screen-win-close nk:screen-win-close
+Builtin selectable nk:selectable set nk:set set-font nk:set-font set-num-vertices nk:set-num-vertices
+Builtin setpos nk:setpos setwin nk:setwin slider nk:slider slider-int nk:slider-int space nk:space
+Builtin spacing nk:spacing stroke-arc nk:stroke-arc stroke-circle nk:stroke-circle stroke-curve nk:stroke-curve
+Builtin stroke-line nk:stroke-line stroke-polygon nk:stroke-polygon stroke-polyline nk:stroke-polyline
+Builtin stroke-rect nk:stroke-rect stroke-tri nk:stroke-tri style-from-table nk:style-from-table sw-gl nk:sw-gl
+Builtin text? nk:text? tooltip nk:tooltip translate nk:translate tree-pop nk:tree-pop tree-state-push nk:tree-state-push
+Builtin use-style nk:use-style vsync nk:vsync widget nk:widget widget-bounds nk:widget-bounds widget-fitting nk:widget-fitting
+Builtin widget-high nk:widget-high widget-hovered? nk:widget-hovered? widget-mouse-click-down? nk:widget-mouse-click-down?
+Builtin widget-mouse-clicked? nk:widget-mouse-clicked? widget-pos nk:widget-pos widget-size nk:widget-size
+Builtin widget-wide nk:widget-wide win nk:win win-bounds nk:win-bounds win-bounds! nk:win-bounds! win-close nk:win-close
+Builtin win-closed? nk:win-closed? win-collapse nk:win-collapse win-collapsed? nk:win-collapsed? win-content-bounds nk:win-content-bounds
+Builtin win-focus nk:win-focus win-focused? nk:win-focused? win-hidden? nk:win-hidden? win-high nk:win-high
+Builtin win-hovered? nk:win-hovered? win-pos nk:win-pos win-scroll-ofs nk:win-scroll-ofs win-scroll-ofs! nk:win-scroll-ofs!
+Builtin win-show nk:win-show win-size nk:win-size win-wide nk:win-wide win? nk:win? MAX ns:MAX ! o:!
+Builtin + o:+ +? o:+? ??? o:??? @ o:@ class o:class exec o:exec isa o:isa method o:method mutate o:mutate
+Builtin new o:new super o:super devname os:devname env os:env lang os:lang mem-arenas os:mem-arenas
+Builtin notify os:notify region os:region cast ptr:cast len ptr:len null? ptr:null? pack ptr:pack unpack ptr:unpack
+Builtin unpack_orig ptr:unpack_orig publish pubsub:publish qsize pubsub:qsize subscribe pubsub:subscribe
Builtin + q:+ clear q:clear len q:len new q:new notify q:notify overwrite q:overwrite peek q:peek pick q:pick
-Builtin pop q:pop push q:push shift q:shift size q:size slide q:slide throwing q:throwing wait q:wait
-Builtin ++match r:++match +/ r:+/ +match r:+match / r:/ @ r:@ err? r:err? len r:len match r:match new r:new
-Builtin rx r:rx str r:str ! s:! * s:* + s:+ - s:- / s:/ /scripts s:/scripts <+ s:<+ = s:= =ic s:=ic
-Builtin >base64 s:>base64 >ucs2 s:>ucs2 @ s:@ append s:append base64> s:base64> clear s:clear cmp s:cmp
-Builtin cmpi s:cmpi compress s:compress days! s:days! each s:each eachline s:eachline expand s:expand
-Builtin fill s:fill fmt s:fmt gershayim s:gershayim globmatch s:globmatch hexupr s:hexupr insert s:insert
-Builtin intl s:intl intl! s:intl! lang s:lang lc s:lc len s:len lsub s:lsub ltrim s:ltrim map s:map
-Builtin months! s:months! new s:new replace s:replace replace! s:replace! rev s:rev rsearch s:rsearch
-Builtin rsub s:rsub rtrim s:rtrim script? s:script? search s:search size s:size slice s:slice strfmap s:strfmap
-Builtin strfmt s:strfmt trim s:trim tsub s:tsub uc s:uc ucs2> s:ucs2> utf8? s:utf8? zt s:zt close sio:close
-Builtin enum sio:enum open sio:open opts! sio:opts! opts@ sio:opts@ read sio:read write sio:write new smtp:new
-Builtin send smtp:send apply-filter snd:apply-filter devices? snd:devices? end-record snd:end-record
-Builtin filter snd:filter formats? snd:formats? freq snd:freq gain snd:gain gain? snd:gain? len snd:len
-Builtin loop snd:loop mix snd:mix new snd:new pause snd:pause play snd:play played snd:played rate snd:rate
-Builtin record snd:record seek snd:seek stop snd:stop stopall snd:stopall unmix snd:unmix volume snd:volume
-Builtin volume? snd:volume? + st:+ . st:. clear st:clear len st:len ndrop st:ndrop new st:new op! st:op!
-Builtin peek st:peek pick st:pick pop st:pop push st:push roll st:roll shift st:shift size st:size
-Builtin slide st:slide swap st:swap throwing st:throwing >buf struct:>buf arr> struct:arr> buf struct:buf
-Builtin buf> struct:buf> byte struct:byte double struct:double field! struct:field! field@ struct:field@
-Builtin float struct:float ignore struct:ignore int struct:int long struct:long struct; struct:struct;
-Builtin word struct:word ! t:! @ t:@ assign t:assign curtask t:curtask def-queue t:def-queue def-stack t:def-stack
-Builtin done? t:done? err! t:err! err? t:err? getq t:getq guitask t:guitask handler t:handler kill t:kill
-Builtin list t:list main t:main name! t:name! name@ t:name@ notify t:notify pop t:pop priority t:priority
-Builtin push t:push push< t:push< q-notify t:q-notify q-wait t:q-wait qlen t:qlen result t:result task t:task
-Builtin task-n t:task-n task-stop t:task-stop wait t:wait ! w:! @ w:@ alias: w:alias: cb w:cb deprecate w:deprecate
-Builtin exec w:exec exec? w:exec? ffifail w:ffifail find w:find forget w:forget is w:is undo w:undo
-Builtin >s xml:>s >txt xml:>txt parse xml:parse parse-html xml:parse-html parse-stream xml:parse-stream
+Builtin pop q:pop push q:push remove q:remove shift q:shift size q:size slide q:slide throwing q:throwing
+Builtin wait q:wait ++match r:++match +/ r:+/ +match r:+match / r:/ @ r:@ len r:len match r:match new r:new
+Builtin rx r:rx str r:str * rat:* + rat:+ - rat:- / rat:/ >n rat:>n >s rat:>s new rat:new proper rat:proper
+Builtin ! s:! * s:* + s:+ - s:- / s:/ /scripts s:/scripts <+ s:<+ = s:= =ic s:=ic >base64 s:>base64
+Builtin >ucs2 s:>ucs2 @ s:@ append s:append base64> s:base64> clear s:clear cmp s:cmp cmpi s:cmpi compress s:compress
+Builtin days! s:days! dist s:dist each s:each each! s:each! eachline s:eachline escape s:escape expand s:expand
+Builtin fill s:fill fmt s:fmt fold s:fold gershayim s:gershayim globmatch s:globmatch hexupr s:hexupr
+Builtin insert s:insert intl s:intl intl! s:intl! lang s:lang lc s:lc lc? s:lc? len s:len lsub s:lsub
+Builtin ltrim s:ltrim map s:map months! s:months! new s:new norm s:norm reduce s:reduce repinsert s:repinsert
+Builtin replace s:replace replace! s:replace! rev s:rev rsearch s:rsearch rsub s:rsub rtrim s:rtrim
+Builtin script? s:script? search s:search size s:size slice s:slice soundex s:soundex strfmap s:strfmap
+Builtin strfmt s:strfmt text-wrap s:text-wrap trim s:trim tsub s:tsub uc s:uc uc? s:uc? ucs2> s:ucs2>
+Builtin utf8? s:utf8? zt s:zt close sio:close enum sio:enum open sio:open opts! sio:opts! opts@ sio:opts@
+Builtin read sio:read write sio:write @ slv:@ auto slv:auto build slv:build constraint slv:constraint
+Builtin dump slv:dump edit slv:edit named-variable slv:named-variable new slv:new relation slv:relation
+Builtin reset slv:reset suggest slv:suggest term slv:term update slv:update v[] slv:v[] variable slv:variable
+Builtin v{} slv:v{} new smtp:new send smtp:send apply-filter snd:apply-filter devices? snd:devices?
+Builtin end-record snd:end-record filter snd:filter formats? snd:formats? freq snd:freq gain snd:gain
+Builtin gain? snd:gain? init snd:init len snd:len loop snd:loop loop? snd:loop? mix snd:mix new snd:new
+Builtin pause snd:pause play snd:play played snd:played rate snd:rate ready? snd:ready? record snd:record
+Builtin resume snd:resume seek snd:seek stop snd:stop stopall snd:stopall volume snd:volume volume? snd:volume?
+Builtin + st:+ . st:. clear st:clear len st:len ndrop st:ndrop new st:new op! st:op! peek st:peek pick st:pick
+Builtin pop st:pop push st:push roll st:roll shift st:shift size st:size slide st:slide swap st:swap
+Builtin throwing st:throwing >buf struct:>buf arr> struct:arr> buf struct:buf buf> struct:buf> byte struct:byte
+Builtin double struct:double field! struct:field! field@ struct:field@ float struct:float ignore struct:ignore
+Builtin int struct:int long struct:long struct; struct:struct; word struct:word ! t:! @ t:@ by-name t:by-name
+Builtin cor t:cor cor-drop t:cor-drop curtask t:curtask def-queue t:def-queue def-stack t:def-stack
+Builtin done? t:done? err! t:err! err? t:err? errno? t:errno? getq t:getq handler t:handler handler@ t:handler@
+Builtin kill t:kill list t:list main t:main max-exceptions t:max-exceptions name! t:name! name@ t:name@
+Builtin notify t:notify parent t:parent pop t:pop priority t:priority push t:push q-notify t:q-notify
+Builtin q-wait t:q-wait qlen t:qlen result t:result set-affinity t:set-affinity setq t:setq start t:start
+Builtin task t:task task-n t:task-n task-stop t:task-stop wait t:wait yield t:yield yield! t:yield!
+Builtin add tree:add binary tree:binary bk tree:bk btree tree:btree cmp! tree:cmp! data tree:data del tree:del
+Builtin find tree:find iter tree:iter next tree:next nodes tree:nodes parent tree:parent parse tree:parse
+Builtin prev tree:prev root tree:root search tree:search trie tree:trie ! w:! (is) w:(is) @ w:@ alias: w:alias:
+Builtin cb w:cb deprecate w:deprecate dlcall w:dlcall dlopen w:dlopen dlsym w:dlsym exec w:exec exec? w:exec?
+Builtin ffifail w:ffifail find w:find forget w:forget is w:is name w:name undo w:undo >s xml:>s >txt xml:>txt
+Builtin md-init xml:md-init md-parse xml:md-parse parse xml:parse parse-html xml:parse-html parse-stream xml:parse-stream
Builtin getmsg[] zmq:getmsg[] sendmsg[] zmq:sendmsg[]
+
" numbers
syn keyword eighthMath decimal hex base@ base!
syn match eighthInteger '\<-\=[0-9.]*[0-9.]\+\>'
+
" recognize hex and binary numbers, the '$' and '%' notation is for eighth
syn match eighthInteger '\<\$\x*\x\+\>' " *1* --- dont't mess
syn match eighthInteger '\<\x*\d\x*\>' " *2* --- this order!
@@ -280,20 +353,17 @@ syn match eighthInteger "\<'.\>"
syn region eighthString start=+\.\?\"+ skip=+"+ end=+$+
syn keyword jsonNull null
syn keyword jsonBool /\(true\|false\)/
- syn region eighthString start=/\<"/ end=/"\>/
+syn region eighthString start=/\<"/ end=/"\>/
syn match jsonObjEntry /"\"[^"]\+\"\ze\s*:/
-"syn region jsonObject start=/{/ end=/}/ contained contains=jsonObjEntry,jsonArray,jsonObject, jsonBool, eighthString
-"syn region jsonArray start=/\[/ end=/\]/ contained contains=jsonArray,jsonObject, jsonBool, eighthString
-
" Include files
-" syn match eighthInclude '\<\(libinclude\|include\|needs\)\s\+\S\+'
syn region eighthComment start="\zs\\" end="$" contains=eighthTodo
" Define the default highlighting.
if !exists("did_eighth_syntax_inits")
let did_eighth_syntax_inits=1
- " The default methods for highlighting. Can be overridden later.
+
+ " The default methods for highlighting. Can be overriden later.
hi def link eighthTodo Todo
hi def link eighthOperators Operator
hi def link eighthMath Number
@@ -320,16 +390,15 @@ if !exists("did_eighth_syntax_inits")
hi def link eighthBuiltin Define
hi def link eighthClasses Define
hi def link eighthClassWord Keyword
-
hi def link jsonObject Delimiter
hi def link jsonObjEntry Label
hi def link jsonArray Special
- hi def link jsonNull Function
- hi def link jsonBool Boolean
+ hi def link jsonNull Function
+ hi def link jsonBool Boolean
endif
let b:current_syntax = "8th"
let &cpo = s:cpo_save
unlet s:cpo_save
-" vim: ts=8:sw=4:nocindent:smartindent:
+" vim: ft=vim:ts=8:sw=4:nocindent:smartindent:
diff --git a/runtime/syntax/chicken.vim b/runtime/syntax/chicken.vim
index 806d08fbb7..f53d872e74 100644
--- a/runtime/syntax/chicken.vim
+++ b/runtime/syntax/chicken.vim
@@ -1,6 +1,6 @@
" Vim syntax file
" Language: Scheme (CHICKEN)
-" Last Change: 2021 Jul 30
+" Last Change: 2021 Oct 01
" Author: Evan Hanson <evhan@foldling.org>
" Maintainer: Evan Hanson <evhan@foldling.org>
" Repository: https://git.foldling.org/vim-scheme.git
@@ -37,7 +37,7 @@ if len(s:c)
syn region c matchgroup=schemeComment start=/#>/ end=/<#/ contains=@c
endif
-# SRFI 26
+" SRFI 26
syn match schemeSyntax /\(([ \t\n]*\)\@<=\(cut\|cute\)\>/
syn keyword schemeSyntax and-let*
diff --git a/runtime/syntax/nginx.vim b/runtime/syntax/nginx.vim
new file mode 100644
index 0000000000..18dd50cbb2
--- /dev/null
+++ b/runtime/syntax/nginx.vim
@@ -0,0 +1,2307 @@
+" Vim syntax file
+" Language: nginx.conf
+" Maintainer: Chris Aumann <me@chr4.org>
+" Last Change: Apr 15, 2017
+
+if exists("b:current_syntax")
+ finish
+end
+
+let b:current_syntax = "nginx"
+
+syn match ngxVariable '\$\(\w\+\|{\w\+}\)'
+syn match ngxVariableBlock '\$\(\w\+\|{\w\+}\)' contained
+syn match ngxVariableString '\$\(\w\+\|{\w\+}\)' contained
+syn region ngxBlock start=+^+ end=+{+ skip=+\${\|{{\|{%+ contains=ngxComment,ngxInteger,ngxIPaddr,ngxDirectiveBlock,ngxVariableBlock,ngxString,ngxThirdPartyLuaBlock oneline
+syn region ngxString start=+[^:a-zA-Z>!\\@]\z(["']\)+lc=1 end=+\z1+ skip=+\\\\\|\\\z1+ contains=ngxVariableString,ngxSSLCipherInsecure
+syn match ngxComment ' *#.*$'
+
+" These regular expressions where taken (and adapted) from
+" http://vim.1045645.n5.nabble.com/IPv6-support-for-quot-dns-quot-zonefile-syntax-highlighting-td1197292.html
+syn match ngxInteger '\W\zs\(\d[0-9.]*\|[0-9.]*\d\)\w\?\ze\W'
+syn match ngxIPaddr '\([0-2]\?\d\{1,2}\.\)\{3}[0-2]\?\d\{1,2}'
+syn match ngxIPaddr '\[\(\x\{1,4}:\)\{6}\(\x\{1,4}:\x\{1,4}\|\([0-2]\?\d\{1,2}\.\)\{3}[0-2]\?\d\{1,2}\)\]'
+syn match ngxIPaddr '\[::\(\(\x\{1,4}:\)\{,6}\x\{1,4}\|\(\x\{1,4}:\)\{,5}\([0-2]\?\d\{1,2}\.\)\{3}[0-2]\?\d\{1,2}\)\]'
+syn match ngxIPaddr '\[\(\x\{1,4}:\)\{1}:\(\(\x\{1,4}:\)\{,5}\x\{1,4}\|\(\x\{1,4}:\)\{,4}\([0-2]\?\d\{1,2}\.\)\{3}[0-2]\?\d\{1,2}\)\]'
+syn match ngxIPaddr '\[\(\x\{1,4}:\)\{2}:\(\(\x\{1,4}:\)\{,4}\x\{1,4}\|\(\x\{1,4}:\)\{,3}\([0-2]\?\d\{1,2}\.\)\{3}[0-2]\?\d\{1,2}\)\]'
+syn match ngxIPaddr '\[\(\x\{1,4}:\)\{3}:\(\(\x\{1,4}:\)\{,3}\x\{1,4}\|\(\x\{1,4}:\)\{,2}\([0-2]\?\d\{1,2}\.\)\{3}[0-2]\?\d\{1,2}\)\]'
+syn match ngxIPaddr '\[\(\x\{1,4}:\)\{4}:\(\(\x\{1,4}:\)\{,2}\x\{1,4}\|\(\x\{1,4}:\)\{,1}\([0-2]\?\d\{1,2}\.\)\{3}[0-2]\?\d\{1,2}\)\]'
+syn match ngxIPaddr '\[\(\x\{1,4}:\)\{5}:\(\(\x\{1,4}:\)\{,1}\x\{1,4}\|\([0-2]\?\d\{1,2}\.\)\{3}[0-2]\?\d\{1,2}\)\]'
+syn match ngxIPaddr '\[\(\x\{1,4}:\)\{6}:\x\{1,4}\]'
+
+" Highlight wildcard listening signs also as IPaddr
+syn match ngxIPaddr '\s\zs\[::]'
+syn match ngxIPaddr '\s\zs\*'
+
+syn keyword ngxBoolean on
+syn keyword ngxBoolean off
+
+syn keyword ngxDirectiveBlock http contained
+syn keyword ngxDirectiveBlock mail contained
+syn keyword ngxDirectiveBlock events contained
+syn keyword ngxDirectiveBlock server contained
+syn keyword ngxDirectiveBlock match contained
+syn keyword ngxDirectiveBlock types contained
+syn keyword ngxDirectiveBlock location contained
+syn keyword ngxDirectiveBlock upstream contained
+syn keyword ngxDirectiveBlock charset_map contained
+syn keyword ngxDirectiveBlock limit_except contained
+syn keyword ngxDirectiveBlock if contained
+syn keyword ngxDirectiveBlock geo contained
+syn keyword ngxDirectiveBlock map contained
+syn keyword ngxDirectiveBlock split_clients contained
+
+syn keyword ngxDirectiveImportant include
+syn keyword ngxDirectiveImportant root
+syn keyword ngxDirectiveImportant server contained
+syn region ngxDirectiveImportantServer matchgroup=ngxDirectiveImportant start=+^\s*\zsserver\ze\s.*;+ skip=+\\\\\|\\\;+ end=+;+he=e-1 contains=ngxUpstreamServerOptions,ngxString,ngxIPaddr,ngxBoolean,ngxInteger,ngxTemplateVar
+syn keyword ngxDirectiveImportant server_name
+syn keyword ngxDirectiveImportant listen contained
+syn region ngxDirectiveImportantListen matchgroup=ngxDirectiveImportant start=+listen+ skip=+\\\\\|\\\;+ end=+;+he=e-1 contains=ngxListenOptions,ngxString,ngxIPaddr,ngxBoolean,ngxInteger,ngxTemplateVar
+syn keyword ngxDirectiveImportant internal
+syn keyword ngxDirectiveImportant proxy_pass
+syn keyword ngxDirectiveImportant memcached_pass
+syn keyword ngxDirectiveImportant fastcgi_pass
+syn keyword ngxDirectiveImportant scgi_pass
+syn keyword ngxDirectiveImportant uwsgi_pass
+syn keyword ngxDirectiveImportant try_files
+syn keyword ngxDirectiveImportant error_page
+syn keyword ngxDirectiveImportant post_action
+
+syn keyword ngxUpstreamServerOptions weight contained
+syn keyword ngxUpstreamServerOptions max_conns contained
+syn keyword ngxUpstreamServerOptions max_fails contained
+syn keyword ngxUpstreamServerOptions fail_timeout contained
+syn keyword ngxUpstreamServerOptions backup contained
+syn keyword ngxUpstreamServerOptions down contained
+syn keyword ngxUpstreamServerOptions resolve contained
+syn keyword ngxUpstreamServerOptions route contained
+syn keyword ngxUpstreamServerOptions service contained
+syn keyword ngxUpstreamServerOptions default_server contained
+syn keyword ngxUpstreamServerOptions slow_start contained
+
+syn keyword ngxListenOptions default_server contained
+syn keyword ngxListenOptions ssl contained
+syn keyword ngxListenOptions http2 contained
+syn keyword ngxListenOptions spdy contained
+syn keyword ngxListenOptions proxy_protocol contained
+syn keyword ngxListenOptions setfib contained
+syn keyword ngxListenOptions fastopen contained
+syn keyword ngxListenOptions backlog contained
+syn keyword ngxListenOptions rcvbuf contained
+syn keyword ngxListenOptions sndbuf contained
+syn keyword ngxListenOptions accept_filter contained
+syn keyword ngxListenOptions deferred contained
+syn keyword ngxListenOptions bind contained
+syn keyword ngxListenOptions ipv6only contained
+syn keyword ngxListenOptions reuseport contained
+syn keyword ngxListenOptions so_keepalive contained
+syn keyword ngxListenOptions keepidle contained
+
+syn keyword ngxDirectiveControl break
+syn keyword ngxDirectiveControl return
+syn keyword ngxDirectiveControl rewrite
+syn keyword ngxDirectiveControl set
+
+syn keyword ngxDirectiveDeprecated connections
+syn keyword ngxDirectiveDeprecated imap
+syn keyword ngxDirectiveDeprecated limit_zone
+syn keyword ngxDirectiveDeprecated mysql_test
+syn keyword ngxDirectiveDeprecated open_file_cache_retest
+syn keyword ngxDirectiveDeprecated optimize_server_names
+syn keyword ngxDirectiveDeprecated satisfy_any
+syn keyword ngxDirectiveDeprecated so_keepalive
+
+syn keyword ngxDirective absolute_redirect
+syn keyword ngxDirective accept_mutex
+syn keyword ngxDirective accept_mutex_delay
+syn keyword ngxDirective acceptex_read
+syn keyword ngxDirective access_log
+syn keyword ngxDirective add_after_body
+syn keyword ngxDirective add_before_body
+syn keyword ngxDirective add_header
+syn keyword ngxDirective addition_types
+syn keyword ngxDirective aio
+syn keyword ngxDirective aio_write
+syn keyword ngxDirective alias
+syn keyword ngxDirective allow
+syn keyword ngxDirective ancient_browser
+syn keyword ngxDirective ancient_browser_value
+syn keyword ngxDirective auth_basic
+syn keyword ngxDirective auth_basic_user_file
+syn keyword ngxDirective auth_http
+syn keyword ngxDirective auth_http_header
+syn keyword ngxDirective auth_http_pass_client_cert
+syn keyword ngxDirective auth_http_timeout
+syn keyword ngxDirective auth_jwt
+syn keyword ngxDirective auth_jwt_key_file
+syn keyword ngxDirective auth_request
+syn keyword ngxDirective auth_request_set
+syn keyword ngxDirective autoindex
+syn keyword ngxDirective autoindex_exact_size
+syn keyword ngxDirective autoindex_format
+syn keyword ngxDirective autoindex_localtime
+syn keyword ngxDirective charset
+syn keyword ngxDirective charset_map
+syn keyword ngxDirective charset_types
+syn keyword ngxDirective chunked_transfer_encoding
+syn keyword ngxDirective client_body_buffer_size
+syn keyword ngxDirective client_body_in_file_only
+syn keyword ngxDirective client_body_in_single_buffer
+syn keyword ngxDirective client_body_temp_path
+syn keyword ngxDirective client_body_timeout
+syn keyword ngxDirective client_header_buffer_size
+syn keyword ngxDirective client_header_timeout
+syn keyword ngxDirective client_max_body_size
+syn keyword ngxDirective connection_pool_size
+syn keyword ngxDirective create_full_put_path
+syn keyword ngxDirective daemon
+syn keyword ngxDirective dav_access
+syn keyword ngxDirective dav_methods
+syn keyword ngxDirective debug_connection
+syn keyword ngxDirective debug_points
+syn keyword ngxDirective default_type
+syn keyword ngxDirective degradation
+syn keyword ngxDirective degrade
+syn keyword ngxDirective deny
+syn keyword ngxDirective devpoll_changes
+syn keyword ngxDirective devpoll_events
+syn keyword ngxDirective directio
+syn keyword ngxDirective directio_alignment
+syn keyword ngxDirective disable_symlinks
+syn keyword ngxDirective empty_gif
+syn keyword ngxDirective env
+syn keyword ngxDirective epoll_events
+syn keyword ngxDirective error_log
+syn keyword ngxDirective etag
+syn keyword ngxDirective eventport_events
+syn keyword ngxDirective expires
+syn keyword ngxDirective f4f
+syn keyword ngxDirective f4f_buffer_size
+syn keyword ngxDirective fastcgi_bind
+syn keyword ngxDirective fastcgi_buffer_size
+syn keyword ngxDirective fastcgi_buffering
+syn keyword ngxDirective fastcgi_buffers
+syn keyword ngxDirective fastcgi_busy_buffers_size
+syn keyword ngxDirective fastcgi_cache
+syn keyword ngxDirective fastcgi_cache_bypass
+syn keyword ngxDirective fastcgi_cache_key
+syn keyword ngxDirective fastcgi_cache_lock
+syn keyword ngxDirective fastcgi_cache_lock_age
+syn keyword ngxDirective fastcgi_cache_lock_timeout
+syn keyword ngxDirective fastcgi_cache_max_range_offset
+syn keyword ngxDirective fastcgi_cache_methods
+syn keyword ngxDirective fastcgi_cache_min_uses
+syn keyword ngxDirective fastcgi_cache_path
+syn keyword ngxDirective fastcgi_cache_purge
+syn keyword ngxDirective fastcgi_cache_revalidate
+syn keyword ngxDirective fastcgi_cache_use_stale
+syn keyword ngxDirective fastcgi_cache_valid
+syn keyword ngxDirective fastcgi_catch_stderr
+syn keyword ngxDirective fastcgi_connect_timeout
+syn keyword ngxDirective fastcgi_force_ranges
+syn keyword ngxDirective fastcgi_hide_header
+syn keyword ngxDirective fastcgi_ignore_client_abort
+syn keyword ngxDirective fastcgi_ignore_headers
+syn keyword ngxDirective fastcgi_index
+syn keyword ngxDirective fastcgi_intercept_errors
+syn keyword ngxDirective fastcgi_keep_conn
+syn keyword ngxDirective fastcgi_limit_rate
+syn keyword ngxDirective fastcgi_max_temp_file_size
+syn keyword ngxDirective fastcgi_next_upstream
+syn keyword ngxDirective fastcgi_next_upstream_timeout
+syn keyword ngxDirective fastcgi_next_upstream_tries
+syn keyword ngxDirective fastcgi_no_cache
+syn keyword ngxDirective fastcgi_param
+syn keyword ngxDirective fastcgi_pass_header
+syn keyword ngxDirective fastcgi_pass_request_body
+syn keyword ngxDirective fastcgi_pass_request_headers
+syn keyword ngxDirective fastcgi_read_timeout
+syn keyword ngxDirective fastcgi_request_buffering
+syn keyword ngxDirective fastcgi_send_lowat
+syn keyword ngxDirective fastcgi_send_timeout
+syn keyword ngxDirective fastcgi_split_path_info
+syn keyword ngxDirective fastcgi_store
+syn keyword ngxDirective fastcgi_store_access
+syn keyword ngxDirective fastcgi_temp_file_write_size
+syn keyword ngxDirective fastcgi_temp_path
+syn keyword ngxDirective flv
+syn keyword ngxDirective geoip_city
+syn keyword ngxDirective geoip_country
+syn keyword ngxDirective geoip_org
+syn keyword ngxDirective geoip_proxy
+syn keyword ngxDirective geoip_proxy_recursive
+syn keyword ngxDirective google_perftools_profiles
+syn keyword ngxDirective gunzip
+syn keyword ngxDirective gunzip_buffers
+syn keyword ngxDirective gzip nextgroup=ngxGzipOn,ngxGzipOff skipwhite
+syn keyword ngxGzipOn on contained
+syn keyword ngxGzipOff off contained
+syn keyword ngxDirective gzip_buffers
+syn keyword ngxDirective gzip_comp_level
+syn keyword ngxDirective gzip_disable
+syn keyword ngxDirective gzip_hash
+syn keyword ngxDirective gzip_http_version
+syn keyword ngxDirective gzip_min_length
+syn keyword ngxDirective gzip_no_buffer
+syn keyword ngxDirective gzip_proxied
+syn keyword ngxDirective gzip_static
+syn keyword ngxDirective gzip_types
+syn keyword ngxDirective gzip_vary
+syn keyword ngxDirective gzip_window
+syn keyword ngxDirective hash
+syn keyword ngxDirective health_check
+syn keyword ngxDirective health_check_timeout
+syn keyword ngxDirective hls
+syn keyword ngxDirective hls_buffers
+syn keyword ngxDirective hls_forward_args
+syn keyword ngxDirective hls_fragment
+syn keyword ngxDirective hls_mp4_buffer_size
+syn keyword ngxDirective hls_mp4_max_buffer_size
+syn keyword ngxDirective http2_chunk_size
+syn keyword ngxDirective http2_body_preread_size
+syn keyword ngxDirective http2_idle_timeout
+syn keyword ngxDirective http2_max_concurrent_streams
+syn keyword ngxDirective http2_max_field_size
+syn keyword ngxDirective http2_max_header_size
+syn keyword ngxDirective http2_max_requests
+syn keyword ngxDirective http2_recv_buffer_size
+syn keyword ngxDirective http2_recv_timeout
+syn keyword ngxDirective if_modified_since
+syn keyword ngxDirective ignore_invalid_headers
+syn keyword ngxDirective image_filter
+syn keyword ngxDirective image_filter_buffer
+syn keyword ngxDirective image_filter_interlace
+syn keyword ngxDirective image_filter_jpeg_quality
+syn keyword ngxDirective image_filter_sharpen
+syn keyword ngxDirective image_filter_transparency
+syn keyword ngxDirective image_filter_webp_quality
+syn keyword ngxDirective imap_auth
+syn keyword ngxDirective imap_capabilities
+syn keyword ngxDirective imap_client_buffer
+syn keyword ngxDirective index
+syn keyword ngxDirective iocp_threads
+syn keyword ngxDirective ip_hash
+syn keyword ngxDirective js_access
+syn keyword ngxDirective js_content
+syn keyword ngxDirective js_filter
+syn keyword ngxDirective js_include
+syn keyword ngxDirective js_preread
+syn keyword ngxDirective js_set
+syn keyword ngxDirective keepalive
+syn keyword ngxDirective keepalive_disable
+syn keyword ngxDirective keepalive_requests
+syn keyword ngxDirective keepalive_timeout
+syn keyword ngxDirective kqueue_changes
+syn keyword ngxDirective kqueue_events
+syn keyword ngxDirective large_client_header_buffers
+syn keyword ngxDirective least_conn
+syn keyword ngxDirective least_time
+syn keyword ngxDirective limit_conn
+syn keyword ngxDirective limit_conn_dry_run
+syn keyword ngxDirective limit_conn_log_level
+syn keyword ngxDirective limit_conn_status
+syn keyword ngxDirective limit_conn_zone
+syn keyword ngxDirective limit_except
+syn keyword ngxDirective limit_rate
+syn keyword ngxDirective limit_rate_after
+syn keyword ngxDirective limit_req
+syn keyword ngxDirective limit_req_dry_run
+syn keyword ngxDirective limit_req_log_level
+syn keyword ngxDirective limit_req_status
+syn keyword ngxDirective limit_req_zone
+syn keyword ngxDirective lingering_close
+syn keyword ngxDirective lingering_time
+syn keyword ngxDirective lingering_timeout
+syn keyword ngxDirective load_module
+syn keyword ngxDirective lock_file
+syn keyword ngxDirective log_format
+syn keyword ngxDirective log_not_found
+syn keyword ngxDirective log_subrequest
+syn keyword ngxDirective map_hash_bucket_size
+syn keyword ngxDirective map_hash_max_size
+syn keyword ngxDirective master_process
+syn keyword ngxDirective max_ranges
+syn keyword ngxDirective memcached_bind
+syn keyword ngxDirective memcached_buffer_size
+syn keyword ngxDirective memcached_connect_timeout
+syn keyword ngxDirective memcached_force_ranges
+syn keyword ngxDirective memcached_gzip_flag
+syn keyword ngxDirective memcached_next_upstream
+syn keyword ngxDirective memcached_next_upstream_timeout
+syn keyword ngxDirective memcached_next_upstream_tries
+syn keyword ngxDirective memcached_read_timeout
+syn keyword ngxDirective memcached_send_timeout
+syn keyword ngxDirective merge_slashes
+syn keyword ngxDirective min_delete_depth
+syn keyword ngxDirective modern_browser
+syn keyword ngxDirective modern_browser_value
+syn keyword ngxDirective mp4
+syn keyword ngxDirective mp4_buffer_size
+syn keyword ngxDirective mp4_max_buffer_size
+syn keyword ngxDirective mp4_limit_rate
+syn keyword ngxDirective mp4_limit_rate_after
+syn keyword ngxDirective msie_padding
+syn keyword ngxDirective msie_refresh
+syn keyword ngxDirective multi_accept
+syn keyword ngxDirective ntlm
+syn keyword ngxDirective open_file_cache
+syn keyword ngxDirective open_file_cache_errors
+syn keyword ngxDirective open_file_cache_events
+syn keyword ngxDirective open_file_cache_min_uses
+syn keyword ngxDirective open_file_cache_valid
+syn keyword ngxDirective open_log_file_cache
+syn keyword ngxDirective output_buffers
+syn keyword ngxDirective override_charset
+syn keyword ngxDirective pcre_jit
+syn keyword ngxDirective perl
+syn keyword ngxDirective perl_modules
+syn keyword ngxDirective perl_require
+syn keyword ngxDirective perl_set
+syn keyword ngxDirective pid
+syn keyword ngxDirective pop3_auth
+syn keyword ngxDirective pop3_capabilities
+syn keyword ngxDirective port_in_redirect
+syn keyword ngxDirective post_acceptex
+syn keyword ngxDirective postpone_gzipping
+syn keyword ngxDirective postpone_output
+syn keyword ngxDirective preread_buffer_size
+syn keyword ngxDirective preread_timeout
+syn keyword ngxDirective protocol nextgroup=ngxMailProtocol skipwhite
+syn keyword ngxMailProtocol imap pop3 smtp contained
+syn keyword ngxDirective proxy
+syn keyword ngxDirective proxy_bind
+syn keyword ngxDirective proxy_buffer
+syn keyword ngxDirective proxy_buffer_size
+syn keyword ngxDirective proxy_buffering
+syn keyword ngxDirective proxy_buffers
+syn keyword ngxDirective proxy_busy_buffers_size
+syn keyword ngxDirective proxy_cache
+syn keyword ngxDirective proxy_cache_bypass
+syn keyword ngxDirective proxy_cache_convert_head
+syn keyword ngxDirective proxy_cache_key
+syn keyword ngxDirective proxy_cache_lock
+syn keyword ngxDirective proxy_cache_lock_age
+syn keyword ngxDirective proxy_cache_lock_timeout
+syn keyword ngxDirective proxy_cache_max_range_offset
+syn keyword ngxDirective proxy_cache_methods
+syn keyword ngxDirective proxy_cache_min_uses
+syn keyword ngxDirective proxy_cache_path
+syn keyword ngxDirective proxy_cache_purge
+syn keyword ngxDirective proxy_cache_revalidate
+syn keyword ngxDirective proxy_cache_use_stale
+syn keyword ngxDirective proxy_cache_valid
+syn keyword ngxDirective proxy_connect_timeout
+syn keyword ngxDirective proxy_cookie_domain
+syn keyword ngxDirective proxy_cookie_path
+syn keyword ngxDirective proxy_download_rate
+syn keyword ngxDirective proxy_force_ranges
+syn keyword ngxDirective proxy_headers_hash_bucket_size
+syn keyword ngxDirective proxy_headers_hash_max_size
+syn keyword ngxDirective proxy_hide_header
+syn keyword ngxDirective proxy_http_version
+syn keyword ngxDirective proxy_ignore_client_abort
+syn keyword ngxDirective proxy_ignore_headers
+syn keyword ngxDirective proxy_intercept_errors
+syn keyword ngxDirective proxy_limit_rate
+syn keyword ngxDirective proxy_max_temp_file_size
+syn keyword ngxDirective proxy_method
+syn keyword ngxDirective proxy_next_upstream contained
+syn region ngxDirectiveProxyNextUpstream matchgroup=ngxDirective start=+^\s*\zsproxy_next_upstream\ze\s.*;+ skip=+\\\\\|\\\;+ end=+;+he=e-1 contains=ngxProxyNextUpstreamOptions,ngxString,ngxTemplateVar
+syn keyword ngxDirective proxy_next_upstream_timeout
+syn keyword ngxDirective proxy_next_upstream_tries
+syn keyword ngxDirective proxy_no_cache
+syn keyword ngxDirective proxy_pass_error_message
+syn keyword ngxDirective proxy_pass_header
+syn keyword ngxDirective proxy_pass_request_body
+syn keyword ngxDirective proxy_pass_request_headers
+syn keyword ngxDirective proxy_protocol
+syn keyword ngxDirective proxy_protocol_timeout
+syn keyword ngxDirective proxy_read_timeout
+syn keyword ngxDirective proxy_redirect
+syn keyword ngxDirective proxy_request_buffering
+syn keyword ngxDirective proxy_responses
+syn keyword ngxDirective proxy_send_lowat
+syn keyword ngxDirective proxy_send_timeout
+syn keyword ngxDirective proxy_set_body
+syn keyword ngxDirective proxy_set_header
+syn keyword ngxDirective proxy_ssl_certificate
+syn keyword ngxDirective proxy_ssl_certificate_key
+syn keyword ngxDirective proxy_ssl_ciphers
+syn keyword ngxDirective proxy_ssl_crl
+syn keyword ngxDirective proxy_ssl_name
+syn keyword ngxDirective proxy_ssl_password_file
+syn keyword ngxDirective proxy_ssl_protocols nextgroup=ngxSSLProtocol skipwhite
+syn keyword ngxDirective proxy_ssl_server_name
+syn keyword ngxDirective proxy_ssl_session_reuse
+syn keyword ngxDirective proxy_ssl_trusted_certificate
+syn keyword ngxDirective proxy_ssl_verify
+syn keyword ngxDirective proxy_ssl_verify_depth
+syn keyword ngxDirective proxy_store
+syn keyword ngxDirective proxy_store_access
+syn keyword ngxDirective proxy_temp_file_write_size
+syn keyword ngxDirective proxy_temp_path
+syn keyword ngxDirective proxy_timeout
+syn keyword ngxDirective proxy_upload_rate
+syn keyword ngxDirective queue
+syn keyword ngxDirective random_index
+syn keyword ngxDirective read_ahead
+syn keyword ngxDirective real_ip_header
+syn keyword ngxDirective real_ip_recursive
+syn keyword ngxDirective recursive_error_pages
+syn keyword ngxDirective referer_hash_bucket_size
+syn keyword ngxDirective referer_hash_max_size
+syn keyword ngxDirective request_pool_size
+syn keyword ngxDirective reset_timedout_connection
+syn keyword ngxDirective resolver
+syn keyword ngxDirective resolver_timeout
+syn keyword ngxDirective rewrite_log
+syn keyword ngxDirective rtsig_overflow_events
+syn keyword ngxDirective rtsig_overflow_test
+syn keyword ngxDirective rtsig_overflow_threshold
+syn keyword ngxDirective rtsig_signo
+syn keyword ngxDirective satisfy
+syn keyword ngxDirective scgi_bind
+syn keyword ngxDirective scgi_buffer_size
+syn keyword ngxDirective scgi_buffering
+syn keyword ngxDirective scgi_buffers
+syn keyword ngxDirective scgi_busy_buffers_size
+syn keyword ngxDirective scgi_cache
+syn keyword ngxDirective scgi_cache_bypass
+syn keyword ngxDirective scgi_cache_key
+syn keyword ngxDirective scgi_cache_lock
+syn keyword ngxDirective scgi_cache_lock_age
+syn keyword ngxDirective scgi_cache_lock_timeout
+syn keyword ngxDirective scgi_cache_max_range_offset
+syn keyword ngxDirective scgi_cache_methods
+syn keyword ngxDirective scgi_cache_min_uses
+syn keyword ngxDirective scgi_cache_path
+syn keyword ngxDirective scgi_cache_purge
+syn keyword ngxDirective scgi_cache_revalidate
+syn keyword ngxDirective scgi_cache_use_stale
+syn keyword ngxDirective scgi_cache_valid
+syn keyword ngxDirective scgi_connect_timeout
+syn keyword ngxDirective scgi_force_ranges
+syn keyword ngxDirective scgi_hide_header
+syn keyword ngxDirective scgi_ignore_client_abort
+syn keyword ngxDirective scgi_ignore_headers
+syn keyword ngxDirective scgi_intercept_errors
+syn keyword ngxDirective scgi_limit_rate
+syn keyword ngxDirective scgi_max_temp_file_size
+syn keyword ngxDirective scgi_next_upstream
+syn keyword ngxDirective scgi_next_upstream_timeout
+syn keyword ngxDirective scgi_next_upstream_tries
+syn keyword ngxDirective scgi_no_cache
+syn keyword ngxDirective scgi_param
+syn keyword ngxDirective scgi_pass_header
+syn keyword ngxDirective scgi_pass_request_body
+syn keyword ngxDirective scgi_pass_request_headers
+syn keyword ngxDirective scgi_read_timeout
+syn keyword ngxDirective scgi_request_buffering
+syn keyword ngxDirective scgi_send_timeout
+syn keyword ngxDirective scgi_store
+syn keyword ngxDirective scgi_store_access
+syn keyword ngxDirective scgi_temp_file_write_size
+syn keyword ngxDirective scgi_temp_path
+syn keyword ngxDirective secure_link
+syn keyword ngxDirective secure_link_md5
+syn keyword ngxDirective secure_link_secret
+syn keyword ngxDirective send_lowat
+syn keyword ngxDirective send_timeout
+syn keyword ngxDirective sendfile
+syn keyword ngxDirective sendfile_max_chunk
+syn keyword ngxDirective server_name_in_redirect
+syn keyword ngxDirective server_names_hash_bucket_size
+syn keyword ngxDirective server_names_hash_max_size
+syn keyword ngxDirective server_tokens
+syn keyword ngxDirective session_log
+syn keyword ngxDirective session_log_format
+syn keyword ngxDirective session_log_zone
+syn keyword ngxDirective set_real_ip_from
+syn keyword ngxDirective slice
+syn keyword ngxDirective smtp_auth
+syn keyword ngxDirective smtp_capabilities
+syn keyword ngxDirective smtp_client_buffer
+syn keyword ngxDirective smtp_greeting_delay
+syn keyword ngxDirective source_charset
+syn keyword ngxDirective spdy_chunk_size
+syn keyword ngxDirective spdy_headers_comp
+syn keyword ngxDirective spdy_keepalive_timeout
+syn keyword ngxDirective spdy_max_concurrent_streams
+syn keyword ngxDirective spdy_pool_size
+syn keyword ngxDirective spdy_recv_buffer_size
+syn keyword ngxDirective spdy_recv_timeout
+syn keyword ngxDirective spdy_streams_index_size
+syn keyword ngxDirective ssi
+syn keyword ngxDirective ssi_ignore_recycled_buffers
+syn keyword ngxDirective ssi_last_modified
+syn keyword ngxDirective ssi_min_file_chunk
+syn keyword ngxDirective ssi_silent_errors
+syn keyword ngxDirective ssi_types
+syn keyword ngxDirective ssi_value_length
+syn keyword ngxDirective ssl
+syn keyword ngxDirective ssl_buffer_size
+syn keyword ngxDirective ssl_certificate
+syn keyword ngxDirective ssl_certificate_key
+syn keyword ngxDirective ssl_ciphers
+syn keyword ngxDirective ssl_client_certificate
+syn keyword ngxDirective ssl_crl
+syn keyword ngxDirective ssl_dhparam
+syn keyword ngxDirective ssl_ecdh_curve
+syn keyword ngxDirective ssl_engine
+syn keyword ngxDirective ssl_handshake_timeout
+syn keyword ngxDirective ssl_password_file
+syn keyword ngxDirective ssl_prefer_server_ciphers nextgroup=ngxSSLPreferServerCiphersOff,ngxSSLPreferServerCiphersOn skipwhite
+syn keyword ngxSSLPreferServerCiphersOn on contained
+syn keyword ngxSSLPreferServerCiphersOff off contained
+syn keyword ngxDirective ssl_preread
+syn keyword ngxDirective ssl_protocols nextgroup=ngxSSLProtocol,ngxSSLProtocolDeprecated skipwhite
+syn match ngxSSLProtocol 'TLSv1' contained nextgroup=ngxSSLProtocol,ngxSSLProtocolDeprecated skipwhite
+syn match ngxSSLProtocol 'TLSv1\.1' contained nextgroup=ngxSSLProtocol,ngxSSLProtocolDeprecated skipwhite
+syn match ngxSSLProtocol 'TLSv1\.2' contained nextgroup=ngxSSLProtocol,ngxSSLProtocolDeprecated skipwhite
+syn match ngxSSLProtocol 'TLSv1\.3' contained nextgroup=ngxSSLProtocol,ngxSSLProtocolDeprecated skipwhite
+
+" Do not enable highlighting of insecure protocols if sslecure is loaded
+if !exists('g:loaded_sslsecure')
+ syn keyword ngxSSLProtocolDeprecated SSLv2 SSLv3 contained nextgroup=ngxSSLProtocol,ngxSSLProtocolDeprecated skipwhite
+else
+ syn match ngxSSLProtocol 'SSLv2' contained nextgroup=ngxSSLProtocol,ngxSSLProtocolDeprecated skipwhite
+ syn match ngxSSLProtocol 'SSLv3' contained nextgroup=ngxSSLProtocol,ngxSSLProtocolDeprecated skipwhite
+endif
+
+syn keyword ngxDirective ssl_session_cache
+syn keyword ngxDirective ssl_session_ticket_key
+syn keyword ngxDirective ssl_session_tickets nextgroup=ngxSSLSessionTicketsOn,ngxSSLSessionTicketsOff skipwhite
+syn keyword ngxSSLSessionTicketsOn on contained
+syn keyword ngxSSLSessionTicketsOff off contained
+syn keyword ngxDirective ssl_session_timeout
+syn keyword ngxDirective ssl_stapling
+syn keyword ngxDirective ssl_stapling_file
+syn keyword ngxDirective ssl_stapling_responder
+syn keyword ngxDirective ssl_stapling_verify
+syn keyword ngxDirective ssl_trusted_certificate
+syn keyword ngxDirective ssl_verify_client
+syn keyword ngxDirective ssl_verify_depth
+syn keyword ngxDirective starttls
+syn keyword ngxDirective state
+syn keyword ngxDirective status
+syn keyword ngxDirective status_format
+syn keyword ngxDirective status_zone
+syn keyword ngxDirective sticky contained
+syn keyword ngxDirective sticky_cookie_insert contained
+syn region ngxDirectiveSticky matchgroup=ngxDirective start=+^\s*\zssticky\ze\s.*;+ skip=+\\\\\|\\\;+ end=+;+he=e-1 contains=ngxCookieOptions,ngxString,ngxBoolean,ngxInteger,ngxTemplateVar
+syn keyword ngxDirective stub_status
+syn keyword ngxDirective sub_filter
+syn keyword ngxDirective sub_filter_last_modified
+syn keyword ngxDirective sub_filter_once
+syn keyword ngxDirective sub_filter_types
+syn keyword ngxDirective tcp_nodelay
+syn keyword ngxDirective tcp_nopush
+syn keyword ngxDirective thread_pool
+syn keyword ngxDirective thread_stack_size
+syn keyword ngxDirective timeout
+syn keyword ngxDirective timer_resolution
+syn keyword ngxDirective types_hash_bucket_size
+syn keyword ngxDirective types_hash_max_size
+syn keyword ngxDirective underscores_in_headers
+syn keyword ngxDirective uninitialized_variable_warn
+syn keyword ngxDirective upstream_conf
+syn keyword ngxDirective use
+syn keyword ngxDirective user
+syn keyword ngxDirective userid
+syn keyword ngxDirective userid_domain
+syn keyword ngxDirective userid_expires
+syn keyword ngxDirective userid_mark
+syn keyword ngxDirective userid_name
+syn keyword ngxDirective userid_p3p
+syn keyword ngxDirective userid_path
+syn keyword ngxDirective userid_service
+syn keyword ngxDirective uwsgi_bind
+syn keyword ngxDirective uwsgi_buffer_size
+syn keyword ngxDirective uwsgi_buffering
+syn keyword ngxDirective uwsgi_buffers
+syn keyword ngxDirective uwsgi_busy_buffers_size
+syn keyword ngxDirective uwsgi_cache
+syn keyword ngxDirective uwsgi_cache_bypass
+syn keyword ngxDirective uwsgi_cache_key
+syn keyword ngxDirective uwsgi_cache_lock
+syn keyword ngxDirective uwsgi_cache_lock_age
+syn keyword ngxDirective uwsgi_cache_lock_timeout
+syn keyword ngxDirective uwsgi_cache_methods
+syn keyword ngxDirective uwsgi_cache_min_uses
+syn keyword ngxDirective uwsgi_cache_path
+syn keyword ngxDirective uwsgi_cache_purge
+syn keyword ngxDirective uwsgi_cache_revalidate
+syn keyword ngxDirective uwsgi_cache_use_stale
+syn keyword ngxDirective uwsgi_cache_valid
+syn keyword ngxDirective uwsgi_connect_timeout
+syn keyword ngxDirective uwsgi_force_ranges
+syn keyword ngxDirective uwsgi_hide_header
+syn keyword ngxDirective uwsgi_ignore_client_abort
+syn keyword ngxDirective uwsgi_ignore_headers
+syn keyword ngxDirective uwsgi_intercept_errors
+syn keyword ngxDirective uwsgi_limit_rate
+syn keyword ngxDirective uwsgi_max_temp_file_size
+syn keyword ngxDirective uwsgi_modifier1
+syn keyword ngxDirective uwsgi_modifier2
+syn keyword ngxDirective uwsgi_next_upstream
+syn keyword ngxDirective uwsgi_next_upstream_timeout
+syn keyword ngxDirective uwsgi_next_upstream_tries
+syn keyword ngxDirective uwsgi_no_cache
+syn keyword ngxDirective uwsgi_param
+syn keyword ngxDirective uwsgi_pass
+syn keyword ngxDirective uwsgi_pass_header
+syn keyword ngxDirective uwsgi_pass_request_body
+syn keyword ngxDirective uwsgi_pass_request_headers
+syn keyword ngxDirective uwsgi_read_timeout
+syn keyword ngxDirective uwsgi_request_buffering
+syn keyword ngxDirective uwsgi_send_timeout
+syn keyword ngxDirective uwsgi_ssl_certificate
+syn keyword ngxDirective uwsgi_ssl_certificate_key
+syn keyword ngxDirective uwsgi_ssl_ciphers
+syn keyword ngxDirective uwsgi_ssl_crl
+syn keyword ngxDirective uwsgi_ssl_name
+syn keyword ngxDirective uwsgi_ssl_password_file
+syn keyword ngxDirective uwsgi_ssl_protocols nextgroup=ngxSSLProtocol skipwhite
+syn keyword ngxDirective uwsgi_ssl_server_name
+syn keyword ngxDirective uwsgi_ssl_session_reuse
+syn keyword ngxDirective uwsgi_ssl_trusted_certificate
+syn keyword ngxDirective uwsgi_ssl_verify
+syn keyword ngxDirective uwsgi_ssl_verify_depth
+syn keyword ngxDirective uwsgi_store
+syn keyword ngxDirective uwsgi_store_access
+syn keyword ngxDirective uwsgi_string
+syn keyword ngxDirective uwsgi_temp_file_write_size
+syn keyword ngxDirective uwsgi_temp_path
+syn keyword ngxDirective valid_referers
+syn keyword ngxDirective variables_hash_bucket_size
+syn keyword ngxDirective variables_hash_max_size
+syn keyword ngxDirective worker_aio_requests
+syn keyword ngxDirective worker_connections
+syn keyword ngxDirective worker_cpu_affinity
+syn keyword ngxDirective worker_priority
+syn keyword ngxDirective worker_processes
+syn keyword ngxDirective worker_rlimit_core
+syn keyword ngxDirective worker_rlimit_nofile
+syn keyword ngxDirective worker_rlimit_sigpending
+syn keyword ngxDirective worker_threads
+syn keyword ngxDirective working_directory
+syn keyword ngxDirective xclient
+syn keyword ngxDirective xml_entities
+syn keyword ngxDirective xslt_last_modified
+syn keyword ngxDirective xslt_param
+syn keyword ngxDirective xslt_string_param
+syn keyword ngxDirective xslt_stylesheet
+syn keyword ngxDirective xslt_types
+syn keyword ngxDirective zone
+
+" Do not enable highlighting of insecure ciphers if sslecure is loaded
+if !exists('g:loaded_sslsecure')
+ " Mark insecure SSL Ciphers (Note: List might not not complete)
+ " Reference: https://www.openssl.org/docs/man1.0.2/apps/ciphers.html
+ syn match ngxSSLCipherInsecure '[^!]\zsSSLv3'
+ syn match ngxSSLCipherInsecure '[^!]\zsSSLv2'
+ syn match ngxSSLCipherInsecure '[^!]\zsHIGH'
+ syn match ngxSSLCipherInsecure '[^!]\zsMEDIUM'
+ syn match ngxSSLCipherInsecure '[^!]\zsLOW'
+ syn match ngxSSLCipherInsecure '[^!]\zsDEFAULT'
+ syn match ngxSSLCipherInsecure '[^!]\zsCOMPLEMENTOFDEFAULT'
+ syn match ngxSSLCipherInsecure '[^!]\zsALL'
+ syn match ngxSSLCipherInsecure '[^!]\zsCOMPLEMENTOFALL'
+
+ " SHA ciphers are only used in HMAC with all known OpenSSL/ LibreSSL cipher suites and MAC
+ " usage is still considered safe
+ " syn match ngxSSLCipherInsecure '[^!]\zsSHA\ze\D' " Match SHA1 without matching SHA256+
+ " syn match ngxSSLCipherInsecure '[^!]\zsSHA1'
+ syn match ngxSSLCipherInsecure '[^!]\zsMD5'
+ syn match ngxSSLCipherInsecure '[^!]\zsRC2'
+ syn match ngxSSLCipherInsecure '[^!]\zsRC4'
+ syn match ngxSSLCipherInsecure '[^!]\zs3DES'
+ syn match ngxSSLCipherInsecure '[^!3]\zsDES'
+ syn match ngxSSLCipherInsecure '[^!]\zsaDSS'
+ syn match ngxSSLCipherInsecure '[^!a]\zsDSS'
+ syn match ngxSSLCipherInsecure '[^!]\zsPSK'
+ syn match ngxSSLCipherInsecure '[^!]\zsIDEA'
+ syn match ngxSSLCipherInsecure '[^!]\zsSEED'
+ syn match ngxSSLCipherInsecure '[^!]\zsEXP\w*' " Match all EXPORT ciphers
+ syn match ngxSSLCipherInsecure '[^!]\zsaGOST\w*' " Match all GOST ciphers
+ syn match ngxSSLCipherInsecure '[^!]\zskGOST\w*'
+ syn match ngxSSLCipherInsecure '[^!ak]\zsGOST\w*'
+ syn match ngxSSLCipherInsecure '[^!]\zs[kae]\?FZA' " Not implemented
+ syn match ngxSSLCipherInsecure '[^!]\zsECB'
+ syn match ngxSSLCipherInsecure '[^!]\zs[aes]NULL'
+
+ " Anonymous cipher suites should never be used
+ syn match ngxSSLCipherInsecure '[^!ECa]\zsDH\ze[^E]' " Try to match DH without DHE, EDH, EECDH, etc.
+ syn match ngxSSLCipherInsecure '[^!EA]\zsECDH\ze[^E]' " Do not match EECDH, ECDHE
+ syn match ngxSSLCipherInsecure '[^!]\zsADH'
+ syn match ngxSSLCipherInsecure '[^!]\zskDHE'
+ syn match ngxSSLCipherInsecure '[^!]\zskEDH'
+ syn match ngxSSLCipherInsecure '[^!]\zskECDHE'
+ syn match ngxSSLCipherInsecure '[^!]\zskEECDH'
+ syn match ngxSSLCipherInsecure '[^!E]\zsAECDH'
+endif
+
+syn keyword ngxProxyNextUpstreamOptions error contained
+syn keyword ngxProxyNextUpstreamOptions timeout contained
+syn keyword ngxProxyNextUpstreamOptions invalid_header contained
+syn keyword ngxProxyNextUpstreamOptions http_500 contained
+syn keyword ngxProxyNextUpstreamOptions http_502 contained
+syn keyword ngxProxyNextUpstreamOptions http_503 contained
+syn keyword ngxProxyNextUpstreamOptions http_504 contained
+syn keyword ngxProxyNextUpstreamOptions http_403 contained
+syn keyword ngxProxyNextUpstreamOptions http_404 contained
+syn keyword ngxProxyNextUpstreamOptions http_429 contained
+syn keyword ngxProxyNextUpstreamOptions non_idempotent contained
+syn keyword ngxProxyNextUpstreamOptions off contained
+
+syn keyword ngxStickyOptions cookie contained
+syn region ngxStickyOptionsCookie matchgroup=ngxStickyOptions start=+^\s*\zssticky\s\s*cookie\ze\s.*;+ skip=+\\\\\|\\\;+ end=+;+he=e-1 contains=ngxCookieOptions,ngxString,ngxBoolean,ngxInteger,ngxTemplateVar
+syn keyword ngxStickyOptions route contained
+syn keyword ngxStickyOptions learn contained
+
+syn keyword ngxCookieOptions expires contained
+syn keyword ngxCookieOptions domain contained
+syn keyword ngxCookieOptions httponly contained
+syn keyword ngxCookieOptions secure contained
+syn keyword ngxCookieOptions path contained
+
+" 3rd party module list:
+" https://www.nginx.com/resources/wiki/modules/
+
+" Accept Language Module <https://www.nginx.com/resources/wiki/modules/accept_language/>
+" Parses the Accept-Language header and gives the most suitable locale from a list of supported locales.
+syn keyword ngxDirectiveThirdParty set_from_accept_language
+
+" Access Key Module (DEPRECATED) <http://wiki.nginx.org/NginxHttpAccessKeyModule>
+" Denies access unless the request URL contains an access key.
+syn keyword ngxDirectiveDeprecated accesskey
+syn keyword ngxDirectiveDeprecated accesskey_arg
+syn keyword ngxDirectiveDeprecated accesskey_hashmethod
+syn keyword ngxDirectiveDeprecated accesskey_signature
+
+" Asynchronous FastCGI Module <https://github.com/rsms/afcgi>
+" Primarily a modified version of the Nginx FastCGI module which implements multiplexing of connections, allowing a single FastCGI server to handle many concurrent requests.
+" syn keyword ngxDirectiveThirdParty fastcgi_bind
+" syn keyword ngxDirectiveThirdParty fastcgi_buffer_size
+" syn keyword ngxDirectiveThirdParty fastcgi_buffers
+" syn keyword ngxDirectiveThirdParty fastcgi_busy_buffers_size
+" syn keyword ngxDirectiveThirdParty fastcgi_cache
+" syn keyword ngxDirectiveThirdParty fastcgi_cache_key
+" syn keyword ngxDirectiveThirdParty fastcgi_cache_methods
+" syn keyword ngxDirectiveThirdParty fastcgi_cache_min_uses
+" syn keyword ngxDirectiveThirdParty fastcgi_cache_path
+" syn keyword ngxDirectiveThirdParty fastcgi_cache_use_stale
+" syn keyword ngxDirectiveThirdParty fastcgi_cache_valid
+" syn keyword ngxDirectiveThirdParty fastcgi_catch_stderr
+" syn keyword ngxDirectiveThirdParty fastcgi_connect_timeout
+" syn keyword ngxDirectiveThirdParty fastcgi_hide_header
+" syn keyword ngxDirectiveThirdParty fastcgi_ignore_client_abort
+" syn keyword ngxDirectiveThirdParty fastcgi_ignore_headers
+" syn keyword ngxDirectiveThirdParty fastcgi_index
+" syn keyword ngxDirectiveThirdParty fastcgi_intercept_errors
+" syn keyword ngxDirectiveThirdParty fastcgi_max_temp_file_size
+" syn keyword ngxDirectiveThirdParty fastcgi_next_upstream
+" syn keyword ngxDirectiveThirdParty fastcgi_param
+" syn keyword ngxDirectiveThirdParty fastcgi_pass
+" syn keyword ngxDirectiveThirdParty fastcgi_pass_header
+" syn keyword ngxDirectiveThirdParty fastcgi_pass_request_body
+" syn keyword ngxDirectiveThirdParty fastcgi_pass_request_headers
+" syn keyword ngxDirectiveThirdParty fastcgi_read_timeout
+" syn keyword ngxDirectiveThirdParty fastcgi_send_lowat
+" syn keyword ngxDirectiveThirdParty fastcgi_send_timeout
+" syn keyword ngxDirectiveThirdParty fastcgi_split_path_info
+" syn keyword ngxDirectiveThirdParty fastcgi_store
+" syn keyword ngxDirectiveThirdParty fastcgi_store_access
+" syn keyword ngxDirectiveThirdParty fastcgi_temp_file_write_size
+" syn keyword ngxDirectiveThirdParty fastcgi_temp_path
+syn keyword ngxDirectiveDeprecated fastcgi_upstream_fail_timeout
+syn keyword ngxDirectiveDeprecated fastcgi_upstream_max_fails
+
+" Akamai G2O Module <https://github.com/kaltura/nginx_mod_akamai_g2o>
+" Nginx Module for Authenticating Akamai G2O requests
+syn keyword ngxDirectiveThirdParty g2o
+syn keyword ngxDirectiveThirdParty g2o_nonce
+syn keyword ngxDirectiveThirdParty g2o_key
+
+" Lua Module <https://github.com/alacner/nginx_lua_module>
+" You can be very simple to execute lua code for nginx
+syn keyword ngxDirectiveThirdParty lua_file
+
+" Array Variable Module <https://github.com/openresty/array-var-nginx-module>
+" Add support for array-typed variables to nginx config files
+syn keyword ngxDirectiveThirdParty array_split
+syn keyword ngxDirectiveThirdParty array_join
+syn keyword ngxDirectiveThirdParty array_map
+syn keyword ngxDirectiveThirdParty array_map_op
+
+" Nginx Audio Track for HTTP Live Streaming <https://github.com/flavioribeiro/nginx-audio-track-for-hls-module>
+" This nginx module generates audio track for hls streams on the fly.
+syn keyword ngxDirectiveThirdParty ngx_hls_audio_track
+syn keyword ngxDirectiveThirdParty ngx_hls_audio_track_rootpath
+syn keyword ngxDirectiveThirdParty ngx_hls_audio_track_output_format
+syn keyword ngxDirectiveThirdParty ngx_hls_audio_track_output_header
+
+" AWS Proxy Module <https://github.com/anomalizer/ngx_aws_auth>
+" Nginx module to proxy to authenticated AWS services
+syn keyword ngxDirectiveThirdParty aws_access_key
+syn keyword ngxDirectiveThirdParty aws_key_scope
+syn keyword ngxDirectiveThirdParty aws_signing_key
+syn keyword ngxDirectiveThirdParty aws_endpoint
+syn keyword ngxDirectiveThirdParty aws_s3_bucket
+syn keyword ngxDirectiveThirdParty aws_sign
+
+" Backtrace module <https://github.com/alibaba/nginx-backtrace>
+" A Nginx module to dump backtrace when a worker process exits abnormally
+syn keyword ngxDirectiveThirdParty backtrace_log
+syn keyword ngxDirectiveThirdParty backtrace_max_stack_size
+
+" Brotli Module <https://github.com/google/ngx_brotli>
+" Nginx module for Brotli compression
+syn keyword ngxDirectiveThirdParty brotli_static
+syn keyword ngxDirectiveThirdParty brotli
+syn keyword ngxDirectiveThirdParty brotli_types
+syn keyword ngxDirectiveThirdParty brotli_buffers
+syn keyword ngxDirectiveThirdParty brotli_comp_level
+syn keyword ngxDirectiveThirdParty brotli_window
+syn keyword ngxDirectiveThirdParty brotli_min_length
+
+" Cache Purge Module <https://github.com/FRiCKLE/ngx_cache_purge>
+" Adds ability to purge content from FastCGI, proxy, SCGI and uWSGI caches.
+syn keyword ngxDirectiveThirdParty fastcgi_cache_purge
+syn keyword ngxDirectiveThirdParty proxy_cache_purge
+" syn keyword ngxDirectiveThirdParty scgi_cache_purge
+" syn keyword ngxDirectiveThirdParty uwsgi_cache_purge
+
+" Chunkin Module (DEPRECATED) <http://wiki.nginx.org/NginxHttpChunkinModule>
+" HTTP 1.1 chunked-encoding request body support for Nginx.
+syn keyword ngxDirectiveDeprecated chunkin
+syn keyword ngxDirectiveDeprecated chunkin_keepalive
+syn keyword ngxDirectiveDeprecated chunkin_max_chunks_per_buf
+syn keyword ngxDirectiveDeprecated chunkin_resume
+
+" Circle GIF Module <https://github.com/evanmiller/nginx_circle_gif>
+" Generates simple circle images with the colors and size specified in the URL.
+syn keyword ngxDirectiveThirdParty circle_gif
+syn keyword ngxDirectiveThirdParty circle_gif_max_radius
+syn keyword ngxDirectiveThirdParty circle_gif_min_radius
+syn keyword ngxDirectiveThirdParty circle_gif_step_radius
+
+" Nginx-Clojure Module <http://nginx-clojure.github.io/index.html>
+" Parses the Accept-Language header and gives the most suitable locale from a list of supported locales.
+syn keyword ngxDirectiveThirdParty jvm_path
+syn keyword ngxDirectiveThirdParty jvm_var
+syn keyword ngxDirectiveThirdParty jvm_classpath
+syn keyword ngxDirectiveThirdParty jvm_classpath_check
+syn keyword ngxDirectiveThirdParty jvm_workers
+syn keyword ngxDirectiveThirdParty jvm_options
+syn keyword ngxDirectiveThirdParty jvm_handler_type
+syn keyword ngxDirectiveThirdParty jvm_init_handler_name
+syn keyword ngxDirectiveThirdParty jvm_init_handler_code
+syn keyword ngxDirectiveThirdParty jvm_exit_handler_name
+syn keyword ngxDirectiveThirdParty jvm_exit_handler_code
+syn keyword ngxDirectiveThirdParty handlers_lazy_init
+syn keyword ngxDirectiveThirdParty auto_upgrade_ws
+syn keyword ngxDirectiveThirdParty content_handler_type
+syn keyword ngxDirectiveThirdParty content_handler_name
+syn keyword ngxDirectiveThirdParty content_handler_code
+syn keyword ngxDirectiveThirdParty rewrite_handler_type
+syn keyword ngxDirectiveThirdParty rewrite_handler_name
+syn keyword ngxDirectiveThirdParty rewrite_handler_code
+syn keyword ngxDirectiveThirdParty access_handler_type
+syn keyword ngxDirectiveThirdParty access_handler_name
+syn keyword ngxDirectiveThirdParty access_handler_code
+syn keyword ngxDirectiveThirdParty header_filter_type
+syn keyword ngxDirectiveThirdParty header_filter_name
+syn keyword ngxDirectiveThirdParty header_filter_code
+syn keyword ngxDirectiveThirdParty content_handler_property
+syn keyword ngxDirectiveThirdParty rewrite_handler_property
+syn keyword ngxDirectiveThirdParty access_handler_property
+syn keyword ngxDirectiveThirdParty header_filter_property
+syn keyword ngxDirectiveThirdParty always_read_body
+syn keyword ngxDirectiveThirdParty shared_map
+syn keyword ngxDirectiveThirdParty write_page_size
+
+" Upstream Consistent Hash <https://www.nginx.com/resources/wiki/modules/consistent_hash/>
+" A load balancer that uses an internal consistent hash ring to select the right backend node.
+syn keyword ngxDirectiveThirdParty consistent_hash
+
+" Nginx Development Kit <https://github.com/simpl/ngx_devel_kit>
+" The NDK is an Nginx module that is designed to extend the core functionality of the excellent Nginx webserver in a way that can be used as a basis of other Nginx modules.
+" NDK_UPSTREAM_LIST
+" This submodule provides a directive that creates a list of upstreams, with optional weighting. This list can then be used by other modules to hash over the upstreams however they choose.
+syn keyword ngxDirectiveThirdParty upstream_list
+
+" Drizzle Module <https://www.nginx.com/resources/wiki/modules/drizzle/>
+" Upstream module for talking to MySQL and Drizzle directly
+syn keyword ngxDirectiveThirdParty drizzle_server
+syn keyword ngxDirectiveThirdParty drizzle_keepalive
+syn keyword ngxDirectiveThirdParty drizzle_query
+syn keyword ngxDirectiveThirdParty drizzle_pass
+syn keyword ngxDirectiveThirdParty drizzle_connect_timeout
+syn keyword ngxDirectiveThirdParty drizzle_send_query_timeout
+syn keyword ngxDirectiveThirdParty drizzle_recv_cols_timeout
+syn keyword ngxDirectiveThirdParty drizzle_recv_rows_timeout
+syn keyword ngxDirectiveThirdParty drizzle_buffer_size
+syn keyword ngxDirectiveThirdParty drizzle_module_header
+syn keyword ngxDirectiveThirdParty drizzle_status
+
+" Dynamic ETags Module <https://github.com/kali/nginx-dynamic-etags>
+" Attempt at handling ETag / If-None-Match on proxied content.
+syn keyword ngxDirectiveThirdParty dynamic_etags
+
+" Echo Module <https://www.nginx.com/resources/wiki/modules/echo/>
+" Bringing the power of "echo", "sleep", "time" and more to Nginx's config file
+syn keyword ngxDirectiveThirdParty echo
+syn keyword ngxDirectiveThirdParty echo_duplicate
+syn keyword ngxDirectiveThirdParty echo_flush
+syn keyword ngxDirectiveThirdParty echo_sleep
+syn keyword ngxDirectiveThirdParty echo_blocking_sleep
+syn keyword ngxDirectiveThirdParty echo_reset_timer
+syn keyword ngxDirectiveThirdParty echo_read_request_body
+syn keyword ngxDirectiveThirdParty echo_location_async
+syn keyword ngxDirectiveThirdParty echo_location
+syn keyword ngxDirectiveThirdParty echo_subrequest_async
+syn keyword ngxDirectiveThirdParty echo_subrequest
+syn keyword ngxDirectiveThirdParty echo_foreach_split
+syn keyword ngxDirectiveThirdParty echo_end
+syn keyword ngxDirectiveThirdParty echo_request_body
+syn keyword ngxDirectiveThirdParty echo_exec
+syn keyword ngxDirectiveThirdParty echo_status
+syn keyword ngxDirectiveThirdParty echo_before_body
+syn keyword ngxDirectiveThirdParty echo_after_body
+
+" Encrypted Session Module <https://github.com/openresty/encrypted-session-nginx-module>
+" Encrypt and decrypt nginx variable values
+syn keyword ngxDirectiveThirdParty encrypted_session_key
+syn keyword ngxDirectiveThirdParty encrypted_session_iv
+syn keyword ngxDirectiveThirdParty encrypted_session_expires
+syn keyword ngxDirectiveThirdParty set_encrypt_session
+syn keyword ngxDirectiveThirdParty set_decrypt_session
+
+" Enhanced Memcached Module <https://github.com/bpaquet/ngx_http_enhanced_memcached_module>
+" This module is based on the standard Nginx Memcached module, with some additonal features
+syn keyword ngxDirectiveThirdParty enhanced_memcached_pass
+syn keyword ngxDirectiveThirdParty enhanced_memcached_hash_keys_with_md5
+syn keyword ngxDirectiveThirdParty enhanced_memcached_allow_put
+syn keyword ngxDirectiveThirdParty enhanced_memcached_allow_delete
+syn keyword ngxDirectiveThirdParty enhanced_memcached_stats
+syn keyword ngxDirectiveThirdParty enhanced_memcached_flush
+syn keyword ngxDirectiveThirdParty enhanced_memcached_flush_namespace
+syn keyword ngxDirectiveThirdParty enhanced_memcached_bind
+syn keyword ngxDirectiveThirdParty enhanced_memcached_connect_timeout
+syn keyword ngxDirectiveThirdParty enhanced_memcached_send_timeout
+syn keyword ngxDirectiveThirdParty enhanced_memcached_buffer_size
+syn keyword ngxDirectiveThirdParty enhanced_memcached_read_timeout
+
+" Events Module (DEPRECATED) <http://docs.dutov.org/nginx_modules_events_en.html>
+" Provides options for start/stop events.
+syn keyword ngxDirectiveDeprecated on_start
+syn keyword ngxDirectiveDeprecated on_stop
+
+" EY Balancer Module <https://github.com/ezmobius/nginx-ey-balancer>
+" Adds a request queue to Nginx that allows the limiting of concurrent requests passed to the upstream.
+syn keyword ngxDirectiveThirdParty max_connections
+syn keyword ngxDirectiveThirdParty max_connections_max_queue_length
+syn keyword ngxDirectiveThirdParty max_connections_queue_timeout
+
+" Upstream Fair Balancer <https://www.nginx.com/resources/wiki/modules/fair_balancer/>
+" Sends an incoming request to the least-busy backend server, rather than distributing requests round-robin.
+syn keyword ngxDirectiveThirdParty fair
+syn keyword ngxDirectiveThirdParty upstream_fair_shm_size
+
+" Fancy Indexes Module <https://github.com/aperezdc/ngx-fancyindex>
+" Like the built-in autoindex module, but fancier.
+syn keyword ngxDirectiveThirdParty fancyindex
+syn keyword ngxDirectiveThirdParty fancyindex_default_sort
+syn keyword ngxDirectiveThirdParty fancyindex_directories_first
+syn keyword ngxDirectiveThirdParty fancyindex_css_href
+syn keyword ngxDirectiveThirdParty fancyindex_exact_size
+syn keyword ngxDirectiveThirdParty fancyindex_name_length
+syn keyword ngxDirectiveThirdParty fancyindex_footer
+syn keyword ngxDirectiveThirdParty fancyindex_header
+syn keyword ngxDirectiveThirdParty fancyindex_show_path
+syn keyword ngxDirectiveThirdParty fancyindex_ignore
+syn keyword ngxDirectiveThirdParty fancyindex_hide_symlinks
+syn keyword ngxDirectiveThirdParty fancyindex_localtime
+syn keyword ngxDirectiveThirdParty fancyindex_time_format
+
+" Form Auth Module <https://github.com/veruu/ngx_form_auth>
+" Provides authentication and authorization with credentials submitted via POST request
+syn keyword ngxDirectiveThirdParty form_auth
+syn keyword ngxDirectiveThirdParty form_auth_pam_service
+syn keyword ngxDirectiveThirdParty form_auth_login
+syn keyword ngxDirectiveThirdParty form_auth_password
+syn keyword ngxDirectiveThirdParty form_auth_remote_user
+
+" Form Input Module <https://github.com/calio/form-input-nginx-module>
+" Reads HTTP POST and PUT request body encoded in "application/x-www-form-urlencoded" and parses the arguments into nginx variables.
+syn keyword ngxDirectiveThirdParty set_form_input
+syn keyword ngxDirectiveThirdParty set_form_input_multi
+
+" GeoIP Module (DEPRECATED) <http://wiki.nginx.org/NginxHttp3rdPartyGeoIPModule>
+" Country code lookups via the MaxMind GeoIP API.
+syn keyword ngxDirectiveDeprecated geoip_country_file
+
+" GeoIP 2 Module <https://github.com/leev/ngx_http_geoip2_module>
+" Creates variables with values from the maxmind geoip2 databases based on the client IP
+syn keyword ngxDirectiveThirdParty geoip2
+
+" GridFS Module <https://github.com/mdirolf/nginx-gridfs>
+" Nginx module for serving files from MongoDB's GridFS
+syn keyword ngxDirectiveThirdParty gridfs
+
+" Headers More Module <https://github.com/openresty/headers-more-nginx-module>
+" Set and clear input and output headers...more than "add"!
+syn keyword ngxDirectiveThirdParty more_clear_headers
+syn keyword ngxDirectiveThirdParty more_clear_input_headers
+syn keyword ngxDirectiveThirdParty more_set_headers
+syn keyword ngxDirectiveThirdParty more_set_input_headers
+
+" Health Checks Upstreams Module <https://www.nginx.com/resources/wiki/modules/healthcheck/>
+" Polls backends and if they respond with HTTP 200 + an optional request body, they are marked good. Otherwise, they are marked bad.
+syn keyword ngxDirectiveThirdParty healthcheck_enabled
+syn keyword ngxDirectiveThirdParty healthcheck_delay
+syn keyword ngxDirectiveThirdParty healthcheck_timeout
+syn keyword ngxDirectiveThirdParty healthcheck_failcount
+syn keyword ngxDirectiveThirdParty healthcheck_send
+syn keyword ngxDirectiveThirdParty healthcheck_expected
+syn keyword ngxDirectiveThirdParty healthcheck_buffer
+syn keyword ngxDirectiveThirdParty healthcheck_status
+
+" HTTP Accounting Module <https://github.com/Lax/ngx_http_accounting_module>
+" Add traffic stat function to nginx. Useful for http accounting based on nginx configuration logic
+syn keyword ngxDirectiveThirdParty http_accounting
+syn keyword ngxDirectiveThirdParty http_accounting_log
+syn keyword ngxDirectiveThirdParty http_accounting_id
+syn keyword ngxDirectiveThirdParty http_accounting_interval
+syn keyword ngxDirectiveThirdParty http_accounting_perturb
+
+" Nginx Digest Authentication module <https://github.com/atomx/nginx-http-auth-digest>
+" Digest Authentication for Nginx
+syn keyword ngxDirectiveThirdParty auth_digest
+syn keyword ngxDirectiveThirdParty auth_digest_user_file
+syn keyword ngxDirectiveThirdParty auth_digest_timeout
+syn keyword ngxDirectiveThirdParty auth_digest_expires
+syn keyword ngxDirectiveThirdParty auth_digest_replays
+syn keyword ngxDirectiveThirdParty auth_digest_shm_size
+
+" Auth PAM Module <https://github.com/sto/ngx_http_auth_pam_module>
+" HTTP Basic Authentication using PAM.
+syn keyword ngxDirectiveThirdParty auth_pam
+syn keyword ngxDirectiveThirdParty auth_pam_service_name
+
+" HTTP Auth Request Module <http://nginx.org/en/docs/http/ngx_http_auth_request_module.html>
+" Implements client authorization based on the result of a subrequest
+" syn keyword ngxDirectiveThirdParty auth_request
+" syn keyword ngxDirectiveThirdParty auth_request_set
+
+" HTTP Concatenation module for Nginx <https://github.com/alibaba/nginx-http-concat>
+" A Nginx module for concatenating files in a given context: CSS and JS files usually
+syn keyword ngxDirectiveThirdParty concat
+syn keyword ngxDirectiveThirdParty concat_types
+syn keyword ngxDirectiveThirdParty concat_unique
+syn keyword ngxDirectiveThirdParty concat_max_files
+syn keyword ngxDirectiveThirdParty concat_delimiter
+syn keyword ngxDirectiveThirdParty concat_ignore_file_error
+
+" HTTP Dynamic Upstream Module <https://github.com/yzprofile/ngx_http_dyups_module>
+" Update upstreams' config by restful interface
+syn keyword ngxDirectiveThirdParty dyups_interface
+syn keyword ngxDirectiveThirdParty dyups_read_msg_timeout
+syn keyword ngxDirectiveThirdParty dyups_shm_zone_size
+syn keyword ngxDirectiveThirdParty dyups_upstream_conf
+syn keyword ngxDirectiveThirdParty dyups_trylock
+
+" HTTP Footer If Filter Module <https://github.com/flygoast/ngx_http_footer_if_filter>
+" The ngx_http_footer_if_filter_module is used to add given content to the end of the response according to the condition specified.
+syn keyword ngxDirectiveThirdParty footer_if
+
+" HTTP Footer Filter Module <https://github.com/alibaba/nginx-http-footer-filter>
+" This module implements a body filter that adds a given string to the page footer.
+syn keyword ngxDirectiveThirdParty footer
+syn keyword ngxDirectiveThirdParty footer_types
+
+" HTTP Internal Redirect Module <https://github.com/flygoast/ngx_http_internal_redirect>
+" Make an internal redirect to the uri specified according to the condition specified.
+syn keyword ngxDirectiveThirdParty internal_redirect_if
+syn keyword ngxDirectiveThirdParty internal_redirect_if_no_postponed
+
+" HTTP JavaScript Module <https://github.com/peter-leonov/ngx_http_js_module>
+" Embedding SpiderMonkey. Nearly full port on Perl module.
+syn keyword ngxDirectiveThirdParty js
+syn keyword ngxDirectiveThirdParty js_filter
+syn keyword ngxDirectiveThirdParty js_filter_types
+syn keyword ngxDirectiveThirdParty js_load
+syn keyword ngxDirectiveThirdParty js_maxmem
+syn keyword ngxDirectiveThirdParty js_require
+syn keyword ngxDirectiveThirdParty js_set
+syn keyword ngxDirectiveThirdParty js_utf8
+
+" HTTP Push Module (DEPRECATED) <http://pushmodule.slact.net/>
+" Turn Nginx into an adept long-polling HTTP Push (Comet) server.
+syn keyword ngxDirectiveDeprecated push_buffer_size
+syn keyword ngxDirectiveDeprecated push_listener
+syn keyword ngxDirectiveDeprecated push_message_timeout
+syn keyword ngxDirectiveDeprecated push_queue_messages
+syn keyword ngxDirectiveDeprecated push_sender
+
+" HTTP Redis Module <https://www.nginx.com/resources/wiki/modules/redis/>
+" Redis <http://code.google.com/p/redis/> support.
+syn keyword ngxDirectiveThirdParty redis_bind
+syn keyword ngxDirectiveThirdParty redis_buffer_size
+syn keyword ngxDirectiveThirdParty redis_connect_timeout
+syn keyword ngxDirectiveThirdParty redis_next_upstream
+syn keyword ngxDirectiveThirdParty redis_pass
+syn keyword ngxDirectiveThirdParty redis_read_timeout
+syn keyword ngxDirectiveThirdParty redis_send_timeout
+
+" Iconv Module <https://github.com/calio/iconv-nginx-module>
+" A character conversion nginx module using libiconv
+syn keyword ngxDirectiveThirdParty set_iconv
+syn keyword ngxDirectiveThirdParty iconv_buffer_size
+syn keyword ngxDirectiveThirdParty iconv_filter
+
+" IP Blocker Module <https://github.com/tmthrgd/nginx-ip-blocker>
+" An efficient shared memory IP blocking system for nginx.
+syn keyword ngxDirectiveThirdParty ip_blocker
+
+" IP2Location Module <https://github.com/chrislim2888/ip2location-nginx>
+" Allows user to lookup for geolocation information using IP2Location database
+syn keyword ngxDirectiveThirdParty ip2location_database
+
+" JS Module <https://github.com/peter-leonov/ngx_http_js_module>
+" Reflect the nginx functionality in JS
+syn keyword ngxDirectiveThirdParty js
+syn keyword ngxDirectiveThirdParty js_access
+syn keyword ngxDirectiveThirdParty js_load
+syn keyword ngxDirectiveThirdParty js_set
+
+" Limit Upload Rate Module <https://github.com/cfsego/limit_upload_rate>
+" Limit client-upload rate when they are sending request bodies to you
+syn keyword ngxDirectiveThirdParty limit_upload_rate
+syn keyword ngxDirectiveThirdParty limit_upload_rate_after
+
+" Limit Upstream Module <https://github.com/cfsego/nginx-limit-upstream>
+" Limit the number of connections to upstream for NGINX
+syn keyword ngxDirectiveThirdParty limit_upstream_zone
+syn keyword ngxDirectiveThirdParty limit_upstream_conn
+syn keyword ngxDirectiveThirdParty limit_upstream_log_level
+
+" Log If Module <https://github.com/cfsego/ngx_log_if>
+" Conditional accesslog for nginx
+syn keyword ngxDirectiveThirdParty access_log_bypass_if
+
+" Log Request Speed (DEPRECATED) <http://wiki.nginx.org/NginxHttpLogRequestSpeed>
+" Log the time it took to process each request.
+syn keyword ngxDirectiveDeprecated log_request_speed_filter
+syn keyword ngxDirectiveDeprecated log_request_speed_filter_timeout
+
+" Log ZeroMQ Module <https://github.com/alticelabs/nginx-log-zmq>
+" ZeroMQ logger module for nginx
+syn keyword ngxDirectiveThirdParty log_zmq_server
+syn keyword ngxDirectiveThirdParty log_zmq_endpoint
+syn keyword ngxDirectiveThirdParty log_zmq_format
+syn keyword ngxDirectiveThirdParty log_zmq_off
+
+" Lower/UpperCase Module <https://github.com/replay/ngx_http_lower_upper_case>
+" This module simply uppercases or lowercases a string and saves it into a new variable.
+syn keyword ngxDirectiveThirdParty lower
+syn keyword ngxDirectiveThirdParty upper
+
+" Lua Upstream Module <https://github.com/openresty/lua-upstream-nginx-module>
+" Nginx C module to expose Lua API to ngx_lua for Nginx upstreams
+
+" Lua Module <https://github.com/openresty/lua-nginx-module>
+" Embed the Power of Lua into NGINX HTTP servers
+syn keyword ngxDirectiveThirdParty lua_use_default_type
+syn keyword ngxDirectiveThirdParty lua_malloc_trim
+syn keyword ngxDirectiveThirdParty lua_code_cache
+syn keyword ngxDirectiveThirdParty lua_regex_cache_max_entries
+syn keyword ngxDirectiveThirdParty lua_regex_match_limit
+syn keyword ngxDirectiveThirdParty lua_package_path
+syn keyword ngxDirectiveThirdParty lua_package_cpath
+syn keyword ngxDirectiveThirdParty init_by_lua
+syn keyword ngxDirectiveThirdParty init_by_lua_file
+syn keyword ngxDirectiveThirdParty init_worker_by_lua
+syn keyword ngxDirectiveThirdParty init_worker_by_lua_file
+syn keyword ngxDirectiveThirdParty set_by_lua
+syn keyword ngxDirectiveThirdParty set_by_lua_file
+syn keyword ngxDirectiveThirdParty content_by_lua
+syn keyword ngxDirectiveThirdParty content_by_lua_file
+syn keyword ngxDirectiveThirdParty rewrite_by_lua
+syn keyword ngxDirectiveThirdParty rewrite_by_lua_file
+syn keyword ngxDirectiveThirdParty access_by_lua
+syn keyword ngxDirectiveThirdParty access_by_lua_file
+syn keyword ngxDirectiveThirdParty header_filter_by_lua
+syn keyword ngxDirectiveThirdParty header_filter_by_lua_file
+syn keyword ngxDirectiveThirdParty body_filter_by_lua
+syn keyword ngxDirectiveThirdParty body_filter_by_lua_file
+syn keyword ngxDirectiveThirdParty log_by_lua
+syn keyword ngxDirectiveThirdParty log_by_lua_file
+syn keyword ngxDirectiveThirdParty balancer_by_lua_file
+syn keyword ngxDirectiveThirdParty lua_need_request_body
+syn keyword ngxDirectiveThirdParty ssl_certificate_by_lua_file
+syn keyword ngxDirectiveThirdParty ssl_session_fetch_by_lua_file
+syn keyword ngxDirectiveThirdParty ssl_session_store_by_lua_file
+syn keyword ngxDirectiveThirdParty lua_shared_dict
+syn keyword ngxDirectiveThirdParty lua_socket_connect_timeout
+syn keyword ngxDirectiveThirdParty lua_socket_send_timeout
+syn keyword ngxDirectiveThirdParty lua_socket_send_lowat
+syn keyword ngxDirectiveThirdParty lua_socket_read_timeout
+syn keyword ngxDirectiveThirdParty lua_socket_buffer_size
+syn keyword ngxDirectiveThirdParty lua_socket_pool_size
+syn keyword ngxDirectiveThirdParty lua_socket_keepalive_timeout
+syn keyword ngxDirectiveThirdParty lua_socket_log_errors
+syn keyword ngxDirectiveThirdParty lua_ssl_ciphers
+syn keyword ngxDirectiveThirdParty lua_ssl_crl
+syn keyword ngxDirectiveThirdParty lua_ssl_protocols
+syn keyword ngxDirectiveThirdParty lua_ssl_trusted_certificate
+syn keyword ngxDirectiveThirdParty lua_ssl_verify_depth
+syn keyword ngxDirectiveThirdParty lua_http10_buffering
+syn keyword ngxDirectiveThirdParty rewrite_by_lua_no_postpone
+syn keyword ngxDirectiveThirdParty access_by_lua_no_postpone
+syn keyword ngxDirectiveThirdParty lua_transform_underscores_in_response_headers
+syn keyword ngxDirectiveThirdParty lua_check_client_abort
+syn keyword ngxDirectiveThirdParty lua_max_pending_timers
+syn keyword ngxDirectiveThirdParty lua_max_running_timers
+
+" MD5 Filter Module <https://github.com/kainswor/nginx_md5_filter>
+" A content filter for nginx, which returns the md5 hash of the content otherwise returned.
+syn keyword ngxDirectiveThirdParty md5_filter
+
+" Memc Module <https://github.com/openresty/memc-nginx-module>
+" An extended version of the standard memcached module that supports set, add, delete, and many more memcached commands.
+syn keyword ngxDirectiveThirdParty memc_buffer_size
+syn keyword ngxDirectiveThirdParty memc_cmds_allowed
+syn keyword ngxDirectiveThirdParty memc_connect_timeout
+syn keyword ngxDirectiveThirdParty memc_flags_to_last_modified
+syn keyword ngxDirectiveThirdParty memc_next_upstream
+syn keyword ngxDirectiveThirdParty memc_pass
+syn keyword ngxDirectiveThirdParty memc_read_timeout
+syn keyword ngxDirectiveThirdParty memc_send_timeout
+syn keyword ngxDirectiveThirdParty memc_upstream_fail_timeout
+syn keyword ngxDirectiveThirdParty memc_upstream_max_fails
+
+" Mod Security Module <https://github.com/SpiderLabs/ModSecurity>
+" ModSecurity is an open source, cross platform web application firewall (WAF) engine
+syn keyword ngxDirectiveThirdParty ModSecurityConfig
+syn keyword ngxDirectiveThirdParty ModSecurityEnabled
+syn keyword ngxDirectiveThirdParty pool_context
+syn keyword ngxDirectiveThirdParty pool_context_hash_size
+
+" Mogilefs Module <http://www.grid.net.ru/nginx/mogilefs.en.html>
+" MogileFS client for nginx web server.
+syn keyword ngxDirectiveThirdParty mogilefs_pass
+syn keyword ngxDirectiveThirdParty mogilefs_methods
+syn keyword ngxDirectiveThirdParty mogilefs_domain
+syn keyword ngxDirectiveThirdParty mogilefs_class
+syn keyword ngxDirectiveThirdParty mogilefs_tracker
+syn keyword ngxDirectiveThirdParty mogilefs_noverify
+syn keyword ngxDirectiveThirdParty mogilefs_connect_timeout
+syn keyword ngxDirectiveThirdParty mogilefs_send_timeout
+syn keyword ngxDirectiveThirdParty mogilefs_read_timeout
+
+" Mongo Module <https://github.com/simpl/ngx_mongo>
+" Upstream module that allows nginx to communicate directly with MongoDB database.
+syn keyword ngxDirectiveThirdParty mongo_auth
+syn keyword ngxDirectiveThirdParty mongo_pass
+syn keyword ngxDirectiveThirdParty mongo_query
+syn keyword ngxDirectiveThirdParty mongo_json
+syn keyword ngxDirectiveThirdParty mongo_bind
+syn keyword ngxDirectiveThirdParty mongo_connect_timeout
+syn keyword ngxDirectiveThirdParty mongo_send_timeout
+syn keyword ngxDirectiveThirdParty mongo_read_timeout
+syn keyword ngxDirectiveThirdParty mongo_buffering
+syn keyword ngxDirectiveThirdParty mongo_buffer_size
+syn keyword ngxDirectiveThirdParty mongo_buffers
+syn keyword ngxDirectiveThirdParty mongo_busy_buffers_size
+syn keyword ngxDirectiveThirdParty mongo_next_upstream
+
+" MP4 Streaming Lite Module <https://www.nginx.com/resources/wiki/modules/mp4_streaming/>
+" Will seek to a certain time within H.264/MP4 files when provided with a 'start' parameter in the URL.
+" syn keyword ngxDirectiveThirdParty mp4
+
+" NAXSI Module <https://github.com/nbs-system/naxsi>
+" NAXSI is an open-source, high performance, low rules maintenance WAF for NGINX
+syn keyword ngxDirectiveThirdParty DeniedUrl denied_url
+syn keyword ngxDirectiveThirdParty LearningMode learning_mode
+syn keyword ngxDirectiveThirdParty SecRulesEnabled rules_enabled
+syn keyword ngxDirectiveThirdParty SecRulesDisabled rules_disabled
+syn keyword ngxDirectiveThirdParty CheckRule check_rule
+syn keyword ngxDirectiveThirdParty BasicRule basic_rule
+syn keyword ngxDirectiveThirdParty MainRule main_rule
+syn keyword ngxDirectiveThirdParty LibInjectionSql libinjection_sql
+syn keyword ngxDirectiveThirdParty LibInjectionXss libinjection_xss
+
+" Nchan Module <https://nchan.slact.net/>
+" Fast, horizontally scalable, multiprocess pub/sub queuing server and proxy for HTTP, long-polling, Websockets and EventSource (SSE)
+syn keyword ngxDirectiveThirdParty nchan_channel_id
+syn keyword ngxDirectiveThirdParty nchan_channel_id_split_delimiter
+syn keyword ngxDirectiveThirdParty nchan_eventsource_event
+syn keyword ngxDirectiveThirdParty nchan_longpoll_multipart_response
+syn keyword ngxDirectiveThirdParty nchan_publisher
+syn keyword ngxDirectiveThirdParty nchan_publisher_channel_id
+syn keyword ngxDirectiveThirdParty nchan_publisher_upstream_request
+syn keyword ngxDirectiveThirdParty nchan_pubsub
+syn keyword ngxDirectiveThirdParty nchan_subscribe_request
+syn keyword ngxDirectiveThirdParty nchan_subscriber
+syn keyword ngxDirectiveThirdParty nchan_subscriber_channel_id
+syn keyword ngxDirectiveThirdParty nchan_subscriber_compound_etag_message_id
+syn keyword ngxDirectiveThirdParty nchan_subscriber_first_message
+syn keyword ngxDirectiveThirdParty nchan_subscriber_http_raw_stream_separator
+syn keyword ngxDirectiveThirdParty nchan_subscriber_last_message_id
+syn keyword ngxDirectiveThirdParty nchan_subscriber_message_id_custom_etag_header
+syn keyword ngxDirectiveThirdParty nchan_subscriber_timeout
+syn keyword ngxDirectiveThirdParty nchan_unsubscribe_request
+syn keyword ngxDirectiveThirdParty nchan_websocket_ping_interval
+syn keyword ngxDirectiveThirdParty nchan_authorize_request
+syn keyword ngxDirectiveThirdParty nchan_max_reserved_memory
+syn keyword ngxDirectiveThirdParty nchan_message_buffer_length
+syn keyword ngxDirectiveThirdParty nchan_message_timeout
+syn keyword ngxDirectiveThirdParty nchan_redis_idle_channel_cache_timeout
+syn keyword ngxDirectiveThirdParty nchan_redis_namespace
+syn keyword ngxDirectiveThirdParty nchan_redis_pass
+syn keyword ngxDirectiveThirdParty nchan_redis_ping_interval
+syn keyword ngxDirectiveThirdParty nchan_redis_server
+syn keyword ngxDirectiveThirdParty nchan_redis_storage_mode
+syn keyword ngxDirectiveThirdParty nchan_redis_url
+syn keyword ngxDirectiveThirdParty nchan_store_messages
+syn keyword ngxDirectiveThirdParty nchan_use_redis
+syn keyword ngxDirectiveThirdParty nchan_access_control_allow_origin
+syn keyword ngxDirectiveThirdParty nchan_channel_group
+syn keyword ngxDirectiveThirdParty nchan_channel_group_accounting
+syn keyword ngxDirectiveThirdParty nchan_group_location
+syn keyword ngxDirectiveThirdParty nchan_group_max_channels
+syn keyword ngxDirectiveThirdParty nchan_group_max_messages
+syn keyword ngxDirectiveThirdParty nchan_group_max_messages_disk
+syn keyword ngxDirectiveThirdParty nchan_group_max_messages_memory
+syn keyword ngxDirectiveThirdParty nchan_group_max_subscribers
+syn keyword ngxDirectiveThirdParty nchan_subscribe_existing_channels_only
+syn keyword ngxDirectiveThirdParty nchan_channel_event_string
+syn keyword ngxDirectiveThirdParty nchan_channel_events_channel_id
+syn keyword ngxDirectiveThirdParty nchan_stub_status
+syn keyword ngxDirectiveThirdParty nchan_max_channel_id_length
+syn keyword ngxDirectiveThirdParty nchan_max_channel_subscribers
+syn keyword ngxDirectiveThirdParty nchan_channel_timeout
+syn keyword ngxDirectiveThirdParty nchan_storage_engine
+
+" Nginx Notice Module <https://github.com/kr/nginx-notice>
+" Serve static file to POST requests.
+syn keyword ngxDirectiveThirdParty notice
+syn keyword ngxDirectiveThirdParty notice_type
+
+" OCSP Proxy Module <https://github.com/kyprizel/nginx_ocsp_proxy-module>
+" Nginx OCSP processing module designed for response caching
+syn keyword ngxDirectiveThirdParty ocsp_proxy
+syn keyword ngxDirectiveThirdParty ocsp_cache_timeout
+
+" Eval Module <https://github.com/openresty/nginx-eval-module>
+" Module for nginx web server evaluates response of proxy or memcached module into variables.
+syn keyword ngxDirectiveThirdParty eval
+syn keyword ngxDirectiveThirdParty eval_escalate
+syn keyword ngxDirectiveThirdParty eval_buffer_size
+syn keyword ngxDirectiveThirdParty eval_override_content_type
+syn keyword ngxDirectiveThirdParty eval_subrequest_in_memory
+
+" OpenSSL Version Module <https://github.com/apcera/nginx-openssl-version>
+" Nginx OpenSSL version check at startup
+syn keyword ngxDirectiveThirdParty openssl_version_minimum
+syn keyword ngxDirectiveThirdParty openssl_builddate_minimum
+
+" Owner Match Module <https://www.nginx.com/resources/wiki/modules/owner_match/>
+" Control access for specific owners and groups of files
+syn keyword ngxDirectiveThirdParty omallow
+syn keyword ngxDirectiveThirdParty omdeny
+
+" Accept Language Module <https://www.nginx.com/resources/wiki/modules/accept_language/>
+" Parses the Accept-Language header and gives the most suitable locale from a list of supported locales.
+syn keyword ngxDirectiveThirdParty pagespeed
+
+" PHP Memcache Standard Balancer Module <https://github.com/replay/ngx_http_php_memcache_standard_balancer>
+" Loadbalancer that is compatible to the standard loadbalancer in the php-memcache module
+syn keyword ngxDirectiveThirdParty hash_key
+
+" PHP Session Module <https://github.com/replay/ngx_http_php_session>
+" Nginx module to parse php sessions
+syn keyword ngxDirectiveThirdParty php_session_parse
+syn keyword ngxDirectiveThirdParty php_session_strip_formatting
+
+" Phusion Passenger Module <https://www.phusionpassenger.com/library/config/nginx/>
+" Passenger is an open source web application server.
+syn keyword ngxDirectiveThirdParty passenger_root
+syn keyword ngxDirectiveThirdParty passenger_enabled
+syn keyword ngxDirectiveThirdParty passenger_base_uri
+syn keyword ngxDirectiveThirdParty passenger_document_root
+syn keyword ngxDirectiveThirdParty passenger_ruby
+syn keyword ngxDirectiveThirdParty passenger_python
+syn keyword ngxDirectiveThirdParty passenger_nodejs
+syn keyword ngxDirectiveThirdParty passenger_meteor_app_settings
+syn keyword ngxDirectiveThirdParty passenger_app_env
+syn keyword ngxDirectiveThirdParty passenger_app_root
+syn keyword ngxDirectiveThirdParty passenger_app_group_name
+syn keyword ngxDirectiveThirdParty passenger_app_type
+syn keyword ngxDirectiveThirdParty passenger_startup_file
+syn keyword ngxDirectiveThirdParty passenger_restart_dir
+syn keyword ngxDirectiveThirdParty passenger_spawn_method
+syn keyword ngxDirectiveThirdParty passenger_env_var
+syn keyword ngxDirectiveThirdParty passenger_load_shell_envvars
+syn keyword ngxDirectiveThirdParty passenger_rolling_restarts
+syn keyword ngxDirectiveThirdParty passenger_resist_deployment_errors
+syn keyword ngxDirectiveThirdParty passenger_user_switching
+syn keyword ngxDirectiveThirdParty passenger_user
+syn keyword ngxDirectiveThirdParty passenger_group
+syn keyword ngxDirectiveThirdParty passenger_default_user
+syn keyword ngxDirectiveThirdParty passenger_default_group
+syn keyword ngxDirectiveThirdParty passenger_show_version_in_header
+syn keyword ngxDirectiveThirdParty passenger_friendly_error_pages
+syn keyword ngxDirectiveThirdParty passenger_disable_security_update_check
+syn keyword ngxDirectiveThirdParty passenger_security_update_check_proxy
+syn keyword ngxDirectiveThirdParty passenger_max_pool_size
+syn keyword ngxDirectiveThirdParty passenger_min_instances
+syn keyword ngxDirectiveThirdParty passenger_max_instances
+syn keyword ngxDirectiveThirdParty passenger_max_instances_per_app
+syn keyword ngxDirectiveThirdParty passenger_pool_idle_time
+syn keyword ngxDirectiveThirdParty passenger_max_preloader_idle_time
+syn keyword ngxDirectiveThirdParty passenger_force_max_concurrent_requests_per_process
+syn keyword ngxDirectiveThirdParty passenger_start_timeout
+syn keyword ngxDirectiveThirdParty passenger_concurrency_model
+syn keyword ngxDirectiveThirdParty passenger_thread_count
+syn keyword ngxDirectiveThirdParty passenger_max_requests
+syn keyword ngxDirectiveThirdParty passenger_max_request_time
+syn keyword ngxDirectiveThirdParty passenger_memory_limit
+syn keyword ngxDirectiveThirdParty passenger_stat_throttle_rate
+syn keyword ngxDirectiveThirdParty passenger_core_file_descriptor_ulimit
+syn keyword ngxDirectiveThirdParty passenger_app_file_descriptor_ulimit
+syn keyword ngxDirectiveThirdParty passenger_pre_start
+syn keyword ngxDirectiveThirdParty passenger_set_header
+syn keyword ngxDirectiveThirdParty passenger_max_request_queue_size
+syn keyword ngxDirectiveThirdParty passenger_request_queue_overflow_status_code
+syn keyword ngxDirectiveThirdParty passenger_sticky_sessions
+syn keyword ngxDirectiveThirdParty passenger_sticky_sessions_cookie_name
+syn keyword ngxDirectiveThirdParty passenger_abort_websockets_on_process_shutdown
+syn keyword ngxDirectiveThirdParty passenger_ignore_client_abort
+syn keyword ngxDirectiveThirdParty passenger_intercept_errors
+syn keyword ngxDirectiveThirdParty passenger_pass_header
+syn keyword ngxDirectiveThirdParty passenger_ignore_headers
+syn keyword ngxDirectiveThirdParty passenger_headers_hash_bucket_size
+syn keyword ngxDirectiveThirdParty passenger_headers_hash_max_size
+syn keyword ngxDirectiveThirdParty passenger_buffer_response
+syn keyword ngxDirectiveThirdParty passenger_response_buffer_high_watermark
+syn keyword ngxDirectiveThirdParty passenger_buffer_size, passenger_buffers, passenger_busy_buffers_size
+syn keyword ngxDirectiveThirdParty passenger_socket_backlog
+syn keyword ngxDirectiveThirdParty passenger_log_level
+syn keyword ngxDirectiveThirdParty passenger_log_file
+syn keyword ngxDirectiveThirdParty passenger_file_descriptor_log_file
+syn keyword ngxDirectiveThirdParty passenger_debugger
+syn keyword ngxDirectiveThirdParty passenger_instance_registry_dir
+syn keyword ngxDirectiveThirdParty passenger_data_buffer_dir
+syn keyword ngxDirectiveThirdParty passenger_fly_with
+syn keyword ngxDirectiveThirdParty union_station_support
+syn keyword ngxDirectiveThirdParty union_station_key
+syn keyword ngxDirectiveThirdParty union_station_proxy_address
+syn keyword ngxDirectiveThirdParty union_station_filter
+syn keyword ngxDirectiveThirdParty union_station_gateway_address
+syn keyword ngxDirectiveThirdParty union_station_gateway_port
+syn keyword ngxDirectiveThirdParty union_station_gateway_cert
+syn keyword ngxDirectiveDeprecated rails_spawn_method
+syn keyword ngxDirectiveDeprecated passenger_debug_log_file
+
+" Postgres Module <http://labs.frickle.com/nginx_ngx_postgres/>
+" Upstream module that allows nginx to communicate directly with PostgreSQL database.
+syn keyword ngxDirectiveThirdParty postgres_server
+syn keyword ngxDirectiveThirdParty postgres_keepalive
+syn keyword ngxDirectiveThirdParty postgres_pass
+syn keyword ngxDirectiveThirdParty postgres_query
+syn keyword ngxDirectiveThirdParty postgres_rewrite
+syn keyword ngxDirectiveThirdParty postgres_output
+syn keyword ngxDirectiveThirdParty postgres_set
+syn keyword ngxDirectiveThirdParty postgres_escape
+syn keyword ngxDirectiveThirdParty postgres_connect_timeout
+syn keyword ngxDirectiveThirdParty postgres_result_timeout
+
+" Pubcookie Module <https://www.vanko.me/book/page/pubcookie-module-nginx>
+" Authorizes users using encrypted cookies
+syn keyword ngxDirectiveThirdParty pubcookie_inactive_expire
+syn keyword ngxDirectiveThirdParty pubcookie_hard_expire
+syn keyword ngxDirectiveThirdParty pubcookie_app_id
+syn keyword ngxDirectiveThirdParty pubcookie_dir_depth
+syn keyword ngxDirectiveThirdParty pubcookie_catenate_app_ids
+syn keyword ngxDirectiveThirdParty pubcookie_app_srv_id
+syn keyword ngxDirectiveThirdParty pubcookie_login
+syn keyword ngxDirectiveThirdParty pubcookie_login_method
+syn keyword ngxDirectiveThirdParty pubcookie_post
+syn keyword ngxDirectiveThirdParty pubcookie_domain
+syn keyword ngxDirectiveThirdParty pubcookie_granting_cert_file
+syn keyword ngxDirectiveThirdParty pubcookie_session_key_file
+syn keyword ngxDirectiveThirdParty pubcookie_session_cert_file
+syn keyword ngxDirectiveThirdParty pubcookie_crypt_key_file
+syn keyword ngxDirectiveThirdParty pubcookie_end_session
+syn keyword ngxDirectiveThirdParty pubcookie_encryption
+syn keyword ngxDirectiveThirdParty pubcookie_session_reauth
+syn keyword ngxDirectiveThirdParty pubcookie_auth_type_names
+syn keyword ngxDirectiveThirdParty pubcookie_no_prompt
+syn keyword ngxDirectiveThirdParty pubcookie_on_demand
+syn keyword ngxDirectiveThirdParty pubcookie_addl_request
+syn keyword ngxDirectiveThirdParty pubcookie_no_obscure_cookies
+syn keyword ngxDirectiveThirdParty pubcookie_no_clean_creds
+syn keyword ngxDirectiveThirdParty pubcookie_egd_device
+syn keyword ngxDirectiveThirdParty pubcookie_no_blank
+syn keyword ngxDirectiveThirdParty pubcookie_super_debug
+syn keyword ngxDirectiveThirdParty pubcookie_set_remote_user
+
+" Push Stream Module <https://github.com/wandenberg/nginx-push-stream-module>
+" A pure stream http push technology for your Nginx setup
+syn keyword ngxDirectiveThirdParty push_stream_channels_statistics
+syn keyword ngxDirectiveThirdParty push_stream_publisher
+syn keyword ngxDirectiveThirdParty push_stream_subscriber
+syn keyword ngxDirectiveThirdParty push_stream_shared_memory_size
+syn keyword ngxDirectiveThirdParty push_stream_channel_deleted_message_text
+syn keyword ngxDirectiveThirdParty push_stream_channel_inactivity_time
+syn keyword ngxDirectiveThirdParty push_stream_ping_message_text
+syn keyword ngxDirectiveThirdParty push_stream_timeout_with_body
+syn keyword ngxDirectiveThirdParty push_stream_message_ttl
+syn keyword ngxDirectiveThirdParty push_stream_max_subscribers_per_channel
+syn keyword ngxDirectiveThirdParty push_stream_max_messages_stored_per_channel
+syn keyword ngxDirectiveThirdParty push_stream_max_channel_id_length
+syn keyword ngxDirectiveThirdParty push_stream_max_number_of_channels
+syn keyword ngxDirectiveThirdParty push_stream_max_number_of_wildcard_channels
+syn keyword ngxDirectiveThirdParty push_stream_wildcard_channel_prefix
+syn keyword ngxDirectiveThirdParty push_stream_events_channel_id
+syn keyword ngxDirectiveThirdParty push_stream_channels_path
+syn keyword ngxDirectiveThirdParty push_stream_store_messages
+syn keyword ngxDirectiveThirdParty push_stream_channel_info_on_publish
+syn keyword ngxDirectiveThirdParty push_stream_authorized_channels_only
+syn keyword ngxDirectiveThirdParty push_stream_header_template_file
+syn keyword ngxDirectiveThirdParty push_stream_header_template
+syn keyword ngxDirectiveThirdParty push_stream_message_template
+syn keyword ngxDirectiveThirdParty push_stream_footer_template
+syn keyword ngxDirectiveThirdParty push_stream_wildcard_channel_max_qtd
+syn keyword ngxDirectiveThirdParty push_stream_ping_message_interval
+syn keyword ngxDirectiveThirdParty push_stream_subscriber_connection_ttl
+syn keyword ngxDirectiveThirdParty push_stream_longpolling_connection_ttl
+syn keyword ngxDirectiveThirdParty push_stream_websocket_allow_publish
+syn keyword ngxDirectiveThirdParty push_stream_last_received_message_time
+syn keyword ngxDirectiveThirdParty push_stream_last_received_message_tag
+syn keyword ngxDirectiveThirdParty push_stream_last_event_id
+syn keyword ngxDirectiveThirdParty push_stream_user_agent
+syn keyword ngxDirectiveThirdParty push_stream_padding_by_user_agent
+syn keyword ngxDirectiveThirdParty push_stream_allowed_origins
+syn keyword ngxDirectiveThirdParty push_stream_allow_connections_to_events_channel
+
+" rDNS Module <https://github.com/flant/nginx-http-rdns>
+" Make a reverse DNS (rDNS) lookup for incoming connection and provides simple access control of incoming hostname by allow/deny rules
+syn keyword ngxDirectiveThirdParty rdns
+syn keyword ngxDirectiveThirdParty rdns_allow
+syn keyword ngxDirectiveThirdParty rdns_deny
+
+" RDS CSV Module <https://github.com/openresty/rds-csv-nginx-module>
+" Nginx output filter module to convert Resty-DBD-Streams (RDS) to Comma-Separated Values (CSV)
+syn keyword ngxDirectiveThirdParty rds_csv
+syn keyword ngxDirectiveThirdParty rds_csv_row_terminator
+syn keyword ngxDirectiveThirdParty rds_csv_field_separator
+syn keyword ngxDirectiveThirdParty rds_csv_field_name_header
+syn keyword ngxDirectiveThirdParty rds_csv_content_type
+syn keyword ngxDirectiveThirdParty rds_csv_buffer_size
+
+" RDS JSON Module <https://github.com/openresty/rds-json-nginx-module>
+" An output filter that formats Resty DBD Streams generated by ngx_drizzle and others to JSON
+syn keyword ngxDirectiveThirdParty rds_json
+syn keyword ngxDirectiveThirdParty rds_json_buffer_size
+syn keyword ngxDirectiveThirdParty rds_json_format
+syn keyword ngxDirectiveThirdParty rds_json_root
+syn keyword ngxDirectiveThirdParty rds_json_success_property
+syn keyword ngxDirectiveThirdParty rds_json_user_property
+syn keyword ngxDirectiveThirdParty rds_json_errcode_key
+syn keyword ngxDirectiveThirdParty rds_json_errstr_key
+syn keyword ngxDirectiveThirdParty rds_json_ret
+syn keyword ngxDirectiveThirdParty rds_json_content_type
+
+" Redis Module <https://www.nginx.com/resources/wiki/modules/redis/>
+" Use this module to perform simple caching
+syn keyword ngxDirectiveThirdParty redis_pass
+syn keyword ngxDirectiveThirdParty redis_bind
+syn keyword ngxDirectiveThirdParty redis_connect_timeout
+syn keyword ngxDirectiveThirdParty redis_read_timeout
+syn keyword ngxDirectiveThirdParty redis_send_timeout
+syn keyword ngxDirectiveThirdParty redis_buffer_size
+syn keyword ngxDirectiveThirdParty redis_next_upstream
+syn keyword ngxDirectiveThirdParty redis_gzip_flag
+
+" Redis 2 Module <https://github.com/openresty/redis2-nginx-module>
+" Nginx upstream module for the Redis 2.0 protocol
+syn keyword ngxDirectiveThirdParty redis2_query
+syn keyword ngxDirectiveThirdParty redis2_raw_query
+syn keyword ngxDirectiveThirdParty redis2_raw_queries
+syn keyword ngxDirectiveThirdParty redis2_literal_raw_query
+syn keyword ngxDirectiveThirdParty redis2_pass
+syn keyword ngxDirectiveThirdParty redis2_connect_timeout
+syn keyword ngxDirectiveThirdParty redis2_send_timeout
+syn keyword ngxDirectiveThirdParty redis2_read_timeout
+syn keyword ngxDirectiveThirdParty redis2_buffer_size
+syn keyword ngxDirectiveThirdParty redis2_next_upstream
+
+" Replace Filter Module <https://github.com/openresty/replace-filter-nginx-module>
+" Streaming regular expression replacement in response bodies
+syn keyword ngxDirectiveThirdParty replace_filter
+syn keyword ngxDirectiveThirdParty replace_filter_types
+syn keyword ngxDirectiveThirdParty replace_filter_max_buffered_size
+syn keyword ngxDirectiveThirdParty replace_filter_last_modified
+syn keyword ngxDirectiveThirdParty replace_filter_skip
+
+" Roboo Module <https://github.com/yuri-gushin/Roboo>
+" HTTP Robot Mitigator
+
+" RRD Graph Module <https://www.nginx.com/resources/wiki/modules/rrd_graph/>
+" This module provides an HTTP interface to RRDtool's graphing facilities.
+syn keyword ngxDirectiveThirdParty rrd_graph
+syn keyword ngxDirectiveThirdParty rrd_graph_root
+
+" RTMP Module <https://github.com/arut/nginx-rtmp-module>
+" NGINX-based Media Streaming Server
+syn keyword ngxDirectiveThirdParty rtmp
+" syn keyword ngxDirectiveThirdParty server
+" syn keyword ngxDirectiveThirdParty listen
+syn keyword ngxDirectiveThirdParty application
+" syn keyword ngxDirectiveThirdParty timeout
+syn keyword ngxDirectiveThirdParty ping
+syn keyword ngxDirectiveThirdParty ping_timeout
+syn keyword ngxDirectiveThirdParty max_streams
+syn keyword ngxDirectiveThirdParty ack_window
+syn keyword ngxDirectiveThirdParty chunk_size
+syn keyword ngxDirectiveThirdParty max_queue
+syn keyword ngxDirectiveThirdParty max_message
+syn keyword ngxDirectiveThirdParty out_queue
+syn keyword ngxDirectiveThirdParty out_cork
+" syn keyword ngxDirectiveThirdParty allow
+" syn keyword ngxDirectiveThirdParty deny
+syn keyword ngxDirectiveThirdParty exec_push
+syn keyword ngxDirectiveThirdParty exec_pull
+syn keyword ngxDirectiveThirdParty exec
+syn keyword ngxDirectiveThirdParty exec_options
+syn keyword ngxDirectiveThirdParty exec_static
+syn keyword ngxDirectiveThirdParty exec_kill_signal
+syn keyword ngxDirectiveThirdParty respawn
+syn keyword ngxDirectiveThirdParty respawn_timeout
+syn keyword ngxDirectiveThirdParty exec_publish
+syn keyword ngxDirectiveThirdParty exec_play
+syn keyword ngxDirectiveThirdParty exec_play_done
+syn keyword ngxDirectiveThirdParty exec_publish_done
+syn keyword ngxDirectiveThirdParty exec_record_done
+syn keyword ngxDirectiveThirdParty live
+syn keyword ngxDirectiveThirdParty meta
+syn keyword ngxDirectiveThirdParty interleave
+syn keyword ngxDirectiveThirdParty wait_key
+syn keyword ngxDirectiveThirdParty wait_video
+syn keyword ngxDirectiveThirdParty publish_notify
+syn keyword ngxDirectiveThirdParty drop_idle_publisher
+syn keyword ngxDirectiveThirdParty sync
+syn keyword ngxDirectiveThirdParty play_restart
+syn keyword ngxDirectiveThirdParty idle_streams
+syn keyword ngxDirectiveThirdParty record
+syn keyword ngxDirectiveThirdParty record_path
+syn keyword ngxDirectiveThirdParty record_suffix
+syn keyword ngxDirectiveThirdParty record_unique
+syn keyword ngxDirectiveThirdParty record_append
+syn keyword ngxDirectiveThirdParty record_lock
+syn keyword ngxDirectiveThirdParty record_max_size
+syn keyword ngxDirectiveThirdParty record_max_frames
+syn keyword ngxDirectiveThirdParty record_interval
+syn keyword ngxDirectiveThirdParty recorder
+syn keyword ngxDirectiveThirdParty record_notify
+syn keyword ngxDirectiveThirdParty play
+syn keyword ngxDirectiveThirdParty play_temp_path
+syn keyword ngxDirectiveThirdParty play_local_path
+syn keyword ngxDirectiveThirdParty pull
+syn keyword ngxDirectiveThirdParty push
+syn keyword ngxDirectiveThirdParty push_reconnect
+syn keyword ngxDirectiveThirdParty session_relay
+syn keyword ngxDirectiveThirdParty on_connect
+syn keyword ngxDirectiveThirdParty on_play
+syn keyword ngxDirectiveThirdParty on_publish
+syn keyword ngxDirectiveThirdParty on_done
+syn keyword ngxDirectiveThirdParty on_play_done
+syn keyword ngxDirectiveThirdParty on_publish_done
+syn keyword ngxDirectiveThirdParty on_record_done
+syn keyword ngxDirectiveThirdParty on_update
+syn keyword ngxDirectiveThirdParty notify_update_timeout
+syn keyword ngxDirectiveThirdParty notify_update_strict
+syn keyword ngxDirectiveThirdParty notify_relay_redirect
+syn keyword ngxDirectiveThirdParty notify_method
+syn keyword ngxDirectiveThirdParty hls
+syn keyword ngxDirectiveThirdParty hls_path
+syn keyword ngxDirectiveThirdParty hls_fragment
+syn keyword ngxDirectiveThirdParty hls_playlist_length
+syn keyword ngxDirectiveThirdParty hls_sync
+syn keyword ngxDirectiveThirdParty hls_continuous
+syn keyword ngxDirectiveThirdParty hls_nested
+syn keyword ngxDirectiveThirdParty hls_base_url
+syn keyword ngxDirectiveThirdParty hls_cleanup
+syn keyword ngxDirectiveThirdParty hls_fragment_naming
+syn keyword ngxDirectiveThirdParty hls_fragment_slicing
+syn keyword ngxDirectiveThirdParty hls_variant
+syn keyword ngxDirectiveThirdParty hls_type
+syn keyword ngxDirectiveThirdParty hls_keys
+syn keyword ngxDirectiveThirdParty hls_key_path
+syn keyword ngxDirectiveThirdParty hls_key_url
+syn keyword ngxDirectiveThirdParty hls_fragments_per_key
+syn keyword ngxDirectiveThirdParty dash
+syn keyword ngxDirectiveThirdParty dash_path
+syn keyword ngxDirectiveThirdParty dash_fragment
+syn keyword ngxDirectiveThirdParty dash_playlist_length
+syn keyword ngxDirectiveThirdParty dash_nested
+syn keyword ngxDirectiveThirdParty dash_cleanup
+" syn keyword ngxDirectiveThirdParty access_log
+" syn keyword ngxDirectiveThirdParty log_format
+syn keyword ngxDirectiveThirdParty max_connections
+syn keyword ngxDirectiveThirdParty rtmp_stat
+syn keyword ngxDirectiveThirdParty rtmp_stat_stylesheet
+syn keyword ngxDirectiveThirdParty rtmp_auto_push
+syn keyword ngxDirectiveThirdParty rtmp_auto_push_reconnect
+syn keyword ngxDirectiveThirdParty rtmp_socket_dir
+syn keyword ngxDirectiveThirdParty rtmp_control
+
+" RTMPT Module <https://github.com/kwojtek/nginx-rtmpt-proxy-module>
+" Module for nginx to proxy rtmp using http protocol
+syn keyword ngxDirectiveThirdParty rtmpt_proxy_target
+syn keyword ngxDirectiveThirdParty rtmpt_proxy_rtmp_timeout
+syn keyword ngxDirectiveThirdParty rtmpt_proxy_http_timeout
+syn keyword ngxDirectiveThirdParty rtmpt_proxy
+syn keyword ngxDirectiveThirdParty rtmpt_proxy_stat
+syn keyword ngxDirectiveThirdParty rtmpt_proxy_stylesheet
+
+" Syntactically Awesome Module <https://github.com/mneudert/sass-nginx-module>
+" Providing on-the-fly compiling of Sass files as an NGINX module.
+syn keyword ngxDirectiveThirdParty sass_compile
+syn keyword ngxDirectiveThirdParty sass_error_log
+syn keyword ngxDirectiveThirdParty sass_include_path
+syn keyword ngxDirectiveThirdParty sass_indent
+syn keyword ngxDirectiveThirdParty sass_is_indented_syntax
+syn keyword ngxDirectiveThirdParty sass_linefeed
+syn keyword ngxDirectiveThirdParty sass_precision
+syn keyword ngxDirectiveThirdParty sass_output_style
+syn keyword ngxDirectiveThirdParty sass_source_comments
+syn keyword ngxDirectiveThirdParty sass_source_map_embed
+
+" Secure Download Module <https://www.nginx.com/resources/wiki/modules/secure_download/>
+" Enables you to create links which are only valid until a certain datetime is reached
+syn keyword ngxDirectiveThirdParty secure_download
+syn keyword ngxDirectiveThirdParty secure_download_secret
+syn keyword ngxDirectiveThirdParty secure_download_path_mode
+
+" Selective Cache Purge Module <https://github.com/wandenberg/nginx-selective-cache-purge-module>
+" A module to purge cache by GLOB patterns. The supported patterns are the same as supported by Redis.
+syn keyword ngxDirectiveThirdParty selective_cache_purge_redis_unix_socket
+syn keyword ngxDirectiveThirdParty selective_cache_purge_redis_host
+syn keyword ngxDirectiveThirdParty selective_cache_purge_redis_port
+syn keyword ngxDirectiveThirdParty selective_cache_purge_redis_database
+syn keyword ngxDirectiveThirdParty selective_cache_purge_query
+
+" Set cconv Module <https://github.com/liseen/set-cconv-nginx-module>
+" Cconv rewrite set commands
+syn keyword ngxDirectiveThirdParty set_cconv_to_simp
+syn keyword ngxDirectiveThirdParty set_cconv_to_trad
+syn keyword ngxDirectiveThirdParty set_pinyin_to_normal
+
+" Set Hash Module <https://github.com/simpl/ngx_http_set_hash>
+" Nginx module that allows the setting of variables to the value of a variety of hashes
+syn keyword ngxDirectiveThirdParty set_md5
+syn keyword ngxDirectiveThirdParty set_md5_upper
+syn keyword ngxDirectiveThirdParty set_murmur2
+syn keyword ngxDirectiveThirdParty set_murmur2_upper
+syn keyword ngxDirectiveThirdParty set_sha1
+syn keyword ngxDirectiveThirdParty set_sha1_upper
+
+" Set Lang Module <https://github.com/simpl/ngx_http_set_lang>
+" Provides a variety of ways for setting a variable denoting the langauge that content should be returned in.
+syn keyword ngxDirectiveThirdParty set_lang
+syn keyword ngxDirectiveThirdParty set_lang_method
+syn keyword ngxDirectiveThirdParty lang_cookie
+syn keyword ngxDirectiveThirdParty lang_get_var
+syn keyword ngxDirectiveThirdParty lang_list
+syn keyword ngxDirectiveThirdParty lang_post_var
+syn keyword ngxDirectiveThirdParty lang_host
+syn keyword ngxDirectiveThirdParty lang_referer
+
+" Set Misc Module <https://github.com/openresty/set-misc-nginx-module>
+" Various set_xxx directives added to nginx's rewrite module
+syn keyword ngxDirectiveThirdParty set_if_empty
+syn keyword ngxDirectiveThirdParty set_quote_sql_str
+syn keyword ngxDirectiveThirdParty set_quote_pgsql_str
+syn keyword ngxDirectiveThirdParty set_quote_json_str
+syn keyword ngxDirectiveThirdParty set_unescape_uri
+syn keyword ngxDirectiveThirdParty set_escape_uri
+syn keyword ngxDirectiveThirdParty set_hashed_upstream
+syn keyword ngxDirectiveThirdParty set_encode_base32
+syn keyword ngxDirectiveThirdParty set_base32_padding
+syn keyword ngxDirectiveThirdParty set_misc_base32_padding
+syn keyword ngxDirectiveThirdParty set_base32_alphabet
+syn keyword ngxDirectiveThirdParty set_decode_base32
+syn keyword ngxDirectiveThirdParty set_encode_base64
+syn keyword ngxDirectiveThirdParty set_decode_base64
+syn keyword ngxDirectiveThirdParty set_encode_hex
+syn keyword ngxDirectiveThirdParty set_decode_hex
+syn keyword ngxDirectiveThirdParty set_sha1
+syn keyword ngxDirectiveThirdParty set_md5
+syn keyword ngxDirectiveThirdParty set_hmac_sha1
+syn keyword ngxDirectiveThirdParty set_random
+syn keyword ngxDirectiveThirdParty set_secure_random_alphanum
+syn keyword ngxDirectiveThirdParty set_secure_random_lcalpha
+syn keyword ngxDirectiveThirdParty set_rotate
+syn keyword ngxDirectiveThirdParty set_local_today
+syn keyword ngxDirectiveThirdParty set_formatted_gmt_time
+syn keyword ngxDirectiveThirdParty set_formatted_local_time
+
+" SFlow Module <https://github.com/sflow/nginx-sflow-module>
+" A binary, random-sampling nginx module designed for: lightweight, centralized, continuous, real-time monitoring of very large and very busy web farms.
+syn keyword ngxDirectiveThirdParty sflow
+
+" Shibboleth Module <https://github.com/nginx-shib/nginx-http-shibboleth>
+" Shibboleth auth request module for nginx
+syn keyword ngxDirectiveThirdParty shib_request
+syn keyword ngxDirectiveThirdParty shib_request_set
+syn keyword ngxDirectiveThirdParty shib_request_use_headers
+
+" Slice Module <https://github.com/alibaba/nginx-http-slice>
+" Nginx module for serving a file in slices (reverse byte-range)
+" syn keyword ngxDirectiveThirdParty slice
+syn keyword ngxDirectiveThirdParty slice_arg_begin
+syn keyword ngxDirectiveThirdParty slice_arg_end
+syn keyword ngxDirectiveThirdParty slice_header
+syn keyword ngxDirectiveThirdParty slice_footer
+syn keyword ngxDirectiveThirdParty slice_header_first
+syn keyword ngxDirectiveThirdParty slice_footer_last
+
+" SlowFS Cache Module <https://github.com/FRiCKLE/ngx_slowfs_cache/>
+" Module adding ability to cache static files.
+syn keyword ngxDirectiveThirdParty slowfs_big_file_size
+syn keyword ngxDirectiveThirdParty slowfs_cache
+syn keyword ngxDirectiveThirdParty slowfs_cache_key
+syn keyword ngxDirectiveThirdParty slowfs_cache_min_uses
+syn keyword ngxDirectiveThirdParty slowfs_cache_path
+syn keyword ngxDirectiveThirdParty slowfs_cache_purge
+syn keyword ngxDirectiveThirdParty slowfs_cache_valid
+syn keyword ngxDirectiveThirdParty slowfs_temp_path
+
+" Small Light Module <https://github.com/cubicdaiya/ngx_small_light>
+" Dynamic Image Transformation Module For nginx.
+syn keyword ngxDirectiveThirdParty small_light
+syn keyword ngxDirectiveThirdParty small_light_getparam_mode
+syn keyword ngxDirectiveThirdParty small_light_material_dir
+syn keyword ngxDirectiveThirdParty small_light_pattern_define
+syn keyword ngxDirectiveThirdParty small_light_radius_max
+syn keyword ngxDirectiveThirdParty small_light_sigma_max
+syn keyword ngxDirectiveThirdParty small_light_imlib2_temp_dir
+syn keyword ngxDirectiveThirdParty small_light_buffer
+
+" Sorted Querystring Filter Module <https://github.com/wandenberg/nginx-sorted-querystring-module>
+" Nginx module to expose querystring parameters sorted in a variable to be used on cache_key as example
+syn keyword ngxDirectiveThirdParty sorted_querystring_filter_parameter
+
+" Sphinx2 Module <https://github.com/reeteshranjan/sphinx2-nginx-module>
+" Nginx upstream module for Sphinx 2.x
+syn keyword ngxDirectiveThirdParty sphinx2_pass
+syn keyword ngxDirectiveThirdParty sphinx2_bind
+syn keyword ngxDirectiveThirdParty sphinx2_connect_timeout
+syn keyword ngxDirectiveThirdParty sphinx2_send_timeout
+syn keyword ngxDirectiveThirdParty sphinx2_buffer_size
+syn keyword ngxDirectiveThirdParty sphinx2_read_timeout
+syn keyword ngxDirectiveThirdParty sphinx2_next_upstream
+
+" HTTP SPNEGO auth Module <https://github.com/stnoonan/spnego-http-auth-nginx-module>
+" This module implements adds SPNEGO support to nginx(http://nginx.org). It currently supports only Kerberos authentication via GSSAPI
+syn keyword ngxDirectiveThirdParty auth_gss
+syn keyword ngxDirectiveThirdParty auth_gss_keytab
+syn keyword ngxDirectiveThirdParty auth_gss_realm
+syn keyword ngxDirectiveThirdParty auth_gss_service_name
+syn keyword ngxDirectiveThirdParty auth_gss_authorized_principal
+syn keyword ngxDirectiveThirdParty auth_gss_allow_basic_fallback
+
+" SR Cache Module <https://github.com/openresty/srcache-nginx-module>
+" Transparent subrequest-based caching layout for arbitrary nginx locations
+syn keyword ngxDirectiveThirdParty srcache_fetch
+syn keyword ngxDirectiveThirdParty srcache_fetch_skip
+syn keyword ngxDirectiveThirdParty srcache_store
+syn keyword ngxDirectiveThirdParty srcache_store_max_size
+syn keyword ngxDirectiveThirdParty srcache_store_skip
+syn keyword ngxDirectiveThirdParty srcache_store_statuses
+syn keyword ngxDirectiveThirdParty srcache_store_ranges
+syn keyword ngxDirectiveThirdParty srcache_header_buffer_size
+syn keyword ngxDirectiveThirdParty srcache_store_hide_header
+syn keyword ngxDirectiveThirdParty srcache_store_pass_header
+syn keyword ngxDirectiveThirdParty srcache_methods
+syn keyword ngxDirectiveThirdParty srcache_ignore_content_encoding
+syn keyword ngxDirectiveThirdParty srcache_request_cache_control
+syn keyword ngxDirectiveThirdParty srcache_response_cache_control
+syn keyword ngxDirectiveThirdParty srcache_store_no_store
+syn keyword ngxDirectiveThirdParty srcache_store_no_cache
+syn keyword ngxDirectiveThirdParty srcache_store_private
+syn keyword ngxDirectiveThirdParty srcache_default_expire
+syn keyword ngxDirectiveThirdParty srcache_max_expire
+
+" SSSD Info Module <https://github.com/veruu/ngx_sssd_info>
+" Retrives additional attributes from SSSD for current authentizated user
+syn keyword ngxDirectiveThirdParty sssd_info
+syn keyword ngxDirectiveThirdParty sssd_info_output_to
+syn keyword ngxDirectiveThirdParty sssd_info_groups
+syn keyword ngxDirectiveThirdParty sssd_info_group
+syn keyword ngxDirectiveThirdParty sssd_info_group_separator
+syn keyword ngxDirectiveThirdParty sssd_info_attributes
+syn keyword ngxDirectiveThirdParty sssd_info_attribute
+syn keyword ngxDirectiveThirdParty sssd_info_attribute_separator
+
+" Static Etags Module <https://github.com/mikewest/nginx-static-etags>
+" Generate etags for static content
+syn keyword ngxDirectiveThirdParty FileETag
+
+" Statsd Module <https://github.com/zebrafishlabs/nginx-statsd>
+" An nginx module for sending statistics to statsd
+syn keyword ngxDirectiveThirdParty statsd_server
+syn keyword ngxDirectiveThirdParty statsd_sample_rate
+syn keyword ngxDirectiveThirdParty statsd_count
+syn keyword ngxDirectiveThirdParty statsd_timing
+
+" Sticky Module <https://bitbucket.org/nginx-goodies/nginx-sticky-module-ng>
+" Add a sticky cookie to be always forwarded to the same upstream server
+" syn keyword ngxDirectiveThirdParty sticky
+
+" Stream Echo Module <https://github.com/openresty/stream-echo-nginx-module>
+" TCP/stream echo module for NGINX (a port of ngx_http_echo_module)
+syn keyword ngxDirectiveThirdParty echo
+syn keyword ngxDirectiveThirdParty echo_duplicate
+syn keyword ngxDirectiveThirdParty echo_flush_wait
+syn keyword ngxDirectiveThirdParty echo_sleep
+syn keyword ngxDirectiveThirdParty echo_send_timeout
+syn keyword ngxDirectiveThirdParty echo_read_bytes
+syn keyword ngxDirectiveThirdParty echo_read_line
+syn keyword ngxDirectiveThirdParty echo_request_data
+syn keyword ngxDirectiveThirdParty echo_discard_request
+syn keyword ngxDirectiveThirdParty echo_read_buffer_size
+syn keyword ngxDirectiveThirdParty echo_read_timeout
+syn keyword ngxDirectiveThirdParty echo_client_error_log_level
+syn keyword ngxDirectiveThirdParty echo_lingering_close
+syn keyword ngxDirectiveThirdParty echo_lingering_time
+syn keyword ngxDirectiveThirdParty echo_lingering_timeout
+
+" Stream Lua Module <https://github.com/openresty/stream-lua-nginx-module>
+" Embed the power of Lua into Nginx stream/TCP Servers.
+syn keyword ngxDirectiveThirdParty lua_resolver
+syn keyword ngxDirectiveThirdParty lua_resolver_timeout
+syn keyword ngxDirectiveThirdParty lua_lingering_close
+syn keyword ngxDirectiveThirdParty lua_lingering_time
+syn keyword ngxDirectiveThirdParty lua_lingering_timeout
+
+" Stream Upsync Module <https://github.com/xiaokai-wang/nginx-stream-upsync-module>
+" Sync upstreams from consul or others, dynamiclly modify backend-servers attribute(weight, max_fails,...), needn't reload nginx.
+syn keyword ngxDirectiveThirdParty upsync
+syn keyword ngxDirectiveThirdParty upsync_dump_path
+syn keyword ngxDirectiveThirdParty upsync_lb
+syn keyword ngxDirectiveThirdParty upsync_show
+
+" Strip Module <https://github.com/evanmiller/mod_strip>
+" Whitespace remover.
+syn keyword ngxDirectiveThirdParty strip
+
+" Subrange Module <https://github.com/Qihoo360/ngx_http_subrange_module>
+" Split one big HTTP/Range request to multiple subrange requesets
+syn keyword ngxDirectiveThirdParty subrange
+
+" Substitutions Module <https://www.nginx.com/resources/wiki/modules/substitutions/>
+" A filter module which can do both regular expression and fixed string substitutions on response bodies.
+syn keyword ngxDirectiveThirdParty subs_filter
+syn keyword ngxDirectiveThirdParty subs_filter_types
+
+" Summarizer Module <https://github.com/reeteshranjan/summarizer-nginx-module>
+" Upstream nginx module to get summaries of documents using the summarizer daemon service
+syn keyword ngxDirectiveThirdParty smrzr_filename
+syn keyword ngxDirectiveThirdParty smrzr_ratio
+
+" Supervisord Module <https://github.com/FRiCKLE/ngx_supervisord/>
+" Module providing nginx with API to communicate with supervisord and manage (start/stop) backends on-demand.
+syn keyword ngxDirectiveThirdParty supervisord
+syn keyword ngxDirectiveThirdParty supervisord_inherit_backend_status
+syn keyword ngxDirectiveThirdParty supervisord_name
+syn keyword ngxDirectiveThirdParty supervisord_start
+syn keyword ngxDirectiveThirdParty supervisord_stop
+
+" Tarantool Upstream Module <https://github.com/tarantool/nginx_upstream_module>
+" Tarantool NginX upstream module (REST, JSON API, websockets, load balancing)
+syn keyword ngxDirectiveThirdParty tnt_pass
+syn keyword ngxDirectiveThirdParty tnt_http_methods
+syn keyword ngxDirectiveThirdParty tnt_http_rest_methods
+syn keyword ngxDirectiveThirdParty tnt_pass_http_request
+syn keyword ngxDirectiveThirdParty tnt_pass_http_request_buffer_size
+syn keyword ngxDirectiveThirdParty tnt_method
+syn keyword ngxDirectiveThirdParty tnt_http_allowed_methods - experemental
+syn keyword ngxDirectiveThirdParty tnt_send_timeout
+syn keyword ngxDirectiveThirdParty tnt_read_timeout
+syn keyword ngxDirectiveThirdParty tnt_buffer_size
+syn keyword ngxDirectiveThirdParty tnt_next_upstream
+syn keyword ngxDirectiveThirdParty tnt_connect_timeout
+syn keyword ngxDirectiveThirdParty tnt_next_upstream
+syn keyword ngxDirectiveThirdParty tnt_next_upstream_tries
+syn keyword ngxDirectiveThirdParty tnt_next_upstream_timeout
+
+" TCP Proxy Module <http://yaoweibin.github.io/nginx_tcp_proxy_module/>
+" Add the feature of tcp proxy with nginx, with health check and status monitor
+syn keyword ngxDirectiveBlock tcp
+" syn keyword ngxDirectiveThirdParty server
+" syn keyword ngxDirectiveThirdParty listen
+" syn keyword ngxDirectiveThirdParty allow
+" syn keyword ngxDirectiveThirdParty deny
+" syn keyword ngxDirectiveThirdParty so_keepalive
+" syn keyword ngxDirectiveThirdParty tcp_nodelay
+" syn keyword ngxDirectiveThirdParty timeout
+" syn keyword ngxDirectiveThirdParty server_name
+" syn keyword ngxDirectiveThirdParty resolver
+" syn keyword ngxDirectiveThirdParty resolver_timeout
+" syn keyword ngxDirectiveThirdParty upstream
+syn keyword ngxDirectiveThirdParty check
+syn keyword ngxDirectiveThirdParty check_http_send
+syn keyword ngxDirectiveThirdParty check_http_expect_alive
+syn keyword ngxDirectiveThirdParty check_smtp_send
+syn keyword ngxDirectiveThirdParty check_smtp_expect_alive
+syn keyword ngxDirectiveThirdParty check_shm_size
+syn keyword ngxDirectiveThirdParty check_status
+" syn keyword ngxDirectiveThirdParty ip_hash
+" syn keyword ngxDirectiveThirdParty proxy_pass
+" syn keyword ngxDirectiveThirdParty proxy_buffer
+" syn keyword ngxDirectiveThirdParty proxy_connect_timeout
+" syn keyword ngxDirectiveThirdParty proxy_read_timeout
+syn keyword ngxDirectiveThirdParty proxy_write_timeout
+
+" Testcookie Module <https://github.com/kyprizel/testcookie-nginx-module>
+" NGINX module for L7 DDoS attack mitigation
+syn keyword ngxDirectiveThirdParty testcookie
+syn keyword ngxDirectiveThirdParty testcookie_name
+syn keyword ngxDirectiveThirdParty testcookie_domain
+syn keyword ngxDirectiveThirdParty testcookie_expires
+syn keyword ngxDirectiveThirdParty testcookie_path
+syn keyword ngxDirectiveThirdParty testcookie_secret
+syn keyword ngxDirectiveThirdParty testcookie_session
+syn keyword ngxDirectiveThirdParty testcookie_arg
+syn keyword ngxDirectiveThirdParty testcookie_max_attempts
+syn keyword ngxDirectiveThirdParty testcookie_p3p
+syn keyword ngxDirectiveThirdParty testcookie_fallback
+syn keyword ngxDirectiveThirdParty testcookie_whitelist
+syn keyword ngxDirectiveThirdParty testcookie_pass
+syn keyword ngxDirectiveThirdParty testcookie_redirect_via_refresh
+syn keyword ngxDirectiveThirdParty testcookie_refresh_template
+syn keyword ngxDirectiveThirdParty testcookie_refresh_status
+syn keyword ngxDirectiveThirdParty testcookie_deny_keepalive
+syn keyword ngxDirectiveThirdParty testcookie_get_only
+syn keyword ngxDirectiveThirdParty testcookie_https_location
+syn keyword ngxDirectiveThirdParty testcookie_refresh_encrypt_cookie
+syn keyword ngxDirectiveThirdParty testcookie_refresh_encrypt_cookie_key
+syn keyword ngxDirectiveThirdParty testcookie_refresh_encrypt_iv
+syn keyword ngxDirectiveThirdParty testcookie_internal
+syn keyword ngxDirectiveThirdParty testcookie_httponly_flag
+syn keyword ngxDirectiveThirdParty testcookie_secure_flag
+
+" Types Filter Module <https://github.com/flygoast/ngx_http_types_filter>
+" Change the `Content-Type` output header depending on an extension variable according to a condition specified in the 'if' clause.
+syn keyword ngxDirectiveThirdParty types_filter
+syn keyword ngxDirectiveThirdParty types_filter_use_default
+
+" Unzip Module <https://github.com/youzee/nginx-unzip-module>
+" Enabling fetching of files that are stored in zipped archives.
+syn keyword ngxDirectiveThirdParty file_in_unzip_archivefile
+syn keyword ngxDirectiveThirdParty file_in_unzip_extract
+syn keyword ngxDirectiveThirdParty file_in_unzip
+
+" Upload Progress Module <https://www.nginx.com/resources/wiki/modules/upload_progress/>
+" An upload progress system, that monitors RFC1867 POST upload as they are transmitted to upstream servers
+syn keyword ngxDirectiveThirdParty upload_progress
+syn keyword ngxDirectiveThirdParty track_uploads
+syn keyword ngxDirectiveThirdParty report_uploads
+syn keyword ngxDirectiveThirdParty upload_progress_content_type
+syn keyword ngxDirectiveThirdParty upload_progress_header
+syn keyword ngxDirectiveThirdParty upload_progress_jsonp_parameter
+syn keyword ngxDirectiveThirdParty upload_progress_json_output
+syn keyword ngxDirectiveThirdParty upload_progress_jsonp_output
+syn keyword ngxDirectiveThirdParty upload_progress_template
+
+" Upload Module <https://www.nginx.com/resources/wiki/modules/upload/>
+" Parses request body storing all files being uploaded to a directory specified by upload_store directive
+syn keyword ngxDirectiveThirdParty upload_pass
+syn keyword ngxDirectiveThirdParty upload_resumable
+syn keyword ngxDirectiveThirdParty upload_store
+syn keyword ngxDirectiveThirdParty upload_state_store
+syn keyword ngxDirectiveThirdParty upload_store_access
+syn keyword ngxDirectiveThirdParty upload_set_form_field
+syn keyword ngxDirectiveThirdParty upload_aggregate_form_field
+syn keyword ngxDirectiveThirdParty upload_pass_form_field
+syn keyword ngxDirectiveThirdParty upload_cleanup
+syn keyword ngxDirectiveThirdParty upload_buffer_size
+syn keyword ngxDirectiveThirdParty upload_max_part_header_len
+syn keyword ngxDirectiveThirdParty upload_max_file_size
+syn keyword ngxDirectiveThirdParty upload_limit_rate
+syn keyword ngxDirectiveThirdParty upload_max_output_body_len
+syn keyword ngxDirectiveThirdParty upload_tame_arrays
+syn keyword ngxDirectiveThirdParty upload_pass_args
+
+" Upstream Fair Module <https://github.com/gnosek/nginx-upstream-fair>
+" The fair load balancer module for nginx http://nginx.localdomain.pl
+syn keyword ngxDirectiveThirdParty fair
+syn keyword ngxDirectiveThirdParty upstream_fair_shm_size
+
+" Upstream Hash Module (DEPRECATED) <http://wiki.nginx.org/NginxHttpUpstreamRequestHashModule>
+" Provides simple upstream load distribution by hashing a configurable variable.
+" syn keyword ngxDirectiveDeprecated hash
+syn keyword ngxDirectiveDeprecated hash_again
+
+" Upstream Domain Resolve Module <https://www.nginx.com/resources/wiki/modules/domain_resolve/>
+" A load-balancer that resolves an upstream domain name asynchronously.
+syn keyword ngxDirectiveThirdParty jdomain
+
+" Upsync Module <https://github.com/weibocom/nginx-upsync-module>
+" Sync upstreams from consul or others, dynamiclly modify backend-servers attribute(weight, max_fails,...), needn't reload nginx
+syn keyword ngxDirectiveThirdParty upsync
+syn keyword ngxDirectiveThirdParty upsync_dump_path
+syn keyword ngxDirectiveThirdParty upsync_lb
+syn keyword ngxDirectiveThirdParty upstream_show
+
+" URL Module <https://github.com/vozlt/nginx-module-url>
+" Nginx url encoding converting module
+syn keyword ngxDirectiveThirdParty url_encoding_convert
+syn keyword ngxDirectiveThirdParty url_encoding_convert_from
+syn keyword ngxDirectiveThirdParty url_encoding_convert_to
+
+" User Agent Module <https://github.com/alibaba/nginx-http-user-agent>
+" Match browsers and crawlers
+syn keyword ngxDirectiveThirdParty user_agent
+
+" Upstrema Ketama Chash Module <https://github.com/flygoast/ngx_http_upstream_ketama_chash>
+" Nginx load-balancer module implementing ketama consistent hashing.
+syn keyword ngxDirectiveThirdParty ketama_chash
+
+" Video Thumbextractor Module <https://github.com/wandenberg/nginx-video-thumbextractor-module>
+" Extract thumbs from a video file
+syn keyword ngxDirectiveThirdParty video_thumbextractor
+syn keyword ngxDirectiveThirdParty video_thumbextractor_video_filename
+syn keyword ngxDirectiveThirdParty video_thumbextractor_video_second
+syn keyword ngxDirectiveThirdParty video_thumbextractor_image_width
+syn keyword ngxDirectiveThirdParty video_thumbextractor_image_height
+syn keyword ngxDirectiveThirdParty video_thumbextractor_only_keyframe
+syn keyword ngxDirectiveThirdParty video_thumbextractor_next_time
+syn keyword ngxDirectiveThirdParty video_thumbextractor_tile_rows
+syn keyword ngxDirectiveThirdParty video_thumbextractor_tile_cols
+syn keyword ngxDirectiveThirdParty video_thumbextractor_tile_max_rows
+syn keyword ngxDirectiveThirdParty video_thumbextractor_tile_max_cols
+syn keyword ngxDirectiveThirdParty video_thumbextractor_tile_sample_interval
+syn keyword ngxDirectiveThirdParty video_thumbextractor_tile_color
+syn keyword ngxDirectiveThirdParty video_thumbextractor_tile_margin
+syn keyword ngxDirectiveThirdParty video_thumbextractor_tile_padding
+syn keyword ngxDirectiveThirdParty video_thumbextractor_threads
+syn keyword ngxDirectiveThirdParty video_thumbextractor_processes_per_worker
+
+" Eval Module <http://www.grid.net.ru/nginx/eval.en.html>
+" Module for nginx web server evaluates response of proxy or memcached module into variables.
+syn keyword ngxDirectiveThirdParty eval
+syn keyword ngxDirectiveThirdParty eval_escalate
+syn keyword ngxDirectiveThirdParty eval_override_content_type
+
+" VTS Module <https://github.com/vozlt/nginx-module-vts>
+" Nginx virtual host traffic status module
+syn keyword ngxDirectiveThirdParty vhost_traffic_status
+syn keyword ngxDirectiveThirdParty vhost_traffic_status_zone
+syn keyword ngxDirectiveThirdParty vhost_traffic_status_display
+syn keyword ngxDirectiveThirdParty vhost_traffic_status_display_format
+syn keyword ngxDirectiveThirdParty vhost_traffic_status_display_jsonp
+syn keyword ngxDirectiveThirdParty vhost_traffic_status_filter
+syn keyword ngxDirectiveThirdParty vhost_traffic_status_filter_by_host
+syn keyword ngxDirectiveThirdParty vhost_traffic_status_filter_by_set_key
+syn keyword ngxDirectiveThirdParty vhost_traffic_status_filter_check_duplicate
+syn keyword ngxDirectiveThirdParty vhost_traffic_status_limit
+syn keyword ngxDirectiveThirdParty vhost_traffic_status_limit_traffic
+syn keyword ngxDirectiveThirdParty vhost_traffic_status_limit_traffic_by_set_key
+syn keyword ngxDirectiveThirdParty vhost_traffic_status_limit_check_duplicate
+
+" XSS Module <https://github.com/openresty/xss-nginx-module>
+" Native support for cross-site scripting (XSS) in an nginx.
+syn keyword ngxDirectiveThirdParty xss_get
+syn keyword ngxDirectiveThirdParty xss_callback_arg
+syn keyword ngxDirectiveThirdParty xss_override_status
+syn keyword ngxDirectiveThirdParty xss_check_status
+syn keyword ngxDirectiveThirdParty xss_input_types
+
+" ZIP Module <https://www.nginx.com/resources/wiki/modules/zip/>
+" ZIP archiver for nginx
+
+" Contained LUA blocks for embedded syntax highlighting
+syn keyword ngxThirdPartyLuaBlock balancer_by_lua_block contained
+syn keyword ngxThirdPartyLuaBlock init_by_lua_block contained
+syn keyword ngxThirdPartyLuaBlock init_worker_by_lua_block contained
+syn keyword ngxThirdPartyLuaBlock set_by_lua_block contained
+syn keyword ngxThirdPartyLuaBlock content_by_lua_block contained
+syn keyword ngxThirdPartyLuaBlock rewrite_by_lua_block contained
+syn keyword ngxThirdPartyLuaBlock access_by_lua_block contained
+syn keyword ngxThirdPartyLuaBlock header_filter_by_lua_block contained
+syn keyword ngxThirdPartyLuaBlock body_filter_by_lua_block contained
+syn keyword ngxThirdPartyLuaBlock log_by_lua_block contained
+syn keyword ngxThirdPartyLuaBlock ssl_certificate_by_lua_block contained
+syn keyword ngxThirdPartyLuaBlock ssl_session_fetch_by_lua_block contained
+syn keyword ngxThirdPartyLuaBlock ssl_session_store_by_lua_block contained
+
+
+" Nested syntax in ERB templating statements
+" Subtype needs to be set to '', otherwise recursive errors occur when opening *.nginx files
+let b:eruby_subtype = ''
+unlet b:current_syntax
+syn include @ERB syntax/eruby.vim
+syn region ngxTemplate start=+<%[^\=]+ end=+%>+ oneline contains=@ERB
+syn region ngxTemplateVar start=+<%=+ end=+%>+ oneline
+let b:current_syntax = "nginx"
+
+" Nested syntax in Jinja templating statements
+" This dependend on https://github.com/lepture/vim-jinja
+unlet b:current_syntax
+try
+ syn include @JINJA syntax/jinja.vim
+ syn region ngxTemplate start=+{%+ end=+%}+ oneline contains=@JINJA
+ syn region ngxTemplateVar start=+{{+ end=+}}+ oneline
+catch
+endtry
+let b:current_syntax = "nginx"
+
+" Enable nested LUA syntax highlighting
+unlet b:current_syntax
+syn include @LUA syntax/lua.vim
+syn region ngxLua start=+^\s*\w\+_by_lua_block\s*{+ end=+}+me=s-1 contains=ngxBlock,@LUA
+let b:current_syntax = "nginx"
+
+
+" Highlight
+hi link ngxComment Comment
+hi link ngxVariable Identifier
+hi link ngxVariableBlock Identifier
+hi link ngxVariableString PreProc
+hi link ngxString String
+hi link ngxIPaddr Delimiter
+hi link ngxBoolean Boolean
+hi link ngxInteger Number
+hi link ngxDirectiveBlock Statement
+hi link ngxDirectiveImportant Type
+hi link ngxDirectiveControl Keyword
+hi link ngxDirectiveDeprecated Error
+hi link ngxDirective Function
+hi link ngxDirectiveThirdParty Function
+hi link ngxListenOptions PreProc
+hi link ngxUpstreamServerOptions PreProc
+hi link ngxProxyNextUpstreamOptions PreProc
+hi link ngxMailProtocol Keyword
+hi link ngxSSLProtocol PreProc
+hi link ngxSSLProtocolDeprecated Error
+hi link ngxStickyOptions ngxDirective
+hi link ngxCookieOptions PreProc
+hi link ngxTemplateVar Identifier
+
+hi link ngxSSLSessionTicketsOff ngxBoolean
+hi link ngxSSLSessionTicketsOn Error
+hi link ngxSSLPreferServerCiphersOn ngxBoolean
+hi link ngxSSLPreferServerCiphersOff Error
+hi link ngxGzipOff ngxBoolean
+hi link ngxGzipOn Error
+hi link ngxSSLCipherInsecure Error
+
+hi link ngxThirdPartyLuaBlock Function
diff --git a/runtime/syntax/sml.vim b/runtime/syntax/sml.vim
index afff5304e6..53ff12a859 100644
--- a/runtime/syntax/sml.vim
+++ b/runtime/syntax/sml.vim
@@ -3,19 +3,18 @@
" Filenames: *.sml *.sig
" Maintainers: Markus Mottl <markus.mottl@gmail.com>
" Fabrizio Zeno Cornelli <zeno@filibusta.crema.unimi.it>
-" Last Change: 2019 Oct 01 - Only spell check strings & comments (Chuan Wei Foo)
+" Last Change: 2021 Oct 04
" 2015 Aug 31 - Fixed opening of modules (Ramana Kumar)
" 2006 Oct 23 - Fixed character highlighting bug (MM)
" quit when a syntax file was already loaded
if exists("b:current_syntax")
+ finish
+endif
" Disable spell checking of syntax.
syn spell notoplevel
- finish
-endif
-
" SML is case sensitive.
syn case match
diff --git a/runtime/syntax/tcl.vim b/runtime/syntax/tcl.vim
index 64efd6fec4..73b2b3fa11 100644
--- a/runtime/syntax/tcl.vim
+++ b/runtime/syntax/tcl.vim
@@ -6,9 +6,9 @@
" (previously Matt Neumann <mattneu@purpleturtle.com>)
" (previously Allan Kelly <allan@fruitloaf.co.uk>)
" Original: Robin Becker <robin@jessikat.demon.co.uk>
-" Last Change: 2014-02-12
+" Last Change: 2021 Oct 03
" Version: 1.14
-" URL: http://bitbucket.org/taylor_venable/metasyntax/src/tip/Config/vim/syntax/tcl.vim
+" URL: (removed, no longer worked)
" quit when a syntax file was already loaded
if exists("b:current_syntax")
diff --git a/runtime/syntax/tcsh.vim b/runtime/syntax/tcsh.vim
index b535d11df8..27c6417fd0 100644
--- a/runtime/syntax/tcsh.vim
+++ b/runtime/syntax/tcsh.vim
@@ -1,6 +1,7 @@
" tcsh.vim: Vim syntax file for tcsh scripts
-" Maintainer: Gautam Iyer <gi1242@gmail.com>
-" Modified: Thu 17 Dec 2009 06:05:07 PM EST
+" Maintainer: Doug Kearns <dougkearns@NoSpam.com> where NoSpam=gmail
+" Author: Gautam Iyer <gi1242+vim@NoSpam.com> where NoSpam=gmail
+" Modified: Sun 26 Sep 2021 12:40:55 PM EDT
"
" Description: We break up each statement into a "command" and an "end" part.
" All groups are either a "command" or part of the "end" of a statement (ie
diff --git a/runtime/syntax/typescriptcommon.vim b/runtime/syntax/typescriptcommon.vim
index 4074f04a35..ef362fc721 100644
--- a/runtime/syntax/typescriptcommon.vim
+++ b/runtime/syntax/typescriptcommon.vim
@@ -1,7 +1,7 @@
" Vim syntax file
" Language: TypeScript and TypeScriptReact
" Maintainer: Bram Moolenaar, Herrington Darkholme
-" Last Change: 2020 Oct 27
+" Last Change: 2021 Sep 22
" Based On: Herrington Darkholme's yats.vim
" Changes: See https:github.com/HerringtonDarkholme/yats.vim
" Credits: See yats.vim on github
@@ -625,7 +625,8 @@ syntax keyword typescriptReadonlyArrayKeyword readonly
" extension
if get(g:, 'yats_host_keyword', 1)
syntax keyword typescriptGlobal containedin=typescriptIdentifierName Function Boolean
- syntax keyword typescriptGlobal containedin=typescriptIdentifierName Error EvalError
+ " use of nextgroup Suggested by Doug Kearns
+ syntax keyword typescriptGlobal containedin=typescriptIdentifierName Error EvalError nextgroup=typescriptFuncCallArg
syntax keyword typescriptGlobal containedin=typescriptIdentifierName InternalError
syntax keyword typescriptGlobal containedin=typescriptIdentifierName RangeError ReferenceError
syntax keyword typescriptGlobal containedin=typescriptIdentifierName StopIteration
diff --git a/runtime/syntax/xpm.vim b/runtime/syntax/xpm.vim
index 0667ca28ad..be9f38723e 100644
--- a/runtime/syntax/xpm.vim
+++ b/runtime/syntax/xpm.vim
@@ -1,19 +1,22 @@
" Vim syntax file
" Language: X Pixmap
" Maintainer: Ronald Schild <rs@scutum.de>
-" Last Change: 2017 Feb 01
+" Last Change: 2021 Oct 04
" Version: 5.4n.1
" Jemma Nelson added termguicolors support
+" Dominique Pellé fixed spelling support
" quit when a syntax file was already loaded
if exists("b:current_syntax")
finish
endif
+syn spell notoplevel
+
syn keyword xpmType char
syn keyword xpmStorageClass static
syn keyword xpmTodo TODO FIXME XXX contained
-syn region xpmComment start="/\*" end="\*/" contains=xpmTodo
+syn region xpmComment start="/\*" end="\*/" contains=xpmTodo,@Spell
syn region xpmPixelString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=@xpmColors
if has("gui_running") || has("termguicolors") && &termguicolors
diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
index 36e01153f1..f37e4c9d37 100755
--- a/scripts/gen_vimdoc.py
+++ b/scripts/gen_vimdoc.py
@@ -91,6 +91,7 @@ CONFIG = {
'vim.c',
'buffer.c',
'window.c',
+ 'win_config.c',
'tabpage.c',
'ui.c',
],
diff --git a/scripts/pvscheck.sh b/scripts/pvscheck.sh
index 904ff81700..195a76763f 100755
--- a/scripts/pvscheck.sh
+++ b/scripts/pvscheck.sh
@@ -373,6 +373,7 @@ run_analysis() {(
analyze \
--lic-file PVS-Studio.lic \
--threads "$(get_jobs_num)" \
+ --exclude-path src/cjson \
--exclude-path src/xdiff \
--output-file PVS-studio.log \
--file build/compile_commands.json \
diff --git a/scripts/release.sh b/scripts/release.sh
index 4ec959d697..380503662d 100755
--- a/scripts/release.sh
+++ b/scripts/release.sh
@@ -80,8 +80,8 @@ _do_release_commit() {
_do_bump_commit() {
$__sed -i.bk 's/(NVIM_VERSION_PRERELEASE) ""/\1 "-dev"/' CMakeLists.txt
$__sed -i.bk 's/set\((NVIM_VERSION_PATCH) [[:digit:]]/set(\1 ?/' CMakeLists.txt
- rm CMakeLists.txt.bk
- rm runtime/nvim.appdata.xml.bk
+ rm -f CMakeLists.txt.bk
+ rm -f runtime/nvim.appdata.xml.bk
nvim +'/NVIM_VERSION' +1new +'exe "norm! iUpdate version numbers!!!"' \
-O CMakeLists.txt
diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh
index f4b817dfff..d92480abb9 100755
--- a/scripts/vim-patch.sh
+++ b/scripts/vim-patch.sh
@@ -125,8 +125,12 @@ commit_message() {
}
find_git_remote() {
- git_remote=$(git remote -v \
- | awk '$2 ~ /github.com[:\/]neovim\/neovim/ && $3 == "(fetch)" {print $1; exit}')
+ local git_remote
+ if [[ "${1-}" == fork ]]; then
+ git_remote=$(git remote -v | awk '$2 !~ /github.com[:\/]neovim\/neovim/ && $3 == "(fetch)" {print $1; exit}')
+ else
+ git_remote=$(git remote -v | awk '$2 ~ /github.com[:\/]neovim\/neovim/ && $3 == "(fetch)" {print $1; exit}')
+ fi
if [[ -z "$git_remote" ]]; then
git_remote="origin"
fi
@@ -268,8 +272,8 @@ stage_patch() {
get_vimpatch "$1"
local try_apply="${2:-}"
- local git_remote
- git_remote="$(find_git_remote)"
+ local nvim_remote
+ nvim_remote="$(find_git_remote)"
local checked_out_branch
checked_out_branch="$(git rev-parse --abbrev-ref HEAD)"
@@ -277,16 +281,16 @@ stage_patch() {
msg_ok "Current branch '${checked_out_branch}' seems to be a vim-patch"
echo " branch; not creating a new branch."
else
- printf '\nFetching "%s/master".\n' "${git_remote}"
- output="$(git fetch "${git_remote}" master 2>&1)" &&
+ printf '\nFetching "%s/master".\n' "${nvim_remote}"
+ output="$(git fetch "${nvim_remote}" master 2>&1)" &&
msg_ok "${output}" ||
(msg_err "${output}"; false)
local nvim_branch="${BRANCH_PREFIX}${vim_version}"
echo
- echo "Creating new branch '${nvim_branch}' based on '${git_remote}/master'."
+ echo "Creating new branch '${nvim_branch}' based on '${nvim_remote}/master'."
cd "${NVIM_SOURCE_DIR}"
- output="$(git checkout -b "${nvim_branch}" "${git_remote}/master" 2>&1)" &&
+ output="$(git checkout -b "${nvim_branch}" "${nvim_remote}/master" 2>&1)" &&
msg_ok "${output}" ||
(msg_err "${output}"; false)
fi
@@ -362,13 +366,13 @@ submit_pr() {
exit 1
fi
- local git_remote
- git_remote="$(find_git_remote)"
+ local nvim_remote
+ nvim_remote="$(find_git_remote)"
local pr_body
- pr_body="$(git log --grep=vim-patch --reverse --format='#### %s%n%n%b%n' "${git_remote}"/master..HEAD)"
+ pr_body="$(git log --grep=vim-patch --reverse --format='#### %s%n%n%b%n' "${nvim_remote}"/master..HEAD)"
local patches
# Extract just the "vim-patch:X.Y.ZZZZ" or "vim-patch:sha" portion of each log
- patches=("$(git log --grep=vim-patch --reverse --format='%s' "${git_remote}"/master..HEAD | sed 's/: .*//')")
+ patches=("$(git log --grep=vim-patch --reverse --format='%s' "${nvim_remote}"/master..HEAD | sed 's/: .*//')")
# shellcheck disable=SC2206
patches=(${patches[@]//vim-patch:}) # Remove 'vim-patch:' prefix for each item in array.
local pr_title="${patches[*]}" # Create space-separated string from array.
@@ -376,8 +380,19 @@ submit_pr() {
pr_title="$(printf 'vim-patch:%s' "${pr_title#,}")"
if [[ $push_first -ne 0 ]]; then
- echo "Pushing to 'origin/${checked_out_branch}'."
- output="$(git push origin "${checked_out_branch}" 2>&1)" &&
+ local push_remote
+ push_remote="$(git config --get branch."${checked_out_branch}".pushRemote || true)"
+ if [[ -z "$push_remote" ]]; then
+ push_remote="$(git config --get remote.pushDefault || true)"
+ if [[ -z "$push_remote" ]]; then
+ push_remote="$(git config --get branch."${checked_out_branch}".remote || true)"
+ if [[ -z "$push_remote" ]] || [[ "$push_remote" == "$nvim_remote" ]]; then
+ push_remote="$(find_git_remote fork)"
+ fi
+ fi
+ fi
+ echo "Pushing to '${push_remote}/${checked_out_branch}'."
+ output="$(git push "${push_remote}" "${checked_out_branch}" 2>&1)" &&
msg_ok "${output}" ||
(msg_err "${output}"; false)
diff --git a/src/cjson/lua_cjson.c b/src/cjson/lua_cjson.c
index 92d07963bd..cf9e82c38e 100644
--- a/src/cjson/lua_cjson.c
+++ b/src/cjson/lua_cjson.c
@@ -171,10 +171,18 @@ typedef struct {
} json_config_t;
typedef struct {
+ /* convert null in json objects to lua nil instead of vim.NIL */
+ int luanil_object;
+ /* convert null in json arrays to lua nil instead of vim.NIL */
+ int luanil_array;
+} json_options_t;
+
+typedef struct {
const char *data;
const char *ptr;
strbuf_t *tmp; /* Temporary storage for strings */
json_config_t *cfg;
+ json_options_t *options;
int current_depth;
} json_parse_t;
@@ -865,7 +873,7 @@ static int json_encode(lua_State *l)
/* ===== DECODING ===== */
static void json_process_value(lua_State *l, json_parse_t *json,
- json_token_t *token);
+ json_token_t *token, bool use_luanil);
static int hexdigit2int(char hex)
{
@@ -1296,7 +1304,7 @@ static void json_parse_object_context(lua_State *l, json_parse_t *json)
/* Fetch value */
json_next_token(json, &token);
- json_process_value(l, json, &token);
+ json_process_value(l, json, &token, json->options->luanil_object);
/* Set key = value */
lua_rawset(l, -3);
@@ -1343,7 +1351,7 @@ static void json_parse_array_context(lua_State *l, json_parse_t *json)
}
for (i = 1; ; i++) {
- json_process_value(l, json, &token);
+ json_process_value(l, json, &token, json->options->luanil_array);
lua_rawseti(l, -2, i); /* arr[i] = value */
json_next_token(json, &token);
@@ -1362,7 +1370,7 @@ static void json_parse_array_context(lua_State *l, json_parse_t *json)
/* Handle the "value" context */
static void json_process_value(lua_State *l, json_parse_t *json,
- json_token_t *token)
+ json_token_t *token, bool use_luanil)
{
switch (token->type) {
case T_STRING:
@@ -1381,7 +1389,11 @@ static void json_process_value(lua_State *l, json_parse_t *json,
json_parse_array_context(l, json);
break;;
case T_NULL:
- nlua_pushref(l, nlua_nil_ref);
+ if (use_luanil) {
+ lua_pushnil(l);
+ } else {
+ nlua_pushref(l, nlua_nil_ref);
+ }
break;;
default:
json_throw_parse_error(l, json, "value", token);
@@ -1392,12 +1404,46 @@ static int json_decode(lua_State *l)
{
json_parse_t json;
json_token_t token;
+ json_options_t options = { .luanil_object = false, .luanil_array = false };
+
+
size_t json_len;
- luaL_argcheck(l, lua_gettop(l) == 1, 1, "expected 1 argument");
+ switch (lua_gettop(l)) {
+ case 1:
+ break;
+ case 2:
+ luaL_checktype(l, 2, LUA_TTABLE);
+ lua_getfield(l, 2, "luanil");
+
+ /* We only handle the luanil option for now */
+ if (lua_isnil(l, -1)) {
+ lua_pop(l, 1);
+ break;
+ }
+
+ luaL_checktype(l, -1, LUA_TTABLE);
+
+ lua_getfield(l, -1, "object");
+ if (!lua_isnil(l, -1)) {
+ options.luanil_object = true;
+ }
+ lua_pop(l, 1);
+
+ lua_getfield(l, -1, "array");
+ if (!lua_isnil(l, -1)) {
+ options.luanil_array = true;
+ }
+ /* Also pop the luanil table */
+ lua_pop(l, 2);
+ break;
+ default:
+ return luaL_error (l, "expected 1 or 2 arguments");
+ }
json.cfg = json_fetch_config(l);
json.data = luaL_checklstring(l, 1, &json_len);
+ json.options = &options;
json.current_depth = 0;
json.ptr = json.data;
@@ -1415,7 +1461,7 @@ static int json_decode(lua_State *l)
json.tmp = strbuf_new(json_len);
json_next_token(&json, &token);
- json_process_value(l, &json, &token);
+ json_process_value(l, &json, &token, json.options->luanil_object);
/* Ensure there is no more input left */
json_next_token(&json, &token);
diff --git a/src/clint.py b/src/clint.py
index e7d76366b0..4b7bf002e6 100755
--- a/src/clint.py
+++ b/src/clint.py
@@ -2544,6 +2544,7 @@ def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
r'(?<!\bPMap)'
r'(?<!\bArrayOf)'
r'(?<!\bDictionaryOf)'
+ r'(?<!\bDict)'
r'\((?:const )?(?:struct )?[a-zA-Z_]\w*(?: *\*(?:const)?)*\)'
r' +'
r'-?(?:\*+|&)?(?:\w+|\+\+|--|\()', cast_line)
diff --git a/src/mpack/conv.c b/src/mpack/conv.c
index 31297a8784..6bd446ca49 100644
--- a/src/mpack/conv.c
+++ b/src/mpack/conv.c
@@ -301,7 +301,6 @@ MPACK_API double mpack_unpack_number(mpack_token_t t)
*/
if (!hi) {
assert(t.length <= 4);
- hi = 0;
lo = (~lo & (((mpack_uint32_t)1 << ((t.length * 8) - 1)) - 1));
} else {
hi = ~hi;
diff --git a/src/mpack/lmpack.c b/src/mpack/lmpack.c
index 4b0e132a3a..2d6131d7cb 100644
--- a/src/mpack/lmpack.c
+++ b/src/mpack/lmpack.c
@@ -445,7 +445,6 @@ static int lmpack_unpacker_unpack_str(lua_State *L, Unpacker *unpacker,
if (rv == MPACK_NOMEM) {
unpacker->parser = lmpack_grow_parser(unpacker->parser);
if (!unpacker->parser) {
- unpacker->unpacking = 0;
return luaL_error(L, "failed to grow Unpacker capacity");
}
}
@@ -799,7 +798,6 @@ static int lmpack_packer_pack(lua_State *L)
if (result == MPACK_NOMEM) {
packer->parser = lmpack_grow_parser(packer->parser);
if (!packer->parser) {
- packer->packing = 0;
return luaL_error(L, "Failed to grow Packer capacity");
}
}
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index e35e7ce2d4..9c6eafa2df 100644
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -27,6 +27,7 @@ set(BINARY_LIB_DIR ${PROJECT_BINARY_DIR}/lib/nvim/)
set(API_DISPATCH_GENERATOR ${GENERATOR_DIR}/gen_api_dispatch.lua)
set(API_UI_EVENTS_GENERATOR ${GENERATOR_DIR}/gen_api_ui_events.lua)
set(GENERATOR_C_GRAMMAR ${GENERATOR_DIR}/c_grammar.lua)
+set(GENERATOR_HASHY ${GENERATOR_DIR}/hashy.lua)
set(API_METADATA ${PROJECT_BINARY_DIR}/api_metadata.mpack)
set(FUNCS_DATA ${PROJECT_BINARY_DIR}/funcs_data.mpack)
set(LUA_API_C_BINDINGS ${GENERATED_DIR}/lua_api_c_bindings.generated.c)
@@ -42,12 +43,15 @@ set(GENERATED_UI_EVENTS_METADATA ${GENERATED_DIR}/api/private/ui_events_metadata
set(GENERATED_EX_CMDS_ENUM ${GENERATED_INCLUDES_DIR}/ex_cmds_enum.generated.h)
set(GENERATED_EX_CMDS_DEFS ${GENERATED_DIR}/ex_cmds_defs.generated.h)
set(GENERATED_FUNCS ${GENERATED_DIR}/funcs.generated.h)
+set(GENERATED_KEYSETS ${GENERATED_DIR}/keysets.generated.h)
+set(GENERATED_KEYSETS_DEFS ${GENERATED_DIR}/keysets_defs.generated.h)
set(GENERATED_EVENTS_ENUM ${GENERATED_INCLUDES_DIR}/auevents_enum.generated.h)
set(GENERATED_EVENTS_NAMES_MAP ${GENERATED_DIR}/auevents_name_map.generated.h)
set(GENERATED_OPTIONS ${GENERATED_DIR}/options.generated.h)
set(EX_CMDS_GENERATOR ${GENERATOR_DIR}/gen_ex_cmds.lua)
set(FUNCS_GENERATOR ${GENERATOR_DIR}/gen_eval.lua)
set(EVENTS_GENERATOR ${GENERATOR_DIR}/gen_events.lua)
+set(KEYSETS_GENERATOR ${GENERATOR_DIR}/gen_keysets.lua)
set(OPTIONS_GENERATOR ${GENERATOR_DIR}/gen_options.lua)
set(UNICODE_TABLES_GENERATOR ${GENERATOR_DIR}/gen_unicode_tables.lua)
set(UNICODE_DIR ${PROJECT_SOURCE_DIR}/unicode)
@@ -261,6 +265,7 @@ foreach(sfile ${NVIM_SOURCES}
"${GENERATED_UI_EVENTS_CALL}"
"${GENERATED_UI_EVENTS_REMOTE}"
"${GENERATED_UI_EVENTS_BRIDGE}"
+ "${GENERATED_KEYSETS}"
)
get_filename_component(full_d ${sfile} PATH)
file(RELATIVE_PATH d "${CMAKE_CURRENT_LIST_DIR}" "${full_d}")
@@ -364,12 +369,14 @@ add_custom_command(
list(APPEND NVIM_GENERATED_FOR_HEADERS
"${GENERATED_EX_CMDS_ENUM}"
"${GENERATED_EVENTS_ENUM}"
+ "${GENERATED_KEYSETS_DEFS}"
)
list(APPEND NVIM_GENERATED_FOR_SOURCES
"${GENERATED_API_DISPATCH}"
"${GENERATED_EX_CMDS_DEFS}"
"${GENERATED_EVENTS_NAMES_MAP}"
+ "${GENERATED_KEYSETS}"
"${GENERATED_OPTIONS}"
"${GENERATED_UNICODE_TABLES}"
"${VIM_MODULE_FILE}"
@@ -404,6 +411,12 @@ add_custom_command(OUTPUT ${GENERATED_EVENTS_ENUM} ${GENERATED_EVENTS_NAMES_MAP}
DEPENDS ${EVENTS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/auevents.lua
)
+add_custom_command(OUTPUT ${GENERATED_KEYSETS} ${GENERATED_KEYSETS_DEFS}
+ COMMAND ${LUA_PRG} ${KEYSETS_GENERATOR}
+ ${CMAKE_CURRENT_LIST_DIR} ${LUA_SHARED_MODULE_SOURCE} ${GENERATED_KEYSETS} ${GENERATED_KEYSETS_DEFS}
+ DEPENDS ${KEYSETS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/api/keysets.lua ${GENERATOR_HASHY}
+)
+
add_custom_command(OUTPUT ${GENERATED_OPTIONS}
COMMAND ${LUA_PRG} ${OPTIONS_GENERATOR}
${CMAKE_CURRENT_LIST_DIR} ${GENERATED_OPTIONS}
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index 0ef2776263..3ab7e6b778 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -858,7 +858,7 @@ ArrayOf(Dictionary) nvim_buf_get_keymap(Buffer buffer, String mode, Error *err)
/// @see |nvim_set_keymap()|
///
/// @param buffer Buffer handle, or 0 for current buffer
-void nvim_buf_set_keymap(Buffer buffer, String mode, String lhs, String rhs, Dictionary opts,
+void nvim_buf_set_keymap(Buffer buffer, String mode, String lhs, String rhs, Dict(keymap) *opts,
Error *err)
FUNC_API_SINCE(6)
{
@@ -874,8 +874,7 @@ void nvim_buf_del_keymap(Buffer buffer, String mode, String lhs, Error *err)
FUNC_API_SINCE(6)
{
String rhs = { .data = "", .size = 0 };
- Dictionary opts = ARRAY_DICT_INIT;
- modify_keymap(buffer, true, mode, lhs, rhs, opts, err);
+ modify_keymap(buffer, true, mode, lhs, rhs, NULL, err);
}
/// Gets a map of buffer-local |user-commands|.
@@ -885,22 +884,13 @@ void nvim_buf_del_keymap(Buffer buffer, String mode, String lhs, Error *err)
/// @param[out] err Error details, if any.
///
/// @returns Map of maps describing commands.
-Dictionary nvim_buf_get_commands(Buffer buffer, Dictionary opts, Error *err)
+Dictionary nvim_buf_get_commands(Buffer buffer, Dict(get_commands) *opts, Error *err)
FUNC_API_SINCE(4)
{
bool global = (buffer == -1);
- bool builtin = false;
-
- for (size_t i = 0; i < opts.size; i++) {
- String k = opts.items[i].key;
- Object v = opts.items[i].value;
- if (!strequal("builtin", k.data)) {
- api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data);
- return (Dictionary)ARRAY_DICT_INIT;
- }
- if (strequal("builtin", k.data)) {
- builtin = v.data.boolean;
- }
+ bool builtin = api_object_to_bool(opts->builtin, "builtin", false, err);
+ if (ERROR_SET(err)) {
+ return (Dictionary)ARRAY_DICT_INIT;
}
if (global) {
@@ -1118,14 +1108,97 @@ Boolean nvim_buf_is_valid(Buffer buffer)
return ret;
}
-/// Return a tuple (row,col) representing the position of the named mark.
+/// Deletes a named mark in the buffer. See |mark-motions|.
+///
+/// @note only deletes marks set in the buffer, if the mark is not set
+/// in the buffer it will return false.
+/// @param buffer Buffer to set the mark on
+/// @param name Mark name
+/// @return true if the mark was deleted, else false.
+/// @see |nvim_buf_set_mark()|
+/// @see |nvim_del_mark()|
+Boolean nvim_buf_del_mark(Buffer buffer, String name, Error *err)
+ FUNC_API_SINCE(8)
+{
+ bool res = false;
+ buf_T *buf = find_buffer_by_handle(buffer, err);
+
+ if (!buf) {
+ return res;
+ }
+
+ if (name.size != 1) {
+ api_set_error(err, kErrorTypeValidation,
+ "Mark name must be a single character");
+ return res;
+ }
+
+ pos_T *pos = getmark_buf(buf, *name.data, false);
+
+ // pos point to NULL when there's no mark with name
+ if (pos == NULL) {
+ api_set_error(err, kErrorTypeValidation, "Invalid mark name: '%c'",
+ *name.data);
+ return res;
+ }
+
+ // pos->lnum is 0 when the mark is not valid in the buffer, or is not set.
+ if (pos->lnum != 0) {
+ // since the mark belongs to the buffer delete it.
+ res = set_mark(buf, name, 0, 0, err);
+ }
+
+ return res;
+}
+
+/// Sets a named mark in the given buffer, all marks are allowed
+/// file/uppercase, visual, last change, etc. See |mark-motions|.
+///
+/// Marks are (1,0)-indexed. |api-indexing|
+///
+/// @note Passing 0 as line deletes the mark
+///
+/// @param buffer Buffer to set the mark on
+/// @param name Mark name
+/// @param line Line number
+/// @param col Column/row number
+/// @return true if the mark was set, else false.
+/// @see |nvim_buf_del_mark()|
+/// @see |nvim_buf_get_mark()|
+Boolean nvim_buf_set_mark(Buffer buffer, String name,
+ Integer line, Integer col, Error *err)
+ FUNC_API_SINCE(8)
+{
+ bool res = false;
+ buf_T *buf = find_buffer_by_handle(buffer, err);
+
+ if (!buf) {
+ return res;
+ }
+
+ if (name.size != 1) {
+ api_set_error(err, kErrorTypeValidation,
+ "Mark name must be a single character");
+ return res;
+ }
+
+ res = set_mark(buf, name, line, col, err);
+
+ return res;
+}
+
+/// Returns a tuple (row,col) representing the position of the named mark. See
+/// |mark-motions|.
///
/// Marks are (1,0)-indexed. |api-indexing|
///
/// @param buffer Buffer handle, or 0 for current buffer
/// @param name Mark name
/// @param[out] err Error details, if any
-/// @return (row, col) tuple
+/// @return (row, col) tuple, (0, 0) if the mark is not set, or is an
+/// uppercase/file mark set in another buffer.
+/// @see |nvim_buf_set_mark()|
+/// @see |nvim_buf_del_mark()|
ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Error *err)
FUNC_API_SINCE(1)
{
@@ -1485,7 +1558,7 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
/// @param[out] err Error details, if any
/// @return Id of the created/updated extmark
Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer col,
- Dictionary opts, Error *err)
+ Dict(set_extmark) *opts, Error *err)
FUNC_API_SINCE(7)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -1498,211 +1571,174 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
return 0;
}
- bool ephemeral = false;
uint64_t id = 0;
+ if (opts->id.type == kObjectTypeInteger && opts->id.data.integer > 0) {
+ id = (uint64_t)opts->id.data.integer;
+ } else if (HAS_KEY(opts->id)) {
+ api_set_error(err, kErrorTypeValidation, "id is not a positive integer");
+ goto error;
+ }
+
int line2 = -1;
- Decoration decor = DECORATION_INIT;
+ if (opts->end_line.type == kObjectTypeInteger) {
+ Integer val = opts->end_line.data.integer;
+ if (val < 0 || val > buf->b_ml.ml_line_count) {
+ api_set_error(err, kErrorTypeValidation, "end_line value outside range");
+ goto error;
+ } else {
+ line2 = (int)val;
+ }
+ } else if (HAS_KEY(opts->end_line)) {
+ api_set_error(err, kErrorTypeValidation, "end_line is not an integer");
+ goto error;
+ }
+
colnr_T col2 = -1;
+ if (opts->end_col.type == kObjectTypeInteger) {
+ Integer val = opts->end_col.data.integer;
+ if (val < 0 || val > MAXCOL) {
+ api_set_error(err, kErrorTypeValidation, "end_col value outside range");
+ goto error;
+ } else {
+ col2 = (int)val;
+ }
+ } else if (HAS_KEY(opts->end_col)) {
+ api_set_error(err, kErrorTypeValidation, "end_col is not an integer");
+ goto error;
+ }
- bool right_gravity = true;
- bool end_right_gravity = false;
- bool end_gravity_set = false;
+ Decoration decor = DECORATION_INIT;
- VirtLines virt_lines = KV_INITIAL_VALUE;
- bool virt_lines_above = false;
- bool virt_lines_leftcol = false;
+ if (HAS_KEY(opts->hl_group)) {
+ decor.hl_id = object_to_hl_id(opts->hl_group, "hl_group", err);
+ if (ERROR_SET(err)) {
+ goto error;
+ }
+ }
- for (size_t i = 0; i < opts.size; i++) {
- String k = opts.items[i].key;
- Object *v = &opts.items[i].value;
- if (strequal("id", k.data)) {
- if (v->type != kObjectTypeInteger || v->data.integer <= 0) {
- api_set_error(err, kErrorTypeValidation,
- "id is not a positive integer");
- goto error;
- }
+ if (opts->virt_text.type == kObjectTypeArray) {
+ decor.virt_text = parse_virt_text(opts->virt_text.data.array, err,
+ &decor.virt_text_width);
+ if (ERROR_SET(err)) {
+ goto error;
+ }
+ } else if (HAS_KEY(opts->virt_text)) {
+ api_set_error(err, kErrorTypeValidation, "virt_text is not an Array");
+ goto error;
+ }
+
+ if (opts->virt_text_pos.type == kObjectTypeString) {
+ String str = opts->virt_text_pos.data.string;
+ if (strequal("eol", str.data)) {
+ decor.virt_text_pos = kVTEndOfLine;
+ } else if (strequal("overlay", str.data)) {
+ decor.virt_text_pos = kVTOverlay;
+ } else if (strequal("right_align", str.data)) {
+ decor.virt_text_pos = kVTRightAlign;
+ } else {
+ api_set_error(err, kErrorTypeValidation, "virt_text_pos: invalid value");
+ goto error;
+ }
+ } else if (HAS_KEY(opts->virt_text_pos)) {
+ api_set_error(err, kErrorTypeValidation, "virt_text_pos is not a String");
+ goto error;
+ }
- id = (uint64_t)v->data.integer;
- } else if (strequal("end_line", k.data)) {
- if (v->type != kObjectTypeInteger) {
- api_set_error(err, kErrorTypeValidation,
- "end_line is not an integer");
- goto error;
- }
- if (v->data.integer < 0 || v->data.integer > buf->b_ml.ml_line_count) {
- api_set_error(err, kErrorTypeValidation,
- "end_line value outside range");
- goto error;
- }
+ if (opts->virt_text_win_col.type == kObjectTypeInteger) {
+ decor.col = (int)opts->virt_text_win_col.data.integer;
+ decor.virt_text_pos = kVTWinCol;
+ } else if (HAS_KEY(opts->virt_text_win_col)) {
+ api_set_error(err, kErrorTypeValidation,
+ "virt_text_win_col is not a Number of the correct size");
+ goto error;
+ }
- line2 = (int)v->data.integer;
- } else if (strequal("end_col", k.data)) {
- if (v->type != kObjectTypeInteger) {
- api_set_error(err, kErrorTypeValidation,
- "end_col is not an integer");
- goto error;
- }
- if (v->data.integer < 0 || v->data.integer > MAXCOL) {
- api_set_error(err, kErrorTypeValidation,
- "end_col value outside range");
- goto error;
- }
+#define OPTION_TO_BOOL(target, name, val) \
+ target = api_object_to_bool(opts-> name, #name, val, err); \
+ if (ERROR_SET(err)) { \
+ goto error; \
+ }
- col2 = (colnr_T)v->data.integer;
- } else if (strequal("hl_group", k.data)) {
- String hl_group;
- switch (v->type) {
- case kObjectTypeString:
- hl_group = v->data.string;
- decor.hl_id = syn_check_group((char_u *)(hl_group.data),
- (int)hl_group.size);
- break;
- case kObjectTypeInteger:
- decor.hl_id = (int)v->data.integer;
- break;
- default:
- api_set_error(err, kErrorTypeValidation,
- "hl_group is not valid.");
- goto error;
- }
- } else if (strequal("virt_text", k.data)) {
- if (v->type != kObjectTypeArray) {
- api_set_error(err, kErrorTypeValidation,
- "virt_text is not an Array");
- goto error;
- }
- decor.virt_text = parse_virt_text(v->data.array, err,
- &decor.virt_text_width);
- if (ERROR_SET(err)) {
- goto error;
- }
- } else if (strequal("virt_text_pos", k.data)) {
- if (v->type != kObjectTypeString) {
- api_set_error(err, kErrorTypeValidation,
- "virt_text_pos is not a String");
- goto error;
- }
- String str = v->data.string;
- if (strequal("eol", str.data)) {
- decor.virt_text_pos = kVTEndOfLine;
- } else if (strequal("overlay", str.data)) {
- decor.virt_text_pos = kVTOverlay;
- } else if (strequal("right_align", str.data)) {
- decor.virt_text_pos = kVTRightAlign;
- } else {
- api_set_error(err, kErrorTypeValidation,
- "virt_text_pos: invalid value");
- goto error;
- }
- } else if (strequal("virt_text_win_col", k.data)) {
- if (v->type != kObjectTypeInteger) {
- api_set_error(err, kErrorTypeValidation,
- "virt_text_win_col is not a Number of the correct size");
- goto error;
- }
+ OPTION_TO_BOOL(decor.virt_text_hide, virt_text_hide, false);
+ OPTION_TO_BOOL(decor.hl_eol, hl_eol, false);
+
+ if (opts->hl_mode.type == kObjectTypeString) {
+ String str = opts->hl_mode.data.string;
+ if (strequal("replace", str.data)) {
+ decor.hl_mode = kHlModeReplace;
+ } else if (strequal("combine", str.data)) {
+ decor.hl_mode = kHlModeCombine;
+ } else if (strequal("blend", str.data)) {
+ decor.hl_mode = kHlModeBlend;
+ } else {
+ api_set_error(err, kErrorTypeValidation,
+ "virt_text_pos: invalid value");
+ goto error;
+ }
+ } else if (HAS_KEY(opts->hl_mode)) {
+ api_set_error(err, kErrorTypeValidation, "hl_mode is not a String");
+ goto error;
+ }
- decor.col = (int)v->data.integer;
- decor.virt_text_pos = kVTWinCol;
- } else if (strequal("virt_text_hide", k.data)) {
- decor.virt_text_hide = api_object_to_bool(*v,
- "virt_text_hide", false, err);
- if (ERROR_SET(err)) {
- goto error;
- }
- } else if (strequal("virt_lines", k.data)) {
- if (v->type != kObjectTypeArray) {
- api_set_error(err, kErrorTypeValidation,
- "virt_lines is not an Array");
- goto error;
- }
- Array a = v->data.array;
- for (size_t j = 0; j < a.size; j++) {
- if (a.items[j].type != kObjectTypeArray) {
- api_set_error(err, kErrorTypeValidation,
- "virt_text_line item is not an Array");
- goto error;
- }
- int dummig;
- VirtText jtem = parse_virt_text(a.items[j].data.array, err, &dummig);
- kv_push(virt_lines, jtem);
- if (ERROR_SET(err)) {
- goto error;
- }
- }
- } else if (strequal("virt_lines_above", k.data)) {
- virt_lines_above = api_object_to_bool(*v, "virt_lines_above", false, err);
- if (ERROR_SET(err)) {
- goto error;
- }
- } else if (strequal("virt_lines_leftcol", k.data)) {
- virt_lines_leftcol = api_object_to_bool(*v, "virt_lines_leftcol", false, err);
- if (ERROR_SET(err)) {
- goto error;
- }
- } else if (strequal("hl_eol", k.data)) {
- decor.hl_eol = api_object_to_bool(*v, "hl_eol", false, err);
- if (ERROR_SET(err)) {
- goto error;
- }
- } else if (strequal("hl_mode", k.data)) {
- if (v->type != kObjectTypeString) {
- api_set_error(err, kErrorTypeValidation,
- "hl_mode is not a String");
- goto error;
- }
- String str = v->data.string;
- if (strequal("replace", str.data)) {
- decor.hl_mode = kHlModeReplace;
- } else if (strequal("combine", str.data)) {
- decor.hl_mode = kHlModeCombine;
- } else if (strequal("blend", str.data)) {
- decor.hl_mode = kHlModeBlend;
- } else {
- api_set_error(err, kErrorTypeValidation,
- "virt_text_pos: invalid value");
+ VirtLines virt_lines = KV_INITIAL_VALUE;
+ bool virt_lines_above = false;
+ bool virt_lines_leftcol = false;
+
+ if (opts->virt_lines.type == kObjectTypeArray) {
+ Array a = opts->virt_lines.data.array;
+ for (size_t j = 0; j < a.size; j++) {
+ if (a.items[j].type != kObjectTypeArray) {
+ api_set_error(err, kErrorTypeValidation, "virt_text_line item is not an Array");
goto error;
}
- } else if (strequal("ephemeral", k.data)) {
- ephemeral = api_object_to_bool(*v, "ephemeral", false, err);
+ int dummig;
+ VirtText jtem = parse_virt_text(a.items[j].data.array, err, &dummig);
+ kv_push(virt_lines, jtem);
if (ERROR_SET(err)) {
goto error;
}
- } else if (strequal("priority", k.data)) {
- if (v->type != kObjectTypeInteger) {
- api_set_error(err, kErrorTypeValidation,
- "priority is not a Number of the correct size");
- goto error;
- }
+ }
+ } else if (HAS_KEY(opts->virt_lines)) {
+ api_set_error(err, kErrorTypeValidation, "virt_lines is not an Array");
+ goto error;
+ }
- if (v->data.integer < 0 || v->data.integer > UINT16_MAX) {
- api_set_error(err, kErrorTypeValidation,
- "priority is not a valid value");
- goto error;
- }
- decor.priority = (DecorPriority)v->data.integer;
- } else if (strequal("right_gravity", k.data)) {
- if (v->type != kObjectTypeBoolean) {
- api_set_error(err, kErrorTypeValidation,
- "right_gravity must be a boolean");
- goto error;
- }
- right_gravity = v->data.boolean;
- } else if (strequal("end_right_gravity", k.data)) {
- if (v->type != kObjectTypeBoolean) {
- api_set_error(err, kErrorTypeValidation,
- "end_right_gravity must be a boolean");
- goto error;
- }
- end_right_gravity = v->data.boolean;
- end_gravity_set = true;
- } else {
- api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data);
+ OPTION_TO_BOOL(virt_lines_above, virt_lines_above, false);
+ OPTION_TO_BOOL(virt_lines_leftcol, virt_lines_leftcol, false);
+
+ if (opts->priority.type == kObjectTypeInteger) {
+ Integer val = opts->priority.data.integer;
+
+ if (val < 0 || val > UINT16_MAX) {
+ api_set_error(err, kErrorTypeValidation, "priority is not a valid value");
goto error;
}
+ decor.priority = (DecorPriority)val;
+ } else if (HAS_KEY(opts->priority)) {
+ api_set_error(err, kErrorTypeValidation, "priority is not a Number of the correct size");
+ goto error;
+ }
+
+ bool right_gravity = true;
+ OPTION_TO_BOOL(right_gravity, right_gravity, true);
+
+ // Only error out if they try to set end_right_gravity without
+ // setting end_col or end_line
+ if (line2 == -1 && col2 == -1 && HAS_KEY(opts->end_right_gravity)) {
+ api_set_error(err, kErrorTypeValidation,
+ "cannot set end_right_gravity without setting end_line or end_col");
+ goto error;
}
+ bool end_right_gravity = false;
+ OPTION_TO_BOOL(end_right_gravity, end_right_gravity, false);
+
size_t len = 0;
+
+ bool ephemeral = false;
+ OPTION_TO_BOOL(ephemeral, ephemeral, false);
+
if (line < 0 || line > buf->b_ml.ml_line_count) {
api_set_error(err, kErrorTypeValidation, "line value outside range");
return 0;
@@ -1717,15 +1753,6 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
return 0;
}
-
- // Only error out if they try to set end_right_gravity without
- // setting end_col or end_line
- if (line2 == -1 && col2 == -1 && end_gravity_set) {
- api_set_error(err, kErrorTypeValidation,
- "cannot set end_right_gravity "
- "without setting end_line or end_col");
- }
-
if (col2 >= 0) {
if (line2 >= 0 && line2 < buf->b_ml.ml_line_count) {
len = ephemeral ? MAXCOL : STRLEN(ml_get_buf(buf, (linenr_T)line2 + 1, false));
@@ -1744,15 +1771,6 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
col2 = 0;
}
- if (decor.virt_text_pos == kVTRightAlign) {
- decor.col = 0;
- for (size_t i = 0; i < kv_size(decor.virt_text); i++) {
- decor.col
- += (int)mb_string2cells((char_u *)kv_A(decor.virt_text, i).text);
- }
- }
-
-
Decoration *d = NULL;
if (ephemeral) {
diff --git a/src/nvim/api/deprecated.c b/src/nvim/api/deprecated.c
index 332fc0ba96..907d09e5b7 100644
--- a/src/nvim/api/deprecated.c
+++ b/src/nvim/api/deprecated.c
@@ -165,6 +165,7 @@ Integer nvim_buf_set_virtual_text(Buffer buffer, Integer src_id, Integer line, A
/// @param lines Array of lines
/// @param[out] err Error details, if any
void buffer_insert(Buffer buffer, Integer lnum, ArrayOf(String) lines, Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
// "lnum" will be the index of the line after inserting,
// no matter if it is negative or not
@@ -184,6 +185,7 @@ void buffer_insert(Buffer buffer, Integer lnum, ArrayOf(String) lines, Error *er
/// @param[out] err Error details, if any
/// @return Line string
String buffer_get_line(Buffer buffer, Integer index, Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
String rv = { .size = 0 };
@@ -212,6 +214,7 @@ String buffer_get_line(Buffer buffer, Integer index, Error *err)
/// @param line Contents of the new line
/// @param[out] err Error details, if any
void buffer_set_line(Buffer buffer, Integer index, String line, Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
Object l = STRING_OBJ(line);
Array array = { .items = &l, .size = 1 };
@@ -230,6 +233,7 @@ void buffer_set_line(Buffer buffer, Integer index, String line, Error *err)
/// @param index line index
/// @param[out] err Error details, if any
void buffer_del_line(Buffer buffer, Integer index, Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
Array array = ARRAY_DICT_INIT;
index = convert_index(index);
@@ -255,6 +259,7 @@ ArrayOf(String) buffer_get_line_slice(Buffer buffer,
Boolean include_start,
Boolean include_end,
Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
start = convert_index(start) + !include_start;
end = convert_index(end) + include_end;
@@ -278,6 +283,7 @@ ArrayOf(String) buffer_get_line_slice(Buffer buffer,
/// @param[out] err Error details, if any
void buffer_set_line_slice(Buffer buffer, Integer start, Integer end, Boolean include_start,
Boolean include_end, ArrayOf(String) replacement, Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
start = convert_index(start) + !include_start;
end = convert_index(end) + include_end;
@@ -298,6 +304,7 @@ void buffer_set_line_slice(Buffer buffer, Integer start, Integer end, Boolean in
/// @warning It may return nil if there was no previous value
/// or if previous value was `v:null`.
Object buffer_set_var(Buffer buffer, String name, Object value, Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -317,6 +324,7 @@ Object buffer_set_var(Buffer buffer, String name, Object value, Error *err)
/// @param[out] err Error details, if any
/// @return Old value
Object buffer_del_var(Buffer buffer, String name, Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -340,6 +348,7 @@ Object buffer_del_var(Buffer buffer, String name, Error *err)
/// @warning It may return nil if there was no previous value
/// or if previous value was `v:null`.
Object window_set_var(Window window, String name, Object value, Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
win_T *win = find_window_by_handle(window, err);
@@ -359,6 +368,7 @@ Object window_set_var(Window window, String name, Object value, Error *err)
/// @param[out] err Error details, if any
/// @return Old value
Object window_del_var(Window window, String name, Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
win_T *win = find_window_by_handle(window, err);
@@ -382,6 +392,7 @@ Object window_del_var(Window window, String name, Error *err)
/// @warning It may return nil if there was no previous value
/// or if previous value was `v:null`.
Object tabpage_set_var(Tabpage tabpage, String name, Object value, Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
tabpage_T *tab = find_tab_by_handle(tabpage, err);
@@ -401,6 +412,7 @@ Object tabpage_set_var(Tabpage tabpage, String name, Object value, Error *err)
/// @param[out] err Error details, if any
/// @return Old value
Object tabpage_del_var(Tabpage tabpage, String name, Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
tabpage_T *tab = find_tab_by_handle(tabpage, err);
@@ -417,6 +429,7 @@ Object tabpage_del_var(Tabpage tabpage, String name, Error *err)
/// OR if previous value was `v:null`.
/// @return Old value or nil if there was no previous value.
Object vim_set_var(String name, Object value, Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
return dict_set_var(&globvardict, name, value, false, true, err);
}
@@ -424,6 +437,7 @@ Object vim_set_var(String name, Object value, Error *err)
/// @deprecated
/// @see nvim_del_var
Object vim_del_var(String name, Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
return dict_set_var(&globvardict, name, NIL, true, true, err);
}
diff --git a/src/nvim/api/keysets.lua b/src/nvim/api/keysets.lua
new file mode 100644
index 0000000000..76ce9e15ea
--- /dev/null
+++ b/src/nvim/api/keysets.lua
@@ -0,0 +1,52 @@
+return {
+ context = {
+ "types";
+ };
+ set_extmark = {
+ "id";
+ "end_line";
+ "end_col";
+ "hl_group";
+ "virt_text";
+ "virt_text_pos";
+ "virt_text_win_col";
+ "virt_text_hide";
+ "hl_eol";
+ "hl_mode";
+ "ephemeral";
+ "priority";
+ "right_gravity";
+ "end_right_gravity";
+ "virt_lines";
+ "virt_lines_above";
+ "virt_lines_leftcol";
+ };
+ keymap = {
+ "noremap";
+ "nowait";
+ "silent";
+ "script";
+ "expr";
+ "unique";
+ };
+ get_commands = {
+ "builtin";
+ };
+ float_config = {
+ "row";
+ "col";
+ "width";
+ "height";
+ "anchor";
+ "relative";
+ "win";
+ "bufpos";
+ "external";
+ "focusable";
+ "zindex";
+ "border";
+ "style";
+ "noautocmd";
+ };
+}
+
diff --git a/src/nvim/api/private/defs.h b/src/nvim/api/private/defs.h
index f0d48bf145..8346e01558 100644
--- a/src/nvim/api/private/defs.h
+++ b/src/nvim/api/private/defs.h
@@ -19,6 +19,7 @@
#ifdef INCLUDE_GENERATED_DECLARATIONS
# define ArrayOf(...) Array
# define DictionaryOf(...) Dictionary
+# define Dict(name) KeyDict_##name
#endif
// Basic types
@@ -129,5 +130,14 @@ struct key_value_pair {
Object value;
};
+typedef Object *(*field_hash)(void *retval, const char *str, size_t len);
+typedef struct {
+ char *str;
+ size_t ptr_off;
+} KeySetLink;
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "keysets_defs.generated.h"
+#endif
#endif // NVIM_API_PRIVATE_DEFS_H
diff --git a/src/nvim/api/private/dispatch.c b/src/nvim/api/private/dispatch.c
index 5e93ccce17..ee0cdc4c07 100644
--- a/src/nvim/api/private/dispatch.c
+++ b/src/nvim/api/private/dispatch.c
@@ -15,6 +15,7 @@
#include "nvim/api/ui.h"
#include "nvim/api/vim.h"
#include "nvim/api/window.h"
+#include "nvim/api/win_config.h"
#include "nvim/log.h"
#include "nvim/map.h"
#include "nvim/msgpack_rpc/helpers.h"
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index 193f1dd572..46ef41cc38 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -6,6 +6,7 @@
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
+#include <stddef.h>
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
@@ -24,6 +25,7 @@
#include "nvim/lua/executor.h"
#include "nvim/map.h"
#include "nvim/map_defs.h"
+#include "nvim/mark.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/msgpack_rpc/helpers.h"
@@ -395,7 +397,7 @@ void set_option_to(uint64_t channel_id, void *to, int type, String name, Object
return;
}
- stringval = (char *)value.data.string.data;
+ stringval = value.data.string.data;
}
const sctx_T save_current_sctx = current_sctx;
@@ -814,7 +816,7 @@ Array string_to_array(const String input, bool crlf)
/// buffer, or -1 to signify global behavior ("all buffers")
/// @param is_unmap When true, removes the mapping that matches {lhs}.
void modify_keymap(Buffer buffer, bool is_unmap, String mode, String lhs, String rhs,
- Dictionary opts, Error *err)
+ Dict(keymap) *opts, Error *err)
{
char *err_msg = NULL; // the error message to report, if any
char *err_arg = NULL; // argument for the error message format string
@@ -833,10 +835,21 @@ void modify_keymap(Buffer buffer, bool is_unmap, String mode, String lhs, String
return;
}
- MapArguments parsed_args;
- memset(&parsed_args, 0, sizeof(parsed_args));
- if (parse_keymap_opts(opts, &parsed_args, err)) {
- goto fail_and_free;
+ MapArguments parsed_args = MAP_ARGUMENTS_INIT;
+ if (opts) {
+#define KEY_TO_BOOL(name) \
+ parsed_args. name = api_object_to_bool(opts-> name, #name, false, err); \
+ if (ERROR_SET(err)) { \
+ goto fail_and_free; \
+ }
+
+ KEY_TO_BOOL(nowait);
+ KEY_TO_BOOL(noremap);
+ KEY_TO_BOOL(silent);
+ KEY_TO_BOOL(script);
+ KEY_TO_BOOL(expr);
+ KEY_TO_BOOL(unique);
+#undef KEY_TO_BOOL
}
parsed_args.buffer = !global;
@@ -947,95 +960,6 @@ fail_and_free:
return;
}
-/// Read in the given opts, setting corresponding flags in `out`.
-///
-/// @param opts A dictionary passed to @ref nvim_set_keymap or
-/// @ref nvim_buf_set_keymap.
-/// @param[out] out MapArguments object in which to set parsed
-/// |:map-arguments| flags.
-/// @param[out] err Error details, if any.
-///
-/// @returns Zero on success, nonzero on failure.
-Integer parse_keymap_opts(Dictionary opts, MapArguments *out, Error *err)
-{
- char *err_msg = NULL; // the error message to report, if any
- char *err_arg = NULL; // argument for the error message format string
- ErrorType err_type = kErrorTypeNone;
-
- out->buffer = false;
- out->nowait = false;
- out->silent = false;
- out->script = false;
- out->expr = false;
- out->unique = false;
-
- for (size_t i = 0; i < opts.size; i++) {
- KeyValuePair *key_and_val = &opts.items[i];
- char *optname = key_and_val->key.data;
-
- if (key_and_val->value.type != kObjectTypeBoolean) {
- err_msg = "Gave non-boolean value for an opt: %s";
- err_arg = optname;
- err_type = kErrorTypeValidation;
- goto fail_with_message;
- }
-
- bool was_valid_opt = false;
- switch (optname[0]) {
- // note: strncmp up to and including the null terminator, so that
- // "nowaitFoobar" won't match against "nowait"
-
- // don't recognize 'buffer' as a key; user shouldn't provide <buffer>
- // when calling nvim_set_keymap or nvim_buf_set_keymap, since it can be
- // inferred from which function they called
- case 'n':
- if (STRNCMP(optname, "noremap", 8) == 0) {
- was_valid_opt = true;
- out->noremap = key_and_val->value.data.boolean;
- } else if (STRNCMP(optname, "nowait", 7) == 0) {
- was_valid_opt = true;
- out->nowait = key_and_val->value.data.boolean;
- }
- break;
- case 's':
- if (STRNCMP(optname, "silent", 7) == 0) {
- was_valid_opt = true;
- out->silent = key_and_val->value.data.boolean;
- } else if (STRNCMP(optname, "script", 7) == 0) {
- was_valid_opt = true;
- out->script = key_and_val->value.data.boolean;
- }
- break;
- case 'e':
- if (STRNCMP(optname, "expr", 5) == 0) {
- was_valid_opt = true;
- out->expr = key_and_val->value.data.boolean;
- }
- break;
- case 'u':
- if (STRNCMP(optname, "unique", 7) == 0) {
- was_valid_opt = true;
- out->unique = key_and_val->value.data.boolean;
- }
- break;
- default:
- break;
- } // switch
- if (!was_valid_opt) {
- err_msg = "Invalid key: %s";
- err_arg = optname;
- err_type = kErrorTypeValidation;
- goto fail_with_message;
- }
- } // for
-
- return 0;
-
-fail_with_message:
- api_set_error(err, err_type, err_msg, err_arg);
- return 1;
-}
-
/// Collects `n` buffer lines into array `l`, optionally replacing newlines
/// with NUL.
///
@@ -1725,367 +1649,65 @@ const char *describe_ns(NS ns_id)
return "(UNKNOWN PLUGIN)";
}
-static bool parse_float_anchor(String anchor, FloatAnchor *out)
+bool api_dict_to_keydict(void *rv, field_hash hashy, Dictionary dict, Error *err)
{
- if (anchor.size == 0) {
- *out = (FloatAnchor)0;
- }
- char *str = anchor.data;
- if (striequal(str, "NW")) {
- *out = 0; // NW is the default
- } else if (striequal(str, "NE")) {
- *out = kFloatAnchorEast;
- } else if (striequal(str, "SW")) {
- *out = kFloatAnchorSouth;
- } else if (striequal(str, "SE")) {
- *out = kFloatAnchorSouth | kFloatAnchorEast;
- } else {
- return false;
- }
- return true;
-}
+ for (size_t i = 0; i < dict.size; i++) {
+ String k = dict.items[i].key;
+ Object *field = hashy(rv, k.data, k.size);
+ if (!field) {
+ api_set_error(err, kErrorTypeValidation, "Invalid key: '%.*s'", (int)k.size, k.data);
+ return false;
+ }
-static bool parse_float_relative(String relative, FloatRelative *out)
-{
- char *str = relative.data;
- if (striequal(str, "editor")) {
- *out = kFloatRelativeEditor;
- } else if (striequal(str, "win")) {
- *out = kFloatRelativeWindow;
- } else if (striequal(str, "cursor")) {
- *out = kFloatRelativeCursor;
- } else {
- return false;
+ *field = dict.items[i].value;
}
+
return true;
}
-static bool parse_float_bufpos(Array bufpos, lpos_T *out)
+void api_free_keydict(void *dict, KeySetLink *table)
{
- if (bufpos.size != 2
- || bufpos.items[0].type != kObjectTypeInteger
- || bufpos.items[1].type != kObjectTypeInteger) {
- return false;
+ for (size_t i = 0; table[i].str; i++) {
+ api_free_object(*(Object *)((char *)dict + table[i].ptr_off));
}
- out->lnum = bufpos.items[0].data.integer;
- out->col = (colnr_T)bufpos.items[1].data.integer;
- return true;
}
-static void parse_border_style(Object style, FloatConfig *fconfig, Error *err)
+/// Set a named mark
+/// buffer and mark name must be validated already
+/// @param buffer Buffer to set the mark on
+/// @param name Mark name
+/// @param line Line number
+/// @param col Column/row number
+/// @return true if the mark was set, else false
+bool set_mark(buf_T *buf, String name, Integer line, Integer col, Error *err)
{
- struct {
- const char *name;
- schar_T chars[8];
- bool shadow_color;
- } defaults[] = {
- { "double", { "╔", "═", "╗", "║", "╝", "═", "╚", "║" }, false },
- { "single", { "┌", "─", "┐", "│", "┘", "─", "└", "│" }, false },
- { "shadow", { "", "", " ", " ", " ", " ", " ", "" }, true },
- { "rounded", { "╭", "─", "╮", "│", "╯", "─", "╰", "│" }, false },
- { "solid", { " ", " ", " ", " ", " ", " ", " ", " " }, false },
- { NULL, { { NUL } }, false },
- };
-
- schar_T *chars = fconfig->border_chars;
- int *hl_ids = fconfig->border_hl_ids;
-
- fconfig->border = true;
-
- if (style.type == kObjectTypeArray) {
- Array arr = style.data.array;
- size_t size = arr.size;
- if (!size || size > 8 || (size & (size-1))) {
- api_set_error(err, kErrorTypeValidation,
- "invalid number of border chars");
- return;
- }
- for (size_t i = 0; i < size; i++) {
- Object iytem = arr.items[i];
- String string;
- int hl_id = 0;
- if (iytem.type == kObjectTypeArray) {
- Array iarr = iytem.data.array;
- if (!iarr.size || iarr.size > 2) {
- api_set_error(err, kErrorTypeValidation, "invalid border char");
- return;
- }
- if (iarr.items[0].type != kObjectTypeString) {
- api_set_error(err, kErrorTypeValidation, "invalid border char");
- return;
- }
- string = iarr.items[0].data.string;
- if (iarr.size == 2) {
- hl_id = object_to_hl_id(iarr.items[1], "border char highlight", err);
- if (ERROR_SET(err)) {
- return;
- }
- }
- } else if (iytem.type == kObjectTypeString) {
- string = iytem.data.string;
- } else {
- api_set_error(err, kErrorTypeValidation, "invalid border char");
- return;
- }
- if (string.size
- && mb_string2cells_len((char_u *)string.data, string.size) > 1) {
- api_set_error(err, kErrorTypeValidation,
- "border chars must be one cell");
- return;
- }
- size_t len = MIN(string.size, sizeof(*chars)-1);
- if (len) {
- memcpy(chars[i], string.data, len);
- }
- chars[i][len] = NUL;
- hl_ids[i] = hl_id;
- }
- while (size < 8) {
- memcpy(chars+size, chars, sizeof(*chars) * size);
- memcpy(hl_ids+size, hl_ids, sizeof(*hl_ids) * size);
- size <<= 1;
- }
- if ((chars[7][0] && chars[1][0] && !chars[0][0])
- || (chars[1][0] && chars[3][0] && !chars[2][0])
- || (chars[3][0] && chars[5][0] && !chars[4][0])
- || (chars[5][0] && chars[7][0] && !chars[6][0])) {
- api_set_error(err, kErrorTypeValidation,
- "corner between used edges must be specified");
- }
- } else if (style.type == kObjectTypeString) {
- String str = style.data.string;
- if (str.size == 0 || strequal(str.data, "none")) {
- fconfig->border = false;
- return;
+ buf = buf == NULL ? curbuf : buf;
+ // If line == 0 the marks is being deleted
+ bool res = false;
+ bool deleting = false;
+ if (line == 0) {
+ col = 0;
+ deleting = true;
+ } else {
+ if (col > MAXCOL) {
+ api_set_error(err, kErrorTypeValidation, "Column value outside range");
+ return res;
}
- for (size_t i = 0; defaults[i].name; i++) {
- if (strequal(str.data, defaults[i].name)) {
- memcpy(chars, defaults[i].chars, sizeof(defaults[i].chars));
- memset(hl_ids, 0, 8 * sizeof(*hl_ids));
- if (defaults[i].shadow_color) {
- int hl_blend = SYN_GROUP_STATIC("FloatShadow");
- int hl_through = SYN_GROUP_STATIC("FloatShadowThrough");
- hl_ids[2] = hl_through;
- hl_ids[3] = hl_blend;
- hl_ids[4] = hl_blend;
- hl_ids[5] = hl_blend;
- hl_ids[6] = hl_through;
- }
- return;
- }
+ if (line < 1 || line > buf->b_ml.ml_line_count) {
+ api_set_error(err, kErrorTypeValidation, "Line value outside range");
+ return res;
}
- api_set_error(err, kErrorTypeValidation,
- "invalid border style \"%s\"", str.data);
}
-}
-
-bool parse_float_config(Dictionary config, FloatConfig *fconfig, bool reconf, bool new_win,
- Error *err)
-{
- // TODO(bfredl): use a get/has_key interface instead and get rid of extra
- // flags
- bool has_row = false, has_col = false, has_relative = false;
- bool has_external = false, has_window = false;
- bool has_width = false, has_height = false;
- bool has_bufpos = false;
-
- for (size_t i = 0; i < config.size; i++) {
- char *key = config.items[i].key.data;
- Object val = config.items[i].value;
- if (!strcmp(key, "row")) {
- has_row = true;
- if (val.type == kObjectTypeInteger) {
- fconfig->row = (double)val.data.integer;
- } else if (val.type == kObjectTypeFloat) {
- fconfig->row = val.data.floating;
- } else {
- api_set_error(err, kErrorTypeValidation,
- "'row' key must be Integer or Float");
- return false;
- }
- } else if (!strcmp(key, "col")) {
- has_col = true;
- if (val.type == kObjectTypeInteger) {
- fconfig->col = (double)val.data.integer;
- } else if (val.type == kObjectTypeFloat) {
- fconfig->col = val.data.floating;
- } else {
- api_set_error(err, kErrorTypeValidation,
- "'col' key must be Integer or Float");
- return false;
- }
- } else if (strequal(key, "width")) {
- has_width = true;
- if (val.type == kObjectTypeInteger && val.data.integer > 0) {
- fconfig->width = (int)val.data.integer;
- } else {
- api_set_error(err, kErrorTypeValidation,
- "'width' key must be a positive Integer");
- return false;
- }
- } else if (strequal(key, "height")) {
- has_height = true;
- if (val.type == kObjectTypeInteger && val.data.integer > 0) {
- fconfig->height = (int)val.data.integer;
- } else {
- api_set_error(err, kErrorTypeValidation,
- "'height' key must be a positive Integer");
- return false;
- }
- } else if (!strcmp(key, "anchor")) {
- if (val.type != kObjectTypeString) {
- api_set_error(err, kErrorTypeValidation,
- "'anchor' key must be String");
- return false;
- }
- if (!parse_float_anchor(val.data.string, &fconfig->anchor)) {
- api_set_error(err, kErrorTypeValidation,
- "Invalid value of 'anchor' key");
- return false;
- }
- } else if (!strcmp(key, "relative")) {
- if (val.type != kObjectTypeString) {
- api_set_error(err, kErrorTypeValidation,
- "'relative' key must be String");
- return false;
- }
- // ignore empty string, to match nvim_win_get_config
- if (val.data.string.size > 0) {
- has_relative = true;
- if (!parse_float_relative(val.data.string, &fconfig->relative)) {
- api_set_error(err, kErrorTypeValidation,
- "Invalid value of 'relative' key");
- return false;
- }
- }
- } else if (!strcmp(key, "win")) {
- has_window = true;
- if (val.type != kObjectTypeInteger
- && val.type != kObjectTypeWindow) {
- api_set_error(err, kErrorTypeValidation,
- "'win' key must be Integer or Window");
- return false;
- }
- fconfig->window = (Window)val.data.integer;
- } else if (!strcmp(key, "bufpos")) {
- if (val.type != kObjectTypeArray) {
- api_set_error(err, kErrorTypeValidation,
- "'bufpos' key must be Array");
- return false;
- }
- if (!parse_float_bufpos(val.data.array, &fconfig->bufpos)) {
- api_set_error(err, kErrorTypeValidation,
- "Invalid value of 'bufpos' key");
- return false;
- }
- has_bufpos = true;
- } else if (!strcmp(key, "external")) {
- has_external = fconfig->external
- = api_object_to_bool(val, "'external' key", false, err);
- if (ERROR_SET(err)) {
- return false;
- }
- } else if (!strcmp(key, "focusable")) {
- fconfig->focusable
- = api_object_to_bool(val, "'focusable' key", true, err);
- if (ERROR_SET(err)) {
- return false;
- }
- } else if (strequal(key, "zindex")) {
- if (val.type == kObjectTypeInteger && val.data.integer > 0) {
- fconfig->zindex = (int)val.data.integer;
- } else {
- api_set_error(err, kErrorTypeValidation,
- "'zindex' key must be a positive Integer");
- return false;
- }
- } else if (!strcmp(key, "border")) {
- parse_border_style(val, fconfig, err);
- if (ERROR_SET(err)) {
- return false;
- }
- } else if (!strcmp(key, "style")) {
- if (val.type != kObjectTypeString) {
- api_set_error(err, kErrorTypeValidation,
- "'style' key must be String");
- return false;
- }
- if (val.data.string.data[0] == NUL) {
- fconfig->style = kWinStyleUnused;
- } else if (striequal(val.data.string.data, "minimal")) {
- fconfig->style = kWinStyleMinimal;
- } else {
- api_set_error(err, kErrorTypeValidation,
- "Invalid value of 'style' key");
- }
- } else if (strequal(key, "noautocmd") && new_win) {
- fconfig->noautocmd
- = api_object_to_bool(val, "'noautocmd' key", false, err);
- if (ERROR_SET(err)) {
- return false;
- }
+ pos_T pos = { line, (int)col, (int)col };
+ res = setmark_pos(*name.data, &pos, buf->handle);
+ if (!res) {
+ if (deleting) {
+ api_set_error(err, kErrorTypeException,
+ "Failed to delete named mark: %c", *name.data);
} else {
- api_set_error(err, kErrorTypeValidation,
- "Invalid key '%s'", key);
- return false;
- }
- }
-
- if (has_window && !(has_relative
- && fconfig->relative == kFloatRelativeWindow)) {
- api_set_error(err, kErrorTypeValidation,
- "'win' key is only valid with relative='win'");
- return false;
- }
-
- if ((has_relative && fconfig->relative == kFloatRelativeWindow)
- && (!has_window || fconfig->window == 0)) {
- fconfig->window = curwin->handle;
- }
-
- if (has_window && !has_bufpos) {
- fconfig->bufpos.lnum = -1;
- }
-
- if (has_bufpos) {
- if (!has_row) {
- fconfig->row = (fconfig->anchor & kFloatAnchorSouth) ? 0 : 1;
- has_row = true;
- }
- if (!has_col) {
- fconfig->col = 0;
- has_col = true;
+ api_set_error(err, kErrorTypeException,
+ "Failed to set named mark: %c", *name.data);
}
}
-
- if (has_relative && has_external) {
- api_set_error(err, kErrorTypeValidation,
- "Only one of 'relative' and 'external' must be used");
- return false;
- } else if (!reconf && !has_relative && !has_external) {
- api_set_error(err, kErrorTypeValidation,
- "One of 'relative' and 'external' must be used");
- return false;
- } else if (has_relative) {
- fconfig->external = false;
- }
-
- if (!reconf && !(has_height && has_width)) {
- api_set_error(err, kErrorTypeValidation,
- "Must specify 'width' and 'height'");
- return false;
- }
-
- if (fconfig->external && !ui_has(kUIMultigrid)) {
- api_set_error(err, kErrorTypeValidation,
- "UI doesn't support external windows");
- return false;
- }
-
- if (has_relative != has_row || has_row != has_col) {
- api_set_error(err, kErrorTypeValidation,
- "'relative' requires 'row'/'col' or 'bufpos'");
- return false;
- }
- return true;
+ return res;
}
diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h
index ecce6afa26..2cdd80bffe 100644
--- a/src/nvim/api/private/helpers.h
+++ b/src/nvim/api/private/helpers.h
@@ -59,6 +59,9 @@
#define NIL ((Object)OBJECT_INIT)
#define NULL_STRING ((String)STRING_INIT)
+// currently treat key=vim.NIL as if the key was missing
+#define HAS_KEY(o) ((o).type != kObjectTypeNil)
+
#define PUT(dict, k, v) \
kv_push(dict, ((KeyValuePair) { .key = cstr_to_string(k), .value = v }))
@@ -138,6 +141,9 @@ typedef struct {
} while (0)
#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "keysets.h.generated.h"
# include "api/private/helpers.h.generated.h"
#endif
+
+
#endif // NVIM_API_PRIVATE_HELPERS_H
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c
index 9b200dcba2..d86aecc318 100644
--- a/src/nvim/api/ui.c
+++ b/src/nvim/api/ui.c
@@ -40,7 +40,6 @@ typedef struct {
static PMap(uint64_t) connected_uis = MAP_INIT;
void remote_ui_disconnect(uint64_t channel_id)
- FUNC_API_NOEXPORT
{
UI *ui = pmap_get(uint64_t)(&connected_uis, channel_id);
if (!ui) {
@@ -57,7 +56,6 @@ void remote_ui_disconnect(uint64_t channel_id)
/// Wait until ui has connected on stdio channel.
void remote_ui_wait_for_attach(void)
- FUNC_API_NOEXPORT
{
Channel *channel = find_channel(CHAN_STDIO);
if (!channel) {
@@ -172,6 +170,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictiona
/// @deprecated
void ui_attach(uint64_t channel_id, Integer width, Integer height, Boolean enable_rgb, Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
Dictionary opts = ARRAY_DICT_INIT;
PUT(opts, "rgb", BOOLEAN_OBJ(enable_rgb));
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 3be45d0cf7..9b39b18c4e 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -59,7 +59,6 @@
#endif
void api_vim_free_all_mem(void)
- FUNC_API_NOEXPORT
{
String name;
handle_T id;
@@ -264,7 +263,6 @@ void nvim__set_hl_ns(Integer ns_id, Error *err)
}
static void on_redraw_event(void **argv)
- FUNC_API_NOEXPORT
{
redraw_all_later(NOT_VALID);
}
@@ -1221,7 +1219,7 @@ fail:
/// buffer in a configured window before calling this. For instance, for a
/// floating display, first create an empty buffer using |nvim_create_buf()|,
/// then display it using |nvim_open_win()|, and then call this function.
-/// Then |nvim_chan_send()| cal be called immediately to process sequences
+/// Then |nvim_chan_send()| can be called immediately to process sequences
/// in a virtual terminal having the intended size.
///
/// @param buffer the buffer to use (expected to be empty)
@@ -1305,153 +1303,6 @@ void nvim_chan_send(Integer chan, String data, Error *err)
}
}
-/// Open a new window.
-///
-/// Currently this is used to open floating and external windows.
-/// Floats are windows that are drawn above the split layout, at some anchor
-/// position in some other window. Floats can be drawn internally or by external
-/// GUI with the |ui-multigrid| extension. External windows are only supported
-/// with multigrid GUIs, and are displayed as separate top-level windows.
-///
-/// For a general overview of floats, see |api-floatwin|.
-///
-/// Exactly one of `external` and `relative` must be specified. The `width` and
-/// `height` of the new window must be specified.
-///
-/// With relative=editor (row=0,col=0) refers to the top-left corner of the
-/// screen-grid and (row=Lines-1,col=Columns-1) refers to the bottom-right
-/// corner. Fractional values are allowed, but the builtin implementation
-/// (used by non-multigrid UIs) will always round down to nearest integer.
-///
-/// Out-of-bounds values, and configurations that make the float not fit inside
-/// the main editor, are allowed. The builtin implementation truncates values
-/// so floats are fully within the main screen grid. External GUIs
-/// could let floats hover outside of the main window like a tooltip, but
-/// this should not be used to specify arbitrary WM screen positions.
-///
-/// Example (Lua): window-relative float
-/// <pre>
-/// vim.api.nvim_open_win(0, false,
-/// {relative='win', row=3, col=3, width=12, height=3})
-/// </pre>
-///
-/// Example (Lua): buffer-relative float (travels as buffer is scrolled)
-/// <pre>
-/// vim.api.nvim_open_win(0, false,
-/// {relative='win', width=12, height=3, bufpos={100,10}})
-/// </pre>
-///
-/// @param buffer Buffer to display, or 0 for current buffer
-/// @param enter Enter the window (make it the current window)
-/// @param config Map defining the window configuration. Keys:
-/// - `relative`: Sets the window layout to "floating", placed at (row,col)
-/// coordinates relative to:
-/// - "editor" The global editor grid
-/// - "win" Window given by the `win` field, or current window.
-/// - "cursor" Cursor position in current window.
-/// - `win`: |window-ID| for relative="win".
-/// - `anchor`: Decides which corner of the float to place at (row,col):
-/// - "NW" northwest (default)
-/// - "NE" northeast
-/// - "SW" southwest
-/// - "SE" southeast
-/// - `width`: Window width (in character cells). Minimum of 1.
-/// - `height`: Window height (in character cells). Minimum of 1.
-/// - `bufpos`: Places float relative to buffer text (only when
-/// relative="win"). Takes a tuple of zero-indexed [line, column].
-/// `row` and `col` if given are applied relative to this
-/// position, else they default to `row=1` and `col=0`
-/// (thus like a tooltip near the buffer text).
-/// - `row`: Row position in units of "screen cell height", may be fractional.
-/// - `col`: Column position in units of "screen cell width", may be
-/// fractional.
-/// - `focusable`: Enable focus by user actions (wincmds, mouse events).
-/// Defaults to true. Non-focusable windows can be entered by
-/// |nvim_set_current_win()|.
-/// - `external`: GUI should display the window as an external
-/// top-level window. Currently accepts no other positioning
-/// configuration together with this.
-/// - `zindex`: Stacking order. floats with higher `zindex` go on top on
-/// floats with lower indices. Must be larger than zero. The
-/// following screen elements have hard-coded z-indices:
-/// - 100: insert completion popupmenu
-/// - 200: message scrollback
-/// - 250: cmdline completion popupmenu (when wildoptions+=pum)
-/// The default value for floats are 50. In general, values below 100 are
-/// recommended, unless there is a good reason to overshadow builtin
-/// elements.
-/// - `style`: Configure the appearance of the window. Currently only takes
-/// one non-empty value:
-/// - "minimal" Nvim will display the window with many UI options
-/// disabled. This is useful when displaying a temporary
-/// float where the text should not be edited. Disables
-/// 'number', 'relativenumber', 'cursorline', 'cursorcolumn',
-/// 'foldcolumn', 'spell' and 'list' options. 'signcolumn'
-/// is changed to `auto` and 'colorcolumn' is cleared. The
-/// end-of-buffer region is hidden by setting `eob` flag of
-/// 'fillchars' to a space char, and clearing the
-/// |EndOfBuffer| region in 'winhighlight'.
-/// - `border`: Style of (optional) window border. This can either be a string
-/// or an array. The string values are
-/// - "none": No border (default).
-/// - "single": A single line box.
-/// - "double": A double line box.
-/// - "rounded": Like "single", but with rounded corners ("╭" etc.).
-/// - "solid": Adds padding by a single whitespace cell.
-/// - "shadow": A drop shadow effect by blending with the background.
-/// - If it is an array, it should have a length of eight or any divisor of
-/// eight. The array will specifify the eight chars building up the border
-/// in a clockwise fashion starting with the top-left corner. As an
-/// example, the double box style could be specified as
-/// [ "╔", "═" ,"╗", "║", "╝", "═", "╚", "║" ].
-/// If the number of chars are less than eight, they will be repeated. Thus
-/// an ASCII border could be specified as
-/// [ "/", "-", "\\", "|" ],
-/// or all chars the same as
-/// [ "x" ].
-/// An empty string can be used to turn off a specific border, for instance,
-/// [ "", "", "", ">", "", "", "", "<" ]
-/// will only make vertical borders but not horizontal ones.
-/// By default, `FloatBorder` highlight is used, which links to `VertSplit`
-/// when not defined. It could also be specified by character:
-/// [ {"+", "MyCorner"}, {"x", "MyBorder"} ].
-/// - `noautocmd`: If true then no buffer-related autocommand events such as
-/// |BufEnter|, |BufLeave| or |BufWinEnter| may fire from
-/// calling this function.
-///
-/// @param[out] err Error details, if any
-///
-/// @return Window handle, or 0 on error
-Window nvim_open_win(Buffer buffer, Boolean enter, Dictionary config, Error *err)
- FUNC_API_SINCE(6)
- FUNC_API_CHECK_TEXTLOCK
-{
- FloatConfig fconfig = FLOAT_CONFIG_INIT;
- if (!parse_float_config(config, &fconfig, false, true, err)) {
- return 0;
- }
- win_T *wp = win_new_float(NULL, fconfig, err);
- if (!wp) {
- return 0;
- }
- if (enter) {
- win_enter(wp, false);
- }
- if (!win_valid(wp)) {
- api_set_error(err, kErrorTypeException, "Window was closed immediately");
- return 0;
- }
- if (buffer > 0) {
- win_set_buf(wp->handle, buffer, fconfig.noautocmd, err);
- }
-
- if (fconfig.style == kWinStyleMinimal) {
- win_set_minimal_style(wp);
- didset_window_options(wp);
- }
- return wp->handle;
-}
-
/// Gets the current list of tabpage handles.
///
/// @return List of tabpage handles
@@ -1507,7 +1358,7 @@ void nvim_set_current_tabpage(Tabpage tabpage, Error *err)
}
}
-/// Creates a new *namespace*, or gets an existing one.
+/// Creates a new \*namespace\* or gets an existing one.
///
/// Namespaces are used for buffer highlights and virtual text, see
/// |nvim_buf_add_highlight()| and |nvim_buf_set_extmark()|.
@@ -1758,24 +1609,15 @@ Dictionary nvim_get_color_map(void)
/// @param[out] err Error details, if any
///
/// @return map of global |context|.
-Dictionary nvim_get_context(Dictionary opts, Error *err)
+Dictionary nvim_get_context(Dict(context) *opts, Error *err)
FUNC_API_SINCE(6)
{
Array types = ARRAY_DICT_INIT;
- for (size_t i = 0; i < opts.size; i++) {
- String k = opts.items[i].key;
- Object v = opts.items[i].value;
- if (strequal("types", k.data)) {
- if (v.type != kObjectTypeArray) {
- api_set_error(err, kErrorTypeValidation, "invalid value for key: %s",
- k.data);
- return (Dictionary)ARRAY_DICT_INIT;
- }
- types = v.data.array;
- } else {
- api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data);
- return (Dictionary)ARRAY_DICT_INIT;
- }
+ if (opts->types.type == kObjectTypeArray) {
+ types = opts->types.data.array;
+ } else if (opts->types.type != kObjectTypeNil) {
+ api_set_error(err, kErrorTypeValidation, "invalid value for key: types");
+ return (Dictionary)ARRAY_DICT_INIT;
}
int int_types = types.size > 0 ? 0 : kCtxAll;
@@ -1885,7 +1727,7 @@ ArrayOf(Dictionary) nvim_get_keymap(String mode)
/// as keys excluding |<buffer>| but including |noremap|.
/// Values are Booleans. Unknown key is an error.
/// @param[out] err Error details, if any.
-void nvim_set_keymap(String mode, String lhs, String rhs, Dictionary opts, Error *err)
+void nvim_set_keymap(String mode, String lhs, String rhs, Dict(keymap) *opts, Error *err)
FUNC_API_SINCE(6)
{
modify_keymap(-1, false, mode, lhs, rhs, opts, err);
@@ -1911,7 +1753,7 @@ void nvim_del_keymap(String mode, String lhs, Error *err)
/// @param[out] err Error details, if any.
///
/// @returns Map of maps describing commands.
-Dictionary nvim_get_commands(Dictionary opts, Error *err)
+Dictionary nvim_get_commands(Dict(get_commands) *opts, Error *err)
FUNC_API_SINCE(4)
{
return nvim_buf_get_commands(-1, opts, err);
@@ -2937,3 +2779,106 @@ void nvim_set_decoration_provider(Integer ns_id, DictionaryOf(LuaRef) opts, Erro
error:
decor_provider_clear(p);
}
+
+/// Deletes a uppercase/file named mark. See |mark-motions|.
+///
+/// @note fails with error if a lowercase or buffer local named mark is used.
+/// @param name Mark name
+/// @return true if the mark was deleted, else false.
+/// @see |nvim_buf_del_mark()|
+/// @see |nvim_get_mark()|
+Boolean nvim_del_mark(String name, Error *err)
+ FUNC_API_SINCE(8)
+{
+ bool res = false;
+ if (name.size != 1) {
+ api_set_error(err, kErrorTypeValidation,
+ "Mark name must be a single character");
+ return res;
+ }
+ // Only allow file/uppercase marks
+ // TODO(muniter): Refactor this ASCII_ISUPPER macro to a proper function
+ if (ASCII_ISUPPER(*name.data) || ascii_isdigit(*name.data)) {
+ res = set_mark(NULL, name, 0, 0, err);
+ } else {
+ api_set_error(err, kErrorTypeValidation,
+ "Only file/uppercase marks allowed, invalid mark name: '%c'",
+ *name.data);
+ }
+ return res;
+}
+
+/// Return a tuple (row, col, buffer, buffername) representing the position of
+/// the uppercase/file named mark. See |mark-motions|.
+///
+/// Marks are (1,0)-indexed. |api-indexing|
+///
+/// @note fails with error if a lowercase or buffer local named mark is used.
+/// @param name Mark name
+/// @return 4-tuple (row, col, buffer, buffername), (0, 0, 0, '') if the mark is
+/// not set.
+/// @see |nvim_buf_set_mark()|
+/// @see |nvim_del_mark()|
+Array nvim_get_mark(String name, Error *err)
+ FUNC_API_SINCE(8)
+{
+ Array rv = ARRAY_DICT_INIT;
+
+ if (name.size != 1) {
+ api_set_error(err, kErrorTypeValidation,
+ "Mark name must be a single character");
+ return rv;
+ } else if (!(ASCII_ISUPPER(*name.data) || ascii_isdigit(*name.data))) {
+ api_set_error(err, kErrorTypeValidation,
+ "Only file/uppercase marks allowed, invalid mark name: '%c'",
+ *name.data);
+ return rv;
+ }
+
+ xfmark_T mark = get_global_mark(*name.data);
+ pos_T pos = mark.fmark.mark;
+ bool allocated = false;
+ int bufnr;
+ char *filename;
+
+ // Marks are from an open buffer it fnum is non zero
+ if (mark.fmark.fnum != 0) {
+ bufnr = mark.fmark.fnum;
+ filename = (char *)buflist_nr2name(bufnr, true, true);
+ allocated = true;
+ // Marks comes from shada
+ } else {
+ filename = (char *)mark.fname;
+ bufnr = 0;
+ }
+
+ bool exists = filename != NULL;
+ Integer row;
+ Integer col;
+
+ if (!exists || pos.lnum <= 0) {
+ if (allocated) {
+ xfree(filename);
+ allocated = false;
+ }
+ filename = "";
+ bufnr = 0;
+ row = 0;
+ col = 0;
+ } else {
+ row = pos.lnum;
+ col = pos.col;
+ }
+
+ ADD(rv, INTEGER_OBJ(row));
+ ADD(rv, INTEGER_OBJ(col));
+ ADD(rv, INTEGER_OBJ(bufnr));
+ ADD(rv, STRING_OBJ(cstr_to_string(filename)));
+
+ if (allocated) {
+ xfree(filename);
+ }
+
+ return rv;
+}
+
diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c
new file mode 100644
index 0000000000..d82e7e8a03
--- /dev/null
+++ b/src/nvim/api/win_config.c
@@ -0,0 +1,639 @@
+// 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
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "nvim/api/private/defs.h"
+#include "nvim/api/private/helpers.h"
+#include "nvim/api/win_config.h"
+#include "nvim/ascii.h"
+#include "nvim/option.h"
+#include "nvim/screen.h"
+#include "nvim/strings.h"
+#include "nvim/syntax.h"
+#include "nvim/ui.h"
+#include "nvim/window.h"
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "api/win_config.c.generated.h"
+#endif
+
+
+/// Open a new window.
+///
+/// Currently this is used to open floating and external windows.
+/// Floats are windows that are drawn above the split layout, at some anchor
+/// position in some other window. Floats can be drawn internally or by external
+/// GUI with the |ui-multigrid| extension. External windows are only supported
+/// with multigrid GUIs, and are displayed as separate top-level windows.
+///
+/// For a general overview of floats, see |api-floatwin|.
+///
+/// Exactly one of `external` and `relative` must be specified. The `width` and
+/// `height` of the new window must be specified.
+///
+/// With relative=editor (row=0,col=0) refers to the top-left corner of the
+/// screen-grid and (row=Lines-1,col=Columns-1) refers to the bottom-right
+/// corner. Fractional values are allowed, but the builtin implementation
+/// (used by non-multigrid UIs) will always round down to nearest integer.
+///
+/// Out-of-bounds values, and configurations that make the float not fit inside
+/// the main editor, are allowed. The builtin implementation truncates values
+/// so floats are fully within the main screen grid. External GUIs
+/// could let floats hover outside of the main window like a tooltip, but
+/// this should not be used to specify arbitrary WM screen positions.
+///
+/// Example (Lua): window-relative float
+/// <pre>
+/// vim.api.nvim_open_win(0, false,
+/// {relative='win', row=3, col=3, width=12, height=3})
+/// </pre>
+///
+/// Example (Lua): buffer-relative float (travels as buffer is scrolled)
+/// <pre>
+/// vim.api.nvim_open_win(0, false,
+/// {relative='win', width=12, height=3, bufpos={100,10}})
+/// </pre>
+///
+/// @param buffer Buffer to display, or 0 for current buffer
+/// @param enter Enter the window (make it the current window)
+/// @param config Map defining the window configuration. Keys:
+/// - `relative`: Sets the window layout to "floating", placed at (row,col)
+/// coordinates relative to:
+/// - "editor" The global editor grid
+/// - "win" Window given by the `win` field, or current window.
+/// - "cursor" Cursor position in current window.
+/// - `win`: |window-ID| for relative="win".
+/// - `anchor`: Decides which corner of the float to place at (row,col):
+/// - "NW" northwest (default)
+/// - "NE" northeast
+/// - "SW" southwest
+/// - "SE" southeast
+/// - `width`: Window width (in character cells). Minimum of 1.
+/// - `height`: Window height (in character cells). Minimum of 1.
+/// - `bufpos`: Places float relative to buffer text (only when
+/// relative="win"). Takes a tuple of zero-indexed [line, column].
+/// `row` and `col` if given are applied relative to this
+/// position, else they default to:
+/// - `row=1` and `col=0` if `anchor` is "NW" or "NE"
+/// - `row=0` and `col=0` if `anchor` is "SW" or "SE"
+/// (thus like a tooltip near the buffer text).
+/// - `row`: Row position in units of "screen cell height", may be fractional.
+/// - `col`: Column position in units of "screen cell width", may be
+/// fractional.
+/// - `focusable`: Enable focus by user actions (wincmds, mouse events).
+/// Defaults to true. Non-focusable windows can be entered by
+/// |nvim_set_current_win()|.
+/// - `external`: GUI should display the window as an external
+/// top-level window. Currently accepts no other positioning
+/// configuration together with this.
+/// - `zindex`: Stacking order. floats with higher `zindex` go on top on
+/// floats with lower indices. Must be larger than zero. The
+/// following screen elements have hard-coded z-indices:
+/// - 100: insert completion popupmenu
+/// - 200: message scrollback
+/// - 250: cmdline completion popupmenu (when wildoptions+=pum)
+/// The default value for floats are 50. In general, values below 100 are
+/// recommended, unless there is a good reason to overshadow builtin
+/// elements.
+/// - `style`: Configure the appearance of the window. Currently only takes
+/// one non-empty value:
+/// - "minimal" Nvim will display the window with many UI options
+/// disabled. This is useful when displaying a temporary
+/// float where the text should not be edited. Disables
+/// 'number', 'relativenumber', 'cursorline', 'cursorcolumn',
+/// 'foldcolumn', 'spell' and 'list' options. 'signcolumn'
+/// is changed to `auto` and 'colorcolumn' is cleared. The
+/// end-of-buffer region is hidden by setting `eob` flag of
+/// 'fillchars' to a space char, and clearing the
+/// |EndOfBuffer| region in 'winhighlight'.
+/// - `border`: Style of (optional) window border. This can either be a string
+/// or an array. The string values are
+/// - "none": No border (default).
+/// - "single": A single line box.
+/// - "double": A double line box.
+/// - "rounded": Like "single", but with rounded corners ("╭" etc.).
+/// - "solid": Adds padding by a single whitespace cell.
+/// - "shadow": A drop shadow effect by blending with the background.
+/// - If it is an array, it should have a length of eight or any divisor of
+/// eight. The array will specifify the eight chars building up the border
+/// in a clockwise fashion starting with the top-left corner. As an
+/// example, the double box style could be specified as
+/// [ "╔", "═" ,"╗", "║", "╝", "═", "╚", "║" ].
+/// If the number of chars are less than eight, they will be repeated. Thus
+/// an ASCII border could be specified as
+/// [ "/", "-", "\\", "|" ],
+/// or all chars the same as
+/// [ "x" ].
+/// An empty string can be used to turn off a specific border, for instance,
+/// [ "", "", "", ">", "", "", "", "<" ]
+/// will only make vertical borders but not horizontal ones.
+/// By default, `FloatBorder` highlight is used, which links to `VertSplit`
+/// when not defined. It could also be specified by character:
+/// [ {"+", "MyCorner"}, {"x", "MyBorder"} ].
+/// - `noautocmd`: If true then no buffer-related autocommand events such as
+/// |BufEnter|, |BufLeave| or |BufWinEnter| may fire from
+/// calling this function.
+///
+/// @param[out] err Error details, if any
+///
+/// @return Window handle, or 0 on error
+Window nvim_open_win(Buffer buffer, Boolean enter, Dict(float_config) *config, Error *err)
+ FUNC_API_SINCE(6)
+ FUNC_API_CHECK_TEXTLOCK
+{
+ FloatConfig fconfig = FLOAT_CONFIG_INIT;
+ if (!parse_float_config(config, &fconfig, false, true, err)) {
+ return 0;
+ }
+ win_T *wp = win_new_float(NULL, fconfig, err);
+ if (!wp) {
+ return 0;
+ }
+ if (enter) {
+ win_enter(wp, false);
+ }
+ // autocmds in win_enter or win_set_buf below may close the window
+ if (win_valid(wp) && buffer > 0) {
+ win_set_buf(wp->handle, buffer, fconfig.noautocmd, err);
+ }
+ if (!win_valid(wp)) {
+ api_set_error(err, kErrorTypeException, "Window was closed immediately");
+ return 0;
+ }
+
+ if (fconfig.style == kWinStyleMinimal) {
+ win_set_minimal_style(wp);
+ didset_window_options(wp);
+ }
+ return wp->handle;
+}
+
+/// Configures window layout. Currently only for floating and external windows
+/// (including changing a split window to those layouts).
+///
+/// When reconfiguring a floating window, absent option keys will not be
+/// changed. `row`/`col` and `relative` must be reconfigured together.
+///
+/// @see |nvim_open_win()|
+///
+/// @param window Window handle, or 0 for current window
+/// @param config Map defining the window configuration,
+/// see |nvim_open_win()|
+/// @param[out] err Error details, if any
+void nvim_win_set_config(Window window, Dict(float_config) *config, Error *err)
+ FUNC_API_SINCE(6)
+{
+ win_T *win = find_window_by_handle(window, err);
+ if (!win) {
+ return;
+ }
+ bool new_float = !win->w_floating;
+ // reuse old values, if not overridden
+ FloatConfig fconfig = new_float ? FLOAT_CONFIG_INIT : win->w_float_config;
+
+ if (!parse_float_config(config, &fconfig, !new_float, false, err)) {
+ return;
+ }
+ if (new_float) {
+ if (!win_new_float(win, fconfig, err)) {
+ return;
+ }
+ redraw_later(win, NOT_VALID);
+ } else {
+ win_config_float(win, fconfig);
+ win->w_pos_changed = true;
+ }
+ if (fconfig.style == kWinStyleMinimal) {
+ win_set_minimal_style(win);
+ didset_window_options(win);
+ }
+}
+
+/// Gets window configuration.
+///
+/// The returned value may be given to |nvim_open_win()|.
+///
+/// `relative` is empty for normal windows.
+///
+/// @param window Window handle, or 0 for current window
+/// @param[out] err Error details, if any
+/// @return Map defining the window configuration, see |nvim_open_win()|
+Dictionary nvim_win_get_config(Window window, Error *err)
+ FUNC_API_SINCE(6)
+{
+ Dictionary rv = ARRAY_DICT_INIT;
+
+ win_T *wp = find_window_by_handle(window, err);
+ if (!wp) {
+ return rv;
+ }
+
+ FloatConfig *config = &wp->w_float_config;
+
+ PUT(rv, "focusable", BOOLEAN_OBJ(config->focusable));
+ PUT(rv, "external", BOOLEAN_OBJ(config->external));
+
+ if (wp->w_floating) {
+ PUT(rv, "width", INTEGER_OBJ(config->width));
+ PUT(rv, "height", INTEGER_OBJ(config->height));
+ if (!config->external) {
+ if (config->relative == kFloatRelativeWindow) {
+ PUT(rv, "win", INTEGER_OBJ(config->window));
+ if (config->bufpos.lnum >= 0) {
+ Array pos = ARRAY_DICT_INIT;
+ ADD(pos, INTEGER_OBJ(config->bufpos.lnum));
+ ADD(pos, INTEGER_OBJ(config->bufpos.col));
+ PUT(rv, "bufpos", ARRAY_OBJ(pos));
+ }
+ }
+ PUT(rv, "anchor", STRING_OBJ(cstr_to_string(float_anchor_str[config->anchor])));
+ PUT(rv, "row", FLOAT_OBJ(config->row));
+ PUT(rv, "col", FLOAT_OBJ(config->col));
+ PUT(rv, "zindex", INTEGER_OBJ(config->zindex));
+ }
+ if (config->border) {
+ Array border = ARRAY_DICT_INIT;
+ for (size_t i = 0; i < 8; i++) {
+ Array tuple = ARRAY_DICT_INIT;
+
+ String s = cstrn_to_string((const char *)config->border_chars[i], sizeof(schar_T));
+
+ int hi_id = config->border_hl_ids[i];
+ char_u *hi_name = syn_id2name(hi_id);
+ if (hi_name[0]) {
+ ADD(tuple, STRING_OBJ(s));
+ ADD(tuple, STRING_OBJ(cstr_to_string((const char *)hi_name)));
+ ADD(border, ARRAY_OBJ(tuple));
+ } else {
+ ADD(border, STRING_OBJ(s));
+ }
+ }
+ PUT(rv, "border", ARRAY_OBJ(border));
+ }
+ }
+
+ const char *rel = (wp->w_floating && !config->external
+ ? float_relative_str[config->relative] : "");
+ PUT(rv, "relative", STRING_OBJ(cstr_to_string(rel)));
+
+ return rv;
+}
+
+static bool parse_float_anchor(String anchor, FloatAnchor *out)
+{
+ if (anchor.size == 0) {
+ *out = (FloatAnchor)0;
+ }
+ char *str = anchor.data;
+ if (striequal(str, "NW")) {
+ *out = 0; // NW is the default
+ } else if (striequal(str, "NE")) {
+ *out = kFloatAnchorEast;
+ } else if (striequal(str, "SW")) {
+ *out = kFloatAnchorSouth;
+ } else if (striequal(str, "SE")) {
+ *out = kFloatAnchorSouth | kFloatAnchorEast;
+ } else {
+ return false;
+ }
+ return true;
+}
+
+static bool parse_float_relative(String relative, FloatRelative *out)
+{
+ char *str = relative.data;
+ if (striequal(str, "editor")) {
+ *out = kFloatRelativeEditor;
+ } else if (striequal(str, "win")) {
+ *out = kFloatRelativeWindow;
+ } else if (striequal(str, "cursor")) {
+ *out = kFloatRelativeCursor;
+ } else {
+ return false;
+ }
+ return true;
+}
+
+static bool parse_float_bufpos(Array bufpos, lpos_T *out)
+{
+ if (bufpos.size != 2
+ || bufpos.items[0].type != kObjectTypeInteger
+ || bufpos.items[1].type != kObjectTypeInteger) {
+ return false;
+ }
+ out->lnum = bufpos.items[0].data.integer;
+ out->col = (colnr_T)bufpos.items[1].data.integer;
+ return true;
+}
+
+static void parse_border_style(Object style, FloatConfig *fconfig, Error *err)
+{
+ struct {
+ const char *name;
+ schar_T chars[8];
+ bool shadow_color;
+ } defaults[] = {
+ { "double", { "╔", "═", "╗", "║", "╝", "═", "╚", "║" }, false },
+ { "single", { "┌", "─", "┐", "│", "┘", "─", "└", "│" }, false },
+ { "shadow", { "", "", " ", " ", " ", " ", " ", "" }, true },
+ { "rounded", { "╭", "─", "╮", "│", "╯", "─", "╰", "│" }, false },
+ { "solid", { " ", " ", " ", " ", " ", " ", " ", " " }, false },
+ { NULL, { { NUL } }, false },
+ };
+
+ schar_T *chars = fconfig->border_chars;
+ int *hl_ids = fconfig->border_hl_ids;
+
+ fconfig->border = true;
+
+ if (style.type == kObjectTypeArray) {
+ Array arr = style.data.array;
+ size_t size = arr.size;
+ if (!size || size > 8 || (size & (size-1))) {
+ api_set_error(err, kErrorTypeValidation,
+ "invalid number of border chars");
+ return;
+ }
+ for (size_t i = 0; i < size; i++) {
+ Object iytem = arr.items[i];
+ String string;
+ int hl_id = 0;
+ if (iytem.type == kObjectTypeArray) {
+ Array iarr = iytem.data.array;
+ if (!iarr.size || iarr.size > 2) {
+ api_set_error(err, kErrorTypeValidation, "invalid border char");
+ return;
+ }
+ if (iarr.items[0].type != kObjectTypeString) {
+ api_set_error(err, kErrorTypeValidation, "invalid border char");
+ return;
+ }
+ string = iarr.items[0].data.string;
+ if (iarr.size == 2) {
+ hl_id = object_to_hl_id(iarr.items[1], "border char highlight", err);
+ if (ERROR_SET(err)) {
+ return;
+ }
+ }
+ } else if (iytem.type == kObjectTypeString) {
+ string = iytem.data.string;
+ } else {
+ api_set_error(err, kErrorTypeValidation, "invalid border char");
+ return;
+ }
+ if (string.size
+ && mb_string2cells_len((char_u *)string.data, string.size) > 1) {
+ api_set_error(err, kErrorTypeValidation,
+ "border chars must be one cell");
+ return;
+ }
+ size_t len = MIN(string.size, sizeof(*chars)-1);
+ if (len) {
+ memcpy(chars[i], string.data, len);
+ }
+ chars[i][len] = NUL;
+ hl_ids[i] = hl_id;
+ }
+ while (size < 8) {
+ memcpy(chars+size, chars, sizeof(*chars) * size);
+ memcpy(hl_ids+size, hl_ids, sizeof(*hl_ids) * size);
+ size <<= 1;
+ }
+ if ((chars[7][0] && chars[1][0] && !chars[0][0])
+ || (chars[1][0] && chars[3][0] && !chars[2][0])
+ || (chars[3][0] && chars[5][0] && !chars[4][0])
+ || (chars[5][0] && chars[7][0] && !chars[6][0])) {
+ api_set_error(err, kErrorTypeValidation,
+ "corner between used edges must be specified");
+ }
+ } else if (style.type == kObjectTypeString) {
+ String str = style.data.string;
+ if (str.size == 0 || strequal(str.data, "none")) {
+ fconfig->border = false;
+ return;
+ }
+ for (size_t i = 0; defaults[i].name; i++) {
+ if (strequal(str.data, defaults[i].name)) {
+ memcpy(chars, defaults[i].chars, sizeof(defaults[i].chars));
+ memset(hl_ids, 0, 8 * sizeof(*hl_ids));
+ if (defaults[i].shadow_color) {
+ int hl_blend = SYN_GROUP_STATIC("FloatShadow");
+ int hl_through = SYN_GROUP_STATIC("FloatShadowThrough");
+ hl_ids[2] = hl_through;
+ hl_ids[3] = hl_blend;
+ hl_ids[4] = hl_blend;
+ hl_ids[5] = hl_blend;
+ hl_ids[6] = hl_through;
+ }
+ return;
+ }
+ }
+ api_set_error(err, kErrorTypeValidation,
+ "invalid border style \"%s\"", str.data);
+ }
+}
+
+static bool parse_float_config(Dict(float_config) *config, FloatConfig *fconfig, bool reconf,
+ bool new_win, Error *err)
+{
+ bool has_relative = false, relative_is_win = false;
+ if (config->relative.type == kObjectTypeString) {
+ // ignore empty string, to match nvim_win_get_config
+ if (config->relative.data.string.size > 0) {
+ if (!parse_float_relative(config->relative.data.string, &fconfig->relative)) {
+ api_set_error(err, kErrorTypeValidation, "Invalid value of 'relative' key");
+ return false;
+ }
+
+ if (!(HAS_KEY(config->row) && HAS_KEY(config->col)) && !HAS_KEY(config->bufpos)) {
+ api_set_error(err, kErrorTypeValidation,
+ "'relative' requires 'row'/'col' or 'bufpos'");
+ return false;
+ }
+
+ has_relative = true;
+ fconfig->external = false;
+ if (fconfig->relative == kFloatRelativeWindow) {
+ relative_is_win = true;
+ fconfig->bufpos.lnum = -1;
+ }
+ }
+ } else if (HAS_KEY(config->relative)) {
+ api_set_error(err, kErrorTypeValidation, "'relative' key must be String");
+ return false;
+ }
+
+ if (config->anchor.type == kObjectTypeString) {
+ if (!parse_float_anchor(config->anchor.data.string, &fconfig->anchor)) {
+ api_set_error(err, kErrorTypeValidation, "Invalid value of 'anchor' key");
+ return false;
+ }
+ } else if (HAS_KEY(config->anchor)) {
+ api_set_error(err, kErrorTypeValidation, "'anchor' key must be String");
+ return false;
+ }
+
+ if (HAS_KEY(config->row)) {
+ if (!has_relative) {
+ api_set_error(err, kErrorTypeValidation, "non-float cannot have 'row'");
+ return false;
+ } else if (config->row.type == kObjectTypeInteger) {
+ fconfig->row = (double)config->row.data.integer;
+ } else if (config->row.type == kObjectTypeFloat) {
+ fconfig->row = config->row.data.floating;
+ } else {
+ api_set_error(err, kErrorTypeValidation,
+ "'row' key must be Integer or Float");
+ return false;
+ }
+ }
+
+ if (HAS_KEY(config->col)) {
+ if (!has_relative) {
+ api_set_error(err, kErrorTypeValidation, "non-float cannot have 'col'");
+ return false;
+ } else if (config->col.type == kObjectTypeInteger) {
+ fconfig->col = (double)config->col.data.integer;
+ } else if (config->col.type == kObjectTypeFloat) {
+ fconfig->col = config->col.data.floating;
+ } else {
+ api_set_error(err, kErrorTypeValidation,
+ "'col' key must be Integer or Float");
+ return false;
+ }
+ }
+
+ if (HAS_KEY(config->bufpos)) {
+ if (!has_relative) {
+ api_set_error(err, kErrorTypeValidation, "non-float cannot have 'bufpos'");
+ return false;
+ } else if (config->bufpos.type == kObjectTypeArray) {
+ if (!parse_float_bufpos(config->bufpos.data.array, &fconfig->bufpos)) {
+ api_set_error(err, kErrorTypeValidation, "Invalid value of 'bufpos' key");
+ return false;
+ }
+
+ if (!HAS_KEY(config->row)) {
+ fconfig->row = (fconfig->anchor & kFloatAnchorSouth) ? 0 : 1;
+ }
+ if (!HAS_KEY(config->col)) {
+ fconfig->col = 0;
+ }
+ } else {
+ api_set_error(err, kErrorTypeValidation, "'bufpos' key must be Array");
+ return false;
+ }
+ }
+
+ if (config->width.type == kObjectTypeInteger && config->width.data.integer > 0) {
+ fconfig->width = (int)config->width.data.integer;
+ } else if (HAS_KEY(config->width)) {
+ api_set_error(err, kErrorTypeValidation, "'width' key must be a positive Integer");
+ return false;
+ } else if (!reconf) {
+ api_set_error(err, kErrorTypeValidation, "Must specify 'width'");
+ return false;
+ }
+
+ if (config->height.type == kObjectTypeInteger && config->height.data.integer > 0) {
+ fconfig->height = (int)config->height.data.integer;
+ } else if (HAS_KEY(config->height)) {
+ api_set_error(err, kErrorTypeValidation, "'height' key must be a positive Integer");
+ return false;
+ } else if (!reconf) {
+ api_set_error(err, kErrorTypeValidation, "Must specify 'height'");
+ return false;
+ }
+
+ if (relative_is_win) {
+ fconfig->window = curwin->handle;
+ if (config->win.type == kObjectTypeInteger || config->win.type == kObjectTypeWindow) {
+ if (config->win.data.integer > 0) {
+ fconfig->window = (Window)config->win.data.integer;
+ }
+ } else if (HAS_KEY(config->win)) {
+ api_set_error(err, kErrorTypeValidation, "'win' key must be Integer or Window");
+ return false;
+ }
+ } else {
+ if (HAS_KEY(config->win)) {
+ api_set_error(err, kErrorTypeValidation, "'win' key is only valid with relative='win'");
+ return false;
+ }
+ }
+
+ if (HAS_KEY(config->external)) {
+ fconfig->external = api_object_to_bool(config->external, "'external' key", false, err);
+ if (ERROR_SET(err)) {
+ return false;
+ }
+ if (has_relative && fconfig->external) {
+ api_set_error(err, kErrorTypeValidation,
+ "Only one of 'relative' and 'external' must be used");
+ return false;
+ }
+ if (fconfig->external && !ui_has(kUIMultigrid)) {
+ api_set_error(err, kErrorTypeValidation,
+ "UI doesn't support external windows");
+ return false;
+ }
+ }
+
+ if (!reconf && (!has_relative && !fconfig->external)) {
+ api_set_error(err, kErrorTypeValidation,
+ "One of 'relative' and 'external' must be used");
+ return false;
+ }
+
+
+ if (HAS_KEY(config->focusable)) {
+ fconfig->focusable = api_object_to_bool(config->focusable, "'focusable' key", false, err);
+ if (ERROR_SET(err)) {
+ return false;
+ }
+ }
+
+ if (config->zindex.type == kObjectTypeInteger && config->zindex.data.integer > 0) {
+ fconfig->zindex = (int)config->zindex.data.integer;
+ } else if (HAS_KEY(config->zindex)) {
+ api_set_error(err, kErrorTypeValidation, "'zindex' key must be a positive Integer");
+ return false;
+ }
+
+ if (HAS_KEY(config->border)) {
+ parse_border_style(config->border, fconfig, err);
+ if (ERROR_SET(err)) {
+ return false;
+ }
+ }
+
+ if (config->style.type == kObjectTypeString) {
+ if (config->style.data.string.data[0] == NUL) {
+ fconfig->style = kWinStyleUnused;
+ } else if (striequal(config->style.data.string.data, "minimal")) {
+ fconfig->style = kWinStyleMinimal;
+ } else {
+ api_set_error(err, kErrorTypeValidation, "Invalid value of 'style' key");
+ }
+ } else if (HAS_KEY(config->style)) {
+ api_set_error(err, kErrorTypeValidation, "'style' key must be String");
+ return false;
+ }
+
+ if (HAS_KEY(config->noautocmd)) {
+ if (!new_win) {
+ api_set_error(err, kErrorTypeValidation, "Invalid key: 'noautocmd'");
+ return false;
+ }
+ fconfig->noautocmd = api_object_to_bool(config->noautocmd, "'noautocmd' key", false, err);
+ if (ERROR_SET(err)) {
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/src/nvim/api/win_config.h b/src/nvim/api/win_config.h
new file mode 100644
index 0000000000..9271c35f23
--- /dev/null
+++ b/src/nvim/api/win_config.h
@@ -0,0 +1,11 @@
+#ifndef NVIM_API_WIN_CONFIG_H
+#define NVIM_API_WIN_CONFIG_H
+
+#include <stdint.h>
+
+#include "nvim/api/private/defs.h"
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "api/win_config.h.generated.h"
+#endif
+#endif // NVIM_API_WIN_CONFIG_H
diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c
index 99ba297111..6e68c057dc 100644
--- a/src/nvim/api/window.c
+++ b/src/nvim/api/window.c
@@ -373,117 +373,6 @@ Boolean nvim_win_is_valid(Window window)
}
-/// Configures window layout. Currently only for floating and external windows
-/// (including changing a split window to those layouts).
-///
-/// When reconfiguring a floating window, absent option keys will not be
-/// changed. `row`/`col` and `relative` must be reconfigured together.
-///
-/// @see |nvim_open_win()|
-///
-/// @param window Window handle, or 0 for current window
-/// @param config Map defining the window configuration,
-/// see |nvim_open_win()|
-/// @param[out] err Error details, if any
-void nvim_win_set_config(Window window, Dictionary config, Error *err)
- FUNC_API_SINCE(6)
-{
- win_T *win = find_window_by_handle(window, err);
- if (!win) {
- return;
- }
- bool new_float = !win->w_floating;
- // reuse old values, if not overridden
- FloatConfig fconfig = new_float ? FLOAT_CONFIG_INIT : win->w_float_config;
-
- if (!parse_float_config(config, &fconfig, !new_float, false, err)) {
- return;
- }
- if (new_float) {
- if (!win_new_float(win, fconfig, err)) {
- return;
- }
- redraw_later(win, NOT_VALID);
- } else {
- win_config_float(win, fconfig);
- win->w_pos_changed = true;
- }
- if (fconfig.style == kWinStyleMinimal) {
- win_set_minimal_style(win);
- didset_window_options(win);
- }
-}
-
-/// Gets window configuration.
-///
-/// The returned value may be given to |nvim_open_win()|.
-///
-/// `relative` is empty for normal windows.
-///
-/// @param window Window handle, or 0 for current window
-/// @param[out] err Error details, if any
-/// @return Map defining the window configuration, see |nvim_open_win()|
-Dictionary nvim_win_get_config(Window window, Error *err)
- FUNC_API_SINCE(6)
-{
- Dictionary rv = ARRAY_DICT_INIT;
-
- win_T *wp = find_window_by_handle(window, err);
- if (!wp) {
- return rv;
- }
-
- FloatConfig *config = &wp->w_float_config;
-
- PUT(rv, "focusable", BOOLEAN_OBJ(config->focusable));
- PUT(rv, "external", BOOLEAN_OBJ(config->external));
-
- if (wp->w_floating) {
- PUT(rv, "width", INTEGER_OBJ(config->width));
- PUT(rv, "height", INTEGER_OBJ(config->height));
- if (!config->external) {
- if (config->relative == kFloatRelativeWindow) {
- PUT(rv, "win", INTEGER_OBJ(config->window));
- if (config->bufpos.lnum >= 0) {
- Array pos = ARRAY_DICT_INIT;
- ADD(pos, INTEGER_OBJ(config->bufpos.lnum));
- ADD(pos, INTEGER_OBJ(config->bufpos.col));
- PUT(rv, "bufpos", ARRAY_OBJ(pos));
- }
- }
- PUT(rv, "anchor", STRING_OBJ(cstr_to_string(float_anchor_str[config->anchor])));
- PUT(rv, "row", FLOAT_OBJ(config->row));
- PUT(rv, "col", FLOAT_OBJ(config->col));
- PUT(rv, "zindex", INTEGER_OBJ(config->zindex));
- }
- if (config->border) {
- Array border = ARRAY_DICT_INIT;
- for (size_t i = 0; i < 8; i++) {
- Array tuple = ARRAY_DICT_INIT;
-
- String s = cstrn_to_string((const char *)config->border_chars[i], sizeof(schar_T));
-
- int hi_id = config->border_hl_ids[i];
- char_u *hi_name = syn_id2name(hi_id);
- if (hi_name[0]) {
- ADD(tuple, STRING_OBJ(s));
- ADD(tuple, STRING_OBJ(cstr_to_string((const char *)hi_name)));
- ADD(border, ARRAY_OBJ(tuple));
- } else {
- ADD(border, STRING_OBJ(s));
- }
- }
- PUT(rv, "border", ARRAY_OBJ(border));
- }
- }
-
- const char *rel = (wp->w_floating && !config->external
- ? float_relative_str[config->relative] : "");
- PUT(rv, "relative", STRING_OBJ(cstr_to_string(rel)));
-
- return rv;
-}
-
/// Closes the window and hide the buffer it contains (like |:hide| with a
/// |window-ID|).
///
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
index e7b2ad9000..d991b88131 100644
--- a/src/nvim/autocmd.c
+++ b/src/nvim/autocmd.c
@@ -199,7 +199,7 @@ static void au_cleanup(void)
}
// Loop over all events.
- for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
+ for (event = (event_T)0; (int)event < NUM_EVENTS;
event = (event_T)((int)event + 1)) {
// Loop over all autocommand patterns.
prev_ap = &(first_autopat[(int)event]);
@@ -266,7 +266,7 @@ void aubuflocal_remove(buf_T *buf)
}
// invalidate buflocals looping through events
- for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
+ for (event = (event_T)0; (int)event < NUM_EVENTS;
event = (event_T)((int)event + 1)) {
// loop over all autocommand patterns
for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next) {
@@ -321,7 +321,7 @@ static void au_del_group(char_u *name)
AutoPat *ap;
int in_use = false;
- for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
+ for (event = (event_T)0; (int)event < NUM_EVENTS;
event = (event_T)((int)event + 1)) {
for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next) {
if (ap->group == i && ap->pat != NULL) {
@@ -475,7 +475,7 @@ static char_u *find_end_event(char_u *arg, int have_group)
pat = arg + 1;
} else {
for (pat = arg; *pat && *pat != '|' && !ascii_iswhite(*pat); pat = p) {
- if ((int)event_name2nr(pat, &p) >= (int)NUM_EVENTS) {
+ if ((int)event_name2nr(pat, &p) >= NUM_EVENTS) {
if (have_group) {
EMSG2(_("E216: No such event: %s"), pat);
} else {
@@ -701,7 +701,7 @@ void do_autocmd(char_u *arg_in, int forceit)
if (!forceit && *cmd != NUL) {
EMSG(_(e_cannot_define_autocommands_for_all_events));
} else {
- for (event_T event = (event_T)0; event < (int)NUM_EVENTS;
+ for (event_T event = (event_T)0; event < NUM_EVENTS;
event = (event_T)(event + 1)) {
if (do_autocmd_event(event, pat, once, nested, cmd, forceit, group)
== FAIL) {
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 3c86f55260..20dd94622f 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -117,7 +117,7 @@ static int read_buffer(int read_stdin, exarg_T *eap, int flags)
line_count = curbuf->b_ml.ml_line_count;
retval = readfile(read_stdin ? NULL : curbuf->b_ffname,
read_stdin ? NULL : curbuf->b_fname,
- (linenr_T)line_count, (linenr_T)0, (linenr_T)MAXLNUM, eap,
+ line_count, (linenr_T)0, (linenr_T)MAXLNUM, eap,
flags | READ_BUFFER);
if (retval == OK) {
// Delete the binary lines.
diff --git a/src/nvim/charset.c b/src/nvim/charset.c
index f899ebf57c..d2f95ad81c 100644
--- a/src/nvim/charset.c
+++ b/src/nvim/charset.c
@@ -412,7 +412,7 @@ char *transstr(const char *const s, bool untab)
{
// Compute the length of the result, taking account of unprintable
// multi-byte characters.
- const size_t len = transstr_len((const char *)s, untab) + 1;
+ const size_t len = transstr_len(s, untab) + 1;
char *const buf = xmalloc(len);
transstr_buf(s, buf, len, untab);
return buf;
diff --git a/src/nvim/debugger.c b/src/nvim/debugger.c
index 0ddf163176..58b1d9ce7f 100644
--- a/src/nvim/debugger.c
+++ b/src/nvim/debugger.c
@@ -398,7 +398,7 @@ void dbg_check_breakpoint(exarg_T *eap)
// replace K_SNR with "<SNR>"
if (debug_breakpoint_name[0] == K_SPECIAL
&& debug_breakpoint_name[1] == KS_EXTRA
- && debug_breakpoint_name[2] == (int)KE_SNR) {
+ && debug_breakpoint_name[2] == KE_SNR) {
p = (char_u *)"<SNR>";
} else {
p = (char_u *)"";
diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c
index 561be9968a..4e80528c74 100644
--- a/src/nvim/decoration.c
+++ b/src/nvim/decoration.c
@@ -421,11 +421,11 @@ int decor_virtual_lines(win_T *wp, linenr_T lnum)
return 0;
}
if (buf->b_virt_line_pos < 0) {
- mtpos_t pos = marktree_lookup(buf->b_marktree, buf->b_virt_line_mark, NULL);
- if (pos.row < 0) {
- buf->b_virt_line_mark = 0;
- }
- buf->b_virt_line_pos = pos.row + (buf->b_virt_line_above ? 0 : 1);
+ mtpos_t pos = marktree_lookup(buf->b_marktree, buf->b_virt_line_mark, NULL);
+ if (pos.row < 0) {
+ buf->b_virt_line_mark = 0;
+ }
+ buf->b_virt_line_pos = pos.row + (buf->b_virt_line_above ? 0 : 1);
}
return (lnum-1 == buf->b_virt_line_pos) ? (int)kv_size(buf->b_virt_lines) : 0;
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index 5c43b2498e..3a7bd21c70 100644
--- a/src/nvim/diff.c
+++ b/src/nvim/diff.c
@@ -1110,7 +1110,7 @@ static int diff_file(diffio_T *dio)
// 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((char *)cmd, len, "diff %s%s%s%s%s%s%s%s %s",
+ 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 --git a/src/nvim/edit.c b/src/nvim/edit.c
index 45edbec4a6..5ac733285d 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -116,7 +116,7 @@ static char *ctrl_x_msgs[] =
static char *ctrl_x_mode_names[] = {
"keyword",
"ctrl_x",
- "unknown", // CTRL_X_SCROLL
+ "scroll",
"whole_line",
"files",
"tags",
@@ -3329,7 +3329,7 @@ void get_complete_info(list_T *what_list, dict_T *retdict)
// Return Insert completion mode name string
static char_u *ins_compl_mode(void)
{
- if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET || compl_started) {
+ if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET || ctrl_x_mode == CTRL_X_SCROLL || compl_started) {
return (char_u *)ctrl_x_mode_names[ctrl_x_mode & ~CTRL_X_WANT_IDENT];
}
return (char_u *)"";
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 768b82b464..a281c09042 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -514,8 +514,8 @@ int var_redir_start(char_u *name, int append)
ga_init(&redir_ga, (int)sizeof(char), 500);
// Parse the variable name (can be a dict or list entry).
- redir_endp = (char_u *)get_lval(redir_varname, NULL, redir_lval, false, false,
- 0, FNE_CHECK_START);
+ redir_endp = get_lval(redir_varname, NULL, redir_lval, false, false,
+ 0, FNE_CHECK_START);
if (redir_endp == NULL || redir_lval->ll_name == NULL
|| *redir_endp != NUL) {
clear_lval(redir_lval);
@@ -597,8 +597,8 @@ void var_redir_stop(void)
tv.vval.v_string = redir_ga.ga_data;
// Call get_lval() again, if it's inside a Dict or List it may
// have changed.
- redir_endp = (char_u *)get_lval(redir_varname, NULL, redir_lval,
- false, false, 0, FNE_CHECK_START);
+ redir_endp = get_lval(redir_varname, NULL, redir_lval,
+ false, false, 0, FNE_CHECK_START);
if (redir_endp != NULL && redir_lval->ll_name != NULL) {
set_var_lval(redir_lval, redir_endp, &tv, false, false, ".");
}
@@ -1711,7 +1711,7 @@ static const char *list_arg_vars(exarg_T *eap, const char *arg, int *first)
if (tofree != NULL) {
name = tofree;
}
- if (get_var_tv((const char *)name, len, &tv, NULL, true, false)
+ if (get_var_tv(name, len, &tv, NULL, true, false)
== FAIL) {
error = true;
} else {
@@ -2023,7 +2023,7 @@ char_u *get_lval(char_u *const name, typval_T *const rettv, lval_T *const lp, co
}
lp->ll_exp_name = (char *)make_expanded_name(name, expr_start, expr_end,
- (char_u *)p);
+ p);
lp->ll_name = lp->ll_exp_name;
if (lp->ll_exp_name == NULL) {
/* Report an invalid expression in braces, unless the
@@ -2419,7 +2419,7 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, co
// handle +=, -=, *=, /=, %= and .=
di = NULL;
- if (get_var_tv((const char *)lp->ll_name, (int)STRLEN(lp->ll_name),
+ if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name),
&tv, &di, true, false) == OK) {
if ((di == NULL
|| (!var_check_ro(di->di_flags, lp->ll_name, TV_CSTRING)
@@ -3004,12 +3004,12 @@ int do_unlet(const char *const name, const size_t name_len, const bool forceit)
hashitem_T *hi = hash_find(ht, (const char_u *)varname);
if (HASHITEM_EMPTY(hi)) {
- hi = find_hi_in_scoped_ht((const char *)name, &ht);
+ hi = find_hi_in_scoped_ht(name, &ht);
}
if (hi != NULL && !HASHITEM_EMPTY(hi)) {
dictitem_T *const di = TV_DICT_HI2DI(hi);
- if (var_check_fixed(di->di_flags, (const char *)name, TV_CSTRING)
- || var_check_ro(di->di_flags, (const char *)name, TV_CSTRING)
+ if (var_check_fixed(di->di_flags, name, TV_CSTRING)
+ || var_check_ro(di->di_flags, name, TV_CSTRING)
|| var_check_lock(d->dv_lock, name, TV_CSTRING)) {
return FAIL;
}
@@ -3069,7 +3069,7 @@ static int do_lock_var(lval_T *lp, char_u *name_end FUNC_ATTR_UNUSED, exarg_T *e
ret = FAIL;
} else {
// Normal name or expanded name.
- dictitem_T *const di = find_var((const char *)lp->ll_name, lp->ll_name_len, NULL,
+ dictitem_T *const di = find_var(lp->ll_name, lp->ll_name_len, NULL,
true);
if (di == NULL) {
ret = FAIL;
@@ -4348,7 +4348,7 @@ static int call_func_rettv(char_u **const arg, typval_T *const rettv, const bool
funcexe.selfdict = selfdict;
funcexe.basetv = basetv;
const int ret = get_func_tv(funcname, is_lua ? *arg - funcname : -1, rettv,
- (char_u **)arg, &funcexe);
+ arg, &funcexe);
// Clear the funcref afterwards, so that deleting it while
// evaluating the arguments is possible (see test55).
@@ -9444,7 +9444,7 @@ static void set_var_const(const char *name, const size_t name_len, typval_T *con
// Search in parent scope which is possible to reference from lambda
if (v == NULL) {
- v = find_var_in_scoped_ht((const char *)name, name_len, true);
+ v = find_var_in_scoped_ht(name, name_len, true);
}
if (tv_is_func(*tv) && !var_check_func_name(name, v == NULL)) {
@@ -9654,7 +9654,7 @@ bool var_check_func_name(const char *const name, const bool new_var)
// Don't allow hiding a function. When "v" is not NULL we might be
// assigning another function to the same var, the type is checked
// below.
- if (new_var && function_exists((const char *)name, false)) {
+ if (new_var && function_exists(name, false)) {
EMSG2(_("E705: Variable name conflicts with existing function: %s"),
name);
return false;
@@ -11325,7 +11325,7 @@ bool var_exists(const char *var)
// get_name_len() takes care of expanding curly braces
const char *name = var;
- const int len = get_name_len((const char **)&var, &tofree, true, false);
+ const int len = get_name_len(&var, &tofree, true, false);
if (len > 0) {
typval_T tv;
diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c
index 1c0afc89f5..5ef0045659 100644
--- a/src/nvim/eval/encode.c
+++ b/src/nvim/eval/encode.c
@@ -268,9 +268,8 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
|| TV_LIST_ITEM_TV(state->li)->vval.v_string != NULL);
for (size_t i = state->offset; i < state->li_length && p < buf_end; i++) {
assert(TV_LIST_ITEM_TV(state->li)->vval.v_string != NULL);
- const char ch = (char)(
- TV_LIST_ITEM_TV(state->li)->vval.v_string[state->offset++]);
- *p++ = (char)((char)ch == (char)NL ? (char)NUL : (char)ch);
+ const char ch = (char)(TV_LIST_ITEM_TV(state->li)->vval.v_string[state->offset++]);
+ *p++ = (char)(ch == (char)NL ? (char)NUL : ch);
}
if (p < buf_end) {
state->li = TV_LIST_ITEM_NEXT(state->list, state->li);
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 5569d74413..50e0b0b258 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -5149,7 +5149,7 @@ static void f_islocked(typval_T *argvars, typval_T *rettv, FunPtr fptr)
EMSG(_(e_trailing));
} else {
if (lv.ll_tv == NULL) {
- di = find_var((const char *)lv.ll_name, lv.ll_name_len, NULL, true);
+ di = find_var(lv.ll_name, lv.ll_name_len, NULL, true);
if (di != NULL) {
// Consider a variable locked when:
// 1. the variable itself is locked
@@ -5984,7 +5984,7 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
static void f_luaeval(typval_T *argvars, typval_T *rettv, FunPtr fptr)
FUNC_ATTR_NONNULL_ALL
{
- const char *const str = (const char *)tv_get_string_chk(&argvars[0]);
+ const char *const str = tv_get_string_chk(&argvars[0]);
if (str == NULL) {
return;
}
@@ -11358,7 +11358,7 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr)
if (new_cwd && *new_cwd != NUL) {
cwd = new_cwd;
// The new cwd must be a directory.
- if (!os_isdir_executable((const char *)cwd)) {
+ if (!os_isdir_executable(cwd)) {
EMSG2(_(e_invarg2), "expected valid directory");
shell_free_argv(argv);
return;
diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c
index 075b50a366..4c8789964f 100644
--- a/src/nvim/eval/typval.c
+++ b/src/nvim/eval/typval.c
@@ -3260,7 +3260,7 @@ const char *tv_get_string(const typval_T *const tv)
const char *tv_get_string_buf(const typval_T *const tv, char *const buf)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT
{
- const char *const res = (const char *)tv_get_string_buf_chk(tv, buf);
+ const char *const res = tv_get_string_buf_chk(tv, buf);
return res != NULL ? res : "";
}
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index a9990df58f..f4f07e0680 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -230,7 +230,22 @@ static int compl_match_arraysize;
static int compl_startcol;
static int compl_selected;
+/// |:checkhealth| completion items
+///
+/// Regenerates on every new command line prompt, to accomodate changes on the
+/// runtime files.
+typedef struct {
+ garray_T names; // healthcheck names
+ unsigned last_gen; // last_prompt_id where names were generated
+} CheckhealthComp;
+
+/// Cookie used when converting filepath to name
+struct healthchecks_cookie {
+ garray_T *names; // global healthchecks
+ bool is_lua; // true if the current entry is a Lua healthcheck
+};
+static CheckhealthComp healthchecks = { GA_INIT(sizeof(char_u *), 10), 0 };
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ex_getln.c.generated.h"
@@ -273,6 +288,68 @@ static void init_incsearch_state(incsearch_state_T *s)
save_viewstate(&s->old_viewstate);
}
+/// Completion for |:checkhealth| command.
+///
+/// Given to ExpandGeneric() to obtain all available heathcheck names.
+/// @param[in] idx Index of the healthcheck item.
+/// @param[in] xp Not used.
+static char_u *get_healthcheck_names(expand_T *xp, int idx)
+{
+ // Generate the first time or on new prompt.
+ if (healthchecks.last_gen == 0 || healthchecks.last_gen != last_prompt_id) {
+ ga_clear_strings(&healthchecks.names);
+ char *patterns[3] = { "autoload/health/**.vim", "lua/**/**/health/init.lua", // NOLINT
+ "lua/**/**/health.lua" }; // NOLINT
+ for (int i = 0; i < 3; i++) {
+ struct healthchecks_cookie hcookie = { .names = &healthchecks.names, .is_lua = i != 0 };
+ do_in_runtimepath((char_u *)patterns[i], DIP_ALL, get_healthcheck_cb, &hcookie);
+
+ if (healthchecks.names.ga_len > 0) {
+ ga_remove_duplicate_strings(&healthchecks.names);
+ }
+ }
+ // Tracked to regenerate items on next prompt.
+ healthchecks.last_gen = last_prompt_id;
+ }
+ return idx <
+ (int)healthchecks.names.ga_len ? ((char_u **)(healthchecks.names.ga_data))[idx] : NULL;
+}
+
+/// Transform healthcheck file path into it's name.
+///
+/// Used as a callback for do_in_runtimepath
+/// @param[in] path Expanded path to a possible healthcheck.
+/// @param[out] cookie Array where names will be inserted.
+static void get_healthcheck_cb(char_u *path, void *cookie)
+{
+ if (path != NULL) {
+ struct healthchecks_cookie *hcookie = (struct healthchecks_cookie *)cookie;
+ char *pattern;
+ char *sub = "\\1";
+ char_u *res;
+
+ if (hcookie->is_lua) {
+ // Lua: transform "../lua/vim/lsp/health.lua" into "vim.lsp"
+ pattern = ".*lua[\\/]\\(.\\{-}\\)[\\/]health\\([\\/]init\\)\\?\\.lua$";
+ } else {
+ // Vim: transform "../autoload/health/provider.vim" into "provider"
+ pattern = ".*[\\/]\\([^\\/]*\\)\\.vim$";
+ }
+
+ res = do_string_sub(path, (char_u *)pattern, (char_u *)sub, NULL, (char_u *)"g");
+ if (hcookie->is_lua && res != NULL) {
+ // Replace slashes with dots as represented by the healthcheck plugin.
+ char_u *ares = do_string_sub(res, (char_u *)"[\\/]", (char_u *)".", NULL, (char_u *)"g");
+ xfree(res);
+ res = ares;
+ }
+
+ if (res != NULL) {
+ GA_APPEND(char_u *, hcookie->names, res);
+ }
+ }
+}
+
// Return true when 'incsearch' highlighting is to be done.
// Sets search_first_line and search_last_line to the address range.
static bool do_incsearch_highlighting(int firstc, int *search_delim, incsearch_state_T *s,
@@ -3037,7 +3114,7 @@ static void ui_ext_cmdline_show(CmdlineInfo *line)
line->cmdindent,
line->level);
if (line->special_char) {
- ui_call_cmdline_special_char(cchar_to_string((char)(line->special_char)),
+ ui_call_cmdline_special_char(cchar_to_string(line->special_char),
line->special_shift,
line->level);
}
@@ -3135,7 +3212,7 @@ void putcmdline(char c, int shift)
}
msg_no_more = false;
} else if (ccline.redraw_state != kCmdRedrawAll) {
- ui_call_cmdline_special_char(cchar_to_string((char)(c)), shift,
+ ui_call_cmdline_special_char(cchar_to_string(c), shift,
ccline.level);
}
cursorcmd();
@@ -4902,10 +4979,6 @@ static int ExpandFromContext(expand_T *xp, char_u *pat, int *num_file, char_u **
char *directories[] = { "syntax", "indent", "ftplugin", NULL };
return ExpandRTDir(pat, DIP_LUA, num_file, file, directories);
}
- if (xp->xp_context == EXPAND_CHECKHEALTH) {
- char *directories[] = { "autoload/health", NULL };
- return ExpandRTDir(pat, 0, num_file, file, directories);
- }
if (xp->xp_context == EXPAND_USER_LIST) {
return ExpandUserList(xp, num_file, file);
}
@@ -4982,6 +5055,7 @@ static int ExpandFromContext(expand_T *xp, char_u *pat, int *num_file, char_u **
{ EXPAND_ENV_VARS, get_env_name, true, true },
{ EXPAND_USER, get_users, true, false },
{ EXPAND_ARGLIST, get_arglist_name, true, false },
+ { EXPAND_CHECKHEALTH, get_healthcheck_names, true, false },
};
int i;
diff --git a/src/nvim/generators/c_grammar.lua b/src/nvim/generators/c_grammar.lua
index c9ab0cf709..a5f76e1c6a 100644
--- a/src/nvim/generators/c_grammar.lua
+++ b/src/nvim/generators/c_grammar.lua
@@ -17,7 +17,7 @@ local fill = ws ^ 0
local c_comment = P('//') * (not_nl ^ 0)
local c_preproc = P('#') * (not_nl ^ 0)
local typed_container =
- (P('ArrayOf(') + P('DictionaryOf(')) * ((any - P(')')) ^ 1) * P(')')
+ (P('ArrayOf(') + P('DictionaryOf(') + P('Dict(')) * ((any - P(')')) ^ 1) * P(')')
local c_id = (
typed_container +
(letter * (alpha ^ 0))
diff --git a/src/nvim/generators/gen_api_dispatch.lua b/src/nvim/generators/gen_api_dispatch.lua
index 99d80cdebc..e38a0af0ec 100644
--- a/src/nvim/generators/gen_api_dispatch.lua
+++ b/src/nvim/generators/gen_api_dispatch.lua
@@ -33,6 +33,10 @@ local function_names = {}
local c_grammar = require('generators.c_grammar')
+local function startswith(String,Start)
+ return string.sub(String,1,string.len(Start))==Start
+end
+
-- read each input file, parse and append to the api metadata
for i = 6, #arg do
local full_path = arg[i]
@@ -47,7 +51,8 @@ for i = 6, #arg do
local tmp = c_grammar.grammar:match(input:read('*all'))
for j = 1, #tmp do
local fn = tmp[j]
- if not fn.noexport then
+ local public = startswith(fn.name, "nvim_") or fn.deprecated_since
+ if public and not fn.noexport then
functions[#functions + 1] = tmp[j]
function_names[fn.name] = true
if #fn.parameters ~= 0 and fn.parameters[1][2] == 'channel_id' then
@@ -76,10 +81,6 @@ local function shallowcopy(orig)
return copy
end
-local function startswith(String,Start)
- return string.sub(String,1,string.len(Start))==Start
-end
-
-- Export functions under older deprecated names.
-- These will be removed eventually.
local deprecated_aliases = require("api.dispatch_deprecated")
@@ -108,9 +109,10 @@ for _,f in ipairs(shallowcopy(functions)) do
f.lua = f.lua_only or not f.remote_only
f.eval = (not f.lua_only) and (not f.remote_only)
else
+ f.deprecated_since = tonumber(f.deprecated_since)
+ assert(f.deprecated_since == 1)
f.remote = true
f.since = 0
- f.deprecated_since = 1
end
f.method = ismethod
local newname = deprecated_aliases[f.name]
@@ -152,6 +154,8 @@ for _,f in ipairs(functions) do
for i,param in ipairs(f.parameters) do
if param[1] == "DictionaryOf(LuaRef)" then
param = {"Dictionary", param[2]}
+ elseif startswith(param[1], "Dict(") then
+ param = {"Dictionary", param[2]}
end
f_exported.parameters[i] = param
end
@@ -173,7 +177,10 @@ local output = io.open(dispatch_outputf, 'wb')
local function real_type(type)
local rv = type
- if c_grammar.typed_container:match(rv) then
+ local rmatch = string.match(type, "Dict%(([_%w]+)%)")
+ if rmatch then
+ return "KeyDict_"..rmatch
+ elseif c_grammar.typed_container:match(rv) then
if rv:match('Array') then
rv = 'Array'
else
@@ -209,8 +216,9 @@ for i = 1, #functions do
-- Declare/initialize variables that will hold converted arguments
for j = 1, #fn.parameters do
local param = fn.parameters[j]
+ local rt = real_type(param[1])
local converted = 'arg_'..j
- output:write('\n '..param[1]..' '..converted..';')
+ output:write('\n '..rt..' '..converted..';')
end
output:write('\n')
output:write('\n if (args.size != '..#fn.parameters..') {')
@@ -225,7 +233,24 @@ for i = 1, #functions do
param = fn.parameters[j]
converted = 'arg_'..j
local rt = real_type(param[1])
- if rt ~= 'Object' then
+ if rt == 'Object' then
+ output:write('\n '..converted..' = args.items['..(j - 1)..'];\n')
+ elseif rt:match('^KeyDict_') then
+ converted = '&' .. converted
+ output:write('\n if (args.items['..(j - 1)..'].type == kObjectTypeDictionary) {') --luacheck: ignore 631
+ output:write('\n memset('..converted..', 0, sizeof(*'..converted..'));') -- TODO: neeeee
+ output:write('\n if (!api_dict_to_keydict('..converted..', '..rt..'_get_field, args.items['..(j - 1)..'].data.dictionary, error)) {')
+ output:write('\n goto cleanup;')
+ output:write('\n }')
+ output:write('\n } else if (args.items['..(j - 1)..'].type == kObjectTypeArray && args.items['..(j - 1)..'].data.array.size == 0) {') --luacheck: ignore 631
+ output:write('\n memset('..converted..', 0, sizeof(*'..converted..'));')
+
+ output:write('\n } else {')
+ output:write('\n api_set_error(error, kErrorTypeException, \
+ "Wrong type for argument '..j..' when calling '..fn.name..', expecting '..param[1]..'");')
+ output:write('\n goto cleanup;')
+ output:write('\n }\n')
+ else
if rt:match('^Buffer$') or rt:match('^Window$') or rt:match('^Tabpage$') then
-- Buffer, Window, and Tabpage have a specific type, but are stored in integer
output:write('\n if (args.items['..
@@ -257,10 +282,7 @@ for i = 1, #functions do
"Wrong type for argument '..j..' when calling '..fn.name..', expecting '..param[1]..'");')
output:write('\n goto cleanup;')
output:write('\n }\n')
- else
- output:write('\n '..converted..' = args.items['..(j - 1)..'];\n')
end
-
args[#args + 1] = converted
end
@@ -423,13 +445,24 @@ local function process_function(fn)
if param[1] == "DictionaryOf(LuaRef)" then
extra = "true, "
end
+ local errshift = 0
+ if string.match(param_type, '^KeyDict_') then
+ write_shifted_output(output, string.format([[
+ %s %s = { 0 }; nlua_pop_keydict(lstate, &%s, %s_get_field, %s&err);]], param_type, cparam, cparam, param_type, extra))
+ cparam = '&'..cparam
+ errshift = 1 -- free incomplete dict on error
+ else
+ write_shifted_output(output, string.format([[
+ const %s %s = nlua_pop_%s(lstate, %s&err);]], param[1], cparam, param_type, extra))
+ end
+
write_shifted_output(output, string.format([[
- const %s %s = nlua_pop_%s(lstate, %s&err);
if (ERROR_SET(&err)) {
goto exit_%u;
}
- ]], param[1], cparam, param_type, extra, #fn.parameters - j))
+
+ ]], #fn.parameters - j + errshift))
free_code[#free_code + 1] = ('api_free_%s(%s);'):format(
lc_param_type, cparam)
cparams = cparam .. ', ' .. cparams
@@ -446,7 +479,7 @@ local function process_function(fn)
for i = 1, #free_code do
local rev_i = #free_code - i + 1
local code = free_code[rev_i]
- if i == 1 then
+ if i == 1 and not string.match(real_type(fn.parameters[1][1]), '^KeyDict_') then
free_at_exit_code = free_at_exit_code .. ('\n %s'):format(code)
else
free_at_exit_code = free_at_exit_code .. ('\n exit_%u:\n %s'):format(
diff --git a/src/nvim/generators/gen_declarations.lua b/src/nvim/generators/gen_declarations.lua
index 0782c8115d..97491679a4 100755
--- a/src/nvim/generators/gen_declarations.lua
+++ b/src/nvim/generators/gen_declarations.lua
@@ -60,7 +60,7 @@ local right_word = concat(
)
local word = branch(
concat(
- branch(lit('ArrayOf('), lit('DictionaryOf(')), -- typed container macro
+ branch(lit('ArrayOf('), lit('DictionaryOf('), lit('Dict(')), -- typed container macro
one_or_more(any_character - lit(')')),
lit(')')
),
diff --git a/src/nvim/generators/gen_keysets.lua b/src/nvim/generators/gen_keysets.lua
new file mode 100644
index 0000000000..63ef202fe1
--- /dev/null
+++ b/src/nvim/generators/gen_keysets.lua
@@ -0,0 +1,67 @@
+
+local nvimsrcdir = arg[1]
+local shared_file = arg[2]
+local funcs_file = arg[3]
+local defs_file = arg[4]
+
+_G.vim = loadfile(shared_file)()
+
+if nvimsrcdir == '--help' then
+ print([[
+Usage:
+ lua gen_keyset.lua TODOFIXUPDATETHIS
+
+Will generate build/src/nvim/auto/keyset.generated.h with definition of functions
+static const array.
+]])
+ os.exit(0)
+end
+
+
+package.path = nvimsrcdir .. '/?.lua;' .. package.path
+local hashy = require'generators.hashy'
+
+local funcspipe = io.open(funcs_file, 'wb')
+local defspipe = io.open(defs_file, 'wb')
+
+local keysets = require'api.keysets'
+
+for name, keys in pairs(keysets) do
+ local neworder, hashfun = hashy.hashy_hash(name, keys, function (idx)
+ return name.."_table["..idx.."].str"
+ end)
+
+ defspipe:write("typedef struct {\n")
+ for _, key in ipairs(neworder) do
+ defspipe:write(" Object "..key..";\n")
+ end
+ defspipe:write("} KeyDict_"..name..";\n\n")
+
+ defspipe:write("extern KeySetLink "..name.."_table[];\n")
+
+ funcspipe:write("KeySetLink "..name.."_table[] = {\n")
+ for _, key in ipairs(neworder) do
+ funcspipe:write(' {"'..key..'", offsetof(KeyDict_'..name..", "..key..")},\n")
+ end
+ funcspipe:write(' {NULL, 0},\n')
+ funcspipe:write("};\n\n")
+
+ funcspipe:write(hashfun)
+
+ funcspipe:write([[
+Object *KeyDict_]]..name..[[_get_field(void *retval, const char *str, size_t len)
+{
+ int hash = ]]..name..[[_hash(str, len);
+ if (hash == -1) {
+ return NULL;
+ }
+
+ return (Object *)((char *)retval + ]]..name..[[_table[hash].ptr_off);
+}
+
+]])
+ defspipe:write("#define api_free_keydict_"..name.."(x) api_free_keydict(x, "..name.."_table)\n")
+end
+
+funcspipe:close()
+defspipe:close()
diff --git a/src/nvim/generators/hashy.lua b/src/nvim/generators/hashy.lua
new file mode 100644
index 0000000000..fac24c810a
--- /dev/null
+++ b/src/nvim/generators/hashy.lua
@@ -0,0 +1,122 @@
+-- HASHY McHASHFACE
+
+local M = {}
+_G.d = M
+
+
+local function setdefault(table, key)
+ local val = table[key]
+ if val == nil then
+ val = {}
+ table[key] = val
+ end
+ return val
+end
+
+function M.build_pos_hash(strings)
+ local len_buckets = {}
+ local maxlen = 0
+ for _,s in ipairs(strings) do
+ table.insert(setdefault(len_buckets, #s),s)
+ if #s > maxlen then maxlen = #s end
+ end
+
+ local len_pos_buckets = {}
+ local worst_buck_size = 0
+
+ for len = 1,maxlen do
+ local strs = len_buckets[len]
+ if strs then
+ -- the best position so far generates `best_bucket`
+ -- with `minsize` worst case collisions
+ local bestpos, minsize, best_bucket = nil, #strs*2, nil
+ for pos = 1,len do
+ local try_bucket = {}
+ for _,str in ipairs(strs) do
+ local poschar = string.sub(str, pos, pos)
+ table.insert(setdefault(try_bucket, poschar), str)
+ end
+ local maxsize = 1
+ for _,pos_strs in pairs(try_bucket) do
+ maxsize = math.max(maxsize, #pos_strs)
+ end
+ if maxsize < minsize then
+ bestpos = pos
+ minsize = maxsize
+ best_bucket = try_bucket
+ end
+ end
+ len_pos_buckets[len] = {bestpos, best_bucket}
+ worst_buck_size = math.max(worst_buck_size, minsize)
+ end
+ end
+ return len_pos_buckets, maxlen, worst_buck_size
+end
+
+function M.switcher(put, tab, maxlen, worst_buck_size)
+ local neworder = {}
+ put " switch (len) {\n"
+ local bucky = worst_buck_size > 1
+ for len = 1,maxlen do
+ local vals = tab[len]
+ if vals then
+ put(" case "..len..": ")
+ local pos, posbuck = unpack(vals)
+ local keys = vim.tbl_keys(posbuck)
+ if #keys > 1 then
+ table.sort(keys)
+ put("switch (str["..(pos-1).."]) {\n")
+ for _,c in ipairs(keys) do
+ local buck = posbuck[c]
+ local startidx = #neworder
+ vim.list_extend(neworder, buck)
+ local endidx = #neworder
+ put(" case '"..c.."': ")
+ put("low = "..startidx.."; ")
+ if bucky then put("high = "..endidx.."; ") end
+ put "break;\n"
+ end
+ put " default: break;\n"
+ put " }\n "
+ else
+ local startidx = #neworder
+ table.insert(neworder, posbuck[keys[1]][1])
+ local endidx = #neworder
+ put("low = "..startidx.."; ")
+ if bucky then put("high = "..endidx.."; ") end
+ end
+ put " break;\n"
+ end
+ end
+ put " default: break;\n"
+ put " }\n"
+ return neworder
+end
+
+function M.hashy_hash(name, strings, access)
+ local stats = {}
+ local put = function(str) table.insert(stats, str) end
+ local len_pos_buckets, maxlen, worst_buck_size = M.build_pos_hash(strings)
+ put("int "..name.."_hash(const char *str, size_t len)\n{\n")
+ if worst_buck_size > 1 then
+ put(" int low = 0, high = 0;\n")
+ else
+ put(" int low = -1;\n")
+ end
+ local neworder = M.switcher(put, len_pos_buckets, maxlen, worst_buck_size)
+ if worst_buck_size > 1 then
+ error [[ not implemented yet ]] -- TODO(bfredl)
+ else
+ put [[
+ if (low < 0) {
+ return -1;
+ }
+ ]]
+ put("if(memcmp(str, "..access("low")..", len)) {\n return -1;\n }\n")
+ put " return low;\n"
+ put "}\n\n"
+ end
+ return neworder, table.concat(stats)
+end
+
+return M
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index beb4ff4da6..f5f8a307d1 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -523,7 +523,7 @@ void restoreRedobuff(save_redo_T *save_redo)
void AppendToRedobuff(const char *s)
{
if (!block_redo) {
- add_buff(&redobuff, (const char *)s, -1L);
+ add_buff(&redobuff, s, -1L);
}
}
@@ -1000,6 +1000,18 @@ void ins_char_typebuf(int c)
buf[3] = NUL;
} else {
buf[utf_char2bytes(c, buf)] = NUL;
+ char_u *p = buf;
+ while (*p) {
+ if ((uint8_t)(*p) == CSI || (uint8_t)(*p) == K_SPECIAL) {
+ bool is_csi = (uint8_t)(*p) == CSI;
+ memmove(p + 3, p + 1, STRLEN(p + 1) + 1);
+ *p++ = K_SPECIAL;
+ *p++ = is_csi ? KS_EXTRA : KS_SPECIAL;
+ *p++ = is_csi ? KE_CSI : KE_FILLER;
+ } else {
+ p++;
+ }
+ }
}
(void)ins_typebuf(buf, KeyNoremap, 0, !KeyTyped, cmd_silent);
}
@@ -1558,7 +1570,7 @@ int vgetc(void)
// a CSI (0x9B),
// of a K_SPECIAL - KS_EXTRA - KE_CSI, which is CSI too.
c = vgetorpeek(true);
- if (vgetorpeek(true) == (int)KE_CSI && c == KS_EXTRA) {
+ if (vgetorpeek(true) == KE_CSI && c == KS_EXTRA) {
buf[i] = CSI;
}
}
@@ -1573,9 +1585,9 @@ int vgetc(void)
if (!no_mapping && KeyTyped
&& (mod_mask == MOD_MASK_ALT || mod_mask == MOD_MASK_META)) {
mod_mask = 0;
- stuffcharReadbuff(c);
- u_sync(false);
- c = ESC;
+ ins_char_typebuf(c);
+ ins_char_typebuf(ESC);
+ continue;
}
break;
@@ -1934,7 +1946,7 @@ static int vgetorpeek(bool advance)
&& (mp->m_keys[0] != K_SPECIAL
|| mp->m_keys[1] != KS_EXTRA
|| mp->m_keys[2]
- != (int)KE_SNR)) {
+ != KE_SNR)) {
continue;
}
/*
@@ -2216,7 +2228,7 @@ static int vgetorpeek(bool advance)
if (!ascii_iswhite(ptr[col])) {
curwin->w_wcol = vcol;
}
- vcol += lbr_chartabsize(ptr, ptr + col, (colnr_T)vcol);
+ vcol += lbr_chartabsize(ptr, ptr + col, vcol);
col += utfc_ptr2len(ptr + col);
}
curwin->w_wrow = curwin->w_cline_row
@@ -2849,7 +2861,7 @@ int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev, buf_T
}
char_u *lhs = (char_u *)&args->lhs;
- char_u *rhs = (char_u *)args->rhs;
+ char_u *rhs = args->rhs;
char_u *orig_rhs = args->orig_rhs;
// check arguments and translate function keys
diff --git a/src/nvim/getchar.h b/src/nvim/getchar.h
index f0b52079aa..83fa00977f 100644
--- a/src/nvim/getchar.h
+++ b/src/nvim/getchar.h
@@ -56,6 +56,8 @@ struct map_arguments {
size_t orig_rhs_len;
};
typedef struct map_arguments MapArguments;
+#define MAP_ARGUMENTS_INIT { false, false, false, false, false, false, false, \
+ { 0 }, 0, NULL, 0, false, NULL, 0 }
#define KEYLEN_PART_KEY -1 // keylen value for incomplete key-code
#define KEYLEN_PART_MAP -2 // keylen value for incomplete mapping
diff --git a/src/nvim/hardcopy.c b/src/nvim/hardcopy.c
index df2c494ace..9d9ffa550a 100644
--- a/src/nvim/hardcopy.c
+++ b/src/nvim/hardcopy.c
@@ -643,12 +643,8 @@ void ex_hardcopy(exarg_T *eap)
* PS.)
*/
if (mch_print_init(&settings,
- curbuf->b_fname == NULL
- ? (char_u *)buf_spname(curbuf)
- : curbuf->b_sfname == NULL
- ? curbuf->b_fname
- : curbuf->b_sfname,
- eap->forceit) == FAIL) {
+ curbuf->b_fname == NULL ? buf_spname(curbuf) : curbuf->b_sfname ==
+ NULL ? curbuf->b_fname : curbuf->b_sfname, eap->forceit) == FAIL) {
return;
}
diff --git a/src/nvim/if_cscope.c b/src/nvim/if_cscope.c
index 31615e744a..76dcb58236 100644
--- a/src/nvim/if_cscope.c
+++ b/src/nvim/if_cscope.c
@@ -9,31 +9,29 @@
* might be a few lines of code that look similar to what Nvi has.
*/
-#include <stdbool.h>
-
#include <assert.h>
#include <errno.h>
-#include <inttypes.h>
#include <fcntl.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <sys/stat.h>
+#include <sys/types.h>
-#include "nvim/buffer.h"
#include "nvim/ascii.h"
-#include "nvim/if_cscope.h"
+#include "nvim/buffer.h"
#include "nvim/charset.h"
+#include "nvim/event/stream.h"
#include "nvim/fileio.h"
-#include "nvim/message.h"
+#include "nvim/if_cscope.h"
#include "nvim/memory.h"
+#include "nvim/message.h"
+#include "nvim/os/input.h"
+#include "nvim/os/os.h"
#include "nvim/os/time.h"
#include "nvim/path.h"
#include "nvim/quickfix.h"
#include "nvim/strings.h"
#include "nvim/tag.h"
-#include "nvim/os/os.h"
-#include "nvim/os/input.h"
-#include "nvim/event/stream.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
#if defined(UNIX)
# include <sys/wait.h>
#endif
@@ -90,19 +88,20 @@ char_u *get_cscope_name(expand_T *xp, int idx)
// Complete with sub-commands of ":cscope":
// add, find, help, kill, reset, show
return (char_u *)cs_cmds[idx].name;
- case EXP_SCSCOPE_SUBCMD:
- {
+ case EXP_SCSCOPE_SUBCMD: {
// Complete with sub-commands of ":scscope": same sub-commands as
// ":cscope" but skip commands which don't support split windows
int i;
- for (i = 0, current_idx = 0; cs_cmds[i].name != NULL; i++)
- if (cs_cmds[i].cansplit)
- if (current_idx++ == idx)
+ for (i = 0, current_idx = 0; cs_cmds[i].name != NULL; i++) {
+ if (cs_cmds[i].cansplit) {
+ if (current_idx++ == idx) {
break;
+ }
+ }
+ }
return (char_u *)cs_cmds[i].name;
}
- case EXP_CSCOPE_FIND:
- {
+ case EXP_CSCOPE_FIND: {
const char *query_type[] =
{
"a", "c", "d", "e", "f", "g", "i", "s", "t", NULL
@@ -114,8 +113,7 @@ char_u *get_cscope_name(expand_T *xp, int idx)
// redundant.
return (char_u *)query_type[idx];
}
- case EXP_CSCOPE_KILL:
- {
+ case EXP_CSCOPE_KILL: {
static char connection[5];
// ":cscope kill" accepts connection numbers or partial names of
@@ -124,8 +122,9 @@ char_u *get_cscope_name(expand_T *xp, int idx)
// connections.
size_t i;
for (i = 0, current_idx = 0; i < csinfo_size; i++) {
- if (csinfo[i].fname == NULL)
+ if (csinfo[i].fname == NULL) {
continue;
+ }
if (current_idx++ == idx) {
vim_snprintf(connection, sizeof(connection), "%zu", i);
return (char_u *)connection;
@@ -172,11 +171,9 @@ void set_context_in_cscope_cmd(expand_T *xp, const char *arg, cmdidx_T cmdidx)
/// Find the command, print help if invalid, and then call the corresponding
/// command function.
-static void
-do_cscope_general(
- exarg_T *eap,
- int make_split // whether to split window
-)
+///
+/// @param make_split whether to split window
+static void do_cscope_general(exarg_T *eap, int make_split)
{
cscmd_T *cmdp;
@@ -187,8 +184,7 @@ do_cscope_general(
if (make_split) {
if (!cmdp->cansplit) {
- (void)MSG_PUTS(_(
- "This cscope command does not support splitting the window.\n"));
+ (void)MSG_PUTS(_("This cscope command does not support splitting the window.\n"));
return;
}
postponed_split = -1;
@@ -228,14 +224,16 @@ void ex_cstag(exarg_T *eap)
case 0:
if (cs_check_for_connections()) {
ret = cs_find_common("g", (char *)(eap->arg), eap->forceit, FALSE,
- FALSE, *eap->cmdlinep);
+ FALSE, *eap->cmdlinep);
if (ret == FALSE) {
cs_free_tags();
- if (msg_col)
+ if (msg_col) {
msg_putchar('\n');
+ }
- if (cs_check_for_tags())
+ if (cs_check_for_tags()) {
ret = do_tag(eap->arg, DT_JUMP, 0, eap->forceit, FALSE);
+ }
}
} else if (cs_check_for_tags()) {
ret = do_tag(eap->arg, DT_JUMP, 0, eap->forceit, FALSE);
@@ -245,21 +243,24 @@ void ex_cstag(exarg_T *eap)
if (cs_check_for_tags()) {
ret = do_tag(eap->arg, DT_JUMP, 0, eap->forceit, FALSE);
if (ret == FALSE) {
- if (msg_col)
+ if (msg_col) {
msg_putchar('\n');
+ }
if (cs_check_for_connections()) {
ret = cs_find_common("g", (char *)(eap->arg), eap->forceit,
- FALSE, FALSE, *eap->cmdlinep);
- if (ret == FALSE)
+ FALSE, FALSE, *eap->cmdlinep);
+ if (ret == FALSE) {
cs_free_tags();
+ }
}
}
} else if (cs_check_for_connections()) {
ret = cs_find_common("g", (char *)(eap->arg), eap->forceit, FALSE,
- FALSE, *eap->cmdlinep);
- if (ret == FALSE)
+ FALSE, *eap->cmdlinep);
+ if (ret == FALSE) {
cs_free_tags();
+ }
}
break;
default:
@@ -306,29 +307,29 @@ void cs_print_tags(void)
/*
* "cscope_connection([{num} , {dbpath} [, {prepend}]])" function
*
- * Checks for the existence of a |cscope| connection. If no
- * parameters are specified, then the function returns:
+ * Checks for the existence of a |cscope| connection. If no
+ * parameters are specified, then the function returns:
*
- * 0, if cscope was not available (not compiled in), or if there
- * are no cscope connections; or
- * 1, if there is at least one cscope connection.
+ * 0, if cscope was not available (not compiled in), or if there
+ * are no cscope connections; or
+ * 1, if there is at least one cscope connection.
*
- * If parameters are specified, then the value of {num}
- * determines how existence of a cscope connection is checked:
+ * If parameters are specified, then the value of {num}
+ * determines how existence of a cscope connection is checked:
*
- * {num} Description of existence check
- * ----- ------------------------------
- * 0 Same as no parameters (e.g., "cscope_connection()").
- * 1 Ignore {prepend}, and use partial string matches for
- * {dbpath}.
- * 2 Ignore {prepend}, and use exact string matches for
- * {dbpath}.
- * 3 Use {prepend}, use partial string matches for both
- * {dbpath} and {prepend}.
- * 4 Use {prepend}, use exact string matches for both
- * {dbpath} and {prepend}.
+ * {num} Description of existence check
+ * ----- ------------------------------
+ * 0 Same as no parameters (e.g., "cscope_connection()").
+ * 1 Ignore {prepend}, and use partial string matches for
+ * {dbpath}.
+ * 2 Ignore {prepend}, and use exact string matches for
+ * {dbpath}.
+ * 3 Use {prepend}, use partial string matches for both
+ * {dbpath} and {prepend}.
+ * 4 Use {prepend}, use exact string matches for both
+ * {dbpath} and {prepend}.
*
- * Note: All string comparisons are case sensitive!
+ * Note: All string comparisons are case sensitive!
*/
bool cs_connection(int num, char_u *dbpath, char_u *ppath)
{
@@ -393,8 +394,9 @@ static int cs_add(exarg_T *eap)
cs_usage_msg(Add);
return CSCOPE_FAILURE;
}
- if ((ppath = strtok((char *)NULL, (const char *)" ")) != NULL)
+ if ((ppath = strtok((char *)NULL, (const char *)" ")) != NULL) {
flags = strtok((char *)NULL, (const char *)" ");
+ }
return cs_add_common(fname, ppath, flags);
}
@@ -413,18 +415,16 @@ static void cs_stat_emsg(char *fname)
/// The common routine to add a new cscope connection. Called by
/// cs_add() and cs_reset(). I really don't like to do this, but this
/// routine uses a number of goto statements.
-static int
-cs_add_common(
- char *arg1, // filename - may contain environment variables
- char *arg2, // prepend path - may contain environment variables
- char *flags
-)
+///
+/// @param arg1 filename - may contain environment variables
+/// @param arg2 prepend path - may contain environment variables
+static int cs_add_common(char *arg1, char *arg2, char *flags)
{
- char *fname = NULL;
- char *fname2 = NULL;
- char *ppath = NULL;
+ char *fname = NULL;
+ char *fname2 = NULL;
+ char *ppath = NULL;
size_t usedlen = 0;
- char_u *fbuf = NULL;
+ char_u *fbuf = NULL;
// get the filename (arg1), expand it, and try to stat it
fname = xmalloc(MAXPATHL + 1);
@@ -443,8 +443,9 @@ cs_add_common(
bool file_info_ok = os_fileinfo(fname, &file_info);
if (!file_info_ok) {
staterr:
- if (p_csverbose)
+ if (p_csverbose) {
cs_stat_emsg(fname);
+ }
goto add_err;
}
@@ -465,31 +466,32 @@ staterr:
while (fname[strlen(fname)-1] == '/'
) {
fname[strlen(fname)-1] = '\0';
- if (fname[0] == '\0')
+ if (fname[0] == '\0') {
break;
+ }
}
- if (fname[0] == '\0')
+ if (fname[0] == '\0') {
(void)sprintf(fname2, "/%s", CSCOPE_DBFILE);
- else
+ } else {
(void)sprintf(fname2, "%s/%s", fname, CSCOPE_DBFILE);
+ }
file_info_ok = os_fileinfo(fname2, &file_info);
if (!file_info_ok) {
- if (p_csverbose)
+ if (p_csverbose) {
cs_stat_emsg(fname2);
+ }
goto add_err;
}
i = cs_insert_filelist(fname2, ppath, flags, &file_info);
- }
- else if (S_ISREG(file_info.stat.st_mode) || S_ISLNK(file_info.stat.st_mode))
- {
+ } else if (S_ISREG(file_info.stat.st_mode) || S_ISLNK(file_info.stat.st_mode)) {
i = cs_insert_filelist(fname, ppath, flags, &file_info);
} else {
- if (p_csverbose)
- (void)EMSG2(
- _("E564: %s is not a directory or a valid cscope database"),
- fname);
+ if (p_csverbose) {
+ (void)EMSG2(_("E564: %s is not a directory or a valid cscope database"),
+ fname);
+ }
goto add_err;
}
@@ -538,15 +540,15 @@ static size_t cs_cnt_connections(void)
size_t cnt = 0;
for (size_t i = 0; i < csinfo_size; i++) {
- if (csinfo[i].fname != NULL)
+ if (csinfo[i].fname != NULL) {
cnt++;
+ }
}
return cnt;
}
-static void cs_reading_emsg(
- size_t idx // connection index
-)
+/// @param idx connection index
+static void cs_reading_emsg(size_t idx)
{
EMSGU(_("E262: error reading cscope connection %" PRIu64), idx);
}
@@ -582,7 +584,7 @@ static int cs_cnt_matches(size_t idx)
// Accept "\S*cscope: X lines", also matches "mlcscope".
// Bail out for the "Unable to search" error.
if (strstr((const char *)buf, "Unable to search database") != NULL) {
- break;
+ break;
}
if ((stok = strtok(buf, (const char *)" ")) == NULL) {
continue;
@@ -591,18 +593,21 @@ static int cs_cnt_matches(size_t idx)
continue;
}
- if ((stok = strtok(NULL, (const char *)" ")) == NULL)
+ if ((stok = strtok(NULL, (const char *)" ")) == NULL) {
continue;
+ }
nlines = atoi(stok);
if (nlines < 0) {
nlines = 0;
break;
}
- if ((stok = strtok(NULL, (const char *)" ")) == NULL)
+ if ((stok = strtok(NULL, (const char *)" ")) == NULL) {
continue;
- if (strncmp((const char *)stok, "lines", 5))
+ }
+ if (strncmp((const char *)stok, "lines", 5)) {
continue;
+ }
break;
}
@@ -620,31 +625,40 @@ static char *cs_create_cmd(char *csoption, char *pattern)
char *pat;
switch (csoption[0]) {
- case '0': case 's':
+ case '0':
+ case 's':
search = 0;
break;
- case '1': case 'g':
+ case '1':
+ case 'g':
search = 1;
break;
- case '2': case 'd':
+ case '2':
+ case 'd':
search = 2;
break;
- case '3': case 'c':
+ case '3':
+ case 'c':
search = 3;
break;
- case '4': case 't':
+ case '4':
+ case 't':
search = 4;
break;
- case '6': case 'e':
+ case '6':
+ case 'e':
search = 6;
break;
- case '7': case 'f':
+ case '7':
+ case 'f':
search = 7;
break;
- case '8': case 'i':
+ case '8':
+ case 'i':
search = 8;
break;
- case '9': case 'a':
+ case '9':
+ case 'a':
search = 9;
break;
default:
@@ -656,9 +670,11 @@ static char *cs_create_cmd(char *csoption, char *pattern)
// Skip white space before the patter, except for text and pattern search,
// they may want to use the leading white space.
pat = pattern;
- if (search != 4 && search != 6)
- while (ascii_iswhite(*pat))
+ if (search != 4 && search != 6) {
+ while (ascii_iswhite(*pat)) {
++pat;
+ }
+ }
cmd = xmalloc(strlen(pat) + 2);
@@ -675,7 +691,7 @@ static int cs_create_connection(size_t i)
#ifdef UNIX
int to_cs[2], from_cs[2];
#endif
- char *prog, *cmd, *ppath = NULL;
+ char *prog, *cmd, *ppath = NULL;
#if defined(UNIX)
/*
@@ -686,14 +702,18 @@ static int cs_create_connection(size_t i)
if (pipe(to_cs) < 0 || pipe(from_cs) < 0) {
(void)EMSG(_("E566: Could not create cscope pipes"));
err_closing:
- if (to_cs[0] != -1)
+ if (to_cs[0] != -1) {
(void)close(to_cs[0]);
- if (to_cs[1] != -1)
+ }
+ if (to_cs[1] != -1) {
(void)close(to_cs[1]);
- if (from_cs[0] != -1)
+ }
+ if (from_cs[0] != -1) {
(void)close(from_cs[0]);
- if (from_cs[1] != -1)
+ }
+ if (from_cs[1] != -1) {
(void)close(from_cs[1]);
+ }
return CSCOPE_FAILURE;
}
@@ -759,8 +779,9 @@ err_closing:
len += strlen(ppath);
}
- if (csinfo[i].flags)
+ if (csinfo[i].flags) {
len += strlen(csinfo[i].flags);
+ }
cmd = xmalloc(len);
@@ -779,10 +800,10 @@ err_closing:
(void)strcat(cmd, " ");
(void)strcat(cmd, csinfo[i].flags);
}
-# ifdef UNIX
+#ifdef UNIX
// on Win32 we still need prog
xfree(prog);
-# endif
+#endif
xfree(ppath);
#if defined(UNIX)
@@ -791,12 +812,14 @@ err_closing:
# if defined(HAVE_SETSID)
(void)setsid();
# else
- if (setpgid(0, 0) == -1)
+ if (setpgid(0, 0) == -1) {
PERROR(_("cs_create_connection setpgid failed"));
+ }
# endif
# endif
- if (execl("/bin/sh", "sh", "-c", cmd, (char *)NULL) == -1)
+ if (execl("/bin/sh", "sh", "-c", cmd, (char *)NULL) == -1) {
PERROR(_("cs_create_connection exec failed"));
+ }
exit(127);
// NOTREACHED
@@ -827,7 +850,7 @@ err_closing:
si.hStdError = stdout_wr;
si.hStdInput = stdin_rd;
created = CreateProcess(NULL, cmd, NULL, NULL, TRUE, CREATE_NEW_CONSOLE,
- NULL, NULL, &si, &pi);
+ NULL, NULL, &si, &pi);
xfree(prog);
xfree(cmd);
@@ -888,9 +911,11 @@ static int cs_find(exarg_T *eap)
* Let's replace the NULs written by strtok() with spaces - we need the
* spaces to correctly display the quickfix/location list window's title.
*/
- for (int i = 0; i < eap_arg_len; ++i)
- if (NUL == eap->arg[i])
+ for (int i = 0; i < eap_arg_len; ++i) {
+ if (NUL == eap->arg[i]) {
eap->arg[i] = ' ';
+ }
+ }
return cs_find_common(opt, pat, eap->forceit, true,
eap->cmdidx == CMD_lcscope, *eap->cmdlinep);
@@ -898,8 +923,8 @@ static int cs_find(exarg_T *eap)
/// Common code for cscope find, shared by cs_find() and ex_cstag().
-static int cs_find_common(char *opt, char *pat, int forceit, int verbose,
- int use_ll, char_u *cmdline)
+static int cs_find_common(char *opt, char *pat, int forceit, int verbose, int use_ll,
+ char_u *cmdline)
{
char *cmd;
int *nummatches;
@@ -966,8 +991,9 @@ static int cs_find_common(char *opt, char *pat, int forceit, int verbose,
// create the actual command to send to cscope
cmd = cs_create_cmd(opt, pat);
- if (cmd == NULL)
+ if (cmd == NULL) {
return FALSE;
+ }
nummatches = xmalloc(sizeof(int) * csinfo_size);
@@ -978,8 +1004,9 @@ static int cs_find_common(char *opt, char *pat, int forceit, int verbose,
}
totmatches = 0;
for (size_t i = 0; i < csinfo_size; i++) {
- if (csinfo[i].fname == NULL || csinfo[i].to_fp == NULL)
+ if (csinfo[i].fname == NULL || csinfo[i].to_fp == NULL) {
continue;
+ }
// send cmd to cscope
(void)fprintf(csinfo[i].to_fp, "%s\n", cmd);
@@ -987,11 +1014,13 @@ static int cs_find_common(char *opt, char *pat, int forceit, int verbose,
nummatches[i] = cs_cnt_matches(i);
- if (nummatches[i] > -1)
+ if (nummatches[i] > -1) {
totmatches += (size_t)nummatches[i];
+ }
- if (nummatches[i] == 0)
+ if (nummatches[i] == 0) {
(void)cs_read_prompt(i);
+ }
}
xfree(cmd);
@@ -1014,10 +1043,10 @@ static int cs_find_common(char *opt, char *pat, int forceit, int verbose,
if (qfpos != NULL && *qfpos != '0') {
// Fill error list.
- FILE *f;
- char_u *tmp = vim_tempname();
- qf_info_T *qi = NULL;
- win_T *wp = NULL;
+ FILE *f;
+ char_u *tmp = vim_tempname();
+ qf_info_T *qi = NULL;
+ win_T *wp = NULL;
f = os_fopen((char *)tmp, "w");
if (f == NULL) {
@@ -1039,14 +1068,15 @@ static int cs_find_common(char *opt, char *pat, int forceit, int verbose,
}
apply_autocmds(EVENT_QUICKFIXCMDPOST, (char_u *)"cscope",
- curbuf->b_fname, TRUE, curbuf);
- if (use_ll)
+ curbuf->b_fname, TRUE, curbuf);
+ if (use_ll) {
/*
* In the location list window, use the displayed location
* list. Otherwise, use the location list for the window.
*/
qi = (bt_quickfix(wp->w_buffer) && wp->w_llist_ref != NULL)
? wp->w_llist_ref : wp->w_llist;
+ }
qf_jump(qi, 0, 0, forceit);
}
}
@@ -1059,11 +1089,11 @@ static int cs_find_common(char *opt, char *pat, int forceit, int verbose,
size_t matched = 0;
// read output
- cs_fill_results((char *)pat, totmatches, nummatches, &matches,
- &contexts, &matched);
+ cs_fill_results(pat, totmatches, nummatches, &matches, &contexts, &matched);
xfree(nummatches);
- if (matches == NULL)
+ if (matches == NULL) {
return FALSE;
+ }
(void)cs_manage_matches(matches, contexts, matched, Store);
@@ -1086,10 +1116,10 @@ static int cs_help(exarg_T *eap)
space_cnt = 0;
}
(void)smsg(_("%-5s: %s%*s (Usage: %s)"),
- cmdp->name,
- help, space_cnt, " ",
- cmdp->usage);
- if (strcmp(cmdp->name, "find") == 0)
+ cmdp->name,
+ help, space_cnt, " ",
+ cmdp->usage);
+ if (strcmp(cmdp->name, "find") == 0) {
MSG_PUTS(_("\n"
" a: Find assignments to this symbol\n"
" c: Find functions calling this function\n"
@@ -1100,6 +1130,7 @@ static int cs_help(exarg_T *eap)
" i: Find files #including this file\n"
" s: Find this C symbol\n"
" t: Find this text string\n"));
+ }
cmdp++;
}
@@ -1121,8 +1152,7 @@ static void clear_csinfo(size_t i)
}
/// Insert a new cscope database filename into the filelist.
-static int cs_insert_filelist(char *fname, char *ppath, char *flags,
- FileInfo *file_info)
+static int cs_insert_filelist(char *fname, char *ppath, char *flags, FileInfo *file_info)
{
size_t i = 0;
bool empty_found = false;
@@ -1130,8 +1160,9 @@ static int cs_insert_filelist(char *fname, char *ppath, char *flags,
for (size_t j = 0; j < csinfo_size; j++) {
if (csinfo[j].fname != NULL
&& os_fileid_equal_fileinfo(&(csinfo[j].file_id), file_info)) {
- if (p_csverbose)
+ if (p_csverbose) {
(void)EMSG(_("E568: duplicate cscope database not added"));
+ }
return CSCOPE_FAILURE;
}
@@ -1154,8 +1185,9 @@ static int cs_insert_filelist(char *fname, char *ppath, char *flags,
csinfo_size *= 2;
csinfo = xrealloc(csinfo, sizeof(csinfo_T)*csinfo_size);
}
- for (size_t j = csinfo_size/2; j < csinfo_size; j++)
+ for (size_t j = csinfo_size/2; j < csinfo_size; j++) {
clear_csinfo(j);
+ }
}
csinfo[i].fname = xmalloc(strlen(fname) + 1);
@@ -1165,14 +1197,16 @@ static int cs_insert_filelist(char *fname, char *ppath, char *flags,
if (ppath != NULL) {
csinfo[i].ppath = xmalloc(strlen(ppath) + 1);
(void)strcpy(csinfo[i].ppath, (const char *)ppath);
- } else
+ } else {
csinfo[i].ppath = NULL;
+ }
if (flags != NULL) {
csinfo[i].flags = xmalloc(strlen(flags) + 1);
(void)strcpy(csinfo[i].flags, (const char *)flags);
- } else
+ } else {
csinfo[i].flags = NULL;
+ }
os_fileinfo_id(file_info, &(csinfo[i].file_id));
assert(i <= INT_MAX);
@@ -1181,25 +1215,28 @@ static int cs_insert_filelist(char *fname, char *ppath, char *flags,
/// Find cscope command in command table.
-static cscmd_T * cs_lookup_cmd(exarg_T *eap)
+static cscmd_T *cs_lookup_cmd(exarg_T *eap)
{
cscmd_T *cmdp;
char *stok;
size_t len;
- if (eap->arg == NULL)
+ if (eap->arg == NULL) {
return NULL;
+ }
// Store length of eap->arg before it gets modified by strtok().
eap_arg_len = (int)STRLEN(eap->arg);
- if ((stok = strtok((char *)(eap->arg), (const char *)" ")) == NULL)
+ if ((stok = strtok((char *)(eap->arg), (const char *)" ")) == NULL) {
return NULL;
+ }
len = strlen(stok);
for (cmdp = cs_cmds; cmdp->name != NULL; ++cmdp) {
- if (strncmp((const char *)(stok), cmdp->name, len) == 0)
+ if (strncmp((const char *)(stok), cmdp->name, len) == 0) {
return cmdp;
+ }
}
return NULL;
}
@@ -1224,21 +1261,23 @@ static int cs_kill(exarg_T *eap)
|| (strlen(stok) < 3 && stok[0] == '-'
&& ascii_isdigit((int)(stok[1])))) {
num = atoi(stok);
- if (num == -1)
+ if (num == -1) {
killall = true;
- else if (num >= 0) {
+ } else if (num >= 0) {
i = (size_t)num;
} else { // All negative values besides -1 are invalid.
- if (p_csverbose)
+ if (p_csverbose) {
(void)EMSG2(_("E261: cscope connection %s not found"), stok);
+ }
return CSCOPE_FAILURE;
}
} else {
// Else it must be part of a name. We will try to find a match
// within all the names in the csinfo data structure
for (i = 0; i < csinfo_size; i++) {
- if (csinfo[i].fname != NULL && strstr(csinfo[i].fname, stok))
+ if (csinfo[i].fname != NULL && strstr(csinfo[i].fname, stok)) {
break;
+ }
}
}
@@ -1250,8 +1289,9 @@ static int cs_kill(exarg_T *eap)
} else {
if (killall) {
for (i = 0; i < csinfo_size; i++) {
- if (csinfo[i].fname)
+ if (csinfo[i].fname) {
cs_kill_execute(i, csinfo[i].fname);
+ }
}
} else {
cs_kill_execute((size_t)i, stok);
@@ -1263,10 +1303,10 @@ static int cs_kill(exarg_T *eap)
/// Actually kills a specific cscope connection.
-static void cs_kill_execute(
- size_t i, // cscope table index
- char *cname // cscope database name
-)
+///
+/// @param i cscope table index
+/// @param cname cscope database name
+static void cs_kill_execute(size_t i, char *cname)
{
if (p_csverbose) {
msg_clr_eos();
@@ -1293,8 +1333,7 @@ static void cs_kill_execute(
/// Besides, even if this particular case didn't happen, the search pattern
/// would still have to be modified to escape all the special regular expression
/// characters to comply with ctags formatting.
-static char *cs_make_vim_style_matches(char *fname, char *slno, char *search,
- char *tagstr)
+static char *cs_make_vim_style_matches(char *fname, char *slno, char *search, char *tagstr)
{
// vim style is ctags:
//
@@ -1339,8 +1378,7 @@ static char *cs_make_vim_style_matches(char *fname, char *slno, char *search,
/// Free: frees up everything and resets
///
/// Print: prints the tags
-static char *cs_manage_matches(char **matches, char **contexts,
- size_t totmatches, mcmd_e cmd)
+static char *cs_manage_matches(char **matches, char **contexts, size_t totmatches, mcmd_e cmd)
{
static char **mp = NULL;
static char **cp = NULL;
@@ -1352,16 +1390,18 @@ static char *cs_manage_matches(char **matches, char **contexts,
case Store:
assert(matches != NULL);
assert(totmatches > 0);
- if (mp != NULL || cp != NULL)
+ if (mp != NULL || cp != NULL) {
(void)cs_manage_matches(NULL, NULL, 0, Free);
+ }
mp = matches;
cp = contexts;
cnt = totmatches;
next = 0;
break;
case Get:
- if (next >= cnt)
+ if (next >= cnt) {
return NULL;
+ }
p = mp[next];
next++;
@@ -1370,8 +1410,9 @@ static char *cs_manage_matches(char **matches, char **contexts,
if (mp != NULL) {
while (cnt--) {
xfree(mp[cnt]);
- if (cp != NULL)
+ if (cp != NULL) {
xfree(cp[cnt]);
+ }
}
xfree(mp);
xfree(cp);
@@ -1396,8 +1437,8 @@ static char *cs_manage_matches(char **matches, char **contexts,
/// Parse cscope output.
-static char *cs_parse_results(size_t cnumber, char *buf, int bufsize,
- char **context, char **linenumber, char **search)
+static char *cs_parse_results(size_t cnumber, char *buf, int bufsize, char **context,
+ char **linenumber, char **search)
{
int ch;
char *p;
@@ -1421,8 +1462,9 @@ retry:
// If the line's too long for the buffer, discard it.
if ((p = strchr(buf, '\n')) == NULL) {
- while ((ch = getc(csinfo[cnumber].fr_fp)) != EOF && ch != '\n')
+ while ((ch = getc(csinfo[cnumber].fr_fp)) != EOF && ch != '\n') {
;
+ }
return NULL;
}
*p = '\0';
@@ -1430,14 +1472,18 @@ retry:
/*
* cscope output is in the following format:
*
- * <filename> <context> <line number> <pattern>
+ * <filename> <context> <line number> <pattern>
*/
- if ((name = strtok((char *)buf, (const char *)" ")) == NULL)
+ char *saveptr = NULL;
+ if ((name = os_strtok(buf, (const char *)" ", &saveptr)) == NULL) {
return NULL;
- if ((*context = strtok(NULL, (const char *)" ")) == NULL)
+ }
+ if ((*context = os_strtok(NULL, (const char *)" ", &saveptr)) == NULL) {
return NULL;
- if ((*linenumber = strtok(NULL, (const char *)" ")) == NULL)
+ }
+ if ((*linenumber = os_strtok(NULL, (const char *)" ", &saveptr)) == NULL) {
return NULL;
+ }
*search = *linenumber + strlen(*linenumber) + 1; // +1 to skip \0
// --- nvi ---
@@ -1463,25 +1509,29 @@ static void cs_file_results(FILE *f, int *nummatches_a)
char *buf = xmalloc(CSREAD_BUFSIZE);
for (size_t i = 0; i < csinfo_size; i++) {
- if (nummatches_a[i] < 1)
+ if (nummatches_a[i] < 1) {
continue;
+ }
for (int j = 0; j < nummatches_a[i]; j++) {
if ((fullname = cs_parse_results(i, buf, CSREAD_BUFSIZE, &cntx,
- &slno, &search)) == NULL)
+ &slno, &search)) == NULL) {
continue;
+ }
context = xmalloc(strlen(cntx) + 5);
- if (strcmp(cntx, "<global>")==0)
+ if (strcmp(cntx, "<global>")==0) {
strcpy(context, "<<global>>");
- else
+ } else {
sprintf(context, "<<%s>>", cntx);
+ }
- if (search == NULL)
+ if (search == NULL) {
fprintf(f, "%s\t%s\t%s\n", fullname, slno, context);
- else
+ } else {
fprintf(f, "%s\t%s\t%s %s\n", fullname, slno, context, search);
+ }
xfree(context);
xfree(fullname);
@@ -1495,9 +1545,8 @@ static void cs_file_results(FILE *f, int *nummatches_a)
/// Get parsed cscope output and calls cs_make_vim_style_matches to convert
/// into ctags format.
/// When there are no matches sets "*matches_p" to NULL.
-static void cs_fill_results(char *tagstr, size_t totmatches, int *nummatches_a,
- char ***matches_p, char ***cntxts_p,
- size_t *matched)
+static void cs_fill_results(char *tagstr, size_t totmatches, int *nummatches_a, char ***matches_p,
+ char ***cntxts_p, size_t *matched)
{
char *buf;
char *search, *slno;
@@ -1514,22 +1563,24 @@ static void cs_fill_results(char *tagstr, size_t totmatches, int *nummatches_a,
cntxts = xmalloc(sizeof(char *) * (size_t)totmatches);
for (size_t i = 0; i < csinfo_size; i++) {
- if (nummatches_a[i] < 1)
+ if (nummatches_a[i] < 1) {
continue;
+ }
for (int j = 0; j < nummatches_a[i]; j++) {
if ((fullname = cs_parse_results(i, buf, CSREAD_BUFSIZE, &cntx,
- &slno, &search)) == NULL)
+ &slno, &search)) == NULL) {
continue;
+ }
matches[totsofar] = cs_make_vim_style_matches(fullname, slno, search,
tagstr);
xfree(fullname);
- if (strcmp(cntx, "<global>") == 0)
+ if (strcmp(cntx, "<global>") == 0) {
cntxts[totsofar] = NULL;
- else {
+ } else {
cntxts[totsofar] = xstrdup(cntx);
}
@@ -1691,9 +1742,9 @@ static void cs_print_tags_priv(char **matches, char **cntxts,
static int cs_read_prompt(size_t i)
{
int ch;
- char *buf = NULL; // buffer for possible error message from cscope
+ char *buf = NULL; // buffer for possible error message from cscope
size_t bufpos = 0;
- char *cs_emsg = _("E609: Cscope error: %s");
+ char *cs_emsg = _("E609: Cscope error: %s");
size_t cs_emsg_len = strlen(cs_emsg);
static char *eprompt = "Press the RETURN key to continue:";
size_t epromptlen = strlen(eprompt);
@@ -1886,10 +1937,12 @@ static void cs_release_csp(size_t i, bool freefnpp)
}
#endif
- if (csinfo[i].fr_fp != NULL)
+ if (csinfo[i].fr_fp != NULL) {
(void)fclose(csinfo[i].fr_fp);
- if (csinfo[i].to_fp != NULL)
+ }
+ if (csinfo[i].to_fp != NULL) {
(void)fclose(csinfo[i].to_fp);
+ }
if (freefnpp) {
xfree(csinfo[i].fname);
@@ -1904,11 +1957,12 @@ static void cs_release_csp(size_t i, bool freefnpp)
/// Calls cs_kill on all cscope connections then reinits.
static int cs_reset(exarg_T *eap)
{
- char **dblist = NULL, **pplist = NULL, **fllist = NULL;
+ char **dblist = NULL, **pplist = NULL, **fllist = NULL;
char buf[25]; // for snprintf " (#%zu)"
- if (csinfo_size == 0)
+ if (csinfo_size == 0) {
return CSCOPE_SUCCESS;
+ }
// malloc our db and ppath list
dblist = xmalloc(csinfo_size * sizeof(char *));
@@ -1919,8 +1973,9 @@ static int cs_reset(exarg_T *eap)
dblist[i] = csinfo[i].fname;
pplist[i] = csinfo[i].ppath;
fllist[i] = csinfo[i].flags;
- if (csinfo[i].fname != NULL)
+ if (csinfo[i].fname != NULL) {
cs_release_csp(i, FALSE);
+ }
}
// rebuild the cscope connection list
@@ -1959,8 +2014,8 @@ static int cs_reset(exarg_T *eap)
/// Contrast this with my development system (Digital Unix), which does.
static char *cs_resolve_file(size_t i, char *name)
{
- char *fullname;
- char_u *csdir = NULL;
+ char *fullname;
+ char_u *csdir = NULL;
/*
* Ppath is freed when we destroy the cscope connection.
@@ -1975,8 +2030,8 @@ static char *cs_resolve_file(size_t i, char *name)
// path in path resolution.
csdir = xmalloc(MAXPATHL);
STRLCPY(csdir, csinfo[i].fname,
- path_tail((char_u *)csinfo[i].fname)
- - (char_u *)csinfo[i].fname + 1);
+ path_tail((char_u *)csinfo[i].fname)
+ - (char_u *)csinfo[i].fname + 1);
len += STRLEN(csdir);
}
@@ -1985,8 +2040,7 @@ static char *cs_resolve_file(size_t i, char *name)
// happens, you are screwed up and need to fix how you're using cscope.
if (csinfo[i].ppath != NULL
&& (strncmp(name, csinfo[i].ppath, strlen(csinfo[i].ppath)) != 0)
- && (name[0] != '/')
- ) {
+ && (name[0] != '/')) {
fullname = xmalloc(len);
(void)sprintf(fullname, "%s/%s", csinfo[i].ppath, name);
} else if (csdir != NULL && csinfo[i].fname != NULL && *csdir != NUL) {
@@ -2005,15 +2059,15 @@ static char *cs_resolve_file(size_t i, char *name)
/// Show all cscope connections.
static int cs_show(exarg_T *eap)
{
- if (cs_cnt_connections() == 0)
+ if (cs_cnt_connections() == 0) {
MSG_PUTS(_("no cscope connections\n"));
- else {
- MSG_PUTS_ATTR(
- _(" # pid database name prepend path\n"),
- HL_ATTR(HLF_T));
+ } else {
+ MSG_PUTS_ATTR(_(" # pid database name prepend path\n"),
+ HL_ATTR(HLF_T));
for (size_t i = 0; i < csinfo_size; i++) {
- if (csinfo[i].fname == NULL)
+ if (csinfo[i].fname == NULL) {
continue;
+ }
if (csinfo[i].ppath != NULL) {
(void)smsg("%2zu %-5" PRId64 " %-34s %-32s", i,
@@ -2033,8 +2087,9 @@ static int cs_show(exarg_T *eap)
/// Only called when VIM exits to quit any cscope sessions.
void cs_end(void)
{
- for (size_t i = 0; i < csinfo_size; i++)
+ for (size_t i = 0; i < csinfo_size; i++) {
cs_release_csp(i, true);
+ }
xfree(csinfo);
csinfo_size = 0;
}
diff --git a/src/nvim/lua/converter.c b/src/nvim/lua/converter.c
index fac5bab664..fd4cfc4c31 100644
--- a/src/nvim/lua/converter.c
+++ b/src/nvim/lua/converter.c
@@ -1299,3 +1299,25 @@ void nlua_init_types(lua_State *const lstate)
lua_rawset(lstate, -3);
}
+
+
+void nlua_pop_keydict(lua_State *L, void *retval, field_hash hashy, Error *err)
+{
+ lua_pushnil(L); // [dict, nil]
+ while (lua_next(L, -2)) {
+ // [dict, key, value]
+ size_t len;
+ const char *s = lua_tolstring(L, -2, &len);
+ Object *field = hashy(retval, s, len);
+ if (!field) {
+ api_set_error(err, kErrorTypeValidation, "invalid key: %.*s", (int)len, s);
+ lua_pop(L, 3); // []
+ return;
+ }
+
+ *field = nlua_pop_Object(L, true, err);
+ }
+ // [dict]
+ lua_pop(L, 1);
+ // []
+}
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index 9333d781cd..3f93bb9a09 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -5,6 +5,7 @@
#include <lua.h>
#include <lualib.h>
+#include "cjson/lua_cjson.h"
#include "luv/luv.h"
#include "mpack/lmpack.h"
#include "nvim/api/private/defs.h"
@@ -40,7 +41,6 @@
#include "nvim/undo.h"
#include "nvim/version.h"
#include "nvim/vim.h"
-#include "cjson/lua_cjson.h"
static int in_fast_callback = 0;
diff --git a/src/nvim/lua/vim.lua b/src/nvim/lua/vim.lua
index 7a209f2d79..5ca4cc82a5 100644
--- a/src/nvim/lua/vim.lua
+++ b/src/nvim/lua/vim.lua
@@ -433,6 +433,7 @@ function vim.notify(msg, log_level, _opts)
end
+---@private
function vim.register_keystroke_callback()
error('vim.register_keystroke_callback is deprecated, instead use: vim.on_key')
end
diff --git a/src/nvim/lua/xdiff.c b/src/nvim/lua/xdiff.c
index 2a1f39083c..3955fbe72c 100644
--- a/src/nvim/lua/xdiff.c
+++ b/src/nvim/lua/xdiff.c
@@ -53,8 +53,8 @@ static int write_string(void *priv, mmbuffer_t *mb, int nbuf)
static int hunk_locations_cb(long start_a, long count_a, long start_b, long count_b, void *cb_data)
{
// Mimic extra offsets done by xdiff, see:
- // src/nvim/xdiff/xemit.c:284
- // src/nvim/xdiff/xutils.c:(356,368)
+ // src/xdiff/xemit.c:284
+ // src/xdiff/xutils.c:(356,368)
if (count_a > 0) {
start_a += 1;
}
@@ -83,8 +83,8 @@ static int hunk_locations_cb(long start_a, long count_a, long start_b, long coun
static int call_on_hunk_cb(long start_a, long count_a, long start_b, long count_b, void *cb_data)
{
// Mimic extra offsets done by xdiff, see:
- // src/nvim/xdiff/xemit.c:284
- // src/nvim/xdiff/xutils.c:(356,368)
+ // src/xdiff/xemit.c:284
+ // src/xdiff/xutils.c:(356,368)
if (count_a > 0) {
start_a += 1;
}
diff --git a/src/nvim/main.c b/src/nvim/main.c
index d977589ad7..069c253bff 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -345,7 +345,8 @@ int main(int argc, char **argv)
// Reset 'loadplugins' for "-u NONE" before "--cmd" arguments.
// Allows for setting 'loadplugins' there.
if (params.use_vimrc != NULL && strequal(params.use_vimrc, "NONE")) {
- p_lpl = false;
+ // When using --clean we still want to load plugins
+ p_lpl = params.clean;
}
// Execute --cmd arguments.
@@ -1306,35 +1307,6 @@ static void set_window_layout(mparm_T *paramp)
}
}
-/*
- * Read all the plugin files.
- * Only when compiled with +eval, since most plugins need it.
- */
-static void load_plugins(void)
-{
- if (p_lpl) {
- char_u *rtp_copy = NULL;
- char_u *const plugin_pattern_vim = (char_u *)"plugin/**/*.vim"; // NOLINT
- char_u *const plugin_pattern_lua = (char_u *)"plugin/**/*.lua"; // NOLINT
-
- // don't use source_runtime() yet so we can check for :packloadall below
- source_in_path(p_rtp, plugin_pattern_vim, DIP_ALL | DIP_NOAFTER);
- source_in_path(p_rtp, plugin_pattern_lua, DIP_ALL | DIP_NOAFTER);
- TIME_MSG("loading rtp plugins");
- xfree(rtp_copy);
-
- // Only source "start" packages if not done already with a :packloadall
- // command.
- if (!did_source_packages) {
- load_start_packages();
- }
- TIME_MSG("loading packages");
-
- source_runtime(plugin_pattern_vim, DIP_ALL | DIP_AFTER);
- source_runtime(plugin_pattern_lua, DIP_ALL | DIP_AFTER);
- TIME_MSG("loading after plugins");
- }
-}
/*
* "-q errorfile": Load the error file now.
diff --git a/src/nvim/mark.c b/src/nvim/mark.c
index b296bf39cf..edec85c0b2 100644
--- a/src/nvim/mark.c
+++ b/src/nvim/mark.c
@@ -1637,6 +1637,15 @@ void get_buf_local_marks(const buf_T *buf, list_T *l)
add_mark(l, "'>", &buf->b_visual.vi_end, buf->b_fnum, NULL);
}
+/// Get a global mark
+///
+/// @param[in] Name of named mark
+/// @param[out] Global/file mark
+xfmark_T get_global_mark(char name)
+{
+ return namedfm[mark_global_index(name)];
+}
+
/// Get information about global marks ('A' to 'Z' and '0' to '9')
///
/// @param[out] l List to store global marks
diff --git a/src/nvim/menu.c b/src/nvim/menu.c
index 2b1a250604..de8503f9d0 100644
--- a/src/nvim/menu.c
+++ b/src/nvim/menu.c
@@ -64,7 +64,7 @@ static vimmenu_T **get_root_menu(const char_u *const name)
/// @param eap Ex command arguments
void ex_menu(exarg_T *eap)
{
- char_u *menu_path;
+ char *menu_path;
int modes;
char_u *map_to; // command mapped to the menu entry
int noremap;
@@ -166,7 +166,7 @@ void ex_menu(exarg_T *eap)
}
- menu_path = arg;
+ menu_path = (char *)arg;
if (*menu_path == '.') {
EMSG2(_(e_invarg2), menu_path);
goto theend;
@@ -178,25 +178,25 @@ void ex_menu(exarg_T *eap)
* If there is only a menu name, display menus with that name.
*/
if (*map_to == NUL && !unmenu && enable == kNone) {
- show_menus(menu_path, modes);
+ show_menus((char_u *)menu_path, modes);
goto theend;
} else if (*map_to != NUL && (unmenu || enable != kNone)) {
EMSG(_(e_trailing));
goto theend;
}
- vimmenu_T **root_menu_ptr = get_root_menu(menu_path);
+ vimmenu_T **root_menu_ptr = get_root_menu((char_u *)menu_path);
if (enable != kNone) {
// Change sensitivity of the menu.
// For the PopUp menu, remove a menu for each mode separately.
// Careful: menu_enable_recurse() changes menu_path.
if (STRCMP(menu_path, "*") == 0) { // meaning: do all menus
- menu_path = (char_u *)"";
+ menu_path = "";
}
if (menu_is_popup(menu_path)) {
- for (i = 0; i < MENU_INDEX_TIP; ++i) {
+ for (i = 0; i < MENU_INDEX_TIP; i++) {
if (modes & (1 << i)) {
p = popup_mode_name(menu_path, i);
menu_enable_recurse(*root_menu_ptr, p, MENU_ALL_MODES, enable);
@@ -204,20 +204,20 @@ void ex_menu(exarg_T *eap)
}
}
}
- menu_enable_recurse(*root_menu_ptr, menu_path, modes, enable);
+ menu_enable_recurse(*root_menu_ptr, (char_u *)menu_path, modes, enable);
} else if (unmenu) {
/*
* Delete menu(s).
*/
if (STRCMP(menu_path, "*") == 0) { // meaning: remove all menus
- menu_path = (char_u *)"";
+ menu_path = "";
}
/*
* For the PopUp menu, remove a menu for each mode separately.
*/
if (menu_is_popup(menu_path)) {
- for (i = 0; i < MENU_INDEX_TIP; ++i) {
+ for (i = 0; i < MENU_INDEX_TIP; i++) {
if (modes & (1 << i)) {
p = popup_mode_name(menu_path, i);
remove_menu(root_menu_ptr, p, MENU_ALL_MODES, true);
@@ -227,7 +227,7 @@ void ex_menu(exarg_T *eap)
}
// Careful: remove_menu() changes menu_path
- remove_menu(root_menu_ptr, menu_path, modes, false);
+ remove_menu(root_menu_ptr, (char_u *)menu_path, modes, false);
} else {
/*
* Add menu(s).
@@ -245,13 +245,13 @@ void ex_menu(exarg_T *eap)
menuarg.modes = modes;
menuarg.noremap[0] = noremap;
menuarg.silent[0] = silent;
- add_menu_path(menu_path, &menuarg, pri_tab, map_to);
+ add_menu_path((char_u *)menu_path, &menuarg, pri_tab, map_to);
/*
* For the PopUp menu, add a menu for each mode separately.
*/
if (menu_is_popup(menu_path)) {
- for (i = 0; i < MENU_INDEX_TIP; ++i) {
+ for (i = 0; i < MENU_INDEX_TIP; i++) {
if (modes & (1 << i)) {
p = popup_mode_name(menu_path, i);
// Include all modes, to make ":amenu" work
@@ -1273,12 +1273,12 @@ int get_menu_cmd_modes(const char *cmd, bool forceit, int *noremap, int *unmenu)
* Modify a menu name starting with "PopUp" to include the mode character.
* Returns the name in allocated memory.
*/
-static char_u *popup_mode_name(char_u *name, int idx)
+static char_u *popup_mode_name(char *name, int idx)
{
size_t len = STRLEN(name);
assert(len >= 4);
- char_u *p = vim_strnsave(name, len + 1);
+ char_u *p = vim_strnsave((char_u *)name, len + 1);
memmove(p + 6, p + 5, len - 4);
p[5] = menu_mode_chars[idx];
@@ -1337,14 +1337,14 @@ static char_u *menu_text(const char_u *str, int *mnemonic, char_u **actext)
bool menu_is_menubar(const char_u *const name)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
- return !menu_is_popup(name)
+ return !menu_is_popup((char *)name)
&& !menu_is_toolbar(name)
&& !menu_is_winbar(name)
&& *name != MNU_HIDDEN_CHAR;
}
// Return true if "name" is a popup menu name.
-bool menu_is_popup(const char_u *const name)
+bool menu_is_popup(const char *const name)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
return STRNCMP(name, "PopUp", 5) == 0;
@@ -1374,7 +1374,7 @@ int menu_is_separator(char_u *name)
static int menu_is_hidden(char_u *name)
{
return (name[0] == MNU_HIDDEN_CHAR)
- || (menu_is_popup(name) && name[5] != NUL);
+ || (menu_is_popup((char *)name) && name[5] != NUL);
}
// Execute "menu". Use by ":emenu" and the window toolbar.
@@ -1383,25 +1383,25 @@ static void execute_menu(const exarg_T *eap, vimmenu_T *menu)
FUNC_ATTR_NONNULL_ARG(2)
{
int idx = -1;
- char_u *mode;
+ char *mode;
// Use the Insert mode entry when returning to Insert mode.
if (((State & INSERT) || restart_edit) && !current_sctx.sc_sid) {
- mode = (char_u *)"Insert";
+ mode = "Insert";
idx = MENU_INDEX_INSERT;
} else if (State & CMDLINE) {
- mode = (char_u *)"Command";
+ mode = "Command";
idx = MENU_INDEX_CMDLINE;
} else if (get_real_state() & VISUAL) {
/* Detect real visual mode -- if we are really in visual mode we
* don't need to do any guesswork to figure out what the selection
* is. Just execute the visual binding for the menu. */
- mode = (char_u *)"Visual";
+ mode = "Visual";
idx = MENU_INDEX_VISUAL;
} else if (eap != NULL && eap->addr_count) {
pos_T tpos;
- mode = (char_u *)"Visual";
+ mode = "Visual";
idx = MENU_INDEX_VISUAL;
/* GEDDES: This is not perfect - but it is a
@@ -1442,7 +1442,7 @@ static void execute_menu(const exarg_T *eap, vimmenu_T *menu)
}
if (idx == -1 || eap == NULL) {
- mode = (char_u *)"Normal";
+ mode = "Normal";
idx = MENU_INDEX_NORMAL;
}
diff --git a/src/nvim/message.c b/src/nvim/message.c
index ed673b52d3..edde51e770 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -3191,7 +3191,7 @@ static void redir_write(const char *const str, const ptrdiff_t maxlen)
size_t len = maxlen == -1 ? STRLEN(s) : (size_t)maxlen;
if (capture_ga) {
- ga_concat_len(capture_ga, (const char *)str, len);
+ ga_concat_len(capture_ga, str, len);
}
if (redir_reg) {
write_reg_contents(redir_reg, s, len, true);
diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c
index cf463fd40a..f02c000e82 100644
--- a/src/nvim/mouse.c
+++ b/src/nvim/mouse.c
@@ -236,6 +236,11 @@ retnomove:
redraw_curbuf_later(INVERTED); // delete the inversion
}
+ if (grid == 0) {
+ row -= curwin->w_grid_alloc.comp_row+curwin->w_grid.row_offset;
+ col -= curwin->w_grid_alloc.comp_col+curwin->w_grid.col_offset;
+ }
+
// When clicking beyond the end of the window, scroll the screen.
// Scroll by however many rows outside the window we are.
if (row < 0) {
@@ -476,7 +481,7 @@ win_T *mouse_find_win(int *gridp, int *rowp, int *colp)
static win_T *mouse_find_grid_win(int *gridp, int *rowp, int *colp)
{
if (*gridp == msg_grid.handle) {
- // rowp += msg_grid_pos; // PVS: dead store #11612
+ *rowp += msg_grid_pos;
*gridp = DEFAULT_GRID_HANDLE;
} else if (*gridp > 1) {
win_T *wp = get_win_by_grid_handle(*gridp);
@@ -677,8 +682,8 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
vcol = offset;
-#define incr() nudge++; ptr_end += utfc_ptr2len(ptr_end)
-#define decr() nudge--; ptr_end -= utfc_ptr2len(ptr_end)
+#define INCR() nudge++; ptr_end += utfc_ptr2len(ptr_end)
+#define DECR() nudge--; ptr_end -= utfc_ptr2len(ptr_end)
while (ptr < ptr_end && *ptr != NUL) {
cwidth = win_chartabsize(curwin, ptr, vcol);
@@ -687,7 +692,7 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
// A tab will "absorb" any previous adjustments.
cwidth = MIN(cwidth, nudge);
while (cwidth > 0) {
- decr();
+ DECR();
cwidth--;
}
}
@@ -695,20 +700,20 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
matchid = syn_get_concealed_id(wp, lnum, (colnr_T)(ptr - line));
if (matchid != 0) {
if (wp->w_p_cole == 3) {
- incr();
+ INCR();
} else {
if (!(row > 0 && ptr == ptr_row_offset)
&& (wp->w_p_cole == 1 || (wp->w_p_cole == 2
&& (wp->w_p_lcs_chars.conceal != NUL
|| syn_get_sub_char() != NUL)))) {
// At least one placeholder character will be displayed.
- decr();
+ DECR();
}
prev_matchid = matchid;
while (prev_matchid == matchid && *ptr != NUL) {
- incr();
+ INCR();
ptr += utfc_ptr2len(ptr);
matchid = syn_get_concealed_id(wp, lnum, (colnr_T)(ptr - line));
}
diff --git a/src/nvim/move.c b/src/nvim/move.c
index ca3dd34204..c4f8e81fa3 100644
--- a/src/nvim/move.c
+++ b/src/nvim/move.c
@@ -794,7 +794,7 @@ void curs_columns(win_T *wp, int may_scroll)
// column
char_u *const sbr = get_showbreak_value(wp);
if (*sbr && *get_cursor_pos_ptr() == NUL
- && wp->w_wcol == (int)vim_strsize(sbr)) {
+ && wp->w_wcol == vim_strsize(sbr)) {
wp->w_wcol = 0;
}
}
diff --git a/src/nvim/msgpack_rpc/helpers.c b/src/nvim/msgpack_rpc/helpers.c
index b1b9c77953..549016e751 100644
--- a/src/nvim/msgpack_rpc/helpers.c
+++ b/src/nvim/msgpack_rpc/helpers.c
@@ -15,6 +15,7 @@
#include "nvim/vim.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "keysets.generated.h"
# include "msgpack_rpc/helpers.c.generated.h"
#endif
diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c
index bbf70a4830..9675cfbb0f 100644
--- a/src/nvim/os/fs.c
+++ b/src/nvim/os/fs.c
@@ -134,7 +134,7 @@ bool os_isdir(const char_u *name)
bool os_isdir_executable(const char *name)
FUNC_ATTR_NONNULL_ALL
{
- int32_t mode = os_getperm((const char *)name);
+ int32_t mode = os_getperm(name);
if (mode < 0) {
return false;
}
diff --git a/src/nvim/os/os_win_console.c b/src/nvim/os/os_win_console.c
index 2c9cb699fc..18e2e02b81 100644
--- a/src/nvim/os/os_win_console.c
+++ b/src/nvim/os/os_win_console.c
@@ -46,29 +46,3 @@ void os_replace_stdout_and_stderr_to_conout(void)
const int conerr_fd = _open_osfhandle((intptr_t)conout_handle, 0);
assert(conerr_fd == STDERR_FILENO);
}
-
-void os_set_vtp(bool enable)
-{
- static TriState is_legacy = kNone;
- if (is_legacy == kNone) {
- uv_tty_vtermstate_t state;
- uv_tty_get_vterm_state(&state);
- is_legacy = (state == UV_TTY_UNSUPPORTED) ? kTrue : kFalse;
- }
- if (!is_legacy && !os_has_vti()) {
- uv_tty_set_vterm_state(enable ? UV_TTY_SUPPORTED : UV_TTY_UNSUPPORTED);
- }
-}
-
-static bool os_has_vti(void)
-{
- static TriState has_vti = kNone;
- if (has_vti == kNone) {
- HANDLE handle = (HANDLE)_get_osfhandle(input_global_fd());
- DWORD dwMode;
- if (handle != INVALID_HANDLE_VALUE && GetConsoleMode(handle, &dwMode)) {
- has_vti = !!(dwMode & ENABLE_VIRTUAL_TERMINAL_INPUT) ? kTrue : kFalse;
- }
- }
- return has_vti == kTrue;
-}
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index eb0ba874f4..046e6dbd12 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -1823,7 +1823,7 @@ static int qf_add_entry(qf_list_T *qfl, char_u *dir, char_u *fname, char_u *modu
if (type != 1 && !vim_isprintc(type)) { // only printable chars allowed
type = 0;
}
- qfp->qf_type = (char_u)type;
+ qfp->qf_type = type;
qfp->qf_valid = valid;
lastp = &qfl->qf_last;
diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c
index 7b72efce23..0e2d23e69b 100644
--- a/src/nvim/runtime.c
+++ b/src/nvim/runtime.c
@@ -5,8 +5,8 @@
///
/// Management of runtime files (including packages)
-#include "nvim/ascii.h"
#include "nvim/api/private/helpers.h"
+#include "nvim/ascii.h"
#include "nvim/charset.h"
#include "nvim/eval.h"
#include "nvim/ex_cmds.h"
@@ -169,9 +169,9 @@ int do_in_path(char_u *path, char_u *name, int flags, DoInRuntimepathCB callback
int do_in_cached_path(char_u *name, int flags, DoInRuntimepathCB callback, void *cookie)
{
runtime_search_path_validate();
- char_u *tail;
+ char_u *tail;
int num_files;
- char_u **files;
+ char_u **files;
int i;
bool did_one = false;
@@ -332,40 +332,56 @@ int do_in_path_and_pp(char_u *path, char_u *name, int flags, DoInRuntimepathCB c
return done;
}
-static void push_path(RuntimeSearchPath *search_path, char *entry, bool after)
+static void push_path(RuntimeSearchPath *search_path, Map(String, handle_T) *rtp_used,
+ char *entry, bool after)
{
- kv_push(*search_path, ((SearchPathItem){ entry, after }));
+ handle_T h = map_get(String, handle_T)(rtp_used, cstr_as_string(entry));
+ if (h == 0) {
+ char *allocated = xstrdup(entry);
+ map_put(String, handle_T)(rtp_used, cstr_as_string(allocated), 1);
+ kv_push(*search_path, ((SearchPathItem){ allocated, after }));
+ }
}
-static void expand_pack_entry(RuntimeSearchPath *search_path, CharVec *after_path,
- char_u *pack_entry)
+static void expand_rtp_entry(RuntimeSearchPath *search_path, Map(String, handle_T) *rtp_used,
+ char *entry, bool after)
{
- static char_u buf[MAXPATHL], buf2[MAXPATHL];
- char *start_dir = "/pack/*/start/*"; // NOLINT
- if (STRLEN(pack_entry) + STRLEN(start_dir) + 1 < MAXPATHL) {
- xstrlcpy((char *)buf, (char *)pack_entry, MAXPATHL);
- xstrlcpy((char *)buf2, (char *)pack_entry, MAXPATHL);
- xstrlcat((char *)buf, start_dir, sizeof buf);
- xstrlcat((char *)buf2, "/start/*", sizeof buf); // NOLINT
- int num_files;
- char_u **files;
-
- char_u *(pat[]) = { buf, buf2 };
- if (gen_expand_wildcards(2, pat, &num_files, &files, EW_DIR) == OK) {
- for (int i = 0; i < num_files; i++) {
- push_path(search_path, xstrdup((char *)files[i]), false);
- size_t after_size = STRLEN(files[i])+7;
- char *after = xmallocz(after_size);
- xstrlcpy(after, (char *)files[i], after_size);
- xstrlcat(after, "/after", after_size);
- if (os_isdir((char_u *)after)) {
- kv_push(*after_path, after);
- } else {
- xfree(after);
- }
- }
- FreeWild(num_files, files);
+ if (map_get(String, handle_T)(rtp_used, cstr_as_string(entry))) {
+ return;
+ }
+
+ if (!*entry) {
+ push_path(search_path, rtp_used, entry, after);
+ }
+
+ int num_files;
+ char_u **files;
+ char_u *(pat[]) = { (char_u *)entry };
+ if (gen_expand_wildcards(1, pat, &num_files, &files, EW_DIR) == OK) {
+ for (int i = 0; i < num_files; i++) {
+ push_path(search_path, rtp_used, (char *)files[i], after);
}
+ FreeWild(num_files, files);
+ }
+}
+
+static void expand_pack_entry(RuntimeSearchPath *search_path, Map(String, handle_T) *rtp_used,
+ CharVec *after_path, char_u *pack_entry)
+{
+ static char buf[MAXPATHL];
+ char *(start_pat[]) = { "/pack/*/start/*", "/start/*" }; // NOLINT
+ for (int i = 0; i < 2; i++) {
+ if (STRLEN(pack_entry) + STRLEN(start_pat[i]) + 1 > MAXPATHL) {
+ continue;
+ }
+ xstrlcpy(buf, (char *)pack_entry, MAXPATHL);
+ xstrlcat(buf, start_pat[i], sizeof buf);
+ expand_rtp_entry(search_path, rtp_used, buf, false);
+ size_t after_size = STRLEN(buf)+7;
+ char *after = xmallocz(after_size);
+ xstrlcpy(after, buf, after_size);
+ xstrlcat(after, "/after", after_size);
+ kv_push(*after_path, after);
}
}
@@ -382,8 +398,10 @@ static bool path_is_after(char_u *buf, size_t buflen)
RuntimeSearchPath runtime_search_path_build(void)
{
kvec_t(String) pack_entries = KV_INITIAL_VALUE;
+ // TODO(bfredl): these should just be sets, when Set(String) is do merge to
+ // master.
Map(String, handle_T) pack_used = MAP_INIT;
- // TODO(bfredl): add a set of existing rtp entries to not duplicate those
+ Map(String, handle_T) rtp_used = MAP_INIT;
RuntimeSearchPath search_path = KV_INITIAL_VALUE;
CharVec after_path = KV_INITIAL_VALUE;
@@ -410,37 +428,40 @@ RuntimeSearchPath runtime_search_path_build(void)
break;
}
- push_path(&search_path, xstrdup((char *)buf), false);
+ // fact: &rtp entries can contain wild chars
+ expand_rtp_entry(&search_path, &rtp_used, (char *)buf, false);
handle_T *h = map_ref(String, handle_T)(&pack_used, cstr_as_string((char *)buf), false);
if (h) {
(*h)++;
- expand_pack_entry(&search_path, &after_path, buf);
+ expand_pack_entry(&search_path, &rtp_used, &after_path, buf);
}
}
for (size_t i = 0; i < kv_size(pack_entries); i++) {
handle_T h = map_get(String, handle_T)(&pack_used, kv_A(pack_entries, i));
if (h == 0) {
- expand_pack_entry(&search_path, &after_path, (char_u *)kv_A(pack_entries, i).data);
+ expand_pack_entry(&search_path, &rtp_used, &after_path, (char_u *)kv_A(pack_entries, i).data);
}
}
// "after" packages
for (size_t i = 0; i < kv_size(after_path); i++) {
- push_path(&search_path, kv_A(after_path, i), true);
+ expand_rtp_entry(&search_path, &rtp_used, kv_A(after_path, i), true);
+ xfree(kv_A(after_path, i));
}
// "after" dirs in rtp
for (; *rtp_entry != NUL;) {
copy_option_part((char_u **)&rtp_entry, buf, MAXPATHL, ",");
- push_path(&search_path, xstrdup((char *)buf), path_is_after(buf, STRLEN(buf)));
+ expand_rtp_entry(&search_path, &rtp_used, (char *)buf, path_is_after(buf, STRLEN(buf)));
}
// strings are not owned
kv_destroy(pack_entries);
kv_destroy(after_path);
map_destroy(String, handle_T)(&pack_used);
+ map_destroy(String, handle_T)(&rtp_used);
return search_path;
}
@@ -452,11 +473,11 @@ void runtime_search_path_invalidate(void)
void runtime_search_path_free(RuntimeSearchPath path)
{
- for (size_t j = 0; j < kv_size(path); j++) {
- SearchPathItem item = kv_A(path, j);
- xfree(item.path);
- }
- kv_destroy(path);
+ for (size_t j = 0; j < kv_size(path); j++) {
+ SearchPathItem item = kv_A(path, j);
+ xfree(item.path);
+ }
+ kv_destroy(path);
}
void runtime_search_path_validate(void)
@@ -521,7 +542,10 @@ static void source_all_matches(char_u *pat)
}
/// Add the package directory to 'runtimepath'
-static int add_pack_dir_to_rtp(char_u *fname)
+///
+/// @param fname the package path
+/// @param is_pack whether the added dir is a "pack/*/start/*/" style package
+static int add_pack_dir_to_rtp(char_u *fname, bool is_pack)
{
char_u *p4, *p3, *p2, *p1, *p;
char_u *buf = NULL;
@@ -599,7 +623,7 @@ static int add_pack_dir_to_rtp(char_u *fname)
// check if rtp/pack/name/start/name/after exists
afterdir = concat_fnames((char *)fname, "after", true);
size_t afterlen = 0;
- if (os_isdir((char_u *)afterdir)) {
+ if (is_pack ? pack_has_entries((char_u *)afterdir) : os_isdir((char_u *)afterdir)) {
afterlen = strlen(afterdir) + 1; // add one for comma
}
@@ -720,7 +744,7 @@ static void add_pack_plugin(bool opt, char_u *fname, void *cookie)
xfree(buf);
if (!found) {
// directory is not yet in 'runtimepath', add it
- if (add_pack_dir_to_rtp(fname) == FAIL) {
+ if (add_pack_dir_to_rtp(fname, false) == FAIL) {
return;
}
}
@@ -741,6 +765,41 @@ static void add_opt_pack_plugin(char_u *fname, void *cookie)
add_pack_plugin(true, fname, cookie);
}
+
+/// Add all packages in the "start" directory to 'runtimepath'.
+void add_pack_start_dirs(void)
+{
+ do_in_path(p_pp, NULL, DIP_ALL + DIP_DIR, add_pack_start_dir, NULL);
+}
+
+static bool pack_has_entries(char_u *buf)
+{
+ int num_files;
+ char_u **files;
+ char_u *(pat[]) = { buf };
+ if (gen_expand_wildcards(1, pat, &num_files, &files, EW_DIR) == OK) {
+ FreeWild(num_files, files);
+ }
+ return num_files > 0;
+}
+
+static void add_pack_start_dir(char_u *fname, void *cookie)
+{
+ static char_u buf[MAXPATHL];
+ char *(start_pat[]) = { "/start/*", "/pack/*/start/*" }; // NOLINT
+ for (int i = 0; i < 2; i++) {
+ if (STRLEN(fname) + STRLEN(start_pat[i]) + 1 > MAXPATHL) {
+ continue;
+ }
+ xstrlcpy((char *)buf, (char *)fname, MAXPATHL);
+ xstrlcat((char *)buf, start_pat[i], sizeof buf);
+ if (pack_has_entries(buf)) {
+ add_pack_dir_to_rtp(buf, true);
+ }
+ }
+}
+
+
/// Load plugins from all packages in the "start" directory.
void load_start_packages(void)
{
@@ -759,10 +818,43 @@ void ex_packloadall(exarg_T *eap)
// First do a round to add all directories to 'runtimepath', then load
// the plugins. This allows for plugins to use an autoload directory
// of another plugin.
+ add_pack_start_dirs();
load_start_packages();
}
}
+/// Read all the plugin files at startup
+void load_plugins(void)
+{
+ if (p_lpl) {
+ char_u *rtp_copy = p_rtp;
+ char_u *const plugin_pattern_vim = (char_u *)"plugin/**/*.vim"; // NOLINT
+ char_u *const plugin_pattern_lua = (char_u *)"plugin/**/*.lua"; // NOLINT
+
+ if (!did_source_packages) {
+ rtp_copy = vim_strsave(p_rtp);
+ add_pack_start_dirs();
+ }
+
+ // don't use source_runtime() yet so we can check for :packloadall below
+ source_in_path(rtp_copy, plugin_pattern_vim, DIP_ALL | DIP_NOAFTER);
+ source_in_path(rtp_copy, plugin_pattern_lua, DIP_ALL | DIP_NOAFTER);
+ TIME_MSG("loading rtp plugins");
+
+ // Only source "start" packages if not done already with a :packloadall
+ // command.
+ if (!did_source_packages) {
+ xfree(rtp_copy);
+ load_start_packages();
+ }
+ TIME_MSG("loading packages");
+
+ source_runtime(plugin_pattern_vim, DIP_ALL | DIP_AFTER);
+ source_runtime(plugin_pattern_lua, DIP_ALL | DIP_AFTER);
+ TIME_MSG("loading after plugins");
+ }
+}
+
/// ":packadd[!] {name}"
void ex_packadd(exarg_T *eap)
{
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 98d8722ec8..fcd8fb1118 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -4545,8 +4545,8 @@ void draw_virt_text(buf_T *buf, int col_off, int *end_col, int max_col)
}
}
-static int draw_virt_text_item(buf_T *buf, int col, VirtText vt, HlMode hl_mode,
- int max_col, int vcol)
+static int draw_virt_text_item(buf_T *buf, int col, VirtText vt, HlMode hl_mode, int max_col,
+ int vcol)
{
LineState s = LINE_STATE("");
int virt_attr = 0;
diff --git a/src/nvim/shada.c b/src/nvim/shada.c
index bf245bec51..0cec28c4de 100644
--- a/src/nvim/shada.c
+++ b/src/nvim/shada.c
@@ -65,26 +65,6 @@ KHASH_SET_INIT_INT64(bufset)
KHASH_MAP_INIT_STR(fnamebufs, buf_T *)
KHASH_SET_INIT_STR(strset)
-#define copy_option_part(src, dest, ...) \
- ((char *)copy_option_part((char_u **)src, (char_u *)dest, __VA_ARGS__))
-#define find_shada_parameter(...) \
- ((const char *)find_shada_parameter(__VA_ARGS__))
-#define home_replace_save(a, b) \
- ((char *)home_replace_save(a, (char_u *)b))
-#define home_replace(a, b, c, d, e) \
- home_replace(a, (char_u *)b, (char_u *)c, d, e)
-#define vim_rename(a, b) \
- (vim_rename((char_u *)a, (char_u *)b))
-#define mb_strnicmp(a, b, c) \
- (mb_strnicmp((char_u *)a, (char_u *)b, c))
-#define path_try_shorten_fname(b) \
- ((char *)path_try_shorten_fname((char_u *)b))
-#define buflist_new(ffname, sfname, ...) \
- (buflist_new((char_u *)ffname, (char_u *)sfname, __VA_ARGS__))
-#define os_isdir(f) (os_isdir((char_u *)f))
-#define regtilde(s, m) ((char *)regtilde((char_u *)s, m))
-#define path_tail_with_sep(f) ((char *)path_tail_with_sep((char_u *)f))
-
#define SEARCH_KEY_MAGIC "sm"
#define SEARCH_KEY_SMARTCASE "sc"
#define SEARCH_KEY_HAS_LINE_OFFSET "sl"
@@ -624,20 +604,6 @@ static inline void hmll_insert(HMLList *const hmll, HMLListEntry *hmll_entry, co
}
}
-/// Iterate over HMLList in backward direction
-///
-/// @param hmll Pointer to the list.
-/// @param cur_entry Name of the variable to iterate over, must be already
-/// defined.
-/// @param code Code to execute on each iteration.
-///
-/// @return `for` cycle header (use `HMLL_FORALL(hmll, cur_entry) {body}`).
-#define HMLL_ITER_BACK(hmll, cur_entry, code) \
- for (cur_entry = (hmll)->last; cur_entry != NULL; \
- cur_entry = cur_entry->prev) { \
- code \
- }
-
/// Free linked list
///
/// @param[in] hmll List to free.
@@ -981,11 +947,12 @@ static void hms_insert(HistoryMergerState *const hms_p, const ShadaEntry entry,
}
}
HMLListEntry *insert_after;
- HMLL_ITER_BACK(hmll, insert_after, {
+ // Iterate over HMLList in backward direction
+ for (insert_after = hmll->last; insert_after != NULL; insert_after = insert_after->prev) {
if (insert_after->data.timestamp <= entry.timestamp) {
break;
}
- })
+ }
hmll_insert(hmll, insert_after, entry, can_free_entry);
}
@@ -1271,7 +1238,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags)
// string is close to useless: you can only use it with :& or :~ and
// that’s all because s//~ is not available until the first call to
// regtilde. Vim was not calling this for some reason.
- (void)regtilde(cur_entry.data.sub_string.sub, p_magic);
+ (void)(char *)regtilde((char_u *)cur_entry.data.sub_string.sub, p_magic);
// Do not free shada entry: its allocated memory was saved above.
break;
case kSDItemHistoryEntry:
@@ -1361,9 +1328,11 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags)
}
case kSDItemBufferList:
for (size_t i = 0; i < cur_entry.data.buffer_list.size; i++) {
- char *const sfname = path_try_shorten_fname(cur_entry.data.buffer_list.buffers[i].fname);
- buf_T *const buf = buflist_new(cur_entry.data.buffer_list.buffers[i].fname, sfname, 0,
- BLN_LISTED);
+ char *const sfname =
+ (char *)path_try_shorten_fname((char_u *)cur_entry.data.buffer_list.buffers[i].fname);
+ buf_T *const buf =
+ buflist_new((char_u *)cur_entry.data.buffer_list.buffers[i].fname, (char_u *)sfname, 0,
+ BLN_LISTED);
if (buf != NULL) {
RESET_FMARK(&buf->b_last_cursor,
cur_entry.data.buffer_list.buffers[i].pos, 0);
@@ -1502,7 +1471,7 @@ static char *shada_filename(const char *file)
if (p_shadafile != NULL && *p_shadafile != NUL) {
file = p_shadafile;
} else {
- if ((file = find_shada_parameter('n')) == NULL || *file == NUL) {
+ if ((file = (char *)find_shada_parameter('n')) == NULL || *file == NUL) {
file = shada_get_default_file();
}
// XXX It used to be one level lower, so that whatever is in
@@ -1522,14 +1491,6 @@ static char *shada_filename(const char *file)
msgpack_pack_str(spacker, sizeof(s) - 1); \
msgpack_pack_str_body(spacker, s, sizeof(s) - 1); \
} while (0)
-#define PACK_STRING(s) \
- do { \
- const String s_ = (s); \
- msgpack_pack_str(spacker, s_.size); \
- if (s_.size) { \
- msgpack_pack_str_body(spacker, s_.data, s_.size); \
- } \
- } while (0)
#define PACK_BIN(s) \
do { \
const String s_ = (s); \
@@ -1810,7 +1771,11 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, ShadaEntr
case kSDItemHeader:
msgpack_pack_map(spacker, entry.data.header.size);
for (size_t i = 0; i < entry.data.header.size; i++) {
- PACK_STRING(entry.data.header.items[i].key);
+ const String s = entry.data.header.items[i].key;
+ msgpack_pack_str(spacker, s.size);
+ if (s.size) {
+ msgpack_pack_str_body(spacker, s.data, s.size);
+ }
const Object obj = entry.data.header.items[i].value;
switch (obj.type) {
case kObjectTypeString:
@@ -1856,7 +1821,6 @@ shada_pack_entry_error:
msgpack_sbuffer_destroy(&sbuf);
return ret;
}
-#undef PACK_STRING
/// Write single ShaDa entry and free it afterwards
///
@@ -2694,7 +2658,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef
.timestamp = sub.timestamp,
.data = {
.sub_string = {
- .sub = (char *)sub.sub,
+ .sub = sub.sub,
.additional_elements = sub.additional_elements,
}
}
@@ -2957,7 +2921,6 @@ shada_write_exit:
return ret;
}
-#undef IGNORE_BUF
#undef PACK_STATIC_STR
/// Write ShaDa file to a given location
@@ -3037,11 +3000,11 @@ shada_write_file_open: {}
}
if (nomerge) {
shada_write_file_nomerge: {}
- char *const tail = path_tail_with_sep(fname);
+ char *const tail = (char *)path_tail_with_sep((char_u *)fname);
if (tail != fname) {
const char tail_save = *tail;
*tail = NUL;
- if (!os_isdir(fname)) {
+ if (!os_isdir((char_u *)fname)) {
int ret;
char *failed_dir;
if ((ret = os_mkdir_recurse(fname, 0700, &failed_dir)) != 0) {
@@ -3092,7 +3055,7 @@ shada_write_file_nomerge: {}
// overwrite a user’s viminfo file after a "su root", with a
// viminfo file that the user can't read.
FileInfo old_info;
- if (os_fileinfo((char *)fname, &old_info)) {
+ if (os_fileinfo(fname, &old_info)) {
if (getuid() == ROOT_UID) {
if (old_info.stat.st_uid != ROOT_UID
|| old_info.stat.st_gid != getgid()) {
@@ -3116,7 +3079,7 @@ shada_write_file_nomerge: {}
}
}
#endif
- if (vim_rename(tempname, fname) == -1) {
+ if (vim_rename((char_u *)tempname, (char_u *)fname) == -1) {
EMSG3(_(RNERR "Can't rename ShaDa file from %s to %s!"),
tempname, fname);
} else {
@@ -3424,8 +3387,7 @@ static ShaDaReadResult msgpack_read_uint64(ShaDaReadDef *const sd_reader, const
sizeof(*un.data.via.map.ptr)); \
ad_ga.ga_len++; \
}
-#define CONVERTED(str, len) (xmemdupz((str), (len)))
-#define BIN_CONVERTED(b) CONVERTED(b.ptr, b.size)
+#define BIN_CONVERTED(b) (xmemdupz((b.ptr), (b.size)))
#define SET_ADDITIONAL_DATA(tgt, name) \
do { \
if (ad_ga.ga_len) { \
@@ -3982,7 +3944,6 @@ shada_read_next_item_error:
goto shada_read_next_item_end;
}
#undef BIN_CONVERTED
-#undef CONVERTED
#undef CHECK_KEY
#undef BOOLEAN_KEY
#undef CONVERTED_STRING_KEY
@@ -4015,13 +3976,13 @@ static bool shada_removable(const char *name)
char part[MAXPATHL + 1];
bool retval = false;
- char *new_name = home_replace_save(NULL, name);
+ char *new_name = (char *)home_replace_save(NULL, (char_u *)name);
for (p = (char *)p_shada; *p; ) {
- (void)copy_option_part(&p, part, ARRAY_SIZE(part), ", ");
+ (void)(char *)copy_option_part((char_u **)&p, (char_u *)part, ARRAY_SIZE(part), ", ");
if (part[0] == 'r') {
- home_replace(NULL, part + 1, NameBuff, MAXPATHL, true);
+ home_replace(NULL, (char_u *)(part + 1), (char_u *)NameBuff, MAXPATHL, true);
size_t n = STRLEN(NameBuff);
- if (mb_strnicmp(NameBuff, new_name, n) == 0) {
+ if (mb_strnicmp((char_u *)NameBuff, (char_u *)new_name, n) == 0) {
retval = true;
break;
}
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index 3e56ad561b..450ec891ad 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -6073,7 +6073,7 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res)
wordlen = 0;
for (const char_u *s = inword; *s != NUL; ) {
const char_u *t = s;
- c = mb_cptr2char_adv((const char_u **)&s);
+ c = mb_cptr2char_adv(&s);
if (slang->sl_rem_accents) {
if (utf_class(c) == 0) {
if (did_white) {
diff --git a/src/nvim/state.c b/src/nvim/state.c
index a9f3d67849..04271d750c 100644
--- a/src/nvim/state.c
+++ b/src/nvim/state.c
@@ -161,6 +161,11 @@ char *get_mode(void)
if (State & VREPLACE_FLAG) {
buf[0] = 'R';
buf[1] = 'v';
+ if (ins_compl_active()) {
+ buf[2] = 'c';
+ } else if (ctrl_x_mode_not_defined_yet()) {
+ buf[2] = 'x';
+ }
} else {
if (State & REPLACE_FLAG) {
buf[0] = 'R';
diff --git a/src/nvim/strings.c b/src/nvim/strings.c
index 79a3db4843..11c1aa1760 100644
--- a/src/nvim/strings.c
+++ b/src/nvim/strings.c
@@ -1,28 +1,26 @@
// 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
+#include <assert.h>
#include <inttypes.h>
+#include <math.h>
#include <stdarg.h>
#include <stdbool.h>
#include <string.h>
-#include <math.h>
-#include <assert.h>
-#include "nvim/assert.h"
-#include "nvim/vim.h"
#include "nvim/ascii.h"
-#include "nvim/strings.h"
-#include "nvim/file_search.h"
+#include "nvim/assert.h"
#include "nvim/buffer.h"
#include "nvim/charset.h"
#include "nvim/diff.h"
#include "nvim/edit.h"
#include "nvim/eval.h"
+#include "nvim/eval/encode.h"
#include "nvim/ex_cmds.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_getln.h"
+#include "nvim/file_search.h"
#include "nvim/fileio.h"
-#include "nvim/func_attr.h"
#include "nvim/fold.h"
#include "nvim/func_attr.h"
#include "nvim/getchar.h"
@@ -35,8 +33,10 @@
#include "nvim/message.h"
#include "nvim/misc1.h"
#include "nvim/move.h"
-#include "nvim/option.h"
#include "nvim/ops.h"
+#include "nvim/option.h"
+#include "nvim/os/os.h"
+#include "nvim/os/shell.h"
#include "nvim/os_unix.h"
#include "nvim/path.h"
#include "nvim/quickfix.h"
@@ -44,12 +44,11 @@
#include "nvim/screen.h"
#include "nvim/search.h"
#include "nvim/spell.h"
+#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/tag.h"
+#include "nvim/vim.h"
#include "nvim/window.h"
-#include "nvim/os/os.h"
-#include "nvim/os/shell.h"
-#include "nvim/eval/encode.h"
/// Copy "string" into newly allocated memory.
char_u *vim_strsave(const char_u *string)
@@ -84,8 +83,7 @@ char_u *vim_strsave_escaped(const char_u *string, const char_u *esc_chars)
* characters where rem_backslash() would remove the backslash.
* Escape the characters with "cc".
*/
-char_u *vim_strsave_escaped_ext(const char_u *string, const char_u *esc_chars,
- char_u cc, bool bsl)
+char_u *vim_strsave_escaped_ext(const char_u *string, const char_u *esc_chars, char_u cc, bool bsl)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL
{
/*
@@ -100,9 +98,10 @@ char_u *vim_strsave_escaped_ext(const char_u *string, const char_u *esc_chars,
p += l - 1;
continue;
}
- if (vim_strchr(esc_chars, *p) != NULL || (bsl && rem_backslash(p)))
- ++length; /* count a backslash */
- ++length; /* count an ordinary char */
+ if (vim_strchr(esc_chars, *p) != NULL || (bsl && rem_backslash(p))) {
+ ++length; // count a backslash
+ }
+ ++length; // count an ordinary char
}
char_u *escaped_string = xmalloc(length);
@@ -112,11 +111,12 @@ char_u *vim_strsave_escaped_ext(const char_u *string, const char_u *esc_chars,
if (l > 1) {
memcpy(p2, p, l);
p2 += l;
- p += l - 1; /* skip multibyte char */
+ p += l - 1; // skip multibyte char
continue;
}
- if (vim_strchr(esc_chars, *p) != NULL || (bsl && rem_backslash(p)))
+ if (vim_strchr(esc_chars, *p) != NULL || (bsl && rem_backslash(p))) {
*p2++ = cc;
+ }
*p2++ = *p;
}
*p2 = NUL;
@@ -182,12 +182,11 @@ char *vim_strnsave_unquoted(const char *const string, const size_t length)
* When "do_newline" is false do not escape newline unless it is csh shell.
* Returns the result in allocated memory.
*/
-char_u *vim_strsave_shellescape(const char_u *string,
- bool do_special, bool do_newline)
+char_u *vim_strsave_shellescape(const char_u *string, bool do_special, bool do_newline)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL
{
- char_u *d;
- char_u *escaped_string;
+ char_u *d;
+ char_u *escaped_string;
size_t l;
int csh_like;
bool fish_like;
@@ -202,7 +201,7 @@ char_u *vim_strsave_shellescape(const char_u *string,
// itself must be escaped to get a literal '\'.
fish_like = fish_like_shell();
- /* First count the number of extra bytes required. */
+ // First count the number of extra bytes required.
size_t length = STRLEN(string) + 3; // two quotes and a trailing NUL
for (const char_u *p = string; *p != NUL; MB_PTR_ADV(p)) {
#ifdef WIN32
@@ -217,12 +216,13 @@ char_u *vim_strsave_shellescape(const char_u *string,
}
if ((*p == '\n' && (csh_like || do_newline))
|| (*p == '!' && (csh_like || do_special))) {
- ++length; /* insert backslash */
- if (csh_like && do_special)
- ++length; /* insert backslash */
+ ++length; // insert backslash
+ if (csh_like && do_special) {
+ ++length; // insert backslash
+ }
}
if (do_special && find_cmdline_var(p, &l) >= 0) {
- ++length; /* insert backslash */
+ ++length; // insert backslash
p += l - 1;
}
if (*p == '\\' && fish_like) {
@@ -230,7 +230,7 @@ char_u *vim_strsave_shellescape(const char_u *string,
}
}
- /* Allocate memory for the result and fill it. */
+ // Allocate memory for the result and fill it.
escaped_string = xmalloc(length);
d = escaped_string;
@@ -264,15 +264,17 @@ char_u *vim_strsave_shellescape(const char_u *string,
if ((*p == '\n' && (csh_like || do_newline))
|| (*p == '!' && (csh_like || do_special))) {
*d++ = '\\';
- if (csh_like && do_special)
+ if (csh_like && do_special) {
*d++ = '\\';
+ }
*d++ = *p++;
continue;
}
if (do_special && find_cmdline_var(p, &l) >= 0) {
- *d++ = '\\'; /* insert backslash */
- while (--l != SIZE_MAX) /* copy the var */
+ *d++ = '\\'; // insert backslash
+ while (--l != SIZE_MAX) { // copy the var
*d++ = *p++;
+ }
continue;
}
if (*p == '\\' && fish_like) {
@@ -285,11 +287,11 @@ char_u *vim_strsave_shellescape(const char_u *string,
}
// add terminating quote and finish with a NUL
-# ifdef WIN32
+#ifdef WIN32
if (!p_ssl) {
*d++ = '"';
} else
-# endif
+#endif
*d++ = '\'';
*d = NUL;
@@ -384,11 +386,12 @@ char *strcase_save(const char *const orig, bool upper)
void del_trailing_spaces(char_u *ptr)
FUNC_ATTR_NONNULL_ALL
{
- char_u *q;
+ char_u *q;
q = ptr + STRLEN(ptr);
- while (--q > ptr && ascii_iswhite(q[0]) && q[-1] != '\\' && q[-1] != Ctrl_V)
+ while (--q > ptr && ascii_iswhite(q[0]) && q[-1] != '\\' && q[-1] != Ctrl_V) {
*q = NUL;
+ }
}
#if (!defined(HAVE_STRCASECMP) && !defined(HAVE_STRICMP))
@@ -404,14 +407,16 @@ int vim_stricmp(const char *s1, const char *s2)
for (;; ) {
i = (int)TOLOWER_LOC(*s1) - (int)TOLOWER_LOC(*s2);
- if (i != 0)
- return i; /* this character different */
- if (*s1 == NUL)
- break; /* strings match until NUL */
+ if (i != 0) {
+ return i; // this character different
+ }
+ if (*s1 == NUL) {
+ break; // strings match until NUL
+ }
++s1;
++s2;
}
- return 0; /* strings match */
+ return 0; // strings match
}
#endif
@@ -428,15 +433,17 @@ int vim_strnicmp(const char *s1, const char *s2, size_t len)
while (len > 0) {
i = (int)TOLOWER_LOC(*s1) - (int)TOLOWER_LOC(*s2);
- if (i != 0)
- return i; /* this character different */
- if (*s1 == NUL)
- break; /* strings match until NUL */
+ if (i != 0) {
+ return i; // this character different
+ }
+ if (*s1 == NUL) {
+ break; // strings match until NUL
+ }
++s1;
++s2;
--len;
}
- return 0; /* strings match */
+ return 0; // strings match
}
#endif
@@ -490,10 +497,13 @@ bool has_non_ascii(const char_u *s)
{
const char_u *p;
- if (s != NULL)
- for (p = s; *p != NUL; ++p)
- if (*p >= 128)
+ if (s != NULL) {
+ for (p = s; *p != NUL; ++p) {
+ if (*p >= 128) {
return true;
+ }
+ }
+ }
return false;
}
@@ -504,7 +514,7 @@ bool has_non_ascii_len(const char *const s, const size_t len)
{
if (s != NULL) {
for (size_t i = 0; i < len; i++) {
- if ((uint8_t) s[i] >= 128) {
+ if ((uint8_t)s[i] >= 128) {
return true;
}
}
@@ -527,7 +537,7 @@ char_u *concat_str(const char_u *restrict str1, const char_u *restrict str2)
static const char *const e_printf =
- N_("E766: Insufficient arguments for printf()");
+ N_("E766: Insufficient arguments for printf()");
/// Get number argument from idxp entry in tvs
///
@@ -606,15 +616,14 @@ static const void *tv_ptr(const typval_T *const tvs, int *const idxp)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
#define OFF(attr) offsetof(union typval_vval_union, attr)
- STATIC_ASSERT(
- OFF(v_string) == OFF(v_list)
- && OFF(v_string) == OFF(v_dict)
- && OFF(v_string) == OFF(v_partial)
- && sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_list)
- && sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_dict)
- && sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_partial),
- "Strings, dictionaries, lists and partials are expected to be pointers, "
- "so that all three of them can be accessed via v_string");
+ STATIC_ASSERT(OFF(v_string) == OFF(v_list)
+ && OFF(v_string) == OFF(v_dict)
+ && OFF(v_string) == OFF(v_partial)
+ && sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_list)
+ && sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_dict)
+ && sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_partial),
+ "Strings, dictionaries, lists and partials are expected to be pointers, "
+ "so that all three of them can be accessed via v_string");
#undef OFF
const int idx = *idxp - 1;
if (tvs[idx].v_type == VAR_UNKNOWN) {
@@ -735,8 +744,8 @@ int vim_snprintf(char *str, size_t str_m, const char *fmt, ...)
// Return the representation of infinity for printf() function:
// "-inf", "inf", "+inf", " inf", "-INF", "INF", "+INF" or " INF".
-static const char *infinity_str(bool positive, char fmt_spec,
- int force_sign, int space_for_positive)
+static const char *infinity_str(bool positive, char fmt_spec, int force_sign,
+ int space_for_positive)
{
static const char *table[] = {
"-inf", "inf", "+inf", " inf",
@@ -765,8 +774,7 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap)
///
/// @return Number of bytes excluding NUL byte that would be written to the
/// string if str_m was greater or equal to the return value.
-int vim_vsnprintf_typval(
- char *str, size_t str_m, const char *fmt, va_list ap, typval_T *const tvs)
+int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap, typval_T *const tvs)
{
size_t str_l = 0;
bool str_avail = str_l < str_m;
@@ -800,7 +808,7 @@ int vim_vsnprintf_typval(
char length_modifier = '\0';
// temporary buffer for simple numeric->string conversion
-# define TMP_LEN 350 // 1e308 seems reasonable as the maximum printable
+#define TMP_LEN 350 // 1e308 seems reasonable as the maximum printable
char tmp[TMP_LEN];
// string address in case of string argument
@@ -832,15 +840,22 @@ int vim_vsnprintf_typval(
// parse flags
while (true) {
switch (*p) {
- case '0': zero_padding = 1; p++; continue;
- case '-': justify_left = 1; p++; continue;
- // if both '0' and '-' flags appear, '0' should be ignored
- case '+': force_sign = 1; space_for_positive = 0; p++; continue;
- case ' ': force_sign = 1; p++; continue;
- // if both ' ' and '+' flags appear, ' ' should be ignored
- case '#': alternate_form = 1; p++; continue;
- case '\'': p++; continue;
- default: break;
+ case '0':
+ zero_padding = 1; p++; continue;
+ case '-':
+ justify_left = 1; p++; continue;
+ // if both '0' and '-' flags appear, '0' should be ignored
+ case '+':
+ force_sign = 1; space_for_positive = 0; p++; continue;
+ case ' ':
+ force_sign = 1; p++; continue;
+ // if both ' ' and '+' flags appear, ' ' should be ignored
+ case '#':
+ alternate_form = 1; p++; continue;
+ case '\'':
+ p++; continue;
+ default:
+ break;
}
break;
}
@@ -905,444 +920,447 @@ int vim_vsnprintf_typval(
// common synonyms
switch (fmt_spec) {
- case 'i': fmt_spec = 'd'; break;
- case 'D': fmt_spec = 'd'; length_modifier = 'l'; break;
- case 'U': fmt_spec = 'u'; length_modifier = 'l'; break;
- case 'O': fmt_spec = 'o'; length_modifier = 'l'; break;
- default: break;
+ case 'i':
+ fmt_spec = 'd'; break;
+ case 'D':
+ fmt_spec = 'd'; length_modifier = 'l'; break;
+ case 'U':
+ fmt_spec = 'u'; length_modifier = 'l'; break;
+ case 'O':
+ fmt_spec = 'o'; length_modifier = 'l'; break;
+ default:
+ break;
}
switch (fmt_spec) {
- case 'b': case 'B':
- case 'd': case 'u': case 'o': case 'x': case 'X':
- if (tvs && length_modifier == '\0') {
- length_modifier = '2';
- }
+ case 'b':
+ case 'B':
+ case 'd':
+ case 'u':
+ case 'o':
+ case 'x':
+ case 'X':
+ if (tvs && length_modifier == '\0') {
+ length_modifier = '2';
+ }
}
// get parameter value, do initial processing
switch (fmt_spec) {
- // '%' and 'c' behave similar to 's' regarding flags and field widths
- case '%': case 'c': case 's': case 'S':
- str_arg_l = 1;
- switch (fmt_spec) {
- case '%':
- str_arg = p;
- break;
-
- case 'c': {
- const int j = tvs ? (int)tv_nr(tvs, &arg_idx) : va_arg(ap, int);
- // standard demands unsigned char
- uchar_arg = (unsigned char)j;
- str_arg = (char *)&uchar_arg;
- break;
- }
+ // '%' and 'c' behave similar to 's' regarding flags and field widths
+ case '%':
+ case 'c':
+ case 's':
+ case 'S':
+ str_arg_l = 1;
+ switch (fmt_spec) {
+ case '%':
+ str_arg = p;
+ break;
- case 's':
- case 'S':
- str_arg = tvs ? tv_str(tvs, &arg_idx, &tofree)
- : va_arg(ap, const char *);
- if (!str_arg) {
- str_arg = "[NULL]";
- str_arg_l = 6;
- } else if (!precision_specified) {
- // make sure not to address string beyond the specified
- // precision
- str_arg_l = strlen(str_arg);
- } else if (precision == 0) {
- // truncate string if necessary as requested by precision
- str_arg_l = 0;
- } else {
- // memchr on HP does not like n > 2^31
- // TODO(elmart): check if this still holds / is relevant
- str_arg_l = (size_t)((char *)xmemscan(str_arg,
- NUL,
- MIN(precision,
- 0x7fffffff))
- - str_arg);
- }
- if (fmt_spec == 'S') {
- if (min_field_width != 0) {
- min_field_width += (strlen(str_arg)
- - mb_string2cells((char_u *)str_arg));
- }
- if (precision) {
- char_u *p1;
- size_t i = 0;
-
- for (p1 = (char_u *)str_arg; *p1;
- p1 += mb_ptr2len(p1)) {
- i += (size_t)utf_ptr2cells(p1);
- if (i > precision) {
- break;
- }
- }
- str_arg_l = (size_t)(p1 - (char_u *)str_arg);
+ case 'c': {
+ const int j = tvs ? (int)tv_nr(tvs, &arg_idx) : va_arg(ap, int);
+ // standard demands unsigned char
+ uchar_arg = (unsigned char)j;
+ str_arg = (char *)&uchar_arg;
+ break;
+ }
+
+ case 's':
+ case 'S':
+ str_arg = tvs ? tv_str(tvs, &arg_idx, &tofree)
+ : va_arg(ap, const char *);
+ if (!str_arg) {
+ str_arg = "[NULL]";
+ str_arg_l = 6;
+ } else if (!precision_specified) {
+ // make sure not to address string beyond the specified
+ // precision
+ str_arg_l = strlen(str_arg);
+ } else if (precision == 0) {
+ // truncate string if necessary as requested by precision
+ str_arg_l = 0;
+ } else {
+ // memchr on HP does not like n > 2^31
+ // TODO(elmart): check if this still holds / is relevant
+ str_arg_l = (size_t)((char *)xmemscan(str_arg,
+ NUL,
+ MIN(precision,
+ 0x7fffffff))
+ - str_arg);
+ }
+ if (fmt_spec == 'S') {
+ if (min_field_width != 0) {
+ min_field_width += (strlen(str_arg)
+ - mb_string2cells((char_u *)str_arg));
+ }
+ if (precision) {
+ char_u *p1;
+ size_t i = 0;
+
+ for (p1 = (char_u *)str_arg; *p1;
+ p1 += mb_ptr2len(p1)) {
+ i += (size_t)utf_ptr2cells(p1);
+ if (i > precision) {
+ break;
}
}
- break;
-
- default:
- break;
+ str_arg_l = (size_t)(p1 - (char_u *)str_arg);
+ }
}
break;
- case 'd':
- case 'u':
- case 'b': case 'B':
- case 'o':
- case 'x': case 'X':
- case 'p': {
- // u, b, B, o, x, X and p conversion specifiers imply
- // the value is unsigned; d implies a signed value
-
- // 0 if numeric argument is zero (or if pointer is NULL for 'p'),
- // +1 if greater than zero (or non NULL for 'p'),
- // -1 if negative (unsigned argument is never negative)
- int arg_sign = 0;
-
- intmax_t arg = 0;
- uintmax_t uarg = 0;
-
- // only defined for p conversion
- const void *ptr_arg = NULL;
-
- if (fmt_spec == 'p') {
- ptr_arg = tvs ? tv_ptr(tvs, &arg_idx) : va_arg(ap, void *);
- if (ptr_arg) {
- arg_sign = 1;
- }
- } else if (fmt_spec == 'd') {
- // signed
- switch (length_modifier) {
- case '\0': {
- arg = (int)(tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, int));
- break;
- }
- case 'h': {
- // char and short arguments are passed as int16_t
- arg = (int16_t)(tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, int));
- break;
- }
- case 'l': {
- arg = (tvs ? (long)tv_nr(tvs, &arg_idx) : va_arg(ap, long));
- break;
- }
- case '2': {
- arg = (
- tvs
+ default:
+ break;
+ }
+ break;
+
+ case 'd':
+ case 'u':
+ case 'b':
+ case 'B':
+ case 'o':
+ case 'x':
+ case 'X':
+ case 'p': {
+ // u, b, B, o, x, X and p conversion specifiers imply
+ // the value is unsigned; d implies a signed value
+
+ // 0 if numeric argument is zero (or if pointer is NULL for 'p'),
+ // +1 if greater than zero (or non NULL for 'p'),
+ // -1 if negative (unsigned argument is never negative)
+ int arg_sign = 0;
+
+ intmax_t arg = 0;
+ uintmax_t uarg = 0;
+
+ // only defined for p conversion
+ const void *ptr_arg = NULL;
+
+ if (fmt_spec == 'p') {
+ ptr_arg = tvs ? tv_ptr(tvs, &arg_idx) : va_arg(ap, void *);
+ if (ptr_arg) {
+ arg_sign = 1;
+ }
+ } else if (fmt_spec == 'd') {
+ // signed
+ switch (length_modifier) {
+ case '\0':
+ arg = (int)(tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, int));
+ break;
+ case 'h':
+ // char and short arguments are passed as int16_t
+ arg = (int16_t)(tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, int));
+ break;
+ case 'l':
+ arg = (tvs ? (long)tv_nr(tvs, &arg_idx) : va_arg(ap, long));
+ break;
+ case '2':
+ arg = (
+ tvs
? (long long)tv_nr(tvs, &arg_idx) // NOLINT (runtime/int)
: va_arg(ap, long long)); // NOLINT (runtime/int)
- break;
- }
- case 'z': {
- arg = (tvs
+ break;
+ case 'z':
+ arg = (tvs
? (ptrdiff_t)tv_nr(tvs, &arg_idx)
: va_arg(ap, ptrdiff_t));
- break;
- }
- }
- if (arg > 0) {
- arg_sign = 1;
- } else if (arg < 0) {
- arg_sign = -1;
- }
- } else {
- // unsigned
- switch (length_modifier) {
- case '\0': {
- uarg = (unsigned int)(tvs
+ break;
+ }
+ if (arg > 0) {
+ arg_sign = 1;
+ } else if (arg < 0) {
+ arg_sign = -1;
+ }
+ } else {
+ // unsigned
+ switch (length_modifier) {
+ case '\0':
+ uarg = (unsigned int)(tvs
? tv_nr(tvs, &arg_idx)
: va_arg(ap, unsigned int));
- break;
- }
- case 'h': {
- uarg = (uint16_t)(tvs
+ break;
+ case 'h':
+ uarg = (uint16_t)(tvs
? tv_nr(tvs, &arg_idx)
: va_arg(ap, unsigned int));
- break;
- }
- case 'l': {
- uarg = (tvs
+ break;
+ case 'l':
+ 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)
- tvs
+ break;
+ case '2':
+ uarg = (uintmax_t)(unsigned long long)( // NOLINT (runtime/int)
+ tvs
? ((unsigned long long) // NOLINT (runtime/int)
tv_nr(tvs, &arg_idx))
: va_arg(ap, unsigned long long)); // NOLINT (runtime/int)
- break;
- }
- case 'z': {
- uarg = (tvs
+ break;
+ case 'z':
+ uarg = (tvs
? (size_t)tv_nr(tvs, &arg_idx)
: va_arg(ap, size_t));
- break;
- }
- }
- arg_sign = (uarg != 0);
+ break;
}
+ arg_sign = (uarg != 0);
+ }
- str_arg = tmp;
- str_arg_l = 0;
+ str_arg = tmp;
+ str_arg_l = 0;
- // For d, i, u, o, x, and X conversions, if precision is specified,
- // '0' flag should be ignored. This is so with Solaris 2.6, Digital
- // UNIX 4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with Perl.
- if (precision_specified) {
- zero_padding = 0;
- }
+ // For d, i, u, o, x, and X conversions, if precision is specified,
+ // '0' flag should be ignored. This is so with Solaris 2.6, Digital
+ // UNIX 4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with Perl.
+ if (precision_specified) {
+ zero_padding = 0;
+ }
- if (fmt_spec == 'd') {
- if (force_sign && arg_sign >= 0) {
- tmp[str_arg_l++] = space_for_positive ? ' ' : '+';
- }
- // leave negative numbers for snprintf to handle, to
- // avoid handling tricky cases like (short int)-32768
- } else if (alternate_form) {
- if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X'
- || fmt_spec == 'b' || fmt_spec == 'B')) {
- tmp[str_arg_l++] = '0';
- tmp[str_arg_l++] = fmt_spec;
- }
- // alternate form should have no effect for p * conversion, but ...
+ if (fmt_spec == 'd') {
+ if (force_sign && arg_sign >= 0) {
+ tmp[str_arg_l++] = space_for_positive ? ' ' : '+';
}
-
- zero_padding_insertion_ind = str_arg_l;
- if (!precision_specified) {
- precision = 1; // default precision is 1
+ // leave negative numbers for snprintf to handle, to
+ // avoid handling tricky cases like (short int)-32768
+ } else if (alternate_form) {
+ if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X'
+ || fmt_spec == 'b' || fmt_spec == 'B')) {
+ tmp[str_arg_l++] = '0';
+ tmp[str_arg_l++] = fmt_spec;
}
- if (precision == 0 && arg_sign == 0) {
- // when zero value is formatted with an explicit precision 0,
- // resulting formatted string is empty (d, i, u, b, B, o, x, X, p)
- } else {
- switch (fmt_spec) {
- case 'p': { // pointer
- str_arg_l += (size_t)snprintf(tmp + str_arg_l,
- sizeof(tmp) - str_arg_l,
- "%p", ptr_arg);
- break;
- }
- case 'd': { // signed
- str_arg_l += (size_t)snprintf(tmp + str_arg_l,
- sizeof(tmp) - str_arg_l,
- "%" PRIdMAX, arg);
- break;
- }
- case 'b': case 'B': { // binary
- size_t bits = 0;
- for (bits = sizeof(uintmax_t) * 8; bits > 0; bits--) {
- if ((uarg >> (bits - 1)) & 0x1) {
- break;
- }
- }
+ // alternate form should have no effect for p * conversion, but ...
+ }
- while (bits > 0) {
- tmp[str_arg_l++] = ((uarg >> --bits) & 0x1) ? '1' : '0';
- }
- break;
- }
- default: { // unsigned
- // construct a simple format string for snprintf
- char f[] = "%" PRIuMAX;
- f[sizeof("%" PRIuMAX) - 1 - 1] = fmt_spec;
- assert(PRIuMAX[sizeof(PRIuMAX) - 1 - 1] == 'u');
- str_arg_l += (size_t)snprintf(tmp + str_arg_l,
- sizeof(tmp) - str_arg_l,
- f, uarg);
+ zero_padding_insertion_ind = str_arg_l;
+ if (!precision_specified) {
+ precision = 1; // default precision is 1
+ }
+ if (precision == 0 && arg_sign == 0) {
+ // when zero value is formatted with an explicit precision 0,
+ // resulting formatted string is empty (d, i, u, b, B, o, x, X, p)
+ } else {
+ switch (fmt_spec) {
+ case 'p': // pointer
+ str_arg_l += (size_t)snprintf(tmp + str_arg_l,
+ sizeof(tmp) - str_arg_l,
+ "%p", ptr_arg);
+ break;
+ case 'd': // signed
+ str_arg_l += (size_t)snprintf(tmp + str_arg_l,
+ sizeof(tmp) - str_arg_l,
+ "%" PRIdMAX, arg);
+ break;
+ case 'b':
+ case 'B': { // binary
+ size_t bits = 0;
+ for (bits = sizeof(uintmax_t) * 8; bits > 0; bits--) {
+ if ((uarg >> (bits - 1)) & 0x1) {
break;
}
}
- assert(str_arg_l < sizeof(tmp));
- // include the optional minus sign and possible "0x" in the region
- // before the zero padding insertion point
- if (zero_padding_insertion_ind < str_arg_l
- && tmp[zero_padding_insertion_ind] == '-') {
- zero_padding_insertion_ind++;
- }
- if (zero_padding_insertion_ind + 1 < str_arg_l
- && tmp[zero_padding_insertion_ind] == '0'
- && (tmp[zero_padding_insertion_ind + 1] == 'x'
- || tmp[zero_padding_insertion_ind + 1] == 'X'
- || tmp[zero_padding_insertion_ind + 1] == 'b'
- || tmp[zero_padding_insertion_ind + 1] == 'B')) {
- zero_padding_insertion_ind += 2;
+ while (bits > 0) {
+ tmp[str_arg_l++] = ((uarg >> --bits) & 0x1) ? '1' : '0';
}
+ break;
+ }
+ default: { // unsigned
+ // construct a simple format string for snprintf
+ char f[] = "%" PRIuMAX;
+ f[sizeof("%" PRIuMAX) - 1 - 1] = fmt_spec;
+ assert(PRIuMAX[sizeof(PRIuMAX) - 1 - 1] == 'u');
+ str_arg_l += (size_t)snprintf(tmp + str_arg_l,
+ sizeof(tmp) - str_arg_l,
+ f, uarg);
+ break;
+ }
}
+ assert(str_arg_l < sizeof(tmp));
- {
- size_t num_of_digits = str_arg_l - zero_padding_insertion_ind;
-
- if (alternate_form && fmt_spec == 'o'
- // unless zero is already the first character
- && !(zero_padding_insertion_ind < str_arg_l
- && tmp[zero_padding_insertion_ind] == '0')) {
- // assure leading zero for alternate-form octal numbers
- if (!precision_specified
- || precision < num_of_digits + 1) {
- // precision is increased to force the first character to be
- // zero, except if a zero value is formatted with an explicit
- // precision of zero
- precision = num_of_digits + 1;
- }
- }
- // zero padding to specified precision?
- if (num_of_digits < precision) {
- number_of_zeros_to_pad = precision - num_of_digits;
- }
+ // include the optional minus sign and possible "0x" in the region
+ // before the zero padding insertion point
+ if (zero_padding_insertion_ind < str_arg_l
+ && tmp[zero_padding_insertion_ind] == '-') {
+ zero_padding_insertion_ind++;
}
- // zero padding to specified minimal field width?
- if (!justify_left && zero_padding) {
- const int n = (int)(min_field_width - (str_arg_l
- + number_of_zeros_to_pad));
- if (n > 0) {
- number_of_zeros_to_pad += (size_t)n;
- }
+ if (zero_padding_insertion_ind + 1 < str_arg_l
+ && tmp[zero_padding_insertion_ind] == '0'
+ && (tmp[zero_padding_insertion_ind + 1] == 'x'
+ || tmp[zero_padding_insertion_ind + 1] == 'X'
+ || tmp[zero_padding_insertion_ind + 1] == 'b'
+ || tmp[zero_padding_insertion_ind + 1] == 'B')) {
+ zero_padding_insertion_ind += 2;
}
- break;
}
- case 'f':
- case 'F':
- case 'e':
- case 'E':
- case 'g':
- case 'G':
- {
- // floating point
- char format[40];
- int remove_trailing_zeroes = false;
-
- double f = tvs ? tv_float(tvs, &arg_idx) : va_arg(ap, double);
- double abs_f = f < 0 ? -f : f;
-
- if (fmt_spec == 'g' || fmt_spec == 'G') {
- // can't use %g directly, cause it prints "1.0" as "1"
- if ((abs_f >= 0.001 && abs_f < 10000000.0) || abs_f == 0.0) {
- fmt_spec = ASCII_ISUPPER(fmt_spec) ? 'F' : 'f';
- } else {
- fmt_spec = fmt_spec == 'g' ? 'e' : 'E';
- }
- remove_trailing_zeroes = true;
+ {
+ size_t num_of_digits = str_arg_l - zero_padding_insertion_ind;
+
+ if (alternate_form && fmt_spec == 'o'
+ // unless zero is already the first character
+ && !(zero_padding_insertion_ind < str_arg_l
+ && tmp[zero_padding_insertion_ind] == '0')) {
+ // assure leading zero for alternate-form octal numbers
+ if (!precision_specified
+ || precision < num_of_digits + 1) {
+ // precision is increased to force the first character to be
+ // zero, except if a zero value is formatted with an explicit
+ // precision of zero
+ precision = num_of_digits + 1;
}
+ }
+ // zero padding to specified precision?
+ if (num_of_digits < precision) {
+ number_of_zeros_to_pad = precision - num_of_digits;
+ }
+ }
+ // zero padding to specified minimal field width?
+ if (!justify_left && zero_padding) {
+ const int n = (int)(min_field_width - (str_arg_l
+ + number_of_zeros_to_pad));
+ if (n > 0) {
+ number_of_zeros_to_pad += (size_t)n;
+ }
+ }
+ break;
+ }
- if (xisinf(f)
- || (strchr("fF", fmt_spec) != NULL && abs_f > 1.0e307)) {
- xstrlcpy(tmp, infinity_str(f > 0.0, fmt_spec,
- force_sign, space_for_positive),
- sizeof(tmp));
- str_arg_l = strlen(tmp);
- zero_padding = 0;
- } else if (xisnan(f)) {
- // Not a number: nan or NAN
- memmove(tmp, ASCII_ISUPPER(fmt_spec) ? "NAN" : "nan", 4);
- str_arg_l = 3;
- zero_padding = 0;
- } else {
- // Regular float number
- format[0] = '%';
- size_t l = 1;
- if (force_sign) {
- format[l++] = space_for_positive ? ' ' : '+';
- }
- if (precision_specified) {
- size_t max_prec = TMP_LEN - 10;
+ case 'f':
+ case 'F':
+ case 'e':
+ case 'E':
+ case 'g':
+ case 'G': {
+ // floating point
+ char format[40];
+ int remove_trailing_zeroes = false;
+
+ double f = tvs ? tv_float(tvs, &arg_idx) : va_arg(ap, double);
+ double abs_f = f < 0 ? -f : f;
+
+ if (fmt_spec == 'g' || fmt_spec == 'G') {
+ // can't use %g directly, cause it prints "1.0" as "1"
+ if ((abs_f >= 0.001 && abs_f < 10000000.0) || abs_f == 0.0) {
+ fmt_spec = ASCII_ISUPPER(fmt_spec) ? 'F' : 'f';
+ } else {
+ fmt_spec = fmt_spec == 'g' ? 'e' : 'E';
+ }
+ remove_trailing_zeroes = true;
+ }
- // make sure we don't get more digits than we have room for
- if ((fmt_spec == 'f' || fmt_spec == 'F') && abs_f > 1.0) {
- max_prec -= (size_t)log10(abs_f);
- }
- if (precision > max_prec) {
- precision = max_prec;
- }
- l += (size_t)snprintf(format + l, sizeof(format) - l, ".%d",
- (int)precision);
- }
+ if (xisinf(f)
+ || (strchr("fF", fmt_spec) != NULL && abs_f > 1.0e307)) {
+ xstrlcpy(tmp, infinity_str(f > 0.0, fmt_spec,
+ force_sign, space_for_positive),
+ sizeof(tmp));
+ str_arg_l = strlen(tmp);
+ zero_padding = 0;
+ } else if (xisnan(f)) {
+ // Not a number: nan or NAN
+ memmove(tmp, ASCII_ISUPPER(fmt_spec) ? "NAN" : "nan", 4);
+ str_arg_l = 3;
+ zero_padding = 0;
+ } else {
+ // Regular float number
+ format[0] = '%';
+ size_t l = 1;
+ if (force_sign) {
+ format[l++] = space_for_positive ? ' ' : '+';
+ }
+ if (precision_specified) {
+ size_t max_prec = TMP_LEN - 10;
- // Cast to char to avoid a conversion warning on Ubuntu 12.04.
- assert(l + 1 < sizeof(format));
- format[l] = (char)(fmt_spec == 'F' ? 'f' : fmt_spec);
- format[l + 1] = NUL;
+ // make sure we don't get more digits than we have room for
+ if ((fmt_spec == 'f' || fmt_spec == 'F') && abs_f > 1.0) {
+ max_prec -= (size_t)log10(abs_f);
+ }
+ if (precision > max_prec) {
+ precision = max_prec;
+ }
+ l += (size_t)snprintf(format + l, sizeof(format) - l, ".%d",
+ (int)precision);
+ }
- str_arg_l = (size_t)snprintf(tmp, sizeof(tmp), format, f);
- assert(str_arg_l < sizeof(tmp));
+ // Cast to char to avoid a conversion warning on Ubuntu 12.04.
+ assert(l + 1 < sizeof(format));
+ format[l] = (char)(fmt_spec == 'F' ? 'f' : fmt_spec);
+ format[l + 1] = NUL;
- if (remove_trailing_zeroes) {
- int i;
- char *tp;
+ str_arg_l = (size_t)snprintf(tmp, sizeof(tmp), format, f);
+ assert(str_arg_l < sizeof(tmp));
- // using %g or %G: remove superfluous zeroes
- if (fmt_spec == 'f' || fmt_spec == 'F') {
- tp = tmp + str_arg_l - 1;
- } else {
- tp = (char *)vim_strchr((char_u *)tmp,
- fmt_spec == 'e' ? 'e' : 'E');
- if (tp) {
- // remove superfluous '+' and leading zeroes from exponent
- if (tp[1] == '+') {
- // change "1.0e+07" to "1.0e07"
- STRMOVE(tp + 1, tp + 2);
- str_arg_l--;
- }
- i = (tp[1] == '-') ? 2 : 1;
- while (tp[i] == '0') {
- // change "1.0e07" to "1.0e7"
- STRMOVE(tp + i, tp + i + 1);
- str_arg_l--;
- }
- tp--;
- }
- }
+ if (remove_trailing_zeroes) {
+ int i;
+ char *tp;
- if (tp != NULL && !precision_specified) {
- // remove trailing zeroes, but keep the one just after a dot
- while (tp > tmp + 2 && *tp == '0' && tp[-1] != '.') {
- STRMOVE(tp, tp + 1);
- tp--;
- str_arg_l--;
- }
+ // using %g or %G: remove superfluous zeroes
+ if (fmt_spec == 'f' || fmt_spec == 'F') {
+ tp = tmp + str_arg_l - 1;
+ } else {
+ tp = (char *)vim_strchr((char_u *)tmp,
+ fmt_spec == 'e' ? 'e' : 'E');
+ if (tp) {
+ // remove superfluous '+' and leading zeroes from exponent
+ if (tp[1] == '+') {
+ // change "1.0e+07" to "1.0e07"
+ STRMOVE(tp + 1, tp + 2);
+ str_arg_l--;
}
- } else {
- // Be consistent: some printf("%e") use 1.0e+12 and some
- // 1.0e+012; remove one zero in the last case.
- char *tp = (char *)vim_strchr((char_u *)tmp,
- fmt_spec == 'e' ? 'e' : 'E');
- if (tp && (tp[1] == '+' || tp[1] == '-') && tp[2] == '0'
- && ascii_isdigit(tp[3]) && ascii_isdigit(tp[4])) {
- STRMOVE(tp + 2, tp + 3);
+ i = (tp[1] == '-') ? 2 : 1;
+ while (tp[i] == '0') {
+ // change "1.0e07" to "1.0e7"
+ STRMOVE(tp + i, tp + i + 1);
str_arg_l--;
}
+ tp--;
}
}
- if (zero_padding && min_field_width > str_arg_l
- && (tmp[0] == '-' || force_sign)) {
- // Padding 0's should be inserted after the sign.
- number_of_zeros_to_pad = min_field_width - str_arg_l;
- zero_padding_insertion_ind = 1;
+
+ if (tp != NULL && !precision_specified) {
+ // remove trailing zeroes, but keep the one just after a dot
+ while (tp > tmp + 2 && *tp == '0' && tp[-1] != '.') {
+ STRMOVE(tp, tp + 1);
+ tp--;
+ str_arg_l--;
+ }
+ }
+ } else {
+ // Be consistent: some printf("%e") use 1.0e+12 and some
+ // 1.0e+012; remove one zero in the last case.
+ char *tp = (char *)vim_strchr((char_u *)tmp,
+ fmt_spec == 'e' ? 'e' : 'E');
+ if (tp && (tp[1] == '+' || tp[1] == '-') && tp[2] == '0'
+ && ascii_isdigit(tp[3]) && ascii_isdigit(tp[4])) {
+ STRMOVE(tp + 2, tp + 3);
+ str_arg_l--;
}
- str_arg = tmp;
- break;
}
+ }
+ if (zero_padding && min_field_width > str_arg_l
+ && (tmp[0] == '-' || force_sign)) {
+ // Padding 0's should be inserted after the sign.
+ number_of_zeros_to_pad = min_field_width - str_arg_l;
+ zero_padding_insertion_ind = 1;
+ }
+ str_arg = tmp;
+ break;
+ }
- default:
- // unrecognized conversion specifier, keep format string as-is
- zero_padding = 0; // turn zero padding off for non-numeric conversion
- justify_left = 1;
- min_field_width = 0; // reset flags
-
- // discard the unrecognized conversion, just keep
- // the unrecognized conversion character
- str_arg = p;
- str_arg_l = 0;
- if (*p) {
- str_arg_l++; // include invalid conversion specifier
- }
- // unchanged if not at end-of-string
- break;
+ default:
+ // unrecognized conversion specifier, keep format string as-is
+ zero_padding = 0; // turn zero padding off for non-numeric conversion
+ justify_left = 1;
+ min_field_width = 0; // reset flags
+
+ // discard the unrecognized conversion, just keep
+ // the unrecognized conversion character
+ str_arg = p;
+ str_arg_l = 0;
+ if (*p) {
+ str_arg_l++; // include invalid conversion specifier
+ }
+ // unchanged if not at end-of-string
+ break;
}
if (*p) {
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index d2c94d9fe8..49f54dcfe1 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -6217,6 +6217,26 @@ static const char *highlight_init_both[] = {
"default link Delimiter Special",
"default link SpecialComment Special",
"default link Debug Special",
+ "default DiagnosticError ctermfg=1 guifg=Red",
+ "default DiagnosticWarn ctermfg=3 guifg=Orange",
+ "default DiagnosticInfo ctermfg=4 guifg=LightBlue",
+ "default DiagnosticHint ctermfg=7 guifg=LightGrey",
+ "default DiagnosticUnderlineError cterm=underline gui=underline guisp=Red",
+ "default DiagnosticUnderlineWarn cterm=underline gui=underline guisp=Orange",
+ "default DiagnosticUnderlineInfo cterm=underline gui=underline guisp=LightBlue",
+ "default DiagnosticUnderlineHint cterm=underline gui=underline guisp=LightGrey",
+ "default link DiagnosticVirtualTextError DiagnosticError",
+ "default link DiagnosticVirtualTextWarn DiagnosticWarn",
+ "default link DiagnosticVirtualTextInfo DiagnosticInfo",
+ "default link DiagnosticVirtualTextHint DiagnosticHint",
+ "default link DiagnosticFloatingError DiagnosticError",
+ "default link DiagnosticFloatingWarn DiagnosticWarn",
+ "default link DiagnosticFloatingInfo DiagnosticInfo",
+ "default link DiagnosticFloatingHint DiagnosticHint",
+ "default link DiagnosticSignError DiagnosticError",
+ "default link DiagnosticSignWarn DiagnosticWarn",
+ "default link DiagnosticSignInfo DiagnosticInfo",
+ "default link DiagnosticSignHint DiagnosticHint",
NULL
};
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index c63cdad098..768cca284b 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -10,9 +10,7 @@
#include <stdbool.h>
#include <string.h>
-#include "nvim/vim.h"
#include "nvim/ascii.h"
-#include "nvim/tag.h"
#include "nvim/buffer.h"
#include "nvim/charset.h"
#include "nvim/cursor.h"
@@ -22,18 +20,21 @@
#include "nvim/ex_cmds2.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_getln.h"
+#include "nvim/file_search.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
+#include "nvim/garray.h"
#include "nvim/if_cscope.h"
#include "nvim/mark.h"
#include "nvim/mbyte.h"
+#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/file_search.h"
-#include "nvim/garray.h"
-#include "nvim/memory.h"
#include "nvim/move.h"
#include "nvim/option.h"
+#include "nvim/os/input.h"
+#include "nvim/os/os.h"
+#include "nvim/os/time.h"
#include "nvim/os_unix.h"
#include "nvim/path.h"
#include "nvim/quickfix.h"
@@ -41,30 +42,29 @@
#include "nvim/screen.h"
#include "nvim/search.h"
#include "nvim/strings.h"
+#include "nvim/tag.h"
#include "nvim/ui.h"
+#include "nvim/vim.h"
#include "nvim/window.h"
-#include "nvim/os/os.h"
-#include "nvim/os/time.h"
-#include "nvim/os/input.h"
/*
* Structure to hold pointers to various items in a tag line.
*/
typedef struct tag_pointers {
// filled in by parse_tag_line():
- char_u *tagname; // start of tag name (skip "file:")
- char_u *tagname_end; // char after tag name
- char_u *fname; // first char of file name
- char_u *fname_end; // char after file name
- char_u *command; // first char of command
+ char_u *tagname; // start of tag name (skip "file:")
+ char_u *tagname_end; // char after tag name
+ char_u *fname; // first char of file name
+ char_u *fname_end; // char after file name
+ char_u *command; // first char of command
// filled in by parse_match():
- char_u *command_end; // first char after command
- char_u *tag_fname; // file name of the tags file. This is used
+ char_u *command_end; // first char after command
+ char_u *tag_fname; // file name of the tags file. This is used
// when 'tr' is set.
- char_u *tagkind; // "kind:" value
- char_u *tagkind_end; // end of tagkind
- char_u *user_data; // user_data string
- char_u *user_data_end; // end of user_data
+ char_u *tagkind; // "kind:" value
+ char_u *tagkind_end; // end of tagkind
+ char_u *user_data; // user_data string
+ char_u *user_data_end; // end of user_data
linenr_T tagline; // "line:" value
} tagptrs_T;
@@ -72,11 +72,11 @@ typedef struct tag_pointers {
* Structure to hold info about the tag pattern being used.
*/
typedef struct {
- char_u *pat; /* the pattern */
- int len; /* length of pat[] */
- char_u *head; /* start of pattern head */
- int headlen; /* length of head[] */
- regmatch_T regmatch; /* regexp program, may be NULL */
+ char_u *pat; // the pattern
+ int len; // length of pat[]
+ char_u *head; // start of pattern head
+ int headlen; // length of head[]
+ regmatch_T regmatch; // regexp program, may be NULL
} pat_T;
// The matching tags are first stored in one of the hash tables. In
@@ -93,11 +93,11 @@ typedef struct {
#define MT_MASK 7 // mask for printing priority
#define MT_COUNT 16
-static char *mt_names[MT_COUNT/2] =
-{"FSC", "F C", "F ", "FS ", " SC", " C", " ", " S "};
+static char *mt_names[MT_COUNT/2] =
+{ "FSC", "F C", "F ", "FS ", " SC", " C", " ", " S " };
-#define NOTAGFILE 99 /* return value for jumpto_tag */
-static char_u *nofile_fname = NULL; /* fname for NOTAGFILE error */
+#define NOTAGFILE 99 // return value for jumpto_tag
+static char_u *nofile_fname = NULL; // fname for NOTAGFILE error
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -111,7 +111,7 @@ static char_u *recurmsg
static char_u *tfu_inv_ret_msg
= (char_u *)N_("E987: invalid return value from tagfunc");
-static char_u *tagmatchname = NULL; /* name of last used tag */
+static char_u *tagmatchname = NULL; // name of last used tag
/*
* Tag for preview window is remembered separately, to avoid messing up the
@@ -124,36 +124,31 @@ static int tfu_in_use = false; // disallow recursive call of tagfunc
// Used instead of NUL to separate tag fields in the growarrays.
#define TAG_SEP 0x02
-/*
- * Jump to tag; handling of tag commands and tag stack
- *
- * *tag != NUL: ":tag {tag}", jump to new tag, add to tag stack
- *
- * type == DT_TAG: ":tag [tag]", jump to newer position or same tag again
- * type == DT_HELP: like DT_TAG, but don't use regexp.
- * type == DT_POP: ":pop" or CTRL-T, jump to old position
- * type == DT_NEXT: jump to next match of same tag
- * type == DT_PREV: jump to previous match of same tag
- * type == DT_FIRST: jump to first match of same tag
- * type == DT_LAST: jump to last match of same tag
- * type == DT_SELECT: ":tselect [tag]", select tag from a list of all matches
- * type == DT_JUMP: ":tjump [tag]", jump to tag or select tag from a list
- * type == DT_CSCOPE: use cscope to find the tag
- * type == DT_LTAG: use location list for displaying tag matches
- * type == DT_FREE: free cached matches
- *
- * for cscope, returns TRUE if we jumped to tag or aborted, FALSE otherwise
- */
-int
-do_tag(
- char_u *tag, // tag (pattern) to jump to
- int type,
- int count,
- int forceit, // :ta with !
- int verbose // print "tag not found" message
-)
+/// Jump to tag; handling of tag commands and tag stack
+///
+/// *tag != NUL: ":tag {tag}", jump to new tag, add to tag stack
+///
+/// type == DT_TAG: ":tag [tag]", jump to newer position or same tag again
+/// type == DT_HELP: like DT_TAG, but don't use regexp.
+/// type == DT_POP: ":pop" or CTRL-T, jump to old position
+/// type == DT_NEXT: jump to next match of same tag
+/// type == DT_PREV: jump to previous match of same tag
+/// type == DT_FIRST: jump to first match of same tag
+/// type == DT_LAST: jump to last match of same tag
+/// type == DT_SELECT: ":tselect [tag]", select tag from a list of all matches
+/// type == DT_JUMP: ":tjump [tag]", jump to tag or select tag from a list
+/// type == DT_CSCOPE: use cscope to find the tag
+/// type == DT_LTAG: use location list for displaying tag matches
+/// type == DT_FREE: free cached matches
+///
+/// for cscope, returns TRUE if we jumped to tag or aborted, FALSE otherwise
+///
+/// @param tag tag (pattern) to jump to
+/// @param forceit :ta with !
+/// @param verbose print "tag not found" message
+int do_tag(char_u *tag, int type, int count, int forceit, int verbose)
{
- taggy_T *tagstack = curwin->w_tagstack;
+ taggy_T *tagstack = curwin->w_tagstack;
int tagstackidx = curwin->w_tagstackidx;
int tagstacklen = curwin->w_tagstacklen;
int cur_match = 0;
@@ -170,16 +165,16 @@ do_tag(
fmark_T saved_fmark;
int jumped_to_tag = false;
int new_num_matches;
- char_u **new_matches;
+ char_u **new_matches;
int use_tagstack;
int skip_msg = false;
char_u *buf_ffname = curbuf->b_ffname; // name for priority computation
int use_tfu = 1;
- /* remember the matches for the last used tag */
+ // remember the matches for the last used tag
static int num_matches = 0;
- static int max_num_matches = 0; /* limit used for match search */
- static char_u **matches = NULL;
+ static int max_num_matches = 0; // limit used for match search
+ static char_u **matches = NULL;
static int flags;
if (tfu_in_use) {
@@ -189,7 +184,7 @@ do_tag(
#ifdef EXITFREE
if (type == DT_FREE) {
- /* remove the list of matches */
+ // remove the list of matches
FreeWild(num_matches, matches);
cs_free_tags();
num_matches = 0;
@@ -207,7 +202,7 @@ do_tag(
free_string_option(nofile_fname);
nofile_fname = NULL;
- clearpos(&saved_fmark.mark); /* shutup gcc 4.0 */
+ clearpos(&saved_fmark.mark); // shutup gcc 4.0
saved_fmark.fnum = 0;
// Don't add a tag to the tagstack if 'tagstack' has been reset.
@@ -226,7 +221,7 @@ do_tag(
use_tagstack = true;
}
- /* new pattern, add to the tag stack */
+ // new pattern, add to the tag stack
if (*tag != NUL
&& (type == DT_TAG || type == DT_SELECT || type == DT_JUMP
|| type == DT_LTAG
@@ -252,7 +247,7 @@ do_tag(
tagstack_clear_entry(&tagstack[--tagstacklen]);
}
- /* if the tagstack is full: remove oldest entry */
+ // if the tagstack is full: remove oldest entry
if (++tagstacklen > TAGSTACKSIZE) {
tagstacklen = TAGSTACKSIZE;
tagstack_clear_entry(&tagstack[0]);
@@ -293,7 +288,7 @@ do_tag(
* way to the bottom now.
*/
tagstackidx = 0;
- } else if (tagstackidx >= tagstacklen) { // count == 0?
+ } else if (tagstackidx >= tagstacklen) { // count == 0?
EMSG(_(topmsg));
goto end_do_tag;
}
@@ -321,8 +316,9 @@ do_tag(
curwin->w_cursor.col = saved_fmark.mark.col;
curwin->w_set_curswant = true;
check_cursor();
- if ((fdo_flags & FDO_TAG) && old_KeyTyped)
+ if ((fdo_flags & FDO_TAG) && old_KeyTyped) {
foldOpenCursor();
+ }
// remove the old list of matches
FreeWild(num_matches, matches);
@@ -333,8 +329,7 @@ do_tag(
}
if (type == DT_TAG
- || type == DT_LTAG
- ) {
+ || type == DT_LTAG) {
if (g_do_tagpreview != 0) {
cur_match = ptag_entry.cur_match;
cur_fnum = ptag_entry.cur_fnum;
@@ -350,7 +345,7 @@ do_tag(
tagstackidx = tagstacklen - 1;
EMSG(_(topmsg));
save_pos = false;
- } else if (tagstackidx < 0) { // must have been count == 0
+ } else if (tagstackidx < 0) { // must have been count == 0
EMSG(_(bottommsg));
tagstackidx = 0;
goto end_do_tag;
@@ -367,23 +362,28 @@ do_tag(
cur_match = ptag_entry.cur_match;
cur_fnum = ptag_entry.cur_fnum;
} else {
- if (--tagstackidx < 0)
+ if (--tagstackidx < 0) {
tagstackidx = 0;
+ }
cur_match = tagstack[tagstackidx].cur_match;
cur_fnum = tagstack[tagstackidx].cur_fnum;
}
switch (type) {
- case DT_FIRST: cur_match = count - 1; break;
+ case DT_FIRST:
+ cur_match = count - 1; break;
case DT_SELECT:
case DT_JUMP:
case DT_CSCOPE:
- case DT_LAST: cur_match = MAXCOL - 1; break;
- case DT_NEXT: cur_match += count; break;
- case DT_PREV: cur_match -= count; break;
+ case DT_LAST:
+ cur_match = MAXCOL - 1; break;
+ case DT_NEXT:
+ cur_match += count; break;
+ case DT_PREV:
+ cur_match -= count; break;
}
- if (cur_match >= MAXCOL)
+ if (cur_match >= MAXCOL) {
cur_match = MAXCOL - 1;
- else if (cur_match < 0) {
+ } else if (cur_match < 0) {
EMSG(_("E425: Cannot go before first matching tag"));
skip_msg = true;
cur_match = 0;
@@ -424,8 +424,9 @@ do_tag(
if (cur_fnum != curbuf->b_fnum) {
buf_T *buf = buflist_findnr(cur_fnum);
- if (buf != NULL)
+ if (buf != NULL) {
buf_ffname = buf->b_ffname;
+ }
}
/*
@@ -433,7 +434,7 @@ do_tag(
*/
for (;; ) {
int other_name;
- char_u *name;
+ char_u *name;
// When desired match not found yet, try to find it (and others).
if (use_tagstack) {
@@ -466,8 +467,9 @@ do_tag(
if (!no_regexp && *name == '/') {
flags = TAG_REGEXP;
++name;
- } else
+ } else {
flags = TAG_NOIC;
+ }
if (type == DT_CSCOPE) {
flags = TAG_CSCOPE;
@@ -490,9 +492,9 @@ do_tag(
* to the start. Avoids that the order changes when using
* ":tnext" and jumping to another file. */
if (!new_tag && !other_name) {
- int j, k;
- int idx = 0;
- tagptrs_T tagp, tagp2;
+ int j, k;
+ int idx = 0;
+ tagptrs_T tagp, tagp2;
// Find the position of each old match in the new list. Need
// to use parse_match() to find the tag line.
@@ -517,8 +519,9 @@ do_tag(
}
if (num_matches <= 0) {
- if (verbose)
+ if (verbose) {
EMSG2(_("E426: tag not found: %s"), name);
+ }
g_do_tagpreview = 0;
} else {
bool ask_for_selection = false;
@@ -533,7 +536,7 @@ do_tag(
} else if (type == DT_SELECT || (type == DT_JUMP && num_matches > 1)) {
print_tag_list(new_tag, use_tagstack, num_matches, matches);
ask_for_selection = true;
- } else if (type == DT_LTAG) {
+ } else if (type == DT_LTAG) {
if (add_llist_tags(tag, num_matches, matches) == FAIL) {
goto end_do_tag;
}
@@ -563,16 +566,17 @@ do_tag(
* There will be an EMSG("file doesn't exist") below then. */
if ((type == DT_NEXT || type == DT_FIRST)
&& nofile_fname == NULL) {
- if (num_matches == 1)
+ if (num_matches == 1) {
EMSG(_("E427: There is only one matching tag"));
- else
+ } else {
EMSG(_("E428: Cannot go beyond last matching tag"));
+ }
skip_msg = true;
}
cur_match = num_matches - 1;
}
if (use_tagstack) {
- tagptrs_T tagp2;
+ tagptrs_T tagp2;
tagstack[tagstackidx].cur_match = cur_match;
tagstack[tagstackidx].cur_fnum = cur_fnum;
@@ -581,12 +585,12 @@ do_tag(
if (use_tfu && parse_match(matches[cur_match], &tagp2) == OK
&& tagp2.user_data) {
XFREE_CLEAR(tagstack[tagstackidx].user_data);
- tagstack[tagstackidx].user_data = vim_strnsave(
- tagp2.user_data, tagp2.user_data_end - tagp2.user_data);
+ tagstack[tagstackidx].user_data = vim_strnsave(tagp2.user_data,
+ tagp2.user_data_end - tagp2.user_data);
}
tagstackidx++;
- } else if (g_do_tagpreview != 0) {
+ } else if (g_do_tagpreview != 0) {
ptag_entry.cur_match = cur_match;
ptag_entry.cur_fnum = cur_fnum;
}
@@ -595,8 +599,9 @@ do_tag(
* Only when going to try the next match, report that the previous
* file didn't exist. Otherwise an EMSG() is given below.
*/
- if (nofile_fname != NULL && error_cur_match != cur_match)
+ if (nofile_fname != NULL && error_cur_match != cur_match) {
smsg(_("File \"%s\" does not exist"), nofile_fname);
+ }
ic = (matches[cur_match][0] & MT_IC_OFF);
@@ -631,7 +636,7 @@ do_tag(
// Let the SwapExists event know what tag we are jumping to.
vim_snprintf((char *)IObuff, IOSIZE, ":ta %s\r", name);
- set_vim_var_string(VV_SWAPCOMMAND, (char *) IObuff, -1);
+ set_vim_var_string(VV_SWAPCOMMAND, (char *)IObuff, -1);
/*
* Jump to the desired match.
@@ -648,11 +653,12 @@ do_tag(
&& (max_num_matches != MAXCOL
|| cur_match < num_matches - 1))) {
error_cur_match = cur_match;
- if (use_tagstack)
+ if (use_tagstack) {
--tagstackidx;
- if (type == DT_PREV)
+ }
+ if (type == DT_PREV) {
--cur_match;
- else {
+ } else {
type = DT_NEXT;
++cur_match;
}
@@ -662,8 +668,9 @@ do_tag(
} else {
/* We may have jumped to another window, check that
* tagstackidx is still valid. */
- if (use_tagstack && tagstackidx > curwin->w_tagstacklen)
+ if (use_tagstack && tagstackidx > curwin->w_tagstacklen) {
tagstackidx = curwin->w_tagstackidx;
+ }
jumped_to_tag = true;
}
}
@@ -684,331 +691,322 @@ end_do_tag:
//
// List all the matching tags.
//
-static void
-print_tag_list(
- int new_tag,
- int use_tagstack,
- int num_matches,
- char_u **matches)
+static void print_tag_list(int new_tag, int use_tagstack, int num_matches, char_u **matches)
{
- taggy_T *tagstack = curwin->w_tagstack;
- int tagstackidx = curwin->w_tagstackidx;
- int i;
- char_u *p;
- char_u *command_end;
- tagptrs_T tagp;
- int taglen;
- int attr;
-
- // Assume that the first match indicates how long the tags can
- // be, and align the file names to that.
- parse_match(matches[0], &tagp);
- taglen = (int)(tagp.tagname_end - tagp.tagname + 2);
- if (taglen < 18) {
- taglen = 18;
- }
- if (taglen > Columns - 25) {
- taglen = MAXCOL;
- }
- if (msg_col == 0) {
- msg_didout = false; // overwrite previous message
- }
- msg_start();
- msg_puts_attr(_(" # pri kind tag"), HL_ATTR(HLF_T));
- msg_clr_eos();
+ taggy_T *tagstack = curwin->w_tagstack;
+ int tagstackidx = curwin->w_tagstackidx;
+ int i;
+ char_u *p;
+ char_u *command_end;
+ tagptrs_T tagp;
+ int taglen;
+ int attr;
+
+ // Assume that the first match indicates how long the tags can
+ // be, and align the file names to that.
+ parse_match(matches[0], &tagp);
+ taglen = (int)(tagp.tagname_end - tagp.tagname + 2);
+ if (taglen < 18) {
+ taglen = 18;
+ }
+ if (taglen > Columns - 25) {
+ taglen = MAXCOL;
+ }
+ if (msg_col == 0) {
+ msg_didout = false; // overwrite previous message
+ }
+ msg_start();
+ msg_puts_attr(_(" # pri kind tag"), HL_ATTR(HLF_T));
+ msg_clr_eos();
+ taglen_advance(taglen);
+ msg_puts_attr(_("file\n"), HL_ATTR(HLF_T));
+
+ for (i = 0; i < num_matches && !got_int; i++) {
+ parse_match(matches[i], &tagp);
+ if (!new_tag && (
+ (g_do_tagpreview != 0
+ && i == ptag_entry.cur_match)
+ || (use_tagstack
+ && i == tagstack[tagstackidx].cur_match))) {
+ *IObuff = '>';
+ } else {
+ *IObuff = ' ';
+ }
+ vim_snprintf((char *)IObuff + 1, IOSIZE - 1,
+ "%2d %s ", i + 1,
+ mt_names[matches[i][0] & MT_MASK]);
+ msg_puts((char *)IObuff);
+ if (tagp.tagkind != NULL) {
+ msg_outtrans_len(tagp.tagkind,
+ (int)(tagp.tagkind_end - tagp.tagkind));
+ }
+ msg_advance(13);
+ msg_outtrans_len_attr(tagp.tagname,
+ (int)(tagp.tagname_end - tagp.tagname),
+ HL_ATTR(HLF_T));
+ msg_putchar(' ');
taglen_advance(taglen);
- msg_puts_attr(_("file\n"), HL_ATTR(HLF_T));
-
- for (i = 0; i < num_matches && !got_int; i++) {
- parse_match(matches[i], &tagp);
- if (!new_tag && (
- (g_do_tagpreview != 0
- && i == ptag_entry.cur_match)
- || (use_tagstack
- && i == tagstack[tagstackidx].cur_match))) {
- *IObuff = '>';
- } else {
- *IObuff = ' ';
+
+ // Find out the actual file name. If it is long, truncate
+ // it and put "..." in the middle
+ p = tag_full_fname(&tagp);
+ if (p != NULL) {
+ msg_outtrans_attr(p, HL_ATTR(HLF_D));
+ XFREE_CLEAR(p);
+ }
+ if (msg_col > 0) {
+ msg_putchar('\n');
+ }
+ if (got_int) {
+ break;
+ }
+ msg_advance(15);
+
+ // print any extra fields
+ command_end = tagp.command_end;
+ if (command_end != NULL) {
+ p = command_end + 3;
+ while (*p && *p != '\r' && *p != '\n') {
+ while (*p == TAB) {
+ p++;
}
- vim_snprintf((char *)IObuff + 1, IOSIZE - 1,
- "%2d %s ", i + 1,
- mt_names[matches[i][0] & MT_MASK]);
- msg_puts((char *)IObuff);
- if (tagp.tagkind != NULL) {
- msg_outtrans_len(tagp.tagkind,
- (int)(tagp.tagkind_end - tagp.tagkind));
+
+ // skip "file:" without a value (static tag)
+ if (STRNCMP(p, "file:", 5) == 0 && ascii_isspace(p[5])) {
+ p += 5;
+ continue;
}
- msg_advance(13);
- msg_outtrans_len_attr(tagp.tagname,
- (int)(tagp.tagname_end - tagp.tagname),
- HL_ATTR(HLF_T));
- msg_putchar(' ');
- taglen_advance(taglen);
-
- // Find out the actual file name. If it is long, truncate
- // it and put "..." in the middle
- p = tag_full_fname(&tagp);
- if (p != NULL) {
- msg_outtrans_attr(p, HL_ATTR(HLF_D));
- XFREE_CLEAR(p);
+ // skip "kind:<kind>" and "<kind>"
+ if (p == tagp.tagkind
+ || (p + 5 == tagp.tagkind
+ && STRNCMP(p, "kind:", 5) == 0)) {
+ p = tagp.tagkind_end;
+ continue;
}
- if (msg_col > 0) {
+ // print all other extra fields
+ attr = HL_ATTR(HLF_CM);
+ while (*p && *p != '\r' && *p != '\n') {
+ if (msg_col + ptr2cells(p) >= Columns) {
msg_putchar('\n');
+ if (got_int) {
+ break;
+ }
+ msg_advance(15);
+ }
+ p = msg_outtrans_one(p, attr);
+ if (*p == TAB) {
+ msg_puts_attr(" ", attr);
+ break;
+ }
+ if (*p == ':') {
+ attr = 0;
+ }
}
+ }
+ if (msg_col > 15) {
+ msg_putchar('\n');
if (got_int) {
- break;
+ break;
}
msg_advance(15);
+ }
+ } else {
+ for (p = tagp.command;
+ *p && *p != '\r' && *p != '\n';
+ p++) {
+ }
+ command_end = p;
+ }
- // print any extra fields
- command_end = tagp.command_end;
- if (command_end != NULL) {
- p = command_end + 3;
- while (*p && *p != '\r' && *p != '\n') {
- while (*p == TAB) {
- p++;
- }
-
- // skip "file:" without a value (static tag)
- if (STRNCMP(p, "file:", 5) == 0 && ascii_isspace(p[5])) {
- p += 5;
- continue;
- }
- // skip "kind:<kind>" and "<kind>"
- if (p == tagp.tagkind
- || (p + 5 == tagp.tagkind
- && STRNCMP(p, "kind:", 5) == 0)) {
- p = tagp.tagkind_end;
- continue;
- }
- // print all other extra fields
- attr = HL_ATTR(HLF_CM);
- while (*p && *p != '\r' && *p != '\n') {
- if (msg_col + ptr2cells(p) >= Columns) {
- msg_putchar('\n');
- if (got_int) {
- break;
- }
- msg_advance(15);
- }
- p = msg_outtrans_one(p, attr);
- if (*p == TAB) {
- msg_puts_attr(" ", attr);
- break;
- }
- if (*p == ':') {
- attr = 0;
- }
- }
- }
- if (msg_col > 15) {
- msg_putchar('\n');
- if (got_int) {
- break;
- }
- msg_advance(15);
- }
- } else {
- for (p = tagp.command;
- *p && *p != '\r' && *p != '\n';
- p++) {
- }
- command_end = p;
- }
-
- // Put the info (in several lines) at column 15.
- // Don't display "/^" and "?^".
- p = tagp.command;
- if (*p == '/' || *p == '?') {
- p++;
- if (*p == '^') {
- p++;
- }
- }
- // Remove leading whitespace from pattern
- while (p != command_end && ascii_isspace(*p)) {
- p++;
- }
+ // Put the info (in several lines) at column 15.
+ // Don't display "/^" and "?^".
+ p = tagp.command;
+ if (*p == '/' || *p == '?') {
+ p++;
+ if (*p == '^') {
+ p++;
+ }
+ }
+ // Remove leading whitespace from pattern
+ while (p != command_end && ascii_isspace(*p)) {
+ p++;
+ }
- while (p != command_end) {
- if (msg_col + (*p == TAB ? 1 : ptr2cells(p)) > Columns) {
- msg_putchar('\n');
- }
- if (got_int) {
- break;
- }
- msg_advance(15);
+ while (p != command_end) {
+ if (msg_col + (*p == TAB ? 1 : ptr2cells(p)) > Columns) {
+ msg_putchar('\n');
+ }
+ if (got_int) {
+ break;
+ }
+ msg_advance(15);
- // skip backslash used for escaping a command char or
- // a backslash
- if (*p == '\\' && (*(p + 1) == *tagp.command
- || *(p + 1) == '\\')) {
- p++;
- }
+ // skip backslash used for escaping a command char or
+ // a backslash
+ if (*p == '\\' && (*(p + 1) == *tagp.command
+ || *(p + 1) == '\\')) {
+ p++;
+ }
- if (*p == TAB) {
- msg_putchar(' ');
- p++;
- } else {
- p = msg_outtrans_one(p, 0);
- }
+ if (*p == TAB) {
+ msg_putchar(' ');
+ p++;
+ } else {
+ p = msg_outtrans_one(p, 0);
+ }
- // don't display the "$/;\"" and "$?;\""
- if (p == command_end - 2 && *p == '$'
- && *(p + 1) == *tagp.command) {
- break;
- }
- // don't display matching '/' or '?'
- if (p == command_end - 1 && *p == *tagp.command
- && (*p == '/' || *p == '?')) {
- break;
- }
- }
- if (msg_col) {
- msg_putchar('\n');
- }
- os_breakcheck();
+ // don't display the "$/;\"" and "$?;\""
+ if (p == command_end - 2 && *p == '$'
+ && *(p + 1) == *tagp.command) {
+ break;
+ }
+ // don't display matching '/' or '?'
+ if (p == command_end - 1 && *p == *tagp.command
+ && (*p == '/' || *p == '?')) {
+ break;
+ }
}
- if (got_int) {
- got_int = false; // only stop the listing
+ if (msg_col) {
+ msg_putchar('\n');
}
+ os_breakcheck();
+ }
+ if (got_int) {
+ got_int = false; // only stop the listing
+ }
}
//
// Add the matching tags to the location list for the current
// window.
//
-static int
-add_llist_tags(
- char_u *tag,
- int num_matches,
- char_u **matches)
+static int add_llist_tags(char_u *tag, int num_matches, char_u **matches)
{
- list_T *list;
- char_u tag_name[128 + 1];
- char_u *fname;
- char_u *cmd;
- int i;
- char_u *p;
- tagptrs_T tagp;
-
- fname = xmalloc(MAXPATHL + 1);
- cmd = xmalloc(CMDBUFFSIZE + 1);
- list = tv_list_alloc(0);
-
- for (i = 0; i < num_matches; i++) {
- int len, cmd_len;
- long lnum;
- dict_T *dict;
-
- parse_match(matches[i], &tagp);
-
- // Save the tag name
- len = (int)(tagp.tagname_end - tagp.tagname);
- if (len > 128) {
- len = 128;
- }
- xstrlcpy((char *)tag_name, (const char *)tagp.tagname, len + 1);
- tag_name[len] = NUL;
+ list_T *list;
+ char_u tag_name[128 + 1];
+ char_u *fname;
+ char_u *cmd;
+ int i;
+ char_u *p;
+ tagptrs_T tagp;
- // Save the tag file name
- p = tag_full_fname(&tagp);
- if (p == NULL) {
- continue;
- }
- xstrlcpy((char *)fname, (const char *)p, MAXPATHL);
- XFREE_CLEAR(p);
-
- // Get the line number or the search pattern used to locate
- // the tag.
- lnum = 0;
- if (isdigit(*tagp.command)) {
- // Line number is used to locate the tag
- lnum = atol((char *)tagp.command);
- } else {
- char_u *cmd_start, *cmd_end;
+ fname = xmalloc(MAXPATHL + 1);
+ cmd = xmalloc(CMDBUFFSIZE + 1);
+ list = tv_list_alloc(0);
- // Search pattern is used to locate the tag
+ for (i = 0; i < num_matches; i++) {
+ int len, cmd_len;
+ long lnum;
+ dict_T *dict;
- // Locate the end of the command
- cmd_start = tagp.command;
- cmd_end = tagp.command_end;
- if (cmd_end == NULL) {
- for (p = tagp.command;
- *p && *p != '\r' && *p != '\n'; p++) {
- }
- cmd_end = p;
- }
+ parse_match(matches[i], &tagp);
- // Now, cmd_end points to the character after the
- // command. Adjust it to point to the last
- // character of the command.
- cmd_end--;
+ // Save the tag name
+ len = (int)(tagp.tagname_end - tagp.tagname);
+ if (len > 128) {
+ len = 128;
+ }
+ xstrlcpy((char *)tag_name, (const char *)tagp.tagname, len + 1);
+ tag_name[len] = NUL;
- // Skip the '/' and '?' characters at the
- // beginning and end of the search pattern.
- if (*cmd_start == '/' || *cmd_start == '?') {
- cmd_start++;
- }
+ // Save the tag file name
+ p = tag_full_fname(&tagp);
+ if (p == NULL) {
+ continue;
+ }
+ xstrlcpy((char *)fname, (const char *)p, MAXPATHL);
+ XFREE_CLEAR(p);
+
+ // Get the line number or the search pattern used to locate
+ // the tag.
+ lnum = 0;
+ if (isdigit(*tagp.command)) {
+ // Line number is used to locate the tag
+ lnum = atol((char *)tagp.command);
+ } else {
+ char_u *cmd_start, *cmd_end;
- if (*cmd_end == '/' || *cmd_end == '?') {
- cmd_end--;
- }
+ // Search pattern is used to locate the tag
- len = 0;
- cmd[0] = NUL;
+ // Locate the end of the command
+ cmd_start = tagp.command;
+ cmd_end = tagp.command_end;
+ if (cmd_end == NULL) {
+ for (p = tagp.command;
+ *p && *p != '\r' && *p != '\n'; p++) {
+ }
+ cmd_end = p;
+ }
- // If "^" is present in the tag search pattern, then
- // copy it first.
- if (*cmd_start == '^') {
- STRCPY(cmd, "^");
- cmd_start++;
- len++;
- }
+ // Now, cmd_end points to the character after the
+ // command. Adjust it to point to the last
+ // character of the command.
+ cmd_end--;
- // Precede the tag pattern with \V to make it very
- // nomagic.
- STRCAT(cmd, "\\V");
- len += 2;
+ // Skip the '/' and '?' characters at the
+ // beginning and end of the search pattern.
+ if (*cmd_start == '/' || *cmd_start == '?') {
+ cmd_start++;
+ }
- cmd_len = (int)(cmd_end - cmd_start + 1);
- if (cmd_len > (CMDBUFFSIZE - 5)) {
- cmd_len = CMDBUFFSIZE - 5;
- }
- snprintf((char *)cmd + len, CMDBUFFSIZE + 1 - len,
- "%.*s", cmd_len, cmd_start);
- len += cmd_len;
-
- if (cmd[len - 1] == '$') {
- // Replace '$' at the end of the search pattern
- // with '\$'
- cmd[len - 1] = '\\';
- cmd[len] = '$';
- len++;
- }
+ if (*cmd_end == '/' || *cmd_end == '?') {
+ cmd_end--;
+ }
- cmd[len] = NUL;
- }
+ len = 0;
+ cmd[0] = NUL;
- dict = tv_dict_alloc();
- tv_list_append_dict(list, dict);
+ // If "^" is present in the tag search pattern, then
+ // copy it first.
+ if (*cmd_start == '^') {
+ STRCPY(cmd, "^");
+ cmd_start++;
+ len++;
+ }
- tv_dict_add_str(dict, S_LEN("text"), (const char *)tag_name);
- tv_dict_add_str(dict, S_LEN("filename"), (const char *)fname);
- tv_dict_add_nr(dict, S_LEN("lnum"), lnum);
- if (lnum == 0) {
- tv_dict_add_str(dict, S_LEN("pattern"), (const char *)cmd);
- }
+ // Precede the tag pattern with \V to make it very
+ // nomagic.
+ STRCAT(cmd, "\\V");
+ len += 2;
+
+ cmd_len = (int)(cmd_end - cmd_start + 1);
+ if (cmd_len > (CMDBUFFSIZE - 5)) {
+ cmd_len = CMDBUFFSIZE - 5;
+ }
+ snprintf((char *)cmd + len, CMDBUFFSIZE + 1 - len,
+ "%.*s", cmd_len, cmd_start);
+ len += cmd_len;
+
+ if (cmd[len - 1] == '$') {
+ // Replace '$' at the end of the search pattern
+ // with '\$'
+ cmd[len - 1] = '\\';
+ cmd[len] = '$';
+ len++;
+ }
+
+ cmd[len] = NUL;
}
- vim_snprintf((char *)IObuff, IOSIZE, "ltag %s", tag);
- set_errorlist(curwin, list, ' ', IObuff, NULL);
+ dict = tv_dict_alloc();
+ tv_list_append_dict(list, dict);
- tv_list_free(list);
- XFREE_CLEAR(fname);
- XFREE_CLEAR(cmd);
+ tv_dict_add_str(dict, S_LEN("text"), (const char *)tag_name);
+ tv_dict_add_str(dict, S_LEN("filename"), (const char *)fname);
+ tv_dict_add_nr(dict, S_LEN("lnum"), lnum);
+ if (lnum == 0) {
+ tv_dict_add_str(dict, S_LEN("pattern"), (const char *)cmd);
+ }
+ }
- return OK;
+ vim_snprintf((char *)IObuff, IOSIZE, "ltag %s", tag);
+ set_errorlist(curwin, list, ' ', IObuff, NULL);
+
+ tv_list_free(list);
+ XFREE_CLEAR(fname);
+ XFREE_CLEAR(cmd);
+
+ return OK;
}
/*
@@ -1024,8 +1022,9 @@ static void taglen_advance(int l)
if (l == MAXCOL) {
msg_putchar('\n');
msg_advance(24);
- } else
+ } else {
msg_advance(13 + l);
+ }
}
/*
@@ -1034,18 +1033,19 @@ static void taglen_advance(int l)
void do_tags(exarg_T *eap)
{
int i;
- char_u *name;
- taggy_T *tagstack = curwin->w_tagstack;
+ char_u *name;
+ taggy_T *tagstack = curwin->w_tagstack;
int tagstackidx = curwin->w_tagstackidx;
int tagstacklen = curwin->w_tagstacklen;
- /* Highlight title */
+ // Highlight title
MSG_PUTS_TITLE(_("\n # TO tag FROM line in file/text"));
for (i = 0; i < tagstacklen; ++i) {
if (tagstack[i].tagname != NULL) {
name = fm_getname(&(tagstack[i].fmark), 30);
- if (name == NULL) /* file name not available */
+ if (name == NULL) { // file name not available
continue;
+ }
msg_putchar('\n');
vim_snprintf((char *)IObuff, IOSIZE, "%c%2d %2d %-15s %5ld ",
@@ -1059,10 +1059,11 @@ void do_tags(exarg_T *eap)
? HL_ATTR(HLF_D) : 0);
xfree(name);
}
- ui_flush(); /* show one line at a time */
+ ui_flush(); // show one line at a time
}
- if (tagstackidx == tagstacklen) /* idx at top of stack */
+ if (tagstackidx == tagstacklen) { // idx at top of stack
MSG_PUTS("\n>");
+ }
}
@@ -1078,15 +1079,17 @@ static int tag_strnicmp(char_u *s1, char_u *s2, size_t len)
while (len > 0) {
i = TOUPPER_ASC(*s1) - TOUPPER_ASC(*s2);
- if (i != 0)
- return i; /* this character different */
- if (*s1 == NUL)
- break; /* strings match until NUL */
+ if (i != 0) {
+ return i; // this character different
+ }
+ if (*s1 == NUL) {
+ break; // strings match until NUL
+ }
++s1;
++s2;
--len;
}
- return 0; /* strings match */
+ return 0; // strings match
}
@@ -1100,48 +1103,54 @@ static void prepare_pats(pat_T *pats, int has_re)
if (has_re) {
/* When the pattern starts with '^' or "\\<", binary searching can be
* used (much faster). */
- if (pats->pat[0] == '^')
+ if (pats->pat[0] == '^') {
pats->head = pats->pat + 1;
- else if (pats->pat[0] == '\\' && pats->pat[1] == '<')
+ } else if (pats->pat[0] == '\\' && pats->pat[1] == '<') {
pats->head = pats->pat + 2;
- if (pats->head == pats->pat)
+ }
+ if (pats->head == pats->pat) {
pats->headlen = 0;
- else
+ } else {
for (pats->headlen = 0; pats->head[pats->headlen] != NUL;
- ++pats->headlen)
+ ++pats->headlen) {
if (vim_strchr((char_u *)(p_magic ? ".[~*\\$" : "\\$"),
- pats->head[pats->headlen]) != NULL)
+ pats->head[pats->headlen]) != NULL) {
break;
- if (p_tl != 0 && pats->headlen > p_tl) /* adjust for 'taglength' */
+ }
+ }
+ }
+ if (p_tl != 0 && pats->headlen > p_tl) { // adjust for 'taglength'
pats->headlen = p_tl;
+ }
}
- if (has_re)
+ if (has_re) {
pats->regmatch.regprog = vim_regcomp(pats->pat, p_magic ? RE_MAGIC : 0);
- else
+ } else {
pats->regmatch.regprog = NULL;
+ }
}
-//
-// Call the user-defined function to generate a list of tags used by
-// find_tags().
-//
-// Return OK if at least 1 tag has been successfully found,
-// NOTDONE if the function returns v:null, and FAIL otherwise.
-//
-static int find_tagfunc_tags(
- char_u *pat, // pattern supplied to the user-defined function
- garray_T *ga, // the tags will be placed here
- int *match_count, // here the number of tags found will be placed
- int flags, // flags from find_tags (TAG_*)
- char_u *buf_ffname) // name of buffer for priority
+/// Call the user-defined function to generate a list of tags used by
+/// find_tags().
+///
+/// Return OK if at least 1 tag has been successfully found,
+/// NOTDONE if the function returns v:null, and FAIL otherwise.
+///
+/// @param pat pattern supplied to the user-defined function
+/// @param ga the tags will be placed here
+/// @param match_count here the number of tags found will be placed
+/// @param flags flags from find_tags (TAG_*)
+/// @param buf_ffname name of buffer for priority
+static int find_tagfunc_tags(char_u *pat, garray_T *ga, int *match_count, int flags,
+ char_u *buf_ffname)
{
- pos_T save_pos;
- list_T *taglist;
- int ntags = 0;
- int result = FAIL;
- typval_T args[4];
- typval_T rettv;
+ pos_T save_pos;
+ list_T *taglist;
+ int ntags = 0;
+ int result = FAIL;
+ typval_T args[4];
+ typval_T rettv;
char_u flagString[4];
taggy_T *tag = &curwin->w_tagstack[curwin->w_tagstackidx];
@@ -1195,12 +1204,12 @@ static int find_tagfunc_tags(
taglist = rettv.vval.v_list;
TV_LIST_ITER_CONST(taglist, li, {
- char_u *res_name;
- char_u *res_fname;
- char_u *res_cmd;
- char_u *res_kind;
- int has_extra = 0;
- int name_only = flags & TAG_NAMES;
+ char_u *res_name;
+ char_u *res_fname;
+ char_u *res_cmd;
+ char_u *res_kind;
+ int has_extra = 0;
+ int name_only = flags & TAG_NAMES;
if (TV_LIST_ITEM_TV(li)->v_type != VAR_DICT) {
EMSG(_(tfu_inv_ret_msg));
@@ -1326,50 +1335,46 @@ static int find_tagfunc_tags(
return result;
}
-/*
- * find_tags() - search for tags in tags files
- *
- * Return FAIL if search completely failed (*num_matches will be 0, *matchesp
- * will be NULL), OK otherwise.
- *
- * There is a priority in which type of tag is recognized.
- *
- * 6. A static or global tag with a full matching tag for the current file.
- * 5. A global tag with a full matching tag for another file.
- * 4. A static tag with a full matching tag for another file.
- * 3. A static or global tag with an ignore-case matching tag for the
- * current file.
- * 2. A global tag with an ignore-case matching tag for another file.
- * 1. A static tag with an ignore-case matching tag for another file.
- *
- * Tags in an emacs-style tags file are always global.
- *
- * flags:
- * TAG_HELP only search for help tags
- * TAG_NAMES only return name of tag
- * TAG_REGEXP use "pat" as a regexp
- * TAG_NOIC don't always ignore case
- * TAG_KEEP_LANG keep language
- * TAG_CSCOPE use cscope results for tags
- * TAG_NO_TAGFUNC do not call the 'tagfunc' function
- */
-int
-find_tags(
- char_u *pat, // pattern to search for
- int *num_matches, // return: number of matches found
- char_u ***matchesp, // return: array of matches found
- int flags,
- int mincount, /* MAXCOL: find all matches
- other: minimal number of matches */
- char_u *buf_ffname /* name of buffer for priority */
-)
+/// find_tags() - search for tags in tags files
+///
+/// Return FAIL if search completely failed (*num_matches will be 0, *matchesp
+/// will be NULL), OK otherwise.
+///
+/// There is a priority in which type of tag is recognized.
+///
+/// 6. A static or global tag with a full matching tag for the current file.
+/// 5. A global tag with a full matching tag for another file.
+/// 4. A static tag with a full matching tag for another file.
+/// 3. A static or global tag with an ignore-case matching tag for the
+/// current file.
+/// 2. A global tag with an ignore-case matching tag for another file.
+/// 1. A static tag with an ignore-case matching tag for another file.
+///
+/// Tags in an emacs-style tags file are always global.
+///
+/// flags:
+/// TAG_HELP only search for help tags
+/// TAG_NAMES only return name of tag
+/// TAG_REGEXP use "pat" as a regexp
+/// TAG_NOIC don't always ignore case
+/// TAG_KEEP_LANG keep language
+/// TAG_CSCOPE use cscope results for tags
+/// TAG_NO_TAGFUNC do not call the 'tagfunc' function
+///
+/// @param pat pattern to search for
+/// @param num_matches return: number of matches found
+/// @param matchesp return: array of matches found
+/// @param mincount MAXCOL: find all matches other: minimal number of matches */
+/// @param buf_ffname name of buffer for priority
+int find_tags(char_u *pat, int *num_matches, char_u ***matchesp, int flags, int mincount,
+ char_u *buf_ffname)
{
- FILE *fp;
- char_u *lbuf; /* line buffer */
- int lbuf_size = LSIZE; /* length of lbuf */
- char_u *tag_fname; /* name of tag file */
- tagname_T tn; /* info for get_tagfname() */
- int first_file; /* trying first tag file */
+ FILE *fp;
+ char_u *lbuf; // line buffer
+ int lbuf_size = LSIZE; // length of lbuf
+ char_u *tag_fname; // name of tag file
+ tagname_T tn; // info for get_tagfname()
+ int first_file; // trying first tag file
tagptrs_T tagp;
bool did_open = false; // did open a tag file
bool stop_searching = false; // stop when match found or error
@@ -1377,8 +1382,8 @@ find_tags(
int is_static; // current tag line is static
int is_current; // file name matches
bool eof = false; // found end-of-file
- char_u *p;
- char_u *s;
+ char_u *p;
+ char_u *s;
int i;
int tag_file_sorted = NUL; // !_TAG_FILE_SORTED value
struct tag_search_info { // Binary search file offsets
@@ -1396,17 +1401,17 @@ find_tags(
off_T offset;
int round;
enum {
- TS_START, /* at start of file */
- TS_LINEAR /* linear searching forward, till EOF */
- , TS_BINARY, /* binary searching */
- TS_SKIP_BACK, /* skipping backwards */
- TS_STEP_FORWARD /* stepping forwards */
- } state; /* Current search state */
+ TS_START, // at start of file
+ TS_LINEAR // linear searching forward, till EOF
+ , TS_BINARY, // binary searching
+ TS_SKIP_BACK, // skipping backwards
+ TS_STEP_FORWARD // stepping forwards
+ } state; // Current search state
int cmplen;
- int match; /* matches */
- int match_no_ic = 0; /* matches with rm_ic == FALSE */
- int match_re; /* match with regexp */
+ int match; // matches
+ int match_no_ic = 0; // matches with rm_ic == FALSE
+ int match_re; // match with regexp
int matchoff = 0;
int save_emsg_off;
@@ -1416,16 +1421,16 @@ find_tags(
hashtab_T ht_match[MT_COUNT]; // stores matches by key
hash_T hash = 0;
int match_count = 0; // number of matches found
- char_u **matches;
+ char_u **matches;
int mtt;
int help_save;
int help_pri = 0;
- char_u *help_lang_find = NULL; // lang to be found
+ char_u *help_lang_find = NULL; // lang to be found
char_u help_lang[3]; // lang of current tags file
- char_u *saved_pat = NULL; // copy of pat[]
+ char_u *saved_pat = NULL; // copy of pat[]
bool is_txt = false;
- pat_T orgpat; /* holds unconverted pattern info */
+ pat_T orgpat; // holds unconverted pattern info
vimconv_T vimconv;
int findall = (mincount == MAXCOL || mincount == TAG_MANY);
@@ -1447,22 +1452,22 @@ find_tags(
// Change the value of 'ignorecase' according to 'tagcase' for the
// duration of this function.
switch (curbuf->b_tc_flags ? curbuf->b_tc_flags : tc_flags) {
- case TC_FOLLOWIC:
- break;
- case TC_IGNORE:
- p_ic = true;
- break;
- case TC_MATCH:
- p_ic = false;
- break;
- case TC_FOLLOWSCS:
- p_ic = ignorecase(pat);
- break;
- case TC_SMART:
- p_ic = ignorecase_opt(pat, true, true);
- break;
- default:
- abort();
+ case TC_FOLLOWIC:
+ break;
+ case TC_IGNORE:
+ p_ic = true;
+ break;
+ case TC_MATCH:
+ p_ic = false;
+ break;
+ case TC_FOLLOWSCS:
+ p_ic = ignorecase(pat);
+ break;
+ case TC_SMART:
+ p_ic = ignorecase_opt(pat, true, true);
+ break;
+ default:
+ abort();
}
help_save = curbuf->b_help;
@@ -1480,7 +1485,7 @@ find_tags(
hash_init(&ht_match[mtt]);
}
- STRCPY(tag_fname, "from cscope"); /* for error messages */
+ STRCPY(tag_fname, "from cscope"); // for error messages
/*
* Initialize a few variables
@@ -1506,15 +1511,17 @@ find_tags(
orgpat.len -= 3;
}
}
- if (p_tl != 0 && orgpat.len > p_tl) /* adjust for 'taglength' */
+ if (p_tl != 0 && orgpat.len > p_tl) { // adjust for 'taglength'
orgpat.len = p_tl;
+ }
save_emsg_off = emsg_off;
- emsg_off = TRUE; /* don't want error for invalid RE here */
+ emsg_off = TRUE; // don't want error for invalid RE here
prepare_pats(&orgpat, has_re);
emsg_off = save_emsg_off;
- if (has_re && orgpat.regmatch.regprog == NULL)
+ if (has_re && orgpat.regmatch.regprog == NULL) {
goto findtag_end;
+ }
// This is only to avoid a compiler warning for using search_info
// uninitialised.
@@ -1580,8 +1587,9 @@ find_tags(
/* When searching for a specific language skip tags files
* for other languages. */
if (help_lang_find != NULL
- && STRICMP(help_lang, help_lang_find) != 0)
+ && STRICMP(help_lang, help_lang_find) != 0) {
continue;
+ }
/* For CTRL-] in a help file prefer a match with the same
* language. */
@@ -1591,23 +1599,26 @@ find_tags(
&& (i = (int)STRLEN(curbuf->b_fname)) > 4
&& curbuf->b_fname[i - 1] == 'x'
&& curbuf->b_fname[i - 4] == '.'
- && STRNICMP(curbuf->b_fname + i - 3, help_lang, 2) == 0)
+ && STRNICMP(curbuf->b_fname + i - 3, help_lang, 2) == 0) {
help_pri = 0;
- else {
+ } else {
help_pri = 1;
for (s = p_hlg; *s != NUL; ++s) {
- if (STRNICMP(s, help_lang, 2) == 0)
+ if (STRNICMP(s, help_lang, 2) == 0) {
break;
+ }
++help_pri;
- if ((s = vim_strchr(s, ',')) == NULL)
+ if ((s = vim_strchr(s, ',')) == NULL) {
break;
+ }
}
if (s == NULL || *s == NUL) {
/* Language not in 'helplang': use last, prefer English,
* unless found already. */
++help_pri;
- if (STRICMP(help_lang, "en") != 0)
+ if (STRICMP(help_lang, "en") != 0) {
++help_pri;
+ }
}
}
}
@@ -1624,7 +1635,7 @@ find_tags(
}
did_open = true; // remember that we found at least one file
- state = TS_START; /* we're at the start of the file */
+ state = TS_START; // we're at the start of the file
/*
* Read and parse the lines in the file one by one
@@ -1636,8 +1647,9 @@ find_tags(
} else {
fast_breakcheck();
}
- if ((flags & TAG_INS_COMP)) /* Double brackets for gcc */
+ if ((flags & TAG_INS_COMP)) { // Double brackets for gcc
ins_compl_check_keys(30, false);
+ }
if (got_int || compl_interrupted) {
stop_searching = true;
break;
@@ -1649,18 +1661,20 @@ find_tags(
retval = OK;
break;
}
- if (get_it_again)
+ if (get_it_again) {
goto line_read_in;
+ }
/*
* For binary search: compute the next offset to use.
*/
if (state == TS_BINARY) {
offset = search_info.low_offset + ((search_info.high_offset
- search_info.low_offset) / 2);
- if (offset == search_info.curr_offset)
- break; /* End the binary search without a match. */
- else
+ if (offset == search_info.curr_offset) {
+ break; // End the binary search without a match.
+ } else {
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;
@@ -1676,7 +1690,7 @@ find_tags(
* start of the next line.
*/
if (state == TS_BINARY || state == TS_SKIP_BACK) {
- /* Adjust the search file offset to the correct position */
+ // Adjust the search file offset to the correct position
search_info.curr_offset_used = search_info.curr_offset;
vim_fseek(fp, search_info.curr_offset, SEEK_SET);
eof = vim_fgets(lbuf, lbuf_size, fp);
@@ -1691,13 +1705,13 @@ find_tags(
}
eof = vim_fgets(lbuf, lbuf_size, fp);
}
- /* skip empty and blank lines */
+ // skip empty and blank lines
while (!eof && vim_isblankline(lbuf)) {
search_info.curr_offset = vim_ftell(fp);
eof = vim_fgets(lbuf, lbuf_size, fp);
}
if (eof) {
- /* Hit end of file. Skip backwards. */
+ // Hit end of file. Skip backwards.
state = TS_SKIP_BACK;
search_info.match_offset = vim_ftell(fp);
search_info.curr_offset = search_info.curr_offset_used;
@@ -1708,7 +1722,7 @@ find_tags(
* Not jumping around in the file: Read the next line.
*/
else {
- /* skip empty and blank lines */
+ // skip empty and blank lines
do {
eof = use_cscope
? cs_fgets(lbuf, lbuf_size)
@@ -1716,13 +1730,13 @@ find_tags(
} while (!eof && vim_isblankline(lbuf));
if (eof) {
- break; /* end of file */
+ break; // end of file
}
}
line_read_in:
if (vimconv.vc_type != CONV_NONE) {
- char_u *conv_line;
+ char_u *conv_line;
int len;
/* Convert every line. Converting the pattern from 'enc' to
@@ -1730,7 +1744,7 @@ line_read_in:
* not recognized. */
conv_line = string_convert(&vimconv, lbuf, NULL);
if (conv_line != NULL) {
- /* Copy or swap lbuf and conv_line. */
+ // Copy or swap lbuf and conv_line.
len = (int)STRLEN(conv_line) + 1;
if (len > lbuf_size) {
xfree(lbuf);
@@ -1754,30 +1768,33 @@ line_read_in:
* case is folded lower case letters sort before "_". */
if (STRNCMP(lbuf, "!_TAG_", 6) <= 0
|| (lbuf[0] == '!' && ASCII_ISLOWER(lbuf[1]))) {
- if (STRNCMP(lbuf, "!_TAG_", 6) != 0)
+ if (STRNCMP(lbuf, "!_TAG_", 6) != 0) {
/* Non-header item before the header, e.g. "!" itself.
*/
goto parse_line;
+ }
/*
* Read header line.
*/
- if (STRNCMP(lbuf, "!_TAG_FILE_SORTED\t", 18) == 0)
+ if (STRNCMP(lbuf, "!_TAG_FILE_SORTED\t", 18) == 0) {
tag_file_sorted = lbuf[18];
+ }
if (STRNCMP(lbuf, "!_TAG_FILE_ENCODING\t", 20) == 0) {
/* Prepare to convert every line from the specified
* encoding to 'encoding'. */
- for (p = lbuf + 20; *p > ' ' && *p < 127; ++p)
+ for (p = lbuf + 20; *p > ' ' && *p < 127; ++p) {
;
+ }
*p = NUL;
convert_setup(&vimconv, lbuf + 20, p_enc);
}
- /* Read the next line. Unrecognized flags are ignored. */
+ // Read the next line. Unrecognized flags are ignored.
continue;
}
- /* Headers ends. */
+ // Headers ends.
/*
* When there is no tag head, or ignoring case, need to do a
@@ -1788,18 +1805,19 @@ line_read_in:
* flag set.
* For cscope, it's always linear.
*/
- if (linear || use_cscope)
+ if (linear || use_cscope) {
state = TS_LINEAR;
- else if (tag_file_sorted == NUL)
+ } else if (tag_file_sorted == NUL) {
state = TS_BINARY;
- else if (tag_file_sorted == '1')
+ } else if (tag_file_sorted == '1') {
state = TS_BINARY;
- else if (tag_file_sorted == '2') {
+ } else if (tag_file_sorted == '2') {
state = TS_BINARY;
sortic = true;
orgpat.regmatch.rm_ic = (p_ic || !noic);
- } else
+ } else {
state = TS_LINEAR;
+ }
if (state == TS_BINARY && orgpat.regmatch.rm_ic && !sortic) {
/* Binary search won't work for ignoring case, use linear
@@ -1865,20 +1883,23 @@ parse_line:
* there is no regexp, or the tag is too short.
*/
cmplen = (int)(tagp.tagname_end - tagp.tagname);
- if (p_tl != 0 && cmplen > p_tl) /* adjust for 'taglength' */
+ if (p_tl != 0 && cmplen > p_tl) { // adjust for 'taglength'
cmplen = p_tl;
- if (has_re && orgpat.headlen < cmplen)
+ }
+ if (has_re && orgpat.headlen < cmplen) {
cmplen = orgpat.headlen;
- else if (state == TS_LINEAR && orgpat.headlen != cmplen)
+ } else if (state == TS_LINEAR && orgpat.headlen != cmplen) {
continue;
+ }
if (state == TS_BINARY) {
/*
* Simplistic check for unsorted tags file.
*/
i = (int)tagp.tagname[0];
- if (sortic)
+ if (sortic) {
i = TOUPPER_ASC(tagp.tagname[0]);
+ }
if (i < search_info.low_char || i > search_info.high_char) {
sort_error = true;
}
@@ -1886,21 +1907,23 @@ parse_line:
/*
* Compare the current tag with the searched tag.
*/
- if (sortic)
+ if (sortic) {
tagcmp = tag_strnicmp(tagp.tagname, orgpat.head,
- (size_t)cmplen);
- else
+ (size_t)cmplen);
+ } else {
tagcmp = STRNCMP(tagp.tagname, orgpat.head, cmplen);
+ }
/*
* A match with a shorter tag means to search forward.
* A match with a longer tag means to search backward.
*/
if (tagcmp == 0) {
- if (cmplen < orgpat.headlen)
+ if (cmplen < orgpat.headlen) {
tagcmp = -1;
- else if (cmplen > orgpat.headlen)
+ } else if (cmplen > orgpat.headlen) {
tagcmp = 1;
+ }
}
if (tagcmp == 0) {
@@ -1915,37 +1938,40 @@ parse_line:
search_info.curr_offset = vim_ftell(fp);
if (search_info.curr_offset < search_info.high_offset) {
search_info.low_offset = search_info.curr_offset;
- if (sortic)
+ if (sortic) {
search_info.low_char =
TOUPPER_ASC(tagp.tagname[0]);
- else
+ } else {
search_info.low_char = tagp.tagname[0];
+ }
continue;
}
}
if (tagcmp > 0
&& search_info.curr_offset != search_info.high_offset) {
search_info.high_offset = search_info.curr_offset;
- if (sortic)
+ if (sortic) {
search_info.high_char =
TOUPPER_ASC(tagp.tagname[0]);
- else
+ } else {
search_info.high_char = tagp.tagname[0];
+ }
continue;
}
- /* No match yet and are at the end of the binary search. */
+ // No match yet and are at the end of the binary search.
break;
- } else if (state == TS_SKIP_BACK) {
+ } else if (state == TS_SKIP_BACK) {
assert(cmplen >= 0);
- if (mb_strnicmp(tagp.tagname, orgpat.head, (size_t)cmplen) != 0)
+ if (mb_strnicmp(tagp.tagname, orgpat.head, (size_t)cmplen) != 0) {
state = TS_STEP_FORWARD;
- else
+ } else {
/* Have to skip back more. Restore the curr_offset
* used, otherwise we get stuck at a long line. */
search_info.curr_offset = search_info.curr_offset_used;
+ }
continue;
- } else if (state == TS_STEP_FORWARD) {
+ } else if (state == TS_STEP_FORWARD) {
assert(cmplen >= 0);
if (mb_strnicmp(tagp.tagname, orgpat.head, (size_t)cmplen) != 0) {
if ((off_T)vim_ftell(fp) > search_info.match_offset) {
@@ -1954,23 +1980,27 @@ parse_line:
continue; // before first match
}
}
- } else
- /* skip this match if it can't match */
- assert(cmplen >= 0);
- if (mb_strnicmp(tagp.tagname, orgpat.head, (size_t)cmplen) != 0)
+ } else {
+ // skip this match if it can't match
+ assert(cmplen >= 0);
+ }
+ if (mb_strnicmp(tagp.tagname, orgpat.head, (size_t)cmplen) != 0) {
continue;
+ }
// Can be a matching tag, isolate the file name and command.
tagp.fname = tagp.tagname_end + 1;
tagp.fname_end = vim_strchr(tagp.fname, TAB);
tagp.command = tagp.fname_end + 1;
- if (tagp.fname_end == NULL)
+ if (tagp.fname_end == NULL) {
i = FAIL;
- else
+ } else {
i = OK;
- } else
+ }
+ } else {
i = parse_tag_line(lbuf,
- &tagp);
+ &tagp);
+ }
if (i == FAIL) {
line_error = true;
break;
@@ -1981,20 +2011,23 @@ parse_line:
* a regexp).
*/
cmplen = (int)(tagp.tagname_end - tagp.tagname);
- if (p_tl != 0 && cmplen > p_tl) /* adjust for 'taglength' */
+ if (p_tl != 0 && cmplen > p_tl) { // adjust for 'taglength'
cmplen = p_tl;
- /* if tag length does not match, don't try comparing */
- if (orgpat.len != cmplen)
+ }
+ // if tag length does not match, don't try comparing
+ if (orgpat.len != cmplen) {
match = FALSE;
- else {
+ } else {
if (orgpat.regmatch.rm_ic) {
assert(cmplen >= 0);
match = mb_strnicmp(tagp.tagname, orgpat.pat, (size_t)cmplen) == 0;
- if (match)
+ if (match) {
match_no_ic = (STRNCMP(tagp.tagname, orgpat.pat,
- cmplen) == 0);
- } else
+ cmplen) == 0);
+ }
+ } else {
match = (STRNCMP(tagp.tagname, orgpat.pat, cmplen) == 0);
+ }
}
/*
@@ -2012,7 +2045,7 @@ parse_line:
if (orgpat.regmatch.rm_ic) {
orgpat.regmatch.rm_ic = FALSE;
match_no_ic = vim_regexec(&orgpat.regmatch, tagp.tagname,
- (colnr_T)0);
+ (colnr_T)0);
orgpat.regmatch.rm_ic = TRUE;
}
}
@@ -2025,7 +2058,7 @@ parse_line:
int len = 0;
if (use_cscope) {
- /* Don't change the ordering, always use the same table. */
+ // Don't change the ordering, always use the same table.
mtt = MT_GL_OTH;
} else {
// Decide in which array to store this match.
@@ -2035,27 +2068,31 @@ parse_line:
// Decide in which of the sixteen tables to store this match.
if (is_static) {
- if (is_current)
+ if (is_current) {
mtt = MT_ST_CUR;
- else
+ } else {
mtt = MT_ST_OTH;
+ }
} else {
- if (is_current)
+ if (is_current) {
mtt = MT_GL_CUR;
- else
+ } else {
mtt = MT_GL_OTH;
+ }
}
- if (orgpat.regmatch.rm_ic && !match_no_ic)
+ if (orgpat.regmatch.rm_ic && !match_no_ic) {
mtt += MT_IC_OFF;
- if (match_re)
+ }
+ if (match_re) {
mtt += MT_RE_OFF;
+ }
}
// Add the found match in ht_match[mtt] and ga_match[mtt].
// Store the info we need later, which depends on the kind of
// tags we are dealing with.
if (help_only) {
-# define ML_EXTRA 3
+#define ML_EXTRA 3
// Append the help-heuristic number after the tagname, for
// sorting it later. The heuristic is ignored for
// detecting duplicates.
@@ -2074,7 +2111,7 @@ parse_line:
+ help_pri);
*tagp.tagname_end = TAB;
- } else if (name_only) {
+ } else if (name_only) {
if (get_it_again) {
char_u *temp_end = tagp.command;
@@ -2148,7 +2185,7 @@ parse_line:
hash_add_item(&ht_match[mtt], hi, mfp, hash);
ga_grow(&ga_match[mtt], 1);
((char_u **)(ga_match[mtt].ga_data))
- [ga_match[mtt].ga_len++] = mfp;
+ [ga_match[mtt].ga_len++] = mfp;
match_count++;
} else {
// duplicate tag, drop it
@@ -2156,9 +2193,10 @@ parse_line:
}
}
}
- if (use_cscope && eof)
+ if (use_cscope && eof) {
break;
- } /* forever */
+ }
+ } // forever
if (line_error) {
EMSG2(_("E431: Format error in tags file \"%s\""), tag_fname);
@@ -2169,10 +2207,12 @@ parse_line:
line_error = false;
}
- if (!use_cscope)
+ if (!use_cscope) {
fclose(fp);
- if (vimconv.vc_type != CONV_NONE)
+ }
+ if (vimconv.vc_type != CONV_NONE) {
convert_setup(&vimconv, NULL, NULL);
+ }
tag_file_sorted = NUL;
if (sort_error) {
@@ -2188,27 +2228,31 @@ parse_line:
stop_searching = true;
}
- if (stop_searching || use_cscope)
+ if (stop_searching || use_cscope) {
break;
+ }
+ } // end of for-each-file loop
- } /* end of for-each-file loop */
-
- if (!use_cscope)
+ if (!use_cscope) {
tagname_free(&tn);
+ }
/* stop searching when already did a linear search, or when TAG_NOIC
* used, and 'ignorecase' not set or already did case-ignore search */
- if (stop_searching || linear || (!p_ic && noic) || orgpat.regmatch.rm_ic)
+ if (stop_searching || linear || (!p_ic && noic) || orgpat.regmatch.rm_ic) {
break;
- if (use_cscope)
+ }
+ if (use_cscope) {
break;
- orgpat.regmatch.rm_ic = TRUE; /* try another time while ignoring case */
+ }
+ orgpat.regmatch.rm_ic = TRUE; // try another time while ignoring case
}
if (!stop_searching) {
- if (!did_open && verbose) /* never opened any tags file */
+ if (!did_open && verbose) { // never opened any tags file
EMSG(_("E433: No tags file"));
- retval = OK; /* It's OK even when no tag found */
+ }
+ retval = OK; // It's OK even when no tag found
}
findtag_end:
@@ -2220,13 +2264,15 @@ findtag_end:
* Move the matches from the ga_match[] arrays into one list of
* matches. When retval == FAIL, free the matches.
*/
- if (retval == FAIL)
+ if (retval == FAIL) {
match_count = 0;
+ }
- if (match_count > 0)
+ if (match_count > 0) {
matches = xmalloc(match_count * sizeof(char_u *));
- else
+ } else {
matches = NULL;
+ }
match_count = 0;
for (mtt = 0; mtt < MT_COUNT; mtt++) {
for (i = 0; i < ga_match[mtt].ga_len; i++) {
@@ -2245,7 +2291,7 @@ findtag_end:
}
}
}
- matches[match_count++] = (char_u *)mfp;
+ matches[match_count++] = mfp;
}
}
@@ -2275,7 +2321,7 @@ static void found_tagfile_cb(char_u *fname, void *cookie)
char_u *const tag_fname = vim_strsave(fname);
#ifdef BACKSLASH_IN_FILENAME
- slash_adjust(tag_fname);
+ slash_adjust(tag_fname);
#endif
simplify_filename(tag_fname);
GA_APPEND(char_u *, &tag_fnames, tag_fname);
@@ -2293,24 +2339,22 @@ void free_tag_stuff(void)
#endif
-/*
- * Get the next name of a tag file from the tag file list.
- * For help files, use "tags" file only.
- *
- * Return FAIL if no more tag file names, OK otherwise.
- */
-int
-get_tagfname(
- tagname_T *tnp, // holds status info
- int first, // TRUE when first file name is wanted
- char_u *buf // pointer to buffer of MAXPATHL chars
-)
+/// Get the next name of a tag file from the tag file list.
+/// For help files, use "tags" file only.
+///
+/// @param tnp holds status info
+/// @param first TRUE when first file name is wanted
+/// @param buf pointer to buffer of MAXPATHL chars
+///
+/// @return FAIL if no more tag file names, OK otherwise.
+int get_tagfname(tagname_T *tnp, int first, char_u *buf)
{
- char_u *fname = NULL;
- char_u *r_ptr;
+ char_u *fname = NULL;
+ char_u *r_ptr;
- if (first)
+ if (first) {
memset(tnp, 0, sizeof(tagname_T));
+ }
if (curbuf->b_help) {
/*
@@ -2328,8 +2372,9 @@ get_tagfname(
if (tnp->tn_hf_idx >= tag_fnames.ga_len) {
/* Not found in 'runtimepath', use 'helpfile', if it exists and
* wasn't used yet, replacing "help.txt" with "tags". */
- if (tnp->tn_hf_idx > tag_fnames.ga_len || *p_hf == NUL)
+ if (tnp->tn_hf_idx > tag_fnames.ga_len || *p_hf == NUL) {
return FAIL;
+ }
++tnp->tn_hf_idx;
STRCPY(buf, p_hf);
STRCPY(path_tail(buf), "tags");
@@ -2367,14 +2412,15 @@ get_tagfname(
for (;; ) {
if (tnp->tn_did_filefind_init) {
fname = vim_findfile(tnp->tn_search_ctx);
- if (fname != NULL)
+ if (fname != NULL) {
break;
+ }
tnp->tn_did_filefind_init = FALSE;
} else {
- char_u *filename = NULL;
+ char_u *filename = NULL;
- /* Stop when used all parts of 'tags'. */
+ // Stop when used all parts of 'tags'.
if (*tnp->tn_np == NUL) {
vim_findfile_cleanup(tnp->tn_search_ctx);
tnp->tn_search_ctx = NULL;
@@ -2395,12 +2441,13 @@ get_tagfname(
*filename++ = NUL;
tnp->tn_search_ctx = vim_findfile_init(buf, filename,
- r_ptr, 100,
- FALSE, /* don't free visited list */
- FINDFILE_FILE, /* we search for a file */
- tnp->tn_search_ctx, TRUE, curbuf->b_ffname);
- if (tnp->tn_search_ctx != NULL)
+ r_ptr, 100,
+ FALSE, // don't free visited list
+ FINDFILE_FILE, // we search for a file
+ tnp->tn_search_ctx, TRUE, curbuf->b_ffname);
+ if (tnp->tn_search_ctx != NULL) {
tnp->tn_did_filefind_init = TRUE;
+ }
}
}
@@ -2420,43 +2467,44 @@ void tagname_free(tagname_T *tnp)
ga_clear_strings(&tag_fnames);
}
-/*
- * Parse one line from the tags file. Find start/end of tag name, start/end of
- * file name and start of search pattern.
- *
- * If is_etag is TRUE, tagp->fname and tagp->fname_end are not set.
- *
- * Return FAIL if there is a format error in this line, OK otherwise.
- */
-static int
-parse_tag_line(
- char_u *lbuf, // line to be parsed
- tagptrs_T *tagp
-)
+/// Parse one line from the tags file. Find start/end of tag name, start/end of
+/// file name and start of search pattern.
+///
+/// If is_etag is TRUE, tagp->fname and tagp->fname_end are not set.
+///
+/// @param lbuf line to be parsed
+///
+/// @return FAIL if there is a format error in this line, OK otherwise.
+static int parse_tag_line(char_u *lbuf, tagptrs_T *tagp)
{
- char_u *p;
+ char_u *p;
- /* Isolate the tagname, from lbuf up to the first white */
+ // Isolate the tagname, from lbuf up to the first white
tagp->tagname = lbuf;
p = vim_strchr(lbuf, TAB);
- if (p == NULL)
+ if (p == NULL) {
return FAIL;
+ }
tagp->tagname_end = p;
- /* Isolate file name, from first to second white space */
- if (*p != NUL)
+ // Isolate file name, from first to second white space
+ if (*p != NUL) {
++p;
+ }
tagp->fname = p;
p = vim_strchr(p, TAB);
- if (p == NULL)
+ if (p == NULL) {
return FAIL;
+ }
tagp->fname_end = p;
- /* find start of search command, after second white space */
- if (*p != NUL)
+ // find start of search command, after second white space
+ if (*p != NUL) {
++p;
- if (*p == NUL)
+ }
+ if (*p == NUL) {
return FAIL;
+ }
tagp->command = p;
return OK;
@@ -2466,12 +2514,12 @@ parse_tag_line(
* Check if tagname is a static tag
*
* Static tags produced by the older ctags program have the format:
- * 'file:tag file /pattern'.
+ * 'file:tag file /pattern'.
* This is only recognized when both occurrence of 'file' are the same, to
* avoid recognizing "string::string" or ":exit".
*
* Static tags produced by the new ctags program have the format:
- * 'tag file /pattern/;"<Tab>file:' "
+ * 'tag file /pattern/;"<Tab>file:' "
*
* Return TRUE if it is a static tag and adjust *tagname to the real tag.
* Return FALSE if it is not a static tag.
@@ -2484,8 +2532,9 @@ static bool test_for_static(tagptrs_T *tagp)
p = tagp->command;
while ((p = vim_strchr(p, '\t')) != NULL) {
++p;
- if (STRNCMP(p, "file:", 5) == 0)
+ if (STRNCMP(p, "file:", 5) == 0) {
return TRUE;
+ }
}
return FALSE;
@@ -2501,32 +2550,29 @@ static size_t matching_line_len(const char_u *const lbuf)
return (p - lbuf) + STRLEN(p);
}
-/*
- * Parse a line from a matching tag. Does not change the line itself.
- *
- * The line that we get looks like this:
- * Emacs tag: <mtt><tag_fname><NUL><ebuf><NUL><lbuf>
- * other tag: <mtt><tag_fname><NUL><NUL><lbuf>
- * without Emacs tags: <mtt><tag_fname><NUL><lbuf>
- *
- * Return OK or FAIL.
- */
-static int
-parse_match(
- char_u *lbuf, // input: matching line
- tagptrs_T *tagp // output: pointers into the line
-)
+/// Parse a line from a matching tag. Does not change the line itself.
+///
+/// The line that we get looks like this:
+/// Emacs tag: <mtt><tag_fname><NUL><ebuf><NUL><lbuf>
+/// other tag: <mtt><tag_fname><NUL><NUL><lbuf>
+/// without Emacs tags: <mtt><tag_fname><NUL><lbuf>
+///
+/// @param lbuf input: matching line
+/// @param tagp output: pointers into the line
+///
+/// @return OK or FAIL.
+static int parse_match(char_u *lbuf, tagptrs_T *tagp)
{
int retval;
- char_u *p;
- char_u *pc, *pt;
+ char_u *p;
+ char_u *pc, *pt;
tagp->tag_fname = lbuf + 1;
lbuf += STRLEN(tagp->tag_fname) + 2;
- /* Find search pattern and the file name for non-etags. */
+ // Find search pattern and the file name for non-etags.
retval = parse_tag_line(lbuf,
- tagp);
+ tagp);
tagp->tagkind = NULL;
tagp->user_data = NULL;
@@ -2534,7 +2580,7 @@ parse_match(
tagp->command_end = NULL;
if (retval == OK) {
- /* Try to find a kind field: "kind:<kind>" or just "<kind>"*/
+ // Try to find a kind field: "kind:<kind>" or just "<kind>"
p = tagp->command;
if (find_extra(&p) == OK) {
tagp->command_end = p;
@@ -2562,8 +2608,9 @@ parse_match(
if (pc == NULL || (pt != NULL && pc > pt)) {
tagp->tagkind = p;
}
- if (pt == NULL)
+ if (pt == NULL) {
break;
+ }
p = pt;
MB_PTR_ADV(p);
}
@@ -2602,32 +2649,30 @@ static char_u *tag_full_fname(tagptrs_T *tagp)
return fullname;
}
-/*
- * Jump to a tag that has been found in one of the tag files
- *
- * returns OK for success, NOTAGFILE when file not found, FAIL otherwise.
- */
-static int jumpto_tag(
- const char_u *lbuf_arg, // line from the tags file for this tag
- int forceit, // :ta with !
- int keep_help // keep help flag (FALSE for cscope)
-)
+/// Jump to a tag that has been found in one of the tag files
+///
+/// @param lbuf_arg line from the tags file for this tag
+/// @param forceit :ta with !
+/// @param keep_help keep help flag (FALSE for cscope)
+///
+/// @return OK for success, NOTAGFILE when file not found, FAIL otherwise.
+static int jumpto_tag(const char_u *lbuf_arg, int forceit, int keep_help)
{
int save_magic;
bool save_p_ws;
int save_p_scs, save_p_ic;
linenr_T save_lnum;
- char_u *str;
- char_u *pbuf; /* search pattern buffer */
- char_u *pbuf_end;
- char_u *tofree_fname = NULL;
- char_u *fname;
+ char_u *str;
+ char_u *pbuf; // search pattern buffer
+ char_u *pbuf_end;
+ char_u *tofree_fname = NULL;
+ char_u *fname;
tagptrs_T tagp;
int retval = FAIL;
int getfile_result = GETFILE_UNUSED;
int search_options;
- win_T *curwin_save = NULL;
- char_u *full_fname = NULL;
+ win_T *curwin_save = NULL;
+ char_u *full_fname = NULL;
const bool old_KeyTyped = KeyTyped; // getting the file may reset it
const int l_g_do_tagpreview = g_do_tagpreview;
const size_t len = matching_line_len(lbuf_arg) + 1;
@@ -2636,7 +2681,7 @@ static int jumpto_tag(
pbuf = xmalloc(LSIZE);
- /* parse the match line into the tagp structure */
+ // parse the match line into the tagp structure
if (parse_match(lbuf, &tagp) == FAIL) {
tagp.fname_end = NULL;
goto erret;
@@ -2646,7 +2691,7 @@ static int jumpto_tag(
*tagp.fname_end = NUL;
fname = tagp.fname;
- /* copy the command to pbuf[], remove trailing CR/NL */
+ // copy the command to pbuf[], remove trailing CR/NL
str = tagp.command;
for (pbuf_end = pbuf; *str && *str != '\n' && *str != '\r'; ) {
*pbuf_end++ = *str++;
@@ -2680,8 +2725,8 @@ static int jumpto_tag(
* autocommand event (e.g., http://sys/file).
*/
if (!os_path_exists(fname)
- && !has_autocmd(EVENT_BUFREADCMD, fname, NULL)
- ) {
+ && !has_autocmd(EVENT_BUFREADCMD, fname,
+ NULL)) {
retval = NOTAGFILE;
xfree(nofile_fname);
nofile_fname = vim_strsave(fname);
@@ -2692,8 +2737,8 @@ static int jumpto_tag(
if (l_g_do_tagpreview != 0) {
- postponed_split = 0; /* don't split again below */
- curwin_save = curwin; /* Save current window */
+ postponed_split = 0; // don't split again below
+ curwin_save = curwin; // Save current window
/*
* If we are reusing a window, we may change dir when
@@ -2750,10 +2795,11 @@ static int jumpto_tag(
if (keep_help) {
/* A :ta from a help file will keep the b_help flag set. For ":ptag"
* we need to use the flag from the window where we came from. */
- if (l_g_do_tagpreview != 0)
+ if (l_g_do_tagpreview != 0) {
keep_help_flag = curwin_save->w_buffer->b_help;
- else
+ } else {
keep_help_flag = curbuf->b_help;
+ }
}
if (getfile_result == GETFILE_UNUSED) {
@@ -2777,10 +2823,11 @@ static int jumpto_tag(
* command. If 'cpoptions' does not contain 't', the search pattern
* is not stored.
*/
- if (vim_strchr(p_cpo, CPO_TAGPAT) != NULL)
+ if (vim_strchr(p_cpo, CPO_TAGPAT) != NULL) {
search_options = 0;
- else
+ } else {
search_options = SEARCH_KEEP;
+ }
/*
* If the command is a search, try here.
@@ -2791,14 +2838,15 @@ static int jumpto_tag(
* anything following.
*/
str = pbuf;
- if (pbuf[0] == '/' || pbuf[0] == '?')
+ if (pbuf[0] == '/' || pbuf[0] == '?') {
str = skip_regexp(pbuf + 1, pbuf[0], FALSE, NULL) + 1;
- if (str > pbuf_end - 1) { /* search command with nothing following */
+ }
+ if (str > pbuf_end - 1) { // search command with nothing following
save_p_ws = p_ws;
save_p_ic = p_ic;
save_p_scs = p_scs;
- p_ws = true; /* need 'wrapscan' for backward searches */
- p_ic = FALSE; /* don't ignore case now */
+ p_ws = true; // need 'wrapscan' for backward searches
+ p_ic = FALSE; // don't ignore case now
p_scs = FALSE;
save_lnum = curwin->w_cursor.lnum;
if (tagp.tagline > 0) {
@@ -2898,15 +2946,17 @@ static int jumpto_tag(
* For a help buffer: Put the cursor line at the top of the window,
* the help subject will be below it.
*/
- if (curbuf->b_help)
+ if (curbuf->b_help) {
set_topline(curwin, curwin->w_cursor.lnum);
- if ((fdo_flags & FDO_TAG) && old_KeyTyped)
+ }
+ if ((fdo_flags & FDO_TAG) && old_KeyTyped) {
foldOpenCursor();
+ }
}
if (l_g_do_tagpreview != 0
&& curwin != curwin_save && win_valid(curwin_save)) {
- /* Return cursor to where we were */
+ // Return cursor to where we were
validate_cursor();
redraw_later(curwin, VALID);
win_enter(curwin_save, true);
@@ -2935,11 +2985,10 @@ erret:
// If 'tagrelative' option set, change fname (name of file containing tag)
// according to tag_fname (name of tag file containing fname).
// Returns a pointer to allocated memory.
-static char_u *expand_tag_fname(char_u *fname, char_u *const tag_fname,
- const bool expand)
+static char_u *expand_tag_fname(char_u *fname, char_u *const tag_fname, const bool expand)
{
- char_u *p;
- char_u *expanded_fname = NULL;
+ char_u *p;
+ char_u *expanded_fname = NULL;
expand_T xpc;
/*
@@ -2949,9 +2998,10 @@ static char_u *expand_tag_fname(char_u *fname, char_u *const tag_fname,
ExpandInit(&xpc);
xpc.xp_context = EXPAND_FILES;
expanded_fname = ExpandOne(&xpc, fname, NULL,
- WILD_LIST_NOTFOUND|WILD_SILENT, WILD_EXPAND_FREE);
- if (expanded_fname != NULL)
+ WILD_LIST_NOTFOUND|WILD_SILENT, WILD_EXPAND_FREE);
+ if (expanded_fname != NULL) {
fname = expanded_fname;
+ }
}
char_u *retval;
@@ -2961,13 +3011,14 @@ static char_u *expand_tag_fname(char_u *fname, char_u *const tag_fname,
retval = xmalloc(MAXPATHL);
STRCPY(retval, tag_fname);
STRLCPY(retval + (p - tag_fname), fname,
- MAXPATHL - (p - tag_fname));
+ MAXPATHL - (p - tag_fname));
/*
* Translate names like "src/a/../b/file.c" into "src/b/file.c".
*/
simplify_filename(retval);
- } else
+ } else {
retval = vim_strsave(fname);
+ }
xfree(expanded_fname);
@@ -2984,9 +3035,9 @@ static int test_for_current(char_u *fname, char_u *fname_end, char_u *tag_fname,
{
int c;
int retval = FALSE;
- char_u *fullname;
+ char_u *fullname;
- if (buf_ffname != NULL) { /* if the buffer has a name */
+ if (buf_ffname != NULL) { // if the buffer has a name
{
c = *fname_end;
*fname_end = NUL;
@@ -3053,13 +3104,8 @@ static void tagstack_clear_entry(taggy_T *item)
XFREE_CLEAR(item->user_data);
}
-int
-expand_tags (
- int tagnames, /* expand tag names */
- char_u *pat,
- int *num_file,
- char_u ***file
-)
+/// @param tagnames expand tag names
+int expand_tags(int tagnames, char_u *pat, int *num_file, char_u ***file)
{
int i;
int extra_flag;
@@ -3116,17 +3162,13 @@ expand_tags (
}
-/*
- * Add a tag field to the dictionary "dict".
- * Return OK or FAIL.
- */
-static int
-add_tag_field(
- dict_T *dict,
- const char *field_name,
- const char_u *start, // start of the value
- const char_u *end // after the value; can be NULL
-)
+/// Add a tag field to the dictionary "dict".
+/// Return OK or FAIL.
+///
+/// @param start start of the value
+/// @param end after the value; can be NULL
+static int add_tag_field(dict_T *dict, const char *field_name, const char_u *start,
+ const char_u *end)
FUNC_ATTR_NONNULL_ARG(1, 2)
{
int len = 0;
@@ -3145,12 +3187,14 @@ add_tag_field(
if (start != NULL) {
if (end == NULL) {
end = start + STRLEN(start);
- while (end > start && (end[-1] == '\r' || end[-1] == '\n'))
+ while (end > start && (end[-1] == '\r' || end[-1] == '\n')) {
--end;
+ }
}
len = (int)(end - start);
- if (len > MAXPATHL - 1)
+ if (len > MAXPATHL - 1) {
len = MAXPATHL - 1;
+ }
STRLCPY(buf, start, len + 1);
}
buf[len] = NUL;
@@ -3165,9 +3209,9 @@ add_tag_field(
int get_tags(list_T *list, char_u *pat, char_u *buf_fname)
{
int num_matches, i, ret;
- char_u **matches;
- char_u *full_fname;
- dict_T *dict;
+ char_u **matches;
+ char_u *full_fname;
+ dict_T *dict;
tagptrs_T tp;
bool is_static;
@@ -3178,7 +3222,7 @@ int get_tags(list_T *list, char_u *pat, char_u *buf_fname)
int parse_result = parse_match(matches[i], &tp);
// Avoid an unused variable warning in release builds.
- (void) parse_result;
+ (void)parse_result;
assert(parse_result == OK);
is_static = test_for_static(&tp);
@@ -3216,29 +3260,35 @@ int get_tags(list_T *list, char_u *pat, char_u *buf_fname)
// skip "file:" (static tag)
p += 4;
} else if (!ascii_iswhite(*p)) {
- char_u *s, *n;
+ char_u *s, *n;
int len;
/* Add extra field as a dict entry. Fields are
* separated by Tabs. */
n = p;
- while (*p != NUL && *p >= ' ' && *p < 127 && *p != ':')
+ while (*p != NUL && *p >= ' ' && *p < 127 && *p != ':') {
++p;
+ }
len = (int)(p - n);
if (*p == ':' && len > 0) {
s = ++p;
- while (*p != NUL && *p >= ' ')
+ while (*p != NUL && *p >= ' ') {
++p;
+ }
n[len] = NUL;
- if (add_tag_field(dict, (char *)n, s, p) == FAIL)
+ if (add_tag_field(dict, (char *)n, s, p) == FAIL) {
ret = FAIL;
+ }
n[len] = ':';
- } else
- /* Skip field without colon. */
- while (*p != NUL && *p >= ' ')
+ } else {
+ // Skip field without colon.
+ while (*p != NUL && *p >= ' ') {
++p;
- if (*p == NUL)
+ }
+ }
+ if (*p == NUL) {
break;
+ }
}
}
}
@@ -3319,14 +3369,8 @@ static void tagstack_shift(win_T *wp)
}
// Push a new item to the tag stack
-static void tagstack_push_item(
- win_T *wp,
- char_u *tagname,
- int cur_fnum,
- int cur_match,
- pos_T mark,
- int fnum,
- char_u *user_data)
+static void tagstack_push_item(win_T *wp, char_u *tagname, int cur_fnum, int cur_match, pos_T mark,
+ int fnum, char_u *user_data)
{
taggy_T *tagstack = wp->w_tagstack;
int idx = wp->w_tagstacklen; // top of the stack
@@ -3382,13 +3426,12 @@ static void tagstack_push_items(win_T *wp, list_T *l)
if (mark.col > 0) {
mark.col--;
}
- tagstack_push_item(
- wp,
- tagname,
- (int)tv_dict_get_number(itemdict, "bufnr"),
- (int)tv_dict_get_number(itemdict, "matchnr") - 1,
- mark, fnum,
- (char_u *)tv_dict_get_string(itemdict, "user_data", true));
+ tagstack_push_item(wp,
+ tagname,
+ (int)tv_dict_get_number(itemdict, "bufnr"),
+ (int)tv_dict_get_number(itemdict, "matchnr") - 1,
+ mark, fnum,
+ (char_u *)tv_dict_get_string(itemdict, "user_data", true));
}
}
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 3335fa500a..07d668ba5b 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -37,45 +37,44 @@
// Some code from pangoterm http://www.leonerd.org.uk/code/pangoterm
#include <assert.h>
-#include <stdio.h>
-#include <stdint.h>
#include <stdbool.h>
-
+#include <stdint.h>
+#include <stdio.h>
#include <vterm.h>
-#include "nvim/log.h"
-#include "nvim/vim.h"
-#include "nvim/terminal.h"
-#include "nvim/message.h"
-#include "nvim/memory.h"
-#include "nvim/option.h"
-#include "nvim/highlight.h"
-#include "nvim/macros.h"
-#include "nvim/mbyte.h"
+#include "nvim/api/private/helpers.h"
+#include "nvim/ascii.h"
#include "nvim/buffer.h"
#include "nvim/change.h"
-#include "nvim/ascii.h"
+#include "nvim/edit.h"
+#include "nvim/event/loop.h"
+#include "nvim/event/time.h"
+#include "nvim/ex_cmds.h"
+#include "nvim/ex_docmd.h"
+#include "nvim/fileio.h"
#include "nvim/getchar.h"
-#include "nvim/ui.h"
-#include "nvim/syntax.h"
-#include "nvim/screen.h"
+#include "nvim/highlight.h"
#include "nvim/keymap.h"
-#include "nvim/edit.h"
-#include "nvim/mouse.h"
-#include "nvim/memline.h"
+#include "nvim/log.h"
+#include "nvim/macros.h"
+#include "nvim/main.h"
#include "nvim/map.h"
+#include "nvim/mbyte.h"
+#include "nvim/memline.h"
+#include "nvim/memory.h"
+#include "nvim/message.h"
#include "nvim/misc1.h"
+#include "nvim/mouse.h"
#include "nvim/move.h"
-#include "nvim/main.h"
+#include "nvim/option.h"
+#include "nvim/os/input.h"
+#include "nvim/screen.h"
#include "nvim/state.h"
-#include "nvim/ex_docmd.h"
-#include "nvim/ex_cmds.h"
+#include "nvim/syntax.h"
+#include "nvim/terminal.h"
+#include "nvim/ui.h"
+#include "nvim/vim.h"
#include "nvim/window.h"
-#include "nvim/fileio.h"
-#include "nvim/event/loop.h"
-#include "nvim/event/time.h"
-#include "nvim/os/input.h"
-#include "nvim/api/private/helpers.h"
typedef struct terminal_state {
VimState state;
@@ -210,7 +209,7 @@ Terminal *terminal_open(buf_T *buf, TerminalOptions opts)
buf->b_p_ma = false; // 'nomodifiable'
buf->b_p_ul = -1; // 'undolevels'
buf->b_p_scbk = // 'scrollback' (initialize local from global)
- (p_scbk < 0) ? 10000 : MAX(1, p_scbk);
+ (p_scbk < 0) ? 10000 : MAX(1, p_scbk);
buf->b_p_tw = 0; // 'textwidth'
set_option_value("wrap", false, NULL, OPT_LOCAL);
set_option_value("list", false, NULL, OPT_LOCAL);
@@ -359,11 +358,21 @@ void terminal_enter(void)
// Disable these options in terminal-mode. They are nonsense because cursor is
// placed at end of buffer to "follow" output. #11072
win_T *save_curwin = curwin;
- int save_w_p_cul = curwin->w_p_cul;
+ bool save_w_p_cul = curwin->w_p_cul;
+ char_u *save_w_p_culopt = NULL;
+ char_u save_w_p_culopt_flags = curwin->w_p_culopt_flags;
int save_w_p_cuc = curwin->w_p_cuc;
long save_w_p_so = curwin->w_p_so;
long save_w_p_siso = curwin->w_p_siso;
- curwin->w_p_cul = false;
+ if (curwin->w_p_cul && curwin->w_p_culopt_flags & CULOPT_NBR) {
+ if (strcmp((char *)curwin->w_p_culopt, "number")) {
+ save_w_p_culopt = curwin->w_p_culopt;
+ curwin->w_p_culopt = (char_u *)xstrdup("number");
+ }
+ curwin->w_p_culopt_flags = CULOPT_NBR;
+ } else {
+ curwin->w_p_cul = false;
+ }
curwin->w_p_cuc = false;
curwin->w_p_so = 0;
curwin->w_p_siso = 0;
@@ -387,9 +396,16 @@ void terminal_enter(void)
if (save_curwin == curwin) { // save_curwin may be invalid (window closed)!
curwin->w_p_cul = save_w_p_cul;
+ if (save_w_p_culopt) {
+ xfree(curwin->w_p_culopt);
+ curwin->w_p_culopt = save_w_p_culopt;
+ }
+ curwin->w_p_culopt_flags = save_w_p_culopt_flags;
curwin->w_p_cuc = save_w_p_cuc;
curwin->w_p_so = save_w_p_so;
curwin->w_p_siso = save_w_p_siso;
+ } else if (save_w_p_culopt) {
+ xfree(save_w_p_culopt);
}
// draw the unfocused cursor
@@ -452,56 +468,56 @@ static int terminal_execute(VimState *state, int key)
TerminalState *s = (TerminalState *)state;
switch (key) {
- case K_LEFTMOUSE:
- case K_LEFTDRAG:
- case K_LEFTRELEASE:
- case K_MOUSEMOVE:
- case K_MIDDLEMOUSE:
- case K_MIDDLEDRAG:
- case K_MIDDLERELEASE:
- case K_RIGHTMOUSE:
- case K_RIGHTDRAG:
- case K_RIGHTRELEASE:
- case K_MOUSEDOWN:
- case K_MOUSEUP:
- if (send_mouse_event(s->term, key)) {
- return 0;
- }
- break;
-
- case K_EVENT:
- // We cannot let an event free the terminal yet. It is still needed.
- s->term->refcount++;
- state_handle_k_event();
- s->term->refcount--;
- if (s->term->buf_handle == 0) {
- s->close = true;
- return 0;
- }
- break;
+ case K_LEFTMOUSE:
+ case K_LEFTDRAG:
+ case K_LEFTRELEASE:
+ case K_MOUSEMOVE:
+ case K_MIDDLEMOUSE:
+ case K_MIDDLEDRAG:
+ case K_MIDDLERELEASE:
+ case K_RIGHTMOUSE:
+ case K_RIGHTDRAG:
+ case K_RIGHTRELEASE:
+ case K_MOUSEDOWN:
+ case K_MOUSEUP:
+ if (send_mouse_event(s->term, key)) {
+ return 0;
+ }
+ break;
+
+ case K_EVENT:
+ // We cannot let an event free the terminal yet. It is still needed.
+ s->term->refcount++;
+ state_handle_k_event();
+ s->term->refcount--;
+ if (s->term->buf_handle == 0) {
+ s->close = true;
+ return 0;
+ }
+ break;
- case K_COMMAND:
- do_cmdline(NULL, getcmdkeycmd, NULL, 0);
- break;
+ case K_COMMAND:
+ do_cmdline(NULL, getcmdkeycmd, NULL, 0);
+ break;
- case Ctrl_N:
- if (s->got_bsl) {
- return 0;
- }
- FALLTHROUGH;
+ case Ctrl_N:
+ if (s->got_bsl) {
+ return 0;
+ }
+ FALLTHROUGH;
- default:
- if (key == Ctrl_BSL && !s->got_bsl) {
- s->got_bsl = true;
- break;
- }
- if (s->term->closed) {
- s->close = true;
- return 0;
- }
+ default:
+ if (key == Ctrl_BSL && !s->got_bsl) {
+ s->got_bsl = true;
+ break;
+ }
+ if (s->term->closed) {
+ s->close = true;
+ return 0;
+ }
- s->got_bsl = false;
- terminal_send_key(s->term, key);
+ s->got_bsl = false;
+ terminal_send_key(s->term, key);
}
if (curbuf->terminal == NULL) {
@@ -554,30 +570,30 @@ static bool is_filter_char(int c)
{
unsigned int flag = 0;
switch (c) {
- case 0x08:
- flag = TPF_BS;
- break;
- case 0x09:
- flag = TPF_HT;
- break;
- case 0x0A:
- case 0x0D:
- break;
- case 0x0C:
- flag = TPF_FF;
- break;
- case 0x1b:
- flag = TPF_ESC;
- break;
- case 0x7F:
- flag = TPF_DEL;
- break;
- default:
- if (c < ' ') {
- flag = TPF_C0;
- } else if (c >= 0x80 && c <= 0x9F) {
- flag = TPF_C1;
- }
+ case 0x08:
+ flag = TPF_BS;
+ break;
+ case 0x09:
+ flag = TPF_HT;
+ break;
+ case 0x0A:
+ case 0x0D:
+ break;
+ case 0x0C:
+ flag = TPF_FF;
+ break;
+ case 0x1b:
+ flag = TPF_ESC;
+ break;
+ case 0x7F:
+ flag = TPF_DEL;
+ break;
+ default:
+ if (c < ' ') {
+ flag = TPF_C0;
+ } else if (c >= 0x80 && c <= 0x9F) {
+ flag = TPF_C1;
+ }
}
return !!(tpf_flags & flag);
}
@@ -666,8 +682,7 @@ static int get_rgb(VTermState *state, VTermColor color)
}
-void terminal_get_line_attributes(Terminal *term, win_T *wp, int linenr,
- int *term_attrs)
+void terminal_get_line_attributes(Terminal *term, win_T *wp, int linenr, int *term_attrs)
{
int height, width;
vterm_get_size(term->vt, &height, &width);
@@ -701,12 +716,12 @@ void terminal_get_line_attributes(Terminal *term, win_T *wp, int linenr,
bool bg_set = vt_bg_idx && vt_bg_idx <= 16 && term->color_set[vt_bg_idx-1];
int hl_attrs = (cell.attrs.bold ? HL_BOLD : 0)
- | (cell.attrs.italic ? HL_ITALIC : 0)
- | (cell.attrs.reverse ? HL_INVERSE : 0)
- | (cell.attrs.underline ? HL_UNDERLINE : 0)
- | (cell.attrs.strike ? HL_STRIKETHROUGH: 0)
- | ((fg_indexed && !fg_set) ? HL_FG_INDEXED : 0)
- | ((bg_indexed && !bg_set) ? HL_BG_INDEXED : 0);
+ | (cell.attrs.italic ? HL_ITALIC : 0)
+ | (cell.attrs.reverse ? HL_INVERSE : 0)
+ | (cell.attrs.underline ? HL_UNDERLINE : 0)
+ | (cell.attrs.strike ? HL_STRIKETHROUGH: 0)
+ | ((fg_indexed && !fg_set) ? HL_FG_INDEXED : 0)
+ | ((bg_indexed && !bg_set) ? HL_BG_INDEXED : 0);
int attr_id = 0;
@@ -757,12 +772,11 @@ static int term_damage(VTermRect rect, void *data)
static int term_moverect(VTermRect dest, VTermRect src, void *data)
{
invalidate_terminal(data, MIN(dest.start_row, src.start_row),
- MAX(dest.end_row, src.end_row));
+ MAX(dest.end_row, src.end_row));
return 1;
}
-static int term_movecursor(VTermPos new, VTermPos old, int visible,
- void *data)
+static int term_movecursor(VTermPos new, VTermPos old, int visible, void *data)
{
Terminal *term = data;
term->cursor.row = new.row;
@@ -791,26 +805,26 @@ static int term_settermprop(VTermProp prop, VTermValue *val, void *data)
Terminal *term = data;
switch (prop) {
- case VTERM_PROP_ALTSCREEN:
- break;
-
- case VTERM_PROP_CURSORVISIBLE:
- term->cursor.visible = val->boolean;
- invalidate_terminal(term, term->cursor.row, term->cursor.row + 1);
- break;
-
- case VTERM_PROP_TITLE: {
- buf_T *buf = handle_get_buffer(term->buf_handle);
- buf_set_term_title(buf, val->string);
- break;
- }
+ case VTERM_PROP_ALTSCREEN:
+ break;
+
+ case VTERM_PROP_CURSORVISIBLE:
+ term->cursor.visible = val->boolean;
+ invalidate_terminal(term, term->cursor.row, term->cursor.row + 1);
+ break;
+
+ case VTERM_PROP_TITLE: {
+ buf_T *buf = handle_get_buffer(term->buf_handle);
+ buf_set_term_title(buf, val->string);
+ break;
+ }
- case VTERM_PROP_MOUSE:
- term->forward_mouse = (bool)val->number;
- break;
+ case VTERM_PROP_MOUSE:
+ term->forward_mouse = (bool)val->number;
+ break;
- default:
- return 0;
+ default:
+ return 0;
}
return 1;
@@ -844,12 +858,11 @@ static int term_sb_push(int cols, const VTermScreenCell *cells, void *data)
// Make room at the start by shifting to the right.
memmove(term->sb_buffer + 1, term->sb_buffer,
- sizeof(term->sb_buffer[0]) * (term->sb_current - 1));
-
+ sizeof(term->sb_buffer[0]) * (term->sb_current - 1));
} else if (term->sb_current > 0) {
// Make room at the start by shifting to the right.
memmove(term->sb_buffer + 1, term->sb_buffer,
- sizeof(term->sb_buffer[0]) * term->sb_current);
+ sizeof(term->sb_buffer[0]) * term->sb_current);
}
if (!sbrow) {
@@ -894,7 +907,7 @@ static int term_sb_pop(int cols, VTermScreenCell *cells, void *data)
term->sb_current--;
// Forget the "popped" row by shifting the rest onto it.
memmove(term->sb_buffer, term->sb_buffer + 1,
- sizeof(term->sb_buffer[0]) * (term->sb_current));
+ sizeof(term->sb_buffer[0]) * (term->sb_current));
size_t cols_to_copy = (size_t)cols;
if (cols_to_copy > sbrow->cols) {
@@ -919,35 +932,41 @@ static int term_sb_pop(int cols, VTermScreenCell *cells, void *data)
static void convert_modifiers(int key, VTermModifier *statep)
{
- if (mod_mask & MOD_MASK_SHIFT) { *statep |= VTERM_MOD_SHIFT; }
- if (mod_mask & MOD_MASK_CTRL) { *statep |= VTERM_MOD_CTRL; }
- if (mod_mask & MOD_MASK_ALT) { *statep |= VTERM_MOD_ALT; }
+ if (mod_mask & MOD_MASK_SHIFT) {
+ *statep |= VTERM_MOD_SHIFT;
+ }
+ if (mod_mask & MOD_MASK_CTRL) {
+ *statep |= VTERM_MOD_CTRL;
+ }
+ if (mod_mask & MOD_MASK_ALT) {
+ *statep |= VTERM_MOD_ALT;
+ }
switch (key) {
- case K_S_TAB:
- case K_S_UP:
- case K_S_DOWN:
- case K_S_LEFT:
- case K_S_RIGHT:
- case K_S_F1:
- case K_S_F2:
- case K_S_F3:
- case K_S_F4:
- case K_S_F5:
- case K_S_F6:
- case K_S_F7:
- case K_S_F8:
- case K_S_F9:
- case K_S_F10:
- case K_S_F11:
- case K_S_F12:
- *statep |= VTERM_MOD_SHIFT;
- break;
-
- case K_C_LEFT:
- case K_C_RIGHT:
- *statep |= VTERM_MOD_CTRL;
- break;
+ case K_S_TAB:
+ case K_S_UP:
+ case K_S_DOWN:
+ case K_S_LEFT:
+ case K_S_RIGHT:
+ case K_S_F1:
+ case K_S_F2:
+ case K_S_F3:
+ case K_S_F4:
+ case K_S_F5:
+ case K_S_F6:
+ case K_S_F7:
+ case K_S_F8:
+ case K_S_F9:
+ case K_S_F10:
+ case K_S_F11:
+ case K_S_F12:
+ *statep |= VTERM_MOD_SHIFT;
+ break;
+
+ case K_C_LEFT:
+ case K_C_RIGHT:
+ *statep |= VTERM_MOD_CTRL;
+ break;
}
}
@@ -956,115 +975,212 @@ static VTermKey convert_key(int key, VTermModifier *statep)
convert_modifiers(key, statep);
switch (key) {
- case K_BS: return VTERM_KEY_BACKSPACE;
- case K_S_TAB: FALLTHROUGH;
- case TAB: return VTERM_KEY_TAB;
- case Ctrl_M: return VTERM_KEY_ENTER;
- case ESC: return VTERM_KEY_ESCAPE;
-
- case K_S_UP: FALLTHROUGH;
- case K_UP: return VTERM_KEY_UP;
- case K_S_DOWN: FALLTHROUGH;
- case K_DOWN: return VTERM_KEY_DOWN;
- case K_S_LEFT: FALLTHROUGH;
- case K_C_LEFT: FALLTHROUGH;
- case K_LEFT: return VTERM_KEY_LEFT;
- case K_S_RIGHT: FALLTHROUGH;
- case K_C_RIGHT: FALLTHROUGH;
- case K_RIGHT: return VTERM_KEY_RIGHT;
-
- case K_INS: return VTERM_KEY_INS;
- case K_DEL: return VTERM_KEY_DEL;
- case K_HOME: return VTERM_KEY_HOME;
- case K_END: return VTERM_KEY_END;
- case K_PAGEUP: return VTERM_KEY_PAGEUP;
- case K_PAGEDOWN: return VTERM_KEY_PAGEDOWN;
-
- case K_K0: FALLTHROUGH;
- case K_KINS: return VTERM_KEY_KP_0;
- case K_K1: FALLTHROUGH;
- case K_KEND: return VTERM_KEY_KP_1;
- case K_K2: FALLTHROUGH;
- case K_KDOWN: return VTERM_KEY_KP_2;
- case K_K3: FALLTHROUGH;
- case K_KPAGEDOWN: return VTERM_KEY_KP_3;
- case K_K4: FALLTHROUGH;
- case K_KLEFT: return VTERM_KEY_KP_4;
- case K_K5: FALLTHROUGH;
- case K_KORIGIN: return VTERM_KEY_KP_5;
- case K_K6: FALLTHROUGH;
- case K_KRIGHT: return VTERM_KEY_KP_6;
- case K_K7: FALLTHROUGH;
- case K_KHOME: return VTERM_KEY_KP_7;
- case K_K8: FALLTHROUGH;
- case K_KUP: return VTERM_KEY_KP_8;
- case K_K9: FALLTHROUGH;
- case K_KPAGEUP: return VTERM_KEY_KP_9;
- case K_KDEL: FALLTHROUGH;
- case K_KPOINT: return VTERM_KEY_KP_PERIOD;
- case K_KENTER: return VTERM_KEY_KP_ENTER;
- case K_KPLUS: return VTERM_KEY_KP_PLUS;
- case K_KMINUS: return VTERM_KEY_KP_MINUS;
- case K_KMULTIPLY: return VTERM_KEY_KP_MULT;
- case K_KDIVIDE: return VTERM_KEY_KP_DIVIDE;
-
- case K_S_F1: FALLTHROUGH;
- case K_F1: return VTERM_KEY_FUNCTION(1);
- case K_S_F2: FALLTHROUGH;
- case K_F2: return VTERM_KEY_FUNCTION(2);
- case K_S_F3: FALLTHROUGH;
- case K_F3: return VTERM_KEY_FUNCTION(3);
- case K_S_F4: FALLTHROUGH;
- case K_F4: return VTERM_KEY_FUNCTION(4);
- case K_S_F5: FALLTHROUGH;
- case K_F5: return VTERM_KEY_FUNCTION(5);
- case K_S_F6: FALLTHROUGH;
- case K_F6: return VTERM_KEY_FUNCTION(6);
- case K_S_F7: FALLTHROUGH;
- case K_F7: return VTERM_KEY_FUNCTION(7);
- case K_S_F8: FALLTHROUGH;
- case K_F8: return VTERM_KEY_FUNCTION(8);
- case K_S_F9: FALLTHROUGH;
- case K_F9: return VTERM_KEY_FUNCTION(9);
- case K_S_F10: FALLTHROUGH;
- case K_F10: return VTERM_KEY_FUNCTION(10);
- case K_S_F11: FALLTHROUGH;
- case K_F11: return VTERM_KEY_FUNCTION(11);
- case K_S_F12: FALLTHROUGH;
- case K_F12: return VTERM_KEY_FUNCTION(12);
-
- case K_F13: return VTERM_KEY_FUNCTION(13);
- case K_F14: return VTERM_KEY_FUNCTION(14);
- case K_F15: return VTERM_KEY_FUNCTION(15);
- case K_F16: return VTERM_KEY_FUNCTION(16);
- case K_F17: return VTERM_KEY_FUNCTION(17);
- case K_F18: return VTERM_KEY_FUNCTION(18);
- case K_F19: return VTERM_KEY_FUNCTION(19);
- case K_F20: return VTERM_KEY_FUNCTION(20);
- case K_F21: return VTERM_KEY_FUNCTION(21);
- case K_F22: return VTERM_KEY_FUNCTION(22);
- case K_F23: return VTERM_KEY_FUNCTION(23);
- case K_F24: return VTERM_KEY_FUNCTION(24);
- case K_F25: return VTERM_KEY_FUNCTION(25);
- case K_F26: return VTERM_KEY_FUNCTION(26);
- case K_F27: return VTERM_KEY_FUNCTION(27);
- case K_F28: return VTERM_KEY_FUNCTION(28);
- case K_F29: return VTERM_KEY_FUNCTION(29);
- case K_F30: return VTERM_KEY_FUNCTION(30);
- case K_F31: return VTERM_KEY_FUNCTION(31);
- case K_F32: return VTERM_KEY_FUNCTION(32);
- case K_F33: return VTERM_KEY_FUNCTION(33);
- case K_F34: return VTERM_KEY_FUNCTION(34);
- case K_F35: return VTERM_KEY_FUNCTION(35);
- case K_F36: return VTERM_KEY_FUNCTION(36);
- case K_F37: return VTERM_KEY_FUNCTION(37);
-
- default: return VTERM_KEY_NONE;
+ case K_BS:
+ return VTERM_KEY_BACKSPACE;
+ case K_S_TAB:
+ FALLTHROUGH;
+ case TAB:
+ return VTERM_KEY_TAB;
+ case Ctrl_M:
+ return VTERM_KEY_ENTER;
+ case ESC:
+ return VTERM_KEY_ESCAPE;
+
+ case K_S_UP:
+ FALLTHROUGH;
+ case K_UP:
+ return VTERM_KEY_UP;
+ case K_S_DOWN:
+ FALLTHROUGH;
+ case K_DOWN:
+ return VTERM_KEY_DOWN;
+ case K_S_LEFT:
+ FALLTHROUGH;
+ case K_C_LEFT:
+ FALLTHROUGH;
+ case K_LEFT:
+ return VTERM_KEY_LEFT;
+ case K_S_RIGHT:
+ FALLTHROUGH;
+ case K_C_RIGHT:
+ FALLTHROUGH;
+ case K_RIGHT:
+ return VTERM_KEY_RIGHT;
+
+ case K_INS:
+ return VTERM_KEY_INS;
+ case K_DEL:
+ return VTERM_KEY_DEL;
+ case K_HOME:
+ return VTERM_KEY_HOME;
+ case K_END:
+ return VTERM_KEY_END;
+ case K_PAGEUP:
+ return VTERM_KEY_PAGEUP;
+ case K_PAGEDOWN:
+ return VTERM_KEY_PAGEDOWN;
+
+ case K_K0:
+ FALLTHROUGH;
+ case K_KINS:
+ return VTERM_KEY_KP_0;
+ case K_K1:
+ FALLTHROUGH;
+ case K_KEND:
+ return VTERM_KEY_KP_1;
+ case K_K2:
+ FALLTHROUGH;
+ case K_KDOWN:
+ return VTERM_KEY_KP_2;
+ case K_K3:
+ FALLTHROUGH;
+ case K_KPAGEDOWN:
+ return VTERM_KEY_KP_3;
+ case K_K4:
+ FALLTHROUGH;
+ case K_KLEFT:
+ return VTERM_KEY_KP_4;
+ case K_K5:
+ FALLTHROUGH;
+ case K_KORIGIN:
+ return VTERM_KEY_KP_5;
+ case K_K6:
+ FALLTHROUGH;
+ case K_KRIGHT:
+ return VTERM_KEY_KP_6;
+ case K_K7:
+ FALLTHROUGH;
+ case K_KHOME:
+ return VTERM_KEY_KP_7;
+ case K_K8:
+ FALLTHROUGH;
+ case K_KUP:
+ return VTERM_KEY_KP_8;
+ case K_K9:
+ FALLTHROUGH;
+ case K_KPAGEUP:
+ return VTERM_KEY_KP_9;
+ case K_KDEL:
+ FALLTHROUGH;
+ case K_KPOINT:
+ return VTERM_KEY_KP_PERIOD;
+ case K_KENTER:
+ return VTERM_KEY_KP_ENTER;
+ case K_KPLUS:
+ return VTERM_KEY_KP_PLUS;
+ case K_KMINUS:
+ return VTERM_KEY_KP_MINUS;
+ case K_KMULTIPLY:
+ return VTERM_KEY_KP_MULT;
+ case K_KDIVIDE:
+ return VTERM_KEY_KP_DIVIDE;
+
+ case K_S_F1:
+ FALLTHROUGH;
+ case K_F1:
+ return VTERM_KEY_FUNCTION(1);
+ case K_S_F2:
+ FALLTHROUGH;
+ case K_F2:
+ return VTERM_KEY_FUNCTION(2);
+ case K_S_F3:
+ FALLTHROUGH;
+ case K_F3:
+ return VTERM_KEY_FUNCTION(3);
+ case K_S_F4:
+ FALLTHROUGH;
+ case K_F4:
+ return VTERM_KEY_FUNCTION(4);
+ case K_S_F5:
+ FALLTHROUGH;
+ case K_F5:
+ return VTERM_KEY_FUNCTION(5);
+ case K_S_F6:
+ FALLTHROUGH;
+ case K_F6:
+ return VTERM_KEY_FUNCTION(6);
+ case K_S_F7:
+ FALLTHROUGH;
+ case K_F7:
+ return VTERM_KEY_FUNCTION(7);
+ case K_S_F8:
+ FALLTHROUGH;
+ case K_F8:
+ return VTERM_KEY_FUNCTION(8);
+ case K_S_F9:
+ FALLTHROUGH;
+ case K_F9:
+ return VTERM_KEY_FUNCTION(9);
+ case K_S_F10:
+ FALLTHROUGH;
+ case K_F10:
+ return VTERM_KEY_FUNCTION(10);
+ case K_S_F11:
+ FALLTHROUGH;
+ case K_F11:
+ return VTERM_KEY_FUNCTION(11);
+ case K_S_F12:
+ FALLTHROUGH;
+ case K_F12:
+ return VTERM_KEY_FUNCTION(12);
+
+ case K_F13:
+ return VTERM_KEY_FUNCTION(13);
+ case K_F14:
+ return VTERM_KEY_FUNCTION(14);
+ case K_F15:
+ return VTERM_KEY_FUNCTION(15);
+ case K_F16:
+ return VTERM_KEY_FUNCTION(16);
+ case K_F17:
+ return VTERM_KEY_FUNCTION(17);
+ case K_F18:
+ return VTERM_KEY_FUNCTION(18);
+ case K_F19:
+ return VTERM_KEY_FUNCTION(19);
+ case K_F20:
+ return VTERM_KEY_FUNCTION(20);
+ case K_F21:
+ return VTERM_KEY_FUNCTION(21);
+ case K_F22:
+ return VTERM_KEY_FUNCTION(22);
+ case K_F23:
+ return VTERM_KEY_FUNCTION(23);
+ case K_F24:
+ return VTERM_KEY_FUNCTION(24);
+ case K_F25:
+ return VTERM_KEY_FUNCTION(25);
+ case K_F26:
+ return VTERM_KEY_FUNCTION(26);
+ case K_F27:
+ return VTERM_KEY_FUNCTION(27);
+ case K_F28:
+ return VTERM_KEY_FUNCTION(28);
+ case K_F29:
+ return VTERM_KEY_FUNCTION(29);
+ case K_F30:
+ return VTERM_KEY_FUNCTION(30);
+ case K_F31:
+ return VTERM_KEY_FUNCTION(31);
+ case K_F32:
+ return VTERM_KEY_FUNCTION(32);
+ case K_F33:
+ return VTERM_KEY_FUNCTION(33);
+ case K_F34:
+ return VTERM_KEY_FUNCTION(34);
+ case K_F35:
+ return VTERM_KEY_FUNCTION(35);
+ case K_F36:
+ return VTERM_KEY_FUNCTION(36);
+ case K_F37:
+ return VTERM_KEY_FUNCTION(37);
+
+ default:
+ return VTERM_KEY_NONE;
}
}
-static void mouse_action(Terminal *term, int button, int row, int col,
- bool drag, VTermModifier mod)
+static void mouse_action(Terminal *term, int button, int row, int col, bool drag, VTermModifier mod)
{
if (term->pressed_button && (term->pressed_button != button || !drag)) {
// release the previous button
@@ -1100,16 +1216,26 @@ static bool send_mouse_event(Terminal *term, int c)
bool drag = false;
switch (c) {
- case K_LEFTDRAG: drag = true; FALLTHROUGH;
- case K_LEFTMOUSE: button = 1; break;
- case K_MOUSEMOVE: drag = true; button = 0; break;
- case K_MIDDLEDRAG: drag = true; FALLTHROUGH;
- case K_MIDDLEMOUSE: button = 2; break;
- case K_RIGHTDRAG: drag = true; FALLTHROUGH;
- case K_RIGHTMOUSE: button = 3; break;
- case K_MOUSEDOWN: button = 4; break;
- case K_MOUSEUP: button = 5; break;
- default: return false;
+ case K_LEFTDRAG:
+ drag = true; FALLTHROUGH;
+ case K_LEFTMOUSE:
+ button = 1; break;
+ case K_MOUSEMOVE:
+ drag = true; button = 0; break;
+ case K_MIDDLEDRAG:
+ drag = true; FALLTHROUGH;
+ case K_MIDDLEMOUSE:
+ button = 2; break;
+ case K_RIGHTDRAG:
+ drag = true; FALLTHROUGH;
+ case K_RIGHTMOUSE:
+ button = 3; break;
+ case K_MOUSEDOWN:
+ button = 4; break;
+ case K_MOUSEUP:
+ button = 5; break;
+ default:
+ return false;
}
mouse_action(term, button, row, col - offset, drag, 0);
@@ -1162,7 +1288,7 @@ static void fetch_row(Terminal *term, int row, int end_col)
if (cell.chars[0]) {
for (int i = 0; cell.chars[i]; i++) {
cell_len += utf_char2bytes((int)cell.chars[i],
- (uint8_t *)ptr + cell_len);
+ (uint8_t *)ptr + cell_len);
}
} else {
*ptr = ' ';
@@ -1181,8 +1307,7 @@ static void fetch_row(Terminal *term, int row, int end_col)
term->textbuf[line_len] = 0;
}
-static bool fetch_cell(Terminal *term, int row, int col,
- VTermScreenCell *cell)
+static bool fetch_cell(Terminal *term, int row, int col, VTermScreenCell *cell)
{
if (row < 0) {
ScrollbackLine *sbrow = term->sb_buffer[-row - 1];
@@ -1197,8 +1322,8 @@ static bool fetch_cell(Terminal *term, int row, int col,
return false;
}
} else {
- vterm_screen_get_cell(term->vts, (VTermPos){.row = row, .col = col},
- cell);
+ vterm_screen_get_cell(term->vts, (VTermPos){ .row = row, .col = col },
+ cell);
}
return true;
}
diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim
index cc789cb6bd..cca89cbd6d 100644
--- a/src/nvim/testdir/test_filetype.vim
+++ b/src/nvim/testdir/test_filetype.vim
@@ -259,7 +259,7 @@ let s:filename_checks = {
\ 'jgraph': ['file.jgr'],
\ 'jovial': ['file.jov', 'file.j73', 'file.jovial'],
\ 'jproperties': ['file.properties', 'file.properties_xx', 'file.properties_xx_xx', 'some.properties_xx_xx_file'],
- \ 'json': ['file.json', 'file.jsonp', 'file.json-patch', 'file.webmanifest', 'Pipfile.lock', 'file.ipynb'],
+ \ 'json': ['file.json', 'file.jsonp', 'file.json-patch', 'file.webmanifest', 'Pipfile.lock', 'file.ipynb', '.babelrc', '.eslintrc', '.prettierrc', '.firebaserc'],
\ 'jsonc': ['file.jsonc'],
\ 'jsp': ['file.jsp'],
\ 'julia': ['file.jl'],
@@ -344,6 +344,7 @@ let s:filename_checks = {
\ 'nanorc': ['/etc/nanorc', 'file.nanorc', 'any/etc/nanorc'],
\ 'ncf': ['file.ncf'],
\ 'netrc': ['.netrc'],
+ \ 'nginx': ['file.nginx', 'nginxfile.conf', 'filenginx.conf', 'any/etc/nginx/file', 'any/usr/local/nginx/conf/file', 'any/nginx/file.conf'],
\ 'ninja': ['file.ninja'],
\ 'nqc': ['file.nqc'],
\ 'nroff': ['file.tr', 'file.nr', 'file.roff', 'file.tmac', 'file.mom', 'tmac.file'],
@@ -491,7 +492,7 @@ let s:filename_checks = {
\ 'tak': ['file.tak'],
\ 'taskdata': ['pending.data', 'completed.data', 'undo.data'],
\ 'taskedit': ['file.task'],
- \ 'tcl': ['file.tcl', 'file.tk', 'file.itcl', 'file.itk', 'file.jacl'],
+ \ 'tcl': ['file.tcl', 'file.tm', 'file.tk', 'file.itcl', 'file.itk', 'file.jacl', '.tclshrc', 'tclsh.rc', '.wishrc'],
\ 'teraterm': ['file.ttl'],
\ 'terminfo': ['file.ti'],
\ 'tex': ['file.latex', 'file.sty', 'file.dtx', 'file.ltx', 'file.bbl'],
diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim
index e82fefc7fc..366615821c 100644
--- a/src/nvim/testdir/test_functions.vim
+++ b/src/nvim/testdir/test_functions.vim
@@ -585,6 +585,8 @@ func Test_mode()
exe "normal iabc\<C-X>\<C-L>\<F2>\<Esc>u"
call assert_equal('i-ic', g:current_modes)
+ exe "normal R\<F2>\<Esc>"
+ call assert_equal('R-R', g:current_modes)
" R_CTRL-P: Multiple matches
exe "normal RBa\<C-P>\<F2>\<Esc>u"
call assert_equal('R-Rc', g:current_modes)
@@ -619,6 +621,42 @@ func Test_mode()
exe "normal Rabc\<C-X>\<C-L>\<F2>\<Esc>u"
call assert_equal('R-Rc', g:current_modes)
+ exe "normal gR\<F2>\<Esc>"
+ call assert_equal('R-Rv', g:current_modes)
+ " gR_CTRL-P: Multiple matches
+ exe "normal gRBa\<C-P>\<F2>\<Esc>u"
+ call assert_equal('R-Rvc', g:current_modes)
+ " gR_CTRL-P: Single match
+ exe "normal gRBro\<C-P>\<F2>\<Esc>u"
+ call assert_equal('R-Rvc', g:current_modes)
+ " gR_CTRL-X
+ exe "normal gRBa\<C-X>\<F2>\<Esc>u"
+ call assert_equal('R-Rvx', g:current_modes)
+ " gR_CTRL-X CTRL-P: Multiple matches
+ exe "normal gRBa\<C-X>\<C-P>\<F2>\<Esc>u"
+ call assert_equal('R-Rvc', g:current_modes)
+ " gR_CTRL-X CTRL-P: Single match
+ exe "normal gRBro\<C-X>\<C-P>\<F2>\<Esc>u"
+ call assert_equal('R-Rvc', g:current_modes)
+ " gR_CTRL-X CTRL-P + CTRL-P: Single match
+ exe "normal gRBro\<C-X>\<C-P>\<C-P>\<F2>\<Esc>u"
+ call assert_equal('R-Rvc', g:current_modes)
+ " gR_CTRL-X CTRL-L: Multiple matches
+ exe "normal gR\<C-X>\<C-L>\<F2>\<Esc>u"
+ call assert_equal('R-Rvc', g:current_modes)
+ " gR_CTRL-X CTRL-L: Single match
+ exe "normal gRBlu\<C-X>\<C-L>\<F2>\<Esc>u"
+ call assert_equal('R-Rvc', g:current_modes)
+ " gR_CTRL-P: No match
+ exe "normal gRCom\<C-P>\<F2>\<Esc>u"
+ call assert_equal('R-Rvc', g:current_modes)
+ " gR_CTRL-X CTRL-P: No match
+ exe "normal gRCom\<C-X>\<C-P>\<F2>\<Esc>u"
+ call assert_equal('R-Rvc', g:current_modes)
+ " gR_CTRL-X CTRL-L: No match
+ exe "normal gRabc\<C-X>\<C-L>\<F2>\<Esc>u"
+ call assert_equal('R-Rvc', g:current_modes)
+
call assert_equal('n', mode(0))
call assert_equal('n', mode(1))
diff --git a/src/nvim/testdir/test_method.vim b/src/nvim/testdir/test_method.vim
index d34448e09e..cdf688b857 100644
--- a/src/nvim/testdir/test_method.vim
+++ b/src/nvim/testdir/test_method.vim
@@ -1,5 +1,7 @@
" Tests for ->method()
+source check.vim
+
func Test_list_method()
let l = [1, 2, 3]
call assert_equal([1, 2, 3, 4], [1, 2, 3]->add(4))
@@ -118,6 +120,7 @@ func Test_method_funcref()
endfunc
func Test_method_float()
+ CheckFeature float
eval 1.234->string()->assert_equal('1.234')
eval -1.234->string()->assert_equal('-1.234')
endfunc
diff --git a/src/nvim/testdir/test_popup.vim b/src/nvim/testdir/test_popup.vim
index 710450293c..eb367cfe5c 100644
--- a/src/nvim/testdir/test_popup.vim
+++ b/src/nvim/testdir/test_popup.vim
@@ -950,6 +950,10 @@ func Test_popup_complete_info_01()
\ ["\<C-X>", 'ctrl_x'],
\ ["\<C-X>\<C-N>", 'keyword'],
\ ["\<C-X>\<C-P>", 'keyword'],
+ \ ["\<C-X>\<C-E>", 'scroll'],
+ \ ["\<C-X>\<C-Y>", 'scroll'],
+ \ ["\<C-X>\<C-E>\<C-E>\<C-Y>", 'scroll'],
+ \ ["\<C-X>\<C-Y>\<C-E>\<C-Y>", 'scroll'],
\ ["\<C-X>\<C-L>", 'whole_line'],
\ ["\<C-X>\<C-F>", 'files'],
\ ["\<C-X>\<C-]>", 'tags'],
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index 803ff23cea..612eaf6667 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -1019,22 +1019,8 @@ static void tui_mouse_on(UI *ui)
{
TUIData *data = ui->data;
if (!data->mouse_enabled) {
-#ifdef WIN32
- // Windows versions with vtp(ENABLE_VIRTUAL_TERMINAL_PROCESSING) and
- // no vti(ENABLE_VIRTUAL_TERMINAL_INPUT) will need to use mouse tracking of
- // libuv. For this reason, vtp (vterm) state of libuv is temporarily
- // disabled because the control sequence needs to be processed by libuv
- // instead of Windows vtp.
- // ref. https://docs.microsoft.com/en-us/windows/console/setconsolemode
- flush_buf(ui);
- os_set_vtp(false);
-#endif
unibi_out_ext(ui, data->unibi_ext.enable_mouse);
data->mouse_enabled = true;
-#ifdef WIN32
- flush_buf(ui);
- os_set_vtp(true);
-#endif
}
}
@@ -1042,22 +1028,8 @@ static void tui_mouse_off(UI *ui)
{
TUIData *data = ui->data;
if (data->mouse_enabled) {
-#ifdef WIN32
- // Windows versions with vtp(ENABLE_VIRTUAL_TERMINAL_PROCESSING) and
- // no vti(ENABLE_VIRTUAL_TERMINAL_INPUT) will need to use mouse tracking of
- // libuv. For this reason, vtp (vterm) state of libuv is temporarily
- // disabled because the control sequence needs to be processed by libuv
- // instead of Windows vtp.
- // ref. https://docs.microsoft.com/en-us/windows/console/setconsolemode
- flush_buf(ui);
- os_set_vtp(false);
-#endif
unibi_out_ext(ui, data->unibi_ext.disable_mouse);
data->mouse_enabled = false;
-#ifdef WIN32
- flush_buf(ui);
- os_set_vtp(true);
-#endif
}
}
diff --git a/src/nvim/ugrid.c b/src/nvim/ugrid.c
index 9e4aaff878..ef84cdf334 100644
--- a/src/nvim/ugrid.c
+++ b/src/nvim/ugrid.c
@@ -2,14 +2,14 @@
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include <assert.h>
+#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
-#include <limits.h>
#include "nvim/assert.h"
-#include "nvim/vim.h"
-#include "nvim/ui.h"
#include "nvim/ugrid.h"
+#include "nvim/ui.h"
+#include "nvim/vim.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ugrid.c.generated.h"
@@ -79,8 +79,7 @@ void ugrid_scroll(UGrid *grid, int top, int bot, int left, int right, int count)
}
}
-static void clear_region(UGrid *grid, int top, int bot, int left, int right,
- sattr_T attr)
+static void clear_region(UGrid *grid, int top, int bot, int left, int right, sattr_T attr)
{
for (int row = top; row <= bot; row++) {
UGRID_FOREACH_CELL(grid, row, left, right+1, {
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index 09709d0f43..aad72af025 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -3,40 +3,40 @@
#include <assert.h>
#include <inttypes.h>
+#include <limits.h>
#include <stdbool.h>
#include <string.h>
-#include <limits.h>
-#include "nvim/vim.h"
-#include "nvim/log.h"
+#include "nvim/ascii.h"
#include "nvim/aucmd.h"
-#include "nvim/ui.h"
#include "nvim/charset.h"
#include "nvim/cursor.h"
+#include "nvim/cursor_shape.h"
#include "nvim/diff.h"
+#include "nvim/event/loop.h"
#include "nvim/ex_cmds2.h"
#include "nvim/ex_getln.h"
#include "nvim/fold.h"
+#include "nvim/garray.h"
+#include "nvim/highlight.h"
+#include "nvim/log.h"
#include "nvim/main.h"
-#include "nvim/ascii.h"
-#include "nvim/misc1.h"
#include "nvim/mbyte.h"
-#include "nvim/garray.h"
#include "nvim/memory.h"
+#include "nvim/misc1.h"
#include "nvim/move.h"
#include "nvim/normal.h"
#include "nvim/option.h"
-#include "nvim/os_unix.h"
-#include "nvim/event/loop.h"
-#include "nvim/os/time.h"
#include "nvim/os/input.h"
#include "nvim/os/signal.h"
+#include "nvim/os/time.h"
+#include "nvim/os_unix.h"
#include "nvim/popupmnu.h"
#include "nvim/screen.h"
-#include "nvim/highlight.h"
+#include "nvim/ui.h"
#include "nvim/ui_compositor.h"
+#include "nvim/vim.h"
#include "nvim/window.h"
-#include "nvim/cursor_shape.h"
#ifdef FEAT_TUI
# include "nvim/tui/tui.h"
#else
@@ -70,9 +70,9 @@ static int pending_has_mouse = -1;
static size_t uilog_seen = 0;
static char uilog_last_event[1024] = { 0 };
-#ifndef EXITFREE
-#define entered_free_all_mem false
-#endif
+# ifndef EXITFREE
+# define entered_free_all_mem false
+# endif
# define UI_LOG(funname) \
do { \
@@ -95,7 +95,7 @@ static char uilog_last_event[1024] = { 0 };
// UI_CALL invokes a function on all registered UI instances.
// This is called by code generated by generators/gen_api_ui_events.lua
// C code should use ui_call_{funname} instead.
-# define UI_CALL(cond, funname, ...) \
+#define UI_CALL(cond, funname, ...) \
do { \
bool any_call = false; \
for (size_t i = 0; i < ui_count; i++) { \
@@ -115,7 +115,7 @@ static char uilog_last_event[1024] = { 0 };
#endif
#ifndef EXITFREE
-#undef entered_free_all_mem
+# undef entered_free_all_mem
#endif
void ui_init(void)
@@ -382,8 +382,8 @@ void ui_set_ext_option(UI *ui, UIExtension ext, bool active)
}
}
-void ui_line(ScreenGrid *grid, int row, int startcol, int endcol, int clearcol,
- int clearattr, bool wrap)
+void ui_line(ScreenGrid *grid, int row, int startcol, int endcol, int clearcol, int clearattr,
+ bool wrap)
{
assert(0 <= row && row < grid->Rows);
LineFlags flags = wrap ? kLineFlagWrap : 0;
@@ -515,23 +515,23 @@ void ui_check_mouse(void)
// normal editing mode (not at hit-return message).
for (char_u *p = p_mouse; *p; p++) {
switch (*p) {
- case 'a':
- if (vim_strchr((char_u *)MOUSE_A, checkfor) != NULL) {
- has_mouse = true;
- return;
- }
- break;
- case MOUSE_HELP:
- if (checkfor != MOUSE_RETURN && curbuf->b_help) {
- has_mouse = true;
- return;
- }
- break;
- default:
- if (checkfor == *p) {
- has_mouse = true;
- return;
- }
+ case 'a':
+ if (vim_strchr((char_u *)MOUSE_A, checkfor) != NULL) {
+ has_mouse = true;
+ return;
+ }
+ break;
+ case MOUSE_HELP:
+ if (checkfor != MOUSE_RETURN && curbuf->b_help) {
+ has_mouse = true;
+ return;
+ }
+ break;
+ default:
+ if (checkfor == *p) {
+ has_mouse = true;
+ return;
+ }
}
}
}
diff --git a/src/nvim/ui_bridge.c b/src/nvim/ui_bridge.c
index bc64414ecf..3402df817a 100644
--- a/src/nvim/ui_bridge.c
+++ b/src/nvim/ui_bridge.c
@@ -5,18 +5,18 @@
// Used by the built-in TUI and libnvim-based UIs.
#include <assert.h>
+#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
-#include <limits.h>
+#include "nvim/api/private/helpers.h"
#include "nvim/log.h"
#include "nvim/main.h"
-#include "nvim/vim.h"
-#include "nvim/ui.h"
#include "nvim/memory.h"
-#include "nvim/ui_bridge.h"
#include "nvim/ugrid.h"
-#include "nvim/api/private/helpers.h"
+#include "nvim/ui.h"
+#include "nvim/ui_bridge.h"
+#include "nvim/vim.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ui_bridge.c.generated.h"
@@ -26,8 +26,7 @@
// Schedule a function call on the UI bridge thread.
#define UI_BRIDGE_CALL(ui, name, argc, ...) \
- ((UIBridgeData *)ui)->scheduler( \
- event_create(ui_bridge_##name##_event, argc, __VA_ARGS__), UI(ui))
+ ((UIBridgeData *)ui)->scheduler(event_create(ui_bridge_##name##_event, argc, __VA_ARGS__), UI(ui))
#define INT2PTR(i) ((void *)(intptr_t)i)
#define PTR2INT(p) ((Integer)(intptr_t)p)
@@ -138,8 +137,8 @@ static void ui_bridge_stop_event(void **argv)
ui->stop(ui);
}
-static void ui_bridge_hl_attr_define(UI *ui, Integer id, HlAttrs attrs,
- HlAttrs cterm_attrs, Array info)
+static void ui_bridge_hl_attr_define(UI *ui, Integer id, HlAttrs attrs, HlAttrs cterm_attrs,
+ Array info)
{
HlAttrs *a = xmalloc(sizeof(HlAttrs));
*a = attrs;
@@ -163,11 +162,9 @@ static void ui_bridge_raw_line_event(void **argv)
xfree(argv[8]);
xfree(argv[9]);
}
-static void ui_bridge_raw_line(UI *ui, Integer grid, Integer row,
- Integer startcol, Integer endcol,
- Integer clearcol, Integer clearattr,
- LineFlags flags, const schar_T *chunk,
- const sattr_T *attrs)
+static void ui_bridge_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Integer endcol,
+ Integer clearcol, Integer clearattr, LineFlags flags,
+ const schar_T *chunk, const sattr_T *attrs)
{
size_t ncol = (size_t)(endcol-startcol);
schar_T *c = xmemdup(chunk, ncol * sizeof(schar_T));
diff --git a/src/nvim/ui_compositor.c b/src/nvim/ui_compositor.c
index 9c9aec1cf5..7a0f68cfeb 100644
--- a/src/nvim/ui_compositor.c
+++ b/src/nvim/ui_compositor.c
@@ -7,27 +7,27 @@
// Layer-based compositing: https://en.wikipedia.org/wiki/Digital_compositing
#include <assert.h>
+#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
-#include <limits.h>
+#include "nvim/api/private/helpers.h"
+#include "nvim/ascii.h"
+#include "nvim/highlight.h"
#include "nvim/lib/kvec.h"
#include "nvim/log.h"
+#include "nvim/lua/executor.h"
#include "nvim/main.h"
-#include "nvim/ascii.h"
-#include "nvim/vim.h"
-#include "nvim/ui.h"
-#include "nvim/highlight.h"
#include "nvim/memory.h"
#include "nvim/message.h"
+#include "nvim/os/os.h"
#include "nvim/popupmnu.h"
-#include "nvim/ui_compositor.h"
-#include "nvim/ugrid.h"
#include "nvim/screen.h"
#include "nvim/syntax.h"
-#include "nvim/api/private/helpers.h"
-#include "nvim/lua/executor.h"
-#include "nvim/os/os.h"
+#include "nvim/ugrid.h"
+#include "nvim/ui.h"
+#include "nvim/ui_compositor.h"
+#include "nvim/vim.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ui_compositor.c.generated.h"
@@ -123,8 +123,8 @@ bool ui_comp_should_draw(void)
/// TODO(bfredl): later on the compositor should just use win_float_pos events,
/// though that will require slight event order adjustment: emit the win_pos
/// events in the beginning of update_screen(0), rather than in ui_flush()
-bool ui_comp_put_grid(ScreenGrid *grid, int row, int col, int height, int width,
- bool valid, bool on_top)
+bool ui_comp_put_grid(ScreenGrid *grid, int row, int col, int height, int width, bool valid,
+ bool on_top)
{
bool moved;
@@ -257,8 +257,7 @@ static void ui_comp_raise_grid(ScreenGrid *grid, size_t new_index)
}
}
-static void ui_comp_grid_cursor_goto(UI *ui, Integer grid_handle,
- Integer r, Integer c)
+static void ui_comp_grid_cursor_goto(UI *ui, Integer grid_handle, Integer r, Integer c)
{
if (!ui_comp_should_draw() || !ui_comp_set_grid((int)grid_handle)) {
return;
@@ -304,8 +303,7 @@ ScreenGrid *ui_comp_mouse_focus(int row, int col)
/// Baseline implementation. This is always correct, but we can sometimes
/// do something more efficient (where efficiency means smaller deltas to
/// the downstream UI.)
-static void compose_line(Integer row, Integer startcol, Integer endcol,
- LineFlags flags)
+static void compose_line(Integer row, Integer startcol, Integer endcol, LineFlags flags)
{
// If rightleft is set, startcol may be -1. In such cases, the assertions
// will fail because no overlap is found. Adjust startcol to prevent it.
@@ -447,8 +445,8 @@ static void compose_line(Integer row, Integer startcol, Integer endcol,
(const sattr_T *)attrbuf+skipstart);
}
-static void compose_debug(Integer startrow, Integer endrow, Integer startcol,
- Integer endcol, int syn_id, bool delay)
+static void compose_debug(Integer startrow, Integer endrow, Integer startcol, Integer endcol,
+ int syn_id, bool delay)
{
if (!(rdb_flags & RDB_COMPOSITOR)) {
return;
@@ -479,8 +477,7 @@ static void debug_delay(Integer lines)
}
-static void compose_area(Integer startrow, Integer endrow,
- Integer startcol, Integer endcol)
+static void compose_area(Integer startrow, Integer endrow, Integer startcol, Integer endcol)
{
compose_debug(startrow, endrow, startcol, endcol, dbghl_recompose, true);
endrow = MIN(endrow, default_grid.Rows);
@@ -505,11 +502,9 @@ void ui_comp_compose_grid(ScreenGrid *grid)
}
}
-static void ui_comp_raw_line(UI *ui, Integer grid, Integer row,
- Integer startcol, Integer endcol,
- Integer clearcol, Integer clearattr,
- LineFlags flags, const schar_T *chunk,
- const sattr_T *attrs)
+static void ui_comp_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Integer endcol,
+ Integer clearcol, Integer clearattr, LineFlags flags,
+ const schar_T *chunk, const sattr_T *attrs)
{
if (!ui_comp_should_draw() || !ui_comp_set_grid((int)grid)) {
return;
@@ -529,11 +524,11 @@ static void ui_comp_raw_line(UI *ui, Integer grid, Integer row,
// when resizing nvim, a window will be attempted to be drawn on the older
// and possibly larger global screen size.
if (row >= default_grid.Rows) {
- DLOG("compositor: invalid row %"PRId64" on grid %"PRId64, row, grid);
+ DLOG("compositor: invalid row %" PRId64 " on grid %" PRId64, row, grid);
return;
}
if (clearcol > default_grid.Columns) {
- DLOG("compositor: invalid last column %"PRId64" on grid %"PRId64,
+ DLOG("compositor: invalid last column %" PRId64 " on grid %" PRId64,
clearcol, grid);
if (startcol >= default_grid.Columns) {
return;
@@ -572,8 +567,8 @@ void ui_comp_set_screen_valid(bool valid)
}
}
-static void ui_comp_msg_set_pos(UI *ui, Integer grid, Integer row,
- Boolean scrolled, String sep_char)
+static void ui_comp_msg_set_pos(UI *ui, Integer grid, Integer row, Boolean scrolled,
+ String sep_char)
{
msg_grid.comp_row = (int)row;
if (scrolled && row > 0) {
@@ -617,9 +612,8 @@ static bool curgrid_covered_above(int row)
return kv_size(layers)-(above_msg?1:0) > curgrid->comp_index+1;
}
-static void ui_comp_grid_scroll(UI *ui, Integer grid, Integer top,
- Integer bot, Integer left, Integer right,
- Integer rows, Integer cols)
+static void ui_comp_grid_scroll(UI *ui, Integer grid, Integer top, Integer bot, Integer left,
+ Integer right, Integer rows, Integer cols)
{
if (!ui_comp_should_draw() || !ui_comp_set_grid((int)grid)) {
return;
@@ -653,8 +647,7 @@ static void ui_comp_grid_scroll(UI *ui, Integer grid, Integer top,
}
}
-static void ui_comp_grid_resize(UI *ui, Integer grid,
- Integer width, Integer height)
+static void ui_comp_grid_resize(UI *ui, Integer grid, Integer width, Integer height)
{
if (grid == 1) {
ui_composed_call_grid_resize(1, width, height);
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index fb96d7e6ff..500845ec72 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -71,52 +71,51 @@
/* Uncomment the next line for including the u_check() function. This warns
* for errors in the debug information. */
-/* #define U_DEBUG 1 */
-#define UH_MAGIC 0x18dade /* value for uh_magic when in use */
-#define UE_MAGIC 0xabc123 /* value for ue_magic when in use */
+// #define U_DEBUG 1
+#define UH_MAGIC 0x18dade // value for uh_magic when in use
+#define UE_MAGIC 0xabc123 // value for ue_magic when in use
#include <assert.h>
+#include <fcntl.h>
#include <inttypes.h>
#include <limits.h>
#include <stdbool.h>
#include <string.h>
-#include <fcntl.h>
#include "auto/config.h"
-
-#include "nvim/buffer.h"
#include "nvim/ascii.h"
+#include "nvim/buffer.h"
+#include "nvim/buffer_updates.h"
#include "nvim/change.h"
-#include "nvim/undo.h"
#include "nvim/cursor.h"
#include "nvim/edit.h"
+#include "nvim/extmark.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
-#include "nvim/buffer_updates.h"
-#include "nvim/pos.h" // MAXLNUM
+#include "nvim/garray.h"
+#include "nvim/lib/kvec.h"
#include "nvim/mark.h"
-#include "nvim/extmark.h"
#include "nvim/memline.h"
+#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/memory.h"
-#include "nvim/garray.h"
#include "nvim/option.h"
+#include "nvim/os/os.h"
+#include "nvim/os/time.h"
#include "nvim/os_unix.h"
#include "nvim/path.h"
+#include "nvim/pos.h" // MAXLNUM
#include "nvim/sha256.h"
#include "nvim/state.h"
#include "nvim/strings.h"
#include "nvim/types.h"
-#include "nvim/os/os.h"
-#include "nvim/os/time.h"
-#include "nvim/lib/kvec.h"
+#include "nvim/undo.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "undo.c.generated.h"
#endif
-/* used in undo_end() to report number of added and deleted lines */
+// used in undo_end() to report number of added and deleted lines
static long u_newcount, u_oldcount;
/*
@@ -136,13 +135,12 @@ static int seen_b_u_curhead;
static int seen_b_u_newhead;
static int header_count;
-static void u_check_tree(u_header_T *uhp,
- u_header_T *exp_uh_next,
- u_header_T *exp_uh_alt_prev) {
+static void u_check_tree(u_header_T *uhp, u_header_T *exp_uh_next, u_header_T *exp_uh_alt_prev) {
u_entry_T *uep;
- if (uhp == NULL)
+ if (uhp == NULL) {
return;
+ }
++header_count;
if (uhp == curbuf->b_u_curhead && ++seen_b_u_curhead > 1) {
EMSG("b_u_curhead found twice (looping?)");
@@ -153,22 +151,22 @@ static void u_check_tree(u_header_T *uhp,
return;
}
- if (uhp->uh_magic != UH_MAGIC)
+ if (uhp->uh_magic != UH_MAGIC) {
EMSG("uh_magic wrong (may be using freed memory)");
- else {
- /* Check pointers back are correct. */
+ } else {
+ // Check pointers back are correct.
if (uhp->uh_next.ptr != exp_uh_next) {
EMSG("uh_next wrong");
smsg("expected: 0x%x, actual: 0x%x",
- exp_uh_next, uhp->uh_next.ptr);
+ exp_uh_next, uhp->uh_next.ptr);
}
if (uhp->uh_alt_prev.ptr != exp_uh_alt_prev) {
EMSG("uh_alt_prev wrong");
smsg("expected: 0x%x, actual: 0x%x",
- exp_uh_alt_prev, uhp->uh_alt_prev.ptr);
+ exp_uh_alt_prev, uhp->uh_alt_prev.ptr);
}
- /* Check the undo tree at this header. */
+ // Check the undo tree at this header.
for (uep = uhp->uh_entry; uep != NULL; uep = uep->ue_next) {
if (uep->ue_magic != UE_MAGIC) {
EMSG("ue_magic wrong (may be using freed memory)");
@@ -176,10 +174,10 @@ static void u_check_tree(u_header_T *uhp,
}
}
- /* Check the next alt tree. */
+ // Check the next alt tree.
u_check_tree(uhp->uh_alt_next.ptr, uhp->uh_next.ptr, uhp);
- /* Check the next header in this branch. */
+ // Check the next header in this branch.
u_check_tree(uhp->uh_prev.ptr, uhp, NULL);
}
}
@@ -192,14 +190,16 @@ static void u_check(int newhead_may_be_NULL) {
u_check_tree(curbuf->b_u_oldhead, NULL, NULL);
if (seen_b_u_newhead == 0 && curbuf->b_u_oldhead != NULL
- && !(newhead_may_be_NULL && curbuf->b_u_newhead == NULL))
+ && !(newhead_may_be_NULL && curbuf->b_u_newhead == NULL)) {
EMSGN("b_u_newhead invalid: 0x%x", curbuf->b_u_newhead);
- if (curbuf->b_u_curhead != NULL && seen_b_u_curhead == 0)
+ }
+ if (curbuf->b_u_curhead != NULL && seen_b_u_curhead == 0) {
EMSGN("b_u_curhead invalid: 0x%x", curbuf->b_u_curhead);
+ }
if (header_count != curbuf->b_u_numhead) {
EMSG("b_u_numhead invalid");
smsg("expected: %" PRId64 ", actual: %" PRId64,
- (int64_t)header_count, (int64_t)curbuf->b_u_numhead);
+ (int64_t)header_count, (int64_t)curbuf->b_u_numhead);
}
}
@@ -228,11 +228,12 @@ int u_save_cursor(void)
int u_save(linenr_T top, linenr_T bot)
{
if (top >= bot || bot > (curbuf->b_ml.ml_line_count + 1)) {
- return FAIL; /* rely on caller to do error messages */
+ return FAIL; // rely on caller to do error messages
}
- if (top + 2 == bot)
+ if (top + 2 == bot) {
u_saveline((linenr_T)(top + 1));
+ }
return u_savecommon(curbuf, top, bot, (linenr_T)0, false);
}
@@ -268,9 +269,8 @@ int u_inssub(linenr_T lnum)
*/
int u_savedel(linenr_T lnum, long nlines)
{
- return u_savecommon(
- curbuf, lnum - 1, lnum + nlines,
- nlines == curbuf->b_ml.ml_line_count ? 2 : lnum, false);
+ return u_savecommon(curbuf, lnum - 1, lnum + nlines,
+ nlines == curbuf->b_ml.ml_line_count ? 2 : lnum, false);
}
/// Return true when undo is allowed. Otherwise print an error message and
@@ -327,16 +327,14 @@ static inline void zero_fmark_additional_data(fmark_T *fmarks)
* Careful: may trigger autocommands that reload the buffer.
* Returns FAIL when lines could not be saved, OK otherwise.
*/
-int u_savecommon(buf_T *buf,
- linenr_T top, linenr_T bot,
- linenr_T newbot, int reload)
+int u_savecommon(buf_T *buf, linenr_T top, linenr_T bot, linenr_T newbot, int reload)
{
linenr_T lnum;
long i;
- u_header_T *uhp;
- u_header_T *old_curhead;
- u_entry_T *uep;
- u_entry_T *prev_uep;
+ u_header_T *uhp;
+ u_header_T *old_curhead;
+ u_entry_T *uep;
+ u_entry_T *prev_uep;
long size;
if (!reload) {
@@ -381,8 +379,9 @@ int u_savecommon(buf_T *buf,
#ifdef U_DEBUG
uhp->uh_magic = UH_MAGIC;
#endif
- } else
+ } else {
uhp = NULL;
+ }
/*
* If we undid more than we redid, move the entry lists before and
@@ -399,7 +398,7 @@ int u_savecommon(buf_T *buf,
*/
while (buf->b_u_numhead > get_undolevel(buf)
&& buf->b_u_oldhead != NULL) {
- u_header_T *uhfree = buf->b_u_oldhead;
+ u_header_T *uhfree = buf->b_u_oldhead;
if (uhfree == old_curhead) {
// Can't reconnect the branch, delete all of it.
@@ -459,11 +458,12 @@ int u_savecommon(buf_T *buf,
uhp->uh_walk = 0;
uhp->uh_entry = NULL;
uhp->uh_getbot_entry = NULL;
- uhp->uh_cursor = curwin->w_cursor; /* save cursor pos. for undo */
- if (virtual_active() && curwin->w_cursor.coladd > 0)
+ uhp->uh_cursor = curwin->w_cursor; // save cursor pos. for undo
+ if (virtual_active() && curwin->w_cursor.coladd > 0) {
uhp->uh_cursor_vcol = getviscol();
- else
+ } else {
uhp->uh_cursor_vcol = -1;
+ }
// save changed and buffer empty flag for undo
uhp->uh_flags = (buf->b_changed ? UH_CHANGED : 0) +
@@ -499,8 +499,9 @@ int u_savecommon(buf_T *buf,
uep = u_get_headentry(buf);
prev_uep = NULL;
for (i = 0; i < 10; ++i) {
- if (uep == NULL)
+ if (uep == NULL) {
break;
+ }
/* If lines have been inserted/deleted we give up.
* Also when the line was included in a multi-line save. */
@@ -509,14 +510,14 @@ int u_savecommon(buf_T *buf,
!= (uep->ue_bot == 0
? buf->b_ml.ml_line_count + 1
: uep->ue_bot))
- : uep->ue_lcount != buf->b_ml.ml_line_count)
+ : uep->ue_lcount != buf->b_ml.ml_line_count)
|| (uep->ue_size > 1
&& top >= uep->ue_top
&& top + 2 <= uep->ue_top + uep->ue_size + 1)) {
break;
}
- /* If it's the same line we can skip saving it again. */
+ // If it's the same line we can skip saving it again.
if (uep->ue_size == 1 && uep->ue_top == top) {
if (i > 0) {
/* It's not the last entry: get ue_bot for the last
@@ -609,25 +610,25 @@ int u_savecommon(buf_T *buf,
// magic at start of undofile
-# define UF_START_MAGIC "Vim\237UnDo\345"
-# define UF_START_MAGIC_LEN 9
+#define UF_START_MAGIC "Vim\237UnDo\345"
+#define UF_START_MAGIC_LEN 9
// magic at start of header
-# define UF_HEADER_MAGIC 0x5fd0
+#define UF_HEADER_MAGIC 0x5fd0
// magic after last header
-# define UF_HEADER_END_MAGIC 0xe7aa
+#define UF_HEADER_END_MAGIC 0xe7aa
// magic at start of entry
-# define UF_ENTRY_MAGIC 0xf518
+#define UF_ENTRY_MAGIC 0xf518
// magic after last entry
-# define UF_ENTRY_END_MAGIC 0x3581
+#define UF_ENTRY_END_MAGIC 0x3581
// 2-byte undofile version number
-# define UF_VERSION 3
+#define UF_VERSION 3
-/* extra fields for header */
-# define UF_LAST_SAVE_NR 1
+// extra fields for header
+#define UF_LAST_SAVE_NR 1
-/* extra fields for uhp */
-# define UHP_SAVE_NR 1
+// extra fields for uhp
+#define UHP_SAVE_NR 1
static char_u e_not_open[] = N_("E828: Cannot open undo file for writing: %s");
@@ -640,7 +641,7 @@ void u_compute_hash(buf_T *buf, char_u *hash)
{
context_sha256_T ctx;
linenr_T lnum;
- char_u *p;
+ char_u *p;
sha256_start(&ctx);
for (lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) {
@@ -688,7 +689,7 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading)
// Loop over 'undodir'. When reading find the first file that exists.
// When not reading use the first directory that exists or ".".
- dirp = (char *) p_udir;
+ dirp = (char *)p_udir;
while (*dirp != NUL) {
size_t dir_len = copy_option_part((char_u **)&dirp, (char_u *)dir_name,
MAXPATHL, ",");
@@ -698,7 +699,7 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading)
const size_t ffname_len = strlen(ffname);
undo_file_name = xmalloc(ffname_len + 6);
memmove(undo_file_name, ffname, ffname_len + 1);
- char *const tail = (char *) path_tail((char_u *) undo_file_name);
+ char *const tail = (char *)path_tail((char_u *)undo_file_name);
const size_t tail_len = strlen(tail);
memmove(tail + 1, tail, tail_len + 1);
*tail = '.';
@@ -754,8 +755,7 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading)
///
/// @param[in] mesg Identifier of the corruption kind.
/// @param[in] file_name File in which error occurred.
-static void corruption_error(const char *const mesg,
- const char *const file_name)
+static void corruption_error(const char *const mesg, const char *const file_name)
FUNC_ATTR_NONNULL_ALL
{
EMSG3(_("E825: Corrupted undo file (%s): %s"), mesg, file_name);
@@ -763,8 +763,8 @@ static void corruption_error(const char *const mesg,
static void u_free_uhp(u_header_T *uhp)
{
- u_entry_T *nuep;
- u_entry_T *uep;
+ u_entry_T *nuep;
+ u_entry_T *uep;
uep = uhp->uh_entry;
while (uep != NULL) {
@@ -890,8 +890,7 @@ static bool serialize_uhp(bufinfo_T *bi, u_header_T *uhp)
return true;
}
-static u_header_T *unserialize_uhp(bufinfo_T *bi,
- const char *file_name)
+static u_header_T *unserialize_uhp(bufinfo_T *bi, const char *file_name)
{
u_header_T *uhp = xmalloc(sizeof(u_header_T));
memset(uhp, 0, sizeof(u_header_T));
@@ -999,7 +998,7 @@ static bool serialize_extmark(bufinfo_T *bi, ExtmarkUndoObject extup)
undo_write_bytes(bi, (uintmax_t)extup.type, 4);
if (!undo_write(bi, (uint8_t *)&(extup.data.splice),
sizeof(ExtmarkSplice))) {
- return false;
+ return false;
}
} else if (extup.type == kExtmarkMove) {
undo_write_bytes(bi, (uintmax_t)UF_ENTRY_MAGIC, 2);
@@ -1013,8 +1012,7 @@ static bool serialize_extmark(bufinfo_T *bi, ExtmarkUndoObject extup)
return true;
}
-static ExtmarkUndoObject *unserialize_extmark(bufinfo_T *bi, bool *error,
- const char *filename)
+static ExtmarkUndoObject *unserialize_extmark(bufinfo_T *bi, bool *error, const char *filename)
{
UndoObjectType type;
uint8_t *buf = NULL;
@@ -1039,7 +1037,7 @@ static ExtmarkUndoObject *unserialize_extmark(bufinfo_T *bi, bool *error,
}
extup->data.move = *(ExtmarkMove *)buf;
} else {
- goto error;
+ goto error;
}
xfree(buf);
@@ -1080,8 +1078,7 @@ static bool serialize_uep(bufinfo_T *bi, u_entry_T *uep)
return true;
}
-static u_entry_T *unserialize_uep(bufinfo_T * bi, bool *error,
- const char *file_name)
+static u_entry_T *unserialize_uep(bufinfo_T * bi, bool *error, const char *file_name)
{
u_entry_T *uep = xmalloc(sizeof(u_entry_T));
memset(uep, 0, sizeof(u_entry_T));
@@ -1171,24 +1168,23 @@ static void unserialize_visualinfo(bufinfo_T *bi, visualinfo_T *info)
/// @param[in] buf Buffer for which undo file is written.
/// @param[in] hash Hash value of the buffer text. Must have #UNDO_HASH_SIZE
/// size.
-void u_write_undo(const char *const name, const bool forceit, buf_T *const buf,
- char_u *const hash)
+void u_write_undo(const char *const name, const bool forceit, buf_T *const buf, char_u *const hash)
FUNC_ATTR_NONNULL_ARG(3, 4)
{
- u_header_T *uhp;
+ u_header_T *uhp;
char *file_name;
int mark;
#ifdef U_DEBUG
int headers_written = 0;
#endif
int fd;
- FILE *fp = NULL;
+ FILE *fp = NULL;
int perm;
bool write_ok = false;
bufinfo_T bi;
if (name == NULL) {
- file_name = u_get_undo_file_name((char *) buf->b_ffname, false);
+ file_name = u_get_undo_file_name((char *)buf->b_ffname, false);
if (file_name == NULL) {
if (p_verbose > 0) {
verbose_enter();
@@ -1198,7 +1194,7 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf,
return;
}
} else {
- file_name = (char *) name;
+ file_name = (char *)name;
}
/*
@@ -1221,16 +1217,18 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf,
* file, and delete it. */
if (os_path_exists((char_u *)file_name)) {
if (name == NULL || !forceit) {
- /* Check we can read it and it's an undo file. */
+ // Check we can read it and it's an undo file.
fd = os_open(file_name, O_RDONLY, 0);
if (fd < 0) {
if (name != NULL || p_verbose > 0) {
- if (name == NULL)
+ if (name == NULL) {
verbose_enter();
+ }
smsg(_("Will not overwrite with undo file, cannot read: %s"),
file_name);
- if (name == NULL)
+ if (name == NULL) {
verbose_leave();
+ }
}
goto theend;
} else {
@@ -1240,12 +1238,14 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf,
if (len < UF_START_MAGIC_LEN
|| memcmp(mbuf, UF_START_MAGIC, UF_START_MAGIC_LEN) != 0) {
if (name != NULL || p_verbose > 0) {
- if (name == NULL)
+ if (name == NULL) {
verbose_enter();
+ }
smsg(_("Will not overwrite, this is not an undo file: %s"),
file_name);
- if (name == NULL)
+ if (name == NULL) {
verbose_leave();
+ }
}
goto theend;
}
@@ -1276,7 +1276,7 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf,
}
#ifdef U_DEBUG
- /* Check there is no problem in undo info before writing. */
+ // Check there is no problem in undo info before writing.
u_check(FALSE);
#endif
@@ -1323,7 +1323,7 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf,
mark = ++lastmark;
uhp = buf->b_u_oldhead;
while (uhp != NULL) {
- /* Serialize current UHP if we haven't seen it */
+ // Serialize current UHP if we haven't seen it
if (uhp->uh_walk != mark) {
uhp->uh_walk = mark;
#ifdef U_DEBUG
@@ -1334,19 +1334,20 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf,
}
}
- /* Now walk through the tree - algorithm from undo_time(). */
- if (uhp->uh_prev.ptr != NULL && uhp->uh_prev.ptr->uh_walk != mark)
+ // Now walk through the tree - algorithm from undo_time().
+ if (uhp->uh_prev.ptr != NULL && uhp->uh_prev.ptr->uh_walk != mark) {
uhp = uhp->uh_prev.ptr;
- else if (uhp->uh_alt_next.ptr != NULL
- && uhp->uh_alt_next.ptr->uh_walk != mark)
+ } else if (uhp->uh_alt_next.ptr != NULL
+ && uhp->uh_alt_next.ptr->uh_walk != mark) {
uhp = uhp->uh_alt_next.ptr;
- else if (uhp->uh_next.ptr != NULL && uhp->uh_alt_prev.ptr == NULL
- && uhp->uh_next.ptr->uh_walk != mark)
+ } else if (uhp->uh_next.ptr != NULL && uhp->uh_alt_prev.ptr == NULL
+ && uhp->uh_next.ptr->uh_walk != mark) {
uhp = uhp->uh_next.ptr;
- else if (uhp->uh_alt_prev.ptr != NULL)
+ } else if (uhp->uh_alt_prev.ptr != NULL) {
uhp = uhp->uh_alt_prev.ptr;
- else
+ } else {
uhp = uhp->uh_next.ptr;
+ }
}
if (undo_write_bytes(&bi, (uintmax_t)UF_HEADER_END_MAGIC, 2)) {
@@ -1361,14 +1362,15 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf,
write_error:
fclose(fp);
- if (!write_ok)
+ if (!write_ok) {
EMSG2(_("E829: write error in undo file: %s"), file_name);
+ }
#ifdef HAVE_ACL
if (buf->b_ffname != NULL) {
vim_acl_T acl;
- /* For systems that support ACL: get the ACL from the original file. */
+ // For systems that support ACL: get the ACL from the original file.
acl = mch_get_acl(buf->b_ffname);
mch_set_acl((char_u *)file_name, acl);
mch_free_acl(acl);
@@ -1376,8 +1378,9 @@ write_error:
#endif
theend:
- if (file_name != name)
+ if (file_name != name) {
xfree(file_name);
+ }
}
/// Loads the undo tree from an undo file.
@@ -1385,8 +1388,7 @@ theend:
/// a bit more verbose.
/// Otherwise use curbuf->b_ffname to generate the undo file name.
/// "hash[UNDO_HASH_SIZE]" must be the hash value of the buffer text.
-void u_read_undo(char *name, const char_u *hash,
- const char_u *orig_name FUNC_ATTR_UNUSED)
+void u_read_undo(char *name, const char_u *hash, const char_u *orig_name FUNC_ATTR_UNUSED)
FUNC_ATTR_NONNULL_ARG(2)
{
u_header_T **uhp_table = NULL;
@@ -1394,7 +1396,7 @@ void u_read_undo(char *name, const char_u *hash,
char *file_name;
if (name == NULL) {
- file_name = u_get_undo_file_name((char *) curbuf->b_ffname, true);
+ file_name = u_get_undo_file_name((char *)curbuf->b_ffname, true);
if (file_name == NULL) {
return;
}
@@ -1405,7 +1407,7 @@ void u_read_undo(char *name, const char_u *hash,
FileInfo file_info_orig;
FileInfo file_info_undo;
if (os_fileinfo((const char *)orig_name, &file_info_orig)
- && os_fileinfo((char *)file_name, &file_info_undo)
+ && os_fileinfo(file_name, &file_info_undo)
&& file_info_orig.stat.st_uid != file_info_undo.stat.st_uid
&& file_info_undo.stat.st_uid != getuid()) {
if (p_verbose > 0) {
@@ -1418,7 +1420,7 @@ void u_read_undo(char *name, const char_u *hash,
}
#endif
} else {
- file_name = (char *) name;
+ file_name = name;
}
if (p_verbose > 0) {
@@ -1465,7 +1467,7 @@ void u_read_undo(char *name, const char_u *hash,
verbose_enter();
}
give_warning((char_u *)
- _("File contents changed, cannot use undo info"), true);
+ _("File contents changed, cannot use undo info"), true);
if (name == NULL) {
verbose_leave();
}
@@ -1508,15 +1510,15 @@ void u_read_undo(char *name, const char_u *hash,
}
int what = undo_read_byte(&bi);
switch (what) {
- case UF_LAST_SAVE_NR:
- last_save_nr = undo_read_4c(&bi);
- break;
+ case UF_LAST_SAVE_NR:
+ last_save_nr = undo_read_4c(&bi);
+ break;
- default:
- // field not supported, skip
- while (--len >= 0) {
- (void)undo_read_byte(&bi);
- }
+ default:
+ // field not supported, skip
+ while (--len >= 0) {
+ (void)undo_read_byte(&bi);
+ }
}
}
@@ -1559,7 +1561,7 @@ void u_read_undo(char *name, const char_u *hash,
size_t amount = num_head * sizeof(int) + 1;
int *uhp_table_used = xmalloc(amount);
memset(uhp_table_used, 0, amount);
-# define SET_FLAG(j) ++ uhp_table_used[j]
+# define SET_FLAG(j) ++uhp_table_used[j]
#else
# define SET_FLAG(j)
#endif
@@ -1666,10 +1668,11 @@ void u_read_undo(char *name, const char_u *hash,
error:
xfree(line_ptr);
if (uhp_table != NULL) {
- for (long i = 0; i < num_read_uhps; i++)
+ for (long i = 0; i < num_read_uhps; i++) {
if (uhp_table[i] != NULL) {
u_free_uhp(uhp_table[i]);
}
+ }
xfree(uhp_table);
}
@@ -1844,7 +1847,7 @@ bool u_undo_and_forget(int count)
to_forget->uh_alt_next.ptr = NULL;
curbuf->b_u_curhead->uh_alt_prev.ptr = to_forget->uh_alt_prev.ptr;
curbuf->b_u_seq_cur = curbuf->b_u_curhead->uh_next.ptr ?
- curbuf->b_u_curhead->uh_next.ptr->uh_seq : 0;
+ curbuf->b_u_curhead->uh_next.ptr->uh_seq : 0;
} else if (curbuf->b_u_newhead) {
curbuf->b_u_seq_cur = curbuf->b_u_newhead->uh_seq;
}
@@ -1876,8 +1879,9 @@ static void u_doit(int startcount, bool quiet, bool do_buf_event)
u_newcount = 0;
u_oldcount = 0;
- if (curbuf->b_ml.ml_flags & ML_EMPTY)
+ if (curbuf->b_ml.ml_flags & ML_EMPTY) {
u_oldcount = -1;
+ }
while (count--) {
/* Do the change warning now, so that it triggers FileChangedRO when
* needed. This may cause the file to be reloaded, that must happen
@@ -1894,7 +1898,7 @@ static void u_doit(int startcount, bool quiet, bool do_buf_event)
}
// nothing to undo
if (curbuf->b_u_numhead == 0 || curbuf->b_u_curhead == NULL) {
- /* stick curbuf->b_u_curhead at end */
+ // stick curbuf->b_u_curhead at end
curbuf->b_u_curhead = curbuf->b_u_oldhead;
beep_flush();
if (count == startcount - 1) {
@@ -1919,8 +1923,9 @@ static void u_doit(int startcount, bool quiet, bool do_buf_event)
/* Advance for next redo. Set "newhead" when at the end of the
* redoable changes. */
- if (curbuf->b_u_curhead->uh_prev.ptr == NULL)
+ if (curbuf->b_u_curhead->uh_prev.ptr == NULL) {
curbuf->b_u_newhead = curbuf->b_u_curhead;
+ }
curbuf->b_u_curhead = curbuf->b_u_curhead->uh_prev.ptr;
}
}
@@ -1941,8 +1946,8 @@ void undo_time(long step, bool sec, bool file, bool absolute)
long closest_start;
long closest_seq = 0;
long val;
- u_header_T *uhp = NULL;
- u_header_T *last;
+ u_header_T *uhp = NULL;
+ u_header_T *last;
int mark;
int nomark = 0; // shut up compiler
int round;
@@ -1958,8 +1963,9 @@ void undo_time(long step, bool sec, bool file, bool absolute)
u_newcount = 0;
u_oldcount = 0;
- if (curbuf->b_ml.ml_flags & ML_EMPTY)
+ if (curbuf->b_ml.ml_flags & ML_EMPTY) {
u_oldcount = -1;
+ }
/* "target" is the node below which we want to be.
* Init "closest" to a value we can't reach. */
@@ -1975,23 +1981,26 @@ void undo_time(long step, bool sec, bool file, bool absolute)
* the last write, count that as moving one file-write, so
* that ":earlier 1f" undoes all changes since the last save. */
uhp = curbuf->b_u_curhead;
- if (uhp != NULL)
+ if (uhp != NULL) {
uhp = uhp->uh_next.ptr;
- else
+ } else {
uhp = curbuf->b_u_newhead;
- if (uhp != NULL && uhp->uh_save_nr != 0)
+ }
+ if (uhp != NULL && uhp->uh_save_nr != 0) {
/* "uh_save_nr" was set in the last block, that means
* there were no changes since the last write */
target = curbuf->b_u_save_nr_cur + step;
- else
- /* count the changes since the last write as one step */
+ } else {
+ // count the changes since the last write as one step
target = curbuf->b_u_save_nr_cur + step + 1;
- if (target <= 0)
+ }
+ if (target <= 0) {
/* Go to before first write: before the oldest change. Use
* the sequence number for that. */
dofile = false;
+ }
} else {
- /* Moving forward to a newer write. */
+ // Moving forward to a newer write.
target = curbuf->b_u_save_nr_cur + step;
if (target > curbuf->b_u_save_nr_last) {
/* Go to after last write: after the latest change. Use
@@ -2000,11 +2009,13 @@ void undo_time(long step, bool sec, bool file, bool absolute)
dofile = false;
}
}
- } else
+ } else {
target = curbuf->b_u_seq_cur + step;
+ }
if (step < 0) {
- if (target < 0)
+ if (target < 0) {
target = 0;
+ }
closest = -1;
} else {
if (dosec) {
@@ -2044,10 +2055,11 @@ void undo_time(long step, bool sec, bool file, bool absolute)
mark = ++lastmark;
nomark = ++lastmark;
- if (curbuf->b_u_curhead == NULL) /* at leaf of the tree */
+ if (curbuf->b_u_curhead == NULL) { // at leaf of the tree
uhp = curbuf->b_u_newhead;
- else
+ } else {
uhp = curbuf->b_u_curhead;
+ }
while (uhp != NULL) {
uhp->uh_walk = mark;
@@ -2065,17 +2077,17 @@ void undo_time(long step, bool sec, bool file, bool absolute)
* "b_u_seq_cur"). When the timestamp is equal find the
* highest/lowest sequence number. */
if ((step < 0 ? uhp->uh_seq <= curbuf->b_u_seq_cur
- : uhp->uh_seq > curbuf->b_u_seq_cur)
+ : uhp->uh_seq > curbuf->b_u_seq_cur)
&& ((dosec && val == closest)
? (step < 0
? uhp->uh_seq < closest_seq
- : uhp->uh_seq > closest_seq)
- : closest == closest_start
+ : uhp->uh_seq > closest_seq)
+ : closest == closest_start
|| (val > target
? (closest > target
? val - target <= closest - target
: val - target <= target - closest)
- : (closest > target
+ : (closest > target
? target - val <= closest - target
: target - val <= target - closest)))) {
closest = val;
@@ -2090,38 +2102,41 @@ void undo_time(long step, bool sec, bool file, bool absolute)
break;
}
- /* go down in the tree if we haven't been there */
+ // go down in the tree if we haven't been there
if (uhp->uh_prev.ptr != NULL && uhp->uh_prev.ptr->uh_walk != nomark
- && uhp->uh_prev.ptr->uh_walk != mark)
+ && uhp->uh_prev.ptr->uh_walk != mark) {
uhp = uhp->uh_prev.ptr;
-
- /* go to alternate branch if we haven't been there */
+ }
+ // go to alternate branch if we haven't been there
else if (uhp->uh_alt_next.ptr != NULL
&& uhp->uh_alt_next.ptr->uh_walk != nomark
- && uhp->uh_alt_next.ptr->uh_walk != mark)
+ && uhp->uh_alt_next.ptr->uh_walk != mark) {
uhp = uhp->uh_alt_next.ptr;
-
+ }
/* go up in the tree if we haven't been there and we are at the
* start of alternate branches */
else if (uhp->uh_next.ptr != NULL && uhp->uh_alt_prev.ptr == NULL
&& uhp->uh_next.ptr->uh_walk != nomark
&& uhp->uh_next.ptr->uh_walk != mark) {
- /* If still at the start we don't go through this change. */
- if (uhp == curbuf->b_u_curhead)
+ // If still at the start we don't go through this change.
+ if (uhp == curbuf->b_u_curhead) {
uhp->uh_walk = nomark;
+ }
uhp = uhp->uh_next.ptr;
} else {
- /* need to backtrack; mark this node as useless */
+ // need to backtrack; mark this node as useless
uhp->uh_walk = nomark;
- if (uhp->uh_alt_prev.ptr != NULL)
+ if (uhp->uh_alt_prev.ptr != NULL) {
uhp = uhp->uh_alt_prev.ptr;
- else
+ } else {
uhp = uhp->uh_next.ptr;
+ }
}
}
- if (uhp != NULL) /* found it */
+ if (uhp != NULL) { // found it
break;
+ }
if (absolute) {
EMSGN(_("E830: Undo number %" PRId64 " not found"), step);
@@ -2129,10 +2144,11 @@ void undo_time(long step, bool sec, bool file, bool absolute)
}
if (closest == closest_start) {
- if (step < 0)
+ if (step < 0) {
MSG(_("Already at oldest change"));
- else
+ } else {
MSG(_("Already at newest change"));
+ }
return;
}
@@ -2153,10 +2169,11 @@ target_zero:
change_warning(curbuf, 0);
uhp = curbuf->b_u_curhead;
- if (uhp == NULL)
+ if (uhp == NULL) {
uhp = curbuf->b_u_newhead;
- else
+ } else {
uhp = uhp->uh_next.ptr;
+ }
if (uhp == NULL
|| (target > 0 && uhp->uh_walk != mark)
|| (uhp->uh_seq == target && !above)) {
@@ -2264,21 +2281,21 @@ target_zero:
/// @param do_buf_event If `true`, send buffer updates.
static void u_undoredo(int undo, bool do_buf_event)
{
- char_u **newarray = NULL;
+ char_u **newarray = NULL;
linenr_T oldsize;
linenr_T newsize;
linenr_T top, bot;
linenr_T lnum;
linenr_T newlnum = MAXLNUM;
long i;
- u_entry_T *uep, *nuep;
- u_entry_T *newlist = NULL;
+ u_entry_T *uep, *nuep;
+ u_entry_T *newlist = NULL;
int old_flags;
int new_flags;
fmark_T namedm[NMARKS];
visualinfo_T visualinfo;
bool empty_buffer; // buffer became empty
- u_header_T *curhead = curbuf->b_u_curhead;
+ u_header_T *curhead = curbuf->b_u_curhead;
/* Don't want autocommands using the undo structures here, they are
* invalid till the end. */
@@ -2307,8 +2324,9 @@ static void u_undoredo(int undo, bool do_buf_event)
for (uep = curhead->uh_entry; uep != NULL; uep = nuep) {
top = uep->ue_top;
bot = uep->ue_bot;
- if (bot == 0)
+ if (bot == 0) {
bot = curbuf->b_ml.ml_line_count + 1;
+ }
if (top > curbuf->b_ml.ml_line_count || top >= bot
|| bot > curbuf->b_ml.ml_line_count + 1) {
unblock_autocmds();
@@ -2317,8 +2335,8 @@ static void u_undoredo(int undo, bool do_buf_event)
return;
}
- oldsize = bot - top - 1; /* number of lines before undo */
- newsize = uep->ue_size; /* number of lines after undo */
+ oldsize = bot - top - 1; // number of lines before undo
+ newsize = uep->ue_size; // number of lines after undo
if (top < newlnum) {
/* If the saved cursor is somewhere in this undo block, move it to
@@ -2332,13 +2350,15 @@ static void u_undoredo(int undo, bool do_buf_event)
/* Use the first line that actually changed. Avoids that
* undoing auto-formatting puts the cursor in the previous
* line. */
- for (i = 0; i < newsize && i < oldsize; ++i)
- if (STRCMP(uep->ue_array[i], ml_get(top + 1 + i)) != 0)
+ for (i = 0; i < newsize && i < oldsize; ++i) {
+ if (STRCMP(uep->ue_array[i], ml_get(top + 1 + i)) != 0) {
break;
+ }
+ }
if (i == newsize && newlnum == MAXLNUM && uep->ue_next == NULL) {
newlnum = top;
curwin->w_cursor.lnum = newlnum + 1;
- } else if (i < newsize) {
+ } else if (i < newsize) {
newlnum = top + i;
curwin->w_cursor.lnum = newlnum + 1;
}
@@ -2347,12 +2367,12 @@ static void u_undoredo(int undo, bool do_buf_event)
empty_buffer = false;
- /* delete the lines between top and bot and save them in newarray */
+ // delete the lines between top and bot and save them in newarray
if (oldsize > 0) {
newarray = xmalloc(sizeof(char_u *) * (size_t)oldsize);
- /* delete backwards, it goes faster in most cases */
+ // delete backwards, it goes faster in most cases
for (lnum = bot - 1, i = oldsize; --i >= 0; --lnum) {
- /* what can we do when we run out of memory? */
+ // what can we do when we run out of memory?
newarray[i] = u_save_line(lnum);
/* remember we deleted the last line in the buffer, and a
* dummy empty line will be inserted */
@@ -2361,10 +2381,11 @@ static void u_undoredo(int undo, bool do_buf_event)
}
ml_delete(lnum, false);
}
- } else
+ } else {
newarray = NULL;
+ }
- /* insert the lines in u_array between top and bot */
+ // insert the lines in u_array between top and bot
if (newsize) {
for (lnum = top, i = 0; i < newsize; ++i, ++lnum) {
/*
@@ -2395,13 +2416,15 @@ static void u_undoredo(int undo, bool do_buf_event)
changed_lines(top + 1, 0, bot, newsize - oldsize, do_buf_event);
- /* set '[ and '] mark */
- if (top + 1 < curbuf->b_op_start.lnum)
+ // set '[ and '] mark
+ if (top + 1 < curbuf->b_op_start.lnum) {
curbuf->b_op_start.lnum = top + 1;
- if (newsize == 0 && top + 1 > curbuf->b_op_end.lnum)
+ }
+ if (newsize == 0 && top + 1 > curbuf->b_op_end.lnum) {
curbuf->b_op_end.lnum = top + 1;
- else if (top + newsize > curbuf->b_op_end.lnum)
+ } else if (top + newsize > curbuf->b_op_end.lnum) {
curbuf->b_op_end.lnum = top + newsize;
+ }
u_newcount += newsize;
u_oldcount += oldsize;
@@ -2424,7 +2447,7 @@ static void u_undoredo(int undo, bool do_buf_event)
undo_info = kv_A(curhead->uh_extmark, i);
extmark_apply_undo(undo_info, undo);
}
- // redo
+ // redo
} else {
for (i = 0; i < (int)kv_size(curhead->uh_extmark); i++) {
undo_info = kv_A(curhead->uh_extmark, i);
@@ -2482,17 +2505,20 @@ static void u_undoredo(int undo, bool do_buf_event)
* Otherwise the cursor should go to the first undone line.
*/
if (curhead->uh_cursor.lnum + 1 == curwin->w_cursor.lnum
- && curwin->w_cursor.lnum > 1)
+ && curwin->w_cursor.lnum > 1) {
--curwin->w_cursor.lnum;
+ }
if (curwin->w_cursor.lnum <= curbuf->b_ml.ml_line_count) {
if (curhead->uh_cursor.lnum == curwin->w_cursor.lnum) {
curwin->w_cursor.col = curhead->uh_cursor.col;
- if (virtual_active() && curhead->uh_cursor_vcol >= 0)
+ if (virtual_active() && curhead->uh_cursor_vcol >= 0) {
coladvance((colnr_T)curhead->uh_cursor_vcol);
- else
+ } else {
curwin->w_cursor.coladd = 0;
- } else
+ }
+ } else {
beginline(BL_SOL | BL_FIX);
+ }
} else {
/* We get here with the current cursor line being past the end (eg
* after adding lines at the end of the file, and then undoing it).
@@ -2502,23 +2528,25 @@ static void u_undoredo(int undo, bool do_buf_event)
curwin->w_cursor.coladd = 0;
}
- /* Make sure the cursor is on an existing line and column. */
+ // Make sure the cursor is on an existing line and column.
check_cursor();
- /* Remember where we are for "g-" and ":earlier 10s". */
+ // Remember where we are for "g-" and ":earlier 10s".
curbuf->b_u_seq_cur = curhead->uh_seq;
- if (undo)
+ if (undo) {
/* We are below the previous undo. However, to make ":earlier 1s"
* work we compute this as being just above the just undone change. */
curbuf->b_u_seq_cur = curhead->uh_next.ptr ?
- curhead->uh_next.ptr->uh_seq : 0;
+ curhead->uh_next.ptr->uh_seq : 0;
+ }
- /* Remember where we are for ":earlier 1f" and ":later 1f". */
+ // Remember where we are for ":earlier 1f" and ":later 1f".
if (curhead->uh_save_nr != 0) {
- if (undo)
+ if (undo) {
curbuf->b_u_save_nr_cur = curhead->uh_save_nr - 1;
- else
+ } else {
curbuf->b_u_save_nr_cur = curhead->uh_save_nr;
+ }
}
/* The timestamp can be the same for multiple changes, just use the one of
@@ -2534,17 +2562,18 @@ static void u_undoredo(int undo, bool do_buf_event)
/// If we deleted or added lines, report the number of less/more lines.
/// Otherwise, report the number of changes (this may be incorrect
/// in some cases, but it's better than nothing).
-static void u_undo_end(
- bool did_undo, ///< just did an undo
- bool absolute, ///< used ":undo N"
- bool quiet)
+///
+/// @param did_undo just did an undo
+/// @param absolute used ":undo N"
+static void u_undo_end(bool did_undo, bool absolute, bool quiet)
{
- char *msgstr;
- u_header_T *uhp;
+ char *msgstr;
+ u_header_T *uhp;
char_u msgbuf[80];
- if ((fdo_flags & FDO_UNDO) && KeyTyped)
+ if ((fdo_flags & FDO_UNDO) && KeyTyped) {
foldOpenCursor();
+ }
if (quiet
|| global_busy // no messages until global is finished
@@ -2552,28 +2581,30 @@ static void u_undo_end(
return;
}
- if (curbuf->b_ml.ml_flags & ML_EMPTY)
+ if (curbuf->b_ml.ml_flags & ML_EMPTY) {
--u_newcount;
+ }
u_oldcount -= u_newcount;
- if (u_oldcount == -1)
+ if (u_oldcount == -1) {
msgstr = N_("more line");
- else if (u_oldcount < 0)
+ } else if (u_oldcount < 0) {
msgstr = N_("more lines");
- else if (u_oldcount == 1)
+ } else if (u_oldcount == 1) {
msgstr = N_("line less");
- else if (u_oldcount > 1)
+ } else if (u_oldcount > 1) {
msgstr = N_("fewer lines");
- else {
+ } else {
u_oldcount = u_newcount;
- if (u_newcount == 1)
+ if (u_newcount == 1) {
msgstr = N_("change");
- else
+ } else {
msgstr = N_("changes");
+ }
}
if (curbuf->b_u_curhead != NULL) {
- /* For ":undo N" we prefer a "after #N" message. */
+ // For ":undo N" we prefer a "after #N" message.
if (absolute && curbuf->b_u_curhead->uh_next.ptr != NULL) {
uhp = curbuf->b_u_curhead->uh_next.ptr;
did_undo = false;
@@ -2600,14 +2631,13 @@ static void u_undo_end(
}
}
- smsg_attr_keep(
- 0,
- _("%" PRId64 " %s; %s #%" PRId64 " %s"),
- u_oldcount < 0 ? (int64_t)-u_oldcount : (int64_t)u_oldcount,
- _(msgstr),
- did_undo ? _("before") : _("after"),
- uhp == NULL ? (int64_t)0L : (int64_t)uhp->uh_seq,
- msgbuf);
+ smsg_attr_keep(0,
+ _("%" PRId64 " %s; %s #%" PRId64 " %s"),
+ u_oldcount < 0 ? (int64_t)-u_oldcount : (int64_t)u_oldcount,
+ _(msgstr),
+ did_undo ? _("before") : _("after"),
+ uhp == NULL ? (int64_t)0L : (int64_t)uhp->uh_seq,
+ msgbuf);
}
/// u_sync: stop adding to the current entry list
@@ -2634,7 +2664,7 @@ void u_sync(bool force)
void ex_undolist(exarg_T *eap)
{
garray_T ga;
- u_header_T *uhp;
+ u_header_T *uhp;
int mark;
int nomark;
int changes = 1;
@@ -2657,28 +2687,29 @@ void ex_undolist(exarg_T *eap)
add_time(IObuff + STRLEN(IObuff), IOSIZE - STRLEN(IObuff),
uhp->uh_time);
if (uhp->uh_save_nr > 0) {
- while (STRLEN(IObuff) < 33)
+ while (STRLEN(IObuff) < 33) {
STRCAT(IObuff, " ");
+ }
vim_snprintf_add((char *)IObuff, IOSIZE,
- " %3ld", uhp->uh_save_nr);
+ " %3ld", uhp->uh_save_nr);
}
GA_APPEND(char_u *, &ga, vim_strsave(IObuff));
}
uhp->uh_walk = mark;
- /* go down in the tree if we haven't been there */
+ // go down in the tree if we haven't been there
if (uhp->uh_prev.ptr != NULL && uhp->uh_prev.ptr->uh_walk != nomark
&& uhp->uh_prev.ptr->uh_walk != mark) {
uhp = uhp->uh_prev.ptr;
++changes;
}
- /* go to alternate branch if we haven't been there */
+ // go to alternate branch if we haven't been there
else if (uhp->uh_alt_next.ptr != NULL
&& uhp->uh_alt_next.ptr->uh_walk != nomark
- && uhp->uh_alt_next.ptr->uh_walk != mark)
+ && uhp->uh_alt_next.ptr->uh_walk != mark) {
uhp = uhp->uh_alt_next.ptr;
-
+ }
/* go up in the tree if we haven't been there and we are at the
* start of alternate branches */
else if (uhp->uh_next.ptr != NULL && uhp->uh_alt_prev.ptr == NULL
@@ -2687,20 +2718,20 @@ void ex_undolist(exarg_T *eap)
uhp = uhp->uh_next.ptr;
--changes;
} else {
- /* need to backtrack; mark this node as done */
+ // need to backtrack; mark this node as done
uhp->uh_walk = nomark;
- if (uhp->uh_alt_prev.ptr != NULL)
+ if (uhp->uh_alt_prev.ptr != NULL) {
uhp = uhp->uh_alt_prev.ptr;
- else {
+ } else {
uhp = uhp->uh_next.ptr;
--changes;
}
}
}
- if (GA_EMPTY(&ga))
+ if (GA_EMPTY(&ga)) {
MSG(_("Nothing to undo"));
- else {
+ } else {
sort_strings((char_u **)ga.ga_data, ga.ga_len);
msg_start();
@@ -2757,17 +2788,18 @@ void u_unchanged(buf_T *buf)
*/
void u_find_first_changed(void)
{
- u_header_T *uhp = curbuf->b_u_newhead;
- u_entry_T *uep;
+ u_header_T *uhp = curbuf->b_u_newhead;
+ u_entry_T *uep;
linenr_T lnum;
- if (curbuf->b_u_curhead != NULL || uhp == NULL)
- return; /* undid something in an autocmd? */
-
- /* Check that the last undo block was for the whole file. */
+ if (curbuf->b_u_curhead != NULL || uhp == NULL) {
+ return; // undid something in an autocmd?
+ }
+ // Check that the last undo block was for the whole file.
uep = uhp->uh_entry;
- if (uep->ue_top != 0 || uep->ue_bot != 0)
+ if (uep->ue_top != 0 || uep->ue_bot != 0) {
return;
+ }
for (lnum = 1; lnum < curbuf->b_ml.ml_line_count
&& lnum <= uep->ue_size; lnum++) {
@@ -2778,7 +2810,7 @@ void u_find_first_changed(void)
}
}
if (curbuf->b_ml.ml_line_count != uep->ue_size) {
- /* lines added or deleted at the end, put the cursor there */
+ // lines added or deleted at the end, put the cursor there
clearpos(&(uhp->uh_cursor));
uhp->uh_cursor.lnum = lnum;
}
@@ -2790,27 +2822,30 @@ void u_find_first_changed(void)
*/
void u_update_save_nr(buf_T *buf)
{
- u_header_T *uhp;
+ u_header_T *uhp;
++buf->b_u_save_nr_last;
buf->b_u_save_nr_cur = buf->b_u_save_nr_last;
uhp = buf->b_u_curhead;
- if (uhp != NULL)
+ if (uhp != NULL) {
uhp = uhp->uh_next.ptr;
- else
+ } else {
uhp = buf->b_u_newhead;
- if (uhp != NULL)
+ }
+ if (uhp != NULL) {
uhp->uh_save_nr = buf->b_u_save_nr_last;
+ }
}
static void u_unch_branch(u_header_T *uhp)
{
- u_header_T *uh;
+ u_header_T *uh;
for (uh = uhp; uh != NULL; uh = uh->uh_prev.ptr) {
uh->uh_flags |= UH_CHANGED;
- if (uh->uh_alt_next.ptr != NULL)
- u_unch_branch(uh->uh_alt_next.ptr); /* recursive */
+ if (uh->uh_alt_next.ptr != NULL) {
+ u_unch_branch(uh->uh_alt_next.ptr); // recursive
+ }
}
}
@@ -2829,11 +2864,11 @@ static u_entry_T *u_get_headentry(buf_T *buf)
/*
* u_getbot(): compute the line number of the previous u_save
- * It is called only when b_u_synced is false.
+ * It is called only when b_u_synced is false.
*/
static void u_getbot(buf_T *buf)
{
- u_entry_T *uep;
+ u_entry_T *uep;
linenr_T extra;
uep = u_get_headentry(buf); // check for corrupt undo list
@@ -2864,95 +2899,91 @@ static void u_getbot(buf_T *buf)
buf->b_u_synced = true;
}
-/*
- * Free one header "uhp" and its entry list and adjust the pointers.
- */
-static void
-u_freeheader(
- buf_T *buf,
- u_header_T *uhp,
- u_header_T **uhpp // if not NULL reset when freeing this header
-)
+/// Free one header "uhp" and its entry list and adjust the pointers.
+///
+/// @param uhpp if not NULL reset when freeing this header
+static void u_freeheader(buf_T *buf, u_header_T *uhp, u_header_T **uhpp)
{
- u_header_T *uhap;
+ u_header_T *uhap;
/* When there is an alternate redo list free that branch completely,
* because we can never go there. */
- if (uhp->uh_alt_next.ptr != NULL)
+ if (uhp->uh_alt_next.ptr != NULL) {
u_freebranch(buf, uhp->uh_alt_next.ptr, uhpp);
+ }
- if (uhp->uh_alt_prev.ptr != NULL)
+ if (uhp->uh_alt_prev.ptr != NULL) {
uhp->uh_alt_prev.ptr->uh_alt_next.ptr = NULL;
+ }
- /* Update the links in the list to remove the header. */
- if (uhp->uh_next.ptr == NULL)
+ // Update the links in the list to remove the header.
+ if (uhp->uh_next.ptr == NULL) {
buf->b_u_oldhead = uhp->uh_prev.ptr;
- else
+ } else {
uhp->uh_next.ptr->uh_prev.ptr = uhp->uh_prev.ptr;
+ }
- if (uhp->uh_prev.ptr == NULL)
+ if (uhp->uh_prev.ptr == NULL) {
buf->b_u_newhead = uhp->uh_next.ptr;
- else
+ } else {
for (uhap = uhp->uh_prev.ptr; uhap != NULL;
- uhap = uhap->uh_alt_next.ptr)
+ uhap = uhap->uh_alt_next.ptr) {
uhap->uh_next.ptr = uhp->uh_next.ptr;
+ }
+ }
u_freeentries(buf, uhp, uhpp);
}
-/*
- * Free an alternate branch and any following alternate branches.
- */
-static void
-u_freebranch(
- buf_T *buf,
- u_header_T *uhp,
- u_header_T **uhpp // if not NULL reset when freeing this header
-)
+/// Free an alternate branch and any following alternate branches.
+///
+/// @param uhpp if not NULL reset when freeing this header
+static void u_freebranch(buf_T *buf, u_header_T *uhp, u_header_T **uhpp)
{
- u_header_T *tofree, *next;
+ u_header_T *tofree, *next;
/* If this is the top branch we may need to use u_freeheader() to update
* all the pointers. */
if (uhp == buf->b_u_oldhead) {
- while (buf->b_u_oldhead != NULL)
+ while (buf->b_u_oldhead != NULL) {
u_freeheader(buf, buf->b_u_oldhead, uhpp);
+ }
return;
}
- if (uhp->uh_alt_prev.ptr != NULL)
+ if (uhp->uh_alt_prev.ptr != NULL) {
uhp->uh_alt_prev.ptr->uh_alt_next.ptr = NULL;
+ }
next = uhp;
while (next != NULL) {
tofree = next;
- if (tofree->uh_alt_next.ptr != NULL)
- u_freebranch(buf, tofree->uh_alt_next.ptr, uhpp); /* recursive */
+ if (tofree->uh_alt_next.ptr != NULL) {
+ u_freebranch(buf, tofree->uh_alt_next.ptr, uhpp); // recursive
+ }
next = tofree->uh_prev.ptr;
u_freeentries(buf, tofree, uhpp);
}
}
-/*
- * Free all the undo entries for one header and the header itself.
- * This means that "uhp" is invalid when returning.
- */
-static void
-u_freeentries(
- buf_T *buf,
- u_header_T *uhp,
- u_header_T **uhpp // if not NULL reset when freeing this header
-)
+/// Free all the undo entries for one header and the header itself.
+/// This means that "uhp" is invalid when returning.
+///
+/// @param uhpp if not NULL reset when freeing this header
+static void u_freeentries(buf_T *buf, u_header_T *uhp, u_header_T **uhpp)
{
- u_entry_T *uep, *nuep;
+ u_entry_T *uep, *nuep;
- /* Check for pointers to the header that become invalid now. */
- if (buf->b_u_curhead == uhp)
+ // Check for pointers to the header that become invalid now.
+ if (buf->b_u_curhead == uhp) {
buf->b_u_curhead = NULL;
- if (buf->b_u_newhead == uhp)
- buf->b_u_newhead = NULL; /* freeing the newest entry */
- if (uhpp != NULL && uhp == *uhpp)
+ }
+ if (buf->b_u_newhead == uhp) {
+ buf->b_u_newhead = NULL; // freeing the newest entry
+ }
+ if (uhpp != NULL && uhp == *uhpp) {
*uhpp = NULL;
+ }
for (uep = uhp->uh_entry; uep != NULL; uep = nuep) {
nuep = uep->ue_next;
@@ -2973,8 +3004,9 @@ u_freeentries(
*/
static void u_freeentry(u_entry_T *uep, long n)
{
- while (n > 0)
+ while (n > 0) {
xfree(uep->ue_array[--n]);
+ }
xfree((char_u *)uep->ue_array);
#ifdef U_DEBUG
uep->ue_magic = 0;
@@ -2999,16 +3031,19 @@ void u_clearall(buf_T *buf)
*/
void u_saveline(linenr_T lnum)
{
- if (lnum == curbuf->b_u_line_lnum) /* line is already saved */
+ if (lnum == curbuf->b_u_line_lnum) { // line is already saved
return;
- if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) /* should never happen */
+ }
+ if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) { // should never happen
return;
+ }
u_clearline();
curbuf->b_u_line_lnum = lnum;
- if (curwin->w_cursor.lnum == lnum)
+ if (curwin->w_cursor.lnum == lnum) {
curbuf->b_u_line_colnr = curwin->w_cursor.col;
- else
+ } else {
curbuf->b_u_line_colnr = 0;
+ }
curbuf->b_u_line_ptr = u_save_line(lnum);
}
@@ -3033,7 +3068,7 @@ void u_clearline(void)
void u_undoline(void)
{
colnr_T t;
- char_u *oldp;
+ char_u *oldp;
if (curbuf->b_u_line_ptr == NULL
|| curbuf->b_u_line_lnum > curbuf->b_ml.ml_line_count) {
@@ -3050,12 +3085,15 @@ void u_undoline(void)
oldp = u_save_line(curbuf->b_u_line_lnum);
ml_replace(curbuf->b_u_line_lnum, curbuf->b_u_line_ptr, true);
changed_bytes(curbuf->b_u_line_lnum, 0);
+ extmark_splice_cols(curbuf, (int)curbuf->b_u_line_lnum-1, 0, (colnr_T)STRLEN(oldp),
+ (colnr_T)STRLEN(curbuf->b_u_line_ptr), kExtmarkUndo);
xfree(curbuf->b_u_line_ptr);
curbuf->b_u_line_ptr = oldp;
t = curbuf->b_u_line_colnr;
- if (curwin->w_cursor.lnum == curbuf->b_u_line_lnum)
+ if (curwin->w_cursor.lnum == curbuf->b_u_line_lnum) {
curbuf->b_u_line_colnr = curwin->w_cursor.col;
+ }
curwin->w_cursor.col = t;
curwin->w_cursor.lnum = curbuf->b_u_line_lnum;
check_cursor_col();
@@ -3106,8 +3144,8 @@ bool bufIsChanged(buf_T *buf)
{
// In a "prompt" buffer we do respect 'modified', so that we can control
// closing the window by setting or resetting that option.
- return (!bt_dontwrite(buf) || bt_prompt(buf))
- && (buf->b_changed || file_ff_differs(buf, true));
+ return (!bt_dontwrite(buf) || bt_prompt(buf))
+ && (buf->b_changed || file_ff_differs(buf, true));
}
// Return true if any buffer has changes. Also buffers that are not written.
diff --git a/src/nvim/version.c b/src/nvim/version.c
index 7c197f1b7f..bc06ef0b98 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -6,32 +6,32 @@
/// Nvim was forked from Vim 7.4.160.
/// Vim originated from Stevie version 3.6 (Fish disk 217) by GRWalter (Fred).
-#include <inttypes.h>
#include <assert.h>
+#include <inttypes.h>
#include <limits.h>
#include "nvim/api/private/helpers.h"
-#include "nvim/vim.h"
#include "nvim/ascii.h"
#include "nvim/buffer.h"
-#include "nvim/iconv.h"
-#include "nvim/version.h"
#include "nvim/charset.h"
+#include "nvim/iconv.h"
+#include "nvim/lua/executor.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/screen.h"
#include "nvim/strings.h"
-#include "nvim/lua/executor.h"
+#include "nvim/version.h"
+#include "nvim/vim.h"
// version info generated by the build system
#include "auto/versiondef.h"
// for ":version", ":intro", and "nvim --version"
#ifndef NVIM_VERSION_MEDIUM
-#define NVIM_VERSION_MEDIUM "v" STR(NVIM_VERSION_MAJOR)\
-"." STR(NVIM_VERSION_MINOR) "." STR(NVIM_VERSION_PATCH)\
-NVIM_VERSION_PRERELEASE
+# define NVIM_VERSION_MEDIUM "v" STR(NVIM_VERSION_MAJOR)\
+ "." STR(NVIM_VERSION_MINOR) "." STR(NVIM_VERSION_PATCH)\
+ NVIM_VERSION_PRERELEASE
#endif
#define NVIM_VERSION_LONG "NVIM " NVIM_VERSION_MEDIUM
@@ -50,23 +50,23 @@ char *version_cflags = "Compilation: " NVIM_VERSION_CFLAGS;
static char *features[] = {
#ifdef HAVE_ACL
-"+acl",
+ "+acl",
#else
-"-acl",
+ "-acl",
#endif
#if defined(HAVE_ICONV)
-"+iconv",
+ "+iconv",
#else
-"-iconv",
+ "-iconv",
#endif
#ifdef FEAT_TUI
-"+tui",
+ "+tui",
#else
-"-tui",
+ "-tui",
#endif
-NULL
+ NULL
};
// clang-format off
@@ -2019,7 +2019,7 @@ void ex_version(exarg_T *eap)
/// @param wrap
static void version_msg_wrap(char_u *s, int wrap)
{
- int len = (int)vim_strsize(s) + (wrap ? 2 : 0);
+ int len = vim_strsize(s) + (wrap ? 2 : 0);
if (!got_int
&& (len < Columns)
@@ -2070,7 +2070,7 @@ void list_in_columns(char_u **items, int size, int current)
// Find the length of the longest item, use that + 1 as the column width.
int i;
for (i = 0; size < 0 ? items[i] != NULL : i < size; i++) {
- int l = (int)vim_strsize(items[i]) + (i == current ? 2 : 0);
+ int l = vim_strsize(items[i]) + (i == current ? 2 : 0);
if (l > width) {
width = l;
diff --git a/src/nvim/window.c b/src/nvim/window.c
index c0f537aab3..ff97eaa757 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -853,12 +853,12 @@ void ui_ext_win_position(win_T *wp)
bool east = c.anchor & kFloatAnchorEast;
bool south = c.anchor & kFloatAnchorSouth;
- int comp_row = (int)row - (south ? wp->w_height : 0);
- int comp_col = (int)col - (east ? wp->w_width : 0);
+ int comp_row = (int)row - (south ? wp->w_height_outer : 0);
+ int comp_col = (int)col - (east ? wp->w_width_outer : 0);
comp_row += grid->comp_row;
comp_col += grid->comp_col;
- comp_row = MAX(MIN(comp_row, Rows-wp->w_height_outer-1), 0);
- comp_col = MAX(MIN(comp_col, Columns-wp->w_width_outer), 0);
+ comp_row = MAX(MIN(comp_row, Rows - wp->w_height_outer - 1), 0);
+ comp_col = MAX(MIN(comp_col, Columns - wp->w_width_outer), 0);
wp->w_winrow = comp_row;
wp->w_wincol = comp_col;
bool valid = (wp->w_redr_type == 0);
diff --git a/src/uncrustify.cfg b/src/uncrustify.cfg
index 5d73e70ed0..db0c50ff22 100644
--- a/src/uncrustify.cfg
+++ b/src/uncrustify.cfg
@@ -1,4 +1,4 @@
-# Uncrustify-0.73.0-186-03faf73c
+# Uncrustify-0.73.0-195-1f883c691
#
# General options
@@ -535,14 +535,21 @@ sp_inside_braces_struct = ignore # ignore/add/remove/force/not_defined
sp_inside_braces_oc_dict = ignore # ignore/add/remove/force/not_defined
# Add or remove space after open brace in an unnamed temporary
-# direct-list-initialization.
+# direct-list-initialization
+# if statement is a brace_init_lst
+# works only if sp_brace_brace is set to ignore.
sp_after_type_brace_init_lst_open = ignore # ignore/add/remove/force/not_defined
# Add or remove space before close brace in an unnamed temporary
-# direct-list-initialization.
+# direct-list-initialization
+# if statement is a brace_init_lst
+# works only if sp_brace_brace is set to ignore.
sp_before_type_brace_init_lst_close = ignore # ignore/add/remove/force/not_defined
-# Add or remove space inside an unnamed temporary direct-list-initialization.
+# Add or remove space inside an unnamed temporary direct-list-initialization
+# if statement is a brace_init_lst
+# works only if sp_brace_brace is set to ignore
+# works only if sp_before_type_brace_init_lst_close is set to ignore.
sp_inside_type_brace_init_lst = ignore # ignore/add/remove/force/not_defined
# Add or remove space inside '{' and '}'.
diff --git a/src/xdiff/xdiffi.c b/src/xdiff/xdiffi.c
index f35ac5d0b0..cfcbb5d982 100644
--- a/src/xdiff/xdiffi.c
+++ b/src/xdiff/xdiffi.c
@@ -1,6 +1,3 @@
-// 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
-
/*
* LibXDiff by Davide Libenzi ( File Differential Library )
* Copyright (C) 2003 Davide Libenzi
diff --git a/src/xdiff/xemit.c b/src/xdiff/xemit.c
index 23c6e2d993..b578e7a9d5 100644
--- a/src/xdiff/xemit.c
+++ b/src/xdiff/xemit.c
@@ -1,6 +1,3 @@
-// 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
-
/*
* LibXDiff by Davide Libenzi ( File Differential Library )
* Copyright (C) 2003 Davide Libenzi
diff --git a/src/xdiff/xhistogram.c b/src/xdiff/xhistogram.c
index 3c84f35626..8598a8550d 100644
--- a/src/xdiff/xhistogram.c
+++ b/src/xdiff/xhistogram.c
@@ -1,6 +1,3 @@
-// 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
-
/*
* Copyright (C) 2010, Google Inc.
* and other copyright owners as documented in JGit's IP log.
diff --git a/src/xdiff/xpatience.c b/src/xdiff/xpatience.c
index 5f547ca5c0..f78c897ad8 100644
--- a/src/xdiff/xpatience.c
+++ b/src/xdiff/xpatience.c
@@ -1,6 +1,3 @@
-// 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
-
/*
* LibXDiff by Davide Libenzi ( File Differential Library )
* Copyright (C) 2003-2016 Davide Libenzi, Johannes E. Schindelin
diff --git a/src/xdiff/xprepare.c b/src/xdiff/xprepare.c
index f13822e4fa..abeb8fb84e 100644
--- a/src/xdiff/xprepare.c
+++ b/src/xdiff/xprepare.c
@@ -1,6 +1,3 @@
-// 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
-
/*
* LibXDiff by Davide Libenzi ( File Differential Library )
* Copyright (C) 2003 Davide Libenzi
diff --git a/src/xdiff/xutils.c b/src/xdiff/xutils.c
index 65aa50497d..f13a854536 100644
--- a/src/xdiff/xutils.c
+++ b/src/xdiff/xutils.c
@@ -1,6 +1,3 @@
-// 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
-
/*
* LibXDiff by Davide Libenzi ( File Differential Library )
* Copyright (C) 2003 Davide Libenzi
diff --git a/test/config/paths.lua.in b/test/config/paths.lua.in
index 7fe5d8ad80..e3979981ba 100644
--- a/test/config/paths.lua.in
+++ b/test/config/paths.lua.in
@@ -19,5 +19,6 @@ if module.test_luajit_prg == '' then
end
end
table.insert(module.include_paths, "${CMAKE_BINARY_DIR}/include")
+table.insert(module.include_paths, "${CMAKE_BINARY_DIR}/src/nvim/auto")
return module
diff --git a/test/functional/api/buffer_spec.lua b/test/functional/api/buffer_spec.lua
index 81fad206da..01fcfab543 100644
--- a/test/functional/api/buffer_spec.lua
+++ b/test/functional/api/buffer_spec.lua
@@ -707,4 +707,59 @@ describe('api/buf', function()
eq({3, 0}, curbuf('get_mark', 'v'))
end)
end)
+
+ describe('nvim_buf_set_mark', function()
+ it('works with buffer local marks', function()
+ curbufmeths.set_lines(-1, -1, true, {'a', 'bit of', 'text'})
+ eq(true, curbufmeths.set_mark('z', 1, 1))
+ eq({1, 1}, curbufmeths.get_mark('z'))
+ end)
+ it('works with file/uppercase marks', function()
+ curbufmeths.set_lines(-1, -1, true, {'a', 'bit of', 'text'})
+ eq(true, curbufmeths.set_mark('Z', 3, 1))
+ eq({3, 1}, curbufmeths.get_mark('Z'))
+ end)
+ it('fails when invalid marks names are used', function()
+ eq(false, pcall(curbufmeths.set_mark, '!', 1, 0))
+ eq(false, pcall(curbufmeths.set_mark, 'fail', 1, 0))
+ end)
+ it('fails when invalid buffer number is used', function()
+ eq(false, pcall(meths.buf_set_mark, 99, 'a', 1, 1))
+ end)
+ end)
+
+ describe('nvim_buf_del_mark', function()
+ it('works with buffer local marks', function()
+ curbufmeths.set_lines(-1, -1, true, {'a', 'bit of', 'text'})
+ curbufmeths.set_mark('z', 3, 1)
+ eq(true, curbufmeths.del_mark('z'))
+ eq({0, 0}, curbufmeths.get_mark('z'))
+ end)
+ it('works with file/uppercase marks', function()
+ curbufmeths.set_lines(-1, -1, true, {'a', 'bit of', 'text'})
+ curbufmeths.set_mark('Z', 3, 3)
+ eq(true, curbufmeths.del_mark('Z'))
+ eq({0, 0}, curbufmeths.get_mark('Z'))
+ end)
+ it('returns false in marks not set in this buffer', function()
+ local abuf = meths.create_buf(false,true)
+ bufmeths.set_lines(abuf, -1, -1, true, {'a', 'bit of', 'text'})
+ bufmeths.set_mark(abuf, 'A', 2, 2)
+ eq(false, curbufmeths.del_mark('A'))
+ eq({2, 2}, bufmeths.get_mark(abuf, 'A'))
+ end)
+ it('returns false if mark was not deleted', function()
+ curbufmeths.set_lines(-1, -1, true, {'a', 'bit of', 'text'})
+ curbufmeths.set_mark('z', 3, 1)
+ eq(true, curbufmeths.del_mark('z'))
+ eq(false, curbufmeths.del_mark('z')) -- Mark was already deleted
+ end)
+ it('fails when invalid marks names are used', function()
+ eq(false, pcall(curbufmeths.del_mark, '!'))
+ eq(false, pcall(curbufmeths.del_mark, 'fail'))
+ end)
+ it('fails when invalid buffer number is used', function()
+ eq(false, pcall(meths.buf_del_mark, 99, 'a'))
+ end)
+ end)
end)
diff --git a/test/functional/api/command_spec.lua b/test/functional/api/command_spec.lua
index 37331d11c7..6f929ad1ca 100644
--- a/test/functional/api/command_spec.lua
+++ b/test/functional/api/command_spec.lua
@@ -21,7 +21,7 @@ describe('nvim_get_commands', function()
it('validates input', function()
eq('builtin=true not implemented', pcall_err(meths.get_commands,
{builtin=true}))
- eq('unexpected key: foo', pcall_err(meths.get_commands,
+ eq("Invalid key: 'foo'", pcall_err(meths.get_commands,
{foo='blah'}))
end)
diff --git a/test/functional/api/keymap_spec.lua b/test/functional/api/keymap_spec.lua
index 4194945645..dd8eef7ca0 100644
--- a/test/functional/api/keymap_spec.lua
+++ b/test/functional/api/keymap_spec.lua
@@ -436,16 +436,16 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
end)
it('error on invalid optnames', function()
- eq('Invalid key: silentt',
+ eq("Invalid key: 'silentt'",
pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', {silentt = true}))
- eq('Invalid key: sidd',
+ eq("Invalid key: 'sidd'",
pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', {sidd = false}))
- eq('Invalid key: nowaiT',
+ eq("Invalid key: 'nowaiT'",
pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', {nowaiT = false}))
end)
it('error on <buffer> option key', function()
- eq('Invalid key: buffer',
+ eq("Invalid key: 'buffer'",
pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', {buffer = true}))
end)
@@ -454,8 +454,8 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
-- note: need '%' to escape hyphens, which have special meaning in lua
it('throws an error when given non-boolean value for '..opt, function()
local opts = {}
- opts[opt] = 2
- eq('Gave non-boolean value for an opt: '..opt,
+ opts[opt] = 'fooo'
+ eq(opt..' is not a boolean',
pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', opts))
end)
end
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index ffef6a6066..6b644ed519 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -12,10 +12,12 @@ local funcs = helpers.funcs
local iswin = helpers.iswin
local meths = helpers.meths
local matches = helpers.matches
+local mkdir_p = helpers.mkdir_p
local ok, nvim_async, feed = helpers.ok, helpers.nvim_async, helpers.feed
local is_os = helpers.is_os
local parse_context = helpers.parse_context
local request = helpers.request
+local rmdir = helpers.rmdir
local source = helpers.source
local next_msg = helpers.next_msg
local tmpname = helpers.tmpname
@@ -1117,7 +1119,7 @@ describe('API', function()
describe('nvim_get_context', function()
it('validates args', function()
- eq('unexpected key: blah',
+ eq("Invalid key: 'blah'",
pcall_err(nvim, 'get_context', {blah={}}))
eq('invalid value for key: types',
pcall_err(nvim, 'get_context', {types=42}))
@@ -1574,6 +1576,18 @@ describe('API', function()
end)
describe('nvim_list_runtime_paths', function()
+ setup(function()
+ local pathsep = helpers.get_pathsep()
+ mkdir_p('Xtest'..pathsep..'a')
+ mkdir_p('Xtest'..pathsep..'b')
+ end)
+ teardown(function()
+ rmdir 'Xtest'
+ end)
+ before_each(function()
+ meths.set_current_dir 'Xtest'
+ end)
+
it('returns nothing with empty &runtimepath', function()
meths.set_option('runtimepath', '')
eq({}, meths.list_runtime_paths())
@@ -1601,8 +1615,7 @@ describe('API', function()
local long_path = ('/a'):rep(8192)
meths.set_option('runtimepath', long_path)
local paths_list = meths.list_runtime_paths()
- neq({long_path}, paths_list)
- eq({long_path:sub(1, #(paths_list[1]))}, paths_list)
+ eq({}, paths_list)
end)
end)
@@ -2254,4 +2267,59 @@ describe('API', function()
]]}
end)
end)
+
+ describe('nvim_del_mark', function()
+ it('works', function()
+ local buf = meths.create_buf(false,true)
+ meths.buf_set_lines(buf, -1, -1, true, {'a', 'bit of', 'text'})
+ eq(true, meths.buf_set_mark(buf, 'F', 2, 2))
+ eq(true, meths.del_mark('F'))
+ eq({0, 0}, meths.buf_get_mark(buf, 'F'))
+ end)
+ it('fails when invalid marks are used', function()
+ eq(false, pcall(meths.del_mark, 'f'))
+ eq(false, pcall(meths.del_mark, '!'))
+ eq(false, pcall(meths.del_mark, 'fail'))
+ end)
+ end)
+ describe('nvim_get_mark', function()
+ it('works', function()
+ local buf = meths.create_buf(false,true)
+ meths.buf_set_lines(buf, -1, -1, true, {'a', 'bit of', 'text'})
+ meths.buf_set_mark(buf, 'F', 2, 2)
+ meths.buf_set_name(buf, "mybuf")
+ local mark = meths.get_mark('F')
+ -- Compare the path tail ony
+ assert(string.find(mark[4], "mybuf$"))
+ eq({2, 2, buf.id, mark[4]}, mark)
+ end)
+ it('fails when invalid marks are used', function()
+ eq(false, pcall(meths.del_mark, 'f'))
+ eq(false, pcall(meths.del_mark, '!'))
+ eq(false, pcall(meths.del_mark, 'fail'))
+ end)
+ it('returns the expected when mark is not set', function()
+ eq(true, meths.del_mark('A'))
+ eq({0, 0, 0, ''}, meths.get_mark('A'))
+ end)
+ it('works with deleted buffers', function()
+ local fname = tmpname()
+ write_file(fname, 'a\nbit of\text')
+ nvim("command", "edit " .. fname)
+ local buf = meths.get_current_buf()
+
+ meths.buf_set_mark(buf, 'F', 2, 2)
+ nvim("command", "new") -- Create new buf to avoid :bd failing
+ nvim("command", "bd! " .. buf.id)
+ os.remove(fname)
+
+ local mark = meths.get_mark('F')
+ -- To avoid comparing relative vs absolute path
+ local mfname = mark[4]
+ local tail_patt = [[[\/][^\/]*$]]
+ -- tail of paths should be equals
+ eq(fname:match(tail_patt), mfname:match(tail_patt))
+ eq({2, 2, buf.id, mark[4]}, mark)
+ end)
+ end)
end)
diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua
index 1d83eb799f..bf2559f8d7 100644
--- a/test/functional/core/startup_spec.lua
+++ b/test/functional/core/startup_spec.lua
@@ -20,6 +20,7 @@ local retry = helpers.retry
local rmdir = helpers.rmdir
local sleep = helpers.sleep
local iswin = helpers.iswin
+local startswith = helpers.startswith
local write_file = helpers.write_file
local meths = helpers.meths
@@ -355,11 +356,50 @@ describe('startup', function()
eq({'ordinary', 'FANCY', 'mittel', 'FANCY after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]])
end)
+ it("handles the correct order with start packages and after/ after startup", function()
+ pack_clear [[ lua _G.test_loadorder = {} ]]
+ command [[ runtime! filen.lua ]]
+ eq({'ordinary', 'FANCY', 'mittel', 'FANCY after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]])
+ end)
+
+ it("handles the correct order with globpath(&rtp, ...)", function()
+ pack_clear [[ set loadplugins | lua _G.test_loadorder = {} ]]
+ command [[
+ for x in globpath(&rtp, "filen.lua",1,1)
+ call v:lua.dofile(x)
+ endfor
+ ]]
+ eq({'ordinary', 'FANCY', 'mittel', 'FANCY after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]])
+
+ local rtp = meths.get_option'rtp'
+ ok(startswith(rtp, 'test/functional/fixtures/nvim,test/functional/fixtures/pack/*/start/*,test/functional/fixtures/start/*,test/functional/fixtures,test/functional/fixtures/middle,'), 'rtp='..rtp)
+ end)
+
it("handles the correct order with opt packages and after/", function()
pack_clear [[ lua _G.test_loadorder = {} vim.cmd "packadd! superspecial\nruntime! filen.lua" ]]
eq({'ordinary', 'SuperSpecial', 'FANCY', 'mittel', 'FANCY after', 'SuperSpecial after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]])
end)
+ it("handles the correct order with opt packages and after/ after startup", function()
+ pack_clear [[ lua _G.test_loadorder = {} ]]
+ command [[
+ packadd! superspecial
+ runtime! filen.lua
+ ]]
+ eq({'ordinary', 'SuperSpecial', 'FANCY', 'mittel', 'FANCY after', 'SuperSpecial after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]])
+ end)
+
+ it("handles the correct order with opt packages and globpath(&rtp, ...)", function()
+ pack_clear [[ set loadplugins | lua _G.test_loadorder = {} ]]
+ command [[
+ packadd! superspecial
+ for x in globpath(&rtp, "filen.lua",1,1)
+ call v:lua.dofile(x)
+ endfor
+ ]]
+ eq({'ordinary', 'SuperSpecial', 'FANCY', 'mittel', 'SuperSpecial after', 'FANCY after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]])
+ end)
+
it("handles the correct order with a package that changes packpath", function()
pack_clear [[ lua _G.test_loadorder = {} vim.cmd "packadd! funky\nruntime! filen.lua" ]]
eq({'ordinary', 'funky!', 'FANCY', 'mittel', 'FANCY after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]])
diff --git a/test/functional/editor/meta_key_spec.lua b/test/functional/editor/meta_key_spec.lua
index 2a9541ba96..c219204409 100644
--- a/test/functional/editor/meta_key_spec.lua
+++ b/test/functional/editor/meta_key_spec.lua
@@ -11,15 +11,20 @@ describe('meta-keys #8226 #13042', function()
end)
it('ALT/META, normal-mode', function()
- -- Unmapped ALT-chords behave as ESC+c
+ -- Unmapped ALT-chord behaves as ESC+c.
insert('hello')
feed('0<A-x><M-x>')
expect('llo')
+ -- Unmapped ALT-chord resolves isolated (non-ALT) ESC mapping. #13086 #15869
+ command('nnoremap <ESC> A<lt>ESC><Esc>')
+ command('nnoremap ; A;<Esc>')
+ feed('<A-;><M-;>')
+ expect('llo<ESC>;<ESC>;')
-- Mapped ALT-chord behaves as mapped.
command('nnoremap <M-l> Ameta-l<Esc>')
command('nnoremap <A-j> Aalt-j<Esc>')
feed('<A-j><M-l>')
- expect('lloalt-jmeta-l')
+ expect('llo<ESC>;<ESC>;alt-jmeta-l')
end)
it('ALT/META, visual-mode', function()
@@ -27,11 +32,15 @@ describe('meta-keys #8226 #13042', function()
insert('peaches')
feed('viw<A-x>viw<M-x>')
expect('peach')
+ -- Unmapped ALT-chord resolves isolated (non-ALT) ESC mapping. #13086 #15869
+ command('vnoremap <ESC> A<lt>ESC>')
+ feed('viw<A-;><ESC>viw<M-;><ESC>')
+ expect('peach<ESC>;<ESC>;')
-- Mapped ALT-chord behaves as mapped.
command('vnoremap <M-l> Ameta-l<Esc>')
command('vnoremap <A-j> Aalt-j<Esc>')
feed('viw<A-j>viw<M-l>')
- expect('peachalt-jmeta-l')
+ expect('peach<ESC>;<ESC>;alt-jmeta-l')
end)
it('ALT/META insert-mode', function()
diff --git a/test/functional/fixtures/autoload/health/full_render.vim b/test/functional/fixtures/autoload/health/full_render.vim
new file mode 100644
index 0000000000..2064b8606e
--- /dev/null
+++ b/test/functional/fixtures/autoload/health/full_render.vim
@@ -0,0 +1,8 @@
+function! health#full_render#check()
+ call health#report_start("report 1")
+ call health#report_ok("life is fine")
+ call health#report_warn("no what installed", ["pip what", "make what"])
+ call health#report_start("report 2")
+ call health#report_info("stuff is stable")
+ call health#report_error("why no hardcopy", [":h :hardcopy", ":h :TOhtml"])
+endfunction
diff --git a/test/functional/fixtures/lua/test_plug/autoload/health/test_plug.vim b/test/functional/fixtures/lua/test_plug/autoload/health/test_plug.vim
new file mode 100644
index 0000000000..de05f56e9e
--- /dev/null
+++ b/test/functional/fixtures/lua/test_plug/autoload/health/test_plug.vim
@@ -0,0 +1,3 @@
+function! health#success1#check()
+ call health#report_start("If you see this I'm broken")
+endfunction
diff --git a/test/functional/fixtures/lua/test_plug/health/init.lua b/test/functional/fixtures/lua/test_plug/health/init.lua
new file mode 100644
index 0000000000..d07632cff4
--- /dev/null
+++ b/test/functional/fixtures/lua/test_plug/health/init.lua
@@ -0,0 +1,11 @@
+local M = {}
+local health = require("health")
+
+M.check = function()
+ health.report_start("report 1")
+ health.report_ok("everything is fine")
+ health.report_start("report 2")
+ health.report_ok("nothing to see here")
+end
+
+return M
diff --git a/test/functional/fixtures/lua/test_plug/submodule/health.lua b/test/functional/fixtures/lua/test_plug/submodule/health.lua
new file mode 100644
index 0000000000..d07632cff4
--- /dev/null
+++ b/test/functional/fixtures/lua/test_plug/submodule/health.lua
@@ -0,0 +1,11 @@
+local M = {}
+local health = require("health")
+
+M.check = function()
+ health.report_start("report 1")
+ health.report_ok("everything is fine")
+ health.report_start("report 2")
+ health.report_ok("nothing to see here")
+end
+
+return M
diff --git a/test/functional/fixtures/lua/test_plug/submodule_failed/health.lua b/test/functional/fixtures/lua/test_plug/submodule_failed/health.lua
new file mode 100644
index 0000000000..3a8af6ebb2
--- /dev/null
+++ b/test/functional/fixtures/lua/test_plug/submodule_failed/health.lua
@@ -0,0 +1,12 @@
+local M = {}
+local health = require("health")
+
+M.check = function()
+ health.report_start("report 1")
+ health.report_ok("everything is fine")
+ health.report_warn("About to add a number to nil")
+ local a = nil + 2
+ return a
+end
+
+return M
diff --git a/test/functional/lua/buffer_updates_spec.lua b/test/functional/lua/buffer_updates_spec.lua
index 073927bf22..aa92c36918 100644
--- a/test/functional/lua/buffer_updates_spec.lua
+++ b/test/functional/lua/buffer_updates_spec.lua
@@ -1050,6 +1050,19 @@ describe('lua: nvim_buf_attach on_bytes', function()
}
end)
+ it("sends updates on U", function()
+ feed("ggiAAA<cr>BBB")
+ feed("<esc>gg$a CCC")
+
+ local check_events = setup_eventcheck(verify, nil)
+
+ feed("ggU")
+
+ check_events {
+ { "test1", "bytes", 1, 6, 0, 7, 7, 0, 0, 0, 0, 3, 3 };
+ }
+ end)
+
teardown(function()
os.remove "Xtest-reload"
os.remove "Xtest-undofile"
diff --git a/test/functional/lua/diagnostic_spec.lua b/test/functional/lua/diagnostic_spec.lua
index 9397af9d9f..45aa4915cd 100644
--- a/test/functional/lua/diagnostic_spec.lua
+++ b/test/functional/lua/diagnostic_spec.lua
@@ -874,6 +874,26 @@ describe('vim.diagnostic', function()
return count_extmarks(diagnostic_bufnr, diagnostic_ns)
]])
end)
+
+ it('sets signs', function()
+ local result = exec_lua [[
+ vim.diagnostic.config({
+ signs = true,
+ })
+
+ local diagnostics = {
+ make_error('Error', 1, 1, 1, 2),
+ make_warning('Warning', 3, 3, 3, 3),
+ }
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
+
+ return vim.fn.sign_getplaced(diagnostic_bufnr, {group = '*'})[1].signs
+ ]]
+
+ eq({2, 'DiagnosticSignError'}, {result[1].lnum, result[1].name})
+ eq({4, 'DiagnosticSignWarn'}, {result[2].lnum, result[2].name})
+ end)
end)
describe('show_line_diagnostics()', function()
@@ -995,37 +1015,6 @@ describe('vim.diagnostic', function()
end)
end)
- describe('set_signs()', function()
- -- TODO(tjdevries): Find out why signs are not displayed when set from Lua...??
- pending('sets signs by default', function()
- exec_lua [[
- vim.diagnostic.config({
- update_in_insert = true,
- signs = true,
- })
-
- local diagnostics = {
- make_error('Delayed Diagnostic', 1, 1, 1, 2),
- make_error('Delayed Diagnostic', 3, 3, 3, 3),
- }
-
- vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
- vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
-
- vim.diagnostic._set_signs(diagnostic_ns, diagnostic_bufnr, diagnostics)
- -- return vim.fn.sign_getplaced()
- ]]
-
- nvim("input", "o")
- nvim("input", "<esc>")
-
- -- TODO(tjdevries): Find a way to get the signs to display in the test...
- eq(nil, exec_lua [[
- return im.fn.sign_getplaced()[1].signs
- ]])
- end)
- end)
-
describe('setloclist()', function()
it('sets diagnostics in lnum order', function()
local loc_list = exec_lua [[
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index a066cfbc10..8651a38025 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -237,29 +237,34 @@ describe('lua stdlib', function()
end)
it("vim.split", function()
- local split = function(str, sep, plain)
- return exec_lua('return vim.split(...)', str, sep, plain)
+ local split = function(str, sep, kwargs)
+ return exec_lua('return vim.split(...)', str, sep, kwargs)
end
local tests = {
- { "a,b", ",", false, { 'a', 'b' } },
- { ":aa::bb:", ":", false, { '', 'aa', '', 'bb', '' } },
- { "::ee::ff:", ":", false, { '', '', 'ee', '', 'ff', '' } },
- { "ab", ".", false, { '', '', '' } },
- { "a1b2c", "[0-9]", false, { 'a', 'b', 'c' } },
- { "xy", "", false, { 'x', 'y' } },
- { "here be dragons", " ", false, { "here", "be", "dragons"} },
- { "axaby", "ab?", false, { '', 'x', 'y' } },
- { "f v2v v3v w2w ", "([vw])2%1", false, { 'f ', ' v3v ', ' ' } },
- { "", "", false, {} },
- { "", "a", false, { '' } },
- { "x*yz*oo*l", "*", true, { 'x', 'yz', 'oo', 'l' } },
+ { "a,b", ",", false, false, { 'a', 'b' } },
+ { ":aa::bb:", ":", false, false, { '', 'aa', '', 'bb', '' } },
+ { ":aa::bb:", ":", false, true, { 'aa', '', 'bb' } },
+ { "::ee::ff:", ":", false, false, { '', '', 'ee', '', 'ff', '' } },
+ { "::ee::ff:", ":", false, true, { 'ee', '', 'ff' } },
+ { "ab", ".", false, false, { '', '', '' } },
+ { "a1b2c", "[0-9]", false, false, { 'a', 'b', 'c' } },
+ { "xy", "", false, false, { 'x', 'y' } },
+ { "here be dragons", " ", false, false, { "here", "be", "dragons"} },
+ { "axaby", "ab?", false, false, { '', 'x', 'y' } },
+ { "f v2v v3v w2w ", "([vw])2%1", false, false, { 'f ', ' v3v ', ' ' } },
+ { "", "", false, false, {} },
+ { "", "a", false, false, { '' } },
+ { "x*yz*oo*l", "*", true, false, { 'x', 'yz', 'oo', 'l' } },
}
for _, t in ipairs(tests) do
- eq(t[4], split(t[1], t[2], t[3]))
+ eq(t[5], split(t[1], t[2], {plain=t[3], trimempty=t[4]}))
end
+ -- Test old signature
+ eq({'x', 'yz', 'oo', 'l'}, split("x*yz*oo*l", "*", true))
+
local loops = {
{ "abc", ".-" },
}
@@ -283,9 +288,8 @@ describe('lua stdlib', function()
vim/shared.lua:0: in function <vim/shared.lua:0>]]),
pcall_err(split, 'string', 1))
eq(dedent([[
- Error executing lua: vim/shared.lua:0: plain: expected boolean, got number
+ Error executing lua: vim/shared.lua:0: kwargs: expected table, got number
stack traceback:
- vim/shared.lua:0: in function 'gsplit'
vim/shared.lua:0: in function <vim/shared.lua:0>]]),
pcall_err(split, 'string', 'string', 1))
end)
diff --git a/test/functional/plugin/health_spec.lua b/test/functional/plugin/health_spec.lua
index 85c67be8f9..45fcf945f4 100644
--- a/test/functional/plugin/health_spec.lua
+++ b/test/functional/plugin/health_spec.lua
@@ -1,4 +1,5 @@
local helpers = require('test.functional.helpers')(after_each)
+local global_helpers = require('test.helpers')
local Screen = require('test.functional.ui.screen')
local clear = helpers.clear
@@ -35,6 +36,7 @@ describe(':checkhealth', function()
clear()
eq('nvim', getcompletion('nvim', 'checkhealth')[1])
eq('provider', getcompletion('prov', 'checkhealth')[1])
+ eq('vim.lsp', getcompletion('vim.ls', 'checkhealth')[1])
end)
end)
@@ -48,42 +50,34 @@ describe('health.vim', function()
command("set runtimepath+=test/functional/fixtures")
end)
- it("health#report_*()", function()
- helpers.source([[
- let g:health_report = execute([
- \ "call health#report_start('Check Bar')",
- \ "call health#report_ok('Bar status')",
- \ "call health#report_ok('Other Bar status')",
- \ "call health#report_warn('Zub')",
- \ "call health#report_start('Baz')",
- \ "call health#report_warn('Zim', ['suggestion 1', 'suggestion 2'])"
- \ ])
- ]])
- local result = helpers.eval("g:health_report")
-
- helpers.eq(helpers.dedent([[
-
-
- ## Check Bar
- - OK: Bar status
- - OK: Other Bar status
- - WARNING: Zub
-
- ## Baz
- - WARNING: Zim
+ describe(":checkhealth", function()
+ it("functions health#report_*() render correctly", function()
+ command("checkhealth full_render")
+ helpers.expect([[
+
+ full_render: health#full_render#check
+ ========================================================================
+ ## report 1
+ - OK: life is fine
+ - WARNING: no what installed
- ADVICE:
- - suggestion 1
- - suggestion 2]]),
- result)
- end)
+ - pip what
+ - make what
+ ## report 2
+ - INFO: stuff is stable
+ - ERROR: why no hardcopy
+ - ADVICE:
+ - :help |:hardcopy|
+ - :help |:TOhtml|
+ ]])
+ end)
- describe(":checkhealth", function()
it("concatenates multiple reports", function()
- command("checkhealth success1 success2")
+ command("checkhealth success1 success2 test_plug")
helpers.expect([[
- health#success1#check
+ success1: health#success1#check
========================================================================
## report 1
- OK: everything is fine
@@ -91,25 +85,111 @@ describe('health.vim', function()
## report 2
- OK: nothing to see here
- health#success2#check
+ success2: health#success2#check
========================================================================
## another 1
- OK: ok
+
+ test_plug: require("test_plug.health").check()
+ ========================================================================
+ ## report 1
+ - OK: everything is fine
+
+ ## report 2
+ - OK: nothing to see here
+ ]])
+ end)
+
+ it("lua plugins, skips vimscript healthchecks with the same name", function()
+ command("checkhealth test_plug")
+ -- Existing file in test/functional/fixtures/lua/test_plug/autoload/health/test_plug.vim
+ -- 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
]])
end)
+ it("lua plugins submodules", 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
+ ]])
+ end)
+
+ it("lua plugins submodules with expression '*'", function()
+ command("checkhealth test_plug*")
+ local buf_lines = helpers.curbuf('get_lines', 0, -1, true)
+ -- avoid dealing with path separators
+ local received = table.concat(buf_lines, '\n', 1, #buf_lines - 2)
+ local expected = helpers.dedent([[
+
+ test_plug: require("test_plug.health").check()
+ ========================================================================
+ ## 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
+
+ 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 24]])
+ eq(expected, received)
+ end)
+
it("gracefully handles broken healthcheck", function()
command("checkhealth broken")
helpers.expect([[
- health#broken#check
+ broken: health#broken#check
========================================================================
- ERROR: Failed to run healthcheck for "broken" plugin. Exception:
- function health#check[21]..health#broken#check, line 1
+ function health#check[24]..health#broken#check, line 1
caused an error
]])
end)
+ it("gracefully handles broken lua healthcheck", function()
+ command("checkhealth test_plug.submodule_failed")
+ local buf_lines = helpers.curbuf('get_lines', 0, -1, true)
+ local received = table.concat(buf_lines, '\n', 1, #buf_lines - 2)
+ -- avoid dealing with path separators
+ local lua_err = "attempt to perform arithmetic on a nil value"
+ local last_line = buf_lines[#buf_lines - 1]
+ assert(string.find(last_line, lua_err) ~= nil, "Lua error not present")
+
+ 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 24]])
+ eq(expected, received)
+ end)
+
it("highlights OK, ERROR", function()
local screen = Screen.new(72, 10)
screen:attach()
@@ -126,11 +206,11 @@ describe('health.vim', function()
command("set laststatus=0")
screen:expect{grid=[[
^ |
- {Heading:health#foo#check} |
+ {Heading:foo: } |
{Bar:========================================================================}|
{Bullet: -} {Error:ERROR:} No healthcheck found for "foo" plugin. |
|
- {Heading:health#success1#check} |
+ {Heading:success1: health#success1#check} |
{Bar:========================================================================}|
{Heading2:##}{Heading: report 1} |
{Bullet: -} {Ok:OK:} everything is fine |
@@ -140,9 +220,10 @@ describe('health.vim', function()
it("gracefully handles invalid healthcheck", function()
command("checkhealth non_existent_healthcheck")
+ -- luacheck: ignore 613
helpers.expect([[
- health#non_existent_healthcheck#check
+ non_existent_healthcheck:
========================================================================
- ERROR: No healthcheck found for "non_existent_healthcheck" plugin.
]])
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index 572573a3a6..8f9b194690 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -132,37 +132,38 @@ local function test_rpc_server(config)
end
describe('LSP', function()
- describe('server_name specified', function()
- before_each(function()
- clear_notrace()
- -- Run an instance of nvim on the file which contains our "scripts".
- -- Pass TEST_NAME to pick the script.
- local test_name = "basic_init"
- exec_lua([=[
- lsp = require('vim.lsp')
- local test_name, fixture_filename, logfile = ...
- function test__start_client()
- return lsp.start_client {
- cmd_env = {
- NVIM_LOG_FILE = logfile;
- };
- cmd = {
- vim.v.progpath, '-Es', '-u', 'NONE', '--headless',
- "-c", string.format("lua TEST_NAME = %q", test_name),
- "-c", "luafile "..fixture_filename;
- };
- root_dir = vim.loop.cwd();
- }
- end
- TEST_CLIENT1 = test__start_client()
- ]=], test_name, fake_lsp_code, fake_lsp_logfile)
- end)
+ before_each(function()
+ clear_notrace()
- after_each(function()
- exec_lua("lsp._vim_exit_handler()")
- -- exec_lua("lsp.stop_all_clients(true)")
- end)
+ -- Run an instance of nvim on the file which contains our "scripts".
+ -- Pass TEST_NAME to pick the script.
+ local test_name = "basic_init"
+ exec_lua([=[
+ lsp = require('vim.lsp')
+ local test_name, fixture_filename, logfile = ...
+ function test__start_client()
+ return lsp.start_client {
+ cmd_env = {
+ NVIM_LOG_FILE = logfile;
+ };
+ cmd = {
+ vim.v.progpath, '-Es', '-u', 'NONE', '--headless',
+ "-c", string.format("lua TEST_NAME = %q", test_name),
+ "-c", "luafile "..fixture_filename;
+ };
+ root_dir = vim.loop.cwd();
+ }
+ end
+ TEST_CLIENT1 = test__start_client()
+ ]=], test_name, fake_lsp_code, fake_lsp_logfile)
+ end)
+
+ after_each(function()
+ exec_lua("lsp._vim_exit_handler()")
+ -- exec_lua("lsp.stop_all_clients(true)")
+ end)
+ describe('server_name specified', function()
it('start_client(), stop_client()', function()
retry(nil, 4000, function()
eq(1, exec_lua('return #lsp.get_active_clients()'))
@@ -334,7 +335,6 @@ describe('LSP', function()
}
end)
it('workspace/configuration returns NIL per section if client was started without config.settings', function()
- clear_notrace()
fake_lsp_server_setup('workspace/configuration no settings')
eq({ NIL, NIL, }, exec_lua [[
local result = {
@@ -2022,83 +2022,6 @@ describe('LSP', function()
end)
end)
- describe('lsp.util.make_floating_popup_options', function()
- before_each(function()
- exec_lua [[
- local bufnr = vim.uri_to_bufnr("file:///fake/uri")
- local winheight = vim.fn.winheight(0)
- for i = 1, winheight do
- vim.api.nvim_buf_set_lines(bufnr, 0, 0, false, {''})
- end
- vim.api.nvim_win_set_buf(0, bufnr)
- vim.api.nvim_win_set_cursor(0, {winheight, 0})
- ]]
- end)
-
- local function popup_row(opts)
- return exec_lua([[
- return vim.lsp.util.make_floating_popup_options(...).row
- ]], 2, 2, opts)
- end
-
- local err_pattern = "^Error executing lua: %.%.%./util%.lua:0: invalid floating preview border: .*%. :help vim%.api%.nvim_open_win%(%)$"
-
- it('calculates default border height correctly', function()
- eq(0, popup_row())
- end)
-
- it('calculates string border height correctly', function()
- eq(0, popup_row({border = 'none'}))
- eq(-2, popup_row({border = 'single'}))
- eq(-2, popup_row({border = 'double'}))
- eq(-2, popup_row({border = 'rounded'}))
- eq(-2, popup_row({border = 'solid'}))
- eq(-1, popup_row({border = 'shadow'}))
- end)
-
- it('error on invalid string border', function()
- matches(err_pattern, pcall_err(popup_row, {border = ''}))
- matches(err_pattern, pcall_err(popup_row, {border = 'invalid'}))
- end)
-
- it('error on invalid array border length', function()
- matches(err_pattern, pcall_err(popup_row, {border = {}}))
- matches(err_pattern, pcall_err(popup_row, {border = {'', '', ''}}))
- matches(err_pattern, pcall_err(popup_row, {border = {'', '', '', '', ''}}))
- end)
-
- it('error on invalid array border member type', function()
- matches(err_pattern, pcall_err(popup_row, {border = {0}}))
- end)
-
- it('calculates 8-array border height correctly', function()
- eq(0, popup_row({border = {'', '', '', '', '', '', '', ''}}))
- eq(-2, popup_row({border = {'', '~', '', '~', '', '~', '', '~'}}))
- eq(-1, popup_row({border = {'', '', '', '~', '', '~', '', ''}}))
- eq(0, popup_row({border = {'', '', '', {'~', 'NormalFloat'}, '', '', '', {'~', 'NormalFloat'}}}))
- eq(-2, popup_row({border = {'', {'~', 'NormalFloat'}, '', '', '', {'~', 'NormalFloat'}, '', ''}}))
- end)
-
- it('calculates 4-array border height correctly', function()
- eq(0, popup_row({border = {'', '', '', ''}}))
- eq(-2, popup_row({border = {'', '~', '', '~'}}))
- eq(0, popup_row({border = {'', '', '', {'~', 'NormalFloat'}}}))
- eq(-2, popup_row({border = {'', {'~', 'NormalFloat'}, '', ''}}))
- end)
-
- it('calculates 2-array border height correctly', function()
- eq(0, popup_row({border = {'', ''}}))
- eq(-2, popup_row({border = {'', '~'}}))
- eq(-2, popup_row({border = {'', {'~', 'NormalFloat'}}}))
- end)
-
- it('calculates 1-array border height correctly', function()
- eq(0, popup_row({border = {''}}))
- eq(-2, popup_row({border = {'~'}}))
- eq(-2, popup_row({border = {{'~', 'NormalFloat'}}}))
- end)
- end)
-
describe('lsp.util._make_floating_popup_size', function()
before_each(function()
exec_lua [[ contents =
diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua
index 103ae59b8e..5442724644 100644
--- a/test/functional/terminal/buffer_spec.lua
+++ b/test/functional/terminal/buffer_spec.lua
@@ -22,14 +22,28 @@ describe(':terminal buffer', function()
it('terminal-mode forces various options', function()
feed([[<C-\><C-N>]])
- command('setlocal cursorline cursorcolumn scrolloff=4 sidescrolloff=7')
- eq({ 1, 1, 4, 7 }, eval('[&l:cursorline, &l:cursorcolumn, &l:scrolloff, &l:sidescrolloff]'))
+ command('setlocal cursorline cursorlineopt=both cursorcolumn scrolloff=4 sidescrolloff=7')
+ eq({ 'both', 1, 1, 4, 7 }, eval('[&l:cursorlineopt, &l:cursorline, &l:cursorcolumn, &l:scrolloff, &l:sidescrolloff]'))
eq('n', eval('mode()'))
-- Enter terminal-mode ("insert" mode in :terminal).
feed('i')
eq('t', eval('mode()'))
- eq({ 0, 0, 0, 0 }, eval('[&l:cursorline, &l:cursorcolumn, &l:scrolloff, &l:sidescrolloff]'))
+ eq({ 'number', 1, 0, 0, 0 }, eval('[&l:cursorlineopt, &l:cursorline, &l:cursorcolumn, &l:scrolloff, &l:sidescrolloff]'))
+ end)
+
+ it('terminal-mode does not change cursorlineopt if cursorline is disabled', function()
+ feed([[<C-\><C-N>]])
+ command('setlocal nocursorline cursorlineopt=both')
+ feed('i')
+ eq({ 0, 'both' }, eval('[&l:cursorline, &l:cursorlineopt]'))
+ end)
+
+ it('terminal-mode disables cursorline when cursorlineopt is only set to "line', function()
+ feed([[<C-\><C-N>]])
+ command('setlocal cursorline cursorlineopt=line')
+ feed('i')
+ eq({ 0, 'line' }, eval('[&l:cursorline, &l:cursorlineopt]'))
end)
describe('when a new file is edited', function()
diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua
index ccf5f963d1..6c2c4b398a 100644
--- a/test/functional/ui/float_spec.lua
+++ b/test/functional/ui/float_spec.lua
@@ -46,6 +46,7 @@ describe('float window', function()
[24] = {foreground = Screen.colors.Black, background = Screen.colors.Grey80};
[25] = {blend = 100, background = Screen.colors.Gray0};
[26] = {blend = 80, background = Screen.colors.Gray0};
+ [27] = {background = Screen.colors.LightGray};
}
it('behavior', function()
@@ -109,6 +110,21 @@ describe('float window', function()
assert_alive()
end)
+ it('closed immediately by autocmd after win_enter #15548', function()
+ eq('Error executing lua: [string "<nvim>"]:0: Window was closed immediately',
+ pcall_err(exec_lua, [[
+ vim.cmd "autocmd BufLeave * ++once quit!"
+ local buf = vim.api.nvim_create_buf(true, true)
+ vim.api.nvim_open_win(buf, true, {
+ relative = "win",
+ row = 0, col = 0,
+ width = 1, height = 1,
+ noautocmd = false,
+ })
+ ]]))
+ assert_alive()
+ end)
+
it('opened with correct height', function()
local height = exec_lua([[
vim.api.nvim_set_option("winheight", 20)
@@ -1514,7 +1530,7 @@ describe('float window', function()
it('API has proper error messages', function()
local buf = meths.create_buf(false,false)
- eq("Invalid key 'bork'",
+ eq("Invalid key: 'bork'",
pcall_err(meths.open_win,buf, false, {width=20,height=2,bork=true}))
eq("'win' key is only valid with relative='win'",
pcall_err(meths.open_win,buf, false, {width=20,height=2,relative='editor',row=0,col=0,win=0}))
@@ -1527,13 +1543,15 @@ describe('float window', function()
eq("'relative' requires 'row'/'col' or 'bufpos'",
pcall_err(meths.open_win,buf, false, {width=20,height=2,relative='editor'}))
eq("'width' key must be a positive Integer",
- pcall_err(meths.open_win,buf, false, {width=-1,height=2,relative='editor'}))
+ pcall_err(meths.open_win,buf, false, {width=-1,height=2,relative='editor', row=0, col=0}))
eq("'height' key must be a positive Integer",
- pcall_err(meths.open_win,buf, false, {width=20,height=-1,relative='editor'}))
+ pcall_err(meths.open_win,buf, false, {width=20,height=-1,relative='editor', row=0, col=0}))
eq("'height' key must be a positive Integer",
- pcall_err(meths.open_win,buf, false, {width=20,height=0,relative='editor'}))
- eq("Must specify 'width' and 'height'",
- pcall_err(meths.open_win,buf, false, {relative='editor'}))
+ pcall_err(meths.open_win,buf, false, {width=20,height=0,relative='editor', row=0, col=0}))
+ eq("Must specify 'width'",
+ pcall_err(meths.open_win,buf, false, {relative='editor', row=0, col=0}))
+ eq("Must specify 'height'",
+ pcall_err(meths.open_win,buf, false, {relative='editor', row=0, col=0, width=2}))
end)
it('can be placed relative window or cursor', function()
@@ -1866,6 +1884,293 @@ describe('float window', function()
end
end)
+ it('always anchor to corner including border', function()
+ screen:try_resize(40,13)
+ meths.buf_set_lines(0, 0, -1, true, {'just some example text', 'some more example text'})
+ feed('ggeee')
+ command('below split')
+ if multigrid then
+ screen:expect([[
+ ## grid 1
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ {5:[No Name] [+] }|
+ [4:----------------------------------------]|
+ [4:----------------------------------------]|
+ [4:----------------------------------------]|
+ [4:----------------------------------------]|
+ [4:----------------------------------------]|
+ {4:[No Name] [+] }|
+ [3:----------------------------------------]|
+ ## grid 2
+ just some example text |
+ some more example text |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ ## grid 3
+ |
+ ## grid 4
+ just some exampl^e text |
+ some more example text |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ ]])
+ else
+ screen:expect([[
+ just some example text |
+ some more example text |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {5:[No Name] [+] }|
+ just some exampl^e text |
+ some more example text |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {4:[No Name] [+] }|
+ |
+ ]])
+ end
+
+ local buf = meths.create_buf(false, false)
+ meths.buf_set_lines(buf, 0, -1, true, {' halloj! ',
+ ' BORDAA '})
+ local win = meths.open_win(buf, false, {relative='cursor', width=9, height=2, row=1, col=-2, border="double"})
+
+ if multigrid then
+ screen:expect{grid=[[
+ ## grid 1
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ {5:[No Name] [+] }|
+ [4:----------------------------------------]|
+ [4:----------------------------------------]|
+ [4:----------------------------------------]|
+ [4:----------------------------------------]|
+ [4:----------------------------------------]|
+ {4:[No Name] [+] }|
+ [3:----------------------------------------]|
+ ## grid 2
+ just some example text |
+ some more example text |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ ## grid 3
+ |
+ ## grid 4
+ just some exampl^e text |
+ some more example text |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ ## grid 6
+ {5:╔═════════╗}|
+ {5:║}{1: halloj! }{5:║}|
+ {5:║}{1: BORDAA }{5:║}|
+ {5:╚═════════╝}|
+ ]], float_pos={
+ [6] = {{id = 1003}, "NW", 4, 1, 14, true}
+ }}
+ else
+ screen:expect([[
+ just some example text |
+ some more example text |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {5:[No Name] [+] }|
+ just some exampl^e text |
+ some more exam{5:╔═════════╗} |
+ {0:~ }{5:║}{1: halloj! }{5:║}{0: }|
+ {0:~ }{5:║}{1: BORDAA }{5:║}{0: }|
+ {0:~ }{5:╚═════════╝}{0: }|
+ {4:[No Name] [+] }|
+ |
+ ]])
+ end
+
+ meths.win_set_config(win, {relative='cursor', row=0, col=-2, anchor='NE'})
+ if multigrid then
+ screen:expect{grid=[[
+ ## grid 1
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ {5:[No Name] [+] }|
+ [4:----------------------------------------]|
+ [4:----------------------------------------]|
+ [4:----------------------------------------]|
+ [4:----------------------------------------]|
+ [4:----------------------------------------]|
+ {4:[No Name] [+] }|
+ [3:----------------------------------------]|
+ ## grid 2
+ just some example text |
+ some more example text |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ ## grid 3
+ |
+ ## grid 4
+ just some exampl^e text |
+ some more example text |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ ## grid 6
+ {5:╔═════════╗}|
+ {5:║}{1: halloj! }{5:║}|
+ {5:║}{1: BORDAA }{5:║}|
+ {5:╚═════════╝}|
+ ]], float_pos={
+ [6] = {{id = 1003}, "NE", 4, 0, 14, true}
+ }}
+ else
+ screen:expect([[
+ just some example text |
+ some more example text |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {5:[No Name] [+] }|
+ jus{5:╔═════════╗}pl^e text |
+ som{5:║}{1: halloj! }{5:║}ple text |
+ {0:~ }{5:║}{1: BORDAA }{5:║}{0: }|
+ {0:~ }{5:╚═════════╝}{0: }|
+ {0:~ }|
+ {4:[No Name] [+] }|
+ |
+ ]])
+ end
+
+ meths.win_set_config(win, {relative='cursor', row=1, col=-2, anchor='SE'})
+ if multigrid then
+ screen:expect{grid=[[
+ ## grid 1
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ {5:[No Name] [+] }|
+ [4:----------------------------------------]|
+ [4:----------------------------------------]|
+ [4:----------------------------------------]|
+ [4:----------------------------------------]|
+ [4:----------------------------------------]|
+ {4:[No Name] [+] }|
+ [3:----------------------------------------]|
+ ## grid 2
+ just some example text |
+ some more example text |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ ## grid 3
+ |
+ ## grid 4
+ just some exampl^e text |
+ some more example text |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ ## grid 6
+ {5:╔═════════╗}|
+ {5:║}{1: halloj! }{5:║}|
+ {5:║}{1: BORDAA }{5:║}|
+ {5:╚═════════╝}|
+ ]], float_pos={
+ [6] = {{id = 1003}, "SE", 4, 1, 14, true}
+ }}
+ else
+ screen:expect([[
+ just some example text |
+ some more example text |
+ {0:~ }|
+ {0:~ }{5:╔═════════╗}{0: }|
+ {0:~ }{5:║}{1: halloj! }{5:║}{0: }|
+ {5:[No║}{1: BORDAA }{5:║ }|
+ jus{5:╚═════════╝}pl^e text |
+ some more example text |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {4:[No Name] [+] }|
+ |
+ ]])
+ end
+
+ meths.win_set_config(win, {relative='cursor', row=0, col=-2, anchor='SW'})
+ if multigrid then
+ screen:expect{grid=[[
+ ## grid 1
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ {5:[No Name] [+] }|
+ [4:----------------------------------------]|
+ [4:----------------------------------------]|
+ [4:----------------------------------------]|
+ [4:----------------------------------------]|
+ [4:----------------------------------------]|
+ {4:[No Name] [+] }|
+ [3:----------------------------------------]|
+ ## grid 2
+ just some example text |
+ some more example text |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ ## grid 3
+ |
+ ## grid 4
+ just some exampl^e text |
+ some more example text |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ ## grid 6
+ {5:╔═════════╗}|
+ {5:║}{1: halloj! }{5:║}|
+ {5:║}{1: BORDAA }{5:║}|
+ {5:╚═════════╝}|
+ ]], float_pos={
+ [6] = {{id = 1003}, "SW", 4, 0, 14, true}
+ }}
+ else
+ screen:expect([[
+ just some example text |
+ some more example text |
+ {0:~ }{5:╔═════════╗}{0: }|
+ {0:~ }{5:║}{1: halloj! }{5:║}{0: }|
+ {0:~ }{5:║}{1: BORDAA }{5:║}{0: }|
+ {5:[No Name] [+] ╚═════════╝ }|
+ just some exampl^e text |
+ some more example text |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {4:[No Name] [+] }|
+ |
+ ]])
+ end
+ end)
+
it('can be placed relative text in a window', function()
screen:try_resize(30,5)
local firstwin = meths.get_current_win().id
@@ -5870,6 +6175,132 @@ describe('float window', function()
end)
end)
+ it("left drag changes visual selection in float window", function()
+ local buf = meths.create_buf(false,false)
+ meths.buf_set_lines(buf, 0, -1, true, {'foo', 'bar'})
+ meths.open_win(buf, false, {relative='editor', width=20, height=3, row=2, col=5})
+ if multigrid then
+ screen:expect{grid=[[
+ ## grid 1
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [3:----------------------------------------]|
+ ## grid 2
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ ## grid 3
+ |
+ ## grid 5
+ {1:foo }|
+ {1:bar }|
+ {2:~ }|
+ ]], float_pos={
+ [5] = {{id = 1002}, "NW", 1, 2, 5, true, 50};
+ }, win_viewport={
+ [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1};
+ [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 2};
+ }}
+ meths.input_mouse('left', 'press', '', 5, 0, 0)
+ screen:expect{grid=[[
+ ## grid 1
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [3:----------------------------------------]|
+ ## grid 2
+ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ ## grid 3
+ |
+ ## grid 5
+ {1:^foo }|
+ {1:bar }|
+ {2:~ }|
+ ]], float_pos={
+ [5] = {{id = 1002}, "NW", 1, 2, 5, true, 50};
+ }, win_viewport={
+ [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1};
+ [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 2};
+ }}
+ meths.input_mouse('left', 'drag', '', 5, 1, 2)
+ screen:expect{grid=[[
+ ## grid 1
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [3:----------------------------------------]|
+ ## grid 2
+ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ ## grid 3
+ {3:-- VISUAL --} |
+ ## grid 5
+ {27:foo}{1: }|
+ {27:ba}{1:^r }|
+ {2:~ }|
+ ]], float_pos={
+ [5] = {{id = 1002}, "NW", 1, 2, 5, true, 50};
+ }, win_viewport={
+ [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1};
+ [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 1, curcol = 2, linecount = 2};
+ }}
+ else
+ screen:expect{grid=[[
+ ^ |
+ {0:~ }|
+ {0:~ }{1:foo }{0: }|
+ {0:~ }{1:bar }{0: }|
+ {0:~ }{2:~ }{0: }|
+ {0:~ }|
+ |
+ ]]}
+
+ meths.input_mouse('left', 'press', '', 0, 2, 5)
+ screen:expect{grid=[[
+ |
+ {0:~ }|
+ {0:~ }{1:^foo }{0: }|
+ {0:~ }{1:bar }{0: }|
+ {0:~ }{2:~ }{0: }|
+ {0:~ }|
+ |
+ ]]}
+
+ meths.input_mouse('left', 'drag', '', 0, 3, 7)
+ screen:expect{grid=[[
+ |
+ {0:~ }|
+ {0:~ }{27:foo}{1: }{0: }|
+ {0:~ }{27:ba}{1:^r }{0: }|
+ {0:~ }{2:~ }{0: }|
+ {0:~ }|
+ {3:-- VISUAL --} |
+ ]]}
+ end
+ end)
+
it("'winblend' option", function()
screen:try_resize(50,9)
screen:set_default_attr_ids({
diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua
index d3fe38ef52..baacef358f 100644
--- a/test/functional/ui/mouse_spec.lua
+++ b/test/functional/ui/mouse_spec.lua
@@ -585,6 +585,69 @@ describe('ui/mouse/input', function()
]])
end)
+ it('left drag changes visual selection in split layout', function()
+ screen:try_resize(53,14)
+ command('set mouse=a')
+ command('vsplit')
+ command('wincmd l')
+ command('below split')
+ command('enew')
+ feed('ifoo\nbar<esc>')
+
+ screen:expect{grid=[[
+ testing {4:│}testing |
+ mouse {4:│}mouse |
+ support and selection {4:│}support and selection |
+ {0:~ }{4:│}{0:~ }|
+ {0:~ }{4:│}{0:~ }|
+ {0:~ }{4:│[No Name] [+] }|
+ {0:~ }{4:│}foo{0:$} |
+ {0:~ }{4:│}ba^r{0:$} |
+ {0:~ }{4:│}{0:~ }|
+ {0:~ }{4:│}{0:~ }|
+ {0:~ }{4:│}{0:~ }|
+ {0:~ }{4:│}{0:~ }|
+ {4:[No Name] [+] }{5:[No Name] [+] }|
+ |
+ ]]}
+
+ meths.input_mouse('left', 'press', '', 0, 6, 27)
+ screen:expect{grid=[[
+ testing {4:│}testing |
+ mouse {4:│}mouse |
+ support and selection {4:│}support and selection |
+ {0:~ }{4:│}{0:~ }|
+ {0:~ }{4:│}{0:~ }|
+ {0:~ }{4:│[No Name] [+] }|
+ {0:~ }{4:│}^foo{0:$} |
+ {0:~ }{4:│}bar{0:$} |
+ {0:~ }{4:│}{0:~ }|
+ {0:~ }{4:│}{0:~ }|
+ {0:~ }{4:│}{0:~ }|
+ {0:~ }{4:│}{0:~ }|
+ {4:[No Name] [+] }{5:[No Name] [+] }|
+ |
+ ]]}
+ meths.input_mouse('left', 'drag', '', 0, 7, 30)
+
+ screen:expect{grid=[[
+ testing {4:│}testing |
+ mouse {4:│}mouse |
+ support and selection {4:│}support and selection |
+ {0:~ }{4:│}{0:~ }|
+ {0:~ }{4:│}{0:~ }|
+ {0:~ }{4:│[No Name] [+] }|
+ {0:~ }{4:│}{1:foo}{3:$} |
+ {0:~ }{4:│}{1:bar}{0:^$} |
+ {0:~ }{4:│}{0:~ }|
+ {0:~ }{4:│}{0:~ }|
+ {0:~ }{4:│}{0:~ }|
+ {0:~ }{4:│}{0:~ }|
+ {4:[No Name] [+] }{5:[No Name] [+] }|
+ {2:-- VISUAL --} |
+ ]]}
+ end)
+
it('two clicks will select the word and enter VISUAL', function()
feed('<LeftMouse><2,2><LeftMouse><2,2>')
screen:expect([[
diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt
index 0959e6df57..29ff0daa8d 100644
--- a/third-party/CMakeLists.txt
+++ b/third-party/CMakeLists.txt
@@ -144,14 +144,8 @@ endif()
include(ExternalProject)
-if(WIN32)
- # "nvim" branch of https://github.com/neovim/libuv
- set(LIBUV_URL https://github.com/neovim/libuv/archive/b899d12b0d56d217f31222da83f8c398355b69ef.tar.gz)
- set(LIBUV_SHA256 eb7e37b824887e1b31a4e31d1d9bad4c03d8b98532d9cce5f67a3b70495a4b2a)
-else()
- set(LIBUV_URL https://github.com/libuv/libuv/archive/v1.42.0.tar.gz)
- set(LIBUV_SHA256 371e5419708f6aaeb8656671f89400b92a9bba6443369af1bb70bcd6e4b3c764)
-endif()
+set(LIBUV_URL https://github.com/libuv/libuv/archive/v1.42.0.tar.gz)
+set(LIBUV_SHA256 371e5419708f6aaeb8656671f89400b92a9bba6443369af1bb70bcd6e4b3c764)
set(MSGPACK_URL https://github.com/msgpack/msgpack-c/releases/download/cpp-3.0.0/msgpack-3.0.0.tar.gz)
set(MSGPACK_SHA256 bfbb71b7c02f806393bc3cbc491b40523b89e64f83860c58e3e54af47de176e4)