aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE/lsp_bug_report.yml34
-rw-r--r--.github/workflows/ci.yml32
-rwxr-xr-x.github/workflows/env.sh14
-rw-r--r--.github/workflows/news.yml7
-rw-r--r--CMakeLists.txt40
-rw-r--r--CMakePresets.json41
-rw-r--r--CONTRIBUTING.md10
-rw-r--r--Makefile17
-rw-r--r--ci/common/build.sh10
-rw-r--r--cmake.config/CMakeLists.txt5
-rw-r--r--cmake.config/config.h.in3
-rw-r--r--cmake.config/iwyu/mapping.imp2
-rw-r--r--cmake.config/pathdef.c.in4
-rw-r--r--cmake.deps/CMakeLists.txt57
-rw-r--r--cmake.deps/cmake/BuildGettext.cmake9
-rw-r--r--cmake.deps/cmake/BuildLibiconv.cmake7
-rw-r--r--cmake.deps/cmake/BuildLibtermkey.cmake35
-rw-r--r--cmake.deps/cmake/BuildLibuv.cmake10
-rw-r--r--cmake.deps/cmake/BuildLibvterm.cmake35
-rw-r--r--cmake.deps/cmake/BuildLuarocks.cmake2
-rw-r--r--cmake.deps/cmake/BuildLuv.cmake48
-rw-r--r--cmake.deps/cmake/BuildMsgpack.cmake28
-rw-r--r--cmake.deps/cmake/BuildTreesitter.cmake28
-rw-r--r--cmake.deps/cmake/BuildTreesitterParsers.cmake8
-rw-r--r--cmake.deps/cmake/BuildUnibilium.cmake23
-rw-r--r--cmake.deps/cmake/Libvterm-tbl2inc_c.cmake163
-rw-r--r--cmake.deps/cmake/LibvtermCMakeLists.txt58
-rw-r--r--cmake.deps/cmake/TreesitterCMakeLists.txt15
-rw-r--r--cmake.deps/cmake/TreesitterParserCMakeLists.txt1
-rw-r--r--cmake.deps/cmake/UnibiliumCMakeLists.txt27
-rw-r--r--cmake.deps/cmake/libtermkeyCMakeLists.txt13
-rw-r--r--cmake/FindLIBVTERM.cmake10
-rw-r--r--cmake/FindUNIBILIUM.cmake12
-rw-r--r--cmake/Findlibvterm.cmake20
-rw-r--r--cmake/Findunibilium.cmake27
-rw-r--r--cmake/GenerateVersion.cmake5
-rw-r--r--cmake/RunTests.cmake10
-rw-r--r--cmake/Util.cmake7
-rw-r--r--runtime/doc/api.txt4
-rw-r--r--runtime/doc/autocmd.txt8
-rw-r--r--runtime/doc/builtin.txt25
-rw-r--r--runtime/doc/eval.txt23
-rw-r--r--runtime/doc/lsp.txt235
-rw-r--r--runtime/doc/lua-guide.txt2
-rw-r--r--runtime/doc/lua.txt19
-rw-r--r--runtime/doc/map.txt8
-rw-r--r--runtime/doc/news.txt14
-rw-r--r--runtime/doc/options.txt49
-rw-r--r--runtime/doc/repeat.txt4
-rw-r--r--runtime/doc/starting.txt8
-rw-r--r--runtime/doc/syntax.txt4
-rw-r--r--runtime/doc/treesitter.txt18
-rw-r--r--runtime/doc/ui.txt1
-rw-r--r--runtime/doc/usr_41.txt1
-rw-r--r--runtime/lua/man.lua20
-rw-r--r--runtime/lua/nvim/health.lua474
-rw-r--r--runtime/lua/vim/_init_packages.lua9
-rw-r--r--runtime/lua/vim/filetype.lua7
-rw-r--r--runtime/lua/vim/fs.lua2
-rw-r--r--runtime/lua/vim/health.lua15
-rw-r--r--runtime/lua/vim/lsp.lua231
-rw-r--r--runtime/lua/vim/lsp/buf.lua23
-rw-r--r--runtime/lua/vim/lsp/handlers.lua7
-rw-r--r--runtime/lua/vim/lsp/protocol.lua11
-rw-r--r--runtime/lua/vim/shared.lua29
-rw-r--r--runtime/lua/vim/treesitter/highlighter.lua6
-rw-r--r--runtime/lua/vim/treesitter/language.lua12
-rw-r--r--runtime/lua/vim/treesitter/query.lua10
-rw-r--r--runtime/nvim.appdata.xml3
-rw-r--r--runtime/tutor/tutor.tutor.json4
-rwxr-xr-xscripts/bump_deps.lua2
-rw-r--r--scripts/gen_help_html.lua23
-rw-r--r--scripts/genvimvim.lua6
-rw-r--r--src/mpack/mpack_core.c3
-rwxr-xr-xsrc/nvim/CMakeLists.txt126
-rw-r--r--src/nvim/api/autocmd.c2
-rw-r--r--src/nvim/api/extmark.c2
-rw-r--r--src/nvim/api/keysets.lua95
-rw-r--r--src/nvim/api/private/converter.c2
-rw-r--r--src/nvim/api/private/helpers.c14
-rw-r--r--src/nvim/api/ui.c7
-rw-r--r--src/nvim/api/vim.c4
-rw-r--r--src/nvim/api/win_config.c2
-rw-r--r--src/nvim/api/window.c7
-rw-r--r--src/nvim/auevents.lua20
-rw-r--r--src/nvim/buffer.c174
-rw-r--r--src/nvim/buffer_defs.h1
-rw-r--r--src/nvim/change.c17
-rw-r--r--src/nvim/charset.c22
-rw-r--r--src/nvim/cmdexpand.c672
-rw-r--r--src/nvim/cmdexpand.h4
-rw-r--r--src/nvim/cmdhist.c18
-rw-r--r--src/nvim/context.c4
-rw-r--r--src/nvim/debugger.c12
-rw-r--r--src/nvim/decoration.c13
-rw-r--r--src/nvim/decoration.h2
-rw-r--r--src/nvim/diff.c8
-rw-r--r--src/nvim/digraph.c40
-rw-r--r--src/nvim/drawline.c148
-rw-r--r--src/nvim/drawscreen.c42
-rw-r--r--src/nvim/edit.c96
-rw-r--r--src/nvim/eval.c270
-rw-r--r--src/nvim/eval.h2
-rw-r--r--src/nvim/eval.lua69
-rw-r--r--src/nvim/eval/buffer.c5
-rw-r--r--src/nvim/eval/encode.c2
-rw-r--r--src/nvim/eval/encode.h1
-rw-r--r--src/nvim/eval/executor.c4
-rw-r--r--src/nvim/eval/funcs.c155
-rw-r--r--src/nvim/eval/typval.c117
-rw-r--r--src/nvim/eval/typval.h12
-rw-r--r--src/nvim/eval/typval_defs.h2
-rw-r--r--src/nvim/eval/typval_encode.c.h4
-rw-r--r--src/nvim/eval/userfunc.c144
-rw-r--r--src/nvim/eval/vars.c84
-rw-r--r--src/nvim/eval/window.c3
-rw-r--r--src/nvim/eval/window.h10
-rw-r--r--src/nvim/event/libuv_process.c2
-rw-r--r--src/nvim/event/process.c1
-rw-r--r--src/nvim/ex_cmds.c34
-rw-r--r--src/nvim/ex_cmds.lua2
-rw-r--r--src/nvim/ex_docmd.c160
-rw-r--r--src/nvim/ex_eval.c9
-rw-r--r--src/nvim/ex_getln.c144
-rw-r--r--src/nvim/ex_getln.h4
-rw-r--r--src/nvim/ex_session.c72
-rw-r--r--src/nvim/file_search.c48
-rw-r--r--src/nvim/fileio.c457
-rw-r--r--src/nvim/fold.c2
-rw-r--r--src/nvim/fold.h2
-rw-r--r--src/nvim/garray.c8
-rw-r--r--src/nvim/garray.h3
-rw-r--r--src/nvim/generators/gen_api_dispatch.lua4
-rw-r--r--src/nvim/generators/gen_eval.lua9
-rw-r--r--src/nvim/generators/gen_events.lua4
-rw-r--r--src/nvim/generators/gen_keysets.lua5
-rw-r--r--src/nvim/generators/gen_options.lua6
-rw-r--r--src/nvim/getchar.c50
-rw-r--r--src/nvim/globals.h12
-rw-r--r--src/nvim/grid.c12
-rw-r--r--src/nvim/hashtab.c17
-rw-r--r--src/nvim/help.c18
-rw-r--r--src/nvim/highlight.c58
-rw-r--r--src/nvim/highlight_defs.h18
-rw-r--r--src/nvim/highlight_group.c158
-rw-r--r--src/nvim/iconv.h20
-rw-r--r--src/nvim/indent.c55
-rw-r--r--src/nvim/indent_c.c3
-rw-r--r--src/nvim/input.c3
-rw-r--r--src/nvim/insexpand.c44
-rw-r--r--src/nvim/keycodes.c44
-rw-r--r--src/nvim/linematch.c1
-rw-r--r--src/nvim/locale.c4
-rw-r--r--src/nvim/lua/converter.c2
-rw-r--r--src/nvim/lua/executor.c92
-rw-r--r--src/nvim/lua/spell.c2
-rw-r--r--src/nvim/lua/stdlib.c33
-rw-r--r--src/nvim/lua/treesitter.c4
-rw-r--r--src/nvim/main.c68
-rw-r--r--src/nvim/main.h3
-rw-r--r--src/nvim/mapping.c203
-rw-r--r--src/nvim/mark.c27
-rw-r--r--src/nvim/marktree.c2
-rw-r--r--src/nvim/mbyte.c193
-rw-r--r--src/nvim/mbyte_defs.h2
-rw-r--r--src/nvim/memfile.c1
-rw-r--r--src/nvim/memline.c48
-rw-r--r--src/nvim/memory.c1
-rw-r--r--src/nvim/menu.c1
-rw-r--r--src/nvim/message.c8
-rw-r--r--src/nvim/mouse.c55
-rw-r--r--src/nvim/move.c4
-rw-r--r--src/nvim/msgpack_rpc/channel.c3
-rw-r--r--src/nvim/msgpack_rpc/server.c2
-rw-r--r--src/nvim/normal.c789
-rw-r--r--src/nvim/normal.h1
-rw-r--r--src/nvim/ops.c188
-rw-r--r--src/nvim/option.c1832
-rw-r--r--src/nvim/option_defs.h53
-rw-r--r--src/nvim/optionstr.c2152
-rw-r--r--src/nvim/os/env.c16
-rw-r--r--src/nvim/os/fileio.c2
-rw-r--r--src/nvim/os/fs.c25
-rw-r--r--src/nvim/os/input.c21
-rw-r--r--src/nvim/os/input.h2
-rw-r--r--src/nvim/os/nvim.manifest20
-rw-r--r--src/nvim/os/os_win_console.c17
-rw-r--r--src/nvim/os/shell.c12
-rw-r--r--src/nvim/os/stdpaths.c2
-rw-r--r--src/nvim/path.c127
-rw-r--r--src/nvim/plines.c5
-rw-r--r--src/nvim/po/tr.po3
-rw-r--r--src/nvim/po/uk.po3
-rw-r--r--src/nvim/po/zh_CN.UTF-8.po17
-rw-r--r--src/nvim/popupmenu.c32
-rw-r--r--src/nvim/profile.c51
-rw-r--r--src/nvim/quickfix.c310
-rw-r--r--src/nvim/regexp.c177
-rw-r--r--src/nvim/regexp_bt.c286
-rw-r--r--src/nvim/regexp_nfa.c260
-rw-r--r--src/nvim/runtime.c292
-rw-r--r--src/nvim/runtime.h1
-rw-r--r--src/nvim/screen.c107
-rw-r--r--src/nvim/search.c486
-rw-r--r--src/nvim/search.h8
-rw-r--r--src/nvim/sha256.c28
-rw-r--r--src/nvim/sha256.h2
-rw-r--r--src/nvim/shada.c14
-rw-r--r--src/nvim/sign.c26
-rw-r--r--src/nvim/sign_defs.h6
-rw-r--r--src/nvim/spell.c425
-rw-r--r--src/nvim/spell_defs.h28
-rw-r--r--src/nvim/spellfile.c618
-rw-r--r--src/nvim/spellsuggest.c236
-rw-r--r--src/nvim/statusline.c67
-rw-r--r--src/nvim/strings.c22
-rw-r--r--src/nvim/syntax.c146
-rw-r--r--src/nvim/tag.c250
-rw-r--r--src/nvim/terminal.c14
-rw-r--r--src/nvim/testdir/check.vim4
-rwxr-xr-xsrc/nvim/testdir/runnvim.sh3
-rw-r--r--src/nvim/testdir/test_autocmd.vim3
-rw-r--r--src/nvim/testdir/test_breakindent.vim40
-rw-r--r--src/nvim/testdir/test_buffer.vim6
-rw-r--r--src/nvim/testdir/test_cmdline.vim853
-rw-r--r--src/nvim/testdir/test_const.vim8
-rw-r--r--src/nvim/testdir/test_cursorline.vim2
-rw-r--r--src/nvim/testdir/test_debugger.vim2
-rw-r--r--src/nvim/testdir/test_edit.vim15
-rw-r--r--src/nvim/testdir/test_filetype.vim10
-rw-r--r--src/nvim/testdir/test_fold.vim71
-rw-r--r--src/nvim/testdir/test_gf.vim25
-rw-r--r--src/nvim/testdir/test_ins_complete.vim27
-rw-r--r--src/nvim/testdir/test_listdict.vim13
-rw-r--r--src/nvim/testdir/test_normal.vim46
-rw-r--r--src/nvim/testdir/test_options.vim24
-rw-r--r--src/nvim/testdir/test_packadd.vim84
-rw-r--r--src/nvim/testdir/test_profile.vim41
-rw-r--r--src/nvim/testdir/test_search.vim16
-rw-r--r--src/nvim/testdir/test_search_stat.vim23
-rw-r--r--src/nvim/testdir/test_shell.vim209
-rw-r--r--src/nvim/testdir/test_spell.vim17
-rw-r--r--src/nvim/testdir/test_startup.vim35
-rw-r--r--src/nvim/testdir/test_substitute.vim13
-rw-r--r--src/nvim/testdir/test_system.vim36
-rw-r--r--src/nvim/testdir/test_taglist.vim4
-rw-r--r--src/nvim/testdir/test_utf8.vim53
-rw-r--r--src/nvim/testdir/test_virtualedit.vim13
-rw-r--r--src/nvim/testdir/test_visual.vim11
-rw-r--r--src/nvim/testdir/test_writefile.vim12
-rw-r--r--src/nvim/testing.c89
-rw-r--r--src/nvim/textformat.c59
-rw-r--r--src/nvim/textobject.c6
-rw-r--r--src/nvim/tui/input.c42
-rw-r--r--src/nvim/tui/input.h8
-rw-r--r--src/nvim/tui/terminfo.c6
-rw-r--r--src/nvim/tui/tui.c47
-rw-r--r--src/nvim/ui.c9
-rw-r--r--src/nvim/ui_client.c18
-rw-r--r--src/nvim/ui_client.h8
-rw-r--r--src/nvim/ui_compositor.c1
-rw-r--r--src/nvim/undo.c80
-rw-r--r--src/nvim/usercmd.c7
-rw-r--r--src/nvim/version.c63
-rw-r--r--src/nvim/vim.h3
-rw-r--r--src/nvim/viml/parser/expressions.c3
-rw-r--r--src/nvim/window.c104
-rw-r--r--src/nvim/window.h1
-rw-r--r--test/busted_runner.lua1
-rw-r--r--test/cmakeconfig/paths.lua.in2
-rw-r--r--test/functional/api/highlight_spec.lua33
-rw-r--r--test/functional/api/server_notifications_spec.lua11
-rw-r--r--test/functional/api/vim_spec.lua27
-rw-r--r--test/functional/autocmd/autocmd_spec.lua42
-rw-r--r--test/functional/autocmd/cmdline_spec.lua26
-rw-r--r--test/functional/autocmd/termxx_spec.lua2
-rw-r--r--test/functional/core/exit_spec.lua6
-rw-r--r--test/functional/core/fileio_spec.lua13
-rw-r--r--test/functional/core/log_spec.lua9
-rw-r--r--test/functional/core/startup_spec.lua13
-rw-r--r--test/functional/editor/completion_spec.lua3
-rw-r--r--test/functional/editor/mark_spec.lua24
-rw-r--r--test/functional/fixtures/fake-lsp-server.lua12
-rw-r--r--test/functional/helpers.lua35
-rw-r--r--test/functional/legacy/055_list_and_dict_types_spec.lua232
-rw-r--r--test/functional/legacy/gf_spec.lua3
-rw-r--r--test/functional/legacy/syn_attr_spec.lua78
-rw-r--r--test/functional/lua/runtime_spec.lua62
-rw-r--r--test/functional/lua/vim_spec.lua27
-rw-r--r--test/functional/options/defaults_spec.lua17
-rw-r--r--test/functional/plugin/lsp/helpers.lua9
-rw-r--r--test/functional/plugin/lsp_spec.lua40
-rw-r--r--test/functional/plugin/man_spec.lua6
-rw-r--r--test/functional/terminal/tui_spec.lua33
-rw-r--r--test/functional/treesitter/language_spec.lua7
-rw-r--r--test/functional/ui/cmdline_highlight_spec.lua8
-rw-r--r--test/functional/ui/fold_spec.lua123
-rw-r--r--test/functional/ui/popupmenu_spec.lua281
-rw-r--r--test/functional/ui/statuscolumn_spec.lua128
-rw-r--r--test/functional/ui/statusline_spec.lua18
-rw-r--r--test/functional/ui/tabline_spec.lua6
-rw-r--r--test/functional/vimscript/api_functions_spec.lua3
-rw-r--r--test/functional/vimscript/ctx_functions_spec.lua12
-rw-r--r--test/functional/vimscript/exepath_spec.lua43
-rw-r--r--test/functional/vimscript/server_spec.lua20
-rw-r--r--test/helpers.lua46
-rw-r--r--test/includes/CMakeLists.txt31
-rw-r--r--test/unit/eval/typval_spec.lua11
-rw-r--r--test/unit/helpers.lua218
-rw-r--r--test/unit/tui_spec.lua19
310 files changed, 11563 insertions, 8511 deletions
diff --git a/.github/ISSUE_TEMPLATE/lsp_bug_report.yml b/.github/ISSUE_TEMPLATE/lsp_bug_report.yml
index 3789fb866b..88867ce644 100644
--- a/.github/ISSUE_TEMPLATE/lsp_bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/lsp_bug_report.yml
@@ -31,8 +31,38 @@ body:
attributes:
label: 'Steps to reproduce using "nvim -u minimal_init.lua"'
description: |
- - Create a minimal_init.lua using vim.lsp.start - read `:h lsp-quickstart` and `:h vim.lsp.start` for more information.
- - _Note_: if the issue is with an autocompletion or other LSP plugin, report to that plugin's issue tracker.
+ - Create a minimal_init.lua using vim.lsp.start:
+
+ ```lua
+ --- CHANGE THESE
+ local pattern = 'the-filetype'
+ local cmd = {'name-of-language-server-executable'}
+ -- Add files/folders here that indicate the root of a project
+ local root_markers = {'.git', '.editorconfig'}
+ -- Change to table with settings if required
+ local settings = vim.empty_dict()
+
+ vim.api.nvim_create_autocmd('FileType', {
+ pattern = pattern,
+ callback = function(args)
+ local match = vim.fs.find(root_markers, { path = args.file, upward = true })[1]
+ local root_dir = match and vim.fn.fnamemodify(match, ':p:h') or vim.NIL
+ vim.lsp.start({
+ name = 'bugged-ls',
+ cmd = cmd,
+ root_dir = root_dir,
+ settings = settings
+ })
+ end
+ })
+ ```
+
+ See `:h lsp-quickstart` and `:h vim.lsp.start` for more information
+
+ - Provide a short code example and describe the folder layout
+ - Describe how to trigger the issue. E.g. using `:lua vim.lsp.buf.*` commands
+
+ _Note_: if the issue is with an autocompletion or other LSP plugin, report to that plugin's issue tracker.
validations:
required: true
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 48338527f4..83ee4f0358 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -16,6 +16,11 @@ concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }}
cancel-in-progress: true
+env:
+ UNCRUSTIFY_VERSION: uncrustify-0.75.0
+ # TEST_FILE: test/functional/core/startup_spec.lua
+ # TEST_FILTER: foo
+
jobs:
lint:
if: (github.event_name == 'pull_request' && github.base_ref == 'master') || (github.event_name == 'push' && github.ref == 'refs/heads/master')
@@ -78,8 +83,10 @@ jobs:
args: --check runtime/
- if: success() || failure() && steps.abort_job.outputs.status == 'success'
- name: lintlua
- run: make lintlua
+ name: luacheck
+ run: |
+ cmake -B $BUILD_DIR -G Ninja
+ cmake --build $BUILD_DIR --target lintlua-luacheck
- if: success() || failure() && steps.abort_job.outputs.status == 'success'
name: lintsh
@@ -121,7 +128,7 @@ jobs:
- uses: actions/checkout@v3
- name: Setup common environment variables
- run: ./.github/workflows/env.sh lint
+ run: ./.github/workflows/env.sh lintc
- name: Install apt packages
run: |
@@ -134,14 +141,17 @@ jobs:
libtree-sitter-dev \
libunibilium-dev \
libuv1-dev \
- libvterm-dev \
lua-busted \
lua-filesystem \
lua-inspect \
lua-lpeg \
- lua-luv-dev \
lua-nvim \
luajit
+ # libvterm-dev \
+ # lua-luv-dev
+
+ # Remove comments from packages once we start using these external
+ # dependencies. See env.sh for more context.
- uses: ./.github/actions/cache
@@ -149,7 +159,7 @@ jobs:
run: ./ci/before_script.sh
- name: Build nvim
- run: ./ci/run_tests.sh build_nvim
+ run: make
- if: "!cancelled()"
name: Determine if run should be aborted
@@ -157,8 +167,8 @@ jobs:
run: echo "status=${{ job.status }}" >> $GITHUB_OUTPUT
- if: success() || failure() && steps.abort_job.outputs.status == 'success'
- name: lintc
- run: make lintc
+ name: clint.py
+ run: cmake --build build --target lintc-clint
- if: success() || failure() && steps.abort_job.outputs.status == 'success'
name: check-single-includes
@@ -205,8 +215,6 @@ jobs:
env:
CC: ${{ matrix.cc }}
CI_OS_NAME: ${{ matrix.os }}
- # TEST_FILE: test/functional/core/startup_spec.lua
- # TEST_FILTER: foo
steps:
- uses: actions/checkout@v3
@@ -283,8 +291,6 @@ jobs:
DEPS_BUILD_DIR: ${{ github.workspace }}/nvim-deps
CACHE_NVIM_DEPS_DIR: ${{ github.workspace }}/nvim-deps
DEPS_PREFIX: ${{ github.workspace }}/nvim-deps/usr
- # TEST_FILE: test/functional/core/startup_spec.lua
- # TEST_FILTER: foo
name: windows (MSVC_64)
steps:
- uses: actions/checkout@v3
@@ -301,7 +307,7 @@ jobs:
- name: Build nvim
run: |
- cmake -B build -G Ninja -DCMAKE_BUILD_TYPE='RelWithDebInfo' -DDEPS_PREFIX="$env:DEPS_PREFIX"
+ cmake -B build -G Ninja -DCMAKE_BUILD_TYPE='RelWithDebInfo' -DDEPS_PREFIX="$env:DEPS_PREFIX" -DCI_BUILD=ON
cmake --build build
- name: Install test deps
diff --git a/.github/workflows/env.sh b/.github/workflows/env.sh
index 4a2217de89..42a355da44 100755
--- a/.github/workflows/env.sh
+++ b/.github/workflows/env.sh
@@ -18,7 +18,6 @@ VALGRIND_LOG=$GITHUB_WORKSPACE/build/log/valgrind-%p.log
CACHE_NVIM_DEPS_DIR=$HOME/.cache/nvim-deps
CACHE_MARKER=$HOME/.cache/nvim-deps/.ci_cache_marker
CACHE_UNCRUSTIFY=$HOME/.cache/uncrustify
-UNCRUSTIFY_VERSION=uncrustify-0.75.0
EOF
DEPS_CMAKE_FLAGS=
@@ -27,7 +26,6 @@ BUILD_FLAGS="CMAKE_FLAGS=-DCI_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_
case "$FLAVOR" in
asan)
- BUILD_FLAGS="$BUILD_FLAGS -DPREFER_LUA=ON"
cat <<EOF >> "$GITHUB_ENV"
CLANG_SANITIZER=ASAN_UBSAN
ASAN_OPTIONS=detect_leaks=1:check_initialization_order=1:log_path=$GITHUB_WORKSPACE/build/log/asan:intercept_tls_get_addr=0
@@ -45,13 +43,15 @@ EOF
BUILD_UCHAR=1
EOF
;;
- lint)
+ lintc)
# Re-enable once system deps are available
# BUILD_FLAGS="$BUILD_FLAGS -DLIBLUV_LIBRARY:FILEPATH=/usr/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)/lua/5.1/luv.so -DLIBLUV_INCLUDE_DIR:PATH=/usr/include/lua5.1"
- DEPS_CMAKE_FLAGS="$DEPS_CMAKE_FLAGS -DUSE_BUNDLED_LUV=ON"
- cat <<EOF >> "$GITHUB_ENV"
-USE_BUNDLED=OFF
-EOF
+
+ # Ideally all dependencies should external for this job, but some
+ # dependencies don't have the required version available. We use the
+ # bundled versions for these with the hopes of being able to remove them
+ # later on.
+ DEPS_CMAKE_FLAGS="$DEPS_CMAKE_FLAGS -DUSE_BUNDLED=OFF -DUSE_BUNDLED_LUV=ON -DUSE_BUNDLED_LIBVTERM=ON"
;;
functionaltest-lua)
BUILD_FLAGS="$BUILD_FLAGS -DPREFER_LUA=ON"
diff --git a/.github/workflows/news.yml b/.github/workflows/news.yml
index 46ac0ec02d..11807e9b42 100644
--- a/.github/workflows/news.yml
+++ b/.github/workflows/news.yml
@@ -22,9 +22,10 @@ jobs:
{
echo "
Pull request includes a new feature or a breaking change, but
- news.txt hasn't been updated yet. news.txt is our primary way of
- communicating changes to users so it's important to keep it up to
- date."
+ news.txt hasn't been updated yet. This is just a reminder
+ that news.txt may need to be updated. You can ignore this CI
+ failure if you think the change won't be of interest to
+ users."
exit 1
}
fi
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cadab62ce6..9c0d999ab8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -31,6 +31,11 @@ set(TOUCHES_DIR ${PROJECT_BINARY_DIR}/touches)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+find_program(CCACHE_PRG ccache)
+if(CCACHE_PRG)
+ set(CMAKE_C_COMPILER_LAUNCHER ${CMAKE_COMMAND} -E env CCACHE_SLOPPINESS=pch_defines,time_macros ${CCACHE_PRG})
+endif()
+
# Prefer our bundled versions of dependencies.
if(DEFINED ENV{DEPS_BUILD_DIR})
if(CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
@@ -112,11 +117,6 @@ endif()
message(STATUS "CMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}")
set_default_buildtype()
-if(CMAKE_BUILD_TYPE MATCHES Debug)
- set(DEBUG 1)
-else()
- set(DEBUG 0)
-endif()
# If not in a git repo (e.g., a tarball) these tokens define the complete
# version string, else they are combined with the result of `git describe`.
@@ -242,6 +242,17 @@ endif()
message(STATUS "Using Lua interpreter: ${LUA_PRG}")
+# Some of the code generation still relies on stable table ordering in order to
+# produce reproducible output - specifically the msgpack'ed data in
+# funcs_metadata.generated.h and ui_events_metadata.generated.h. This should
+# ideally be fixed in the generators, but until then as a workaround you may provide
+# a specific lua implementation that provides the needed stability by setting LUA_GEN_PRG:
+if(NOT LUA_GEN_PRG)
+ set(LUA_GEN_PRG "${LUA_PRG}" CACHE FILEPATH "Path to the lua used for code generation.")
+endif()
+
+message(STATUS "Using Lua interpreter for code generation: ${LUA_GEN_PRG}")
+
option(COMPILE_LUA "Pre-compile Lua sources into bytecode (for sources that are included in the binary)" ON)
if(COMPILE_LUA AND NOT WIN32)
@@ -331,18 +342,12 @@ install_helper(
FILES ${CMAKE_SOURCE_DIR}/src/man/nvim.1
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
-option(ENABLE_LIBICONV "enable libiconv" ON)
-if(ENABLE_LIBICONV)
- find_package(Iconv REQUIRED)
-endif()
-
#
# Go down the tree.
#
add_subdirectory(src/nvim)
get_directory_property(NVIM_VERSION_CFLAGS DIRECTORY src/nvim DEFINITION NVIM_VERSION_CFLAGS)
-add_subdirectory(test/includes)
add_subdirectory(cmake.config)
add_subdirectory(test/functional/fixtures) # compile test programs
add_subdirectory(runtime)
@@ -365,7 +370,7 @@ endif()
if(BUSTED_PRG)
get_target_property(TEST_INCLUDE_DIRS main_lib INTERFACE_INCLUDE_DIRECTORIES)
- set(UNITTEST_PREREQS nvim-test unittest-headers)
+ set(UNITTEST_PREREQS nvim)
set(FUNCTIONALTEST_PREREQS nvim printenv-test printargs-test shell-test pwsh-test streams-test tty-test ${GENERATED_HELP_TAGS})
set(BENCHMARK_PREREQS nvim tty-test)
@@ -375,6 +380,7 @@ if(BUSTED_PRG)
COMMAND ${CMAKE_COMMAND}
-DBUSTED_PRG=${BUSTED_PRG}
-DLUA_PRG=${LUA_PRG}
+ -DNVIM_PRG=$<TARGET_FILE:nvim>
-DWORKING_DIR=${CMAKE_CURRENT_SOURCE_DIR}
-DBUSTED_OUTPUT_TYPE=${BUSTED_OUTPUT_TYPE}
-DTEST_DIR=${CMAKE_CURRENT_SOURCE_DIR}/test
@@ -389,17 +395,9 @@ if(BUSTED_PRG)
message(WARNING "disabling unit tests: no Luajit FFI in ${LUA_PRG}")
endif()
- if(LUA_HAS_FFI)
- set(TEST_LIBNVIM_PATH $<TARGET_FILE:nvim-test>)
- else()
- set(TEST_LIBNVIM_PATH "")
- endif()
configure_file(
${CMAKE_SOURCE_DIR}/test/cmakeconfig/paths.lua.in
- ${CMAKE_BINARY_DIR}/test/cmakeconfig/paths.lua.gen)
- file(GENERATE
- OUTPUT ${CMAKE_BINARY_DIR}/test/cmakeconfig/paths.lua
- INPUT ${CMAKE_BINARY_DIR}/test/cmakeconfig/paths.lua.gen)
+ ${CMAKE_BINARY_DIR}/test/cmakeconfig/paths.lua)
add_custom_target(functionaltest
COMMAND ${CMAKE_COMMAND}
diff --git a/CMakePresets.json b/CMakePresets.json
index 76e38111ea..62abb2697f 100644
--- a/CMakePresets.json
+++ b/CMakePresets.json
@@ -1,5 +1,5 @@
{
- "version": 3,
+ "version": 6,
"configurePresets": [
{
"name": "base",
@@ -14,9 +14,7 @@
"cacheVariables": {
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
},
- "inherits": [
- "base"
- ]
+ "inherits": ["base"]
},
{
"name": "debug",
@@ -25,9 +23,7 @@
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
},
- "inherits": [
- "base"
- ]
+ "inherits": ["base"]
},
{
"name": "release",
@@ -36,9 +32,7 @@
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
},
- "inherits": [
- "base"
- ]
+ "inherits": ["base"]
},
{
"name": "windows-default",
@@ -54,9 +48,7 @@
},
"vendor": {
"microsoft.com/VisualStudioSettings/CMake/1.0": {
- "hostOS": [
- "Windows"
- ]
+ "hostOS": ["Windows"]
}
},
"condition": {
@@ -64,9 +56,7 @@
"lhs": "${hostSystemName}",
"rhs": "Windows"
},
- "inherits": [
- "base"
- ]
+ "inherits": ["base"]
},
{
"name": "iwyu",
@@ -75,9 +65,7 @@
"cacheVariables": {
"ENABLE_IWYU": "ON"
},
- "inherits": [
- "base"
- ]
+ "inherits": ["base"]
}
],
"buildPresets": [
@@ -106,5 +94,20 @@
"name": "iwyu",
"configurePreset": "iwyu"
}
+ ],
+ "workflowPresets": [
+ {
+ "name": "iwyu",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "iwyu"
+ },
+ {
+ "type": "build",
+ "name": "iwyu"
+ }
+ ]
+ }
]
}
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index d0af90d679..f1c7ca1cb3 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -42,6 +42,11 @@ Developer guidelines
make distclean
make # Nvim build system uses ninja automatically, if available.
```
+- Install `ccache` for faster rebuilds of Nvim. Nvim will use it automatically
+ if it's found. To disable caching use:
+ ```
+ CCACHE_DISABLE=true make
+ ```
Pull requests (PRs)
---------------------
@@ -246,10 +251,9 @@ You can lint a single file (but this will _not_ exclude legacy errors):
For managing includes in C files, use [include-what-you-use].
- [Install include-what-you-use][include-what-you-use-install]
-- To see which includes needs fixing just use the cmake preset `iwyu`:
+- To see which includes needs fixing use the cmake preset `iwyu`:
```
- cmake --preset iwyu
- cmake --build --preset iwyu
+ cmake --workflow --preset iwyu
```
- There's also a make target that automatically fixes the suggestions from
IWYU:
diff --git a/Makefile b/Makefile
index 110e9e3760..be1eef92de 100644
--- a/Makefile
+++ b/Makefile
@@ -66,8 +66,7 @@ ifeq ($(CMAKE_GENERATOR),Ninja)
endif
DEPS_CMAKE_FLAGS ?=
-# Back-compat: USE_BUNDLED_DEPS was the old name.
-USE_BUNDLED ?= $(USE_BUNDLED_DEPS)
+USE_BUNDLED ?=
ifneq (,$(USE_BUNDLED))
BUNDLED_CMAKE_FLAG := -DUSE_BUNDLED=$(USE_BUNDLED)
@@ -127,17 +126,19 @@ endif
src/nvim/testdir/%.vim: phony_force
+$(SINGLE_MAKE) -C src/nvim/testdir NVIM_PRG=$(NVIM_PRG) SCRIPTS= $(MAKEOVERRIDES) $(patsubst src/nvim/testdir/%.vim,%,$@)
-functionaltest functionaltest-lua unittest benchmark: | nvim
+functionaltest-lua: | nvim
$(BUILD_TOOL) -C build $@
-lintlua lintsh lintc check-single-includes generated-sources lintcommit lint formatc formatlua format: | build/.ran-cmake
+FORMAT=formatc formatlua format
+LINT=lintlua lintsh lintc check-single-includes lintcommit lint
+TEST=functionaltest unittest
+generated-sources benchmark uninstall $(FORMAT) $(LINT) $(TEST): | build/.ran-cmake
$(CMAKE_PRG) --build build --target $@
-test: functionaltest unittest
+test: $(TEST)
iwyu: build/.ran-cmake
- cmake --preset iwyu
- cmake --build --preset iwyu > build/iwyu.log
+ cmake --workflow --fresh --preset iwyu > build/iwyu.log
iwyu-fix-includes --only_re="src/nvim" --ignore_re="src/nvim/(auto|map.h|eval/encode.c)" --safe_headers < build/iwyu.log
cmake -B build -U ENABLE_IWYU
@@ -172,4 +173,4 @@ $(DEPS_BUILD_DIR)/%: phony_force
$(BUILD_TOOL) -C $(DEPS_BUILD_DIR) $(patsubst $(DEPS_BUILD_DIR)/%,%,$@)
endif
-.PHONY: test lintlua lintsh functionaltest unittest lint lintc clean distclean nvim libnvim cmake deps install appimage checkprefix lintcommit formatc formatlua format
+.PHONY: test clean distclean nvim libnvim cmake deps install appimage checkprefix benchmark uninstall $(FORMAT) $(LINT) $(TEST)
diff --git a/ci/common/build.sh b/ci/common/build.sh
index e30d0337b5..95972aab13 100644
--- a/ci/common/build.sh
+++ b/ci/common/build.sh
@@ -16,8 +16,7 @@ build_make() {
}
build_deps() {
- if test "${FUNCTIONALTEST}" = "functionaltest-lua" \
- || test "${CLANG_SANITIZER}" = "ASAN_UBSAN" ; then
+ if test "${FUNCTIONALTEST}" = "functionaltest-lua" ; then
DEPS_CMAKE_FLAGS="${DEPS_CMAKE_FLAGS} -DUSE_BUNDLED_LUA=ON"
fi
@@ -66,13 +65,6 @@ build_nvim() {
if ! top_make libnvim ; then
exit 1
fi
-
- if test "${FUNCTIONALTEST}" != "functionaltest-lua"; then
- echo "Building nvim-test."
- if ! top_make nvim-test ; then
- exit 1
- fi
- fi
fi
# Invoke nvim to trigger *San early.
diff --git a/cmake.config/CMakeLists.txt b/cmake.config/CMakeLists.txt
index 0ea2124401..6de86cbaf2 100644
--- a/cmake.config/CMakeLists.txt
+++ b/cmake.config/CMakeLists.txt
@@ -51,11 +51,6 @@ check_function_exists(getpwent HAVE_GETPWENT)
check_function_exists(getpwnam HAVE_GETPWNAM)
check_function_exists(getpwuid HAVE_GETPWUID)
check_function_exists(readv HAVE_READV)
-
-if(Iconv_FOUND)
- set(HAVE_ICONV 1)
-endif()
-
check_function_exists(opendir HAVE_OPENDIR)
check_function_exists(readlink HAVE_READLINK)
check_function_exists(setpgid HAVE_SETPGID)
diff --git a/cmake.config/config.h.in b/cmake.config/config.h.in
index f946fa6124..4669e42c0f 100644
--- a/cmake.config/config.h.in
+++ b/cmake.config/config.h.in
@@ -1,8 +1,6 @@
#ifndef AUTO_CONFIG_H
#define AUTO_CONFIG_H
-#cmakedefine DEBUG
-
#cmakedefine SIZEOF_INT @SIZEOF_INT@
#cmakedefine SIZEOF_INTMAX_T @SIZEOF_INTMAX_T@
#cmakedefine SIZEOF_INT32_T @SIZEOF_INT32_T@
@@ -24,7 +22,6 @@
#cmakedefine HAVE_GETPWENT
#cmakedefine HAVE_GETPWNAM
#cmakedefine HAVE_GETPWUID
-#cmakedefine HAVE_ICONV
#cmakedefine HAVE_LANGINFO_H
#cmakedefine HAVE_LOCALE_H
#cmakedefine HAVE_NL_LANGINFO_CODESET
diff --git a/cmake.config/iwyu/mapping.imp b/cmake.config/iwyu/mapping.imp
index 592c60b756..4e55aa9875 100644
--- a/cmake.config/iwyu/mapping.imp
+++ b/cmake.config/iwyu/mapping.imp
@@ -178,6 +178,8 @@
{ include: [ '"regexp_bt.h.generated.h"', private, '"nvim/regexp.h"', public ] },
{ include: [ '"ui_events_call.h.generated.h"', private, '"nvim/ui.h"', public ] },
{ include: [ '"ui_events_client.h.generated.h"', private, '"nvim/ui_client.h"', public ] },
+ { include: [ '"ui_events_remote.generated.h"', private, '"nvim/api/ui.h"', public ] },
+ { include: [ '"ui_events_remote.h.generated.h"', private, '"nvim/api/ui.h"', public ] },
# Def to normal headers: nvim/header_defs.h -> nvim/header.h
#
diff --git a/cmake.config/pathdef.c.in b/cmake.config/pathdef.c.in
index 6a8a2b205a..5d6dfa6b9f 100644
--- a/cmake.config/pathdef.c.in
+++ b/cmake.config/pathdef.c.in
@@ -4,5 +4,5 @@
char *default_vim_dir = "${CMAKE_INSTALL_FULL_DATAROOTDIR}/nvim";
char *default_vimruntime_dir = "";
char *default_lib_dir = "${CMAKE_INSTALL_FULL_LIBDIR}/nvim";
-char_u *compiled_user = (char_u *)"${USERNAME}";
-char_u *compiled_sys = (char_u *)"${HOSTNAME}";
+char *compiled_user = "${USERNAME}";
+char *compiled_sys = "${HOSTNAME}";
diff --git a/cmake.deps/CMakeLists.txt b/cmake.deps/CMakeLists.txt
index 5f0f9378e6..90ae91463d 100644
--- a/cmake.deps/CMakeLists.txt
+++ b/cmake.deps/CMakeLists.txt
@@ -12,13 +12,21 @@ list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" "${PROJECT_SOURCE_DI
include(CheckCCompilerFlag)
include(Util)
+set(DEPS_CMAKE_ARGS
+ -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
+ -DCMAKE_GENERATOR=${CMAKE_GENERATOR}
+ -DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
+ -DCMAKE_POSITION_INDEPENDENT_CODE=ON)
+
+set(DEPS_CMAKE_CACHE_ARGS -DCMAKE_OSX_ARCHITECTURES:STRING=${CMAKE_OSX_ARCHITECTURES})
+
+set_default_buildtype()
+
get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(NOT isMultiConfig)
- set(BUILD_TYPE_STRING -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE})
+ list(APPEND DEPS_CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE})
endif()
-set_default_buildtype()
-
set(DEFAULT_MAKE_CFLAGS CFLAGS+=-g)
check_c_compiler_flag(-Og HAS_OG_FLAG)
@@ -37,6 +45,8 @@ else()
set(DEPS_INSTALL_DIR "${CMAKE_BINARY_DIR}/usr" CACHE PATH "Dependencies install directory.")
endif()
+list(APPEND DEPS_CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR})
+
set(DEPS_BIN_DIR "${DEPS_INSTALL_DIR}/bin" CACHE PATH "Dependencies binary install directory.")
set(DEPS_LIB_DIR "${DEPS_INSTALL_DIR}/lib" CACHE PATH "Dependencies library install directory.")
set(DEPS_BUILD_DIR "${CMAKE_BINARY_DIR}/build" CACHE PATH "Dependencies build directory.")
@@ -75,14 +85,6 @@ endif()
if(UNIX)
find_program(MAKE_PRG NAMES gmake make)
- if(MAKE_PRG)
- execute_process(
- COMMAND "${MAKE_PRG}" --version
- OUTPUT_VARIABLE MAKE_VERSION_INFO)
- if(NOT "${OUTPUT_VARIABLE}" MATCHES ".*GNU.*")
- unset(MAKE_PRG)
- endif()
- endif()
if(NOT MAKE_PRG)
message(FATAL_ERROR "GNU Make is required to build the dependencies.")
else()
@@ -107,27 +109,16 @@ endif()
set(DEPS_C_COMPILER "${CMAKE_C_COMPILER}")
-if(CMAKE_CXX_COMPILER)
- set(DEPS_CXX_COMPILER "${CMAKE_CXX_COMPILER}")
-endif()
-
if(CMAKE_OSX_SYSROOT)
set(DEPS_C_COMPILER "${DEPS_C_COMPILER} -isysroot${CMAKE_OSX_SYSROOT}")
- if(DEPS_CXX_COMPILER)
- set(DEPS_CXX_COMPILER "${DEPS_CXX_COMPILER} -isysroot${CMAKE_OSX_SYSROOT}")
- endif()
endif()
if(CMAKE_OSX_ARCHITECTURES)
- string(REPLACE ";" "|" CMAKE_OSX_ARCHITECTURES_ALT_SEP "${CMAKE_OSX_ARCHITECTURES}")
# The LuaJIT build does not like being passed multiple `-arch` flags
# so we handle a universal build the old-fashioned way.
set(LUAJIT_C_COMPILER "${DEPS_C_COMPILER}")
foreach(ARCH IN LISTS CMAKE_OSX_ARCHITECTURES)
set(DEPS_C_COMPILER "${DEPS_C_COMPILER} -arch ${ARCH}")
- if(DEPS_CXX_COMPILER)
- set(DEPS_CXX_COMPILER "${DEPS_CXX_COMPILER} -arch ${ARCH}")
- endif()
endforeach()
endif()
@@ -140,7 +131,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
OUTPUT_STRIP_TRAILING_WHITESPACE)
set(CMAKE_OSX_DEPLOYMENT_TARGET "${MACOS_VERSION}")
endif()
- message("-- Using deployment target ${CMAKE_OSX_DEPLOYMENT_TARGET}")
+ message(STATUS "Using deployment target ${CMAKE_OSX_DEPLOYMENT_TARGET}")
endif()
include(ExternalProject)
@@ -153,8 +144,8 @@ set(MSGPACK_URL https://github.com/msgpack/msgpack-c/releases/download/c-4.0.0/m
set(MSGPACK_SHA256 420fe35e7572f2a168d17e660ef981a589c9cbe77faa25eb34a520e1fcc032c8)
# https://github.com/LuaJIT/LuaJIT/tree/v2.1
-set(LUAJIT_URL https://github.com/LuaJIT/LuaJIT/archive/a04480e311f93d3ceb2f92549cad3fffa38250ef.tar.gz)
-set(LUAJIT_SHA256 297e9c06d934753f9553fa7d1c1e43381e20094ed3289e0e145dd5f3c203a27e)
+set(LUAJIT_URL https://github.com/LuaJIT/LuaJIT/archive/d0e88930ddde28ff662503f9f20facf34f7265aa.tar.gz)
+set(LUAJIT_SHA256 aa354d1265814db5a1ee9dfff6049e19b148e1fd818f1ecfa4fcf2b19f6e4dd9)
set(LUA_URL https://www.lua.org/ftp/lua-5.1.5.tar.gz)
set(LUA_SHA256 2640fc56a795f29d28ef15e13c34a47e223960b0240e8cb0a82d9b0738695333)
@@ -162,14 +153,14 @@ set(LUA_SHA256 2640fc56a795f29d28ef15e13c34a47e223960b0240e8cb0a82d9b0738695333)
set(LUAROCKS_URL https://github.com/luarocks/luarocks/archive/v3.8.0.tar.gz)
set(LUAROCKS_SHA256 ab6612ca9ab87c6984871d2712d05525775e8b50172701a0a1cabddf76de2be7)
-set(UNIBILIUM_URL https://github.com/neovim/unibilium/archive/92d929f.tar.gz)
-set(UNIBILIUM_SHA256 29815283c654277ef77a3adcc8840db79ddbb20a0f0b0c8f648bd8cd49a02e4b)
+set(UNIBILIUM_URL https://github.com/neovim/unibilium/archive/d72c3598e7ac5d1ebf86ee268b8b4ed95c0fa628.tar.gz)
+set(UNIBILIUM_SHA256 9c4747c862ab5e3076dcf8fa8f0ea7a6b50f20ec5905618b9536655596797487)
set(LIBTERMKEY_URL https://www.leonerd.org.uk/code/libtermkey/libtermkey-0.22.tar.gz)
set(LIBTERMKEY_SHA256 6945bd3c4aaa83da83d80a045c5563da4edd7d0374c62c0d35aec09eb3014600)
-set(LIBVTERM_URL https://www.leonerd.org.uk/code/libvterm/libvterm-0.3.tar.gz)
-set(LIBVTERM_SHA256 61eb0d6628c52bdf02900dfd4468aa86a1a7125228bab8a67328981887483358)
+set(LIBVTERM_URL https://www.leonerd.org.uk/code/libvterm/libvterm-0.3.1.tar.gz)
+set(LIBVTERM_SHA256 25a8ad9c15485368dfd0a8a9dca1aec8fea5c27da3fa74ec518d5d3787f0c397)
set(LUV_VERSION 1.44.2-1)
set(LUV_URL https://github.com/luvit/luv/archive/80c8c00baebe3e994d1616d4b54097c2d6e14834.tar.gz)
@@ -203,11 +194,11 @@ set(TREESITTER_LUA_SHA256 930d0370dc15b66389869355c8e14305b9ba7aafd36edbfdb468c8
set(TREESITTER_VIM_URL https://github.com/vigoux/tree-sitter-viml/archive/55ff1b080c09edeced9b748cf4c16d0b49d17fb9.tar.gz)
set(TREESITTER_VIM_SHA256 1b1cd39e33c8fb02fa7fe3977e844883c2a8508a7edd621f2d21e39a9aeefa92)
-set(TREESITTER_HELP_URL https://github.com/neovim/tree-sitter-vimdoc/archive/ce20f13c3f12506185754888feaae3f2ad54c287.tar.gz)
-set(TREESITTER_HELP_SHA256 2b8b166438cce66064aab56a744430b1f44871f43e47f70b51246d14bb826609)
+set(TREESITTER_HELP_URL https://github.com/neovim/tree-sitter-vimdoc/archive/v1.3.0.tar.gz)
+set(TREESITTER_HELP_SHA256 f33f6d49c7d71feb2fd68ef2b2684da150f9f8e486ad9726213631d673942331)
-set(TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/v0.20.7.tar.gz)
-set(TREESITTER_SHA256 b355e968ec2d0241bbd96748e00a9038f83968f85d822ecb9940cbe4c42e182e)
+set(TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/eb970a83a107cbaba52e31588355c0b09b3a308a.tar.gz)
+set(TREESITTER_SHA256 58063721182f182fb9ec5481794f2ba594e52d6c2497e0214570535054dfc78d)
if(USE_BUNDLED_UNIBILIUM)
include(BuildUnibilium)
diff --git a/cmake.deps/cmake/BuildGettext.cmake b/cmake.deps/cmake/BuildGettext.cmake
index 4ba1f46d2e..1f9fd38702 100644
--- a/cmake.deps/cmake/BuildGettext.cmake
+++ b/cmake.deps/cmake/BuildGettext.cmake
@@ -10,13 +10,10 @@ if(MSVC)
PATCH_COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/cmake/GettextCMakeLists.txt
${DEPS_BUILD_DIR}/src/gettext/CMakeLists.txt
- CMAKE_ARGS
- -DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
- ${BUILD_TYPE_STRING}
- -DCMAKE_GENERATOR=${CMAKE_GENERATOR}
- -DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
+ CMAKE_ARGS ${DEPS_CMAKE_ARGS}
-DLIBICONV_INCLUDE_DIRS=${DEPS_INSTALL_DIR}/include
- -DLIBICONV_LIBRARIES=${DEPS_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}libcharset${CMAKE_STATIC_LIBRARY_SUFFIX}$<SEMICOLON>${DEPS_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}libiconv${CMAKE_STATIC_LIBRARY_SUFFIX})
+ -DLIBICONV_LIBRARIES=${DEPS_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}libcharset${CMAKE_STATIC_LIBRARY_SUFFIX}$<SEMICOLON>${DEPS_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}libiconv${CMAKE_STATIC_LIBRARY_SUFFIX}
+ CMAKE_CACHE_ARGS ${DEPS_CMAKE_CACHE_ARGS})
else()
message(FATAL_ERROR "Trying to build gettext in an unsupported system ${CMAKE_SYSTEM_NAME}/${CMAKE_C_COMPILER_ID}")
endif()
diff --git a/cmake.deps/cmake/BuildLibiconv.cmake b/cmake.deps/cmake/BuildLibiconv.cmake
index 382aae3df7..4b9c07ed6c 100644
--- a/cmake.deps/cmake/BuildLibiconv.cmake
+++ b/cmake.deps/cmake/BuildLibiconv.cmake
@@ -10,11 +10,8 @@ if(MSVC)
PATCH_COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/cmake/LibiconvCMakeLists.txt
${DEPS_BUILD_DIR}/src/libiconv/CMakeLists.txt
- CMAKE_ARGS
- -DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
- ${BUILD_TYPE_STRING}
- -DCMAKE_GENERATOR=${CMAKE_GENERATOR}
- -DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM})
+ CMAKE_ARGS ${DEPS_CMAKE_ARGS}
+ CMAKE_CACHE_ARGS ${DEPS_CMAKE_CACHE_ARGS})
else()
message(FATAL_ERROR "Trying to build libiconv in an unsupported system ${CMAKE_SYSTEM_NAME}/${CMAKE_C_COMPILER_ID}")
endif()
diff --git a/cmake.deps/cmake/BuildLibtermkey.cmake b/cmake.deps/cmake/BuildLibtermkey.cmake
index 1e0fb5d36a..6457a864ba 100644
--- a/cmake.deps/cmake/BuildLibtermkey.cmake
+++ b/cmake.deps/cmake/BuildLibtermkey.cmake
@@ -1,27 +1,3 @@
-if(WIN32)
- set(LIBTERMKEY_CONFIGURE_COMMAND ${CMAKE_COMMAND} -E copy
- ${CMAKE_CURRENT_SOURCE_DIR}/cmake/libtermkeyCMakeLists.txt
- ${DEPS_BUILD_DIR}/src/libtermkey/CMakeLists.txt
- COMMAND ${CMAKE_COMMAND} ${DEPS_BUILD_DIR}/src/libtermkey
- -DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
- ${BUILD_TYPE_STRING}
- # Hack to avoid -rdynamic in Mingw
- -DCMAKE_SHARED_LIBRARY_LINK_C_FLAGS=""
- -DCMAKE_GENERATOR=${CMAKE_GENERATOR}
- -DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
- -DUNIBILIUM_INCLUDE_DIRS=${DEPS_INSTALL_DIR}/include
- -DUNIBILIUM_LIBRARIES=${DEPS_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}unibilium${CMAKE_STATIC_LIBRARY_SUFFIX})
- set(LIBTERMKEY_BUILD_COMMAND ${CMAKE_COMMAND} --build . --config $<CONFIG>)
- set(LIBTERMKEY_INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config $<CONFIG>)
-else()
- find_package(PkgConfig REQUIRED)
-
- set(LIBTERMKEY_BUILD_COMMAND "" BUILD_IN_SOURCE 1)
- set(LIBTERMKEY_INSTALL_COMMAND ${MAKE_PRG} CC=${DEPS_C_COMPILER}
- PREFIX=${DEPS_INSTALL_DIR} PKG_CONFIG_PATH=${DEPS_LIB_DIR}/pkgconfig
- CFLAGS=-fPIC LDFLAGS+=-static ${DEFAULT_MAKE_CFLAGS} install)
-endif()
-
if(USE_EXISTING_SRC_DIR)
unset(LIBTERMKEY_URL)
endif()
@@ -30,8 +6,13 @@ ExternalProject_Add(libtermkey
URL_HASH SHA256=${LIBTERMKEY_SHA256}
DOWNLOAD_NO_PROGRESS TRUE
DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/libtermkey
- CONFIGURE_COMMAND "${LIBTERMKEY_CONFIGURE_COMMAND}"
- BUILD_COMMAND "${LIBTERMKEY_BUILD_COMMAND}"
- INSTALL_COMMAND "${LIBTERMKEY_INSTALL_COMMAND}")
+ PATCH_COMMAND ${CMAKE_COMMAND} -E copy
+ ${CMAKE_CURRENT_SOURCE_DIR}/cmake/libtermkeyCMakeLists.txt
+ ${DEPS_BUILD_DIR}/src/libtermkey/CMakeLists.txt
+ CMAKE_ARGS ${DEPS_CMAKE_ARGS}
+ -DCMAKE_SHARED_LIBRARY_LINK_C_FLAGS="" # Hack to avoid -rdynamic in Mingw
+ -DUNIBILIUM_INCLUDE_DIRS=${DEPS_INSTALL_DIR}/include
+ -DUNIBILIUM_LIBRARIES=${DEPS_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}unibilium${CMAKE_STATIC_LIBRARY_SUFFIX}
+ CMAKE_CACHE_ARGS ${DEPS_CMAKE_CACHE_ARGS})
list(APPEND THIRD_PARTY_DEPS libtermkey)
diff --git a/cmake.deps/cmake/BuildLibuv.cmake b/cmake.deps/cmake/BuildLibuv.cmake
index c21e166d95..eb88458644 100644
--- a/cmake.deps/cmake/BuildLibuv.cmake
+++ b/cmake.deps/cmake/BuildLibuv.cmake
@@ -5,15 +5,11 @@ ExternalProject_Add(libuv
URL ${LIBUV_URL}
URL_HASH SHA256=${LIBUV_SHA256}
DOWNLOAD_NO_PROGRESS TRUE
- CMAKE_ARGS
- -DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
+ DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/libuv
+ CMAKE_ARGS ${DEPS_CMAKE_ARGS}
-DCMAKE_INSTALL_LIBDIR=lib
-DBUILD_TESTING=OFF
- -DCMAKE_POSITION_INDEPENDENT_CODE=ON
-DLIBUV_BUILD_SHARED=OFF
- ${BUILD_TYPE_STRING}
- CMAKE_CACHE_ARGS
- -DCMAKE_OSX_ARCHITECTURES:STRING=${CMAKE_OSX_ARCHITECTURES}
- DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/libuv)
+ CMAKE_CACHE_ARGS ${DEPS_CMAKE_CACHE_ARGS})
list(APPEND THIRD_PARTY_DEPS libuv)
diff --git a/cmake.deps/cmake/BuildLibvterm.cmake b/cmake.deps/cmake/BuildLibvterm.cmake
index dffa545638..b75987eb24 100644
--- a/cmake.deps/cmake/BuildLibvterm.cmake
+++ b/cmake.deps/cmake/BuildLibvterm.cmake
@@ -1,29 +1,3 @@
-if(WIN32)
- set(LIBVTERM_CONFIGURE_COMMAND ${CMAKE_COMMAND} -E copy
- ${CMAKE_CURRENT_SOURCE_DIR}/cmake/LibvtermCMakeLists.txt
- ${DEPS_BUILD_DIR}/src/libvterm/CMakeLists.txt
- COMMAND ${CMAKE_COMMAND} -E copy
- ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Libvterm-tbl2inc_c.cmake
- ${DEPS_BUILD_DIR}/src/libvterm/tbl2inc_c.cmake
- COMMAND ${CMAKE_COMMAND} ${DEPS_BUILD_DIR}/src/libvterm
- -DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
- -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
- -DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
- -DCMAKE_GENERATOR=${CMAKE_GENERATOR})
- if(NOT MSVC)
- list(APPEND LIBVTERM_CONFIGURE_COMMAND "-DCMAKE_C_FLAGS:STRING=-fPIC")
- endif()
- set(LIBVTERM_BUILD_COMMAND ${CMAKE_COMMAND} --build . --config $<CONFIG>)
- set(LIBVTERM_INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config $<CONFIG>)
-else()
- set(LIBVTERM_INSTALL_COMMAND ${MAKE_PRG} CC=${DEPS_C_COMPILER}
- PREFIX=${DEPS_INSTALL_DIR}
- CFLAGS=-fPIC
- LDFLAGS+=-static
- ${DEFAULT_MAKE_CFLAGS}
- install)
-endif()
-
if(USE_EXISTING_SRC_DIR)
unset(LIBVTERM_URL)
endif()
@@ -32,9 +6,10 @@ ExternalProject_Add(libvterm
URL_HASH SHA256=${LIBVTERM_SHA256}
DOWNLOAD_NO_PROGRESS TRUE
DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/libvterm
- BUILD_IN_SOURCE 1
- CONFIGURE_COMMAND "${LIBVTERM_CONFIGURE_COMMAND}"
- BUILD_COMMAND "${LIBVTERM_BUILD_COMMAND}"
- INSTALL_COMMAND "${LIBVTERM_INSTALL_COMMAND}")
+ PATCH_COMMAND ${CMAKE_COMMAND} -E copy
+ ${CMAKE_CURRENT_SOURCE_DIR}/cmake/LibvtermCMakeLists.txt
+ ${DEPS_BUILD_DIR}/src/libvterm/CMakeLists.txt
+ CMAKE_ARGS ${DEPS_CMAKE_ARGS}
+ CMAKE_CACHE_ARGS ${DEPS_CMAKE_CACHE_ARGS})
list(APPEND THIRD_PARTY_DEPS libvterm)
diff --git a/cmake.deps/cmake/BuildLuarocks.cmake b/cmake.deps/cmake/BuildLuarocks.cmake
index d0b4a8e7d1..b84ce34d45 100644
--- a/cmake.deps/cmake/BuildLuarocks.cmake
+++ b/cmake.deps/cmake/BuildLuarocks.cmake
@@ -148,7 +148,7 @@ if(USE_BUNDLED_BUSTED)
set(LUACHECK_EXE "${DEPS_BIN_DIR}/luacheck")
endif()
add_custom_command(OUTPUT ${BUSTED_EXE}
- COMMAND ${LUAROCKS_BINARY} build busted 2.0.0 ${LUAROCKS_BUILDARGS}
+ COMMAND ${LUAROCKS_BINARY} build busted 2.1.1 ${LUAROCKS_BUILDARGS}
DEPENDS penlight)
add_custom_target(busted DEPENDS ${BUSTED_EXE})
diff --git a/cmake.deps/cmake/BuildLuv.cmake b/cmake.deps/cmake/BuildLuv.cmake
index 1a599a9ee2..38c0503c5b 100644
--- a/cmake.deps/cmake/BuildLuv.cmake
+++ b/cmake.deps/cmake/BuildLuv.cmake
@@ -1,13 +1,7 @@
-set(LUV_SRC_DIR ${DEPS_BUILD_DIR}/src/luv)
set(LUV_INCLUDE_FLAGS
"-I${DEPS_INSTALL_DIR}/include -I${DEPS_INSTALL_DIR}/include/luajit-2.1")
-set(LUV_CONFIGURE_COMMAND_COMMON
- ${CMAKE_COMMAND} ${LUV_SRC_DIR}
- -DCMAKE_GENERATOR=${CMAKE_GENERATOR}
- ${BUILD_TYPE_STRING}
- -DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
- -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES_ALT_SEP}
+set(LUV_CMAKE_ARGS
-DLUA_BUILD_TYPE=System
-DLUA_COMPAT53_DIR=${DEPS_BUILD_DIR}/src/lua-compat-5.3
-DWITH_SHARED_LIBUV=ON
@@ -16,43 +10,29 @@ set(LUV_CONFIGURE_COMMAND_COMMON
-DBUILD_MODULE=OFF)
if(USE_BUNDLED_LUAJIT)
- list(APPEND LUV_CONFIGURE_COMMAND_COMMON -DWITH_LUA_ENGINE=LuaJit)
+ list(APPEND LUV_CMAKE_ARGS -DWITH_LUA_ENGINE=LuaJit)
elseif(USE_BUNDLED_LUA)
- list(APPEND LUV_CONFIGURE_COMMAND_COMMON -DWITH_LUA_ENGINE=Lua)
+ list(APPEND LUV_CMAKE_ARGS -DWITH_LUA_ENGINE=Lua)
else()
find_package(LuaJit)
if(LUAJIT_FOUND)
- list(APPEND LUV_CONFIGURE_COMMAND_COMMON -DWITH_LUA_ENGINE=LuaJit)
+ list(APPEND LUV_CMAKE_ARGS -DWITH_LUA_ENGINE=LuaJit)
else()
- list(APPEND LUV_CONFIGURE_COMMAND_COMMON -DWITH_LUA_ENGINE=Lua)
+ list(APPEND LUV_CMAKE_ARGS -DWITH_LUA_ENGINE=Lua)
endif()
endif()
if(USE_BUNDLED_LIBUV)
- set(LUV_CONFIGURE_COMMAND_COMMON
- ${LUV_CONFIGURE_COMMAND_COMMON}
+ list(APPEND LUV_CMAKE_ARGS
-DCMAKE_PREFIX_PATH=${DEPS_INSTALL_DIR}
-DLIBUV_LIBRARIES=uv_a)
endif()
-if(MSVC)
- set(LUV_CONFIGURE_COMMAND
- ${LUV_CONFIGURE_COMMAND_COMMON}
- -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
- -DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
- "-DCMAKE_C_FLAGS:STRING=${LUV_INCLUDE_FLAGS}"
- # Make sure we use the same generator, otherwise we may
- # accidentally end up using different MSVC runtimes
- -DCMAKE_GENERATOR=${CMAKE_GENERATOR})
-else()
- set(LUV_CONFIGURE_COMMAND
- ${LUV_CONFIGURE_COMMAND_COMMON}
- -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
- "-DCMAKE_C_FLAGS:STRING=${LUV_INCLUDE_FLAGS} -fPIC")
- if(CMAKE_GENERATOR MATCHES "Unix Makefiles" AND
- (CMAKE_SYSTEM_NAME MATCHES ".*BSD" OR CMAKE_SYSTEM_NAME MATCHES "DragonFly"))
- set(LUV_CONFIGURE_COMMAND ${LUV_CONFIGURE_COMMAND} -DCMAKE_MAKE_PROGRAM=gmake)
- endif()
+list(APPEND LUV_CMAKE_ARGS
+ "-DCMAKE_C_FLAGS:STRING=${LUV_INCLUDE_FLAGS}")
+if(CMAKE_GENERATOR MATCHES "Unix Makefiles" AND
+ (CMAKE_SYSTEM_NAME MATCHES ".*BSD" OR CMAKE_SYSTEM_NAME MATCHES "DragonFly"))
+ list(APPEND LUV_CMAKE_ARGS -DCMAKE_MAKE_PROGRAM=gmake)
endif()
if(USE_EXISTING_SRC_DIR)
@@ -77,10 +57,8 @@ ExternalProject_Add(luv-static
DOWNLOAD_NO_PROGRESS TRUE
DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/luv
SOURCE_DIR ${DEPS_BUILD_DIR}/src/luv
- CONFIGURE_COMMAND "${LUV_CONFIGURE_COMMAND}"
- BUILD_COMMAND ${CMAKE_COMMAND} --build . --config $<CONFIG>
- INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config $<CONFIG>
- LIST_SEPARATOR |)
+ CMAKE_ARGS ${DEPS_CMAKE_ARGS} ${LUV_CMAKE_ARGS}
+ CMAKE_CACHE_ARGS ${DEPS_CMAKE_CACHE_ARGS})
list(APPEND THIRD_PARTY_DEPS luv-static)
if(USE_BUNDLED_LUAJIT)
diff --git a/cmake.deps/cmake/BuildMsgpack.cmake b/cmake.deps/cmake/BuildMsgpack.cmake
index 3197ec45a1..431420fb62 100644
--- a/cmake.deps/cmake/BuildMsgpack.cmake
+++ b/cmake.deps/cmake/BuildMsgpack.cmake
@@ -1,25 +1,3 @@
-set(MSGPACK_CMAKE_ARGS
- -DMSGPACK_BUILD_TESTS=OFF
- -DMSGPACK_BUILD_EXAMPLES=OFF
- -DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
- -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
- -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES_ALT_SEP}
- "-DCMAKE_C_FLAGS:STRING=-fPIC"
- -DCMAKE_GENERATOR=${CMAKE_GENERATOR})
-
-if(MSVC)
- set(MSGPACK_CMAKE_ARGS
- -DMSGPACK_BUILD_TESTS=OFF
- -DMSGPACK_BUILD_EXAMPLES=OFF
- -DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
- -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
- -DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
- ${BUILD_TYPE_STRING}
- # Make sure we use the same generator, otherwise we may
- # accidentally end up using different MSVC runtimes
- -DCMAKE_GENERATOR=${CMAKE_GENERATOR})
-endif()
-
if(USE_EXISTING_SRC_DIR)
unset(MSGPACK_URL)
endif()
@@ -28,7 +6,9 @@ ExternalProject_Add(msgpack
URL_HASH SHA256=${MSGPACK_SHA256}
DOWNLOAD_NO_PROGRESS TRUE
DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/msgpack
- CMAKE_ARGS "${MSGPACK_CMAKE_ARGS}"
- LIST_SEPARATOR |)
+ CMAKE_ARGS ${DEPS_CMAKE_ARGS}
+ -DMSGPACK_BUILD_TESTS=OFF
+ -DMSGPACK_BUILD_EXAMPLES=OFF
+ CMAKE_CACHE_ARGS ${DEPS_CMAKE_CACHE_ARGS})
list(APPEND THIRD_PARTY_DEPS msgpack)
diff --git a/cmake.deps/cmake/BuildTreesitter.cmake b/cmake.deps/cmake/BuildTreesitter.cmake
index c3ea02014f..d906e6aa59 100644
--- a/cmake.deps/cmake/BuildTreesitter.cmake
+++ b/cmake.deps/cmake/BuildTreesitter.cmake
@@ -1,22 +1,3 @@
-if(MSVC)
- set(TREESITTER_CONFIGURE_COMMAND ${CMAKE_COMMAND} -E copy
- ${CMAKE_CURRENT_SOURCE_DIR}/cmake/TreesitterCMakeLists.txt
- ${DEPS_BUILD_DIR}/src/tree-sitter/CMakeLists.txt
- COMMAND ${CMAKE_COMMAND} ${DEPS_BUILD_DIR}/src/tree-sitter/CMakeLists.txt
- -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
- -DCMAKE_GENERATOR=${CMAKE_GENERATOR}
- -DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
- ${BUILD_TYPE_STRING}
- -DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR})
- set(TREESITTER_BUILD_COMMAND ${CMAKE_COMMAND} --build . --config $<CONFIG>)
- set(TREESITTER_INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config $<CONFIG>)
-else()
- set(TS_CFLAGS "-O3 -Wall -Wextra")
- set(TREESITTER_BUILD_COMMAND ${MAKE_PRG} CC=${DEPS_C_COMPILER} CFLAGS=${TS_CFLAGS})
- set(TREESITTER_INSTALL_COMMAND
- ${MAKE_PRG} CC=${DEPS_C_COMPILER} PREFIX=${DEPS_INSTALL_DIR} install)
-endif()
-
if(USE_EXISTING_SRC_DIR)
unset(TREESITTER_URL)
endif()
@@ -26,9 +7,10 @@ ExternalProject_Add(tree-sitter
DOWNLOAD_NO_PROGRESS TRUE
DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/tree-sitter
INSTALL_DIR ${DEPS_INSTALL_DIR}
- BUILD_IN_SOURCE 1
- CONFIGURE_COMMAND "${TREESITTER_CONFIGURE_COMMAND}"
- BUILD_COMMAND "${TREESITTER_BUILD_COMMAND}"
- INSTALL_COMMAND "${TREESITTER_INSTALL_COMMAND}")
+ PATCH_COMMAND ${CMAKE_COMMAND} -E copy
+ ${CMAKE_CURRENT_SOURCE_DIR}/cmake/TreesitterCMakeLists.txt
+ ${DEPS_BUILD_DIR}/src/tree-sitter/CMakeLists.txt
+ CMAKE_ARGS ${DEPS_CMAKE_ARGS}
+ CMAKE_CACHE_ARGS ${DEPS_CMAKE_CACHE_ARGS})
list(APPEND THIRD_PARTY_DEPS tree-sitter)
diff --git a/cmake.deps/cmake/BuildTreesitterParsers.cmake b/cmake.deps/cmake/BuildTreesitterParsers.cmake
index ead039aae6..d62b19d97d 100644
--- a/cmake.deps/cmake/BuildTreesitterParsers.cmake
+++ b/cmake.deps/cmake/BuildTreesitterParsers.cmake
@@ -8,14 +8,12 @@ function(BuildTSParser LANG TS_URL TS_SHA256 TS_CMAKE_FILE)
URL_HASH SHA256=${TS_SHA256}
DOWNLOAD_NO_PROGRESS TRUE
DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/${NAME}
- CMAKE_CACHE_ARGS
- -DCMAKE_OSX_ARCHITECTURES:STRING=${CMAKE_OSX_ARCHITECTURES}
PATCH_COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/cmake/${TS_CMAKE_FILE}
${DEPS_BUILD_DIR}/src/${NAME}/CMakeLists.txt
- CMAKE_ARGS
- -DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
- -DPARSERLANG=${LANG})
+ CMAKE_ARGS ${DEPS_CMAKE_ARGS}
+ -DPARSERLANG=${LANG}
+ CMAKE_CACHE_ARGS ${DEPS_CMAKE_CACHE_ARGS})
endfunction()
BuildTSParser(c ${TREESITTER_C_URL} ${TREESITTER_C_SHA256} TreesitterParserCMakeLists.txt)
diff --git a/cmake.deps/cmake/BuildUnibilium.cmake b/cmake.deps/cmake/BuildUnibilium.cmake
index cc56499edb..9a8caf89d1 100644
--- a/cmake.deps/cmake/BuildUnibilium.cmake
+++ b/cmake.deps/cmake/BuildUnibilium.cmake
@@ -1,21 +1,3 @@
-if(WIN32)
- set(UNIBILIUM_CONFIGURE_COMMAND ${CMAKE_COMMAND} -E copy
- ${CMAKE_CURRENT_SOURCE_DIR}/cmake/UnibiliumCMakeLists.txt
- ${DEPS_BUILD_DIR}/src/unibilium/CMakeLists.txt
- COMMAND ${CMAKE_COMMAND} ${DEPS_BUILD_DIR}/src/unibilium
- -DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
- -DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
- ${BUILD_TYPE_STRING}
- -DCMAKE_GENERATOR=${CMAKE_GENERATOR})
- set(UNIBILIUM_BUILD_COMMAND ${CMAKE_COMMAND} --build . --config $<CONFIG>)
- set(UNIBILIUM_INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config $<CONFIG>)
-else()
- set(UNIBILIUM_BUILD_COMMAND ${MAKE_PRG} CC=${DEPS_C_COMPILER}
- PREFIX=${DEPS_INSTALL_DIR} CFLAGS=-fPIC LDFLAGS+=-static
- BUILD_IN_SOURCE 1)
- set(UNIBILIUM_INSTALL_COMMAND ${MAKE_PRG} PREFIX=${DEPS_INSTALL_DIR} install)
-endif()
-
if(USE_EXISTING_SRC_DIR)
unset(UNIBILIUM_URL)
endif()
@@ -24,8 +6,7 @@ ExternalProject_Add(unibilium
URL_HASH SHA256=${UNIBILIUM_SHA256}
DOWNLOAD_NO_PROGRESS TRUE
DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/unibilium
- CONFIGURE_COMMAND "${UNIBILIUM_CONFIGURE_COMMAND}"
- BUILD_COMMAND "${UNIBILIUM_BUILD_COMMAND}"
- INSTALL_COMMAND "${UNIBILIUM_INSTALL_COMMAND}")
+ CMAKE_ARGS ${DEPS_CMAKE_ARGS}
+ CMAKE_CACHE_ARGS ${DEPS_CMAKE_CACHE_ARGS})
list(APPEND THIRD_PARTY_DEPS unibilium)
diff --git a/cmake.deps/cmake/Libvterm-tbl2inc_c.cmake b/cmake.deps/cmake/Libvterm-tbl2inc_c.cmake
deleted file mode 100644
index 32d973680f..0000000000
--- a/cmake.deps/cmake/Libvterm-tbl2inc_c.cmake
+++ /dev/null
@@ -1,163 +0,0 @@
-cmake_minimum_required(VERSION 3.10)
-
-set(HEX_ALPHABET "0123456789abcdef")
-
-function(ConvertToHex dec hex)
- while(dec GREATER 0)
- math(EXPR _val "${dec} % 16")
- math(EXPR dec "${dec} / 16")
- string(SUBSTRING ${HEX_ALPHABET} ${_val} 1 _val)
- set(_res "${_val}${_res}")
- endwhile()
- # Pad the result with the number of zeros
- # specified by the optional third argument
- if(${ARGC} EQUAL 3)
- set(padding ${ARGV2})
- string(LENGTH ${_res} _resLen)
- if(_resLen LESS ${padding})
- math(EXPR _neededPadding "${padding} - ${_resLen}")
- foreach(i RANGE 1 ${_neededPadding})
- set(_res "0${_res}")
- endforeach()
- endif()
- endif()
- set(${hex} "0x${_res}" PARENT_SCOPE)
-endfunction()
-
-function(ConvertFromHex hex dec)
- string(TOLOWER ${hex} hex)
- string(LENGTH "${hex}" _strlen)
- set(_res 0)
- while(_strlen GREATER 0)
- math(EXPR _res "${_res} * 16")
- string(SUBSTRING "${hex}" 0 1 NIBBLE)
- string(SUBSTRING "${hex}" 1 -1 hex)
- string(FIND ${HEX_ALPHABET} ${NIBBLE} value)
- if(value EQUAL -1)
- message(FATAL_ERROR "Invalid hex character '${NIBBLE}'")
- endif()
- math(EXPR _res "${_res} + ${value}")
- string(LENGTH "${hex}" _strlen)
- endwhile()
- set(${dec} ${_res} PARENT_SCOPE)
-endfunction()
-
-# Based on http://www.json.org/JSON_checker/utf8_decode.c
-function(DecodeUtf8 hexBytes codePoint)
- string(SUBSTRING ${hexBytes} 0 2 hexByte1)
- ConvertFromHex(${hexByte1} byte1)
- # Zero continuations (0 to 127)
- math(EXPR out "${byte1} & 128")
- if(out EQUAL 0)
- set(${codePoint} ${byte1} PARENT_SCOPE)
- return()
- endif()
- # One continuation (128 to 2047)
- math(EXPR out "${byte1} & 224")
- if(out EQUAL 192)
- string(SUBSTRING ${hexBytes} 2 2 hexByte2)
- ConvertFromHex(${hexByte2} byte2)
- math(EXPR result "((${byte1} & 31) << 6) | ${byte2}")
- if(result GREATER 127)
- set(${codePoint} ${result} PARENT_SCOPE)
- return()
- endif()
- else()
- # Two continuations (2048 to 55295 and 57344 to 65535)
- math(EXPR result "${byte1} & 240")
- if(result EQUAL 224)
- string(SUBSTRING ${hexBytes} 2 2 hexByte2)
- string(SUBSTRING ${hexBytes} 4 2 hexByte3)
- ConvertFromHex(${hexByte2} byte2)
- ConvertFromHex(${hexByte3} byte3)
- math(EXPR result "${byte2} | ${byte3}")
- if(result GREATER -1)
- math(EXPR result "((${byte1} & 15) << 12) | (${byte2} << 6) | ${byte3}")
- if((result GREATER 2047) AND (result LESS 55296 OR result GREATER 57343))
- set(${codePoint} ${result} PARENT_SCOPE)
- return()
- endif()
- endif()
- else()
- # Three continuations (65536 to 1114111)
- math(EXPR result "${byte1} & 248")
- if(result EQUAL 224)
- string(SUBSTRING ${hexBytes} 2 2 hexByte2)
- string(SUBSTRING ${hexBytes} 4 2 hexByte3)
- string(SUBSTRING ${hexBytes} 6 2 hexByte4)
- ConvertFromHex(${hexByte2} byte2)
- ConvertFromHex(${hexByte3} byte3)
- ConvertFromHex(${hexByte4} byte4)
- math(EXPR result "${byte2} | ${byte3} | ${byte4}")
- if(result GREATER -1)
- math(EXPR result "((c & 7) << 18) | (c1 << 12) | (c2 << 6) | c3")
- if((result GREATER 65535) AND (result LESS 1114112))
- set(${codePoint} ${result} PARENT_SCOPE)
- return()
- endif()
- endif()
- endif()
- endif()
- endif()
- message(FATAL_ERROR "Invalid UTF-8 encoding")
-endfunction()
-
-set(inputFile ${CMAKE_ARGV3})
-set(outputFile ${CMAKE_ARGV4})
-# Get the file contents in text and hex-encoded format because
-# CMake doesn't provide functions for converting between the two
-file(READ "${inputFile}" contents)
-file(READ "${inputFile}" hexContents HEX)
-
-# Convert the text contents into a list of lines by escaping
-# the list separator ';' and then replacing new line characters
-# with the list separator
-string(REGEX REPLACE ";" "\\\\;" contents ${contents})
-string(REGEX REPLACE "\n" ";" contents ${contents})
-
-get_filename_component(encname ${inputFile} NAME_WE)
-set(output
- "static const struct StaticTableEncoding encoding_${encname} = {\n"
- " { .decode = &decode_table },\n"
- " {")
-set(hexIndex 0)
-foreach(line ${contents})
- string(LENGTH ${line} lineLength)
- # Convert "A" to 0x41
- string(FIND ${line} "\"" beginQuote)
- if(NOT ${beginQuote} EQUAL -1)
- string(FIND ${line} "\"" endQuote REVERSE)
- if(${beginQuote} EQUAL ${endQuote})
- message(FATAL_ERROR "Line contains only one quote")
- endif()
- math(EXPR beginHexQuote "${hexIndex} + (${beginQuote} + 1)*2")
- math(EXPR endHexQuote "${hexIndex} + (${endQuote} + 1)*2")
- math(EXPR quoteLen "${endHexQuote} - ${beginHexQuote} - 1")
- string(SUBSTRING ${hexContents} ${beginHexQuote} ${quoteLen} hexQuote)
- DecodeUtf8(${hexQuote} codePoint)
- ConvertToHex(${codePoint} hexCodePoint 4)
- STRING(REGEX REPLACE "\"(.+)\"" ${hexCodePoint} line ${line})
- endif()
- # Strip comment
- string(REGEX REPLACE "[ \t\n]*#.*" "" line ${line})
- # Convert 3/1 to [0x31]
- string(REGEX REPLACE "^([0-9]+)/([0-9]+).*" "\\1;\\2" numbers ${line})
- list(GET numbers 0 upperBits)
- list(GET numbers 1 lowerBits)
- math(EXPR res "${upperBits}*16 + ${lowerBits}")
- ConvertToHex(${res} hex 2)
- string(REGEX REPLACE "^([0-9]+)/([0-9]+)" "[${hex}]" line ${line})
- # Convert U+0041 to 0x0041
- string(REPLACE "U+" "0x" line ${line})
- # Indent and append a comma
- set(line " ${line},")
- set(output "${output}\n${line}")
- # Increment the index by the number of characters in the line,
- # plus one for the new line character then multiple by two for the hex digit index
- math(EXPR hexIndex "${hexIndex} + 2*(${lineLength} + 1)")
-endforeach()
-set(output "${output}\n"
- " }\n"
- "}\;\n")
-
-file(WRITE ${outputFile} ${output})
diff --git a/cmake.deps/cmake/LibvtermCMakeLists.txt b/cmake.deps/cmake/LibvtermCMakeLists.txt
index 079ad28ba0..777ce6c54c 100644
--- a/cmake.deps/cmake/LibvtermCMakeLists.txt
+++ b/cmake.deps/cmake/LibvtermCMakeLists.txt
@@ -2,43 +2,18 @@ cmake_minimum_required(VERSION 3.10)
project(libvterm LANGUAGES C)
include(GNUInstallDirs)
-find_package(Perl)
if(MSVC)
- add_compile_options(/W3)
add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE)
else()
- add_compile_options(-Wall -std=c99)
+ add_compile_options(-std=c99)
endif()
-# Generate includes from tables
-file(GLOB TBL_FILES ${CMAKE_SOURCE_DIR}/src/encoding/*.tbl)
-set(TBL_FILES_HEADERS)
-foreach(file ${TBL_FILES})
- get_filename_component(basename ${file} NAME_WE)
- set(tname encoding/${basename}.inc)
- add_custom_command(OUTPUT
- COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/encoding/
- COMMAND ${CMAKE_COMMAND} -P ${CMAKE_SOURCE_DIR}/tbl2inc_c.cmake ${file} ${CMAKE_BINARY_DIR}/${tname}
- COMMENT "Generating ${tname}"
- OUTPUT ${CMAKE_BINARY_DIR}/${tname}
- )
- list(APPEND TBL_FILES_HEADERS ${tname})
- # Only used for verifying that the output of tbl2inc_c.cmake is correct
- set(tname encoding-test/${basename}.inc)
- add_custom_command(OUTPUT
- COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/encoding-test/
- COMMAND ${PERL_EXECUTABLE} -CSD ${CMAKE_SOURCE_DIR}/tbl2inc_c.pl ${file} > ${CMAKE_BINARY_DIR}/${tname}
- COMMENT "Generating ${tname}"
- OUTPUT ${CMAKE_BINARY_DIR}/${tname}
- )
-endforeach()
-
include_directories(${CMAKE_SOURCE_DIR}/include)
include_directories(${CMAKE_BINARY_DIR})
file(GLOB VTERM_SOURCES ${CMAKE_SOURCE_DIR}/src/*.c)
-add_library(vterm ${VTERM_SOURCES} ${TBL_FILES_HEADERS})
+add_library(vterm ${VTERM_SOURCES})
install(TARGETS vterm ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(FILES include/vterm.h include/vterm_keycodes.h
@@ -54,33 +29,4 @@ if(NOT WIN32)
endforeach()
endif()
-# Tests
-add_executable(harness EXCLUDE_FROM_ALL t/harness.c)
-target_link_libraries(harness vterm)
-set_target_properties(harness PROPERTIES
- # run-test.pl expects to find the harness in t/.libs/
- RUNTIME_OUTPUT_DIRECTORY t/.libs)
-
-if(Perl_FOUND)
- file(GLOB TESTFILES ${CMAKE_SOURCE_DIR}/t/*.test)
- add_custom_target(check)
- foreach(testfile ${TESTFILES})
- get_filename_component(target_name ${testfile} NAME_WE)
- add_custom_target(${target_name}
- COMMAND ${PERL_EXECUTABLE} ${CMAKE_SOURCE_DIR}/t/run-test.pl ${testfile}
- COMMENT "**${target_name} **"
- DEPENDS harness)
- add_dependencies(check ${target_name})
- endforeach()
-
- foreach(header_path ${TBL_FILES_HEADERS})
- get_filename_component(header_name ${header_path} NAME)
- set(perl_header_path ${CMAKE_BINARY_DIR}/encoding-test/${header_name})
- add_custom_target(test-${header_name}
- COMMAND ${CMAKE_COMMAND} -E compare_files
- ${header_path} ${perl_header_path}
- DEPENDS ${header_path} ${perl_header_path})
- endforeach()
-endif()
-
# vim: set ft=cmake:
diff --git a/cmake.deps/cmake/TreesitterCMakeLists.txt b/cmake.deps/cmake/TreesitterCMakeLists.txt
index 69372bd2b0..49fb19c96a 100644
--- a/cmake.deps/cmake/TreesitterCMakeLists.txt
+++ b/cmake.deps/cmake/TreesitterCMakeLists.txt
@@ -1,15 +1,9 @@
cmake_minimum_required(VERSION 3.10)
project(tree-sitter LANGUAGES C)
-file(GLOB SRC_FILES ${PROJECT_SOURCE_DIR}/lib/src/*.c)
-foreach(sfile ${SRC_FILES})
- get_filename_component(f ${sfile} NAME)
- if(${f} MATCHES "lib.c$")
- list(REMOVE_ITEM SRC_FILES ${sfile})
- endif()
-endforeach()
-include_directories(${PROJECT_SOURCE_DIR}/lib/include)
-add_library(tree-sitter ${SRC_FILES})
+add_library(tree-sitter lib/src/lib.c)
+target_include_directories(tree-sitter
+ PRIVATE lib/src lib/include)
install(FILES
lib/include/tree_sitter/api.h
@@ -17,7 +11,6 @@ install(FILES
DESTINATION include/tree_sitter)
include(GNUInstallDirs)
-install(TARGETS tree-sitter
- LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
+install(TARGETS tree-sitter DESTINATION ${CMAKE_INSTALL_LIBDIR})
# vim: set ft=cmake:
diff --git a/cmake.deps/cmake/TreesitterParserCMakeLists.txt b/cmake.deps/cmake/TreesitterParserCMakeLists.txt
index 44e4ef160f..9bdf500aa7 100644
--- a/cmake.deps/cmake/TreesitterParserCMakeLists.txt
+++ b/cmake.deps/cmake/TreesitterParserCMakeLists.txt
@@ -11,7 +11,6 @@ add_library(parser
set_target_properties(
parser
PROPERTIES
- POSITION_INDEPENDENT_CODE ON
OUTPUT_NAME ${PARSERLANG}
PREFIX ""
)
diff --git a/cmake.deps/cmake/UnibiliumCMakeLists.txt b/cmake.deps/cmake/UnibiliumCMakeLists.txt
deleted file mode 100644
index 0a5d8481a7..0000000000
--- a/cmake.deps/cmake/UnibiliumCMakeLists.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-cmake_minimum_required(VERSION 3.10)
-project(unibilium LANGUAGES C)
-
-file(GLOB SRC_FILES ${PROJECT_SOURCE_DIR}/*.c)
-add_library(unibilium ${SRC_FILES})
-set_target_properties(unibilium PROPERTIES PUBLIC_HEADER ${PROJECT_SOURCE_DIR}/unibilium.h
- VERSION "${VERSION_MAJOR}.${VERSION_MINOR}")
-
-if(NOT WIN32)
- execute_process(COMMAND "shell ncursesw6-config --terminfo-dirs 2>/dev/null || \
- ncurses6-config --terminfo-dirs 2>/dev/null || \
- ncursesw5-config --terminfo-dirs 2>/dev/null || \
- ncurses5-config --terminfo-dirs 2>/dev/null || \
- echo '/etc/terminfo:/lib/terminfo:/usr/share/terminfo:/usr/lib/terminfo:/usr/local/share/terminfo:/usr/local/lib/terminfo'"
- OUTPUT_VARIABLE TERMINFO_DIRS)
-else()
- set(TERMINFO_DIRS "\"\"")
-endif()
-target_compile_definitions(unibilium PUBLIC TERMINFO_DIRS=${TERMINFO_DIRS})
-
-include(GNUInstallDirs)
-install(TARGETS unibilium
- PUBLIC_HEADER
- ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
- PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
-
-# vim: set ft=cmake:
diff --git a/cmake.deps/cmake/libtermkeyCMakeLists.txt b/cmake.deps/cmake/libtermkeyCMakeLists.txt
index b419d38d7b..26c9d7730b 100644
--- a/cmake.deps/cmake/libtermkeyCMakeLists.txt
+++ b/cmake.deps/cmake/libtermkeyCMakeLists.txt
@@ -20,17 +20,4 @@ install(TARGETS termkey
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
-enable_testing()
-file(GLOB TESTSOURCES "t/[0-9]*.c")
-foreach(f ${TESTSOURCES})
- get_filename_component(t ${f} NAME_WE)
- if(${t} STREQUAL 05read)
- continue()
- endif()
-
- add_executable("test_${t}" ${f} t/taplib.c)
- target_link_libraries("test_${t}" termkey)
- add_test("${t}" "test_${t}")
-endforeach()
-
# vim: set ft=cmake:
diff --git a/cmake/FindLIBVTERM.cmake b/cmake/FindLIBVTERM.cmake
deleted file mode 100644
index 469494ddfd..0000000000
--- a/cmake/FindLIBVTERM.cmake
+++ /dev/null
@@ -1,10 +0,0 @@
-# - Try to find libvterm
-# Once done this will define
-# LIBVTERM_FOUND - System has libvterm
-# LIBVTERM_INCLUDE_DIRS - The libvterm include directories
-# LIBVTERM_LIBRARIES - The libraries needed to use libvterm
-
-include(LibFindMacros)
-
-libfind_pkg_detect(LIBVTERM vterm FIND_PATH vterm.h FIND_LIBRARY vterm)
-libfind_process(LIBVTERM REQUIRED)
diff --git a/cmake/FindUNIBILIUM.cmake b/cmake/FindUNIBILIUM.cmake
deleted file mode 100644
index 0bf27b45e2..0000000000
--- a/cmake/FindUNIBILIUM.cmake
+++ /dev/null
@@ -1,12 +0,0 @@
-# - Try to find unibilium
-# Once done this will define
-# UNIBILIUM_FOUND - System has unibilium
-# UNIBILIUM_INCLUDE_DIRS - The unibilium include directories
-# UNIBILIUM_LIBRARIES - The libraries needed to use unibilium
-
-include(LibFindMacros)
-
-libfind_pkg_detect(UNIBILIUM unibilium
- FIND_PATH unibilium.h
- FIND_LIBRARY unibilium)
-libfind_process(UNIBILIUM)
diff --git a/cmake/Findlibvterm.cmake b/cmake/Findlibvterm.cmake
new file mode 100644
index 0000000000..d8536ca894
--- /dev/null
+++ b/cmake/Findlibvterm.cmake
@@ -0,0 +1,20 @@
+find_path(LIBVTERM_INCLUDE_DIR vterm.h)
+find_library(LIBVTERM_LIBRARY vterm)
+
+if(LIBVTERM_INCLUDE_DIR AND EXISTS "${LIBVTERM_INCLUDE_DIR}/vterm.h")
+ file(STRINGS ${LIBVTERM_INCLUDE_DIR}/vterm.h VTERM_VERSION_MAJOR REGEX "#define VTERM_VERSION_MAJOR")
+ string(REGEX MATCH "[0-9]+" VTERM_VERSION_MAJOR ${VTERM_VERSION_MAJOR})
+
+ file(STRINGS ${LIBVTERM_INCLUDE_DIR}/vterm.h VTERM_VERSION_MINOR REGEX "#define VTERM_VERSION_MINOR")
+ string(REGEX MATCH "[0-9]+" VTERM_VERSION_MINOR ${VTERM_VERSION_MINOR})
+
+ set(VTERM_VERSION ${VTERM_VERSION_MAJOR}.${VTERM_VERSION_MINOR})
+endif()
+
+find_package_handle_standard_args(libvterm
+ REQUIRED_VARS LIBVTERM_INCLUDE_DIR LIBVTERM_LIBRARY
+ VERSION_VAR VTERM_VERSION)
+
+add_library(libvterm INTERFACE)
+target_include_directories(libvterm SYSTEM BEFORE INTERFACE INTERFACE ${LIBVTERM_INCLUDE_DIR})
+target_link_libraries(libvterm INTERFACE ${LIBVTERM_LIBRARY})
diff --git a/cmake/Findunibilium.cmake b/cmake/Findunibilium.cmake
new file mode 100644
index 0000000000..7bfbcba942
--- /dev/null
+++ b/cmake/Findunibilium.cmake
@@ -0,0 +1,27 @@
+find_path(UNIBILIUM_INCLUDE_DIR unibilium.h)
+find_library(UNIBILIUM_LIBRARY unibilium)
+
+find_package_handle_standard_args(unibilium
+ REQUIRED_VARS UNIBILIUM_INCLUDE_DIR UNIBILIUM_LIBRARY)
+
+add_library(unibilium INTERFACE)
+target_include_directories(unibilium SYSTEM BEFORE INTERFACE ${UNIBILIUM_INCLUDE_DIR})
+target_link_libraries(unibilium INTERFACE ${UNIBILIUM_LIBRARY})
+
+list(APPEND CMAKE_REQUIRED_INCLUDES "${UNIBILIUM_INCLUDE_DIR}")
+list(APPEND CMAKE_REQUIRED_LIBRARIES "${UNIBILIUM_LIBRARY}")
+check_c_source_compiles("
+#include <unibilium.h>
+
+int
+main(void)
+{
+ unibi_str_from_var(unibi_var_from_str(\"\"));
+ return unibi_num_from_var(unibi_var_from_num(0));
+}
+" UNIBI_HAS_VAR_FROM)
+list(REMOVE_ITEM CMAKE_REQUIRED_INCLUDES "${UNIBILIUM_INCLUDE_DIR}")
+list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES "${UNIBILIUM_LIBRARY}")
+if(UNIBI_HAS_VAR_FROM)
+ target_compile_definitions(unibilium INTERFACE NVIM_UNIBI_HAS_VAR_FROM)
+endif()
diff --git a/cmake/GenerateVersion.cmake b/cmake/GenerateVersion.cmake
index 8cea39e4de..c092645140 100644
--- a/cmake/GenerateVersion.cmake
+++ b/cmake/GenerateVersion.cmake
@@ -7,7 +7,7 @@ execute_process(
OUTPUT_STRIP_TRAILING_WHITESPACE
RESULT_VARIABLE RES)
-if(RES AND NOT RES EQUAL 0)
+if(RES)
message(STATUS "Using NVIM_VERSION: ${NVIM_VERSION}")
file(WRITE "${OUTPUT}" "")
return()
@@ -33,4 +33,7 @@ endif()
if(NOT "${NVIM_VERSION_HASH}" STREQUAL "${CURRENT_VERSION_HASH}")
message(STATUS "Using NVIM_VERSION: ${NVIM_VERSION}")
file(WRITE "${OUTPUT}" "${NVIM_VERSION_STRING}")
+ if(WIN32)
+ configure_file("${OUTPUT}" "${OUTPUT}" NEWLINE_STYLE UNIX)
+ endif()
endif()
diff --git a/cmake/RunTests.cmake b/cmake/RunTests.cmake
index c3ac5f208e..d724f43a5f 100644
--- a/cmake/RunTests.cmake
+++ b/cmake/RunTests.cmake
@@ -71,8 +71,16 @@ if(NOT DEFINED ENV{TEST_TIMEOUT} OR "$ENV{TEST_TIMEOUT}" STREQUAL "")
endif()
set(ENV{SYSTEM_NAME} ${CMAKE_HOST_SYSTEM_NAME}) # used by test/helpers.lua.
+
+# TODO: eventually always use NVIM_PRG as the runner
+if("${TEST_TYPE}" STREQUAL "unit")
+ set(RUNNER_PRG ${NVIM_PRG} -ll ${WORKING_DIR}/test/busted_runner.lua)
+else()
+ set(RUNNER_PRG ${BUSTED_PRG})
+endif()
+
execute_process(
- COMMAND ${BUSTED_PRG} -v -o test.busted.outputHandlers.${BUSTED_OUTPUT_TYPE}
+ COMMAND ${RUNNER_PRG} -v -o test.busted.outputHandlers.${BUSTED_OUTPUT_TYPE}
--lazy --helper=${TEST_DIR}/${TEST_TYPE}/preload.lua
--lpath=${BUILD_DIR}/?.lua
--lpath=${WORKING_DIR}/runtime/lua/?.lua
diff --git a/cmake/Util.cmake b/cmake/Util.cmake
index a86ced89d6..e15b44d29a 100644
--- a/cmake/Util.cmake
+++ b/cmake/Util.cmake
@@ -79,12 +79,13 @@ function(add_glob_target)
file(TO_CMAKE_PATH "${f}" f)
list(APPEND globfiles ${f})
endforeach()
- foreach(exclude_pattern ${ARG_EXCLUDE})
- list(FILTER globfiles EXCLUDE REGEX ${exclude_pattern})
- endforeach()
list(APPEND ARG_FILES ${globfiles})
endforeach()
+ foreach(exclude_pattern ${ARG_EXCLUDE})
+ list(FILTER ARG_FILES EXCLUDE REGEX ${exclude_pattern})
+ endforeach()
+
if(NOT ARG_TOUCH_STRATEGY)
set(ARG_TOUCH_STRATEGY PER_FILE)
endif()
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index d74657dc8e..95a929b808 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -1133,7 +1133,7 @@ nvim_list_uis() *nvim_list_uis()*
• "width" Requested width of the UI
• "rgb" true if the UI uses RGB colors (false implies |cterm-colors|)
• "ext_..." Requested UI extensions, see |ui-option|
- • "chan" Channel id of remote UI or 0 for TUI
+ • "chan" |channel-id| of remote UI
nvim_list_wins() *nvim_list_wins()*
Gets the current list of window handles.
@@ -3281,7 +3281,7 @@ nvim_create_autocmd({event}, {*opts}) *nvim_create_autocmd()*
• match: (string) expanded value of |<amatch>|
• buf: (number) expanded value of |<abuf>|
• file: (string) expanded value of |<afile>|
- • data: (any) arbitrary data passed to
+ • data: (any) arbitrary data passed from
|nvim_exec_autocmds()|
• command (string) optional: Vim command to execute on event.
diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt
index a39407aeca..8cc4754880 100644
--- a/runtime/doc/autocmd.txt
+++ b/runtime/doc/autocmd.txt
@@ -681,16 +681,12 @@ FuncUndefined When a user function is used but it isn't
UIEnter After a UI connects via |nvim_ui_attach()|, or
after builtin TUI is started, after |VimEnter|.
Sets these |v:event| keys:
- chan: 0 for builtin TUI
- 1 for |--embed|
- |channel-id| of the UI otherwise
+ chan: |channel-id| of the UI
*UILeave*
UILeave After a UI disconnects from Nvim, or after
builtin TUI is stopped, after |VimLeave|.
Sets these |v:event| keys:
- chan: 0 for builtin TUI
- 1 for |--embed|
- |channel-id| of the UI otherwise
+ chan: |channel-id| of the UI
*InsertChange*
InsertChange When typing <Insert> while in Insert or
Replace mode. The |v:insertmode| variable
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index cc1d1b568d..c8f5570bae 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -173,6 +173,7 @@ getbufline({buf}, {lnum} [, {end}])
getbufoneline({buf}, {lnum}) String line {lnum} of buffer {buf}
getbufvar({buf}, {varname} [, {def}])
any variable {varname} in buffer {buf}
+getcellwidths() List get character cell width overrides
getchangelist([{buf}]) List list of change list items
getchar([expr]) Number or String
get one character from the user
@@ -2745,6 +2746,13 @@ getbufvar({buf}, {varname} [, {def}]) *getbufvar()*
< Can also be used as a |method|: >
GetBufnr()->getbufvar(varname)
<
+getcellwidths() *getcellwidths()*
+ Returns a |List| of cell widths of character ranges overridden
+ by |setcellwidths()|. The format is equal to the argument of
+ |setcellwidths()|. If no character ranges have their cell
+ widths overridden, an empty List is returned.
+
+
getchangelist([{buf}]) *getchangelist()*
Returns the |changelist| for the buffer {buf}. For the use
of {buf}, see |bufname()| above. If buffer {buf} doesn't
@@ -2958,7 +2966,8 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()*
arglist file names in argument list
augroup autocmd groups
buffer buffer names
- behave :behave suboptions
+ behave |:behave| suboptions
+ breakpoint |:breakadd| and |:breakdel| suboptions
cmdline |cmdline-completion| result
color color schemes
command Ex command
@@ -2974,7 +2983,7 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()*
function function name
help help subjects
highlight highlight groups
- history :history suboptions
+ history |:history| suboptions
locale locale names (as output of locale -a)
mapclear buffer argument
mapping mapping name
@@ -2982,6 +2991,8 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()*
messages |:messages| suboptions
option options
packadd optional package |pack-add| names
+ runtime |:runtime| completion
+ scriptnames sourced script names |:scriptnames|
shellcmd Shell command
sign |:sign| suboptions
syntax syntax file names |'syntax'|
@@ -2999,6 +3010,13 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()*
is applied to filter the results. Otherwise all the matches
are returned. The 'wildignorecase' option always applies.
+ If the 'wildoptions' option contains "fuzzy", then fuzzy
+ matching is used to get the completion matches. Otherwise
+ regular expression matching is used. Thus this function
+ follows the user preference, what happens on the command line.
+ If you do not want this you can make 'wildoptions' empty
+ before calling getcompletion() and restore it afterwards.
+
If {type} is "cmdline", then the |cmdline-completion| result is
returned. For example, to complete the possible values after
a ":call" command: >
@@ -6934,7 +6952,7 @@ setcellwidths({list}) *setcellwidths()*
{low} and {high} can be the same, in which case this refers to
one character. Otherwise it is the range of characters from
{low} to {high} (inclusive). *E1111* *E1114*
- Only characters with value 0x100 and higher can be used.
+ Only characters with value 0x80 and higher can be used.
{width} must be either 1 or 2, indicating the character width
in screen cells. *E1112*
@@ -8311,6 +8329,7 @@ synIDattr({synID}, {what} [, {mode}]) *synIDattr()*
"underdotted" "1" if dotted underlined
"underdashed" "1" if dashed underlined
"strikethrough" "1" if struckthrough
+ "altfont" "1" if alternative font
"nocombine" "1" if nocombine
Returns an empty string on error.
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 6feb5cbb49..58759a6053 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -2295,13 +2295,15 @@ v:version Vim version number: major version times 100 plus minor
:if has("nvim-0.2.1")
<
- *v:vim_did_enter* *vim_did_enter-variable*
-v:vim_did_enter 0 during startup, 1 just before |VimEnter|.
+ *v:virtnum* *virtnum-variable*
+v:virtnum Virtual line number for the 'statuscolumn' expression.
+ Negative when drawing the status column for virtual lines, zero
+ when drawing an actual buffer line, and positive when drawing
+ the wrapped part of a buffer line.
Read-only.
- *v:wrap* *wrap-variable*
-v:wrap Boolean indicating whether 'statuscolumn' is being evaluated
- for the wrapped part of a line.
+ *v:vim_did_enter* *vim_did_enter-variable*
+v:vim_did_enter 0 during startup, 1 just before |VimEnter|.
Read-only.
*v:warningmsg* *warningmsg-variable*
@@ -2679,6 +2681,8 @@ text...
[depth] is relevant when locking a |List| or
|Dictionary|. It specifies how deep the locking goes:
+ 0 Lock the variable {name} but not its
+ value.
1 Lock the |List| or |Dictionary| itself,
cannot add or remove items, but can
still change their values.
@@ -2692,7 +2696,14 @@ text...
|Dictionary|, one level deeper.
The default [depth] is 2, thus when {name} is a |List|
or |Dictionary| the values cannot be changed.
- *E743*
+
+ Example with [depth] 0: >
+ let mylist = [1, 2, 3]
+ lockvar 0 mylist
+ let mylist[0] = 77 " OK
+ call add(mylist, 4] " OK
+ let mylist = [7, 8, 9] " Error!
+< *E743*
For unlimited depth use [!] and omit [depth].
However, there is a maximum depth of 100 to catch
loops.
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt
index 46cfa60529..215515a2d9 100644
--- a/runtime/doc/lsp.txt
+++ b/runtime/doc/lsp.txt
@@ -832,128 +832,118 @@ start({config}, {opts}) *vim.lsp.start()*
start_client({config}) *vim.lsp.start_client()*
Starts and initializes a client with the given configuration.
- Parameter `cmd` is required.
-
- The following parameters describe fields in the {config} table.
-
- Parameters: ~
- • {cmd} (table|string|fun(dispatchers: table):table)
- command string or list treated like |jobstart()|.
- The command must launch the language server
- process. `cmd` can also be a function that
- creates an RPC client. The function receives a
- dispatchers table and must return a table with
- the functions `request`, `notify`, `is_closing`
- and `terminate` See |vim.lsp.rpc.request()| and
- |vim.lsp.rpc.notify()| For TCP there is a
- built-in rpc client factory:
- |vim.lsp.rpc.connect()|
- • {cmd_cwd} (string, default=|getcwd()|) Directory to launch
- the `cmd` process. Not related to `root_dir`.
- • {cmd_env} (table) Environment flags to pass to the LSP on
- spawn. Can be specified using keys like a map or
- as a list with `k=v` pairs or both. Non-string values are coerced to
- string. Example: >
-
- { "PRODUCTION=true"; "TEST=123"; PORT = 8080; HOST = "0.0.0.0"; }
+ Field `cmd` in {config} is required.
+
+ Parameters: ~
+ • {config} (table) Configuration for the server:
+ • cmd: (table|string|fun(dispatchers: table):table) command
+ string or list treated like |jobstart()|. The command must
+ launch the language server process. `cmd` can also be a
+ function that creates an RPC client. The function receives
+ a dispatchers table and must return a table with the
+ functions `request`, `notify`, `is_closing` and
+ `terminate` See |vim.lsp.rpc.request()| and
+ |vim.lsp.rpc.notify()| For TCP there is a built-in rpc
+ client factory: |vim.lsp.rpc.connect()|
+ • cmd_cwd: (string, default=|getcwd()|) Directory to launch
+ the `cmd` process. Not related to `root_dir`.
+ • cmd_env: (table) Environment flags to pass to the LSP on
+ spawn. Can be specified using keys like a map or as a list
+ with `k=v` pairs or both. Non-string values are coerced to string.
+ Example: >
+
+ { "PRODUCTION=true"; "TEST=123"; PORT = 8080; HOST = "0.0.0.0"; }
<
- • {detached} (boolean, default true) Daemonize the server
- process so that it runs in a separate process
- group from Nvim. Nvim will shutdown the process
- on exit, but if Nvim fails to exit cleanly this
- could leave behind orphaned server processes.
- • {workspace_folders} (table) List of workspace folders passed to the
- language server. For backwards compatibility
- rootUri and rootPath will be derived from the
- first workspace folder in this list. See
- `workspaceFolders` in the LSP spec.
- • {capabilities} Map overriding the default capabilities defined
- by |vim.lsp.protocol.make_client_capabilities()|,
- passed to the language server on initialization.
- Hint: use make_client_capabilities() and modify
- its result.
- • Note: To send an empty dictionary use
- `{[vim.type_idx]=vim.types.dictionary}`, else
- it will be encoded as an array.
- • {handlers} Map of language server method names to
- |lsp-handler|
- • {settings} Map with language server specific settings. These
- are returned to the language server if requested
- via `workspace/configuration`. Keys are
- case-sensitive.
- • {commands} (table) Table that maps string of clientside
- commands to user-defined functions. Commands
- passed to start_client take precedence over the
- global command registry. Each key must be a
- unique command name, and the value is a function
- which is called if any LSP action (code action,
- code lenses, ...) triggers the command.
- • {init_options} Values to pass in the initialization request as
- `initializationOptions`. See `initialize` in the
- LSP spec.
- • {name} (string, default=client-id) Name in log messages.
- • {get_language_id} function(bufnr, filetype) -> language ID as
- string. Defaults to the filetype.
- • {offset_encoding} (default="utf-16") One of "utf-8", "utf-16", or
- "utf-32" which is the encoding that the LSP
- server expects. Client does not verify this is
- correct.
- • {on_error} Callback with parameters (code, ...), invoked
- when the client operation throws an error. `code`
- is a number describing the error. Other arguments
- may be passed depending on the error kind. See
- `vim.lsp.rpc.client_errors` for possible errors.
- Use `vim.lsp.rpc.client_errors[code]` to get
- human-friendly name.
- • {before_init} Callback with parameters (initialize_params,
- config) invoked before the LSP "initialize"
- phase, where `params` contains the parameters
- being sent to the server and `config` is the
- config that was passed to
- |vim.lsp.start_client()|. You can use this to
- modify parameters before they are sent.
- • {on_init} Callback (client, initialize_result) invoked
- after LSP "initialize", where `result` is a table
- of `capabilities` and anything else the server
- may send. For example, clangd sends
- `initialize_result.offsetEncoding` if
- `capabilities.offsetEncoding` was sent to it. You
- can only modify the `client.offset_encoding` here
- before any notifications are sent. Most language
- servers expect to be sent client specified
- settings after initialization. Neovim does not
- make this assumption. A
- `workspace/didChangeConfiguration` notification
- should be sent to the server during on_init.
- • {on_exit} Callback (code, signal, client_id) invoked on
- client exit.
- • code: exit code of the process
- • signal: number describing the signal used to
- terminate (if any)
- • client_id: client handle
- • {on_attach} Callback (client, bufnr) invoked when client
- attaches to a buffer.
- • {trace} "off" | "messages" | "verbose" | nil passed
- directly to the language server in the initialize
- request. Invalid/empty values will default to
- "off"
- • {flags} A table with flags for the client. The current
- (experimental) flags are:
- • allow_incremental_sync (bool, default true):
- Allow using incremental sync for buffer edits
- • debounce_text_changes (number, default 150):
- Debounce didChange notifications to the server
- by the given number in milliseconds. No
- debounce occurs if nil
- • exit_timeout (number|boolean, default false):
- Milliseconds to wait for server to exit cleanly
- after sending the "shutdown" request before
- sending kill -15. If set to false, nvim exits
- immediately after sending the "shutdown"
- request to the server.
- • {root_dir} (string) Directory where the LSP server will base
- its workspaceFolders, rootUri, and rootPath on
- initialization.
+ • detached: (boolean, default true) Daemonize the server
+ process so that it runs in a separate process group from
+ Nvim. Nvim will shutdown the process on exit, but if Nvim
+ fails to exit cleanly this could leave behind orphaned
+ server processes.
+ • workspace_folders: (table) List of workspace folders
+ passed to the language server. For backwards compatibility
+ rootUri and rootPath will be derived from the first
+ workspace folder in this list. See `workspaceFolders` in
+ the LSP spec.
+ • capabilities: Map overriding the default capabilities
+ defined by |vim.lsp.protocol.make_client_capabilities()|,
+ passed to the language server on initialization. Hint: use
+ make_client_capabilities() and modify its result.
+ • Note: To send an empty dictionary use
+ `{[vim.type_idx]=vim.types.dictionary}`, else it will be
+ encoded as an array.
+
+ • handlers: Map of language server method names to
+ |lsp-handler|
+ • settings: Map with language server specific settings.
+ These are returned to the language server if requested via
+ `workspace/configuration`. Keys are case-sensitive.
+ • commands: table Table that maps string of clientside
+ commands to user-defined functions. Commands passed to
+ start_client take precedence over the global command
+ registry. Each key must be a unique command name, and the
+ value is a function which is called if any LSP action
+ (code action, code lenses, ...) triggers the command.
+ • init_options Values to pass in the initialization request
+ as `initializationOptions`. See `initialize` in the LSP
+ spec.
+ • name: (string, default=client-id) Name in log messages.
+ • get_language_id: function(bufnr, filetype) -> language ID
+ as string. Defaults to the filetype.
+ • offset_encoding: (default="utf-16") One of "utf-8",
+ "utf-16", or "utf-32" which is the encoding that the LSP
+ server expects. Client does not verify this is correct.
+ • on_error: Callback with parameters (code, ...), invoked
+ when the client operation throws an error. `code` is a
+ number describing the error. Other arguments may be passed
+ depending on the error kind. See
+ `vim.lsp.rpc.client_errors` for possible errors. Use
+ `vim.lsp.rpc.client_errors[code]` to get human-friendly
+ name.
+ • before_init: Callback with parameters (initialize_params,
+ config) invoked before the LSP "initialize" phase, where
+ `params` contains the parameters being sent to the server
+ and `config` is the config that was passed to
+ |vim.lsp.start_client()|. You can use this to modify
+ parameters before they are sent.
+ • on_init: Callback (client, initialize_result) invoked
+ after LSP "initialize", where `result` is a table of
+ `capabilities` and anything else the server may send. For
+ example, clangd sends `initialize_result.offsetEncoding`
+ if `capabilities.offsetEncoding` was sent to it. You can
+ only modify the `client.offset_encoding` here before any
+ notifications are sent. Most language servers expect to be
+ sent client specified settings after initialization.
+ Neovim does not make this assumption. A
+ `workspace/didChangeConfiguration` notification should be
+ sent to the server during on_init.
+ • on_exit Callback (code, signal, client_id) invoked on
+ client exit.
+ • code: exit code of the process
+ • signal: number describing the signal used to terminate
+ (if any)
+ • client_id: client handle
+
+ • on_attach: Callback (client, bufnr) invoked when client
+ attaches to a buffer.
+ • trace: ("off" | "messages" | "verbose" | nil) passed
+ directly to the language server in the initialize request.
+ Invalid/empty values will default to "off"
+ • flags: A table with flags for the client. The current
+ (experimental) flags are:
+ • allow_incremental_sync (bool, default true): Allow using
+ incremental sync for buffer edits
+ • debounce_text_changes (number, default 150): Debounce
+ didChange notifications to the server by the given
+ number in milliseconds. No debounce occurs if nil
+ • exit_timeout (number|boolean, default false):
+ Milliseconds to wait for server to exit cleanly after
+ sending the "shutdown" request before sending kill -15.
+ If set to false, nvim exits immediately after sending
+ the "shutdown" request to the server.
+
+ • root_dir: (string) Directory where the LSP server will
+ base its workspaceFolders, rootUri, and rootPath on
+ initialization.
Return: ~
Client id. |vim.lsp.get_client_by_id()| Note: client may not be fully
@@ -1022,6 +1012,8 @@ code_action({options}) *vim.lsp.buf.code_action()*
• only (table|nil): List of LSP `CodeActionKind`s used to
filter the code actions. Most language servers support
values like `refactor` or `quickfix`.
+ • triggerKind (number|nil): The reason why code actions
+ were requested.
• filter: (function|nil) Predicate taking an `CodeAction`
and returning a boolean.
@@ -1036,6 +1028,7 @@ code_action({options}) *vim.lsp.buf.code_action()*
See also: ~
https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction
+ vim.lsp.protocol.constants.CodeActionTriggerKind
completion({context}) *vim.lsp.buf.completion()*
Retrieves the completion items at the current cursor position. Can only be
diff --git a/runtime/doc/lua-guide.txt b/runtime/doc/lua-guide.txt
index 71dc48b715..b971a7d2ad 100644
--- a/runtime/doc/lua-guide.txt
+++ b/runtime/doc/lua-guide.txt
@@ -406,9 +406,9 @@ mandatory arguments:
prefix for which the mapping will take effect. The prefixes are the ones
listed in |:map-modes|, or "!" for |:map!|, or empty string for |:map|.
• {lhs} is a string with the key sequences that should trigger the mapping.
- An empty string is equivalent to |<Nop>|, which disables a key.
• {rhs} is either a string with a Vim command or a Lua function that should
be executed when the {lhs} is entered.
+ An empty string is equivalent to |<Nop>|, which disables a key.
Examples:
>lua
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index 16d0bcb612..47249a484b 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -132,8 +132,7 @@ back to Lua's default search mechanism. The first script found is run and
The return value is cached after the first call to `require()` for each module,
with subsequent calls returning the cached value without searching for, or
-executing any script. For further details on `require()`, see the Lua
-documentation at https://www.lua.org/manual/5.1/manual.html#pdf-require.
+executing any script. For further details on `require()`, see |luaref-require()|.
For example, if 'runtimepath' is `foo,bar` and |package.cpath| was
`./?.so;./?.dll` at startup, `require('mod')` searches these paths in order
@@ -1641,6 +1640,7 @@ gsplit({s}, {sep}, {plain}) *vim.gsplit()*
See also: ~
|vim.split()|
+ |luaref-patterns|
https://www.lua.org/pil/20.2.html
http://lua-users.org/wiki/StringLibraryTutorial
@@ -1694,6 +1694,18 @@ pesc({s}) *vim.pesc()*
See also: ~
https://github.com/rxi/lume
+spairs({t}) *vim.spairs()*
+ Enumerate a table sorted by its keys.
+
+ Parameters: ~
+ • {t} (table) List-like table
+
+ Return: ~
+ iterator over sorted keys and their values
+
+ See also: ~
+ Based on https://github.com/premake/premake-core/blob/master/src/base/table.lua
+
split({s}, {sep}, {kwargs}) *vim.split()*
Splits a string at each instance of a separator.
@@ -1913,6 +1925,7 @@ trim({s}) *vim.trim()*
(string) String with whitespace removed from its beginning and end
See also: ~
+ |luaref-patterns|
https://www.lua.org/pil/20.2.html
validate({opt}) *vim.validate()*
@@ -2379,7 +2392,7 @@ normalize({path}) *vim.fs.normalize()*
Examples: >lua
- vim.fs.normalize('C:\Users\jdoe')
+ vim.fs.normalize('C:\\Users\\jdoe')
--> 'C:/Users/jdoe'
vim.fs.normalize('~/src/neovim')
diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt
index ccd48a8959..cb8b162eb6 100644
--- a/runtime/doc/map.txt
+++ b/runtime/doc/map.txt
@@ -1432,9 +1432,11 @@ The function arguments are:
The function may use these for determining context. For the "custom"
argument, it is not necessary to filter candidates against the (implicit
pattern in) ArgLead. Vim will filter the candidates with its regexp engine
-after function return, and this is probably more efficient in most cases. For
-the "customlist" argument, Vim will not filter the returned completion
-candidates and the user supplied function should filter the candidates.
+after function return, and this is probably more efficient in most cases. If
+'wildoptions' contains "fuzzy", then the candidates will be filtered using
+|fuzzy-matching|. For the "customlist" argument, Vim will not
+filter the returned completion candidates and the user supplied function
+should filter the candidates.
The following example lists user names to a Finger command >
:com -complete=custom,ListUsers -nargs=1 Finger !finger <args>
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index ce07c3035c..5c234677ef 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -45,6 +45,8 @@ The following changes may require adaptations in user config or plugins.
- `printheader`
- `printmbcharset`
+• libiconv is now a required build dependency.
+
==============================================================================
NEW FEATURES *news-features*
@@ -143,6 +145,12 @@ The following new APIs or features were added.
instance in the background and display its UI on demand, which previously
only was possible using an external UI implementation.
+• Several improvements were made to make the code generation scripts more
+ deterministic, and a `LUA_GEN_PRG` build parameter has been introduced to
+ allow for a workaround for some remaining reproducibility problems.
+
+• |:highlight| now supports an additional attribute "altfont".
+
==============================================================================
CHANGED FEATURES *news-changes*
@@ -159,11 +167,17 @@ The following changes to existing APIs or features add new behavior.
resulting in a nvim binary which only could be run headless or embedded
in an external process. As of this version, TUI is always available.
+• API calls now show more information about where an exception happened.
+
==============================================================================
REMOVED FEATURES *news-removed*
The following deprecated functions or APIs were removed.
+• It is no longer possible to scroll the whole screen when showing messages
+ longer than 'cmdheight'. |msgsep| is now always enabled even if 'display'
+ doesn't contain the "msgsep" flag.
+
• `filetype.vim` is removed in favor of |lua-filetype|
(Note that filetype logic and tests still align with Vim, so additions or
changes need to be contributed there first.)
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 4498dda300..b1af90a604 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -3843,21 +3843,21 @@ A jump table for the options with a short description can be found at |Q_op|.
The third character is optional.
tab:xy The 'x' is always used, then 'y' as many times as will
- fit. Thus "tab:>-" displays:
+ fit. Thus "tab:>-" displays: >
>
>-
>--
etc.
-
+<
tab:xyz The 'z' is always used, then 'x' is prepended, and
then 'y' is used as many times as will fit. Thus
- "tab:<->" displays:
+ "tab:<->" displays: >
>
<>
<->
<-->
etc.
-
+<
When "tab:" is omitted, a tab is shown as ^I.
*lcs-space*
space:c Character to show for a space. When omitted, spaces
@@ -3869,22 +3869,25 @@ A jump table for the options with a short description can be found at |Q_op|.
setting, except for single spaces. When omitted, the
"space" setting is used. For example,
`:set listchars=multispace:---+` shows ten consecutive
- spaces as:
- ---+---+-- ~
+ spaces as: >
+ ---+---+--
+<
*lcs-lead*
lead:c Character to show for leading spaces. When omitted,
leading spaces are blank. Overrides the "space" and
"multispace" settings for leading spaces. You can
combine it with "tab:", for example: >
:set listchars+=tab:>-,lead:.
-< *lcs-leadmultispace*
+<
+ *lcs-leadmultispace*
leadmultispace:c...
Like the |lcs-multispace| value, but for leading
spaces only. Also overrides |lcs-lead| for leading
multiple spaces.
`:set listchars=leadmultispace:---+` shows ten
- consecutive leading spaces as:
- ---+---+--XXX ~
+ consecutive leading spaces as: >
+ ---+---+--XXX
+<
Where "XXX" denotes the first non-blank characters in
the line.
*lcs-trail*
@@ -6017,12 +6020,20 @@ A jump table for the options with a short description can be found at |Q_op|.
%s sign column for currently drawn line
%C fold column for currently drawn line
- To draw the sign and fold columns, they must be included in
- 'statuscolumn'.
+ NOTE: To draw the sign and fold columns, their items must be included in
+ 'statuscolumn'. Even when they are not included, the status column width
+ will adapt to the 'signcolumn' and 'foldcolumn' width.
+
+ The |v:lnum| variable holds the line number to be drawn.
+ The |v:relnum| variable holds the relative line number to be drawn.
+ The |v:virtnum| variable is negative when drawing virtual lines, zero
+ when drawing the actual buffer line, and positive when
+ drawing the wrapped part of a buffer line.
- The |v:lnum| variable holds the line number to be drawn.
- The |v:relnum| variable holds the relative line number to be drawn.
- The |v:wrap| variable holds true for the wrapped part of a line.
+ NOTE: The %@ click execute function item is supported as well but the
+ specified function will be the same for each row in the same column.
+ It cannot be switched out through a dynamic 'statuscolumn' format, the
+ handler should be written with this in mind.
Examples: >vim
" Relative number with bar separator and click handlers:
@@ -6032,7 +6043,7 @@ A jump table for the options with a short description can be found at |Q_op|.
:let &stc='%=%{v:relnum?v:relnum:v:lnum} '
" Line numbers in hexadecimal for non wrapped part of lines:
- :let &stc='%=%{v:wrap?"":printf("%x",v:lnum)} '
+ :let &stc='%=%{v:virtnum>0?"":printf("%x",v:lnum)} '
" Human readable line numbers with thousands separator:
:let &stc='%{substitute(v:lnum,"\\d\\zs\\ze\\'
@@ -7123,6 +7134,14 @@ A jump table for the options with a short description can be found at |Q_op|.
global
A list of words that change how |cmdline-completion| is done.
The following values are supported:
+ fuzzy Use |fuzzy-matching| to find completion matches. When
+ this value is specified, wildcard expansion will not
+ be used for completion. The matches will be sorted by
+ the "best match" rather than alphabetically sorted.
+ This will find more matches than the wildcard
+ expansion. Currently fuzzy matching based completion
+ is not supported for file and directory names and
+ instead wildcard expansion is used.
pum Display the completion matches using the popup menu
in the same style as the |ins-completion-menu|.
tagfile When using CTRL-D to list matching tags, the kind of
diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt
index 1bbd20702b..bf77aacdc0 100644
--- a/runtime/doc/repeat.txt
+++ b/runtime/doc/repeat.txt
@@ -211,9 +211,7 @@ For writing a Vim script, see chapter 41 of the user manual |usr_41.txt|.
When [!] is included, all found files are sourced.
Else only the first found file is sourced.
- When [where] is omitted, first 'runtimepath' is
- searched, then directories under "start" in 'packpath'
- are searched.
+ When [where] is omitted only 'runtimepath' is used.
Other values:
START search only under "start" in 'packpath'
OPT search only under "opt" in 'packpath'
diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt
index 179bacdb24..5e0718c3bb 100644
--- a/runtime/doc/starting.txt
+++ b/runtime/doc/starting.txt
@@ -239,6 +239,14 @@ argument.
Disables |shada| unless |-i| was given.
Disables swapfile (like |-n|).
+ *-ll*
+-ll {script} [args]
+ Execute a lua script, similarly to |-l|, but the editor is not
+ initialized. This gives a lua enviroment similar to a worker
+ thread. See |lua-loop-threading|.
+
+ Unlike `-l` no prior arguments are allowed.
+
*-b*
-b Binary mode. File I/O will only recognize <NL> to separate
lines. The 'expandtab' option will be reset. The 'textwidth'
diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt
index b4afc3f233..bd5a4f1926 100644
--- a/runtime/doc/syntax.txt
+++ b/runtime/doc/syntax.txt
@@ -4958,7 +4958,8 @@ the same syntax file on all UIs.
*bold* *underline* *undercurl*
*underdouble* *underdotted*
*underdashed* *inverse* *italic*
- *standout* *nocombine* *strikethrough*
+ *standout* *strikethrough* *altfont*
+ *nocombine*
cterm={attr-list} *attr-list* *highlight-cterm* *E418*
attr-list is a comma-separated list (without spaces) of the
following items (in any order):
@@ -4973,6 +4974,7 @@ cterm={attr-list} *attr-list* *highlight-cterm* *E418*
inverse same as reverse
italic
standout
+ altfont
nocombine override attributes instead of combining them
NONE no attributes used (used to reset it)
diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt
index 096cec6678..9bfdc0b94e 100644
--- a/runtime/doc/treesitter.txt
+++ b/runtime/doc/treesitter.txt
@@ -684,6 +684,7 @@ require_language({lang}, {path}, {silent}, {symbol_name})
Parameters: ~
• {lang} (string) Language the parser should parse
+ (alphanumerical and `_` only)
• {path} (string|nil) Optional path the parser is located at
• {silent} (boolean|nil) Don't throw an error if language not
found
@@ -708,8 +709,15 @@ add_directive({name}, {handler}, {force})
Parameters: ~
• {name} (string) Name of the directive, without leading #
- • {handler} function(match:string, pattern:string, bufnr:number,
- predicate:function, metadata:table)
+ • {handler} function(match:table, pattern:string, bufnr:number,
+ predicate:string[], metadata:table)
+ • match: see |treesitter-query|
+ • node-level data are accessible via `match[capture_id]`
+
+ • pattern: see |treesitter-query|
+ • predicate: list of strings containing the full directive
+ being called, e.g. `(node (#set! conceal "-"))` would get
+ the predicate `{ "#set!", "conceal", "-" }`
*vim.treesitter.query.add_predicate()*
add_predicate({name}, {handler}, {force})
@@ -717,8 +725,10 @@ add_predicate({name}, {handler}, {force})
Parameters: ~
• {name} (string) Name of the predicate, without leading #
- • {handler} function(match:string, pattern:string, bufnr:number,
- predicate:function)
+ • {handler} function(match:table, pattern:string, bufnr:number,
+ predicate:string[])
+ • see |vim.treesitter.query.add_directive()| for argument
+ meanings
*vim.treesitter.query.get_node_text()*
get_node_text({node}, {source}, {opts})
diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt
index a2ae9f22ce..3110d0817c 100644
--- a/runtime/doc/ui.txt
+++ b/runtime/doc/ui.txt
@@ -324,6 +324,7 @@ numerical highlight ids to the actual attributes.
`underdouble`: double underlined text. The lines have `special` color.
`underdotted`: underdotted text. The dots have `special` color.
`underdashed`: underdashed text. The dashes have `special` color.
+ `altfont`: alternative font.
`blend`: Blend level (0-100). Could be used by UIs to
support blending floating windows to the
background or to signal a transparent cursor.
diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt
index 226bd029a3..910aebae70 100644
--- a/runtime/doc/usr_41.txt
+++ b/runtime/doc/usr_41.txt
@@ -624,6 +624,7 @@ String manipulation: *string-functions*
strwidth() size of string when displayed
strdisplaywidth() size of string when displayed, deals with tabs
setcellwidths() set character cell width overrides
+ getcellwidths() get character cell width overrides
substitute() substitute a pattern match with a string
submatch() get a specific match in ":s" and substitute()
strpart() get part of a string using byte index
diff --git a/runtime/lua/man.lua b/runtime/lua/man.lua
index a644dd68b8..0956022ac6 100644
--- a/runtime/lua/man.lua
+++ b/runtime/lua/man.lua
@@ -149,15 +149,21 @@ local function highlight_line(line, linenr)
if overstrike then
local last_hl = hls[#hls]
if char == prev_char then
- if char == '_' and attr == UNDERLINE and last_hl and last_hl.final == byte then
- -- This underscore is in the middle of an underlined word
- attr = UNDERLINE
+ if char == '_' and attr == ITALIC and last_hl and last_hl.final == byte then
+ -- This underscore is in the middle of an italic word
+ attr = ITALIC
else
attr = BOLD
end
elseif prev_char == '_' then
- -- char is underlined
- attr = UNDERLINE
+ -- Even though underline is strictly what this should be. <bs>_ was used by nroff to
+ -- indicate italics which wasn't possible on old typewriters so underline was used. Modern
+ -- terminals now support italics so lets use that now.
+ -- See:
+ -- - https://unix.stackexchange.com/questions/274658/purpose-of-ascii-text-with-overstriking-file-format/274795#274795
+ -- - https://cmd.inp.nsk.su/old/cmd2/manuals/unix/UNIX_Unleashed/ch08.htm
+ -- attr = UNDERLINE
+ attr = ITALIC
elseif prev_char == '+' and char == 'o' then
-- bullet (overstrike text '+^Ho')
attr = BOLD
@@ -420,6 +426,10 @@ local function extract_sect_and_name_path(path)
end
local function find_man()
+ if vim.bo.filetype == 'man' then
+ return true
+ end
+
local win = 1
while win <= fn.winnr('$') do
local buf = fn.winbufnr(win)
diff --git a/runtime/lua/nvim/health.lua b/runtime/lua/nvim/health.lua
index c00b921d5c..f11899434e 100644
--- a/runtime/lua/nvim/health.lua
+++ b/runtime/lua/nvim/health.lua
@@ -1,6 +1,22 @@
local M = {}
local health = require('vim.health')
+local fn_bool = function(key)
+ return function(...)
+ return vim.fn[key](...) == 1
+ end
+end
+
+local has = fn_bool('has')
+local executable = fn_bool('executable')
+local empty = fn_bool('empty')
+local filereadable = fn_bool('filereadable')
+local filewritable = fn_bool('filewritable')
+
+local shell_error = function()
+ return vim.v.shell_error ~= 0
+end
+
local suggest_faq = 'https://github.com/neovim/neovim/wiki/Building-Neovim#optimized-builds'
local function check_runtime()
@@ -37,15 +53,6 @@ end
local function check_config()
health.report_start('Configuration')
local ok = true
- local empty = function(o)
- return 0 ~= vim.fn.empty(o)
- end
- local filereadable = function(o)
- return 0 ~= vim.fn.filereadable(o)
- end
- local filewritable = function(o)
- return 0 ~= vim.fn.filewritable(o)
- end
local vimrc = (
empty(vim.env.MYVIMRC) and vim.fn.stdpath('config') .. '/init.vim' or vim.env.MYVIMRC
@@ -65,7 +72,7 @@ local function check_config()
health.report_error('$VIM is invalid: ' .. vim.env.VIM)
end
- if 1 == vim.fn.exists('$NVIM_TUI_ENABLE_CURSOR_SHAPE') then
+ if vim.env.NVIM_TUI_ENABLE_CURSOR_SHAPE then
ok = false
health.report_warn('$NVIM_TUI_ENABLE_CURSOR_SHAPE is ignored in Nvim 0.2+', {
"Use the 'guicursor' option to configure cursor shape. :help 'guicursor'",
@@ -139,240 +146,249 @@ local function check_config()
end
local function check_performance()
- vim.api.nvim_exec([=[
- func! s:check_performance() abort
- let s:suggest_faq = ']=] .. suggest_faq .. [=['
-
- call health#report_start('Performance')
-
- " check buildtype
- let s:buildtype = matchstr(execute('version'), '\v\cbuild type:?\s*[^\n\r\t ]+')
- if empty(s:buildtype)
- call health#report_error('failed to get build type from :version')
- elseif s:buildtype =~# '\v(MinSizeRel|Release|RelWithDebInfo)'
- call health#report_ok(s:buildtype)
- else
- call health#report_info(s:buildtype)
- call health#report_warn(
- \ 'Non-optimized '.(has('debug')?'(DEBUG) ':'').'build. Nvim will be slower.',
- \ ['Install a different Nvim package, or rebuild with `CMAKE_BUILD_TYPE=RelWithDebInfo`.',
- \ s:suggest_faq])
- endif
-
- " check for slow shell invocation
- let s:slow_cmd_time = 1.5
- let s:start_time = reltime()
- call system('echo')
- let s:elapsed_time = reltimefloat(reltime(s:start_time))
- if s:elapsed_time > s:slow_cmd_time
- call health#report_warn(
- \ 'Slow shell invocation (took '.printf('%.2f', s:elapsed_time).' seconds).')
- endif
- endf
-
- call s:check_performance()
- ]=], false)
+ health.report_start('Performance')
+
+ -- Check buildtype
+ local buildtype = vim.fn.matchstr(vim.fn.execute('version'), [[\v\cbuild type:?\s*[^\n\r\t ]+]])
+ if empty(buildtype) then
+ health.report_error('failed to get build type from :version')
+ elseif vim.regex([[\v(MinSizeRel|Release|RelWithDebInfo)]]):match_str(buildtype) then
+ health.report_ok(buildtype)
+ else
+ health.report_info(buildtype)
+ health.report_warn('Non-optimized debug build. Nvim will be slower.', {
+ 'Install a different Nvim package, or rebuild with `CMAKE_BUILD_TYPE=RelWithDebInfo`.',
+ suggest_faq,
+ })
+ end
+
+ -- check for slow shell invocation
+ local slow_cmd_time = 1.5
+ local start_time = vim.fn.reltime()
+ vim.fn.system('echo')
+ local elapsed_time = vim.fn.reltimefloat(vim.fn.reltime(start_time))
+ if elapsed_time > slow_cmd_time then
+ health.report_warn(
+ 'Slow shell invocation (took ' .. vim.fn.printf('%.2f', elapsed_time) .. ' seconds).'
+ )
+ end
end
-- Load the remote plugin manifest file and check for unregistered plugins
local function check_rplugin_manifest()
- vim.api.nvim_exec(
- [=[
- func! s:check_rplugin_manifest() abort
- call health#report_start('Remote Plugins')
- let existing_rplugins = {}
-
- for item in remote#host#PluginsForHost('python')
- let existing_rplugins[item.path] = 'python'
- endfor
-
- for item in remote#host#PluginsForHost('python3')
- let existing_rplugins[item.path] = 'python3'
- endfor
-
- let require_update = 0
-
- for path in map(split(&runtimepath, ','), 'resolve(v:val)')
- let python_glob = glob(path.'/rplugin/python*', 1, 1)
- if empty(python_glob)
- continue
- endif
-
- let python_dir = python_glob[0]
- let python_version = fnamemodify(python_dir, ':t')
-
- for script in glob(python_dir.'/*.py', 1, 1)
- \ + glob(python_dir.'/*/__init__.py', 1, 1)
- let contents = join(readfile(script))
- if contents =~# '\<\%(from\|import\)\s\+neovim\>'
- if script =~# '[\/]__init__\.py$'
- let script = tr(fnamemodify(script, ':h'), '\', '/')
- endif
-
- if !has_key(existing_rplugins, script)
- let msg = printf('"%s" is not registered.', fnamemodify(path, ':t'))
- if python_version ==# 'pythonx'
- if !has('python3')
- let msg .= ' (python3 not available)'
- endif
- elseif !has(python_version)
- let msg .= printf(' (%s not available)', python_version)
- else
- let require_update = 1
- endif
-
- call health#report_warn(msg)
- endif
-
- break
- endif
- endfor
- endfor
-
- if require_update
- call health#report_warn('Out of date', ['Run `:UpdateRemotePlugins`'])
- else
- call health#report_ok('Up to date')
- endif
- endf
+ health.report_start('Remote Plugins')
- call s:check_rplugin_manifest()
- ]=],
- false
- )
+ local existing_rplugins = {}
+ for _, item in ipairs(vim.fn['remote#host#PluginsForHost']('python')) do
+ existing_rplugins[item.path] = 'python'
+ end
+
+ for item in ipairs(vim.fn['remote#host#PluginsForHost']('python3')) do
+ existing_rplugins[item.path] = 'python3'
+ end
+
+ local require_update = false
+ local handle_path = function(path)
+ local python_glob = vim.fn.glob(path .. '/rplugin/python*', true, true)
+ if empty(python_glob) then
+ return
+ end
+
+ local python_dir = python_glob[1]
+ local python_version = vim.fn.fnamemodify(python_dir, ':t')
+
+ local scripts = vim.fn.glob(python_dir .. '/*.py', true, true)
+ vim.list_extend(scripts, vim.fn.glob(python_dir .. '/*/__init__.py', true, true))
+
+ for script in ipairs(scripts) do
+ local contents = vim.fn.join(vim.fn.readfile(script))
+ if vim.regex([[\<\%(from\|import\)\s\+neovim\>]]):match_str(contents) then
+ if vim.regex([[[\/]__init__\.py$]]):match_str(script) then
+ script = vim.fn.tr(vim.fn.fnamemodify(script, ':h'), '\\', '/')
+ end
+ if not existing_rplugins[script] then
+ local msg = vim.fn.printf('"%s" is not registered.', vim.fn.fnamemodify(path, ':t'))
+ if python_version == 'pythonx' then
+ if not has('python3') then
+ msg = msg .. ' (python3 not available)'
+ end
+ elseif not has(python_version) then
+ msg = msg .. vim.fn.printf(' (%s not available)', python_version)
+ else
+ require_update = true
+ end
+
+ health.report_warn(msg)
+ end
+
+ break
+ end
+ end
+ end
+
+ for _, path in ipairs(vim.fn.map(vim.fn.split(vim.o.runtimepath, ','), 'resolve(v:val)')) do
+ handle_path(path)
+ end
+
+ if require_update then
+ health.report_warn('Out of date', { 'Run `:UpdateRemotePlugins`' })
+ else
+ health.report_ok('Up to date')
+ end
end
local function check_tmux()
- vim.api.nvim_exec([=[
- let s:suggest_faq = ']=] .. suggest_faq .. [=['
-
- func! s:get_tmux_option(option) abort
- let cmd = 'tmux show-option -qvg '.a:option " try global scope
- let out = system(split(cmd))
- let val = substitute(out, '\v(\s|\r|\n)', '', 'g')
- if v:shell_error
- call health#report_error('command failed: '.cmd."\n".out)
+ if empty(vim.env.TMUX) or not executable('tmux') then
+ return
+ end
+
+ local get_tmux_option = function(option)
+ local cmd = 'tmux show-option -qvg ' .. option -- try global scope
+ local out = vim.fn.system(vim.fn.split(cmd))
+ local val = vim.fn.substitute(out, [[\v(\s|\r|\n)]], '', 'g')
+ if shell_error() then
+ health.report_error('command failed: ' .. cmd .. '\n' .. out)
return 'error'
- elseif empty(val)
- let cmd = 'tmux show-option -qvgs '.a:option " try session scope
- let out = system(split(cmd))
- let val = substitute(out, '\v(\s|\r|\n)', '', 'g')
- if v:shell_error
- call health#report_error('command failed: '.cmd."\n".out)
+ elseif empty(val) then
+ cmd = 'tmux show-option -qvgs ' .. option -- try session scope
+ out = vim.fn.system(vim.fn.split(cmd))
+ val = vim.fn.substitute(out, [[\v(\s|\r|\n)]], '', 'g')
+ if shell_error() then
+ health.report_error('command failed: ' .. cmd .. '\n' .. out)
return 'error'
- endif
- endif
+ end
+ end
return val
- endf
+ end
- func! s:check_tmux() abort
- if empty($TMUX) || !executable('tmux')
- return
- endif
- call health#report_start('tmux')
-
- " check escape-time
- let suggestions = ["set escape-time in ~/.tmux.conf:\nset-option -sg escape-time 10",
- \ s:suggest_faq]
- let tmux_esc_time = s:get_tmux_option('escape-time')
- if tmux_esc_time !=# 'error'
- if empty(tmux_esc_time)
- call health#report_error('`escape-time` is not set', suggestions)
- elseif tmux_esc_time > 300
- call health#report_error(
- \ '`escape-time` ('.tmux_esc_time.') is higher than 300ms', suggestions)
- else
- call health#report_ok('escape-time: '.tmux_esc_time)
- endif
- endif
-
- " check focus-events
- let suggestions = ["(tmux 1.9+ only) Set `focus-events` in ~/.tmux.conf:\nset-option -g focus-events on"]
- let tmux_focus_events = s:get_tmux_option('focus-events')
- if tmux_focus_events !=# 'error'
- if empty(tmux_focus_events) || tmux_focus_events !=# 'on'
- call health#report_warn(
- \ "`focus-events` is not enabled. |'autoread'| may not work.", suggestions)
- else
- call health#report_ok('focus-events: '.tmux_focus_events)
- endif
- endif
-
- " check default-terminal and $TERM
- call health#report_info('$TERM: '.$TERM)
- let cmd = 'tmux show-option -qvg default-terminal'
- let out = system(split(cmd))
- let tmux_default_term = substitute(out, '\v(\s|\r|\n)', '', 'g')
- if empty(tmux_default_term)
- let cmd = 'tmux show-option -qvgs default-terminal'
- let out = system(split(cmd))
- let tmux_default_term = substitute(out, '\v(\s|\r|\n)', '', 'g')
- endif
-
- if v:shell_error
- call health#report_error('command failed: '.cmd."\n".out)
- elseif tmux_default_term !=# $TERM
- call health#report_info('default-terminal: '.tmux_default_term)
- call health#report_error(
- \ '$TERM differs from the tmux `default-terminal` setting. Colors might look wrong.',
- \ ['$TERM may have been set by some rc (.bashrc, .zshrc, ...).'])
- elseif $TERM !~# '\v(tmux-256color|screen-256color)'
- call health#report_error(
- \ '$TERM should be "screen-256color" or "tmux-256color" in tmux. Colors might look wrong.',
- \ ["Set default-terminal in ~/.tmux.conf:\nset-option -g default-terminal \"screen-256color\"",
- \ s:suggest_faq])
- endif
-
- " check for RGB capabilities
- let info = system(['tmux', 'show-messages', '-JT'])
- let has_tc = stridx(info, " Tc: (flag) true") != -1
- let has_rgb = stridx(info, " RGB: (flag) true") != -1
- if !has_tc && !has_rgb
- call health#report_warn(
- \ "Neither Tc nor RGB capability set. True colors are disabled. |'termguicolors'| won't work properly.",
- \ ["Put this in your ~/.tmux.conf and replace XXX by your $TERM outside of tmux:\nset-option -sa terminal-overrides ',XXX:RGB'",
- \ "For older tmux versions use this instead:\nset-option -ga terminal-overrides ',XXX:Tc'"])
- endif
- endf
-
- call s:check_tmux()
- ]=], false)
+ health.report_start('tmux')
+
+ -- check escape-time
+ local suggestions =
+ { 'set escape-time in ~/.tmux.conf:\nset-option -sg escape-time 10', suggest_faq }
+ local tmux_esc_time = get_tmux_option('escape-time')
+ if tmux_esc_time ~= 'error' then
+ if empty(tmux_esc_time) then
+ health.report_error('`escape-time` is not set', suggestions)
+ elseif tonumber(tmux_esc_time) > 300 then
+ health.report_error(
+ '`escape-time` (' .. tmux_esc_time .. ') is higher than 300ms',
+ suggestions
+ )
+ else
+ health.report_ok('escape-time: ' .. tmux_esc_time)
+ end
+ end
+
+ -- check focus-events
+ local tmux_focus_events = get_tmux_option('focus-events')
+ if tmux_focus_events ~= 'error' then
+ if empty(tmux_focus_events) or tmux_focus_events ~= 'on' then
+ health.report_warn(
+ "`focus-events` is not enabled. |'autoread'| may not work.",
+ { '(tmux 1.9+ only) Set `focus-events` in ~/.tmux.conf:\nset-option -g focus-events on' }
+ )
+ else
+ health.report_ok('focus-events: ' .. tmux_focus_events)
+ end
+ end
+
+ -- check default-terminal and $TERM
+ health.report_info('$TERM: ' .. vim.env.TERM)
+ local cmd = 'tmux show-option -qvg default-terminal'
+ local out = vim.fn.system(vim.fn.split(cmd))
+ local tmux_default_term = vim.fn.substitute(out, [[\v(\s|\r|\n)]], '', 'g')
+ if empty(tmux_default_term) then
+ cmd = 'tmux show-option -qvgs default-terminal'
+ out = vim.fn.system(vim.fn.split(cmd))
+ tmux_default_term = vim.fn.substitute(out, [[\v(\s|\r|\n)]], '', 'g')
+ end
+
+ if shell_error() then
+ health.report_error('command failed: ' .. cmd .. '\n' .. out)
+ elseif tmux_default_term ~= vim.env.TERM then
+ health.report_info('default-terminal: ' .. tmux_default_term)
+ health.report_error(
+ '$TERM differs from the tmux `default-terminal` setting. Colors might look wrong.',
+ { '$TERM may have been set by some rc (.bashrc, .zshrc, ...).' }
+ )
+ elseif not vim.regex([[\v(tmux-256color|screen-256color)]]):match_str(vim.env.TERM) then
+ health.report_error(
+ '$TERM should be "screen-256color" or "tmux-256color" in tmux. Colors might look wrong.',
+ {
+ 'Set default-terminal in ~/.tmux.conf:\nset-option -g default-terminal "screen-256color"',
+ suggest_faq,
+ }
+ )
+ end
+
+ -- check for RGB capabilities
+ local info = vim.fn.system({ 'tmux', 'display-message', '-p', '#{client_termfeatures}' })
+ info = vim.split(vim.trim(info), ',', { trimempty = true })
+ if not vim.tbl_contains(info, 'RGB') then
+ local has_rgb = false
+ if #info == 0 then
+ -- client_termfeatures may not be supported; fallback to checking show-messages
+ info = vim.fn.system({ 'tmux', 'show-messages', '-JT' })
+ has_rgb = info:find(' Tc: (flag) true', 1, true) or info:find(' RGB: (flag) true', 1, true)
+ end
+ if not has_rgb then
+ health.report_warn(
+ "Neither Tc nor RGB capability set. True colors are disabled. |'termguicolors'| won't work properly.",
+ {
+ "Put this in your ~/.tmux.conf and replace XXX by your $TERM outside of tmux:\nset-option -sa terminal-features ',XXX:RGB'",
+ "For older tmux versions use this instead:\nset-option -ga terminal-overrides ',XXX:Tc'",
+ }
+ )
+ end
+ end
end
local function check_terminal()
- vim.api.nvim_exec(
- [=[
- func! s:check_terminal() abort
- if !executable('infocmp')
- return
- endif
- call health#report_start('terminal')
- let cmd = 'infocmp -L'
- let out = system(split(cmd))
- let kbs_entry = matchstr(out, 'key_backspace=[^,[:space:]]*')
- let kdch1_entry = matchstr(out, 'key_dc=[^,[:space:]]*')
-
- if v:shell_error
- \ && (!has('win32')
- \ || empty(matchstr(out,
- \ 'infocmp: couldn''t open terminfo file .\+'
- \ ..'\%(conemu\|vtpcon\|win32con\)')))
- call health#report_error('command failed: '.cmd."\n".out)
- else
- call health#report_info(printf('key_backspace (kbs) terminfo entry: `%s`', (empty(kbs_entry) ? '? (not found)' : kbs_entry)))
- call health#report_info(printf('key_dc (kdch1) terminfo entry: `%s`', (empty(kbs_entry) ? '? (not found)' : kdch1_entry)))
- endif
- for env_var in ['XTERM_VERSION', 'VTE_VERSION', 'TERM_PROGRAM', 'COLORTERM', 'SSH_TTY']
- if exists('$'.env_var)
- call health#report_info(printf('$%s="%s"', env_var, eval('$'.env_var)))
- endif
- endfor
- endf
-
- call s:check_terminal()
- ]=],
- false
- )
+ if not executable('infocmp') then
+ return
+ end
+
+ health.report_start('terminal')
+ local cmd = 'infocmp -L'
+ local out = vim.fn.system(vim.fn.split(cmd))
+ local kbs_entry = vim.fn.matchstr(out, 'key_backspace=[^,[:space:]]*')
+ local kdch1_entry = vim.fn.matchstr(out, 'key_dc=[^,[:space:]]*')
+
+ if
+ shell_error()
+ and (
+ not has('win32')
+ or empty(
+ vim.fn.matchstr(
+ out,
+ [[infocmp: couldn't open terminfo file .\+\%(conemu\|vtpcon\|win32con\)]]
+ )
+ )
+ )
+ then
+ health.report_error('command failed: ' .. cmd .. '\n' .. out)
+ else
+ health.report_info(
+ vim.fn.printf(
+ 'key_backspace (kbs) terminfo entry: `%s`',
+ (empty(kbs_entry) and '? (not found)' or kbs_entry)
+ )
+ )
+
+ health.report_info(
+ vim.fn.printf(
+ 'key_dc (kdch1) terminfo entry: `%s`',
+ (empty(kbs_entry) and '? (not found)' or kdch1_entry)
+ )
+ )
+ end
+
+ for env_var in ipairs({ 'XTERM_VERSION', 'VTE_VERSION', 'TERM_PROGRAM', 'COLORTERM', 'SSH_TTY' }) do
+ if vim.env[env_var] then
+ health.report_info(vim.fn.printf('$%s="%s"', env_var, vim.env[env_var]))
+ end
+ end
end
function M.check()
diff --git a/runtime/lua/vim/_init_packages.lua b/runtime/lua/vim/_init_packages.lua
index 0c4ee8636d..e3a442af5e 100644
--- a/runtime/lua/vim/_init_packages.lua
+++ b/runtime/lua/vim/_init_packages.lua
@@ -42,8 +42,11 @@ function vim._load_package(name)
return nil
end
--- Insert vim._load_package after the preloader at position 2
-table.insert(package.loaders, 2, vim._load_package)
+-- TODO(bfredl): dedicated state for this?
+if vim.api then
+ -- Insert vim._load_package after the preloader at position 2
+ table.insert(package.loaders, 2, vim._load_package)
+end
-- builtin functions which always should be available
require('vim.shared')
@@ -78,6 +81,6 @@ function vim.empty_dict()
end
-- only on main thread: functions for interacting with editor state
-if not vim.is_thread() then
+if vim.api and not vim.is_thread() then
require('vim._editor')
end
diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua
index b73519f1be..d1a84fcecf 100644
--- a/runtime/lua/vim/filetype.lua
+++ b/runtime/lua/vim/filetype.lua
@@ -190,6 +190,7 @@ local extension = {
BUILD = 'bzl',
qc = 'c',
cabal = 'cabal',
+ capnp = 'capnp',
cdl = 'cdl',
toc = 'cdrtoc',
cfc = 'cf',
@@ -225,6 +226,7 @@ local extension = {
hook = function(path, bufnr)
return M.getlines(bufnr, 1) == '[Trigger]' and 'conf'
end,
+ nmconnection = 'confini',
mklx = 'context',
mkiv = 'context',
mkii = 'context',
@@ -330,6 +332,7 @@ local extension = {
am = 'elf',
exs = 'elixir',
elm = 'elm',
+ lc = 'elsa',
elv = 'elvish',
ent = function(path, bufnr)
return require('vim.filetype.detect').ent(bufnr)
@@ -566,6 +569,7 @@ local extension = {
libsonnet = 'jsonnet',
jsp = 'jsp',
jl = 'julia',
+ kdl = 'kdl',
kv = 'kivy',
kix = 'kix',
kts = 'kotlin',
@@ -1021,6 +1025,7 @@ local extension = {
texinfo = 'texinfo',
text = 'text',
tfvars = 'terraform-vars',
+ thrift = 'thrift',
tla = 'tla',
tli = 'tli',
toml = 'toml',
@@ -1459,6 +1464,7 @@ local filename = {
['Pipfile.lock'] = 'json',
['.firebaserc'] = 'json',
['.prettierrc'] = 'json',
+ ['.stylelintrc'] = 'json',
['.babelrc'] = 'jsonc',
['.eslintrc'] = 'jsonc',
['.hintrc'] = 'jsonc',
@@ -1694,6 +1700,7 @@ local filename = {
fglrxrc = 'xml',
['/etc/blkid.tab'] = 'xml',
['/etc/blkid.tab.old'] = 'xml',
+ ['.clangd'] = 'yaml',
['.clang-format'] = 'yaml',
['.clang-tidy'] = 'yaml',
['/etc/zprofile'] = 'zsh',
diff --git a/runtime/lua/vim/fs.lua b/runtime/lua/vim/fs.lua
index 65e6ca677c..a0d2c4c339 100644
--- a/runtime/lua/vim/fs.lua
+++ b/runtime/lua/vim/fs.lua
@@ -282,7 +282,7 @@ end
---
--- Examples:
--- <pre>lua
---- vim.fs.normalize('C:\\Users\\jdoe')
+--- vim.fs.normalize('C:\\\\Users\\\\jdoe')
--- --> 'C:/Users/jdoe'
---
--- vim.fs.normalize('~/src/neovim')
diff --git a/runtime/lua/vim/health.lua b/runtime/lua/vim/health.lua
index b875da0abc..044880e076 100644
--- a/runtime/lua/vim/health.lua
+++ b/runtime/lua/vim/health.lua
@@ -23,7 +23,20 @@ end
local path2name = function(path)
if path:match('%.lua$') then
-- Lua: transform "../lua/vim/lsp/health.lua" into "vim.lsp"
- return path:gsub('.-lua[%\\%/]', '', 1):gsub('[%\\%/]', '.'):gsub('%.health.-$', '')
+
+ -- Get full path, make sure all slashes are '/'
+ path = vim.fs.normalize(path)
+
+ -- Remove everything up to the last /lua/ folder
+ path = path:gsub('^.*/lua/', '')
+
+ -- Remove the filename (health.lua)
+ path = vim.fn.fnamemodify(path, ':h')
+
+ -- Change slashes to dots
+ path = path:gsub('/', '.')
+
+ return path
else
-- Vim: transform "../autoload/health/provider.vim" into "provider"
return vim.fn.fnamemodify(path, ':t:r')
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
index cfd6c938f7..c5392ac154 100644
--- a/runtime/lua/vim/lsp.lua
+++ b/runtime/lua/vim/lsp.lua
@@ -897,115 +897,114 @@ end
--
--- Starts and initializes a client with the given configuration.
---
---- Parameter `cmd` is required.
----
---- The following parameters describe fields in the {config} table.
----
----
----@param cmd: (table|string|fun(dispatchers: table):table) command string or
---- list treated like |jobstart()|. The command must launch the language server
---- process. `cmd` can also be a function that creates an RPC client.
---- The function receives a dispatchers table and must return a table with the
---- functions `request`, `notify`, `is_closing` and `terminate`
---- See |vim.lsp.rpc.request()| and |vim.lsp.rpc.notify()|
---- For TCP there is a built-in rpc client factory: |vim.lsp.rpc.connect()|
----
----@param cmd_cwd: (string, default=|getcwd()|) Directory to launch
---- the `cmd` process. Not related to `root_dir`.
----
----@param cmd_env: (table) Environment flags to pass to the LSP on
---- spawn. Can be specified using keys like a map or as a list with `k=v`
---- pairs or both. Non-string values are coerced to string.
---- Example:
---- <pre>
---- { "PRODUCTION=true"; "TEST=123"; PORT = 8080; HOST = "0.0.0.0"; }
---- </pre>
----
----@param detached: (boolean, default true) Daemonize the server process so that it runs in a
---- separate process group from Nvim. Nvim will shutdown the process on exit, but if Nvim fails to
---- exit cleanly this could leave behind orphaned server processes.
----
----@param workspace_folders (table) List of workspace folders passed to the
---- language server. For backwards compatibility rootUri and rootPath will be
---- derived from the first workspace folder in this list. See `workspaceFolders` in
---- the LSP spec.
----
----@param capabilities Map overriding the default capabilities defined by
---- |vim.lsp.protocol.make_client_capabilities()|, passed to the language
---- server on initialization. Hint: use make_client_capabilities() and modify
---- its result.
---- - Note: To send an empty dictionary use
---- `{[vim.type_idx]=vim.types.dictionary}`, else it will be encoded as an
---- array.
+--- Field `cmd` in {config} is required.
+---
+---@param config (table) Configuration for the server:
+--- - cmd: (table|string|fun(dispatchers: table):table) command string or
+--- list treated like |jobstart()|. The command must launch the language server
+--- process. `cmd` can also be a function that creates an RPC client.
+--- The function receives a dispatchers table and must return a table with the
+--- functions `request`, `notify`, `is_closing` and `terminate`
+--- See |vim.lsp.rpc.request()| and |vim.lsp.rpc.notify()|
+--- For TCP there is a built-in rpc client factory: |vim.lsp.rpc.connect()|
+---
+--- - cmd_cwd: (string, default=|getcwd()|) Directory to launch
+--- the `cmd` process. Not related to `root_dir`.
+---
+--- - cmd_env: (table) Environment flags to pass to the LSP on
+--- spawn. Can be specified using keys like a map or as a list with `k=v`
+--- pairs or both. Non-string values are coerced to string.
+--- Example:
+--- <pre>
+--- { "PRODUCTION=true"; "TEST=123"; PORT = 8080; HOST = "0.0.0.0"; }
+--- </pre>
+---
+--- - detached: (boolean, default true) Daemonize the server process so that it runs in a
+--- separate process group from Nvim. Nvim will shutdown the process on exit, but if Nvim fails to
+--- exit cleanly this could leave behind orphaned server processes.
+---
+--- - workspace_folders: (table) List of workspace folders passed to the
+--- language server. For backwards compatibility rootUri and rootPath will be
+--- derived from the first workspace folder in this list. See `workspaceFolders` in
+--- the LSP spec.
+---
+--- - capabilities: Map overriding the default capabilities defined by
+--- |vim.lsp.protocol.make_client_capabilities()|, passed to the language
+--- server on initialization. Hint: use make_client_capabilities() and modify
+--- its result.
+--- - Note: To send an empty dictionary use
+--- `{[vim.type_idx]=vim.types.dictionary}`, else it will be encoded as an
+--- array.
+---
+--- - handlers: Map of language server method names to |lsp-handler|
+---
+--- - settings: Map with language server specific settings. These are
+--- returned to the language server if requested via `workspace/configuration`.
+--- Keys are case-sensitive.
+---
+--- - commands: table Table that maps string of clientside commands to user-defined functions.
+--- Commands passed to start_client take precedence over the global command registry. Each key
+--- must be a unique command name, and the value is a function which is called if any LSP action
+--- (code action, code lenses, ...) triggers the command.
+---
+--- - init_options Values to pass in the initialization request
+--- as `initializationOptions`. See `initialize` in the LSP spec.
+---
+--- - name: (string, default=client-id) Name in log messages.
+---
+--- - get_language_id: function(bufnr, filetype) -> language ID as string.
+--- Defaults to the filetype.
+---
+--- - offset_encoding: (default="utf-16") One of "utf-8", "utf-16",
+--- or "utf-32" which is the encoding that the LSP server expects. Client does
+--- not verify this is correct.
+---
+--- - on_error: Callback with parameters (code, ...), invoked
+--- when the client operation throws an error. `code` is a number describing
+--- the error. Other arguments may be passed depending on the error kind. See
+--- `vim.lsp.rpc.client_errors` for possible errors.
+--- Use `vim.lsp.rpc.client_errors[code]` to get human-friendly name.
+---
+--- - before_init: Callback with parameters (initialize_params, config)
+--- invoked before the LSP "initialize" phase, where `params` contains the
+--- parameters being sent to the server and `config` is the config that was
+--- passed to |vim.lsp.start_client()|. You can use this to modify parameters before
+--- they are sent.
+---
+--- - on_init: Callback (client, initialize_result) invoked after LSP
+--- "initialize", where `result` is a table of `capabilities` and anything else
+--- the server may send. For example, clangd sends
+--- `initialize_result.offsetEncoding` if `capabilities.offsetEncoding` was
+--- sent to it. You can only modify the `client.offset_encoding` here before
+--- any notifications are sent. Most language servers expect to be sent client specified settings after
+--- initialization. Neovim does not make this assumption. A
+--- `workspace/didChangeConfiguration` notification should be sent
+--- to the server during on_init.
+---
+--- - on_exit Callback (code, signal, client_id) invoked on client
+--- exit.
+--- - code: exit code of the process
+--- - signal: number describing the signal used to terminate (if any)
+--- - client_id: client handle
---
----@param handlers Map of language server method names to |lsp-handler|
+--- - on_attach: Callback (client, bufnr) invoked when client
+--- attaches to a buffer.
---
----@param settings Map with language server specific settings. These are
---- returned to the language server if requested via `workspace/configuration`.
---- Keys are case-sensitive.
+--- - trace: ("off" | "messages" | "verbose" | nil) passed directly to the language
+--- server in the initialize request. Invalid/empty values will default to "off"
---
----@param commands table Table that maps string of clientside commands to user-defined functions.
---- Commands passed to start_client take precedence over the global command registry. Each key
---- must be a unique command name, and the value is a function which is called if any LSP action
---- (code action, code lenses, ...) triggers the command.
+--- - flags: A table with flags for the client. The current (experimental) flags are:
+--- - allow_incremental_sync (bool, default true): Allow using incremental sync for buffer edits
+--- - debounce_text_changes (number, default 150): Debounce didChange
+--- notifications to the server by the given number in milliseconds. No debounce
+--- occurs if nil
+--- - exit_timeout (number|boolean, default false): Milliseconds to wait for server to
+--- exit cleanly after sending the "shutdown" request before sending kill -15.
+--- If set to false, nvim exits immediately after sending the "shutdown" request to the server.
---
----@param init_options Values to pass in the initialization request
---- as `initializationOptions`. See `initialize` in the LSP spec.
----
----@param name (string, default=client-id) Name in log messages.
----
----@param get_language_id function(bufnr, filetype) -> language ID as string.
---- Defaults to the filetype.
----
----@param offset_encoding (default="utf-16") One of "utf-8", "utf-16",
---- or "utf-32" which is the encoding that the LSP server expects. Client does
---- not verify this is correct.
----
----@param on_error Callback with parameters (code, ...), invoked
---- when the client operation throws an error. `code` is a number describing
---- the error. Other arguments may be passed depending on the error kind. See
---- `vim.lsp.rpc.client_errors` for possible errors.
---- Use `vim.lsp.rpc.client_errors[code]` to get human-friendly name.
----
----@param before_init Callback with parameters (initialize_params, config)
---- invoked before the LSP "initialize" phase, where `params` contains the
---- parameters being sent to the server and `config` is the config that was
---- passed to |vim.lsp.start_client()|. You can use this to modify parameters before
---- they are sent.
----
----@param on_init Callback (client, initialize_result) invoked after LSP
---- "initialize", where `result` is a table of `capabilities` and anything else
---- the server may send. For example, clangd sends
---- `initialize_result.offsetEncoding` if `capabilities.offsetEncoding` was
---- sent to it. You can only modify the `client.offset_encoding` here before
---- any notifications are sent. Most language servers expect to be sent client specified settings after
---- initialization. Neovim does not make this assumption. A
---- `workspace/didChangeConfiguration` notification should be sent
---- to the server during on_init.
----
----@param on_exit Callback (code, signal, client_id) invoked on client
---- exit.
---- - code: exit code of the process
---- - signal: number describing the signal used to terminate (if any)
---- - client_id: client handle
----
----@param on_attach Callback (client, bufnr) invoked when client
---- attaches to a buffer.
----
----@param trace: "off" | "messages" | "verbose" | nil passed directly to the language
---- server in the initialize request. Invalid/empty values will default to "off"
----@param flags: A table with flags for the client. The current (experimental) flags are:
---- - allow_incremental_sync (bool, default true): Allow using incremental sync for buffer edits
---- - debounce_text_changes (number, default 150): Debounce didChange
---- notifications to the server by the given number in milliseconds. No debounce
---- occurs if nil
---- - exit_timeout (number|boolean, default false): Milliseconds to wait for server to
---- exit cleanly after sending the "shutdown" request before sending kill -15.
---- If set to false, nvim exits immediately after sending the "shutdown" request to the server.
----
----@param root_dir string Directory where the LSP
---- server will base its workspaceFolders, rootUri, and rootPath
---- on initialization.
+--- - root_dir: (string) Directory where the LSP
+--- server will base its workspaceFolders, rootUri, and rootPath
+--- on initialization.
---
---@returns Client id. |vim.lsp.get_client_by_id()| Note: client may not be
--- fully initialized. Use `on_init` to do any actions once
@@ -1557,15 +1556,21 @@ end
--- Notify all attached clients that a buffer has changed.
local text_document_did_change_handler
do
- text_document_did_change_handler =
- function(_, bufnr, changedtick, firstline, lastline, new_lastline)
- -- Detach (nvim_buf_attach) via returning True to on_lines if no clients are attached
- if tbl_isempty(all_buffer_active_clients[bufnr] or {}) then
- return true
- end
- util.buf_versions[bufnr] = changedtick
- changetracking.send_changes(bufnr, firstline, lastline, new_lastline)
+ text_document_did_change_handler = function(
+ _,
+ bufnr,
+ changedtick,
+ firstline,
+ lastline,
+ new_lastline
+ )
+ -- Detach (nvim_buf_attach) via returning True to on_lines if no clients are attached
+ if tbl_isempty(all_buffer_active_clients[bufnr] or {}) then
+ return true
end
+ util.buf_versions[bufnr] = changedtick
+ changetracking.send_changes(bufnr, firstline, lastline, new_lastline)
+ end
end
---@private
diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua
index 8f4bd15eaa..6ac885c78f 100644
--- a/runtime/lua/vim/lsp/buf.lua
+++ b/runtime/lua/vim/lsp/buf.lua
@@ -197,20 +197,21 @@ function M.format(options)
clients = vim.tbl_filter(options.filter, clients)
end
+ local mode = api.nvim_get_mode().mode
+ local range = options.range
+ if not range and mode == 'v' or mode == 'V' then
+ range = range_from_selection()
+ end
+ local method = range and 'textDocument/rangeFormatting' or 'textDocument/formatting'
+
clients = vim.tbl_filter(function(client)
- return client.supports_method('textDocument/formatting')
+ return client.supports_method(method)
end, clients)
if #clients == 0 then
vim.notify('[LSP] Format request failed, no matching language servers.')
end
- local mode = api.nvim_get_mode().mode
- local range = options.range
- if not range and mode == 'v' or mode == 'V' then
- range = range_from_selection()
- end
-
---@private
local function set_range(client, params)
if range then
@@ -221,7 +222,6 @@ function M.format(options)
return params
end
- local method = range and 'textDocument/rangeFormatting' or 'textDocument/formatting'
if options.async then
local do_format
do_format = function(idx, client)
@@ -487,7 +487,7 @@ function M.add_workspace_folder(workspace_folder)
end
local params = util.make_workspace_params(
{ { uri = vim.uri_from_fname(workspace_folder), name = workspace_folder } },
- { {} }
+ {}
)
for _, client in pairs(vim.lsp.get_active_clients({ bufnr = 0 })) do
local found = false
@@ -733,6 +733,7 @@ end
--- List of LSP `CodeActionKind`s used to filter the code actions.
--- Most language servers support values like `refactor`
--- or `quickfix`.
+--- - triggerKind (number|nil): The reason why code actions were requested.
--- - filter: (function|nil)
--- Predicate taking an `CodeAction` and returning a boolean.
--- - apply: (boolean|nil)
@@ -746,6 +747,7 @@ end
--- using mark-like indexing. See |api-indexing|
---
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction
+---@see vim.lsp.protocol.constants.CodeActionTriggerKind
function M.code_action(options)
validate({ options = { options, 't', true } })
options = options or {}
@@ -755,6 +757,9 @@ function M.code_action(options)
options = { options = options }
end
local context = options.context or {}
+ if not context.triggerKind then
+ context.triggerKind = vim.lsp.protocol.CodeActionTriggerKind.Invoked
+ end
if not context.diagnostics then
local bufnr = api.nvim_get_current_buf()
context.diagnostics = vim.lsp.diagnostic.get_line_diagnostics(bufnr)
diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua
index b383ca1c35..5096100a60 100644
--- a/runtime/lua/vim/lsp/handlers.lua
+++ b/runtime/lua/vim/lsp/handlers.lua
@@ -131,9 +131,10 @@ end
--see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit
M['workspace/applyEdit'] = function(_, workspace_edit, ctx)
- if not workspace_edit then
- return
- end
+ assert(
+ workspace_edit,
+ 'workspace/applyEdit must be called with `ApplyWorkspaceEditParams`. Server is violating the specification'
+ )
-- TODO(ashkan) Do something more with label?
local client_id = ctx.client_id
local client = vim.lsp.get_client_by_id(client_id)
diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua
index 92cda0b34f..12345b6c8c 100644
--- a/runtime/lua/vim/lsp/protocol.lua
+++ b/runtime/lua/vim/lsp/protocol.lua
@@ -304,6 +304,17 @@ local constants = {
-- Base kind for an organize imports source action
SourceOrganizeImports = 'source.organizeImports',
},
+ -- The reason why code actions were requested.
+ ---@enum lsp.CodeActionTriggerKind
+ CodeActionTriggerKind = {
+ -- Code actions were explicitly requested by the user or by an extension.
+ Invoked = 1,
+ -- Code actions were requested automatically.
+ --
+ -- This typically happens when current selection in a file changes, but can
+ -- also be triggered when file content changes.
+ Automatic = 2,
+ },
}
for k, v in pairs(constants) do
diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua
index b53c66ba63..cc48e3f193 100644
--- a/runtime/lua/vim/shared.lua
+++ b/runtime/lua/vim/shared.lua
@@ -60,6 +60,7 @@ end)()
--- Splits a string at each instance of a separator.
---
---@see |vim.split()|
+---@see |luaref-patterns|
---@see https://www.lua.org/pil/20.2.html
---@see http://lua-users.org/wiki/StringLibraryTutorial
---
@@ -457,6 +458,33 @@ function vim.tbl_flatten(t)
return result
end
+--- Enumerate a table sorted by its keys.
+---
+---@see Based on https://github.com/premake/premake-core/blob/master/src/base/table.lua
+---
+---@param t table List-like table
+---@return iterator over sorted keys and their values
+function vim.spairs(t)
+ assert(type(t) == 'table', string.format('Expected table, got %s', type(t)))
+
+ -- collect the keys
+ local keys = {}
+ for k in pairs(t) do
+ table.insert(keys, k)
+ end
+ table.sort(keys)
+
+ -- Return the iterator function.
+ -- TODO(justinmk): Return "iterator function, table {t}, and nil", like pairs()?
+ local i = 0
+ return function()
+ i = i + 1
+ if keys[i] then
+ return keys[i], t[keys[i]]
+ end
+ end
+end
+
--- Tests if a Lua table can be treated as an array.
---
--- Empty table `{}` is assumed to be an array, unless it was created by
@@ -529,6 +557,7 @@ end
--- Trim whitespace (Lua pattern "%s") from both sides of a string.
---
+---@see |luaref-patterns|
---@see https://www.lua.org/pil/20.2.html
---@param s string String to trim
---@return string String with whitespace removed from its beginning and end
diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua
index e99994c8a9..d77a0d0d03 100644
--- a/runtime/lua/vim/treesitter/highlighter.lua
+++ b/runtime/lua/vim/treesitter/highlighter.lua
@@ -88,7 +88,6 @@ function TSHighlighter.new(tree, opts)
end
end
- self.orig_syntax = vim.bo[self.bufnr].syntax
self.orig_spelloptions = vim.bo[self.bufnr].spelloptions
vim.bo[self.bufnr].syntax = ''
@@ -120,8 +119,11 @@ function TSHighlighter:destroy()
end
if vim.api.nvim_buf_is_loaded(self.bufnr) then
- vim.bo[self.bufnr].syntax = self.orig_syntax
vim.bo[self.bufnr].spelloptions = self.orig_spelloptions
+ vim.b[self.bufnr].ts_highlight = nil
+ if vim.g.syntax_on == 1 then
+ a.nvim_exec_autocmds('FileType', { group = 'syntaxset', buffer = self.bufnr })
+ end
end
end
diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua
index c92d63b8c4..8634e53b7b 100644
--- a/runtime/lua/vim/treesitter/language.lua
+++ b/runtime/lua/vim/treesitter/language.lua
@@ -6,7 +6,7 @@ local M = {}
---
--- Parsers are searched in the `parser` runtime directory, or the provided {path}
---
----@param lang string Language the parser should parse
+---@param lang string Language the parser should parse (alphanumerical and `_` only)
---@param path (string|nil) Optional path the parser is located at
---@param silent (boolean|nil) Don't throw an error if language not found
---@param symbol_name (string|nil) Internal symbol name for the language to load
@@ -16,13 +16,19 @@ function M.require_language(lang, path, silent, symbol_name)
return true
end
if path == nil then
- local fname = 'parser/' .. vim.fn.fnameescape(lang) .. '.*'
+ if not (lang and lang:match('[%w_]+') == lang) then
+ if silent then
+ return false
+ end
+ error("'" .. lang .. "' is not a valid language name")
+ end
+
+ local fname = 'parser/' .. lang .. '.*'
local paths = a.nvim_get_runtime_file(fname, false)
if #paths == 0 then
if silent then
return false
end
-
error("no parser for '" .. lang .. "' language, see :help treesitter-parsers")
end
path = paths[1]
diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua
index 4bec5db527..dbf134573d 100644
--- a/runtime/lua/vim/treesitter/query.lua
+++ b/runtime/lua/vim/treesitter/query.lua
@@ -419,7 +419,8 @@ local directive_handlers = {
--- Adds a new predicate to be used in queries
---
---@param name string Name of the predicate, without leading #
----@param handler function(match:string, pattern:string, bufnr:number, predicate:function)
+---@param handler function(match:table, pattern:string, bufnr:number, predicate:string[])
+--- - see |vim.treesitter.query.add_directive()| for argument meanings
function M.add_predicate(name, handler, force)
if predicate_handlers[name] and not force then
error(string.format('Overriding %s', name))
@@ -436,7 +437,12 @@ end
--- metadata table `metadata[capture_id].key = value`
---
---@param name string Name of the directive, without leading #
----@param handler function(match:string, pattern:string, bufnr:number, predicate:function, metadata:table)
+---@param handler function(match:table, pattern:string, bufnr:number, predicate:string[], metadata:table)
+--- - match: see |treesitter-query|
+--- - node-level data are accessible via `match[capture_id]`
+--- - pattern: see |treesitter-query|
+--- - predicate: list of strings containing the full directive being called, e.g.
+--- `(node (#set! conceal "-"))` would get the predicate `{ "#set!", "conceal", "-" }`
function M.add_directive(name, handler, force)
if directive_handlers[name] and not force then
error(string.format('Overriding %s', name))
diff --git a/runtime/nvim.appdata.xml b/runtime/nvim.appdata.xml
index 7411a7190a..7d2ea49df4 100644
--- a/runtime/nvim.appdata.xml
+++ b/runtime/nvim.appdata.xml
@@ -26,9 +26,12 @@
</screenshots>
<releases>
+ <release date="2023-02-02" version="0.8.3"/>
<release date="2022-12-29" version="0.8.2"/>
<release date="2022-11-14" version="0.8.1"/>
<release date="2022-09-30" version="0.8.0"/>
+ <release date="2022-06-26" version="0.7.2"/>
+ <release date="2022-06-26" version="0.7.1"/>
<release date="2022-04-15" version="0.7.0"/>
<release date="2021-12-31" version="0.6.1"/>
<release date="2021-11-30" version="0.6.0"/>
diff --git a/runtime/tutor/tutor.tutor.json b/runtime/tutor/tutor.tutor.json
index bf3eae8586..e8628e2f0e 100644
--- a/runtime/tutor/tutor.tutor.json
+++ b/runtime/tutor/tutor.tutor.json
@@ -2,8 +2,8 @@
"expect": {
"63": "This is text with **important information**",
"64": "This is text with **important information**",
- "71": "Document '&variable'",
- "72": "Document '&variable'",
+ "71": "TODO: Document '&variable'",
+ "72": "TODO: Document '&variable'",
"78": "# This is a level 1 header",
"79": "# This is a level 1 header",
"80": "### This is a level 3 header",
diff --git a/scripts/bump_deps.lua b/scripts/bump_deps.lua
index 1873c3cd0d..f980e800cf 100755
--- a/scripts/bump_deps.lua
+++ b/scripts/bump_deps.lua
@@ -54,7 +54,7 @@ local function run_die(cmd, err_msg)
end
local function require_executable(cmd)
- local cmd_path = run_die({ 'command', '-v', cmd }, cmd .. ' not found!')
+ local cmd_path = run_die({ 'sh', '-c', 'command -v ' .. cmd }, cmd .. ' not found!')
run_die({ 'test', '-x', cmd_path }, cmd .. ' is not executable')
end
diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua
index fa7c14eaa3..2563f2f410 100644
--- a/scripts/gen_help_html.lua
+++ b/scripts/gen_help_html.lua
@@ -60,19 +60,18 @@ local exclude_invalid = {
["'previewpopup'"] = "quickref.txt",
["'pvp'"] = "quickref.txt",
["'string'"] = "eval.txt",
- Query = "treesitter.txt",
- ["eq?"] = "treesitter.txt",
- ["lsp-request"] = "lsp.txt",
- matchit = "vim_diff.txt",
- ["matchit.txt"] = "help.txt",
+ Query = 'treesitter.txt',
+ ['eq?'] = 'treesitter.txt',
+ ['lsp-request'] = 'lsp.txt',
+ matchit = 'vim_diff.txt',
+ ['matchit.txt'] = 'help.txt',
["set!"] = "treesitter.txt",
- ["v:_null_blob"] = "builtin.txt",
- ["v:_null_dict"] = "builtin.txt",
- ["v:_null_list"] = "builtin.txt",
- ["v:_null_string"] = "builtin.txt",
- ["vim.lsp.buf_request()"] = "lsp.txt",
- ["vim.lsp.util.get_progress_messages()"] = "lsp.txt",
- ["vim.treesitter.start()"] = "treesitter.txt",
+ ['v:_null_blob'] = 'builtin.txt',
+ ['v:_null_dict'] = 'builtin.txt',
+ ['v:_null_list'] = 'builtin.txt',
+ ['v:_null_string'] = 'builtin.txt',
+ ['vim.lsp.buf_request()'] = 'lsp.txt',
+ ['vim.lsp.util.get_progress_messages()'] = 'lsp.txt',
}
-- False-positive "invalid URLs".
diff --git a/scripts/genvimvim.lua b/scripts/genvimvim.lua
index 868084a583..3e9e7077be 100644
--- a/scripts/genvimvim.lua
+++ b/scripts/genvimvim.lua
@@ -11,6 +11,8 @@ local funcs_file = arg[3]
package.path = nvimsrcdir .. '/?.lua;' .. package.path
+_G.vim = loadfile(nvimsrcdir..'/../../runtime/lua/vim/shared.lua')()
+
local lld = {}
local syn_fd = io.open(syntax_file, 'w')
lld.line_length = 0
@@ -115,7 +117,7 @@ end
local nvimau_start = 'syn keyword nvimAutoEvent contained '
w('\n\n' .. nvimau_start)
-for au, _ in pairs(auevents.nvim_specific) do
+for au, _ in vim.spairs(auevents.nvim_specific) do
if lld.line_length > 850 then
w('\n' .. nvimau_start)
end
@@ -126,7 +128,7 @@ w('\n\nsyn case match')
local vimfun_start = 'syn keyword vimFuncName contained '
w('\n\n' .. vimfun_start)
local funcs = mpack.unpack(io.open(funcs_file, 'rb'):read("*all"))
-for name, _ in pairs(funcs) do
+for _, name in ipairs(funcs) do
if name then
if lld.line_length > 850 then
w('\n' .. vimfun_start)
diff --git a/src/mpack/mpack_core.c b/src/mpack/mpack_core.c
index 4ee67a032a..3424f444b9 100644
--- a/src/mpack/mpack_core.c
+++ b/src/mpack/mpack_core.c
@@ -173,6 +173,9 @@ MPACK_API int mpack_write(mpack_tokbuf_t *tokbuf, char **buf, size_t *buflen,
int mpack_rtoken(const char **buf, size_t *buflen, mpack_token_t *tok)
{
+ if (*buflen == 0) {
+ return MPACK_EOF;
+ }
unsigned char t = ADVANCE(buf, buflen);
if (t < 0x80) {
/* positive fixint */
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index b95709526b..7b56af59da 100755
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -22,24 +22,19 @@ find_package(TreeSitter REQUIRED)
target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${TreeSitter_INCLUDE_DIRS})
target_link_libraries(main_lib INTERFACE ${TreeSitter_LIBRARIES})
-find_package(UNIBILIUM 2.0 REQUIRED)
-target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${UNIBILIUM_INCLUDE_DIRS})
-target_link_libraries(main_lib INTERFACE ${UNIBILIUM_LIBRARIES})
+find_package(unibilium 2.0 REQUIRED)
+target_link_libraries(main_lib INTERFACE unibilium)
find_package(LibTermkey 0.22 REQUIRED)
target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${LIBTERMKEY_INCLUDE_DIRS})
target_link_libraries(main_lib INTERFACE ${LIBTERMKEY_LIBRARIES})
-find_package(LIBVTERM 0.3 REQUIRED)
-target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${LIBVTERM_INCLUDE_DIRS})
-target_link_libraries(main_lib INTERFACE ${LIBVTERM_LIBRARIES})
+find_package(libvterm 0.3 REQUIRED)
+target_link_libraries(main_lib INTERFACE libvterm)
-if(Iconv_FOUND)
- target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${Iconv_INCLUDE_DIRS})
- if(Iconv_LIBRARIES)
- target_link_libraries(main_lib INTERFACE ${Iconv_LIBRARIES})
- endif()
-endif()
+find_package(Iconv REQUIRED)
+target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${Iconv_INCLUDE_DIRS})
+target_link_libraries(main_lib INTERFACE ${Iconv_LIBRARIES})
option(ENABLE_LIBINTL "enable libintl" ON)
if(ENABLE_LIBINTL)
@@ -57,7 +52,7 @@ if(PREFER_LUA)
find_package(Lua 5.1 EXACT REQUIRED)
target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${LUA_INCLUDE_DIR})
target_link_libraries(main_lib INTERFACE ${LUA_LIBRARIES})
- # Passive (not REQUIRED): if LUAJIT_FOUND is not set, nvim-test is skipped.
+ # Passive (not REQUIRED): if LUAJIT_FOUND is not set, fixtures for unittests is skipped.
find_package(LuaJit)
else()
find_package(LuaJit REQUIRED)
@@ -65,12 +60,6 @@ else()
target_link_libraries(main_lib INTERFACE ${LUAJIT_LIBRARIES})
endif()
-# Determine platform's threading library. Set CMAKE_THREAD_PREFER_PTHREAD
-# explicitly to indicate a strong preference for pthread.
-set(CMAKE_THREAD_PREFER_PTHREAD ON)
-find_package(Threads REQUIRED)
-target_link_libraries(main_lib INTERFACE ${CMAKE_THREAD_LIBS_INIT})
-
option(ENABLE_IWYU "Run include-what-you-use with the compiler." OFF)
if(ENABLE_IWYU)
find_program(IWYU_PRG NAMES include-what-you-use iwyu)
@@ -85,13 +74,18 @@ if(ENABLE_IWYU)
string(APPEND iwyu_flags "-Xiwyu;--mapping_file=${PROJECT_SOURCE_DIR}/cmake.config/iwyu/gcc.symbols.imp")
set_target_properties(nvim PROPERTIES C_INCLUDE_WHAT_YOU_USE "${iwyu_flags}")
- target_compile_definitions(nvim PRIVATE EXITFREE)
+ target_compile_definitions(main_lib INTERFACE EXITFREE)
endif()
if(MSVC)
- # XXX: /W4 gives too many warnings. #3241
- target_compile_options(main_lib INTERFACE -W1 -wd4311)
+ # TODO(dundargoc): bump warning level
+ target_compile_options(main_lib INTERFACE -W2)
+
+ # Disable warnings that give too many false positives.
+ target_compile_options(main_lib INTERFACE -wd4311 -wd4146)
target_compile_definitions(main_lib INTERFACE _CRT_SECURE_NO_WARNINGS _CRT_NONSTDC_NO_DEPRECATE)
+
+ target_sources(main_lib INTERFACE ${CMAKE_CURRENT_LIST_DIR}/os/nvim.manifest)
else()
target_compile_options(main_lib INTERFACE -Wall -Wextra -pedantic -Wno-unused-parameter
-Wstrict-prototypes -std=gnu99 -Wshadow -Wconversion
@@ -179,24 +173,6 @@ if(CI_BUILD)
endif()
endif()
-list(APPEND CMAKE_REQUIRED_INCLUDES "${UNIBILIUM_INCLUDE_DIRS}")
-list(APPEND CMAKE_REQUIRED_LIBRARIES "${UNIBILIUM_LIBRARIES}")
-check_c_source_compiles("
-#include <unibilium.h>
-
-int
-main(void)
-{
- unibi_str_from_var(unibi_var_from_str(\"\"));
- return unibi_num_from_var(unibi_var_from_num(0));
-}
-" UNIBI_HAS_VAR_FROM)
-list(REMOVE_ITEM CMAKE_REQUIRED_INCLUDES "${UNIBILIUM_INCLUDE_DIRS}")
-list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES "${UNIBILIUM_LIBRARIES}")
-if(UNIBI_HAS_VAR_FROM)
- target_compile_definitions(main_lib INTERFACE NVIM_UNIBI_HAS_VAR_FROM)
-endif()
-
list(APPEND CMAKE_REQUIRED_INCLUDES "${MSGPACK_INCLUDE_DIRS}")
check_c_source_compiles("
#include <msgpack.h>
@@ -455,8 +431,11 @@ endforeach()
list(REMOVE_ITEM NVIM_SOURCES ${to_remove})
-if(NOT MSVC)
- # xdiff, mpack, lua-cjson: inlined external project, we don't maintain it. #9306
+# xdiff, mpack, lua-cjson: inlined external project, we don't maintain it. #9306
+if(MSVC)
+ set_source_files_properties(
+ ${EXTERNAL_SOURCES} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} /wd4090 /wd4244")
+else()
set_source_files_properties(
${EXTERNAL_SOURCES} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-conversion -Wno-missing-noreturn -Wno-missing-format-attribute -Wno-double-promotion -Wno-strict-prototypes")
endif()
@@ -564,11 +543,11 @@ add_custom_command(OUTPUT ${GENERATED_UNICODE_TABLES}
add_custom_command(
OUTPUT ${GENERATED_API_DISPATCH} ${GENERATED_FUNCS_METADATA}
${API_METADATA} ${LUA_API_C_BINDINGS}
- COMMAND ${LUA_PRG} ${API_DISPATCH_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}
- ${GENERATED_API_DISPATCH}
- ${GENERATED_FUNCS_METADATA} ${API_METADATA}
- ${LUA_API_C_BINDINGS}
- ${API_HEADERS}
+ COMMAND ${LUA_GEN_PRG} ${API_DISPATCH_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}
+ ${GENERATED_API_DISPATCH}
+ ${GENERATED_FUNCS_METADATA} ${API_METADATA}
+ ${LUA_API_C_BINDINGS}
+ ${API_HEADERS}
DEPENDS
${API_HEADERS}
${MSGPACK_RPC_HEADERS}
@@ -613,12 +592,12 @@ add_custom_command(
${GENERATED_UI_EVENTS_REMOTE}
${GENERATED_UI_EVENTS_METADATA}
${GENERATED_UI_EVENTS_CLIENT}
- COMMAND ${LUA_PRG} ${API_UI_EVENTS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}
- ${CMAKE_CURRENT_LIST_DIR}/api/ui_events.in.h
- ${GENERATED_UI_EVENTS_CALL}
- ${GENERATED_UI_EVENTS_REMOTE}
- ${GENERATED_UI_EVENTS_METADATA}
- ${GENERATED_UI_EVENTS_CLIENT}
+ COMMAND ${LUA_GEN_PRG} ${API_UI_EVENTS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}
+ ${CMAKE_CURRENT_LIST_DIR}/api/ui_events.in.h
+ ${GENERATED_UI_EVENTS_CALL}
+ ${GENERATED_UI_EVENTS_REMOTE}
+ ${GENERATED_UI_EVENTS_METADATA}
+ ${GENERATED_UI_EVENTS_CLIENT}
DEPENDS
${API_UI_EVENTS_GENERATOR}
${GENERATOR_C_GRAMMAR}
@@ -685,8 +664,6 @@ foreach(hfile ${NVIM_GENERATED_FOR_HEADERS})
endif()
endforeach()
-# Our dependencies come first.
-
if (CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
target_link_libraries(main_lib INTERFACE pthread c++abi)
endif()
@@ -702,6 +679,14 @@ if(UNIX)
endif()
endif()
+if(NOT LUAJIT_FOUND)
+ message(STATUS "luajit not found, skipping unit tests")
+elseif(CMAKE_BUILD_TYPE MATCHES Debug)
+ glob_wrapper(UNIT_TEST_FIXTURES ${PROJECT_SOURCE_DIR}/test/unit/fixtures/*.c)
+ list(APPEND NVIM_SOURCES ${UNIT_TEST_FIXTURES})
+ target_compile_definitions(main_lib INTERFACE UNIT_TESTING)
+endif()
+
target_sources(nvim PRIVATE ${NVIM_GENERATED_FOR_SOURCES} ${NVIM_GENERATED_FOR_HEADERS}
${NVIM_GENERATED_SOURCES} ${NVIM_SOURCES} ${NVIM_HEADERS}
${EXTERNAL_SOURCES} ${EXTERNAL_HEADERS})
@@ -855,38 +840,11 @@ endif()
set_target_properties(
libnvim
PROPERTIES
- POSITION_INDEPENDENT_CODE ON
OUTPUT_NAME ${LIBNVIM_NAME}
)
target_compile_definitions(libnvim PRIVATE MAKE_LIB)
target_link_libraries(libnvim PRIVATE main_lib PUBLIC libuv_lib)
-if(NOT LUAJIT_FOUND)
- message(STATUS "luajit not found, skipping nvim-test (unit tests) target")
-else()
- glob_wrapper(UNIT_TEST_FIXTURES ${PROJECT_SOURCE_DIR}/test/unit/fixtures/*.c)
- add_library(
- nvim-test
- MODULE
- EXCLUDE_FROM_ALL
- ${NVIM_SOURCES} ${NVIM_GENERATED_SOURCES}
- ${NVIM_HEADERS} ${NVIM_GENERATED_FOR_SOURCES} ${NVIM_GENERATED_FOR_HEADERS}
- ${EXTERNAL_SOURCES} ${EXTERNAL_HEADERS}
- ${UNIT_TEST_FIXTURES}
- )
- target_link_libraries(nvim-test PRIVATE ${LUAJIT_LIBRARIES} main_lib PUBLIC libuv_lib)
- if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
- target_link_libraries(nvim-test PRIVATE "-framework CoreServices")
- endif()
- target_include_directories(nvim-test PRIVATE ${LUAJIT_INCLUDE_DIRS})
- set_target_properties(
- nvim-test
- PROPERTIES
- POSITION_INDEPENDENT_CODE ON
- )
- target_compile_definitions(nvim-test PRIVATE UNIT_TESTING)
-endif()
-
if(CLANG_ASAN_UBSAN)
message(STATUS "Enabling Clang address sanitizer and undefined behavior sanitizer for nvim.")
if(CI_BUILD)
@@ -977,7 +935,9 @@ add_glob_target(
TARGET lintc-clint
COMMAND ${PROJECT_SOURCE_DIR}/src/clint.py
FLAGS --output=${LINT_OUTPUT_FORMAT}
- FILES ${LINT_NVIM_SOURCES})
+ FILES ${LINT_NVIM_SOURCES}
+ EXCLUDE
+ tui/terminfo_defs.h)
add_custom_target(uncrustify-version
COMMAND ${CMAKE_COMMAND}
diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c
index 931363e199..a2cb297b15 100644
--- a/src/nvim/api/autocmd.c
+++ b/src/nvim/api/autocmd.c
@@ -404,7 +404,7 @@ cleanup:
/// - match: (string) expanded value of |<amatch>|
/// - buf: (number) expanded value of |<abuf>|
/// - file: (string) expanded value of |<afile>|
-/// - data: (any) arbitrary data passed to |nvim_exec_autocmds()|
+/// - data: (any) arbitrary data passed from |nvim_exec_autocmds()|
/// - command (string) optional: Vim command to execute on event. Cannot be used with
/// {callback}
/// - once (boolean) optional: defaults to false. Run the autocommand
diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c
index 44e7ed3986..ab3b3485e4 100644
--- a/src/nvim/api/extmark.c
+++ b/src/nvim/api/extmark.c
@@ -698,7 +698,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
}
if (opts->sign_text.type == kObjectTypeString) {
- if (!init_sign_text((char **)&decor.sign_text,
+ if (!init_sign_text(&decor.sign_text,
opts->sign_text.data.string.data)) {
api_set_error(err, kErrorTypeValidation, "sign_text is not a valid value");
goto error;
diff --git a/src/nvim/api/keysets.lua b/src/nvim/api/keysets.lua
index 8f909e937f..30dcef6127 100644
--- a/src/nvim/api/keysets.lua
+++ b/src/nvim/api/keysets.lua
@@ -1,8 +1,8 @@
return {
- context = {
+ { 'context', {
"types";
- };
- set_decoration_provider = {
+ }};
+ { 'set_decoration_provider', {
"on_start";
"on_buf";
"on_win";
@@ -10,8 +10,8 @@ return {
"on_end";
"_on_hl_def";
"_on_spell_nav";
- };
- set_extmark = {
+ }};
+ { 'set_extmark', {
"id";
"end_line";
"end_row";
@@ -39,8 +39,8 @@ return {
"conceal";
"spell";
"ui_watched";
- };
- keymap = {
+ }};
+ { 'keymap', {
"noremap";
"nowait";
"silent";
@@ -50,11 +50,11 @@ return {
"callback";
"desc";
"replace_keycodes";
- };
- get_commands = {
+ }};
+ { 'get_commands', {
"builtin";
- };
- user_command = {
+ }};
+ { 'user_command', {
"addr";
"bang";
"bar";
@@ -67,8 +67,8 @@ return {
"preview";
"range";
"register";
- };
- float_config = {
+ }};
+ { 'float_config', {
"row";
"col";
"width";
@@ -85,25 +85,25 @@ return {
"title_pos";
"style";
"noautocmd";
- };
- runtime = {
+ }};
+ { 'runtime', {
"is_lua";
"do_source";
- };
- eval_statusline = {
+ }};
+ { 'eval_statusline', {
"winid";
"maxwidth";
"fillchar";
"highlights";
"use_winbar";
"use_tabline";
- };
- option = {
+ }};
+ { 'option', {
"scope";
"win";
"buf";
- };
- highlight = {
+ }};
+ { 'highlight', {
"bold";
"standout";
"strikethrough";
@@ -114,6 +114,7 @@ return {
"underdashed";
"italic";
"reverse";
+ "altfont";
"nocombine";
"default";
"cterm";
@@ -128,8 +129,8 @@ return {
"blend";
"fg_indexed";
"bg_indexed";
- };
- highlight_cterm = {
+ }};
+ { 'highlight_cterm', {
"bold";
"standout";
"strikethrough";
@@ -140,16 +141,17 @@ return {
"underdashed";
"italic";
"reverse";
+ "altfont";
"nocombine";
- };
+ }};
-- Autocmds
- clear_autocmds = {
+ { 'clear_autocmds', {
"buffer";
"event";
"group";
"pattern";
- };
- create_autocmd = {
+ }};
+ { 'create_autocmd', {
"buffer";
"callback";
"command";
@@ -158,24 +160,24 @@ return {
"nested";
"once";
"pattern";
- };
- exec_autocmds = {
+ }};
+ { 'exec_autocmds', {
"buffer";
"group";
"modeline";
"pattern";
"data";
- };
- get_autocmds = {
+ }};
+ { 'get_autocmds', {
"event";
"group";
"pattern";
"buffer";
- };
- create_augroup = {
+ }};
+ { 'create_augroup', {
"clear";
- };
- cmd = {
+ }};
+ { 'cmd', {
"cmd";
"range";
"count";
@@ -187,12 +189,12 @@ return {
"nargs";
"addr";
"nextcmd";
- };
- cmd_magic = {
+ }};
+ { 'cmd_magic', {
"file";
"bar";
- };
- cmd_mods = {
+ }};
+ { 'cmd_mods', {
"silent";
"emsg_silent";
"unsilent";
@@ -213,16 +215,15 @@ return {
"verbose";
"vertical";
"split";
- };
- cmd_mods_filter = {
+ }};
+ { 'cmd_mods_filter', {
"pattern";
"force";
- };
- cmd_opts = {
+ }};
+ { 'cmd_opts', {
"output";
- };
- echo_opts = {
+ }};
+ { 'echo_opts', {
"verbose";
- };
+ }};
}
-
diff --git a/src/nvim/api/private/converter.c b/src/nvim/api/private/converter.c
index 7770ba39d8..58ff552ab7 100644
--- a/src/nvim/api/private/converter.c
+++ b/src/nvim/api/private/converter.c
@@ -358,7 +358,7 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err)
}
case kObjectTypeLuaRef: {
- char *name = (char *)register_luafunc(api_new_luaref(obj.data.luaref));
+ char *name = register_luafunc(api_new_luaref(obj.data.luaref));
tv->v_type = VAR_FUNC;
tv->vval.v_string = xstrdup(name);
break;
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index 4ff600618d..519f2cc5bf 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -33,7 +33,6 @@
#include "nvim/pos.h"
#include "nvim/ui.h"
#include "nvim/version.h"
-#include "nvim/vim.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/private/funcs_metadata.generated.h"
@@ -151,7 +150,18 @@ bool try_end(Error *err)
xfree(msg);
}
} else if (did_throw) {
- api_set_error(err, kErrorTypeException, "%s", current_exception->value);
+ if (*current_exception->throw_name != NUL) {
+ if (current_exception->throw_lnum != 0) {
+ api_set_error(err, kErrorTypeException, "%s, line %" PRIdLINENR ": %s",
+ current_exception->throw_name, current_exception->throw_lnum,
+ current_exception->value);
+ } else {
+ api_set_error(err, kErrorTypeException, "%s: %s",
+ current_exception->throw_name, current_exception->value);
+ }
+ } else {
+ api_set_error(err, kErrorTypeException, "%s", current_exception->value);
+ }
discard_current_exception();
}
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c
index 32b294c0ce..e67607a7e4 100644
--- a/src/nvim/api/ui.c
+++ b/src/nvim/api/ui.c
@@ -13,7 +13,11 @@
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/ui.h"
+#include "nvim/autocmd.h"
#include "nvim/channel.h"
+#include "nvim/event/loop.h"
+#include "nvim/event/wstream.h"
+#include "nvim/globals.h"
#include "nvim/grid.h"
#include "nvim/highlight.h"
#include "nvim/main.h"
@@ -27,13 +31,12 @@
#include "nvim/types.h"
#include "nvim/ui.h"
#include "nvim/vim.h"
-#include "nvim/window.h"
#define BUF_POS(data) ((size_t)((data)->buf_wptr - (data)->buf))
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/ui.c.generated.h"
-# include "ui_events_remote.generated.h"
+# include "ui_events_remote.generated.h" // IWYU pragma: export
#endif
static PMap(uint64_t) connected_uis = MAP_INIT;
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 65b08ecade..a53b30dd8a 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -1834,7 +1834,7 @@ Dictionary nvim__stats(void)
/// - "width" Requested width of the UI
/// - "rgb" true if the UI uses RGB colors (false implies |cterm-colors|)
/// - "ext_..." Requested UI extensions, see |ui-option|
-/// - "chan" Channel id of remote UI or 0 for TUI
+/// - "chan" |channel-id| of remote UI
Array nvim_list_uis(void)
FUNC_API_SINCE(4)
{
@@ -2271,7 +2271,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
if (sp->userhl == 0) {
grpname = get_default_stl_hl(wp, use_winbar);
} else if (sp->userhl < 0) {
- grpname = (char *)syn_id2name(-sp->userhl);
+ grpname = syn_id2name(-sp->userhl);
} else {
snprintf(user_group, sizeof(user_group), "User%d", sp->userhl);
grpname = user_group;
diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c
index f81d26b486..0ffeac1bff 100644
--- a/src/nvim/api/win_config.c
+++ b/src/nvim/api/win_config.c
@@ -278,7 +278,7 @@ Dictionary nvim_win_get_config(Window window, Error *err)
String s = cstrn_to_string((const char *)config->border_chars[i], sizeof(schar_T));
int hi_id = config->border_hl_ids[i];
- char *hi_name = (char *)syn_id2name(hi_id);
+ char *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)));
diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c
index df8ad165ba..e2c234ab29 100644
--- a/src/nvim/api/window.c
+++ b/src/nvim/api/window.c
@@ -369,11 +369,16 @@ void nvim_win_hide(Window window, Error *err)
tabpage_T *tabpage = win_find_tabpage(win);
TryState tstate;
try_enter(&tstate);
- if (tabpage == curtab) {
+
+ // Never close the autocommand window.
+ if (is_aucmd_win(win)) {
+ emsg(_(e_autocmd_close));
+ } else if (tabpage == curtab) {
win_close(win, false, false);
} else {
win_close_othertab(win, false, tabpage);
}
+
vim_ignored = try_leave(&tstate, err);
}
diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua
index 2c0cb771c3..a75ee3bbd5 100644
--- a/src/nvim/auevents.lua
+++ b/src/nvim/auevents.lua
@@ -127,10 +127,22 @@ return {
'WinScrolled', -- after a window was scrolled or resized
},
aliases = {
- BufCreate = 'BufAdd',
- BufRead = 'BufReadPost',
- BufWrite = 'BufWritePre',
- FileEncoding = 'EncodingChanged',
+ {
+ 'BufCreate',
+ 'BufAdd'
+ },
+ {
+ 'BufRead',
+ 'BufReadPost'
+ },
+ {
+ 'BufWrite',
+ 'BufWritePre'
+ },
+ {
+ 'FileEncoding',
+ 'EncodingChanged'
+ },
},
-- List of nvim-specific events or aliases for the purpose of generating
-- syntax file
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index cd1059eb0d..5dcb10751f 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -88,6 +88,7 @@
#include "nvim/regexp.h"
#include "nvim/runtime.h"
#include "nvim/screen.h"
+#include "nvim/search.h"
#include "nvim/sign.h"
#include "nvim/spell.h"
#include "nvim/statusline.h"
@@ -2254,12 +2255,13 @@ int buflist_findpat(const char *pattern, const char *pattern_end, bool unlisted,
regmatch_T regmatch;
regmatch.regprog = vim_regcomp(p, magic_isset() ? RE_MAGIC : 0);
- if (regmatch.regprog == NULL) {
- xfree(pat);
- return -1;
- }
FOR_ALL_BUFFERS_BACKWARDS(buf) {
+ if (regmatch.regprog == NULL) {
+ // invalid pattern, possibly after switching engine
+ xfree(pat);
+ return -1;
+ }
if (buf->b_p_bl == find_listed
&& (!diffmode || diff_mode_buf(buf))
&& buflist_match(&regmatch, buf, false) != NULL) {
@@ -2337,7 +2339,6 @@ int ExpandBufnames(char *pat, int *num_file, char ***file, int options)
int round;
char *p;
int attempt;
- char *patc;
bufmatch_T *matches = NULL;
*num_file = 0; // return values in case of FAIL
@@ -2347,31 +2348,34 @@ int ExpandBufnames(char *pat, int *num_file, char ***file, int options)
return FAIL;
}
- // Make a copy of "pat" and change "^" to "\(^\|[\/]\)".
- if (*pat == '^') {
- patc = xmalloc(strlen(pat) + 11);
- STRCPY(patc, "\\(^\\|[\\/]\\)");
- STRCPY(patc + 11, pat + 1);
- } else {
- patc = pat;
+ const bool fuzzy = cmdline_fuzzy_complete(pat);
+
+ char *patc = NULL;
+ // Make a copy of "pat" and change "^" to "\(^\|[\/]\)" (if doing regular
+ // expression matching)
+ if (!fuzzy) {
+ if (*pat == '^') {
+ patc = xmalloc(strlen(pat) + 11);
+ STRCPY(patc, "\\(^\\|[\\/]\\)");
+ STRCPY(patc + 11, pat + 1);
+ } else {
+ patc = pat;
+ }
}
+ fuzmatch_str_T *fuzmatch = NULL;
// attempt == 0: try match with '\<', match at start of word
// attempt == 1: try match without '\<', match anywhere
- for (attempt = 0; attempt <= 1; attempt++) {
- if (attempt > 0 && patc == pat) {
- break; // there was no anchor, no need to try again
- }
-
+ for (attempt = 0; attempt <= (fuzzy ? 0 : 1); attempt++) {
regmatch_T regmatch;
- regmatch.regprog = vim_regcomp(patc + attempt * 11, RE_MAGIC);
- if (regmatch.regprog == NULL) {
- if (patc != pat) {
- xfree(patc);
+ if (!fuzzy) {
+ if (attempt > 0 && patc == pat) {
+ break; // there was no anchor, no need to try again
}
- return FAIL;
+ regmatch.regprog = vim_regcomp(patc + attempt * 11, RE_MAGIC);
}
+ int score = 0;
// round == 1: Count the matches.
// round == 2: Build the array to keep the matches.
for (round = 1; round <= 2; round++) {
@@ -2387,64 +2391,108 @@ int ExpandBufnames(char *pat, int *num_file, char ***file, int options)
continue;
}
}
- p = buflist_match(&regmatch, buf, p_wic);
- if (p != NULL) {
- if (round == 1) {
- count++;
- } else {
- if (options & WILD_HOME_REPLACE) {
- p = home_replace_save(buf, p);
- } else {
- p = xstrdup(p);
+
+ if (!fuzzy) {
+ if (regmatch.regprog == NULL) {
+ // invalid pattern, possibly after recompiling
+ if (patc != pat) {
+ xfree(patc);
}
- if (matches != NULL) {
- matches[count].buf = buf;
- matches[count].match = p;
- count++;
- } else {
- (*file)[count++] = p;
+ return FAIL;
+ }
+ p = buflist_match(&regmatch, buf, p_wic);
+ } else {
+ p = NULL;
+ // first try matching with the short file name
+ if ((score = fuzzy_match_str(buf->b_sfname, pat)) != 0) {
+ p = buf->b_sfname;
+ }
+ if (p == NULL) {
+ // next try matching with the full path file name
+ if ((score = fuzzy_match_str(buf->b_ffname, pat)) != 0) {
+ p = buf->b_ffname;
}
}
}
+
+ if (p == NULL) {
+ continue;
+ }
+
+ if (round == 1) {
+ count++;
+ continue;
+ }
+
+ if (options & WILD_HOME_REPLACE) {
+ p = home_replace_save(buf, p);
+ } else {
+ p = xstrdup(p);
+ }
+
+ if (!fuzzy) {
+ if (matches != NULL) {
+ matches[count].buf = buf;
+ matches[count].match = p;
+ count++;
+ } else {
+ (*file)[count++] = p;
+ }
+ } else {
+ fuzmatch[count].idx = count;
+ fuzmatch[count].str = p;
+ fuzmatch[count].score = score;
+ count++;
+ }
}
if (count == 0) { // no match found, break here
break;
}
if (round == 1) {
- *file = xmalloc((size_t)count * sizeof(**file));
-
- if (options & WILD_BUFLASTUSED) {
- matches = xmalloc((size_t)count * sizeof(*matches));
+ if (!fuzzy) {
+ *file = xmalloc((size_t)count * sizeof(**file));
+ if (options & WILD_BUFLASTUSED) {
+ matches = xmalloc((size_t)count * sizeof(*matches));
+ }
+ } else {
+ fuzmatch = xmalloc((size_t)count * sizeof(fuzmatch_str_T));
}
}
}
- vim_regfree(regmatch.regprog);
- if (count) { // match(es) found, break here
- break;
+
+ if (!fuzzy) {
+ vim_regfree(regmatch.regprog);
+ if (count) { // match(es) found, break here
+ break;
+ }
}
}
- if (patc != pat) {
+ if (!fuzzy && patc != pat) {
xfree(patc);
}
- if (matches != NULL) {
- if (count > 1) {
- qsort(matches, (size_t)count, sizeof(bufmatch_T), buf_time_compare);
- }
-
- // if the current buffer is first in the list, place it at the end
- if (matches[0].buf == curbuf) {
- for (int i = 1; i < count; i++) {
- (*file)[i - 1] = matches[i].match;
+ if (!fuzzy) {
+ if (matches != NULL) {
+ if (count > 1) {
+ qsort(matches, (size_t)count, sizeof(bufmatch_T), buf_time_compare);
}
- (*file)[count - 1] = matches[0].match;
- } else {
- for (int i = 0; i < count; i++) {
- (*file)[i] = matches[i].match;
+
+ // if the current buffer is first in the list, place it at the end
+ if (matches[0].buf == curbuf) {
+ for (int i = 1; i < count; i++) {
+ (*file)[i - 1] = matches[i].match;
+ }
+ (*file)[count - 1] = matches[0].match;
+ } else {
+ for (int i = 0; i < count; i++) {
+ (*file)[i] = matches[i].match;
+ }
}
+ xfree(matches);
}
- xfree(matches);
+ } else {
+ fuzzymatches_to_strmatches(fuzmatch, file, count, false);
}
*num_file = count;
@@ -2452,6 +2500,7 @@ int ExpandBufnames(char *pat, int *num_file, char ***file, int options)
}
/// Check for a match on the file name for buffer "buf" with regprog "prog".
+/// Note that rmp->regprog may become NULL when switching regexp engine.
///
/// @param ignore_case When true, ignore case. Use 'fic' otherwise.
static char *buflist_match(regmatch_T *rmp, buf_T *buf, bool ignore_case)
@@ -2464,7 +2513,8 @@ static char *buflist_match(regmatch_T *rmp, buf_T *buf, bool ignore_case)
return match;
}
-/// Try matching the regexp in "prog" with file name "name".
+/// Try matching the regexp in "rmp->regprog" with file name "name".
+/// Note that rmp->regprog may become NULL when switching regexp engine.
///
/// @param ignore_case When true, ignore case. Use 'fileignorecase' otherwise.
///
@@ -3293,7 +3343,7 @@ void maketitle(void)
(SPACE_FOR_DIR - (size_t)(buf_p - buf)), true);
#ifdef BACKSLASH_IN_FILENAME
// Avoid "c:/name" to be reduced to "c".
- if (isalpha((uint8_t)buf_p) && *(buf_p + 1) == ':') {
+ if (isalpha((uint8_t)(*buf_p)) && *(buf_p + 1) == ':') {
buf_p += 2;
}
#endif
@@ -3779,7 +3829,7 @@ static int chk_modeline(linenr_T lnum, int flags)
&& (s[0] != 'V'
|| strncmp(skipwhite(e + 1), "set", 3) == 0)
&& (s[3] == ':'
- || (VIM_VERSION_100 >= vers && isdigit(s[3]))
+ || (VIM_VERSION_100 >= vers && isdigit((uint8_t)s[3]))
|| (VIM_VERSION_100 < vers && s[3] == '<')
|| (VIM_VERSION_100 > vers && s[3] == '>')
|| (VIM_VERSION_100 == vers && s[3] == '='))) {
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index f01edd1ad2..4c99191170 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -1392,6 +1392,7 @@ struct window_S {
int w_prev_fraction_row;
linenr_T w_nrwidth_line_count; // line count when ml_nrwidth_width was computed.
+ linenr_T w_statuscol_line_count; // line count when 'statuscolumn' width was computed.
int w_nrwidth_width; // nr of chars to print line count.
qf_info_T *w_llist; // Location list for this window
diff --git a/src/nvim/change.c b/src/nvim/change.c
index e8c4af9879..06696610b0 100644
--- a/src/nvim/change.c
+++ b/src/nvim/change.c
@@ -418,14 +418,7 @@ void appended_lines(linenr_T lnum, linenr_T count)
/// Like appended_lines(), but adjust marks first.
void appended_lines_mark(linenr_T lnum, long count)
{
- // Skip mark_adjust when adding a line after the last one, there can't
- // be marks there. But it's still needed in diff mode.
- if (lnum + count < curbuf->b_ml.ml_line_count || curwin->w_p_diff) {
- mark_adjust(lnum + 1, (linenr_T)MAXLNUM, (linenr_T)count, 0L, kExtmarkUndo);
- } else {
- extmark_adjust(curbuf, lnum + 1, (linenr_T)MAXLNUM, (linenr_T)count, 0L,
- kExtmarkUndo);
- }
+ mark_adjust(lnum + 1, (linenr_T)MAXLNUM, (linenr_T)count, 0L, kExtmarkUndo);
changed_lines(lnum + 1, 0, lnum + 1, (linenr_T)count, true);
}
@@ -1694,13 +1687,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
}
// Postpone calling changed_lines(), because it would mess up folding
// with markers.
- // Skip mark_adjust when adding a line after the last one, there can't
- // be marks there. But still needed in diff mode.
- if (curwin->w_cursor.lnum + 1 < curbuf->b_ml.ml_line_count
- || curwin->w_p_diff) {
- mark_adjust(curwin->w_cursor.lnum + 1, (linenr_T)MAXLNUM, 1L, 0L,
- kExtmarkNOOP);
- }
+ mark_adjust(curwin->w_cursor.lnum + 1, (linenr_T)MAXLNUM, 1L, 0L, kExtmarkNOOP);
did_append = true;
} else {
// In MODE_VREPLACE state we are starting to replace the next line.
diff --git a/src/nvim/charset.c b/src/nvim/charset.c
index 4115743e1c..5aec9ccf9d 100644
--- a/src/nvim/charset.c
+++ b/src/nvim/charset.c
@@ -13,6 +13,7 @@
#include <string.h>
#include "auto/config.h"
+#include "klib/kvec.h"
#include "nvim/ascii.h"
#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
@@ -35,6 +36,7 @@
#include "nvim/plines.h"
#include "nvim/pos.h"
#include "nvim/state.h"
+#include "nvim/strings.h"
#include "nvim/vim.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -144,19 +146,19 @@ int buf_init_chartab(buf_T *buf, int global)
// options Each option is a list of characters, character numbers or
// ranges, separated by commas, e.g.: "200-210,x,#-178,-"
for (i = global ? 0 : 3; i <= 3; i++) {
- const char_u *p;
+ const char *p;
if (i == 0) {
// first round: 'isident'
- p = (char_u *)p_isi;
+ p = p_isi;
} else if (i == 1) {
// second round: 'isprint'
- p = (char_u *)p_isp;
+ p = p_isp;
} else if (i == 2) {
// third round: 'isfname'
- p = (char_u *)p_isf;
+ p = p_isf;
} else { // i == 3
// fourth round: 'iskeyword'
- p = (char_u *)buf->b_p_isk;
+ p = buf->b_p_isk;
}
while (*p) {
@@ -252,8 +254,8 @@ int buf_init_chartab(buf_T *buf, int global)
c++;
}
- c = *p;
- p = (char_u *)skip_to_option_part((char *)p);
+ c = (uint8_t)(*p);
+ p = skip_to_option_part(p);
if ((c == ',') && (*p == NUL)) {
// Trailing comma is not allowed.
@@ -538,9 +540,9 @@ static char_u transchar_charbuf[11];
/// @param[in] c Character to translate.
///
/// @return translated character into a static buffer.
-char_u *transchar(int c)
+char *transchar(int c)
{
- return transchar_buf(curbuf, c);
+ return (char *)transchar_buf(curbuf, c);
}
char_u *transchar_buf(const buf_T *buf, int c)
@@ -582,7 +584,7 @@ char_u *transchar_byte(const int c)
transchar_nonprint(curbuf, transchar_charbuf, c);
return transchar_charbuf;
}
- return transchar(c);
+ return (char_u *)transchar(c);
}
/// Convert non-printable characters to 2..4 printable ones
diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c
index b5ec3e7032..5e4b49db24 100644
--- a/src/nvim/cmdexpand.c
+++ b/src/nvim/cmdexpand.c
@@ -89,9 +89,42 @@ static int compl_match_arraysize;
static int compl_startcol;
static int compl_selected;
-#define SHOW_FILE_TEXT(m) (showtail \
- ? showmatches_gettail(matches[m], false) \
- : matches[m])
+#define SHOW_MATCH(m) (showtail ? showmatches_gettail(matches[m], false) : matches[m])
+
+/// Returns true if fuzzy completion is supported for a given cmdline completion
+/// context.
+static bool cmdline_fuzzy_completion_supported(const expand_T *const xp)
+ FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE
+{
+ return (wop_flags & WOP_FUZZY)
+ && xp->xp_context != EXPAND_BOOL_SETTINGS
+ && xp->xp_context != EXPAND_COLORS
+ && xp->xp_context != EXPAND_COMPILER
+ && xp->xp_context != EXPAND_DIRECTORIES
+ && xp->xp_context != EXPAND_FILES
+ && xp->xp_context != EXPAND_FILES_IN_PATH
+ && xp->xp_context != EXPAND_FILETYPE
+ && xp->xp_context != EXPAND_HELP
+ && xp->xp_context != EXPAND_LUA
+ && xp->xp_context != EXPAND_OLD_SETTING
+ && xp->xp_context != EXPAND_OWNSYNTAX
+ && xp->xp_context != EXPAND_PACKADD
+ && xp->xp_context != EXPAND_RUNTIME
+ && xp->xp_context != EXPAND_SHELLCMD
+ && xp->xp_context != EXPAND_TAGS
+ && xp->xp_context != EXPAND_TAGS_LISTFILES
+ && xp->xp_context != EXPAND_USER_LIST
+ && xp->xp_context != EXPAND_USER_LUA;
+}
+
+/// Returns true if fuzzy completion for cmdline completion is enabled and
+/// "fuzzystr" is not empty. If search pattern is empty, then don't use fuzzy
+/// matching.
+bool cmdline_fuzzy_complete(const char *const fuzzystr)
+ FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE
+{
+ return (wop_flags & WOP_FUZZY) && *fuzzystr != NUL;
+}
/// Sort function for the completion matches.
/// <SNR> functions should be sorted to the end.
@@ -110,71 +143,75 @@ static int sort_func_compare(const void *s1, const void *s2)
}
/// Escape special characters in the cmdline completion matches.
-static void ExpandEscape(expand_T *xp, char *str, int numfiles, char **files, int options)
+static void wildescape(expand_T *xp, const char *str, int numfiles, char **files)
{
- int i;
char *p;
const int vse_what = xp->xp_context == EXPAND_BUFFERS ? VSE_BUFFER : VSE_NONE;
- // May change home directory back to "~"
- if (options & WILD_HOME_REPLACE) {
- tilde_replace(str, numfiles, files);
- }
-
- if (options & WILD_ESCAPE) {
- if (xp->xp_context == EXPAND_FILES
- || xp->xp_context == EXPAND_FILES_IN_PATH
- || xp->xp_context == EXPAND_SHELLCMD
- || xp->xp_context == EXPAND_BUFFERS
- || xp->xp_context == EXPAND_DIRECTORIES) {
- // Insert a backslash into a file name before a space, \, %, #
- // and wildmatch characters, except '~'.
- for (i = 0; i < numfiles; i++) {
- // for ":set path=" we need to escape spaces twice
- if (xp->xp_backslash == XP_BS_THREE) {
- p = vim_strsave_escaped(files[i], " ");
- xfree(files[i]);
- files[i] = p;
+ if (xp->xp_context == EXPAND_FILES
+ || xp->xp_context == EXPAND_FILES_IN_PATH
+ || xp->xp_context == EXPAND_SHELLCMD
+ || xp->xp_context == EXPAND_BUFFERS
+ || xp->xp_context == EXPAND_DIRECTORIES) {
+ // Insert a backslash into a file name before a space, \, %, #
+ // and wildmatch characters, except '~'.
+ for (int i = 0; i < numfiles; i++) {
+ // for ":set path=" we need to escape spaces twice
+ if (xp->xp_backslash == XP_BS_THREE) {
+ p = vim_strsave_escaped(files[i], " ");
+ xfree(files[i]);
+ files[i] = p;
#if defined(BACKSLASH_IN_FILENAME)
- p = vim_strsave_escaped(files[i], (char_u *)" ");
- xfree(files[i]);
- files[i] = p;
+ p = vim_strsave_escaped(files[i], " ");
+ xfree(files[i]);
+ files[i] = p;
#endif
- }
+ }
#ifdef BACKSLASH_IN_FILENAME
- p = vim_strsave_fnameescape((const char *)files[i], vse_what);
+ p = vim_strsave_fnameescape(files[i], vse_what);
#else
- p = vim_strsave_fnameescape((const char *)files[i],
- xp->xp_shell ? VSE_SHELL : vse_what);
+ p = vim_strsave_fnameescape(files[i], xp->xp_shell ? VSE_SHELL : vse_what);
#endif
- xfree(files[i]);
- files[i] = p;
+ xfree(files[i]);
+ files[i] = p;
- // If 'str' starts with "\~", replace "~" at start of
- // files[i] with "\~".
- if (str[0] == '\\' && str[1] == '~' && files[i][0] == '~') {
- escape_fname(&files[i]);
- }
+ // If 'str' starts with "\~", replace "~" at start of
+ // files[i] with "\~".
+ if (str[0] == '\\' && str[1] == '~' && files[i][0] == '~') {
+ escape_fname(&files[i]);
}
- xp->xp_backslash = XP_BS_NONE;
+ }
+ xp->xp_backslash = XP_BS_NONE;
- // If the first file starts with a '+' escape it. Otherwise it
- // could be seen as "+cmd".
- if (*files[0] == '+') {
- escape_fname(&files[0]);
- }
- } else if (xp->xp_context == EXPAND_TAGS) {
- // Insert a backslash before characters in a tag name that
- // would terminate the ":tag" command.
- for (i = 0; i < numfiles; i++) {
- p = vim_strsave_escaped(files[i], "\\|\"");
- xfree(files[i]);
- files[i] = p;
- }
+ // If the first file starts with a '+' escape it. Otherwise it
+ // could be seen as "+cmd".
+ if (*files[0] == '+') {
+ escape_fname(&files[0]);
+ }
+ } else if (xp->xp_context == EXPAND_TAGS) {
+ // Insert a backslash before characters in a tag name that
+ // would terminate the ":tag" command.
+ for (int i = 0; i < numfiles; i++) {
+ p = vim_strsave_escaped(files[i], "\\|\"");
+ xfree(files[i]);
+ files[i] = p;
}
}
}
+/// Escape special characters in the cmdline completion matches.
+static void ExpandEscape(expand_T *xp, char *str, int numfiles, char **files, int options)
+{
+ // May change home directory back to "~"
+ if (options & WILD_HOME_REPLACE) {
+ tilde_replace(str, numfiles, files);
+ }
+
+ if (options & WILD_ESCAPE) {
+ wildescape(xp, str, numfiles, files);
+ }
+}
+
/// Return FAIL if this is not an appropriate context in which to do
/// completion of anything, return OK if it is (even if there are no matches).
/// For the caller, this means that the character is just passed through like a
@@ -215,12 +252,19 @@ int nextwild(expand_T *xp, int type, int options, bool escape)
assert(ccline->cmdpos >= i);
xp->xp_pattern_len = (size_t)ccline->cmdpos - (size_t)i;
- if (type == WILD_NEXT || type == WILD_PREV || type == WILD_PUM_WANT) {
+ if (type == WILD_NEXT || type == WILD_PREV
+ || type == WILD_PAGEUP || type == WILD_PAGEDOWN
+ || type == WILD_PUM_WANT) {
// Get next/previous match for a previous expanded pattern.
p2 = ExpandOne(xp, NULL, NULL, 0, type);
} else {
+ if (cmdline_fuzzy_completion_supported(xp)) {
+ // If fuzzy matching, don't modify the search string
+ p1 = xstrdup(xp->xp_pattern);
+ } else {
+ p1 = addstar(xp->xp_pattern, xp->xp_pattern_len, xp->xp_context);
+ }
// Translate string into pattern and expand it.
- p1 = addstar(xp->xp_pattern, xp->xp_pattern_len, xp->xp_context);
const int use_options = (options
| WILD_HOME_REPLACE
| WILD_ADD_SLASH
@@ -296,7 +340,7 @@ static int cmdline_pum_create(CmdlineInfo *ccline, expand_T *xp, char **matches,
compl_match_array = xmalloc(sizeof(pumitem_T) * (size_t)compl_match_arraysize);
for (int i = 0; i < numMatches; i++) {
compl_match_array[i] = (pumitem_T){
- .pum_text = SHOW_FILE_TEXT(i),
+ .pum_text = SHOW_MATCH(i),
.pum_info = NULL,
.pum_extra = NULL,
.pum_kind = NULL,
@@ -397,7 +441,6 @@ static int wildmenu_match_len(expand_T *xp, char *s)
/// @param matches list of matches
static void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int match, int showtail)
{
-#define L_MATCH(m) (showtail ? showmatches_gettail(matches[m], false) : matches[m])
int row;
char *buf;
int len;
@@ -426,7 +469,7 @@ static void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int m
highlight = false;
}
// count 1 for the ending ">"
- clen = wildmenu_match_len(xp, L_MATCH(match)) + 3;
+ clen = wildmenu_match_len(xp, SHOW_MATCH(match)) + 3;
if (match == 0) {
first_match = 0;
} else if (match < first_match) {
@@ -436,7 +479,7 @@ static void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int m
} else {
// check if match fits on the screen
for (i = first_match; i < match; i++) {
- clen += wildmenu_match_len(xp, L_MATCH(i)) + 2;
+ clen += wildmenu_match_len(xp, SHOW_MATCH(i)) + 2;
}
if (first_match > 0) {
clen += 2;
@@ -447,7 +490,7 @@ static void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int m
// if showing the last match, we can add some on the left
clen = 2;
for (i = match; i < num_matches; i++) {
- clen += wildmenu_match_len(xp, L_MATCH(i)) + 2;
+ clen += wildmenu_match_len(xp, SHOW_MATCH(i)) + 2;
if ((long)clen >= Columns) {
break;
}
@@ -459,7 +502,7 @@ static void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int m
}
if (add_left) {
while (first_match > 0) {
- clen += wildmenu_match_len(xp, L_MATCH(first_match - 1)) + 2;
+ clen += wildmenu_match_len(xp, SHOW_MATCH(first_match - 1)) + 2;
if ((long)clen >= Columns) {
break;
}
@@ -479,13 +522,13 @@ static void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int m
clen = len;
i = first_match;
- while (clen + wildmenu_match_len(xp, L_MATCH(i)) + 2 < Columns) {
+ while (clen + wildmenu_match_len(xp, SHOW_MATCH(i)) + 2 < Columns) {
if (i == match) {
selstart = buf + len;
selstart_col = clen;
}
- s = L_MATCH(i);
+ s = SHOW_MATCH(i);
// Check for menu separators - replace with '|'
emenu = (xp->xp_context == EXPAND_MENUS
|| xp->xp_context == EXPAND_MENUNAMES);
@@ -592,6 +635,44 @@ static char *get_next_or_prev_match(int mode, expand_T *xp, int *p_findex, char
findex--;
} else if (mode == WILD_NEXT) {
findex++;
+ } else if (mode == WILD_PAGEUP) {
+ if (findex == 0) {
+ // at the first entry, don't select any entries
+ findex = -1;
+ } else if (findex == -1) {
+ // no entry is selected. select the last entry
+ findex = xp->xp_numfiles - 1;
+ } else {
+ // go up by the pum height
+ int ht = pum_get_height();
+ if (ht > 3) {
+ ht -= 2;
+ }
+ findex -= ht;
+ if (findex < 0) {
+ // few entries left, select the first entry
+ findex = 0;
+ }
+ }
+ } else if (mode == WILD_PAGEDOWN) {
+ if (findex == xp->xp_numfiles - 1) {
+ // at the last entry, don't select any entries
+ findex = -1;
+ } else if (findex == -1) {
+ // no entry is selected. select the first entry
+ findex = 0;
+ } else {
+ // go down by the pum height
+ int ht = pum_get_height();
+ if (ht > 3) {
+ ht -= 2;
+ }
+ findex += ht;
+ if (findex >= xp->xp_numfiles) {
+ // few entries left, select the last entry
+ findex = xp->xp_numfiles - 1;
+ }
+ }
} else { // mode == WILD_PUM_WANT
assert(pum_want.active);
findex = pum_want.item;
@@ -769,7 +850,9 @@ char *ExpandOne(expand_T *xp, char *str, char *orig, int options, int mode)
int i;
// first handle the case of using an old match
- if (mode == WILD_NEXT || mode == WILD_PREV || mode == WILD_PUM_WANT) {
+ if (mode == WILD_NEXT || mode == WILD_PREV
+ || mode == WILD_PAGEUP || mode == WILD_PAGEDOWN
+ || mode == WILD_PUM_WANT) {
return get_next_or_prev_match(mode, xp, &findex, orig_save);
}
@@ -897,7 +980,7 @@ static void showmatches_oneline(expand_T *xp, char **matches, int numMatches, in
// Expansion was done before and special characters
// were escaped, need to halve backslashes. Also
// $HOME has been replaced with ~/.
- char *exp_path = (char *)expand_env_save_opt(matches[j], true);
+ char *exp_path = expand_env_save_opt(matches[j], true);
char *path = exp_path != NULL ? exp_path : matches[j];
char *halved_slash = backslash_halve_save(path);
isdir = os_isdir(halved_slash);
@@ -910,14 +993,14 @@ static void showmatches_oneline(expand_T *xp, char **matches, int numMatches, in
isdir = os_isdir(matches[j]);
}
if (showtail) {
- p = SHOW_FILE_TEXT(j);
+ p = SHOW_MATCH(j);
} else {
home_replace(NULL, matches[j], NameBuff, MAXPATHL, true);
p = NameBuff;
}
} else {
isdir = false;
- p = SHOW_FILE_TEXT(j);
+ p = SHOW_MATCH(j);
}
lastlen = msg_outtrans_attr(p, isdir ? dir_attr : 0);
}
@@ -990,7 +1073,7 @@ int showmatches(expand_T *xp, int wildmenu)
home_replace(NULL, matches[i], NameBuff, MAXPATHL, true);
j = vim_strsize(NameBuff);
} else {
- j = vim_strsize(SHOW_FILE_TEXT(i));
+ j = vim_strsize(SHOW_MATCH(i));
}
if (j > maxlen) {
maxlen = j;
@@ -1092,7 +1175,7 @@ static bool expand_showtail(expand_T *xp)
// separator, on DOS the '*' "path\*\file" must not be skipped.
if (rem_backslash(s)) {
s++;
- } else if (vim_strchr("*?[", *s) != NULL) {
+ } else if (vim_strchr("*?[", (uint8_t)(*s)) != NULL) {
return false;
}
}
@@ -1133,6 +1216,7 @@ char *addstar(char *fname, size_t len, int context)
|| context == EXPAND_OWNSYNTAX
|| context == EXPAND_FILETYPE
|| context == EXPAND_PACKADD
+ || context == EXPAND_RUNTIME
|| ((context == EXPAND_TAGS_LISTFILES || context == EXPAND_TAGS)
&& fname[0] == '/')) {
retval = xstrnsave(fname, len);
@@ -1292,13 +1376,16 @@ static const char *set_cmd_index(const char *cmd, exarg_T *eap, expand_T *xp, in
{
const char *p = NULL;
size_t len = 0;
+ const bool fuzzy = cmdline_fuzzy_complete(cmd);
// Isolate the command and search for it in the command table.
// Exceptions:
- // - the 'k' command can directly be followed by any character, but
- // do accept "keepmarks", "keepalt" and "keepjumps".
+ // - the 'k' command can directly be followed by any character, but do
+ // accept "keepmarks", "keepalt" and "keepjumps". As fuzzy matching can
+ // find matches anywhere in the command name, do this only for command
+ // expansion based on regular expression and not for fuzzy matching.
// - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r'
- if (*cmd == 'k' && cmd[1] != 'e') {
+ if (!fuzzy && (*cmd == 'k' && cmd[1] != 'e')) {
eap->cmdidx = CMD_k;
p = cmd + 1;
} else {
@@ -1320,7 +1407,7 @@ static const char *set_cmd_index(const char *cmd, exarg_T *eap, expand_T *xp, in
}
}
// check for non-alpha command
- if (p == cmd && vim_strchr("@*!=><&~#", *p) != NULL) {
+ if (p == cmd && vim_strchr("@*!=><&~#", (uint8_t)(*p)) != NULL) {
p++;
}
len = (size_t)(p - cmd);
@@ -1332,7 +1419,11 @@ static const char *set_cmd_index(const char *cmd, exarg_T *eap, expand_T *xp, in
eap->cmdidx = excmd_get_cmdidx(cmd, len);
- if (cmd[0] >= 'A' && cmd[0] <= 'Z') {
+ // User defined commands support alphanumeric characters.
+ // Also when doing fuzzy expansion for non-shell commands, support
+ // alphanumeric characters.
+ if ((cmd[0] >= 'A' && cmd[0] <= 'Z')
+ || (fuzzy && eap->cmdidx != CMD_bang && *p != NUL)) {
while (ASCII_ISALNUM(*p) || *p == '*') { // Allow * wild card
p++;
}
@@ -1346,7 +1437,7 @@ static const char *set_cmd_index(const char *cmd, exarg_T *eap, expand_T *xp, in
}
if (eap->cmdidx == CMD_SIZE) {
- if (*cmd == 's' && vim_strchr("cgriI", cmd[1]) != NULL) {
+ if (*cmd == 's' && vim_strchr("cgriI", (uint8_t)cmd[1]) != NULL) {
eap->cmdidx = CMD_substitute;
p = cmd + 1;
} else if (cmd[0] >= 'A' && cmd[0] <= 'Z') {
@@ -1615,6 +1706,78 @@ static const char *set_context_in_lang_cmd(expand_T *xp, const char *arg)
return NULL;
}
+static enum {
+ EXP_BREAKPT_ADD, ///< expand ":breakadd" sub-commands
+ EXP_BREAKPT_DEL, ///< expand ":breakdel" sub-commands
+ EXP_PROFDEL, ///< expand ":profdel" sub-commands
+} breakpt_expand_what;
+
+/// Set the completion context for the :breakadd command. Always returns NULL.
+static const char *set_context_in_breakadd_cmd(expand_T *xp, const char *arg, cmdidx_T cmdidx)
+{
+ xp->xp_context = EXPAND_BREAKPOINT;
+ xp->xp_pattern = (char *)arg;
+
+ if (cmdidx == CMD_breakadd) {
+ breakpt_expand_what = EXP_BREAKPT_ADD;
+ } else if (cmdidx == CMD_breakdel) {
+ breakpt_expand_what = EXP_BREAKPT_DEL;
+ } else {
+ breakpt_expand_what = EXP_PROFDEL;
+ }
+
+ const char *p = skipwhite(arg);
+ if (*p == NUL) {
+ return NULL;
+ }
+ const char *subcmd_start = p;
+
+ if (strncmp("file ", p, 5) == 0 || strncmp("func ", p, 5) == 0) {
+ // :breakadd file [lnum] <filename>
+ // :breakadd func [lnum] <funcname>
+ p += 4;
+ p = skipwhite(p);
+
+ // skip line number (if specified)
+ if (ascii_isdigit(*p)) {
+ p = skipdigits(p);
+ if (*p != ' ') {
+ xp->xp_context = EXPAND_NOTHING;
+ return NULL;
+ }
+ p = skipwhite(p);
+ }
+ if (strncmp("file", subcmd_start, 4) == 0) {
+ xp->xp_context = EXPAND_FILES;
+ } else {
+ xp->xp_context = EXPAND_USER_FUNC;
+ }
+ xp->xp_pattern = (char *)p;
+ } else if (strncmp("expr ", p, 5) == 0) {
+ // :breakadd expr <expression>
+ xp->xp_context = EXPAND_EXPRESSION;
+ xp->xp_pattern = skipwhite(p + 5);
+ }
+
+ return NULL;
+}
+
+static const char *set_context_in_scriptnames_cmd(expand_T *xp, const char *arg)
+{
+ xp->xp_context = EXPAND_NOTHING;
+ xp->xp_pattern = NULL;
+
+ char *p = skipwhite(arg);
+ if (ascii_isdigit(*p)) {
+ return NULL;
+ }
+
+ xp->xp_context = EXPAND_SCRIPTNAMES;
+ xp->xp_pattern = p;
+
+ return NULL;
+}
+
/// Set the completion context in "xp" for command "cmd" with index "cmdidx".
/// The argument to the command is "arg" and the argument flags is "argt".
/// For user-defined commands and for environment variables, "context" has the
@@ -1931,6 +2094,10 @@ static const char *set_context_by_cmdname(const char *cmd, cmdidx_T cmdidx, expa
xp->xp_pattern = (char *)arg;
break;
+ case CMD_runtime:
+ set_context_in_runtime_cmd(xp, arg);
+ break;
+
#ifdef HAVE_WORKING_LIBINTL
case CMD_language:
return set_context_in_lang_cmd(xp, arg);
@@ -1969,6 +2136,14 @@ static const char *set_context_by_cmdname(const char *cmd, cmdidx_T cmdidx, expa
xp->xp_pattern = (char *)arg;
break;
+ case CMD_breakadd:
+ case CMD_profdel:
+ case CMD_breakdel:
+ return set_context_in_breakadd_cmd(xp, arg, cmdidx);
+
+ case CMD_scriptnames:
+ return set_context_in_scriptnames_cmd(xp, arg);
+
case CMD_lua:
xp->xp_context = EXPAND_LUA;
break;
@@ -2002,7 +2177,7 @@ static const char *set_one_cmd_context(expand_T *xp, const char *buff)
// 1. skip comment lines and leading space, colons or bars
const char *cmd;
- for (cmd = buff; vim_strchr(" \t:|", *cmd) != NULL; cmd++) {}
+ for (cmd = buff; vim_strchr(" \t:|", (uint8_t)(*cmd)) != NULL; cmd++) {}
xp->xp_pattern = (char *)cmd;
if (*cmd == NUL) {
@@ -2180,7 +2355,7 @@ void set_cmd_context(expand_T *xp, char *str, int len, int col, int use_ccline)
} else if (use_ccline && ccline->input_fn) {
xp->xp_context = ccline->xp_context;
xp->xp_pattern = ccline->cmdbuff;
- xp->xp_arg = (char *)ccline->xp_arg;
+ xp->xp_arg = ccline->xp_arg;
} else {
while (nextcomm != NULL) {
nextcomm = set_one_cmd_context(xp, nextcomm);
@@ -2226,7 +2401,12 @@ int expand_cmdline(expand_T *xp, const char *str, int col, int *matchcount, char
// add star to file name, or convert to regexp if not exp. files.
assert((str + col) - xp->xp_pattern >= 0);
xp->xp_pattern_len = (size_t)((str + col) - xp->xp_pattern);
- file_str = addstar(xp->xp_pattern, xp->xp_pattern_len, xp->xp_context);
+ if (cmdline_fuzzy_completion_supported(xp)) {
+ // If fuzzy matching, don't modify the search string
+ file_str = xstrdup(xp->xp_pattern);
+ } else {
+ file_str = addstar(xp->xp_pattern, xp->xp_pattern_len, xp->xp_context);
+ }
if (p_wic) {
options += WILD_ICASE;
@@ -2316,6 +2496,45 @@ static char *get_behave_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx)
}
/// Function given to ExpandGeneric() to obtain the possible arguments of the
+/// ":breakadd {expr, file, func, here}" command.
+/// ":breakdel {func, file, here}" command.
+static char *get_breakadd_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx)
+{
+ char *opts[] = { "expr", "file", "func", "here" };
+
+ if (idx >= 0 && idx <= 3) {
+ // breakadd {expr, file, func, here}
+ if (breakpt_expand_what == EXP_BREAKPT_ADD) {
+ return opts[idx];
+ } else if (breakpt_expand_what == EXP_BREAKPT_DEL) {
+ // breakdel {func, file, here}
+ if (idx <= 2) {
+ return opts[idx + 1];
+ }
+ } else {
+ // profdel {func, file}
+ if (idx <= 1) {
+ return opts[idx + 1];
+ }
+ }
+ }
+ return NULL;
+}
+
+/// Function given to ExpandGeneric() to obtain the possible arguments for the
+/// ":scriptnames" command.
+static char *get_scriptnames_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx)
+{
+ if (!SCRIPT_ID_VALID(idx + 1)) {
+ return NULL;
+ }
+
+ scriptitem_T *si = &SCRIPT_ITEM(idx + 1);
+ home_replace(NULL, si->sn_name, NameBuff, MAXPATHL, true);
+ return NameBuff;
+}
+
+/// Function given to ExpandGeneric() to obtain the possible arguments of the
/// ":messages {clear}" command.
static char *get_messages_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx)
{
@@ -2360,7 +2579,7 @@ static char *get_healthcheck_names(expand_T *xp FUNC_ATTR_UNUSED, int idx)
}
/// Do the expansion based on xp->xp_context and "rmp".
-static int ExpandOther(expand_T *xp, regmatch_T *rmp, char ***matches, int *numMatches)
+static int ExpandOther(char *pat, expand_T *xp, regmatch_T *rmp, char ***matches, int *numMatches)
{
typedef CompleteListItemGetter ExpandFunc;
static struct expgen {
@@ -2399,6 +2618,8 @@ static int ExpandOther(expand_T *xp, regmatch_T *rmp, char ***matches, int *numM
{ EXPAND_ENV_VARS, get_env_name, true, true },
{ EXPAND_USER, get_users, true, false },
{ EXPAND_ARGLIST, get_arglist_name, true, false },
+ { EXPAND_BREAKPOINT, get_breakadd_arg, true, true },
+ { EXPAND_SCRIPTNAMES, get_scriptnames_arg, true, false },
{ EXPAND_CHECKHEALTH, get_healthcheck_names, true, false },
};
int ret = FAIL;
@@ -2410,7 +2631,7 @@ static int ExpandOther(expand_T *xp, regmatch_T *rmp, char ***matches, int *numM
if (tab[i].ic) {
rmp->rm_ic = true;
}
- ExpandGeneric(xp, rmp, matches, numMatches, tab[i].func, tab[i].escaped);
+ ExpandGeneric(pat, xp, rmp, matches, numMatches, tab[i].func, tab[i].escaped);
ret = OK;
break;
}
@@ -2450,9 +2671,11 @@ static int map_wildopts_to_ewflags(int options)
/// @param options WILD_ flags
static int ExpandFromContext(expand_T *xp, char *pat, char ***matches, int *numMatches, int options)
{
- regmatch_T regmatch;
+ regmatch_T regmatch = { .rm_ic = false };
int ret;
int flags = map_wildopts_to_ewflags(options);
+ const bool fuzzy = cmdline_fuzzy_complete(pat)
+ && cmdline_fuzzy_completion_supported(xp);
if (xp->xp_context == EXPAND_FILES
|| xp->xp_context == EXPAND_DIRECTORIES
@@ -2493,11 +2716,11 @@ static int ExpandFromContext(expand_T *xp, char *pat, char ***matches, int *numM
}
if (xp->xp_context == EXPAND_COLORS) {
char *directories[] = { "colors", NULL };
- return ExpandRTDir(pat, DIP_START + DIP_OPT + DIP_LUA, numMatches, matches, directories);
+ return ExpandRTDir(pat, DIP_START + DIP_OPT, numMatches, matches, directories);
}
if (xp->xp_context == EXPAND_COMPILER) {
char *directories[] = { "compiler", NULL };
- return ExpandRTDir(pat, DIP_LUA, numMatches, matches, directories);
+ return ExpandRTDir(pat, 0, numMatches, matches, directories);
}
if (xp->xp_context == EXPAND_OWNSYNTAX) {
char *directories[] = { "syntax", NULL };
@@ -2505,7 +2728,7 @@ static int ExpandFromContext(expand_T *xp, char *pat, char ***matches, int *numM
}
if (xp->xp_context == EXPAND_FILETYPE) {
char *directories[] = { "syntax", "indent", "ftplugin", NULL };
- return ExpandRTDir(pat, DIP_LUA, numMatches, matches, directories);
+ return ExpandRTDir(pat, 0, numMatches, matches, directories);
}
if (xp->xp_context == EXPAND_USER_LIST) {
return ExpandUserList(xp, matches, numMatches);
@@ -2516,6 +2739,9 @@ static int ExpandFromContext(expand_T *xp, char *pat, char ***matches, int *numM
if (xp->xp_context == EXPAND_PACKADD) {
return ExpandPackAddDir(pat, numMatches, matches);
}
+ if (xp->xp_context == EXPAND_RUNTIME) {
+ return expand_runtime_cmd(pat, numMatches, matches);
+ }
// When expanding a function name starting with s:, match the <SNR>nr_
// prefix.
@@ -2533,26 +2759,30 @@ static int ExpandFromContext(expand_T *xp, char *pat, char ***matches, int *numM
return nlua_expand_pat(xp, pat, numMatches, matches);
}
- regmatch.regprog = vim_regcomp(pat, magic_isset() ? RE_MAGIC : 0);
- if (regmatch.regprog == NULL) {
- return FAIL;
- }
+ if (!fuzzy) {
+ regmatch.regprog = vim_regcomp(pat, magic_isset() ? RE_MAGIC : 0);
+ if (regmatch.regprog == NULL) {
+ return FAIL;
+ }
- // set ignore-case according to p_ic, p_scs and pat
- regmatch.rm_ic = ignorecase(pat);
+ // set ignore-case according to p_ic, p_scs and pat
+ regmatch.rm_ic = ignorecase(pat);
+ }
if (xp->xp_context == EXPAND_SETTINGS
|| xp->xp_context == EXPAND_BOOL_SETTINGS) {
- ret = ExpandSettings(xp, &regmatch, numMatches, matches);
+ ret = ExpandSettings(xp, &regmatch, pat, numMatches, matches, fuzzy);
} else if (xp->xp_context == EXPAND_MAPPINGS) {
- ret = ExpandMappings(&regmatch, numMatches, matches);
+ ret = ExpandMappings(pat, &regmatch, numMatches, matches);
} else if (xp->xp_context == EXPAND_USER_DEFINED) {
- ret = ExpandUserDefined(xp, &regmatch, matches, numMatches);
+ ret = ExpandUserDefined(pat, xp, &regmatch, matches, numMatches);
} else {
- ret = ExpandOther(xp, &regmatch, matches, numMatches);
+ ret = ExpandOther(pat, xp, &regmatch, matches, numMatches);
}
- vim_regfree(regmatch.regprog);
+ if (!fuzzy) {
+ vim_regfree(regmatch.regprog);
+ }
xfree(tofree);
return ret;
@@ -2565,72 +2795,107 @@ static int ExpandFromContext(expand_T *xp, char *pat, char ***matches, int *numM
/// program. Matching strings are copied into an array, which is returned.
///
/// @param func returns a string from the list
-static void ExpandGeneric(expand_T *xp, regmatch_T *regmatch, char ***matches, int *numMatches,
- CompleteListItemGetter func, int escaped)
+static void ExpandGeneric(const char *const pat, expand_T *xp, regmatch_T *regmatch,
+ char ***matches, int *numMatches, CompleteListItemGetter func,
+ int escaped)
{
- int i;
- size_t count = 0;
- char *str;
+ const bool fuzzy = cmdline_fuzzy_complete(pat);
+ *matches = NULL;
+ *numMatches = 0;
- // count the number of matching names
- for (i = 0;; i++) {
- str = (*func)(xp, i);
- if (str == NULL) { // end of list
- break;
- }
- if (*str == NUL) { // skip empty strings
- continue;
- }
- if (vim_regexec(regmatch, str, (colnr_T)0)) {
- count++;
- }
- }
- if (count == 0) {
- return;
+ garray_T ga;
+ if (!fuzzy) {
+ ga_init(&ga, sizeof(char *), 30);
+ } else {
+ ga_init(&ga, sizeof(fuzmatch_str_T), 30);
}
- assert(count < INT_MAX);
- *numMatches = (int)count;
- *matches = xmalloc(count * sizeof(char *));
- // copy the matching names into allocated memory
- count = 0;
- for (i = 0;; i++) {
- str = (*func)(xp, i);
+ for (int i = 0;; i++) {
+ char *str = (*func)(xp, i);
if (str == NULL) { // End of list.
break;
}
if (*str == NUL) { // Skip empty strings.
continue;
}
- if (vim_regexec(regmatch, str, (colnr_T)0)) {
- if (escaped) {
- str = vim_strsave_escaped(str, " \t\\.");
+
+ bool match;
+ int score = 0;
+ if (xp->xp_pattern[0] != NUL) {
+ if (!fuzzy) {
+ match = vim_regexec(regmatch, str, (colnr_T)0);
} else {
- str = xstrdup(str);
+ score = fuzzy_match_str(str, pat);
+ match = (score != 0);
}
- (*matches)[count++] = str;
- if (func == get_menu_names) {
- // Test for separator added by get_menu_names().
- str += strlen(str) - 1;
- if (*str == '\001') {
- *str = '.';
- }
+ } else {
+ match = true;
+ }
+
+ if (!match) {
+ continue;
+ }
+
+ if (escaped) {
+ str = vim_strsave_escaped(str, " \t\\.");
+ } else {
+ str = xstrdup(str);
+ }
+
+ if (fuzzy) {
+ GA_APPEND(fuzmatch_str_T, &ga, ((fuzmatch_str_T){
+ .idx = ga.ga_len,
+ .str = str,
+ .score = score,
+ }));
+ } else {
+ GA_APPEND(char *, &ga, str);
+ }
+
+ if (func == get_menu_names) {
+ // Test for separator added by get_menu_names().
+ str += strlen(str) - 1;
+ if (*str == '\001') {
+ *str = '.';
}
}
}
- // Sort the results. Keep menu's in the specified order.
- if (xp->xp_context != EXPAND_MENUNAMES && xp->xp_context != EXPAND_MENUS) {
- if (xp->xp_context == EXPAND_EXPRESSION
- || xp->xp_context == EXPAND_FUNCTIONS
- || xp->xp_context == EXPAND_USER_FUNC) {
+ if (ga.ga_len == 0) {
+ return;
+ }
+
+ // Sort the matches when using regular expression matching and sorting
+ // applies to the completion context. Menus and scriptnames should be kept
+ // in the specified order.
+ const bool sort_matches = !fuzzy
+ && xp->xp_context != EXPAND_MENUNAMES
+ && xp->xp_context != EXPAND_MENUS
+ && xp->xp_context != EXPAND_SCRIPTNAMES;
+
+ // <SNR> functions should be sorted to the end.
+ const bool funcsort = xp->xp_context == EXPAND_EXPRESSION
+ || xp->xp_context == EXPAND_FUNCTIONS
+ || xp->xp_context == EXPAND_USER_FUNC;
+
+ // Sort the matches.
+ if (sort_matches) {
+ if (funcsort) {
// <SNR> functions should be sorted to the end.
- qsort((void *)(*matches), (size_t)(*numMatches), sizeof(char *), sort_func_compare);
+ qsort(ga.ga_data, (size_t)ga.ga_len, sizeof(char *), sort_func_compare);
} else {
- sort_strings(*matches, *numMatches);
+ sort_strings(ga.ga_data, ga.ga_len);
}
}
+ if (!fuzzy) {
+ *matches = ga.ga_data;
+ *numMatches = ga.ga_len;
+ } else {
+ fuzzymatches_to_strmatches(ga.ga_data, matches, ga.ga_len, funcsort);
+ *numMatches = ga.ga_len;
+ }
+
// Reset the variables used for special highlight names expansion, so that
// they don't show up when getting normal highlight names by ID.
reset_expand_highlight();
@@ -2647,30 +2912,31 @@ static void expand_shellcmd_onedir(char *buf, char *s, size_t l, char *pat, char
// Expand matches in one directory of $PATH.
int ret = expand_wildcards(1, &buf, numMatches, matches, flags);
- if (ret == OK) {
- ga_grow(gap, *numMatches);
- {
- for (int i = 0; i < *numMatches; i++) {
- char *name = (*matches)[i];
-
- if (strlen(name) > l) {
- // Check if this name was already found.
- hash_T hash = hash_hash((char_u *)name + l);
- hashitem_T *hi =
- hash_lookup(ht, (const char *)(name + l), strlen(name + l), hash);
- if (HASHITEM_EMPTY(hi)) {
- // Remove the path that was prepended.
- STRMOVE(name, name + l);
- ((char **)gap->ga_data)[gap->ga_len++] = name;
- hash_add_item(ht, hi, (char_u *)name, hash);
- name = NULL;
- }
- }
- xfree(name);
+ if (ret != OK) {
+ return;
+ }
+
+ ga_grow(gap, *numMatches);
+
+ for (int i = 0; i < *numMatches; i++) {
+ char *name = (*matches)[i];
+
+ if (strlen(name) > l) {
+ // Check if this name was already found.
+ hash_T hash = hash_hash(name + l);
+ hashitem_T *hi =
+ hash_lookup(ht, (const char *)(name + l), strlen(name + l), hash);
+ if (HASHITEM_EMPTY(hi)) {
+ // Remove the path that was prepended.
+ STRMOVE(name, name + l);
+ ((char **)gap->ga_data)[gap->ga_len++] = name;
+ hash_add_item(ht, hi, name, hash);
+ name = NULL;
}
- xfree(*matches);
}
+ xfree(name);
}
+ xfree(*matches);
}
/// Complete a shell command.
@@ -2710,7 +2976,7 @@ static void expand_shellcmd(char *filepat, char ***matches, int *numMatches, int
path = ".";
} else {
// For an absolute name we don't use $PATH.
- if (!path_is_absolute((char_u *)pat)) {
+ if (!path_is_absolute(pat)) {
path = vim_getenv("PATH");
}
if (path == NULL) {
@@ -2809,22 +3075,28 @@ static void *call_user_expand_func(user_expand_func_T user_expand_func, expand_T
return ret;
}
-/// Expand names with a function defined by the user.
-static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, char ***matches, int *numMatches)
+/// Expand names with a function defined by the user (EXPAND_USER_DEFINED and
+/// EXPAND_USER_LIST).
+static int ExpandUserDefined(const char *const pat, expand_T *xp, regmatch_T *regmatch,
+ char ***matches, int *numMatches)
{
- char *e;
- garray_T ga;
-
+ const bool fuzzy = cmdline_fuzzy_complete(pat);
*matches = NULL;
*numMatches = 0;
- char *const retstr = call_user_expand_func((user_expand_func_T)call_func_retstr, xp);
+ char *const retstr = call_user_expand_func((user_expand_func_T)call_func_retstr, xp);
if (retstr == NULL) {
return FAIL;
}
- ga_init(&ga, (int)sizeof(char *), 3);
- for (char *s = retstr; *s != NUL; s = e) {
+ garray_T ga;
+ if (!fuzzy) {
+ ga_init(&ga, (int)sizeof(char *), 3);
+ } else {
+ ga_init(&ga, (int)sizeof(fuzmatch_str_T), 3);
+ }
+
+ for (char *s = retstr, *e; *s != NUL; s = e) {
e = vim_strchr(s, '\n');
if (e == NULL) {
e = s + strlen(s);
@@ -2832,10 +3104,31 @@ static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, char ***matches
const char keep = *e;
*e = NUL;
- const bool skip = xp->xp_pattern[0] && vim_regexec(regmatch, s, (colnr_T)0) == 0;
+ bool match;
+ int score = 0;
+ if (xp->xp_pattern[0] != NUL) {
+ if (!fuzzy) {
+ match = vim_regexec(regmatch, s, (colnr_T)0);
+ } else {
+ score = fuzzy_match_str(s, pat);
+ match = (score != 0);
+ }
+ } else {
+ match = true; // match everything
+ }
+
*e = keep;
- if (!skip) {
- GA_APPEND(char *, &ga, xstrnsave(s, (size_t)(e - s)));
+
+ if (match) {
+ if (!fuzzy) {
+ GA_APPEND(char *, &ga, xstrnsave(s, (size_t)(e - s)));
+ } else {
+ GA_APPEND(fuzmatch_str_T, &ga, ((fuzmatch_str_T){
+ .idx = ga.ga_len,
+ .str = xstrnsave(s, (size_t)(e - s)),
+ .score = score,
+ }));
+ }
}
if (*e != NUL) {
@@ -2843,8 +3136,18 @@ static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, char ***matches
}
}
xfree(retstr);
- *matches = ga.ga_data;
- *numMatches = ga.ga_len;
+
+ if (ga.ga_len == 0) {
+ return OK;
+ }
+
+ if (!fuzzy) {
+ *matches = ga.ga_data;
+ *numMatches = ga.ga_len;
+ } else {
+ fuzzymatches_to_strmatches(ga.ga_data, matches, ga.ga_len, false);
+ *numMatches = ga.ga_len;
+ }
return OK;
}
@@ -2907,11 +3210,12 @@ static int ExpandUserLua(expand_T *xp, int *num_file, char ***file)
/// Expand `file` for all comma-separated directories in `path`.
/// Adds matches to `ga`.
-void globpath(char *path, char *file, garray_T *ga, int expand_options)
+/// If "dirs" is true only expand directory names.
+void globpath(char *path, char *file, garray_T *ga, int expand_options, bool dirs)
{
expand_T xpc;
ExpandInit(&xpc);
- xpc.xp_context = EXPAND_FILES;
+ xpc.xp_context = dirs ? EXPAND_DIRECTORIES : EXPAND_FILES;
char *buf = xmalloc(MAXPATHL);
@@ -3077,8 +3381,7 @@ static int wildmenu_process_key_filenames(CmdlineInfo *cclp, int key, expand_T *
j -= utf_head_off(cclp->cmdbuff, cclp->cmdbuff + j);
if (vim_ispathsep(cclp->cmdbuff[j])
#ifdef BACKSLASH_IN_FILENAME
- && vim_strchr((const char_u *)" *?[{`$%#", cclp->cmdbuff[j + 1])
- == NULL
+ && vim_strchr(" *?[{`$%#", (uint8_t)cclp->cmdbuff[j + 1]) == NULL
#endif
) {
if (found) {
@@ -3231,14 +3534,23 @@ void f_getcompletion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
set_context_in_menu_cmd(&xpc, "menu", xpc.xp_pattern, false);
xpc.xp_pattern_len = strlen(xpc.xp_pattern);
}
-
if (xpc.xp_context == EXPAND_SIGN) {
set_context_in_sign_cmd(&xpc, xpc.xp_pattern);
xpc.xp_pattern_len = strlen(xpc.xp_pattern);
}
+ if (xpc.xp_context == EXPAND_RUNTIME) {
+ set_context_in_runtime_cmd(&xpc, xpc.xp_pattern);
+ xpc.xp_pattern_len = strlen(xpc.xp_pattern);
+ }
theend:
- pat = addstar(xpc.xp_pattern, xpc.xp_pattern_len, xpc.xp_context);
+ if (cmdline_fuzzy_completion_supported(&xpc)) {
+ // when fuzzy matching, don't modify the search string
+ pat = xstrdup(xpc.xp_pattern);
+ } else {
+ pat = addstar(xpc.xp_pattern, xpc.xp_pattern_len, xpc.xp_context);
+ }
+
ExpandOne(&xpc, pat, NULL, options, WILD_ALL_KEEP);
tv_list_alloc_ret(rettv, xpc.xp_numfiles);
diff --git a/src/nvim/cmdexpand.h b/src/nvim/cmdexpand.h
index cdd6192086..810e289f7c 100644
--- a/src/nvim/cmdexpand.h
+++ b/src/nvim/cmdexpand.h
@@ -19,8 +19,8 @@ enum {
WILD_ALL_KEEP = 8,
WILD_CANCEL = 9,
WILD_APPLY = 10,
- // WILD_PAGEUP = 11, not ported yet
- // WILD_PAGEDOWN = 12, not ported yet
+ WILD_PAGEUP = 11,
+ WILD_PAGEDOWN = 12,
WILD_PUM_WANT = 13,
};
diff --git a/src/nvim/cmdhist.c b/src/nvim/cmdhist.c
index d12ac87bbb..2df82d9355 100644
--- a/src/nvim/cmdhist.c
+++ b/src/nvim/cmdhist.c
@@ -280,7 +280,7 @@ static HistoryType get_histtype(const char *const name, const size_t len, const
}
}
- if (vim_strchr(":=@>?/", name[0]) != NULL && len == 1) {
+ if (vim_strchr(":=@>?/", (uint8_t)name[0]) != NULL && len == 1) {
return hist_char2type(name[0]);
}
@@ -437,7 +437,7 @@ int clr_history(const int histype)
/// Remove all entries matching {str} from a history.
///
/// @param histype may be one of the HIST_ values.
-static int del_history_entry(int histype, char_u *str)
+static int del_history_entry(int histype, char *str)
{
if (hislen == 0 || histype < 0 || histype >= HIST_COUNT || *str == NUL
|| hisidx[histype] < 0) {
@@ -446,7 +446,7 @@ static int del_history_entry(int histype, char_u *str)
const int idx = hisidx[histype];
regmatch_T regmatch;
- regmatch.regprog = vim_regcomp((char *)str, RE_MAGIC + RE_STRING);
+ regmatch.regprog = vim_regcomp(str, RE_MAGIC + RE_STRING);
if (regmatch.regprog == NULL) {
return false;
}
@@ -560,7 +560,7 @@ void f_histdel(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
// string given: remove all matching entries
char buf[NUMBUFLEN];
n = del_history_entry(get_histtype(str, strlen(str), false),
- (char_u *)tv_get_string_buf(&argvars[1], buf));
+ (char *)tv_get_string_buf(&argvars[1], buf));
}
rettv->vval.v_number = n;
}
@@ -611,7 +611,7 @@ void ex_history(exarg_T *eap)
int idx;
int i, j, k;
char *end;
- char_u *arg = (char_u *)eap->arg;
+ char *arg = eap->arg;
if (hislen == 0) {
msg(_("'history' option is zero"));
@@ -619,12 +619,12 @@ void ex_history(exarg_T *eap)
}
if (!(ascii_isdigit(*arg) || *arg == '-' || *arg == ',')) {
- end = (char *)arg;
+ end = arg;
while (ASCII_ISALPHA(*end)
- || vim_strchr(":=@>/?", *end) != NULL) {
+ || vim_strchr(":=@>/?", (uint8_t)(*end)) != NULL) {
end++;
}
- histype1 = get_histtype((const char *)arg, (size_t)(end - (char *)arg), false);
+ histype1 = get_histtype(arg, (size_t)(end - arg), false);
if (histype1 == HIST_INVALID) {
if (STRNICMP(arg, "all", end - (char *)arg) == 0) {
histype1 = 0;
@@ -637,7 +637,7 @@ void ex_history(exarg_T *eap)
histype2 = histype1;
}
} else {
- end = (char *)arg;
+ end = arg;
}
if (!get_list_range(&end, &hisidx1, &hisidx2) || *end != NUL) {
semsg(_(e_trailing_arg), end);
diff --git a/src/nvim/context.c b/src/nvim/context.c
index b064a92b74..9de6c16536 100644
--- a/src/nvim/context.c
+++ b/src/nvim/context.c
@@ -5,7 +5,9 @@
#include <assert.h>
#include <stdbool.h>
+#include <stdint.h>
#include <stdio.h>
+#include <string.h>
#include "nvim/api/private/converter.h"
#include "nvim/api/private/helpers.h"
@@ -23,8 +25,6 @@
#include "nvim/message.h"
#include "nvim/option.h"
#include "nvim/shada.h"
-#include "nvim/types.h"
-#include "nvim/vim.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "context.c.generated.h"
diff --git a/src/nvim/debugger.c b/src/nvim/debugger.c
index 3dfbcd1f81..f7e70a78ce 100644
--- a/src/nvim/debugger.c
+++ b/src/nvim/debugger.c
@@ -403,7 +403,7 @@ void ex_debug(exarg_T *eap)
debug_break_level = debug_break_level_save;
}
-static char_u *debug_breakpoint_name = NULL;
+static char *debug_breakpoint_name = NULL;
static linenr_T debug_breakpoint_lnum;
/// When debugging or a breakpoint is set on a skipped command, no debug prompt
@@ -412,7 +412,7 @@ static linenr_T debug_breakpoint_lnum;
/// a skipped command decides itself that a debug prompt should be displayed, it
/// can do so by calling dbg_check_skipped().
static int debug_skipped;
-static char_u *debug_skipped_name;
+static char *debug_skipped_name;
/// Go to debug mode when a breakpoint was encountered or "ex_nesting_level" is
/// at or below the break level. But only when the line is actually
@@ -426,8 +426,8 @@ void dbg_check_breakpoint(exarg_T *eap)
if (!eap->skip) {
char *p;
// replace K_SNR with "<SNR>"
- if (debug_breakpoint_name[0] == K_SPECIAL
- && debug_breakpoint_name[1] == KS_EXTRA
+ if ((uint8_t)debug_breakpoint_name[0] == K_SPECIAL
+ && (uint8_t)debug_breakpoint_name[1] == KS_EXTRA
&& debug_breakpoint_name[2] == KE_SNR) {
p = "<SNR>";
} else {
@@ -802,7 +802,7 @@ static linenr_T debuggy_find(bool file, char *fname, linenr_T after, garray_T *g
// while matching should abort it.
prev_got_int = got_int;
got_int = false;
- if (vim_regexec_prog(&bp->dbg_prog, false, (char_u *)name, (colnr_T)0)) {
+ if (vim_regexec_prog(&bp->dbg_prog, false, name, (colnr_T)0)) {
lnum = bp->dbg_lnum;
if (fp != NULL) {
*fp = bp->dbg_forceit;
@@ -857,6 +857,6 @@ static linenr_T debuggy_find(bool file, char *fname, linenr_T after, garray_T *g
void dbg_breakpoint(char *name, linenr_T lnum)
{
// We need to check if this line is actually executed in do_one_cmd()
- debug_breakpoint_name = (char_u *)name;
+ debug_breakpoint_name = name;
debug_breakpoint_lnum = lnum;
}
diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c
index 037eb9f0d9..63c55ec602 100644
--- a/src/nvim/decoration.c
+++ b/src/nvim/decoration.c
@@ -7,6 +7,7 @@
#include "nvim/decoration.h"
#include "nvim/drawscreen.h"
#include "nvim/extmark.h"
+#include "nvim/fold.h"
#include "nvim/highlight.h"
#include "nvim/highlight_group.h"
#include "nvim/memory.h"
@@ -407,7 +408,7 @@ void decor_redraw_signs(buf_T *buf, int row, int *num_signs, SignTextAttrs sattr
}
if (j < SIGN_SHOW_MAX) {
sattrs[j] = (SignTextAttrs) {
- .text = (char *)decor->sign_text,
+ .text = decor->sign_text,
.hl_attr_id = decor->sign_hl_id == 0 ? 0 : syn_id2attr(decor->sign_hl_id),
.priority = decor->priority
};
@@ -550,7 +551,8 @@ void decor_add_ephemeral(int start_row, int start_col, int end_row, int end_col,
decor_add(&decor_state, start_row, start_col, end_row, end_col, decor, true, ns_id, mark_id);
}
-int decor_virt_lines(win_T *wp, linenr_T lnum, VirtLines *lines)
+/// @param has_fold whether line "lnum" has a fold, or kNone when not calculated yet
+int decor_virt_lines(win_T *wp, linenr_T lnum, VirtLines *lines, TriState has_fold)
{
buf_T *buf = wp->w_buffer;
if (!buf->b_virt_line_blocks) {
@@ -564,6 +566,10 @@ int decor_virt_lines(win_T *wp, linenr_T lnum, VirtLines *lines)
int end_row = (int)lnum;
MarkTreeIter itr[1] = { 0 };
marktree_itr_get(buf->b_marktree, row, 0, itr);
+ bool below_fold = lnum > 1 && hasFoldingWin(wp, lnum - 1, NULL, NULL, true, NULL);
+ if (has_fold == kNone) {
+ has_fold = hasFoldingWin(wp, lnum, NULL, NULL, true, NULL);
+ }
while (true) {
mtkey_t mark = marktree_itr_current(itr);
if (mark.pos.row < 0 || mark.pos.row >= end_row) {
@@ -572,8 +578,9 @@ int decor_virt_lines(win_T *wp, linenr_T lnum, VirtLines *lines)
goto next_mark;
}
bool above = mark.pos.row > (lnum - 2);
+ bool has_fold_cur = above ? has_fold : below_fold;
Decoration *decor = mark.decor_full;
- if (decor && decor->virt_lines_above == above) {
+ if (!has_fold_cur && decor && decor->virt_lines_above == above) {
virt_lines += (int)kv_size(decor->virt_lines);
if (lines) {
kv_splice(*lines, decor->virt_lines);
diff --git a/src/nvim/decoration.h b/src/nvim/decoration.h
index cee1eb2f94..c9ec8ede7f 100644
--- a/src/nvim/decoration.h
+++ b/src/nvim/decoration.h
@@ -58,7 +58,7 @@ struct Decoration {
DecorPriority priority;
int col; // fixed col value, like win_col
int virt_text_width; // width of virt_text
- char_u *sign_text;
+ char *sign_text;
int sign_hl_id;
int number_hl_id;
int line_hl_id;
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index 45f00cb41e..032de561b3 100644
--- a/src/nvim/diff.c
+++ b/src/nvim/diff.c
@@ -1218,7 +1218,7 @@ void ex_diffpatch(exarg_T *eap)
fullname = FullName_save(eap->arg, false);
esc_name = vim_strsave_shellescape(fullname != NULL ? fullname : eap->arg, true, true);
#else
- esc_name = (char *)vim_strsave_shellescape(eap->arg, true, true);
+ esc_name = vim_strsave_shellescape(eap->arg, true, true);
#endif
size_t buflen = strlen(tmp_orig) + strlen(esc_name) + strlen(tmp_new) + 16;
buf = xmalloc(buflen);
@@ -1575,7 +1575,7 @@ static bool extract_hunk(FILE *fd, diffhunk_T *hunk, diffstyle_T *diffstyle)
// --- file1 2018-03-20 13:23:35.783153140 +0100
// +++ file2 2018-03-20 13:23:41.183156066 +0100
// @@ -1,3 +1,5 @@
- if (isdigit(*line)) {
+ if (isdigit((uint8_t)(*line))) {
*diffstyle = DIFF_ED;
} else if ((strncmp(line, "@@ ", 3) == 0)) {
*diffstyle = DIFF_UNIFIED;
@@ -1593,7 +1593,7 @@ static bool extract_hunk(FILE *fd, diffhunk_T *hunk, diffstyle_T *diffstyle)
}
if (*diffstyle == DIFF_ED) {
- if (!isdigit(*line)) {
+ if (!isdigit((uint8_t)(*line))) {
continue; // not the start of a diff block
}
if (parse_diff_ed(line, hunk) == FAIL) {
@@ -2293,7 +2293,7 @@ static bool diff_equal_char(const char *const p1, const char *const p2, int *con
static int diff_cmp(char *s1, char *s2)
{
if ((diff_flags & DIFF_IBLANK)
- && (*(char_u *)skipwhite(s1) == NUL || *skipwhite(s2) == NUL)) {
+ && (*skipwhite(s1) == NUL || *skipwhite(s2) == NUL)) {
return 0;
}
diff --git a/src/nvim/digraph.c b/src/nvim/digraph.c
index 33038dfb9f..a057978a5e 100644
--- a/src/nvim/digraph.c
+++ b/src/nvim/digraph.c
@@ -1489,7 +1489,7 @@ int do_digraph(int c)
/// Find a digraph for "val". If found return the string to display it.
/// If not found return NULL.
-char_u *get_digraph_for_char(int val_arg)
+char *get_digraph_for_char(int val_arg)
{
const int val = val_arg;
const digr_T *dp;
@@ -1506,7 +1506,7 @@ char_u *get_digraph_for_char(int val_arg)
r[0] = dp->char1;
r[1] = dp->char2;
r[2] = NUL;
- return r;
+ return (char *)r;
}
dp++;
}
@@ -1749,16 +1749,16 @@ static void digraph_getlist_appendpair(const digr_T *dp, list_T *l)
list_T *l2 = tv_list_alloc(2);
tv_list_append_list(l, l2);
- char_u buf[30];
- buf[0] = dp->char1;
- buf[1] = dp->char2;
+ char buf[30];
+ buf[0] = (char)dp->char1;
+ buf[1] = (char)dp->char2;
buf[2] = NUL;
- tv_list_append_string(l2, (char *)buf, -1);
+ tv_list_append_string(l2, buf, -1);
- char_u *p = buf;
- p += utf_char2bytes(dp->result, (char *)p);
+ char *p = buf;
+ p += utf_char2bytes(dp->result, p);
*p = NUL;
- tv_list_append_string(l2, (char *)buf, -1);
+ tv_list_append_string(l2, buf, -1);
}
void digraph_getlist_common(bool list_all, typval_T *rettv)
@@ -1824,7 +1824,7 @@ struct dg_header_entry {
static void printdigraph(const digr_T *dp, result_T *previous)
FUNC_ATTR_NONNULL_ARG(1)
{
- char_u buf[30];
+ char buf[30];
int list_width = 13;
if (dp->result == 0) {
@@ -1854,29 +1854,29 @@ static void printdigraph(const digr_T *dp, result_T *previous)
}
}
- char_u *p = &buf[0];
- *p++ = dp->char1;
- *p++ = dp->char2;
+ char *p = &buf[0];
+ *p++ = (char)dp->char1;
+ *p++ = (char)dp->char2;
*p++ = ' ';
*p = NUL;
- msg_outtrans((char *)buf);
+ msg_outtrans(buf);
p = buf;
// add a space to draw a composing char on
if (utf_iscomposing(dp->result)) {
*p++ = ' ';
}
- p += utf_char2bytes(dp->result, (char *)p);
+ p += utf_char2bytes(dp->result, p);
*p = NUL;
- msg_outtrans_attr((char *)buf, HL_ATTR(HLF_8));
+ msg_outtrans_attr(buf, HL_ATTR(HLF_8));
p = buf;
if (char2cells(dp->result) == 1) {
*p++ = ' ';
}
assert(p >= buf);
- vim_snprintf((char *)p, sizeof(buf) - (size_t)(p - buf), " %3d", dp->result);
- msg_outtrans((char *)buf);
+ vim_snprintf(p, sizeof(buf) - (size_t)(p - buf), " %3d", dp->result);
+ msg_outtrans(buf);
}
/// Get the two digraph characters from a typval.
@@ -1885,7 +1885,7 @@ static int get_digraph_chars(const typval_T *arg, int *char1, int *char2)
{
char buf_chars[NUMBUFLEN];
const char *chars = tv_get_string_buf_chk(arg, buf_chars);
- const char_u *p = (const char_u *)chars;
+ const char *p = chars;
if (p != NULL) {
if (*p != NUL) {
@@ -1917,7 +1917,7 @@ static bool digraph_set_common(const typval_T *argchars, const typval_T *argdigr
if (digraph == NULL) {
return false;
}
- const char_u *p = (const char_u *)digraph;
+ const char *p = digraph;
int n = mb_cptr2char_adv(&p);
if (*p != NUL) {
semsg(_(e_digraph_argument_must_be_one_character_str), digraph);
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c
index 8fc1a4b029..01ff207c2b 100644
--- a/src/nvim/drawline.c
+++ b/src/nvim/drawline.c
@@ -400,40 +400,56 @@ static int get_sign_attrs(buf_T *buf, linenr_T lnum, SignTextAttrs *sattrs, int
/// Prepare and build the 'statuscolumn' string for line "lnum" in window "wp".
/// Fill "stcp" with the built status column string and attributes.
+/// This can be called three times per win_line(), once for virt_lines, once for
+/// the start of the buffer line "lnum" and once for the wrapped lines.
///
/// @param[out] stcp Status column attributes
static void get_statuscol_str(win_T *wp, linenr_T lnum, int row, int startrow, int filler_lines,
- int cul_attr, int sign_num_attr, int sign_cul_attr, char_u *extra,
- foldinfo_T foldinfo, SignTextAttrs *sattrs, statuscol_T *stcp)
+ int cul_attr, int sign_num_attr, int sign_cul_attr, statuscol_T *stcp,
+ foldinfo_T foldinfo, SignTextAttrs *sattrs)
{
- long relnum = 0;
- bool wrapped = row != startrow + filler_lines;
+ long relnum = -1;
bool use_cul = use_cursor_line_sign(wp, lnum);
+ int virtnum = row - startrow - filler_lines;
- // Set num, fold and sign text and attrs, empty when wrapped
- if (row == startrow) {
- relnum = labs(get_cursor_rel_lnum(wp, lnum));
+ // When called the first time for line "lnum" set num_attr
+ if (stcp->num_attr == 0) {
stcp->num_attr = sign_num_attr ? sign_num_attr
: get_line_number_attr(wp, lnum, row, startrow, filler_lines);
-
+ }
+ // When called for the first non-filler row of line "lnum" set num v:vars and fold column
+ if (virtnum == 0) {
+ relnum = labs(get_cursor_rel_lnum(wp, lnum));
if (compute_foldcolumn(wp, 0)) {
size_t n = fill_foldcolumn(stcp->fold_text, wp, foldinfo, lnum);
stcp->fold_text[n] = NUL;
stcp->fold_attr = win_hl_attr(wp, use_cul ? HLF_CLF : HLF_FC);
}
}
-
+ // Make sure to clear->set->clear sign column for filler->first->wrapped lines
int i = 0;
for (; i < wp->w_scwidth; i++) {
- SignTextAttrs *sattr = wrapped ? NULL : sign_get_attr(i, sattrs, wp->w_scwidth);
+ SignTextAttrs *sattr = virtnum ? NULL : sign_get_attr(i, sattrs, wp->w_scwidth);
stcp->sign_text[i] = sattr && sattr->text ? sattr->text : " ";
stcp->sign_attr[i] = sattr ? (use_cul && sign_cul_attr ? sign_cul_attr : sattr->hl_attr_id)
: win_hl_attr(wp, use_cul ? HLF_CLS : HLF_SC);
}
stcp->sign_text[i] = NULL;
- int width = build_statuscol_str(wp, row == startrow, wrapped, lnum, relnum,
- stcp->width, ' ', stcp->text, &stcp->hlrec, stcp);
+ // When a buffer's line count has changed, make a best estimate for the full
+ // width of the status column by building with "w_nrwidth_line_count". Add
+ // potentially truncated width and rebuild before drawing anything.
+ if (wp->w_statuscol_line_count != wp->w_nrwidth_line_count) {
+ wp->w_statuscol_line_count = wp->w_nrwidth_line_count;
+ set_vim_var_nr(VV_VIRTNUM, 0);
+ build_statuscol_str(wp, wp->w_nrwidth_line_count, 0, stcp->width,
+ ' ', stcp->text, &stcp->hlrec, stcp);
+ stcp->width += stcp->truncate;
+ }
+ set_vim_var_nr(VV_VIRTNUM, virtnum);
+
+ int width = build_statuscol_str(wp, lnum, relnum, stcp->width,
+ ' ', stcp->text, &stcp->hlrec, stcp);
// Force a redraw in case of error or when truncated
if (*wp->w_p_stc == NUL || (stcp->truncate > 0 && wp->w_nrwidth < MAX_NUMBERWIDTH)) {
if (stcp->truncate) { // Avoid truncating 'statuscolumn'
@@ -466,9 +482,8 @@ static void get_statuscol_str(win_T *wp, linenr_T lnum, int row, int startrow, i
///
/// @param stcp Status column attributes
/// @param[out] draw_state Current draw state in win_line()
-static void get_statuscol_display_info(LineDrawState *draw_state, int *char_attr, int *n_extrap,
- int *c_extrap, int *c_finalp, char_u *extra, char **pp_extra,
- statuscol_T *stcp)
+static void get_statuscol_display_info(statuscol_T *stcp, LineDrawState *draw_state, int *char_attr,
+ int *n_extrap, int *c_extrap, int *c_finalp, char **pp_extra)
{
*c_extrap = NUL;
*c_finalp = NUL;
@@ -509,7 +524,7 @@ static bool use_cursor_line_nr(win_T *wp, linenr_T lnum, int row, int startrow,
&& (wp->w_p_culopt_flags & CULOPT_LINE)));
}
-static inline void get_line_number_str(win_T *wp, linenr_T lnum, char_u *buf, size_t buf_len)
+static inline void get_line_number_str(win_T *wp, linenr_T lnum, char *buf, size_t buf_len)
{
long num;
char *fmt = "%*ld ";
@@ -527,7 +542,7 @@ static inline void get_line_number_str(win_T *wp, linenr_T lnum, char_u *buf, si
}
}
- snprintf((char *)buf, buf_len, fmt, number_width(wp), num);
+ snprintf(buf, buf_len, fmt, number_width(wp), num);
}
static int get_line_number_attr(win_T *wp, linenr_T lnum, int row, int startrow, int filler_lines)
@@ -608,7 +623,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
int row; // row in the window, excl w_winrow
ScreenGrid *grid = &wp->w_grid; // grid specific to the window
- char_u extra[57]; // sign, line number and 'fdc' must
+ char extra[57]; // sign, line number and 'fdc' must
// fit in here
int n_extra = 0; // number of extra chars
char *p_extra = NULL; // string of extra chars, plus NUL
@@ -802,7 +817,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
nextline[SPWORDLEN] = NUL;
if (lnum < wp->w_buffer->b_ml.ml_line_count) {
line = ml_get_buf(wp->w_buffer, lnum + 1, false);
- spell_cat_line(nextline + SPWORDLEN, (char_u *)line, SPWORDLEN);
+ spell_cat_line(nextline + SPWORDLEN, line, SPWORDLEN);
}
// When a word wrapped from the previous line the start of the current
@@ -936,7 +951,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
area_highlighting = true;
}
VirtLines virt_lines = KV_INITIAL_VALUE;
- int n_virt_lines = decor_virt_lines(wp, lnum, &virt_lines);
+ int n_virt_lines = decor_virt_lines(wp, lnum, &virt_lines, has_fold);
filler_lines += n_virt_lines;
if (lnum == wp->w_topline) {
filler_lines = wp->w_topfill;
@@ -1128,7 +1143,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// no bad word found at line start, don't check until end of a
// word
spell_hlf = HLF_COUNT;
- word_end = (int)(spell_to_word_end((char_u *)ptr, wp) - (char_u *)line + 1);
+ word_end = (int)(spell_to_word_end(ptr, wp) - line + 1);
} else {
// bad word found, use attributes until end of word
assert(len <= INT_MAX);
@@ -1200,6 +1215,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
}
int sign_idx = 0;
+ int virt_line_index;
+ int virt_line_offset = -1;
// Repeat for the whole displayed line.
for (;;) {
int has_match_conc = 0; ///< match wants to conceal
@@ -1226,9 +1243,22 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
}
}
- // Skip fold, sign and number states if 'statuscolumn' is set.
- if (draw_state == WL_FOLD - 1 && n_extra == 0 && statuscol.draw) {
- draw_state = WL_STC - 1;
+ if (draw_state == WL_FOLD - 1 && n_extra == 0) {
+ if (filler_todo > 0) {
+ int index = filler_todo - (filler_lines - n_virt_lines);
+ if (index > 0) {
+ virt_line_index = (int)kv_size(virt_lines) - index;
+ assert(virt_line_index >= 0);
+ virt_line_offset = kv_A(virt_lines, virt_line_index).left_col ? 0 : win_col_off(wp);
+ }
+ }
+ if (!virt_line_offset) {
+ // Skip the column states if there is a "virt_left_col" line.
+ draw_state = WL_BRI - 1;
+ } else if (statuscol.draw) {
+ // Skip fold, sign and number states if 'statuscolumn' is set.
+ draw_state = WL_STC - 1;
+ }
}
if (draw_state == WL_FOLD - 1 && n_extra == 0) {
@@ -1259,7 +1289,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
if (wp->w_scwidth > 0) {
get_sign_display_info(false, wp, lnum, sattrs, row,
startrow, filler_lines, filler_todo,
- &c_extra, &c_final, (char *)extra, sizeof(extra),
+ &c_extra, &c_final, extra, sizeof(extra),
&p_extra, &n_extra, &char_attr, sign_idx,
sign_cul_attr);
sign_idx++;
@@ -1284,29 +1314,29 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
if (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u' && num_signs > 0) {
get_sign_display_info(true, wp, lnum, sattrs, row,
startrow, filler_lines, filler_todo,
- &c_extra, &c_final, (char *)extra, sizeof(extra),
+ &c_extra, &c_final, extra, sizeof(extra),
&p_extra, &n_extra, &char_attr, sign_idx,
sign_cul_attr);
} else {
// Draw the line number (empty space after wrapping).
if (row == startrow + filler_lines) {
- get_line_number_str(wp, lnum, (char_u *)extra, sizeof(extra));
+ get_line_number_str(wp, lnum, extra, sizeof(extra));
if (wp->w_skipcol > 0) {
- for (p_extra = (char *)extra; *p_extra == ' '; p_extra++) {
+ for (p_extra = extra; *p_extra == ' '; p_extra++) {
*p_extra = '-';
}
}
if (wp->w_p_rl) { // reverse line numbers
// like rl_mirror(), but keep the space at the end
- char *p2 = skipwhite((char *)extra);
+ char *p2 = skipwhite(extra);
p2 = skiptowhite(p2) - 1;
- for (char *p1 = skipwhite((char *)extra); p1 < p2; p1++, p2--) {
+ for (char *p1 = skipwhite(extra); p1 < p2; p1++, p2--) {
const char t = *p1;
*p1 = *p2;
*p2 = t;
}
}
- p_extra = (char *)extra;
+ p_extra = extra;
c_extra = NUL;
} else {
c_extra = ' ';
@@ -1327,14 +1357,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// Draw the 'statuscolumn' if option is set.
if (statuscol.draw) {
if (statuscol.textp == NULL) {
- get_statuscol_str(wp, lnum, row, startrow, filler_lines, cul_attr, sign_num_attr,
- sign_cul_attr, extra, foldinfo, sattrs, &statuscol);
+ get_statuscol_str(wp, lnum, row, startrow, filler_lines, cul_attr,
+ sign_num_attr, sign_cul_attr, &statuscol, foldinfo, sattrs);
if (wp->w_redr_statuscol) {
- return 0;
+ break;
}
}
- get_statuscol_display_info(&draw_state, &char_attr, &n_extra, &c_extra,
- &c_final, extra, &p_extra, &statuscol);
+ get_statuscol_display_info(&statuscol, &draw_state, &char_attr,
+ &n_extra, &c_extra, &c_final, &p_extra);
}
}
@@ -1413,7 +1443,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
}
char_attr = win_hl_attr(wp, HLF_DED);
}
- char *const sbr = (char *)get_showbreak_value(wp);
+ char *const sbr = get_showbreak_value(wp);
if (*sbr != NUL && need_showbreak) {
// Draw 'showbreak' at the start of each broken line.
p_extra = sbr;
@@ -1488,7 +1518,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
&& has_fold
&& col == win_col_offset
&& n_extra == 0
- && row == startrow) {
+ && row == startrow + filler_lines) {
char_attr = win_hl_attr(wp, HLF_FL);
linenr_T lnume = lnum + foldinfo.fi_lines - 1;
@@ -1509,7 +1539,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
&& has_fold
&& col < grid->cols
&& n_extra == 0
- && row == startrow) {
+ && row == startrow + filler_lines) {
// fill rest of line with 'fold'
c_extra = wp->w_p_fcs_chars.fold;
c_final = NUL;
@@ -1521,7 +1551,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
&& has_fold
&& col >= grid->cols
&& n_extra != 0
- && row == startrow) {
+ && row == startrow + filler_lines) {
// Truncate the folding.
n_extra = 0;
}
@@ -1710,14 +1740,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
|| (mb_l > 1 && (!vim_isprintc(mb_c)))) {
// Illegal UTF-8 byte: display as <xx>.
// Non-BMP character : display as ? or fullwidth ?.
- transchar_hex((char *)extra, mb_c);
+ transchar_hex(extra, mb_c);
if (wp->w_p_rl) { // reverse
- rl_mirror((char *)extra);
+ rl_mirror(extra);
}
- p_extra = (char *)extra;
+ p_extra = extra;
c = (uint8_t)(*p_extra);
- mb_c = mb_ptr2char_adv((const char_u **)&p_extra);
+ mb_c = mb_ptr2char_adv((const char **)&p_extra);
mb_utf8 = (c >= 0x80);
n_extra = (int)strlen(p_extra);
c_extra = NUL;
@@ -1805,7 +1835,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
syntax_attr = get_syntax_attr((colnr_T)v - 1,
has_spell ? &can_spell : NULL, false);
- if (did_emsg) {
+ if (did_emsg) { // -V547
wp->w_s->b_syn_error = true;
has_syntax = false;
} else {
@@ -1890,7 +1920,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
p = prev_ptr;
}
cap_col -= (int)(prev_ptr - line);
- size_t tmplen = spell_check(wp, (char_u *)p, &spell_hlf, &cap_col, nochange);
+ size_t tmplen = spell_check(wp, p, &spell_hlf, &cap_col, nochange);
assert(tmplen <= INT_MAX);
len = (int)tmplen;
word_end = (int)v + len;
@@ -1960,7 +1990,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// We have just drawn the showbreak value, no need to add
// space for it again.
if (vcol == vcol_sbr) {
- n_extra -= mb_charlen((char *)get_showbreak_value(wp));
+ n_extra -= mb_charlen(get_showbreak_value(wp));
if (n_extra < 0) {
n_extra = 0;
}
@@ -2056,12 +2086,12 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
if (c == TAB && (!wp->w_p_list || wp->w_p_lcs_chars.tab1)) {
int tab_len = 0;
long vcol_adjusted = vcol; // removed showbreak length
- char_u *const sbr = get_showbreak_value(wp);
+ char *const sbr = get_showbreak_value(wp);
// Only adjust the tab_len, when at the first column after the
// showbreak value was drawn.
if (*sbr != NUL && vcol == vcol_sbr && wp->w_p_wrap) {
- vcol_adjusted = vcol - mb_charlen((char *)sbr);
+ vcol_adjusted = vcol - mb_charlen(sbr);
}
// tab amount depends on current column
tab_len = tabstop_padding((colnr_T)vcol_adjusted,
@@ -2734,7 +2764,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// At end of screen line and there is more to come: Display the line
// so far. If there is no more to display it is caught above.
if ((wp->w_p_rl ? (col < 0) : (col >= grid->cols))
- && foldinfo.fi_lines == 0
+ && (!has_fold || virt_line_offset >= 0)
&& (draw_state != WL_LINE
|| *ptr != NUL
|| filler_todo > 0
@@ -2751,15 +2781,9 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
&& !wp->w_p_rl; // Not right-to-left.
int draw_col = col - boguscols;
- if (filler_todo > 0) {
- int index = filler_todo - (filler_lines - n_virt_lines);
- if (index > 0) {
- int i = (int)kv_size(virt_lines) - index;
- assert(i >= 0);
- int offset = kv_A(virt_lines, i).left_col ? 0 : win_col_offset;
- draw_virt_text_item(buf, offset, kv_A(virt_lines, i).line,
- kHlModeReplace, grid->cols, 0);
- }
+ if (virt_line_offset >= 0) {
+ draw_virt_text_item(buf, virt_line_offset, kv_A(virt_lines, virt_line_index).line,
+ kHlModeReplace, grid->cols, 0);
} else {
draw_virt_text(wp, buf, win_col_offset, &draw_col, grid->cols, row);
}
@@ -2819,16 +2843,18 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
need_showbreak = true;
}
if (statuscol.draw) {
- if (row == startrow + 1 || row == startrow + filler_lines) {
+ if (row == startrow + filler_lines + 1 || row == startrow + filler_lines) {
// Re-evaluate 'statuscolumn' for the first wrapped row and non filler line
statuscol.textp = NULL;
- } else { // Otherwise just reset the text/hlrec pointers
+ } else if (statuscol.textp) {
+ // Draw the already built 'statuscolumn' on the next wrapped or filler line
statuscol.textp = statuscol.text;
statuscol.hlrecp = statuscol.hlrec;
} // Fall back to default columns if the 'n' flag isn't in 'cpo'
statuscol.draw = vim_strchr(p_cpo, CPO_NUMCOL) == NULL;
}
filler_todo--;
+ virt_line_offset = -1;
// When the filler lines are actually below the last line of the
// file, don't draw the line itself, break here.
if (filler_todo == 0 && (wp->w_botfill || end_fill)) {
diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c
index 568dbe99c0..04c342e068 100644
--- a/src/nvim/drawscreen.c
+++ b/src/nvim/drawscreen.c
@@ -126,12 +126,14 @@ static char *provider_err = NULL;
void conceal_check_cursor_line(void)
{
bool should_conceal = conceal_cursor_line(curwin);
- if (curwin->w_p_cole > 0 && (conceal_cursor_used != should_conceal)) {
- redrawWinline(curwin, curwin->w_cursor.lnum);
- // Need to recompute cursor column, e.g., when starting Visual mode
- // without concealing.
- curs_columns(curwin, true);
+ if (curwin->w_p_cole <= 0 || conceal_cursor_used == should_conceal) {
+ return;
}
+
+ redrawWinline(curwin, curwin->w_cursor.lnum);
+ // Need to recompute cursor column, e.g., when starting Visual mode
+ // without concealing.
+ curs_columns(curwin, true);
}
/// Resize default_grid to Rows and Columns.
@@ -837,25 +839,29 @@ static bool vsep_connected(win_T *wp, WindowCorner corner)
/// Draw the vertical separator right of window "wp"
static void draw_vsep_win(win_T *wp)
{
- if (wp->w_vsep_width) {
- // draw the vertical separator right of this window
- int hl;
- int c = fillchar_vsep(wp, &hl);
- grid_fill(&default_grid, wp->w_winrow, W_ENDROW(wp),
- W_ENDCOL(wp), W_ENDCOL(wp) + 1, c, ' ', hl);
+ if (!wp->w_vsep_width) {
+ return;
}
+
+ // draw the vertical separator right of this window
+ int hl;
+ int c = fillchar_vsep(wp, &hl);
+ grid_fill(&default_grid, wp->w_winrow, W_ENDROW(wp),
+ W_ENDCOL(wp), W_ENDCOL(wp) + 1, c, ' ', hl);
}
/// Draw the horizontal separator below window "wp"
static void draw_hsep_win(win_T *wp)
{
- if (wp->w_hsep_height) {
- // draw the horizontal separator below this window
- int hl;
- int c = fillchar_hsep(wp, &hl);
- grid_fill(&default_grid, W_ENDROW(wp), W_ENDROW(wp) + 1,
- wp->w_wincol, W_ENDCOL(wp), c, c, hl);
+ if (!wp->w_hsep_height) {
+ return;
}
+
+ // draw the horizontal separator below this window
+ int hl;
+ int c = fillchar_hsep(wp, &hl);
+ grid_fill(&default_grid, W_ENDROW(wp), W_ENDROW(wp) + 1,
+ wp->w_wincol, W_ENDCOL(wp), c, c, hl);
}
/// Get the separator connector for specified window corner of window "wp"
@@ -1906,7 +1912,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
if (j > 0 && !wp->w_botfill && row < wp->w_grid.rows) {
// Display filler text below last line. win_line() will check
// for ml_line_count+1 and only draw filler lines
- foldinfo_T info = FOLDINFO_INIT;
+ foldinfo_T info = { 0 };
row = win_line(wp, wp->w_botline, row, wp->w_grid.rows,
false, false, info, &line_providers, &provider_err);
}
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index b83e732cec..96df6a3044 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -107,10 +107,9 @@ static colnr_T Insstart_textlen; // length of line when insert started
static colnr_T Insstart_blank_vcol; // vcol for first inserted blank
static bool update_Insstart_orig = true; // set Insstart_orig to Insstart
-static char_u *last_insert = NULL; // the text of the previous insert,
- // K_SPECIAL is escaped
-static int last_insert_skip; // nr of chars in front of previous insert
-static int new_insert_skip; // nr of chars in front of current insert
+static char *last_insert = NULL; // the text of the previous insert, K_SPECIAL is escaped
+static int last_insert_skip; // nr of chars in front of previous insert
+static int new_insert_skip; // nr of chars in front of current insert
static int did_restart_edit; // "restart_edit" when calling edit()
static bool can_cindent; // may do cindenting on this line
@@ -324,7 +323,7 @@ static void insert_enter(InsertState *s)
// Get the current length of the redo buffer, those characters have to be
// skipped if we want to get to the inserted characters.
- s->ptr = (char *)get_inserted();
+ s->ptr = get_inserted();
if (s->ptr == NULL) {
new_insert_skip = 0;
} else {
@@ -558,12 +557,12 @@ static int insert_execute(VimState *state, int key)
// completion: Add to "compl_leader".
if (ins_compl_accept_char(s->c)) {
// Trigger InsertCharPre.
- char_u *str = do_insert_char_pre(s->c);
- char_u *p;
+ char *str = do_insert_char_pre(s->c);
+ char *p;
if (str != NULL) {
for (p = str; *p != NUL; MB_PTR_ADV(p)) {
- ins_compl_addleader(utf_ptr2char((char *)p));
+ ins_compl_addleader(utf_ptr2char(p));
}
xfree(str);
} else {
@@ -1122,7 +1121,7 @@ normalchar:
if (!p_paste) {
// Trigger InsertCharPre.
- char *str = (char *)do_insert_char_pre(s->c);
+ char *str = do_insert_char_pre(s->c);
char *p;
if (str != NULL) {
@@ -1544,8 +1543,8 @@ void display_dollar(colnr_T col)
curwin->w_cursor.col = col;
// If on the last byte of a multi-byte move to the first byte.
- char_u *p = (char_u *)get_cursor_line_ptr();
- curwin->w_cursor.col -= utf_head_off((char *)p, (char *)p + col);
+ char *p = get_cursor_line_ptr();
+ curwin->w_cursor.col -= utf_head_off(p, p + col);
curs_columns(curwin, false); // Recompute w_wrow and w_wcol
if (curwin->w_wcol < curwin->w_grid.cols) {
edit_putchar('$', false);
@@ -1579,7 +1578,7 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang
int last_vcol;
int insstart_less; // reduction for Insstart.col
int new_cursor_col;
- char_u *ptr;
+ char *ptr;
int save_p_list;
int start_col;
colnr_T vc;
@@ -1658,9 +1657,9 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang
// Advance the cursor until we reach the right screen column.
last_vcol = 0;
- ptr = (char_u *)get_cursor_line_ptr();
+ ptr = get_cursor_line_ptr();
chartabsize_T cts;
- init_chartabsize_arg(&cts, curwin, 0, 0, (char *)ptr, (char *)ptr);
+ init_chartabsize_arg(&cts, curwin, 0, 0, ptr, ptr);
while (cts.cts_vcol <= (int)curwin->w_virtcol) {
last_vcol = cts.cts_vcol;
if (cts.cts_vcol > 0) {
@@ -1683,7 +1682,7 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang
ptr = xmallocz(i);
memset(ptr, ' ', i);
new_cursor_col += (int)i;
- ins_str((char *)ptr);
+ ins_str(ptr);
xfree(ptr);
}
@@ -2062,8 +2061,8 @@ void insertchar(int c, int flags, int second_indent)
// Need to remove existing (middle) comment leader and insert end
// comment leader. First, check what comment leader we can find.
- char_u *line = (char_u *)get_cursor_line_ptr();
- int i = get_leader_len((char *)line, &p, false, true);
+ char *line = get_cursor_line_ptr();
+ int i = get_leader_len(line, &p, false, true);
if (i > 0 && vim_strchr(p, COM_MIDDLE) != NULL) { // Just checking
// Skip middle-comment string
while (*p && p[-1] != ':') { // find end of middle flags
@@ -2304,11 +2303,11 @@ static void stop_insert(pos_T *end_insert_pos, int esc, int nomove)
// Save the inserted text for later redo with ^@ and CTRL-A.
// Don't do it when "restart_edit" was set and nothing was inserted,
// otherwise CTRL-O w and then <Left> will clear "last_insert".
- ptr = (char *)get_inserted();
+ ptr = get_inserted();
if (did_restart_edit == 0 || (ptr != NULL
&& (int)strlen(ptr) > new_insert_skip)) {
xfree(last_insert);
- last_insert = (char_u *)ptr;
+ last_insert = ptr;
last_insert_skip = new_insert_skip;
} else {
xfree(ptr);
@@ -2414,7 +2413,7 @@ static void stop_insert(pos_T *end_insert_pos, int esc, int nomove)
// Used for the replace command.
void set_last_insert(int c)
{
- char_u *s;
+ char *s;
xfree(last_insert);
last_insert = xmalloc(MB_MAXBYTES * 3 + 5);
@@ -2423,7 +2422,7 @@ void set_last_insert(int c)
if (c < ' ' || c == DEL) {
*s++ = Ctrl_V;
}
- s = add_char2buf(c, s);
+ s = (char *)add_char2buf(c, (char_u *)s);
*s++ = ESC;
*s++ = NUL;
last_insert_skip = 0;
@@ -2738,12 +2737,12 @@ char_u *get_last_insert(void)
if (last_insert == NULL) {
return NULL;
}
- return last_insert + last_insert_skip;
+ return (char_u *)last_insert + last_insert_skip;
}
// Get last inserted string, and remove trailing <Esc>.
// Returns pointer to allocated memory (must be freed) or NULL.
-char_u *get_last_insert_save(void)
+char *get_last_insert_save(void)
{
char *s;
int len;
@@ -2751,13 +2750,13 @@ char_u *get_last_insert_save(void)
if (last_insert == NULL) {
return NULL;
}
- s = xstrdup((char *)last_insert + last_insert_skip);
+ s = xstrdup(last_insert + last_insert_skip);
len = (int)strlen(s);
if (len > 0 && s[len - 1] == ESC) { // remove trailing ESC
s[len - 1] = NUL;
}
- return (char_u *)s;
+ return s;
}
/// Check the word in front of the cursor for an abbreviation.
@@ -3127,7 +3126,7 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty)
// make up some named keys <o>, <O>, <e>, <0>, <>>, <<>, <*>,
// <:> and <!> so that people can re-indent on o, O, e, 0, <,
// >, *, : and ! keys if they really really want to.
- if (vim_strchr("<>!*oOe0:", look[1]) != NULL
+ if (vim_strchr("<>!*oOe0:", (uint8_t)look[1]) != NULL
&& keytyped == look[1]) {
return true;
}
@@ -3182,7 +3181,7 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty)
// TODO(@brammool): multi-byte
if (keytyped == (int)(uint8_t)p[-1]
|| (icase && keytyped < 256
- && TOLOWER_LOC(keytyped) == TOLOWER_LOC((int)p[-1]))) {
+ && TOLOWER_LOC(keytyped) == TOLOWER_LOC((uint8_t)p[-1]))) {
line = get_cursor_pos_ptr();
assert(p >= look && (uintmax_t)(p - look) <= SIZE_MAX);
if ((curwin->w_cursor.col == (colnr_T)(p - look)
@@ -3475,7 +3474,7 @@ static void ins_ctrl_hat(void)
State |= MODE_LANGMAP;
}
}
- set_iminsert_global();
+ set_iminsert_global(curbuf);
showmode();
// Show/unshow value of 'keymap' in status lines.
status_redraw_curbuf();
@@ -3661,8 +3660,7 @@ static bool ins_start_select(int c)
static void ins_insert(int replaceState)
{
set_vim_var_string(VV_INSERTMODE, ((State & REPLACE_FLAG) ? "i" :
- replaceState == MODE_VREPLACE ? "v" :
- "r"), 1);
+ replaceState == MODE_VREPLACE ? "v" : "r"), 1);
ins_apply_autocmds(EVENT_INSERTCHANGE);
if (State & REPLACE_FLAG) {
State = MODE_INSERT | (State & MODE_LANGMAP);
@@ -4503,7 +4501,7 @@ static bool ins_tab(void)
if (!curbuf->b_p_et && (tabstop_count(curbuf->b_p_vsts_array) > 0
|| get_sts_value() > 0
|| (p_sta && ind))) {
- char_u *ptr;
+ char *ptr;
char *saved_line = NULL; // init for GCC
pos_T pos;
pos_T fpos;
@@ -4518,9 +4516,9 @@ static bool ins_tab(void)
pos = curwin->w_cursor;
cursor = &pos;
saved_line = xstrdup(get_cursor_line_ptr());
- ptr = (char_u *)saved_line + pos.col;
+ ptr = saved_line + pos.col;
} else {
- ptr = (char_u *)get_cursor_pos_ptr();
+ ptr = get_cursor_pos_ptr();
cursor = &curwin->w_cursor;
}
@@ -4548,9 +4546,9 @@ static bool ins_tab(void)
getvcol(curwin, &fpos, &vcol, NULL, NULL);
getvcol(curwin, cursor, &want_vcol, NULL, NULL);
- char_u *tab = (char_u *)"\t";
+ char *tab = "\t";
chartabsize_T cts;
- init_chartabsize_arg(&cts, curwin, 0, vcol, (char *)tab, (char *)tab);
+ init_chartabsize_arg(&cts, curwin, 0, vcol, tab, tab);
// Use as many TABs as possible. Beware of 'breakindent', 'showbreak'
// and 'linebreak' adding extra virtual columns.
@@ -4579,13 +4577,13 @@ static bool ins_tab(void)
if (change_col >= 0) {
int repl_off = 0;
// Skip over the spaces we need.
- init_chartabsize_arg(&cts, curwin, 0, vcol, (char *)ptr, (char *)ptr);
+ init_chartabsize_arg(&cts, curwin, 0, vcol, ptr, ptr);
while (cts.cts_vcol < want_vcol && *cts.cts_ptr == ' ') {
cts.cts_vcol += lbr_chartabsize(&cts);
cts.cts_ptr++;
repl_off++;
}
- ptr = (char_u *)cts.cts_ptr;
+ ptr = cts.cts_ptr;
vcol = cts.cts_vcol;
clear_chartabsize_arg(&cts);
@@ -4762,8 +4760,8 @@ static int ins_digraph(void)
int ins_copychar(linenr_T lnum)
{
int c;
- char_u *ptr, *prev_ptr;
- char_u *line;
+ char *ptr, *prev_ptr;
+ char *line;
if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) {
vim_beep(BO_COPY);
@@ -4771,25 +4769,25 @@ int ins_copychar(linenr_T lnum)
}
// try to advance to the cursor column
- line = (char_u *)ml_get(lnum);
+ line = ml_get(lnum);
prev_ptr = line;
validate_virtcol();
chartabsize_T cts;
- init_chartabsize_arg(&cts, curwin, lnum, 0, (char *)line, (char *)line);
+ init_chartabsize_arg(&cts, curwin, lnum, 0, line, line);
while (cts.cts_vcol < curwin->w_virtcol && *cts.cts_ptr != NUL) {
- prev_ptr = (char_u *)cts.cts_ptr;
+ prev_ptr = cts.cts_ptr;
cts.cts_vcol += lbr_chartabsize_adv(&cts);
}
if (cts.cts_vcol > curwin->w_virtcol) {
ptr = prev_ptr;
} else {
- ptr = (char_u *)cts.cts_ptr;
+ ptr = cts.cts_ptr;
}
clear_chartabsize_arg(&cts);
- c = utf_ptr2char((char *)ptr);
+ c = utf_ptr2char(ptr);
if (c == NUL) {
vim_beep(BO_COPY);
}
@@ -4838,7 +4836,7 @@ static int ins_ctrl_ey(int tc)
static void ins_try_si(int c)
{
pos_T *pos, old_pos;
- char_u *ptr;
+ char *ptr;
int i;
bool temp;
@@ -4852,7 +4850,7 @@ static void ins_try_si(int c)
// containing the matching '(' if there is one. This handles the
// case where an "if (..\n..) {" statement continues over multiple
// lines -- webb
- ptr = (char_u *)ml_get(pos->lnum);
+ ptr = ml_get(pos->lnum);
i = pos->col;
if (i > 0) { // skip blanks before '{'
while (--i > 0 && ascii_iswhite(ptr[i])) {}
@@ -4877,7 +4875,7 @@ static void ins_try_si(int c)
old_pos = curwin->w_cursor;
i = get_indent();
while (curwin->w_cursor.lnum > 1) {
- ptr = (char_u *)skipwhite(ml_get(--(curwin->w_cursor.lnum)));
+ ptr = skipwhite(ml_get(--(curwin->w_cursor.lnum)));
// ignore empty lines and lines starting with '#'.
if (*ptr != '#' && *ptr != NUL) {
@@ -4928,7 +4926,7 @@ colnr_T get_nolist_virtcol(void)
// "c" is the character that was typed.
// Return a pointer to allocated memory with the replacement string.
// Return NULL to continue inserting "c".
-static char_u *do_insert_char_pre(int c)
+static char *do_insert_char_pre(int c)
{
char buf[MB_MAXBYTES + 1];
const int save_State = State;
@@ -4959,7 +4957,7 @@ static char_u *do_insert_char_pre(int c)
// Restore the State, it may have been changed.
State = save_State;
- return (char_u *)res;
+ return res;
}
bool get_can_cindent(void)
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index f9825496a5..4392ea306f 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -268,7 +268,7 @@ static struct vimvar {
VV(VV__NULL_BLOB, "_null_blob", VAR_BLOB, VV_RO),
VV(VV_LUA, "lua", VAR_PARTIAL, VV_RO),
VV(VV_RELNUM, "relnum", VAR_NUMBER, VV_RO),
- VV(VV_WRAP, "wrap", VAR_BOOL, VV_RO),
+ VV(VV_VIRTNUM, "virtnum", VAR_NUMBER, VV_RO),
};
#undef VV
@@ -1485,9 +1485,9 @@ char *get_lval(char *const name, typval_T *const rettv, lval_T *const lp, const
tv_clear(&var1);
break;
// existing variable, need to check if it can be changed
- } else if (!(flags & GLV_READ_ONLY) && var_check_ro(lp->ll_di->di_flags,
- (const char *)name,
- (size_t)(p - name))) {
+ } else if (!(flags & GLV_READ_ONLY)
+ && (var_check_ro(lp->ll_di->di_flags, name, (size_t)(p - name))
+ || var_check_lock(lp->ll_di->di_flags, name, (size_t)(p - name)))) {
tv_clear(&var1);
return NULL;
}
@@ -1618,7 +1618,7 @@ void set_var_lval(lval_T *lp, char *endp, typval_T *rettv, int copy, const bool
semsg(_(e_letwrong), op);
return;
}
- if (var_check_lock(lp->ll_blob->bv_lock, lp->ll_name, TV_CSTRING)) {
+ if (value_check_lock(lp->ll_blob->bv_lock, lp->ll_name, TV_CSTRING)) {
return;
}
@@ -1648,7 +1648,7 @@ void set_var_lval(lval_T *lp, char *endp, typval_T *rettv, int copy, const bool
// the end is an error otherwise.
if (lp->ll_n1 < gap->ga_len || lp->ll_n1 == gap->ga_len) {
ga_grow(&lp->ll_blob->bv_ga, 1);
- tv_blob_set(lp->ll_blob, (int)lp->ll_n1, (char_u)val);
+ tv_blob_set(lp->ll_blob, (int)lp->ll_n1, (uint8_t)val);
if (lp->ll_n1 == gap->ga_len) {
gap->ga_len++;
}
@@ -1681,10 +1681,10 @@ void set_var_lval(lval_T *lp, char *endp, typval_T *rettv, int copy, const bool
set_var_const(lp->ll_name, lp->ll_name_len, rettv, copy, is_const);
}
*endp = (char)cc;
- } else if (var_check_lock(lp->ll_newkey == NULL
- ? lp->ll_tv->v_lock
- : lp->ll_tv->vval.v_dict->dv_lock,
- lp->ll_name, TV_CSTRING)) {
+ } else if (value_check_lock(lp->ll_newkey == NULL
+ ? lp->ll_tv->v_lock
+ : lp->ll_tv->vval.v_dict->dv_lock,
+ lp->ll_name, TV_CSTRING)) {
// Skip
} else if (lp->ll_range) {
listitem_T *ll_li = lp->ll_li;
@@ -1698,8 +1698,8 @@ void set_var_lval(lval_T *lp, char *endp, typval_T *rettv, int copy, const bool
// Check whether any of the list items is locked
for (ri = tv_list_first(rettv->vval.v_list);
ri != NULL && ll_li != NULL;) {
- if (var_check_lock(TV_LIST_ITEM_TV(ll_li)->v_lock, lp->ll_name,
- TV_CSTRING)) {
+ if (value_check_lock(TV_LIST_ITEM_TV(ll_li)->v_lock, lp->ll_name,
+ TV_CSTRING)) {
return;
}
ri = TV_LIST_ITEM_NEXT(rettv->vval.v_list, ri);
@@ -2185,7 +2185,7 @@ int pattern_match(const char *pat, const char *text, bool ic)
regmatch.regprog = vim_regcomp((char *)pat, RE_MAGIC + RE_STRING);
if (regmatch.regprog != NULL) {
regmatch.rm_ic = ic;
- matches = vim_regexec_nl(&regmatch, (char_u *)text, (colnr_T)0);
+ matches = vim_regexec_nl(&regmatch, (char *)text, (colnr_T)0);
vim_regfree(regmatch.regprog);
}
p_cpo = save_cpo;
@@ -2543,7 +2543,7 @@ static int eval4(char **arg, typval_T *rettv, int evaluate)
if (p[2] == 'n' && p[3] == 'o' && p[4] == 't') {
len = 5;
}
- if (!isalnum(p[len]) && p[len] != '_') {
+ if (!isalnum((uint8_t)p[len]) && p[len] != '_') {
type = len == 2 ? EXPR_IS : EXPR_ISNOT;
}
}
@@ -2660,10 +2660,10 @@ static int eval5(char **arg, typval_T *rettv, int evaluate)
blob_T *const b = tv_blob_alloc();
for (int i = 0; i < tv_blob_len(b1); i++) {
- ga_append(&b->bv_ga, (char)tv_blob_get(b1, i));
+ ga_append(&b->bv_ga, tv_blob_get(b1, i));
}
for (int i = 0; i < tv_blob_len(b2); i++) {
- ga_append(&b->bv_ga, (char)tv_blob_get(b2, i));
+ ga_append(&b->bv_ga, tv_blob_get(b2, i));
}
tv_clear(rettv);
@@ -2887,12 +2887,7 @@ static int eval6(char **arg, typval_T *rettv, int evaluate, int want_string)
/// @return OK or FAIL.
static int eval7(char **arg, typval_T *rettv, int evaluate, int want_string)
{
- varnumber_T n;
- int len;
- char *s;
- const char *start_leader, *end_leader;
int ret = OK;
- char *alias;
static int recurse = 0;
// Initialise variable so that tv_clear() can't mistake this for a
@@ -2900,11 +2895,11 @@ static int eval7(char **arg, typval_T *rettv, int evaluate, int want_string)
rettv->v_type = VAR_UNKNOWN;
// Skip '!', '-' and '+' characters. They are handled later.
- start_leader = *arg;
+ const char *start_leader = *arg;
while (**arg == '!' || **arg == '-' || **arg == '+') {
*arg = skipwhite(*arg + 1);
}
- end_leader = *arg;
+ const char *end_leader = *arg;
// Limit recursion to 1000 levels. At least at 10000 we run out of stack
// and crash. With MSVC the stack is smaller.
@@ -2931,88 +2926,9 @@ static int eval7(char **arg, typval_T *rettv, int evaluate, int want_string)
case '6':
case '7':
case '8':
- case '9': {
- char *p = skipdigits(*arg + 1);
- int get_float = false;
-
- // We accept a float when the format matches
- // "[0-9]\+\.[0-9]\+\([eE][+-]\?[0-9]\+\)\?". This is very
- // strict to avoid backwards compatibility problems.
- // Don't look for a float after the "." operator, so that
- // ":let vers = 1.2.3" doesn't fail.
- if (!want_string && p[0] == '.' && ascii_isdigit(p[1])) {
- get_float = true;
- p = skipdigits(p + 2);
- if (*p == 'e' || *p == 'E') {
- p++;
- if (*p == '-' || *p == '+') {
- p++;
- }
- if (!ascii_isdigit(*p)) {
- get_float = false;
- } else {
- p = skipdigits(p + 1);
- }
- }
- if (ASCII_ISALPHA(*p) || *p == '.') {
- get_float = false;
- }
- }
- if (get_float) {
- float_T f;
-
- *arg += string2float(*arg, &f);
- if (evaluate) {
- rettv->v_type = VAR_FLOAT;
- rettv->vval.v_float = f;
- }
- } else if (**arg == '0' && ((*arg)[1] == 'z' || (*arg)[1] == 'Z')) {
- blob_T *blob = NULL;
- // Blob constant: 0z0123456789abcdef
- if (evaluate) {
- blob = tv_blob_alloc();
- }
- char *bp;
- for (bp = *arg + 2; ascii_isxdigit(bp[0]); bp += 2) {
- if (!ascii_isxdigit(bp[1])) {
- if (blob != NULL) {
- emsg(_("E973: Blob literal should have an even number of hex "
- "characters"));
- ga_clear(&blob->bv_ga);
- XFREE_CLEAR(blob);
- }
- ret = FAIL;
- break;
- }
- if (blob != NULL) {
- ga_append(&blob->bv_ga, (char)((hex2nr(*bp) << 4) + hex2nr(*(bp + 1))));
- }
- if (bp[2] == '.' && ascii_isxdigit(bp[3])) {
- bp++;
- }
- }
- if (blob != NULL) {
- tv_blob_set_ret(rettv, blob);
- }
- *arg = bp;
- } else {
- // decimal, hex or octal number
- vim_str2nr(*arg, NULL, &len, STR2NR_ALL, &n, NULL, 0, true);
- if (len == 0) {
- if (evaluate) {
- semsg(_(e_invexpr2), *arg);
- }
- ret = FAIL;
- break;
- }
- *arg += len;
- if (evaluate) {
- rettv->v_type = VAR_NUMBER;
- rettv->vval.v_number = n;
- }
- }
+ case '9':
+ ret = get_number_tv(arg, rettv, evaluate, want_string);
break;
- }
// String constant: "string".
case '"':
@@ -3090,8 +3006,9 @@ static int eval7(char **arg, typval_T *rettv, int evaluate, int want_string)
if (ret == NOTDONE) {
// Must be a variable or function name.
// Can also be a curly-braces kind of name: {expr}.
- s = *arg;
- len = get_name_len((const char **)arg, &alias, evaluate, true);
+ char *s = *arg;
+ char *alias;
+ int len = get_name_len((const char **)arg, &alias, evaluate, true);
if (alias != NULL) {
s = alias;
}
@@ -3716,6 +3633,91 @@ int get_option_tv(const char **const arg, typval_T *const rettv, const bool eval
return ret;
}
+/// Allocate a variable for a number constant. Also deals with "0z" for blob.
+///
+/// @return OK or FAIL.
+static int get_number_tv(char **arg, typval_T *rettv, bool evaluate, bool want_string)
+{
+ char *p = skipdigits(*arg + 1);
+ bool get_float = false;
+
+ // We accept a float when the format matches
+ // "[0-9]\+\.[0-9]\+\([eE][+-]\?[0-9]\+\)\?". This is very
+ // strict to avoid backwards compatibility problems.
+ // Don't look for a float after the "." operator, so that
+ // ":let vers = 1.2.3" doesn't fail.
+ if (!want_string && p[0] == '.' && ascii_isdigit(p[1])) {
+ get_float = true;
+ p = skipdigits(p + 2);
+ if (*p == 'e' || *p == 'E') {
+ p++;
+ if (*p == '-' || *p == '+') {
+ p++;
+ }
+ if (!ascii_isdigit(*p)) {
+ get_float = false;
+ } else {
+ p = skipdigits(p + 1);
+ }
+ }
+ if (ASCII_ISALPHA(*p) || *p == '.') {
+ get_float = false;
+ }
+ }
+ if (get_float) {
+ float_T f;
+ *arg += string2float(*arg, &f);
+ if (evaluate) {
+ rettv->v_type = VAR_FLOAT;
+ rettv->vval.v_float = f;
+ }
+ } else if (**arg == '0' && ((*arg)[1] == 'z' || (*arg)[1] == 'Z')) {
+ // Blob constant: 0z0123456789abcdef
+ blob_T *blob = NULL;
+ if (evaluate) {
+ blob = tv_blob_alloc();
+ }
+ char *bp;
+ for (bp = *arg + 2; ascii_isxdigit(bp[0]); bp += 2) {
+ if (!ascii_isxdigit(bp[1])) {
+ if (blob != NULL) {
+ emsg(_("E973: Blob literal should have an even number of hex characters"));
+ ga_clear(&blob->bv_ga);
+ XFREE_CLEAR(blob);
+ }
+ return FAIL;
+ }
+ if (blob != NULL) {
+ ga_append(&blob->bv_ga, (uint8_t)((hex2nr(*bp) << 4) + hex2nr(*(bp + 1))));
+ }
+ if (bp[2] == '.' && ascii_isxdigit(bp[3])) {
+ bp++;
+ }
+ }
+ if (blob != NULL) {
+ tv_blob_set_ret(rettv, blob);
+ }
+ *arg = bp;
+ } else {
+ // decimal, hex or octal number
+ int len;
+ varnumber_T n;
+ vim_str2nr(*arg, NULL, &len, STR2NR_ALL, &n, NULL, 0, true);
+ if (len == 0) {
+ if (evaluate) {
+ semsg(_(e_invexpr2), *arg);
+ }
+ return FAIL;
+ }
+ *arg += len;
+ if (evaluate) {
+ rettv->v_type = VAR_NUMBER;
+ rettv->vval.v_number = n;
+ }
+ }
+ return OK;
+}
+
/// Allocate a variable for a string constant.
///
/// @return OK or FAIL.
@@ -3777,7 +3779,7 @@ static int get_string_tv(char **arg, typval_T *rettv, int evaluate)
case 'U':
if (ascii_isxdigit(p[1])) {
int n, nr;
- int c = toupper(*p);
+ int c = toupper((uint8_t)(*p));
if (c == 'X') {
n = 2;
@@ -3828,7 +3830,7 @@ static int get_string_tv(char **arg, typval_T *rettv, int evaluate)
if (p[1] != '*') {
flags |= FSK_SIMPLIFY;
}
- extra = trans_special((const char **)&p, strlen(p), (char_u *)name, flags, false, NULL);
+ extra = trans_special((const char **)&p, strlen(p), name, flags, false, NULL);
if (extra != 0) {
name += extra;
if (name >= rettv->vval.v_string + len) {
@@ -3924,7 +3926,7 @@ static void partial_free(partial_T *pt)
xfree(pt->pt_argv);
tv_dict_unref(pt->pt_dict);
if (pt->pt_name != NULL) {
- func_unref((char_u *)pt->pt_name);
+ func_unref(pt->pt_name);
xfree(pt->pt_name);
} else {
func_ptr_unref(pt->pt_func);
@@ -4490,7 +4492,7 @@ bool set_ref_in_item(typval_T *tv, int copyID, ht_stack_T **ht_stack, list_stack
// A partial does not have a copyID, because it cannot contain itself.
if (pt != NULL) {
- abort = set_ref_in_func((char_u *)pt->pt_name, pt->pt_func, copyID);
+ abort = set_ref_in_func(pt->pt_name, pt->pt_func, copyID);
if (pt->pt_dict != NULL) {
typval_T dtv;
@@ -4507,7 +4509,7 @@ bool set_ref_in_item(typval_T *tv, int copyID, ht_stack_T **ht_stack, list_stack
break;
}
case VAR_FUNC:
- abort = set_ref_in_func((char_u *)tv->vval.v_string, NULL, copyID);
+ abort = set_ref_in_func(tv->vval.v_string, NULL, copyID);
break;
case VAR_UNKNOWN:
case VAR_BOOL:
@@ -4795,12 +4797,12 @@ void filter_map(typval_T *argvars, typval_T *rettv, int map)
} else if (argvars[0].v_type == VAR_LIST) {
if ((l = argvars[0].vval.v_list) == NULL
|| (!map
- && var_check_lock(tv_list_locked(l), arg_errmsg, TV_TRANSLATE))) {
+ && value_check_lock(tv_list_locked(l), arg_errmsg, TV_TRANSLATE))) {
return;
}
} else if (argvars[0].v_type == VAR_DICT) {
if ((d = argvars[0].vval.v_dict) == NULL
- || (!map && var_check_lock(d->dv_lock, arg_errmsg, TV_TRANSLATE))) {
+ || (!map && value_check_lock(d->dv_lock, arg_errmsg, TV_TRANSLATE))) {
return;
}
} else {
@@ -4839,7 +4841,7 @@ void filter_map(typval_T *argvars, typval_T *rettv, int map)
dictitem_T *di = TV_DICT_HI2DI(hi);
if (map
- && (var_check_lock(di->di_tv.v_lock, arg_errmsg, TV_TRANSLATE)
+ && (value_check_lock(di->di_tv.v_lock, arg_errmsg, TV_TRANSLATE)
|| var_check_ro(di->di_flags, arg_errmsg, TV_TRANSLATE))) {
break;
}
@@ -4879,7 +4881,7 @@ void filter_map(typval_T *argvars, typval_T *rettv, int map)
}
if (map) {
if (tv.vval.v_number != val) {
- tv_blob_set(b, i, (char_u)tv.vval.v_number);
+ tv_blob_set(b, i, (uint8_t)tv.vval.v_number);
}
} else if (rem) {
char *const p = argvars[0].vval.v_blob->bv_ga.ga_data;
@@ -4899,8 +4901,8 @@ void filter_map(typval_T *argvars, typval_T *rettv, int map)
}
for (listitem_T *li = tv_list_first(l); li != NULL;) {
if (map
- && var_check_lock(TV_LIST_ITEM_TV(li)->v_lock, arg_errmsg,
- TV_TRANSLATE)) {
+ && value_check_lock(TV_LIST_ITEM_TV(li)->v_lock, arg_errmsg,
+ TV_TRANSLATE)) {
break;
}
vimvars[VV_KEY].vv_nr = idx;
@@ -5000,7 +5002,7 @@ void common_function(typval_T *argvars, typval_T *rettv, bool is_funcref)
// Don't check an autoload name for existence here.
} else if (trans_name != NULL
&& (is_funcref
- ? find_func((char_u *)trans_name) == NULL
+ ? find_func(trans_name) == NULL
: !translated_function_exists((const char *)trans_name))) {
semsg(_("E700: Unknown function: %s"), s);
} else {
@@ -5099,12 +5101,12 @@ void common_function(typval_T *argvars, typval_T *rettv, bool is_funcref)
func_ptr_ref(pt->pt_func);
xfree(name);
} else if (is_funcref) {
- pt->pt_func = find_func((char_u *)trans_name);
+ pt->pt_func = find_func(trans_name);
func_ptr_ref(pt->pt_func);
xfree(name);
} else {
pt->pt_name = name;
- func_ref((char_u *)name);
+ func_ref(name);
}
rettv->v_type = VAR_PARTIAL;
@@ -5113,7 +5115,7 @@ void common_function(typval_T *argvars, typval_T *rettv, bool is_funcref)
// result is a VAR_FUNC
rettv->v_type = VAR_FUNC;
rettv->vval.v_string = name;
- func_ref((char_u *)name);
+ func_ref(name);
}
}
theend:
@@ -5529,12 +5531,12 @@ bool callback_from_typval(Callback *const callback, const typval_T *const arg)
if (callback->data.funcref == NULL) {
callback->data.funcref = xstrdup(name);
}
- func_ref((char_u *)callback->data.funcref);
+ func_ref(callback->data.funcref);
callback->type = kCallbackFuncref;
}
} else if (nlua_is_table_from_lua(arg)) {
// TODO(tjdvries): UnifiedCallback
- char *name = (char *)nlua_register_table_as_callable(arg);
+ char *name = nlua_register_table_as_callable(arg);
if (name != NULL) {
callback->data.funcref = xstrdup(name);
@@ -6302,7 +6304,7 @@ int get_id_len(const char **const arg)
// slice "[n:]". Also "xx:" is not a namespace.
len = (int)(p - *arg);
if (len > 1
- || (len == 1 && vim_strchr(namespace_char, **arg) == NULL)) {
+ || (len == 1 && vim_strchr(namespace_char, (uint8_t)(**arg)) == NULL)) {
break;
}
}
@@ -6430,7 +6432,7 @@ const char *find_name_end(const char *arg, const char **expr_start, const char *
// slice "[n:]". Also "xx:" is not a namespace. But {ns}: is.
len = (int)(p - arg);
if ((len > 1 && p[-1] != '}')
- || (len == 1 && vim_strchr(namespace_char, *arg) == NULL)) {
+ || (len == 1 && vim_strchr(namespace_char, (uint8_t)(*arg)) == NULL)) {
break;
}
}
@@ -7408,7 +7410,7 @@ void ex_echo(exarg_T *eap)
/// ":echohl {name}".
void ex_echohl(exarg_T *eap)
{
- echo_attr = syn_name2attr((char_u *)eap->arg);
+ echo_attr = syn_name2attr(eap->arg);
}
/// ":execute expr1 ..." execute the result of an expression.
@@ -8081,7 +8083,7 @@ char *do_string_sub(char *str, char *pat, char *sub, typval_T *expr, const char
if (regmatch.regprog != NULL) {
char *tail = str;
char *end = str + strlen(str);
- while (vim_regexec_nl(&regmatch, (char_u *)str, (colnr_T)(tail - str))) {
+ while (vim_regexec_nl(&regmatch, str, (colnr_T)(tail - str))) {
// Skip empty match except for first match.
if (regmatch.startp[0] == regmatch.endp[0]) {
if (zero_width == regmatch.startp[0]) {
@@ -8100,7 +8102,7 @@ char *do_string_sub(char *str, char *pat, char *sub, typval_T *expr, const char
// - The text up to where the match is.
// - The substituted text.
// - The text after the match.
- sublen = vim_regsub(&regmatch, (char_u *)sub, expr, (char_u *)tail, 0, REGSUB_MAGIC);
+ sublen = vim_regsub(&regmatch, sub, expr, tail, 0, REGSUB_MAGIC);
ga_grow(&ga, (int)((end - tail) + sublen -
(regmatch.endp[0] - regmatch.startp[0])));
@@ -8108,8 +8110,8 @@ char *do_string_sub(char *str, char *pat, char *sub, typval_T *expr, const char
int i = (int)(regmatch.startp[0] - tail);
memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i);
// add the substituted text
- (void)vim_regsub(&regmatch, (char_u *)sub, expr,
- (char_u *)ga.ga_data + ga.ga_len + i, sublen,
+ (void)vim_regsub(&regmatch, sub, expr,
+ (char *)ga.ga_data + ga.ga_len + i, sublen,
REGSUB_COPY | REGSUB_MAGIC);
ga.ga_len += i + sublen - 1;
tail = regmatch.endp[0];
@@ -8297,7 +8299,7 @@ bool eval_has_provider(const char *feat)
if (get_var_tv(buf, len, &tv, NULL, false, true) == FAIL) {
// Show a hint if Call() is defined but g:loaded_xx_provider is missing.
snprintf(buf, sizeof(buf), "provider#%s#Call", name);
- if (!!find_func((char_u *)buf) && p_lpl) {
+ if (!!find_func(buf) && p_lpl) {
semsg("provider: %s: missing required variable g:loaded_%s_provider",
name, name);
}
@@ -8312,7 +8314,7 @@ bool eval_has_provider(const char *feat)
if (ok) {
// Call() must be defined if provider claims to be working.
snprintf(buf, sizeof(buf), "provider#%s#Call", name);
- if (!find_func((char_u *)buf)) {
+ if (!find_func(buf)) {
semsg("provider: %s: g:loaded_%s_provider=2 but %s is not defined",
name, name, buf);
ok = false;
@@ -8335,10 +8337,10 @@ void eval_fmt_source_name_line(char *buf, size_t bufsize)
/// ":checkhealth [plugins]"
void ex_checkhealth(exarg_T *eap)
{
- bool found = !!find_func((char_u *)"health#check");
+ bool found = !!find_func("health#check");
if (!found
&& script_autoload("health#check", sizeof("health#check") - 1, false)) {
- found = !!find_func((char_u *)"health#check");
+ found = !!find_func("health#check");
}
if (!found) {
const char *vimruntime_env = os_getenv("VIMRUNTIME");
diff --git a/src/nvim/eval.h b/src/nvim/eval.h
index d67414f12f..86bc76e793 100644
--- a/src/nvim/eval.h
+++ b/src/nvim/eval.h
@@ -166,7 +166,7 @@ typedef enum {
VV__NULL_BLOB, // Blob with NULL value. For test purposes only.
VV_LUA,
VV_RELNUM,
- VV_WRAP,
+ VV_VIRTNUM,
} VimVarIndex;
/// All recognized msgpack types
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index 14be6aba73..9a5ab51c71 100644
--- a/src/nvim/eval.lua
+++ b/src/nvim/eval.lua
@@ -26,7 +26,7 @@ return {
acos={args=1, base=1, float_func="acos"}, -- WJMc
add={args=2, base=1},
['and']={args=2, base=1},
- api_info={},
+ api_info={fast=true},
append={args=2, base=2},
appendbufline={args=3, base=3},
argc={args={0, 1}},
@@ -64,14 +64,14 @@ return {
bufwinid={args=1, base=1},
bufwinnr={args=1, base=1},
byte2line={args=1, base=1},
- byteidx={args=2, base=1},
- byteidxcomp={args=2, base=1},
+ byteidx={args=2, base=1, fast=true},
+ byteidxcomp={args=2, base=1, fast=true},
call={args={2, 3}, base=1},
ceil={args=1, base=1, float_func="ceil"},
changenr={},
chanclose={args={1, 2}},
chansend={args=2},
- char2nr={args={1, 2}, base=1},
+ char2nr={args={1, 2}, base=1, fast=true},
charclass={args=1, base=1},
charcol={args={1, 2}, base=1},
charidx={args={2, 3}, base=1},
@@ -100,7 +100,7 @@ return {
deletebufline={args={2,3}, base=1},
dictwatcheradd={args=3},
dictwatcherdel={args=3},
- did_filetype={},
+ did_filetype={fast=true},
diff_filler={args=1, base=1},
diff_hlID={args=2, base=1},
digraph_get={args=1, base=1},
@@ -108,11 +108,11 @@ return {
digraph_set={args=2, base=1},
digraph_setlist={args=1, base=1},
empty={args=1, base=1},
- environ={},
- escape={args=2, base=1},
+ environ={fast=true},
+ escape={args=2, base=1, fast=true},
eval={args=1, base=1},
eventhandler={},
- executable={args=1, base=1},
+ executable={args=1, base=1, fast=true},
execute={args={1, 2}, base=1},
exepath={args=1, base=1},
exists={args=1, base=1},
@@ -122,8 +122,8 @@ return {
extend={args={2, 3}, base=1},
feedkeys={args={1, 2}, base=1},
file_readable={args=1, base=1, func='f_filereadable'}, -- obsolete
- filereadable={args=1, base=1},
- filewritable={args=1, base=1},
+ filereadable={args=1, base=1, fast=true},
+ filewritable={args=1, base=1, fast=true},
filter={args=2, base=1},
finddir={args={1, 3}, base=1},
findfile={args={1, 3}, base=1},
@@ -131,8 +131,8 @@ return {
float2nr={args=1, base=1},
floor={args=1, base=1, float_func="floor"},
fmod={args=2, base=1},
- fnameescape={args=1, base=1},
- fnamemodify={args=2, base=1},
+ fnameescape={args=1, base=1, fast=true},
+ fnamemodify={args=2, base=1, fast=true},
foldclosed={args=1, base=1},
foldclosedend={args=1, base=1},
foldlevel={args=1, base=1},
@@ -148,6 +148,7 @@ return {
getbufline={args={2, 3}, base=1},
getbufoneline={args=2, base=1},
getbufvar={args={2, 3}, base=1},
+ getcellwidths={},
getchangelist={args={0, 1}, base=1},
getchar={args={0, 1}},
getcharmod={},
@@ -166,17 +167,17 @@ return {
getcwd={args={0, 2}, base=1},
getenv={args=1, base=1},
getfontname={args={0, 1}},
- getfperm={args=1, base=1},
- getfsize={args=1, base=1},
- getftime={args=1, base=1},
- getftype={args=1, base=1},
+ getfperm={args=1, base=1, fast=true},
+ getfsize={args=1, base=1, fast=true},
+ getftime={args=1, base=1, fast=true},
+ getftype={args=1, base=1, fast=true},
getjumplist={args={0, 2}, base=1},
getline={args={1, 2}, base=1},
getloclist={args={1, 2}},
getmarklist={args={0, 1}, base=1},
getmatches={args={0, 1}},
getmousepos={},
- getpid={},
+ getpid={fast=true},
getpos={args=1, base=1},
getqflist={args={0, 1}},
getreg={args={0, 3}, base=1},
@@ -207,7 +208,7 @@ return {
histnr={args=1, base=1},
hlID={args=1, base=1},
hlexists={args=1, base=1},
- hostname={},
+ hostname={fast=true},
iconv={args=3, base=1, fast=true},
indent={args=1, base=1},
index={args={2, 4}, base=1},
@@ -220,7 +221,7 @@ return {
insert={args={2, 3}, base=1},
interrupt={args=0},
invert={args=1, base=1},
- isdirectory={args=1, base=1},
+ isdirectory={args=1, base=1, fast=true},
isinf={args=1, base=1},
islocked={args=1, base=1},
isnan={args=1, base=1},
@@ -299,13 +300,13 @@ return {
reg_executing={},
reg_recording={},
reg_recorded={},
- reltime={args={0, 2}, base=1},
- reltimefloat={args=1, base=1},
- reltimestr={args=1, base=1},
+ reltime={args={0, 2}, base=1, fast=true},
+ reltimefloat={args=1, base=1, fast=true},
+ reltimestr={args=1, base=1, fast=true},
remove={args={2, 3}, base=1},
rename={args=2, base=1},
- ['repeat']={args=2, base=1},
- resolve={args=1, base=1},
+ ['repeat']={args=2, base=1, fast=true},
+ resolve={args=1, base=1, fast=true},
reverse={args=1, base=1},
round={args=1, base=1, float_func="round"},
rpcnotify={args=varargs(2)},
@@ -373,24 +374,24 @@ return {
split={args={1, 3}, base=1},
sqrt={args=1, base=1, float_func="sqrt"},
srand={args={0, 1}, base=1},
- stdpath={args=1},
+ stdpath={args=1, fast=true},
str2float={args=1, base=1},
str2list={args={1, 2}, base=1},
str2nr={args={1, 3}, base=1},
strcharlen={args=1, base=1},
- strcharpart={args={2, 3}, base=1},
+ strcharpart={args={2, 3}, base=1, fast=true},
strchars={args={1, 2}, base=1},
strdisplaywidth={args={1, 2}, base=1},
strftime={args={1, 2}, base=1},
strgetchar={args=2, base=1},
- stridx={args={2, 3}, base=1},
+ stridx={args={2, 3}, base=1, fast=true},
string={args=1, base=1},
strlen={args=1, base=1},
- strpart={args={2, 4}, base=1},
+ strpart={args={2, 4}, base=1, fast=true},
strptime={args=2, base=1},
strridx={args={2, 3}, base=1},
- strtrans={args=1, base=1},
- strwidth={args=1, base=1},
+ strtrans={args=1, base=1, fast=true},
+ strwidth={args=1, base=1, fast=true},
submatch={args={1, 2}, base=1},
substitute={args=4, base=1},
swapinfo={args=1, base=1},
@@ -418,12 +419,12 @@ return {
timer_start={args={2, 3}, base=1},
timer_stop={args=1, base=1},
timer_stopall={args=0},
- tolower={args=1, base=1},
- toupper={args=1, base=1},
+ tolower={args=1, base=1, fast=true},
+ toupper={args=1, base=1, fast=true},
tr={args=3, base=1},
trim={args={1, 3}, base=1},
trunc={args=1, base=1, float_func="trunc"},
- type={args=1, base=1},
+ type={args=1, base=1, fast=true},
undofile={args=1, base=1},
undotree={},
uniq={args={1, 3}, base=1},
@@ -446,7 +447,7 @@ return {
win_splitmove={args={2, 3}, base=1},
winbufnr={args=1, base=1},
wincol={},
- windowsversion={},
+ windowsversion={fast=true},
winheight={args=1, base=1},
winlayout={args={0, 1}, base=1},
winline={},
diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c
index 72eb0f8d67..2f37d1ba2e 100644
--- a/src/nvim/eval/buffer.c
+++ b/src/nvim/eval/buffer.c
@@ -9,6 +9,7 @@
#include "nvim/ascii.h"
#include "nvim/autocmd.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/change.h"
#include "nvim/cursor.h"
#include "nvim/eval.h"
@@ -277,9 +278,9 @@ void f_appendbufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
/// "bufadd(expr)" function
void f_bufadd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- char_u *name = (char_u *)tv_get_string(&argvars[0]);
+ char *name = (char *)tv_get_string(&argvars[0]);
- rettv->vval.v_number = buflist_add(*name == NUL ? NULL : (char *)name, 0);
+ rettv->vval.v_number = buflist_add(*name == NUL ? NULL : name, 0);
}
/// "bufexists(expr)" function
diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c
index 03d4862550..c2f1eae8af 100644
--- a/src/nvim/eval/encode.c
+++ b/src/nvim/eval/encode.c
@@ -309,7 +309,7 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
if (buf_[i_] == '\'') { \
ga_append(gap, '\''); \
} \
- ga_append(gap, buf_[i_]); \
+ ga_append(gap, (uint8_t)buf_[i_]); \
} \
ga_append(gap, '\''); \
} \
diff --git a/src/nvim/eval/encode.h b/src/nvim/eval/encode.h
index e66dab1cff..41e7614fc0 100644
--- a/src/nvim/eval/encode.h
+++ b/src/nvim/eval/encode.h
@@ -4,6 +4,7 @@
#include <msgpack.h>
#include <msgpack/pack.h>
#include <stddef.h>
+#include <string.h>
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
diff --git a/src/nvim/eval/executor.c b/src/nvim/eval/executor.c
index 86d6063b01..9caea2fef1 100644
--- a/src/nvim/eval/executor.c
+++ b/src/nvim/eval/executor.c
@@ -51,7 +51,7 @@ int eexe_mod_op(typval_T *const tv1, const typval_T *const tv2, const char *cons
blob_T *const b1 = tv1->vval.v_blob;
blob_T *const b2 = tv2->vval.v_blob;
for (int i = 0; i < tv_blob_len(b2); i++) {
- ga_append(&b1->bv_ga, (char)tv_blob_get(b2, i));
+ ga_append(&b1->bv_ga, tv_blob_get(b2, i));
}
}
return OK;
@@ -69,7 +69,7 @@ int eexe_mod_op(typval_T *const tv1, const typval_T *const tv2, const char *cons
if (tv2->v_type == VAR_LIST) {
break;
}
- if (vim_strchr("+-*/%", *op) != NULL) {
+ if (vim_strchr("+-*/%", (uint8_t)(*op)) != NULL) {
// nr += nr or nr -= nr, nr *= nr, nr /= nr, nr %= nr
varnumber_T n = tv_get_number(tv1);
if (tv2->v_type == VAR_FLOAT) {
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index d6b9ca20fc..48f3cd4293 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -244,11 +244,11 @@ int call_internal_func(const char *const fname, const int argcount, typval_T *co
}
/// Invoke a method for base->method().
-int call_internal_method(const char_u *const fname, const int argcount, typval_T *const argvars,
+int call_internal_method(const char *const fname, const int argcount, typval_T *const argvars,
typval_T *const rettv, typval_T *const basetv)
FUNC_ATTR_NONNULL_ALL
{
- const EvalFuncDef *const fdef = find_internal_func((const char *)fname);
+ const EvalFuncDef *const fdef = find_internal_func(fname);
if (fdef == NULL) {
return FCERR_UNKNOWN;
} else if (fdef->base_arg == BASE_NONE) {
@@ -362,20 +362,20 @@ static void f_add(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
rettv->vval.v_number = 1; // Default: failed.
if (argvars[0].v_type == VAR_LIST) {
list_T *const l = argvars[0].vval.v_list;
- if (!var_check_lock(tv_list_locked(l), N_("add() argument"),
- TV_TRANSLATE)) {
+ if (!value_check_lock(tv_list_locked(l), N_("add() argument"),
+ TV_TRANSLATE)) {
tv_list_append_tv(l, &argvars[1]);
tv_copy(&argvars[0], rettv);
}
} else if (argvars[0].v_type == VAR_BLOB) {
blob_T *const b = argvars[0].vval.v_blob;
if (b != NULL
- && !var_check_lock(b->bv_lock, N_("add() argument"), TV_TRANSLATE)) {
+ && !value_check_lock(b->bv_lock, N_("add() argument"), TV_TRANSLATE)) {
bool error = false;
const varnumber_T n = tv_get_number_chk(&argvars[1], &error);
if (!error) {
- ga_append(&b->bv_ga, (char)n);
+ ga_append(&b->bv_ga, (uint8_t)n);
tv_copy(&argvars[0], rettv);
}
}
@@ -557,7 +557,7 @@ static void f_call(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
func = partial_name(partial);
} else if (nlua_is_table_from_lua(&argvars[0])) {
// TODO(tjdevries): UnifiedCallback
- func = (char *)nlua_register_table_as_callable(&argvars[0]);
+ func = nlua_register_table_as_callable(&argvars[0]);
owned = true;
} else {
func = (char *)tv_get_string(&argvars[0]);
@@ -572,16 +572,16 @@ static void f_call(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (argvars[2].v_type != VAR_DICT) {
emsg(_(e_dictreq));
if (owned) {
- func_unref((char_u *)func);
+ func_unref(func);
}
return;
}
selfdict = argvars[2].vval.v_dict;
}
- func_call((char_u *)func, &argvars[1], partial, selfdict, rettv);
+ func_call(func, &argvars[1], partial, selfdict, rettv);
if (owned) {
- func_unref((char_u *)func);
+ func_unref(func);
}
}
@@ -1419,7 +1419,7 @@ static void f_diff_hlID(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
hlID = HLF_CHD; // Changed line.
}
}
- rettv->vval.v_number = hlID == (hlf_T)0 ? 0 : (int)(hlID + 1);
+ rettv->vval.v_number = hlID == (hlf_T)0 ? 0 : (hlID + 1);
}
/// "empty({expr})" function
@@ -1695,7 +1695,7 @@ static void f_exepath(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
#ifdef BACKSLASH_IN_FILENAME
if (path != NULL) {
- slash_adjust((char_u *)path);
+ slash_adjust(path);
}
#endif
@@ -1749,7 +1749,7 @@ static void f_expand(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
int options = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND;
bool error = false;
#ifdef BACKSLASH_IN_FILENAME
- char_u *p_csl_save = p_csl;
+ char *p_csl_save = p_csl;
// avoid using 'completeslash' here
p_csl = empty_option;
@@ -1770,7 +1770,7 @@ static void f_expand(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
size_t len;
char *errormsg = NULL;
- char *result = (char *)eval_vars((char_u *)s, (char_u *)s, &len, NULL, &errormsg, NULL, false);
+ char *result = eval_vars((char *)s, s, &len, NULL, &errormsg, NULL, false);
if (p_verbose == 0) {
emsg_off--;
} else if (errormsg != NULL) {
@@ -1896,9 +1896,9 @@ static void f_flatten(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
list_T *list = argvars[0].vval.v_list;
if (list != NULL
- && !var_check_lock(tv_list_locked(list),
- N_("flatten() argument"),
- TV_TRANSLATE)
+ && !value_check_lock(tv_list_locked(list),
+ N_("flatten() argument"),
+ TV_TRANSLATE)
&& tv_list_flatten(list, maxdepth) == OK) {
tv_copy(&argvars[0], rettv);
}
@@ -1915,7 +1915,7 @@ static void f_extend(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
list_T *const l1 = argvars[0].vval.v_list;
list_T *const l2 = argvars[1].vval.v_list;
- if (!var_check_lock(tv_list_locked(l1), arg_errmsg, TV_TRANSLATE)) {
+ if (!value_check_lock(tv_list_locked(l1), arg_errmsg, TV_TRANSLATE)) {
listitem_T *item;
if (argvars[2].v_type != VAR_UNKNOWN) {
long before = (long)tv_get_number_chk(&argvars[2], &error);
@@ -1944,13 +1944,13 @@ static void f_extend(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
dict_T *const d1 = argvars[0].vval.v_dict;
dict_T *const d2 = argvars[1].vval.v_dict;
if (d1 == NULL) {
- const bool locked = var_check_lock(VAR_FIXED, arg_errmsg, TV_TRANSLATE);
+ const bool locked = value_check_lock(VAR_FIXED, arg_errmsg, TV_TRANSLATE);
(void)locked;
assert(locked == true);
} else if (d2 == NULL) {
// Do nothing
tv_copy(&argvars[0], rettv);
- } else if (!var_check_lock(d1->dv_lock, arg_errmsg, TV_TRANSLATE)) {
+ } else if (!value_check_lock(d1->dv_lock, arg_errmsg, TV_TRANSLATE)) {
const char *action = "force";
// Check the third argument.
if (argvars[2].v_type != VAR_UNKNOWN) {
@@ -2022,7 +2022,7 @@ static void f_filewritable(typval_T *argvars, typval_T *rettv, EvalFuncData fptr
static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what)
{
char *fresult = NULL;
- char *path = *curbuf->b_p_path == NUL ? (char *)p_path : curbuf->b_p_path;
+ char *path = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path;
int count = 1;
bool first = true;
bool error = false;
@@ -2248,7 +2248,7 @@ static void f_get(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
rettv->v_type = (*what == 'f' ? VAR_FUNC : VAR_STRING);
assert(name != NULL);
if (rettv->v_type == VAR_FUNC) {
- func_ref((char_u *)name);
+ func_ref((char *)name);
}
if (*what == 'n' && pt->pt_name == NULL && pt->pt_func != NULL) {
// use <SNR> instead of the byte code
@@ -2982,8 +2982,8 @@ static void f_globpath(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
const char *const file = tv_get_string_buf_chk(&argvars[1], buf1);
if (file != NULL && !error) {
garray_T ga;
- ga_init(&ga, (int)sizeof(char_u *), 10);
- globpath((char *)tv_get_string(&argvars[0]), (char *)file, &ga, flags);
+ ga_init(&ga, (int)sizeof(char *), 10);
+ globpath((char *)tv_get_string(&argvars[0]), (char *)file, &ga, flags, false);
if (rettv->v_type == VAR_STRING) {
rettv->vval.v_string = ga_concat_strings_sep(&ga, "\n");
@@ -3064,9 +3064,6 @@ static void f_has(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
"conceal",
"cursorbind",
"cursorshape",
-#ifdef DEBUG
- "debug",
-#endif
"dialog_con",
"diff",
"digraphs",
@@ -3082,9 +3079,7 @@ static void f_has(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
"fork",
#endif
"gettext",
-#if defined(HAVE_ICONV)
"iconv",
-#endif
"insert_expand",
"jumplist",
"keymap",
@@ -3556,8 +3551,8 @@ static void f_insert(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
blob_T *const b = argvars[0].vval.v_blob;
if (b == NULL
- || var_check_lock(b->bv_lock, N_("insert() argument"),
- TV_TRANSLATE)) {
+ || value_check_lock(b->bv_lock, N_("insert() argument"),
+ TV_TRANSLATE)) {
return;
}
@@ -3584,16 +3579,16 @@ static void f_insert(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
ga_grow(&b->bv_ga, 1);
- char_u *const p = (char_u *)b->bv_ga.ga_data;
+ uint8_t *const p = (uint8_t *)b->bv_ga.ga_data;
memmove(p + before + 1, p + before, (size_t)(len - before));
- *(p + before) = (char_u)val;
+ *(p + before) = (uint8_t)val;
b->bv_ga.ga_len++;
tv_copy(&argvars[0], rettv);
} else if (argvars[0].v_type != VAR_LIST) {
semsg(_(e_listblobarg), "insert()");
- } else if (!var_check_lock(tv_list_locked((l = argvars[0].vval.v_list)),
- N_("insert() argument"), TV_TRANSLATE)) {
+ } else if (!value_check_lock(tv_list_locked((l = argvars[0].vval.v_list)),
+ N_("insert() argument"), TV_TRANSLATE)) {
long before = 0;
if (argvars[2].v_type != VAR_UNKNOWN) {
before = tv_get_number_chk(&argvars[2], &error);
@@ -4488,7 +4483,7 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv,
}
}
- match = vim_regexec_nl(&regmatch, (char_u *)str, startcol);
+ match = vim_regexec_nl(&regmatch, str, startcol);
if (match && --nth <= 0) {
break;
@@ -5885,7 +5880,7 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
q[-1] = NUL;
q = path_tail(p);
}
- if (q > p && !path_is_absolute((const char_u *)buf)) {
+ if (q > p && !path_is_absolute(buf)) {
// Symlink is relative to directory of argument. Replace the
// symlink with the resolved name in the same directory.
const size_t p_len = strlen(p);
@@ -5976,7 +5971,7 @@ static void f_reverse(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
const int len = tv_blob_len(b);
for (int i = 0; i < len / 2; i++) {
- const char_u tmp = tv_blob_get(b, i);
+ const uint8_t tmp = tv_blob_get(b, i);
tv_blob_set(b, i, tv_blob_get(b, len - i - 1));
tv_blob_set(b, len - i - 1, tmp);
}
@@ -5985,8 +5980,8 @@ static void f_reverse(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
semsg(_(e_listblobarg), "reverse()");
} else {
list_T *const l = argvars[0].vval.v_list;
- if (!var_check_lock(tv_list_locked(l), N_("reverse() argument"),
- TV_TRANSLATE)) {
+ if (!value_check_lock(tv_list_locked(l), N_("reverse() argument"),
+ TV_TRANSLATE)) {
tv_list_reverse(l);
tv_list_set_ret(rettv, l);
}
@@ -6228,7 +6223,7 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp)
// Repeat until {skip} returns false.
for (;;) {
subpatnum
- = searchit(curwin, curbuf, &pos, NULL, dir, (char_u *)pat, 1, options, RE_SEARCH, &sia);
+ = searchit(curwin, curbuf, &pos, NULL, dir, (char *)pat, 1, options, RE_SEARCH, &sia);
// finding the first match again means there is no match where {skip}
// evaluates to zero.
if (firstpos.lnum != 0 && equalpos(pos, firstpos)) {
@@ -6239,7 +6234,9 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp)
// didn't find it or no skip argument
break;
}
- firstpos = pos;
+ if (firstpos.lnum == 0) {
+ firstpos = pos;
+ }
// If the skip expression matches, ignore this match.
{
@@ -6468,7 +6465,7 @@ static void f_rpcstart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
// Allocate extra memory for the argument vector and the NULL pointer
int argvl = argsl + 2;
- char **argv = xmalloc(sizeof(char_u *) * (size_t)argvl);
+ char **argv = xmalloc(sizeof(char *) * (size_t)argvl);
// Copy program name
argv[0] = xstrdup(argvars[0].vval.v_string);
@@ -6644,7 +6641,7 @@ static void f_searchdecl(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
}
if (!error && name != NULL) {
- rettv->vval.v_number = find_decl((char_u *)name, strlen(name), locally,
+ rettv->vval.v_number = find_decl((char *)name, strlen(name), locally,
thisblock, SEARCH_KEEP) == FAIL;
}
}
@@ -6810,7 +6807,7 @@ long do_searchpair(const char *spat, const char *mpat, const char *epat, int dir
.sa_tm = &tm,
};
- int n = searchit(curwin, curbuf, &pos, NULL, dir, (char_u *)pat, 1L,
+ int n = searchit(curwin, curbuf, &pos, NULL, dir, pat, 1L,
options, RE_SEARCH, &sia);
if (n == FAIL || (firstpos.lnum != 0 && equalpos(pos, firstpos))) {
// didn't find it or found the first match again: FAIL
@@ -7069,11 +7066,11 @@ static void f_setcharsearch(typval_T *argvars, typval_T *rettv, EvalFuncData fpt
return;
}
- char_u *const csearch = (char_u *)tv_dict_get_string(d, "char", false);
+ char *const csearch = tv_dict_get_string(d, "char", false);
if (csearch != NULL) {
int pcc[MAX_MCO];
- const int c = utfc_ptr2char((char *)csearch, pcc);
- set_last_csearch(c, csearch, utfc_ptr2len((char *)csearch));
+ const int c = utfc_ptr2char(csearch, pcc);
+ set_last_csearch(c, csearch, utfc_ptr2len(csearch));
}
dictitem_T *di = tv_dict_find(d, S_LEN("forward"));
@@ -7553,7 +7550,7 @@ static void f_spellbadword(typval_T *argvars, typval_T *rettv, EvalFuncData fptr
if (str != NULL) {
// Check the argument for spelling.
while (*str != NUL) {
- len = spell_check(curwin, (char_u *)str, &attr, &capcol, false);
+ len = spell_check(curwin, (char *)str, &attr, &capcol, false);
if (attr != HLF_COUNT) {
word = str;
break;
@@ -7612,7 +7609,7 @@ static void f_spellsuggest(typval_T *argvars, typval_T *rettv, EvalFuncData fptr
maxcount = 25;
}
- spell_suggest_list(&ga, (char_u *)str, maxcount, need_capital, false);
+ spell_suggest_list(&ga, (char *)str, maxcount, need_capital, false);
f_spellsuggest_return:
tv_list_alloc_ret(rettv, (ptrdiff_t)ga.ga_len);
@@ -7668,7 +7665,7 @@ static void f_split(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (*str == NUL) {
match = false; // Empty item at the end.
} else {
- match = vim_regexec_nl(&regmatch, (char_u *)str, col);
+ match = vim_regexec_nl(&regmatch, (char *)str, col);
}
const char *end;
if (match) {
@@ -7823,34 +7820,35 @@ static void f_strftime(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
// MSVC returns NULL for an invalid value of seconds.
if (curtime_ptr == NULL) {
rettv->vval.v_string = xstrdup(_("(Invalid)"));
- } else {
- vimconv_T conv;
+ return;
+ }
- conv.vc_type = CONV_NONE;
- char *enc = (char *)enc_locale();
- convert_setup(&conv, p_enc, enc);
- if (conv.vc_type != CONV_NONE) {
- p = string_convert(&conv, p, NULL);
- }
- char result_buf[256];
- if (p == NULL || strftime(result_buf, sizeof(result_buf), p, curtime_ptr) == 0) {
- result_buf[0] = NUL;
- }
+ vimconv_T conv;
- if (conv.vc_type != CONV_NONE) {
- xfree(p);
- }
- convert_setup(&conv, enc, p_enc);
- if (conv.vc_type != CONV_NONE) {
- rettv->vval.v_string = string_convert(&conv, result_buf, NULL);
- } else {
- rettv->vval.v_string = xstrdup(result_buf);
- }
+ conv.vc_type = CONV_NONE;
+ char *enc = enc_locale();
+ convert_setup(&conv, p_enc, enc);
+ if (conv.vc_type != CONV_NONE) {
+ p = string_convert(&conv, p, NULL);
+ }
+ char result_buf[256];
+ if (p == NULL || strftime(result_buf, sizeof(result_buf), p, curtime_ptr) == 0) {
+ result_buf[0] = NUL;
+ }
- // Release conversion descriptors.
- convert_setup(&conv, NULL, NULL);
- xfree(enc);
+ if (conv.vc_type != CONV_NONE) {
+ xfree(p);
}
+ convert_setup(&conv, enc, p_enc);
+ if (conv.vc_type != CONV_NONE) {
+ rettv->vval.v_string = string_convert(&conv, result_buf, NULL);
+ } else {
+ rettv->vval.v_string = xstrdup(result_buf);
+ }
+
+ // Release conversion descriptors.
+ convert_setup(&conv, NULL, NULL);
+ xfree(enc);
}
/// "strgetchar()" function
@@ -7930,11 +7928,11 @@ static void strchar_common(typval_T *argvars, typval_T *rettv, bool skipcc)
{
const char *s = tv_get_string(&argvars[0]);
varnumber_T len = 0;
- int (*func_mb_ptr2char_adv)(const char_u **pp);
+ int (*func_mb_ptr2char_adv)(const char **pp);
func_mb_ptr2char_adv = skipcc ? mb_ptr2char_adv : mb_cptr2char_adv;
while (*s != NUL) {
- func_mb_ptr2char_adv((const char_u **)&s);
+ func_mb_ptr2char_adv(&s);
len++;
}
rettv->vval.v_number = len;
@@ -8097,7 +8095,7 @@ static void f_strptime(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
vimconv_T conv = {
.vc_type = CONV_NONE,
};
- char *enc = (char *)enc_locale();
+ char *enc = enc_locale();
convert_setup(&conv, p_enc, enc);
if (conv.vc_type != CONV_NONE) {
fmt = string_convert(&conv, fmt, NULL);
@@ -8654,6 +8652,7 @@ static void f_timer_pause(typval_T *argvars, typval_T *unused, EvalFuncData fptr
emsg(_(e_number_exp));
return;
}
+
int paused = (bool)tv_get_number(&argvars[1]);
timer_T *timer = find_timer_by_nr(tv_get_number(&argvars[0]));
if (timer != NULL) {
diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c
index 7c61a2f990..c298064d86 100644
--- a/src/nvim/eval/typval.c
+++ b/src/nvim/eval/typval.c
@@ -900,8 +900,8 @@ void tv_list_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg)
list_T *l;
bool error = false;
- if (var_check_lock(tv_list_locked((l = argvars[0].vval.v_list)),
- arg_errmsg, TV_TRANSLATE)) {
+ if (value_check_lock(tv_list_locked((l = argvars[0].vval.v_list)),
+ arg_errmsg, TV_TRANSLATE)) {
return;
}
@@ -1156,7 +1156,7 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort)
semsg(_(e_listarg), sort ? "sort()" : "uniq()");
} else {
list_T *const l = argvars[0].vval.v_list;
- if (var_check_lock(tv_list_locked(l), arg_errmsg, TV_TRANSLATE)) {
+ if (value_check_lock(tv_list_locked(l), arg_errmsg, TV_TRANSLATE)) {
goto theend;
}
tv_list_set_ret(rettv, l);
@@ -1599,7 +1599,7 @@ void callback_free(Callback *callback)
{
switch (callback->type) {
case kCallbackFuncref:
- func_unref((char_u *)callback->data.funcref);
+ func_unref(callback->data.funcref);
xfree(callback->data.funcref);
break;
case kCallbackPartial:
@@ -1628,7 +1628,7 @@ void callback_put(Callback *cb, typval_T *tv)
case kCallbackFuncref:
tv->v_type = VAR_FUNC;
tv->vval.v_string = xstrdup(cb->data.funcref);
- func_ref((char_u *)cb->data.funcref);
+ func_ref(cb->data.funcref);
break;
case kCallbackLua:
// TODO(tjdevries): Unified Callback.
@@ -1654,7 +1654,7 @@ void callback_copy(Callback *dest, Callback *src)
break;
case kCallbackFuncref:
dest->data.funcref = xstrdup(src->data.funcref);
- func_ref((char_u *)src->data.funcref);
+ func_ref(src->data.funcref);
break;
case kCallbackLua:
dest->data.luaref = api_new_luaref(src->data.luaref);
@@ -2494,7 +2494,7 @@ void tv_dict_extend(dict_T *const d1, dict_T *const d2, const char *const action
} else if (*action == 'f' && di2 != di1) {
typval_T oldtv;
- if (var_check_lock(di1->di_tv.v_lock, arg_errmsg, arg_errmsg_len)
+ if (value_check_lock(di1->di_tv.v_lock, arg_errmsg, arg_errmsg_len)
|| var_check_ro(di1->di_flags, arg_errmsg, arg_errmsg_len)) {
break;
}
@@ -2710,7 +2710,7 @@ void tv_blob_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg)
{
blob_T *const b = argvars[0].vval.v_blob;
- if (b != NULL && var_check_lock(b->bv_lock, arg_errmsg, TV_TRANSLATE)) {
+ if (b != NULL && value_check_lock(b->bv_lock, arg_errmsg, TV_TRANSLATE)) {
return;
}
@@ -2730,7 +2730,7 @@ void tv_blob_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg)
}
if (argvars[2].v_type == VAR_UNKNOWN) {
// Remove one item, return its value.
- char_u *const p = (char_u *)b->bv_ga.ga_data;
+ uint8_t *const p = (uint8_t *)b->bv_ga.ga_data;
rettv->vval.v_number = (varnumber_T)(*(p + idx));
memmove(p + idx, p + idx + 1, (size_t)(len - idx - 1));
b->bv_ga.ga_len--;
@@ -2752,9 +2752,8 @@ void tv_blob_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg)
blob->bv_ga.ga_len = (int)(end - idx + 1);
ga_grow(&blob->bv_ga, (int)(end - idx + 1));
- char_u *const p = (char_u *)b->bv_ga.ga_data;
- memmove((char_u *)blob->bv_ga.ga_data, p + idx,
- (size_t)(end - idx + 1));
+ uint8_t *const p = (uint8_t *)b->bv_ga.ga_data;
+ memmove(blob->bv_ga.ga_data, p + idx, (size_t)(end - idx + 1));
tv_blob_set_ret(rettv, blob);
if (len - end - 1 > 0) {
@@ -2902,7 +2901,7 @@ void tv_dict_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg)
if (argvars[2].v_type != VAR_UNKNOWN) {
semsg(_(e_toomanyarg), "remove()");
} else if ((d = argvars[0].vval.v_dict) != NULL
- && !var_check_lock(d->dv_lock, arg_errmsg, TV_TRANSLATE)) {
+ && !value_check_lock(d->dv_lock, arg_errmsg, TV_TRANSLATE)) {
const char *key = tv_get_string_chk(&argvars[1]);
if (key != NULL) {
dictitem_T *di = tv_dict_find(d, key, -1);
@@ -3007,7 +3006,7 @@ void tv_blob_copy(typval_T *const from, typval_T *const to)
(tv)->v_lock = VAR_UNLOCKED; \
} while (0)
-static inline int _nothing_conv_func_start(typval_T *const tv, char_u *const fun)
+static inline int _nothing_conv_func_start(typval_T *const tv, char *const fun)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ARG(1)
{
tv->v_lock = VAR_UNLOCKED;
@@ -3209,17 +3208,19 @@ static inline void _nothing_conv_dict_end(typval_T *const tv, dict_T **const dic
/// @param[in,out] tv Value to free.
void tv_clear(typval_T *const tv)
{
- if (tv != NULL && tv->v_type != VAR_UNKNOWN) {
- // WARNING: do not translate the string here, gettext is slow and function
- // is used *very* often. At the current state encode_vim_to_nothing() does
- // not error out and does not use the argument anywhere.
- //
- // If situation changes and this argument will be used, translate it in the
- // place where it is used.
- const int evn_ret = encode_vim_to_nothing(NULL, tv, "tv_clear() argument");
- (void)evn_ret;
- assert(evn_ret == OK);
+ if (tv == NULL || tv->v_type == VAR_UNKNOWN) {
+ return;
}
+
+ // WARNING: do not translate the string here, gettext is slow and function
+ // is used *very* often. At the current state encode_vim_to_nothing() does
+ // not error out and does not use the argument anywhere.
+ //
+ // If situation changes and this argument will be used, translate it in the
+ // place where it is used.
+ const int evn_ret = encode_vim_to_nothing(NULL, tv, "tv_clear() argument");
+ (void)evn_ret;
+ assert(evn_ret == OK);
}
//{{{3 Free
@@ -3229,35 +3230,37 @@ void tv_clear(typval_T *const tv)
/// @param tv Object to free.
void tv_free(typval_T *tv)
{
- if (tv != NULL) {
- switch (tv->v_type) {
- case VAR_PARTIAL:
- partial_unref(tv->vval.v_partial);
- break;
- case VAR_FUNC:
- func_unref((char_u *)tv->vval.v_string);
- FALLTHROUGH;
- case VAR_STRING:
- xfree(tv->vval.v_string);
- break;
- case VAR_BLOB:
- tv_blob_unref(tv->vval.v_blob);
- break;
- case VAR_LIST:
- tv_list_unref(tv->vval.v_list);
- break;
- case VAR_DICT:
- tv_dict_unref(tv->vval.v_dict);
- break;
- case VAR_BOOL:
- case VAR_SPECIAL:
- case VAR_NUMBER:
- case VAR_FLOAT:
- case VAR_UNKNOWN:
- break;
- }
- xfree(tv);
+ if (tv == NULL) {
+ return;
+ }
+
+ switch (tv->v_type) {
+ case VAR_PARTIAL:
+ partial_unref(tv->vval.v_partial);
+ break;
+ case VAR_FUNC:
+ func_unref(tv->vval.v_string);
+ FALLTHROUGH;
+ case VAR_STRING:
+ xfree(tv->vval.v_string);
+ break;
+ case VAR_BLOB:
+ tv_blob_unref(tv->vval.v_blob);
+ break;
+ case VAR_LIST:
+ tv_list_unref(tv->vval.v_list);
+ break;
+ case VAR_DICT:
+ tv_dict_unref(tv->vval.v_dict);
+ break;
+ case VAR_BOOL:
+ case VAR_SPECIAL:
+ case VAR_NUMBER:
+ case VAR_FLOAT:
+ case VAR_UNKNOWN:
+ break;
}
+ xfree(tv);
}
//{{{3 Copy
@@ -3288,7 +3291,7 @@ void tv_copy(const typval_T *const from, typval_T *const to)
if (from->vval.v_string != NULL) {
to->vval.v_string = xstrdup(from->vval.v_string);
if (from->v_type == VAR_FUNC) {
- func_ref((char_u *)to->vval.v_string);
+ func_ref(to->vval.v_string);
}
}
break;
@@ -3460,12 +3463,12 @@ bool tv_check_lock(const typval_T *tv, const char *name, size_t name_len)
default:
break;
}
- return var_check_lock(tv->v_lock, name, name_len)
- || (lock != VAR_UNLOCKED && var_check_lock(lock, name, name_len));
+ return value_check_lock(tv->v_lock, name, name_len)
+ || (lock != VAR_UNLOCKED && value_check_lock(lock, name, name_len));
}
-/// @return true if variable "name" is locked (immutable)
-bool var_check_lock(VarLockStatus lock, const char *name, size_t name_len)
+/// @return true if variable "name" has a locked (immutable) value
+bool value_check_lock(VarLockStatus lock, const char *name, size_t name_len)
{
const char *error_message = NULL;
switch (lock) {
diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h
index 1ee3b5bf69..3f59cd3547 100644
--- a/src/nvim/eval/typval.h
+++ b/src/nvim/eval/typval.h
@@ -358,7 +358,7 @@ static inline int tv_blob_len(const blob_T *const b)
return b->bv_ga.ga_len;
}
-static inline char_u tv_blob_get(const blob_T *b, int idx)
+static inline uint8_t tv_blob_get(const blob_T *b, int idx)
REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT;
/// Get the byte at index `idx` in the blob.
@@ -367,12 +367,12 @@ static inline char_u tv_blob_get(const blob_T *b, int idx)
/// @param[in] idx Index in a blob. Must be valid.
///
/// @return Byte value at the given index.
-static inline char_u tv_blob_get(const blob_T *const b, int idx)
+static inline uint8_t tv_blob_get(const blob_T *const b, int idx)
{
- return ((char_u *)b->bv_ga.ga_data)[idx];
+ return ((uint8_t *)b->bv_ga.ga_data)[idx];
}
-static inline void tv_blob_set(blob_T *b, int idx, char_u c)
+static inline void tv_blob_set(blob_T *b, int idx, uint8_t c)
REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ALL;
/// Store the byte `c` at index `idx` in the blob.
@@ -380,9 +380,9 @@ static inline void tv_blob_set(blob_T *b, int idx, char_u c)
/// @param[in] b Blob to index. Cannot be NULL.
/// @param[in] idx Index in a blob. Must be valid.
/// @param[in] c Value to store.
-static inline void tv_blob_set(blob_T *const b, int idx, char_u c)
+static inline void tv_blob_set(blob_T *const b, int idx, uint8_t c)
{
- ((char_u *)b->bv_ga.ga_data)[idx] = c;
+ ((uint8_t *)b->bv_ga.ga_data)[idx] = c;
}
/// Initialize VimL object
diff --git a/src/nvim/eval/typval_defs.h b/src/nvim/eval/typval_defs.h
index 939e5d0810..4615198441 100644
--- a/src/nvim/eval/typval_defs.h
+++ b/src/nvim/eval/typval_defs.h
@@ -337,7 +337,7 @@ struct ufunc {
///< used for s: variables
int uf_refcount; ///< reference count, see func_name_refcount()
funccall_T *uf_scoped; ///< l: local variables for closure
- char_u *uf_name_exp; ///< if "uf_name[]" starts with SNR the name with
+ char *uf_name_exp; ///< if "uf_name[]" starts with SNR the name with
///< "<SNR>" as a string, otherwise NULL
char uf_name[]; ///< Name of function (actual size equals name);
///< can start with <SNR>123_
diff --git a/src/nvim/eval/typval_encode.c.h b/src/nvim/eval/typval_encode.c.h
index 6c931d3f88..6d29286a58 100644
--- a/src/nvim/eval/typval_encode.c.h
+++ b/src/nvim/eval/typval_encode.c.h
@@ -339,7 +339,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE(
tv_blob_len(tv->vval.v_blob));
break;
case VAR_FUNC:
- TYPVAL_ENCODE_CONV_FUNC_START(tv, (char_u *)tv->vval.v_string);
+ TYPVAL_ENCODE_CONV_FUNC_START(tv, tv->vval.v_string);
TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(tv, 0);
TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, -1);
TYPVAL_ENCODE_CONV_FUNC_END(tv);
@@ -347,7 +347,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE(
case VAR_PARTIAL: {
partial_T *const pt = tv->vval.v_partial;
(void)pt;
- TYPVAL_ENCODE_CONV_FUNC_START(tv, (pt == NULL ? NULL : (char_u *)partial_name(pt))); // -V547
+ TYPVAL_ENCODE_CONV_FUNC_START(tv, (pt == NULL ? NULL : partial_name(pt))); // -V547
_mp_push(*mpstack, ((MPConvStackVal) { // -V779
.type = kMPConvPartial,
.tv = tv,
diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c
index c70d56cd25..6c6dc3fa43 100644
--- a/src/nvim/eval/userfunc.c
+++ b/src/nvim/eval/userfunc.c
@@ -45,6 +45,7 @@
#include "nvim/runtime.h"
#include "nvim/search.h"
#include "nvim/strings.h"
+#include "nvim/types.h"
#include "nvim/ui.h"
#include "nvim/vim.h"
@@ -83,7 +84,7 @@ hashtab_T *func_tbl_get(void)
}
/// Get function arguments.
-static int get_function_args(char **argp, char_u endchar, garray_T *newargs, int *varargs,
+static int get_function_args(char **argp, char endchar, garray_T *newargs, int *varargs,
garray_T *default_args, bool skip)
{
bool mustend = false;
@@ -105,7 +106,7 @@ static int get_function_args(char **argp, char_u endchar, garray_T *newargs, int
// Isolate the arguments: "arg1, arg2, ...)"
bool any_default = false;
- while (*p != (char)endchar) {
+ while (*p != endchar) {
if (p[0] == '.' && p[1] == '.' && p[2] == '.') {
if (varargs != NULL) {
*varargs = true;
@@ -117,7 +118,7 @@ static int get_function_args(char **argp, char_u endchar, garray_T *newargs, int
while (ASCII_ISALNUM(*p) || *p == '_') {
p++;
}
- if (arg == p || isdigit(*arg)
+ if (arg == p || isdigit((uint8_t)(*arg))
|| (p - arg == 9 && strncmp(arg, "firstline", 9) == 0)
|| (p - arg == 8 && strncmp(arg, "lastline", 8) == 0)) {
if (!skip) {
@@ -187,14 +188,14 @@ static int get_function_args(char **argp, char_u endchar, garray_T *newargs, int
}
}
p = skipwhite(p);
- if (mustend && *p != (char)endchar) {
+ if (mustend && *p != endchar) {
if (!skip) {
semsg(_(e_invarg2), *argp);
}
break;
}
}
- if (*p != (char)endchar) {
+ if (*p != endchar) {
goto err_ret;
}
p++; // skip "endchar"
@@ -228,12 +229,12 @@ static void register_closure(ufunc_T *fp)
}
/// @return a name for a lambda. Returned in static memory.
-char_u *get_lambda_name(void)
+char *get_lambda_name(void)
{
- static char_u name[30];
+ static char name[30];
static int lambda_no = 0;
- snprintf((char *)name, sizeof(name), "<lambda>%d", ++lambda_no);
+ snprintf(name, sizeof(name), "<lambda>%d", ++lambda_no);
return name;
}
@@ -307,7 +308,7 @@ int get_lambda_tv(char **arg, typval_T *rettv, bool evaluate)
char *p;
garray_T newlines;
- char *name = (char *)get_lambda_name();
+ char *name = get_lambda_name();
fp = xcalloc(1, offsetof(ufunc_T, uf_name) + strlen(name) + 1);
pt = xcalloc(1, sizeof(partial_T));
@@ -581,9 +582,9 @@ static char *fname_trans_sid(const char *const name, char *const fname_buf, char
/// Find a function by name, return pointer to it in ufuncs.
///
/// @return NULL for unknown function.
-ufunc_T *find_func(const char_u *name)
+ufunc_T *find_func(const char *name)
{
- hashitem_T *hi = hash_find(&func_hashtab, (char *)name);
+ hashitem_T *hi = hash_find(&func_hashtab, name);
if (!HASHITEM_EMPTY(hi)) {
return HI2UF(hi);
}
@@ -759,13 +760,12 @@ static void funccal_unref(funccall_T *fc, ufunc_T *fp, bool force)
static bool func_remove(ufunc_T *fp)
{
hashitem_T *hi = hash_find(&func_hashtab, (char *)UF2HIKEY(fp));
-
- if (!HASHITEM_EMPTY(hi)) {
- hash_remove(&func_hashtab, hi);
- return true;
+ if (HASHITEM_EMPTY(hi)) {
+ return false;
}
- return false;
+ hash_remove(&func_hashtab, hi);
+ return true;
}
static void func_clear_items(ufunc_T *fp)
@@ -1225,9 +1225,9 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett
/// For the first we only count the name stored in func_hashtab as a reference,
/// using function() does not count as a reference, because the function is
/// looked up by name.
-static bool func_name_refcount(const char_u *name)
+static bool func_name_refcount(const char *name)
{
- return isdigit(*name) || *name == '<';
+ return isdigit((uint8_t)(*name)) || *name == '<';
}
/// Call a user function after checking the arguments.
@@ -1318,7 +1318,7 @@ void free_all_functions(void)
// Only free functions that are not refcounted, those are
// supposed to be freed when no longer referenced.
fp = HI2UF(hi);
- if (func_name_refcount((char_u *)fp->uf_name)) {
+ if (func_name_refcount(fp->uf_name)) {
skipped++;
} else {
changed = func_hashtab.ht_changed;
@@ -1344,7 +1344,7 @@ void free_all_functions(void)
// Only free functions that are not refcounted, those are
// supposed to be freed when no longer referenced.
fp = HI2UF(hi);
- if (func_name_refcount((char_u *)fp->uf_name)) {
+ if (func_name_refcount(fp->uf_name)) {
skipped++;
} else {
func_free(fp);
@@ -1381,7 +1381,7 @@ static bool builtin_function(const char *name, int len)
return p == NULL;
}
-int func_call(char_u *name, typval_T *args, partial_T *partial, dict_T *selfdict, typval_T *rettv)
+int func_call(char *name, typval_T *args, partial_T *partial, dict_T *selfdict, typval_T *rettv)
{
typval_T argv[MAX_FUNC_ARGS + 1];
int argc = 0;
@@ -1403,7 +1403,7 @@ int func_call(char_u *name, typval_T *args, partial_T *partial, dict_T *selfdict
funcexe.fe_evaluate = true;
funcexe.fe_partial = partial;
funcexe.fe_selfdict = selfdict;
- r = call_func((char *)name, -1, rettv, argc, argv, &funcexe);
+ r = call_func(name, -1, rettv, argc, argv, &funcexe);
func_call_skip_call:
// Free the arguments.
@@ -1434,30 +1434,30 @@ varnumber_T callback_call_retnr(Callback *callback, int argcount, typval_T *argv
/// Give an error message for the result of a function.
/// Nothing if "error" is FCERR_NONE.
-static void user_func_error(int error, const char_u *name)
+static void user_func_error(int error, const char *name)
FUNC_ATTR_NONNULL_ALL
{
switch (error) {
case FCERR_UNKNOWN:
- emsg_funcname(N_("E117: Unknown function: %s"), (char *)name);
+ emsg_funcname(N_("E117: Unknown function: %s"), name);
break;
case FCERR_NOTMETHOD:
- emsg_funcname(N_("E276: Cannot use function as a method: %s"), (char *)name);
+ emsg_funcname(N_("E276: Cannot use function as a method: %s"), name);
break;
case FCERR_DELETED:
- emsg_funcname(N_("E933: Function was deleted: %s"), (char *)name);
+ emsg_funcname(N_("E933: Function was deleted: %s"), name);
break;
case FCERR_TOOMANY:
- emsg_funcname(_(e_toomanyarg), (char *)name);
+ emsg_funcname(_(e_toomanyarg), name);
break;
case FCERR_TOOFEW:
- emsg_funcname(N_("E119: Not enough arguments for function: %s"), (char *)name);
+ emsg_funcname(N_("E119: Not enough arguments for function: %s"), name);
break;
case FCERR_SCRIPT:
- emsg_funcname(N_("E120: Using <SID> not in a script context: %s"), (char *)name);
+ emsg_funcname(N_("E120: Using <SID> not in a script context: %s"), name);
break;
case FCERR_DICT:
- emsg_funcname(N_("E725: Calling dict function without Dictionary: %s"), (char *)name);
+ emsg_funcname(N_("E725: Calling dict function without Dictionary: %s"), name);
break;
}
}
@@ -1579,7 +1579,7 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t
} else if (fp != NULL || !builtin_function((const char *)rfname, -1)) {
// User defined function.
if (fp == NULL) {
- fp = find_func((char_u *)rfname);
+ fp = find_func(rfname);
}
// Trigger FuncUndefined event, may load the function.
@@ -1587,13 +1587,13 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t
&& apply_autocmds(EVENT_FUNCUNDEFINED, rfname, rfname, true, NULL)
&& !aborting()) {
// executed an autocommand, search for the function again
- fp = find_func((char_u *)rfname);
+ fp = find_func(rfname);
}
// Try loading a package.
if (fp == NULL && script_autoload((const char *)rfname, strlen(rfname),
true) && !aborting()) {
// Loaded a package, search for the function again.
- fp = find_func((char_u *)rfname);
+ fp = find_func(rfname);
}
if (fp != NULL && (fp->uf_flags & FC_DELETED)) {
@@ -1611,7 +1611,7 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t
} else if (funcexe->fe_basetv != NULL) {
// expr->method(): Find the method name in the table, call its
// implementation with the base as one of the arguments.
- error = call_internal_method((char_u *)fname, argcount, argvars, rettv,
+ error = call_internal_method(fname, argcount, argvars, rettv,
funcexe->fe_basetv);
} else {
// Find the function name in the table, call its implementation.
@@ -1635,7 +1635,7 @@ theend:
// Report an error unless the argument evaluation or function call has been
// cancelled due to an aborting error, an interrupt, or an exception.
if (!aborting()) {
- user_func_error(error, (name != NULL) ? (char_u *)name : (char_u *)funcname);
+ user_func_error(error, (name != NULL) ? name : funcname);
}
// clear the copies made from the partial
@@ -1651,7 +1651,7 @@ theend:
char *printable_func_name(ufunc_T *fp)
{
- return fp->uf_name_exp != NULL ? (char *)fp->uf_name_exp : fp->uf_name;
+ return fp->uf_name_exp != NULL ? fp->uf_name_exp : fp->uf_name;
}
/// List the head of the function: "name(arg1, arg2)".
@@ -1723,7 +1723,7 @@ static void list_func_head(ufunc_T *fp, int indent, bool force)
/// @param partial return: partial of a FuncRef
///
/// @return the function name in allocated memory, or NULL for failure.
-char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, partial_T **partial)
+char *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, partial_T **partial)
FUNC_ATTR_NONNULL_ARG(1)
{
char *name = NULL;
@@ -1744,7 +1744,7 @@ char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, pa
&& (*pp)[2] == KE_SNR) {
*pp += 3;
len = get_id_len((const char **)pp) + 3;
- return (char_u *)xmemdupz(start, (size_t)len);
+ return xmemdupz(start, (size_t)len);
}
// A name starting with "<SID>" or "<SNR>" is local to a script. But
@@ -1923,7 +1923,7 @@ char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, pa
theend:
clear_lval(&lv);
- return (char_u *)name;
+ return name;
}
/// If the "funcname" starts with "s:" or "<SID>", then expands it to the
@@ -1975,7 +1975,7 @@ char *save_function_name(char **name, bool skip, int flags, funcdict_T *fudi)
CLEAR_POINTER(fudi);
}
} else {
- saved = (char *)trans_function_name(&p, skip, flags, fudi, NULL);
+ saved = trans_function_name(&p, skip, flags, fudi, NULL);
}
*name = p;
return saved;
@@ -2000,8 +2000,8 @@ static void list_functions(regmatch_T *regmatch)
if ((fp->uf_flags & FC_DEAD) == 0
&& (regmatch == NULL
? (!message_filtered((char *)fp->uf_name)
- && !func_name_refcount((char_u *)fp->uf_name))
- : (!isdigit(*fp->uf_name)
+ && !func_name_refcount(fp->uf_name))
+ : (!isdigit((uint8_t)(*fp->uf_name))
&& vim_regexec(regmatch, (char *)fp->uf_name, 0)))) {
list_func_head(fp, false, false);
if (changed != func_hashtab.ht_changed) {
@@ -2132,7 +2132,7 @@ void ex_function(exarg_T *eap)
*p = NUL;
}
if (!eap->skip && !got_int) {
- fp = find_func((char_u *)name);
+ fp = find_func(name);
if (fp != NULL) {
list_func_head(fp, !eap->forceit, eap->forceit);
for (int j = 0; j < fp->uf_lines.ga_len && !got_int; j++) {
@@ -2255,7 +2255,7 @@ void ex_function(exarg_T *eap)
if (!eap->skip && !eap->forceit) {
if (fudi.fd_dict != NULL && fudi.fd_newkey == NULL) {
emsg(_(e_funcdict));
- } else if (name != NULL && find_func((char_u *)name) != NULL) {
+ } else if (name != NULL && find_func(name) != NULL) {
emsg_funcname(e_funcexts, name);
}
}
@@ -2295,7 +2295,7 @@ void ex_function(exarg_T *eap)
} else {
xfree(line_to_free);
if (eap->getline == NULL) {
- theline = (char *)getcmdline(':', 0L, indent, do_concat);
+ theline = getcmdline(':', 0L, indent, do_concat);
} else {
theline = eap->getline(':', eap->cookie, indent, do_concat);
}
@@ -2509,7 +2509,7 @@ void ex_function(exarg_T *eap)
goto erret;
}
- fp = find_func((char_u *)name);
+ fp = find_func(name);
if (fp != NULL) {
// Function can be replaced with "function!" and when sourcing the
// same script again, but only once.
@@ -2531,7 +2531,7 @@ void ex_function(exarg_T *eap)
fp = NULL;
overwrite = true;
} else {
- char_u *exp_name = fp->uf_name_exp;
+ char *exp_name = fp->uf_name_exp;
// redefine existing function, keep the expanded name
XFREE_CLEAR(name);
fp->uf_name_exp = NULL;
@@ -2550,13 +2550,13 @@ void ex_function(exarg_T *eap)
goto erret;
}
if (fudi.fd_di == NULL) {
- if (var_check_lock(fudi.fd_dict->dv_lock, (const char *)eap->arg,
- TV_CSTRING)) {
+ if (value_check_lock(fudi.fd_dict->dv_lock, (const char *)eap->arg,
+ TV_CSTRING)) {
// Can't add a function to a locked dictionary
goto erret;
}
- } else if (var_check_lock(fudi.fd_di->di_tv.v_lock, (const char *)eap->arg,
- TV_CSTRING)) {
+ } else if (value_check_lock(fudi.fd_di->di_tv.v_lock, (const char *)eap->arg,
+ TV_CSTRING)) {
// Can't change an existing function if it is locked
goto erret;
}
@@ -2689,7 +2689,7 @@ bool translated_function_exists(const char *name)
if (builtin_function(name, -1)) {
return find_internal_func((char *)name) != NULL;
}
- return find_func((const char_u *)name) != NULL;
+ return find_func(name) != NULL;
}
/// Check whether function with the given name exists
@@ -2707,7 +2707,7 @@ bool function_exists(const char *const name, bool no_deref)
if (no_deref) {
flag |= TFN_NO_DEREF;
}
- char *const p = (char *)trans_function_name((char **)&nm, false, flag, NULL, NULL);
+ char *const p = trans_function_name((char **)&nm, false, flag, NULL, NULL);
nm = skipwhite(nm);
// Only accept "funcname", "funcname ", "funcname (..." and
@@ -2769,7 +2769,7 @@ void ex_delfunction(exarg_T *eap)
{
ufunc_T *fp = NULL;
char *p;
- char_u *name;
+ char *name;
funcdict_T fudi;
p = eap->arg;
@@ -2791,7 +2791,7 @@ void ex_delfunction(exarg_T *eap)
*p = NUL;
}
- if (isdigit(*name) && fudi.fd_dict == NULL) {
+ if (isdigit((uint8_t)(*name)) && fudi.fd_dict == NULL) {
if (!eap->skip) {
semsg(_(e_invarg2), eap->arg);
}
@@ -2832,7 +2832,7 @@ void ex_delfunction(exarg_T *eap)
// it and the refcount is more than one, it should be kept.
// A numbered function or lambda should be kept if the refcount is
// one or more.
- if (fp->uf_refcount > (func_name_refcount((char_u *)fp->uf_name) ? 0 : 1)) {
+ if (fp->uf_refcount > (func_name_refcount(fp->uf_name) ? 0 : 1)) {
// Function is still referenced somewhere. Don't free it but
// do remove it from the hashtable.
if (func_remove(fp)) {
@@ -2848,7 +2848,7 @@ void ex_delfunction(exarg_T *eap)
/// Unreference a Function: decrement the reference count and free it when it
/// becomes zero.
-void func_unref(char_u *name)
+void func_unref(char *name)
{
ufunc_T *fp = NULL;
@@ -2857,7 +2857,7 @@ void func_unref(char_u *name)
}
fp = find_func(name);
- if (fp == NULL && isdigit(*name)) {
+ if (fp == NULL && isdigit((uint8_t)(*name))) {
#ifdef EXITFREE
if (!entered_free_all_mem) {
internal_error("func_unref()");
@@ -2890,7 +2890,7 @@ void func_ptr_unref(ufunc_T *fp)
}
/// Count a reference to a Function.
-void func_ref(char_u *name)
+void func_ref(char *name)
{
ufunc_T *fp;
@@ -2900,7 +2900,7 @@ void func_ref(char_u *name)
fp = find_func(name);
if (fp != NULL) {
(fp->uf_refcount)++;
- } else if (isdigit(*name)) {
+ } else if (isdigit((uint8_t)(*name))) {
// Only give an error for a numbered function.
// Fail silently, when named or lambda function isn't found.
internal_error("func_ref()");
@@ -3017,7 +3017,7 @@ void ex_call(exarg_T *eap)
return;
}
- tofree = (char *)trans_function_name(&arg, false, TFN_INT, &fudi, &partial);
+ tofree = trans_function_name(&arg, false, TFN_INT, &fudi, &partial);
if (fudi.fd_newkey != NULL) {
// Still need to give an error message for missing key.
semsg(_(e_dictkey), fudi.fd_newkey);
@@ -3304,7 +3304,7 @@ void make_partial(dict_T *const selfdict, typval_T *const rettv)
: rettv->vval.v_partial->pt_name;
// Translate "s:func" to the stored function name.
fname = fname_trans_sid(fname, fname_buf, &tofree, &error);
- fp = find_func((char_u *)fname);
+ fp = find_func(fname);
xfree(tofree);
}
@@ -3327,7 +3327,7 @@ void make_partial(dict_T *const selfdict, typval_T *const rettv)
// be referenced elsewhere.
if (ret_pt->pt_name != NULL) {
pt->pt_name = xstrdup(ret_pt->pt_name);
- func_ref((char_u *)pt->pt_name);
+ func_ref(pt->pt_name);
} else {
pt->pt_func = ret_pt->pt_func;
func_ptr_ref(pt->pt_func);
@@ -3348,9 +3348,9 @@ void make_partial(dict_T *const selfdict, typval_T *const rettv)
}
/// @return the name of the executed function.
-char_u *func_name(void *cookie)
+char *func_name(void *cookie)
{
- return (char_u *)((funccall_T *)cookie)->func->uf_name;
+ return ((funccall_T *)cookie)->func->uf_name;
}
/// @return the address holding the next breakpoint line for a funccall cookie.
@@ -3609,7 +3609,7 @@ bool set_ref_in_functions(int copyID)
if (!HASHITEM_EMPTY(hi)) {
todo--;
fp = HI2UF(hi);
- if (!func_name_refcount((char_u *)fp->uf_name)
+ if (!func_name_refcount(fp->uf_name)
&& set_ref_in_func(NULL, fp, copyID)) {
return true;
}
@@ -3635,7 +3635,7 @@ bool set_ref_in_func_args(int copyID)
/// "ht_stack" is used to add hashtabs to be marked. Can be NULL.
///
/// @return true if setting references failed somehow.
-bool set_ref_in_func(char_u *name, ufunc_T *fp_in, int copyID)
+bool set_ref_in_func(char *name, ufunc_T *fp_in, int copyID)
{
ufunc_T *fp = fp_in;
funccall_T *fc;
@@ -3649,8 +3649,8 @@ bool set_ref_in_func(char_u *name, ufunc_T *fp_in, int copyID)
}
if (fp_in == NULL) {
- fname = fname_trans_sid((char *)name, fname_buf, &tofree, &error);
- fp = find_func((char_u *)fname);
+ fname = fname_trans_sid(name, fname_buf, &tofree, &error);
+ fp = find_func(fname);
}
if (fp != NULL) {
for (fc = fp->uf_scoped; fc != NULL; fc = fc->func->uf_scoped) {
@@ -3662,9 +3662,9 @@ bool set_ref_in_func(char_u *name, ufunc_T *fp_in, int copyID)
}
/// Registers a luaref as a lambda.
-char_u *register_luafunc(LuaRef ref)
+char *register_luafunc(LuaRef ref)
{
- char *name = (char *)get_lambda_name();
+ char *name = get_lambda_name();
ufunc_T *fp = xcalloc(1, offsetof(ufunc_T, uf_name) + strlen(name) + 1);
fp->uf_refcount = 1;
@@ -3678,5 +3678,5 @@ char_u *register_luafunc(LuaRef ref)
hash_add(&func_hashtab, UF2HIKEY(fp));
// coverity[leaked_storage]
- return (char_u *)fp->uf_name;
+ return fp->uf_name;
}
diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c
index 206df03381..9ed245d6c4 100644
--- a/src/nvim/eval/vars.c
+++ b/src/nvim/eval/vars.c
@@ -106,7 +106,7 @@ static list_T *heredoc_get(exarg_T *eap, char *cmd)
return NULL;
}
*p = NUL;
- if (islower(*marker)) {
+ if (islower((uint8_t)(*marker))) {
emsg(_("E221: Marker cannot start with lower case letter"));
return NULL;
}
@@ -208,7 +208,7 @@ static void ex_let_const(exarg_T *eap, const bool is_const)
argend--;
}
expr = skipwhite(argend);
- if (*expr != '=' && !((vim_strchr("+-*/%.", *expr) != NULL
+ if (*expr != '=' && !((vim_strchr("+-*/%.", (uint8_t)(*expr)) != NULL
&& expr[1] == '=') || strncmp(expr, "..=", 3) == 0)) {
// ":let" without "=": list variables
if (*arg == '[') {
@@ -244,7 +244,7 @@ static void ex_let_const(exarg_T *eap, const bool is_const)
op[0] = '=';
op[1] = NUL;
if (*expr != '=') {
- if (vim_strchr("+-*/%.", *expr) != NULL) {
+ if (vim_strchr("+-*/%.", (uint8_t)(*expr)) != NULL) {
op[0] = *expr; // +=, -=, *=, /=, %= or .=
if (expr[0] == '.' && expr[1] == '.') { // ..=
expr++;
@@ -590,10 +590,10 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
if (len == 0) {
semsg(_(e_invarg2), name - 1);
} else {
- if (op != NULL && vim_strchr("+-*/%", *op) != NULL) {
+ if (op != NULL && vim_strchr("+-*/%", (uint8_t)(*op)) != NULL) {
semsg(_(e_letwrong), op);
} else if (endchars != NULL
- && vim_strchr(endchars, *skipwhite(arg)) == NULL) {
+ && vim_strchr(endchars, (uint8_t)(*skipwhite(arg))) == NULL) {
emsg(_(e_letunexp));
} else if (!check_secure()) {
char *tofree = NULL;
@@ -629,7 +629,7 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
char *const p = (char *)find_option_end((const char **)&arg, &scope);
if (p == NULL
|| (endchars != NULL
- && vim_strchr(endchars, *skipwhite(p)) == NULL)) {
+ && vim_strchr(endchars, (uint8_t)(*skipwhite(p))) == NULL)) {
emsg(_(e_letunexp));
} else {
varnumber_T n = 0;
@@ -716,10 +716,10 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
return NULL;
}
arg++;
- if (op != NULL && vim_strchr("+-*/%", *op) != NULL) {
+ if (op != NULL && vim_strchr("+-*/%", (uint8_t)(*op)) != NULL) {
semsg(_(e_letwrong), op);
} else if (endchars != NULL
- && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL) {
+ && vim_strchr(endchars, (uint8_t)(*skipwhite(arg + 1))) == NULL) {
emsg(_(e_letunexp));
} else {
char *s;
@@ -747,7 +747,7 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
char *const p = get_lval(arg, tv, &lv, false, false, 0, FNE_CHECK_START);
if (p != NULL && lv.ll_name != NULL) {
- if (endchars != NULL && vim_strchr(endchars, *skipwhite(p)) == NULL) {
+ if (endchars != NULL && vim_strchr(endchars, (uint8_t)(*skipwhite(p))) == NULL) {
emsg(_(e_letunexp));
} else {
set_var_lval(&lv, p, tv, copy, is_const, op);
@@ -877,13 +877,13 @@ static int do_unlet_var(lval_T *lp, char *name_end, exarg_T *eap, int deep FUNC_
} else if ((lp->ll_list != NULL
// ll_list is not NULL when lvalue is not in a list, NULL lists
// yield E689.
- && var_check_lock(tv_list_locked(lp->ll_list),
- lp->ll_name,
- lp->ll_name_len))
+ && value_check_lock(tv_list_locked(lp->ll_list),
+ lp->ll_name,
+ lp->ll_name_len))
|| (lp->ll_dict != NULL
- && var_check_lock(lp->ll_dict->dv_lock,
- lp->ll_name,
- lp->ll_name_len))) {
+ && value_check_lock(lp->ll_dict->dv_lock,
+ lp->ll_name,
+ lp->ll_name_len))) {
return FAIL;
} else if (lp->ll_range) {
assert(lp->ll_list != NULL);
@@ -892,9 +892,9 @@ static int do_unlet_var(lval_T *lp, char *name_end, exarg_T *eap, int deep FUNC_
listitem_T *last_li = first_li;
for (;;) {
listitem_T *const li = TV_LIST_ITEM_NEXT(lp->ll_list, lp->ll_li);
- if (var_check_lock(TV_LIST_ITEM_TV(lp->ll_li)->v_lock,
- lp->ll_name,
- lp->ll_name_len)) {
+ if (value_check_lock(TV_LIST_ITEM_TV(lp->ll_li)->v_lock,
+ lp->ll_name,
+ lp->ll_name_len)) {
return false;
}
lp->ll_li = li;
@@ -976,11 +976,11 @@ int do_unlet(const char *const name, const size_t name_len, const bool forceit)
dictitem_T *const di = TV_DICT_HI2DI(hi);
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)) {
+ || value_check_lock(d->dv_lock, name, TV_CSTRING)) {
return FAIL;
}
- if (var_check_lock(d->dv_lock, name, TV_CSTRING)) {
+ if (value_check_lock(d->dv_lock, name, TV_CSTRING)) {
return FAIL;
}
@@ -1023,10 +1023,6 @@ static int do_lock_var(lval_T *lp, char *name_end FUNC_ATTR_UNUSED, exarg_T *eap
bool lock = eap->cmdidx == CMD_lockvar;
int ret = OK;
- if (deep == 0) { // Nothing to do.
- return OK;
- }
-
if (lp->ll_tv == NULL) {
if (*lp->ll_name == '$') {
semsg(_(e_lock_unlock), lp->ll_name);
@@ -1050,9 +1046,13 @@ static int do_lock_var(lval_T *lp, char *name_end FUNC_ATTR_UNUSED, exarg_T *eap
} else {
di->di_flags &= (uint8_t)(~DI_FLAGS_LOCK);
}
- tv_item_lock(&di->di_tv, deep, lock, false);
+ if (deep != 0) {
+ tv_item_lock(&di->di_tv, deep, lock, false);
+ }
}
}
+ } else if (deep == 0) {
+ // nothing to do
} else if (lp->ll_range) {
listitem_T *li = lp->ll_li;
@@ -1282,12 +1282,18 @@ void set_var_const(const char *name, const size_t name_len, typval_T *const tv,
return;
}
- // existing variable, need to clear the value
+ // Check in this order for backwards compatibility:
+ // - Whether the variable is read-only
+ // - Whether the variable value is locked
+ // - Whether the variable is locked
if (var_check_ro(v->di_flags, name, name_len)
- || var_check_lock(v->di_tv.v_lock, name, name_len)) {
+ || value_check_lock(v->di_tv.v_lock, name, name_len)
+ || var_check_lock(v->di_flags, name, name_len)) {
return;
}
+ // existing variable, need to clear the value
+
// Handle setting internal v: variables separately where needed to
// prevent changing the type.
if (is_vimvarht(ht)) {
@@ -1341,7 +1347,7 @@ void set_var_const(const char *name, const size_t name_len, typval_T *const tv,
// Make sure dict is valid
assert(dict != NULL);
- v = xmalloc(sizeof(dictitem_T) + strlen(varname));
+ v = xmalloc(offsetof(dictitem_T, di_key) + strlen(varname) + 1);
STRCPY(v->di_key, varname);
if (hash_add(ht, (char *)v->di_key) == FAIL) {
xfree(v);
@@ -1418,6 +1424,26 @@ bool var_check_ro(const int flags, const char *name, size_t name_len)
return true;
}
+/// Return true if di_flags "flags" indicates variable "name" is locked.
+/// Also give an error message.
+bool var_check_lock(const int flags, const char *name, size_t name_len)
+{
+ if (!(flags & DI_FLAGS_LOCK)) {
+ return false;
+ }
+
+ if (name_len == TV_TRANSLATE) {
+ name = _(name);
+ name_len = strlen(name);
+ } else if (name_len == TV_CSTRING) {
+ name_len = strlen(name);
+ }
+
+ semsg(_("E1122: Variable is locked: %*s"), (int)name_len, name);
+
+ return true;
+}
+
/// Check whether variable is fixed (DI_FLAGS_FIX)
///
/// Also gives an error message.
@@ -1464,7 +1490,7 @@ bool var_wrong_func_name(const char *const name, const bool new_var)
{
// Allow for w: b: s: and t:.
// Allow autoload variable.
- if (!(vim_strchr("wbst", name[0]) != NULL && name[1] == ':')
+ if (!(vim_strchr("wbst", (uint8_t)name[0]) != NULL && name[1] == ':')
&& !ASCII_ISUPPER((name[0] != NUL && name[1] == ':') ? name[2] : name[0])
&& vim_strchr(name, '#') == NULL) {
semsg(_("E704: Funcref variable name must start with a capital: %s"), name);
diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c
index 4bcbc13534..f58a0c488a 100644
--- a/src/nvim/eval/window.c
+++ b/src/nvim/eval/window.c
@@ -12,6 +12,7 @@
#include "nvim/ascii.h"
#include "nvim/autocmd.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/cursor.h"
#include "nvim/eval/funcs.h"
#include "nvim/eval/typval.h"
@@ -139,6 +140,8 @@ void win_findbuf(typval_T *argvars, list_T *list)
/// Find window specified by "vp" in tabpage "tp".
///
/// @param tp NULL for current tab page
+/// @return current window if "vp" is number zero.
+/// NULL if not found.
win_T *find_win_by_nr(typval_T *vp, tabpage_T *tp)
{
int nr = (int)tv_get_number_chk(vp, NULL);
diff --git a/src/nvim/eval/window.h b/src/nvim/eval/window.h
index 682a794113..995f0a55a9 100644
--- a/src/nvim/eval/window.h
+++ b/src/nvim/eval/window.h
@@ -2,9 +2,19 @@
#define NVIM_EVAL_WINDOW_H
#include <stdbool.h>
+#include <string.h>
+#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
+#include "nvim/cursor.h"
#include "nvim/eval/typval_defs.h"
+#include "nvim/globals.h"
+#include "nvim/mark.h"
+#include "nvim/option_defs.h"
+#include "nvim/os/os.h"
+#include "nvim/pos.h"
+#include "nvim/vim.h"
+#include "nvim/window.h"
/// Structure used by switch_win() to pass values to restore_win()
typedef struct {
diff --git a/src/nvim/event/libuv_process.c b/src/nvim/event/libuv_process.c
index 10a09275d9..e528d21a71 100644
--- a/src/nvim/event/libuv_process.c
+++ b/src/nvim/event/libuv_process.c
@@ -1,6 +1,7 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+#include <assert.h>
#include <stdint.h>
#include <uv.h>
@@ -12,6 +13,7 @@
#include "nvim/log.h"
#include "nvim/macros.h"
#include "nvim/os/os.h"
+#include "nvim/ui_client.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/libuv_process.c.generated.h"
diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c
index 9dfd6f329a..1a524a56ca 100644
--- a/src/nvim/event/process.c
+++ b/src/nvim/event/process.c
@@ -20,6 +20,7 @@
#include "nvim/os/shell.h"
#include "nvim/os/time.h"
#include "nvim/rbuffer.h"
+#include "nvim/ui_client.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/process.c.generated.h"
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index c2af0e6986..437a05f61d 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -158,7 +158,7 @@ void do_ascii(const exarg_T *const eap)
char buf2[20];
buf2[0] = NUL;
- dig = (char *)get_digraph_for_char(cval);
+ dig = get_digraph_for_char(cval);
if (dig != NULL) {
iobuff_len += (size_t)vim_snprintf(IObuff + iobuff_len,
sizeof(IObuff) - iobuff_len,
@@ -206,7 +206,7 @@ void do_ascii(const exarg_T *const eap)
}
iobuff_len += (size_t)utf_char2bytes(c, IObuff + iobuff_len);
- dig = (char *)get_digraph_for_char(c);
+ dig = get_digraph_for_char(c);
if (dig != NULL) {
iobuff_len += (size_t)vim_snprintf(IObuff + iobuff_len,
sizeof(IObuff) - iobuff_len,
@@ -528,7 +528,7 @@ void ex_sort(exarg_T *eap)
emsg(_(e_noprevre));
goto sortend;
}
- regmatch.regprog = vim_regcomp((char *)last_search_pat(), RE_MAGIC);
+ regmatch.regprog = vim_regcomp(last_search_pat(), RE_MAGIC);
} else {
regmatch.regprog = vim_regcomp(p + 1, RE_MAGIC);
}
@@ -1348,7 +1348,7 @@ static char *find_pipe(const char *cmd)
}
if (*p == '"') {
inquote = !inquote;
- } else if (rem_backslash((const char_u *)p)) {
+ } else if (rem_backslash(p)) {
p++;
}
}
@@ -1420,7 +1420,7 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp)
#else
// For shells that don't understand braces around commands, at least allow
// the use of commands in a pipe.
- xstrlcpy(buf, (char *)cmd, len);
+ xstrlcpy(buf, cmd, len);
if (itmp != NULL) {
// If there is a pipe, we have to put the '<' in front of it.
// Don't do this when 'shellquote' is not empty, otherwise the
@@ -3332,7 +3332,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
}
// new pattern and substitution
if (eap->cmd[0] == 's' && *cmd != NUL && !ascii_iswhite(*cmd)
- && vim_strchr("0123456789cegriIp|\"", *cmd) == NULL) {
+ && vim_strchr("0123456789cegriIp|\"", (uint8_t)(*cmd)) == NULL) {
// don't accept alphanumeric for separator
if (check_regexp_delim(*cmd) == FAIL) {
return 0;
@@ -3343,7 +3343,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
// //sub/r). "\&sub&" use last substitute pattern (like //sub/).
if (*cmd == '\\') {
cmd++;
- if (vim_strchr("/?&", *cmd) == NULL) {
+ if (vim_strchr("/?&", (uint8_t)(*cmd)) == NULL) {
emsg(_(e_backslash));
return 0;
}
@@ -3351,11 +3351,11 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
which_pat = RE_SEARCH; // use last '/' pattern
}
pat = ""; // empty search pattern
- delimiter = (char_u)(*cmd++); // remember delimiter character
+ delimiter = (uint8_t)(*cmd++); // remember delimiter character
has_second_delim = true;
} else { // find the end of the regexp
which_pat = RE_LAST; // use last used regexp
- delimiter = (char_u)(*cmd++); // remember delimiter character
+ delimiter = (uint8_t)(*cmd++); // remember delimiter character
pat = cmd; // remember start of search pat
cmd = skip_regexp_ex(cmd, delimiter, magic_isset(), &eap->arg, NULL, NULL);
if (cmd[0] == delimiter) { // end delimiter found
@@ -3443,7 +3443,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
return 0;
}
- if (search_regcomp((char_u *)pat, NULL, RE_SUBST, which_pat,
+ if (search_regcomp(pat, NULL, RE_SUBST, which_pat,
(cmdpreview ? 0 : SEARCH_HIS), &regmatch) == FAIL) {
if (subflags.do_error) {
emsg(_(e_invcmd));
@@ -3697,7 +3697,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
msg_putchar('\n');
xfree(prompt);
if (resp != NULL) {
- typed = (char_u)(*resp);
+ typed = (uint8_t)(*resp);
xfree(resp);
} else {
// getcmdline_prompt() returns NULL if there is no command line to return.
@@ -3895,7 +3895,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
// When it fails sublen is zero.
sublen = vim_regsub_multi(&regmatch,
sub_firstlnum - regmatch.startpos[0].lnum,
- (char_u *)sub, (char_u *)sub_firstline, 0,
+ sub, sub_firstline, 0,
REGSUB_BACKSLASH
| (magic_isset() ? REGSUB_MAGIC : 0));
textlock--;
@@ -3938,7 +3938,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
textlock++;
(void)vim_regsub_multi(&regmatch,
sub_firstlnum - regmatch.startpos[0].lnum,
- (char_u *)sub, (char_u *)new_end, sublen,
+ sub, new_end, sublen,
REGSUB_COPY | REGSUB_BACKSLASH
| (magic_isset() ? REGSUB_MAGIC : 0));
textlock--;
@@ -4372,7 +4372,7 @@ void ex_global(exarg_T *eap)
// "\&": use previous substitute pattern.
if (*cmd == '\\') {
cmd++;
- if (vim_strchr("/?&", *cmd) == NULL) {
+ if (vim_strchr("/?&", (uint8_t)(*cmd)) == NULL) {
emsg(_(e_backslash));
return;
}
@@ -4398,8 +4398,8 @@ void ex_global(exarg_T *eap)
}
}
- char_u *used_pat;
- if (search_regcomp((char_u *)pat, &used_pat, RE_BOTH, which_pat,
+ char *used_pat;
+ if (search_regcomp(pat, &used_pat, RE_BOTH, which_pat,
SEARCH_HIS, &regmatch) == FAIL) {
emsg(_(e_invcmd));
return;
@@ -4704,7 +4704,7 @@ char *skip_vimgrep_pat(char *p, char **s, int *flags)
if (s != NULL) {
*s = p + 1;
}
- c = (char_u)(*p);
+ c = (uint8_t)(*p);
p = skip_regexp(p + 1, c, true);
if (*p != c) {
return NULL;
diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua
index 68db03bd7d..c8b6ceab69 100644
--- a/src/nvim/ex_cmds.lua
+++ b/src/nvim/ex_cmds.lua
@@ -2387,7 +2387,7 @@ module.cmds = {
},
{
command='scriptnames',
- flags=bit.bor(BANG, RANGE, COUNT, TRLBAR, CMDWIN, LOCK_OK),
+ flags=bit.bor(BANG, FILES, RANGE, COUNT, TRLBAR, CMDWIN, LOCK_OK),
addr_type='ADDR_OTHER',
func='ex_scriptnames',
},
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index e11dd0a2f6..a24e8458a6 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -369,7 +369,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
// Get the function or script name and the address where the next breakpoint
// line and the debug tick for a function or script are stored.
if (getline_is_func) {
- fname = (char *)func_name(real_cookie);
+ fname = func_name(real_cookie);
breakpoint = func_breakpoint(real_cookie);
dbg_tick = func_dbg_tick(real_cookie);
} else if (getline_equal(fgetline, cookie, getsourceline)) {
@@ -919,7 +919,7 @@ static char *get_loop_line(int c, void *cookie, int indent, bool do_concat)
char *line;
// First time inside the ":while"/":for": get line normally.
if (cp->getline == NULL) {
- line = (char *)getcmdline(c, 0L, indent, do_concat);
+ line = getcmdline(c, 0L, indent, do_concat);
} else {
line = cp->getline(c, cp->cookie, indent, do_concat);
}
@@ -2852,7 +2852,7 @@ bool checkforcmd(char **pp, const char *cmd, int len)
break;
}
}
- if (i >= len && !isalpha((*pp)[i])) {
+ if (i >= len && !ASCII_ISALPHA((*pp)[i])) {
*pp = skipwhite(*pp + i);
return true;
}
@@ -2877,7 +2877,7 @@ static void append_command(char *cmd)
STRCAT(IObuff, ": ");
d = IObuff + strlen(IObuff);
while (*s != NUL && d - IObuff + 5 < IOSIZE) {
- if ((char_u)s[0] == 0xc2 && (char_u)s[1] == 0xa0) {
+ if ((uint8_t)s[0] == 0xc2 && (uint8_t)s[1] == 0xa0) {
s += 2;
STRCPY(d, "<a0>");
d += 4;
@@ -2890,6 +2890,33 @@ static void append_command(char *cmd)
*d = NUL;
}
+/// Return true and set "*idx" if "p" points to a one letter command.
+/// - The 'k' command can directly be followed by any character.
+/// - The 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r'
+/// but :sre[wind] is another command, as are :scr[iptnames],
+/// :scs[cope], :sim[alt], :sig[ns] and :sil[ent].
+static int one_letter_cmd(const char *p, cmdidx_T *idx)
+{
+ if (*p == 'k') {
+ *idx = CMD_k;
+ return true;
+ }
+ if (p[0] == 's'
+ && ((p[1] == 'c'
+ && (p[2] == NUL
+ || (p[2] != 's' && p[2] != 'r'
+ && (p[3] == NUL
+ || (p[3] != 'i' && p[4] != 'p')))))
+ || p[1] == 'g'
+ || (p[1] == 'i' && p[2] != 'm' && p[2] != 'l' && p[2] != 'g')
+ || p[1] == 'I'
+ || (p[1] == 'r' && p[2] != 'e'))) {
+ *idx = CMD_substitute;
+ return true;
+ }
+ return false;
+}
+
/// Find an Ex command by its name, either built-in or user.
/// Start of the name can be found at eap->cmd.
/// Sets eap->cmdidx and returns a pointer to char after the command name.
@@ -2900,27 +2927,8 @@ char *find_ex_command(exarg_T *eap, int *full)
FUNC_ATTR_NONNULL_ARG(1)
{
// Isolate the command and search for it in the command table.
- // Exceptions:
- // - the 'k' command can directly be followed by any character.
- // - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r'
- // but :sre[wind] is another command, as are :scr[iptnames],
- // :scs[cope], :sim[alt], :sig[ns] and :sil[ent].
- // - the "d" command can directly be followed by 'l' or 'p' flag.
char *p = eap->cmd;
- if (*p == 'k') {
- eap->cmdidx = CMD_k;
- p++;
- } else if (p[0] == 's'
- && ((p[1] == 'c'
- && (p[2] == NUL
- || (p[2] != 's' && p[2] != 'r'
- && (p[3] == NUL
- || (p[3] != 'i' && p[4] != 'p')))))
- || p[1] == 'g'
- || (p[1] == 'i' && p[2] != 'm' && p[2] != 'l' && p[2] != 'g')
- || p[1] == 'I'
- || (p[1] == 'r' && p[2] != 'e'))) {
- eap->cmdidx = CMD_substitute;
+ if (one_letter_cmd(p, &eap->cmdidx)) {
p++;
} else {
while (ASCII_ISALPHA(*p)) {
@@ -2934,10 +2942,11 @@ char *find_ex_command(exarg_T *eap, int *full)
}
// check for non-alpha command
- if (p == eap->cmd && vim_strchr("@!=><&~#", *p) != NULL) {
+ if (p == eap->cmd && vim_strchr("@!=><&~#", (uint8_t)(*p)) != NULL) {
p++;
}
int len = (int)(p - eap->cmd);
+ // The "d" command can directly be followed by 'l' or 'p' flag.
if (*eap->cmd == 'd' && (p[-1] == 'l' || p[-1] == 'p')) {
// Check for ":dl", ":dell", etc. to ":deletel": that's
// :delete with the 'l' flag. Same for 'p'.
@@ -2958,7 +2967,7 @@ char *find_ex_command(exarg_T *eap, int *full)
}
if (ASCII_ISLOWER(eap->cmd[0])) {
- const int c1 = (char_u)eap->cmd[0];
+ const int c1 = (uint8_t)eap->cmd[0];
const int c2 = len == 1 ? NUL : eap->cmd[1];
if (command_count != CMD_SIZE) {
@@ -3135,9 +3144,11 @@ cmdidx_T excmd_get_cmdidx(const char *cmd, size_t len)
{
cmdidx_T idx;
- for (idx = (cmdidx_T)0; (int)idx < CMD_SIZE; idx = (cmdidx_T)((int)idx + 1)) {
- if (strncmp(cmdnames[(int)idx].cmd_name, cmd, len) == 0) {
- break;
+ if (!one_letter_cmd(cmd, &idx)) {
+ for (idx = (cmdidx_T)0; (int)idx < CMD_SIZE; idx = (cmdidx_T)((int)idx + 1)) {
+ if (strncmp(cmdnames[(int)idx].cmd_name, cmd, len) == 0) {
+ break;
+ }
}
}
@@ -3161,7 +3172,7 @@ uint32_t excmd_get_argt(cmdidx_T idx)
/// @return the "cmd" pointer advanced to beyond the range.
char *skip_range(const char *cmd, int *ctx)
{
- while (vim_strchr(" \t0123456789.$%'/?-+,;\\", *cmd) != NULL) {
+ while (vim_strchr(" \t0123456789.$%'/?-+,;\\", (uint8_t)(*cmd)) != NULL) {
if (*cmd == '\\') {
if (cmd[1] == '?' || cmd[1] == '/' || cmd[1] == '&') {
cmd++;
@@ -3350,7 +3361,7 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, int
case '/':
case '?': // '/' or '?' - search
- c = (char_u)(*cmd++);
+ c = (uint8_t)(*cmd++);
if (addr_type != ADDR_LINES) {
addr_error(addr_type);
cmd = NULL;
@@ -3423,7 +3434,7 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, int
pos.coladd = 0;
if (searchit(curwin, curbuf, &pos, NULL,
*cmd == '?' ? BACKWARD : FORWARD,
- (char_u *)"", 1L, SEARCH_MSG, i, NULL) != FAIL) {
+ "", 1L, SEARCH_MSG, i, NULL) != FAIL) {
lnum = pos.lnum;
} else {
cmd = NULL;
@@ -3484,7 +3495,7 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, int
if (ascii_isdigit(*cmd)) {
i = '+'; // "number" is same as "+number"
} else {
- i = (char_u)(*cmd++);
+ i = (uint8_t)(*cmd++);
}
if (!ascii_isdigit(*cmd)) { // '+' is '+1'
n = 1;
@@ -3531,7 +3542,7 @@ error:
/// Get flags from an Ex command argument.
static void get_flags(exarg_T *eap)
{
- while (vim_strchr("lp#", *eap->arg) != NULL) {
+ while (vim_strchr("lp#", (uint8_t)(*eap->arg)) != NULL) {
if (*eap->arg == 'l') {
eap->flags |= EXFLAG_LIST;
} else if (*eap->arg == 'p') {
@@ -3699,7 +3710,7 @@ char *replace_makeprg(exarg_T *eap, char *arg, char **cmdlinep)
if ((eap->cmdidx == CMD_make || eap->cmdidx == CMD_lmake || isgrep)
&& !grep_internal(eap->cmdidx)) {
const char *program = isgrep ? (*curbuf->b_p_gp == NUL ? p_gp : curbuf->b_p_gp)
- : (*curbuf->b_p_mp == NUL ? (char *)p_mp : curbuf->b_p_mp);
+ : (*curbuf->b_p_mp == NUL ? p_mp : curbuf->b_p_mp);
arg = skipwhite(arg);
@@ -3748,7 +3759,7 @@ int expand_filename(exarg_T *eap, char **cmdlinep, char **errormsgp)
}
// Quick check if this cannot be the start of a special string.
// Also removes backslash before '%', '#' and '<'.
- if (vim_strchr("%#<", *p) == NULL) {
+ if (vim_strchr("%#<", (uint8_t)(*p)) == NULL) {
p++;
continue;
}
@@ -3756,8 +3767,8 @@ int expand_filename(exarg_T *eap, char **cmdlinep, char **errormsgp)
// Try to find a match at this position.
size_t srclen;
int escaped;
- char *repl = (char *)eval_vars((char_u *)p, (char_u *)eap->arg, &srclen, &(eap->do_ecmd_lnum),
- errormsgp, &escaped, true);
+ char *repl = eval_vars(p, eap->arg, &srclen, &(eap->do_ecmd_lnum),
+ errormsgp, &escaped, true);
if (*errormsgp != NULL) { // error detected
return FAIL;
}
@@ -3801,8 +3812,8 @@ int expand_filename(exarg_T *eap, char **cmdlinep, char **errormsgp)
#endif
for (l = repl; *l; l++) {
- if (vim_strchr((char *)ESCAPE_CHARS, *l) != NULL) {
- l = vim_strsave_escaped(repl, (char *)ESCAPE_CHARS);
+ if (vim_strchr(ESCAPE_CHARS, (uint8_t)(*l)) != NULL) {
+ l = vim_strsave_escaped(repl, ESCAPE_CHARS);
xfree(repl);
repl = l;
break;
@@ -3857,7 +3868,7 @@ int expand_filename(exarg_T *eap, char **cmdlinep, char **errormsgp)
backslash_halve(eap->arg);
}
#else
- backslash_halve((char_u *)eap->arg);
+ backslash_halve(eap->arg);
#endif
if (has_wildcards) {
@@ -4033,15 +4044,15 @@ char *skip_cmd_arg(char *p, int rembs)
return p;
}
-int get_bad_opt(const char_u *p, exarg_T *eap)
+int get_bad_opt(const char *p, exarg_T *eap)
FUNC_ATTR_NONNULL_ALL
{
if (STRICMP(p, "keep") == 0) {
eap->bad_char = BAD_KEEP;
} else if (STRICMP(p, "drop") == 0) {
eap->bad_char = BAD_DROP;
- } else if (MB_BYTE2LEN(*p) == 1 && p[1] == NUL) {
- eap->bad_char = *p;
+ } else if (MB_BYTE2LEN((uint8_t)(*p)) == 1 && p[1] == NUL) {
+ eap->bad_char = (uint8_t)(*p);
} else {
return FAIL;
}
@@ -4118,7 +4129,7 @@ static int getargopt(exarg_T *eap)
if (check_ff_value(eap->cmd + eap->force_ff) == FAIL) {
return FAIL;
}
- eap->force_ff = (char_u)eap->cmd[eap->force_ff];
+ eap->force_ff = (uint8_t)eap->cmd[eap->force_ff];
} else if (pp == &eap->force_enc) {
// Make 'fileencoding' lower case.
for (char *p = eap->cmd + eap->force_enc; *p != NUL; p++) {
@@ -4127,7 +4138,7 @@ static int getargopt(exarg_T *eap)
} else {
// Check ++bad= argument. Must be a single-byte character, "keep" or
// "drop".
- if (get_bad_opt((char_u *)eap->cmd + bad_char_idx, eap) == FAIL) {
+ if (get_bad_opt(eap->cmd + bad_char_idx, eap) == FAIL) {
return FAIL;
}
}
@@ -4965,8 +4976,8 @@ void ex_splitview(exarg_T *eap)
}
if (eap->cmdidx == CMD_sfind || eap->cmdidx == CMD_tabfind) {
- fname = (char *)find_file_in_path(eap->arg, strlen(eap->arg),
- FNAME_MESS, true, curbuf->b_ffname);
+ fname = find_file_in_path(eap->arg, strlen(eap->arg),
+ FNAME_MESS, true, curbuf->b_ffname);
if (fname == NULL) {
goto theend;
}
@@ -4976,7 +4987,7 @@ void ex_splitview(exarg_T *eap)
// Either open new tab page or split the window.
if (use_tab) {
if (win_new_tabpage(cmdmod.cmod_tab != 0 ? cmdmod.cmod_tab : eap->addr_count == 0
- ? 0 : (int)eap->line2 + 1, (char_u *)eap->arg) != FAIL) {
+ ? 0 : (int)eap->line2 + 1, eap->arg) != FAIL) {
do_exedit(eap, old_curwin);
apply_autocmds(EVENT_TABNEWENTERED, NULL, NULL, false, curbuf);
@@ -5158,15 +5169,15 @@ static void ex_resize(exarg_T *eap)
/// ":find [+command] <file>" command.
static void ex_find(exarg_T *eap)
{
- char *fname = (char *)find_file_in_path(eap->arg, strlen(eap->arg),
- FNAME_MESS, true, curbuf->b_ffname);
+ char *fname = find_file_in_path(eap->arg, strlen(eap->arg),
+ FNAME_MESS, true, curbuf->b_ffname);
if (eap->addr_count > 0) {
// Repeat finding the file "count" times. This matters when it
// appears several times in the path.
linenr_T count = eap->line2;
while (fname != NULL && --count > 0) {
xfree(fname);
- fname = (char *)find_file_in_path(NULL, 0, FNAME_MESS, false, curbuf->b_ffname);
+ fname = find_file_in_path(NULL, 0, FNAME_MESS, false, curbuf->b_ffname);
}
}
@@ -5238,9 +5249,9 @@ void do_exedit(exarg_T *eap, win_T *old_curwin)
old_curwin == NULL ? curwin : NULL);
} else if ((eap->cmdidx != CMD_split && eap->cmdidx != CMD_vsplit)
|| *eap->arg != NUL) {
- // Can't edit another file when "curbuf->b_ro_locked" is set. Only ":edit"
- // can bring us here, others are stopped earlier.
- if (*eap->arg != NUL && curbuf_locked()) {
+ // Can't edit another file when "textlock" or "curbuf->b_ro_locked" is set.
+ // Only ":edit" or ":script" can bring us here, others are stopped earlier.
+ if (*eap->arg != NUL && text_or_buf_locked()) {
return;
}
n = readonlymode;
@@ -5961,18 +5972,18 @@ static void ex_undo(exarg_T *eap)
static void ex_wundo(exarg_T *eap)
{
- char hash[UNDO_HASH_SIZE];
+ uint8_t hash[UNDO_HASH_SIZE];
- u_compute_hash(curbuf, (char_u *)hash);
- u_write_undo(eap->arg, eap->forceit, curbuf, (char_u *)hash);
+ u_compute_hash(curbuf, hash);
+ u_write_undo(eap->arg, eap->forceit, curbuf, hash);
}
static void ex_rundo(exarg_T *eap)
{
- char hash[UNDO_HASH_SIZE];
+ uint8_t hash[UNDO_HASH_SIZE];
- u_compute_hash(curbuf, (char_u *)hash);
- u_read_undo(eap->arg, (char_u *)hash, NULL);
+ u_compute_hash(curbuf, hash);
+ u_read_undo(eap->arg, hash, NULL);
}
/// ":redo".
@@ -5991,7 +6002,7 @@ static void ex_later(exarg_T *eap)
if (*p == NUL) {
count = 1;
- } else if (isdigit(*p)) {
+ } else if (isdigit((uint8_t)(*p))) {
count = getdigits_long(&p, false, 0);
switch (*p) {
case 's':
@@ -6049,7 +6060,7 @@ static void ex_redir(exarg_T *eap)
close_redir();
arg++;
if (valid_yank_reg(*arg, true) && *arg != '_') {
- redir_reg = (char_u)(*arg++);
+ redir_reg = (uint8_t)(*arg++);
if (*arg == '>' && arg[1] == '>') { // append
arg += 2;
} else {
@@ -6714,8 +6725,8 @@ ssize_t find_cmdline_var(const char *src, size_t *usedlen)
/// @return an allocated string if a valid match was found.
/// Returns NULL if no match was found. "usedlen" then still contains the
/// number of characters to skip.
-char_u *eval_vars(char_u *src, const char_u *srcstart, size_t *usedlen, linenr_T *lnump,
- char **errormsg, int *escaped, bool empty_is_error)
+char *eval_vars(char *src, const char *srcstart, size_t *usedlen, linenr_T *lnump, char **errormsg,
+ int *escaped, bool empty_is_error)
{
char *result;
char *resultbuf = NULL;
@@ -6731,7 +6742,7 @@ char_u *eval_vars(char_u *src, const char_u *srcstart, size_t *usedlen, linenr_T
}
// Check if there is something to do.
- ssize_t spec_idx = find_cmdline_var((char *)src, usedlen);
+ ssize_t spec_idx = find_cmdline_var(src, usedlen);
if (spec_idx < 0) { // no match
*usedlen = 1;
return NULL;
@@ -6789,16 +6800,16 @@ char_u *eval_vars(char_u *src, const char_u *srcstart, size_t *usedlen, linenr_T
skip_mod = true;
break;
}
- char *s = (char *)src + 1;
+ char *s = src + 1;
if (*s == '<') { // "#<99" uses v:oldfiles.
s++;
}
int i = getdigits_int(&s, false, 0);
- if ((char_u *)s == src + 2 && src[1] == '-') {
+ if (s == src + 2 && src[1] == '-') {
// just a minus sign, don't skip over it
s--;
}
- *usedlen = (size_t)((char_u *)s - src); // length of what we expand
+ *usedlen = (size_t)(s - src); // length of what we expand
if (src[1] == '<' && i != 0) {
if (*usedlen < 2) {
@@ -6834,7 +6845,7 @@ char_u *eval_vars(char_u *src, const char_u *srcstart, size_t *usedlen, linenr_T
break;
case SPEC_CFILE: // file name under cursor
- result = (char *)file_name_at_cursor(FNAME_MESS|FNAME_HYP, 1L, NULL);
+ result = file_name_at_cursor(FNAME_MESS|FNAME_HYP, 1L, NULL);
if (result == NULL) {
*errormsg = "";
return NULL;
@@ -6844,7 +6855,7 @@ char_u *eval_vars(char_u *src, const char_u *srcstart, size_t *usedlen, linenr_T
case SPEC_AFILE: // file name for autocommand
if (autocmd_fname != NULL
- && !path_is_absolute((char_u *)autocmd_fname)
+ && !path_is_absolute(autocmd_fname)
// For CmdlineEnter and related events, <afile> is not a path! #9348
&& !strequal("/", autocmd_fname)) {
// Still need to turn the fname into a full path. It was
@@ -6951,7 +6962,7 @@ char_u *eval_vars(char_u *src, const char_u *srcstart, size_t *usedlen, linenr_T
resultlen = (size_t)(s - result);
}
} else if (!skip_mod) {
- valid |= modify_fname((char *)src, tilde_file, usedlen, &result,
+ valid |= modify_fname(src, tilde_file, usedlen, &result,
&resultbuf, &resultlen);
if (result == NULL) {
*errormsg = "";
@@ -6974,7 +6985,7 @@ char_u *eval_vars(char_u *src, const char_u *srcstart, size_t *usedlen, linenr_T
result = xstrnsave(result, resultlen);
}
xfree(resultbuf);
- return (char_u *)result;
+ return result;
}
/// Expand the <sfile> string in "arg".
@@ -6991,8 +7002,7 @@ char *expand_sfile(char *arg)
// replace "<sfile>" with the sourced file name, and do ":" stuff
size_t srclen;
char *errormsg;
- char *repl = (char *)eval_vars((char_u *)p, (char_u *)result, &srclen, NULL, &errormsg, NULL,
- true);
+ char *repl = eval_vars(p, result, &srclen, NULL, &errormsg, NULL, true);
if (errormsg != NULL) {
if (*errormsg) {
emsg(errormsg);
diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c
index 6450892e39..f76e60f6c5 100644
--- a/src/nvim/ex_eval.c
+++ b/src/nvim/ex_eval.c
@@ -449,8 +449,8 @@ static int throw_exception(void *value, except_type_T type, char *cmdname)
// when no active try block is found, see do_cmdline().
if (type == ET_USER) {
if (strncmp(value, "Vim", 3) == 0
- && (((char_u *)value)[3] == NUL || ((char_u *)value)[3] == ':'
- || ((char_u *)value)[3] == '(')) {
+ && (((char *)value)[3] == NUL || ((char *)value)[3] == ':'
+ || ((char *)value)[3] == '(')) {
emsg(_("E608: Cannot :throw exceptions with 'Vim' prefix"));
goto fail;
}
@@ -1150,7 +1150,7 @@ void ex_throw(exarg_T *eap)
// On error or when an exception is thrown during argument evaluation, do
// not throw.
if (!eap->skip && value != NULL) {
- if (throw_exception((char_u *)value, ET_USER, NULL) == FAIL) {
+ if (throw_exception(value, ET_USER, NULL) == FAIL) {
xfree(value);
} else {
do_throw(eap->cstack);
@@ -1372,8 +1372,7 @@ void ex_catch(exarg_T *eap)
//
prev_got_int = got_int;
got_int = false;
- caught = vim_regexec_nl(&regmatch, (char_u *)current_exception->value,
- (colnr_T)0);
+ caught = vim_regexec_nl(&regmatch, current_exception->value, (colnr_T)0);
got_int |= prev_got_int;
vim_regfree(regmatch.regprog);
}
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 72208c976f..76c3680742 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -274,7 +274,7 @@ static bool do_incsearch_highlighting(int firstc, int *search_delim, incsearch_s
parse_command_modifiers(&ea, &dummy, &dummy_cmdmod, true);
cmd = skip_range(ea.cmd, NULL);
- if (vim_strchr("sgvl", *cmd) == NULL) {
+ if (vim_strchr("sgvl", (uint8_t)(*cmd)) == NULL) {
goto theend;
}
@@ -381,7 +381,7 @@ static void may_do_incsearch_highlighting(int firstc, long count, incsearch_stat
proftime_T tm;
int skiplen, patlen;
char next_char;
- char_u use_last_pat;
+ bool use_last_pat;
int search_delim;
// Parsing range may already set the last search pattern.
@@ -558,7 +558,7 @@ static int may_add_char_to_search(int firstc, int *c, incsearch_state_T *s)
// command line has no uppercase characters, convert
// the character to lowercase
if (p_ic && p_scs
- && !pat_has_uppercase((char_u *)ccline.cmdbuff + skiplen)) {
+ && !pat_has_uppercase(ccline.cmdbuff + skiplen)) {
*c = mb_tolower(*c);
}
if (*c == search_delim
@@ -725,7 +725,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent, bool clea
if (ccline.input_fn) {
s->xpc.xp_context = ccline.xp_context;
s->xpc.xp_pattern = ccline.cmdbuff;
- s->xpc.xp_arg = (char *)ccline.xp_arg;
+ s->xpc.xp_arg = ccline.xp_arg;
}
// Avoid scrolling when called by a recursive do_cmdline(), e.g. when
@@ -773,7 +773,8 @@ static uint8_t *command_line_enter(int firstc, long count, int indent, bool clea
tl_ret = try_leave(&tstate, &err);
if (!tl_ret && ERROR_SET(&err)) {
msg_putchar('\n');
- msg_printf_attr(HL_ATTR(HLF_E)|MSG_HIST, (char *)e_autocmd_err, err.msg);
+ msg_scroll = true;
+ msg_puts_attr(err.msg, HL_ATTR(HLF_E)|MSG_HIST);
api_clear_error(&err);
redrawcmd();
}
@@ -881,7 +882,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent, bool clea
if (!tl_ret && ERROR_SET(&err)) {
msg_putchar('\n');
- semsg(e_autocmd_err, err.msg);
+ emsg(err.msg);
did_emsg = false;
api_clear_error(&err);
}
@@ -907,7 +908,7 @@ theend:
xfree(ccline.last_colors.cmdbuff);
kv_destroy(ccline.last_colors.colors);
- char_u *p = (char_u *)ccline.cmdbuff;
+ char *p = ccline.cmdbuff;
if (ui_has(kUICmdline)) {
ui_call_cmdline_hide(ccline.level);
@@ -922,7 +923,7 @@ theend:
ccline.cmdbuff = NULL;
}
- return p;
+ return (uint8_t *)p;
}
static int command_line_check(VimState *state)
@@ -1234,10 +1235,20 @@ static int command_line_execute(VimState *state, int key)
}
}
+ // The wildmenu is cleared if the pressed key is not used for
+ // navigating the wild menu (i.e. the key is not 'wildchar' or
+ // 'wildcharm' or Ctrl-N or Ctrl-P or Ctrl-A or Ctrl-L).
+ // If the popup menu is displayed, then PageDown and PageUp keys are
+ // also used to navigate the menu.
+ bool end_wildmenu = (!(s->c == p_wc && KeyTyped) && s->c != p_wcm && s->c != Ctrl_Z
+ && s->c != Ctrl_N && s->c != Ctrl_P && s->c != Ctrl_A
+ && s->c != Ctrl_L);
+ end_wildmenu = end_wildmenu && (!cmdline_pum_active()
+ || (s->c != K_PAGEDOWN && s->c != K_PAGEUP
+ && s->c != K_KPAGEDOWN && s->c != K_KPAGEUP));
+
// free expanded names when finished walking through matches
- if (!(s->c == p_wc && KeyTyped) && s->c != p_wcm && s->c != Ctrl_Z
- && s->c != Ctrl_N && s->c != Ctrl_P && s->c != Ctrl_A
- && s->c != Ctrl_L) {
+ if (end_wildmenu) {
command_line_end_wildmenu(s);
}
@@ -1368,7 +1379,7 @@ static int may_do_command_line_next_incsearch(int firstc, long count, incsearch_
char save;
if (search_delim == ccline.cmdbuff[skiplen]) {
- pat = (char *)last_search_pattern();
+ pat = last_search_pattern();
if (pat == NULL) {
restore_last_search_pattern();
return FAIL;
@@ -1398,7 +1409,7 @@ static int may_do_command_line_next_incsearch(int firstc, long count, incsearch_
pat[patlen] = NUL;
int found = searchit(curwin, curbuf, &t, NULL,
next_match ? FORWARD : BACKWARD,
- (char_u *)pat, count, search_flags,
+ pat, count, search_flags,
RE_SEARCH, NULL);
emsg_off--;
pat[patlen] = save;
@@ -1463,7 +1474,7 @@ static int command_line_erase_chars(CommandLineState *s)
}
if (s->c == K_DEL) {
- ccline.cmdpos += mb_off_next((char_u *)ccline.cmdbuff,
+ ccline.cmdpos += mb_off_next(ccline.cmdbuff,
ccline.cmdbuff + ccline.cmdpos);
}
@@ -1546,9 +1557,9 @@ static void command_line_toggle_langmap(CommandLineState *s)
if (s->b_im_ptr != NULL) {
if (s->b_im_ptr == &curbuf->b_p_iminsert) {
- set_iminsert_global();
+ set_iminsert_global(curbuf);
} else {
- set_imsearch_global();
+ set_imsearch_global(curbuf);
}
}
ui_cursor_shape(); // may show different cursor shape
@@ -2000,8 +2011,8 @@ static int command_line_handle_key(CommandLineState *s)
case Ctrl_N: // next match
case Ctrl_P: // previous match
if (s->xpc.xp_numfiles > 0) {
- if (nextwild(&s->xpc, (s->c == Ctrl_P) ? WILD_PREV : WILD_NEXT,
- 0, s->firstc != '@') == FAIL) {
+ const int wild_type = (s->c == Ctrl_P) ? WILD_PREV : WILD_NEXT;
+ if (nextwild(&s->xpc, wild_type, 0, s->firstc != '@') == FAIL) {
break;
}
return command_line_not_changed(s);
@@ -2016,13 +2027,26 @@ static int command_line_handle_key(CommandLineState *s)
case K_KPAGEUP:
case K_PAGEDOWN:
case K_KPAGEDOWN:
- switch (command_line_browse_history(s)) {
- case CMDLINE_CHANGED:
- return command_line_changed(s);
- case GOTO_NORMAL_MODE:
- return 0;
- default:
+ if (cmdline_pum_active()
+ && (s->c == K_PAGEUP || s->c == K_PAGEDOWN
+ || s->c == K_KPAGEUP || s->c == K_KPAGEDOWN)) {
+ // If the popup menu is displayed, then PageUp and PageDown
+ // are used to scroll the menu.
+ const int wild_type =
+ (s->c == K_PAGEDOWN || s->c == K_KPAGEDOWN) ? WILD_PAGEDOWN : WILD_PAGEUP;
+ if (nextwild(&s->xpc, wild_type, 0, s->firstc != '@') == FAIL) {
+ break;
+ }
return command_line_not_changed(s);
+ } else {
+ switch (command_line_browse_history(s)) {
+ case CMDLINE_CHANGED:
+ return command_line_changed(s);
+ case GOTO_NORMAL_MODE:
+ return 0;
+ default:
+ return command_line_not_changed(s);
+ }
}
case Ctrl_G: // next match
@@ -2141,7 +2165,7 @@ static bool empty_pattern_magic(char *p, size_t len, magic_T magic_val)
{
// remove trailing \v and the like
while (len >= 2 && p[len - 2] == '\\'
- && vim_strchr("mMvVcCZ", p[len - 1]) != NULL) {
+ && vim_strchr("mMvVcCZ", (uint8_t)p[len - 1]) != NULL) {
len -= 2;
}
@@ -2521,7 +2545,8 @@ static void do_autocmd_cmdlinechanged(int firstc)
bool tl_ret = try_leave(&tstate, &err);
if (!tl_ret && ERROR_SET(&err)) {
msg_putchar('\n');
- msg_printf_attr(HL_ATTR(HLF_E)|MSG_HIST, (char *)e_autocmd_err, err.msg);
+ msg_scroll = true;
+ msg_puts_attr(err.msg, HL_ATTR(HLF_E)|MSG_HIST);
api_clear_error(&err);
redrawcmd();
}
@@ -2600,9 +2625,9 @@ static void abandon_cmdline(void)
///
/// @param count only used for incremental search
/// @param indent indent for inside conditionals
-char_u *getcmdline(int firstc, long count, int indent, bool do_concat FUNC_ATTR_UNUSED)
+char *getcmdline(int firstc, long count, int indent, bool do_concat FUNC_ATTR_UNUSED)
{
- return command_line_enter(firstc, count, indent, true);
+ return (char *)command_line_enter(firstc, count, indent, true);
}
/// Get a command line with a prompt
@@ -2635,10 +2660,10 @@ char *getcmdline_prompt(const int firstc, const char *const prompt, const int at
CLEAR_FIELD(ccline);
}
ccline.prompt_id = last_prompt_id++;
- ccline.cmdprompt = (char_u *)prompt;
+ ccline.cmdprompt = (char *)prompt;
ccline.cmdattr = attr;
ccline.xp_context = xp_context;
- ccline.xp_arg = (char_u *)xp_arg;
+ ccline.xp_arg = (char *)xp_arg;
ccline.input_fn = (firstc == '@');
ccline.highlight_callback = highlight_callback;
@@ -2662,12 +2687,6 @@ char *getcmdline_prompt(const int firstc, const char *const prompt, const int at
return ret;
}
-// Return current cmdline prompt
-char_u *get_cmdprompt(void)
-{
- return ccline.cmdprompt;
-}
-
/// Read the 'wildmode' option, fill wim_flags[].
int check_opt_wim(void)
{
@@ -2847,7 +2866,7 @@ char *getexline(int c, void *cookie, int indent, bool do_concat)
(void)vgetc();
}
- return (char *)getcmdline(c, 1L, indent, do_concat);
+ return getcmdline(c, 1L, indent, do_concat);
}
bool cmdline_overstrike(void)
@@ -2885,7 +2904,7 @@ void realloc_cmdbuff(int len)
return; // no need to resize
}
- char_u *p = (char_u *)ccline.cmdbuff;
+ char *p = ccline.cmdbuff;
alloc_cmdbuff(len); // will get some more
// There isn't always a NUL after the command, but it may need to be
// there, thus copy up to the NUL and add a NUL.
@@ -2897,7 +2916,7 @@ void realloc_cmdbuff(int len)
&& ccline.xpc->xp_pattern != NULL
&& ccline.xpc->xp_context != EXPAND_NOTHING
&& ccline.xpc->xp_context != EXPAND_UNSUCCESSFUL) {
- int i = (int)((char_u *)ccline.xpc->xp_pattern - p);
+ int i = (int)(ccline.xpc->xp_pattern - p);
// If xp_pattern points inside the old cmdbuff it needs to be adjusted
// to point into the newly allocated memory.
@@ -3232,10 +3251,10 @@ static void draw_cmdline(int start, int len)
bool do_arabicshape = false;
int mb_l;
for (int i = start; i < start + len; i += mb_l) {
- char_u *p = (char_u *)ccline.cmdbuff + i;
+ char *p = ccline.cmdbuff + i;
int u8cc[MAX_MCO];
- int u8c = utfc_ptr2char_len((char *)p, u8cc, start + len - i);
- mb_l = utfc_ptr2len_len((char *)p, start + len - i);
+ int u8c = utfc_ptr2char_len(p, u8cc, start + len - i);
+ mb_l = utfc_ptr2len_len(p, start + len - i);
if (ARABIC_CHAR(u8c)) {
do_arabicshape = true;
break;
@@ -3268,10 +3287,10 @@ static void draw_cmdline(int start, int len)
int prev_c = 0;
int prev_c1 = 0;
for (int i = start; i < start + len; i += mb_l) {
- char_u *p = (char_u *)ccline.cmdbuff + i;
+ char *p = ccline.cmdbuff + i;
int u8cc[MAX_MCO];
- int u8c = utfc_ptr2char_len((char *)p, u8cc, start + len - i);
- mb_l = utfc_ptr2len_len((char *)p, start + len - i);
+ int u8c = utfc_ptr2char_len(p, u8cc, start + len - i);
+ mb_l = utfc_ptr2len_len(p, start + len - i);
if (ARABIC_CHAR(u8c)) {
int pc;
int pc1 = 0;
@@ -3285,7 +3304,7 @@ static void draw_cmdline(int start, int len)
if (i + mb_l >= start + len) {
nc = NUL;
} else {
- nc = utf_ptr2char((char *)p + mb_l);
+ nc = utf_ptr2char(p + mb_l);
}
} else {
// Displaying from left to right.
@@ -3294,7 +3313,7 @@ static void draw_cmdline(int start, int len)
} else {
int pcc[MAX_MCO];
- pc = utfc_ptr2char_len((char *)p + mb_l, pcc, start + len - i - mb_l);
+ pc = utfc_ptr2char_len(p + mb_l, pcc, start + len - i - mb_l);
pc1 = pcc[0];
}
nc = prev_c;
@@ -3344,7 +3363,7 @@ static void ui_ext_cmdline_show(CmdlineInfo *line)
if (cmdline_star) {
content = arena_array(&arena, 1);
size_t len = 0;
- for (char_u *p = (char_u *)ccline.cmdbuff; *p; MB_PTR_ADV(p)) {
+ for (char *p = ccline.cmdbuff; *p; MB_PTR_ADV(p)) {
len++;
}
char *buf = arena_alloc(&arena, len, false);
@@ -3375,7 +3394,7 @@ static void ui_ext_cmdline_show(CmdlineInfo *line)
char charbuf[2] = { (char)line->cmdfirstc, 0 };
ui_call_cmdline_show(content, line->cmdpos,
cstr_as_string(charbuf),
- cstr_as_string((char *)(line->cmdprompt)),
+ cstr_as_string((line->cmdprompt)),
line->cmdindent,
line->level);
if (line->special_char) {
@@ -3657,7 +3676,7 @@ static void restore_cmdline(CmdlineInfo *ccp)
static bool cmdline_paste(int regname, bool literally, bool remcr)
{
char *arg;
- char_u *p;
+ char *p;
bool allocated;
// check for valid regname; also accept special characters for CTRL-R in
@@ -3689,7 +3708,7 @@ static bool cmdline_paste(int regname, bool literally, bool remcr)
// When 'incsearch' is set and CTRL-R CTRL-W used: skip the duplicate
// part of the word.
- p = (char_u *)arg;
+ p = arg;
if (p_is && regname == Ctrl_W) {
char *w;
int len;
@@ -3722,19 +3741,19 @@ static bool cmdline_paste(int regname, bool literally, bool remcr)
// When "literally" is true, insert literally.
// When "literally" is false, insert as typed, but don't leave the command
// line.
-void cmdline_paste_str(char_u *s, int literally)
+void cmdline_paste_str(char *s, int literally)
{
int c, cv;
if (literally) {
- put_on_cmdline((char *)s, -1, true);
+ put_on_cmdline(s, -1, true);
} else {
while (*s != NUL) {
- cv = *s;
+ cv = (uint8_t)(*s);
if (cv == Ctrl_V && s[1]) {
s++;
}
- c = mb_cptr2char_adv((const char_u **)&s);
+ c = mb_cptr2char_adv((const char **)&s);
if (cv == Ctrl_V || c == ESC || c == Ctrl_C
|| c == CAR || c == NL || c == Ctrl_L
|| (c == Ctrl_BSL && *s == Ctrl_N)) {
@@ -3775,7 +3794,7 @@ static void redrawcmdprompt(void)
msg_putchar(ccline.cmdfirstc);
}
if (ccline.cmdprompt != NULL) {
- msg_puts_attr((const char *)ccline.cmdprompt, ccline.cmdattr);
+ msg_puts_attr(ccline.cmdprompt, ccline.cmdattr);
ccline.cmdindent = msg_col + (msg_row - cmdline_row) * Columns;
// do the reverse of cmd_startcol()
if (ccline.cmdfirstc != NUL) {
@@ -3950,8 +3969,8 @@ char *vim_strsave_fnameescape(const char *const fname, const int what)
{
#ifdef BACKSLASH_IN_FILENAME
# define PATH_ESC_CHARS " \t\n*?[{`%#'\"|!<"
-# define BUFFER_ESC_CHARS ((char_u *)" \t\n*?[`%#'\"|!<")
- char_u buf[sizeof(PATH_ESC_CHARS)];
+# define BUFFER_ESC_CHARS (" \t\n*?[`%#'\"|!<")
+ char buf[sizeof(PATH_ESC_CHARS)];
int j = 0;
// Don't escape '[', '{' and '!' if they are in 'isfname' and for the
@@ -3963,8 +3982,7 @@ char *vim_strsave_fnameescape(const char *const fname, const int what)
}
}
buf[j] = NUL;
- char *p = (char *)vim_strsave_escaped((const char_u *)fname,
- (const char_u *)buf);
+ char *p = vim_strsave_escaped(fname, buf);
#else
# define PATH_ESC_CHARS " \t\n*?[{`$\\%#'\"|!<"
# define SHELL_ESC_CHARS " \t\n*?[{`$\\%#'\"|!<>();&"
@@ -3993,11 +4011,11 @@ char *vim_strsave_fnameescape(const char *const fname, const int what)
/// Put a backslash before the file name in "pp", which is in allocated memory.
void escape_fname(char **pp)
{
- char_u *p = xmalloc(strlen(*pp) + 2);
+ char *p = xmalloc(strlen(*pp) + 2);
p[0] = '\\';
STRCPY(p + 1, *pp);
xfree(*pp);
- *pp = (char *)p;
+ *pp = p;
}
/// For each file name in files[num_files]:
@@ -4271,7 +4289,7 @@ char *check_cedit(void)
if (*p_cedit == NUL) {
cedit_key = -1;
} else {
- n = string_to_key((char_u *)p_cedit);
+ n = string_to_key(p_cedit);
if (vim_isprintc(n)) {
return e_invarg;
}
diff --git a/src/nvim/ex_getln.h b/src/nvim/ex_getln.h
index 916b695a35..61ac4b69c5 100644
--- a/src/nvim/ex_getln.h
+++ b/src/nvim/ex_getln.h
@@ -54,14 +54,14 @@ struct cmdline_info {
int cmdspos; ///< cursor column on screen
int cmdfirstc; ///< ':', '/', '?', '=', '>' or NUL
int cmdindent; ///< number of spaces before cmdline
- char_u *cmdprompt; ///< message in front of cmdline
+ char *cmdprompt; ///< message in front of cmdline
int cmdattr; ///< attributes for prompt
int overstrike; ///< Typing mode on the command line. Shared by
///< getcmdline() and put_on_cmdline().
expand_T *xpc; ///< struct being used for expansion, xp_pattern
///< may point into cmdbuff
int xp_context; ///< type of expansion
- char_u *xp_arg; ///< user-defined expansion arg
+ char *xp_arg; ///< user-defined expansion arg
int input_fn; ///< when true Invoked for input() function
unsigned prompt_id; ///< Prompt number, used to disable coloring on errors.
Callback highlight_callback; ///< Callback used for coloring user input.
diff --git a/src/nvim/ex_session.c b/src/nvim/ex_session.c
index cae9c18309..3de5e1db52 100644
--- a/src/nvim/ex_session.c
+++ b/src/nvim/ex_session.c
@@ -38,7 +38,6 @@
#include "nvim/path.h"
#include "nvim/pos.h"
#include "nvim/runtime.h"
-#include "nvim/types.h"
#include "nvim/vim.h"
#include "nvim/window.h"
@@ -113,40 +112,43 @@ static int ses_win_rec(FILE *fd, frame_T *fr)
frame_T *frc;
int count = 0;
- if (fr->fr_layout != FR_LEAF) {
- // Find first frame that's not skipped and then create a window for
- // each following one (first frame is already there).
- frc = ses_skipframe(fr->fr_child);
- if (frc != NULL) {
- while ((frc = ses_skipframe(frc->fr_next)) != NULL) {
- // Make window as big as possible so that we have lots of room
- // to split.
- if (fprintf(fd, "%s%s",
- "wincmd _ | wincmd |\n",
- (fr->fr_layout == FR_COL ? "split\n" : "vsplit\n")) < 0) {
- return FAIL;
- }
- count++;
+ if (fr->fr_layout == FR_LEAF) {
+ return OK;
+ }
+
+ // Find first frame that's not skipped and then create a window for
+ // each following one (first frame is already there).
+ frc = ses_skipframe(fr->fr_child);
+ if (frc != NULL) {
+ while ((frc = ses_skipframe(frc->fr_next)) != NULL) {
+ // Make window as big as possible so that we have lots of room
+ // to split.
+ if (fprintf(fd, "%s%s",
+ "wincmd _ | wincmd |\n",
+ (fr->fr_layout == FR_COL ? "split\n" : "vsplit\n")) < 0) {
+ return FAIL;
}
+ count++;
}
+ }
- // Go back to the first window.
- if (count > 0 && (fprintf(fd, fr->fr_layout == FR_COL
- ? "%dwincmd k\n" : "%dwincmd h\n", count) < 0)) {
- return FAIL;
- }
+ // Go back to the first window.
+ if (count > 0 && (fprintf(fd, fr->fr_layout == FR_COL
+ ? "%dwincmd k\n" : "%dwincmd h\n", count) < 0)) {
+ return FAIL;
+ }
- // Recursively create frames/windows in each window of this column or row.
- frc = ses_skipframe(fr->fr_child);
- while (frc != NULL) {
- ses_win_rec(fd, frc);
- frc = ses_skipframe(frc->fr_next);
- // Go to next window.
- if (frc != NULL && put_line(fd, "wincmd w") == FAIL) {
- return FAIL;
- }
+ // Recursively create frames/windows in each window of this column or row.
+ frc = ses_skipframe(fr->fr_child);
+ while (frc != NULL) {
+ ses_win_rec(fd, frc);
+ frc = ses_skipframe(frc->fr_next);
+ // Go to next window.
+ if (frc != NULL && put_line(fd, "wincmd w") == FAIL) {
+ return FAIL;
}
}
+
return OK;
}
@@ -907,12 +909,14 @@ static int makeopens(FILE *fd, char *dirnow)
void ex_loadview(exarg_T *eap)
{
char *fname = get_view_file(*eap->arg);
- if (fname != NULL) {
- if (do_source(fname, false, DOSO_NONE) == FAIL) {
- semsg(_(e_notopen), fname);
- }
- xfree(fname);
+ if (fname == NULL) {
+ return;
+ }
+
+ if (do_source(fname, false, DOSO_NONE) == FAIL) {
+ semsg(_(e_notopen), fname);
}
+ xfree(fname);
}
/// ":mkexrc", ":mkvimrc", ":mkview", ":mksession".
diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c
index d0280b3571..a0435afd65 100644
--- a/src/nvim/file_search.c
+++ b/src/nvim/file_search.c
@@ -143,7 +143,7 @@ typedef struct ff_visited_list_hdr {
// '**' can be expanded to several directory levels.
// Set the default maximum depth.
-#define FF_MAX_STAR_STAR_EXPAND ((char_u)30)
+#define FF_MAX_STAR_STAR_EXPAND 30
// The search context:
// ffsc_stack_ptr: the stack for the dirs to search
@@ -182,7 +182,7 @@ typedef struct ff_search_ctx_T {
# include "file_search.c.generated.h"
#endif
-static char_u e_pathtoolong[] = N_("E854: path too long for completion");
+static char e_pathtoolong[] = N_("E854: path too long for completion");
/// Initialization routine for vim_findfile().
///
@@ -302,14 +302,12 @@ void *vim_findfile_init(char *path, char *filename, char *stopdirs, int level, i
#ifdef BACKSLASH_IN_FILENAME
// "c:dir" needs "c:" to be expanded, otherwise use current dir
if (*path != NUL && path[1] == ':') {
- char_u drive[3];
+ char drive[3];
drive[0] = path[0];
drive[1] = ':';
drive[2] = NUL;
- if (vim_FullName((const char *)drive, (char *)ff_expand_buffer, MAXPATHL,
- true)
- == FAIL) {
+ if (vim_FullName(drive, ff_expand_buffer, MAXPATHL, true) == FAIL) {
goto error_return;
}
path += 2;
@@ -504,15 +502,15 @@ error_return:
}
/// @return the stopdir string. Check that ';' is not escaped.
-char_u *vim_findfile_stopdir(char *buf)
+char *vim_findfile_stopdir(char *buf)
{
- char_u *r_ptr = (char_u *)buf;
+ char *r_ptr = buf;
while (*r_ptr != NUL && *r_ptr != ';') {
if (r_ptr[0] == '\\' && r_ptr[1] == ';') {
// Overwrite the escape char,
// use strlen(r_ptr) to move the trailing '\0'.
- STRMOVE(r_ptr, (char *)r_ptr + 1);
+ STRMOVE(r_ptr, r_ptr + 1);
r_ptr++;
}
r_ptr++;
@@ -551,7 +549,7 @@ void vim_findfile_cleanup(void *ctx)
///
/// @return a pointer to an allocated file name or,
/// NULL if nothing found.
-char_u *vim_findfile(void *search_ctx_arg)
+char *vim_findfile(void *search_ctx_arg)
{
char *file_path;
char *rest_of_wildcards;
@@ -829,7 +827,7 @@ char_u *vim_findfile(void *search_ctx_arg)
verbose_leave_scroll();
}
#endif
- return (char_u *)file_path;
+ return file_path;
}
// Not found or found already, try next suffix.
@@ -1094,7 +1092,7 @@ static int ff_check_visited(ff_visited_T **visited_list, char *fname, char *wc_p
}
// New file/dir. Add it to the list of visited files/dirs.
- vp = xmalloc(sizeof(ff_visited_T) + strlen(ff_expand_buffer));
+ vp = xmalloc(offsetof(ff_visited_T, ffv_fname) + strlen(ff_expand_buffer) + 1);
if (!url) {
vp->file_id_valid = true;
@@ -1287,13 +1285,13 @@ static int ff_path_in_stoplist(char *path, int path_len, char **stopdirs_v)
/// @param rel_fname file name searching relative to
///
/// @return an allocated string for the file name. NULL for error.
-char_u *find_file_in_path(char *ptr, size_t len, int options, int first, char *rel_fname)
+char *find_file_in_path(char *ptr, size_t len, int options, int first, char *rel_fname)
{
- return (char_u *)find_file_in_path_option(ptr, len, options, first,
- (*curbuf->b_p_path == NUL
- ? (char *)p_path
- : curbuf->b_p_path),
- FINDFILE_BOTH, rel_fname, curbuf->b_p_sua);
+ return find_file_in_path_option(ptr, len, options, first,
+ (*curbuf->b_p_path == NUL
+ ? p_path
+ : curbuf->b_p_path),
+ FINDFILE_BOTH, rel_fname, curbuf->b_p_sua);
}
static char *ff_file_to_find = NULL;
@@ -1322,10 +1320,10 @@ void free_findfile(void)
/// @param rel_fname file name searching relative to
///
/// @return an allocated string for the file name. NULL for error.
-char_u *find_directory_in_path(char_u *ptr, size_t len, int options, char_u *rel_fname)
+char *find_directory_in_path(char *ptr, size_t len, int options, char *rel_fname)
{
- return (char_u *)find_file_in_path_option((char *)ptr, len, options, true, (char *)p_cdpath,
- FINDFILE_DIR, (char *)rel_fname, "");
+ return find_file_in_path_option(ptr, len, options, true, p_cdpath,
+ FINDFILE_DIR, rel_fname, "");
}
/// @param ptr file name
@@ -1446,7 +1444,7 @@ char *find_file_in_path_option(char *ptr, size_t len, int options, int first, ch
for (;;) {
if (did_findfile_init) {
- file_name = (char *)vim_findfile(fdip_search_ctx);
+ file_name = vim_findfile(fdip_search_ctx);
if (file_name != NULL) {
break;
}
@@ -1469,7 +1467,7 @@ char *find_file_in_path_option(char *ptr, size_t len, int options, int first, ch
copy_option_part(&dir, buf, MAXPATHL, " ,");
// get the stopdir string
- r_ptr = (char *)vim_findfile_stopdir(buf);
+ r_ptr = vim_findfile_stopdir(buf);
fdip_search_ctx = vim_findfile_init(buf, ff_file_to_find,
r_ptr, 100, false, find_what,
fdip_search_ctx, false, rel_fname);
@@ -1610,8 +1608,8 @@ int vim_chdirfile(char *fname, CdCause cause)
/// Change directory to "new_dir". Search 'cdpath' for relative directory names.
int vim_chdir(char *new_dir)
{
- char *dir_name = (char *)find_directory_in_path((char_u *)new_dir, strlen(new_dir),
- FNAME_MESS, (char_u *)curbuf->b_ffname);
+ char *dir_name = find_directory_in_path(new_dir, strlen(new_dir),
+ FNAME_MESS, curbuf->b_ffname);
if (dir_name == NULL) {
return -1;
}
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index 0ee547d124..fbb5c4f1fa 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -105,7 +105,7 @@ enum {
// Structure to pass arguments from buf_write() to buf_write_bytes().
struct bw_info {
int bw_fd; // file descriptor
- char_u *bw_buf; // buffer with data to be written
+ char *bw_buf; // buffer with data to be written
int bw_len; // length of data
#ifdef HAS_BW_FLAGS
int bw_flags; // FIO_ flags
@@ -113,14 +113,12 @@ struct bw_info {
char_u bw_rest[CONV_RESTLEN]; // not converted bytes
int bw_restlen; // nr of bytes in bw_rest[]
int bw_first; // first write call
- char_u *bw_conv_buf; // buffer for writing converted chars
+ char *bw_conv_buf; // buffer for writing converted chars
size_t bw_conv_buflen; // size of bw_conv_buf
int bw_conv_error; // set for conversion error
linenr_T bw_conv_error_lnum; // first line with error or zero
linenr_T bw_start_lnum; // line number at start of buffer
-#ifdef HAVE_ICONV
iconv_t bw_iconv_fd; // descriptor for iconv() or -1
-#endif
};
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -248,11 +246,9 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
char *fenc_next = NULL; // next item in 'fencs' or NULL
bool advance_fenc = false;
long real_size = 0;
-#ifdef HAVE_ICONV
iconv_t iconv_fd = (iconv_t)-1; // descriptor for iconv() or -1
bool did_iconv = false; // true when iconv() failed and trying
// 'charconvert' next
-#endif
bool converted = false; // true if conversion done
bool notconverted = false; // true if conversion wanted but it wasn't possible
char conv_rest[CONV_RESTLEN];
@@ -278,7 +274,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
&& fname != NULL
&& vim_strchr(p_cpo, CPO_FNAMER) != NULL
&& !(flags & READ_DUMMY)) {
- if (set_rw_fname((char_u *)fname, (char_u *)sfname) == FAIL) {
+ if (set_rw_fname(fname, sfname) == FAIL) {
return FAIL;
}
}
@@ -779,13 +775,11 @@ retry:
}
}
-#ifdef HAVE_ICONV
if (iconv_fd != (iconv_t)-1) {
// aborted conversion with iconv(), close the descriptor
iconv_close(iconv_fd);
iconv_fd = (iconv_t)-1;
}
-#endif
if (advance_fenc) {
// Try the next entry in 'fileencodings'.
@@ -835,32 +829,24 @@ retry:
// appears not to handle this correctly. This works just like
// conversion to UTF-8 except how the resulting character is put in
// the buffer.
- fio_flags = get_fio_flags((char_u *)fenc);
+ fio_flags = get_fio_flags(fenc);
}
-#ifdef HAVE_ICONV
// Try using iconv() if we can't convert internally.
if (fio_flags == 0
&& !did_iconv) {
- iconv_fd = (iconv_t)my_iconv_open((char_u *)"utf-8", (char_u *)fenc);
+ iconv_fd = (iconv_t)my_iconv_open("utf-8", fenc);
}
-#endif
// Use the 'charconvert' expression when conversion is required
// and we can't do it internally or with iconv().
if (fio_flags == 0 && !read_stdin && !read_buffer && *p_ccv != NUL
- && !read_fifo
-#ifdef HAVE_ICONV
- && iconv_fd == (iconv_t)-1
-#endif
- ) {
-#ifdef HAVE_ICONV
+ && !read_fifo && iconv_fd == (iconv_t)-1) {
did_iconv = false;
-#endif
// Skip conversion when it's already done (retry for wrong
// "fileformat").
if (tmpname == NULL) {
- tmpname = (char *)readfile_charconvert((char_u *)fname, (char_u *)fenc, &fd);
+ tmpname = readfile_charconvert(fname, fenc, &fd);
if (tmpname == NULL) {
// Conversion failed. Try another one.
advance_fenc = true;
@@ -874,11 +860,7 @@ retry:
}
}
} else {
- if (fio_flags == 0
-#ifdef HAVE_ICONV
- && iconv_fd == (iconv_t)-1
-#endif
- ) {
+ if (fio_flags == 0 && iconv_fd == (iconv_t)-1) {
// Conversion wanted but we can't.
// Try the next conversion in 'fileencodings'
advance_fenc = true;
@@ -961,12 +943,9 @@ retry:
// ucs-4 to utf-8: 4 bytes become up to 6 bytes, size must be
// multiple of 4
real_size = (int)size;
-#ifdef HAVE_ICONV
if (iconv_fd != (iconv_t)-1) {
size = size / ICONV_MULT;
- } else {
-#endif
- if (fio_flags & FIO_LATIN1) {
+ } else if (fio_flags & FIO_LATIN1) {
size = size / 2;
} else if (fio_flags & (FIO_UCS2 | FIO_UTF16)) {
size = (size * 2 / 3) & ~1;
@@ -975,9 +954,7 @@ retry:
} else if (fio_flags == FIO_UCSBOM) {
size = size / ICONV_MULT; // worst case
}
-#ifdef HAVE_ICONV
- }
-#endif
+
if (conv_restlen > 0) {
// Insert unconverted bytes from previous line.
memmove(ptr, conv_rest, (size_t)conv_restlen); // -V614
@@ -991,13 +968,11 @@ retry:
if (read_buf_lnum > from) {
size = 0;
} else {
- int n, ni;
- long tlen;
-
- tlen = 0;
+ int ni;
+ long tlen = 0;
for (;;) {
p = (char_u *)ml_get(read_buf_lnum) + read_buf_col;
- n = (int)strlen((char *)p);
+ int n = (int)strlen((char *)p);
if ((int)tlen + n + 1 > size) {
// Filled up to "size", append partial line.
// Change NL to NUL to reverse the effect done
@@ -1049,11 +1024,7 @@ retry:
// not be converted. Truncated file?
// When we did a conversion report an error.
- if (fio_flags != 0
-#ifdef HAVE_ICONV
- || iconv_fd != (iconv_t)-1
-#endif
- ) {
+ if (fio_flags != 0 || iconv_fd != (iconv_t)-1) {
if (can_retry) {
goto rewind_retry;
}
@@ -1074,23 +1045,17 @@ retry:
// character if we were converting; if we weren't,
// leave the UTF8 checking code to do it, as it
// works slightly differently.
- if (bad_char_behavior != BAD_KEEP && (fio_flags != 0
-#ifdef HAVE_ICONV
- || iconv_fd != (iconv_t)-1
-#endif
- )) { // NOLINT(whitespace/parens)
+ if (bad_char_behavior != BAD_KEEP && (fio_flags != 0 || iconv_fd != (iconv_t)-1)) {
while (conv_restlen > 0) {
*(--ptr) = (char)bad_char_behavior;
conv_restlen--;
}
}
fio_flags = 0; // don't convert this
-#ifdef HAVE_ICONV
if (iconv_fd != (iconv_t)-1) {
iconv_close(iconv_fd);
iconv_fd = (iconv_t)-1;
}
-#endif
}
}
}
@@ -1107,15 +1072,15 @@ retry:
|| (!curbuf->b_p_bomb
&& tmpname == NULL
&& (*fenc == 'u' || *fenc == NUL)))) {
- char_u *ccname;
+ char *ccname;
int blen = 0;
// no BOM detection in a short file or in binary mode
if (size < 2 || curbuf->b_p_bin) {
ccname = NULL;
} else {
- ccname = check_for_bom((char_u *)ptr, size, &blen,
- fio_flags == FIO_UCSBOM ? FIO_ALL : get_fio_flags((char_u *)fenc));
+ ccname = check_for_bom(ptr, size, &blen,
+ fio_flags == FIO_UCSBOM ? FIO_ALL : get_fio_flags(fenc));
}
if (ccname != NULL) {
// Remove BOM from the text
@@ -1137,7 +1102,7 @@ retry:
if (fenc_alloced) {
xfree(fenc);
}
- fenc = (char *)ccname;
+ fenc = ccname;
fenc_alloced = false;
}
// retry reading without getting new bytes or rewinding
@@ -1155,7 +1120,6 @@ retry:
break;
}
-#ifdef HAVE_ICONV
if (iconv_fd != (iconv_t)-1) {
// Attempt conversion of the read bytes to 'encoding' using iconv().
const char *fromp = ptr;
@@ -1175,7 +1139,7 @@ retry:
goto rewind_retry;
}
if (conv_error == 0) {
- conv_error = readfile_linenr(linecnt, (char_u *)ptr, (char_u *)top);
+ conv_error = readfile_linenr(linecnt, ptr, top);
}
// Deal with a bad byte and continue with the next.
@@ -1193,7 +1157,7 @@ retry:
if (from_size > 0) {
// Some remaining characters, keep them for the next
// round.
- memmove(conv_rest, (char_u *)fromp, from_size);
+ memmove(conv_rest, fromp, from_size);
conv_restlen = (int)from_size;
}
@@ -1202,7 +1166,6 @@ retry:
memmove(line_start, buffer, (size_t)linerest);
size = (top - ptr);
}
-#endif
if (fio_flags != 0) {
unsigned int u8c;
@@ -1287,7 +1250,7 @@ retry:
goto rewind_retry;
}
if (conv_error == 0) {
- conv_error = readfile_linenr(linecnt, (char_u *)ptr, p);
+ conv_error = readfile_linenr(linecnt, ptr, (char *)p);
}
if (bad_char_behavior == BAD_DROP) {
continue;
@@ -1315,7 +1278,7 @@ retry:
goto rewind_retry;
}
if (conv_error == 0) {
- conv_error = readfile_linenr(linecnt, (char_u *)ptr, p);
+ conv_error = readfile_linenr(linecnt, ptr, (char *)p);
}
if (bad_char_behavior == BAD_DROP) {
continue;
@@ -1356,7 +1319,7 @@ retry:
goto rewind_retry;
}
if (conv_error == 0) {
- conv_error = readfile_linenr(linecnt, (char_u *)ptr, p);
+ conv_error = readfile_linenr(linecnt, ptr, (char *)p);
}
if (bad_char_behavior == BAD_DROP) {
continue;
@@ -1394,7 +1357,7 @@ retry:
// an incomplete character at the end though, the next
// read() will get the next bytes, we'll check it
// then.
- l = utf_ptr2len_len(p, todo);
+ l = utf_ptr2len_len((char *)p, todo);
if (l > todo && !incomplete_tail) {
// Avoid retrying with a different encoding when
// a truncated file is more likely, or attempting
@@ -1420,15 +1383,15 @@ retry:
if (can_retry && !incomplete_tail) {
break;
}
-#ifdef HAVE_ICONV
+
// When we did a conversion report an error.
if (iconv_fd != (iconv_t)-1 && conv_error == 0) {
- conv_error = readfile_linenr(linecnt, (char_u *)ptr, p);
+ conv_error = readfile_linenr(linecnt, ptr, (char *)p);
}
-#endif
+
// Remember the first linenr with an illegal byte
if (conv_error == 0 && illegal_byte == 0) {
- illegal_byte = readfile_linenr(linecnt, (char_u *)ptr, p);
+ illegal_byte = readfile_linenr(linecnt, ptr, (char *)p);
}
// Drop, keep or replace the bad byte.
@@ -1448,17 +1411,13 @@ retry:
// Detected a UTF-8 error.
rewind_retry:
// Retry reading with another conversion.
-#ifdef HAVE_ICONV
if (*p_ccv != NUL && iconv_fd != (iconv_t)-1) {
// iconv() failed, try 'charconvert'
did_iconv = true;
} else {
-#endif
- // use next item from 'fileencodings'
- advance_fenc = true;
-#ifdef HAVE_ICONV
- }
-#endif
+ // use next item from 'fileencodings'
+ advance_fenc = true;
+ }
file_rewind = true;
goto retry;
}
@@ -1554,7 +1513,7 @@ rewind_retry:
break;
}
if (read_undo_file) {
- sha256_update(&sha_ctx, (char_u *)line_start, (size_t)len);
+ sha256_update(&sha_ctx, (uint8_t *)line_start, (size_t)len);
}
lnum++;
if (--read_count == 0) {
@@ -1610,7 +1569,7 @@ rewind_retry:
break;
}
if (read_undo_file) {
- sha256_update(&sha_ctx, (char_u *)line_start, (size_t)len);
+ sha256_update(&sha_ctx, (uint8_t *)line_start, (size_t)len);
}
lnum++;
if (--read_count == 0) {
@@ -1667,7 +1626,7 @@ failed:
error = true;
} else {
if (read_undo_file) {
- sha256_update(&sha_ctx, (char_u *)line_start, (size_t)len);
+ sha256_update(&sha_ctx, (uint8_t *)line_start, (size_t)len);
}
read_no_eol_lnum = ++lnum;
}
@@ -1683,11 +1642,9 @@ failed:
if (fenc_alloced) {
xfree(fenc);
}
-#ifdef HAVE_ICONV
if (iconv_fd != (iconv_t)-1) {
iconv_close(iconv_fd);
}
-#endif
if (!read_buffer && !read_stdin) {
close(fd); // errors are ignored
@@ -1887,7 +1844,7 @@ failed:
char_u hash[UNDO_HASH_SIZE];
sha256_finish(&sha_ctx, hash);
- u_read_undo(NULL, hash, (char_u *)fname);
+ u_read_undo(NULL, hash, fname);
}
if (!read_stdin && !read_fifo && (!read_buffer || sfname != NULL)) {
@@ -1958,9 +1915,9 @@ bool is_dev_fd_file(char *fname)
/// @param linecnt line count before reading more bytes
/// @param p start of more bytes read
/// @param endp end of more bytes read
-static linenr_T readfile_linenr(linenr_T linecnt, char_u *p, const char_u *endp)
+static linenr_T readfile_linenr(linenr_T linecnt, char *p, const char *endp)
{
- char_u *s;
+ char *s;
linenr_T lnum;
lnum = curbuf->b_ml.ml_line_count - linecnt + 1;
@@ -2040,7 +1997,7 @@ static char *next_fenc(char **pp, bool *alloced)
*pp = NULL;
return "";
}
- p = vim_strchr((*pp), ',');
+ p = vim_strchr(*pp, ',');
if (p == NULL) {
r = enc_canonize(*pp);
*pp += strlen(*pp);
@@ -2065,22 +2022,22 @@ static char *next_fenc(char **pp, bool *alloced)
///
/// @return name of the resulting converted file (the caller should delete it after reading it).
/// Returns NULL if the conversion failed ("*fdp" is not set) .
-static char_u *readfile_charconvert(char_u *fname, char_u *fenc, int *fdp)
+static char *readfile_charconvert(char *fname, char *fenc, int *fdp)
{
- char_u *tmpname;
+ char *tmpname;
char *errmsg = NULL;
- tmpname = (char_u *)vim_tempname();
+ tmpname = vim_tempname();
if (tmpname == NULL) {
errmsg = _("Can't find temp file for conversion");
} else {
close(*fdp); // close the input file, ignore errors
*fdp = -1;
- if (eval_charconvert((char *)fenc, "utf-8",
- (char *)fname, (char *)tmpname) == FAIL) {
+ if (eval_charconvert(fenc, "utf-8",
+ fname, tmpname) == FAIL) {
errmsg = _("Conversion with 'charconvert' failed");
}
- if (errmsg == NULL && (*fdp = os_open((char *)tmpname, O_RDONLY, 0)) < 0) {
+ if (errmsg == NULL && (*fdp = os_open(tmpname, O_RDONLY, 0)) < 0) {
errmsg = _("can't read output of 'charconvert'");
}
}
@@ -2090,14 +2047,14 @@ static char_u *readfile_charconvert(char_u *fname, char_u *fenc, int *fdp)
// another type of conversion might still work.
msg(errmsg);
if (tmpname != NULL) {
- os_remove((char *)tmpname); // delete converted file
+ os_remove(tmpname); // delete converted file
XFREE_CLEAR(tmpname);
}
}
// If the input file is closed, open it (caller should check for error).
if (*fdp < 0) {
- *fdp = os_open((char *)fname, O_RDONLY, 0);
+ *fdp = os_open(fname, O_RDONLY, 0);
}
return tmpname;
@@ -2167,7 +2124,6 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
bool errmsg_allocated = false;
char *buffer;
char smallbuf[SMBUFSIZE];
- char *backup_ext;
int bufsize;
long perm; // file permissions
int retval = OK;
@@ -2233,9 +2189,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
write_info.bw_conv_error = false;
write_info.bw_conv_error_lnum = 0;
write_info.bw_restlen = 0;
-#ifdef HAVE_ICONV
write_info.bw_iconv_fd = (iconv_t)-1;
-#endif
// After writing a file changedtick changes but we don't want to display
// the line.
@@ -2254,7 +2208,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
&& !filtering
&& (!append || vim_strchr(p_cpo, CPO_FNAMEAPP) != NULL)
&& vim_strchr(p_cpo, CPO_FNAMEW) != NULL) {
- if (set_rw_fname((char_u *)fname, (char_u *)sfname) == FAIL) {
+ if (set_rw_fname(fname, sfname) == FAIL) {
return FAIL;
}
buf = curbuf; // just in case autocmds made "buf" invalid
@@ -2473,7 +2427,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
if (!filtering) {
filemess(buf,
#ifndef UNIX
- (char_u *)sfname,
+ sfname,
#else
fname,
#endif
@@ -2517,7 +2471,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
}
#else // win32
// Check for a writable device name.
- c = fname == NULL ? NODE_OTHER : os_nodetype((char *)fname);
+ c = fname == NULL ? NODE_OTHER : os_nodetype(fname);
if (c == NODE_OTHER) {
SET_ERRMSG_NUM("E503", _("is not a file or writable device"));
goto fail;
@@ -2535,7 +2489,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
goto fail;
}
if (overwriting) {
- os_fileinfo((char *)fname, &file_info_old);
+ os_fileinfo(fname, &file_info_old);
}
}
#endif // !UNIX
@@ -2566,13 +2520,13 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
#ifdef HAVE_ACL
// For systems that support ACL: get the ACL from the original file.
if (!newfile) {
- acl = os_get_acl((char_u *)fname);
+ acl = os_get_acl(fname);
}
#endif
// If 'backupskip' is not empty, don't make a backup for some files.
dobackup = (p_wb || p_bk || *p_pm != NUL);
- if (dobackup && *p_bsk != NUL && match_file_list(p_bsk, (char_u *)sfname, (char_u *)ffname)) {
+ if (dobackup && *p_bsk != NUL && match_file_list(p_bsk, sfname, ffname)) {
dobackup = false;
}
@@ -2598,8 +2552,6 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
if ((bkc & BKC_YES) || append) { // "yes"
backup_copy = true;
} else if ((bkc & BKC_AUTO)) { // "auto"
- int i;
-
// Don't rename the file when:
// - it's a hard link
// - it's a symbolic link
@@ -2614,7 +2566,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
// First find a file name that doesn't exist yet (use some
// arbitrary numbers).
STRCPY(IObuff, fname);
- for (i = 4913;; i += 123) {
+ for (int i = 4913;; i += 123) {
char *tail = path_tail(IObuff);
size_t size = (size_t)(tail - IObuff);
snprintf(tail, IOSIZE - size, "%d", i);
@@ -2667,18 +2619,10 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
}
// make sure we have a valid backup extension to use
- if (*p_bex == NUL) {
- backup_ext = ".bak";
- } else {
- backup_ext = p_bex;
- }
+ char *backup_ext = *p_bex == NUL ? ".bak" : p_bex;
if (backup_copy) {
- char *wp;
int some_error = false;
- char *dirp;
- char *rootname;
- char *p;
// Try to make the backup in each directory in the 'bdir' option.
//
@@ -2690,11 +2634,11 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
//
// For these reasons, the existing writable file must be truncated
// and reused. Creation of a backup COPY will be attempted.
- dirp = p_bdir;
+ char *dirp = p_bdir;
while (*dirp) {
// Isolate one directory name, using an entry in 'bdir'.
size_t dir_len = copy_option_part(&dirp, IObuff, IOSIZE, ",");
- p = IObuff + dir_len;
+ char *p = IObuff + dir_len;
bool trailing_pathseps = after_pathsep(IObuff, p) && p[-1] == p[-2];
if (trailing_pathseps) {
IObuff[dir_len - 2] = NUL;
@@ -2717,7 +2661,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
}
}
- rootname = get_file_in_dir(fname, IObuff);
+ char *rootname = get_file_in_dir(fname, IObuff);
if (rootname == NULL) {
some_error = true; // out of memory
goto nobackup;
@@ -2753,7 +2697,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
// delete an existing one, and try to use another name instead.
// Change one character, just before the extension.
//
- wp = backup + strlen(backup) - 1 - strlen(backup_ext);
+ char *wp = backup + strlen(backup) - 1 - strlen(backup_ext);
if (wp < backup) { // empty file name ???
wp = backup;
}
@@ -2806,7 +2750,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
(double)file_info_old.stat.st_mtim.tv_sec);
#endif
#ifdef HAVE_ACL
- os_set_acl((char_u *)backup, acl);
+ os_set_acl(backup, acl);
#endif
SET_ERRMSG(NULL);
break;
@@ -2824,10 +2768,6 @@ nobackup:
}
SET_ERRMSG(NULL);
} else {
- char *dirp;
- char *p;
- char *rootname;
-
// Make a backup by renaming the original file.
// If 'cpoptions' includes the "W" flag, we don't want to
@@ -2841,11 +2781,11 @@ nobackup:
// Form the backup file name - change path/fo.o.h to
// path/fo.o.h.bak Try all directories in 'backupdir', first one
// that works is used.
- dirp = p_bdir;
+ char *dirp = p_bdir;
while (*dirp) {
// Isolate one directory name and make the backup file name.
size_t dir_len = copy_option_part(&dirp, IObuff, IOSIZE, ",");
- p = IObuff + dir_len;
+ char *p = IObuff + dir_len;
bool trailing_pathseps = after_pathsep(IObuff, p) && p[-1] == p[-2];
if (trailing_pathseps) {
IObuff[dir_len - 2] = NUL;
@@ -2869,7 +2809,7 @@ nobackup:
}
if (backup == NULL) {
- rootname = get_file_in_dir(fname, IObuff);
+ char *rootname = get_file_in_dir(fname, IObuff);
if (rootname == NULL) {
backup = NULL;
} else {
@@ -2980,7 +2920,7 @@ nobackup:
// Latin1 to Unicode conversion. This is handled in buf_write_bytes().
// Prepare the flags for it and allocate bw_conv_buf when needed.
if (converted) {
- wb_flags = get_fio_flags((char_u *)fenc);
+ wb_flags = get_fio_flags(fenc);
if (wb_flags & (FIO_UCS2 | FIO_UCS4 | FIO_UTF16 | FIO_UTF8)) {
// Need to allocate a buffer to translate into.
if (wb_flags & (FIO_UCS2 | FIO_UTF16 | FIO_UTF8)) {
@@ -2996,10 +2936,9 @@ nobackup:
}
if (converted && wb_flags == 0) {
-#ifdef HAVE_ICONV
// Use iconv() conversion when conversion is needed and it's not done
// internally.
- write_info.bw_iconv_fd = (iconv_t)my_iconv_open((char_u *)fenc, (char_u *)"utf-8");
+ write_info.bw_iconv_fd = (iconv_t)my_iconv_open(fenc, "utf-8");
if (write_info.bw_iconv_fd != (iconv_t)-1) {
// We're going to use iconv(), allocate a buffer to convert in.
write_info.bw_conv_buflen = (size_t)bufsize * ICONV_MULT;
@@ -3009,28 +2948,21 @@ nobackup:
}
write_info.bw_first = true;
} else {
-#endif
-
- // When the file needs to be converted with 'charconvert' after
- // writing, write to a temp file instead and let the conversion
- // overwrite the original file.
- if (*p_ccv != NUL) {
- wfname = vim_tempname();
- if (wfname == NULL) { // Can't write without a tempfile!
- SET_ERRMSG(_("E214: Can't find temp file for writing"));
- goto restore_backup;
+ // When the file needs to be converted with 'charconvert' after
+ // writing, write to a temp file instead and let the conversion
+ // overwrite the original file.
+ if (*p_ccv != NUL) {
+ wfname = vim_tempname();
+ if (wfname == NULL) { // Can't write without a tempfile!
+ SET_ERRMSG(_("E214: Can't find temp file for writing"));
+ goto restore_backup;
+ }
}
}
}
-#ifdef HAVE_ICONV
-}
-#endif
-
if (converted && wb_flags == 0
-#ifdef HAVE_ICONV
&& write_info.bw_iconv_fd == (iconv_t)-1
-#endif
&& wfname == fname) {
if (!forceit) {
SET_ERRMSG(_("E213: Cannot convert (add ! to write without conversion)"));
@@ -3151,7 +3083,7 @@ restore_backup:
}
SET_ERRMSG(NULL);
- write_info.bw_buf = (char_u *)buffer;
+ write_info.bw_buf = buffer;
nchars = 0;
// use "++bin", "++nobin" or 'binary'
@@ -3164,7 +3096,7 @@ restore_backup:
// Skip the BOM when appending and the file already existed, the BOM
// only makes sense at the start of the file.
if (buf->b_p_bomb && !write_bin && (!append || perm < 0)) {
- write_info.bw_len = make_bom((char_u *)buffer, (char_u *)fenc);
+ write_info.bw_len = make_bom((char_u *)buffer, fenc);
if (write_info.bw_len > 0) {
// don't convert
write_info.bw_flags = FIO_NOCONVERT | wb_flags;
@@ -3196,7 +3128,7 @@ restore_backup:
// Keep it fast!
ptr = ml_get_buf(buf, lnum, false) - 1;
if (write_undo_file) {
- sha256_update(&sha_ctx, (char_u *)ptr + 1, (uint32_t)(strlen(ptr + 1) + 1));
+ sha256_update(&sha_ctx, (uint8_t *)ptr + 1, (uint32_t)(strlen(ptr + 1) + 1));
}
while ((c = *++ptr) != NUL) {
if (c == NL) {
@@ -3342,7 +3274,7 @@ restore_backup:
// Probably need to set the ACL before changing the user (can't set the
// ACL on a file the user doesn't own).
if (!backup_copy) {
- os_set_acl((char_u *)wfname, acl);
+ os_set_acl(wfname, acl);
}
#endif
@@ -3551,12 +3483,10 @@ nofail:
}
xfree(fenc_tofree);
xfree(write_info.bw_conv_buf);
-#ifdef HAVE_ICONV
if (write_info.bw_iconv_fd != (iconv_t)-1) {
iconv_close(write_info.bw_iconv_fd);
write_info.bw_iconv_fd = (iconv_t)-1;
}
-#endif
#ifdef HAVE_ACL
os_free_acl(acl);
#endif
@@ -3605,10 +3535,10 @@ nofail:
// When writing the whole file and 'undofile' is set, also write the undo
// file.
if (retval == OK && write_undo_file) {
- char hash[UNDO_HASH_SIZE];
+ uint8_t hash[UNDO_HASH_SIZE];
- sha256_finish(&sha_ctx, (char_u *)hash);
- u_write_undo(NULL, false, buf, (char_u *)hash);
+ sha256_finish(&sha_ctx, hash);
+ u_write_undo(NULL, false, buf, hash);
}
if (!should_abort(retval)) {
@@ -3652,7 +3582,7 @@ nofail:
/// Set the name of the current buffer. Use when the buffer doesn't have a
/// name and a ":r" or ":w" command with a file name is used.
-static int set_rw_fname(char_u *fname, char_u *sfname)
+static int set_rw_fname(char *fname, char *sfname)
{
buf_T *buf = curbuf;
@@ -3670,7 +3600,7 @@ static int set_rw_fname(char_u *fname, char_u *sfname)
return FAIL;
}
- if (setfname(curbuf, (char *)fname, (char *)sfname, false) == OK) {
+ if (setfname(curbuf, fname, sfname, false) == OK) {
curbuf->b_flags |= BF_NOTEDITED;
}
@@ -3743,9 +3673,7 @@ static bool msg_add_fileformat(int eol_type)
/// Append line and character count to IObuff.
void msg_add_lines(int insert_space, long lnum, off_T nchars)
{
- char *p;
-
- p = IObuff + strlen(IObuff);
+ char *p = IObuff + strlen(IObuff);
if (insert_space) {
*p++ = ' ';
@@ -3801,7 +3729,7 @@ static bool time_differs(const FileInfo *file_info, long mtime, long mtime_ns) F
|| file_info->stat.st_mtim.tv_sec - mtime > 1
|| mtime - file_info->stat.st_mtim.tv_sec > 1;
#else
- || (long)file_info->stat.st_mtim.tv_sec != mtime;
+ || file_info->stat.st_mtim.tv_sec != mtime;
#endif
}
@@ -3811,48 +3739,37 @@ static bool time_differs(const FileInfo *file_info, long mtime, long mtime_ns) F
/// @return FAIL for failure, OK otherwise.
static int buf_write_bytes(struct bw_info *ip)
{
- int wlen;
- char_u *buf = ip->bw_buf; // data to write
- int len = ip->bw_len; // length of data
+ char *buf = ip->bw_buf; // data to write
+ int len = ip->bw_len; // length of data
#ifdef HAS_BW_FLAGS
- int flags = ip->bw_flags; // extra flags
+ int flags = ip->bw_flags; // extra flags
#endif
// Skip conversion when writing the BOM.
if (!(flags & FIO_NOCONVERT)) {
- char_u *p;
- unsigned c;
- int n;
-
if (flags & FIO_UTF8) {
// Convert latin1 in the buffer to UTF-8 in the file.
- p = ip->bw_conv_buf; // translate to buffer
- for (wlen = 0; wlen < len; wlen++) {
- p += utf_char2bytes(buf[wlen], (char *)p);
+ char *p = ip->bw_conv_buf; // translate to buffer
+ for (int wlen = 0; wlen < len; wlen++) {
+ p += utf_char2bytes((uint8_t)buf[wlen], p);
}
buf = ip->bw_conv_buf;
len = (int)(p - ip->bw_conv_buf);
} else if (flags & (FIO_UCS4 | FIO_UTF16 | FIO_UCS2 | FIO_LATIN1)) {
+ unsigned c;
+ int n = 0;
// Convert UTF-8 bytes in the buffer to UCS-2, UCS-4, UTF-16 or
// Latin1 chars in the file.
- if (flags & FIO_LATIN1) {
- p = buf; // translate in-place (can only get shorter)
- } else {
- p = ip->bw_conv_buf; // translate to buffer
- }
- for (wlen = 0; wlen < len; wlen += n) {
+ // translate in-place (can only get shorter) or to buffer
+ char *p = flags & FIO_LATIN1 ? buf : ip->bw_conv_buf;
+ for (int wlen = 0; wlen < len; wlen += n) {
if (wlen == 0 && ip->bw_restlen != 0) {
- int l;
-
// Use remainder of previous call. Append the start of
// buf[] to get a full sequence. Might still be too
// short!
- l = CONV_RESTLEN - ip->bw_restlen;
- if (l > len) {
- l = len;
- }
+ int l = MIN(len, CONV_RESTLEN - ip->bw_restlen);
memmove(ip->bw_rest + ip->bw_restlen, buf, (size_t)l);
- n = utf_ptr2len_len(ip->bw_rest, ip->bw_restlen + l);
+ n = utf_ptr2len_len((char *)ip->bw_rest, ip->bw_restlen + l);
if (n > ip->bw_restlen + len) {
// We have an incomplete byte sequence at the end to
// be written. We can't convert it without the
@@ -3892,9 +3809,9 @@ static int buf_write_bytes(struct bw_info *ip)
break;
}
if (n > 1) {
- c = (unsigned)utf_ptr2char((char *)buf + wlen);
+ c = (unsigned)utf_ptr2char(buf + wlen);
} else {
- c = buf[wlen];
+ c = (uint8_t)buf[wlen];
}
}
@@ -3914,32 +3831,28 @@ static int buf_write_bytes(struct bw_info *ip)
}
}
-#ifdef HAVE_ICONV
if (ip->bw_iconv_fd != (iconv_t)-1) {
const char *from;
size_t fromlen;
- char *to;
size_t tolen;
// Convert with iconv().
if (ip->bw_restlen > 0) {
- char *fp;
-
// Need to concatenate the remainder of the previous call and
// the bytes of the current call. Use the end of the
// conversion buffer for this.
fromlen = (size_t)len + (size_t)ip->bw_restlen;
- fp = (char *)ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
+ char *fp = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
memmove(fp, ip->bw_rest, (size_t)ip->bw_restlen);
memmove(fp + ip->bw_restlen, buf, (size_t)len);
from = fp;
tolen = ip->bw_conv_buflen - fromlen;
} else {
- from = (const char *)buf;
+ from = buf;
fromlen = (size_t)len;
tolen = ip->bw_conv_buflen;
}
- to = (char *)ip->bw_conv_buf;
+ char *to = ip->bw_conv_buf;
if (ip->bw_first) {
size_t save_len = tolen;
@@ -3950,7 +3863,7 @@ static int buf_write_bytes(struct bw_info *ip)
// There is a bug in iconv() on Linux (which appears to be
// wide-spread) which sets "to" to NULL and messes up "tolen".
if (to == NULL) {
- to = (char *)ip->bw_conv_buf;
+ to = ip->bw_conv_buf;
tolen = save_len;
}
ip->bw_first = false;
@@ -3971,16 +3884,15 @@ static int buf_write_bytes(struct bw_info *ip)
ip->bw_restlen = (int)fromlen;
buf = ip->bw_conv_buf;
- len = (int)((char_u *)to - ip->bw_conv_buf);
+ len = (int)(to - ip->bw_conv_buf);
}
-#endif
}
if (ip->bw_fd < 0) {
// Only checking conversion, which is OK if we get here.
return OK;
}
- wlen = (int)write_eintr(ip->bw_fd, buf, (size_t)len);
+ int wlen = (int)write_eintr(ip->bw_fd, buf, (size_t)len);
return (wlen < len) ? FAIL : OK;
}
@@ -3991,11 +3903,10 @@ static int buf_write_bytes(struct bw_info *ip)
/// @param flags FIO_ flags that specify which encoding to use
///
/// @return true for an error, false when it's OK.
-static bool ucs2bytes(unsigned c, char_u **pp, int flags) FUNC_ATTR_NONNULL_ALL
+static bool ucs2bytes(unsigned c, char **pp, int flags) FUNC_ATTR_NONNULL_ALL
{
- char_u *p = *pp;
+ char_u *p = (char_u *)(*pp);
bool error = false;
- int cc;
if (flags & FIO_UCS4) {
if (flags & FIO_ENDIAN_L) {
@@ -4018,7 +3929,7 @@ static bool ucs2bytes(unsigned c, char_u **pp, int flags) FUNC_ATTR_NONNULL_ALL
if (c >= 0x100000) {
error = true;
}
- cc = (int)(((c >> 10) & 0x3ff) + 0xd800);
+ int cc = (int)(((c >> 10) & 0x3ff) + 0xd800);
if (flags & FIO_ENDIAN_L) {
*p++ = (uint8_t)cc;
*p++ = (uint8_t)(cc >> 8);
@@ -4047,7 +3958,7 @@ static bool ucs2bytes(unsigned c, char_u **pp, int flags) FUNC_ATTR_NONNULL_ALL
}
}
- *pp = p;
+ *pp = (char *)p;
return error;
}
@@ -4061,7 +3972,6 @@ static bool need_conversion(const char *fenc)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
int same_encoding;
- int enc_flags;
int fenc_flags;
if (*fenc == NUL || strcmp(p_enc, fenc) == 0) {
@@ -4070,8 +3980,8 @@ static bool need_conversion(const char *fenc)
} else {
// Ignore difference between "ansi" and "latin1", "ucs-4" and
// "ucs-4be", etc.
- enc_flags = get_fio_flags((char_u *)p_enc);
- fenc_flags = get_fio_flags((char_u *)fenc);
+ int enc_flags = get_fio_flags(p_enc);
+ fenc_flags = get_fio_flags(fenc);
same_encoding = (enc_flags != 0 && fenc_flags == enc_flags);
}
if (same_encoding) {
@@ -4089,14 +3999,12 @@ static bool need_conversion(const char *fenc)
/// use 'encoding'.
///
/// @param name string to check for encoding
-static int get_fio_flags(const char_u *name)
+static int get_fio_flags(const char *name)
{
- int prop;
-
if (*name == NUL) {
- name = (char_u *)p_enc;
+ name = p_enc;
}
- prop = enc_canon_props((char *)name);
+ int prop = enc_canon_props(name);
if (prop & ENC_UNICODE) {
if (prop & ENC_2BYTE) {
if (prop & ENC_ENDIAN_L) {
@@ -4130,8 +4038,9 @@ static int get_fio_flags(const char_u *name)
///
/// @return the name of the encoding and set "*lenp" to the length or,
/// NULL when no BOM found.
-static char_u *check_for_bom(const char_u *p, long size, int *lenp, int flags)
+static char *check_for_bom(const char *p_in, long size, int *lenp, int flags)
{
+ const uint8_t *p = (const uint8_t *)p_in;
char *name = NULL;
int len = 2;
@@ -4167,18 +4076,15 @@ static char_u *check_for_bom(const char_u *p, long size, int *lenp, int flags)
}
*lenp = len;
- return (char_u *)name;
+ return name;
}
/// Generate a BOM in "buf[4]" for encoding "name".
///
/// @return the length of the BOM (zero when no BOM).
-static int make_bom(char_u *buf, char_u *name)
+static int make_bom(char_u *buf, char *name)
{
- int flags;
- char_u *p;
-
- flags = get_fio_flags(name);
+ int flags = get_fio_flags(name);
// Can't put a BOM in a non-Unicode file.
if (flags == FIO_LATIN1 || flags == 0) {
@@ -4191,9 +4097,9 @@ static int make_bom(char_u *buf, char_u *name)
buf[2] = 0xbf;
return 3;
}
- p = buf;
+ char *p = (char *)buf;
(void)ucs2bytes(0xfeff, &p, flags);
- return (int)(p - buf);
+ return (int)((char_u *)p - buf);
}
/// Shorten filename of a buffer.
@@ -4205,20 +4111,18 @@ static int make_bom(char_u *buf, char_u *name)
///
/// For buffers that have buftype "nofile" or "scratch": never change the file
/// name.
-void shorten_buf_fname(buf_T *buf, char_u *dirname, int force)
+void shorten_buf_fname(buf_T *buf, char *dirname, int force)
{
- char *p;
-
if (buf->b_fname != NULL
&& !bt_nofilename(buf)
&& !path_with_url(buf->b_fname)
&& (force
|| buf->b_sfname == NULL
- || path_is_absolute((char_u *)buf->b_sfname))) {
+ || path_is_absolute(buf->b_sfname))) {
if (buf->b_sfname != buf->b_ffname) {
XFREE_CLEAR(buf->b_sfname);
}
- p = path_shorten_fname(buf->b_ffname, (char *)dirname);
+ char *p = path_shorten_fname(buf->b_ffname, dirname);
if (p != NULL) {
buf->b_sfname = xstrdup(p);
buf->b_fname = buf->b_sfname;
@@ -4232,11 +4136,11 @@ void shorten_buf_fname(buf_T *buf, char_u *dirname, int force)
/// Shorten filenames for all buffers.
void shorten_fnames(int force)
{
- char_u dirname[MAXPATHL];
+ char dirname[MAXPATHL];
- os_dirname((char *)dirname, MAXPATHL);
+ os_dirname(dirname, MAXPATHL);
FOR_ALL_BUFFERS(buf) {
- shorten_buf_fname(buf, dirname, force);
+ shorten_buf_fname(buf, (char *)dirname, force);
// Always make the swap file name a full path, a "nofile" buffer may
// also have a swap file.
@@ -4515,10 +4419,7 @@ int vim_rename(const char *from, const char *to)
{
int fd_in;
int fd_out;
- int n;
char *errmsg = NULL;
- char *buffer;
- long perm;
#ifdef HAVE_ACL
vim_acl_T acl; // ACL from original file
#endif
@@ -4552,7 +4453,7 @@ int vim_rename(const char *from, const char *to)
}
if (use_tmp_file) {
- char_u tempname[MAXPATHL + 1];
+ char tempname[MAXPATHL + 1];
// Find a name that doesn't exist and is in the same directory.
// Rename "from" to "tempname" and then rename "tempname" to "to".
@@ -4560,18 +4461,18 @@ int vim_rename(const char *from, const char *to)
return -1;
}
STRCPY(tempname, from);
- for (n = 123; n < 99999; n++) {
- char *tail = path_tail((char *)tempname);
- snprintf(tail, (size_t)((MAXPATHL + 1) - (tail - (char *)tempname - 1)), "%d", n);
+ for (int n = 123; n < 99999; n++) {
+ char *tail = path_tail(tempname);
+ snprintf(tail, (size_t)((MAXPATHL + 1) - (tail - tempname - 1)), "%d", n);
- if (!os_path_exists((char *)tempname)) {
- if (os_rename((char_u *)from, tempname) == OK) {
- if (os_rename(tempname, (char_u *)to) == OK) {
+ if (!os_path_exists(tempname)) {
+ if (os_rename(from, tempname) == OK) {
+ if (os_rename(tempname, to) == OK) {
return 0;
}
// Strange, the second step failed. Try moving the
// file back and return failure.
- (void)os_rename(tempname, (char_u *)from);
+ (void)os_rename(tempname, from);
return -1;
}
// If it fails for one temp name it will most likely fail
@@ -4589,15 +4490,15 @@ int vim_rename(const char *from, const char *to)
os_remove((char *)to);
// First try a normal rename, return if it works.
- if (os_rename((char_u *)from, (char_u *)to) == OK) {
+ if (os_rename(from, to) == OK) {
return 0;
}
// Rename() failed, try copying the file.
- perm = os_getperm(from);
+ long perm = os_getperm(from);
#ifdef HAVE_ACL
// For systems that support ACL: get the ACL from the original file.
- acl = os_get_acl((char_u *)from);
+ acl = os_get_acl(from);
#endif
fd_in = os_open((char *)from, O_RDONLY, 0);
if (fd_in < 0) {
@@ -4620,7 +4521,7 @@ int vim_rename(const char *from, const char *to)
// Avoid xmalloc() here as vim_rename() is called by buf_write() when nvim
// is `preserve_exit()`ing.
- buffer = try_malloc(BUFSIZE);
+ char *buffer = try_malloc(BUFSIZE);
if (buffer == NULL) {
close(fd_out);
close(fd_in);
@@ -4630,6 +4531,7 @@ int vim_rename(const char *from, const char *to)
return -1;
}
+ int n;
while ((n = (int)read_eintr(fd_in, buffer, BUFSIZE)) > 0) {
if (write_eintr(fd_out, buffer, (size_t)n) != n) {
errmsg = _("E208: Error writing to \"%s\"");
@@ -4647,10 +4549,10 @@ int vim_rename(const char *from, const char *to)
to = from;
}
#ifndef UNIX // For Unix os_open() already set the permission.
- os_setperm((const char *)to, perm);
+ os_setperm(to, perm);
#endif
#ifdef HAVE_ACL
- os_set_acl((char_u *)to, acl);
+ os_set_acl(to, acl);
os_free_acl(acl);
#endif
if (errmsg != NULL) {
@@ -4673,8 +4575,6 @@ static int already_warned = false;
/// @return true if some message was written (screen should be redrawn and cursor positioned).
int check_timestamps(int focus)
{
- int didit = 0;
-
// Don't check timestamps while system() or another low-level function may
// cause us to lose and gain focus.
if (no_check_timestamps > 0) {
@@ -4689,6 +4589,8 @@ int check_timestamps(int focus)
return false;
}
+ int didit = 0;
+
if (!stuff_empty() || global_busy || !typebuf_typed()
|| autocmd_busy || curbuf->b_ro_locked > 0
|| allbuf_lock > 0) {
@@ -4732,13 +4634,11 @@ static int move_lines(buf_T *frombuf, buf_T *tobuf)
{
buf_T *tbuf = curbuf;
int retval = OK;
- linenr_T lnum;
- char *p;
// Copy the lines in "frombuf" to "tobuf".
curbuf = tobuf;
- for (lnum = 1; lnum <= frombuf->b_ml.ml_line_count; lnum++) {
- p = xstrdup(ml_get_buf(frombuf, lnum, false));
+ for (linenr_T lnum = 1; lnum <= frombuf->b_ml.ml_line_count; lnum++) {
+ char *p = xstrdup(ml_get_buf(frombuf, lnum, false));
if (ml_append(lnum - 1, p, 0, false) == FAIL) {
xfree(p);
retval = FAIL;
@@ -4750,7 +4650,7 @@ static int move_lines(buf_T *frombuf, buf_T *tobuf)
// Delete all the lines in "frombuf".
if (retval != FAIL) {
curbuf = frombuf;
- for (lnum = curbuf->b_ml.ml_line_count; lnum > 0; lnum--) {
+ for (linenr_T lnum = curbuf->b_ml.ml_line_count; lnum > 0; lnum--) {
if (ml_delete(lnum, false) == FAIL) {
// Oops! We could try putting back the saved lines, but that
// might fail again...
@@ -4774,7 +4674,6 @@ int buf_check_timestamp(buf_T *buf)
FUNC_ATTR_NONNULL_ALL
{
int retval = 0;
- char *path;
char *mesg = NULL;
char *mesg2 = "";
bool helpmesg = false;
@@ -4789,8 +4688,6 @@ int buf_check_timestamp(buf_T *buf)
uint64_t orig_size = buf->b_orig_size;
int orig_mode = buf->b_orig_mode;
static bool busy = false;
- char *s;
- char *reason;
bufref_T bufref;
set_bufref(&bufref, buf);
@@ -4838,6 +4735,7 @@ int buf_check_timestamp(buf_T *buf)
// was set, the global option value otherwise.
reload = RELOAD_NORMAL;
} else {
+ char *reason;
if (!file_info_ok) {
reason = "deleted";
} else if (bufIsChanged(buf)) {
@@ -4864,7 +4762,7 @@ int buf_check_timestamp(buf_T *buf)
if (!bufref_valid(&bufref)) {
emsg(_("E246: FileChangedShell autocommand deleted buffer"));
}
- s = get_vim_var_str(VV_FCS_CHOICE);
+ char *s = get_vim_var_str(VV_FCS_CHOICE);
if (strcmp(s, "reload") == 0 && *reason != 'd') {
reload = RELOAD_NORMAL;
} else if (strcmp(s, "edit") == 0) {
@@ -4917,7 +4815,7 @@ int buf_check_timestamp(buf_T *buf)
}
if (mesg != NULL) {
- path = home_replace_save(buf, buf->b_fname);
+ char *path = home_replace_save(buf, buf->b_fname);
if (!helpmesg) {
mesg2 = "";
}
@@ -5000,8 +4898,6 @@ int buf_check_timestamp(buf_T *buf)
void buf_reload(buf_T *buf, int orig_mode, bool reload_options)
{
exarg_T ea;
- pos_T old_cursor;
- linenr_T old_topline;
int old_ro = buf->b_p_ro;
buf_T *savebuf;
bufref_T bufref;
@@ -5021,8 +4917,8 @@ void buf_reload(buf_T *buf, int orig_mode, bool reload_options)
prep_exarg(&ea, buf);
}
- old_cursor = curwin->w_cursor;
- old_topline = curwin->w_topline;
+ pos_T old_cursor = curwin->w_cursor;
+ linenr_T old_topline = curwin->w_topline;
if (p_ur < 0 || curbuf->b_ml.ml_line_count <= p_ur) {
// Save all the text, so that the reload can be undone.
@@ -5156,11 +5052,11 @@ void write_lnum_adjust(linenr_T offset)
#if defined(BACKSLASH_IN_FILENAME)
/// Convert all backslashes in fname to forward slashes in-place,
/// unless when it looks like a URL.
-void forward_slash(char_u *fname)
+void forward_slash(char *fname)
{
- char_u *p;
+ char *p;
- if (path_with_url((const char *)fname)) {
+ if (path_with_url(fname)) {
return;
}
for (p = fname; *p != NUL; p++) {
@@ -5317,7 +5213,7 @@ int delete_recursive(const char *name)
garray_T ga;
if (readdir_core(&ga, exp, NULL, NULL) == OK) {
for (int i = 0; i < ga.ga_len; i++) {
- vim_snprintf(NameBuff, MAXPATHL, "%s/%s", exp, ((char_u **)ga.ga_data)[i]);
+ vim_snprintf(NameBuff, MAXPATHL, "%s/%s", exp, ((char **)ga.ga_data)[i]);
if (delete_recursive((const char *)NameBuff) != 0) {
// Remember the failure but continue deleting any further
// entries.
@@ -5505,28 +5401,22 @@ bool match_file_pat(char *pattern, regprog_T **prog, char *fname, char *sfname,
/// @param ffname full file name
///
/// @return true if there was a match
-bool match_file_list(char_u *list, char_u *sfname, char_u *ffname)
+bool match_file_list(char *list, char *sfname, char *ffname)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1, 3)
{
- char_u buf[100];
- char_u *tail;
- char_u *regpat;
- char allow_dirs;
- bool match;
- char *p;
-
- tail = (char_u *)path_tail((char *)sfname);
+ char *tail = path_tail(sfname);
// try all patterns in 'wildignore'
- p = (char *)list;
+ char *p = list;
while (*p) {
- copy_option_part(&p, (char *)buf, ARRAY_SIZE(buf), ",");
- regpat = (char_u *)file_pat_to_reg_pat((char *)buf, NULL, &allow_dirs, false);
+ char buf[100];
+ copy_option_part(&p, buf, ARRAY_SIZE(buf), ",");
+ char allow_dirs;
+ char *regpat = file_pat_to_reg_pat(buf, NULL, &allow_dirs, false);
if (regpat == NULL) {
break;
}
- match = match_file_pat((char *)regpat, NULL, (char *)ffname, (char *)sfname, (char *)tail,
- (int)allow_dirs);
+ bool match = match_file_pat(regpat, NULL, ffname, sfname, tail, (int)allow_dirs);
xfree(regpat);
if (match) {
return true;
@@ -5549,15 +5439,10 @@ bool match_file_list(char_u *list, char_u *sfname, char_u *ffname)
char *file_pat_to_reg_pat(const char *pat, const char *pat_end, char *allow_dirs, int no_bslash)
FUNC_ATTR_NONNULL_ARG(1)
{
- const char *endp;
- char *reg_pat;
- const char *p;
- int nested = 0;
- bool add_dollar = true;
-
if (allow_dirs != NULL) {
*allow_dirs = false;
}
+
if (pat_end == NULL) {
pat_end = pat + strlen(pat);
}
@@ -5568,7 +5453,7 @@ char *file_pat_to_reg_pat(const char *pat, const char *pat_end, char *allow_dirs
size_t size = 2; // '^' at start, '$' at end.
- for (p = pat; p < pat_end; p++) {
+ for (const char *p = pat; p < pat_end; p++) {
switch (*p) {
case '*':
case '.':
@@ -5589,7 +5474,7 @@ char *file_pat_to_reg_pat(const char *pat, const char *pat_end, char *allow_dirs
break;
}
}
- reg_pat = xmalloc(size + 1);
+ char *reg_pat = xmalloc(size + 1);
size_t i = 0;
@@ -5600,14 +5485,16 @@ char *file_pat_to_reg_pat(const char *pat, const char *pat_end, char *allow_dirs
} else {
reg_pat[i++] = '^';
}
- endp = pat_end - 1;
+ const char *endp = pat_end - 1;
+ bool add_dollar = true;
if (endp >= pat && *endp == '*') {
while (endp - pat > 0 && *endp == '*') {
endp--;
}
add_dollar = false;
}
- for (p = pat; *p && nested >= 0 && p <= endp; p++) {
+ int nested = 0;
+ for (const char *p = pat; *p && nested >= 0 && p <= endp; p++) {
switch (*p) {
case '*':
reg_pat[i++] = '.';
diff --git a/src/nvim/fold.c b/src/nvim/fold.c
index 6cb9e5c38d..7306131574 100644
--- a/src/nvim/fold.c
+++ b/src/nvim/fold.c
@@ -2873,7 +2873,7 @@ static void foldlevelIndent(fline_T *flp)
// empty line or lines starting with a character in 'foldignore': level
// depends on surrounding lines
- if (*s == NUL || vim_strchr(flp->wp->w_p_fdi, *s) != NULL) {
+ if (*s == NUL || vim_strchr(flp->wp->w_p_fdi, (uint8_t)(*s)) != NULL) {
// first and last line can't be undefined, use level 0
if (lnum == 1 || lnum == buf->b_ml.ml_line_count) {
flp->lvl = 0;
diff --git a/src/nvim/fold.h b/src/nvim/fold.h
index 9c3a34ab31..ac1e8c9419 100644
--- a/src/nvim/fold.h
+++ b/src/nvim/fold.h
@@ -20,8 +20,6 @@ typedef struct foldinfo {
linenr_T fi_lines;
} foldinfo_T;
-#define FOLDINFO_INIT { 0, 0, 0, 0 }
-
EXTERN int disable_fold_update INIT(= 0);
#ifdef INCLUDE_GENERATED_DECLARATIONS
diff --git a/src/nvim/garray.c b/src/nvim/garray.c
index 0f11868031..aa9a44d410 100644
--- a/src/nvim/garray.c
+++ b/src/nvim/garray.c
@@ -173,9 +173,9 @@ char *ga_concat_strings_sep(const garray_T *gap, const char *sep)
/// @param gap
///
/// @returns the concatenated strings
-char_u *ga_concat_strings(const garray_T *gap) FUNC_ATTR_NONNULL_RET
+char *ga_concat_strings(const garray_T *gap) FUNC_ATTR_NONNULL_RET
{
- return (char_u *)ga_concat_strings_sep(gap, ",");
+ return ga_concat_strings_sep(gap, ",");
}
/// Concatenate a string to a growarray which contains characters.
@@ -216,7 +216,7 @@ void ga_concat_len(garray_T *const gap, const char *restrict s, const size_t len
///
/// @param gap
/// @param c
-void ga_append(garray_T *gap, char c)
+void ga_append(garray_T *gap, uint8_t c)
{
- GA_APPEND(char, gap, c);
+ GA_APPEND(uint8_t, gap, c);
}
diff --git a/src/nvim/garray.h b/src/nvim/garray.h
index 3e2650b410..1623c4db7b 100644
--- a/src/nvim/garray.h
+++ b/src/nvim/garray.h
@@ -27,7 +27,8 @@ typedef struct growarray {
#define GA_APPEND(item_type, gap, item) \
do { \
ga_grow(gap, 1); \
- ((item_type *)(gap)->ga_data)[(gap)->ga_len++] = (item); \
+ ((item_type *)(gap)->ga_data)[(gap)->ga_len] = (item); \
+ (gap)->ga_len++; \
} while (0)
#define GA_APPEND_VIA_PTR(item_type, gap) \
diff --git a/src/nvim/generators/gen_api_dispatch.lua b/src/nvim/generators/gen_api_dispatch.lua
index 96c9b21b8f..35f6bf8455 100644
--- a/src/nvim/generators/gen_api_dispatch.lua
+++ b/src/nvim/generators/gen_api_dispatch.lua
@@ -426,7 +426,9 @@ for _,fn in ipairs(functions) do
end
remote_fns.redraw = {impl_name="ui_client_redraw", fast=true}
-local hashorder, hashfun = hashy.hashy_hash("msgpack_rpc_get_handler_for", vim.tbl_keys(remote_fns), function (idx)
+local names = vim.tbl_keys(remote_fns)
+table.sort(names)
+local hashorder, hashfun = hashy.hashy_hash("msgpack_rpc_get_handler_for", names, function (idx)
return "method_handlers["..idx.."].name"
end)
diff --git a/src/nvim/generators/gen_eval.lua b/src/nvim/generators/gen_eval.lua
index a50e058e00..baed6a74c2 100644
--- a/src/nvim/generators/gen_eval.lua
+++ b/src/nvim/generators/gen_eval.lua
@@ -73,14 +73,13 @@ for _,fun in ipairs(metadata) do
end
end
+local func_names = vim.tbl_keys(funcs)
+table.sort(func_names)
local funcsdata = io.open(funcs_file, 'w')
-funcsdata:write(mpack.pack(funcs))
+funcsdata:write(mpack.pack(func_names))
funcsdata:close()
-
-local names = vim.tbl_keys(funcs)
-
-local neworder, hashfun = hashy.hashy_hash("find_internal_func", names, function (idx)
+local neworder, hashfun = hashy.hashy_hash("find_internal_func", func_names, function (idx)
return "functions["..idx.."].name"
end)
hashpipe:write("static const EvalFuncDef functions[] = {\n")
diff --git a/src/nvim/generators/gen_events.lua b/src/nvim/generators/gen_events.lua
index 6ee45a14af..8db7f22452 100644
--- a/src/nvim/generators/gen_events.lua
+++ b/src/nvim/generators/gen_events.lua
@@ -32,7 +32,9 @@ for i, event in ipairs(events) do
end
end
-for alias, event in pairs(aliases) do
+for _, v in ipairs(aliases) do
+ local alias = v[1]
+ local event = v[2]
names_tgt:write(('\n {%u, "%s", EVENT_%s},'):format(#alias, alias, event:upper()))
end
diff --git a/src/nvim/generators/gen_keysets.lua b/src/nvim/generators/gen_keysets.lua
index 633c5da184..b1c1f3e2d8 100644
--- a/src/nvim/generators/gen_keysets.lua
+++ b/src/nvim/generators/gen_keysets.lua
@@ -1,4 +1,3 @@
-
local nvimsrcdir = arg[1]
local shared_file = arg[2]
local funcs_file = arg[3]
@@ -38,7 +37,9 @@ local function sanitize(key)
return key
end
-for name, keys in pairs(keysets) do
+for _, v in ipairs(keysets) do
+ local name = v[1]
+ local keys = v[2]
local neworder, hashfun = hashy.hashy_hash(name, keys, function (idx)
return name.."_table["..idx.."].str"
end)
diff --git a/src/nvim/generators/gen_options.lua b/src/nvim/generators/gen_options.lua
index af21d44eaf..edb7dae159 100644
--- a/src/nvim/generators/gen_options.lua
+++ b/src/nvim/generators/gen_options.lua
@@ -159,7 +159,7 @@ local dump_option = function(i, o)
if #o.scope == 2 then
pv_name = 'OPT_BOTH(' .. pv_name .. ')'
end
- defines['PV_' .. varname:sub(3):upper()] = pv_name
+ table.insert(defines, { 'PV_' .. varname:sub(3):upper() , pv_name})
w(' .indir=' .. pv_name)
end
if o.enable_if then
@@ -192,7 +192,7 @@ w(' [' .. ('%u'):format(#options.options) .. ']={.fullname=NULL}')
w('};')
w('')
-for k, v in pairs(defines) do
- w('#define ' .. k .. ' ' .. v)
+for _, v in ipairs(defines) do
+ w('#define ' .. v[1] .. ' ' .. v[2])
end
opt_fd:close()
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index b9e3b6b902..8ed9381bca 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -151,11 +151,11 @@ void free_buff(buffheader_T *buf)
/// K_SPECIAL in the returned string is escaped.
///
/// @param dozero count == zero is not an error
-static char_u *get_buffcont(buffheader_T *buffer, int dozero)
+static char *get_buffcont(buffheader_T *buffer, int dozero)
{
size_t count = 0;
- char_u *p = NULL;
- char_u *p2;
+ char *p = NULL;
+ char *p2;
// compute the total length of the string
for (const buffblock_T *bp = buffer->bh_first.b_next;
@@ -168,7 +168,7 @@ static char_u *get_buffcont(buffheader_T *buffer, int dozero)
p2 = p;
for (const buffblock_T *bp = buffer->bh_first.b_next;
bp != NULL; bp = bp->b_next) {
- for (const char_u *str = (char_u *)bp->b_str; *str;) {
+ for (const char *str = bp->b_str; *str;) {
*p2++ = *str++;
}
}
@@ -185,7 +185,7 @@ char_u *get_recorded(void)
char *p;
size_t len;
- p = (char *)get_buffcont(&recordbuff, true);
+ p = get_buffcont(&recordbuff, true);
free_buff(&recordbuff);
// Remove the characters that were added the last time, these must be the
@@ -207,7 +207,7 @@ char_u *get_recorded(void)
/// Return the contents of the redo buffer as a single string.
/// K_SPECIAL in the returned string is escaped.
-char_u *get_inserted(void)
+char *get_inserted(void)
{
return get_buffcont(&redobuff, false);
}
@@ -252,7 +252,7 @@ static void add_buff(buffheader_T *const buf, const char *const s, ptrdiff_t sle
} else {
len = (size_t)slen;
}
- buffblock_T *p = xmalloc(sizeof(buffblock_T) + len);
+ buffblock_T *p = xmalloc(offsetof(buffblock_T, b_str) + len + 1);
buf->bh_space = len - (size_t)slen;
xstrlcpy(p->b_str, s, (size_t)slen + 1);
@@ -475,7 +475,7 @@ void saveRedobuff(save_redo_T *save_redo)
old_redobuff.bh_first.b_next = NULL;
// Make a copy, so that ":normal ." in a function works.
- char *const s = (char *)get_buffcont(&save_redo->sr_redobuff, false);
+ char *const s = get_buffcont(&save_redo->sr_redobuff, false);
if (s == NULL) {
return;
}
@@ -538,7 +538,7 @@ void AppendToRedobuffLit(const char *str, int len)
// Handle a special or multibyte character.
// Composing chars separately are handled separately.
- const int c = mb_cptr2char_adv((const char_u **)&s);
+ const int c = mb_cptr2char_adv(&s);
if (c < ' ' || c == DEL || (*s == NUL && (c == '0' || c == '^'))) {
add_char_buff(&redobuff, Ctrl_V);
}
@@ -599,7 +599,7 @@ void stuffReadbuffSpec(const char *s)
stuffReadbuffLen(s, 3);
s += 3;
} else {
- int c = mb_cptr2char_adv((const char_u **)&s);
+ int c = mb_cptr2char_adv(&s);
if (c == CAR || c == NL || c == ESC) {
c = ' ';
}
@@ -640,7 +640,7 @@ void stuffescaped(const char *arg, bool literally)
// stuff a single special character
if (*arg != NUL) {
- const int c = mb_cptr2char_adv((const char_u **)&arg);
+ const int c = mb_cptr2char_adv(&arg);
if (literally && ((c < ' ' && c != TAB) || c == DEL)) {
stuffcharReadbuff(Ctrl_V);
}
@@ -886,7 +886,7 @@ int ins_typebuf(char *str, int noremap, int offset, bool nottyped, bool silent)
// often.
int newoff = MAXMAPLEN + 4;
int extra = addlen + newoff + 4 * (MAXMAPLEN + 4);
- if (typebuf.tb_len > 2147483674 - extra) {
+ if (typebuf.tb_len > INT_MAX - extra) {
// string is getting too long for 32 bit int
emsg(_(e_toocompl)); // also calls flush_buffers
setcursor();
@@ -2526,10 +2526,12 @@ static int vgetorpeek(bool advance)
// move cursor left, if possible
if (curwin->w_cursor.col != 0) {
if (curwin->w_wcol > 0) {
- if (did_ai) {
- // We are expecting to truncate the trailing
- // white-space, so find the last non-white
- // character -- webb
+ // After auto-indenting and no text is following,
+ // we are expecting to truncate the trailing
+ // white-space, so find the last non-white
+ // character -- webb
+ if (did_ai
+ && *skipwhite(get_cursor_line_ptr() + curwin->w_cursor.col) == NUL) {
curwin->w_wcol = 0;
ptr = (char_u *)get_cursor_line_ptr();
chartabsize_T cts;
@@ -2993,16 +2995,16 @@ char *getcmdkeycmd(int promptc, void *cookie, int indent, bool do_concat)
ga_concat(&line_ga, "<SNR>");
} else {
if (cmod != 0) {
- ga_append(&line_ga, (char)K_SPECIAL);
- ga_append(&line_ga, (char)KS_MODIFIER);
- ga_append(&line_ga, (char)cmod);
+ ga_append(&line_ga, K_SPECIAL);
+ ga_append(&line_ga, KS_MODIFIER);
+ ga_append(&line_ga, (uint8_t)cmod);
}
if (IS_SPECIAL(c1)) {
- ga_append(&line_ga, (char)K_SPECIAL);
- ga_append(&line_ga, (char)K_SECOND(c1));
- ga_append(&line_ga, (char)K_THIRD(c1));
+ ga_append(&line_ga, K_SPECIAL);
+ ga_append(&line_ga, (uint8_t)K_SECOND(c1));
+ ga_append(&line_ga, (uint8_t)K_THIRD(c1));
} else {
- ga_append(&line_ga, (char)c1);
+ ga_append(&line_ga, (uint8_t)c1);
}
}
@@ -3038,7 +3040,7 @@ bool map_execute_lua(void)
} else if (c1 == '\r' || c1 == '\n') {
c1 = NUL; // end the line
} else {
- ga_append(&line_ga, (char)c1);
+ ga_append(&line_ga, (uint8_t)c1);
}
}
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index aa8dbf6331..df4ae05522 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -494,6 +494,9 @@ EXTERN int v_dying INIT(= 0);
EXTERN bool stdin_isatty INIT(= true);
// is stdout a terminal?
EXTERN bool stdout_isatty INIT(= true);
+// is stderr a terminal?
+EXTERN bool stderr_isatty INIT(= true);
+
/// filedesc set by embedder for reading first buffer like `cmd | nvim -`
EXTERN int stdin_fd INIT(= -1);
@@ -771,7 +774,7 @@ EXTERN bool g_tag_at_cursor INIT(= false); // whether the tag command comes
EXTERN int replace_offset INIT(= 0); // offset for replace_push()
-EXTERN char_u *escape_chars INIT(= (char_u *)" \t\\\"|"); // need backslash in cmd line
+EXTERN char *escape_chars INIT(= " \t\\\"|"); // need backslash in cmd line
EXTERN int keep_help_flag INIT(= false); // doing :ta from help file
@@ -803,8 +806,8 @@ enum {
extern char *default_vim_dir;
extern char *default_vimruntime_dir;
extern char *default_lib_dir;
-extern char_u *compiled_user;
-extern char_u *compiled_sys;
+extern char *compiled_user;
+extern char *compiled_sys;
#endif
// When a window has a local directory, the absolute path of the global
@@ -822,7 +825,7 @@ EXTERN int cmdwin_type INIT(= 0); ///< type of cmdline window or 0
EXTERN int cmdwin_result INIT(= 0); ///< result of cmdline window or 0
EXTERN int cmdwin_level INIT(= 0); ///< cmdline recursion level
-EXTERN char_u no_lines_msg[] INIT(= N_("--No lines in buffer--"));
+EXTERN char no_lines_msg[] INIT(= N_("--No lines in buffer--"));
// When ":global" is used to number of substitutions and changed lines is
// accumulated until it's finished.
@@ -999,7 +1002,6 @@ EXTERN char e_fnametoolong[] INIT(= N_("E856: Filename too long"));
EXTERN char e_float_as_string[] INIT(= N_("E806: using Float as a String"));
EXTERN char e_cannot_edit_other_buf[] INIT(= N_("E788: Not allowed to edit another buffer now"));
-EXTERN char e_autocmd_err[] INIT(= N_("E5500: autocmd has thrown an exception: %s"));
EXTERN char e_cmdmap_err[] INIT(= N_("E5520: <Cmd> mapping must end with <CR>"));
EXTERN char e_cmdmap_repeated[]
INIT(= N_("E5521: <Cmd> mapping must end with <CR> before second <Cmd>"));
diff --git a/src/nvim/grid.c b/src/nvim/grid.c
index 4702e224c6..46f8a59710 100644
--- a/src/nvim/grid.c
+++ b/src/nvim/grid.c
@@ -142,16 +142,16 @@ void grid_putchar(ScreenGrid *grid, int c, int row, int col, int attr)
/// Also return its attribute in *attrp;
void grid_getbytes(ScreenGrid *grid, int row, int col, char *bytes, int *attrp)
{
- size_t off;
-
grid_adjust(&grid, &row, &col);
// safety check
- if (grid->chars != NULL && row < grid->rows && col < grid->cols) {
- off = grid->line_offset[row] + (size_t)col;
- *attrp = grid->attrs[off];
- schar_copy(bytes, grid->chars[off]);
+ if (grid->chars == NULL || row >= grid->rows || col >= grid->cols) {
+ return;
}
+
+ size_t off = grid->line_offset[row] + (size_t)col;
+ *attrp = grid->attrs[off];
+ schar_copy(bytes, grid->chars[off]);
}
/// put string '*text' on the window grid at position 'row' and 'col', with
diff --git a/src/nvim/hashtab.c b/src/nvim/hashtab.c
index 042cb43ce4..851e70caca 100644
--- a/src/nvim/hashtab.c
+++ b/src/nvim/hashtab.c
@@ -30,6 +30,7 @@
#include "nvim/hashtab.h"
#include "nvim/memory.h"
#include "nvim/message.h"
+#include "nvim/types.h"
#include "nvim/vim.h"
// Magic value for algorithm that walks through the array.
@@ -87,7 +88,7 @@ void hash_clear_all(hashtab_T *ht, unsigned int off)
/// is changed in any way.
hashitem_T *hash_find(const hashtab_T *const ht, const char *const key)
{
- return hash_lookup(ht, key, strlen(key), hash_hash((char_u *)key));
+ return hash_lookup(ht, key, strlen(key), hash_hash(key));
}
/// Like hash_find, but key is not NUL-terminated
@@ -203,13 +204,13 @@ void hash_debug_results(void)
/// FAIL if key already present
int hash_add(hashtab_T *ht, char *key)
{
- hash_T hash = hash_hash((char_u *)key);
+ hash_T hash = hash_hash(key);
hashitem_T *hi = hash_lookup(ht, key, strlen(key), hash);
if (!HASHITEM_EMPTY(hi)) {
internal_error("hash_add()");
return FAIL;
}
- hash_add_item(ht, hi, (char_u *)key, hash);
+ hash_add_item(ht, hi, key, hash);
return OK;
}
@@ -220,14 +221,14 @@ int hash_add(hashtab_T *ht, char *key)
/// @param key Pointer to the key for the new item. The key has to be contained
/// in the new item (@see hashitem_T). Must not be NULL.
/// @param hash The precomputed hash value for the key.
-void hash_add_item(hashtab_T *ht, hashitem_T *hi, char_u *key, hash_T hash)
+void hash_add_item(hashtab_T *ht, hashitem_T *hi, char *key, hash_T hash)
{
ht->ht_used++;
ht->ht_changed++;
if (hi->hi_key == NULL) {
ht->ht_filled++;
}
- hi->hi_key = (char *)key;
+ hi->hi_key = key;
hi->hi_hash = hash;
// When the space gets low may resize the array.
@@ -405,9 +406,9 @@ static void hash_may_resize(hashtab_T *ht, size_t minitems)
/// run a script that uses hashtables a lot. Vim will then print statistics
/// when exiting. Try that with the current hash algorithm and yours. The
/// lower the percentage the better.
-hash_T hash_hash(const char_u *key)
+hash_T hash_hash(const char *key)
{
- hash_T hash = *key;
+ hash_T hash = (uint8_t)(*key);
if (hash == 0) {
return (hash_T)0;
@@ -415,7 +416,7 @@ hash_T hash_hash(const char_u *key)
// A simplistic algorithm that appears to do very well.
// Suggested by George Reilly.
- const uint8_t *p = key + 1;
+ const uint8_t *p = (uint8_t *)key + 1;
while (*p != NUL) {
HASH_CYCLE_BODY(hash, p);
}
diff --git a/src/nvim/help.c b/src/nvim/help.c
index 0a695a0aa7..bbc552fa4c 100644
--- a/src/nvim/help.c
+++ b/src/nvim/help.c
@@ -412,7 +412,7 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep
// And also "\_$" and "\_^".
if (arg[0] == '\\'
&& ((arg[1] != NUL && arg[2] == NUL)
- || (vim_strchr("%_z@", arg[1]) != NULL
+ || (vim_strchr("%_z@", (uint8_t)arg[1]) != NULL
&& arg[2] != NUL))) {
vim_snprintf(d, IOSIZE, "/\\\\%s", arg + 1);
// Check for "/\\_$", should be "/\\_\$"
@@ -471,7 +471,7 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep
// Insert '-' before and after "CTRL-X" when applicable.
if (*s < ' '
|| (*s == '^' && s[1]
- && (ASCII_ISALPHA(s[1]) || vim_strchr("?@[\\]^", s[1]) != NULL))) {
+ && (ASCII_ISALPHA(s[1]) || vim_strchr("?@[\\]^", (uint8_t)s[1]) != NULL))) {
if (d > IObuff && d[-1] != '_' && d[-1] != '\\') {
*d++ = '_'; // prepend a '_' to make x_CTRL-x
}
@@ -555,7 +555,7 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep
// Sort the matches found on the heuristic number that is after the
// tag name.
qsort((void *)(*matches), (size_t)(*num_matches),
- sizeof(char_u *), help_compare);
+ sizeof(char *), help_compare);
// Delete more than TAG_MANY to reduce the size of the listing.
while (*num_matches > TAG_MANY) {
xfree((*matches)[--*num_matches]);
@@ -799,7 +799,7 @@ void fix_help_buffer(void)
// The text is utf-8 when a byte
// above 127 is found and no
// illegal byte sequence is found.
- if ((char_u)(*s) >= 0x80 && this_utf != kFalse) {
+ if ((uint8_t)(*s) >= 0x80 && this_utf != kFalse) {
this_utf = kTrue;
const int l = utf_ptr2len(s);
if (l == 1) {
@@ -923,7 +923,7 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool
// If using the "++t" argument or generating tags for "$VIMRUNTIME/doc"
// add the "help-tags" tag.
- ga_init(&ga, (int)sizeof(char_u *), 100);
+ ga_init(&ga, (int)sizeof(char *), 100);
if (add_help_tags
|| path_full_compare("$VIMRUNTIME/doc", dir, false, true) == kEqualFiles) {
size_t s_len = 18 + strlen(tagfname);
@@ -948,7 +948,7 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool
// Detect utf-8 file by a non-ASCII char in the first line.
TriState this_utf8 = kNone;
for (s = IObuff; *s != NUL; s++) {
- if ((char_u)(*s) >= 0x80) {
+ if ((uint8_t)(*s) >= 0x80) {
this_utf8 = kTrue;
const int l = utf_ptr2len(s);
if (l == 1) {
@@ -974,12 +974,12 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool
}
if (in_example) {
// skip over example; a non-white in the first column ends it
- if (vim_strchr(" \t\n\r", IObuff[0])) {
+ if (vim_strchr(" \t\n\r", (uint8_t)IObuff[0])) {
continue;
}
in_example = false;
}
- p1 = vim_strchr((char *)IObuff, '*'); // find first '*'
+ p1 = vim_strchr(IObuff, '*'); // find first '*'
while (p1 != NULL) {
p2 = strchr((const char *)p1 + 1, '*'); // Find second '*'.
if (p2 != NULL && p2 > p1 + 1) { // Skip "*" and "**".
@@ -994,7 +994,7 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool
// followed by a white character or end-of-line.
if (s == p2
&& (p1 == IObuff || p1[-1] == ' ' || p1[-1] == '\t')
- && (vim_strchr(" \t\n\r", s[1]) != NULL
+ && (vim_strchr(" \t\n\r", (uint8_t)s[1]) != NULL
|| s[1] == '\0')) {
*p2 = '\0';
p1++;
diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c
index c3a259c87d..c20eac3c28 100644
--- a/src/nvim/highlight.c
+++ b/src/nvim/highlight.c
@@ -649,7 +649,7 @@ int hl_blend_attrs(int back_attr, int front_attr, bool *through)
cattrs = battrs;
cattrs.rgb_fg_color = rgb_blend(ratio, battrs.rgb_fg_color,
fattrs.rgb_bg_color);
- if (cattrs.rgb_ae_attr & (HL_ANY_UNDERLINE)) {
+ if (cattrs.rgb_ae_attr & (HL_UNDERLINE_MASK)) {
cattrs.rgb_sp_color = rgb_blend(ratio, battrs.rgb_sp_color,
fattrs.rgb_bg_color);
} else {
@@ -667,7 +667,7 @@ int hl_blend_attrs(int back_attr, int front_attr, bool *through)
}
cattrs.rgb_fg_color = rgb_blend(ratio/2, battrs.rgb_fg_color,
fattrs.rgb_fg_color);
- if (cattrs.rgb_ae_attr & (HL_ANY_UNDERLINE)) {
+ if (cattrs.rgb_ae_attr & (HL_UNDERLINE_MASK)) {
cattrs.rgb_sp_color = rgb_blend(ratio/2, battrs.rgb_bg_color,
fattrs.rgb_sp_color);
} else {
@@ -825,46 +825,52 @@ void hlattrs2dict(Dictionary *dict, HlAttrs ae, bool use_rgb)
Dictionary hl = *dict;
int mask = use_rgb ? ae.rgb_ae_attr : ae.cterm_ae_attr;
+ if (mask & HL_INVERSE) {
+ PUT_C(hl, "reverse", BOOLEAN_OBJ(true));
+ }
+
if (mask & HL_BOLD) {
PUT_C(hl, "bold", BOOLEAN_OBJ(true));
}
- if (mask & HL_STANDOUT) {
- PUT_C(hl, "standout", BOOLEAN_OBJ(true));
+ if (mask & HL_ITALIC) {
+ PUT_C(hl, "italic", BOOLEAN_OBJ(true));
}
- if (mask & HL_UNDERLINE) {
+ switch (mask & HL_UNDERLINE_MASK) {
+ case HL_UNDERLINE:
PUT_C(hl, "underline", BOOLEAN_OBJ(true));
- }
+ break;
- if (mask & HL_UNDERCURL) {
+ case HL_UNDERCURL:
PUT_C(hl, "undercurl", BOOLEAN_OBJ(true));
- }
+ break;
- if (mask & HL_UNDERDOUBLE) {
+ case HL_UNDERDOUBLE:
PUT_C(hl, "underdouble", BOOLEAN_OBJ(true));
- }
+ break;
- if (mask & HL_UNDERDOTTED) {
+ case HL_UNDERDOTTED:
PUT_C(hl, "underdotted", BOOLEAN_OBJ(true));
- }
+ break;
- if (mask & HL_UNDERDASHED) {
+ case HL_UNDERDASHED:
PUT_C(hl, "underdashed", BOOLEAN_OBJ(true));
+ break;
}
- if (mask & HL_ITALIC) {
- PUT_C(hl, "italic", BOOLEAN_OBJ(true));
- }
-
- if (mask & HL_INVERSE) {
- PUT_C(hl, "reverse", BOOLEAN_OBJ(true));
+ if (mask & HL_STANDOUT) {
+ PUT_C(hl, "standout", BOOLEAN_OBJ(true));
}
if (mask & HL_STRIKETHROUGH) {
PUT_C(hl, "strikethrough", BOOLEAN_OBJ(true));
}
+ if (mask & HL_ALTFONT) {
+ PUT_C(hl, "altfont", BOOLEAN_OBJ(true));
+ }
+
if (mask & HL_NOCOMBINE) {
PUT_C(hl, "nocombine", BOOLEAN_OBJ(true));
}
@@ -920,16 +926,17 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e
m = m | flag; \
}
+ CHECK_FLAG(dict, mask, reverse, , HL_INVERSE);
CHECK_FLAG(dict, mask, bold, , HL_BOLD);
- CHECK_FLAG(dict, mask, standout, , HL_STANDOUT);
+ CHECK_FLAG(dict, mask, italic, , HL_ITALIC);
CHECK_FLAG(dict, mask, underline, , HL_UNDERLINE);
CHECK_FLAG(dict, mask, undercurl, , HL_UNDERCURL);
CHECK_FLAG(dict, mask, underdouble, , HL_UNDERDOUBLE);
CHECK_FLAG(dict, mask, underdotted, , HL_UNDERDOTTED);
CHECK_FLAG(dict, mask, underdashed, , HL_UNDERDASHED);
- CHECK_FLAG(dict, mask, italic, , HL_ITALIC);
- CHECK_FLAG(dict, mask, reverse, , HL_INVERSE);
+ CHECK_FLAG(dict, mask, standout, , HL_STANDOUT);
CHECK_FLAG(dict, mask, strikethrough, , HL_STRIKETHROUGH);
+ CHECK_FLAG(dict, mask, altfont, , HL_ALTFONT);
if (use_rgb) {
CHECK_FLAG(dict, mask, fg_indexed, , HL_FG_INDEXED);
CHECK_FLAG(dict, mask, bg_indexed, , HL_BG_INDEXED);
@@ -1005,13 +1012,14 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e
}
cterm_mask_provided = true;
+ CHECK_FLAG(cterm, cterm_mask, reverse, , HL_INVERSE);
CHECK_FLAG(cterm, cterm_mask, bold, , HL_BOLD);
- CHECK_FLAG(cterm, cterm_mask, standout, , HL_STANDOUT);
+ CHECK_FLAG(cterm, cterm_mask, italic, , HL_ITALIC);
CHECK_FLAG(cterm, cterm_mask, underline, , HL_UNDERLINE);
CHECK_FLAG(cterm, cterm_mask, undercurl, , HL_UNDERCURL);
- CHECK_FLAG(cterm, cterm_mask, italic, , HL_ITALIC);
- CHECK_FLAG(cterm, cterm_mask, reverse, , HL_INVERSE);
+ CHECK_FLAG(cterm, cterm_mask, standout, , HL_STANDOUT);
CHECK_FLAG(cterm, cterm_mask, strikethrough, , HL_STRIKETHROUGH);
+ CHECK_FLAG(cterm, cterm_mask, altfont, , HL_ALTFONT);
CHECK_FLAG(cterm, cterm_mask, nocombine, , HL_NOCOMBINE);
} else if (dict->cterm.type == kObjectTypeArray && dict->cterm.data.array.size == 0) {
// empty list from Lua API should clear all cterm attributes
diff --git a/src/nvim/highlight_defs.h b/src/nvim/highlight_defs.h
index 2557a248c3..95c81ac9db 100644
--- a/src/nvim/highlight_defs.h
+++ b/src/nvim/highlight_defs.h
@@ -15,19 +15,23 @@ typedef enum {
HL_INVERSE = 0x01,
HL_BOLD = 0x02,
HL_ITALIC = 0x04,
+ // The next three bits are all underline styles
+ HL_UNDERLINE_MASK = 0x38,
HL_UNDERLINE = 0x08,
HL_UNDERCURL = 0x10,
- HL_UNDERDOUBLE = 0x20,
- HL_UNDERDOTTED = 0x40,
- HL_UNDERDASHED = 0x80,
- HL_STANDOUT = 0x0100,
- HL_NOCOMBINE = 0x0200,
- HL_STRIKETHROUGH = 0x0400,
+ HL_UNDERDOUBLE = 0x18,
+ HL_UNDERDOTTED = 0x20,
+ HL_UNDERDASHED = 0x28,
+ // 0x30 and 0x38 spare for underline styles
+ HL_STANDOUT = 0x0040,
+ HL_STRIKETHROUGH = 0x0080,
+ HL_ALTFONT = 0x0100,
+ // 0x0200 spare
+ HL_NOCOMBINE = 0x0400,
HL_BG_INDEXED = 0x0800,
HL_FG_INDEXED = 0x1000,
HL_DEFAULT = 0x2000,
HL_GLOBAL = 0x4000,
- HL_ANY_UNDERLINE = HL_UNDERLINE | HL_UNDERDOUBLE | HL_UNDERCURL | HL_UNDERDOTTED | HL_UNDERDASHED,
} HlAttrFlags;
/// Stores a complete highlighting entry, including colors and attributes
diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c
index 404835c4a9..3d91335f55 100644
--- a/src/nvim/highlight_group.c
+++ b/src/nvim/highlight_group.c
@@ -67,32 +67,32 @@ Map(cstr_t, int) highlight_unames = MAP_INIT;
static char *(hl_name_table[]) =
{ "bold", "standout", "underline",
"undercurl", "underdouble", "underdotted", "underdashed",
- "italic", "reverse", "inverse", "strikethrough", "nocombine", "NONE" };
+ "italic", "reverse", "inverse", "strikethrough", "altfont",
+ "nocombine", "NONE" };
static int hl_attr_table[] =
{ HL_BOLD, HL_STANDOUT, HL_UNDERLINE,
HL_UNDERCURL, HL_UNDERDOUBLE, HL_UNDERDOTTED, HL_UNDERDASHED,
- HL_ITALIC, HL_INVERSE, HL_INVERSE, HL_STRIKETHROUGH, HL_NOCOMBINE, 0 };
+ HL_ITALIC, HL_INVERSE, HL_INVERSE, HL_STRIKETHROUGH, HL_ALTFONT,
+ HL_NOCOMBINE, 0 };
/// Structure that stores information about a highlight group.
/// The ID of a highlight group is also called group ID. It is the index in
/// the highlight_ga array PLUS ONE.
typedef struct {
- char_u *sg_name; ///< highlight group name
- char *sg_name_u; ///< uppercase of sg_name
+ char *sg_name; ///< highlight group name
+ char *sg_name_u; ///< uppercase of sg_name
bool sg_cleared; ///< "hi clear" was used
int sg_attr; ///< Screen attr @see ATTR_ENTRY
int sg_link; ///< link to this highlight group ID
int sg_deflink; ///< default link; restored in highlight_clear()
int sg_set; ///< combination of flags in \ref SG_SET
sctx_T sg_deflink_sctx; ///< script where the default link was set
- sctx_T sg_script_ctx; ///< script in which the group was last set
- // for terminal UIs
+ sctx_T sg_script_ctx; ///< script in which the group was last set for terminal UIs
int sg_cterm; ///< "cterm=" highlighting attr
///< (combination of \ref HlAttrFlags)
int sg_cterm_fg; ///< terminal fg color number + 1
int sg_cterm_bg; ///< terminal bg color number + 1
- bool sg_cterm_bold; ///< bold attr was set for light color
- // for RGB UIs
+ bool sg_cterm_bold; ///< bold attr was set for light color for RGB UIs
int sg_gui; ///< "gui=" highlighting attributes
///< (combination of \ref HlAttrFlags)
RgbValue sg_rgb_fg; ///< RGB foreground color
@@ -571,7 +571,7 @@ int highlight_num_groups(void)
}
/// Returns the name of a highlight group.
-char_u *highlight_group_name(int id)
+char *highlight_group_name(int id)
{
return hl_table[id].sg_name;
}
@@ -658,8 +658,6 @@ void init_highlight(bool both, bool reset)
/// @return OK for success, FAIL for failure.
int load_colors(char *name)
{
- char_u *buf;
- int retval = FAIL;
static bool recursive = false;
// When being called recursively, this is probably because setting
@@ -671,13 +669,13 @@ int load_colors(char *name)
recursive = true;
size_t buflen = strlen(name) + 12;
- buf = xmalloc(buflen);
+ char *buf = xmalloc(buflen);
apply_autocmds(EVENT_COLORSCHEMEPRE, name, curbuf->b_fname, false, curbuf);
- snprintf((char *)buf, buflen, "colors/%s.vim", name);
- retval = source_runtime((char *)buf, DIP_START + DIP_OPT);
+ snprintf(buf, buflen, "colors/%s.vim", name);
+ int retval = source_runtime(buf, DIP_START + DIP_OPT);
if (retval == FAIL) {
- snprintf((char *)buf, buflen, "colors/%s.lua", name);
- retval = source_runtime((char *)buf, DIP_START + DIP_OPT);
+ snprintf(buf, buflen, "colors/%s.lua", name);
+ retval = source_runtime(buf, DIP_START + DIP_OPT);
}
xfree(buf);
if (retval == OK) {
@@ -873,25 +871,6 @@ update:
void do_highlight(const char *line, const bool forceit, const bool init)
FUNC_ATTR_NONNULL_ALL
{
- const char *name_end;
- const char *linep;
- const char *key_start;
- const char *arg_start;
- int off;
- int len;
- int attr;
- int id;
- int idx;
- HlGroup item_before;
- bool did_change = false;
- bool dodefault = false;
- bool doclear = false;
- bool dolink = false;
- bool error = false;
- int color;
- bool is_normal_group = false; // "Normal" group
- bool did_highlight_changed = false;
-
// If no argument, list current highlighting.
if (!init && ends_excmd((uint8_t)(*line))) {
for (int i = 1; i <= highlight_ga.ga_len && !got_int; i++) {
@@ -901,9 +880,11 @@ void do_highlight(const char *line, const bool forceit, const bool init)
return;
}
+ bool dodefault = false;
+
// Isolate the name.
- name_end = (const char *)skiptowhite(line);
- linep = (const char *)skipwhite(name_end);
+ const char *name_end = (const char *)skiptowhite(line);
+ const char *linep = (const char *)skipwhite(name_end);
// Check for "default" argument.
if (strncmp(line, "default", (size_t)(name_end - line)) == 0) {
@@ -913,6 +894,9 @@ void do_highlight(const char *line, const bool forceit, const bool init)
linep = (const char *)skipwhite(name_end);
}
+ bool doclear = false;
+ bool dolink = false;
+
// Check for "clear" or "link" argument.
if (strncmp(line, "clear", (size_t)(name_end - line)) == 0) {
doclear = true;
@@ -922,7 +906,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
// ":highlight {group-name}": list highlighting for one group.
if (!doclear && !dolink && ends_excmd((uint8_t)(*linep))) {
- id = syn_name2id_len(line, (size_t)(name_end - line));
+ int id = syn_name2id_len(line, (size_t)(name_end - line));
if (id == 0) {
semsg(_("E411: highlight group not found: %s"), line);
} else {
@@ -1024,11 +1008,11 @@ void do_highlight(const char *line, const bool forceit, const bool init)
}
// Find the group name in the table. If it does not exist yet, add it.
- id = syn_check_group(line, (size_t)(name_end - line));
+ int id = syn_check_group(line, (size_t)(name_end - line));
if (id == 0) { // Failed (out of memory).
return;
}
- idx = id - 1; // Index is ID minus one.
+ int idx = id - 1; // Index is ID minus one.
// Return if "default" was used and the group already has settings
if (dodefault && hl_has_settings(idx, true)) {
@@ -1036,8 +1020,8 @@ void do_highlight(const char *line, const bool forceit, const bool init)
}
// Make a copy so we can check if any attribute actually changed
- item_before = hl_table[idx];
- is_normal_group = (strcmp(hl_table[idx].sg_name_u, "NORMAL") == 0);
+ HlGroup item_before = hl_table[idx];
+ bool is_normal_group = (strcmp(hl_table[idx].sg_name_u, "NORMAL") == 0);
// Clear the highlighting for ":hi clear {group}" and ":hi clear".
if (doclear || (forceit && init)) {
@@ -1047,11 +1031,16 @@ void do_highlight(const char *line, const bool forceit, const bool init)
}
}
+ bool did_change = false;
+ bool error = false;
+
char key[64];
char arg[512];
if (!doclear) {
+ const char *arg_start;
+
while (!ends_excmd((uint8_t)(*linep))) {
- key_start = linep;
+ const char *key_start = linep;
if (*linep == '=') {
semsg(_("E415: unexpected equal sign: %s"), key_start);
error = true;
@@ -1071,7 +1060,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
}
memcpy(key, key_start, key_len);
key[key_len] = NUL;
- vim_strup((char_u *)key);
+ vim_strup(key);
linep = (const char *)skipwhite(linep);
if (strcmp(key, "NONE") == 0) {
@@ -1128,12 +1117,12 @@ void do_highlight(const char *line, const bool forceit, const bool init)
if (strcmp(key, "TERM") == 0
|| strcmp(key, "CTERM") == 0
|| strcmp(key, "GUI") == 0) {
- attr = 0;
- off = 0;
+ int attr = 0;
+ int off = 0;
int i;
while (arg[off] != NUL) {
for (i = ARRAY_SIZE(hl_attr_table); --i >= 0;) {
- len = (int)strlen(hl_name_table[i]);
+ int len = (int)strlen(hl_name_table[i]);
if (STRNICMP(arg + off, hl_name_table[i], len) == 0) {
attr |= hl_attr_table[i];
off += len;
@@ -1183,6 +1172,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
hl_table[idx].sg_cterm_bold = false;
}
+ int color;
if (ascii_isdigit(*arg)) {
color = atoi(arg);
} else if (STRICMP(arg, "fg") == 0) {
@@ -1203,7 +1193,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
}
} else {
// Reduce calls to STRICMP a bit, it can be slow.
- off = TOUPPER_ASC(*arg);
+ int off = TOUPPER_ASC(*arg);
int i;
for (i = ARRAY_SIZE(color_names); --i >= 0;) {
if (off == color_names[i][0]
@@ -1360,6 +1350,8 @@ void do_highlight(const char *line, const bool forceit, const bool init)
}
}
+ bool did_highlight_changed = false;
+
if (!error && is_normal_group) {
// Need to update all groups, because they might be using "bg" and/or
// "fg", which have been changed now.
@@ -1471,7 +1463,7 @@ static void highlight_list_one(const int id)
const HlGroup *sgp = &hl_table[id - 1]; // index is ID minus one
bool didh = false;
- if (message_filtered((char *)sgp->sg_name)) {
+ if (message_filtered(sgp->sg_name)) {
return;
}
@@ -1505,7 +1497,7 @@ static void highlight_list_one(const int id)
didh = true;
msg_puts_attr("links to", HL_ATTR(HLF_D));
msg_putchar(' ');
- msg_outtrans((char *)hl_table[hl_table[id - 1].sg_link - 1].sg_name);
+ msg_outtrans(hl_table[hl_table[id - 1].sg_link - 1].sg_name);
}
if (!didh) {
@@ -1527,7 +1519,7 @@ Dictionary get_global_hl_defs(Arena *arena)
hlattrs2dict(&attrs, syn_attr2entry(h->sg_attr), true);
} else if (h->sg_link > 0) {
attrs = arena_dict(arena, 1);
- char *link = (char *)hl_table[h->sg_link - 1].sg_name;
+ char *link = hl_table[h->sg_link - 1].sg_name;
PUT_C(attrs, "link", STRING_OBJ(cstr_as_string(link)));
}
PUT_C(rv, (char *)h->sg_name, DICTIONARY_OBJ(attrs));
@@ -1544,8 +1536,6 @@ Dictionary get_global_hl_defs(Arena *arena)
static bool highlight_list_arg(const int id, bool didh, const int type, int iarg, const char *sarg,
const char *const name)
{
- char buf[100];
-
if (got_int) {
return false;
}
@@ -1554,6 +1544,7 @@ static bool highlight_list_arg(const int id, bool didh, const int type, int iarg
return didh;
}
+ char buf[100];
const char *ts = buf;
if (type == LIST_INT) {
snprintf((char *)buf, sizeof(buf), "%d", iarg - 1);
@@ -1562,12 +1553,17 @@ static bool highlight_list_arg(const int id, bool didh, const int type, int iarg
} else { // type == LIST_ATTR
buf[0] = NUL;
for (int i = 0; hl_attr_table[i] != 0; i++) {
- if (iarg & hl_attr_table[i]) {
+ if (((hl_attr_table[i] & HL_UNDERLINE_MASK)
+ && ((iarg & HL_UNDERLINE_MASK) == hl_attr_table[i]))
+ || (!(hl_attr_table[i] & HL_UNDERLINE_MASK)
+ && (iarg & hl_attr_table[i]))) {
if (buf[0] != NUL) {
xstrlcat(buf, ",", 100);
}
xstrlcat(buf, hl_name_table[i], 100);
- iarg &= ~hl_attr_table[i]; // don't want "inverse"
+ if (!(hl_attr_table[i] & HL_UNDERLINE_MASK)) {
+ iarg &= ~hl_attr_table[i]; // don't want "inverse"
+ }
}
}
}
@@ -1594,19 +1590,24 @@ static bool highlight_list_arg(const int id, bool didh, const int type, int iarg
const char *highlight_has_attr(const int id, const int flag, const int modec)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
{
- int attr;
-
if (id <= 0 || id > highlight_ga.ga_len) {
return NULL;
}
+ int attr;
+
if (modec == 'g') {
attr = hl_table[id - 1].sg_gui;
} else {
attr = hl_table[id - 1].sg_cterm;
}
- return (attr & flag) ? "1" : NULL;
+ if (flag & HL_UNDERLINE_MASK) {
+ int ul = attr & HL_UNDERLINE_MASK;
+ return ul == flag ? "1" : NULL;
+ } else {
+ return (attr & flag) ? "1" : NULL;
+ }
}
/// Return color name of the given highlight group
@@ -1622,7 +1623,6 @@ const char *highlight_color(const int id, const char *const what, const int mode
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
static char name[20];
- int n;
bool fg = false;
bool sp = false;
bool font = false;
@@ -1641,6 +1641,9 @@ const char *highlight_color(const int id, const char *const what, const int mode
} else if (!(TOLOWER_ASC(what[0]) == 'b' && TOLOWER_ASC(what[1]) == 'g')) {
return NULL;
}
+
+ int n;
+
if (modec == 'g') {
if (what[2] == '#' && ui_rgb_attached()) {
if (fg) {
@@ -1702,7 +1705,7 @@ bool syn_list_header(const bool did_header, const int outlen, const int id, bool
if (got_int) {
return true;
}
- msg_outtrans((char *)hl_table[id - 1].sg_name);
+ msg_outtrans(hl_table[id - 1].sg_name);
name_col = msg_col;
endcol = 15;
} else if ((ui_has(kUIMessages) || msg_silent) && !force_newline) {
@@ -1795,7 +1798,7 @@ int syn_name2id_len(const char *name, size_t len)
// Avoid alloc()/free(), these are slow too.
memcpy(name_u, name, len);
name_u[len] = '\0';
- vim_strup((char_u *)name_u);
+ vim_strup(name_u);
// map_get(..., int) returns 0 when no key is present, which is
// the expected value for missing highlight group.
@@ -1804,10 +1807,10 @@ int syn_name2id_len(const char *name, size_t len)
/// Lookup a highlight group name and return its attributes.
/// Return zero if not found.
-int syn_name2attr(const char_u *name)
+int syn_name2attr(const char *name)
FUNC_ATTR_NONNULL_ALL
{
- int id = syn_name2id((char *)name);
+ int id = syn_name2id(name);
if (id != 0) {
return syn_id2attr(id);
@@ -1823,10 +1826,10 @@ int highlight_exists(const char *name)
/// Return the name of highlight group "id".
/// When not a valid ID return an empty string.
-char_u *syn_id2name(int id)
+char *syn_id2name(int id)
{
if (id <= 0 || id > highlight_ga.ga_len) {
- return (char_u *)"";
+ return "";
}
return hl_table[id - 1].sg_name;
}
@@ -1896,7 +1899,7 @@ static int syn_add_group(const char *name, size_t len)
// Append another syntax_highlight entry.
HlGroup *hlgp = GA_APPEND_VIA_PTR(HlGroup, &highlight_ga);
CLEAR_POINTER(hlgp);
- hlgp->sg_name = (char_u *)arena_memdupz(&highlight_arena, name, len);
+ hlgp->sg_name = arena_memdupz(&highlight_arena, name, len);
hlgp->sg_rgb_bg = -1;
hlgp->sg_rgb_fg = -1;
hlgp->sg_rgb_sp = -1;
@@ -1908,7 +1911,7 @@ static int syn_add_group(const char *name, size_t len)
hlgp->sg_parent = scoped_parent;
// will get set to false by caller if settings are added
hlgp->sg_cleared = true;
- vim_strup((char_u *)hlgp->sg_name_u);
+ vim_strup(hlgp->sg_name_u);
int id = highlight_ga.ga_len; // ID is index plus one
@@ -2048,17 +2051,15 @@ static void combine_stl_hlt(int id, int id_S, int id_alt, int hlcnt, int i, int
/// screen redraw after any :highlight command.
void highlight_changed(void)
{
- int id;
char userhl[30]; // use 30 to avoid compiler warning
int id_S = -1;
int id_SNC = 0;
- int hlcnt;
need_highlight_changed = false;
/// Translate builtin highlight groups into attributes for quick lookup.
for (int hlf = 0; hlf < HLF_COUNT; hlf++) {
- id = syn_check_group(hlf_names[hlf], strlen(hlf_names[hlf]));
+ int id = syn_check_group(hlf_names[hlf], strlen(hlf_names[hlf]));
if (id == 0) {
abort();
}
@@ -2097,7 +2098,7 @@ void highlight_changed(void)
// Must to be in there simultaneously in case of table overflows in
// get_attr_entry()
ga_grow(&highlight_ga, 10);
- hlcnt = highlight_ga.ga_len;
+ int hlcnt = highlight_ga.ga_len;
if (id_S == -1) {
// Make sure id_S is always valid to simplify code below. Use the last entry
CLEAR_POINTER(&hl_table[hlcnt + 9]);
@@ -2105,7 +2106,7 @@ void highlight_changed(void)
}
for (int i = 0; i < 9; i++) {
snprintf(userhl, sizeof(userhl), "User%d", i + 1);
- id = syn_name2id(userhl);
+ int id = syn_name2id(userhl);
if (id == 0) {
highlight_user[i] = 0;
highlight_stlnc[i] = 0;
@@ -2171,12 +2172,10 @@ void set_context_in_highlight_cmd(expand_T *xp, const char *arg)
/// List highlighting matches in a nice way.
static void highlight_list(void)
{
- int i;
-
- for (i = 10; --i >= 0;) {
+ for (int i = 10; --i >= 0;) {
highlight_list_two(i, HL_ATTR(HLF_D));
}
- for (i = 40; --i >= 0;) {
+ for (int i = 40; --i >= 0;) {
highlight_list_two(99, 0);
}
}
@@ -2921,9 +2920,9 @@ color_name_table_T color_name_table[] = {
/// return the hex value or -1 if could not find a correct value
RgbValue name_to_color(const char *name, int *idx)
{
- if (name[0] == '#' && isxdigit(name[1]) && isxdigit(name[2])
- && isxdigit(name[3]) && isxdigit(name[4]) && isxdigit(name[5])
- && isxdigit(name[6]) && name[7] == NUL) {
+ if (name[0] == '#' && isxdigit((uint8_t)name[1]) && isxdigit((uint8_t)name[2])
+ && isxdigit((uint8_t)name[3]) && isxdigit((uint8_t)name[4]) && isxdigit((uint8_t)name[5])
+ && isxdigit((uint8_t)name[6]) && name[7] == NUL) {
// rgb hex string
*idx = kColorIdxHex;
return (RgbValue)strtol((char *)(name + 1), NULL, 16);
@@ -2947,7 +2946,6 @@ RgbValue name_to_color(const char *name, int *idx)
} else { // found match
*idx = m;
return color_name_table[m].color;
- break;
}
}
diff --git a/src/nvim/iconv.h b/src/nvim/iconv.h
index 509f83c415..f5f3f25786 100644
--- a/src/nvim/iconv.h
+++ b/src/nvim/iconv.h
@@ -1,20 +1,18 @@
#ifndef NVIM_ICONV_H
#define NVIM_ICONV_H
-#include "auto/config.h"
+#include <errno.h>
+#include <iconv.h>
-#ifdef HAVE_ICONV
-# include <errno.h>
-# include <iconv.h>
+#include "auto/config.h"
// define some missing constants if necessary
-# ifndef EILSEQ
-# define EILSEQ 123
-# endif
-# define ICONV_ERRNO errno
-# define ICONV_E2BIG E2BIG
-# define ICONV_EINVAL EINVAL
-# define ICONV_EILSEQ EILSEQ
+#ifndef EILSEQ
+# define EILSEQ 123
#endif
+#define ICONV_ERRNO errno
+#define ICONV_E2BIG E2BIG
+#define ICONV_EINVAL EINVAL
+#define ICONV_EILSEQ EILSEQ
#endif // NVIM_ICONV_H
diff --git a/src/nvim/indent.c b/src/nvim/indent.c
index be1dfb77cf..ec6c72da6d 100644
--- a/src/nvim/indent.c
+++ b/src/nvim/indent.c
@@ -17,6 +17,7 @@
#include "nvim/edit.h"
#include "nvim/eval.h"
#include "nvim/eval/typval_defs.h"
+#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/extmark.h"
#include "nvim/gettext.h"
@@ -24,6 +25,7 @@
#include "nvim/indent.h"
#include "nvim/indent_c.h"
#include "nvim/mark.h"
+#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
@@ -386,7 +388,7 @@ int get_indent_buf(buf_T *buf, linenr_T lnum)
/// Count the size (in window cells) of the indent in line "ptr", with
/// 'tabstop' at "ts".
/// If @param list is true, count only screen size for tabs.
-int get_indent_str(const char_u *ptr, int ts, bool list)
+int get_indent_str(const char *ptr, int ts, bool list)
FUNC_ATTR_NONNULL_ALL
{
int count = 0;
@@ -400,7 +402,7 @@ int get_indent_str(const char_u *ptr, int ts, bool list)
} else {
// In list mode, when tab is not set, count screen char width
// for Tab, displays: ^I
- count += ptr2cells((char *)ptr);
+ count += ptr2cells(ptr);
}
} else if (*ptr == ' ') {
// Count a space for one.
@@ -803,7 +805,7 @@ int get_breakindent_win(win_T *wp, char *line)
{
static int prev_indent = 0; // Cached indent value.
static long prev_ts = 0L; // Cached tabstop value.
- static const char_u *prev_line = NULL; // cached pointer to line.
+ static const char *prev_line = NULL; // cached pointer to line.
static varnumber_T prev_tick = 0; // Changedtick of cached value.
static long *prev_vts = NULL; // Cached vartabs values.
static int prev_list = 0; // cached list value
@@ -820,12 +822,12 @@ int get_breakindent_win(win_T *wp, char *line)
// - 'tabstop' changed
// - 'briopt_list changed' changed or
// - 'formatlistpattern' changed
- if (prev_line != (char_u *)line || prev_ts != wp->w_buffer->b_p_ts
+ if (prev_line != line || prev_ts != wp->w_buffer->b_p_ts
|| prev_tick != buf_get_changedtick(wp->w_buffer)
|| prev_listopt != wp->w_briopt_list
|| (prev_flp == NULL || (strcmp(prev_flp, get_flp_value(wp->w_buffer)) != 0))
|| prev_vts != wp->w_buffer->b_p_vts_array) {
- prev_line = (char_u *)line;
+ prev_line = line;
prev_ts = wp->w_buffer->b_p_ts;
prev_tick = buf_get_changedtick(wp->w_buffer);
prev_vts = wp->w_buffer->b_p_vts_array;
@@ -850,7 +852,7 @@ int get_breakindent_win(win_T *wp, char *line)
if (wp->w_briopt_list > 0) {
prev_list += wp->w_briopt_list;
} else {
- prev_list = (int)(*regmatch.endp - *regmatch.startp);
+ prev_indent = (int)(*regmatch.endp - *regmatch.startp);
}
}
vim_regfree(regmatch.regprog);
@@ -869,17 +871,13 @@ int get_breakindent_win(win_T *wp, char *line)
bri += win_col_off2(wp);
// add additional indent for numbered lists
- if (wp->w_briopt_list != 0) {
- if (wp->w_briopt_list > 0) {
- bri += prev_list;
- } else {
- bri = prev_list;
- }
+ if (wp->w_briopt_list > 0) {
+ bri += prev_list;
}
// indent minus the length of the showbreak string
if (wp->w_briopt_sbr) {
- bri -= vim_strsize((char *)get_showbreak_value(wp));
+ bri -= vim_strsize(get_showbreak_value(wp));
}
// never indent past left window margin
@@ -901,10 +899,10 @@ int get_breakindent_win(win_T *wp, char *line)
// the line.
int inindent(int extra)
{
- char_u *ptr;
+ char *ptr;
colnr_T col;
- for (col = 0, ptr = (char_u *)get_cursor_line_ptr(); ascii_iswhite(*ptr); col++) {
+ for (col = 0, ptr = get_cursor_line_ptr(); ascii_iswhite(*ptr); col++) {
ptr++;
}
@@ -1187,7 +1185,7 @@ int get_lisp_indent(void)
{
pos_T *pos, realpos, paren;
int amount;
- char_u *that;
+ char *that;
colnr_T col;
colnr_T firsttry;
int parencount;
@@ -1222,7 +1220,7 @@ int get_lisp_indent(void)
continue;
}
- for (that = (char_u *)get_cursor_line_ptr(); *that != NUL; that++) {
+ for (that = get_cursor_line_ptr(); *that != NUL; that++) {
if (*that == ';') {
while (*(that + 1) != NUL) {
that++;
@@ -1272,20 +1270,20 @@ int get_lisp_indent(void)
curwin->w_cursor.col = pos->col;
col = pos->col;
- that = (char_u *)get_cursor_line_ptr();
+ that = get_cursor_line_ptr();
if (vi_lisp && (get_indent() == 0)) {
amount = 2;
} else {
- char_u *line = that;
+ char *line = that;
chartabsize_T cts;
- init_chartabsize_arg(&cts, curwin, pos->lnum, 0, (char *)line, (char *)line);
+ init_chartabsize_arg(&cts, curwin, pos->lnum, 0, line, line);
while (*cts.cts_ptr != NUL && col > 0) {
cts.cts_vcol += lbr_chartabsize_adv(&cts);
col--;
}
amount = cts.cts_vcol;
- that = (char_u *)cts.cts_ptr;
+ that = cts.cts_ptr;
clear_chartabsize_arg(&cts);
// Some keywords require "body" indenting rules (the
@@ -1293,7 +1291,7 @@ int get_lisp_indent(void)
// (let ((a 1)) instead (let ((a 1))
// (...)) of (...))
if (!vi_lisp && ((*that == '(') || (*that == '['))
- && lisp_match((char *)that + 1)) {
+ && lisp_match(that + 1)) {
amount += 2;
} else {
if (*that != NUL) {
@@ -1303,12 +1301,12 @@ int get_lisp_indent(void)
firsttry = amount;
init_chartabsize_arg(&cts, curwin, (colnr_T)(that - line),
- amount, (char *)line, (char *)that);
+ amount, line, that);
while (ascii_iswhite(*cts.cts_ptr)) {
cts.cts_vcol += lbr_chartabsize(&cts);
cts.cts_ptr++;
}
- that = (char_u *)cts.cts_ptr;
+ that = cts.cts_ptr;
amount = cts.cts_vcol;
clear_chartabsize_arg(&cts);
@@ -1324,9 +1322,10 @@ int get_lisp_indent(void)
quotecount = 0;
init_chartabsize_arg(&cts, curwin,
- (colnr_T)(that - line), amount, (char *)line, (char *)that);
+ (colnr_T)(that - line), amount, line, that);
if (vi_lisp || ((*that != '"') && (*that != '\'')
- && (*that != '#') && ((*that < '0') || (*that > '9')))) {
+ && (*that != '#')
+ && (((uint8_t)(*that) < '0') || ((uint8_t)(*that) > '9')))) {
while (*cts.cts_ptr
&& (!ascii_iswhite(*cts.cts_ptr) || quotecount || parencount)
&& (!((*cts.cts_ptr == '(' || *cts.cts_ptr == '[')
@@ -1352,7 +1351,7 @@ int get_lisp_indent(void)
cts.cts_vcol += lbr_chartabsize(&cts);
cts.cts_ptr++;
}
- that = (char_u *)cts.cts_ptr;
+ that = cts.cts_ptr;
amount = cts.cts_vcol;
clear_chartabsize_arg(&cts);
@@ -1375,7 +1374,7 @@ static int lisp_match(char *p)
{
char buf[LSIZE];
int len;
- char *word = (char *)(*curbuf->b_p_lw != NUL ? (char_u *)curbuf->b_p_lw : p_lispwords);
+ char *word = *curbuf->b_p_lw != NUL ? curbuf->b_p_lw : p_lispwords;
while (*word != NUL) {
(void)copy_option_part(&word, buf, LSIZE, ",");
diff --git a/src/nvim/indent_c.c b/src/nvim/indent_c.c
index ccf4448e93..1c771073b2 100644
--- a/src/nvim/indent_c.c
+++ b/src/nvim/indent_c.c
@@ -23,7 +23,6 @@
#include "nvim/pos.h"
#include "nvim/search.h"
#include "nvim/strings.h"
-#include "nvim/types.h"
#include "nvim/vim.h"
// Find result cache for cpp_baseclass
@@ -705,7 +704,7 @@ static int cin_get_equal_amount(linenr_T lnum)
s = ml_get(lnum);
line = s;
- while (*s != NUL && vim_strchr("=;{}\"'", *s) == NULL) {
+ while (*s != NUL && vim_strchr("=;{}\"'", (uint8_t)(*s)) == NULL) {
if (cin_iscomment(s)) { // ignore comments
s = cin_skipcomment(s);
} else {
diff --git a/src/nvim/input.c b/src/nvim/input.c
index 0f0af9d5f0..96214d45c2 100644
--- a/src/nvim/input.c
+++ b/src/nvim/input.c
@@ -29,7 +29,8 @@
# include "input.c.generated.h" // IWYU pragma: export
#endif
-/// Ask for a reply from the user, 'y' or 'n'
+/// Ask for a reply from the user, a 'y' or a 'n', with prompt "str" (which
+/// should have been translated already).
///
/// No other characters are accepted, the message is repeated until a valid
/// reply is entered or <C-c> is hit.
diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c
index fa8e78f624..6de3b0a9d0 100644
--- a/src/nvim/insexpand.c
+++ b/src/nvim/insexpand.c
@@ -7,6 +7,7 @@
#include <limits.h>
#include <stdbool.h>
#include <stddef.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -597,7 +598,7 @@ static char *ins_compl_infercase_gettext(const char *str, int char_len, int comp
// Allocate wide character array for the completion and fill it.
int *const wca = xmalloc((size_t)char_len * sizeof(*wca));
{
- const char_u *p = (char_u *)str;
+ const char *p = str;
for (int i = 0; i < char_len; i++) {
wca[i] = mb_ptr2char_adv(&p);
}
@@ -605,7 +606,7 @@ static char *ins_compl_infercase_gettext(const char *str, int char_len, int comp
// Rule 1: Were any chars converted to lower?
{
- const char_u *p = (char_u *)compl_orig_text;
+ const char *p = compl_orig_text;
for (int i = 0; i < min_len; i++) {
const int c = mb_ptr2char_adv(&p);
if (mb_islower(c)) {
@@ -624,7 +625,7 @@ static char *ins_compl_infercase_gettext(const char *str, int char_len, int comp
// Rule 2: No lower case, 2nd consecutive letter converted to
// upper case.
if (!has_lower) {
- const char_u *p = (char_u *)compl_orig_text;
+ const char *p = compl_orig_text;
for (int i = 0; i < min_len; i++) {
const int c = mb_ptr2char_adv(&p);
if (was_letter && mb_isupper(c) && mb_islower(wca[i])) {
@@ -640,7 +641,7 @@ static char *ins_compl_infercase_gettext(const char *str, int char_len, int comp
// Copy the original case of the part we typed.
{
- const char_u *p = (char_u *)compl_orig_text;
+ const char *p = compl_orig_text;
for (int i = 0; i < min_len; i++) {
const int c = mb_ptr2char_adv(&p);
if (mb_islower(c)) {
@@ -2257,14 +2258,14 @@ static void copy_global_to_buflocal_cb(Callback *globcb, Callback *bufcb)
/// Invoked when the 'completefunc' option is set. The option value can be a
/// name of a function (string), or function(<name>) or funcref(<name>) or a
/// lambda expression.
-int set_completefunc_option(void)
+void set_completefunc_option(char **errmsg)
{
- int retval = option_set_callback_func(curbuf->b_p_cfu, &cfu_cb);
- if (retval == OK) {
- set_buflocal_cfu_callback(curbuf);
+ if (option_set_callback_func(curbuf->b_p_cfu, &cfu_cb) == FAIL) {
+ *errmsg = e_invarg;
+ return;
}
- return retval;
+ set_buflocal_cfu_callback(curbuf);
}
/// Copy the global 'completefunc' callback function to the buffer-local
@@ -2278,14 +2279,13 @@ void set_buflocal_cfu_callback(buf_T *buf)
/// Invoked when the 'omnifunc' option is set. The option value can be a
/// name of a function (string), or function(<name>) or funcref(<name>) or a
/// lambda expression.
-int set_omnifunc_option(void)
+void set_omnifunc_option(buf_T *buf, char **errmsg)
{
- int retval = option_set_callback_func(curbuf->b_p_ofu, &ofu_cb);
- if (retval == OK) {
- set_buflocal_ofu_callback(curbuf);
+ if (option_set_callback_func(buf->b_p_ofu, &ofu_cb) == FAIL) {
+ *errmsg = e_invarg;
+ return;
}
-
- return retval;
+ set_buflocal_ofu_callback(buf);
}
/// Copy the global 'omnifunc' callback function to the buffer-local 'omnifunc'
@@ -2299,7 +2299,7 @@ void set_buflocal_ofu_callback(buf_T *buf)
/// Invoked when the 'thesaurusfunc' option is set. The option value can be a
/// name of a function (string), or function(<name>) or funcref(<name>) or a
/// lambda expression.
-int set_thesaurusfunc_option(void)
+void set_thesaurusfunc_option(char **errmsg)
{
int retval;
@@ -2311,7 +2311,9 @@ int set_thesaurusfunc_option(void)
retval = option_set_callback_func(p_tsrfu, &tsrfu_cb);
}
- return retval;
+ if (retval == FAIL) {
+ *errmsg = e_invarg;
+ }
}
/// Mark the global 'completefunc' 'omnifunc' and 'thesaurusfunc' callbacks with
@@ -2856,7 +2858,7 @@ static int process_next_cpt_value(ins_compl_next_state_T *st, int *compl_type_ar
// Remember the first match so that the loop stops when we
// wrap and come back there a second time.
st->set_match_pos = true;
- } else if (vim_strchr("buwU", *st->e_cpt) != NULL
+ } else if (vim_strchr("buwU", (uint8_t)(*st->e_cpt)) != NULL
&& (st->ins_buf = ins_compl_next_buf(st->ins_buf, *st->e_cpt)) != curbuf) {
// Scan a buffer, but not the current one.
if (st->ins_buf->b_ml.ml_mfp != NULL) { // loaded buffer
@@ -2950,7 +2952,7 @@ static void get_next_dict_tsr_completion(int compl_type, char *dict, int dict_f)
} else {
ins_compl_dictionaries(dict != NULL ? dict
: (compl_type == CTRL_X_THESAURUS
- ? (*curbuf->b_p_tsr == NUL ? (char *)p_tsr : curbuf->b_p_tsr)
+ ? (*curbuf->b_p_tsr == NUL ? p_tsr : curbuf->b_p_tsr)
: (*curbuf->b_p_dict ==
NUL ? p_dict : curbuf->b_p_dict)),
compl_pattern,
@@ -2996,7 +2998,7 @@ static void get_next_filename_completion(void)
#ifdef BACKSLASH_IN_FILENAME
if (curbuf->b_p_csl[0] != NUL) {
for (int i = 0; i < num_matches; i++) {
- char_u *ptr = matches[i];
+ char *ptr = matches[i];
while (*ptr != NUL) {
if (curbuf->b_p_csl[0] == 's' && *ptr == '\\') {
*ptr = '/';
@@ -3160,7 +3162,7 @@ static int get_next_default_completion(ins_compl_next_state_T *st, pos_T *start_
compl_direction, compl_pattern);
} else {
found_new_match = searchit(NULL, st->ins_buf, st->cur_match_pos,
- NULL, compl_direction, (char_u *)compl_pattern, 1L,
+ NULL, compl_direction, compl_pattern, 1L,
SEARCH_KEEP + SEARCH_NFMSG, RE_LAST, NULL);
}
msg_silent--;
diff --git a/src/nvim/keycodes.c b/src/nvim/keycodes.c
index a4228fcc7e..e19806e464 100644
--- a/src/nvim/keycodes.c
+++ b/src/nvim/keycodes.c
@@ -474,7 +474,7 @@ char_u *get_special_key_name(int c, int modifiers)
int i, idx;
int table_idx;
- char_u *s;
+ char *s;
string[0] = '<';
idx = 1;
@@ -543,7 +543,7 @@ char_u *get_special_key_name(int c, int modifiers)
} else {
s = transchar(c);
while (*s) {
- string[idx++] = *s++;
+ string[idx++] = (uint8_t)(*s++);
}
}
}
@@ -572,7 +572,7 @@ char_u *get_special_key_name(int c, int modifiers)
/// @param[out] did_simplify found <C-H>, etc.
///
/// @return Number of characters added to dst, zero for no match.
-unsigned int trans_special(const char **const srcp, const size_t src_len, char_u *const dst,
+unsigned int trans_special(const char **const srcp, const size_t src_len, char *const dst,
const int flags, const bool escape_ks, bool *const did_simplify)
FUNC_ATTR_NONNULL_ARG(1, 3) FUNC_ATTR_WARN_UNUSED_RESULT
{
@@ -582,7 +582,7 @@ unsigned int trans_special(const char **const srcp, const size_t src_len, char_u
return 0;
}
- return special_to_buf(key, modifiers, escape_ks, dst);
+ return special_to_buf(key, modifiers, escape_ks, (char_u *)dst);
}
/// Put the character sequence for "key" with "modifiers" into "dst" and return
@@ -629,11 +629,11 @@ int find_special_key(const char **const srcp, const size_t src_len, int *const m
const int flags, bool *const did_simplify)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1, 3)
{
- const char_u *last_dash;
- const char_u *end_of_name;
- const char_u *src;
- const char_u *bp;
- const char_u *const end = (char_u *)(*srcp) + src_len - 1;
+ const char *last_dash;
+ const char *end_of_name;
+ const char *src;
+ const char *bp;
+ const char *const end = *srcp + src_len - 1;
const bool in_string = flags & FSK_IN_STRING;
int modifiers;
int bit;
@@ -645,7 +645,7 @@ int find_special_key(const char **const srcp, const size_t src_len, int *const m
return 0;
}
- src = (char_u *)(*srcp);
+ src = *srcp;
if (src[0] != '<') {
return 0;
}
@@ -659,7 +659,7 @@ int find_special_key(const char **const srcp, const size_t src_len, int *const m
if (*bp == '-') {
last_dash = bp;
if (bp + 1 <= end) {
- l = utfc_ptr2len_len((char *)bp + 1, (int)(end - bp) + 1);
+ l = utfc_ptr2len_len(bp + 1, (int)(end - bp) + 1);
// Anything accepted, like <C-?>.
// <C-"> or <M-"> are not special in strings as " is
// the string delimiter. With a backslash it works: <M-\">
@@ -674,7 +674,7 @@ int find_special_key(const char **const srcp, const size_t src_len, int *const m
if (end - bp > 3 && bp[0] == 't' && bp[1] == '_') {
bp += 3; // skip t_xx, xx may be '-' or '>'
} else if (end - bp > 4 && STRNICMP(bp, "char-", 5) == 0) {
- vim_str2nr((char *)bp + 5, NULL, &l, STR2NR_ALL, NULL, NULL, 0, true);
+ vim_str2nr(bp + 5, NULL, &l, STR2NR_ALL, NULL, NULL, 0, true);
if (l == 0) {
emsg(_(e_invarg));
return 0;
@@ -691,7 +691,7 @@ int find_special_key(const char **const srcp, const size_t src_len, int *const m
modifiers = 0x0;
for (bp = src + 1; bp < last_dash; bp++) {
if (*bp != '-') {
- bit = name_to_mod_mask(*bp);
+ bit = name_to_mod_mask((uint8_t)(*bp));
if (bit == 0x0) {
break; // Illegal modifier name
}
@@ -704,7 +704,7 @@ int find_special_key(const char **const srcp, const size_t src_len, int *const m
if (STRNICMP(last_dash + 1, "char-", 5) == 0
&& ascii_isdigit(last_dash[6])) {
// <Char-123> or <Char-033> or <Char-0x33>
- vim_str2nr((char *)last_dash + 6, NULL, &l, STR2NR_ALL, NULL, &n, 0, true);
+ vim_str2nr(last_dash + 6, NULL, &l, STR2NR_ALL, NULL, &n, 0, true);
if (l == 0) {
emsg(_(e_invarg));
return 0;
@@ -718,12 +718,12 @@ int find_special_key(const char **const srcp, const size_t src_len, int *const m
// Special case for a double-quoted string
off = l = 2;
} else {
- l = utfc_ptr2len((char *)last_dash + 1);
+ l = utfc_ptr2len(last_dash + 1);
}
if (modifiers != 0 && last_dash[l + 1] == '>') {
- key = utf_ptr2char((char *)last_dash + off);
+ key = utf_ptr2char(last_dash + off);
} else {
- key = get_special_key_code(last_dash + off);
+ key = get_special_key_code((char_u *)last_dash + off);
if (!(flags & FSK_KEEP_X_KEY)) {
key = handle_x_keys(key);
}
@@ -753,7 +753,7 @@ int find_special_key(const char **const srcp, const size_t src_len, int *const m
}
*modp = modifiers;
- *srcp = (char *)end_of_name;
+ *srcp = end_of_name;
return key;
} // else { ELOG("unknown key: '%s'", src); }
}
@@ -944,7 +944,7 @@ char *replace_termcodes(const char *const from, const size_t from_len, char **co
}
}
- slen = trans_special(&src, (size_t)(end - src) + 1, (char_u *)result + dlen,
+ slen = trans_special(&src, (size_t)(end - src) + 1, result + dlen,
FSK_KEYCODE | ((flags & REPTERM_NO_SIMPLIFY) ? 0 : FSK_SIMPLIFY),
true, did_simplify);
if (slen) {
@@ -1059,8 +1059,8 @@ char *vim_strsave_escape_ks(char *p)
// Need a buffer to hold up to three times as much. Four in case of an
// illegal utf-8 byte:
// 0xc0 -> 0xc3 - 0x80 -> 0xc3 K_SPECIAL KS_SPECIAL KE_FILLER
- char_u *res = xmalloc(strlen(p) * 4 + 1);
- char_u *d = res;
+ char *res = xmalloc(strlen(p) * 4 + 1);
+ char_u *d = (char_u *)res;
for (char_u *s = (char_u *)p; *s != NUL;) {
if (s[0] == K_SPECIAL && s[1] != NUL && s[2] != NUL) {
// Copy special key unmodified.
@@ -1076,7 +1076,7 @@ char *vim_strsave_escape_ks(char *p)
}
*d = NUL;
- return (char *)res;
+ return res;
}
/// Remove escaping from K_SPECIAL characters. Reverse of
diff --git a/src/nvim/linematch.c b/src/nvim/linematch.c
index 629a31c913..a9dac40731 100644
--- a/src/nvim/linematch.c
+++ b/src/nvim/linematch.c
@@ -9,7 +9,6 @@
#include "nvim/linematch.h"
#include "nvim/macros.h"
#include "nvim/memory.h"
-#include "nvim/vim.h"
// struct for running the diff linematch algorithm
typedef struct {
diff --git a/src/nvim/locale.c b/src/nvim/locale.c
index 6322271073..c3cfd3bedb 100644
--- a/src/nvim/locale.c
+++ b/src/nvim/locale.c
@@ -294,7 +294,7 @@ static char **find_locales(void)
if (locale_a == NULL) {
return NULL;
}
- ga_init(&locales_ga, sizeof(char_u *), 20);
+ ga_init(&locales_ga, sizeof(char *), 20);
// Transform locale_a string where each locale is separated by "\n"
// into an array of locale strings.
@@ -308,7 +308,7 @@ static char **find_locales(void)
xfree(locale_a);
// Guarantee that .ga_data is NULL terminated
ga_grow(&locales_ga, 1);
- ((char_u **)locales_ga.ga_data)[locales_ga.ga_len] = NULL;
+ ((char **)locales_ga.ga_data)[locales_ga.ga_len] = NULL;
return locales_ga.ga_data;
}
# endif
diff --git a/src/nvim/lua/converter.c b/src/nvim/lua/converter.c
index 3c129fe7ce..6160b84485 100644
--- a/src/nvim/lua/converter.c
+++ b/src/nvim/lua/converter.c
@@ -391,7 +391,7 @@ nlua_pop_typval_table_processing_end:
case LUA_TFUNCTION: {
LuaRef func = nlua_ref_global(lstate, -1);
- char *name = (char *)register_luafunc(func);
+ char *name = register_luafunc(func);
cur.tv->v_type = VAR_FUNC;
cur.tv->vval.v_string = xstrdup(name);
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index 12ddbd094f..1415ceeaed 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -49,6 +49,7 @@
#include "nvim/message.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/option_defs.h"
+#include "nvim/os/fileio.h"
#include "nvim/os/os.h"
#include "nvim/path.h"
#include "nvim/pos.h"
@@ -56,7 +57,6 @@
#include "nvim/runtime.h"
#include "nvim/strings.h"
#include "nvim/ui.h"
-#include "nvim/ui_compositor.h"
#include "nvim/undo.h"
#include "nvim/usercmd.h"
#include "nvim/version.h"
@@ -64,6 +64,7 @@
#include "nvim/window.h"
static int in_fast_callback = 0;
+static bool in_script = false;
// Initialized in nlua_init().
static lua_State *global_lstate = NULL;
@@ -133,8 +134,13 @@ static void nlua_error(lua_State *const lstate, const char *const msg)
str = lua_tolstring(lstate, -1, &len);
}
- msg_ext_set_kind("lua_error");
- semsg_multiline(msg, (int)len, str);
+ if (in_script) {
+ os_errmsg(str);
+ os_errmsg("\n");
+ } else {
+ msg_ext_set_kind("lua_error");
+ semsg_multiline(msg, (int)len, str);
+ }
lua_pop(lstate, 1);
}
@@ -534,7 +540,7 @@ int nlua_get_global_ref_count(void)
return nlua_global_refs->ref_count;
}
-static void nlua_common_vim_init(lua_State *lstate, bool is_thread)
+static void nlua_common_vim_init(lua_State *lstate, bool is_thread, bool is_standalone)
FUNC_ATTR_NONNULL_ARG(1)
{
nlua_ref_state_t *ref_state = nlua_new_ref_state(lstate, is_thread);
@@ -567,7 +573,9 @@ static void nlua_common_vim_init(lua_State *lstate, bool is_thread)
lua_setfield(lstate, -2, "_empty_dict_mt");
// vim.loop
- if (is_thread) {
+ if (is_standalone) {
+ // do nothing, use libluv like in a standalone interpreter
+ } else if (is_thread) {
luv_set_callback(lstate, nlua_luv_thread_cb_cfpcall);
luv_set_thread(lstate, nlua_luv_thread_cfpcall);
luv_set_cthread(lstate, nlua_luv_thread_cfcpcall);
@@ -606,7 +614,7 @@ static int nlua_module_preloader(lua_State *lstate)
return 1;
}
-static bool nlua_init_packages(lua_State *lstate)
+static bool nlua_init_packages(lua_State *lstate, bool is_standalone)
FUNC_ATTR_NONNULL_ALL
{
// put builtin packages in preload
@@ -618,7 +626,7 @@ static bool nlua_init_packages(lua_State *lstate)
lua_pushcclosure(lstate, nlua_module_preloader, 1); // [package, preload, cclosure]
lua_setfield(lstate, -2, def.name); // [package, preload]
- if (nlua_disable_preload && strequal(def.name, "vim.inspect")) {
+ if ((nlua_disable_preload && !is_standalone) && strequal(def.name, "vim.inspect")) {
break;
}
}
@@ -769,7 +777,7 @@ static bool nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
lua_pushcfunction(lstate, &nlua_ui_detach);
lua_setfield(lstate, -2, "ui_detach");
- nlua_common_vim_init(lstate, false);
+ nlua_common_vim_init(lstate, false, false);
// patch require() (only for --startuptime)
if (time_fd != NULL) {
@@ -788,7 +796,7 @@ static bool nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
lua_setglobal(lstate, "vim");
- if (!nlua_init_packages(lstate)) {
+ if (!nlua_init_packages(lstate, false)) {
return false;
}
@@ -813,6 +821,9 @@ void nlua_init(char **argv, int argc, int lua_arg0)
luaL_openlibs(lstate);
if (!nlua_state_init(lstate)) {
os_errmsg(_("E970: Failed to initialize builtin lua modules\n"));
+#ifdef EXITFREE
+ nlua_common_free_all_mem(lstate);
+#endif
os_exit(1);
}
@@ -824,9 +835,28 @@ void nlua_init(char **argv, int argc, int lua_arg0)
static lua_State *nlua_thread_acquire_vm(void)
{
+ return nlua_init_state(true);
+}
+
+void nlua_run_script(char **argv, int argc, int lua_arg0)
+ FUNC_ATTR_NORETURN
+{
+ in_script = true;
+ global_lstate = nlua_init_state(false);
+ luv_set_thread_cb(nlua_thread_acquire_vm, nlua_common_free_all_mem);
+ nlua_init_argv(global_lstate, argv, argc, lua_arg0);
+ bool lua_ok = nlua_exec_file(argv[lua_arg0 - 1]);
+#ifdef EXITFREE
+ nlua_free_all_mem();
+#endif
+ exit(lua_ok ? 0 : 1);
+}
+
+lua_State *nlua_init_state(bool thread)
+{
// If it is called from the main thread, it will attempt to rebuild the cache.
const uv_thread_t self = uv_thread_self();
- if (uv_thread_equal(&main_thread, &self)) {
+ if (!in_script && uv_thread_equal(&main_thread, &self)) {
runtime_search_path_validate();
}
@@ -835,9 +865,11 @@ static lua_State *nlua_thread_acquire_vm(void)
// Add in the lua standard libraries
luaL_openlibs(lstate);
- // print
- lua_pushcfunction(lstate, &nlua_print);
- lua_setglobal(lstate, "print");
+ if (!in_script) {
+ // print
+ lua_pushcfunction(lstate, &nlua_print);
+ lua_setglobal(lstate, "print");
+ }
lua_pushinteger(lstate, 0);
lua_setfield(lstate, LUA_REGISTRYINDEX, "nlua.refcount");
@@ -845,18 +877,20 @@ static lua_State *nlua_thread_acquire_vm(void)
// vim
lua_newtable(lstate);
- nlua_common_vim_init(lstate, true);
+ nlua_common_vim_init(lstate, thread, in_script);
nlua_state_add_stdlib(lstate, true);
- lua_createtable(lstate, 0, 0);
- lua_pushcfunction(lstate, nlua_thr_api_nvim__get_runtime);
- lua_setfield(lstate, -2, "nvim__get_runtime");
- lua_setfield(lstate, -2, "api");
+ if (!in_script) {
+ lua_createtable(lstate, 0, 0);
+ lua_pushcfunction(lstate, nlua_thr_api_nvim__get_runtime);
+ lua_setfield(lstate, -2, "nvim__get_runtime");
+ lua_setfield(lstate, -2, "api");
+ }
lua_setglobal(lstate, "vim");
- nlua_init_packages(lstate);
+ nlua_init_packages(lstate, in_script);
lua_getglobal(lstate, "package");
lua_getfield(lstate, -1, "loaded");
@@ -1440,11 +1474,11 @@ int nlua_source_using_linegetter(LineGetter fgetline, void *cookie, char *name)
estack_push(ETYPE_SCRIPT, name, 0);
garray_T ga;
- char_u *line = NULL;
+ char *line = NULL;
- ga_init(&ga, (int)sizeof(char_u *), 10);
- while ((line = (char_u *)fgetline(0, cookie, 0, false)) != NULL) {
- GA_APPEND(char_u *, &ga, line);
+ ga_init(&ga, (int)sizeof(char *), 10);
+ while ((line = fgetline(0, cookie, 0, false)) != NULL) {
+ GA_APPEND(char *, &ga, line);
}
char *code = ga_concat_strings_sep(&ga, "\n");
size_t len = strlen(code);
@@ -1877,7 +1911,7 @@ int nlua_expand_pat(expand_T *xp, char *pat, int *num_results, char ***results)
goto cleanup_array;
}
- GA_APPEND(char_u *, &result_array, (char_u *)string_to_cstr(v.data.string));
+ GA_APPEND(char *, &result_array, string_to_cstr(v.data.string));
}
xp->xp_pattern += prefix_len;
@@ -1914,7 +1948,7 @@ bool nlua_is_table_from_lua(const typval_T *const arg)
}
}
-char_u *nlua_register_table_as_callable(const typval_T *const arg)
+char *nlua_register_table_as_callable(const typval_T *const arg)
{
LuaRef table_ref = LUA_NOREF;
if (arg->v_type == VAR_DICT) {
@@ -1950,7 +1984,7 @@ char_u *nlua_register_table_as_callable(const typval_T *const arg)
LuaRef func = nlua_ref_global(lstate, -1);
- char_u *name = register_luafunc(func);
+ char *name = register_luafunc(func);
lua_pop(lstate, 1); // []
assert(top == lua_gettop(lstate));
@@ -1960,8 +1994,8 @@ char_u *nlua_register_table_as_callable(const typval_T *const arg)
void nlua_execute_on_key(int c)
{
- char_u buf[NUMBUFLEN];
- size_t buf_len = special_to_buf(c, mod_mask, false, buf);
+ char buf[NUMBUFLEN];
+ size_t buf_len = special_to_buf(c, mod_mask, false, (char_u *)buf);
lua_State *const lstate = global_lstate;
@@ -1977,7 +2011,7 @@ void nlua_execute_on_key(int c)
luaL_checktype(lstate, -1, LUA_TFUNCTION);
// [ vim, vim._on_key, buf ]
- lua_pushlstring(lstate, (const char *)buf, buf_len);
+ lua_pushlstring(lstate, buf, buf_len);
int save_got_int = got_int;
got_int = false; // avoid interrupts when the key typed is Ctrl-C
diff --git a/src/nvim/lua/spell.c b/src/nvim/lua/spell.c
index 0a566b2f86..d510d25e90 100644
--- a/src/nvim/lua/spell.c
+++ b/src/nvim/lua/spell.c
@@ -61,7 +61,7 @@ int nlua_spell_check(lua_State *lstate)
while (*str != NUL) {
attr = HLF_COUNT;
- len = spell_check(curwin, (char_u *)str, &attr, &capcol, false);
+ len = spell_check(curwin, (char *)str, &attr, &capcol, false);
assert(len <= INT_MAX);
if (attr != HLF_COUNT) {
diff --git a/src/nvim/lua/stdlib.c b/src/nvim/lua/stdlib.c
index dac96790d7..6ebca6d97e 100644
--- a/src/nvim/lua/stdlib.c
+++ b/src/nvim/lua/stdlib.c
@@ -40,17 +40,17 @@
# include "lua/stdlib.c.generated.h"
#endif
-static int regex_match(lua_State *lstate, regprog_T **prog, char_u *str)
+static int regex_match(lua_State *lstate, regprog_T **prog, char *str)
{
regmatch_T rm;
rm.regprog = *prog;
rm.rm_ic = false;
- bool match = vim_regexec(&rm, (char *)str, 0);
+ bool match = vim_regexec(&rm, str, 0);
*prog = rm.regprog;
if (match) {
- lua_pushinteger(lstate, (lua_Integer)(rm.startp[0] - (char *)str));
- lua_pushinteger(lstate, (lua_Integer)(rm.endp[0] - (char *)str));
+ lua_pushinteger(lstate, (lua_Integer)(rm.startp[0] - str));
+ lua_pushinteger(lstate, (lua_Integer)(rm.endp[0] - str));
return 2;
}
return 0;
@@ -60,7 +60,7 @@ static int regex_match_str(lua_State *lstate)
{
regprog_T **prog = regex_check(lstate);
const char *str = luaL_checkstring(lstate, 2);
- int nret = regex_match(lstate, prog, (char_u *)str);
+ int nret = regex_match(lstate, prog, (char *)str);
if (!*prog) {
return luaL_error(lstate, "regex: internal error");
@@ -116,7 +116,7 @@ static int regex_match_line(lua_State *lstate)
line[end] = NUL;
}
- int nret = regex_match(lstate, prog, (char_u *)line + start);
+ int nret = regex_match(lstate, prog, line + start);
if (end >= 0) {
line[end] = save;
@@ -198,7 +198,7 @@ static int nlua_str_utf_pos(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
size_t idx = 1;
size_t clen;
for (size_t i = 0; i < s1_len && s1[i] != NUL; i += clen) {
- clen = (size_t)utf_ptr2len_len((const char_u *)(s1) + i, (int)(s1_len - i));
+ clen = (size_t)utf_ptr2len_len(s1 + i, (int)(s1_len - i));
lua_pushinteger(lstate, (long)i + 1);
lua_rawseti(lstate, -2, (int)idx);
idx++;
@@ -266,8 +266,7 @@ int nlua_str_byteindex(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
use_utf16 = lua_toboolean(lstate, 3);
}
- ssize_t byteidx = mb_utf_index_to_bytes((const char_u *)s1, s1_len,
- (size_t)idx, use_utf16);
+ ssize_t byteidx = mb_utf_index_to_bytes(s1, s1_len, (size_t)idx, use_utf16);
if (byteidx == -1) {
return luaL_error(lstate, "index out of range");
}
@@ -483,8 +482,6 @@ static int nlua_stricmp(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
return 1;
}
-#if defined(HAVE_ICONV)
-
/// Convert string from one encoding to another
static int nlua_iconv(lua_State *lstate)
{
@@ -503,14 +500,14 @@ static int nlua_iconv(lua_State *lstate)
size_t str_len = 0;
const char *str = lua_tolstring(lstate, 1, &str_len);
- char_u *from = (char_u *)enc_canonize(enc_skip((char *)lua_tolstring(lstate, 2, NULL)));
- char_u *to = (char_u *)enc_canonize(enc_skip((char *)lua_tolstring(lstate, 3, NULL)));
+ char *from = enc_canonize(enc_skip((char *)lua_tolstring(lstate, 2, NULL)));
+ char *to = enc_canonize(enc_skip((char *)lua_tolstring(lstate, 3, NULL)));
vimconv_T vimconv;
vimconv.vc_type = CONV_NONE;
- convert_setup_ext(&vimconv, (char *)from, false, (char *)to, false);
+ convert_setup_ext(&vimconv, from, false, to, false);
- char_u *ret = (char_u *)string_convert(&vimconv, (char *)str, &str_len);
+ char *ret = string_convert(&vimconv, (char *)str, &str_len);
convert_setup(&vimconv, NULL, NULL);
@@ -520,15 +517,13 @@ static int nlua_iconv(lua_State *lstate)
if (ret == NULL) {
lua_pushnil(lstate);
} else {
- lua_pushlstring(lstate, (char *)ret, str_len);
+ lua_pushlstring(lstate, ret, str_len);
xfree(ret);
}
return 1;
}
-#endif
-
void nlua_state_add_stdlib(lua_State *const lstate, bool is_thread)
{
if (!is_thread) {
@@ -575,12 +570,10 @@ void nlua_state_add_stdlib(lua_State *const lstate, bool is_thread)
luaopen_spell(lstate);
lua_setfield(lstate, -2, "spell");
-#if defined(HAVE_ICONV)
// vim.iconv
// depends on p_ambw, p_emoji
lua_pushcfunction(lstate, &nlua_iconv);
lua_setfield(lstate, -2, "iconv");
-#endif
}
// vim.mpack
diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c
index fecf746036..56f4daed1a 100644
--- a/src/nvim/lua/treesitter.c
+++ b/src/nvim/lua/treesitter.c
@@ -182,8 +182,8 @@ int tslua_add_language(lua_State *L)
uv_lib_t lib;
if (uv_dlopen(path, &lib)) {
- snprintf(IObuff, IOSIZE, "Failed to load parser: uv_dlopen: %s",
- uv_dlerror(&lib));
+ snprintf(IObuff, IOSIZE, "Failed to load parser for language '%s': uv_dlopen: %s",
+ lang_name, uv_dlerror(&lib));
uv_dlclose(&lib);
lua_pushstring(L, IObuff);
return lua_error(L);
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 6f14a00949..e26922bf8e 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -10,7 +10,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <time.h>
#include "auto/config.h"
#include "nvim/arglist.h"
@@ -62,7 +61,6 @@
#include "nvim/os/fileio.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
-#include "nvim/os/pty_process.h"
#include "nvim/os/stdpaths_defs.h"
#include "nvim/os/time.h"
#include "nvim/path.h"
@@ -97,7 +95,6 @@
#include "nvim/msgpack_rpc/helpers.h"
#include "nvim/msgpack_rpc/server.h"
#include "nvim/os/signal.h"
-#include "nvim/tui/tui.h"
// values for "window_layout"
enum {
@@ -242,6 +239,14 @@ int main(int argc, char **argv)
argv0 = argv[0];
+ if (argc > 1 && STRICMP(argv[1], "-ll") == 0) {
+ if (argc == 2) {
+ print_mainerr(err_arg_missing, argv[1]);
+ exit(1);
+ }
+ nlua_run_script(argv, argc, 3);
+ }
+
char *fname = NULL; // file name from command line
mparm_T params; // various parameters passed between
// main() and other functions.
@@ -289,7 +294,13 @@ int main(int argc, char **argv)
}
}
- bool use_builtin_ui = (!headless_mode && !embedded_mode && !silent_mode);
+#ifdef MSWIN
+ // on windows we use CONIN special file, thus we don't know this yet.
+ bool has_term = true;
+#else
+ bool has_term = (stdin_isatty || stdout_isatty || stderr_isatty);
+#endif
+ bool use_builtin_ui = (has_term && !headless_mode && !embedded_mode && !silent_mode);
// don't bind the server yet, if we are using builtin ui.
// This will be done when nvim server has been forked from the ui process
@@ -305,7 +316,7 @@ int main(int argc, char **argv)
bool remote_ui = (ui_client_channel_id != 0);
if (use_builtin_ui && !remote_ui) {
- ui_client_forward_stdin = !params.input_isatty;
+ ui_client_forward_stdin = !stdin_isatty;
uint64_t rv = ui_client_start_server(params.argc, params.argv);
if (!rv) {
os_errmsg("Failed to start Nvim server!\n");
@@ -362,8 +373,8 @@ int main(int argc, char **argv)
debug_break_level = params.use_debug_break_level;
// Read ex-commands if invoked with "-es".
- if (!params.input_isatty && !params.input_istext && silent_mode && exmode_active) {
- input_start(STDIN_FILENO);
+ if (!stdin_isatty && !params.input_istext && silent_mode && exmode_active) {
+ input_start();
}
if (ui_client_channel_id) {
@@ -542,7 +553,9 @@ int main(int argc, char **argv)
if (params.diff_mode) {
// set options in each window for "nvim -d".
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- diff_win_options(wp, true);
+ if (!wp->w_arg_idx_invalid) {
+ diff_win_options(wp, true);
+ }
}
}
@@ -579,6 +592,7 @@ int main(int argc, char **argv)
if (use_builtin_ui) {
os_icon_init();
}
+ os_title_save();
#endif
// Adjust default register name for "unnamed" in 'clipboard'. Can only be
@@ -640,8 +654,8 @@ void os_exit(int r)
if (!event_teardown() && r == 0) {
r = 1; // Exit with error if main_loop did not teardown gracefully.
}
- if (input_global_fd() >= 0) {
- stream_set_blocking(input_global_fd(), true); // normalize stream (#2598)
+ if (used_stdin) {
+ stream_set_blocking(STDIN_FILENO, true); // normalize stream (#2598)
}
ILOG("Nvim exit: %d", r);
@@ -760,7 +774,7 @@ void getout(int exitval)
// Apply 'titleold'.
if (p_title && *p_titleold != NUL) {
- ui_call_set_title(cstr_as_string((char *)p_titleold));
+ ui_call_set_title(cstr_as_string(p_titleold));
}
if (garbage_collect_at_exit) {
@@ -770,6 +784,7 @@ void getout(int exitval)
#ifdef MSWIN
// Restore Windows console icon before exiting.
os_icon_set(NULL, NULL);
+ os_title_reset();
#endif
os_exit(exitval);
@@ -786,9 +801,9 @@ void preserve_exit(void)
// Prevent repeated calls into this method.
if (really_exiting) {
- if (input_global_fd() >= 0) {
+ if (used_stdin) {
// normalize stream (#2598)
- stream_set_blocking(input_global_fd(), true);
+ stream_set_blocking(STDIN_FILENO, true);
}
exit(2);
}
@@ -796,6 +811,11 @@ void preserve_exit(void)
really_exiting = true;
// Ignore SIGHUP while we are already exiting. #9274
signal_reject_deadly();
+
+ if (ui_client_channel_id) {
+ os_exit(1);
+ }
+
os_errmsg(IObuff);
os_errmsg("\n");
ui_flush();
@@ -880,7 +900,7 @@ static void remote_request(mparm_T *params, int remote_args, char *server_addr,
os_errmsg("Remote ui failed to start: ");
os_errmsg(connect_error);
os_errmsg("\n");
- exit(1);
+ os_exit(1);
}
ui_client_channel_id = chan;
@@ -964,7 +984,7 @@ static bool edit_stdin(mparm_T *parmp)
bool implicit = !headless_mode
&& !(embedded_mode && stdin_fd <= 0)
&& (!exmode_active || parmp->input_istext)
- && !parmp->input_isatty
+ && !stdin_isatty
&& parmp->scriptin == NULL; // `-s -` was not given.
return parmp->had_stdin_file || implicit;
}
@@ -1450,11 +1470,9 @@ static void init_startuptime(mparm_T *paramp)
static void check_and_set_isatty(mparm_T *paramp)
{
- stdin_isatty
- = paramp->input_isatty = os_isatty(STDIN_FILENO);
- stdout_isatty
- = paramp->output_isatty = os_isatty(STDOUT_FILENO);
- paramp->err_isatty = os_isatty(STDERR_FILENO);
+ stdin_isatty = os_isatty(STDIN_FILENO);
+ stdout_isatty = os_isatty(STDOUT_FILENO);
+ stderr_isatty = os_isatty(STDERR_FILENO);
TIME_MSG("window checked");
}
@@ -1506,7 +1524,7 @@ static void handle_quickfix(mparm_T *paramp)
set_string_option_direct("ef", -1, paramp->use_ef, OPT_FREE, SID_CARG);
}
vim_snprintf(IObuff, IOSIZE, "cfile %s", p_ef);
- if (qf_init(NULL, (char *)p_ef, p_efm, true, IObuff, p_menc) < 0) {
+ if (qf_init(NULL, p_ef, p_efm, true, IObuff, p_menc) < 0) {
msg_putchar('\n');
os_exit(3);
}
@@ -2106,6 +2124,12 @@ static int execute_env(char *env)
static void mainerr(const char *errstr, const char *str)
FUNC_ATTR_NORETURN
{
+ print_mainerr(errstr, str);
+ os_exit(1);
+}
+
+static void print_mainerr(const char *errstr, const char *str)
+{
char *prgname = path_tail(argv0);
signal_stop(); // kill us with CTRL-C here, if you like
@@ -2121,8 +2145,6 @@ static void mainerr(const char *errstr, const char *str)
os_errmsg(_("\nMore info with \""));
os_errmsg(prgname);
os_errmsg(" -h\"\n");
-
- os_exit(1);
}
/// Prints version information for "nvim -v" or "nvim --version".
diff --git a/src/nvim/main.h b/src/nvim/main.h
index 46d7217364..2d54837872 100644
--- a/src/nvim/main.h
+++ b/src/nvim/main.h
@@ -30,10 +30,7 @@ typedef struct {
char *tagname; // tag from -t argument
char *use_ef; // 'errorfile' from -q argument
- bool input_isatty; // stdin is a terminal
bool input_istext; // stdin is text, not executable (-E/-Es)
- bool output_isatty; // stdout is a terminal
- bool err_isatty; // stderr is a terminal
int no_swap_file; // "-n" argument used
int use_debug_break_level;
diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c
index 04a0107fe8..831d1299a8 100644
--- a/src/nvim/mapping.c
+++ b/src/nvim/mapping.c
@@ -5,6 +5,7 @@
#include <assert.h>
#include <inttypes.h>
+#include <lauxlib.h>
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
@@ -17,6 +18,7 @@
#include "nvim/ascii.h"
#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
+#include "nvim/cmdexpand.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
@@ -38,6 +40,7 @@
#include "nvim/pos.h"
#include "nvim/regexp.h"
#include "nvim/runtime.h"
+#include "nvim/search.h"
#include "nvim/strings.h"
#include "nvim/vim.h"
@@ -1196,7 +1199,7 @@ static char_u *translate_mapping(char_u *str, int cpo_flags)
}
if (c) {
- ga_append(&ga, (char)c);
+ ga_append(&ga, (uint8_t)c);
}
}
ga_append(&ga, NUL);
@@ -1267,93 +1270,135 @@ char_u *set_context_in_map_cmd(expand_T *xp, char *cmd, char *arg, bool forceit,
/// Find all mapping/abbreviation names that match regexp "regmatch".
/// For command line expansion of ":[un]map" and ":[un]abbrev" in all modes.
/// @return OK if matches found, FAIL otherwise.
-int ExpandMappings(regmatch_T *regmatch, int *num_file, char ***file)
+int ExpandMappings(char *pat, regmatch_T *regmatch, int *numMatches, char ***matches)
{
- mapblock_T *mp;
- int hash;
- int count;
- int round;
- char *p;
- int i;
-
- *num_file = 0; // return values in case of FAIL
- *file = NULL;
-
- // round == 1: Count the matches.
- // round == 2: Build the array to keep the matches.
- for (round = 1; round <= 2; round++) {
- count = 0;
-
- for (i = 0; i < 7; i++) {
- if (i == 0) {
- p = "<silent>";
- } else if (i == 1) {
- p = "<unique>";
- } else if (i == 2) {
- p = "<script>";
- } else if (i == 3) {
- p = "<expr>";
- } else if (i == 4 && !expand_buffer) {
- p = "<buffer>";
- } else if (i == 5) {
- p = "<nowait>";
- } else if (i == 6) {
- p = "<special>";
- } else {
+ const bool fuzzy = cmdline_fuzzy_complete(pat);
+
+ *numMatches = 0; // return values in case of FAIL
+ *matches = NULL;
+
+ garray_T ga;
+ if (!fuzzy) {
+ ga_init(&ga, sizeof(char *), 3);
+ } else {
+ ga_init(&ga, sizeof(fuzmatch_str_T), 3);
+ }
+
+ // First search in map modifier arguments
+ for (int i = 0; i < 7; i++) {
+ char *p;
+ if (i == 0) {
+ p = "<silent>";
+ } else if (i == 1) {
+ p = "<unique>";
+ } else if (i == 2) {
+ p = "<script>";
+ } else if (i == 3) {
+ p = "<expr>";
+ } else if (i == 4 && !expand_buffer) {
+ p = "<buffer>";
+ } else if (i == 5) {
+ p = "<nowait>";
+ } else if (i == 6) {
+ p = "<special>";
+ } else {
+ continue;
+ }
+
+ bool match;
+ int score = 0;
+ if (!fuzzy) {
+ match = vim_regexec(regmatch, p, (colnr_T)0);
+ } else {
+ score = fuzzy_match_str(p, pat);
+ match = (score != 0);
+ }
+
+ if (!match) {
+ continue;
+ }
+
+ if (fuzzy) {
+ GA_APPEND(fuzmatch_str_T, &ga, ((fuzmatch_str_T){
+ .idx = ga.ga_len,
+ .str = xstrdup(p),
+ .score = score,
+ }));
+ } else {
+ GA_APPEND(char *, &ga, xstrdup(p));
+ }
+ }
+
+ for (int hash = 0; hash < 256; hash++) {
+ mapblock_T *mp;
+ if (expand_isabbrev) {
+ if (hash > 0) { // only one abbrev list
+ break; // for (hash)
+ }
+ mp = first_abbr;
+ } else if (expand_buffer) {
+ mp = curbuf->b_maphash[hash];
+ } else {
+ mp = maphash[hash];
+ }
+ for (; mp; mp = mp->m_next) {
+ if (!(mp->m_mode & expand_mapmodes)) {
continue;
}
- if (vim_regexec(regmatch, p, (colnr_T)0)) {
- if (round == 1) {
- count++;
- } else {
- (*file)[count++] = xstrdup(p);
- }
+ char *p = (char *)translate_mapping((char_u *)mp->m_keys, CPO_TO_CPO_FLAGS);
+ if (p == NULL) {
+ continue;
}
- }
- for (hash = 0; hash < 256; hash++) {
- if (expand_isabbrev) {
- if (hash > 0) { // only one abbrev list
- break; // for (hash)
- }
- mp = first_abbr;
- } else if (expand_buffer) {
- mp = curbuf->b_maphash[hash];
+ bool match;
+ int score = 0;
+ if (!fuzzy) {
+ match = vim_regexec(regmatch, p, (colnr_T)0);
} else {
- mp = maphash[hash];
+ score = fuzzy_match_str(p, pat);
+ match = (score != 0);
}
- for (; mp; mp = mp->m_next) {
- if (mp->m_mode & expand_mapmodes) {
- p = (char *)translate_mapping((char_u *)mp->m_keys, CPO_TO_CPO_FLAGS);
- if (p != NULL && vim_regexec(regmatch, p, (colnr_T)0)) {
- if (round == 1) {
- count++;
- } else {
- (*file)[count++] = p;
- p = NULL;
- }
- }
- xfree(p);
- }
- } // for (mp)
- } // for (hash)
- if (count == 0) { // no match found
- break; // for (round)
- }
+ if (!match) {
+ xfree(p);
+ continue;
+ }
- if (round == 1) {
- *file = xmalloc((size_t)count * sizeof(char *));
- }
- } // for (round)
+ if (fuzzy) {
+ GA_APPEND(fuzmatch_str_T, &ga, ((fuzmatch_str_T){
+ .idx = ga.ga_len,
+ .str = p,
+ .score = score,
+ }));
+ } else {
+ GA_APPEND(char *, &ga, p);
+ }
+ } // for (mp)
+ } // for (hash)
+ if (ga.ga_len == 0) {
+ return FAIL;
+ }
+
+ if (!fuzzy) {
+ *matches = ga.ga_data;
+ *numMatches = ga.ga_len;
+ } else {
+ fuzzymatches_to_strmatches(ga.ga_data, matches, ga.ga_len, false);
+ *numMatches = ga.ga_len;
+ }
+
+ int count = *numMatches;
if (count > 1) {
// Sort the matches
- sort_strings(*file, count);
+ // Fuzzy matching already sorts the matches
+ if (!fuzzy) {
+ sort_strings(*matches, count);
+ }
// Remove multiple entries
- char **ptr1 = *file;
+ char **ptr1 = *matches;
char **ptr2 = ptr1 + 1;
char **ptr3 = ptr1 + count;
@@ -1367,7 +1412,7 @@ int ExpandMappings(regmatch_T *regmatch, int *num_file, char ***file)
}
}
- *num_file = count;
+ *numMatches = count;
return count == 0 ? FAIL : OK;
}
@@ -1806,9 +1851,9 @@ int makemap(FILE *fd, buf_T *buf)
}
if (putc(' ', fd) < 0
- || put_escstr(fd, (char_u *)mp->m_keys, 0) == FAIL
+ || put_escstr(fd, mp->m_keys, 0) == FAIL
|| putc(' ', fd) < 0
- || put_escstr(fd, (char_u *)mp->m_str, 1) == FAIL
+ || put_escstr(fd, mp->m_str, 1) == FAIL
|| put_eol(fd) < 0) {
return FAIL;
}
@@ -1834,9 +1879,9 @@ int makemap(FILE *fd, buf_T *buf)
// "what": 0 for :map lhs, 1 for :map rhs, 2 for :set
//
// return FAIL for failure, OK otherwise
-int put_escstr(FILE *fd, char_u *strstart, int what)
+int put_escstr(FILE *fd, char *strstart, int what)
{
- char_u *str = strstart;
+ char_u *str = (char_u *)strstart;
int c;
// :map xx <Nop>
@@ -1913,7 +1958,7 @@ int put_escstr(FILE *fd, char_u *strstart, int what)
}
} else if (c < ' ' || c > '~' || c == '|'
|| (what == 0 && c == ' ')
- || (what == 1 && str == strstart && c == ' ')
+ || (what == 1 && str == (char_u *)strstart && c == ' ')
|| (what != 2 && c == '<')) {
if (putc(Ctrl_V, fd) < 0) {
return FAIL;
diff --git a/src/nvim/mark.c b/src/nvim/mark.c
index b98935e93d..f1a1f25e6c 100644
--- a/src/nvim/mark.c
+++ b/src/nvim/mark.c
@@ -5,6 +5,7 @@
#include <assert.h>
#include <limits.h>
+#include <stdint.h>
#include <stdio.h>
#include <string.h>
@@ -39,7 +40,6 @@
#include "nvim/sign.h"
#include "nvim/strings.h"
#include "nvim/textobject.h"
-#include "nvim/types.h"
#include "nvim/undo_defs.h"
#include "nvim/vim.h"
@@ -1380,18 +1380,21 @@ void mark_col_adjust(linenr_T lnum, colnr_T mincol, linenr_T lnum_amount, long c
// When deleting lines, this may create duplicate marks in the
// jumplist. They will be removed here for the specified window.
-// When "checktail" is true, removes tail jump if it matches current position.
-void cleanup_jumplist(win_T *wp, bool checktail)
+// When "loadfiles" is true first ensure entries have the "fnum" field set
+// (this may be a bit slow).
+void cleanup_jumplist(win_T *wp, bool loadfiles)
{
int i;
- // Load all the files from the jump list. This is
- // needed to properly clean up duplicate entries, but will take some
- // time.
- for (i = 0; i < wp->w_jumplistlen; i++) {
- if ((wp->w_jumplist[i].fmark.fnum == 0)
- && (wp->w_jumplist[i].fmark.mark.lnum != 0)) {
- fname2fnum(&wp->w_jumplist[i]);
+ if (loadfiles) {
+ // If specified, load all the files from the jump list. This is
+ // needed to properly clean up duplicate entries, but will take some
+ // time.
+ for (i = 0; i < wp->w_jumplistlen; i++) {
+ if ((wp->w_jumplist[i].fmark.fnum == 0)
+ && (wp->w_jumplist[i].fmark.mark.lnum != 0)) {
+ fname2fnum(&wp->w_jumplist[i]);
+ }
}
}
@@ -1439,8 +1442,8 @@ void cleanup_jumplist(win_T *wp, bool checktail)
// When pointer is below last jump, remove the jump if it matches the current
// line. This avoids useless/phantom jumps. #9805
- if (checktail && wp->w_jumplistlen
- && wp->w_jumplistidx == wp->w_jumplistlen) {
+ if (loadfiles // otherwise (i.e.: Shada), last entry should be kept
+ && wp->w_jumplistlen && wp->w_jumplistidx == wp->w_jumplistlen) {
const xfmark_T *fm_last = &wp->w_jumplist[wp->w_jumplistlen - 1];
if (fm_last->fmark.fnum == curbuf->b_fnum
&& fm_last->fmark.mark.lnum == wp->w_cursor.lnum) {
diff --git a/src/nvim/marktree.c b/src/nvim/marktree.c
index 2036ddd21d..77ba6e6fa4 100644
--- a/src/nvim/marktree.c
+++ b/src/nvim/marktree.c
@@ -1182,7 +1182,7 @@ static size_t check_node(MarkTree *b, mtnode_t *x, mtpos_t *last, bool *last_rig
assert(x->ptr[i] != x->ptr[j]);
}
}
- } else {
+ } else if (x->n > 0) {
*last = x->key[x->n - 1].pos;
}
return n_keys;
diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c
index 93ac0fccfa..8b50ba719a 100644
--- a/src/nvim/mbyte.c
+++ b/src/nvim/mbyte.c
@@ -100,8 +100,8 @@ static char e_list_item_nr_cell_width_invalid[]
= N_("E1112: List item %d cell width invalid");
static char e_overlapping_ranges_for_nr[]
= N_("E1113: Overlapping ranges for 0x%lx");
-static char e_only_values_of_0x100_and_higher_supported[]
- = N_("E1114: Only values of 0x100 and higher supported");
+static char e_only_values_of_0x80_and_higher_supported[]
+ = N_("E1114: Only values of 0x80 and higher supported");
// To speed up BYTELEN(); keep a lookup table to quickly get the length in
// bytes of a UTF-8 character from the first byte of a UTF-8 string. Bytes
@@ -406,9 +406,9 @@ int bomb_size(void)
}
// Remove all BOM from "s" by moving remaining text.
-void remove_bom(char_u *s)
+void remove_bom(char *s)
{
- char *p = (char *)s;
+ char *p = s;
while ((p = strchr(p, 0xef)) != NULL) {
if ((uint8_t)p[1] == 0xbb && (uint8_t)p[2] == 0xbf) {
@@ -482,12 +482,16 @@ static bool intable(const struct interval *table, size_t n_items, int c)
/// gen_unicode_tables.lua, which must be manually invoked as needed.
int utf_char2cells(int c)
{
- if (c >= 0x100) {
+ // Use the value from setcellwidths() at 0x80 and higher, unless the
+ // character is not printable.
+ if (c >= 0x80 && vim_isprintc(c)) {
int n = cw_value(c);
if (n != 0) {
return n;
}
+ }
+ if (c >= 0x100) {
if (!utf_printable(c)) {
return 6; // unprintable, displays <xxxx>
}
@@ -540,7 +544,7 @@ int utf_ptr2cells_len(const char *p, int size)
// Need to convert to a wide character.
if (size > 0 && (uint8_t)(*p) >= 0x80) {
- if (utf_ptr2len_len((char_u *)p, size) < utf8len_tab[(uint8_t)(*p)]) {
+ if (utf_ptr2len_len(p, size) < utf8len_tab[(uint8_t)(*p)]) {
return 1; // truncated
}
c = utf_ptr2char((char *)p);
@@ -566,8 +570,8 @@ size_t mb_string2cells(const char *str)
{
size_t clen = 0;
- for (const char_u *p = (char_u *)str; *p != NUL; p += utfc_ptr2len((char *)p)) {
- clen += (size_t)utf_ptr2cells((char *)p);
+ for (const char *p = str; *p != NUL; p += utfc_ptr2len(p)) {
+ clen += (size_t)utf_ptr2cells(p);
}
return clen;
@@ -584,9 +588,9 @@ size_t mb_string2cells_len(const char *str, size_t size)
{
size_t clen = 0;
- for (const char_u *p = (char_u *)str; *p != NUL && p < (char_u *)str + size;
- p += utfc_ptr2len_len((char *)p, (int)size + (int)(p - (char_u *)str))) {
- clen += (size_t)utf_ptr2cells((char *)p);
+ for (const char *p = str; *p != NUL && p < str + size;
+ p += utfc_ptr2len_len(p, (int)size + (int)(p - str))) {
+ clen += (size_t)utf_ptr2cells(p);
}
return clen;
@@ -699,23 +703,23 @@ static int utf_safe_read_char_adv(const char_u **s, size_t *n)
// Get character at **pp and advance *pp to the next character.
// Note: composing characters are skipped!
-int mb_ptr2char_adv(const char_u **const pp)
+int mb_ptr2char_adv(const char **const pp)
{
int c;
- c = utf_ptr2char((char *)(*pp));
- *pp += utfc_ptr2len((char *)(*pp));
+ c = utf_ptr2char(*pp);
+ *pp += utfc_ptr2len(*pp);
return c;
}
// Get character at **pp and advance *pp to the next character.
// Note: composing characters are returned as separate characters.
-int mb_cptr2char_adv(const char_u **pp)
+int mb_cptr2char_adv(const char **pp)
{
int c;
- c = utf_ptr2char((char *)(*pp));
- *pp += utf_ptr2len((char *)(*pp));
+ c = utf_ptr2char(*pp);
+ *pp += utf_ptr2len(*pp);
return c;
}
@@ -785,7 +789,7 @@ int utfc_ptr2char_len(const char *p, int *pcc, int maxlen)
int i = 0;
- int len = utf_ptr2len_len((char_u *)p, maxlen);
+ int len = utf_ptr2len_len(p, maxlen);
// Is it safe to use utf_ptr2char()?
bool safe = len > 1 && len <= maxlen;
int c = safe ? utf_ptr2char(p) : (uint8_t)(*p);
@@ -793,7 +797,7 @@ int utfc_ptr2char_len(const char *p, int *pcc, int maxlen)
// Only accept a composing char when the first char isn't illegal.
if ((safe || c < 0x80) && len < maxlen && (uint8_t)p[len] >= 0x80) {
for (; i < MAX_MCO; i++) {
- int len_cc = utf_ptr2len_len((char_u *)p + len, maxlen - len);
+ int len_cc = utf_ptr2len_len(p + len, maxlen - len);
safe = len_cc > 1 && len_cc <= maxlen - len;
if (!safe || (pcc[i] = utf_ptr2char(p + len)) < 0x80
|| !(i == 0 ? utf_composinglike(p, p + len) : utf_iscomposing(pcc[i]))) {
@@ -848,13 +852,13 @@ int utf_byte2len(int b)
// Returns 1 for an illegal byte sequence (also in incomplete byte seq.).
// Returns number > "size" for an incomplete byte sequence.
// Never returns zero.
-int utf_ptr2len_len(const char_u *p, int size)
+int utf_ptr2len_len(const char *p, int size)
{
int len;
int i;
int m;
- len = utf8len_tab[*p];
+ len = utf8len_tab[(uint8_t)(*p)];
if (len == 1) {
return 1; // NUL, ascii or illegal lead byte
}
@@ -925,7 +929,7 @@ int utfc_ptr2len_len(const char *p, int size)
}
// Skip over first UTF-8 char, stopping at a NUL byte.
- len = utf_ptr2len_len((char_u *)p, size);
+ len = utf_ptr2len_len(p, size);
// Check for illegal byte and incomplete byte sequence.
if ((len == 1 && (uint8_t)p[0] >= 0x80) || len > size) {
@@ -944,7 +948,7 @@ int utfc_ptr2len_len(const char *p, int size)
// Next character length should not go beyond size to ensure that
// utf_composinglike(...) does not read beyond size.
- len_next_char = utf_ptr2len_len((char_u *)p + len, size - len);
+ len_next_char = utf_ptr2len_len(p + len, size - len);
if (len_next_char > size - len) {
break;
}
@@ -1462,7 +1466,7 @@ void mb_utflen(const char *s, size_t len, size_t *codepoints, size_t *codeunits)
size_t count = 0, extra = 0;
size_t clen;
for (size_t i = 0; i < len; i += clen) {
- clen = (size_t)utf_ptr2len_len((char_u *)s + i, (int)(len - i));
+ clen = (size_t)utf_ptr2len_len(s + i, (int)(len - i));
// NB: gets the byte value of invalid sequence bytes.
// we only care whether the char fits in the BMP or not
int c = (clen > 1) ? utf_ptr2char(s + i) : (uint8_t)s[i];
@@ -1475,7 +1479,7 @@ void mb_utflen(const char *s, size_t len, size_t *codepoints, size_t *codeunits)
*codeunits += count + extra;
}
-ssize_t mb_utf_index_to_bytes(const char_u *s, size_t len, size_t index, bool use_utf16_units)
+ssize_t mb_utf_index_to_bytes(const char *s, size_t len, size_t index, bool use_utf16_units)
FUNC_ATTR_NONNULL_ALL
{
size_t count = 0;
@@ -1487,7 +1491,7 @@ ssize_t mb_utf_index_to_bytes(const char_u *s, size_t len, size_t index, bool us
clen = (size_t)utf_ptr2len_len(s + i, (int)(len - i));
// NB: gets the byte value of invalid sequence bytes.
// we only care whether the char fits in the BMP or not
- int c = (clen > 1) ? utf_ptr2char((char *)s + i) : s[i];
+ int c = (clen > 1) ? utf_ptr2char(s + i) : (uint8_t)s[i];
count++;
if (use_utf16_units && c > 0xFFFF) {
count++;
@@ -1534,14 +1538,14 @@ void show_utf8(void)
{
int len;
int rlen = 0;
- char_u *line;
+ char *line;
int clen;
int i;
// Get the byte length of the char under the cursor, including composing
// characters.
- line = (char_u *)get_cursor_pos_ptr();
- len = utfc_ptr2len((char *)line);
+ line = get_cursor_pos_ptr();
+ len = utfc_ptr2len(line);
if (len == 0) {
msg("NUL");
return;
@@ -1555,10 +1559,10 @@ void show_utf8(void)
STRCPY(IObuff + rlen, "+ ");
rlen += 2;
}
- clen = utf_ptr2len((char *)line + i);
+ clen = utf_ptr2len(line + i);
}
sprintf(IObuff + rlen, "%02x ", // NOLINT(runtime/printf)
- (line[i] == NL) ? NUL : line[i]); // NUL is stored as NL
+ (line[i] == NL) ? NUL : (uint8_t)line[i]); // NUL is stored as NL
clen--;
rlen += (int)strlen(IObuff + rlen);
if (rlen > IOSIZE - 20) {
@@ -1787,7 +1791,7 @@ void mb_copy_char(const char **const fp, char **const tp)
/// Return the offset from "p_in" to the first byte of a character. When "p_in" is
/// at the start of a character 0 is returned, otherwise the offset to the next
/// character. Can start anywhere in a stream of bytes.
-int mb_off_next(const char_u *base, const char *p_in)
+int mb_off_next(const char *base, const char *p_in)
{
const uint8_t *p = (uint8_t *)p_in;
int i;
@@ -1801,7 +1805,7 @@ int mb_off_next(const char_u *base, const char *p_in)
for (i = 0; (p[i] & 0xc0) == 0x80; i++) {}
if (i > 0) {
// Check for illegal sequence.
- for (j = 0; p - j > base; j++) {
+ for (j = 0; p - j > (uint8_t *)base; j++) {
if ((p[-j] & 0xc0) != 0x80) {
break;
}
@@ -1884,7 +1888,7 @@ void utf_find_illegal(void)
char *p;
int len;
vimconv_T vimconv;
- char_u *tofree = NULL;
+ char *tofree = NULL;
vimconv.vc_type = CONV_NONE;
if (enc_canon_props(curbuf->b_p_fenc) & ENC_8BIT) {
@@ -1899,11 +1903,11 @@ void utf_find_illegal(void)
p = get_cursor_pos_ptr();
if (vimconv.vc_type != CONV_NONE) {
xfree(tofree);
- tofree = (char_u *)string_convert(&vimconv, p, NULL);
+ tofree = string_convert(&vimconv, p, NULL);
if (tofree == NULL) {
break;
}
- p = (char *)tofree;
+ p = tofree;
}
while (*p != NUL) {
@@ -1916,7 +1920,7 @@ void utf_find_illegal(void)
} else {
int l;
- len = (int)(p - (char *)tofree);
+ len = (int)(p - tofree);
for (p = get_cursor_pos_ptr(); *p != NUL && len-- > 0; p += l) {
l = utf_ptr2len(p);
curwin->w_cursor.col += l;
@@ -2024,7 +2028,7 @@ char *mb_prevptr(char *line, char *p)
/// following composing characters) counts as one.
int mb_charlen(const char *str)
{
- const char_u *p = (char_u *)str;
+ const char *p = str;
int count;
if (p == NULL) {
@@ -2032,20 +2036,20 @@ int mb_charlen(const char *str)
}
for (count = 0; *p != NUL; count++) {
- p += utfc_ptr2len((char *)p);
+ p += utfc_ptr2len(p);
}
return count;
}
/// Like mb_charlen() but for a string with specified length.
-int mb_charlen_len(const char_u *str, int len)
+int mb_charlen_len(const char *str, int len)
{
- const char_u *p = str;
+ const char *p = str;
int count;
for (count = 0; *p != NUL && p < str + len; count++) {
- p += utfc_ptr2len((char *)p);
+ p += utfc_ptr2len(p);
}
return count;
@@ -2196,7 +2200,7 @@ static int enc_alias_search(const char *name)
// Get the canonicalized encoding of the current locale.
// Returns an allocated string when successful, NULL when not.
-char_u *enc_locale(void)
+char *enc_locale(void)
{
int i;
char buf[50];
@@ -2232,7 +2236,7 @@ char_u *enc_locale(void)
const char *p = vim_strchr(s, '.');
if (p != NULL) {
if (p > s + 2 && !STRNICMP(p + 1, "EUC", 3)
- && !isalnum((int)p[4]) && p[4] != '-' && p[-3] == '_') {
+ && !isalnum((uint8_t)p[4]) && p[4] != '-' && p[-3] == '_') {
// Copy "XY.EUC" to "euc-XY" to buf[10].
memmove(buf, "euc-", 4);
buf[4] = (char)(ASCII_ISALNUM(p[-2]) ? TOLOWER_ASC(p[-2]) : 0);
@@ -2256,20 +2260,18 @@ enc_locale_copy_enc:
buf[i] = NUL;
}
- return (char_u *)enc_canonize(buf);
+ return enc_canonize(buf);
}
-#if defined(HAVE_ICONV)
-
// Call iconv_open() with a check if iconv() works properly (there are broken
// versions).
// Returns (void *)-1 if failed.
// (should return iconv_t, but that causes problems with prototypes).
-void *my_iconv_open(char_u *to, char_u *from)
+void *my_iconv_open(char *to, char *from)
{
iconv_t fd;
-# define ICONV_TESTLEN 400
- char_u tobuf[ICONV_TESTLEN];
+#define ICONV_TESTLEN 400
+ char tobuf[ICONV_TESTLEN];
char *p;
size_t tolen;
static WorkingStatus iconv_working = kUnknown;
@@ -2277,7 +2279,7 @@ void *my_iconv_open(char_u *to, char_u *from)
if (iconv_working == kBroken) {
return (void *)-1; // detected a broken iconv() previously
}
- fd = iconv_open(enc_skip((char *)to), enc_skip((char *)from));
+ fd = iconv_open(enc_skip(to), enc_skip(from));
if (fd != (iconv_t)-1 && iconv_working == kUnknown) {
// Do a dummy iconv() call to check if it actually works. There is a
@@ -2285,7 +2287,7 @@ void *my_iconv_open(char_u *to, char_u *from)
// because it's wide-spread. The symptoms are that after outputting
// the initial shift state the "to" pointer is NULL and conversion
// stops for no apparent reason after about 8160 characters.
- p = (char *)tobuf;
+ p = tobuf;
tolen = ICONV_TESTLEN;
(void)iconv(fd, NULL, NULL, &p, &tolen);
if (p == NULL) {
@@ -2305,8 +2307,8 @@ void *my_iconv_open(char_u *to, char_u *from)
// sequence and set "*unconvlenp" to the length of it.
// Returns the converted string in allocated memory. NULL for an error.
// If resultlenp is not NULL, sets it to the result length in bytes.
-static char_u *iconv_string(const vimconv_T *const vcp, const char_u *str, size_t slen,
- size_t *unconvlenp, size_t *resultlenp)
+static char *iconv_string(const vimconv_T *const vcp, const char *str, size_t slen,
+ size_t *unconvlenp, size_t *resultlenp)
{
const char *from;
size_t fromlen;
@@ -2314,11 +2316,11 @@ static char_u *iconv_string(const vimconv_T *const vcp, const char_u *str, size_
size_t tolen;
size_t len = 0;
size_t done = 0;
- char_u *result = NULL;
- char_u *p;
+ char *result = NULL;
+ char *p;
int l;
- from = (char *)str;
+ from = str;
fromlen = slen;
for (;;) {
if (len == 0 || ICONV_ERRNO == ICONV_E2BIG) {
@@ -2333,7 +2335,7 @@ static char_u *iconv_string(const vimconv_T *const vcp, const char_u *str, size_
result = p;
}
- to = (char *)result + done;
+ to = result + done;
tolen = len - done - 2;
// Avoid a warning for systems with a wrong iconv() prototype by
// casting the second argument to void *.
@@ -2373,17 +2375,15 @@ static char_u *iconv_string(const vimconv_T *const vcp, const char_u *str, size_
break;
}
// Not enough room or skipping illegal sequence.
- done = (size_t)(to - (char *)result);
+ done = (size_t)(to - result);
}
if (resultlenp != NULL && result != NULL) {
- *resultlenp = (size_t)(to - (char *)result);
+ *resultlenp = (size_t)(to - result);
}
return result;
}
-#endif // HAVE_ICONV
-
/// Setup "vcp" for conversion from "from" to "to".
/// The names must have been made canonical with enc_canonize().
/// vcp->vc_type must have been initialized to CONV_NONE.
@@ -2408,11 +2408,9 @@ int convert_setup_ext(vimconv_T *vcp, char *from, bool from_unicode_is_utf8, cha
int to_is_utf8;
// Reset to no conversion.
-#ifdef HAVE_ICONV
if (vcp->vc_type == CONV_ICONV && vcp->vc_fd != (iconv_t)-1) {
iconv_close(vcp->vc_fd);
}
-#endif
*vcp = (vimconv_T)MBYTE_NONE_CONV;
// No conversion when one of the names is empty or they are equal.
@@ -2448,18 +2446,15 @@ int convert_setup_ext(vimconv_T *vcp, char *from, bool from_unicode_is_utf8, cha
} else if (from_is_utf8 && (to_prop & ENC_LATIN9)) {
// Internal utf-8 -> latin9 conversion.
vcp->vc_type = CONV_TO_LATIN9;
- }
-#ifdef HAVE_ICONV
- else { // NOLINT(readability/braces)
+ } else {
// Use iconv() for conversion.
- vcp->vc_fd = (iconv_t)my_iconv_open(to_is_utf8 ? (char_u *)"utf-8" : (char_u *)to,
- from_is_utf8 ? (char_u *)"utf-8" : (char_u *)from);
+ vcp->vc_fd = (iconv_t)my_iconv_open(to_is_utf8 ? "utf-8" : to,
+ from_is_utf8 ? "utf-8" : from);
if (vcp->vc_fd != (iconv_t)-1) {
vcp->vc_type = CONV_ICONV;
vcp->vc_factor = 4; // could be longer too...
}
}
-#endif
if (vcp->vc_type == CONV_NONE) {
return FAIL;
}
@@ -2474,14 +2469,13 @@ int convert_setup_ext(vimconv_T *vcp, char *from, bool from_unicode_is_utf8, cha
/// When something goes wrong, NULL is returned and "*lenp" is unchanged.
char *string_convert(const vimconv_T *const vcp, char *ptr, size_t *lenp)
{
- return (char *)string_convert_ext(vcp, (char_u *)ptr, lenp, NULL);
+ return string_convert_ext(vcp, ptr, lenp, NULL);
}
// Like string_convert(), but when "unconvlenp" is not NULL and there are is
// an incomplete sequence at the end it is not converted and "*unconvlenp" is
// set to the number of remaining bytes.
-char_u *string_convert_ext(const vimconv_T *const vcp, char_u *ptr, size_t *lenp,
- size_t *unconvlenp)
+char *string_convert_ext(const vimconv_T *const vcp, char *ptr, size_t *lenp, size_t *unconvlenp)
{
char_u *retval = NULL;
char_u *d;
@@ -2490,12 +2484,12 @@ char_u *string_convert_ext(const vimconv_T *const vcp, char_u *ptr, size_t *lenp
size_t len;
if (lenp == NULL) {
- len = strlen((char *)ptr);
+ len = strlen(ptr);
} else {
len = *lenp;
}
if (len == 0) {
- return (char_u *)xstrdup("");
+ return xstrdup("");
}
switch (vcp->vc_type) {
@@ -2503,7 +2497,7 @@ char_u *string_convert_ext(const vimconv_T *const vcp, char_u *ptr, size_t *lenp
retval = xmalloc(len * 2 + 1);
d = retval;
for (size_t i = 0; i < len; i++) {
- c = ptr[i];
+ c = (uint8_t)ptr[i];
if (c < 0x80) {
*d++ = (char_u)c;
} else {
@@ -2521,7 +2515,7 @@ char_u *string_convert_ext(const vimconv_T *const vcp, char_u *ptr, size_t *lenp
retval = xmalloc(len * 3 + 1);
d = retval;
for (size_t i = 0; i < len; i++) {
- c = ptr[i];
+ c = (uint8_t)ptr[i];
switch (c) {
case 0xa4:
c = 0x20ac; break; // euro
@@ -2557,7 +2551,7 @@ char_u *string_convert_ext(const vimconv_T *const vcp, char_u *ptr, size_t *lenp
if (l == 0) {
*d++ = NUL;
} else if (l == 1) {
- uint8_t l_w = utf8len_tab_zero[ptr[i]];
+ uint8_t l_w = utf8len_tab_zero[(uint8_t)ptr[i]];
if (l_w == 0) {
// Illegal utf-8 byte cannot be converted
@@ -2569,9 +2563,9 @@ char_u *string_convert_ext(const vimconv_T *const vcp, char_u *ptr, size_t *lenp
*unconvlenp = len - i;
break;
}
- *d++ = ptr[i];
+ *d++ = (uint8_t)ptr[i];
} else {
- c = utf_ptr2char((char *)ptr + i);
+ c = utf_ptr2char(ptr + i);
if (vcp->vc_type == CONV_TO_LATIN9) {
switch (c) {
case 0x20ac:
@@ -2623,14 +2617,12 @@ char_u *string_convert_ext(const vimconv_T *const vcp, char_u *ptr, size_t *lenp
}
break;
-#ifdef HAVE_ICONV
case CONV_ICONV: // conversion with vcp->vc_fd
- retval = iconv_string(vcp, ptr, len, unconvlenp, lenp);
+ retval = (char_u *)iconv_string(vcp, ptr, len, unconvlenp, lenp);
break;
-#endif
}
- return retval;
+ return (char *)retval;
}
/// Table set by setcellwidths().
@@ -2709,7 +2701,7 @@ void f_setcellwidths(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (li_tv->v_type != VAR_LIST || li_tv->vval.v_list == NULL) {
semsg(_(e_list_item_nr_is_not_list), item);
- xfree(ptrs);
+ xfree((void *)ptrs);
return;
}
@@ -2725,25 +2717,25 @@ void f_setcellwidths(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
if (i == 0) {
n1 = lili_tv->vval.v_number;
- if (n1 < 0x100) {
- emsg(_(e_only_values_of_0x100_and_higher_supported));
- xfree(ptrs);
+ if (n1 < 0x80) {
+ emsg(_(e_only_values_of_0x80_and_higher_supported));
+ xfree((void *)ptrs);
return;
}
} else if (i == 1 && lili_tv->vval.v_number < n1) {
semsg(_(e_list_item_nr_range_invalid), item);
- xfree(ptrs);
+ xfree((void *)ptrs);
return;
} else if (i == 2 && (lili_tv->vval.v_number < 1 || lili_tv->vval.v_number > 2)) {
semsg(_(e_list_item_nr_cell_width_invalid), item);
- xfree(ptrs);
+ xfree((void *)ptrs);
return;
}
}
if (i != 3) {
semsg(_(e_list_item_nr_does_not_contain_3_numbers), item);
- xfree(ptrs);
+ xfree((void *)ptrs);
return;
}
@@ -2762,7 +2754,7 @@ void f_setcellwidths(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
const varnumber_T n1 = TV_LIST_ITEM_TV(lili)->vval.v_number;
if (item > 0 && n1 <= table[item - 1].last) {
semsg(_(e_overlapping_ranges_for_nr), (long)n1);
- xfree(ptrs);
+ xfree((void *)ptrs);
xfree(table);
return;
}
@@ -2773,7 +2765,7 @@ void f_setcellwidths(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
table[item].width = (char)TV_LIST_ITEM_TV(lili)->vval.v_number;
}
- xfree(ptrs);
+ xfree((void *)ptrs);
cw_interval_T *const cw_table_save = cw_table;
const size_t cw_table_size_save = cw_table_size;
@@ -2795,6 +2787,21 @@ void f_setcellwidths(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
redraw_all_later(UPD_NOT_VALID);
}
+/// "getcellwidths()" function
+void f_getcellwidths(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
+{
+ tv_list_alloc_ret(rettv, (ptrdiff_t)cw_table_size);
+
+ for (size_t i = 0; i < cw_table_size; i++) {
+ list_T *entry = tv_list_alloc(3);
+ tv_list_append_number(entry, (varnumber_T)cw_table[i].first);
+ tv_list_append_number(entry, (varnumber_T)cw_table[i].last);
+ tv_list_append_number(entry, (varnumber_T)cw_table[i].width);
+
+ tv_list_append_list(rettv->vval.v_list, entry);
+ }
+}
+
void f_charclass(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (tv_check_for_string_arg(argvars, 0) == FAIL
diff --git a/src/nvim/mbyte_defs.h b/src/nvim/mbyte_defs.h
index 53b01a211f..e913e20f9f 100644
--- a/src/nvim/mbyte_defs.h
+++ b/src/nvim/mbyte_defs.h
@@ -46,9 +46,7 @@ typedef enum {
typedef struct {
int vc_type; ///< Zero or more ConvFlags.
int vc_factor; ///< Maximal expansion factor.
-#ifdef HAVE_ICONV
iconv_t vc_fd; ///< Value for CONV_ICONV.
-#endif
bool vc_fail; ///< What to do with invalid characters: if true, fail,
///< otherwise use '?'.
} vimconv_T;
diff --git a/src/nvim/memfile.c b/src/nvim/memfile.c
index 61d7893948..46be9ccea5 100644
--- a/src/nvim/memfile.c
+++ b/src/nvim/memfile.c
@@ -62,7 +62,6 @@
#include "nvim/os/os.h"
#include "nvim/path.h"
#include "nvim/pos.h"
-#include "nvim/types.h"
#include "nvim/vim.h"
#define MEMFILE_PAGE_SIZE 4096 /// default page size
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index eee3b9d517..b3fc64a68c 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -149,7 +149,7 @@ struct data_block {
#define DB_INDEX_MASK (~DB_MARKED)
#define INDEX_SIZE (sizeof(unsigned)) // size of one db_index entry
-#define HEADER_SIZE (sizeof(DATA_BL) - INDEX_SIZE) // size of data block header
+#define HEADER_SIZE (offsetof(DATA_BL, db_index)) // size of data block header
enum {
B0_FNAME_SIZE_ORG = 900, // what it was in older versions
@@ -749,7 +749,7 @@ void ml_recover(bool checkext)
int len = (int)strlen(fname);
if (checkext && len >= 4
&& STRNICMP(fname + len - 4, ".s", 2) == 0
- && vim_strchr("abcdefghijklmnopqrstuvw", TOLOWER_ASC(fname[len - 2])) != NULL
+ && vim_strchr("abcdefghijklmnopqrstuvw", TOLOWER_ASC((uint8_t)fname[len - 2])) != NULL
&& ASCII_ISALPHA(fname[len - 1])) {
directly = true;
fname_used = xstrdup(fname); // make a copy for mf_open()
@@ -757,7 +757,7 @@ void ml_recover(bool checkext)
directly = false;
// count the number of matching swap files
- len = recover_names((char_u *)fname, false, 0, NULL);
+ len = recover_names(fname, false, 0, NULL);
if (len == 0) { // no swap files found
semsg(_("E305: No swap file found for %s"), fname);
goto theend;
@@ -767,7 +767,7 @@ void ml_recover(bool checkext)
i = 1;
} else { // several swap files found, choose
// list the names of the swap files
- (void)recover_names((char_u *)fname, true, 0, NULL);
+ (void)recover_names(fname, true, 0, NULL);
msg_putchar('\n');
msg_puts(_("Enter number of swap file to use (0 to quit): "));
i = get_number(false, NULL);
@@ -776,7 +776,7 @@ void ml_recover(bool checkext)
}
}
// get the swap file name that will be used
- (void)recover_names((char_u *)fname, false, i, &fname_used);
+ (void)recover_names(fname, false, i, &fname_used);
}
if (fname_used == NULL) {
goto theend; // user chose invalid number.
@@ -1201,24 +1201,24 @@ theend:
/// @param list when true, list the swap file names
/// @param nr when non-zero, return nr'th swap file name
/// @param fname_out result when "nr" > 0
-int recover_names(char_u *fname, int list, int nr, char **fname_out)
+int recover_names(char *fname, int list, int nr, char **fname_out)
{
int num_names;
char *(names[6]);
- char_u *tail;
+ char *tail;
char *p;
int file_count = 0;
char **files;
- char_u *fname_res = NULL;
+ char *fname_res = NULL;
#ifdef HAVE_READLINK
- char_u fname_buf[MAXPATHL];
+ char fname_buf[MAXPATHL];
#endif
if (fname != NULL) {
#ifdef HAVE_READLINK
// Expand symlink in the file name, because the swap file is created
// with the actual file instead of with the symlink.
- if (resolve_symlink((char *)fname, (char *)fname_buf) == OK) {
+ if (resolve_symlink(fname, fname_buf) == OK) {
fname_res = fname_buf;
} else
#endif
@@ -1250,7 +1250,7 @@ int recover_names(char_u *fname, int list, int nr, char **fname_out)
names[2] = xstrdup(".sw?");
num_names = 3;
} else {
- num_names = recov_file_names(names, (char *)fname_res, true);
+ num_names = recov_file_names(names, fname_res, true);
}
} else { // check directory dir_name
if (fname == NULL) {
@@ -1267,13 +1267,12 @@ int recover_names(char_u *fname, int list, int nr, char **fname_out)
&& len > 1
&& p[-1] == p[-2]) {
// Ends with '//', Use Full path for swap name
- tail = (char_u *)make_percent_swname(dir_name,
- (char *)fname_res);
+ tail = make_percent_swname(dir_name, fname_res);
} else {
- tail = (char_u *)path_tail((char *)fname_res);
- tail = (char_u *)concat_fnames(dir_name, (char *)tail, true);
+ tail = path_tail(fname_res);
+ tail = concat_fnames(dir_name, tail, true);
}
- num_names = recov_file_names(names, (char *)tail, false);
+ num_names = recov_file_names(names, tail, false);
xfree(tail);
}
}
@@ -1290,11 +1289,11 @@ int recover_names(char_u *fname, int list, int nr, char **fname_out)
// not able to execute the shell).
// Try finding a swap file by simply adding ".swp" to the file name.
if (*dirp == NUL && file_count + num_files == 0 && fname != NULL) {
- char_u *swapname = (char_u *)modname((char *)fname_res, ".swp", true);
+ char *swapname = modname(fname_res, ".swp", true);
if (swapname != NULL) {
- if (os_path_exists((char *)swapname)) {
- files = xmalloc(sizeof(char_u *));
- files[0] = (char *)swapname;
+ if (os_path_exists(swapname)) {
+ files = xmalloc(sizeof(char *));
+ files[0] = swapname;
swapname = NULL;
num_files = 1;
}
@@ -1877,7 +1876,7 @@ int ml_append(linenr_T lnum, char *line, colnr_T len, bool newfile)
/// @param line text of the new line
/// @param len length of new line, including NUL, or 0
/// @param newfile flag, see above
-int ml_append_buf(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, bool newfile)
+int ml_append_buf(buf_T *buf, linenr_T lnum, char *line, colnr_T len, bool newfile)
FUNC_ATTR_NONNULL_ARG(1)
{
if (buf->b_ml.ml_mfp == NULL) {
@@ -1887,7 +1886,7 @@ int ml_append_buf(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, bool new
if (buf->b_ml.ml_line_lnum != 0) {
ml_flush_line(buf);
}
- return ml_append_int(buf, lnum, (char *)line, len, newfile, false);
+ return ml_append_int(buf, lnum, line, len, newfile, false);
}
/// @param lnum append after this line (can be 0)
@@ -2721,7 +2720,8 @@ static bhdr_T *ml_new_ptr(memfile_T *mfp)
PTR_BL *pp = hp->bh_data;
pp->pb_id = PTR_ID;
pp->pb_count = 0;
- pp->pb_count_max = (uint16_t)((mfp->mf_page_size - sizeof(PTR_BL)) / sizeof(PTR_EN) + 1);
+ pp->pb_count_max
+ = (uint16_t)((mfp->mf_page_size - offsetof(PTR_BL, pb_pointer)) / sizeof(PTR_EN));
return hp;
}
@@ -3000,7 +3000,7 @@ int resolve_symlink(const char *fname, char *buf)
// If it's relative, build a new path based on the directory
// portion of the filename (if any) and the path the symlink
// points to.
- if (path_is_absolute((char_u *)buf)) {
+ if (path_is_absolute(buf)) {
STRCPY(tmp, buf);
} else {
char *tail = path_tail(tmp);
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index aa8314b23d..5356300382 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -31,7 +31,6 @@
#include "nvim/message.h"
#include "nvim/sign.h"
#include "nvim/ui.h"
-#include "nvim/ui_compositor.h"
#include "nvim/usercmd.h"
#include "nvim/vim.h"
diff --git a/src/nvim/menu.c b/src/nvim/menu.c
index 0fa45ac24a..2a18b08d8d 100644
--- a/src/nvim/menu.c
+++ b/src/nvim/menu.c
@@ -6,6 +6,7 @@
#include <assert.h>
#include <stdbool.h>
+#include <stdint.h>
#include <string.h>
#include "nvim/ascii.h"
diff --git a/src/nvim/message.c b/src/nvim/message.c
index de4acd601f..3b3dfcd5b6 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -2514,7 +2514,7 @@ static void store_sb_text(char **sb_str, char *s, int attr, int *sb_col, int fin
}
if (s > *sb_str) {
- mp = xmalloc((sizeof(msgchunk_T) + (size_t)(s - *sb_str)));
+ mp = xmalloc(offsetof(msgchunk_T, sb_text) + (size_t)(s - *sb_str) + 1);
mp->sb_eol = (char)finish;
mp->sb_msg_col = *sb_col;
mp->sb_attr = attr;
@@ -3006,7 +3006,7 @@ static int do_more_prompt(int typed_char)
#if defined(MSWIN)
/// Headless (no UI) error message handler.
-static void do_msg(char *str, bool errmsg)
+static void do_msg(const char *str, bool errmsg)
{
static bool did_err = false;
assert(str != NULL);
@@ -3026,13 +3026,13 @@ static void do_msg(char *str, bool errmsg)
}
}
-void os_errmsg(char *str)
+void os_errmsg(const char *str)
{
do_msg(str, true);
}
/// Headless (no UI) message handler.
-void os_msg(char *str)
+void os_msg(const char *str)
{
do_msg(str, false);
}
diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c
index b7d15fe9af..950b025e53 100644
--- a/src/nvim/mouse.c
+++ b/src/nvim/mouse.c
@@ -3,6 +3,7 @@
#include <assert.h>
#include <stdbool.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -85,17 +86,17 @@ static int get_mouse_class(char *p)
/// Move "pos" back to the start of the word it's in.
static void find_start_of_word(pos_T *pos)
{
- char_u *line;
+ char *line;
int cclass;
int col;
- line = (char_u *)ml_get(pos->lnum);
- cclass = get_mouse_class((char *)line + pos->col);
+ line = ml_get(pos->lnum);
+ cclass = get_mouse_class(line + pos->col);
while (pos->col > 0) {
col = pos->col - 1;
- col -= utf_head_off((char *)line, (char *)line + col);
- if (get_mouse_class((char *)line + col) != cclass) {
+ col -= utf_head_off(line, line + col);
+ if (get_mouse_class(line + col) != cclass) {
break;
}
pos->col = col;
@@ -106,19 +107,19 @@ static void find_start_of_word(pos_T *pos)
/// When 'selection' is "exclusive", the position is just after the word.
static void find_end_of_word(pos_T *pos)
{
- char_u *line;
+ char *line;
int cclass;
int col;
- line = (char_u *)ml_get(pos->lnum);
+ line = ml_get(pos->lnum);
if (*p_sel == 'e' && pos->col > 0) {
pos->col--;
- pos->col -= utf_head_off((char *)line, (char *)line + pos->col);
+ pos->col -= utf_head_off(line, line + pos->col);
}
- cclass = get_mouse_class((char *)line + pos->col);
+ cclass = get_mouse_class(line + pos->col);
while (line[pos->col] != NUL) {
- col = pos->col + utfc_ptr2len((char *)line + pos->col);
- if (get_mouse_class((char *)line + col) != cclass) {
+ col = pos->col + utfc_ptr2len(line + pos->col);
+ if (get_mouse_class(line + col) != cclass) {
if (*p_sel == 'e') {
pos->col = col;
}
@@ -1539,16 +1540,16 @@ colnr_T vcol2col(win_T *const wp, const linenr_T lnum, const colnr_T vcol)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
// try to advance to the specified column
- char_u *line = (char_u *)ml_get_buf(wp->w_buffer, lnum, false);
+ char *line = ml_get_buf(wp->w_buffer, lnum, false);
chartabsize_T cts;
- init_chartabsize_arg(&cts, wp, lnum, 0, (char *)line, (char *)line);
+ init_chartabsize_arg(&cts, wp, lnum, 0, line, line);
while (cts.cts_vcol < vcol && *cts.cts_ptr != NUL) {
cts.cts_vcol += win_lbr_chartabsize(&cts, NULL);
MB_PTR_ADV(cts.cts_ptr);
}
clear_chartabsize_arg(&cts);
- return (colnr_T)((char_u *)cts.cts_ptr - line);
+ return (colnr_T)(cts.cts_ptr - line);
}
/// Set UI mouse depending on current mode and 'mouse'.
@@ -1574,10 +1575,10 @@ static void set_mouse_topline(win_T *wp)
static colnr_T scroll_line_len(linenr_T lnum)
{
colnr_T col = 0;
- char_u *line = (char_u *)ml_get(lnum);
+ char *line = ml_get(lnum);
if (*line != NUL) {
for (;;) {
- int numchar = win_chartabsize(curwin, (char *)line, col);
+ int numchar = win_chartabsize(curwin, line, col);
MB_PTR_ADV(line);
if (*line == NUL) { // don't count the last character
break;
@@ -1679,10 +1680,10 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
// highlighting the second byte, not the ninth.
linenr_T lnum = wp->w_cursor.lnum;
- char_u *line = (char_u *)ml_get(lnum);
- char_u *ptr = line;
- char_u *ptr_end;
- char_u *ptr_row_offset = line; // Where we begin adjusting `ptr_end`
+ char *line = ml_get(lnum);
+ char *ptr = line;
+ char *ptr_end;
+ char *ptr_row_offset = line; // Where we begin adjusting `ptr_end`
// Find the offset where scanning should begin.
int offset = wp->w_leftcol;
@@ -1700,8 +1701,8 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
// checked for concealed characters.
vcol = 0;
while (vcol < offset && *ptr != NUL) {
- vcol += win_chartabsize(curwin, (char *)ptr, vcol);
- ptr += utfc_ptr2len((char *)ptr);
+ vcol += win_chartabsize(curwin, ptr, vcol);
+ ptr += utfc_ptr2len(ptr);
}
ptr_row_offset = ptr;
@@ -1711,8 +1712,8 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
vcol = offset;
ptr_end = ptr_row_offset;
while (vcol < col && *ptr_end != NUL) {
- vcol += win_chartabsize(curwin, (char *)ptr_end, vcol);
- ptr_end += utfc_ptr2len((char *)ptr_end);
+ vcol += win_chartabsize(curwin, ptr_end, vcol);
+ ptr_end += utfc_ptr2len(ptr_end);
}
int matchid;
@@ -1726,7 +1727,7 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
#define DECR() nudge--; ptr_end -= utfc_ptr2len((char *)ptr_end)
while (ptr < ptr_end && *ptr != NUL) {
- cwidth = win_chartabsize(curwin, (char *)ptr, vcol);
+ cwidth = win_chartabsize(curwin, ptr, vcol);
vcol += cwidth;
if (cwidth > 1 && *ptr == '\t' && nudge > 0) {
// A tab will "absorb" any previous adjustments.
@@ -1754,7 +1755,7 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
while (prev_matchid == matchid && *ptr != NUL) {
INCR();
- ptr += utfc_ptr2len((char *)ptr);
+ ptr += utfc_ptr2len(ptr);
matchid = syn_get_concealed_id(wp, lnum, (colnr_T)(ptr - line));
}
@@ -1762,7 +1763,7 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
}
}
- ptr += utfc_ptr2len((char *)ptr);
+ ptr += utfc_ptr2len(ptr);
}
return col + nudge;
diff --git a/src/nvim/move.c b/src/nvim/move.c
index dc2f4b4844..3af26b910e 100644
--- a/src/nvim/move.c
+++ b/src/nvim/move.c
@@ -27,12 +27,14 @@
#include "nvim/eval/window.h"
#include "nvim/fold.h"
#include "nvim/getchar.h"
+#include "nvim/gettext.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
#include "nvim/highlight.h"
#include "nvim/macros.h"
#include "nvim/mbyte.h"
#include "nvim/memline_defs.h"
+#include "nvim/message.h"
#include "nvim/mouse.h"
#include "nvim/move.h"
#include "nvim/option.h"
@@ -758,7 +760,7 @@ void curs_columns(win_T *wp, int may_scroll)
// When cursor wraps to first char of next line in Insert
// mode, the 'showbreak' string isn't shown, backup to first
// column
- char *const sbr = (char *)get_showbreak_value(wp);
+ char *const sbr = get_showbreak_value(wp);
if (*sbr && *get_cursor_pos_ptr() == NUL
&& wp->w_wcol == vim_strsize(sbr)) {
wp->w_wcol = 0;
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index 0c23a7798c..d60e18590f 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -20,14 +20,15 @@
#include "nvim/channel.h"
#include "nvim/event/defs.h"
#include "nvim/event/loop.h"
+#include "nvim/event/process.h"
#include "nvim/event/rstream.h"
#include "nvim/event/stream.h"
#include "nvim/event/wstream.h"
-#include "nvim/globals.h"
#include "nvim/log.h"
#include "nvim/main.h"
#include "nvim/map.h"
#include "nvim/memory.h"
+#include "nvim/message.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/msgpack_rpc/channel_defs.h"
#include "nvim/msgpack_rpc/helpers.h"
diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c
index b1e033d9f1..1d75c208be 100644
--- a/src/nvim/msgpack_rpc/server.c
+++ b/src/nvim/msgpack_rpc/server.c
@@ -101,7 +101,7 @@ char *server_address_new(const char *name)
xfree(dir);
#endif
if ((size_t)r >= sizeof(fmt)) {
- ELOG("truncated server address");
+ ELOG("truncated server address: %.40s...", fmt);
}
return xstrdup(fmt);
}
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 8f4240c062..b88cfb8926 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -451,12 +451,34 @@ static int find_command(int cmdchar)
/// message, return true.
static bool check_text_locked(oparg_T *oap)
{
- if (text_locked()) {
+ if (!text_locked()) {
+ return false;
+ }
+
+ if (oap != NULL) {
clearopbeep(oap);
- text_locked_msg();
+ }
+ text_locked_msg();
+ return true;
+}
+
+/// If text is locked, "curbuf->b_ro_locked" or "allbuf_lock" is set:
+/// Give an error message, possibly beep and return true.
+/// "oap" may be NULL.
+static bool check_text_or_curbuf_locked(oparg_T *oap)
+{
+ if (check_text_locked(oap)) {
return true;
}
- return false;
+
+ if (!curbuf_locked()) {
+ return false;
+ }
+
+ if (oap != NULL) {
+ clearop(oap);
+ }
+ return true;
}
/// Normal state entry point. This is called on:
@@ -1107,8 +1129,7 @@ static int normal_execute(VimState *state, int key)
goto finish;
}
- if ((nv_cmds[s->idx].cmd_flags & NV_NCW)
- && (check_text_locked(&s->oa) || curbuf_locked())) {
+ if ((nv_cmds[s->idx].cmd_flags & NV_NCW) && check_text_or_curbuf_locked(&s->oa)) {
// this command is not allowed now
s->command_finished = true;
goto finish;
@@ -1505,8 +1526,7 @@ void restore_visual_mode(void)
/// @param dir the direction of searching, is either FORWARD or BACKWARD
/// @param *colp is in/decremented if "ptr[-dir]" should also be included.
/// @param bnp points to a counter for square brackets.
-static bool find_is_eval_item(const char_u *const ptr, int *const colp, int *const bnp,
- const int dir)
+static bool find_is_eval_item(const char *const ptr, int *const colp, int *const bnp, const int dir)
{
// Accept everything inside [].
if ((*ptr == ']' && dir == BACKWARD) || (*ptr == '[' && dir == FORWARD)) {
@@ -1614,7 +1634,7 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol, char **text
|| (find_type & FIND_IDENT))
&& (!(find_type & FIND_EVAL)
|| prevcol == 0
- || !find_is_eval_item((char_u *)ptr + prevcol, &prevcol, &bn, BACKWARD))) {
+ || !find_is_eval_item(ptr + prevcol, &prevcol, &bn, BACKWARD))) {
break;
}
col = prevcol;
@@ -1657,7 +1677,7 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol, char **text
: mb_get_class(ptr + col) != 0)
|| ((find_type & FIND_EVAL)
&& col <= (int)startcol
- && find_is_eval_item((char_u *)ptr + col, &col, &bn, FORWARD)))) {
+ && find_is_eval_item(ptr + col, &col, &bn, FORWARD)))) {
col += utfc_ptr2len(ptr + col);
}
@@ -1906,7 +1926,7 @@ bool add_to_showcmd(int c)
}
}
- char *p = (char *)transchar(c);
+ char *p = transchar(c);
if (*p == ' ') {
STRCPY(p, "<20>");
}
@@ -2191,17 +2211,19 @@ static void nv_addsub(cmdarg_T *cap)
/// CTRL-F, CTRL-B, etc: Scroll page up or down.
static void nv_page(cmdarg_T *cap)
{
- if (!checkclearop(cap->oap)) {
- if (mod_mask & MOD_MASK_CTRL) {
- // <C-PageUp>: tab page back; <C-PageDown>: tab page forward
- if (cap->arg == BACKWARD) {
- goto_tabpage(-(int)cap->count1);
- } else {
- goto_tabpage((int)cap->count0);
- }
+ if (checkclearop(cap->oap)) {
+ return;
+ }
+
+ if (mod_mask & MOD_MASK_CTRL) {
+ // <C-PageUp>: tab page back; <C-PageDown>: tab page forward
+ if (cap->arg == BACKWARD) {
+ goto_tabpage(-(int)cap->count1);
} else {
- (void)onepage(cap->arg, cap->count1);
+ goto_tabpage((int)cap->count0);
}
+ } else {
+ (void)onepage(cap->arg, cap->count1);
}
}
@@ -2213,22 +2235,23 @@ static void nv_gd(oparg_T *oap, int nchar, int thisblock)
size_t len;
char *ptr;
if ((len = find_ident_under_cursor(&ptr, FIND_IDENT)) == 0
- || !find_decl((char_u *)ptr, len, nchar == 'd', thisblock, SEARCH_START)) {
+ || !find_decl(ptr, len, nchar == 'd', thisblock, SEARCH_START)) {
clearopbeep(oap);
- } else {
- if ((fdo_flags & FDO_SEARCH) && KeyTyped && oap->op_type == OP_NOP) {
- foldOpenCursor();
- }
- // clear any search statistics
- if (messaging() && !msg_silent && !shortmess(SHM_SEARCHCOUNT)) {
- clear_cmdline = true;
- }
+ return;
+ }
+
+ if ((fdo_flags & FDO_SEARCH) && KeyTyped && oap->op_type == OP_NOP) {
+ foldOpenCursor();
+ }
+ // clear any search statistics
+ if (messaging() && !msg_silent && !shortmess(SHM_SEARCHCOUNT)) {
+ clear_cmdline = true;
}
}
/// @return true if line[offset] is not inside a C-style comment or string,
/// false otherwise.
-static bool is_ident(const char_u *line, int offset)
+static bool is_ident(const char *line, int offset)
{
bool incomment = false;
int instring = 0;
@@ -2236,11 +2259,11 @@ static bool is_ident(const char_u *line, int offset)
for (int i = 0; i < offset && line[i] != NUL; i++) {
if (instring != 0) {
- if (prev != '\\' && line[i] == instring) {
+ if (prev != '\\' && (uint8_t)line[i] == instring) {
instring = 0;
}
} else if ((line[i] == '"' || line[i] == '\'') && !incomment) {
- instring = line[i];
+ instring = (uint8_t)line[i];
} else {
if (incomment) {
if (prev == '*' && line[i] == '/') {
@@ -2253,7 +2276,7 @@ static bool is_ident(const char_u *line, int offset)
}
}
- prev = line[i];
+ prev = (uint8_t)line[i];
}
return incomment == false && instring == 0;
@@ -2267,7 +2290,7 @@ static bool is_ident(const char_u *line, int offset)
/// @param flags_arg flags passed to searchit()
///
/// @return fail when not found.
-bool find_decl(char_u *ptr, size_t len, bool locally, bool thisblock, int flags_arg)
+bool find_decl(char *ptr, size_t len, bool locally, bool thisblock, int flags_arg)
{
char *pat;
pos_T old_pos;
@@ -2285,7 +2308,7 @@ bool find_decl(char_u *ptr, size_t len, bool locally, bool thisblock, int flags_
// Put "\V" before the pattern to avoid that the special meaning of "."
// and "~" causes trouble.
assert(len <= INT_MAX);
- sprintf(pat, vim_iswordp((char *)ptr) ? "\\V\\<%.*s\\>" : "\\V%.*s", // NOLINT(runtime/printf)
+ sprintf(pat, vim_iswordp(ptr) ? "\\V\\<%.*s\\>" : "\\V%.*s", // NOLINT(runtime/printf)
(int)len, ptr);
old_pos = curwin->w_cursor;
save_p_ws = p_ws;
@@ -2313,7 +2336,7 @@ bool find_decl(char_u *ptr, size_t len, bool locally, bool thisblock, int flags_
clearpos(&found_pos);
for (;;) {
t = searchit(curwin, curbuf, &curwin->w_cursor, NULL, FORWARD,
- (char_u *)pat, 1L, searchflags, RE_LAST, NULL);
+ pat, 1L, searchflags, RE_LAST, NULL);
if (curwin->w_cursor.lnum >= old_pos.lnum) {
t = false; // match after start is failure too
}
@@ -2346,7 +2369,7 @@ bool find_decl(char_u *ptr, size_t len, bool locally, bool thisblock, int flags_
curwin->w_cursor.col = 0;
continue;
}
- bool valid = is_ident((char_u *)get_cursor_line_ptr(), curwin->w_cursor.col);
+ bool valid = is_ident(get_cursor_line_ptr(), curwin->w_cursor.col);
// If the current position is not a valid identifier and a previous match is
// present, favor that one instead.
@@ -2527,7 +2550,7 @@ static bool nv_screengo(oparg_T *oap, int dir, long dist)
validate_virtcol();
colnr_T virtcol = curwin->w_virtcol;
if (virtcol > (colnr_T)width1 && *get_showbreak_value(curwin) != NUL) {
- virtcol -= vim_strsize((char *)get_showbreak_value(curwin));
+ virtcol -= vim_strsize(get_showbreak_value(curwin));
}
int c = utf_ptr2char(get_cursor_pos_ptr());
@@ -3195,44 +3218,45 @@ static void nv_colon(cmdarg_T *cap)
if (VIsual_active && !is_cmdkey && !is_lua) {
nv_operator(cap);
- } else {
- if (cap->oap->op_type != OP_NOP) {
- // Using ":" as a movement is charwise exclusive.
- cap->oap->motion_type = kMTCharWise;
- cap->oap->inclusive = false;
- } else if (cap->count0 && !is_cmdkey && !is_lua) {
- // translate "count:" into ":.,.+(count - 1)"
- stuffcharReadbuff('.');
- if (cap->count0 > 1) {
- stuffReadbuff(",.+");
- stuffnumReadbuff(cap->count0 - 1L);
- }
- }
+ return;
+ }
- // When typing, don't type below an old message
- if (KeyTyped) {
- compute_cmdrow();
+ if (cap->oap->op_type != OP_NOP) {
+ // Using ":" as a movement is charwise exclusive.
+ cap->oap->motion_type = kMTCharWise;
+ cap->oap->inclusive = false;
+ } else if (cap->count0 && !is_cmdkey && !is_lua) {
+ // translate "count:" into ":.,.+(count - 1)"
+ stuffcharReadbuff('.');
+ if (cap->count0 > 1) {
+ stuffReadbuff(",.+");
+ stuffnumReadbuff(cap->count0 - 1L);
}
+ }
- if (is_lua) {
- cmd_result = map_execute_lua();
- } else {
- // get a command line and execute it
- cmd_result = do_cmdline(NULL, is_cmdkey ? getcmdkeycmd : getexline, NULL,
- cap->oap->op_type != OP_NOP ? DOCMD_KEEPLINE : 0);
- }
+ // When typing, don't type below an old message
+ if (KeyTyped) {
+ compute_cmdrow();
+ }
- if (cmd_result == false) {
- // The Ex command failed, do not execute the operator.
- clearop(cap->oap);
- } else if (cap->oap->op_type != OP_NOP
- && (cap->oap->start.lnum > curbuf->b_ml.ml_line_count
- || cap->oap->start.col >
- (colnr_T)strlen(ml_get(cap->oap->start.lnum))
- || did_emsg)) {
- // The start of the operator has become invalid by the Ex command.
- clearopbeep(cap->oap);
- }
+ if (is_lua) {
+ cmd_result = map_execute_lua();
+ } else {
+ // get a command line and execute it
+ cmd_result = do_cmdline(NULL, is_cmdkey ? getcmdkeycmd : getexline, NULL,
+ cap->oap->op_type != OP_NOP ? DOCMD_KEEPLINE : 0);
+ }
+
+ if (cmd_result == false) {
+ // The Ex command failed, do not execute the operator.
+ clearop(cap->oap);
+ } else if (cap->oap->op_type != OP_NOP
+ && (cap->oap->start.lnum > curbuf->b_ml.ml_line_count
+ || cap->oap->start.col >
+ (colnr_T)strlen(ml_get(cap->oap->start.lnum))
+ || did_emsg)) {
+ // The start of the operator has become invalid by the Ex command.
+ clearopbeep(cap->oap);
}
}
@@ -3263,14 +3287,16 @@ static void nv_ctrlh(cmdarg_T *cap)
/// CTRL-L: clear screen and redraw.
static void nv_clear(cmdarg_T *cap)
{
- if (!checkclearop(cap->oap)) {
- // Clear all syntax states to force resyncing.
- syn_stack_free_all(curwin->w_s);
- FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- wp->w_s->b_syn_slow = false;
- }
- redraw_later(curwin, UPD_CLEAR);
+ if (checkclearop(cap->oap)) {
+ return;
+ }
+
+ // Clear all syntax states to force resyncing.
+ syn_stack_free_all(curwin->w_s);
+ FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
+ wp->w_s->b_syn_slow = false;
}
+ redraw_later(curwin, UPD_CLEAR);
}
/// CTRL-O: In Select mode: switch to Visual mode for one command.
@@ -3301,21 +3327,23 @@ static void nv_hat(cmdarg_T *cap)
/// "Z" commands.
static void nv_Zet(cmdarg_T *cap)
{
- if (!checkclearopq(cap->oap)) {
- switch (cap->nchar) {
- // "ZZ": equivalent to ":x".
- case 'Z':
- do_cmdline_cmd("x");
- break;
+ if (checkclearopq(cap->oap)) {
+ return;
+ }
- // "ZQ": equivalent to ":q!" (Elvis compatible).
- case 'Q':
- do_cmdline_cmd("q!");
- break;
+ switch (cap->nchar) {
+ // "ZZ": equivalent to ":x".
+ case 'Z':
+ do_cmdline_cmd("x");
+ break;
- default:
- clearopbeep(cap->oap);
- }
+ // "ZQ": equivalent to ":q!" (Elvis compatible).
+ case 'Q':
+ do_cmdline_cmd("q!");
+ break;
+
+ default:
+ clearopbeep(cap->oap);
}
}
@@ -3446,7 +3474,7 @@ static void nv_ident(cmdarg_T *cap)
// Allocate buffer to put the command in. Inserting backslashes can
// double the length of the word. p_kp / curbuf->b_p_kp could be added
// and some numbers.
- char *kp = *curbuf->b_p_kp == NUL ? (char *)p_kp : curbuf->b_p_kp; // 'keywordprg'
+ char *kp = *curbuf->b_p_kp == NUL ? p_kp : curbuf->b_p_kp; // 'keywordprg'
bool kp_help = (*kp == NUL || strcmp(kp, ":he") == 0 || strcmp(kp, ":help") == 0);
if (kp_help && *skipwhite(ptr) == NUL) {
emsg(_(e_noident)); // found white space only
@@ -3532,7 +3560,7 @@ static void nv_ident(cmdarg_T *cap)
p = buf + strlen(buf);
while (n-- > 0) {
// put a backslash before \ and some others
- if (vim_strchr(aux_ptr, *ptr) != NULL) {
+ if (vim_strchr(aux_ptr, (uint8_t)(*ptr)) != NULL) {
*p++ = '\\';
}
// When current byte is a part of multibyte character, copy all
@@ -3846,13 +3874,14 @@ static void nv_up(cmdarg_T *cap)
// <S-Up> is page up
cap->arg = BACKWARD;
nv_page(cap);
- } else {
- cap->oap->motion_type = kMTLineWise;
- if (cursor_up(cap->count1, cap->oap->op_type == OP_NOP) == false) {
- clearopbeep(cap->oap);
- } else if (cap->arg) {
- beginline(BL_WHITE | BL_FIX);
- }
+ return;
+ }
+
+ cap->oap->motion_type = kMTLineWise;
+ if (cursor_up(cap->count1, cap->oap->op_type == OP_NOP) == false) {
+ clearopbeep(cap->oap);
+ } else if (cap->arg) {
+ beginline(BL_WHITE | BL_FIX);
}
}
@@ -3895,15 +3924,11 @@ static void nv_gotofile(cmdarg_T *cap)
char *ptr;
linenr_T lnum = -1;
- if (check_text_locked(cap->oap)) {
- return;
- }
- if (curbuf_locked()) {
- clearop(cap->oap);
+ if (check_text_or_curbuf_locked(cap->oap)) {
return;
}
- ptr = (char *)grab_file_name(cap->count1, &lnum);
+ ptr = grab_file_name(cap->count1, &lnum);
if (ptr != NULL) {
// do autowrite if necessary
@@ -3972,7 +3997,7 @@ static void nv_search(cmdarg_T *cap)
// When using 'incsearch' the cursor may be moved to set a different search
// start position.
- cap->searchbuf = (char *)getcmdline(cap->cmdchar, cap->count1, 0, true);
+ cap->searchbuf = getcmdline(cap->cmdchar, cap->count1, 0, true);
if (cap->searchbuf == NULL) {
clearop(oap);
@@ -4058,22 +4083,23 @@ static void nv_csearch(cmdarg_T *cap)
cap->oap->motion_type = kMTCharWise;
if (IS_SPECIAL(cap->nchar) || searchc(cap, t_cmd) == false) {
clearopbeep(cap->oap);
- } else {
- curwin->w_set_curswant = true;
- // Include a Tab for "tx" and for "dfx".
- if (gchar_cursor() == TAB && virtual_active() && cap->arg == FORWARD
- && (t_cmd || cap->oap->op_type != OP_NOP)) {
- colnr_T scol, ecol;
+ return;
+ }
- getvcol(curwin, &curwin->w_cursor, &scol, NULL, &ecol);
- curwin->w_cursor.coladd = ecol - scol;
- } else {
- curwin->w_cursor.coladd = 0;
- }
- adjust_for_sel(cap);
- if ((fdo_flags & FDO_HOR) && KeyTyped && cap->oap->op_type == OP_NOP) {
- foldOpenCursor();
- }
+ curwin->w_set_curswant = true;
+ // Include a Tab for "tx" and for "dfx".
+ if (gchar_cursor() == TAB && virtual_active() && cap->arg == FORWARD
+ && (t_cmd || cap->oap->op_type != OP_NOP)) {
+ colnr_T scol, ecol;
+
+ getvcol(curwin, &curwin->w_cursor, &scol, NULL, &ecol);
+ curwin->w_cursor.coladd = ecol - scol;
+ } else {
+ curwin->w_cursor.coladd = 0;
+ }
+ adjust_for_sel(cap);
+ if ((fdo_flags & FDO_HOR) && KeyTyped && cap->oap->op_type == OP_NOP) {
+ foldOpenCursor();
}
}
@@ -4395,25 +4421,28 @@ static void nv_brace(cmdarg_T *cap)
cap->oap->inclusive = false;
curwin->w_set_curswant = true;
- if (findsent(cap->arg, cap->count1) == false) {
+ if (findsent(cap->arg, cap->count1) == FAIL) {
clearopbeep(cap->oap);
- } else {
- // Don't leave the cursor on the NUL past end of line.
- adjust_cursor(cap->oap);
- curwin->w_cursor.coladd = 0;
- if ((fdo_flags & FDO_BLOCK) && KeyTyped && cap->oap->op_type == OP_NOP) {
- foldOpenCursor();
- }
+ return;
+ }
+
+ // Don't leave the cursor on the NUL past end of line.
+ adjust_cursor(cap->oap);
+ curwin->w_cursor.coladd = 0;
+ if ((fdo_flags & FDO_BLOCK) && KeyTyped && cap->oap->op_type == OP_NOP) {
+ foldOpenCursor();
}
}
/// "m" command: Mark a position.
static void nv_mark(cmdarg_T *cap)
{
- if (!checkclearop(cap->oap)) {
- if (setmark(cap->nchar) == false) {
- clearopbeep(cap->oap);
- }
+ if (checkclearop(cap->oap)) {
+ return;
+ }
+
+ if (setmark(cap->nchar) == false) {
+ clearopbeep(cap->oap);
}
}
@@ -4427,11 +4456,12 @@ static void nv_findpar(cmdarg_T *cap)
curwin->w_set_curswant = true;
if (!findpar(&cap->oap->inclusive, cap->arg, cap->count1, NUL, false)) {
clearopbeep(cap->oap);
- } else {
- curwin->w_cursor.coladd = 0;
- if ((fdo_flags & FDO_BLOCK) && KeyTyped && cap->oap->op_type == OP_NOP) {
- foldOpenCursor();
- }
+ return;
+ }
+
+ curwin->w_cursor.coladd = 0;
+ if ((fdo_flags & FDO_BLOCK) && KeyTyped && cap->oap->op_type == OP_NOP) {
+ foldOpenCursor();
}
}
@@ -4452,14 +4482,16 @@ static void nv_undo(cmdarg_T *cap)
/// <Undo> command.
static void nv_kundo(cmdarg_T *cap)
{
- if (!checkclearopq(cap->oap)) {
- if (bt_prompt(curbuf)) {
- clearopbeep(cap->oap);
- return;
- }
- u_undo((int)cap->count1);
- curwin->w_set_curswant = true;
+ if (checkclearopq(cap->oap)) {
+ return;
}
+
+ if (bt_prompt(curbuf)) {
+ clearopbeep(cap->oap);
+ return;
+ }
+ u_undo((int)cap->count1);
+ curwin->w_set_curswant = true;
}
/// Handle the "r" command.
@@ -4670,15 +4702,20 @@ static void nv_Replace(cmdarg_T *cap)
VIsual_mode_orig = VIsual_mode; // remember original area for gv
VIsual_mode = 'V';
nv_operator(cap);
- } else if (!checkclearopq(cap->oap)) {
- if (!MODIFIABLE(curbuf)) {
- emsg(_(e_modifiable));
- } else {
- if (virtual_active()) {
- coladvance(getviscol());
- }
- invoke_edit(cap, false, cap->arg ? 'V' : 'R', false);
+ return;
+ }
+
+ if (checkclearopq(cap->oap)) {
+ return;
+ }
+
+ if (!MODIFIABLE(curbuf)) {
+ emsg(_(e_modifiable));
+ } else {
+ if (virtual_active()) {
+ coladvance(getviscol());
}
+ invoke_edit(cap, false, cap->arg ? 'V' : 'R', false);
}
}
@@ -4689,20 +4726,25 @@ static void nv_vreplace(cmdarg_T *cap)
cap->cmdchar = 'r';
cap->nchar = cap->extra_char;
nv_replace(cap); // Do same as "r" in Visual mode for now
- } else if (!checkclearopq(cap->oap)) {
- if (!MODIFIABLE(curbuf)) {
- emsg(_(e_modifiable));
- } else {
- if (cap->extra_char == Ctrl_V) { // get another character
- cap->extra_char = get_literal(false);
- }
- stuffcharReadbuff(cap->extra_char);
- stuffcharReadbuff(ESC);
- if (virtual_active()) {
- coladvance(getviscol());
- }
- invoke_edit(cap, true, 'v', false);
+ return;
+ }
+
+ if (checkclearopq(cap->oap)) {
+ return;
+ }
+
+ if (!MODIFIABLE(curbuf)) {
+ emsg(_(e_modifiable));
+ } else {
+ if (cap->extra_char == Ctrl_V) { // get another character
+ cap->extra_char = get_literal(false);
+ }
+ stuffcharReadbuff(cap->extra_char);
+ stuffcharReadbuff(ESC);
+ if (virtual_active()) {
+ coladvance(getviscol());
}
+ invoke_edit(cap, true, 'v', false);
}
}
@@ -4903,42 +4945,44 @@ static void nv_pcmark(cmdarg_T *cap)
MarkMoveRes move_res = 0; // Result from moving to the mark
const bool old_KeyTyped = KeyTyped; // getting file may reset it.
- if (!checkclearopq(cap->oap)) {
- if (cap->cmdchar == TAB && mod_mask == MOD_MASK_CTRL) {
- if (!goto_tabpage_lastused()) {
- clearopbeep(cap->oap);
- }
- return;
- }
+ if (checkclearopq(cap->oap)) {
+ return;
+ }
- if (cap->cmdchar == 'g') {
- fm = get_changelist(curbuf, curwin, (int)cap->count1);
- } else {
- fm = get_jumplist(curwin, (int)cap->count1);
- flags |= KMarkNoContext | kMarkJumpList;
- }
- // Changelist and jumplist have their own error messages. Therefore avoid
- // calling nv_mark_move_to() when not found to avoid incorrect error
- // messages.
- if (fm != NULL) {
- move_res = nv_mark_move_to(cap, flags, fm);
- } else if (cap->cmdchar == 'g') {
- if (curbuf->b_changelistlen == 0) {
- emsg(_("E664: changelist is empty"));
- } else if (cap->count1 < 0) {
- emsg(_("E662: At start of changelist"));
- } else {
- emsg(_("E663: At end of changelist"));
- }
- } else {
+ if (cap->cmdchar == TAB && mod_mask == MOD_MASK_CTRL) {
+ if (!goto_tabpage_lastused()) {
clearopbeep(cap->oap);
}
- if (cap->oap->op_type == OP_NOP
- && (move_res & kMarkSwitchedBuf || move_res & kMarkChangedLine)
- && (fdo_flags & FDO_MARK)
- && old_KeyTyped) {
- foldOpenCursor();
+ return;
+ }
+
+ if (cap->cmdchar == 'g') {
+ fm = get_changelist(curbuf, curwin, (int)cap->count1);
+ } else {
+ fm = get_jumplist(curwin, (int)cap->count1);
+ flags |= KMarkNoContext | kMarkJumpList;
+ }
+ // Changelist and jumplist have their own error messages. Therefore avoid
+ // calling nv_mark_move_to() when not found to avoid incorrect error
+ // messages.
+ if (fm != NULL) {
+ move_res = nv_mark_move_to(cap, flags, fm);
+ } else if (cap->cmdchar == 'g') {
+ if (curbuf->b_changelistlen == 0) {
+ emsg(_("E664: changelist is empty"));
+ } else if (cap->count1 < 0) {
+ emsg(_("E662: At start of changelist"));
+ } else {
+ emsg(_("E663: At end of changelist"));
}
+ } else {
+ clearopbeep(cap->oap);
+ }
+ if (cap->oap->op_type == OP_NOP
+ && (move_res & kMarkSwitchedBuf || move_res & kMarkChangedLine)
+ && (fdo_flags & FDO_MARK)
+ && old_KeyTyped) {
+ foldOpenCursor();
}
}
@@ -5028,9 +5072,13 @@ static void nv_visual(cmdarg_T *cap)
curwin->w_curswant = MAXCOL;
coladvance(MAXCOL);
} else if (VIsual_mode == Ctrl_V) {
+ // Update curswant on the original line, that is where "col" is valid.
+ linenr_T lnum = curwin->w_cursor.lnum;
+ curwin->w_cursor.lnum = VIsual.lnum;
update_curswant_force();
assert(cap->count0 >= INT_MIN && cap->count0 <= INT_MAX);
curwin->w_curswant += resel_VIsual_vcol * (int)cap->count0 - 1;
+ curwin->w_cursor.lnum = lnum;
coladvance(curwin->w_curswant);
} else {
curwin->w_set_curswant = true;
@@ -5669,42 +5717,46 @@ static void nv_g_cmd(cmdarg_T *cap)
/// Handle "o" and "O" commands.
static void n_opencmd(cmdarg_T *cap)
{
- if (!checkclearopq(cap->oap)) {
- if (cap->cmdchar == 'O') {
- // Open above the first line of a folded sequence of lines
- (void)hasFolding(curwin->w_cursor.lnum,
- &curwin->w_cursor.lnum, NULL);
- } else {
- // Open below the last line of a folded sequence of lines
- (void)hasFolding(curwin->w_cursor.lnum,
- NULL, &curwin->w_cursor.lnum);
- }
- if (u_save((linenr_T)(curwin->w_cursor.lnum -
- (cap->cmdchar == 'O' ? 1 : 0)),
- (linenr_T)(curwin->w_cursor.lnum +
- (cap->cmdchar == 'o' ? 1 : 0)))
- && open_line(cap->cmdchar == 'O' ? BACKWARD : FORWARD,
- has_format_option(FO_OPEN_COMS) ? OPENLINE_DO_COM : 0,
- 0, NULL)) {
- if (win_cursorline_standout(curwin)) {
- // force redraw of cursorline
- curwin->w_valid &= ~VALID_CROW;
- }
- invoke_edit(cap, false, cap->cmdchar, true);
+ if (checkclearopq(cap->oap)) {
+ return;
+ }
+
+ if (cap->cmdchar == 'O') {
+ // Open above the first line of a folded sequence of lines
+ (void)hasFolding(curwin->w_cursor.lnum,
+ &curwin->w_cursor.lnum, NULL);
+ } else {
+ // Open below the last line of a folded sequence of lines
+ (void)hasFolding(curwin->w_cursor.lnum,
+ NULL, &curwin->w_cursor.lnum);
+ }
+ if (u_save((linenr_T)(curwin->w_cursor.lnum -
+ (cap->cmdchar == 'O' ? 1 : 0)),
+ (linenr_T)(curwin->w_cursor.lnum +
+ (cap->cmdchar == 'o' ? 1 : 0)))
+ && open_line(cap->cmdchar == 'O' ? BACKWARD : FORWARD,
+ has_format_option(FO_OPEN_COMS) ? OPENLINE_DO_COM : 0,
+ 0, NULL)) {
+ if (win_cursorline_standout(curwin)) {
+ // force redraw of cursorline
+ curwin->w_valid &= ~VALID_CROW;
}
+ invoke_edit(cap, false, cap->cmdchar, true);
}
}
/// "." command: redo last change.
static void nv_dot(cmdarg_T *cap)
{
- if (!checkclearopq(cap->oap)) {
- // If "restart_edit" is true, the last but one command is repeated
- // instead of the last command (inserting text). This is used for
- // CTRL-O <.> in insert mode.
- if (start_redo(cap->count0, restart_edit != 0 && !arrow_used) == false) {
- clearopbeep(cap->oap);
- }
+ if (checkclearopq(cap->oap)) {
+ return;
+ }
+
+ // If "restart_edit" is true, the last but one command is repeated
+ // instead of the last command (inserting text). This is used for
+ // CTRL-O <.> in insert mode.
+ if (start_redo(cap->count0, restart_edit != 0 && !arrow_used) == false) {
+ clearopbeep(cap->oap);
}
}
@@ -5728,10 +5780,12 @@ static void nv_redo_or_register(cmdarg_T *cap)
return;
}
- if (!checkclearopq(cap->oap)) {
- u_redo((int)cap->count1);
- curwin->w_set_curswant = true;
+ if (checkclearopq(cap->oap)) {
+ return;
}
+
+ u_redo((int)cap->count1);
+ curwin->w_set_curswant = true;
}
/// Handle "U" command.
@@ -5743,10 +5797,15 @@ static void nv_Undo(cmdarg_T *cap)
cap->cmdchar = 'g';
cap->nchar = 'U';
nv_operator(cap);
- } else if (!checkclearopq(cap->oap)) {
- u_undoline();
- curwin->w_set_curswant = true;
+ return;
}
+
+ if (checkclearopq(cap->oap)) {
+ return;
+ }
+
+ u_undoline();
+ curwin->w_set_curswant = true;
}
/// '~' command: If tilde is not an operator and Visual is off: swap case of a
@@ -6309,16 +6368,21 @@ static void nv_record(cmdarg_T *cap)
cap->cmdchar = 'g';
cap->nchar = 'q';
nv_operator(cap);
- } else if (!checkclearop(cap->oap)) {
- if (cap->nchar == ':' || cap->nchar == '/' || cap->nchar == '?') {
- stuffcharReadbuff(cap->nchar);
- stuffcharReadbuff(K_CMDWIN);
- } else {
- // (stop) recording into a named register, unless executing a
- // register.
- if (reg_executing == 0 && do_record(cap->nchar) == FAIL) {
- clearopbeep(cap->oap);
- }
+ return;
+ }
+
+ if (checkclearop(cap->oap)) {
+ return;
+ }
+
+ if (cap->nchar == ':' || cap->nchar == '/' || cap->nchar == '?') {
+ stuffcharReadbuff(cap->nchar);
+ stuffcharReadbuff(K_CMDWIN);
+ } else {
+ // (stop) recording into a named register, unless executing a
+ // register.
+ if (reg_executing == 0 && do_record(cap->nchar) == FAIL) {
+ clearopbeep(cap->oap);
}
}
}
@@ -6360,24 +6424,29 @@ static void nv_join(cmdarg_T *cap)
{
if (VIsual_active) { // join the visual lines
nv_operator(cap);
- } else if (!checkclearop(cap->oap)) {
- if (cap->count0 <= 1) {
- cap->count0 = 2; // default for join is two lines!
- }
- if (curwin->w_cursor.lnum + cap->count0 - 1 >
- curbuf->b_ml.ml_line_count) {
- // can't join when on the last line
- if (cap->count0 <= 2) {
- clearopbeep(cap->oap);
- return;
- }
- cap->count0 = curbuf->b_ml.ml_line_count - curwin->w_cursor.lnum + 1;
- }
+ return;
+ }
- prep_redo(cap->oap->regname, cap->count0,
- NUL, cap->cmdchar, NUL, NUL, cap->nchar);
- do_join((size_t)cap->count0, cap->nchar == NUL, true, true, true);
+ if (checkclearop(cap->oap)) {
+ return;
}
+
+ if (cap->count0 <= 1) {
+ cap->count0 = 2; // default for join is two lines!
+ }
+ if (curwin->w_cursor.lnum + cap->count0 - 1 >
+ curbuf->b_ml.ml_line_count) {
+ // can't join when on the last line
+ if (cap->count0 <= 2) {
+ clearopbeep(cap->oap);
+ return;
+ }
+ cap->count0 = curbuf->b_ml.ml_line_count - curwin->w_cursor.lnum + 1;
+ }
+
+ prep_redo(cap->oap->regname, cap->count0,
+ NUL, cap->cmdchar, NUL, NUL, cap->nchar);
+ do_join((size_t)cap->count0, cap->nchar == NUL, true, true, true);
}
/// "P", "gP", "p" and "gp" commands.
@@ -6407,117 +6476,121 @@ static void nv_put_opt(cmdarg_T *cap, bool fix_indent)
} else {
clearopbeep(cap->oap);
}
- } else if (bt_prompt(curbuf) && !prompt_curpos_editable()) {
- clearopbeep(cap->oap);
- } else {
- if (fix_indent) {
- dir = (cap->cmdchar == ']' && cap->nchar == 'p')
- ? FORWARD : BACKWARD;
- flags |= PUT_FIXINDENT;
- } else {
- dir = (cap->cmdchar == 'P'
- || ((cap->cmdchar == 'g' || cap->cmdchar == 'z')
- && cap->nchar == 'P')) ? BACKWARD : FORWARD;
- }
- prep_redo_cmd(cap);
- if (cap->cmdchar == 'g') {
- flags |= PUT_CURSEND;
- } else if (cap->cmdchar == 'z') {
- flags |= PUT_BLOCK_INNER;
- }
+ return;
+ }
- if (VIsual_active) {
- // Putting in Visual mode: The put text replaces the selected
- // text. First delete the selected text, then put the new text.
- // Need to save and restore the registers that the delete
- // overwrites if the old contents is being put.
- was_visual = true;
- regname = cap->oap->regname;
- bool keep_registers = cap->cmdchar == 'P';
- // '+' and '*' could be the same selection
- bool clipoverwrite = (regname == '+' || regname == '*') && (cb_flags & CB_UNNAMEDMASK);
- if (regname == 0 || regname == '"' || clipoverwrite
- || ascii_isdigit(regname) || regname == '-') {
- // The delete might overwrite the register we want to put, save it first
- savereg = copy_register(regname);
- }
+ if (bt_prompt(curbuf) && !prompt_curpos_editable()) {
+ clearopbeep(cap->oap);
+ return;
+ }
- // To place the cursor correctly after a blockwise put, and to leave the
- // text in the correct position when putting over a selection with
- // 'virtualedit' and past the end of the line, we use the 'c' operator in
- // do_put(), which requires the visual selection to still be active.
- if (!VIsual_active || VIsual_mode == 'V' || regname != '.') {
- // Now delete the selected text. Avoid messages here.
- cap->cmdchar = 'd';
- cap->nchar = NUL;
- cap->oap->regname = keep_registers ? '_' : NUL;
- msg_silent++;
- nv_operator(cap);
- do_pending_operator(cap, 0, false);
- empty = (curbuf->b_ml.ml_flags & ML_EMPTY);
- msg_silent--;
+ if (fix_indent) {
+ dir = (cap->cmdchar == ']' && cap->nchar == 'p')
+ ? FORWARD : BACKWARD;
+ flags |= PUT_FIXINDENT;
+ } else {
+ dir = (cap->cmdchar == 'P'
+ || ((cap->cmdchar == 'g' || cap->cmdchar == 'z')
+ && cap->nchar == 'P')) ? BACKWARD : FORWARD;
+ }
+ prep_redo_cmd(cap);
+ if (cap->cmdchar == 'g') {
+ flags |= PUT_CURSEND;
+ } else if (cap->cmdchar == 'z') {
+ flags |= PUT_BLOCK_INNER;
+ }
- // delete PUT_LINE_BACKWARD;
- cap->oap->regname = regname;
- }
+ if (VIsual_active) {
+ // Putting in Visual mode: The put text replaces the selected
+ // text. First delete the selected text, then put the new text.
+ // Need to save and restore the registers that the delete
+ // overwrites if the old contents is being put.
+ was_visual = true;
+ regname = cap->oap->regname;
+ bool keep_registers = cap->cmdchar == 'P';
+ // '+' and '*' could be the same selection
+ bool clipoverwrite = (regname == '+' || regname == '*') && (cb_flags & CB_UNNAMEDMASK);
+ if (regname == 0 || regname == '"' || clipoverwrite
+ || ascii_isdigit(regname) || regname == '-') {
+ // The delete might overwrite the register we want to put, save it first
+ savereg = copy_register(regname);
+ }
+
+ // To place the cursor correctly after a blockwise put, and to leave the
+ // text in the correct position when putting over a selection with
+ // 'virtualedit' and past the end of the line, we use the 'c' operator in
+ // do_put(), which requires the visual selection to still be active.
+ if (!VIsual_active || VIsual_mode == 'V' || regname != '.') {
+ // Now delete the selected text. Avoid messages here.
+ cap->cmdchar = 'd';
+ cap->nchar = NUL;
+ cap->oap->regname = keep_registers ? '_' : NUL;
+ msg_silent++;
+ nv_operator(cap);
+ do_pending_operator(cap, 0, false);
+ empty = (curbuf->b_ml.ml_flags & ML_EMPTY);
+ msg_silent--;
- // When deleted a linewise Visual area, put the register as
- // lines to avoid it joined with the next line. When deletion was
- // charwise, split a line when putting lines.
- if (VIsual_mode == 'V') {
- flags |= PUT_LINE;
- } else if (VIsual_mode == 'v') {
- flags |= PUT_LINE_SPLIT;
- }
- if (VIsual_mode == Ctrl_V && dir == FORWARD) {
- flags |= PUT_LINE_FORWARD;
- }
- dir = BACKWARD;
- if ((VIsual_mode != 'V'
- && curwin->w_cursor.col < curbuf->b_op_start.col)
- || (VIsual_mode == 'V'
- && curwin->w_cursor.lnum < curbuf->b_op_start.lnum)) {
- // cursor is at the end of the line or end of file, put
- // forward.
- dir = FORWARD;
- }
- // May have been reset in do_put().
- VIsual_active = true;
+ // delete PUT_LINE_BACKWARD;
+ cap->oap->regname = regname;
}
- do_put(cap->oap->regname, savereg, dir, cap->count1, flags);
- // If a register was saved, free it
- if (savereg != NULL) {
- free_register(savereg);
- xfree(savereg);
+ // When deleted a linewise Visual area, put the register as
+ // lines to avoid it joined with the next line. When deletion was
+ // charwise, split a line when putting lines.
+ if (VIsual_mode == 'V') {
+ flags |= PUT_LINE;
+ } else if (VIsual_mode == 'v') {
+ flags |= PUT_LINE_SPLIT;
+ }
+ if (VIsual_mode == Ctrl_V && dir == FORWARD) {
+ flags |= PUT_LINE_FORWARD;
+ }
+ dir = BACKWARD;
+ if ((VIsual_mode != 'V'
+ && curwin->w_cursor.col < curbuf->b_op_start.col)
+ || (VIsual_mode == 'V'
+ && curwin->w_cursor.lnum < curbuf->b_op_start.lnum)) {
+ // cursor is at the end of the line or end of file, put
+ // forward.
+ dir = FORWARD;
}
+ // May have been reset in do_put().
+ VIsual_active = true;
+ }
+ do_put(cap->oap->regname, savereg, dir, cap->count1, flags);
- // What to reselect with "gv"? Selecting the just put text seems to
- // be the most useful, since the original text was removed.
- if (was_visual) {
- curbuf->b_visual.vi_start = curbuf->b_op_start;
- curbuf->b_visual.vi_end = curbuf->b_op_end;
- // need to adjust cursor position
- if (*p_sel == 'e') {
- inc(&curbuf->b_visual.vi_end);
- }
+ // If a register was saved, free it
+ if (savereg != NULL) {
+ free_register(savereg);
+ xfree(savereg);
+ }
+
+ // What to reselect with "gv"? Selecting the just put text seems to
+ // be the most useful, since the original text was removed.
+ if (was_visual) {
+ curbuf->b_visual.vi_start = curbuf->b_op_start;
+ curbuf->b_visual.vi_end = curbuf->b_op_end;
+ // need to adjust cursor position
+ if (*p_sel == 'e') {
+ inc(&curbuf->b_visual.vi_end);
}
+ }
- // When all lines were selected and deleted do_put() leaves an empty
- // line that needs to be deleted now.
- if (empty && *ml_get(curbuf->b_ml.ml_line_count) == NUL) {
- ml_delete(curbuf->b_ml.ml_line_count, true);
- deleted_lines(curbuf->b_ml.ml_line_count + 1, 1);
+ // When all lines were selected and deleted do_put() leaves an empty
+ // line that needs to be deleted now.
+ if (empty && *ml_get(curbuf->b_ml.ml_line_count) == NUL) {
+ ml_delete(curbuf->b_ml.ml_line_count, true);
+ deleted_lines(curbuf->b_ml.ml_line_count + 1, 1);
- // If the cursor was in that line, move it to the end of the last
- // line.
- if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) {
- curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
- coladvance(MAXCOL);
- }
+ // If the cursor was in that line, move it to the end of the last
+ // line.
+ if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) {
+ curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
+ coladvance(MAXCOL);
}
- auto_format(false, true);
}
+ auto_format(false, true);
}
/// "o" and "O" commands.
diff --git a/src/nvim/normal.h b/src/nvim/normal.h
index 90a5c4103e..bed1a40b97 100644
--- a/src/nvim/normal.h
+++ b/src/nvim/normal.h
@@ -4,6 +4,7 @@
#include <stdbool.h>
#include "nvim/buffer_defs.h"
+#include "nvim/macros.h"
#include "nvim/pos.h"
// Values for find_ident_under_cursor()
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 34432c58db..435ca106ab 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -723,7 +723,7 @@ int get_expr_register(void)
{
char *new_line;
- new_line = (char *)getcmdline('=', 0L, 0, true);
+ new_line = getcmdline('=', 0L, 0, true);
if (new_line == NULL) {
return NUL;
}
@@ -1006,7 +1006,7 @@ static int stuff_yank(int regname, char *p)
} else {
free_register(reg);
set_yreg_additional_data(reg, NULL);
- reg->y_array = xmalloc(sizeof(char_u *));
+ reg->y_array = xmalloc(sizeof(char *));
reg->y_array[0] = p;
reg->y_size = 1;
reg->y_type = kMTCharWise;
@@ -1028,14 +1028,14 @@ static int execreg_lastc = NUL;
/// with a \. Lines that start with a comment "\ character are ignored.
/// @returns the concatenated line. The index of the line that should be
/// processed next is returned in idx.
-static char_u *execreg_line_continuation(char **lines, size_t *idx)
+static char *execreg_line_continuation(char **lines, size_t *idx)
{
size_t i = *idx;
assert(i > 0);
const size_t cmd_end = i;
garray_T ga;
- ga_init(&ga, (int)sizeof(char_u), 400);
+ ga_init(&ga, (int)sizeof(char), 400);
char *p;
@@ -1068,7 +1068,7 @@ static char_u *execreg_line_continuation(char **lines, size_t *idx)
ga_clear(&ga);
*idx = i;
- return (char_u *)str;
+ return str;
}
/// Execute a yank register: copy it into the stuff buffer
@@ -1118,9 +1118,9 @@ int do_execreg(int regname, int colon, int addcr, int silent)
// When in Visual mode "'<,'>" will be prepended to the command.
// Remove it when it's already there.
if (VIsual_active && strncmp(p, "'<,'>", 5) == 0) {
- retval = put_in_typebuf((char_u *)p + 5, true, true, silent);
+ retval = put_in_typebuf(p + 5, true, true, silent);
} else {
- retval = put_in_typebuf((char_u *)p, true, true, silent);
+ retval = put_in_typebuf(p, true, true, silent);
}
xfree(p);
} else if (regname == '=') {
@@ -1128,15 +1128,15 @@ int do_execreg(int regname, int colon, int addcr, int silent)
if (p == NULL) {
return FAIL;
}
- retval = put_in_typebuf((char_u *)p, true, colon, silent);
+ retval = put_in_typebuf(p, true, colon, silent);
xfree(p);
} else if (regname == '.') { // use last inserted text
- p = (char *)get_last_insert_save();
+ p = get_last_insert_save();
if (p == NULL) {
emsg(_(e_noinstext));
return FAIL;
}
- retval = put_in_typebuf((char_u *)p, false, colon, silent);
+ retval = put_in_typebuf(p, false, colon, silent);
xfree(p);
} else {
yankreg_T *reg = get_yank_register(regname, YREG_PASTE);
@@ -1164,7 +1164,7 @@ int do_execreg(int regname, int colon, int addcr, int silent)
if (colon && i > 0) {
p = skipwhite(str);
if (*p == '\\' || (p[0] == '"' && p[1] == '\\' && p[2] == ' ')) {
- str = (char *)execreg_line_continuation(reg->y_array, &i);
+ str = execreg_line_continuation(reg->y_array, &i);
free_str = true;
}
}
@@ -1193,18 +1193,20 @@ static void put_reedit_in_typebuf(int silent)
{
char_u buf[3];
- if (restart_edit != NUL) {
- if (restart_edit == 'V') {
- buf[0] = 'g';
- buf[1] = 'R';
- buf[2] = NUL;
- } else {
- buf[0] = (char_u)(restart_edit == 'I' ? 'i' : restart_edit);
- buf[1] = NUL;
- }
- if (ins_typebuf((char *)buf, REMAP_NONE, 0, true, silent) == OK) {
- restart_edit = NUL;
- }
+ if (restart_edit == NUL) {
+ return;
+ }
+
+ if (restart_edit == 'V') {
+ buf[0] = 'g';
+ buf[1] = 'R';
+ buf[2] = NUL;
+ } else {
+ buf[0] = (char_u)(restart_edit == 'I' ? 'i' : restart_edit);
+ buf[1] = NUL;
+ }
+ if (ins_typebuf((char *)buf, REMAP_NONE, 0, true, silent) == OK) {
+ restart_edit = NUL;
}
}
@@ -1214,7 +1216,7 @@ static void put_reedit_in_typebuf(int silent)
/// @param esc when true then it is to be taken literally: Escape K_SPECIAL
/// characters and no remapping.
/// @param colon add ':' before the line
-static int put_in_typebuf(char_u *s, bool esc, bool colon, int silent)
+static int put_in_typebuf(char *s, bool esc, bool colon, int silent)
{
int retval = OK;
@@ -1226,9 +1228,9 @@ static int put_in_typebuf(char_u *s, bool esc, bool colon, int silent)
char *p;
if (esc) {
- p = vim_strsave_escape_ks((char *)s);
+ p = vim_strsave_escape_ks(s);
} else {
- p = (char *)s;
+ p = s;
}
if (p == NULL) {
retval = FAIL;
@@ -1347,11 +1349,11 @@ bool get_spec_reg(int regname, char **argp, bool *allocated, bool errmsg)
if (last_search_pat() == NULL && errmsg) {
emsg(_(e_noprevre));
}
- *argp = (char *)last_search_pat();
+ *argp = last_search_pat();
return true;
case '.': // last inserted text
- *argp = (char *)get_last_insert_save();
+ *argp = get_last_insert_save();
*allocated = true;
if (*argp == NULL && errmsg) {
emsg(_(e_noinstext));
@@ -1363,9 +1365,8 @@ bool get_spec_reg(int regname, char **argp, bool *allocated, bool errmsg)
if (!errmsg) {
return false;
}
- *argp
- = (char *)file_name_at_cursor(FNAME_MESS | FNAME_HYP | (regname == Ctrl_P ? FNAME_EXP : 0),
- 1L, NULL);
+ *argp = file_name_at_cursor(FNAME_MESS | FNAME_HYP | (regname == Ctrl_P ? FNAME_EXP : 0),
+ 1L, NULL);
*allocated = true;
return true;
@@ -1418,11 +1419,11 @@ bool cmdline_paste_reg(int regname, bool literally_arg, bool remcr)
}
for (size_t i = 0; i < reg->y_size; i++) {
- cmdline_paste_str((char_u *)reg->y_array[i], literally);
+ cmdline_paste_str(reg->y_array[i], literally);
// Insert ^M between lines, unless `remcr` is true.
if (i < reg->y_size - 1 && !remcr) {
- cmdline_paste_str((char_u *)"\r", literally);
+ cmdline_paste_str("\r", literally);
}
// Check for CTRL-C, in case someone tries to paste a few thousand
@@ -1455,7 +1456,7 @@ int op_delete(oparg_T *oap)
{
int n;
linenr_T lnum;
- char_u *ptr;
+ char *ptr;
char *newp, *oldp;
struct block_def bd = { 0 };
linenr_T old_lcount = curbuf->b_ml.ml_line_count;
@@ -1489,11 +1490,11 @@ int op_delete(oparg_T *oap)
&& oap->line_count > 1
&& oap->motion_force == NUL
&& oap->op_type == OP_DELETE) {
- ptr = (char_u *)ml_get(oap->end.lnum) + oap->end.col;
+ ptr = ml_get(oap->end.lnum) + oap->end.col;
if (*ptr != NUL) {
ptr += oap->inclusive;
}
- ptr = (char_u *)skipwhite((char *)ptr);
+ ptr = skipwhite(ptr);
if (*ptr == NUL && inindent(0)) {
oap->motion_type = kMTLineWise;
}
@@ -1785,10 +1786,12 @@ setmarks:
/// Used for deletion.
static void mb_adjust_opend(oparg_T *oap)
{
- if (oap->inclusive) {
- char *p = ml_get(oap->end.lnum);
- oap->end.col += utf_cp_tail_off(p, p + oap->end.col);
+ if (!oap->inclusive) {
+ return;
}
+
+ char *p = ml_get(oap->end.lnum);
+ oap->end.col += utf_cp_tail_off(p, p + oap->end.col);
}
/// Put character 'c' at position 'lp'
@@ -2573,12 +2576,14 @@ void free_register(yankreg_T *reg)
FUNC_ATTR_NONNULL_ALL
{
set_yreg_additional_data(reg, NULL);
- if (reg->y_array != NULL) {
- for (size_t i = reg->y_size; i-- > 0;) { // from y_size - 1 to 0 included
- xfree(reg->y_array[i]);
- }
- XFREE_CLEAR(reg->y_array);
+ if (reg->y_array == NULL) {
+ return;
+ }
+
+ for (size_t i = reg->y_size; i-- > 0;) { // from y_size - 1 to 0 included
+ xfree(reg->y_array[i]);
}
+ XFREE_CLEAR(reg->y_array);
}
/// Yanks the text between "oap->start" and "oap->end" into a yank register.
@@ -2738,7 +2743,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
}
if (curr != reg) { // append the new block to the old block
- new_ptr = xmalloc(sizeof(char_u *) * (curr->y_size + reg->y_size));
+ new_ptr = xmalloc(sizeof(char *) * (curr->y_size + reg->y_size));
for (j = 0; j < curr->y_size; j++) {
new_ptr[j] = curr->y_array[j];
}
@@ -3081,7 +3086,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
if (y_array != NULL) {
break;
}
- y_array = xmalloc(y_size * sizeof(char_u *));
+ y_array = xmalloc(y_size * sizeof(char *));
}
} else {
y_size = 1; // use fake one-line yank register
@@ -3146,7 +3151,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
if (y_size == 0 || y_array == NULL) {
semsg(_("E353: Nothing in register %s"),
- regname == 0 ? (char_u *)"\"" : transchar(regname));
+ regname == 0 ? "\"" : transchar(regname));
goto end;
}
@@ -3711,20 +3716,23 @@ void adjust_cursor_eol(void)
{
unsigned int cur_ve_flags = get_ve_flags();
- if (curwin->w_cursor.col > 0
- && gchar_cursor() == NUL
- && (cur_ve_flags & VE_ONEMORE) == 0
- && !(restart_edit || (State & MODE_INSERT))) {
- // Put the cursor on the last character in the line.
- dec_cursor();
+ const bool adj_cursor = (curwin->w_cursor.col > 0
+ && gchar_cursor() == NUL
+ && (cur_ve_flags & VE_ONEMORE) == 0
+ && !(restart_edit || (State & MODE_INSERT)));
+ if (!adj_cursor) {
+ return;
+ }
- if (cur_ve_flags == VE_ALL) {
- colnr_T scol, ecol;
+ // Put the cursor on the last character in the line.
+ dec_cursor();
- // Coladd is set to the width of the last character.
- getvcol(curwin, &curwin->w_cursor, &scol, NULL, &ecol);
- curwin->w_cursor.coladd = ecol - scol + 1;
- }
+ if (cur_ve_flags == VE_ALL) {
+ colnr_T scol, ecol;
+
+ // Coladd is set to the width of the last character.
+ getvcol(curwin, &curwin->w_cursor, &scol, NULL, &ecol);
+ curwin->w_cursor.coladd = ecol - scol + 1;
}
}
@@ -3884,9 +3892,9 @@ void ex_display(exarg_T *eap)
// display last search pattern
if (last_search_pat() != NULL
&& (arg == NULL || vim_strchr(arg, '/') != NULL) && !got_int
- && !message_filtered((char *)last_search_pat())) {
+ && !message_filtered(last_search_pat())) {
msg_puts("\n c \"/ ");
- dis_msg((char *)last_search_pat(), false);
+ dis_msg(last_search_pat(), false);
}
// display last used expression
@@ -4205,11 +4213,13 @@ static bool reset_lbr(void)
/// Restore 'linebreak' and take care of side effects.
static void restore_lbr(bool lbr_saved)
{
- if (!curwin->w_p_lbr && lbr_saved) {
- // changing 'linebreak' may require w_virtcol to be updated
- curwin->w_p_lbr = true;
- curwin->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL);
+ if (curwin->w_p_lbr || !lbr_saved) {
+ return;
}
+
+ // changing 'linebreak' may require w_virtcol to be updated
+ curwin->w_p_lbr = true;
+ curwin->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL);
}
/// prepare a few things for block mode yank/delete/tilde
@@ -4468,7 +4478,7 @@ void op_addsub(oparg_T *oap, linenr_T Prenum1, bool g_cmd)
int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
{
int col;
- char_u *buf1 = NULL;
+ char *buf1 = NULL;
char buf2[NUMBUFLEN];
int pre; // 'X' or 'x': hex; '0': octal; 'B' or 'b': bin
static bool hexupper = false; // 0xABC
@@ -4740,7 +4750,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
// When there are many leading zeros it could be very long.
// Allocate a bit too much.
buf1 = xmalloc((size_t)length + NUMBUFLEN);
- ptr = (char *)buf1;
+ ptr = buf1;
if (negative && (!visual || was_positive)) {
*ptr++ = '-';
}
@@ -4792,7 +4802,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
}
*ptr = NUL;
STRCAT(buf1, buf2);
- ins_str((char *)buf1); // insert the new number
+ ins_str(buf1); // insert the new number
endpos = curwin->w_cursor;
if (curwin->w_cursor.col) {
curwin->w_cursor.col--;
@@ -5081,7 +5091,7 @@ void write_reg_contents_ex(int name, const char *str, ssize_t len, bool must_app
// Special case: '/' search pattern
if (name == '/') {
- set_last_search_pat((char_u *)str, RE_SEARCH, true, true);
+ set_last_search_pat(str, RE_SEARCH, true, true);
return;
}
@@ -5171,7 +5181,7 @@ static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type, const char *str,
// Count the number of lines within the string
if (str_list) {
- for (char_u **ss = (char_u **)str; *ss != NULL; ss++) {
+ for (char **ss = (char **)str; *ss != NULL; ss++) {
newlines++;
}
} else {
@@ -5193,7 +5203,7 @@ static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type, const char *str,
}
// Grow the register array to hold the pointers to the new lines.
- char **pp = xrealloc(y_ptr->y_array, (y_ptr->y_size + newlines) * sizeof(char_u *));
+ char **pp = xrealloc(y_ptr->y_array, (y_ptr->y_size + newlines) * sizeof(char *));
y_ptr->y_array = pp;
size_t lnum = y_ptr->y_size; // The current line number.
@@ -5212,12 +5222,11 @@ static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type, const char *str,
}
} else {
size_t line_len;
- for (const char_u *start = (char_u *)str, *end = (char_u *)str + len;
+ for (const char *start = str, *end = str + len;
start < end + extraline;
start += line_len + 1, lnum++) {
assert(end - start >= 0);
- line_len = (size_t)((char_u *)xmemscan(start, '\n',
- (size_t)(end - start)) - start);
+ line_len = (size_t)((char *)xmemscan(start, '\n', (size_t)(end - start)) - start);
if (line_len > maxlen) {
maxlen = line_len;
}
@@ -5269,8 +5278,8 @@ void clear_oparg(oparg_T *oap)
/// line, stopping if it encounters an end-of-line (NUL byte). In that
/// case, eol_size will be added to the character count to account for
/// the size of the EOL character.
-static varnumber_T line_count_info(char_u *line, varnumber_T *wc, varnumber_T *cc,
- varnumber_T limit, int eol_size)
+static varnumber_T line_count_info(char *line, varnumber_T *wc, varnumber_T *cc, varnumber_T limit,
+ int eol_size)
{
varnumber_T i;
varnumber_T words = 0;
@@ -5287,7 +5296,7 @@ static varnumber_T line_count_info(char_u *line, varnumber_T *wc, varnumber_T *c
is_word = 1;
}
chars++;
- i += utfc_ptr2len((char *)line + i);
+ i += utfc_ptr2len(line + i);
}
if (is_word) {
@@ -5312,8 +5321,8 @@ static varnumber_T line_count_info(char_u *line, varnumber_T *wc, varnumber_T *c
void cursor_pos_info(dict_T *dict)
{
char *p;
- char_u buf1[50];
- char_u buf2[40];
+ char buf1[50];
+ char buf2[40];
linenr_T lnum;
varnumber_T byte_count = 0;
varnumber_T bom_count = 0;
@@ -5422,7 +5431,7 @@ void cursor_pos_info(dict_T *dict)
break;
}
if (s != NULL) {
- byte_count_cursor += line_count_info((char_u *)s, &word_count_cursor,
+ byte_count_cursor += line_count_info(s, &word_count_cursor,
&char_count_cursor, len, eol_size);
if (lnum == curbuf->b_ml.ml_line_count
&& !curbuf->b_p_eol
@@ -5437,14 +5446,14 @@ void cursor_pos_info(dict_T *dict)
word_count_cursor += word_count;
char_count_cursor += char_count;
byte_count_cursor = byte_count
- + line_count_info((char_u *)ml_get(lnum), &word_count_cursor,
+ + line_count_info(ml_get(lnum), &word_count_cursor,
&char_count_cursor,
(varnumber_T)curwin->w_cursor.col + 1,
eol_size);
}
}
// Add to the running totals
- byte_count += line_count_info((char_u *)ml_get(lnum), &word_count, &char_count,
+ byte_count += line_count_info(ml_get(lnum), &word_count, &char_count,
(varnumber_T)MAXCOL, eol_size);
}
@@ -5459,7 +5468,7 @@ void cursor_pos_info(dict_T *dict)
getvcols(curwin, &min_pos, &max_pos, &min_pos.col, &max_pos.col);
int64_t cols;
STRICT_SUB(oparg.end_vcol + 1, oparg.start_vcol, &cols, int64_t);
- vim_snprintf((char *)buf1, sizeof(buf1), _("%" PRId64 " Cols; "),
+ vim_snprintf(buf1, sizeof(buf1), _("%" PRId64 " Cols; "),
cols);
} else {
buf1[0] = NUL;
@@ -5490,7 +5499,7 @@ void cursor_pos_info(dict_T *dict)
} else {
p = get_cursor_line_ptr();
validate_virtcol();
- col_print((char *)buf1, sizeof(buf1), (int)curwin->w_cursor.col + 1,
+ col_print(buf1, sizeof(buf1), (int)curwin->w_cursor.col + 1,
(int)curwin->w_virtcol + 1);
col_print((char *)buf2, sizeof(buf2), (int)strlen(p), linetabsize(p));
@@ -5500,7 +5509,7 @@ void cursor_pos_info(dict_T *dict)
_("Col %s of %s; Line %" PRId64 " of %" PRId64 ";"
" Word %" PRId64 " of %" PRId64 ";"
" Byte %" PRId64 " of %" PRId64 ""),
- (char *)buf1, (char *)buf2,
+ buf1, buf2,
(int64_t)curwin->w_cursor.lnum,
(int64_t)curbuf->b_ml.ml_line_count,
(int64_t)word_count_cursor, (int64_t)word_count,
@@ -5511,7 +5520,7 @@ void cursor_pos_info(dict_T *dict)
" Word %" PRId64 " of %" PRId64 ";"
" Char %" PRId64 " of %" PRId64 ";"
" Byte %" PRId64 " of %" PRId64 ""),
- (char *)buf1, (char *)buf2,
+ buf1, buf2,
(int64_t)curwin->w_cursor.lnum,
(int64_t)curbuf->b_ml.ml_line_count,
(int64_t)word_count_cursor, (int64_t)word_count,
@@ -5617,10 +5626,11 @@ static void op_colon(oparg_T *oap)
static Callback opfunc_cb;
/// Process the 'operatorfunc' option value.
-/// @return OK or FAIL
-int set_operatorfunc_option(void)
+void set_operatorfunc_option(char **errmsg)
{
- return option_set_callback_func(p_opfunc, &opfunc_cb);
+ if (option_set_callback_func(p_opfunc, &opfunc_cb) == FAIL) {
+ *errmsg = e_invarg;
+ }
}
#if defined(EXITFREE)
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 02c770e608..387b94533c 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -36,6 +36,7 @@
#include "nvim/buffer.h"
#include "nvim/change.h"
#include "nvim/charset.h"
+#include "nvim/cmdexpand.h"
#include "nvim/cursor_shape.h"
#include "nvim/decoration_provider.h"
#include "nvim/diff.h"
@@ -81,6 +82,7 @@
#include "nvim/regexp.h"
#include "nvim/runtime.h"
#include "nvim/screen.h"
+#include "nvim/search.h"
#include "nvim/sign_defs.h"
#include "nvim/spell.h"
#include "nvim/spellfile.h"
@@ -173,8 +175,6 @@ void set_init_tablocal(void)
/// editor state initialized here. Do logging in set_init_2 or later.
void set_init_1(bool clean_arg)
{
- int opt_idx;
-
langmap_init();
// Find default value for 'shell' option.
@@ -202,7 +202,7 @@ void set_init_1(bool clean_arg)
static char *(names[3]) = { "TMPDIR", "TEMP", "TMP" };
#endif
garray_T ga;
- opt_idx = findoption("backupskip");
+ int opt_idx = findoption("backupskip");
ga_init(&ga, 1, 100);
for (size_t n = 0; n < ARRAY_SIZE(names); n++) {
@@ -251,19 +251,14 @@ void set_init_1(bool clean_arg)
}
{
- char *cdpath;
- char *buf;
- int i;
- int j;
-
// Initialize the 'cdpath' option's default value.
- cdpath = vim_getenv("CDPATH");
+ char *cdpath = vim_getenv("CDPATH");
if (cdpath != NULL) {
- buf = xmalloc(2 * strlen(cdpath) + 2);
+ char *buf = xmalloc(2 * strlen(cdpath) + 2);
{
buf[0] = ','; // start with ",", current dir first
- j = 1;
- for (i = 0; cdpath[i] != NUL; i++) {
+ int j = 1;
+ for (int i = 0; cdpath[i] != NUL; i++) {
if (vim_ispathlistsep(cdpath[i])) {
buf[j++] = ',';
} else {
@@ -274,7 +269,7 @@ void set_init_1(bool clean_arg)
}
}
buf[j] = NUL;
- opt_idx = findoption("cdpath");
+ int opt_idx = findoption("cdpath");
if (opt_idx >= 0) {
options[opt_idx].def_val = buf;
options[opt_idx].flags |= P_DEF_ALLOCED;
@@ -339,25 +334,25 @@ void set_init_1(bool clean_arg)
// them.
// Don't set the P_ALLOCED flag, because we don't want to free the
// default.
- for (opt_idx = 0; options[opt_idx].fullname; opt_idx++) {
- if (options[opt_idx].flags & P_NO_DEF_EXP) {
+ for (int opt_idx = 0; options[opt_idx].fullname; opt_idx++) {
+ vimoption_T *opt = &options[opt_idx];
+ if (opt->flags & P_NO_DEF_EXP) {
continue;
}
char *p;
- if ((options[opt_idx].flags & P_GETTEXT)
- && options[opt_idx].var != NULL) {
- p = _(*(char **)options[opt_idx].var);
+ if ((opt->flags & P_GETTEXT) && opt->var != NULL) {
+ p = _(*(char **)opt->var);
} else {
p = option_expand(opt_idx, NULL);
}
if (p != NULL) {
p = xstrdup(p);
- *(char **)options[opt_idx].var = p;
- if (options[opt_idx].flags & P_DEF_ALLOCED) {
- xfree(options[opt_idx].def_val);
+ *(char **)opt->var = p;
+ if (opt->flags & P_DEF_ALLOCED) {
+ xfree(opt->def_val);
}
- options[opt_idx].def_val = p;
- options[opt_idx].flags |= P_DEF_ALLOCED;
+ opt->def_val = p;
+ opt->flags |= P_DEF_ALLOCED;
}
}
@@ -379,12 +374,12 @@ void set_init_1(bool clean_arg)
// enc_locale() will try to find the encoding of the current locale.
// This will be used when 'default' is used as encoding specifier
// in 'fileencodings'
- char_u *p = enc_locale();
+ char *p = enc_locale();
if (p == NULL) {
// use utf-8 as 'default' if locale encoding can't be detected.
- p = (char_u *)xmemdupz(S_LEN("utf-8"));
+ p = xmemdupz(S_LEN("utf-8"));
}
- fenc_default = (char *)p;
+ fenc_default = p;
#ifdef HAVE_WORKING_LIBINTL
// GNU gettext 0.10.37 supports this feature: set the codeset used for
@@ -400,32 +395,32 @@ void set_init_1(bool clean_arg)
/// This does not take care of side effects!
///
/// @param opt_flags OPT_FREE, OPT_LOCAL and/or OPT_GLOBAL
-static void set_option_default(int opt_idx, int opt_flags)
+static void set_option_default(const int opt_idx, int opt_flags)
{
- char_u *varp; // pointer to variable for current option
int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0;
- varp = (char_u *)get_varp_scope(&(options[opt_idx]), both ? OPT_LOCAL : opt_flags);
- uint32_t flags = options[opt_idx].flags;
+ // pointer to variable for current option
+ vimoption_T *opt = &options[opt_idx];
+ char_u *varp = (char_u *)get_varp_scope(opt, both ? OPT_LOCAL : opt_flags);
+ uint32_t flags = opt->flags;
if (varp != NULL) { // skip hidden option, nothing to do for it
if (flags & P_STRING) {
// Use set_string_option_direct() for local options to handle
// freeing and allocating the value.
- if (options[opt_idx].indir != PV_NONE) {
- set_string_option_direct(NULL, opt_idx,
- options[opt_idx].def_val, opt_flags, 0);
+ if (opt->indir != PV_NONE) {
+ set_string_option_direct(NULL, opt_idx, opt->def_val, opt_flags, 0);
} else {
if ((opt_flags & OPT_FREE) && (flags & P_ALLOCED)) {
free_string_option(*(char **)(varp));
}
- *(char **)varp = options[opt_idx].def_val;
- options[opt_idx].flags &= ~P_ALLOCED;
+ *(char **)varp = opt->def_val;
+ opt->flags &= ~P_ALLOCED;
}
} else if (flags & P_NUM) {
- if (options[opt_idx].indir == PV_SCROLL) {
+ if (opt->indir == PV_SCROLL) {
win_comp_scroll(curwin);
} else {
- long def_val = (long)options[opt_idx].def_val;
+ long def_val = (long)opt->def_val;
if ((long *)varp == &curwin->w_p_so
|| (long *)varp == &curwin->w_p_siso) {
// 'scrolloff' and 'sidescrolloff' local values have a
@@ -436,21 +431,21 @@ static void set_option_default(int opt_idx, int opt_flags)
}
// May also set global value for local option.
if (both) {
- *(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) =
+ *(long *)get_varp_scope(opt, OPT_GLOBAL) =
def_val;
}
}
} else { // P_BOOL
- *(int *)varp = (int)(intptr_t)options[opt_idx].def_val;
+ *(int *)varp = (int)(intptr_t)opt->def_val;
#ifdef UNIX
// 'modeline' defaults to off for root
- if (options[opt_idx].indir == PV_ML && getuid() == ROOT_UID) {
+ if (opt->indir == PV_ML && getuid() == ROOT_UID) {
*(int *)varp = false;
}
#endif
// May also set global value for local option.
if (both) {
- *(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) =
+ *(int *)get_varp_scope(opt, OPT_GLOBAL) =
*(int *)varp;
}
}
@@ -493,12 +488,13 @@ static void set_string_default(const char *name, char *val, bool allocated)
{
int opt_idx = findoption(name);
if (opt_idx >= 0) {
- if (options[opt_idx].flags & P_DEF_ALLOCED) {
- xfree(options[opt_idx].def_val);
+ vimoption_T *opt = &options[opt_idx];
+ if (opt->flags & P_DEF_ALLOCED) {
+ xfree(opt->def_val);
}
- options[opt_idx].def_val = allocated ? val : xstrdup(val);
- options[opt_idx].flags |= P_DEF_ALLOCED;
+ opt->def_val = allocated ? val : xstrdup(val);
+ opt->flags |= P_DEF_ALLOCED;
}
}
@@ -507,12 +503,12 @@ static void set_string_default(const char *name, char *val, bool allocated)
static char *find_dup_item(char *origval, const char *newval, uint32_t flags)
FUNC_ATTR_NONNULL_ARG(2)
{
- int bs = 0;
-
if (origval == NULL) {
return NULL;
}
+ int bs = 0;
+
const size_t newlen = strlen(newval);
for (char *s = origval; *s != NUL; s++) {
if ((!(flags & P_COMMA) || s == origval || (s[-1] == ',' && !(bs & 1)))
@@ -572,11 +568,9 @@ void set_init_2(bool headless)
// set in set_init_1 but logging is not allowed there
ILOG("startup runtimepath/packpath value: %s", p_rtp);
- int idx;
-
// 'scroll' defaults to half the window height. The stored default is zero,
// which results in the actual value computed from the window height.
- idx = findoption("scroll");
+ int idx = findoption("scroll");
if (idx >= 0 && !(options[idx].flags & P_WAS_SET)) {
set_option_default(idx, OPT_LOCAL);
}
@@ -674,23 +668,25 @@ void set_helplang_default(const char *lang)
return;
}
int idx = findoption("hlg");
- if (idx >= 0 && !(options[idx].flags & P_WAS_SET)) {
- if (options[idx].flags & P_ALLOCED) {
- free_string_option(p_hlg);
- }
- p_hlg = xmemdupz(lang, lang_len);
- // zh_CN becomes "cn", zh_TW becomes "tw".
- if (STRNICMP(p_hlg, "zh_", 3) == 0 && strlen(p_hlg) >= 5) {
- p_hlg[0] = (char)TOLOWER_ASC(p_hlg[3]);
- p_hlg[1] = (char)TOLOWER_ASC(p_hlg[4]);
- } else if (strlen(p_hlg) >= 1 && *p_hlg == 'C') {
- // any C like setting, such as C.UTF-8, becomes "en"
- p_hlg[0] = 'e';
- p_hlg[1] = 'n';
- }
- p_hlg[2] = NUL;
- options[idx].flags |= P_ALLOCED;
+ if (idx < 0 || (options[idx].flags & P_WAS_SET)) {
+ return;
+ }
+
+ if (options[idx].flags & P_ALLOCED) {
+ free_string_option(p_hlg);
}
+ p_hlg = xmemdupz(lang, lang_len);
+ // zh_CN becomes "cn", zh_TW becomes "tw".
+ if (STRNICMP(p_hlg, "zh_", 3) == 0 && strlen(p_hlg) >= 5) {
+ p_hlg[0] = (char)TOLOWER_ASC(p_hlg[3]);
+ p_hlg[1] = (char)TOLOWER_ASC(p_hlg[4]);
+ } else if (strlen(p_hlg) >= 1 && *p_hlg == 'C') {
+ // any C like setting, such as C.UTF-8, becomes "en"
+ p_hlg[0] = 'e';
+ p_hlg[1] = 'n';
+ }
+ p_hlg[2] = NUL;
+ options[idx].flags |= P_ALLOCED;
}
/// 'title' and 'icon' only default to true if they have not been set or reset
@@ -730,25 +726,181 @@ void ex_set(exarg_T *eap)
(void)do_set(eap->arg, flags);
}
+static void do_set_bool(int opt_idx, int opt_flags, int prefix, int nextchar, const char *varp,
+ char **errmsg)
+{
+ varnumber_T value;
+
+ // ":set opt!": invert
+ // ":set opt&": reset to default value
+ // ":set opt<": reset to global value
+ if (nextchar == '!') {
+ value = *(int *)(varp) ^ 1;
+ } else if (nextchar == '&') {
+ value = (int)(intptr_t)options[opt_idx].def_val;
+ } else if (nextchar == '<') {
+ // For 'autoread' -1 means to use global value.
+ if ((int *)varp == &curbuf->b_p_ar && opt_flags == OPT_LOCAL) {
+ value = -1;
+ } else {
+ value = *(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL);
+ }
+ } else {
+ if (prefix == 2) {
+ value = *(int *)varp ^ 1; // ":set invopt": invert
+ } else {
+ value = prefix; // ":set opt" or ":set noopt": set or reset
+ }
+ }
+
+ *errmsg = set_bool_option(opt_idx, (char_u *)varp, (int)value, opt_flags);
+}
+
+static void do_set_num(int opt_idx, int opt_flags, char **argp, int nextchar, const set_op_T op,
+ const char *varp, char *errbuf, size_t errbuflen, char **errmsg)
+{
+ varnumber_T value;
+ char *arg = *argp;
+
+ // Different ways to set a number option:
+ // & set to default value
+ // < set to global value
+ // <xx> accept special key codes for 'wildchar'
+ // c accept any non-digit for 'wildchar'
+ // [-]0-9 set number
+ // other error
+ arg++;
+ if (nextchar == '&') {
+ value = (long)(intptr_t)options[opt_idx].def_val;
+ } else if (nextchar == '<') {
+ // For 'undolevels' NO_LOCAL_UNDOLEVEL means to
+ // use the global value.
+ if ((long *)varp == &curbuf->b_p_ul && opt_flags == OPT_LOCAL) {
+ value = NO_LOCAL_UNDOLEVEL;
+ } else {
+ value = *(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL);
+ }
+ } else if (((long *)varp == &p_wc
+ || (long *)varp == &p_wcm)
+ && (*arg == '<'
+ || *arg == '^'
+ || (*arg != NUL && (!arg[1] || ascii_iswhite(arg[1]))
+ && !ascii_isdigit(*arg)))) {
+ value = string_to_key(arg);
+ if (value == 0 && (long *)varp != &p_wcm) {
+ *errmsg = e_invarg;
+ return;
+ }
+ } else if (*arg == '-' || ascii_isdigit(*arg)) {
+ int i;
+ // Allow negative, octal and hex numbers.
+ vim_str2nr(arg, NULL, &i, STR2NR_ALL, &value, NULL, 0, true);
+ if (i == 0 || (arg[i] != NUL && !ascii_iswhite(arg[i]))) {
+ *errmsg = e_number_required_after_equal;
+ return;
+ }
+ } else {
+ *errmsg = e_number_required_after_equal;
+ return;
+ }
+
+ if (op == OP_ADDING) {
+ value = *(long *)varp + value;
+ }
+ if (op == OP_PREPENDING) {
+ value = *(long *)varp * value;
+ }
+ if (op == OP_REMOVING) {
+ value = *(long *)varp - value;
+ }
+ *errmsg = set_num_option(opt_idx, (char_u *)varp, (long)value,
+ errbuf, errbuflen, opt_flags);
+}
+
+// Handle some special cases with string option values
+static void munge_string_opt_val(char **varp, char **oldval, char **const origval,
+ char_u **const origval_l, char_u **const origval_g,
+ char **const argp, char *const whichwrap, size_t whichwraplen,
+ char **const save_argp)
+{
+ // Set 'keywordprg' to ":help" if an empty
+ // value was passed to :set by the user.
+ if (varp == &p_kp && (**argp == NUL || **argp == ' ')) {
+ *save_argp = *argp;
+ *argp = ":help";
+ } else if (varp == &p_bs && ascii_isdigit(**(char_u **)varp)) {
+ // Convert 'backspace' number to string, for
+ // adding, prepending and removing string.
+ const int i = getdigits_int(varp, true, 0);
+ switch (i) {
+ case 0:
+ *varp = empty_option;
+ break;
+ case 1:
+ *varp = xstrdup("indent,eol");
+ break;
+ case 2:
+ *varp = xstrdup("indent,eol,start");
+ break;
+ case 3:
+ *varp = xstrdup("indent,eol,nostop");
+ break;
+ }
+ xfree(*oldval);
+ if (*origval == *oldval) {
+ *origval = *varp;
+ }
+ if (*origval_l == (char_u *)(*oldval)) {
+ *origval_l = *(char_u **)varp;
+ }
+ if (*origval_g == (char_u *)(*oldval)) {
+ *origval_g = *(char_u **)varp;
+ }
+ *oldval = *varp;
+ } else if (varp == &p_ww && ascii_isdigit(**argp)) {
+ // Convert 'whichwrap' number to string, for backwards compatibility
+ // with Vim 3.0.
+ *whichwrap = NUL;
+ int i = getdigits_int(argp, true, 0);
+ if (i & 1) {
+ xstrlcat(whichwrap, "b,", whichwraplen);
+ }
+ if (i & 2) {
+ xstrlcat(whichwrap, "s,", whichwraplen);
+ }
+ if (i & 4) {
+ xstrlcat(whichwrap, "h,l,", whichwraplen);
+ }
+ if (i & 8) {
+ xstrlcat(whichwrap, "<,>,", whichwraplen);
+ }
+ if (i & 16) {
+ xstrlcat(whichwrap, "[,],", whichwraplen);
+ }
+ if (*whichwrap != NUL) { // remove trailing ,
+ whichwrap[strlen(whichwrap) - 1] = NUL;
+ }
+ *save_argp = *argp;
+ *argp = whichwrap;
+ } else if (**argp == '>' && (varp == &p_dir || varp == &p_bdir)) {
+ // Remove '>' before 'dir' and 'bdir', for backwards compatibility with
+ // version 3.0
+ (*argp)++;
+ }
+}
+
/// Part of do_set() for string options.
-/// @return FAIL on failure, do not process further options.
-static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, set_op_T op_arg,
- uint32_t flags, char *varp_arg, char *errbuf, size_t errbuflen,
- int *value_checked, char **errmsg)
+static void do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, set_op_T op_arg,
+ uint32_t flags, char *varp_arg, char *errbuf, size_t errbuflen,
+ int *value_checked, char **errmsg)
{
char *arg = *argp;
set_op_T op = op_arg;
char *varp = varp_arg;
char *save_arg = NULL;
char *s = NULL;
- char *oldval = NULL; // previous value if *varp
- char *origval = NULL;
char_u *origval_l = NULL;
char_u *origval_g = NULL;
- char *saved_origval = NULL;
- char *saved_origval_l = NULL;
- char *saved_origval_g = NULL;
- char *saved_newval = NULL;
char whichwrap[80];
// When using ":set opt=val" for a global option
@@ -760,7 +912,7 @@ static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar,
}
// The old value is kept until we are sure that the new value is valid.
- oldval = *(char **)varp;
+ char *oldval = *(char **)varp;
if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) {
origval_l = *(char_u **)get_varp_scope(&(options[opt_idx]), OPT_LOCAL);
@@ -773,6 +925,7 @@ static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar,
}
}
+ char *origval;
// When setting the local value of a global option, the old value may be
// the global value.
if (((int)options[opt_idx].indir & PV_BOTH) && (opt_flags & OPT_LOCAL)) {
@@ -803,70 +956,8 @@ static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar,
} else {
arg++; // jump to after the '=' or ':'
- // Set 'keywordprg' to ":help" if an empty
- // value was passed to :set by the user.
- if (varp == (char *)&p_kp && (*arg == NUL || *arg == ' ')) {
- save_arg = arg;
- arg = ":help";
- } else if (varp == (char *)&p_bs && ascii_isdigit(**(char_u **)varp)) {
- // Convert 'backspace' number to string, for
- // adding, prepending and removing string.
- int i = getdigits_int((char **)varp, true, 0);
- switch (i) {
- case 0:
- *(char **)varp = empty_option;
- break;
- case 1:
- *(char_u **)varp = (char_u *)xstrdup("indent,eol");
- break;
- case 2:
- *(char_u **)varp = (char_u *)xstrdup("indent,eol,start");
- break;
- case 3:
- *(char_u **)varp = (char_u *)xstrdup("indent,eol,nostop");
- break;
- }
- xfree(oldval);
- if (origval == oldval) {
- origval = *(char **)varp;
- }
- if (origval_l == (char_u *)oldval) {
- origval_l = *(char_u **)varp;
- }
- if (origval_g == (char_u *)oldval) {
- origval_g = *(char_u **)varp;
- }
- oldval = *(char **)varp;
- } else if (varp == (char *)&p_ww && ascii_isdigit(*arg)) {
- // Convert 'whichwrap' number to string, for backwards compatibility
- // with Vim 3.0.
- *whichwrap = NUL;
- int i = getdigits_int(&arg, true, 0);
- if (i & 1) {
- xstrlcat(whichwrap, "b,", sizeof(whichwrap));
- }
- if (i & 2) {
- xstrlcat(whichwrap, "s,", sizeof(whichwrap));
- }
- if (i & 4) {
- xstrlcat(whichwrap, "h,l,", sizeof(whichwrap));
- }
- if (i & 8) {
- xstrlcat(whichwrap, "<,>,", sizeof(whichwrap));
- }
- if (i & 16) {
- xstrlcat(whichwrap, "[,],", sizeof(whichwrap));
- }
- if (*whichwrap != NUL) { // remove trailing ,
- whichwrap[strlen(whichwrap) - 1] = NUL;
- }
- save_arg = arg;
- arg = whichwrap;
- } else if (*arg == '>' && (varp == (char *)&p_dir || varp == (char *)&p_bdir)) {
- // Remove '>' before 'dir' and 'bdir', for backwards compatibility with
- // version 3.0
- arg++;
- }
+ munge_string_opt_val((char **)varp, &oldval, &origval, &origval_l, &origval_g, &arg,
+ whichwrap, sizeof(whichwrap), &save_arg);
// Copy the new string into allocated memory.
// Can't use set_string_option_direct(), because we need to remove the
@@ -995,14 +1086,14 @@ static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar,
// 'whichwrap'
if (flags & P_ONECOMMA) {
if (*s != ',' && *(s + 1) == ','
- && vim_strchr(s + 2, *s) != NULL) {
+ && vim_strchr(s + 2, (uint8_t)(*s)) != NULL) {
// Remove the duplicated value and the next comma.
STRMOVE(s, s + 2);
continue;
}
} else {
if ((!(flags & P_COMMA) || *s != ',')
- && vim_strchr(s + 1, *s) != NULL) {
+ && vim_strchr(s + 1, (uint8_t)(*s)) != NULL) {
STRMOVE(s, s + 1);
continue;
}
@@ -1020,13 +1111,13 @@ static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar,
*(char_u **)(varp) = (char_u *)newval;
// origval may be freed by did_set_string_option(), make a copy.
- saved_origval = (origval != NULL) ? xstrdup(origval) : NULL;
- saved_origval_l = (origval_l != NULL) ? xstrdup((char *)origval_l) : NULL;
- saved_origval_g = (origval_g != NULL) ? xstrdup((char *)origval_g) : NULL;
+ char *saved_origval = (origval != NULL) ? xstrdup(origval) : NULL;
+ char *saved_origval_l = (origval_l != NULL) ? xstrdup((char *)origval_l) : NULL;
+ char *saved_origval_g = (origval_g != NULL) ? xstrdup((char *)origval_g) : NULL;
// newval (and varp) may become invalid if the buffer is closed by
// autocommands.
- saved_newval = (newval != NULL) ? xstrdup(newval) : NULL;
+ char *saved_newval = (newval != NULL) ? xstrdup(newval) : NULL;
{
uint32_t *p = insecure_flag(curwin, opt_idx, opt_flags);
@@ -1068,416 +1159,391 @@ static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar,
xfree(saved_newval);
*argp = arg;
- return *errmsg == NULL ? OK : FAIL;
}
-/// Parse 'arg' for option settings.
-///
-/// 'arg' may be IObuff, but only when no errors can be present and option
-/// does not need to be expanded with option_expand().
-/// "opt_flags":
-/// 0 for ":set"
-/// OPT_GLOBAL for ":setglobal"
-/// OPT_LOCAL for ":setlocal" and a modeline
-/// OPT_MODELINE for a modeline
-/// OPT_WINONLY to only set window-local options
-/// OPT_NOWIN to skip setting window-local options
-///
-/// @param arg option string (may be written to!)
-///
+static set_op_T get_op(const char *arg)
+{
+ set_op_T op = OP_NONE;
+ if (*arg != NUL && *(arg + 1) == '=') {
+ if (*arg == '+') {
+ op = OP_ADDING; // "+="
+ } else if (*arg == '^') {
+ op = OP_PREPENDING; // "^="
+ } else if (*arg == '-') {
+ op = OP_REMOVING; // "-="
+ }
+ }
+ return op;
+}
+
+static int get_option_prefix(char **argp)
+{
+ if (strncmp(*argp, "no", 2) == 0) {
+ *argp += 2;
+ return 0;
+ } else if (strncmp(*argp, "inv", 3) == 0) {
+ *argp += 3;
+ return 2;
+ }
+
+ return 1;
+}
+
+/// @param[in] arg Pointer to start option name
+/// @param[out] opt_idxp Option index in options[] table.
+/// @param[out] keyp
+/// @param[out] len Length of option name
/// @return FAIL if an error is detected, OK otherwise
-int do_set(char *arg, int opt_flags)
+static int parse_option_name(char *arg, int *keyp, int *lenp, int *opt_idxp)
{
- int did_show = false; // already showed one value
+ // find end of name
+ int key = 0;
+ int len;
+ int opt_idx;
- if (*arg == NUL) {
- showoptions(0, opt_flags);
- did_show = true;
- goto theend;
- }
-
- char errbuf[80];
-
- while (*arg != NUL) { // loop to process all options
- char *errmsg = NULL;
- char *startarg = arg; // remember for error message
-
- if (strncmp(arg, "all", 3) == 0 && !isalpha(arg[3])
- && !(opt_flags & OPT_MODELINE)) {
- // ":set all" show all options.
- // ":set all&" set all options to their default value.
- arg += 3;
- if (*arg == '&') {
- arg++;
- // Only for :set command set global value of local options.
- set_options_default(OPT_FREE | opt_flags);
- didset_options();
- didset_options2();
- ui_refresh_options();
- redraw_all_later(UPD_CLEAR);
- } else {
- showoptions(1, opt_flags);
- did_show = true;
- }
+ if (*arg == '<') {
+ opt_idx = -1;
+ // look out for <t_>;>
+ if (arg[1] == 't' && arg[2] == '_' && arg[3] && arg[4]) {
+ len = 5;
} else {
- int prefix = 1; // 1: nothing, 0: "no", 2: "inv" in front of name
- if (strncmp(arg, "no", 2) == 0) {
- prefix = 0;
- arg += 2;
- } else if (strncmp(arg, "inv", 3) == 0) {
- prefix = 2;
- arg += 3;
+ len = 1;
+ while (arg[len] != NUL && arg[len] != '>') {
+ len++;
}
-
- // find end of name
- int key = 0;
- int len;
- int opt_idx;
- if (*arg == '<') {
- opt_idx = -1;
- // look out for <t_>;>
- if (arg[1] == 't' && arg[2] == '_' && arg[3] && arg[4]) {
- len = 5;
- } else {
- len = 1;
- while (arg[len] != NUL && arg[len] != '>') {
- len++;
- }
- }
- if (arg[len] != '>') {
- errmsg = e_invarg;
- goto skip;
- }
- if (arg[1] == 't' && arg[2] == '_') { // could be term code
- opt_idx = findoption_len((const char *)arg + 1, (size_t)(len - 1));
- }
+ }
+ if (arg[len] != '>') {
+ return FAIL;
+ }
+ if (arg[1] == 't' && arg[2] == '_') { // could be term code
+ opt_idx = findoption_len((const char *)arg + 1, (size_t)(len - 1));
+ }
+ len++;
+ if (opt_idx == -1) {
+ key = find_key_option(arg + 1, true);
+ }
+ } else {
+ // The two characters after "t_" may not be alphanumeric.
+ if (arg[0] == 't' && arg[1] == '_' && arg[2] && arg[3]) {
+ len = 4;
+ } else {
+ len = 0;
+ while (ASCII_ISALNUM(arg[len]) || arg[len] == '_') {
len++;
- if (opt_idx == -1) {
- key = find_key_option(arg + 1, true);
- }
- } else {
- len = 0;
- // The two characters after "t_" may not be alphanumeric.
- if (arg[0] == 't' && arg[1] == '_' && arg[2] && arg[3]) {
- len = 4;
- } else {
- while (ASCII_ISALNUM(arg[len]) || arg[len] == '_') {
- len++;
- }
- }
- opt_idx = findoption_len((const char *)arg, (size_t)len);
- if (opt_idx == -1) {
- key = find_key_option(arg, false);
- }
}
+ }
+ opt_idx = findoption_len((const char *)arg, (size_t)len);
+ if (opt_idx == -1) {
+ key = find_key_option(arg, false);
+ }
+ }
- // remember character after option name
- int afterchar = (uint8_t)arg[len];
+ *keyp = key;
+ *lenp = len;
+ *opt_idxp = opt_idx;
- // skip white space, allow ":set ai ?"
- while (ascii_iswhite(arg[len])) {
- len++;
- }
+ return OK;
+}
- set_op_T op = OP_NONE;
- if (arg[len] != NUL && arg[len + 1] == '=') {
- if (arg[len] == '+') {
- op = OP_ADDING; // "+="
- len++;
- } else if (arg[len] == '^') {
- op = OP_PREPENDING; // "^="
- len++;
- } else if (arg[len] == '-') {
- op = OP_REMOVING; // "-="
- len++;
- }
- }
- char_u nextchar = (uint8_t)arg[len]; // next non-white char after option name
+static int validate_opt_idx(win_T *win, int opt_idx, int opt_flags, uint32_t flags, int prefix,
+ char **errmsg)
+{
+ // Only bools can have a prefix of 'inv' or 'no'
+ if (!(flags & P_BOOL) && prefix != 1) {
+ *errmsg = e_invarg;
+ return FAIL;
+ }
- if (opt_idx == -1 && key == 0) { // found a mismatch: skip
- errmsg = e_unknown_option;
- goto skip;
- }
+ // Skip all options that are not window-local (used when showing
+ // an already loaded buffer in a window).
+ if ((opt_flags & OPT_WINONLY)
+ && (opt_idx < 0 || options[opt_idx].var != VAR_WIN)) {
+ return FAIL;
+ }
- uint32_t flags; // flags for current option
- char *varp = NULL; // pointer to variable for current option
-
- if (opt_idx >= 0) {
- if (options[opt_idx].var == NULL) { // hidden option: skip
- // Only give an error message when requesting the value of
- // a hidden option, ignore setting it.
- if (vim_strchr("=:!&<", nextchar) == NULL
- && (!(options[opt_idx].flags & P_BOOL)
- || nextchar == '?')) {
- errmsg = e_unsupportedoption;
- }
- goto skip;
- }
+ // Skip all options that are window-local (used for :vimgrep).
+ if ((opt_flags & OPT_NOWIN) && opt_idx >= 0
+ && options[opt_idx].var == VAR_WIN) {
+ return FAIL;
+ }
- flags = options[opt_idx].flags;
- varp = get_varp_scope(&(options[opt_idx]), opt_flags);
- } else {
- flags = P_STRING;
- }
+ // Disallow changing some options from modelines.
+ if (opt_flags & OPT_MODELINE) {
+ if (flags & (P_SECURE | P_NO_ML)) {
+ *errmsg = e_not_allowed_in_modeline;
+ return FAIL;
+ }
+ if ((flags & P_MLE) && !p_mle) {
+ *errmsg = e_not_allowed_in_modeline_when_modelineexpr_is_off;
+ return FAIL;
+ }
+ // In diff mode some options are overruled. This avoids that
+ // 'foldmethod' becomes "marker" instead of "diff" and that
+ // "wrap" gets set.
+ if (win->w_p_diff
+ && opt_idx >= 0 // shut up coverity warning
+ && (options[opt_idx].indir == PV_FDM
+ || options[opt_idx].indir == PV_WRAP)) {
+ return FAIL;
+ }
+ }
- // Skip all options that are not window-local (used when showing
- // an already loaded buffer in a window).
- if ((opt_flags & OPT_WINONLY)
- && (opt_idx < 0 || options[opt_idx].var != VAR_WIN)) {
- goto skip;
- }
+ // Disallow changing some options in the sandbox
+ if (sandbox != 0 && (flags & P_SECURE)) {
+ *errmsg = e_sandbox;
+ return FAIL;
+ }
- // Skip all options that are window-local (used for :vimgrep).
- if ((opt_flags & OPT_NOWIN) && opt_idx >= 0
- && options[opt_idx].var == VAR_WIN) {
- goto skip;
- }
+ return OK;
+}
- // Disallow changing some options from modelines.
- if (opt_flags & OPT_MODELINE) {
- if (flags & (P_SECURE | P_NO_ML)) {
- errmsg = e_not_allowed_in_modeline;
- goto skip;
- }
- if ((flags & P_MLE) && !p_mle) {
- errmsg = e_not_allowed_in_modeline_when_modelineexpr_is_off;
- goto skip;
- }
- // In diff mode some options are overruled. This avoids that
- // 'foldmethod' becomes "marker" instead of "diff" and that
- // "wrap" gets set.
- if (curwin->w_p_diff
- && opt_idx >= 0 // shut up coverity warning
- && (options[opt_idx].indir == PV_FDM
- || options[opt_idx].indir == PV_WRAP)) {
- goto skip;
- }
- }
+static void do_set_option_value(int opt_idx, int opt_flags, char **argp, int prefix, int nextchar,
+ set_op_T op, uint32_t flags, char *varp, char *errbuf,
+ size_t errbuflen, char **errmsg)
+{
+ int value_checked = false;
+ if (flags & P_BOOL) { // boolean
+ do_set_bool(opt_idx, opt_flags, prefix, nextchar, varp, errmsg);
+ } else if (flags & P_NUM) { // numeric
+ do_set_num(opt_idx, opt_flags, argp, nextchar, op, varp, errbuf, errbuflen, errmsg);
+ } else if (opt_idx >= 0) { // string.
+ do_set_string(opt_idx, opt_flags, argp, nextchar, op, flags, varp, errbuf,
+ errbuflen, &value_checked, errmsg);
+ } else {
+ // key code option(FIXME(tarruda): Show a warning or something
+ // similar)
+ }
- // Disallow changing some options in the sandbox
- if (sandbox != 0 && (flags & P_SECURE)) {
- errmsg = e_sandbox;
- goto skip;
- }
+ if (*errmsg != NULL) {
+ return;
+ }
- if (vim_strchr("?=:!&<", nextchar) != NULL) {
- arg += len;
- if (nextchar == '&' && arg[1] == 'v' && arg[2] == 'i') {
- if (arg[3] == 'm') { // "opt&vim": set to Vim default
- arg += 3;
- } else { // "opt&vi": set to Vi default
- arg += 2;
- }
- }
- if (vim_strchr("?!&<", nextchar) != NULL
- && arg[1] != NUL && !ascii_iswhite(arg[1])) {
- errmsg = e_trailing;
- goto skip;
- }
- }
+ if (opt_idx >= 0) {
+ did_set_option(opt_idx, opt_flags, op == OP_NONE, value_checked);
+ }
+}
- //
- // allow '=' and ':' as MS-DOS command.com allows only one
- // '=' character per "set" command line. grrr. (jw)
- //
- if (nextchar == '?'
- || (prefix == 1
- && vim_strchr("=:&<", nextchar) == NULL
- && !(flags & P_BOOL))) {
- // print value
- if (did_show) {
- msg_putchar('\n'); // cursor below last one
- } else {
- gotocmdline(true); // cursor at status line
- did_show = true; // remember that we did a line
- }
- if (opt_idx >= 0) {
- showoneopt(&options[opt_idx], opt_flags);
- if (p_verbose > 0) {
- // Mention where the option was last set.
- if (varp == (char *)options[opt_idx].var) {
- option_last_set_msg(options[opt_idx].last_set);
- } else if ((int)options[opt_idx].indir & PV_WIN) {
- option_last_set_msg(curwin->w_p_script_ctx[
- (int)options[opt_idx].indir & PV_MASK]);
- } else if ((int)options[opt_idx].indir & PV_BUF) {
- option_last_set_msg(curbuf->b_p_script_ctx[
- (int)options[opt_idx].indir & PV_MASK]);
- }
- }
- } else {
- errmsg = e_key_code_not_set;
- goto skip;
- }
- if (nextchar != '?'
- && nextchar != NUL && !ascii_iswhite(afterchar)) {
- errmsg = e_trailing;
- }
- } else {
- int value_checked = false;
- varnumber_T value;
+static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errbuf,
+ size_t errbuflen, char **errmsg)
+{
+ // 1: nothing, 0: "no", 2: "inv" in front of name
+ int prefix = get_option_prefix(argp);
- if (flags & P_BOOL) { // boolean
- if (nextchar == '=' || nextchar == ':') {
- errmsg = e_invarg;
- goto skip;
- }
+ char *arg = *argp;
- // ":set opt!": invert
- // ":set opt&": reset to default value
- // ":set opt<": reset to global value
- if (nextchar == '!') {
- value = *(int *)(varp) ^ 1;
- } else if (nextchar == '&') {
- value = (int)(intptr_t)options[opt_idx].def_val;
- } else if (nextchar == '<') {
- // For 'autoread' -1 means to use global value.
- if ((int *)varp == &curbuf->b_p_ar
- && opt_flags == OPT_LOCAL) {
- value = -1;
- } else {
- value = *(int *)get_varp_scope(&(options[opt_idx]),
- OPT_GLOBAL);
- }
- } else {
- // ":set invopt": invert
- // ":set opt" or ":set noopt": set or reset
- if (nextchar != NUL && !ascii_iswhite(afterchar)) {
- errmsg = e_trailing;
- goto skip;
- }
- if (prefix == 2) { // inv
- value = *(int *)(varp) ^ 1;
- } else {
- value = prefix;
- }
- }
+ // find end of name
+ int key = 0;
+ int len;
+ int opt_idx;
+ if (parse_option_name(arg, &key, &len, &opt_idx) == FAIL) {
+ *errmsg = e_invarg;
+ return;
+ }
- errmsg = set_bool_option(opt_idx, (char_u *)varp, (int)value, opt_flags);
- } else { // Numeric or string.
- if (vim_strchr("=:&<", nextchar) == NULL
- || prefix != 1) {
- errmsg = e_invarg;
- goto skip;
- }
+ // remember character after option name
+ int afterchar = (uint8_t)arg[len];
- if (flags & P_NUM) { // numeric
- // Different ways to set a number option:
- // & set to default value
- // < set to global value
- // <xx> accept special key codes for 'wildchar'
- // c accept any non-digit for 'wildchar'
- // [-]0-9 set number
- // other error
- arg++;
- if (nextchar == '&') {
- value = (long)(intptr_t)options[opt_idx].def_val;
- } else if (nextchar == '<') {
- // For 'undolevels' NO_LOCAL_UNDOLEVEL means to
- // use the global value.
- if ((long *)varp == &curbuf->b_p_ul && opt_flags == OPT_LOCAL) {
- value = NO_LOCAL_UNDOLEVEL;
- } else {
- value = *(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL);
- }
- } else if (((long *)varp == &p_wc
- || (long *)varp == &p_wcm)
- && (*arg == '<'
- || *arg == '^'
- || (*arg != NUL && (!arg[1] || ascii_iswhite(arg[1]))
- && !ascii_isdigit(*arg)))) {
- value = string_to_key((char_u *)arg);
- if (value == 0 && (long *)varp != &p_wcm) {
- errmsg = e_invarg;
- goto skip;
- }
- } else if (*arg == '-' || ascii_isdigit(*arg)) {
- int i;
- // Allow negative, octal and hex numbers.
- vim_str2nr(arg, NULL, &i, STR2NR_ALL, &value, NULL, 0, true);
- if (i == 0 || (arg[i] != NUL && !ascii_iswhite(arg[i]))) {
- errmsg = e_number_required_after_equal;
- goto skip;
- }
- } else {
- errmsg = e_number_required_after_equal;
- goto skip;
- }
+ // skip white space, allow ":set ai ?"
+ while (ascii_iswhite(arg[len])) {
+ len++;
+ }
- if (op == OP_ADDING) {
- value = *(long *)varp + value;
- }
- if (op == OP_PREPENDING) {
- value = *(long *)varp * value;
- }
- if (op == OP_REMOVING) {
- value = *(long *)varp - value;
- }
- errmsg = set_num_option(opt_idx, (char_u *)varp, (long)value,
- errbuf, sizeof(errbuf),
- opt_flags);
- } else if (opt_idx >= 0) { // String.
- if (do_set_string(opt_idx, opt_flags, &arg, nextchar,
- op, flags, varp, errbuf, sizeof(errbuf),
- &value_checked, &errmsg) == FAIL) {
- if (errmsg != NULL) {
- goto skip;
- }
- break;
- }
- } else {
- // key code option(FIXME(tarruda): Show a warning or something
- // similar)
- }
- }
+ set_op_T op = get_op(arg + len);
+ if (op != OP_NONE) {
+ len++;
+ }
- if (opt_idx >= 0) {
- did_set_option(opt_idx, opt_flags, op == OP_NONE, value_checked);
- }
+ uint8_t nextchar = (uint8_t)arg[len]; // next non-white char after option name
+
+ if (opt_idx == -1 && key == 0) { // found a mismatch: skip
+ *errmsg = e_unknown_option;
+ return;
+ }
+
+ uint32_t flags; // flags for current option
+ char *varp = NULL; // pointer to variable for current option
+
+ if (opt_idx >= 0) {
+ if (options[opt_idx].var == NULL) { // hidden option: skip
+ // Only give an error message when requesting the value of
+ // a hidden option, ignore setting it.
+ if (vim_strchr("=:!&<", nextchar) == NULL
+ && (!(options[opt_idx].flags & P_BOOL)
+ || nextchar == '?')) {
+ *errmsg = e_unsupportedoption;
}
+ return;
+ }
-skip:
- // Advance to next argument.
- // - skip until a blank found, taking care of backslashes
- // - skip blanks
- // - skip one "=val" argument (for hidden options ":set gfn =xx")
- for (int i = 0; i < 2; i++) {
- while (*arg != NUL && !ascii_iswhite(*arg)) {
- if (*arg++ == '\\' && *arg != NUL) {
- arg++;
- }
- }
- arg = skipwhite(arg);
- if (*arg != '=') {
- break;
- }
+ flags = options[opt_idx].flags;
+ varp = get_varp_scope(&(options[opt_idx]), opt_flags);
+ } else {
+ flags = P_STRING;
+ }
+
+ if (validate_opt_idx(curwin, opt_idx, opt_flags, flags, prefix, errmsg) == FAIL) {
+ return;
+ }
+
+ if (vim_strchr("?=:!&<", nextchar) != NULL) {
+ *argp += len;
+ if (nextchar == '&' && (*argp)[1] == 'v' && (*argp)[2] == 'i') {
+ if ((*argp)[3] == 'm') { // "opt&vim": set to Vim default
+ *argp += 3;
+ } else { // "opt&vi": set to Vi default
+ *argp += 2;
}
}
+ if (vim_strchr("?!&<", nextchar) != NULL
+ && (*argp)[1] != NUL && !ascii_iswhite((*argp)[1])) {
+ *errmsg = e_trailing;
+ return;
+ }
+ }
- if (errmsg != NULL) {
- xstrlcpy(IObuff, _(errmsg), IOSIZE);
- int i = (int)strlen(IObuff) + 2;
- if (i + (arg - startarg) < IOSIZE) {
- // append the argument with the error
- STRCAT(IObuff, ": ");
- assert(arg >= startarg);
- memmove(IObuff + i, startarg, (size_t)(arg - startarg));
- IObuff[i + (arg - startarg)] = NUL;
+ //
+ // allow '=' and ':' as MS-DOS command.com allows only one
+ // '=' character per "set" command line. grrr. (jw)
+ //
+ if (nextchar == '?'
+ || (prefix == 1
+ && vim_strchr("=:&<", nextchar) == NULL
+ && !(flags & P_BOOL))) {
+ // print value
+ if (*did_show) {
+ msg_putchar('\n'); // cursor below last one
+ } else {
+ gotocmdline(true); // cursor at status line
+ *did_show = true; // remember that we did a line
+ }
+ if (opt_idx >= 0) {
+ showoneopt(&options[opt_idx], opt_flags);
+ if (p_verbose > 0) {
+ // Mention where the option was last set.
+ if (varp == (char *)options[opt_idx].var) {
+ option_last_set_msg(options[opt_idx].last_set);
+ } else if ((int)options[opt_idx].indir & PV_WIN) {
+ option_last_set_msg(curwin->w_p_script_ctx[(int)options[opt_idx].indir & PV_MASK]);
+ } else if ((int)options[opt_idx].indir & PV_BUF) {
+ option_last_set_msg(curbuf->b_p_script_ctx[(int)options[opt_idx].indir & PV_MASK]);
+ }
}
- // make sure all characters are printable
- trans_characters(IObuff, IOSIZE);
+ } else {
+ *errmsg = e_key_code_not_set;
+ return;
+ }
+ if (nextchar != '?' && nextchar != NUL && !ascii_iswhite(afterchar)) {
+ *errmsg = e_trailing;
+ }
+ return;
+ }
- no_wait_return++; // wait_return() done later
- emsg(IObuff); // show error highlighted
- no_wait_return--;
+ if (flags & P_BOOL) {
+ if (vim_strchr("=:", nextchar) != NULL) {
+ *errmsg = e_invarg;
+ return;
+ }
- return FAIL;
+ if (vim_strchr("!&<", nextchar) == NULL && nextchar != NUL && !ascii_iswhite(afterchar)) {
+ *errmsg = e_trailing;
+ return;
}
+ } else {
+ if (vim_strchr("=:&<", nextchar) == NULL) {
+ *errmsg = e_invarg;
+ return;
+ }
+ }
+
+ do_set_option_value(opt_idx, opt_flags, argp, prefix, nextchar, op, flags, varp,
+ errbuf, errbuflen, errmsg);
+}
+
+/// Parse 'arg' for option settings.
+///
+/// 'arg' may be IObuff, but only when no errors can be present and option
+/// does not need to be expanded with option_expand().
+/// "opt_flags":
+/// 0 for ":set"
+/// OPT_GLOBAL for ":setglobal"
+/// OPT_LOCAL for ":setlocal" and a modeline
+/// OPT_MODELINE for a modeline
+/// OPT_WINONLY to only set window-local options
+/// OPT_NOWIN to skip setting window-local options
+///
+/// @param arg option string (may be written to!)
+///
+/// @return FAIL if an error is detected, OK otherwise
+int do_set(char *arg, int opt_flags)
+{
+ bool did_show = false; // already showed one value
- arg = skipwhite(arg);
+ if (*arg == NUL) {
+ showoptions(false, opt_flags);
+ did_show = true;
+ } else {
+ while (*arg != NUL) { // loop to process all options
+ if (strncmp(arg, "all", 3) == 0 && !ASCII_ISALPHA(arg[3])
+ && !(opt_flags & OPT_MODELINE)) {
+ // ":set all" show all options.
+ // ":set all&" set all options to their default value.
+ arg += 3;
+ if (*arg == '&') {
+ arg++;
+ // Only for :set command set global value of local options.
+ set_options_default(OPT_FREE | opt_flags);
+ didset_options();
+ didset_options2();
+ ui_refresh_options();
+ redraw_all_later(UPD_CLEAR);
+ } else {
+ showoptions(true, opt_flags);
+ did_show = true;
+ }
+ } else {
+ char *startarg = arg; // remember for error message
+ char *errmsg = NULL;
+ char errbuf[80];
+
+ do_set_option(opt_flags, &arg, &did_show, errbuf, sizeof(errbuf), &errmsg);
+
+ // Advance to next argument.
+ // - skip until a blank found, taking care of backslashes
+ // - skip blanks
+ // - skip one "=val" argument (for hidden options ":set gfn =xx")
+ for (int i = 0; i < 2; i++) {
+ arg = skiptowhite_esc(arg);
+ arg = skipwhite(arg);
+ if (*arg != '=') {
+ break;
+ }
+ }
+
+ if (errmsg != NULL) {
+ xstrlcpy(IObuff, _(errmsg), IOSIZE);
+ int i = (int)strlen(IObuff) + 2;
+ if (i + (arg - startarg) < IOSIZE) {
+ // append the argument with the error
+ STRCAT(IObuff, ": ");
+ assert(arg >= startarg);
+ memmove(IObuff + i, startarg, (size_t)(arg - startarg));
+ IObuff[i + (arg - startarg)] = NUL;
+ }
+ // make sure all characters are printable
+ trans_characters(IObuff, IOSIZE);
+
+ no_wait_return++; // wait_return() done later
+ emsg(IObuff); // show error highlighted
+ no_wait_return--;
+
+ return FAIL;
+ }
+ }
+
+ arg = skipwhite(arg);
+ }
}
-theend:
if (silent_mode && did_show) {
// After displaying option values in silent mode.
silent_mode = false;
@@ -1516,15 +1582,15 @@ void did_set_option(int opt_idx, int opt_flags, int new_value, int value_checked
/// Convert a key name or string into a key value.
/// Used for 'wildchar' and 'cedit' options.
-int string_to_key(char_u *arg)
+int string_to_key(char *arg)
{
if (*arg == '<') {
- return find_key_option((char *)arg + 1, true);
+ return find_key_option(arg + 1, true);
}
if (*arg == '^') {
- return CTRL_CHR(arg[1]);
+ return CTRL_CHR((uint8_t)arg[1]);
}
- return *arg;
+ return (uint8_t)(*arg);
}
// When changing 'title', 'titlestring', 'icon' or 'iconstring', call
@@ -1597,9 +1663,9 @@ void set_options_bin(int oldval, int newval, int opt_flags)
/// number, return -1.
int get_shada_parameter(int type)
{
- char_u *p = find_shada_parameter(type);
+ char *p = find_shada_parameter(type);
if (p != NULL && ascii_isdigit(*p)) {
- return atoi((char *)p);
+ return atoi(p);
}
return -1;
}
@@ -1607,11 +1673,11 @@ int get_shada_parameter(int type)
/// Find the parameter represented by the given character (eg ''', ':', '"', or
/// '/') in the 'shada' option and return a pointer to the string after it.
/// Return NULL if the parameter is not specified in the string.
-char_u *find_shada_parameter(int type)
+char *find_shada_parameter(int type)
{
for (char *p = p_shada; *p; p++) {
if (*p == type) {
- return (char_u *)p + 1;
+ return p + 1;
}
if (*p == 'n') { // 'n' is always the last one
break;
@@ -1650,7 +1716,7 @@ static char *option_expand(int opt_idx, char *val)
// names.
// For 'spellsuggest' expand after "file:".
expand_env_esc(val, NameBuff, MAXPATHL,
- (char_u **)options[opt_idx].var == &p_tags, false,
+ (char **)options[opt_idx].var == &p_tags, false,
(char_u **)options[opt_idx].var == (char_u **)&p_sps ? "file:" :
NULL);
if (strcmp(NameBuff, val) == 0) { // they are the same
@@ -1703,9 +1769,7 @@ static void didset_options2(void)
/// Check for string options that are NULL (normally only termcap options).
void check_options(void)
{
- int opt_idx;
-
- for (opt_idx = 0; options[opt_idx].fullname != NULL; opt_idx++) {
+ for (int opt_idx = 0; options[opt_idx].fullname != NULL; opt_idx++) {
if ((options[opt_idx].flags & P_STRING) && options[opt_idx].var != NULL) {
check_string_option((char **)get_varp(&(options[opt_idx])));
}
@@ -1769,9 +1833,9 @@ void redraw_titles(void)
bool valid_name(const char *val, const char *allowed)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
- for (const char_u *s = (char_u *)val; *s != NUL; s++) {
+ for (const char *s = val; *s != NUL; s++) {
if (!ASCII_ISALNUM(*s)
- && vim_strchr(allowed, *s) == NULL) {
+ && vim_strchr(allowed, (uint8_t)(*s)) == NULL) {
return false;
}
}
@@ -1970,7 +2034,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va
|| (opt_flags & OPT_GLOBAL) || opt_flags == 0)
&& !bufIsChanged(bp) && bp->b_ml.ml_mfp != NULL) {
u_compute_hash(bp, hash);
- u_read_undo(NULL, hash, (char_u *)bp->b_fname);
+ u_read_undo(NULL, hash, bp->b_fname);
}
}
}
@@ -2256,8 +2320,7 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf,
errmsg = e_positive;
}
} else if (pp == &p_ch) {
- int minval = 0;
- if (value < minval) {
+ if (value < 0) {
errmsg = e_positive;
} else {
p_ch_was_zero = value == 0;
@@ -2593,7 +2656,7 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf,
}
/// Called after an option changed: check if something needs to be redrawn.
-void check_redraw(uint32_t flags)
+void check_redraw_for(buf_T *buf, win_T *win, uint32_t flags)
{
// Careful: P_RALL is a combination of other P_ flags
bool all = (flags & P_RALL) == P_RALL;
@@ -2607,19 +2670,24 @@ void check_redraw(uint32_t flags)
}
if ((flags & P_RBUF) || (flags & P_RWIN) || all) {
- changed_window_setting();
+ changed_window_setting_win(win);
}
if (flags & P_RBUF) {
- redraw_curbuf_later(UPD_NOT_VALID);
+ redraw_buf_later(buf, UPD_NOT_VALID);
}
if (flags & P_RWINONLY) {
- redraw_later(curwin, UPD_NOT_VALID);
+ redraw_later(win, UPD_NOT_VALID);
}
if (all) {
redraw_all_later(UPD_NOT_VALID);
}
}
+void check_redraw(uint32_t flags)
+{
+ check_redraw_for(curbuf, curwin, flags);
+}
+
/// Find index for named option
///
/// @param[in] arg Option to find index for.
@@ -2876,7 +2944,6 @@ int get_option_value_strict(char *name, int64_t *numval, char **stringval, int o
return SOPT_STRING | SOPT_GLOBAL;
}
- char_u *varp = NULL;
int rv = 0;
int opt_idx = findoption(name);
if (opt_idx < 0) {
@@ -2926,6 +2993,8 @@ int get_option_value_strict(char *name, int64_t *numval, char **stringval, int o
return rv;
}
+ char_u *varp = NULL;
+
if (opt_type == SREQ_GLOBAL) {
if (p->var == VAR_WIN) {
return 0;
@@ -3003,58 +3072,62 @@ char *set_option_value(const char *const name, const long number, const char *co
int opt_idx = findoption(name);
if (opt_idx < 0) {
semsg(_("E355: Unknown option: %s"), name);
- } else {
- uint32_t flags = options[opt_idx].flags;
- // Disallow changing some options in the sandbox
- if (sandbox > 0 && (flags & P_SECURE)) {
- emsg(_(e_sandbox));
- return NULL;
+ return NULL;
+ }
+
+ uint32_t flags = options[opt_idx].flags;
+ // Disallow changing some options in the sandbox
+ if (sandbox > 0 && (flags & P_SECURE)) {
+ emsg(_(e_sandbox));
+ return NULL;
+ }
+
+ if (flags & P_STRING) {
+ const char *s = string;
+ if (s == NULL || opt_flags & OPT_CLEAR) {
+ s = "";
}
- if (flags & P_STRING) {
- const char *s = string;
- if (s == NULL || opt_flags & OPT_CLEAR) {
- s = "";
- }
- return set_string_option(opt_idx, s, opt_flags);
- }
-
- char_u *varp = (char_u *)get_varp_scope(&(options[opt_idx]), opt_flags);
- if (varp != NULL) { // hidden option is not changed
- if (number == 0 && string != NULL) {
- int idx;
-
- // Either we are given a string or we are setting option
- // to zero.
- for (idx = 0; string[idx] == '0'; idx++) {}
- if (string[idx] != NUL || idx == 0) {
- // There's another character after zeros or the string
- // is empty. In both cases, we are trying to set a
- // num option using a string.
- semsg(_("E521: Number required: &%s = '%s'"),
- name, string);
- return NULL; // do nothing as we hit an error
- }
- }
- long numval = number;
- if (opt_flags & OPT_CLEAR) {
- if ((int *)varp == &curbuf->b_p_ar) {
- numval = -1;
- } else if ((long *)varp == &curbuf->b_p_ul) {
- numval = NO_LOCAL_UNDOLEVEL;
- } else if ((long *)varp == &curwin->w_p_so || (long *)varp == &curwin->w_p_siso) {
- numval = -1;
- } else {
- char *s = NULL;
- (void)get_option_value(name, &numval, &s, NULL, OPT_GLOBAL);
- }
- }
- if (flags & P_NUM) {
- return set_num_option(opt_idx, varp, numval, NULL, 0, opt_flags);
- }
- return set_bool_option(opt_idx, varp, (int)numval, opt_flags);
+ return set_string_option(opt_idx, s, opt_flags);
+ }
+
+ char_u *varp = (char_u *)get_varp_scope(&(options[opt_idx]), opt_flags);
+ if (varp == NULL) {
+ // hidden option is not changed
+ return NULL;
+ }
+
+ if (number == 0 && string != NULL) {
+ int idx;
+
+ // Either we are given a string or we are setting option
+ // to zero.
+ for (idx = 0; string[idx] == '0'; idx++) {}
+ if (string[idx] != NUL || idx == 0) {
+ // There's another character after zeros or the string
+ // is empty. In both cases, we are trying to set a
+ // num option using a string.
+ semsg(_("E521: Number required: &%s = '%s'"),
+ name, string);
+ return NULL; // do nothing as we hit an error
+ }
+ }
+ long numval = number;
+ if (opt_flags & OPT_CLEAR) {
+ if ((int *)varp == &curbuf->b_p_ar) {
+ numval = -1;
+ } else if ((long *)varp == &curbuf->b_p_ul) {
+ numval = NO_LOCAL_UNDOLEVEL;
+ } else if ((long *)varp == &curwin->w_p_so || (long *)varp == &curwin->w_p_siso) {
+ numval = -1;
+ } else {
+ char *s = NULL;
+ (void)get_option_value(name, &numval, &s, NULL, OPT_GLOBAL);
}
}
- return NULL;
+ if (flags & P_NUM) {
+ return set_num_option(opt_idx, varp, numval, NULL, 0, opt_flags);
+ }
+ return set_bool_option(opt_idx, varp, (int)numval, opt_flags);
}
/// Call set_option_value() and when an error is returned report it.
@@ -3086,10 +3159,10 @@ bool is_string_option(const char *name)
// Translate a string like "t_xx", "<t_xx>" or "<S-Tab>" to a key number.
// When "has_lt" is true there is a '<' before "*arg_arg".
// Returns 0 when the key is not recognized.
-int find_key_option_len(const char_u *arg_arg, size_t len, bool has_lt)
+int find_key_option_len(const char *arg_arg, size_t len, bool has_lt)
{
int key = 0;
- const char *arg = (char *)arg_arg;
+ const char *arg = arg_arg;
// Don't use get_special_key_code() for t_xx, we don't want it to call
// add_termcap_entry().
@@ -3109,14 +3182,14 @@ int find_key_option_len(const char_u *arg_arg, size_t len, bool has_lt)
static int find_key_option(const char *arg, bool has_lt)
{
- return find_key_option_len((char_u *)arg, strlen(arg), has_lt);
+ return find_key_option_len(arg, strlen(arg), has_lt);
}
-/// if 'all' == 0: show changed options
-/// if 'all' == 1: show all normal options
+/// if 'all' == false: show changed options
+/// if 'all' == true: show all normal options
///
/// @param opt_flags OPT_LOCAL and/or OPT_GLOBAL
-static void showoptions(int all, int opt_flags)
+static void showoptions(bool all, int opt_flags)
{
#define INC 20
#define GAP 3
@@ -3427,12 +3500,13 @@ int makefoldset(FILE *fd)
static int put_setstring(FILE *fd, char *cmd, char *name, char **valuep, uint64_t flags)
{
- char_u *buf = NULL;
- char_u *part = NULL;
-
if (fprintf(fd, "%s %s=", cmd, name) < 0) {
return FAIL;
}
+
+ char *buf = NULL;
+ char_u *part = NULL;
+
if (*valuep != NULL) {
// Output 'pastetoggle' as key names. For other
// options some characters have to be escaped with
@@ -3440,7 +3514,7 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char **valuep, uint64_
if (valuep == &p_pt) {
char_u *s = (char_u *)(*valuep);
while (*s != NUL) {
- if (put_escstr(fd, (char_u *)str2special((const char **)&s, false, false), 2) == FAIL) {
+ if (put_escstr(fd, (char *)str2special((const char **)&s, false, false), 2) == FAIL) {
return FAIL;
}
}
@@ -3449,7 +3523,7 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char **valuep, uint64_
// replace home directory in the whole option value into "buf"
buf = xmalloc(size);
- home_replace(NULL, *valuep, (char *)buf, size, false);
+ home_replace(NULL, *valuep, buf, size, false);
// If the option value is longer than MAXPATHL, we need to append
// each comma separated part of the option separately, so that it
@@ -3462,7 +3536,7 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char **valuep, uint64_
if (put_eol(fd) == FAIL) {
goto fail;
}
- char *p = (char *)buf;
+ char *p = buf;
while (*p != NUL) {
// for each comma separated option part, append value to
// the option, :set rtp+=value
@@ -3470,7 +3544,7 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char **valuep, uint64_
goto fail;
}
(void)copy_option_part(&p, (char *)part, size, ",");
- if (put_escstr(fd, part, 2) == FAIL || put_eol(fd) == FAIL) {
+ if (put_escstr(fd, (char *)part, 2) == FAIL || put_eol(fd) == FAIL) {
goto fail;
}
}
@@ -3483,7 +3557,7 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char **valuep, uint64_
return FAIL;
}
xfree(buf);
- } else if (put_escstr(fd, (char_u *)(*valuep), 2) == FAIL) {
+ } else if (put_escstr(fd, *valuep, 2) == FAIL) {
return FAIL;
}
}
@@ -3499,11 +3573,10 @@ fail:
static int put_setnum(FILE *fd, char *cmd, char *name, long *valuep)
{
- long wc;
-
if (fprintf(fd, "%s %s=", cmd, name) < 0) {
return FAIL;
}
+ long wc;
if (wc_use_keyname((char_u *)valuep, &wc)) {
// print 'wildchar' and 'wildcharm' as a key name
if (fputs((char *)get_special_key_name((int)wc, 0), fd) < 0) {
@@ -3639,83 +3712,87 @@ void unset_global_local_option(char *name, void *from)
}
}
-/// Get pointer to option variable, depending on local or global scope.
-///
-/// @param scope can be OPT_LOCAL, OPT_GLOBAL or a combination.
-char *get_varp_scope(vimoption_T *p, int scope)
+char *get_varp_scope_from(vimoption_T *p, int scope, buf_T *buf, win_T *win)
{
if ((scope & OPT_GLOBAL) && p->indir != PV_NONE) {
if (p->var == VAR_WIN) {
- return GLOBAL_WO(get_varp(p));
+ return GLOBAL_WO(get_varp_from(p, buf, win));
}
return (char *)p->var;
}
if ((scope & OPT_LOCAL) && ((int)p->indir & PV_BOTH)) {
switch ((int)p->indir) {
case PV_FP:
- return (char *)&(curbuf->b_p_fp);
+ return (char *)&(buf->b_p_fp);
case PV_EFM:
- return (char *)&(curbuf->b_p_efm);
+ return (char *)&(buf->b_p_efm);
case PV_GP:
- return (char *)&(curbuf->b_p_gp);
+ return (char *)&(buf->b_p_gp);
case PV_MP:
- return (char *)&(curbuf->b_p_mp);
+ return (char *)&(buf->b_p_mp);
case PV_EP:
- return (char *)&(curbuf->b_p_ep);
+ return (char *)&(buf->b_p_ep);
case PV_KP:
- return (char *)&(curbuf->b_p_kp);
+ return (char *)&(buf->b_p_kp);
case PV_PATH:
- return (char *)&(curbuf->b_p_path);
+ return (char *)&(buf->b_p_path);
case PV_AR:
- return (char *)&(curbuf->b_p_ar);
+ return (char *)&(buf->b_p_ar);
case PV_TAGS:
- return (char *)&(curbuf->b_p_tags);
+ return (char *)&(buf->b_p_tags);
case PV_TC:
- return (char *)&(curbuf->b_p_tc);
+ return (char *)&(buf->b_p_tc);
case PV_SISO:
- return (char *)&(curwin->w_p_siso);
+ return (char *)&(win->w_p_siso);
case PV_SO:
- return (char *)&(curwin->w_p_so);
+ return (char *)&(win->w_p_so);
case PV_DEF:
- return (char *)&(curbuf->b_p_def);
+ return (char *)&(buf->b_p_def);
case PV_INC:
- return (char *)&(curbuf->b_p_inc);
+ return (char *)&(buf->b_p_inc);
case PV_DICT:
- return (char *)&(curbuf->b_p_dict);
+ return (char *)&(buf->b_p_dict);
case PV_TSR:
- return (char *)&(curbuf->b_p_tsr);
+ return (char *)&(buf->b_p_tsr);
case PV_TSRFU:
- return (char *)&(curbuf->b_p_tsrfu);
+ return (char *)&(buf->b_p_tsrfu);
case PV_TFU:
- return (char *)&(curbuf->b_p_tfu);
+ return (char *)&(buf->b_p_tfu);
case PV_SBR:
- return (char *)&(curwin->w_p_sbr);
+ return (char *)&(win->w_p_sbr);
case PV_STL:
- return (char *)&(curwin->w_p_stl);
+ return (char *)&(win->w_p_stl);
case PV_WBR:
- return (char *)&(curwin->w_p_wbr);
+ return (char *)&(win->w_p_wbr);
case PV_UL:
- return (char *)&(curbuf->b_p_ul);
+ return (char *)&(buf->b_p_ul);
case PV_LW:
- return (char *)&(curbuf->b_p_lw);
+ return (char *)&(buf->b_p_lw);
case PV_BKC:
- return (char *)&(curbuf->b_p_bkc);
+ return (char *)&(buf->b_p_bkc);
case PV_MENC:
- return (char *)&(curbuf->b_p_menc);
+ return (char *)&(buf->b_p_menc);
case PV_FCS:
- return (char *)&(curwin->w_p_fcs);
+ return (char *)&(win->w_p_fcs);
case PV_LCS:
- return (char *)&(curwin->w_p_lcs);
+ return (char *)&(win->w_p_lcs);
case PV_VE:
- return (char *)&(curwin->w_p_ve);
+ return (char *)&(win->w_p_ve);
}
return NULL; // "cannot happen"
}
- return (char *)get_varp(p);
+ return (char *)get_varp_from(p, buf, win);
}
-/// Get pointer to option variable.
-static char_u *get_varp(vimoption_T *p)
+/// Get pointer to option variable, depending on local or global scope.
+///
+/// @param scope can be OPT_LOCAL, OPT_GLOBAL or a combination.
+char *get_varp_scope(vimoption_T *p, int scope)
+{
+ return get_varp_scope_from(p, scope, curbuf, curwin);
+}
+
+static char_u *get_varp_from(vimoption_T *p, buf_T *buf, win_T *win)
{
// hidden option, always return NULL
if (p->var == NULL) {
@@ -3728,314 +3805,320 @@ static char_u *get_varp(vimoption_T *p)
// global option with local value: use local value if it's been set
case PV_EP:
- return *curbuf->b_p_ep != NUL
- ? (char_u *)&curbuf->b_p_ep : p->var;
+ return *buf->b_p_ep != NUL
+ ? (char_u *)&buf->b_p_ep : p->var;
case PV_KP:
- return *curbuf->b_p_kp != NUL
- ? (char_u *)&curbuf->b_p_kp : p->var;
+ return *buf->b_p_kp != NUL
+ ? (char_u *)&buf->b_p_kp : p->var;
case PV_PATH:
- return *curbuf->b_p_path != NUL
- ? (char_u *)&(curbuf->b_p_path) : p->var;
+ return *buf->b_p_path != NUL
+ ? (char_u *)&(buf->b_p_path) : p->var;
case PV_AR:
- return curbuf->b_p_ar >= 0
- ? (char_u *)&(curbuf->b_p_ar) : p->var;
+ return buf->b_p_ar >= 0
+ ? (char_u *)&(buf->b_p_ar) : p->var;
case PV_TAGS:
- return *curbuf->b_p_tags != NUL
- ? (char_u *)&(curbuf->b_p_tags) : p->var;
+ return *buf->b_p_tags != NUL
+ ? (char_u *)&(buf->b_p_tags) : p->var;
case PV_TC:
- return *curbuf->b_p_tc != NUL
- ? (char_u *)&(curbuf->b_p_tc) : p->var;
+ return *buf->b_p_tc != NUL
+ ? (char_u *)&(buf->b_p_tc) : p->var;
case PV_SISO:
- return curwin->w_p_siso >= 0
- ? (char_u *)&(curwin->w_p_siso) : p->var;
+ return win->w_p_siso >= 0
+ ? (char_u *)&(win->w_p_siso) : p->var;
case PV_SO:
- return curwin->w_p_so >= 0
- ? (char_u *)&(curwin->w_p_so) : p->var;
+ return win->w_p_so >= 0
+ ? (char_u *)&(win->w_p_so) : p->var;
case PV_BKC:
- return *curbuf->b_p_bkc != NUL
- ? (char_u *)&(curbuf->b_p_bkc) : p->var;
+ return *buf->b_p_bkc != NUL
+ ? (char_u *)&(buf->b_p_bkc) : p->var;
case PV_DEF:
- return *curbuf->b_p_def != NUL
- ? (char_u *)&(curbuf->b_p_def) : p->var;
+ return *buf->b_p_def != NUL
+ ? (char_u *)&(buf->b_p_def) : p->var;
case PV_INC:
- return *curbuf->b_p_inc != NUL
- ? (char_u *)&(curbuf->b_p_inc) : p->var;
+ return *buf->b_p_inc != NUL
+ ? (char_u *)&(buf->b_p_inc) : p->var;
case PV_DICT:
- return *curbuf->b_p_dict != NUL
- ? (char_u *)&(curbuf->b_p_dict) : p->var;
+ return *buf->b_p_dict != NUL
+ ? (char_u *)&(buf->b_p_dict) : p->var;
case PV_TSR:
- return *curbuf->b_p_tsr != NUL
- ? (char_u *)&(curbuf->b_p_tsr) : p->var;
+ return *buf->b_p_tsr != NUL
+ ? (char_u *)&(buf->b_p_tsr) : p->var;
case PV_TSRFU:
- return *curbuf->b_p_tsrfu != NUL
- ? (char_u *)&(curbuf->b_p_tsrfu) : p->var;
+ return *buf->b_p_tsrfu != NUL
+ ? (char_u *)&(buf->b_p_tsrfu) : p->var;
case PV_FP:
- return *curbuf->b_p_fp != NUL
- ? (char_u *)&(curbuf->b_p_fp) : p->var;
+ return *buf->b_p_fp != NUL
+ ? (char_u *)&(buf->b_p_fp) : p->var;
case PV_EFM:
- return *curbuf->b_p_efm != NUL
- ? (char_u *)&(curbuf->b_p_efm) : p->var;
+ return *buf->b_p_efm != NUL
+ ? (char_u *)&(buf->b_p_efm) : p->var;
case PV_GP:
- return *curbuf->b_p_gp != NUL
- ? (char_u *)&(curbuf->b_p_gp) : p->var;
+ return *buf->b_p_gp != NUL
+ ? (char_u *)&(buf->b_p_gp) : p->var;
case PV_MP:
- return *curbuf->b_p_mp != NUL
- ? (char_u *)&(curbuf->b_p_mp) : p->var;
+ return *buf->b_p_mp != NUL
+ ? (char_u *)&(buf->b_p_mp) : p->var;
case PV_SBR:
- return *curwin->w_p_sbr != NUL
- ? (char_u *)&(curwin->w_p_sbr) : p->var;
+ return *win->w_p_sbr != NUL
+ ? (char_u *)&(win->w_p_sbr) : p->var;
case PV_STL:
- return *curwin->w_p_stl != NUL
- ? (char_u *)&(curwin->w_p_stl) : p->var;
+ return *win->w_p_stl != NUL
+ ? (char_u *)&(win->w_p_stl) : p->var;
case PV_WBR:
- return *curwin->w_p_wbr != NUL
- ? (char_u *)&(curwin->w_p_wbr) : p->var;
+ return *win->w_p_wbr != NUL
+ ? (char_u *)&(win->w_p_wbr) : p->var;
case PV_UL:
- return curbuf->b_p_ul != NO_LOCAL_UNDOLEVEL
- ? (char_u *)&(curbuf->b_p_ul) : p->var;
+ return buf->b_p_ul != NO_LOCAL_UNDOLEVEL
+ ? (char_u *)&(buf->b_p_ul) : p->var;
case PV_LW:
- return *curbuf->b_p_lw != NUL
- ? (char_u *)&(curbuf->b_p_lw) : p->var;
+ return *buf->b_p_lw != NUL
+ ? (char_u *)&(buf->b_p_lw) : p->var;
case PV_MENC:
- return *curbuf->b_p_menc != NUL
- ? (char_u *)&(curbuf->b_p_menc) : p->var;
+ return *buf->b_p_menc != NUL
+ ? (char_u *)&(buf->b_p_menc) : p->var;
case PV_FCS:
- return *curwin->w_p_fcs != NUL
- ? (char_u *)&(curwin->w_p_fcs) : p->var;
+ return *win->w_p_fcs != NUL
+ ? (char_u *)&(win->w_p_fcs) : p->var;
case PV_LCS:
- return *curwin->w_p_lcs != NUL
- ? (char_u *)&(curwin->w_p_lcs) : p->var;
+ return *win->w_p_lcs != NUL
+ ? (char_u *)&(win->w_p_lcs) : p->var;
case PV_VE:
- return *curwin->w_p_ve != NUL
- ? (char_u *)&curwin->w_p_ve : p->var;
+ return *win->w_p_ve != NUL
+ ? (char_u *)&win->w_p_ve : p->var;
case PV_ARAB:
- return (char_u *)&(curwin->w_p_arab);
+ return (char_u *)&(win->w_p_arab);
case PV_LIST:
- return (char_u *)&(curwin->w_p_list);
+ return (char_u *)&(win->w_p_list);
case PV_SPELL:
- return (char_u *)&(curwin->w_p_spell);
+ return (char_u *)&(win->w_p_spell);
case PV_CUC:
- return (char_u *)&(curwin->w_p_cuc);
+ return (char_u *)&(win->w_p_cuc);
case PV_CUL:
- return (char_u *)&(curwin->w_p_cul);
+ return (char_u *)&(win->w_p_cul);
case PV_CULOPT:
- return (char_u *)&(curwin->w_p_culopt);
+ return (char_u *)&(win->w_p_culopt);
case PV_CC:
- return (char_u *)&(curwin->w_p_cc);
+ return (char_u *)&(win->w_p_cc);
case PV_DIFF:
- return (char_u *)&(curwin->w_p_diff);
+ return (char_u *)&(win->w_p_diff);
case PV_FDC:
- return (char_u *)&(curwin->w_p_fdc);
+ return (char_u *)&(win->w_p_fdc);
case PV_FEN:
- return (char_u *)&(curwin->w_p_fen);
+ return (char_u *)&(win->w_p_fen);
case PV_FDI:
- return (char_u *)&(curwin->w_p_fdi);
+ return (char_u *)&(win->w_p_fdi);
case PV_FDL:
- return (char_u *)&(curwin->w_p_fdl);
+ return (char_u *)&(win->w_p_fdl);
case PV_FDM:
- return (char_u *)&(curwin->w_p_fdm);
+ return (char_u *)&(win->w_p_fdm);
case PV_FML:
- return (char_u *)&(curwin->w_p_fml);
+ return (char_u *)&(win->w_p_fml);
case PV_FDN:
- return (char_u *)&(curwin->w_p_fdn);
+ return (char_u *)&(win->w_p_fdn);
case PV_FDE:
- return (char_u *)&(curwin->w_p_fde);
+ return (char_u *)&(win->w_p_fde);
case PV_FDT:
- return (char_u *)&(curwin->w_p_fdt);
+ return (char_u *)&(win->w_p_fdt);
case PV_FMR:
- return (char_u *)&(curwin->w_p_fmr);
+ return (char_u *)&(win->w_p_fmr);
case PV_NU:
- return (char_u *)&(curwin->w_p_nu);
+ return (char_u *)&(win->w_p_nu);
case PV_RNU:
- return (char_u *)&(curwin->w_p_rnu);
+ return (char_u *)&(win->w_p_rnu);
case PV_NUW:
- return (char_u *)&(curwin->w_p_nuw);
+ return (char_u *)&(win->w_p_nuw);
case PV_WFH:
- return (char_u *)&(curwin->w_p_wfh);
+ return (char_u *)&(win->w_p_wfh);
case PV_WFW:
- return (char_u *)&(curwin->w_p_wfw);
+ return (char_u *)&(win->w_p_wfw);
case PV_PVW:
- return (char_u *)&(curwin->w_p_pvw);
+ return (char_u *)&(win->w_p_pvw);
case PV_RL:
- return (char_u *)&(curwin->w_p_rl);
+ return (char_u *)&(win->w_p_rl);
case PV_RLC:
- return (char_u *)&(curwin->w_p_rlc);
+ return (char_u *)&(win->w_p_rlc);
case PV_SCROLL:
- return (char_u *)&(curwin->w_p_scr);
+ return (char_u *)&(win->w_p_scr);
case PV_WRAP:
- return (char_u *)&(curwin->w_p_wrap);
+ return (char_u *)&(win->w_p_wrap);
case PV_LBR:
- return (char_u *)&(curwin->w_p_lbr);
+ return (char_u *)&(win->w_p_lbr);
case PV_BRI:
- return (char_u *)&(curwin->w_p_bri);
+ return (char_u *)&(win->w_p_bri);
case PV_BRIOPT:
- return (char_u *)&(curwin->w_p_briopt);
+ return (char_u *)&(win->w_p_briopt);
case PV_SCBIND:
- return (char_u *)&(curwin->w_p_scb);
+ return (char_u *)&(win->w_p_scb);
case PV_CRBIND:
- return (char_u *)&(curwin->w_p_crb);
+ return (char_u *)&(win->w_p_crb);
case PV_COCU:
- return (char_u *)&(curwin->w_p_cocu);
+ return (char_u *)&(win->w_p_cocu);
case PV_COLE:
- return (char_u *)&(curwin->w_p_cole);
+ return (char_u *)&(win->w_p_cole);
case PV_AI:
- return (char_u *)&(curbuf->b_p_ai);
+ return (char_u *)&(buf->b_p_ai);
case PV_BIN:
- return (char_u *)&(curbuf->b_p_bin);
+ return (char_u *)&(buf->b_p_bin);
case PV_BOMB:
- return (char_u *)&(curbuf->b_p_bomb);
+ return (char_u *)&(buf->b_p_bomb);
case PV_BH:
- return (char_u *)&(curbuf->b_p_bh);
+ return (char_u *)&(buf->b_p_bh);
case PV_BT:
- return (char_u *)&(curbuf->b_p_bt);
+ return (char_u *)&(buf->b_p_bt);
case PV_BL:
- return (char_u *)&(curbuf->b_p_bl);
+ return (char_u *)&(buf->b_p_bl);
case PV_CHANNEL:
- return (char_u *)&(curbuf->b_p_channel);
+ return (char_u *)&(buf->b_p_channel);
case PV_CI:
- return (char_u *)&(curbuf->b_p_ci);
+ return (char_u *)&(buf->b_p_ci);
case PV_CIN:
- return (char_u *)&(curbuf->b_p_cin);
+ return (char_u *)&(buf->b_p_cin);
case PV_CINK:
- return (char_u *)&(curbuf->b_p_cink);
+ return (char_u *)&(buf->b_p_cink);
case PV_CINO:
- return (char_u *)&(curbuf->b_p_cino);
+ return (char_u *)&(buf->b_p_cino);
case PV_CINSD:
- return (char_u *)&(curbuf->b_p_cinsd);
+ return (char_u *)&(buf->b_p_cinsd);
case PV_CINW:
- return (char_u *)&(curbuf->b_p_cinw);
+ return (char_u *)&(buf->b_p_cinw);
case PV_COM:
- return (char_u *)&(curbuf->b_p_com);
+ return (char_u *)&(buf->b_p_com);
case PV_CMS:
- return (char_u *)&(curbuf->b_p_cms);
+ return (char_u *)&(buf->b_p_cms);
case PV_CPT:
- return (char_u *)&(curbuf->b_p_cpt);
+ return (char_u *)&(buf->b_p_cpt);
#ifdef BACKSLASH_IN_FILENAME
case PV_CSL:
- return (char_u *)&(curbuf->b_p_csl);
+ return (char_u *)&(buf->b_p_csl);
#endif
case PV_CFU:
- return (char_u *)&(curbuf->b_p_cfu);
+ return (char_u *)&(buf->b_p_cfu);
case PV_OFU:
- return (char_u *)&(curbuf->b_p_ofu);
+ return (char_u *)&(buf->b_p_ofu);
case PV_EOF:
- return (char_u *)&(curbuf->b_p_eof);
+ return (char_u *)&(buf->b_p_eof);
case PV_EOL:
- return (char_u *)&(curbuf->b_p_eol);
+ return (char_u *)&(buf->b_p_eol);
case PV_FIXEOL:
- return (char_u *)&(curbuf->b_p_fixeol);
+ return (char_u *)&(buf->b_p_fixeol);
case PV_ET:
- return (char_u *)&(curbuf->b_p_et);
+ return (char_u *)&(buf->b_p_et);
case PV_FENC:
- return (char_u *)&(curbuf->b_p_fenc);
+ return (char_u *)&(buf->b_p_fenc);
case PV_FF:
- return (char_u *)&(curbuf->b_p_ff);
+ return (char_u *)&(buf->b_p_ff);
case PV_FT:
- return (char_u *)&(curbuf->b_p_ft);
+ return (char_u *)&(buf->b_p_ft);
case PV_FO:
- return (char_u *)&(curbuf->b_p_fo);
+ return (char_u *)&(buf->b_p_fo);
case PV_FLP:
- return (char_u *)&(curbuf->b_p_flp);
+ return (char_u *)&(buf->b_p_flp);
case PV_IMI:
- return (char_u *)&(curbuf->b_p_iminsert);
+ return (char_u *)&(buf->b_p_iminsert);
case PV_IMS:
- return (char_u *)&(curbuf->b_p_imsearch);
+ return (char_u *)&(buf->b_p_imsearch);
case PV_INF:
- return (char_u *)&(curbuf->b_p_inf);
+ return (char_u *)&(buf->b_p_inf);
case PV_ISK:
- return (char_u *)&(curbuf->b_p_isk);
+ return (char_u *)&(buf->b_p_isk);
case PV_INEX:
- return (char_u *)&(curbuf->b_p_inex);
+ return (char_u *)&(buf->b_p_inex);
case PV_INDE:
- return (char_u *)&(curbuf->b_p_inde);
+ return (char_u *)&(buf->b_p_inde);
case PV_INDK:
- return (char_u *)&(curbuf->b_p_indk);
+ return (char_u *)&(buf->b_p_indk);
case PV_FEX:
- return (char_u *)&(curbuf->b_p_fex);
+ return (char_u *)&(buf->b_p_fex);
case PV_LISP:
- return (char_u *)&(curbuf->b_p_lisp);
+ return (char_u *)&(buf->b_p_lisp);
case PV_LOP:
- return (char_u *)&(curbuf->b_p_lop);
+ return (char_u *)&(buf->b_p_lop);
case PV_ML:
- return (char_u *)&(curbuf->b_p_ml);
+ return (char_u *)&(buf->b_p_ml);
case PV_MPS:
- return (char_u *)&(curbuf->b_p_mps);
+ return (char_u *)&(buf->b_p_mps);
case PV_MA:
- return (char_u *)&(curbuf->b_p_ma);
+ return (char_u *)&(buf->b_p_ma);
case PV_MOD:
- return (char_u *)&(curbuf->b_changed);
+ return (char_u *)&(buf->b_changed);
case PV_NF:
- return (char_u *)&(curbuf->b_p_nf);
+ return (char_u *)&(buf->b_p_nf);
case PV_PI:
- return (char_u *)&(curbuf->b_p_pi);
+ return (char_u *)&(buf->b_p_pi);
case PV_QE:
- return (char_u *)&(curbuf->b_p_qe);
+ return (char_u *)&(buf->b_p_qe);
case PV_RO:
- return (char_u *)&(curbuf->b_p_ro);
+ return (char_u *)&(buf->b_p_ro);
case PV_SCBK:
- return (char_u *)&(curbuf->b_p_scbk);
+ return (char_u *)&(buf->b_p_scbk);
case PV_SI:
- return (char_u *)&(curbuf->b_p_si);
+ return (char_u *)&(buf->b_p_si);
case PV_STS:
- return (char_u *)&(curbuf->b_p_sts);
+ return (char_u *)&(buf->b_p_sts);
case PV_SUA:
- return (char_u *)&(curbuf->b_p_sua);
+ return (char_u *)&(buf->b_p_sua);
case PV_SWF:
- return (char_u *)&(curbuf->b_p_swf);
+ return (char_u *)&(buf->b_p_swf);
case PV_SMC:
- return (char_u *)&(curbuf->b_p_smc);
+ return (char_u *)&(buf->b_p_smc);
case PV_SYN:
- return (char_u *)&(curbuf->b_p_syn);
+ return (char_u *)&(buf->b_p_syn);
case PV_SPC:
- return (char_u *)&(curwin->w_s->b_p_spc);
+ return (char_u *)&(win->w_s->b_p_spc);
case PV_SPF:
- return (char_u *)&(curwin->w_s->b_p_spf);
+ return (char_u *)&(win->w_s->b_p_spf);
case PV_SPL:
- return (char_u *)&(curwin->w_s->b_p_spl);
+ return (char_u *)&(win->w_s->b_p_spl);
case PV_SPO:
- return (char_u *)&(curwin->w_s->b_p_spo);
+ return (char_u *)&(win->w_s->b_p_spo);
case PV_SW:
- return (char_u *)&(curbuf->b_p_sw);
+ return (char_u *)&(buf->b_p_sw);
case PV_TFU:
- return (char_u *)&(curbuf->b_p_tfu);
+ return (char_u *)&(buf->b_p_tfu);
case PV_TS:
- return (char_u *)&(curbuf->b_p_ts);
+ return (char_u *)&(buf->b_p_ts);
case PV_TW:
- return (char_u *)&(curbuf->b_p_tw);
+ return (char_u *)&(buf->b_p_tw);
case PV_UDF:
- return (char_u *)&(curbuf->b_p_udf);
+ return (char_u *)&(buf->b_p_udf);
case PV_WM:
- return (char_u *)&(curbuf->b_p_wm);
+ return (char_u *)&(buf->b_p_wm);
case PV_VSTS:
- return (char_u *)&(curbuf->b_p_vsts);
+ return (char_u *)&(buf->b_p_vsts);
case PV_VTS:
- return (char_u *)&(curbuf->b_p_vts);
+ return (char_u *)&(buf->b_p_vts);
case PV_KMAP:
- return (char_u *)&(curbuf->b_p_keymap);
+ return (char_u *)&(buf->b_p_keymap);
case PV_SCL:
- return (char_u *)&(curwin->w_p_scl);
+ return (char_u *)&(win->w_p_scl);
case PV_WINHL:
- return (char_u *)&(curwin->w_p_winhl);
+ return (char_u *)&(win->w_p_winhl);
case PV_WINBL:
- return (char_u *)&(curwin->w_p_winbl);
+ return (char_u *)&(win->w_p_winbl);
case PV_STC:
- return (char_u *)&(curwin->w_p_stc);
+ return (char_u *)&(win->w_p_stc);
default:
iemsg(_("E356: get_varp ERROR"));
}
// always return a valid pointer to avoid a crash!
- return (char_u *)&(curbuf->b_p_wm);
+ return (char_u *)&(buf->b_p_wm);
+}
+
+/// Get pointer to option variable.
+static inline char_u *get_varp(vimoption_T *p)
+{
+ return get_varp_from(p, curbuf, curwin);
}
/// Get the value of 'equalprg', either the buffer-local one or the global one.
-char_u *get_equalprg(void)
+char *get_equalprg(void)
{
if (*curbuf->b_p_ep == NUL) {
return p_ep;
}
- return (char_u *)curbuf->b_p_ep;
+ return curbuf->b_p_ep;
}
/// Copy options from one window to another.
@@ -4221,7 +4304,7 @@ static void init_buf_opt_idx(void)
void buf_copy_options(buf_T *buf, int flags)
{
int should_copy = true;
- char_u *save_p_isk = NULL; // init for GCC
+ char *save_p_isk = NULL; // init for GCC
int did_isk = false;
// Skip this when the option defaults have not been set yet. Happens when
@@ -4254,7 +4337,7 @@ void buf_copy_options(buf_T *buf, int flags)
// (jumping back to a help file with CTRL-T or CTRL-O)
bool dont_do_help = ((flags & BCO_NOHELP) && buf->b_help) || buf->b_p_initialized;
if (dont_do_help) { // don't free b_p_isk
- save_p_isk = (char_u *)buf->b_p_isk;
+ save_p_isk = buf->b_p_isk;
buf->b_p_isk = NULL;
}
// Always free the allocated strings. If not already initialized,
@@ -4449,7 +4532,7 @@ void buf_copy_options(buf_T *buf, int flags)
// Don't touch these at all when BCO_NOHELP is used and going from
// or to a help buffer.
if (dont_do_help) {
- buf->b_p_isk = (char *)save_p_isk;
+ buf->b_p_isk = save_p_isk;
if (p_vts && p_vts != empty_option && !buf->b_p_vts_array) {
(void)tabstop_set(p_vts, &buf->b_p_vts_array);
} else {
@@ -4504,15 +4587,15 @@ void reset_modifiable(void)
}
/// Set the global value for 'iminsert' to the local value.
-void set_iminsert_global(void)
+void set_iminsert_global(buf_T *buf)
{
- p_iminsert = curbuf->b_p_iminsert;
+ p_iminsert = buf->b_p_iminsert;
}
/// Set the global value for 'imsearch' to the local value.
-void set_imsearch_global(void)
+void set_imsearch_global(buf_T *buf)
{
- p_imsearch = curbuf->b_p_imsearch;
+ p_imsearch = buf->b_p_imsearch;
}
static int expand_option_idx = -1;
@@ -4522,11 +4605,6 @@ static int expand_option_flags = 0;
/// @param opt_flags OPT_GLOBAL and/or OPT_LOCAL
void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
{
- uint32_t flags = 0; // init for GCC
- int opt_idx = 0; // init for GCC
- char *p;
- int is_term_option = false;
-
expand_option_flags = opt_flags;
xp->xp_context = EXPAND_SETTINGS;
@@ -4534,7 +4612,7 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
xp->xp_pattern = arg;
return;
}
- p = arg + strlen(arg) - 1;
+ char *p = arg + strlen(arg) - 1;
if (*p == ' ' && *(p - 1) != '\\') {
xp->xp_pattern = p + 1;
return;
@@ -4566,6 +4644,9 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
arg = p;
char nextchar;
+ uint32_t flags = 0;
+ int opt_idx = 0;
+ int is_term_option = false;
if (*arg == '<') {
while (*p != '>') {
@@ -4696,13 +4777,56 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
}
}
-int ExpandSettings(expand_T *xp, regmatch_T *regmatch, int *num_file, char ***file)
+/// Returns true if "str" either matches "regmatch" or fuzzy matches "pat".
+///
+/// If "test_only" is true and "fuzzy" is false and if "str" matches the regular
+/// expression "regmatch", then returns true. Otherwise returns false.
+///
+/// If "test_only" is false and "fuzzy" is false and if "str" matches the
+/// regular expression "regmatch", then stores the match in matches[idx] and
+/// returns true.
+///
+/// If "test_only" is true and "fuzzy" is true and if "str" fuzzy matches
+/// "fuzzystr", then returns true. Otherwise returns false.
+///
+/// If "test_only" is false and "fuzzy" is true and if "str" fuzzy matches
+/// "fuzzystr", then stores the match details in fuzmatch[idx] and returns true.
+static bool match_str(char *const str, regmatch_T *const regmatch, char **const matches,
+ const int idx, const bool test_only, const bool fuzzy,
+ const char *const fuzzystr, fuzmatch_str_T *const fuzmatch)
+{
+ if (!fuzzy) {
+ if (vim_regexec(regmatch, str, (colnr_T)0)) {
+ if (!test_only) {
+ matches[idx] = xstrdup(str);
+ }
+ return true;
+ }
+ } else {
+ const int score = fuzzy_match_str(str, fuzzystr);
+ if (score != 0) {
+ if (!test_only) {
+ fuzmatch[idx].idx = idx;
+ fuzmatch[idx].str = xstrdup(str);
+ fuzmatch[idx].score = score;
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+int ExpandSettings(expand_T *xp, regmatch_T *regmatch, char *fuzzystr, int *numMatches,
+ char ***matches, const bool can_fuzzy)
{
int num_normal = 0; // Nr of matching non-term-code settings
int count = 0;
static char *(names[]) = { "all" };
int ic = regmatch->rm_ic; // remember the ignore-case flag
+ fuzmatch_str_T *fuzmatch = NULL;
+ const bool fuzzy = can_fuzzy && cmdline_fuzzy_complete(fuzzystr);
+
// do this loop twice:
// loop == 0: count the number of matching options
// loop == 1: copy the matching options into allocated memory
@@ -4712,11 +4836,12 @@ int ExpandSettings(expand_T *xp, regmatch_T *regmatch, int *num_file, char ***fi
if (xp->xp_context != EXPAND_BOOL_SETTINGS) {
for (match = 0; match < (int)ARRAY_SIZE(names);
match++) {
- if (vim_regexec(regmatch, names[match], (colnr_T)0)) {
+ if (match_str(names[match], regmatch, *matches,
+ count, (loop == 0), fuzzy, fuzzystr, fuzmatch)) {
if (loop == 0) {
num_normal++;
} else {
- (*file)[count++] = xstrdup(names[match]);
+ count++;
}
}
}
@@ -4731,42 +4856,54 @@ int ExpandSettings(expand_T *xp, regmatch_T *regmatch, int *num_file, char ***fi
&& !(options[opt_idx].flags & P_BOOL)) {
continue;
}
- match = false;
- if (vim_regexec(regmatch, str, (colnr_T)0)
- || (options[opt_idx].shortname != NULL
- && vim_regexec(regmatch,
- options[opt_idx].shortname,
- (colnr_T)0))) {
- match = true;
- }
- if (match) {
+ if (match_str(str, regmatch, *matches, count, (loop == 0),
+ fuzzy, fuzzystr, fuzmatch)) {
+ if (loop == 0) {
+ num_normal++;
+ } else {
+ count++;
+ }
+ } else if (!fuzzy && options[opt_idx].shortname != NULL
+ && vim_regexec(regmatch, options[opt_idx].shortname, (colnr_T)0)) {
+ // Compare against the abbreviated option name (for regular
+ // expression match). Fuzzy matching (previous if) already
+ // matches against both the expanded and abbreviated names.
if (loop == 0) {
num_normal++;
} else {
- (*file)[count++] = xstrdup(str);
+ (*matches)[count++] = xstrdup(str);
}
}
}
if (loop == 0) {
if (num_normal > 0) {
- *num_file = num_normal;
+ *numMatches = num_normal;
} else {
return OK;
}
- *file = xmalloc((size_t)(*num_file) * sizeof(char *));
+ if (!fuzzy) {
+ *matches = xmalloc((size_t)(*numMatches) * sizeof(char *));
+ } else {
+ fuzmatch = xmalloc((size_t)(*numMatches) * sizeof(fuzmatch_str_T));
+ }
}
}
+
+ if (fuzzy) {
+ fuzzymatches_to_strmatches(fuzmatch, matches, count, false);
+ }
+
return OK;
}
-void ExpandOldSetting(int *num_file, char ***file)
+void ExpandOldSetting(int *numMatches, char ***matches)
{
char *var = NULL;
- *num_file = 0;
- *file = xmalloc(sizeof(char_u *));
+ *numMatches = 0;
+ *matches = xmalloc(sizeof(char *));
// For a terminal key code expand_option_idx is < 0.
if (expand_option_idx < 0) {
@@ -4783,7 +4920,7 @@ void ExpandOldSetting(int *num_file, char ***file)
// A backslash is required before some characters. This is the reverse of
// what happens in do_set().
- char_u *buf = (char_u *)vim_strsave_escaped(var, (char *)escape_chars);
+ char *buf = vim_strsave_escaped(var, escape_chars);
#ifdef BACKSLASH_IN_FILENAME
// For MS-Windows et al. we don't double backslashes at the start and
@@ -4799,8 +4936,8 @@ void ExpandOldSetting(int *num_file, char ***file)
}
#endif
- *file[0] = (char *)buf;
- *num_file = 1;
+ *matches[0] = buf;
+ *numMatches = 1;
}
/// Get the value for the numeric or string option///opp in a nice format into
@@ -4817,7 +4954,7 @@ static void option_value2string(vimoption_T *opp, int scope)
if (wc_use_keyname((char_u *)varp, &wc)) {
xstrlcpy(NameBuff, (char *)get_special_key_name((int)wc, 0), sizeof(NameBuff));
} else if (wc != 0) {
- xstrlcpy(NameBuff, (char *)transchar((int)wc), sizeof(NameBuff));
+ xstrlcpy(NameBuff, transchar((int)wc), sizeof(NameBuff));
} else {
snprintf(NameBuff,
sizeof(NameBuff),
@@ -5035,10 +5172,11 @@ bool option_was_set(const char *name)
void reset_option_was_set(const char *name)
{
const int idx = findoption(name);
-
- if (idx >= 0) {
- options[idx].flags &= ~P_WAS_SET;
+ if (idx < 0) {
+ return;
}
+
+ options[idx].flags &= ~P_WAS_SET;
}
/// fill_breakat_flags() -- called when 'breakat' changes value.
@@ -5199,16 +5337,16 @@ unsigned int get_ve_flags(void)
///
/// @param win If not NULL, the window to get the local option from; global
/// otherwise.
-char_u *get_showbreak_value(win_T *const win)
+char *get_showbreak_value(win_T *const win)
FUNC_ATTR_WARN_UNUSED_RESULT
{
if (win->w_p_sbr == NULL || *win->w_p_sbr == NUL) {
- return (char_u *)p_sbr;
+ return p_sbr;
}
if (strcmp(win->w_p_sbr, "NONE") == 0) {
- return (char_u *)empty_option;
+ return empty_option;
}
- return (char_u *)win->w_p_sbr;
+ return win->w_p_sbr;
}
/// Return the current end-of-line type: EOL_DOS, EOL_UNIX or EOL_MAC.
@@ -5327,9 +5465,9 @@ size_t copy_option_part(char **option, char *buf, size_t maxlen, char *sep_chars
if (*p == '.') {
buf[len++] = *p++;
}
- while (*p != NUL && vim_strchr(sep_chars, *p) == NULL) {
+ while (*p != NUL && vim_strchr(sep_chars, (uint8_t)(*p)) == NULL) {
// Skip backslash before a separator character and space.
- if (p[0] == '\\' && vim_strchr(sep_chars, p[1]) != NULL) {
+ if (p[0] == '\\' && vim_strchr(sep_chars, (uint8_t)p[1]) != NULL) {
p++;
}
if (len < maxlen - 1) {
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index 3ffab71f22..d190fc5999 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -442,7 +442,7 @@ EXTERN unsigned bo_flags;
#define BO_SPELL 0x20000
#define BO_WILD 0x40000
-EXTERN char_u *p_bsk; // 'backupskip'
+EXTERN char *p_bsk; // 'backupskip'
EXTERN char *p_breakat; // 'breakat'
EXTERN char *p_bh; ///< 'bufhidden'
EXTERN char *p_bt; ///< 'buftype'
@@ -468,7 +468,7 @@ EXTERN long p_columns; // 'columns'
EXTERN int p_confirm; // 'confirm'
EXTERN char *p_cot; // 'completeopt'
#ifdef BACKSLASH_IN_FILENAME
-EXTERN char_u *p_csl; // 'completeslash'
+EXTERN char *p_csl; // 'completeslash'
#endif
EXTERN long p_pb; // 'pumblend'
EXTERN long p_ph; // 'pumheight'
@@ -494,9 +494,9 @@ EXTERN int p_ed; // 'edcompatible'
EXTERN char *p_ead; // 'eadirection'
EXTERN int p_emoji; // 'emoji'
EXTERN int p_ea; // 'equalalways'
-EXTERN char_u *p_ep; // 'equalprg'
+EXTERN char *p_ep; // 'equalprg'
EXTERN int p_eb; // 'errorbells'
-EXTERN char_u *p_ef; // 'errorfile'
+EXTERN char *p_ef; // 'errorfile'
EXTERN char *p_efm; // 'errorformat'
EXTERN char *p_gefm; // 'grepformat'
EXTERN char *p_gp; // 'grepprg'
@@ -531,12 +531,12 @@ EXTERN unsigned fdo_flags;
EXTERN char *p_fex; ///< 'formatexpr'
EXTERN char *p_flp; ///< 'formatlistpat'
EXTERN char *p_fo; ///< 'formatoptions'
-EXTERN char_u *p_fp; // 'formatprg'
+EXTERN char *p_fp; // 'formatprg'
EXTERN int p_fs; // 'fsync'
EXTERN int p_gd; // 'gdefault'
EXTERN char *p_guicursor; // 'guicursor'
-EXTERN char_u *p_guifont; // 'guifont'
-EXTERN char_u *p_guifontwide; // 'guifontwide'
+EXTERN char *p_guifont; // 'guifont'
+EXTERN char *p_guifontwide; // 'guifontwide'
EXTERN char *p_hf; // 'helpfile'
EXTERN long p_hh; // 'helpheight'
EXTERN char *p_hlg; // 'helplang'
@@ -568,17 +568,17 @@ EXTERN unsigned jop_flags;
#define JOP_STACK 0x01
#define JOP_VIEW 0x02
EXTERN char *p_keymap; ///< 'keymap'
-EXTERN char_u *p_kp; // 'keywordprg'
+EXTERN char *p_kp; // 'keywordprg'
EXTERN char *p_km; // 'keymodel'
EXTERN char *p_langmap; // 'langmap'
EXTERN int p_lnr; // 'langnoremap'
EXTERN int p_lrm; // 'langremap'
-EXTERN char_u *p_lm; // 'langmenu'
+EXTERN char *p_lm; // 'langmenu'
EXTERN long p_lines; // 'lines'
EXTERN long p_linespace; // 'linespace'
EXTERN int p_lisp; ///< 'lisp'
EXTERN char *p_lop; ///< 'lispoptions'
-EXTERN char_u *p_lispwords; // 'lispwords'
+EXTERN char *p_lispwords; // 'lispwords'
EXTERN long p_ls; // 'laststatus'
EXTERN long p_stal; // 'showtabline'
EXTERN char *p_lcs; // 'listchars'
@@ -588,7 +588,7 @@ EXTERN int p_lpl; // 'loadplugins'
EXTERN int p_magic; // 'magic'
EXTERN char *p_menc; // 'makeencoding'
EXTERN char *p_mef; // 'makeef'
-EXTERN char_u *p_mp; // 'makeprg'
+EXTERN char *p_mp; // 'makeprg'
EXTERN char *p_mps; ///< 'matchpairs'
EXTERN long p_mat; // 'matchtime'
EXTERN long p_mco; // 'maxcombine'
@@ -613,13 +613,13 @@ EXTERN long p_mouset; // 'mousetime'
EXTERN int p_more; // 'more'
EXTERN char *p_nf; ///< 'nrformats'
EXTERN char *p_opfunc; // 'operatorfunc'
-EXTERN char_u *p_para; // 'paragraphs'
+EXTERN char *p_para; // 'paragraphs'
EXTERN int p_paste; // 'paste'
EXTERN char *p_pt; // 'pastetoggle'
EXTERN char *p_pex; // 'patchexpr'
EXTERN char *p_pm; // 'patchmode'
-EXTERN char_u *p_path; // 'path'
-EXTERN char_u *p_cdpath; // 'cdpath'
+EXTERN char *p_path; // 'path'
+EXTERN char *p_cdpath; // 'cdpath'
EXTERN int p_pi; ///< 'preserveindent'
EXTERN long p_pyx; // 'pyxversion'
EXTERN char *p_qe; ///< 'quoteescape'
@@ -673,11 +673,11 @@ EXTERN unsigned ssop_flags;
#define SSOP_SKIP_RTP 0x20000
EXTERN char *p_sh; // 'shell'
-EXTERN char_u *p_shcf; // 'shellcmdflag'
+EXTERN char *p_shcf; // 'shellcmdflag'
EXTERN char *p_sp; // 'shellpipe'
EXTERN char *p_shq; // 'shellquote'
EXTERN char *p_sxq; // 'shellxquote'
-EXTERN char_u *p_sxe; // 'shellxescape'
+EXTERN char *p_sxe; // 'shellxescape'
EXTERN char *p_srr; // 'shellredir'
EXTERN int p_stmp; // 'shelltemp'
#ifdef BACKSLASH_IN_FILENAME
@@ -725,7 +725,7 @@ EXTERN unsigned int spo_flags;
EXTERN char *p_sps; // 'spellsuggest'
EXTERN int p_spr; // 'splitright'
EXTERN int p_sol; // 'startofline'
-EXTERN char_u *p_su; // 'suffixes'
+EXTERN char *p_su; // 'suffixes'
EXTERN char *p_swb; // 'switchbuf'
EXTERN unsigned swb_flags;
// Keep in sync with p_swb_values in optionstr.c
@@ -747,7 +747,7 @@ EXTERN unsigned tc_flags; ///< flags from 'tagcase'
#define TC_SMART 0x10
EXTERN long p_tl; ///< 'taglength'
EXTERN int p_tr; ///< 'tagrelative'
-EXTERN char_u *p_tags; ///< 'tags'
+EXTERN char *p_tags; ///< 'tags'
EXTERN int p_tgst; ///< 'tagstack'
EXTERN int p_tbidi; ///< 'termbidi'
EXTERN long p_tw; ///< 'textwidth'
@@ -756,13 +756,13 @@ EXTERN int p_timeout; ///< 'timeout'
EXTERN long p_tm; ///< 'timeoutlen'
EXTERN int p_title; ///< 'title'
EXTERN long p_titlelen; ///< 'titlelen'
-EXTERN char_u *p_titleold; ///< 'titleold'
+EXTERN char *p_titleold; ///< 'titleold'
EXTERN char *p_titlestring; ///< 'titlestring'
-EXTERN char_u *p_tsr; ///< 'thesaurus'
+EXTERN char *p_tsr; ///< 'thesaurus'
EXTERN int p_tgc; ///< 'termguicolors'
EXTERN int p_ttimeout; ///< 'ttimeout'
EXTERN long p_ttm; ///< 'ttimeoutlen'
-EXTERN char_u *p_udir; ///< 'undodir'
+EXTERN char *p_udir; ///< 'undodir'
EXTERN int p_udf; ///< 'undofile'
EXTERN long p_ul; ///< 'undolevels'
EXTERN long p_ur; ///< 'undoreload'
@@ -778,15 +778,15 @@ EXTERN unsigned vop_flags; ///< uses SSOP_ flags
EXTERN int p_vb; ///< 'visualbell'
EXTERN char *p_ve; ///< 'virtualedit'
EXTERN unsigned ve_flags;
-#define VE_BLOCK 5U // includes "all"
-#define VE_INSERT 6U // includes "all"
+#define VE_BLOCK 5U // includes "all"
+#define VE_INSERT 6U // includes "all"
#define VE_ALL 4U
#define VE_ONEMORE 8U
-#define VE_NONE 16U // "none"
-#define VE_NONEU 32U // "NONE"
+#define VE_NONE 16U // "none"
+#define VE_NONEU 32U // "NONE"
EXTERN long p_verbose; // 'verbose'
#ifdef IN_OPTION_C
-char_u *p_vfile = (char_u *)""; // used before options are initialized
+char *p_vfile = ""; // used before options are initialized
#else
extern char *p_vfile; // 'verbosefile'
#endif
@@ -795,6 +795,7 @@ EXTERN char *p_wop; // 'wildoptions'
EXTERN unsigned wop_flags;
#define WOP_TAGFILE 0x01
#define WOP_PUM 0x02
+#define WOP_FUZZY 0x04
EXTERN long p_window; // 'window'
EXTERN char *p_wak; // 'winaltkeys'
EXTERN char *p_wig; // 'wildignore'
diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c
index a97e9b7c7e..ca50c3ab00 100644
--- a/src/nvim/optionstr.c
+++ b/src/nvim/optionstr.c
@@ -3,6 +3,7 @@
#include <assert.h>
#include <stdbool.h>
+#include <stdint.h>
#include <string.h>
#include "nvim/api/private/helpers.h"
@@ -90,7 +91,7 @@ static char *(p_swb_values[]) = { "useopen", "usetab", "split", "newtab", "vspli
static char *(p_spk_values[]) = { "cursor", "screen", "topline", NULL };
static char *(p_tc_values[]) = { "followic", "ignore", "match", "followscs", "smart", NULL };
static char *(p_ve_values[]) = { "block", "insert", "all", "onemore", "none", "NONE", NULL };
-static char *(p_wop_values[]) = { "tagfile", "pum", NULL };
+static char *(p_wop_values[]) = { "tagfile", "pum", "fuzzy", NULL };
static char *(p_wak_values[]) = { "yes", "menu", "no", NULL };
static char *(p_mousem_values[]) = { "extend", "popup", "popup_setpos", "mac", NULL };
static char *(p_sel_values[]) = { "inclusive", "exclusive", "old", NULL };
@@ -166,36 +167,37 @@ void trigger_optionset_string(int opt_idx, int opt_flags, char *oldval, char *ol
char *oldval_g, char *newval)
{
// Don't do this recursively.
- if (oldval != NULL
- && newval != NULL
- && *get_vim_var_str(VV_OPTION_TYPE) == NUL) {
- char buf_type[7];
+ if (oldval == NULL || newval == NULL
+ || *get_vim_var_str(VV_OPTION_TYPE) != NUL) {
+ return;
+ }
- vim_snprintf(buf_type, ARRAY_SIZE(buf_type), "%s",
- (opt_flags & OPT_LOCAL) ? "local" : "global");
- set_vim_var_string(VV_OPTION_OLD, oldval, -1);
- set_vim_var_string(VV_OPTION_NEW, newval, -1);
- set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
- if (opt_flags & OPT_LOCAL) {
- set_vim_var_string(VV_OPTION_COMMAND, "setlocal", -1);
- set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, -1);
- }
- if (opt_flags & OPT_GLOBAL) {
- set_vim_var_string(VV_OPTION_COMMAND, "setglobal", -1);
- set_vim_var_string(VV_OPTION_OLDGLOBAL, oldval, -1);
- }
- if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) {
- set_vim_var_string(VV_OPTION_COMMAND, "set", -1);
- set_vim_var_string(VV_OPTION_OLDLOCAL, oldval_l, -1);
- set_vim_var_string(VV_OPTION_OLDGLOBAL, oldval_g, -1);
- }
- if (opt_flags & OPT_MODELINE) {
- set_vim_var_string(VV_OPTION_COMMAND, "modeline", -1);
- set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, -1);
- }
- apply_autocmds(EVENT_OPTIONSET, get_option(opt_idx)->fullname, NULL, false, NULL);
- reset_v_option_vars();
+ char buf_type[7];
+
+ vim_snprintf(buf_type, ARRAY_SIZE(buf_type), "%s",
+ (opt_flags & OPT_LOCAL) ? "local" : "global");
+ set_vim_var_string(VV_OPTION_OLD, oldval, -1);
+ set_vim_var_string(VV_OPTION_NEW, newval, -1);
+ set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
+ if (opt_flags & OPT_LOCAL) {
+ set_vim_var_string(VV_OPTION_COMMAND, "setlocal", -1);
+ set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, -1);
+ }
+ if (opt_flags & OPT_GLOBAL) {
+ set_vim_var_string(VV_OPTION_COMMAND, "setglobal", -1);
+ set_vim_var_string(VV_OPTION_OLDGLOBAL, oldval, -1);
+ }
+ if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) {
+ set_vim_var_string(VV_OPTION_COMMAND, "set", -1);
+ set_vim_var_string(VV_OPTION_OLDLOCAL, oldval_l, -1);
+ set_vim_var_string(VV_OPTION_OLDGLOBAL, oldval_g, -1);
+ }
+ if (opt_flags & OPT_MODELINE) {
+ set_vim_var_string(VV_OPTION_COMMAND, "modeline", -1);
+ set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, -1);
}
+ apply_autocmds(EVENT_OPTIONSET, get_option(opt_idx)->fullname, NULL, false, NULL);
+ reset_v_option_vars();
}
static char *illegal_char(char *errbuf, size_t errbuflen, int c)
@@ -204,7 +206,7 @@ static char *illegal_char(char *errbuf, size_t errbuflen, int c)
return "";
}
vim_snprintf(errbuf, errbuflen, _("E539: Illegal character <%s>"),
- (char *)transchar(c));
+ transchar(c));
return errbuf;
}
@@ -612,8 +614,8 @@ char *check_stl_option(char *s)
groupdepth++;
continue;
}
- if (vim_strchr(STL_ALL, *s) == NULL) {
- return illegal_char(errbuf, sizeof(errbuf), *s);
+ if (vim_strchr(STL_ALL, (uint8_t)(*s)) == NULL) {
+ return illegal_char(errbuf, sizeof(errbuf), (uint8_t)(*s));
}
if (*s == '{') {
bool reevaluate = (*++s == '%');
@@ -636,952 +638,1238 @@ char *check_stl_option(char *s)
return NULL;
}
-static int shada_idx = -1;
+/// Check for a "normal" directory or file name in some options. Disallow a
+/// path separator (slash and/or backslash), wildcards and characters that are
+/// often illegal in a file name. Be more permissive if "secure" is off.
+static bool check_illegal_path_names(char *val, uint32_t flags)
+{
+ return (((flags & P_NFNAME)
+ && strpbrk(val, (secure ? "/\\*?[|;&<>\r\n" : "/\\*?[<>\r\n")) != NULL)
+ || ((flags & P_NDNAME)
+ && strpbrk(val, "*?[|;&<>\r\n") != NULL));
+}
-/// Handle string options that need some action to perform when changed.
-/// The new value must be allocated.
-///
-/// @param opt_idx index in options[] table
-/// @param varp pointer to the option variable
-/// @param oldval previous value of the option
-/// @param errbuf buffer for errors, or NULL
-/// @param errbuflen length of errors buffer
-/// @param opt_flags OPT_LOCAL and/or OPT_GLOBAL
-/// @param value_checked value was checked to be safe, no need to set P_INSECURE
-///
-/// @return NULL for success, or an untranslated error message for an error
-char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf, size_t errbuflen,
- int opt_flags, int *value_checked)
+static void did_set_backupcopy(buf_T *buf, char *oldval, int opt_flags, char **errmsg)
{
- char *errmsg = NULL;
- char *s, *p;
- int did_chartab = false;
- vimoption_T *opt = get_option(opt_idx);
- bool free_oldval = (opt->flags & P_ALLOCED);
- bool value_changed = false;
+ char *bkc = p_bkc;
+ unsigned int *flags = &bkc_flags;
- // Get the global option to compare with, otherwise we would have to check
- // two values for all local options.
- char **gvarp = (char **)get_varp_scope(opt, OPT_GLOBAL);
+ if (opt_flags & OPT_LOCAL) {
+ bkc = buf->b_p_bkc;
+ flags = &buf->b_bkc_flags;
+ }
- // Disallow changing some options from secure mode
- if ((secure || sandbox != 0)
- && (opt->flags & P_SECURE)) {
- errmsg = e_secure;
- } else if (((opt->flags & P_NFNAME)
- && strpbrk(*varp, (secure ? "/\\*?[|;&<>\r\n" : "/\\*?[<>\r\n")) != NULL)
- || ((opt->flags & P_NDNAME)
- && strpbrk(*varp, "*?[|;&<>\r\n") != NULL)) {
- // Check for a "normal" directory or file name in some options. Disallow a
- // path separator (slash and/or backslash), wildcards and characters that
- // are often illegal in a file name. Be more permissive if "secure" is off.
- errmsg = e_invarg;
- } else if (gvarp == &p_bkc) { // 'backupcopy'
- char *bkc = p_bkc;
- unsigned int *flags = &bkc_flags;
+ if ((opt_flags & OPT_LOCAL) && *bkc == NUL) {
+ // make the local value empty: use the global value
+ *flags = 0;
+ } else {
+ if (opt_strings_flags(bkc, p_bkc_values, flags, true) != OK) {
+ *errmsg = e_invarg;
+ }
- if (opt_flags & OPT_LOCAL) {
- bkc = curbuf->b_p_bkc;
- flags = &curbuf->b_bkc_flags;
+ if (((*flags & BKC_AUTO) != 0)
+ + ((*flags & BKC_YES) != 0)
+ + ((*flags & BKC_NO) != 0) != 1) {
+ // Must have exactly one of "auto", "yes" and "no".
+ (void)opt_strings_flags(oldval, p_bkc_values, flags, true);
+ *errmsg = e_invarg;
}
+ }
+}
- if ((opt_flags & OPT_LOCAL) && *bkc == NUL) {
- // make the local value empty: use the global value
- *flags = 0;
- } else {
- if (opt_strings_flags(bkc, p_bkc_values, flags, true) != OK) {
- errmsg = e_invarg;
- }
+static void did_set_backupext_or_patchmode(char **errmsg)
+{
+ if (strcmp(*p_bex == '.' ? p_bex + 1 : p_bex,
+ *p_pm == '.' ? p_pm + 1 : p_pm) == 0) {
+ *errmsg = e_backupext_and_patchmode_are_equal;
+ }
+}
- if (((*flags & BKC_AUTO) != 0)
- + ((*flags & BKC_YES) != 0)
- + ((*flags & BKC_NO) != 0) != 1) {
- // Must have exactly one of "auto", "yes" and "no".
- (void)opt_strings_flags(oldval, p_bkc_values, flags, true);
- errmsg = e_invarg;
- }
- }
- } else if (varp == &p_bex || varp == &p_pm) { // 'backupext' and 'patchmode'
- if (strcmp(*p_bex == '.' ? p_bex + 1 : p_bex,
- *p_pm == '.' ? p_pm + 1 : p_pm) == 0) {
- errmsg = e_backupext_and_patchmode_are_equal;
- }
- } else if (varp == &curwin->w_p_briopt) { // 'breakindentopt'
- if (briopt_check(curwin) == FAIL) {
- errmsg = e_invarg;
- }
- // list setting requires a redraw
- if (curwin->w_briopt_list) {
- redraw_all_later(UPD_NOT_VALID);
- }
- } else if (varp == &p_isi
- || varp == &(curbuf->b_p_isk)
- || varp == &p_isp
- || varp == &p_isf) {
- // 'isident', 'iskeyword', 'isprint or 'isfname' option: refill g_chartab[]
- // If the new option is invalid, use old value. 'lisp' option: refill
- // g_chartab[] for '-' char
- if (init_chartab() == FAIL) {
- did_chartab = true; // need to restore it below
- errmsg = e_invarg; // error in value
- }
- } else if (varp == &p_hf) { // 'helpfile'
- // May compute new values for $VIM and $VIMRUNTIME
- if (didset_vim) {
- vim_unsetenv_ext("VIM");
- }
- if (didset_vimruntime) {
- vim_unsetenv_ext("VIMRUNTIME");
- }
- } else if (varp == &p_rtp || varp == &p_pp) { // 'runtimepath' 'packpath'
- runtime_search_path_invalidate();
- } else if (varp == &curwin->w_p_culopt
- || gvarp == &curwin->w_allbuf_opt.wo_culopt) { // 'cursorlineopt'
- if (**varp == NUL || fill_culopt_flags(*varp, curwin) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &curwin->w_p_cc) { // 'colorcolumn'
- errmsg = check_colorcolumn(curwin);
- } else if (varp == &p_hlg) { // 'helplang'
- // Check for "", "ab", "ab,cd", etc.
- for (s = p_hlg; *s != NUL; s += 3) {
- if (s[1] == NUL || ((s[2] != ',' || s[3] == NUL) && s[2] != NUL)) {
- errmsg = e_invarg;
- break;
- }
- if (s[2] == NUL) {
- break;
- }
- }
- } else if (varp == &p_hl) { // 'highlight'
- if (strcmp(*varp, HIGHLIGHT_INIT) != 0) {
- errmsg = e_unsupportedoption;
- }
- } else if (varp == &p_jop) { // 'jumpoptions'
- if (opt_strings_flags(p_jop, p_jop_values, &jop_flags, true) != OK) {
- errmsg = e_invarg;
- }
- } else if (gvarp == &p_nf) { // 'nrformats'
- if (check_opt_strings(*varp, p_nf_values, true) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_ssop) { // 'sessionoptions'
- if (opt_strings_flags(p_ssop, p_ssop_values, &ssop_flags, true) != OK) {
- errmsg = e_invarg;
- }
- if ((ssop_flags & SSOP_CURDIR) && (ssop_flags & SSOP_SESDIR)) {
- // Don't allow both "sesdir" and "curdir".
- (void)opt_strings_flags(oldval, p_ssop_values, &ssop_flags, true);
- errmsg = e_invarg;
- }
- } else if (varp == &p_vop) { // 'viewoptions'
- if (opt_strings_flags(p_vop, p_ssop_values, &vop_flags, true) != OK) {
- errmsg = e_invarg;
+static void did_set_breakindentopt(win_T *win, char **errmsg)
+{
+ if (briopt_check(win) == FAIL) {
+ *errmsg = e_invarg;
+ }
+ // list setting requires a redraw
+ if (win == curwin && win->w_briopt_list) {
+ redraw_all_later(UPD_NOT_VALID);
+ }
+}
+
+static void did_set_isopt(buf_T *buf, bool *did_chartab, char **errmsg)
+{
+ // 'isident', 'iskeyword', 'isprint or 'isfname' option: refill g_chartab[]
+ // If the new option is invalid, use old value.
+ // 'lisp' option: refill g_chartab[] for '-' char
+ if (buf_init_chartab(buf, true) == FAIL) {
+ *did_chartab = true; // need to restore it below
+ *errmsg = e_invarg; // error in value
+ }
+}
+
+static void did_set_helpfile(void)
+{
+ // May compute new values for $VIM and $VIMRUNTIME
+ if (didset_vim) {
+ vim_unsetenv_ext("VIM");
+ }
+ if (didset_vimruntime) {
+ vim_unsetenv_ext("VIMRUNTIME");
+ }
+}
+
+static void did_set_cursorlineopt(win_T *win, char **varp, char **errmsg)
+{
+ if (**varp == NUL || fill_culopt_flags(*varp, win) != OK) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_helplang(char **errmsg)
+{
+ // Check for "", "ab", "ab,cd", etc.
+ for (char *s = p_hlg; *s != NUL; s += 3) {
+ if (s[1] == NUL || ((s[2] != ',' || s[3] == NUL) && s[2] != NUL)) {
+ *errmsg = e_invarg;
+ break;
}
- } else if (varp == &p_rdb) { // 'redrawdebug'
- if (opt_strings_flags(p_rdb, p_rdb_values, &rdb_flags, true) != OK) {
- errmsg = e_invarg;
+ if (s[2] == NUL) {
+ break;
}
- } else if (varp == &p_sbo) { // 'scrollopt'
- if (check_opt_strings(p_sbo, p_scbopt_values, true) != OK) {
- errmsg = e_invarg;
+ }
+}
+
+static void did_set_highlight(char **varp, char **errmsg)
+{
+ if (strcmp(*varp, HIGHLIGHT_INIT) != 0) {
+ *errmsg = e_unsupportedoption;
+ }
+}
+
+static void did_set_opt_flags(char *val, char **values, unsigned *flagp, bool list, char **errmsg)
+{
+ if (opt_strings_flags(val, values, flagp, list) != OK) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_opt_strings(char *val, char **values, bool list, char **errmsg)
+{
+ did_set_opt_flags(val, values, NULL, list, errmsg);
+}
+
+static void did_set_sessionoptions(char *oldval, char **errmsg)
+{
+ if (opt_strings_flags(p_ssop, p_ssop_values, &ssop_flags, true) != OK) {
+ *errmsg = e_invarg;
+ }
+ if ((ssop_flags & SSOP_CURDIR) && (ssop_flags & SSOP_SESDIR)) {
+ // Don't allow both "sesdir" and "curdir".
+ (void)opt_strings_flags(oldval, p_ssop_values, &ssop_flags, true);
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_ambiwidth(char **errmsg)
+{
+ if (check_opt_strings(p_ambw, p_ambw_values, false) != OK) {
+ *errmsg = e_invarg;
+ } else {
+ *errmsg = check_chars_options();
+ }
+}
+
+static void did_set_background(char **errmsg)
+{
+ if (check_opt_strings(p_bg, p_bg_values, false) != OK) {
+ *errmsg = e_invarg;
+ return;
+ }
+
+ int dark = (*p_bg == 'd');
+
+ init_highlight(false, false);
+
+ if (dark != (*p_bg == 'd') && get_var_value("g:colors_name") != NULL) {
+ // The color scheme must have set 'background' back to another
+ // value, that's not what we want here. Disable the color
+ // scheme and set the colors again.
+ do_unlet(S_LEN("g:colors_name"), true);
+ free_string_option(p_bg);
+ p_bg = xstrdup((dark ? "dark" : "light"));
+ check_string_option(&p_bg);
+ init_highlight(false, false);
+ }
+}
+
+static void did_set_wildmode(char **errmsg)
+{
+ if (check_opt_wim() == FAIL) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_winaltkeys(char **errmsg)
+{
+ if (*p_wak == NUL || check_opt_strings(p_wak, p_wak_values, false) != OK) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_eventignore(char **errmsg)
+{
+ if (check_ei() == FAIL) {
+ *errmsg = e_invarg;
+ }
+}
+
+// 'encoding', 'fileencoding' and 'makeencoding'
+static void did_set_encoding(buf_T *buf, char **varp, char **gvarp, int opt_flags, char **errmsg)
+{
+ if (gvarp == &p_fenc) {
+ if (!MODIFIABLE(buf) && opt_flags != OPT_GLOBAL) {
+ *errmsg = e_modifiable;
+ return;
}
- } else if (varp == &p_ambw || (int *)varp == &p_emoji) { // 'ambiwidth'
- if (check_opt_strings(p_ambw, p_ambw_values, false) != OK) {
- errmsg = e_invarg;
- } else {
- errmsg = check_chars_options();
- }
- } else if (varp == &p_bg) { // 'background'
- if (check_opt_strings(p_bg, p_bg_values, false) == OK) {
- int dark = (*p_bg == 'd');
-
- init_highlight(false, false);
-
- if (dark != (*p_bg == 'd') && get_var_value("g:colors_name") != NULL) {
- // The color scheme must have set 'background' back to another
- // value, that's not what we want here. Disable the color
- // scheme and set the colors again.
- do_unlet(S_LEN("g:colors_name"), true);
- free_string_option(p_bg);
- p_bg = xstrdup((dark ? "dark" : "light"));
- check_string_option(&p_bg);
- init_highlight(false, false);
- }
- } else {
- errmsg = e_invarg;
- }
- } else if (varp == &p_wim) { // 'wildmode'
- if (check_opt_wim() == FAIL) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_wop) { // 'wildoptions'
- if (opt_strings_flags(p_wop, p_wop_values, &wop_flags, true) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_wak) { // 'winaltkeys'
- if (*p_wak == NUL
- || check_opt_strings(p_wak, p_wak_values, false) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_ei) { // 'eventignore'
- if (check_ei() == FAIL) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_enc || gvarp == &p_fenc || gvarp == &p_menc) {
- // 'encoding', 'fileencoding' and 'makeencoding'
- if (gvarp == &p_fenc) {
- if (!MODIFIABLE(curbuf) && opt_flags != OPT_GLOBAL) {
- errmsg = e_modifiable;
- } else if (vim_strchr(*varp, ',') != NULL) {
- // No comma allowed in 'fileencoding'; catches confusing it
- // with 'fileencodings'.
- errmsg = e_invarg;
- } else {
- // May show a "+" in the title now.
- redraw_titles();
- // Add 'fileencoding' to the swap file.
- ml_setflags(curbuf);
- }
+
+ if (vim_strchr(*varp, ',') != NULL) {
+ // No comma allowed in 'fileencoding'; catches confusing it
+ // with 'fileencodings'.
+ *errmsg = e_invarg;
+ return;
}
- if (errmsg == NULL) {
- // canonize the value, so that strcmp() can be used on it
- p = enc_canonize(*varp);
- xfree(*varp);
- *varp = p;
- if (varp == &p_enc) {
- // only encoding=utf-8 allowed
- if (strcmp(p_enc, "utf-8") != 0) {
- errmsg = e_unsupportedoption;
- } else {
- spell_reload();
- }
- }
+ // May show a "+" in the title now.
+ redraw_titles();
+ // Add 'fileencoding' to the swap file.
+ ml_setflags(buf);
+ }
+
+ // canonize the value, so that strcmp() can be used on it
+ char *p = enc_canonize(*varp);
+ xfree(*varp);
+ *varp = p;
+ if (varp == &p_enc) {
+ // only encoding=utf-8 allowed
+ if (strcmp(p_enc, "utf-8") != 0) {
+ *errmsg = e_unsupportedoption;
+ return;
}
- } else if (varp == &curbuf->b_p_keymap) {
- if (!valid_filetype(*varp)) {
- errmsg = e_invarg;
- } else {
- int secure_save = secure;
+ spell_reload();
+ }
+}
+
+static void did_set_keymap(buf_T *buf, char **varp, int opt_flags, int *value_checked,
+ char **errmsg)
+{
+ if (!valid_filetype(*varp)) {
+ *errmsg = e_invarg;
+ return;
+ }
- // Reset the secure flag, since the value of 'keymap' has
- // been checked to be safe.
- secure = 0;
+ int secure_save = secure;
- // load or unload key mapping tables
- errmsg = keymap_init();
+ // Reset the secure flag, since the value of 'keymap' has
+ // been checked to be safe.
+ secure = 0;
- secure = secure_save;
+ // load or unload key mapping tables
+ *errmsg = keymap_init();
- // Since we check the value, there is no need to set P_INSECURE,
- // even when the value comes from a modeline.
- *value_checked = true;
- }
+ secure = secure_save;
- if (errmsg == NULL) {
- if (*curbuf->b_p_keymap != NUL) {
- // Installed a new keymap, switch on using it.
- curbuf->b_p_iminsert = B_IMODE_LMAP;
- if (curbuf->b_p_imsearch != B_IMODE_USE_INSERT) {
- curbuf->b_p_imsearch = B_IMODE_LMAP;
- }
- } else {
- // Cleared the keymap, may reset 'iminsert' and 'imsearch'.
- if (curbuf->b_p_iminsert == B_IMODE_LMAP) {
- curbuf->b_p_iminsert = B_IMODE_NONE;
- }
- if (curbuf->b_p_imsearch == B_IMODE_LMAP) {
- curbuf->b_p_imsearch = B_IMODE_USE_INSERT;
- }
- }
- if ((opt_flags & OPT_LOCAL) == 0) {
- set_iminsert_global();
- set_imsearch_global();
+ // Since we check the value, there is no need to set P_INSECURE,
+ // even when the value comes from a modeline.
+ *value_checked = true;
+
+ if (*errmsg == NULL) {
+ if (*buf->b_p_keymap != NUL) {
+ // Installed a new keymap, switch on using it.
+ buf->b_p_iminsert = B_IMODE_LMAP;
+ if (buf->b_p_imsearch != B_IMODE_USE_INSERT) {
+ buf->b_p_imsearch = B_IMODE_LMAP;
}
- status_redraw_curbuf();
- }
- } else if (gvarp == &p_ff) { // 'fileformat'
- if (!MODIFIABLE(curbuf) && !(opt_flags & OPT_GLOBAL)) {
- errmsg = e_modifiable;
- } else if (check_opt_strings(*varp, p_ff_values, false) != OK) {
- errmsg = e_invarg;
} else {
- redraw_titles();
- // update flag in swap file
- ml_setflags(curbuf);
- // Redraw needed when switching to/from "mac": a CR in the text
- // will be displayed differently.
- if (get_fileformat(curbuf) == EOL_MAC || *oldval == 'm') {
- redraw_curbuf_later(UPD_NOT_VALID);
+ // Cleared the keymap, may reset 'iminsert' and 'imsearch'.
+ if (buf->b_p_iminsert == B_IMODE_LMAP) {
+ buf->b_p_iminsert = B_IMODE_NONE;
+ }
+ if (buf->b_p_imsearch == B_IMODE_LMAP) {
+ buf->b_p_imsearch = B_IMODE_USE_INSERT;
}
}
- } else if (varp == &p_ffs) { // 'fileformats'
- if (check_opt_strings(p_ffs, p_ff_values, true) != OK) {
- errmsg = e_invarg;
+ if ((opt_flags & OPT_LOCAL) == 0) {
+ set_iminsert_global(buf);
+ set_imsearch_global(buf);
}
- } else if (gvarp == &p_mps) { // 'matchpairs'
- for (p = *varp; *p != NUL; p++) {
- int x2 = -1;
- int x3 = -1;
+ status_redraw_buf(buf);
+ }
+}
+
+static void did_set_fileformat(buf_T *buf, char **varp, const char *oldval, int opt_flags,
+ char **errmsg)
+{
+ if (!MODIFIABLE(buf) && !(opt_flags & OPT_GLOBAL)) {
+ *errmsg = e_modifiable;
+ } else if (check_opt_strings(*varp, p_ff_values, false) != OK) {
+ *errmsg = e_invarg;
+ } else {
+ redraw_titles();
+ // update flag in swap file
+ ml_setflags(buf);
+ // Redraw needed when switching to/from "mac": a CR in the text
+ // will be displayed differently.
+ if (get_fileformat(buf) == EOL_MAC || *oldval == 'm') {
+ redraw_buf_later(buf, UPD_NOT_VALID);
+ }
+ }
+}
+
+static void did_set_matchpairs(char **varp, char **errmsg)
+{
+ for (char *p = *varp; *p != NUL; p++) {
+ int x2 = -1;
+ int x3 = -1;
+ p += utfc_ptr2len(p);
+ if (*p != NUL) {
+ x2 = (unsigned char)(*p++);
+ }
+ if (*p != NUL) {
+ x3 = utf_ptr2char(p);
p += utfc_ptr2len(p);
- if (*p != NUL) {
- x2 = (unsigned char)(*p++);
- }
- if (*p != NUL) {
- x3 = utf_ptr2char(p);
- p += utfc_ptr2len(p);
- }
- if (x2 != ':' || x3 == -1 || (*p != NUL && *p != ',')) {
- errmsg = e_invarg;
- break;
- }
- if (*p == NUL) {
- break;
- }
}
- } else if (gvarp == &p_com) { // 'comments'
- for (s = *varp; *s;) {
- while (*s && *s != ':') {
- if (vim_strchr(COM_ALL, *s) == NULL
- && !ascii_isdigit(*s) && *s != '-') {
- errmsg = illegal_char(errbuf, errbuflen, *s);
- break;
- }
- s++;
- }
- if (*s++ == NUL) {
- errmsg = N_("E524: Missing colon");
- } else if (*s == ',' || *s == NUL) {
- errmsg = N_("E525: Zero length string");
- }
- if (errmsg != NULL) {
+ if (x2 != ':' || x3 == -1 || (*p != NUL && *p != ',')) {
+ *errmsg = e_invarg;
+ break;
+ }
+ if (*p == NUL) {
+ break;
+ }
+ }
+}
+
+static void did_set_comments(char **varp, char *errbuf, size_t errbuflen, char **errmsg)
+{
+ for (char *s = *varp; *s;) {
+ while (*s && *s != ':') {
+ if (vim_strchr(COM_ALL, (uint8_t)(*s)) == NULL
+ && !ascii_isdigit(*s) && *s != '-') {
+ *errmsg = illegal_char(errbuf, errbuflen, (uint8_t)(*s));
break;
}
- while (*s && *s != ',') {
- if (*s == '\\' && s[1] != NUL) {
- s++;
- }
+ s++;
+ }
+ if (*s++ == NUL) {
+ *errmsg = N_("E524: Missing colon");
+ } else if (*s == ',' || *s == NUL) {
+ *errmsg = N_("E525: Zero length string");
+ }
+ if (*errmsg != NULL) {
+ break;
+ }
+ while (*s && *s != ',') {
+ if (*s == '\\' && s[1] != NUL) {
s++;
}
- s = skip_to_option_part(s);
- }
- } else if (varp == &p_lcs || varp == &p_fcs) { // global 'listchars' or 'fillchars'
- char **local_ptr = varp == &p_lcs ? &curwin->w_p_lcs : &curwin->w_p_fcs;
- // only apply the global value to "curwin" when it does not have a local value
- errmsg =
- set_chars_option(curwin, varp, **local_ptr == NUL || !(opt_flags & OPT_GLOBAL));
- if (errmsg == NULL) {
- // If the current window is set to use the global
- // 'listchars'/'fillchars' value, clear the window-local value.
- if (!(opt_flags & OPT_GLOBAL)) {
- clear_string_option(local_ptr);
- }
- FOR_ALL_TAB_WINDOWS(tp, wp) {
- // If the current window has a local value need to apply it
- // again, it was changed when setting the global value.
- // If no error was returned above, we don't expect an error
- // here, so ignore the return value.
- local_ptr = varp == &p_lcs ? &wp->w_p_lcs : &wp->w_p_fcs;
- if (**local_ptr == NUL) {
- (void)set_chars_option(wp, local_ptr, true);
- }
- }
- redraw_all_later(UPD_NOT_VALID);
+ s++;
}
- } else if (varp == &curwin->w_p_lcs) { // local 'listchars'
- errmsg = set_chars_option(curwin, varp, true);
- } else if (varp == &curwin->w_p_fcs) { // local 'fillchars'
- errmsg = set_chars_option(curwin, varp, true);
- } else if (varp == &p_cedit) { // 'cedit'
- errmsg = check_cedit();
- } else if (varp == &p_vfile) { // 'verbosefile'
- verbose_stop();
- if (*p_vfile != NUL && verbose_open() == FAIL) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_shada) { // 'shada'
- // TODO(ZyX-I): Remove this code in the future, alongside with &viminfo
- // option.
- opt_idx = ((opt->fullname[0] == 'v')
- ? (shada_idx == -1 ? ((shada_idx = findoption("shada"))) : shada_idx)
- : opt_idx);
- opt = get_option(opt_idx);
- // Update free_oldval now that we have the opt_idx for 'shada', otherwise
- // there would be a disconnect between the check for P_ALLOCED at the start
- // of the function and the set of P_ALLOCED at the end of the function.
- free_oldval = (opt->flags & P_ALLOCED);
- for (s = p_shada; *s;) {
- // Check it's a valid character
- if (vim_strchr("!\"%'/:<@cfhnrs", *s) == NULL) {
- errmsg = illegal_char(errbuf, errbuflen, *s);
- break;
- }
- if (*s == 'n') { // name is always last one
- break;
- } else if (*s == 'r') { // skip until next ','
- while (*++s && *s != ',') {}
- } else if (*s == '%') {
- // optional number
- while (ascii_isdigit(*++s)) {}
- } else if (*s == '!' || *s == 'h' || *s == 'c') {
- s++; // no extra chars
- } else { // must have a number
- while (ascii_isdigit(*++s)) {}
-
- if (!ascii_isdigit(*(s - 1))) {
- if (errbuf != NULL) {
- vim_snprintf(errbuf, errbuflen,
- _("E526: Missing number after <%s>"),
- transchar_byte((uint8_t)(*(s - 1))));
- errmsg = errbuf;
- } else {
- errmsg = "";
- }
- break;
- }
+ s = skip_to_option_part(s);
+ }
+}
+
+static void did_set_global_listfillchars(win_T *win, char **varp, int opt_flags, char **errmsg)
+{
+ char **local_ptr = varp == &p_lcs ? &win->w_p_lcs : &win->w_p_fcs;
+ // only apply the global value to "win" when it does not have a local value
+ *errmsg = set_chars_option(win, varp, **local_ptr == NUL || !(opt_flags & OPT_GLOBAL));
+ if (*errmsg == NULL) {
+ // If the current window is set to use the global
+ // 'listchars'/'fillchars' value, clear the window-local value.
+ if (!(opt_flags & OPT_GLOBAL)) {
+ clear_string_option(local_ptr);
+ }
+ FOR_ALL_TAB_WINDOWS(tp, wp) {
+ // If the current window has a local value need to apply it
+ // again, it was changed when setting the global value.
+ // If no error was returned above, we don't expect an error
+ // here, so ignore the return value.
+ local_ptr = varp == &p_lcs ? &wp->w_p_lcs : &wp->w_p_fcs;
+ if (**local_ptr == NUL) {
+ (void)set_chars_option(wp, local_ptr, true);
}
- if (*s == ',') {
- s++;
- } else if (*s) {
+ }
+ redraw_all_later(UPD_NOT_VALID);
+ }
+}
+
+static void did_set_verbosefile(char **errmsg)
+{
+ verbose_stop();
+ if (*p_vfile != NUL && verbose_open() == FAIL) {
+ *errmsg = e_invarg;
+ }
+}
+
+static int shada_idx = -1;
+
+static void did_set_shada(vimoption_T **opt, int *opt_idx, bool *free_oldval, char *errbuf,
+ size_t errbuflen, char **errmsg)
+{
+ // TODO(ZyX-I): Remove this code in the future, alongside with &viminfo
+ // option.
+ *opt_idx = (((*opt)->fullname[0] == 'v')
+ ? (shada_idx == -1 ? ((shada_idx = findoption("shada"))) : shada_idx)
+ : *opt_idx);
+ *opt = get_option(*opt_idx);
+ // Update free_oldval now that we have the opt_idx for 'shada', otherwise
+ // there would be a disconnect between the check for P_ALLOCED at the start
+ // of the function and the set of P_ALLOCED at the end of the function.
+ *free_oldval = ((*opt)->flags & P_ALLOCED);
+ for (char *s = p_shada; *s;) {
+ // Check it's a valid character
+ if (vim_strchr("!\"%'/:<@cfhnrs", (uint8_t)(*s)) == NULL) {
+ *errmsg = illegal_char(errbuf, errbuflen, (uint8_t)(*s));
+ break;
+ }
+ if (*s == 'n') { // name is always last one
+ break;
+ } else if (*s == 'r') { // skip until next ','
+ while (*++s && *s != ',') {}
+ } else if (*s == '%') {
+ // optional number
+ while (ascii_isdigit(*++s)) {}
+ } else if (*s == '!' || *s == 'h' || *s == 'c') {
+ s++; // no extra chars
+ } else { // must have a number
+ while (ascii_isdigit(*++s)) {}
+
+ if (!ascii_isdigit(*(s - 1))) {
if (errbuf != NULL) {
- errmsg = N_("E527: Missing comma");
+ vim_snprintf(errbuf, errbuflen,
+ _("E526: Missing number after <%s>"),
+ transchar_byte((uint8_t)(*(s - 1))));
+ *errmsg = errbuf;
} else {
- errmsg = "";
+ *errmsg = "";
}
break;
}
}
- if (*p_shada && errmsg == NULL && get_shada_parameter('\'') < 0) {
- errmsg = N_("E528: Must specify a ' value");
- }
- } else if (gvarp == &p_sbr) { // 'showbreak'
- for (s = *varp; *s;) {
- if (ptr2cells(s) != 1) {
- errmsg = e_showbreak_contains_unprintable_or_wide_character;
+ if (*s == ',') {
+ s++;
+ } else if (*s) {
+ if (errbuf != NULL) {
+ *errmsg = N_("E527: Missing comma");
+ } else {
+ *errmsg = "";
}
- MB_PTR_ADV(s);
+ break;
}
- } else if (varp == &p_guicursor) { // 'guicursor'
- errmsg = parse_shape_opt(SHAPE_CURSOR);
- } else if (varp == &p_langmap) { // 'langmap'
- langmap_set();
- } else if (varp == &p_breakat) { // 'breakat'
- fill_breakat_flags();
- } else if (varp == &p_titlestring || varp == &p_iconstring) {
- // 'titlestring' and 'iconstring'
- int flagval = (varp == &p_titlestring) ? STL_IN_TITLE : STL_IN_ICON;
+ }
+ if (*p_shada && *errmsg == NULL && get_shada_parameter('\'') < 0) {
+ *errmsg = N_("E528: Must specify a ' value");
+ }
+}
- // NULL => statusline syntax
- if (vim_strchr(*varp, '%') && check_stl_option(*varp) == NULL) {
- stl_syntax |= flagval;
- } else {
- stl_syntax &= ~flagval;
+static void did_set_showbreak(char **varp, char **errmsg)
+{
+ for (char *s = *varp; *s;) {
+ if (ptr2cells(s) != 1) {
+ *errmsg = e_showbreak_contains_unprintable_or_wide_character;
}
- did_set_title();
- } else if (varp == &p_sel) { // 'selection'
- if (*p_sel == NUL
- || check_opt_strings(p_sel, p_sel_values, false) != OK) {
- errmsg = e_invarg;
+ MB_PTR_ADV(s);
+ }
+}
+
+static void did_set_titleiconstring(char **varp)
+{
+ // 'titlestring' and 'iconstring'
+ int flagval = (varp == &p_titlestring) ? STL_IN_TITLE : STL_IN_ICON;
+
+ // NULL => statusline syntax
+ if (vim_strchr(*varp, '%') && check_stl_option(*varp) == NULL) {
+ stl_syntax |= flagval;
+ } else {
+ stl_syntax &= ~flagval;
+ }
+ did_set_title();
+}
+
+static void did_set_selection(char **errmsg)
+{
+ if (*p_sel == NUL || check_opt_strings(p_sel, p_sel_values, false) != OK) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_keymodel(char **errmsg)
+{
+ if (check_opt_strings(p_km, p_km_values, true) != OK) {
+ *errmsg = e_invarg;
+ return;
+ }
+ km_stopsel = (vim_strchr(p_km, 'o') != NULL);
+ km_startsel = (vim_strchr(p_km, 'a') != NULL);
+}
+
+static void did_set_display(char **errmsg)
+{
+ if (opt_strings_flags(p_dy, p_dy_values, &dy_flags, true) != OK) {
+ *errmsg = e_invarg;
+ return;
+ }
+ (void)init_chartab();
+ msg_grid_validate();
+}
+
+static void did_set_spellfile(char **varp, char **errmsg)
+{
+ // When there is a window for this buffer in which 'spell'
+ // is set load the wordlists.
+
+ if ((!valid_spellfile(*varp))) {
+ *errmsg = e_invarg;
+ } else {
+ *errmsg = did_set_spell_option(true);
+ }
+}
+
+static void did_set_spell(char **varp, char **errmsg)
+{
+ // When there is a window for this buffer in which 'spell'
+ // is set load the wordlists.
+ if (!valid_spelllang(*varp)) {
+ *errmsg = e_invarg;
+ } else {
+ *errmsg = did_set_spell_option(false);
+ }
+}
+
+static void did_set_spellcapcheck(win_T *win, char **errmsg)
+{
+ // When 'spellcapcheck' is set compile the regexp program.
+ *errmsg = compile_cap_prog(win->w_s);
+}
+
+static void did_set_spelloptions(win_T *win, char **errmsg)
+{
+ if (opt_strings_flags(win->w_s->b_p_spo, p_spo_values, &(win->w_s->b_p_spo_flags),
+ true) != OK) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_spellsuggest(char **errmsg)
+{
+ if (spell_check_sps() != OK) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_mkspellmem(char **errmsg)
+{
+ if (spell_check_msm() != OK) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_buftype(buf_T *buf, win_T *win, char **errmsg)
+{
+ // When 'buftype' is set, check for valid value.
+ if ((buf->terminal && buf->b_p_bt[0] != 't')
+ || (!buf->terminal && buf->b_p_bt[0] == 't')
+ || check_opt_strings(buf->b_p_bt, p_buftype_values, false) != OK) {
+ *errmsg = e_invarg;
+ } else {
+ if (win->w_status_height || global_stl_height()) {
+ win->w_redr_status = true;
+ redraw_later(win, UPD_VALID);
}
- } else if (varp == &p_slm) { // 'selectmode'
- if (check_opt_strings(p_slm, p_slm_values, true) != OK) {
- errmsg = e_invarg;
+ buf->b_help = (buf->b_p_bt[0] == 'h');
+ redraw_titles();
+ }
+}
+
+// 'statusline', 'winbar', 'tabline', 'rulerformat' or 'statuscolumn'
+static void did_set_statusline(win_T *win, char **varp, char **gvarp, char **errmsg)
+{
+ if (varp == &p_ruf) { // reset ru_wid first
+ ru_wid = 0;
+ } else if (varp == &win->w_p_stc) {
+ win->w_nrwidth_line_count = 0;
+ }
+ char *s = *varp;
+ if (varp == &p_ruf && *s == '%') {
+ // set ru_wid if 'ruf' starts with "%99("
+ if (*++s == '-') { // ignore a '-'
+ s++;
}
- } else if (varp == &p_km) { // 'keymodel'
- if (check_opt_strings(p_km, p_km_values, true) != OK) {
- errmsg = e_invarg;
+ int wid = getdigits_int(&s, true, 0);
+ if (wid && *s == '(' && (*errmsg = check_stl_option(p_ruf)) == NULL) {
+ ru_wid = wid;
} else {
- km_stopsel = (vim_strchr(p_km, 'o') != NULL);
- km_startsel = (vim_strchr(p_km, 'a') != NULL);
+ *errmsg = check_stl_option(p_ruf);
}
- } else if (varp == &p_mousem) { // 'mousemodel'
- if (check_opt_strings(p_mousem, p_mousem_values, false) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_mousescroll) { // 'mousescroll'
- errmsg = check_mousescroll(p_mousescroll);
- } else if (varp == &p_swb) { // 'switchbuf'
- if (opt_strings_flags(p_swb, p_swb_values, &swb_flags, true) != OK) {
- errmsg = e_invarg;
+ } else if (varp == &p_ruf || s[0] != '%' || s[1] != '!') {
+ // check 'statusline', 'winbar', 'tabline' or 'statuscolumn'
+ // only if it doesn't start with "%!"
+ *errmsg = check_stl_option(s);
+ }
+ if (varp == &p_ruf && *errmsg == NULL) {
+ comp_col();
+ }
+ // add / remove window bars for 'winbar'
+ if (gvarp == &p_wbr) {
+ set_winbar(true);
+ }
+}
+
+static void did_set_complete(char **varp, char *errbuf, size_t errbuflen, char **errmsg)
+{
+ // check if it is a valid value for 'complete' -- Acevedo
+ for (char *s = *varp; *s;) {
+ while (*s == ',' || *s == ' ') {
+ s++;
}
- } else if (varp == &p_spk) { // 'splitkeep'
- if (check_opt_strings(p_spk, p_spk_values, false) != OK) {
- errmsg = e_invarg;
+ if (!*s) {
+ break;
}
- } else if (varp == &p_debug) { // 'debug'
- if (check_opt_strings(p_debug, p_debug_values, true) != OK) {
- errmsg = e_invarg;
+ if (vim_strchr(".wbuksid]tU", (uint8_t)(*s)) == NULL) {
+ *errmsg = illegal_char(errbuf, errbuflen, (uint8_t)(*s));
+ break;
}
- } else if (varp == &p_dy) { // 'display'
- if (opt_strings_flags(p_dy, p_dy_values, &dy_flags, true) != OK) {
- errmsg = e_invarg;
- } else {
- (void)init_chartab();
- msg_grid_validate();
- }
- } else if (varp == &p_ead) { // 'eadirection'
- if (check_opt_strings(p_ead, p_ead_values, false) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_cb) { // 'clipboard'
- if (opt_strings_flags(p_cb, p_cb_values, &cb_flags, true) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &(curwin->w_s->b_p_spl) // 'spell'
- || varp == &(curwin->w_s->b_p_spf)) {
- // When 'spelllang' or 'spellfile' is set and there is a window for this
- // buffer in which 'spell' is set load the wordlists.
- const bool is_spellfile = varp == &(curwin->w_s->b_p_spf);
-
- if ((is_spellfile && !valid_spellfile(*varp))
- || (!is_spellfile && !valid_spelllang(*varp))) {
- errmsg = e_invarg;
- } else {
- errmsg = did_set_spell_option(is_spellfile);
- }
- } else if (varp == &(curwin->w_s->b_p_spc)) {
- // When 'spellcapcheck' is set compile the regexp program.
- errmsg = compile_cap_prog(curwin->w_s);
- } else if (varp == &(curwin->w_s->b_p_spo)) { // 'spelloptions'
- if (opt_strings_flags(curwin->w_s->b_p_spo, p_spo_values, &(curwin->w_s->b_p_spo_flags),
- true) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_sps) { // 'spellsuggest'
- if (spell_check_sps() != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_msm) { // 'mkspellmem'
- if (spell_check_msm() != OK) {
- errmsg = e_invarg;
- }
- } else if (gvarp == &p_bh) {
- // When 'bufhidden' is set, check for valid value.
- if (check_opt_strings(curbuf->b_p_bh, p_bufhidden_values, false) != OK) {
- errmsg = e_invarg;
- }
- } else if (gvarp == &p_bt) {
- // When 'buftype' is set, check for valid value.
- if ((curbuf->terminal && curbuf->b_p_bt[0] != 't')
- || (!curbuf->terminal && curbuf->b_p_bt[0] == 't')
- || check_opt_strings(curbuf->b_p_bt, p_buftype_values, false) != OK) {
- errmsg = e_invarg;
- } else {
- if (curwin->w_status_height || global_stl_height()) {
- curwin->w_redr_status = true;
- redraw_later(curwin, UPD_VALID);
- }
- curbuf->b_help = (curbuf->b_p_bt[0] == 'h');
- redraw_titles();
- }
- } else if (gvarp == &p_stl || gvarp == &p_wbr || varp == &p_tal
- || varp == &p_ruf || varp == &curwin->w_p_stc) {
- // 'statusline', 'winbar', 'tabline', 'rulerformat' or 'statuscolumn'
- int wid;
-
- if (varp == &p_ruf) { // reset ru_wid first
- ru_wid = 0;
- } else if (varp == &curwin->w_p_stc) {
- curwin->w_nrwidth_line_count = 0;
- }
- s = *varp;
- if (varp == &p_ruf && *s == '%') {
- // set ru_wid if 'ruf' starts with "%99("
- if (*++s == '-') { // ignore a '-'
- s++;
- }
- wid = getdigits_int(&s, true, 0);
- if (wid && *s == '(' && (errmsg = check_stl_option(p_ruf)) == NULL) {
- ru_wid = wid;
- } else {
- errmsg = check_stl_option(p_ruf);
- }
- } else if (varp == &p_ruf || s[0] != '%' || s[1] != '!') {
- // check 'statusline', 'winbar', 'tabline' or 'statuscolumn'
- // only if it doesn't start with "%!"
- errmsg = check_stl_option(s);
- }
- if (varp == &p_ruf && errmsg == NULL) {
- comp_col();
- }
- // add / remove window bars for 'winbar'
- if (gvarp == &p_wbr) {
- set_winbar(true);
- }
- } else if (gvarp == &p_cpt) {
- // check if it is a valid value for 'complete' -- Acevedo
- for (s = *varp; *s;) {
- while (*s == ',' || *s == ' ') {
- s++;
- }
- if (!*s) {
- break;
- }
- if (vim_strchr(".wbuksid]tU", *s) == NULL) {
- errmsg = illegal_char(errbuf, errbuflen, *s);
- break;
- }
- if (*++s != NUL && *s != ',' && *s != ' ') {
- if (s[-1] == 'k' || s[-1] == 's') {
- // skip optional filename after 'k' and 's'
- while (*s && *s != ',' && *s != ' ') {
- if (*s == '\\' && s[1] != NUL) {
- s++;
- }
+ if (*++s != NUL && *s != ',' && *s != ' ') {
+ if (s[-1] == 'k' || s[-1] == 's') {
+ // skip optional filename after 'k' and 's'
+ while (*s && *s != ',' && *s != ' ') {
+ if (*s == '\\' && s[1] != NUL) {
s++;
}
+ s++;
+ }
+ } else {
+ if (errbuf != NULL) {
+ vim_snprintf(errbuf, errbuflen,
+ _("E535: Illegal character after <%c>"),
+ *--s);
+ *errmsg = errbuf;
} else {
- if (errbuf != NULL) {
- vim_snprintf(errbuf, errbuflen,
- _("E535: Illegal character after <%c>"),
- *--s);
- errmsg = errbuf;
- } else {
- errmsg = "";
- }
- break;
+ *errmsg = "";
}
+ break;
}
}
- } else if (varp == &p_cot) { // 'completeopt'
- if (check_opt_strings(p_cot, p_cot_values, true) != OK) {
- errmsg = e_invarg;
- } else {
- completeopt_was_set();
- }
+ }
+}
+
+static void did_set_completeopt(char **errmsg)
+{
+ if (check_opt_strings(p_cot, p_cot_values, true) != OK) {
+ *errmsg = e_invarg;
+ } else {
+ completeopt_was_set();
+ }
+}
+
#ifdef BACKSLASH_IN_FILENAME
- } else if (gvarp == &p_csl) { // 'completeslash'
- if (check_opt_strings(p_csl, p_csl_values, false) != OK
- || check_opt_strings(curbuf->b_p_csl, p_csl_values, false) != OK) {
- errmsg = e_invarg;
- }
+static void did_set_completeslash(buf_T *buf, char **errmsg)
+{
+ if (check_opt_strings(p_csl, p_csl_values, false) != OK
+ || check_opt_strings(buf->b_p_csl, p_csl_values, false) != OK) {
+ *errmsg = e_invarg;
+ }
+}
#endif
- } else if (varp == &curwin->w_p_scl) { // 'signcolumn'
- if (check_signcolumn(*varp) != OK) {
- errmsg = e_invarg;
- }
- // When changing the 'signcolumn' to or from 'number', recompute the
- // width of the number column if 'number' or 'relativenumber' is set.
- if (((*oldval == 'n' && *(oldval + 1) == 'u')
- || (*curwin->w_p_scl == 'n' && *(curwin->w_p_scl + 1) == 'u'))
- && (curwin->w_p_nu || curwin->w_p_rnu)) {
- curwin->w_nrwidth_line_count = 0;
- }
- } else if (varp == &p_sloc) { // 'showcmdloc'
- if (check_opt_strings(p_sloc, p_sloc_values, false) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &curwin->w_p_fdc
- || varp == &curwin->w_allbuf_opt.wo_fdc) {
- // 'foldcolumn'
- if (**varp == NUL || check_opt_strings(*varp, p_fdc_values, false) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_pt) {
- // 'pastetoggle': translate key codes like in a mapping
- if (*p_pt) {
- p = NULL;
- (void)replace_termcodes(p_pt,
- strlen(p_pt),
- &p, REPTERM_FROM_PART | REPTERM_DO_LT, NULL,
- CPO_TO_CPO_FLAGS);
- if (p != NULL) {
- free_string_option(p_pt);
- p_pt = p;
- }
- }
- } else if (varp == &p_bs) { // 'backspace'
- if (ascii_isdigit(*p_bs)) {
- if (*p_bs > '3' || p_bs[1] != NUL) {
- errmsg = e_invarg;
- }
- } else if (check_opt_strings(p_bs, p_bs_values, true) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_bo) {
- if (opt_strings_flags(p_bo, p_bo_values, &bo_flags, true) != OK) {
- errmsg = e_invarg;
- }
- } else if (gvarp == &p_tc) { // 'tagcase'
- unsigned int *flags;
- if (opt_flags & OPT_LOCAL) {
- p = curbuf->b_p_tc;
- flags = &curbuf->b_tc_flags;
- } else {
- p = p_tc;
- flags = &tc_flags;
- }
+static void did_set_signcolumn(win_T *win, char **varp, const char *oldval, char **errmsg)
+{
+ if (check_signcolumn(*varp) != OK) {
+ *errmsg = e_invarg;
+ }
+ // When changing the 'signcolumn' to or from 'number', recompute the
+ // width of the number column if 'number' or 'relativenumber' is set.
+ if (((*oldval == 'n' && *(oldval + 1) == 'u')
+ || (*win->w_p_scl == 'n' && *(win->w_p_scl + 1) == 'u'))
+ && (win->w_p_nu || win->w_p_rnu)) {
+ win->w_nrwidth_line_count = 0;
+ }
+}
- if ((opt_flags & OPT_LOCAL) && *p == NUL) {
- // make the local value empty: use the global value
- *flags = 0;
- } else if (*p == NUL
- || opt_strings_flags(p, p_tc_values, flags, false) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_cmp) { // 'casemap'
- if (opt_strings_flags(p_cmp, p_cmp_values, &cmp_flags, true) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_dip) { // 'diffopt'
- if (diffopt_changed() == FAIL) {
- errmsg = e_invarg;
- }
- } else if (gvarp == &curwin->w_allbuf_opt.wo_fdm) { // 'foldmethod'
- if (check_opt_strings(*varp, p_fdm_values, false) != OK
- || *curwin->w_p_fdm == NUL) {
- errmsg = e_invarg;
- } else {
- foldUpdateAll(curwin);
- if (foldmethodIsDiff(curwin)) {
- newFoldLevel();
- }
- }
- } else if (gvarp == &curwin->w_allbuf_opt.wo_fmr) { // 'foldmarker'
- p = vim_strchr(*varp, ',');
- if (p == NULL) {
- errmsg = N_("E536: comma required");
- } else if (p == *varp || p[1] == NUL) {
- errmsg = e_invarg;
- } else if (foldmethodIsMarker(curwin)) {
- foldUpdateAll(curwin);
- }
- } else if (gvarp == &p_cms) { // 'commentstring'
- if (**varp != NUL && strstr(*varp, "%s") == NULL) {
- errmsg = N_("E537: 'commentstring' must be empty or contain %s");
- }
- } else if (varp == &p_fdo) { // 'foldopen'
- if (opt_strings_flags(p_fdo, p_fdo_values, &fdo_flags, true) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_fcl) { // 'foldclose'
- if (check_opt_strings(p_fcl, p_fcl_values, true) != OK) {
- errmsg = e_invarg;
- }
- } else if (gvarp == &curwin->w_allbuf_opt.wo_fdi) { // 'foldignore'
- if (foldmethodIsIndent(curwin)) {
- foldUpdateAll(curwin);
- }
- } else if (gvarp == &p_ve) { // 'virtualedit'
- char *ve = p_ve;
- unsigned int *flags = &ve_flags;
+static void did_set_foldcolumn(char **varp, char **errmsg)
+{
+ if (**varp == NUL || check_opt_strings(*varp, p_fdc_values, false) != OK) {
+ *errmsg = e_invarg;
+ }
+}
- if (opt_flags & OPT_LOCAL) {
- ve = curwin->w_p_ve;
- flags = &curwin->w_ve_flags;
+static void did_set_pastetoggle(void)
+{
+ // 'pastetoggle': translate key codes like in a mapping
+ if (*p_pt) {
+ char *p = NULL;
+ (void)replace_termcodes(p_pt,
+ strlen(p_pt),
+ &p, REPTERM_FROM_PART | REPTERM_DO_LT, NULL,
+ CPO_TO_CPO_FLAGS);
+ if (p != NULL) {
+ free_string_option(p_pt);
+ p_pt = p;
}
+ }
+}
- if ((opt_flags & OPT_LOCAL) && *ve == NUL) {
- // make the local value empty: use the global value
- *flags = 0;
- } else {
- if (opt_strings_flags(ve, p_ve_values, flags, true) != OK) {
- errmsg = e_invarg;
- } else if (strcmp(p_ve, oldval) != 0) {
- // Recompute cursor position in case the new 've' setting
- // changes something.
- validate_virtcol();
- coladvance(curwin->w_virtcol);
- }
+static void did_set_backspace(char **errmsg)
+{
+ if (ascii_isdigit(*p_bs)) {
+ if (*p_bs > '3' || p_bs[1] != NUL) {
+ *errmsg = e_invarg;
}
- } else if (gvarp == &p_cino) { // 'cinoptions'
- // TODO(vim): recognize errors
- parse_cino(curbuf);
- } else if (gvarp == &p_lop) { // 'lispoptions'
- if (**varp != NUL && strcmp(*varp, "expr:0") != 0 && strcmp(*varp, "expr:1") != 0) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_icm) { // 'inccommand'
- if (check_opt_strings(p_icm, p_icm_values, false) != OK) {
- errmsg = e_invarg;
- }
- } else if (gvarp == &p_ft) {
- if (!valid_filetype(*varp)) {
- errmsg = e_invarg;
- } else {
- value_changed = strcmp(oldval, *varp) != 0;
+ } else if (check_opt_strings(p_bs, p_bs_values, true) != OK) {
+ *errmsg = e_invarg;
+ }
+}
- // Since we check the value, there is no need to set P_INSECURE,
- // even when the value comes from a modeline.
- *value_checked = true;
- }
- } else if (gvarp == &p_syn) {
- if (!valid_filetype(*varp)) {
- errmsg = e_invarg;
- } else {
- value_changed = strcmp(oldval, *varp) != 0;
+static void did_set_tagcase(buf_T *buf, int opt_flags, char **errmsg)
+{
+ unsigned int *flags;
+ char *p;
- // Since we check the value, there is no need to set P_INSECURE,
- // even when the value comes from a modeline.
- *value_checked = true;
- }
- } else if (varp == &curwin->w_p_winhl) {
- if (!parse_winhl_opt(curwin)) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_tpf) {
- if (opt_strings_flags(p_tpf, p_tpf_values, &tpf_flags, true) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &(curbuf->b_p_vsts)) { // 'varsofttabstop'
- char *cp;
+ if (opt_flags & OPT_LOCAL) {
+ p = buf->b_p_tc;
+ flags = &buf->b_tc_flags;
+ } else {
+ p = p_tc;
+ flags = &tc_flags;
+ }
- if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) {
- XFREE_CLEAR(curbuf->b_p_vsts_array);
- } else {
- for (cp = *varp; *cp; cp++) {
- if (ascii_isdigit(*cp)) {
- continue;
- }
- if (*cp == ',' && cp > *varp && *(cp - 1) != ',') {
- continue;
- }
- errmsg = e_invarg;
- break;
- }
- if (errmsg == NULL) {
- long *oldarray = curbuf->b_p_vsts_array;
- if (tabstop_set(*varp, &(curbuf->b_p_vsts_array))) {
- xfree(oldarray);
- } else {
- errmsg = e_invarg;
- }
- }
- }
- } else if (varp == &(curbuf->b_p_vts)) { // 'vartabstop'
- char *cp;
+ if ((opt_flags & OPT_LOCAL) && *p == NUL) {
+ // make the local value empty: use the global value
+ *flags = 0;
+ } else if (*p == NUL
+ || opt_strings_flags(p, p_tc_values, flags, false) != OK) {
+ *errmsg = e_invarg;
+ }
+}
- if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) {
- XFREE_CLEAR(curbuf->b_p_vts_array);
- } else {
- for (cp = *varp; *cp; cp++) {
- if (ascii_isdigit(*cp)) {
- continue;
- }
- if (*cp == ',' && cp > *varp && *(cp - 1) != ',') {
- continue;
- }
- errmsg = e_invarg;
- break;
- }
- if (errmsg == NULL) {
- long *oldarray = curbuf->b_p_vts_array;
- if (tabstop_set(*varp, &(curbuf->b_p_vts_array))) {
- xfree(oldarray);
- if (foldmethodIsIndent(curwin)) {
- foldUpdateAll(curwin);
- }
- } else {
- errmsg = e_invarg;
- }
- }
+static void did_set_diffopt(char **errmsg)
+{
+ if (diffopt_changed() == FAIL) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_foldmethod(win_T *win, char **varp, char **errmsg)
+{
+ if (check_opt_strings(*varp, p_fdm_values, false) != OK
+ || *win->w_p_fdm == NUL) {
+ *errmsg = e_invarg;
+ } else {
+ foldUpdateAll(win);
+ if (foldmethodIsDiff(win)) {
+ newFoldLevel();
}
- } else if (varp == &p_dex
- || varp == &curwin->w_p_fde
- || varp == &curwin->w_p_fdt
- || gvarp == &p_fex
- || gvarp == &p_inex
- || gvarp == &p_inde
- || varp == &p_pex) { // '*expr' options
- char **p_opt = NULL;
+ }
+}
- // If the option value starts with <SID> or s:, then replace that with
- // the script identifier.
+static void did_set_foldmarker(win_T *win, char **varp, char **errmsg)
+{
+ char *p = vim_strchr(*varp, ',');
+ if (p == NULL) {
+ *errmsg = N_("E536: comma required");
+ } else if (p == *varp || p[1] == NUL) {
+ *errmsg = e_invarg;
+ } else if (foldmethodIsMarker(win)) {
+ foldUpdateAll(win);
+ }
+}
- if (varp == &p_dex) { // 'diffexpr'
- p_opt = &p_dex;
- }
- if (varp == &curwin->w_p_fde) { // 'foldexpr'
- p_opt = &curwin->w_p_fde;
- }
- if (varp == &curwin->w_p_fdt) { // 'foldtext'
- p_opt = &curwin->w_p_fdt;
- }
- if (gvarp == &p_fex) { // 'formatexpr'
- p_opt = &curbuf->b_p_fex;
- }
- if (gvarp == &p_inex) { // 'includeexpr'
- p_opt = &curbuf->b_p_inex;
- }
- if (gvarp == &p_inde) { // 'indentexpr'
- p_opt = &curbuf->b_p_inde;
- }
- if (varp == &p_pex) { // 'patchexpr'
- p_opt = &p_pex;
- }
+static void did_set_commentstring(char **varp, char **errmsg)
+{
+ if (**varp != NUL && strstr(*varp, "%s") == NULL) {
+ *errmsg = N_("E537: 'commentstring' must be empty or contain %s");
+ }
+}
- if (p_opt != NULL) {
- char *name = get_scriptlocal_funcname(*p_opt);
- if (name != NULL) {
- free_string_option(*p_opt);
- *p_opt = name;
- }
- }
+static void did_set_foldignore(win_T *win)
+{
+ if (foldmethodIsIndent(win)) {
+ foldUpdateAll(win);
+ }
+}
- if (varp == &curwin->w_p_fde && foldmethodIsExpr(curwin)) {
- foldUpdateAll(curwin);
- }
- } else if (gvarp == &p_cfu) { // 'completefunc'
- if (set_completefunc_option() == FAIL) {
- errmsg = e_invarg;
+static void did_set_virtualedit(win_T *win, int opt_flags, char *oldval, char **errmsg)
+{
+ char *ve = p_ve;
+ unsigned int *flags = &ve_flags;
+
+ if (opt_flags & OPT_LOCAL) {
+ ve = win->w_p_ve;
+ flags = &win->w_ve_flags;
+ }
+
+ if ((opt_flags & OPT_LOCAL) && *ve == NUL) {
+ // make the local value empty: use the global value
+ *flags = 0;
+ } else {
+ if (opt_strings_flags(ve, p_ve_values, flags, true) != OK) {
+ *errmsg = e_invarg;
+ } else if (strcmp(ve, oldval) != 0) {
+ // Recompute cursor position in case the new 've' setting
+ // changes something.
+ validate_virtcol_win(win);
+ // XXX: this only works when win == curwin
+ coladvance(win->w_virtcol);
}
- } else if (gvarp == &p_ofu) { // 'omnifunc'
- if (set_omnifunc_option() == FAIL) {
- errmsg = e_invarg;
+ }
+}
+
+static void did_set_lispoptions(char **varp, char **errmsg)
+{
+ if (**varp != NUL && strcmp(*varp, "expr:0") != 0 && strcmp(*varp, "expr:1") != 0) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_filetype_or_syntax(char **varp, char *oldval, int *value_checked,
+ bool *value_changed, char **errmsg)
+{
+ if (!valid_filetype(*varp)) {
+ *errmsg = e_invarg;
+ return;
+ }
+
+ *value_changed = strcmp(oldval, *varp) != 0;
+
+ // Since we check the value, there is no need to set P_INSECURE,
+ // even when the value comes from a modeline.
+ *value_checked = true;
+}
+
+static void did_set_winhl(win_T *win, char **errmsg)
+{
+ if (!parse_winhl_opt(win)) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_varsoftabstop(buf_T *buf, char **varp, char **errmsg)
+{
+ if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) {
+ XFREE_CLEAR(buf->b_p_vsts_array);
+ return;
+ }
+
+ for (char *cp = *varp; *cp; cp++) {
+ if (ascii_isdigit(*cp)) {
+ continue;
}
- } else if (gvarp == &p_tsrfu) { // 'thesaurusfunc'
- if (set_thesaurusfunc_option() == FAIL) {
- errmsg = e_invarg;
+ if (*cp == ',' && cp > *varp && *(cp - 1) != ',') {
+ continue;
}
- } else if (varp == &p_opfunc) { // 'operatorfunc'
- if (set_operatorfunc_option() == FAIL) {
- errmsg = e_invarg;
+ *errmsg = e_invarg;
+ return;
+ }
+
+ long *oldarray = buf->b_p_vsts_array;
+ if (tabstop_set(*varp, &(buf->b_p_vsts_array))) {
+ xfree(oldarray);
+ } else {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_vartabstop(buf_T *buf, win_T *win, char **varp, char **errmsg)
+{
+ if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) {
+ XFREE_CLEAR(buf->b_p_vts_array);
+ return;
+ }
+
+ for (char *cp = *varp; *cp; cp++) {
+ if (ascii_isdigit(*cp)) {
+ continue;
}
- } else if (varp == &p_qftf) { // 'quickfixtextfunc'
- if (qf_process_qftf_option() == FAIL) {
- errmsg = e_invarg;
+ if (*cp == ',' && cp > *varp && *(cp - 1) != ',') {
+ continue;
}
- } else if (gvarp == &p_tfu) { // 'tagfunc'
- if (set_tagfunc_option() == FAIL) {
- errmsg = e_invarg;
+ *errmsg = e_invarg;
+ return;
+ }
+
+ long *oldarray = buf->b_p_vts_array;
+ if (tabstop_set(*varp, &(buf->b_p_vts_array))) {
+ xfree(oldarray);
+ if (foldmethodIsIndent(win)) {
+ foldUpdateAll(win);
}
} else {
- // Options that are a list of flags.
- p = NULL;
- if (varp == &p_ww) { // 'whichwrap'
- p = WW_ALL;
- }
- if (varp == &p_shm) { // 'shortmess'
- p = SHM_ALL;
- } else if (varp == &(p_cpo)) { // 'cpoptions'
- p = CPO_VI;
- } else if (varp == &(curbuf->b_p_fo)) { // 'formatoptions'
- p = FO_ALL;
- } else if (varp == &curwin->w_p_cocu) { // 'concealcursor'
- p = COCU_ALL;
- } else if (varp == &p_mouse) { // 'mouse'
- p = MOUSE_ALL;
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_optexpr(char **varp)
+{
+ char *name = get_scriptlocal_funcname(*varp);
+ if (name != NULL) {
+ free_string_option(*varp);
+ *varp = name;
+ }
+}
+
+// handle option that is a list of flags.
+static void did_set_option_listflag(char **varp, char *flags, char *errbuf, size_t errbuflen,
+ char **errmsg)
+{
+ for (char *s = *varp; *s; s++) {
+ if (vim_strchr(flags, (uint8_t)(*s)) == NULL) {
+ *errmsg = illegal_char(errbuf, errbuflen, (uint8_t)(*s));
+ break;
}
- if (p != NULL) {
- for (s = *varp; *s; s++) {
- if (vim_strchr(p, *s) == NULL) {
- errmsg = illegal_char(errbuf, errbuflen, *s);
- break;
- }
- }
+ }
+}
+
+// When 'syntax' is set, load the syntax of that name
+static void do_syntax_autocmd(buf_T *buf, bool value_changed)
+{
+ static int syn_recursive = 0;
+
+ syn_recursive++;
+ // Only pass true for "force" when the value changed or not used
+ // recursively, to avoid endless recurrence.
+ apply_autocmds(EVENT_SYNTAX, buf->b_p_syn, buf->b_fname,
+ value_changed || syn_recursive == 1, buf);
+ buf->b_flags |= BF_SYN_SET;
+ syn_recursive--;
+}
+
+static void do_filetype_autocmd(buf_T *buf, char **varp, int opt_flags, bool value_changed)
+{
+ // 'filetype' is set, trigger the FileType autocommand
+ // Skip this when called from a modeline and the filetype was
+ // already set to this value.
+ if (!(opt_flags & OPT_MODELINE) || value_changed) {
+ static int ft_recursive = 0;
+ int secure_save = secure;
+
+ // Reset the secure flag, since the value of 'filetype' has
+ // been checked to be safe.
+ secure = 0;
+
+ ft_recursive++;
+ did_filetype = true;
+ // Only pass true for "force" when the value changed or not
+ // used recursively, to avoid endless recurrence.
+ apply_autocmds(EVENT_FILETYPE, buf->b_p_ft, buf->b_fname,
+ value_changed || ft_recursive == 1, buf);
+ ft_recursive--;
+ // Just in case the old "buf" is now invalid
+ if (varp != &(buf->b_p_ft)) {
+ varp = NULL;
+ }
+ secure = secure_save;
+ }
+}
+
+static void do_spelllang_source(win_T *win)
+{
+ char fname[200];
+ char *q = win->w_s->b_p_spl;
+
+ // Skip the first name if it is "cjk".
+ if (strncmp(q, "cjk,", 4) == 0) {
+ q += 4;
+ }
+
+ // Source the spell/LANG.vim in 'runtimepath'.
+ // They could set 'spellcapcheck' depending on the language.
+ // Use the first name in 'spelllang' up to '_region' or
+ // '.encoding'.
+ char *p;
+ for (p = q; *p != NUL; p++) {
+ if (!ASCII_ISALNUM(*p) && *p != '-') {
+ break;
}
}
+ if (p > q) {
+ vim_snprintf(fname, sizeof(fname), "spell/%.*s.vim", (int)(p - q), q);
+ source_runtime(fname, DIP_ALL);
+ }
+}
+
+/// Handle string options that need some action to perform when changed.
+/// The new value must be allocated.
+///
+/// @param opt_idx index in options[] table
+/// @param varp pointer to the option variable
+/// @param oldval previous value of the option
+/// @param errbuf buffer for errors, or NULL
+/// @param errbuflen length of errors buffer
+/// @param opt_flags OPT_LOCAL and/or OPT_GLOBAL
+/// @param value_checked value was checked to be safe, no need to set P_INSECURE
+///
+/// @return NULL for success, or an untranslated error message for an error
+static char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx, char **varp,
+ char *oldval, char *errbuf, size_t errbuflen, int opt_flags,
+ int *value_checked)
+{
+ char *errmsg = NULL;
+ bool did_chartab = false;
+ vimoption_T *opt = get_option(opt_idx);
+ bool free_oldval = (opt->flags & P_ALLOCED);
+ bool value_changed = false;
+
+ // Get the global option to compare with, otherwise we would have to check
+ // two values for all local options.
+ char **gvarp = (char **)get_varp_scope(opt, OPT_GLOBAL);
- // If error detected, restore the previous value.
+ // Disallow changing some options from secure mode
+ if ((secure || sandbox != 0) && (opt->flags & P_SECURE)) {
+ errmsg = e_secure;
+ // Check for a "normal" directory or file name in some options.
+ } else if (check_illegal_path_names(*varp, opt->flags)) {
+ errmsg = e_invarg;
+ } else if (gvarp == &p_bkc) { // 'backupcopy'
+ did_set_backupcopy(buf, oldval, opt_flags, &errmsg);
+ } else if (varp == &p_bex // 'backupext'
+ || varp == &p_pm) { // 'patchmode'
+ did_set_backupext_or_patchmode(&errmsg);
+ } else if (varp == &win->w_p_briopt) { // 'breakindentopt'
+ did_set_breakindentopt(win, &errmsg);
+ } else if (varp == &p_isi // 'isident'
+ || varp == &buf->b_p_isk // 'iskeyword'
+ || varp == &p_isp // 'isprint'
+ || varp == &p_isf) { // 'isfname'
+ did_set_isopt(buf, &did_chartab, &errmsg);
+ } else if (varp == &p_hf) { // 'helpfile'
+ did_set_helpfile();
+ } else if (varp == &p_rtp // 'runtimepath'
+ || varp == &p_pp) { // 'packpath'
+ runtime_search_path_invalidate();
+ } else if (gvarp == &win->w_allbuf_opt.wo_culopt) { // 'cursorlineopt'
+ did_set_cursorlineopt(win, varp, &errmsg);
+ } else if (varp == &win->w_p_cc) { // 'colorcolumn'
+ errmsg = check_colorcolumn(win);
+ } else if (varp == &p_hlg) { // 'helplang'
+ did_set_helplang(&errmsg);
+ } else if (varp == &p_hl) { // 'highlight'
+ did_set_highlight(varp, &errmsg);
+ } else if (varp == &p_jop) { // 'jumpoptions'
+ did_set_opt_flags(p_jop, p_jop_values, &jop_flags, true, &errmsg);
+ } else if (gvarp == &p_nf) { // 'nrformats'
+ did_set_opt_strings(*varp, p_nf_values, true, &errmsg);
+ } else if (varp == &p_ssop) { // 'sessionoptions'
+ did_set_sessionoptions(oldval, &errmsg);
+ } else if (varp == &p_vop) { // 'viewoptions'
+ did_set_opt_flags(p_vop, p_ssop_values, &vop_flags, true, &errmsg);
+ } else if (varp == &p_rdb) { // 'redrawdebug'
+ did_set_opt_flags(p_rdb, p_rdb_values, &rdb_flags, true, &errmsg);
+ } else if (varp == &p_sbo) { // 'scrollopt'
+ did_set_opt_strings(p_sbo, p_scbopt_values, true, &errmsg);
+ } else if (varp == &p_ambw // 'ambiwidth'
+ || (int *)varp == &p_emoji) { // 'emoji'
+ did_set_ambiwidth(&errmsg);
+ } else if (varp == &p_bg) { // 'background'
+ did_set_background(&errmsg);
+ } else if (varp == &p_wim) { // 'wildmode'
+ did_set_wildmode(&errmsg);
+ } else if (varp == &p_wop) { // 'wildoptions'
+ did_set_opt_flags(p_wop, p_wop_values, &wop_flags, true, &errmsg);
+ } else if (varp == &p_wak) { // 'winaltkeys'
+ did_set_winaltkeys(&errmsg);
+ } else if (varp == &p_ei) { // 'eventignore'
+ did_set_eventignore(&errmsg);
+ } else if (varp == &p_enc // 'encoding'
+ || gvarp == &p_fenc // 'fileencoding'
+ || gvarp == &p_menc) { // 'makeencoding'
+ did_set_encoding(buf, varp, gvarp, opt_flags, &errmsg);
+ } else if (varp == &buf->b_p_keymap) { // 'keymap'
+ did_set_keymap(buf, varp, opt_flags, value_checked, &errmsg);
+ } else if (gvarp == &p_ff) { // 'fileformat'
+ did_set_fileformat(buf, varp, oldval, opt_flags, &errmsg);
+ } else if (varp == &p_ffs) { // 'fileformats'
+ did_set_opt_strings(p_ffs, p_ff_values, true, &errmsg);
+ } else if (gvarp == &p_mps) { // 'matchpairs'
+ did_set_matchpairs(varp, &errmsg);
+ } else if (gvarp == &p_com) { // 'comments'
+ did_set_comments(varp, errbuf, errbuflen, &errmsg);
+ } else if (varp == &p_lcs // global 'listchars'
+ || varp == &p_fcs) { // global 'fillchars'
+ did_set_global_listfillchars(win, varp, opt_flags, &errmsg);
+ } else if (varp == &win->w_p_lcs) { // local 'listchars'
+ errmsg = set_chars_option(win, varp, true);
+ } else if (varp == &win->w_p_fcs) { // local 'fillchars'
+ errmsg = set_chars_option(win, varp, true);
+ } else if (varp == &p_cedit) { // 'cedit'
+ errmsg = check_cedit();
+ } else if (varp == &p_vfile) { // 'verbosefile'
+ did_set_verbosefile(&errmsg);
+ } else if (varp == &p_shada) { // 'shada'
+ did_set_shada(&opt, &opt_idx, &free_oldval, errbuf, errbuflen, &errmsg);
+ } else if (gvarp == &p_sbr) { // 'showbreak'
+ did_set_showbreak(varp, &errmsg);
+ } else if (varp == &p_guicursor) { // 'guicursor'
+ errmsg = parse_shape_opt(SHAPE_CURSOR);
+ } else if (varp == &p_langmap) { // 'langmap'
+ langmap_set();
+ } else if (varp == &p_breakat) { // 'breakat'
+ fill_breakat_flags();
+ } else if (varp == &p_titlestring // 'titlestring'
+ || varp == &p_iconstring) { // 'iconstring'
+ did_set_titleiconstring(varp);
+ } else if (varp == &p_sel) { // 'selection'
+ did_set_selection(&errmsg);
+ } else if (varp == &p_slm) { // 'selectmode'
+ did_set_opt_strings(p_slm, p_slm_values, true, &errmsg);
+ } else if (varp == &p_km) { // 'keymodel'
+ did_set_keymodel(&errmsg);
+ } else if (varp == &p_mousem) { // 'mousemodel'
+ did_set_opt_strings(p_mousem, p_mousem_values, false, &errmsg);
+ } else if (varp == &p_mousescroll) { // 'mousescroll'
+ errmsg = check_mousescroll(p_mousescroll);
+ } else if (varp == &p_swb) { // 'switchbuf'
+ did_set_opt_flags(p_swb, p_swb_values, &swb_flags, true, &errmsg);
+ } else if (varp == &p_spk) { // 'splitkeep'
+ did_set_opt_strings(p_spk, p_spk_values, false, &errmsg);
+ } else if (varp == &p_debug) { // 'debug'
+ did_set_opt_strings(p_debug, p_debug_values, true, &errmsg);
+ } else if (varp == &p_dy) { // 'display'
+ did_set_display(&errmsg);
+ } else if (varp == &p_ead) { // 'eadirection'
+ did_set_opt_strings(p_ead, p_ead_values, false, &errmsg);
+ } else if (varp == &p_cb) { // 'clipboard'
+ did_set_opt_flags(p_cb, p_cb_values, &cb_flags, true, &errmsg);
+ } else if (varp == &win->w_s->b_p_spf) { // 'spellfile'
+ did_set_spellfile(varp, &errmsg);
+ } else if (varp == &win->w_s->b_p_spl) { // 'spell'
+ did_set_spell(varp, &errmsg);
+ } else if (varp == &win->w_s->b_p_spc) { // 'spellcapcheck'
+ did_set_spellcapcheck(win, &errmsg);
+ } else if (varp == &win->w_s->b_p_spo) { // 'spelloptions'
+ did_set_spelloptions(win, &errmsg);
+ } else if (varp == &p_sps) { // 'spellsuggest'
+ did_set_spellsuggest(&errmsg);
+ } else if (varp == &p_msm) { // 'mkspellmem'
+ did_set_mkspellmem(&errmsg);
+ } else if (gvarp == &p_bh) { // 'bufhidden'
+ did_set_opt_strings(buf->b_p_bh, p_bufhidden_values, false, &errmsg);
+ } else if (gvarp == &p_bt) { // 'buftype'
+ did_set_buftype(buf, win, &errmsg);
+ } else if (gvarp == &p_stl // 'statusline'
+ || gvarp == &p_wbr // 'winbar'
+ || varp == &p_tal // 'tabline'
+ || varp == &p_ruf // 'rulerformat'
+ || varp == &win->w_p_stc) { // 'statuscolumn'
+ did_set_statusline(win, varp, gvarp, &errmsg);
+ } else if (gvarp == &p_cpt) { // 'complete'
+ did_set_complete(varp, errbuf, errbuflen, &errmsg);
+ } else if (varp == &p_cot) { // 'completeopt'
+ did_set_completeopt(&errmsg);
+#ifdef BACKSLASH_IN_FILENAME
+ } else if (gvarp == &p_csl) { // 'completeslash'
+ did_set_completeslash(buf, &errmsg);
+#endif
+ } else if (varp == &win->w_p_scl) { // 'signcolumn'
+ did_set_signcolumn(win, varp, oldval, &errmsg);
+ } else if (varp == &p_sloc) { // 'showcmdloc'
+ did_set_opt_strings(*varp, p_sloc_values, false, &errmsg);
+ } else if (gvarp == &win->w_allbuf_opt.wo_fdc) { // 'foldcolumn'
+ did_set_foldcolumn(varp, &errmsg);
+ } else if (varp == &p_pt) { // 'pastetoggle'
+ did_set_pastetoggle();
+ } else if (varp == &p_bs) { // 'backspace'
+ did_set_backspace(&errmsg);
+ } else if (varp == &p_bo) {
+ did_set_opt_flags(p_bo, p_bo_values, &bo_flags, true, &errmsg);
+ } else if (gvarp == &p_tc) { // 'tagcase'
+ did_set_tagcase(buf, opt_flags, &errmsg);
+ } else if (varp == &p_cmp) { // 'casemap'
+ did_set_opt_flags(p_cmp, p_cmp_values, &cmp_flags, true, &errmsg);
+ } else if (varp == &p_dip) { // 'diffopt'
+ did_set_diffopt(&errmsg);
+ } else if (gvarp == &win->w_allbuf_opt.wo_fdm) { // 'foldmethod'
+ did_set_foldmethod(win, varp, &errmsg);
+ } else if (gvarp == &win->w_allbuf_opt.wo_fmr) { // 'foldmarker'
+ did_set_foldmarker(win, varp, &errmsg);
+ } else if (gvarp == &p_cms) { // 'commentstring'
+ did_set_commentstring(varp, &errmsg);
+ } else if (varp == &p_fdo) { // 'foldopen'
+ did_set_opt_flags(p_fdo, p_fdo_values, &fdo_flags, true, &errmsg);
+ } else if (varp == &p_fcl) { // 'foldclose'
+ did_set_opt_strings(*varp, p_fcl_values, true, &errmsg);
+ } else if (gvarp == &win->w_allbuf_opt.wo_fdi) { // 'foldignore'
+ did_set_foldignore(win);
+ } else if (gvarp == &p_ve) { // 'virtualedit'
+ did_set_virtualedit(win, opt_flags, oldval, &errmsg);
+ } else if (gvarp == &p_cino) { // 'cinoptions'
+ // TODO(vim): recognize errors
+ parse_cino(buf);
+ } else if (gvarp == &p_lop) { // 'lispoptions'
+ did_set_lispoptions(varp, &errmsg);
+ } else if (varp == &p_icm) { // 'inccommand'
+ did_set_opt_strings(*varp, p_icm_values, false, &errmsg);
+ } else if (gvarp == &p_ft // 'filetype'
+ || gvarp == &p_syn) { // 'syntax'
+ did_set_filetype_or_syntax(varp, oldval, value_checked, &value_changed, &errmsg);
+ } else if (varp == &win->w_p_winhl) { // 'winhighlight'
+ did_set_winhl(win, &errmsg);
+ } else if (varp == &p_tpf) {
+ did_set_opt_flags(p_tpf, p_tpf_values, &tpf_flags, true, &errmsg);
+ } else if (varp == &buf->b_p_vsts) { // 'varsofttabstop'
+ did_set_varsoftabstop(buf, varp, &errmsg);
+ } else if (varp == &buf->b_p_vts) { // 'vartabstop'
+ did_set_vartabstop(buf, win, varp, &errmsg);
+ } else if (varp == &p_dex // 'diffexpr'
+ || gvarp == &win->w_allbuf_opt.wo_fde // 'foldexpr'
+ || gvarp == &win->w_allbuf_opt.wo_fdt // 'foldtext'
+ || gvarp == &p_fex // 'formatexpr'
+ || gvarp == &p_inex // 'includeexpr'
+ || gvarp == &p_inde // 'indentexpr'
+ || varp == &p_pex // 'patchexpr'
+ || varp == &p_ccv) { // 'charconvert'
+ did_set_optexpr(varp);
+ if (varp == &win->w_p_fde && foldmethodIsExpr(win)) {
+ foldUpdateAll(win);
+ }
+ } else if (gvarp == &p_cfu) { // 'completefunc'
+ set_completefunc_option(&errmsg);
+ } else if (gvarp == &p_ofu) { // 'omnifunc'
+ set_omnifunc_option(buf, &errmsg);
+ } else if (gvarp == &p_tsrfu) { // 'thesaurusfunc'
+ set_thesaurusfunc_option(&errmsg);
+ } else if (varp == &p_opfunc) { // 'operatorfunc'
+ set_operatorfunc_option(&errmsg);
+ } else if (varp == &p_qftf) { // 'quickfixtextfunc'
+ qf_process_qftf_option(&errmsg);
+ } else if (gvarp == &p_tfu) { // 'tagfunc'
+ set_tagfunc_option(&errmsg);
+ } else if (varp == &p_ww) { // 'whichwrap'
+ did_set_option_listflag(varp, WW_ALL, errbuf, errbuflen, &errmsg);
+ } else if (varp == &p_shm) { // 'shortmess'
+ did_set_option_listflag(varp, SHM_ALL, errbuf, errbuflen, &errmsg);
+ } else if (varp == &p_cpo) { // 'cpoptions'
+ did_set_option_listflag(varp, CPO_VI, errbuf, errbuflen, &errmsg);
+ } else if (varp == &buf->b_p_fo) { // 'formatoptions'
+ did_set_option_listflag(varp, FO_ALL, errbuf, errbuflen, &errmsg);
+ } else if (varp == &win->w_p_cocu) { // 'concealcursor'
+ did_set_option_listflag(varp, COCU_ALL, errbuf, errbuflen, &errmsg);
+ } else if (varp == &p_mouse) { // 'mouse'
+ did_set_option_listflag(varp, MOUSE_ALL, errbuf, errbuflen, &errmsg);
+ } else if (gvarp == &p_flp) { // 'formatlistpat'
+ if (win->w_briopt_list) {
+ // Changing Formatlistpattern when briopt includes the list setting:
+ // redraw
+ redraw_all_later(UPD_NOT_VALID);
+ }
+ }
+
+ // If an error is detected, restore the previous value.
if (errmsg != NULL) {
free_string_option(*varp);
*varp = oldval;
// When resetting some values, need to act on it.
if (did_chartab) {
- (void)init_chartab();
+ (void)buf_init_chartab(buf, true);
}
} else {
// Remember where the option was set.
@@ -1598,7 +1886,7 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf
&& (opt->indir & PV_BOTH)) {
// global option with local value set to use global value; free
// the local value and make it empty
- p = get_varp_scope(opt, OPT_LOCAL);
+ char *p = get_varp_scope(opt, OPT_LOCAL);
free_string_option(*(char **)p);
*(char **)p = empty_option;
} else if (!(opt_flags & OPT_LOCAL) && opt_flags != OPT_GLOBAL) {
@@ -1607,65 +1895,12 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf
}
// Trigger the autocommand only after setting the flags.
- // When 'syntax' is set, load the syntax of that name
- if (varp == &(curbuf->b_p_syn)) {
- static int syn_recursive = 0;
-
- syn_recursive++;
- // Only pass true for "force" when the value changed or not used
- // recursively, to avoid endless recurrence.
- apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn, curbuf->b_fname,
- value_changed || syn_recursive == 1, curbuf);
- curbuf->b_flags |= BF_SYN_SET;
- syn_recursive--;
- } else if (varp == &(curbuf->b_p_ft)) {
- // 'filetype' is set, trigger the FileType autocommand
- // Skip this when called from a modeline and the filetype was
- // already set to this value.
- if (!(opt_flags & OPT_MODELINE) || value_changed) {
- static int ft_recursive = 0;
- int secure_save = secure;
-
- // Reset the secure flag, since the value of 'filetype' has
- // been checked to be safe.
- secure = 0;
-
- ft_recursive++;
- did_filetype = true;
- // Only pass true for "force" when the value changed or not
- // used recursively, to avoid endless recurrence.
- apply_autocmds(EVENT_FILETYPE, curbuf->b_p_ft, curbuf->b_fname,
- value_changed || ft_recursive == 1, curbuf);
- ft_recursive--;
- // Just in case the old "curbuf" is now invalid
- if (varp != &(curbuf->b_p_ft)) {
- varp = NULL;
- }
- secure = secure_save;
- }
- }
- if (varp == &(curwin->w_s->b_p_spl)) {
- char fname[200];
- char *q = curwin->w_s->b_p_spl;
-
- // Skip the first name if it is "cjk".
- if (strncmp(q, "cjk,", 4) == 0) {
- q += 4;
- }
-
- // Source the spell/LANG.vim in 'runtimepath'.
- // They could set 'spellcapcheck' depending on the language.
- // Use the first name in 'spelllang' up to '_region' or
- // '.encoding'.
- for (p = q; *p != NUL; p++) {
- if (!ASCII_ISALNUM(*p) && *p != '-') {
- break;
- }
- }
- if (p > q) {
- vim_snprintf(fname, sizeof(fname), "spell/%.*s.vim", (int)(p - q), q);
- source_runtime(fname, DIP_ALL);
- }
+ if (varp == &buf->b_p_syn) {
+ do_syntax_autocmd(buf, value_changed);
+ } else if (varp == &buf->b_p_ft) {
+ do_filetype_autocmd(buf, varp, opt_flags, value_changed);
+ } else if (varp == &win->w_s->b_p_spl) {
+ do_spelllang_source(win);
}
}
@@ -1673,22 +1908,23 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf
setmouse(); // in case 'mouse' changed
}
- // Changing Formatlistpattern when briopt includes the list setting:
- // redraw
- if ((varp == &p_flp || varp == &(curbuf->b_p_flp)) && curwin->w_briopt_list) {
- redraw_all_later(UPD_NOT_VALID);
- }
-
- if (curwin->w_curswant != MAXCOL
+ if (win->w_curswant != MAXCOL
&& (opt->flags & (P_CURSWANT | P_RALL)) != 0) {
- curwin->w_set_curswant = true;
+ win->w_set_curswant = true;
}
- check_redraw(opt->flags);
+ check_redraw_for(buf, win, opt->flags);
return errmsg;
}
+char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf, size_t errbuflen,
+ int opt_flags, int *value_checked)
+{
+ return did_set_string_option_for(curbuf, curwin, opt_idx, varp, oldval, errbuf, errbuflen,
+ opt_flags, value_checked);
+}
+
/// Check an option that can be a range of string values.
///
/// @param list when true: accept a list of values
diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c
index e1db7a8ef7..0611de14aa 100644
--- a/src/nvim/os/env.c
+++ b/src/nvim/os/env.c
@@ -543,7 +543,7 @@ void free_homedir(void)
/// @see {expand_env}
char *expand_env_save(char *src)
{
- return (char *)expand_env_save_opt(src, false);
+ return expand_env_save_opt(src, false);
}
/// Similar to expand_env_save() but when "one" is `true` handle the string as
@@ -551,10 +551,10 @@ char *expand_env_save(char *src)
/// @param src String containing environment variables to expand
/// @param one Should treat as only one file name
/// @see {expand_env}
-char_u *expand_env_save_opt(char *src, bool one)
+char *expand_env_save_opt(char *src, bool one)
{
- char_u *p = xmalloc(MAXPATHL);
- expand_env_esc(src, (char *)p, MAXPATHL, false, one, NULL);
+ char *p = xmalloc(MAXPATHL);
+ expand_env_esc(src, p, MAXPATHL, false, one, NULL);
return p;
}
@@ -656,7 +656,7 @@ void expand_env_esc(char *restrict srcp, char *restrict dst, int dstlen, bool es
#endif
} else if (src[1] == NUL // home directory
|| vim_ispathsep(src[1])
- || vim_strchr(" ,\t\n", src[1]) != NULL) {
+ || vim_strchr(" ,\t\n", (uint8_t)src[1]) != NULL) {
var = homedir;
tail = src + 1;
} else { // user directory
@@ -689,7 +689,7 @@ void expand_env_esc(char *restrict srcp, char *restrict dst, int dstlen, bool es
#else
// cannot expand user's home directory, so don't try
var = NULL;
- tail = (char_u *)""; // for gcc
+ tail = ""; // for gcc
#endif // UNIX
}
@@ -697,7 +697,7 @@ void expand_env_esc(char *restrict srcp, char *restrict dst, int dstlen, bool es
// If 'shellslash' is set change backslashes to forward slashes.
// Can't use slash_adjust(), p_ssl may be set temporarily.
if (p_ssl && var != NULL && vim_strchr(var, '\\') != NULL) {
- char_u *p = xstrdup(var);
+ char *p = xstrdup(var);
if (mustfree) {
xfree(var);
@@ -1198,7 +1198,7 @@ bool os_setenv_append_path(const char *fname)
// No prescribed maximum on unix.
# define MAX_ENVPATHLEN INT_MAX
#endif
- if (!path_is_absolute((char_u *)fname)) {
+ if (!path_is_absolute(fname)) {
internal_error("os_setenv_append_path()");
return false;
}
diff --git a/src/nvim/os/fileio.c b/src/nvim/os/fileio.c
index e93e1febcb..5af39555c9 100644
--- a/src/nvim/os/fileio.c
+++ b/src/nvim/os/fileio.c
@@ -16,6 +16,8 @@
#include "auto/config.h"
#include "nvim/gettext.h"
+#include "nvim/globals.h"
+#include "nvim/log.h"
#include "nvim/macros.h"
#include "nvim/memory.h"
#include "nvim/message.h"
diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c
index e0449d468a..6157341ec9 100644
--- a/src/nvim/os/fs.c
+++ b/src/nvim/os/fs.c
@@ -146,11 +146,7 @@ bool os_isdir(const char *name)
return false;
}
- if (!S_ISDIR(mode)) {
- return false;
- }
-
- return true;
+ return S_ISDIR(mode);
}
/// Check what `name` is:
@@ -302,7 +298,9 @@ static bool is_executable(const char *name, char **abspath)
static bool is_executable_ext(const char *name, char **abspath)
FUNC_ATTR_NONNULL_ARG(1)
{
- const bool is_unix_shell = strstr((char *)path_tail(p_sh), "sh") != NULL;
+ const bool is_unix_shell = strstr(path_tail(p_sh), "powershell") == NULL
+ && strstr(path_tail(p_sh), "pwsh") == NULL
+ && strstr(path_tail(p_sh), "sh") != NULL;
char *nameext = strrchr(name, '.');
size_t nameext_len = nameext ? strlen(nameext) : 0;
xstrlcpy(os_buf, name, sizeof(os_buf));
@@ -328,11 +326,11 @@ static bool is_executable_ext(const char *name, char **abspath)
const char *ext_end = ext;
size_t ext_len =
- copy_option_part(&ext_end, (char_u *)buf_end,
+ copy_option_part((char **)&ext_end, buf_end,
sizeof(os_buf) - (size_t)(buf_end - os_buf), ENV_SEPSTR);
if (ext_len != 0) {
bool in_pathext = nameext_len == ext_len
- && 0 == mb_strnicmp((char_u *)nameext, (char_u *)ext, ext_len);
+ && 0 == mb_strnicmp(nameext, ext, ext_len);
if (((in_pathext || is_unix_shell) && is_executable(name, abspath))
|| is_executable(os_buf, abspath)) {
@@ -789,14 +787,14 @@ int os_setperm(const char *const name, int perm)
// Return a pointer to the ACL of file "fname" in allocated memory.
// Return NULL if the ACL is not available for whatever reason.
-vim_acl_T os_get_acl(const char_u *fname)
+vim_acl_T os_get_acl(const char *fname)
{
vim_acl_T ret = NULL;
return ret;
}
// Set the ACL of file "fname" to "acl" (unless it's NULL).
-void os_set_acl(const char_u *fname, vim_acl_T aclent)
+void os_set_acl(const char *fname, vim_acl_T aclent)
{
if (aclent == NULL) {
return;
@@ -912,12 +910,11 @@ int os_file_is_writable(const char *name)
/// Rename a file or directory.
///
/// @return `OK` for success, `FAIL` for failure.
-int os_rename(const char_u *path, const char_u *new_path)
+int os_rename(const char *path, const char *new_path)
FUNC_ATTR_NONNULL_ALL
{
int r;
- RUN_UV_FS_FUNC(r, uv_fs_rename, (const char *)path, (const char *)new_path,
- NULL);
+ RUN_UV_FS_FUNC(r, uv_fs_rename, path, new_path, NULL);
return (r == kLibuvSuccess ? OK : FAIL);
}
@@ -1380,7 +1377,7 @@ bool os_is_reparse_point_include(const char *path)
}
p = utf16_path;
- if (isalpha(p[0]) && p[1] == L':' && IS_PATH_SEP(p[2])) {
+ if (isalpha((uint8_t)p[0]) && p[1] == L':' && IS_PATH_SEP(p[2])) {
p += 3;
} else if (IS_PATH_SEP(p[0]) && IS_PATH_SEP(p[1])) {
p += 2;
diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c
index 5d2ac1e102..759b3cf83c 100644
--- a/src/nvim/os/input.c
+++ b/src/nvim/os/input.c
@@ -44,7 +44,6 @@ typedef enum {
static Stream read_stream = { .closed = true }; // Input before UI starts.
static RBuffer *input_buffer = NULL;
static bool input_eof = false;
-static int global_fd = -1;
static bool blocking = false;
static int cursorhold_time = 0; ///< time waiting for CursorHold event
static int cursorhold_tb_change_cnt = 0; ///< tb_change_cnt when waiting started
@@ -58,25 +57,14 @@ void input_init(void)
input_buffer = rbuffer_new(INPUT_BUFFER_SIZE + MAX_KEY_CODE_LEN);
}
-void input_global_fd_init(int fd)
-{
- global_fd = fd;
-}
-
-/// Global TTY (or pipe for "-es") input stream, before UI starts.
-int input_global_fd(void)
-{
- return global_fd;
-}
-
-void input_start(int fd)
+void input_start(void)
{
if (!read_stream.closed) {
return;
}
- input_global_fd_init(fd);
- rstream_init_fd(&main_loop, &read_stream, fd, READ_BUFFER_SIZE);
+ used_stdin = true;
+ rstream_init_fd(&main_loop, &read_stream, STDIN_FILENO, READ_BUFFER_SIZE);
rstream_start(&read_stream, input_read_cb, NULL);
}
@@ -266,7 +254,8 @@ size_t input_enqueue(String keys)
uint8_t buf[19] = { 0 };
// Do not simplify the keys here. Simplification will be done later.
unsigned int new_size
- = trans_special((const char **)&ptr, (size_t)(end - ptr), buf, FSK_KEYCODE, true, NULL);
+ = trans_special((const char **)&ptr, (size_t)(end - ptr), (char *)buf, FSK_KEYCODE, true,
+ NULL);
if (new_size) {
new_size = handle_mouse_event(&ptr, buf, new_size);
diff --git a/src/nvim/os/input.h b/src/nvim/os/input.h
index 7026781407..6f25efdc7b 100644
--- a/src/nvim/os/input.h
+++ b/src/nvim/os/input.h
@@ -7,6 +7,8 @@
#include "nvim/api/private/defs.h"
#include "nvim/event/multiqueue.h"
+EXTERN bool used_stdin INIT(= false);
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/input.h.generated.h"
#endif
diff --git a/src/nvim/os/nvim.manifest b/src/nvim/os/nvim.manifest
new file mode 100644
index 0000000000..8878822a5d
--- /dev/null
+++ b/src/nvim/os/nvim.manifest
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
+ <assemblyIdentity
+ processorArchitecture="*"
+ version="0.9.0.0"
+ type="win32"
+ name="Neovim"
+ />
+ <description>Neovim</description>
+ <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+ <application>
+ <!-- Windows 10 and Windows 11 -->
+ <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
+ <!-- Windows 8.1 -->
+ <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
+ <!-- Windows 8 -->
+ <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
+ </application>
+ </compatibility>
+</assembly>
diff --git a/src/nvim/os/os_win_console.c b/src/nvim/os/os_win_console.c
index ec0f03a1dc..006e27d28f 100644
--- a/src/nvim/os/os_win_console.c
+++ b/src/nvim/os/os_win_console.c
@@ -10,11 +10,12 @@
# include "os/os_win_console.c.generated.h"
#endif
+static char origTitle[256] = { 0 };
static HWND hWnd = NULL;
static HICON hOrigIconSmall = NULL;
static HICON hOrigIcon = NULL;
-int os_get_conin_fd(void)
+int os_open_conin_fd(void)
{
const HANDLE conin_handle = CreateFile("CONIN$",
GENERIC_READ | GENERIC_WRITE,
@@ -30,7 +31,7 @@ int os_get_conin_fd(void)
void os_replace_stdin_to_conin(void)
{
close(STDIN_FILENO);
- const int conin_fd = os_get_conin_fd();
+ const int conin_fd = os_open_conin_fd();
assert(conin_fd == STDIN_FILENO);
}
@@ -92,3 +93,15 @@ void os_icon_init(void)
}
}
}
+
+/// Saves the original Windows console title.
+void os_title_save(void)
+{
+ GetConsoleTitle(origTitle, sizeof(origTitle));
+}
+
+/// Resets the original Windows console title.
+void os_title_reset(void)
+{
+ SetConsoleTitle(origTitle);
+}
diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c
index 8177f06c64..f1e2c5440f 100644
--- a/src/nvim/os/shell.c
+++ b/src/nvim/os/shell.c
@@ -221,7 +221,7 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in
// "command" below.
len++; // add space
for (j = 0; pat[i][j] != NUL; j++) {
- if (vim_strchr(SHELL_SPECIAL, pat[i][j]) != NULL) {
+ if (vim_strchr(SHELL_SPECIAL, (uint8_t)pat[i][j]) != NULL) {
len++; // may add a backslash
}
len++;
@@ -304,14 +304,14 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in
// backslash inside backticks, before a special character
// and before a backtick.
if (intick
- || vim_strchr(SHELL_SPECIAL, pat[i][j + 1]) != NULL
+ || vim_strchr(SHELL_SPECIAL, (uint8_t)pat[i][j + 1]) != NULL
|| pat[i][j + 1] == '`') {
*p++ = '\\';
}
j++;
} else if (!intick
&& ((flags & EW_KEEPDOLLAR) == 0 || pat[i][j] != '$')
- && vim_strchr(SHELL_SPECIAL, pat[i][j]) != NULL) {
+ && vim_strchr(SHELL_SPECIAL, (uint8_t)pat[i][j]) != NULL) {
// Put a backslash before a special character, but not
// when inside ``. And not for $var when EW_KEEPDOLLAR is
// set.
@@ -570,7 +570,7 @@ notfound:
char **shell_build_argv(const char *cmd, const char *extra_args)
FUNC_ATTR_NONNULL_RET
{
- size_t argc = tokenize(p_sh, NULL) + (cmd ? tokenize((char *)p_shcf, NULL) : 0);
+ size_t argc = tokenize(p_sh, NULL) + (cmd ? tokenize(p_shcf, NULL) : 0);
char **rv = xmalloc((argc + 4) * sizeof(*rv));
// Split 'shell'
@@ -581,7 +581,7 @@ char **shell_build_argv(const char *cmd, const char *extra_args)
}
if (cmd) {
- i += tokenize((char *)p_shcf, rv + i); // Split 'shellcmdflag'
+ i += tokenize(p_shcf, rv + i); // Split 'shellcmdflag'
rv[i++] = shell_xescape_xquote(cmd); // Copy (and escape) `cmd`.
}
@@ -1332,7 +1332,7 @@ static char *shell_xescape_xquote(const char *cmd)
const char *ecmd = cmd;
if (*p_sxe != NUL && strcmp(p_sxq, "(") == 0) {
- ecmd = vim_strsave_escaped_ext(cmd, (char *)p_sxe, '^', false);
+ ecmd = vim_strsave_escaped_ext(cmd, p_sxe, '^', false);
}
size_t ncmd_size = strlen(ecmd) + strlen(p_sxq) * 2 + 1;
char *ncmd = xmalloc(ncmd_size);
diff --git a/src/nvim/os/stdpaths.c b/src/nvim/os/stdpaths.c
index a99a8d25ce..6b07b6ef70 100644
--- a/src/nvim/os/stdpaths.c
+++ b/src/nvim/os/stdpaths.c
@@ -121,7 +121,7 @@ char *get_xdg_home(const XDGVarType idx)
#endif
#ifdef BACKSLASH_IN_FILENAME
- slash_adjust((char_u *)dir);
+ slash_adjust(dir);
#endif
}
return dir;
diff --git a/src/nvim/path.c b/src/nvim/path.c
index 9350335e54..e4c2253357 100644
--- a/src/nvim/path.c
+++ b/src/nvim/path.c
@@ -6,6 +6,7 @@
#include <limits.h>
#include <stdbool.h>
#include <stddef.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -154,7 +155,7 @@ char *path_tail_with_sep(char *fname)
/// @post if `len` is not null, stores the length of the executable name.
///
/// @return The position of the last path separator + 1.
-const char_u *invocation_path_tail(const char *invocation, size_t *len)
+const char *invocation_path_tail(const char *invocation, size_t *len)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_NONNULL_ARG(1)
{
const char *tail = get_past_head(invocation);
@@ -171,7 +172,7 @@ const char_u *invocation_path_tail(const char *invocation, size_t *len)
*len = (size_t)(p - tail);
}
- return (char_u *)tail;
+ return tail;
}
/// Get the next path component of a path name.
@@ -210,10 +211,10 @@ int path_head_length(void)
/// @return
/// - True if path begins with a path head
/// - False otherwise
-bool is_path_head(const char_u *path)
+bool is_path_head(const char *path)
{
#ifdef MSWIN
- return isalpha(path[0]) && path[1] == ':';
+ return isalpha((uint8_t)path[0]) && path[1] == ':';
#else
return vim_ispathsep(*path);
#endif
@@ -228,7 +229,7 @@ char *get_past_head(const char *path)
#ifdef MSWIN
// May skip "c:"
- if (is_path_head((char_u *)path)) {
+ if (is_path_head(path)) {
retval = path + 2;
}
#endif
@@ -510,7 +511,7 @@ char *FullName_save(const char *fname, bool force)
char *save_abs_path(const char *name)
FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL
{
- if (!path_is_absolute((char_u *)name)) {
+ if (!path_is_absolute(name)) {
return FullName_save(name, true);
}
return xstrdup(name);
@@ -535,7 +536,7 @@ bool path_has_wildcard(const char *p)
// Windows:
const char *wildcards = "?*$[`";
#endif
- if (vim_strchr(wildcards, *p) != NULL
+ if (vim_strchr(wildcards, (uint8_t)(*p)) != NULL
|| (p[0] == '~' && p[1] != NUL)) {
return true;
}
@@ -648,7 +649,7 @@ static size_t do_path_expand(garray_T *gap, const char *path, size_t wildoff, in
}
s = p + 1;
} else if (path_end >= path + wildoff
- && (vim_strchr("*?[{~$", *path_end) != NULL
+ && (vim_strchr("*?[{~$", (uint8_t)(*path_end)) != NULL
#ifndef MSWIN
|| (!p_fic && (flags & EW_ICASE) && mb_isalpha(utf_ptr2char((char *)path_end)))
#endif
@@ -782,8 +783,8 @@ static size_t do_path_expand(garray_T *gap, const char *path, size_t wildoff, in
// slow, thus skip it.
size_t matches = (size_t)(gap->ga_len - start_len);
if (matches > 0 && !got_int) {
- qsort(((char_u **)gap->ga_data) + start_len, matches,
- sizeof(char_u *), pstrcmp);
+ qsort(((char **)gap->ga_data) + start_len, matches,
+ sizeof(char *), pstrcmp);
}
return matches;
}
@@ -841,11 +842,11 @@ static bool is_unique(char *maybe_unique, garray_T *gap, int i)
// expanding each into their equivalent path(s).
static void expand_path_option(char *curdir, garray_T *gap)
{
- char_u *path_option = *curbuf->b_p_path == NUL ? p_path : (char_u *)curbuf->b_p_path;
+ char *path_option = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path;
char *buf = xmalloc(MAXPATHL);
while (*path_option != NUL) {
- copy_option_part((char **)&path_option, buf, MAXPATHL, " ,");
+ copy_option_part(&path_option, buf, MAXPATHL, " ,");
if (buf[0] == '.' && (buf[1] == NUL || vim_ispathsep(buf[1]))) {
// Relative to current buffer:
@@ -870,7 +871,7 @@ static void expand_path_option(char *curdir, garray_T *gap)
STRCPY(buf, curdir); // relative to current directory
} else if (path_with_url(buf)) {
continue; // URL can't be used here
- } else if (!path_is_absolute((char_u *)buf)) {
+ } else if (!path_is_absolute(buf)) {
// Expand relative path to their full path equivalent
size_t len = strlen(curdir);
if (len + strlen(buf) + 3 > MAXPATHL) {
@@ -894,11 +895,11 @@ static void expand_path_option(char *curdir, garray_T *gap)
// path: /foo/bar/baz
// fname: /foo/bar/baz/quux.txt
// returns: ^this
-static char_u *get_path_cutoff(char_u *fname, garray_T *gap)
+static char *get_path_cutoff(char *fname, garray_T *gap)
{
int maxlen = 0;
- char_u **path_part = (char_u **)gap->ga_data;
- char_u *cutoff = NULL;
+ char **path_part = gap->ga_data;
+ char *cutoff = NULL;
for (int i = 0; i < gap->ga_len; i++) {
int j = 0;
@@ -984,7 +985,7 @@ static void uniquefy_paths(garray_T *gap, char *pattern)
}
// Shorten the filename while maintaining its uniqueness
- path_cutoff = (char *)get_path_cutoff((char_u *)path, &path_ga);
+ path_cutoff = get_path_cutoff(path, &path_ga);
// Don't assume all files can be reached without path when search
// pattern starts with **/, so only remove path_cutoff
@@ -1011,7 +1012,7 @@ static void uniquefy_paths(garray_T *gap, char *pattern)
}
}
- if (path_is_absolute((char_u *)path)) {
+ if (path_is_absolute(path)) {
// Last resort: shorten relative to curdir if possible.
// 'possible' means:
// 1. It is under the current directory.
@@ -1127,7 +1128,7 @@ static int expand_in_path(garray_T *const gap, char *const pattern, const int fl
return 0;
}
- char *const paths = (char *)ga_concat_strings(&path_ga);
+ char *const paths = ga_concat_strings(&path_ga);
ga_clear_strings(&path_ga);
int glob_flags = 0;
@@ -1137,7 +1138,7 @@ static int expand_in_path(garray_T *const gap, char *const pattern, const int fl
if (flags & EW_ADDSLASH) {
glob_flags |= WILD_ADD_SLASH;
}
- globpath(paths, pattern, gap, glob_flags);
+ globpath(paths, pattern, gap, glob_flags, false);
xfree(paths);
return gap->ga_len;
@@ -1145,12 +1146,12 @@ static int expand_in_path(garray_T *const gap, char *const pattern, const int fl
/// Return true if "p" contains what looks like an environment variable.
/// Allowing for escaping.
-static bool has_env_var(char_u *p)
+static bool has_env_var(char *p)
{
for (; *p; MB_PTR_ADV(p)) {
if (*p == '\\' && p[1] != NUL) {
p++;
- } else if (vim_strchr("$", *p) != NULL) {
+ } else if (vim_strchr("$", (uint8_t)(*p)) != NULL) {
return true;
}
}
@@ -1161,7 +1162,7 @@ static bool has_env_var(char_u *p)
// Return true if "p" contains a special wildcard character, one that Vim
// cannot expand, requires using a shell.
-static bool has_special_wildchar(char_u *p)
+static bool has_special_wildchar(char *p)
{
for (; *p; MB_PTR_ADV(p)) {
// Disallow line break characters.
@@ -1171,13 +1172,13 @@ static bool has_special_wildchar(char_u *p)
// Allow for escaping.
if (*p == '\\' && p[1] != NUL && p[1] != '\r' && p[1] != '\n') {
p++;
- } else if (vim_strchr(SPECIAL_WILDCHAR, *p) != NULL) {
+ } else if (vim_strchr(SPECIAL_WILDCHAR, (uint8_t)(*p)) != NULL) {
// A { must be followed by a matching }.
- if (*p == '{' && vim_strchr((char *)p, '}') == NULL) {
+ if (*p == '{' && vim_strchr(p, '}') == NULL) {
continue;
}
// A quote and backtick must be followed by another one.
- if ((*p == '`' || *p == '\'') && vim_strchr((char *)p, *p) == NULL) {
+ if ((*p == '`' || *p == '\'') && vim_strchr(p, (uint8_t)(*p)) == NULL) {
continue;
}
return true;
@@ -1231,7 +1232,7 @@ int gen_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, i
// avoids starting the shell for each argument separately.
// For `=expr` do use the internal function.
for (int i = 0; i < num_pat; i++) {
- if (has_special_wildchar((char_u *)pat[i])
+ if (has_special_wildchar(pat[i])
&& !(vim_backtick(pat[i]) && pat[i][1] == '=')) {
return os_expand_wildcards(num_pat, pat, num_file, file, flags);
}
@@ -1258,8 +1259,8 @@ int gen_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, i
}
} else {
// First expand environment variables, "~/" and "~user/".
- if ((has_env_var((char_u *)p) && !(flags & EW_NOTENV)) || *p == '~') {
- p = (char *)expand_env_save_opt(p, true);
+ if ((has_env_var(p) && !(flags & EW_NOTENV)) || *p == '~') {
+ p = expand_env_save_opt(p, true);
if (p == NULL) {
p = pat[i];
} else {
@@ -1267,7 +1268,7 @@ int gen_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, i
// On Unix, if expand_env() can't expand an environment
// variable, use the shell to do that. Discard previously
// found file names and start all over again.
- if (has_env_var((char_u *)p) || *p == '~') {
+ if (has_env_var(p) || *p == '~') {
xfree(p);
ga_clear_strings(&ga);
i = os_expand_wildcards(num_pat, pat, num_file, file,
@@ -1286,7 +1287,7 @@ int gen_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, i
// given.
if (path_has_exp_wildcard(p) || (flags & EW_ICASE)) {
if ((flags & EW_PATH)
- && !path_is_absolute((char_u *)p)
+ && !path_is_absolute(p)
&& !(p[0] == '.'
&& (vim_ispathsep(p[1])
|| (p[1] == '.'
@@ -1413,9 +1414,9 @@ static int expand_backtick(garray_T *gap, char *pat, int flags)
/// backslash twice.
/// When 'shellslash' set do it the other way around.
/// When the path looks like a URL leave it unmodified.
-void slash_adjust(char_u *p)
+void slash_adjust(char *p)
{
- if (path_with_url((const char *)p)) {
+ if (path_with_url(p)) {
return;
}
@@ -1428,8 +1429,8 @@ void slash_adjust(char_u *p)
}
while (*p) {
- if (*p == (char_u)psepcN) {
- *p = (char_u)psepc;
+ if (*p == psepcN) {
+ *p = psepc;
}
MB_PTR_ADV(p);
}
@@ -1460,7 +1461,7 @@ void addfile(garray_T *gap, char *f, int flags)
#ifdef FNAME_ILLEGAL
// if the file/dir contains illegal characters, don't add it
- if (strpbrk((char *)f, FNAME_ILLEGAL) != NULL) {
+ if (strpbrk(f, FNAME_ILLEGAL) != NULL) {
return;
}
#endif
@@ -1477,7 +1478,7 @@ void addfile(garray_T *gap, char *f, int flags)
return;
}
- char_u *p = xmalloc(strlen(f) + 1 + isdir);
+ char *p = xmalloc(strlen(f) + 1 + isdir);
STRCPY(p, f);
#ifdef BACKSLASH_IN_FILENAME
@@ -1485,9 +1486,9 @@ void addfile(garray_T *gap, char *f, int flags)
#endif
// Append a slash or backslash after directory names if none is present.
if (isdir && (flags & EW_ADDSLASH)) {
- add_pathsep((char *)p);
+ add_pathsep(p);
}
- GA_APPEND(char_u *, gap, p);
+ GA_APPEND(char *, gap, p);
}
// Converts a file name into a canonical form. It simplifies a file name into
@@ -1689,8 +1690,8 @@ char *find_file_name_in_path(char *ptr, size_t len, int options, long count, cha
}
if (options & FNAME_EXP) {
- file_name = (char *)find_file_in_path(ptr, len, options & ~FNAME_MESS, true,
- rel_fname);
+ file_name = find_file_in_path(ptr, len, options & ~FNAME_MESS, true,
+ rel_fname);
// If the file could not be found in a normal way, try applying
// 'includeexpr' (unless done already).
@@ -1700,8 +1701,8 @@ char *find_file_name_in_path(char *ptr, size_t len, int options, long count, cha
if (tofree != NULL) {
ptr = tofree;
len = strlen(ptr);
- file_name = (char *)find_file_in_path(ptr, len, options & ~FNAME_MESS,
- true, rel_fname);
+ file_name = find_file_in_path(ptr, len, options & ~FNAME_MESS,
+ true, rel_fname);
}
}
if (file_name == NULL && (options & FNAME_MESS)) {
@@ -1716,7 +1717,7 @@ char *find_file_name_in_path(char *ptr, size_t len, int options, long count, cha
while (file_name != NULL && --count > 0) {
xfree(file_name);
file_name =
- (char *)find_file_in_path(ptr, len, options, false, rel_fname);
+ find_file_in_path(ptr, len, options, false, rel_fname);
}
} else {
file_name = xstrnsave(ptr, len);
@@ -1767,7 +1768,7 @@ int path_with_url(const char *fname)
// non-URL text.
// first character must be alpha
- if (!isalpha(*fname)) {
+ if (!ASCII_ISALPHA(*fname)) {
return 0;
}
@@ -1776,7 +1777,7 @@ int path_with_url(const char *fname)
}
// check body: alpha or dash
- for (p = fname + 1; (isalpha(*p) || (*p == '-')); p++) {}
+ for (p = fname + 1; (ASCII_ISALPHA(*p) || (*p == '-')); p++) {}
// check last char is not a dash
if (p[-1] == '-') {
@@ -1799,7 +1800,7 @@ bool path_with_extension(const char *path, const char *extension)
/// Return true if "name" is a full (absolute) path name or URL.
bool vim_isAbsName(char *name)
{
- return path_with_url(name) != 0 || path_is_absolute((char_u *)name);
+ return path_with_url(name) != 0 || path_is_absolute(name);
}
/// Save absolute file name to "buf[len]".
@@ -1823,7 +1824,7 @@ int vim_FullName(const char *fname, char *buf, size_t len, bool force)
if (strlen(fname) > (len - 1)) {
xstrlcpy(buf, fname, len); // truncate
#ifdef MSWIN
- slash_adjust((char_u *)buf);
+ slash_adjust(buf);
#endif
return FAIL;
}
@@ -1838,7 +1839,7 @@ int vim_FullName(const char *fname, char *buf, size_t len, bool force)
xstrlcpy(buf, fname, len); // something failed; use the filename
}
#ifdef MSWIN
- slash_adjust((char_u *)buf);
+ slash_adjust(buf);
#endif
return rv;
}
@@ -1858,7 +1859,7 @@ char *fix_fname(const char *fname)
#ifdef UNIX
return FullName_save(fname, true);
#else
- if (!vim_isAbsName((char_u *)fname)
+ if (!vim_isAbsName((char *)fname)
|| strstr(fname, "..") != NULL
|| strstr(fname, "//") != NULL
# ifdef BACKSLASH_IN_FILENAME
@@ -2075,7 +2076,7 @@ char *path_shorten_fname(char *full_path, char *dir_name)
size_t len = strlen(dir_name);
// If dir_name is a path head, full_path can always be made relative.
- if (len == (size_t)path_head_length() && is_path_head((char_u *)dir_name)) {
+ if (len == (size_t)path_head_length() && is_path_head(dir_name)) {
return full_path + len;
}
@@ -2123,9 +2124,9 @@ int expand_wildcards_eval(char **pat, int *num_file, char ***file, int flags)
if (is_cur_alt_file || *exp_pat == '<') {
emsg_off++;
- eval_pat = (char *)eval_vars((char_u *)exp_pat, (char_u *)exp_pat, &usedlen, NULL, &ignored_msg,
- NULL,
- true);
+ eval_pat = eval_vars(exp_pat, exp_pat, &usedlen, NULL, &ignored_msg,
+ NULL,
+ true);
emsg_off--;
if (eval_pat != NULL) {
star_follows = strcmp(exp_pat + usedlen, "*") == 0;
@@ -2185,15 +2186,15 @@ int expand_wildcards(int num_pat, char **pat, int *num_files, char ***files, int
// Remove names that match 'wildignore'.
if (*p_wig) {
- char_u *ffname;
+ char *ffname;
// check all files in (*files)[]
assert(*num_files == 0 || *files != NULL);
for (i = 0; i < *num_files; i++) {
- ffname = (char_u *)FullName_save((*files)[i], false);
+ ffname = FullName_save((*files)[i], false);
assert((*files)[i] != NULL);
assert(ffname != NULL);
- if (match_file_list((char_u *)p_wig, (char_u *)(*files)[i], ffname)) {
+ if (match_file_list(p_wig, (*files)[i], ffname)) {
// remove this matching file from the list
xfree((*files)[i]);
for (j = i; j + 1 < *num_files; j++) {
@@ -2240,7 +2241,7 @@ int match_suffix(char *fname)
size_t fnamelen = strlen(fname);
size_t setsuflen = 0;
- for (char *setsuf = (char *)p_su; *setsuf;) {
+ for (char *setsuf = p_su; *setsuf;) {
setsuflen = copy_option_part(&setsuf, suf_buf, MAXSUFLEN, ".,");
if (setsuflen == 0) {
char *tail = path_tail(fname);
@@ -2290,7 +2291,7 @@ int path_full_dir_name(char *directory, char *buffer, size_t len)
// Path does not exist (yet). For a full path fail,
// will use the path as-is. For a relative path use
// the current directory and append the file name.
- if (path_is_absolute((const char_u *)directory)) {
+ if (path_is_absolute(directory)) {
// Do not return immediately since we may be in the wrong directory.
retval = FAIL;
} else {
@@ -2360,7 +2361,7 @@ static int path_to_absolute(const char *fname, char *buf, size_t len, int force)
char *end_of_path = (char *)fname;
// expand it if forced or not an absolute path
- if (force || !path_is_absolute((char_u *)fname)) {
+ if (force || !path_is_absolute(fname)) {
p = strrchr(fname, '/');
#ifdef MSWIN
if (p == NULL) {
@@ -2389,14 +2390,14 @@ static int path_to_absolute(const char *fname, char *buf, size_t len, int force)
/// Check if file `fname` is a full (absolute) path.
///
/// @return `true` if "fname" is absolute.
-int path_is_absolute(const char_u *fname)
+int path_is_absolute(const char *fname)
{
#ifdef MSWIN
if (*fname == NUL) {
return false;
}
// A name like "d:/foo" and "//server/share" is absolute
- return ((isalpha(fname[0]) && fname[1] == ':' && vim_ispathsep_nocolon(fname[2]))
+ return ((isalpha((uint8_t)fname[0]) && fname[1] == ':' && vim_ispathsep_nocolon(fname[2]))
|| (vim_ispathsep_nocolon(fname[0]) && fname[0] == fname[1]));
#else
// UNIX: This just checks if the file name starts with '/' or '~'.
@@ -2416,7 +2417,7 @@ void path_guess_exepath(const char *argv0, char *buf, size_t bufsize)
{
const char *path = os_getenv("PATH");
- if (path == NULL || path_is_absolute((char_u *)argv0)) {
+ if (path == NULL || path_is_absolute(argv0)) {
xstrlcpy(buf, argv0, bufsize);
} else if (argv0[0] == '.' || strchr(argv0, PATHSEP)) {
// Relative to CWD.
diff --git a/src/nvim/plines.c b/src/nvim/plines.c
index e4d1ddf8d8..5469d94800 100644
--- a/src/nvim/plines.c
+++ b/src/nvim/plines.c
@@ -23,7 +23,6 @@
#include "nvim/option.h"
#include "nvim/plines.h"
#include "nvim/pos.h"
-#include "nvim/types.h"
#include "nvim/vim.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -52,7 +51,7 @@ int plines_win(win_T *wp, linenr_T lnum, bool winheight)
/// @return Number of filler lines above lnum
int win_get_fill(win_T *wp, linenr_T lnum)
{
- int virt_lines = decor_virt_lines(wp, lnum, NULL);
+ int virt_lines = decor_virt_lines(wp, lnum, NULL, kNone);
// be quick when there are no filler lines
if (diffopt_filler()) {
@@ -441,7 +440,7 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
// Set *headp to the size of what we add.
// Do not use 'showbreak' at the NUL after the text.
added = 0;
- char *const sbr = c == NUL ? empty_option : (char *)get_showbreak_value(wp);
+ char *const sbr = c == NUL ? empty_option : get_showbreak_value(wp);
if ((*sbr != NUL || wp->w_p_bri) && wp->w_p_wrap && vcol != 0) {
colnr_T sbrlen = 0;
int numberwidth = win_col_off(wp);
diff --git a/src/nvim/po/tr.po b/src/nvim/po/tr.po
index 7d6af4d2cf..eb7879efc4 100644
--- a/src/nvim/po/tr.po
+++ b/src/nvim/po/tr.po
@@ -5625,9 +5625,6 @@ msgstr "$VIMRUNTIME öntanımlı konumu: \""
msgid "Nvim is open source and freely distributable"
msgstr "Nvim açık kaynaklıdır ve özgürce dağıtılabilir"
-msgid "https://neovim.io/#chat"
-msgstr "https://neovim.io/#chat"
-
msgid "type :help nvim<Enter> if you are new! "
msgstr "eğer yeniyseniz :help nvim<Enter> "
diff --git a/src/nvim/po/uk.po b/src/nvim/po/uk.po
index b521e37177..06f845f113 100644
--- a/src/nvim/po/uk.po
+++ b/src/nvim/po/uk.po
@@ -5550,9 +5550,6 @@ msgstr " заміна для $VIMRUNTIME: \""
msgid "Nvim is open source and freely distributable"
msgstr "Nvim — це відкрита й вільно розповсюджувана програма"
-msgid "https://neovim.io/#chat"
-msgstr "https://neovim.io/#chat"
-
msgid "type :help nvim<Enter> if you are new! "
msgstr ":help nvim<Enter> якщо ви вперше! "
diff --git a/src/nvim/po/zh_CN.UTF-8.po b/src/nvim/po/zh_CN.UTF-8.po
index 0606adcc37..af050823d3 100644
--- a/src/nvim/po/zh_CN.UTF-8.po
+++ b/src/nvim/po/zh_CN.UTF-8.po
@@ -19,7 +19,7 @@ msgstr ""
"Project-Id-Version: Vim(Simplified Chinese)\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-11-17 08:00+0800\n"
-"PO-Revision-Date: 2022-11-17 22:29+0800\n"
+"PO-Revision-Date: 2023-01-24 13:00+0800\n"
"Last-Translator: Sizhe Zhao <prc.zhao@outlook.com>\n"
"Language-Team: Simplified Chinese <i18n-translation@lists.linux.net.cn>\n"
"Language: zh_CN\n"
@@ -7248,17 +7248,13 @@ msgstr " $VIMRUNTIME 预设值: \""
msgid "Nvim is open source and freely distributable"
msgstr "Nvim 是可自由分发的开放源代码软件"
-#: ../version.c:2806
-msgid "https://neovim.io/#chat"
-msgstr ""
-
#: ../version.c:2808
msgid "type :help nvim<Enter> if you are new! "
-msgstr ""
+msgstr "输入 :help nvim<Enter> 了解 Neovim! "
#: ../version.c:2809
msgid "type :checkhealth<Enter> to optimize Nvim"
-msgstr ""
+msgstr "输入 :checkhealth<Enter> 优化 Neovim "
#: ../version.c:2810
msgid "type :q<Enter> to exit "
@@ -7266,11 +7262,12 @@ msgstr "输入 :q<Enter> 退出 "
#: ../version.c:2811
msgid "type :help<Enter> for help "
-msgstr ""
+msgstr "输入 :help<Enter> 查看帮助 "
#: ../version.c:2813
-msgid "type :help news<Enter> to see changes in"
-msgstr ""
+#, c-format
+msgid "type :help news<Enter> to see changes in v%s.%s"
+msgstr "输入 :help news<Enter> 查看 v%s.%s 的变化"
#: ../version.c:2816
msgid "Help poor children in Uganda!"
diff --git a/src/nvim/popupmenu.c b/src/nvim/popupmenu.c
index 1d55b2ef31..245ce87865 100644
--- a/src/nvim/popupmenu.c
+++ b/src/nvim/popupmenu.c
@@ -218,11 +218,16 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i
// pum above "pum_win_row"
pum_above = true;
- // Leave two lines of context if possible
- if (curwin->w_wrow - curwin->w_cline_row >= 2) {
- context_lines = 2;
+ if (State == MODE_CMDLINE) {
+ // for cmdline pum, no need for context lines
+ context_lines = 0;
} else {
- context_lines = curwin->w_wrow - curwin->w_cline_row;
+ // Leave two lines of context if possible
+ if (curwin->w_wrow - curwin->w_cline_row >= 2) {
+ context_lines = 2;
+ } else {
+ context_lines = curwin->w_wrow - curwin->w_cline_row;
+ }
}
if (pum_win_row >= size + context_lines) {
@@ -241,13 +246,17 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i
// pum below "pum_win_row"
pum_above = false;
- // Leave two lines of context if possible
- validate_cheight();
- if (curwin->w_cline_row + curwin->w_cline_height - curwin->w_wrow >= 3) {
- context_lines = 3;
+ if (State == MODE_CMDLINE) {
+ // for cmdline pum, no need for context lines
+ context_lines = 0;
} else {
- context_lines = curwin->w_cline_row
- + curwin->w_cline_height - curwin->w_wrow;
+ // Leave two lines of context if possible
+ validate_cheight();
+ if (curwin->w_cline_row + curwin->w_cline_height - curwin->w_wrow >= 3) {
+ context_lines = 3;
+ } else {
+ context_lines = curwin->w_cline_row + curwin->w_cline_height - curwin->w_wrow;
+ }
}
pum_row = pum_win_row + context_lines;
@@ -815,7 +824,7 @@ static bool pum_set_selected(int n, int repeat)
// When the preview window was resized we need to
// update the view on the buffer. Only go back to
// the window when needed, otherwise it will always be
- // redraw.
+ // redrawn.
if (resized) {
no_u_sync++;
win_enter(curwin_save, true);
@@ -878,6 +887,7 @@ void pum_check_clear(void)
grid_free(&pum_grid);
}
pum_is_drawn = false;
+ pum_external = false;
}
}
diff --git a/src/nvim/profile.c b/src/nvim/profile.c
index 866834fc71..fd024f2d38 100644
--- a/src/nvim/profile.c
+++ b/src/nvim/profile.c
@@ -299,7 +299,7 @@ void ex_profile(exarg_T *eap)
if (len == 5 && strncmp(eap->arg, "start", 5) == 0 && *e != NUL) {
xfree(profile_fname);
- profile_fname = (char *)expand_env_save_opt(e, true);
+ profile_fname = expand_env_save_opt(e, true);
do_profiling = PROF_YES;
profile_set_wait(profile_zero());
set_vim_var_nr(VV_PROFILING, 1L);
@@ -354,7 +354,6 @@ char *get_profile_name(expand_T *xp, int idx)
switch (pexpand_what) {
case PEXP_SUBCMD:
return pexpand_cmds[idx];
- // case PEXP_FUNC: TODO
default:
return NULL;
}
@@ -373,13 +372,17 @@ void set_context_in_profile_cmd(expand_T *xp, const char *arg)
return;
}
- if (end_subcmd - arg == 5 && strncmp(arg, "start", 5) == 0) {
+ if ((end_subcmd - arg == 5 && strncmp(arg, "start", 5) == 0)
+ || (end_subcmd - arg == 4 && strncmp(arg, "file", 4) == 0)) {
xp->xp_context = EXPAND_FILES;
xp->xp_pattern = skipwhite(end_subcmd);
return;
+ } else if (end_subcmd - arg == 4 && strncmp(arg, "func", 4) == 0) {
+ xp->xp_context = EXPAND_USER_FUNC;
+ xp->xp_pattern = skipwhite(end_subcmd);
+ return;
}
- // TODO(tarruda): expand function names after "func"
xp->xp_context = EXPAND_NOTHING;
}
@@ -700,17 +703,17 @@ void script_prof_save(proftime_T *tm)
/// Count time spent in children after invoking another script or function.
void script_prof_restore(const proftime_T *tm)
{
- scriptitem_T *si;
+ if (!SCRIPT_ID_VALID(current_sctx.sc_sid)) {
+ return;
+ }
- if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= script_items.ga_len) {
- si = &SCRIPT_ITEM(current_sctx.sc_sid);
- if (si->sn_prof_on && --si->sn_pr_nest == 0) {
- si->sn_pr_child = profile_end(si->sn_pr_child);
- // don't count wait time
- si->sn_pr_child = profile_sub_wait(*tm, si->sn_pr_child);
- si->sn_pr_children = profile_add(si->sn_pr_children, si->sn_pr_child);
- si->sn_prl_children = profile_add(si->sn_prl_children, si->sn_pr_child);
- }
+ scriptitem_T *si = &SCRIPT_ITEM(current_sctx.sc_sid);
+ if (si->sn_prof_on && --si->sn_pr_nest == 0) {
+ si->sn_pr_child = profile_end(si->sn_pr_child);
+ // don't count wait time
+ si->sn_pr_child = profile_sub_wait(*tm, si->sn_pr_child);
+ si->sn_pr_children = profile_add(si->sn_pr_children, si->sn_pr_child);
+ si->sn_prl_children = profile_add(si->sn_prl_children, si->sn_pr_child);
}
}
@@ -784,17 +787,17 @@ static void script_dump_profile(FILE *fd)
/// Dump the profiling info.
void profile_dump(void)
{
- FILE *fd;
+ if (profile_fname == NULL) {
+ return;
+ }
- if (profile_fname != NULL) {
- fd = os_fopen(profile_fname, "w");
- if (fd == NULL) {
- semsg(_(e_notopen), profile_fname);
- } else {
- script_dump_profile(fd);
- func_dump_profile(fd);
- fclose(fd);
- }
+ FILE *fd = os_fopen(profile_fname, "w");
+ if (fd == NULL) {
+ semsg(_(e_notopen), profile_fname);
+ } else {
+ script_dump_profile(fd);
+ func_dump_profile(fd);
+ fclose(fd);
}
}
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index c895ac16f1..5518fdfa51 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -384,9 +384,9 @@ static char *efmpat_to_regpat(const char *efmpat, char *regpat, efm_T *efminfo,
return NULL;
}
if ((idx && idx < FMT_PATTERN_R
- && vim_strchr("DXOPQ", efminfo->prefix) != NULL)
+ && vim_strchr("DXOPQ", (uint8_t)efminfo->prefix) != NULL)
|| (idx == FMT_PATTERN_R
- && vim_strchr("OPQ", efminfo->prefix) == NULL)) {
+ && vim_strchr("OPQ", (uint8_t)efminfo->prefix) == NULL)) {
semsg(_("E373: Unexpected %%%c in format string"), *efmpat);
return NULL;
}
@@ -468,10 +468,10 @@ static char *scanf_fmt_to_regpat(const char **pefmp, const char *efm, int len, c
static const char *efm_analyze_prefix(const char *efmp, efm_T *efminfo)
FUNC_ATTR_NONNULL_ALL
{
- if (vim_strchr("+-", *efmp) != NULL) {
+ if (vim_strchr("+-", (uint8_t)(*efmp)) != NULL) {
efminfo->flags = *efmp++;
}
- if (vim_strchr("DXAEWINCZGOPQ", *efmp) != NULL) {
+ if (vim_strchr("DXAEWINCZGOPQ", (uint8_t)(*efmp)) != NULL) {
efminfo->prefix = *efmp;
} else {
semsg(_("E376: Invalid %%%c in format string prefix"), *efmp);
@@ -510,7 +510,7 @@ static int efm_to_regpat(const char *efm, int len, efm_T *fmt_ptr, char *regpat)
if (ptr == NULL) {
return FAIL;
}
- } else if (vim_strchr("%\\.^$~[", *efmp) != NULL) {
+ } else if (vim_strchr("%\\.^$~[", (uint8_t)(*efmp)) != NULL) {
*ptr++ = *efmp; // regexp magic characters
} else if (*efmp == '#') {
*ptr++ = '*';
@@ -530,7 +530,7 @@ static int efm_to_regpat(const char *efm, int len, efm_T *fmt_ptr, char *regpat)
} else { // copy normal character
if (*efmp == '\\' && efmp + 1 < efm + len) {
efmp++;
- } else if (vim_strchr(".*^$~[", *efmp) != NULL) {
+ } else if (vim_strchr(".*^$~[", (uint8_t)(*efmp)) != NULL) {
*ptr++ = '\\'; // escape regexp atoms
}
if (*efmp) {
@@ -868,7 +868,7 @@ static int qf_get_nextline(qfstate_T *state)
#endif
}
- remove_bom((char_u *)state->linebuf);
+ remove_bom(state->linebuf);
return QF_OK;
}
@@ -925,7 +925,7 @@ restofline:
// match or no match.
fields->valid = true;
for (; fmt_ptr != NULL; fmt_ptr = fmt_ptr->next) {
- idx = (char_u)fmt_ptr->prefix;
+ idx = (uint8_t)fmt_ptr->prefix;
status = qf_parse_get_fields(linebuf, linelen, fmt_ptr, fields,
qfl->qf_multiline, qfl->qf_multiscan,
&tail);
@@ -1190,13 +1190,15 @@ static void qf_store_title(qf_list_T *qfl, const char *title)
{
XFREE_CLEAR(qfl->qf_title);
- if (title != NULL) {
- size_t len = strlen(title) + 1;
- char *p = xmallocz(len);
-
- qfl->qf_title = p;
- xstrlcpy(p, title, len + 1);
+ if (title == NULL) {
+ return;
}
+
+ size_t len = strlen(title) + 1;
+ char *p = xmallocz(len);
+
+ qfl->qf_title = p;
+ xstrlcpy(p, title, len + 1);
}
/// The title of a quickfix/location list is set, by default, to the command
@@ -1483,7 +1485,7 @@ static int qf_parse_match(char *linebuf, size_t linelen, efm_T *fmt_ptr, regmatc
if ((idx == 'C' || idx == 'Z') && !qf_multiline) {
return QF_FAIL;
}
- if (vim_strchr("EWIN", idx) != NULL) {
+ if (vim_strchr("EWIN", (uint8_t)idx) != NULL) {
fields->type = idx;
} else {
fields->type = 0;
@@ -1524,7 +1526,7 @@ static int qf_parse_match(char *linebuf, size_t linelen, efm_T *fmt_ptr, regmatc
static int qf_parse_get_fields(char *linebuf, size_t linelen, efm_T *fmt_ptr, qffields_T *fields,
int qf_multiline, int qf_multiscan, char **tail)
{
- if (qf_multiscan && vim_strchr("OPQ", fmt_ptr->prefix) == NULL) {
+ if (qf_multiscan && vim_strchr("OPQ", (uint8_t)fmt_ptr->prefix) == NULL) {
return QF_FAIL;
}
@@ -1684,14 +1686,16 @@ int qf_stack_get_bufnr(void)
static void wipe_qf_buffer(qf_info_T *qi)
FUNC_ATTR_NONNULL_ALL
{
- if (qi->qf_bufnr != INVALID_QFBUFNR) {
- buf_T *const qfbuf = buflist_findnr(qi->qf_bufnr);
- if (qfbuf != NULL && qfbuf->b_nwindows == 0) {
- // If the quickfix buffer is not loaded in any window, then
- // wipe the buffer.
- close_buffer(NULL, qfbuf, DOBUF_WIPE, false, false);
- qi->qf_bufnr = INVALID_QFBUFNR;
- }
+ if (qi->qf_bufnr == INVALID_QFBUFNR) {
+ return;
+ }
+
+ buf_T *const qfbuf = buflist_findnr(qi->qf_bufnr);
+ if (qfbuf != NULL && qfbuf->b_nwindows == 0) {
+ // If the quickfix buffer is not loaded in any window, then
+ // wipe the buffer.
+ close_buffer(NULL, qfbuf, DOBUF_WIPE, false, false);
+ qi->qf_bufnr = INVALID_QFBUFNR;
}
}
@@ -3168,15 +3172,15 @@ void qf_list(exarg_T *eap)
// Get the attributes for the different quickfix highlight items. Note
// that this depends on syntax items defined in the qf.vim syntax file
- qfFileAttr = syn_name2attr((char_u *)"qfFileName");
+ qfFileAttr = syn_name2attr("qfFileName");
if (qfFileAttr == 0) {
qfFileAttr = HL_ATTR(HLF_D);
}
- qfSepAttr = syn_name2attr((char_u *)"qfSeparator");
+ qfSepAttr = syn_name2attr("qfSeparator");
if (qfSepAttr == 0) {
qfSepAttr = HL_ATTR(HLF_D);
}
- qfLineAttr = syn_name2attr((char_u *)"qfLineNr");
+ qfLineAttr = syn_name2attr("qfLineNr");
if (qfLineAttr == 0) {
qfLineAttr = HL_ATTR(HLF_N);
}
@@ -3850,10 +3854,11 @@ static buf_T *qf_find_buf(qf_info_T *qi)
}
/// Process the 'quickfixtextfunc' option value.
-/// @return OK or FAIL
-int qf_process_qftf_option(void)
+void qf_process_qftf_option(char **errmsg)
{
- return option_set_callback_func(p_qftf, &qftf_cb);
+ if (option_set_callback_func(p_qftf, &qftf_cb) == FAIL) {
+ *errmsg = e_invarg;
+ }
}
/// Update the w:quickfix_title variable in the quickfix/location list window in
@@ -3878,59 +3883,61 @@ static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last)
{
// Check if a buffer for the quickfix list exists. Update it.
buf_T *buf = qf_find_buf(qi);
- if (buf != NULL) {
- linenr_T old_line_count = buf->b_ml.ml_line_count;
- int qf_winid = 0;
-
- win_T *win;
- if (IS_LL_STACK(qi)) {
- if (curwin->w_llist == qi) {
- win = curwin;
- } else {
- // Find the file window (non-quickfix) with this location list
- win = qf_find_win_with_loclist(qi);
- if (win == NULL) {
- // File window is not found. Find the location list window.
- win = qf_find_win(qi);
- }
- if (win == NULL) {
- return;
- }
+ if (buf == NULL) {
+ return;
+ }
+
+ linenr_T old_line_count = buf->b_ml.ml_line_count;
+ int qf_winid = 0;
+
+ win_T *win;
+ if (IS_LL_STACK(qi)) {
+ if (curwin->w_llist == qi) {
+ win = curwin;
+ } else {
+ // Find the file window (non-quickfix) with this location list
+ win = qf_find_win_with_loclist(qi);
+ if (win == NULL) {
+ // File window is not found. Find the location list window.
+ win = qf_find_win(qi);
+ }
+ if (win == NULL) {
+ return;
}
- qf_winid = (int)win->handle;
}
+ qf_winid = (int)win->handle;
+ }
- // autocommands may cause trouble
- incr_quickfix_busy();
-
- aco_save_T aco;
+ // autocommands may cause trouble
+ incr_quickfix_busy();
- if (old_last == NULL) {
- // set curwin/curbuf to buf and save a few things
- aucmd_prepbuf(&aco, buf);
- }
+ aco_save_T aco;
- qf_update_win_titlevar(qi);
+ if (old_last == NULL) {
+ // set curwin/curbuf to buf and save a few things
+ aucmd_prepbuf(&aco, buf);
+ }
- qf_fill_buffer(qf_get_curlist(qi), buf, old_last, qf_winid);
- buf_inc_changedtick(buf);
+ qf_update_win_titlevar(qi);
- if (old_last == NULL) {
- (void)qf_win_pos_update(qi, 0);
+ qf_fill_buffer(qf_get_curlist(qi), buf, old_last, qf_winid);
+ buf_inc_changedtick(buf);
- // restore curwin/curbuf and a few other things
- aucmd_restbuf(&aco);
- }
+ if (old_last == NULL) {
+ (void)qf_win_pos_update(qi, 0);
- // Only redraw when added lines are visible. This avoids flickering when
- // the added lines are not visible.
- if ((win = qf_find_win(qi)) != NULL && old_line_count < win->w_botline) {
- redraw_buf_later(buf, UPD_NOT_VALID);
- }
+ // restore curwin/curbuf and a few other things
+ aucmd_restbuf(&aco);
+ }
- // always called after incr_quickfix_busy()
- decr_quickfix_busy();
+ // Only redraw when added lines are visible. This avoids flickering when
+ // the added lines are not visible.
+ if ((win = qf_find_win(qi)) != NULL && old_line_count < win->w_botline) {
+ redraw_buf_later(buf, UPD_NOT_VALID);
}
+
+ // always called after incr_quickfix_busy()
+ decr_quickfix_busy();
}
// Add an error line to the quickfix buffer.
@@ -3959,11 +3966,11 @@ static int qf_buf_add_line(qf_list_T *qfl, buf_T *buf, linenr_T lnum, const qfli
// buffer.
if (first_bufline
&& (errbuf->b_sfname == NULL
- || path_is_absolute((char_u *)errbuf->b_sfname))) {
+ || path_is_absolute(errbuf->b_sfname))) {
if (*dirname == NUL) {
os_dirname(dirname, MAXPATHL);
}
- shorten_buf_fname(errbuf, (char_u *)dirname, false);
+ shorten_buf_fname(errbuf, dirname, false);
}
xstrlcpy(IObuff, errbuf->b_fname, IOSIZE);
}
@@ -3997,7 +4004,7 @@ static int qf_buf_add_line(qf_list_T *qfl, buf_T *buf, linenr_T lnum, const qfli
IObuff + len, IOSIZE - len);
}
- if (ml_append_buf(buf, lnum, (char_u *)IObuff,
+ if (ml_append_buf(buf, lnum, IObuff,
(colnr_T)strlen(IObuff) + 1, false) == FAIL) {
return FAIL;
}
@@ -4188,14 +4195,16 @@ static int qf_id2nr(const qf_info_T *const qi, const unsigned qfid)
static int qf_restore_list(qf_info_T *qi, unsigned save_qfid)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
- if (qf_get_curlist(qi)->qf_id != save_qfid) {
- const int curlist = qf_id2nr(qi, save_qfid);
- if (curlist < 0) {
- // list is not present
- return FAIL;
- }
- qi->qf_curlist = curlist;
+ if (qf_get_curlist(qi)->qf_id == save_qfid) {
+ return OK;
+ }
+
+ const int curlist = qf_id2nr(qi, save_qfid);
+ if (curlist < 0) {
+ // list is not present
+ return FAIL;
}
+ qi->qf_curlist = curlist;
return OK;
}
@@ -5040,8 +5049,8 @@ void ex_cfile(exarg_T *eap)
// first error.
// :caddfile adds to an existing quickfix list. If there is no
// quickfix list then a new list is created.
- int res = qf_init(wp, (char *)p_ef, p_efm, (eap->cmdidx != CMD_caddfile
- && eap->cmdidx != CMD_laddfile),
+ int res = qf_init(wp, p_ef, p_efm, (eap->cmdidx != CMD_caddfile
+ && eap->cmdidx != CMD_laddfile),
qf_cmdtitle(*eap->cmdlinep), enc);
if (wp != NULL) {
qi = GET_LOC_LIST(wp);
@@ -5105,7 +5114,7 @@ static void vgr_init_regmatch(regmmatch_T *regmatch, char *s)
emsg(_(e_noprevre));
return;
}
- regmatch->regprog = vim_regcomp((char *)last_search_pat(), RE_MAGIC);
+ regmatch->regprog = vim_regcomp(last_search_pat(), RE_MAGIC);
} else {
regmatch->regprog = vim_regcomp(s, RE_MAGIC);
}
@@ -5230,8 +5239,7 @@ static bool vgr_match_buflines(qf_list_T *qfl, char *fname, buf_T *buf, char *sp
const size_t sz = sizeof(matches) / sizeof(matches[0]);
// Fuzzy string match
- while (fuzzy_match((char_u *)str + col, (char_u *)spat, false, &score, matches,
- (int)sz) > 0) {
+ while (fuzzy_match(str + col, spat, false, &score, matches, (int)sz) > 0) {
// Pass the buffer number so that it gets used even for a
// dummy buffer, unless duplicate_name is set, then the
// buffer will be wiped out below.
@@ -5737,12 +5745,14 @@ static void wipe_dummy_buffer(buf_T *buf, char *dirname_start)
// 'autochdir' option have changed it.
static void unload_dummy_buffer(buf_T *buf, char *dirname_start)
{
- if (curbuf != buf) { // safety check
- close_buffer(NULL, buf, DOBUF_UNLOAD, false, true);
-
- // When autocommands/'autochdir' option changed directory: go back.
- restore_start_dir(dirname_start);
+ if (curbuf == buf) { // safety check
+ return;
}
+
+ close_buffer(NULL, buf, DOBUF_UNLOAD, false, true);
+
+ // When autocommands/'autochdir' option changed directory: go back.
+ restore_start_dir(dirname_start);
}
/// Copy the specified quickfix entry items into a new dict and append the dict
@@ -5867,32 +5877,34 @@ static int qf_get_list_from_lines(dict_T *what, dictitem_T *di, dict_T *retdict)
int status = FAIL;
// Only a List value is supported
- if (di->di_tv.v_type == VAR_LIST && di->di_tv.vval.v_list != NULL) {
- char *errorformat = p_efm;
- dictitem_T *efm_di;
- // If errorformat is supplied then use it, otherwise use the 'efm'
- // option setting
- if ((efm_di = tv_dict_find(what, S_LEN("efm"))) != NULL) {
- if (efm_di->di_tv.v_type != VAR_STRING
- || efm_di->di_tv.vval.v_string == NULL) {
- return FAIL;
- }
- errorformat = efm_di->di_tv.vval.v_string;
- }
-
- list_T *l = tv_list_alloc(kListLenMayKnow);
- qf_info_T *const qi = qf_alloc_stack(QFLT_INTERNAL);
+ if (di->di_tv.v_type != VAR_LIST || di->di_tv.vval.v_list == NULL) {
+ return FAIL;
+ }
- if (qf_init_ext(qi, 0, NULL, NULL, &di->di_tv, errorformat,
- true, (linenr_T)0, (linenr_T)0, NULL, NULL) > 0) {
- (void)get_errorlist(qi, NULL, 0, 0, l);
- qf_free(&qi->qf_lists[0]);
+ char *errorformat = p_efm;
+ dictitem_T *efm_di;
+ // If errorformat is supplied then use it, otherwise use the 'efm'
+ // option setting
+ if ((efm_di = tv_dict_find(what, S_LEN("efm"))) != NULL) {
+ if (efm_di->di_tv.v_type != VAR_STRING
+ || efm_di->di_tv.vval.v_string == NULL) {
+ return FAIL;
}
- xfree(qi);
+ errorformat = efm_di->di_tv.vval.v_string;
+ }
- tv_dict_add_list(retdict, S_LEN("items"), l);
- status = OK;
+ list_T *l = tv_list_alloc(kListLenMayKnow);
+ qf_info_T *const qi = qf_alloc_stack(QFLT_INTERNAL);
+
+ if (qf_init_ext(qi, 0, NULL, NULL, &di->di_tv, errorformat,
+ true, (linenr_T)0, (linenr_T)0, NULL, NULL) > 0) {
+ (void)get_errorlist(qi, NULL, 0, 0, l);
+ qf_free(&qi->qf_lists[0]);
}
+ xfree(qi);
+
+ tv_dict_add_list(retdict, S_LEN("items"), l);
+ status = OK;
return status;
}
@@ -6935,43 +6947,45 @@ void ex_cexpr(exarg_T *eap)
// Evaluate the expression. When the result is a string or a list we can
// use it to fill the errorlist.
typval_T tv;
- if (eval0(eap->arg, &tv, &eap->nextcmd, true) != FAIL) {
- if ((tv.v_type == VAR_STRING && tv.vval.v_string != NULL)
- || tv.v_type == VAR_LIST) {
- incr_quickfix_busy();
- int res = qf_init_ext(qi, qi->qf_curlist, NULL, NULL, &tv, p_efm,
- (eap->cmdidx != CMD_caddexpr
- && eap->cmdidx != CMD_laddexpr),
- (linenr_T)0, (linenr_T)0,
- qf_cmdtitle(*eap->cmdlinep), NULL);
- if (qf_stack_empty(qi)) {
- decr_quickfix_busy();
- goto cleanup;
- }
- if (res >= 0) {
- qf_list_changed(qf_get_curlist(qi));
- }
- // Remember the current quickfix list identifier, so that we can
- // check for autocommands changing the current quickfix list.
- unsigned save_qfid = qf_get_curlist(qi)->qf_id;
- if (au_name != NULL) {
- apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, curbuf->b_fname, true, curbuf);
- }
- // Jump to the first error for a new list and if autocmds didn't
- // free the list.
- if (res > 0
- && (eap->cmdidx == CMD_cexpr || eap->cmdidx == CMD_lexpr)
- && qflist_valid(wp, save_qfid)) {
- // display the first error
- qf_jump_first(qi, save_qfid, eap->forceit);
- }
+ if (eval0(eap->arg, &tv, &eap->nextcmd, true) == FAIL) {
+ return;
+ }
+
+ if ((tv.v_type == VAR_STRING && tv.vval.v_string != NULL)
+ || tv.v_type == VAR_LIST) {
+ incr_quickfix_busy();
+ int res = qf_init_ext(qi, qi->qf_curlist, NULL, NULL, &tv, p_efm,
+ (eap->cmdidx != CMD_caddexpr
+ && eap->cmdidx != CMD_laddexpr),
+ (linenr_T)0, (linenr_T)0,
+ qf_cmdtitle(*eap->cmdlinep), NULL);
+ if (qf_stack_empty(qi)) {
decr_quickfix_busy();
- } else {
- emsg(_("E777: String or List expected"));
+ goto cleanup;
}
-cleanup:
- tv_clear(&tv);
+ if (res >= 0) {
+ qf_list_changed(qf_get_curlist(qi));
+ }
+ // Remember the current quickfix list identifier, so that we can
+ // check for autocommands changing the current quickfix list.
+ unsigned save_qfid = qf_get_curlist(qi)->qf_id;
+ if (au_name != NULL) {
+ apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, curbuf->b_fname, true, curbuf);
+ }
+ // Jump to the first error for a new list and if autocmds didn't
+ // free the list.
+ if (res > 0
+ && (eap->cmdidx == CMD_cexpr || eap->cmdidx == CMD_lexpr)
+ && qflist_valid(wp, save_qfid)) {
+ // display the first error
+ qf_jump_first(qi, save_qfid, eap->forceit);
+ }
+ decr_quickfix_busy();
+ } else {
+ emsg(_("E777: String or List expected"));
}
+cleanup:
+ tv_clear(&tv);
}
// Get the location list for ":lhelpgrep"
diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c
index e396e54ced..122f3e2020 100644
--- a/src/nvim/regexp.c
+++ b/src/nvim/regexp.c
@@ -87,7 +87,7 @@ static int toggle_Magic(int x)
#define REGMAGIC 0234
// Utility definitions.
-#define UCHARAT(p) ((int)(*(char_u *)(p)))
+#define UCHARAT(p) ((int)(*(uint8_t *)(p)))
// Used for an error (down from) vim_regcomp(): give the error message, set
// rc_did_emsg and return NULL
@@ -327,7 +327,7 @@ static int reg_strict; // "[abc" is illegal
// uncrustify:off
// META[] is used often enough to justify turning it into a table.
-static char_u META_flags[] = {
+static uint8_t META_flags[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// % & ( ) * + .
@@ -361,7 +361,7 @@ static int nextchr; // used for ungetchr()
#define REG_NPAREN 3 // \%(\)
typedef struct {
- char_u *regparse;
+ char *regparse;
int prevchr_len;
int curchr;
int prevchr;
@@ -393,12 +393,12 @@ static int get_equi_class(char **pp)
{
int c;
int l = 1;
- char_u *p = (char_u *)(*pp);
+ char *p = *pp;
if (p[1] == '=' && p[2] != NUL) {
- l = utfc_ptr2len((char *)p + 2);
+ l = utfc_ptr2len(p + 2);
if (p[l + 2] == '=' && p[l + 3] == ']') {
- c = utf_ptr2char((char *)p + 2);
+ c = utf_ptr2char(p + 2);
*pp += l + 4;
return c;
}
@@ -414,12 +414,12 @@ static int get_coll_element(char **pp)
{
int c;
int l = 1;
- char_u *p = (char_u *)(*pp);
+ char *p = *pp;
if (p[0] != NUL && p[1] == '.' && p[2] != NUL) {
- l = utfc_ptr2len((char *)p + 2);
+ l = utfc_ptr2len(p + 2);
if (p[l + 2] == '.' && p[l + 3] == ']') {
- c = utf_ptr2char((char *)p + 2);
+ c = utf_ptr2char(p + 2);
*pp += l + 4;
return c;
}
@@ -437,7 +437,7 @@ static void get_cpo_flags(void)
/// Skip over a "[]" range.
/// "p" must point to the character after the '['.
/// The returned pointer is on the matching ']', or the terminating NUL.
-static char_u *skip_anyof(char *p)
+static char *skip_anyof(char *p)
{
int l;
@@ -456,9 +456,9 @@ static char_u *skip_anyof(char *p)
MB_PTR_ADV(p);
}
} else if (*p == '\\'
- && (vim_strchr(REGEXP_INRANGE, p[1]) != NULL
+ && (vim_strchr(REGEXP_INRANGE, (uint8_t)p[1]) != NULL
|| (!reg_cpo_lit
- && vim_strchr(REGEXP_ABBR, p[1]) != NULL))) {
+ && vim_strchr(REGEXP_ABBR, (uint8_t)p[1]) != NULL))) {
p += 2;
} else if (*p == '[') {
if (get_char_class(&p) == CLASS_NONE
@@ -472,7 +472,7 @@ static char_u *skip_anyof(char *p)
}
}
- return (char_u *)p;
+ return p;
}
/// Skip past regular expression.
@@ -522,7 +522,7 @@ char *skip_regexp_ex(char *startp, int dirc, int magic, char **newp, int *droppe
}
if ((p[0] == '[' && mymagic >= MAGIC_ON)
|| (p[0] == '\\' && p[1] == '[' && mymagic <= MAGIC_OFF)) {
- p = (char *)skip_anyof(p + 1);
+ p = skip_anyof(p + 1);
if (p[0] == NUL) {
break;
}
@@ -559,9 +559,9 @@ static int at_start; // True when on the first character
static int prev_at_start; // True when on the second character
// Start parsing at "str".
-static void initchr(char_u *str)
+static void initchr(char *str)
{
- regparse = (char *)str;
+ regparse = str;
prevchr_len = 0;
curchr = prevprevchr = prevchr = nextchr = -1;
at_start = true;
@@ -572,7 +572,7 @@ static void initchr(char_u *str)
// starts in the same state again.
static void save_parse_state(parse_state_T *ps)
{
- ps->regparse = (char_u *)regparse;
+ ps->regparse = regparse;
ps->prevchr_len = prevchr_len;
ps->curchr = curchr;
ps->prevchr = prevchr;
@@ -586,7 +586,7 @@ static void save_parse_state(parse_state_T *ps)
// Restore a previously saved parse state.
static void restore_parse_state(parse_state_T *ps)
{
- regparse = (char *)ps->regparse;
+ regparse = ps->regparse;
prevchr_len = ps->prevchr_len;
curchr = ps->curchr;
prevchr = ps->prevchr;
@@ -677,7 +677,7 @@ static int peekchr(void)
// '$' is only magic as the very last char and if it's in front of
// either "\|", "\)", "\&", or "\n"
if (reg_magic >= MAGIC_OFF) {
- char_u *p = (char_u *)regparse + 1;
+ uint8_t *p = (uint8_t *)regparse + 1;
bool is_magic_all = (reg_magic == MAGIC_ALL);
// ignore \c \C \m \M \v \V and \Z after '$'
@@ -892,7 +892,7 @@ static int64_t getoctchrs(void)
static int read_limits(long *minval, long *maxval)
{
int reverse = false;
- char_u *first_char;
+ char *first_char;
long tmp;
if (*regparse == '-') {
@@ -900,7 +900,7 @@ static int read_limits(long *minval, long *maxval)
regparse++;
reverse = true;
}
- first_char = (char_u *)regparse;
+ first_char = regparse;
*minval = getdigits_long(&regparse, false, 0);
if (*regparse == ',') { // There is a comma.
if (ascii_isdigit(*++regparse)) {
@@ -938,7 +938,7 @@ static int read_limits(long *minval, long *maxval)
// Sometimes need to save a copy of a line. Since alloc()/free() is very
// slow, we keep one allocated piece of memory and only re-allocate it when
// it's too small. It's freed in bt_regexec_both() when finished.
-static char_u *reg_tofree = NULL;
+static uint8_t *reg_tofree = NULL;
static unsigned reg_tofreelen;
// Structure used to store the execution state of the regex engine.
@@ -960,8 +960,8 @@ typedef struct {
regmatch_T *reg_match;
regmmatch_T *reg_mmatch;
- char_u **reg_startp;
- char_u **reg_endp;
+ uint8_t **reg_startp;
+ uint8_t **reg_endp;
lpos_T *reg_startpos;
lpos_T *reg_endpos;
@@ -973,8 +973,8 @@ typedef struct {
// The current match-position is remembered with these variables:
linenr_T lnum; ///< line number, relative to first line
- char_u *line; ///< start of current line
- char_u *input; ///< current input, points into "line"
+ uint8_t *line; ///< start of current line
+ uint8_t *input; ///< current input, points into "line"
int need_clear_subexpr; ///< subexpressions still need to be cleared
int need_clear_zsubexpr; ///< extmatch subexpressions still need to be
@@ -1019,7 +1019,7 @@ static bool reg_iswordc(int c)
}
// Get pointer to the line "lnum", which is relative to "reg_firstlnum".
-static char_u *reg_getline(linenr_T lnum)
+static char *reg_getline(linenr_T lnum)
{
// when looking behind for a match/no-match lnum is negative. But we
// can't go before line 1
@@ -1028,13 +1028,13 @@ static char_u *reg_getline(linenr_T lnum)
}
if (lnum > rex.reg_maxline) {
// Must have matched the "\n" in the last line.
- return (char_u *)"";
+ return "";
}
- return (char_u *)ml_get_buf(rex.reg_buf, rex.reg_firstlnum + lnum, false);
+ return ml_get_buf(rex.reg_buf, rex.reg_firstlnum + lnum, false);
}
-static char_u *reg_startzp[NSUBEXP]; // Workspace to mark beginning
-static char_u *reg_endzp[NSUBEXP]; // and end of \z(...\) matches
+static uint8_t *reg_startzp[NSUBEXP]; // Workspace to mark beginning
+static uint8_t *reg_endzp[NSUBEXP]; // and end of \z(...\) matches
static lpos_T reg_startzpos[NSUBEXP]; // idem, beginning pos
static lpos_T reg_endzpos[NSUBEXP]; // idem, end pos
@@ -1147,7 +1147,7 @@ static bool reg_match_visual(void)
}
// getvvcol() flushes rex.line, need to get it again
- rex.line = reg_getline(rex.lnum);
+ rex.line = (uint8_t *)reg_getline(rex.lnum);
rex.input = rex.line + col;
unsigned int cols_u = win_linetabsize(wp, rex.reg_firstlnum + rex.lnum, (char *)rex.line, col);
@@ -1184,38 +1184,42 @@ static int prog_magic_wrong(void)
// used (to increase speed).
static void cleanup_subexpr(void)
{
- if (rex.need_clear_subexpr) {
- if (REG_MULTI) {
- // Use 0xff to set lnum to -1
- memset(rex.reg_startpos, 0xff, sizeof(lpos_T) * NSUBEXP);
- memset(rex.reg_endpos, 0xff, sizeof(lpos_T) * NSUBEXP);
- } else {
- memset(rex.reg_startp, 0, sizeof(char_u *) * NSUBEXP);
- memset(rex.reg_endp, 0, sizeof(char_u *) * NSUBEXP);
- }
- rex.need_clear_subexpr = false;
+ if (!rex.need_clear_subexpr) {
+ return;
+ }
+
+ if (REG_MULTI) {
+ // Use 0xff to set lnum to -1
+ memset(rex.reg_startpos, 0xff, sizeof(lpos_T) * NSUBEXP);
+ memset(rex.reg_endpos, 0xff, sizeof(lpos_T) * NSUBEXP);
+ } else {
+ memset(rex.reg_startp, 0, sizeof(char *) * NSUBEXP);
+ memset(rex.reg_endp, 0, sizeof(char *) * NSUBEXP);
}
+ rex.need_clear_subexpr = false;
}
static void cleanup_zsubexpr(void)
{
- if (rex.need_clear_zsubexpr) {
- if (REG_MULTI) {
- // Use 0xff to set lnum to -1
- memset(reg_startzpos, 0xff, sizeof(lpos_T) * NSUBEXP);
- memset(reg_endzpos, 0xff, sizeof(lpos_T) * NSUBEXP);
- } else {
- memset(reg_startzp, 0, sizeof(char_u *) * NSUBEXP);
- memset(reg_endzp, 0, sizeof(char_u *) * NSUBEXP);
- }
- rex.need_clear_zsubexpr = false;
+ if (!rex.need_clear_zsubexpr) {
+ return;
+ }
+
+ if (REG_MULTI) {
+ // Use 0xff to set lnum to -1
+ memset(reg_startzpos, 0xff, sizeof(lpos_T) * NSUBEXP);
+ memset(reg_endzpos, 0xff, sizeof(lpos_T) * NSUBEXP);
+ } else {
+ memset(reg_startzp, 0, sizeof(char *) * NSUBEXP);
+ memset(reg_endzp, 0, sizeof(char *) * NSUBEXP);
}
+ rex.need_clear_zsubexpr = false;
}
// Advance rex.lnum, rex.line and rex.input to the next line.
static void reg_nextline(void)
{
- rex.line = reg_getline(++rex.lnum);
+ rex.line = (uint8_t *)reg_getline(++rex.lnum);
rex.input = rex.line;
fast_breakcheck();
}
@@ -1252,7 +1256,7 @@ static int match_with_backref(linenr_T start_lnum, colnr_T start_col, linenr_T e
}
// Get the line to compare with.
- p = (char *)reg_getline(clnum);
+ p = reg_getline(clnum);
assert(p);
if (clnum == end_lnum) {
@@ -1399,8 +1403,8 @@ static int cstrncmp(char *s1, char *s2, int *n)
str2 = s2;
c1 = c2 = 0;
while ((int)(str1 - s1) < *n) {
- c1 = mb_ptr2char_adv((const char_u **)&str1);
- c2 = mb_ptr2char_adv((const char_u **)&str2);
+ c1 = mb_ptr2char_adv((const char **)&str1);
+ c2 = mb_ptr2char_adv((const char **)&str2);
// decompose the character if necessary, into 'base' characters
// because I don't care about Arabic, I will hard-code the Hebrew
@@ -1434,21 +1438,21 @@ static int cstrncmp(char *s1, char *s2, int *n)
/// @param c character to find in @a s
///
/// @return NULL if no match, otherwise pointer to the position in @a s
-static inline char_u *cstrchr(const char_u *const s, const int c)
+static inline char *cstrchr(const char *const s, const int c)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
FUNC_ATTR_ALWAYS_INLINE
{
if (!rex.reg_ic) {
- return (char_u *)vim_strchr((char *)s, c);
+ return vim_strchr(s, c);
}
// Use folded case for UTF-8, slow! For ASCII use libc strpbrk which is
// expected to be highly optimized.
if (c > 0x80) {
const int folded_c = utf_fold(c);
- for (const char_u *p = s; *p != NUL; p += utfc_ptr2len((char *)p)) {
- if (utf_fold(utf_ptr2char((char *)p)) == folded_c) {
- return (char_u *)p;
+ for (const char *p = s; *p != NUL; p += utfc_ptr2len(p)) {
+ if (utf_fold(utf_ptr2char(p)) == folded_c) {
+ return (char *)p;
}
}
return NULL;
@@ -1460,11 +1464,11 @@ static inline char_u *cstrchr(const char_u *const s, const int c)
} else if (ASCII_ISLOWER(c)) {
cc = TOUPPER_ASC(c);
} else {
- return (char_u *)vim_strchr((char *)s, c);
+ return vim_strchr(s, c);
}
char tofind[] = { (char)c, (char)cc, NUL };
- return (char_u *)strpbrk((const char *)s, tofind);
+ return strpbrk(s, tofind);
}
////////////////////////////////////////////////////////////////
@@ -1636,8 +1640,7 @@ static void clear_submatch_list(staticList10_T *sl)
/// references invalid!
///
/// Returns the size of the replacement, including terminating NUL.
-int vim_regsub(regmatch_T *rmp, char_u *source, typval_T *expr, char_u *dest, int destlen,
- int flags)
+int vim_regsub(regmatch_T *rmp, char *source, typval_T *expr, char *dest, int destlen, int flags)
{
regexec_T rex_save;
bool rex_in_use_save = rex_in_use;
@@ -1653,7 +1656,7 @@ int vim_regsub(regmatch_T *rmp, char_u *source, typval_T *expr, char_u *dest, in
rex.reg_maxline = 0;
rex.reg_buf = curbuf;
rex.reg_line_lbr = true;
- int result = vim_regsub_both((char *)source, expr, (char *)dest, destlen, flags);
+ int result = vim_regsub_both(source, expr, dest, destlen, flags);
rex_in_use = rex_in_use_save;
if (rex_in_use) {
@@ -1663,7 +1666,7 @@ int vim_regsub(regmatch_T *rmp, char_u *source, typval_T *expr, char_u *dest, in
return result;
}
-int vim_regsub_multi(regmmatch_T *rmp, linenr_T lnum, char_u *source, char_u *dest, int destlen,
+int vim_regsub_multi(regmmatch_T *rmp, linenr_T lnum, char *source, char *dest, int destlen,
int flags)
{
regexec_T rex_save;
@@ -1681,7 +1684,7 @@ int vim_regsub_multi(regmmatch_T *rmp, linenr_T lnum, char_u *source, char_u *de
rex.reg_firstlnum = lnum;
rex.reg_maxline = curbuf->b_ml.ml_line_count - lnum;
rex.reg_line_lbr = false;
- int result = vim_regsub_both((char *)source, NULL, (char *)dest, destlen, flags);
+ int result = vim_regsub_both(source, NULL, dest, destlen, flags);
rex_in_use = rex_in_use_save;
if (rex_in_use) {
@@ -1860,7 +1863,7 @@ static int vim_regsub_both(char *source, typval_T *expr, char *dest, int destlen
no = 0;
} else if ('0' <= *src && *src <= '9') {
no = *src++ - '0';
- } else if (vim_strchr("uUlLeE", *src)) {
+ } else if (vim_strchr("uUlLeE", (uint8_t)(*src))) {
switch (*src++) {
case 'u':
func_one = (fptr_T)do_upper;
@@ -1974,7 +1977,7 @@ static int vim_regsub_both(char *source, typval_T *expr, char *dest, int destlen
if (clnum < 0 || rex.reg_mmatch->endpos[no].lnum < 0) {
s = NULL;
} else {
- s = (char *)reg_getline(clnum) + rex.reg_mmatch->startpos[no].col;
+ s = reg_getline(clnum) + rex.reg_mmatch->startpos[no].col;
if (rex.reg_mmatch->endpos[no].lnum == clnum) {
len = rex.reg_mmatch->endpos[no].col
- rex.reg_mmatch->startpos[no].col;
@@ -2005,7 +2008,7 @@ static int vim_regsub_both(char *source, typval_T *expr, char *dest, int destlen
*dst = CAR;
}
dst++;
- s = (char *)reg_getline(++clnum);
+ s = reg_getline(++clnum);
if (rex.reg_mmatch->endpos[no].lnum == clnum) {
len = rex.reg_mmatch->endpos[no].col;
} else {
@@ -2099,7 +2102,7 @@ static char *reg_getline_submatch(linenr_T lnum)
rex.reg_firstlnum = rsm.sm_firstlnum;
rex.reg_maxline = rsm.sm_maxline;
- s = (char *)reg_getline(lnum);
+ s = reg_getline(lnum);
rex.reg_firstlnum = save_first;
rex.reg_maxline = save_max;
@@ -2290,7 +2293,7 @@ static regengine_T nfa_regengine = {
static int regexp_engine = 0;
#ifdef REGEXP_DEBUG
-static char_u regname[][30] = {
+static uint8_t regname[][30] = {
"AUTOMATIC Regexp Engine",
"BACKTRACKING Regexp Engine",
"NFA Regexp Engine"
@@ -2339,10 +2342,10 @@ regprog_T *vim_regcomp(char *expr_arg, int re_flags)
//
const int called_emsg_before = called_emsg;
if (regexp_engine != BACKTRACKING_ENGINE) {
- prog = nfa_regengine.regcomp((char_u *)expr,
+ prog = nfa_regengine.regcomp((uint8_t *)expr,
re_flags + (regexp_engine == AUTOMATIC_ENGINE ? RE_AUTO : 0));
} else {
- prog = bt_regengine.regcomp((char_u *)expr, re_flags);
+ prog = bt_regengine.regcomp((uint8_t *)expr, re_flags);
}
// Check for error compiling regexp with initial engine.
@@ -2366,8 +2369,8 @@ regprog_T *vim_regcomp(char *expr_arg, int re_flags)
// But don't try if an error message was given.
if (regexp_engine == AUTOMATIC_ENGINE && called_emsg == called_emsg_before) {
regexp_engine = BACKTRACKING_ENGINE;
- report_re_switch((char_u *)expr);
- prog = bt_regengine.regcomp((char_u *)expr, re_flags);
+ report_re_switch(expr);
+ prog = bt_regengine.regcomp((uint8_t *)expr, re_flags);
}
}
@@ -2400,12 +2403,12 @@ void free_regexp_stuff(void)
#endif
-static void report_re_switch(char_u *pat)
+static void report_re_switch(char *pat)
{
if (p_verbose > 0) {
verbose_enter();
msg_puts(_("Switching to backtracking RE engine for pattern: "));
- msg_puts((char *)pat);
+ msg_puts(pat);
verbose_leave();
}
}
@@ -2422,7 +2425,7 @@ static void report_re_switch(char_u *pat)
/// @param nl
///
/// @return true if there is a match, false if not.
-static bool vim_regexec_string(regmatch_T *rmp, char_u *line, colnr_T col, bool nl)
+static bool vim_regexec_string(regmatch_T *rmp, char *line, colnr_T col, bool nl)
{
regexec_T rex_save;
bool rex_in_use_save = rex_in_use;
@@ -2445,7 +2448,7 @@ static bool vim_regexec_string(regmatch_T *rmp, char_u *line, colnr_T col, bool
rex.reg_startpos = NULL;
rex.reg_endpos = NULL;
- int result = rmp->regprog->engine->regexec_nl(rmp, line, col, nl);
+ int result = rmp->regprog->engine->regexec_nl(rmp, (uint8_t *)line, col, nl);
rmp->regprog->re_in_use = false;
// NFA engine aborted because it's very slow, use backtracking engine instead.
@@ -2457,11 +2460,11 @@ static bool vim_regexec_string(regmatch_T *rmp, char_u *line, colnr_T col, bool
p_re = BACKTRACKING_ENGINE;
vim_regfree(rmp->regprog);
- report_re_switch((char_u *)pat);
+ report_re_switch(pat);
rmp->regprog = vim_regcomp(pat, re_flags);
if (rmp->regprog != NULL) {
rmp->regprog->re_in_use = true;
- result = rmp->regprog->engine->regexec_nl(rmp, line, col, nl);
+ result = rmp->regprog->engine->regexec_nl(rmp, (uint8_t *)line, col, nl);
rmp->regprog->re_in_use = false;
}
@@ -2479,7 +2482,7 @@ static bool vim_regexec_string(regmatch_T *rmp, char_u *line, colnr_T col, bool
// Note: "*prog" may be freed and changed.
// Return true if there is a match, false if not.
-bool vim_regexec_prog(regprog_T **prog, bool ignore_case, char_u *line, colnr_T col)
+bool vim_regexec_prog(regprog_T **prog, bool ignore_case, char *line, colnr_T col)
{
regmatch_T regmatch = { .regprog = *prog, .rm_ic = ignore_case };
bool r = vim_regexec_string(&regmatch, line, col, false);
@@ -2491,13 +2494,13 @@ bool vim_regexec_prog(regprog_T **prog, bool ignore_case, char_u *line, colnr_T
// Return true if there is a match, false if not.
bool vim_regexec(regmatch_T *rmp, char *line, colnr_T col)
{
- return vim_regexec_string(rmp, (char_u *)line, col, false);
+ return vim_regexec_string(rmp, line, col, false);
}
// Like vim_regexec(), but consider a "\n" in "line" to be a line break.
// Note: "rmp->regprog" may be freed and changed.
// Return true if there is a match, false if not.
-bool vim_regexec_nl(regmatch_T *rmp, char_u *line, colnr_T col)
+bool vim_regexec_nl(regmatch_T *rmp, char *line, colnr_T col)
{
return vim_regexec_string(rmp, line, col, true);
}
@@ -2549,7 +2552,7 @@ long vim_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T lnum,
p_re = BACKTRACKING_ENGINE;
regprog_T *prev_prog = rmp->regprog;
- report_re_switch((char_u *)pat);
+ report_re_switch(pat);
// checking for \z misuse was already done when compiling for NFA,
// allow all here
reg_do_extmatch = REX_ALL;
diff --git a/src/nvim/regexp_bt.c b/src/nvim/regexp_bt.c
index f930d872b6..af3d93f7c4 100644
--- a/src/nvim/regexp_bt.c
+++ b/src/nvim/regexp_bt.c
@@ -242,17 +242,17 @@
static int prevchr_len; ///< byte length of previous char
static int num_complex_braces; ///< Complex \{...} count
-static char_u *regcode; ///< Code-emit pointer, or JUST_CALC_SIZE
+static uint8_t *regcode; ///< Code-emit pointer, or JUST_CALC_SIZE
static long regsize; ///< Code size.
static int reg_toolong; ///< true when offset out of range
-static char_u had_endbrace[NSUBEXP]; ///< flags, true if end of () found
+static uint8_t had_endbrace[NSUBEXP]; ///< flags, true if end of () found
static long brace_min[10]; ///< Minimums for complex brace repeats
static long brace_max[10]; ///< Maximums for complex brace repeats
static int brace_count[10]; ///< Current counts for complex brace repeats
static int one_exactly = false; ///< only do one char for EXACTLY
// When making changes to classchars also change nfa_classcodes.
-static char_u *classchars = (char_u *)".iIkKfFpPsSdDxXoOwWhHaAlLuU";
+static uint8_t *classchars = (uint8_t *)".iIkKfFpPsSdDxXoOwWhHaAlLuU";
static int classcodes[] = {
ANY, IDENT, SIDENT, KWORD, SKWORD,
FNAME, SFNAME, PRINT, SPRINT,
@@ -265,7 +265,7 @@ static int classcodes[] = {
// When regcode is set to this value, code is not emitted and size is computed
// instead.
-#define JUST_CALC_SIZE ((char_u *)-1)
+#define JUST_CALC_SIZE ((uint8_t *)-1)
// Values for rs_state in regitem_T.
typedef enum regstate_E {
@@ -290,7 +290,7 @@ typedef enum regstate_E {
// Also stores the length of "backpos".
typedef struct {
union {
- char_u *ptr; // rex.input pointer, for single-line regexp
+ uint8_t *ptr; // rex.input pointer, for single-line regexp
lpos_T pos; // rex.input pos, for multi-line regexp
} rs_u;
int rs_len;
@@ -299,7 +299,7 @@ typedef struct {
// struct to save start/end pointer/position in for \(\)
typedef struct {
union {
- char_u *ptr;
+ uint8_t *ptr;
lpos_T pos;
} se_u;
} save_se_T;
@@ -320,7 +320,7 @@ typedef struct regbehind_S {
typedef struct regitem_S {
regstate_T rs_state; // what we are doing, one of RS_ above
int16_t rs_no; // submatch nr or BEHIND/NOBEHIND
- char_u *rs_scan; // current node in program
+ uint8_t *rs_scan; // current node in program
union {
save_se_T sesave;
regsave_T regsave;
@@ -339,7 +339,7 @@ typedef struct regstar_S {
// used to store input position when a BACK was encountered, so that we now if
// we made any progress since the last time.
typedef struct backpos_S {
- char_u *bp_scan; // "scan" where BACK was encountered
+ uint8_t *bp_scan; // "scan" where BACK was encountered
regsave_T bp_pos; // last input position
} backpos_T;
@@ -411,14 +411,14 @@ static regsave_T behind_pos;
// Obtain a second single-byte operand stored after a four bytes operand.
#define OPERAND_CMP(p) (p)[7]
-static char_u *reg(int paren, int *flagp);
+static uint8_t *reg(int paren, int *flagp);
#ifdef BT_REGEXP_DUMP
-static void regdump(char_u *, bt_regprog_T *);
+static void regdump(uint8_t *, bt_regprog_T *);
#endif
#ifdef REGEXP_DEBUG
-static char_u *regprop(char_u *);
+static uint8_t *regprop(uint8_t *);
static int regnarrate = 0;
#endif
@@ -428,9 +428,9 @@ static int regnarrate = 0;
#endif
// Setup to parse the regexp. Used once to get the length and once to do it.
-static void regcomp_start(char_u *expr, int re_flags) // see vim_regcomp()
+static void regcomp_start(uint8_t *expr, int re_flags) // see vim_regcomp()
{
- initchr(expr);
+ initchr((char *)expr);
if (re_flags & RE_MAGIC) {
reg_magic = MAGIC_ON;
} else {
@@ -466,7 +466,7 @@ static void regc(int b)
if (regcode == JUST_CALC_SIZE) {
regsize++;
} else {
- *regcode++ = (char_u)b;
+ *regcode++ = (uint8_t)b;
}
}
@@ -1453,15 +1453,15 @@ static void reg_equi_class(int c)
// Emit a node.
// Return pointer to generated code.
-static char_u *regnode(int op)
+static uint8_t *regnode(int op)
{
- char_u *ret;
+ uint8_t *ret;
ret = regcode;
if (ret == JUST_CALC_SIZE) {
regsize += 3;
} else {
- *regcode++ = (char_u)op;
+ *regcode++ = (uint8_t)op;
*regcode++ = NUL; // Null "next" pointer.
*regcode++ = NUL;
}
@@ -1469,19 +1469,19 @@ static char_u *regnode(int op)
}
// Write a four bytes number at "p" and return pointer to the next char.
-static char_u *re_put_uint32(char_u *p, uint32_t val)
+static uint8_t *re_put_uint32(uint8_t *p, uint32_t val)
{
- *p++ = (char_u)((val >> 24) & 0377);
- *p++ = (char_u)((val >> 16) & 0377);
- *p++ = (char_u)((val >> 8) & 0377);
- *p++ = (char_u)(val & 0377);
+ *p++ = (uint8_t)((val >> 24) & 0377);
+ *p++ = (uint8_t)((val >> 16) & 0377);
+ *p++ = (uint8_t)((val >> 8) & 0377);
+ *p++ = (uint8_t)(val & 0377);
return p;
}
// regnext - dig the "next" pointer out of a node
// Returns NULL when calculating size, when there is no next item and when
// there is an error.
-static char_u *regnext(char_u *p)
+static uint8_t *regnext(uint8_t *p)
FUNC_ATTR_NONNULL_ALL
{
int offset;
@@ -1503,7 +1503,7 @@ static char_u *regnext(char_u *p)
}
// Set the next-pointer at the end of a node chain.
-static void regtail(char_u *p, char_u *val)
+static void regtail(uint8_t *p, uint8_t *val)
{
int offset;
@@ -1512,9 +1512,9 @@ static void regtail(char_u *p, char_u *val)
}
// Find last node.
- char_u *scan = p;
+ uint8_t *scan = p;
for (;;) {
- char_u *temp = regnext(scan);
+ uint8_t *temp = regnext(scan);
if (temp == NULL) {
break;
}
@@ -1532,13 +1532,13 @@ static void regtail(char_u *p, char_u *val)
if (offset > 0xffff) {
reg_toolong = true;
} else {
- *(scan + 1) = (char_u)(((unsigned)offset >> 8) & 0377);
- *(scan + 2) = (char_u)(offset & 0377);
+ *(scan + 1) = (uint8_t)(((unsigned)offset >> 8) & 0377);
+ *(scan + 2) = (uint8_t)(offset & 0377);
}
}
// Like regtail, on item after a BRANCH; nop if none.
-static void regoptail(char_u *p, char_u *val)
+static void regoptail(uint8_t *p, uint8_t *val)
{
// When op is neither BRANCH nor BRACE_COMPLEX0-9, it is "operandless"
if (p == NULL || p == JUST_CALC_SIZE
@@ -1552,11 +1552,11 @@ static void regoptail(char_u *p, char_u *val)
// Insert an operator in front of already-emitted operand
//
// Means relocating the operand.
-static void reginsert(int op, char_u *opnd)
+static void reginsert(int op, uint8_t *opnd)
{
- char_u *src;
- char_u *dst;
- char_u *place;
+ uint8_t *src;
+ uint8_t *dst;
+ uint8_t *place;
if (regcode == JUST_CALC_SIZE) {
regsize += 3;
@@ -1570,18 +1570,18 @@ static void reginsert(int op, char_u *opnd)
}
place = opnd; // Op node, where operand used to be.
- *place++ = (char_u)op;
+ *place++ = (uint8_t)op;
*place++ = NUL;
*place = NUL;
}
// Insert an operator in front of already-emitted operand.
// Add a number to the operator.
-static void reginsert_nr(int op, long val, char_u *opnd)
+static void reginsert_nr(int op, long val, uint8_t *opnd)
{
- char_u *src;
- char_u *dst;
- char_u *place;
+ uint8_t *src;
+ uint8_t *dst;
+ uint8_t *place;
if (regcode == JUST_CALC_SIZE) {
regsize += 7;
@@ -1595,7 +1595,7 @@ static void reginsert_nr(int op, long val, char_u *opnd)
}
place = opnd; // Op node, where operand used to be.
- *place++ = (char_u)op;
+ *place++ = (uint8_t)op;
*place++ = NUL;
*place++ = NUL;
assert(val >= 0 && (uintmax_t)val <= UINT32_MAX);
@@ -1606,11 +1606,11 @@ static void reginsert_nr(int op, long val, char_u *opnd)
// The operator has the given limit values as operands. Also set next pointer.
//
// Means relocating the operand.
-static void reginsert_limits(int op, long minval, long maxval, char_u *opnd)
+static void reginsert_limits(int op, long minval, long maxval, uint8_t *opnd)
{
- char_u *src;
- char_u *dst;
- char_u *place;
+ uint8_t *src;
+ uint8_t *dst;
+ uint8_t *place;
if (regcode == JUST_CALC_SIZE) {
regsize += 11;
@@ -1624,7 +1624,7 @@ static void reginsert_limits(int op, long minval, long maxval, char_u *opnd)
}
place = opnd; // Op node, where operand used to be.
- *place++ = (char_u)op;
+ *place++ = (uint8_t)op;
*place++ = NUL;
*place++ = NUL;
assert(minval >= 0 && (uintmax_t)minval <= UINT32_MAX);
@@ -1641,11 +1641,11 @@ static void reginsert_limits(int op, long minval, long maxval, char_u *opnd)
static int seen_endbrace(int refnum)
{
if (!had_endbrace[refnum]) {
- char_u *p;
+ uint8_t *p;
// Trick: check if "@<=" or "@<!" follows, in which case
// the \1 can appear before the referenced match.
- for (p = (char_u *)regparse; *p != NUL; p++) {
+ for (p = (uint8_t *)regparse; *p != NUL; p++) {
if (p[0] == '@' && p[1] == '<' && (p[2] == '!' || p[2] == '=')) {
break;
}
@@ -1665,12 +1665,12 @@ static int seen_endbrace(int refnum)
// Optimization: gobbles an entire sequence of ordinary characters so that
// it can turn them into a single node, which is smaller to store and
// faster to run. Don't do this when one_exactly is set.
-static char_u *regatom(int *flagp)
+static uint8_t *regatom(int *flagp)
{
- char_u *ret;
+ uint8_t *ret;
int flags;
int c;
- char_u *p;
+ uint8_t *p;
int extra = 0;
int save_prev_at_start = prev_at_start;
@@ -1746,7 +1746,7 @@ static char_u *regatom(int *flagp)
case Magic('L'):
case Magic('u'):
case Magic('U'):
- p = (char_u *)vim_strchr((char *)classchars, no_Magic(c));
+ p = (uint8_t *)vim_strchr((char *)classchars, no_Magic(c));
if (p == NULL) {
EMSG_RET_NULL(_("E63: invalid use of \\_"));
}
@@ -1808,17 +1808,17 @@ static char_u *regatom(int *flagp)
case Magic('~'): // previous substitute pattern
if (reg_prev_sub != NULL) {
- char_u *lp;
+ uint8_t *lp;
ret = regnode(EXACTLY);
- lp = (char_u *)reg_prev_sub;
+ lp = (uint8_t *)reg_prev_sub;
while (*lp != NUL) {
regc(*lp++);
}
regc(NUL);
if (*reg_prev_sub != NUL) {
*flagp |= HASWIDTH;
- if ((lp - (char_u *)reg_prev_sub) == 1) {
+ if ((lp - (uint8_t *)reg_prev_sub) == 1) {
*flagp |= SIMPLE;
}
}
@@ -1948,9 +1948,9 @@ static char_u *regatom(int *flagp)
EMSG_ONE_RET_NULL;
}
{
- char_u *lastbranch;
- char_u *lastnode = NULL;
- char_u *br;
+ uint8_t *lastbranch;
+ uint8_t *lastnode = NULL;
+ uint8_t *br;
ret = NULL;
while ((c = getchr()) != ']') {
@@ -2072,8 +2072,8 @@ static char_u *regatom(int *flagp)
if (ret == JUST_CALC_SIZE) {
regsize += 2;
} else {
- *regcode++ = (char_u)c;
- *regcode++ = (char_u)cmp;
+ *regcode++ = (uint8_t)c;
+ *regcode++ = (uint8_t)cmp;
}
break;
} else if ((c == 'l' || c == 'c' || c == 'v') && (cur || got_digit)) {
@@ -2110,7 +2110,7 @@ static char_u *regatom(int *flagp)
// put the number and the optional
// comparator after the opcode
regcode = re_put_uint32(regcode, n);
- *regcode++ = (char_u)cmp;
+ *regcode++ = (uint8_t)cmp;
}
break;
}
@@ -2124,11 +2124,11 @@ static char_u *regatom(int *flagp)
case Magic('['):
collection:
{
- char_u *lp;
+ uint8_t *lp;
// If there is no matching ']', we assume the '[' is a normal
// character. This makes 'incsearch' and ":help [" work.
- lp = skip_anyof(regparse);
+ lp = (uint8_t *)skip_anyof(regparse);
if (*lp == ']') { // there is a matching ']'
int startc = -1; // > 0 when next '-' is a range
int endc;
@@ -2165,7 +2165,7 @@ collection:
endc = get_coll_element(&regparse);
}
if (endc == 0) {
- endc = mb_ptr2char_adv((const char_u **)&regparse);
+ endc = mb_ptr2char_adv((const char **)&regparse);
}
// Handle \o40, \x20 and \u20AC style sequences
@@ -2197,10 +2197,10 @@ collection:
// accepts "\t", "\e", etc., but only when the 'l' flag in
// 'cpoptions' is not included.
else if (*regparse == '\\'
- && (vim_strchr(REGEXP_INRANGE, regparse[1]) != NULL
+ && (vim_strchr(REGEXP_INRANGE, (uint8_t)regparse[1]) != NULL
|| (!reg_cpo_lit
&& vim_strchr(REGEXP_ABBR,
- regparse[1]) != NULL))) {
+ (uint8_t)regparse[1]) != NULL))) {
regparse++;
if (*regparse == 'n') {
// '\n' in range: also match NL
@@ -2460,11 +2460,11 @@ do_multibyte:
// both the endmarker for their branch list and the body of the last branch.
// It might seem that this node could be dispensed with entirely, but the
// endmarker role is not redundant.
-static char_u *regpiece(int *flagp)
+static uint8_t *regpiece(int *flagp)
{
- char_u *ret;
+ uint8_t *ret;
int op;
- char_u *next;
+ uint8_t *next;
int flags;
long minval;
long maxval;
@@ -2597,11 +2597,11 @@ static char_u *regpiece(int *flagp)
// Parse one alternative of an | or & operator.
// Implements the concatenation operator.
-static char_u *regconcat(int *flagp)
+static uint8_t *regconcat(int *flagp)
{
- char_u *first = NULL;
- char_u *chain = NULL;
- char_u *latest;
+ uint8_t *first = NULL;
+ uint8_t *chain = NULL;
+ uint8_t *latest;
int flags;
int cont = true;
@@ -2673,11 +2673,11 @@ static char_u *regconcat(int *flagp)
// Parse one alternative of an | operator.
// Implements the & operator.
-static char_u *regbranch(int *flagp)
+static uint8_t *regbranch(int *flagp)
{
- char_u *ret;
- char_u *chain = NULL;
- char_u *latest;
+ uint8_t *ret;
+ uint8_t *chain = NULL;
+ uint8_t *latest;
int flags;
*flagp = WORST | HASNL; // Tentatively.
@@ -2722,11 +2722,11 @@ static char_u *regbranch(int *flagp)
/// follows makes it hard to avoid.
///
/// @param paren REG_NOPAREN, REG_PAREN, REG_NPAREN or REG_ZPAREN
-static char_u *reg(int paren, int *flagp)
+static uint8_t *reg(int paren, int *flagp)
{
- char_u *ret;
- char_u *br;
- char_u *ender;
+ uint8_t *ret;
+ uint8_t *br;
+ uint8_t *ender;
int parno = 0;
int flags;
@@ -2840,10 +2840,10 @@ static char_u *reg(int paren, int *flagp)
// Beware that the optimization-preparation code in here knows about some
// of the structure of the compiled regexp.
// "re_flags": RE_MAGIC and/or RE_STRING.
-static regprog_T *bt_regcomp(char_u *expr, int re_flags)
+static regprog_T *bt_regcomp(uint8_t *expr, int re_flags)
{
- char_u *scan;
- char_u *longest;
+ uint8_t *scan;
+ uint8_t *longest;
int len;
int flags;
@@ -2862,7 +2862,7 @@ static regprog_T *bt_regcomp(char_u *expr, int re_flags)
}
// Allocate space.
- bt_regprog_T *r = xmalloc(sizeof(bt_regprog_T) + (size_t)regsize);
+ bt_regprog_T *r = xmalloc(offsetof(bt_regprog_T, program) + (size_t)regsize);
r->re_in_use = false;
// Second pass: emit code.
@@ -2890,7 +2890,7 @@ static regprog_T *bt_regcomp(char_u *expr, int re_flags)
r->regflags |= RF_LOOKBH;
}
// Remember whether this pattern has any \z specials in it.
- r->reghasz = (char_u)re_has_z;
+ r->reghasz = (uint8_t)re_has_z;
scan = r->program + 1; // First BRANCH.
if (OP(regnext(scan)) == END) { // Only one top-level choice.
scan = OPERAND(scan);
@@ -2908,7 +2908,7 @@ static regprog_T *bt_regcomp(char_u *expr, int re_flags)
|| OP(scan) == NOTHING
|| OP(scan) == MOPEN + 0 || OP(scan) == NOPEN
|| OP(scan) == MCLOSE + 0 || OP(scan) == NCLOSE) {
- char_u *regnext_scan = regnext(scan);
+ uint8_t *regnext_scan = regnext(scan);
if (OP(regnext_scan) == EXACTLY) {
r->regstart = utf_ptr2char((char *)OPERAND(regnext_scan));
}
@@ -3014,7 +3014,7 @@ static void reg_restore(regsave_T *save, garray_T *gap)
// only call reg_getline() when the line number changed to save
// a bit of time
rex.lnum = save->rs_u.pos.lnum;
- rex.line = reg_getline(rex.lnum);
+ rex.line = (uint8_t *)reg_getline(rex.lnum);
}
rex.input = rex.line + save->rs_u.pos.col;
} else {
@@ -3057,7 +3057,7 @@ static void save_se_multi(save_se_T *savep, lpos_T *posp)
posp->col = (colnr_T)(rex.input - rex.line);
}
-static void save_se_one(save_se_T *savep, char_u **pp)
+static void save_se_one(save_se_T *savep, uint8_t **pp)
{
savep->se_u.ptr = *pp;
*pp = rex.input;
@@ -3067,14 +3067,14 @@ static void save_se_one(save_se_T *savep, char_u **pp)
/// Advances rex.input (and rex.lnum) to just after the matched chars.
///
/// @param maxcount maximum number of matches allowed
-static int regrepeat(char_u *p, long maxcount)
+static int regrepeat(uint8_t *p, long maxcount)
{
long count = 0;
- char_u *opnd;
+ uint8_t *opnd;
int mask;
int testval = 0;
- char_u *scan = rex.input; // Make local copy of rex.input for speed.
+ uint8_t *scan = rex.input; // Make local copy of rex.input for speed.
opnd = OPERAND(p);
switch (OP(p)) {
case ANY:
@@ -3385,12 +3385,12 @@ do_class:
} else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) {
scan++;
} else if ((len = utfc_ptr2len((char *)scan)) > 1) {
- if ((cstrchr(opnd, utf_ptr2char((char *)scan)) == NULL) == testval) {
+ if ((cstrchr((char *)opnd, utf_ptr2char((char *)scan)) == NULL) == testval) {
break;
}
scan += len;
} else {
- if ((cstrchr(opnd, *scan) == NULL) == testval) {
+ if ((cstrchr((char *)opnd, *scan) == NULL) == testval) {
break;
}
scan++;
@@ -3431,7 +3431,7 @@ do_class:
// Push an item onto the regstack.
// Returns pointer to new item. Returns NULL when out of memory.
-static regitem_T *regstack_push(regstate_T state, char_u *scan)
+static regitem_T *regstack_push(regstate_T state, uint8_t *scan)
{
regitem_T *rp;
@@ -3450,7 +3450,7 @@ static regitem_T *regstack_push(regstate_T state, char_u *scan)
}
// Pop an item from the regstack.
-static void regstack_pop(char_u **scan)
+static void regstack_pop(uint8_t **scan)
{
regitem_T *rp;
@@ -3468,15 +3468,17 @@ static void save_subexpr(regbehind_T *bp)
// When "rex.need_clear_subexpr" is set we don't need to save the values, only
// remember that this flag needs to be set again when restoring.
bp->save_need_clear_subexpr = rex.need_clear_subexpr;
- if (!rex.need_clear_subexpr) {
- for (int i = 0; i < NSUBEXP; i++) {
- if (REG_MULTI) {
- bp->save_start[i].se_u.pos = rex.reg_startpos[i];
- bp->save_end[i].se_u.pos = rex.reg_endpos[i];
- } else {
- bp->save_start[i].se_u.ptr = rex.reg_startp[i];
- bp->save_end[i].se_u.ptr = rex.reg_endp[i];
- }
+ if (rex.need_clear_subexpr) {
+ return;
+ }
+
+ for (int i = 0; i < NSUBEXP; i++) {
+ if (REG_MULTI) {
+ bp->save_start[i].se_u.pos = rex.reg_startpos[i];
+ bp->save_end[i].se_u.pos = rex.reg_endpos[i];
+ } else {
+ bp->save_start[i].se_u.ptr = rex.reg_startp[i];
+ bp->save_end[i].se_u.ptr = rex.reg_endp[i];
}
}
}
@@ -3487,15 +3489,17 @@ static void restore_subexpr(regbehind_T *bp)
{
// Only need to restore saved values when they are not to be cleared.
rex.need_clear_subexpr = bp->save_need_clear_subexpr;
- if (!rex.need_clear_subexpr) {
- for (int i = 0; i < NSUBEXP; i++) {
- if (REG_MULTI) {
- rex.reg_startpos[i] = bp->save_start[i].se_u.pos;
- rex.reg_endpos[i] = bp->save_end[i].se_u.pos;
- } else {
- rex.reg_startp[i] = bp->save_start[i].se_u.ptr;
- rex.reg_endp[i] = bp->save_end[i].se_u.ptr;
- }
+ if (rex.need_clear_subexpr) {
+ return;
+ }
+
+ for (int i = 0; i < NSUBEXP; i++) {
+ if (REG_MULTI) {
+ rex.reg_startpos[i] = bp->save_start[i].se_u.pos;
+ rex.reg_endpos[i] = bp->save_end[i].se_u.pos;
+ } else {
+ rex.reg_startp[i] = bp->save_start[i].se_u.ptr;
+ rex.reg_endp[i] = bp->save_end[i].se_u.ptr;
}
}
}
@@ -3516,9 +3520,9 @@ static void restore_subexpr(regbehind_T *bp)
/// just after the last matched character.
/// - false when there is no match. Leaves rex.input and rex.lnum in an
/// undefined state!
-static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out)
+static bool regmatch(uint8_t *scan, proftime_T *tm, int *timed_out)
{
- char_u *next; // Next node.
+ uint8_t *next; // Next node.
int op;
int c;
regitem_T *rp;
@@ -3647,7 +3651,7 @@ static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out)
// Line may have been freed, get it again.
if (REG_MULTI) {
- rex.line = reg_getline(rex.lnum);
+ rex.line = (uint8_t *)reg_getline(rex.lnum);
rex.input = rex.line + col;
}
@@ -3961,7 +3965,7 @@ static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out)
case EXACTLY: {
int len;
- char_u *opnd;
+ uint8_t *opnd;
opnd = OPERAND(scan);
// Inline the first byte, for speed.
@@ -4003,7 +4007,7 @@ static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out)
case ANYBUT:
if (c == NUL) {
status = RA_NOMATCH;
- } else if ((cstrchr(OPERAND(scan), c) == NULL) == (op == ANYOF)) {
+ } else if ((cstrchr((char *)OPERAND(scan), c) == NULL) == (op == ANYOF)) {
status = RA_NOMATCH;
} else {
ADVANCE_REGINPUT();
@@ -4013,7 +4017,7 @@ static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out)
case MULTIBYTECODE: {
int i, len;
- const char_u *opnd = OPERAND(scan);
+ const uint8_t *opnd = OPERAND(scan);
// Safety check (just in case 'encoding' was changed since
// compiling the program).
if ((len = utfc_ptr2len((char *)opnd)) < 2) {
@@ -4699,8 +4703,8 @@ static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out)
(colnr_T)strlen((char *)rex.line);
}
} else {
- const char_u *const line =
- reg_getline(rp->rs_un.regsave.rs_u.pos.lnum);
+ const uint8_t *const line =
+ (uint8_t *)reg_getline(rp->rs_un.regsave.rs_u.pos.lnum);
rp->rs_un.regsave.rs_u.pos.col -=
utf_head_off((char *)line,
@@ -4782,7 +4786,7 @@ static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out)
break;
}
rex.lnum--;
- rex.line = reg_getline(rex.lnum);
+ rex.line = (uint8_t *)reg_getline(rex.lnum);
// Just in case regrepeat() didn't count right.
if (rex.line == NULL) {
break;
@@ -4913,13 +4917,13 @@ static long regtry(bt_regprog_T *prog, colnr_T col, proftime_T *tm, int *timed_o
&& reg_endzpos[i].lnum == reg_startzpos[i].lnum
&& reg_endzpos[i].col >= reg_startzpos[i].col) {
re_extmatch_out->matches[i] =
- (char_u *)xstrnsave((char *)reg_getline(reg_startzpos[i].lnum) + reg_startzpos[i].col,
- (size_t)(reg_endzpos[i].col - reg_startzpos[i].col));
+ (uint8_t *)xstrnsave((char *)reg_getline(reg_startzpos[i].lnum) + reg_startzpos[i].col,
+ (size_t)(reg_endzpos[i].col - reg_startzpos[i].col));
}
} else {
if (reg_startzp[i] != NULL && reg_endzp[i] != NULL) {
re_extmatch_out->matches[i] =
- (char_u *)xstrnsave((char *)reg_startzp[i], (size_t)(reg_endzp[i] - reg_startzp[i]));
+ (uint8_t *)xstrnsave((char *)reg_startzp[i], (size_t)(reg_endzp[i] - reg_startzp[i]));
}
}
}
@@ -4935,10 +4939,10 @@ static long regtry(bt_regprog_T *prog, colnr_T col, proftime_T *tm, int *timed_o
/// @param timed_out flag set on timeout or NULL
///
/// @return 0 for failure, or number of lines contained in the match.
-static long bt_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm, int *timed_out)
+static long bt_regexec_both(uint8_t *line, colnr_T startcol, proftime_T *tm, int *timed_out)
{
bt_regprog_T *prog;
- char_u *s;
+ uint8_t *s;
colnr_T col = startcol;
long retval = 0L;
@@ -4962,13 +4966,13 @@ static long bt_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm, int
if (REG_MULTI) {
prog = (bt_regprog_T *)rex.reg_mmatch->regprog;
- line = reg_getline((linenr_T)0);
+ line = (uint8_t *)reg_getline((linenr_T)0);
rex.reg_startpos = rex.reg_mmatch->startpos;
rex.reg_endpos = rex.reg_mmatch->endpos;
} else {
prog = (bt_regprog_T *)rex.reg_match->regprog;
- rex.reg_startp = (char_u **)rex.reg_match->startp;
- rex.reg_endp = (char_u **)rex.reg_match->endp;
+ rex.reg_startp = (uint8_t **)rex.reg_match->startp;
+ rex.reg_endp = (uint8_t **)rex.reg_match->endp;
}
// Be paranoid...
@@ -5007,14 +5011,14 @@ static long bt_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm, int
// This is used very often, esp. for ":global". Use two versions of
// the loop to avoid overhead of conditions.
if (!rex.reg_ic) {
- while ((s = (char_u *)vim_strchr((char *)s, c)) != NULL) {
+ while ((s = (uint8_t *)vim_strchr((char *)s, c)) != NULL) {
if (cstrncmp((char *)s, (char *)prog->regmust, &prog->regmlen) == 0) {
break; // Found it.
}
MB_PTR_ADV(s);
}
} else {
- while ((s = cstrchr(s, c)) != NULL) {
+ while ((s = (uint8_t *)cstrchr((char *)s, c)) != NULL) {
if (cstrncmp((char *)s, (char *)prog->regmust, &prog->regmlen) == 0) {
break; // Found it.
}
@@ -5049,7 +5053,7 @@ static long bt_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm, int
while (!got_int) {
if (prog->regstart != NUL) {
// Skip until the char we know it must start with.
- s = cstrchr(rex.line + col, prog->regstart);
+ s = (uint8_t *)cstrchr((char *)rex.line + col, prog->regstart);
if (s == NULL) {
retval = 0;
break;
@@ -5071,7 +5075,7 @@ static long bt_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm, int
// if not currently on the first line, get it again
if (rex.lnum != 0) {
rex.lnum = 0;
- rex.line = reg_getline((linenr_T)0);
+ rex.line = (uint8_t *)reg_getline((linenr_T)0);
}
if (rex.line[col] == NUL) {
break;
@@ -5141,7 +5145,7 @@ theend:
/// @param col column to start looking for match
///
/// @return 0 for failure, number of lines contained in the match otherwise.
-static int bt_regexec_nl(regmatch_T *rmp, char_u *line, colnr_T col, bool line_lbr)
+static int bt_regexec_nl(regmatch_T *rmp, uint8_t *line, colnr_T col, bool line_lbr)
{
rex.reg_match = rmp;
rex.reg_mmatch = NULL;
@@ -5178,7 +5182,7 @@ static long bt_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T
}
// Compare a number with the operand of RE_LNUM, RE_COL or RE_VCOL.
-static int re_num_cmp(uint32_t val, char_u *scan)
+static int re_num_cmp(uint32_t val, uint8_t *scan)
{
uint32_t n = (uint32_t)OPERAND_MIN(scan);
@@ -5194,12 +5198,12 @@ static int re_num_cmp(uint32_t val, char_u *scan)
#ifdef BT_REGEXP_DUMP
// regdump - dump a regexp onto stdout in vaguely comprehensible form
-static void regdump(char_u *pattern, bt_regprog_T *r)
+static void regdump(uint8_t *pattern, bt_regprog_T *r)
{
- char_u *s;
+ uint8_t *s;
int op = EXACTLY; // Arbitrary non-END op.
- char_u *next;
- char_u *end = NULL;
+ uint8_t *next;
+ uint8_t *end = NULL;
FILE *f;
# ifdef BT_REGEXP_LOG
@@ -5280,7 +5284,7 @@ static void regdump(char_u *pattern, bt_regprog_T *r)
#ifdef REGEXP_DEBUG
// regprop - printable representation of opcode
-static char_u *regprop(char_u *op)
+static uint8_t *regprop(uint8_t *op)
{
char *p;
static char buf[50];
@@ -5652,6 +5656,6 @@ static char_u *regprop(char_u *op)
if (p != NULL) {
STRCAT(buf, p);
}
- return (char_u *)buf;
+ return (uint8_t *)buf;
}
#endif // REGEXP_DEBUG
diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c
index 6e7ff31c03..ea59e7d464 100644
--- a/src/nvim/regexp_nfa.c
+++ b/src/nvim/regexp_nfa.c
@@ -244,10 +244,10 @@ static int nfa_classcodes[] = {
NFA_UPPER, NFA_NUPPER
};
-static char_u e_nul_found[] = N_("E865: (NFA) Regexp end encountered prematurely");
-static char_u e_misplaced[] = N_("E866: (NFA regexp) Misplaced %c");
-static char_u e_ill_char_class[] = N_("E877: (NFA regexp) Invalid character class: %" PRId64);
-static char_u e_value_too_large[] = N_("E951: \\% value too large");
+static char e_nul_found[] = N_("E865: (NFA) Regexp end encountered prematurely");
+static char e_misplaced[] = N_("E866: (NFA regexp) Misplaced %c");
+static char e_ill_char_class[] = N_("E877: (NFA regexp) Invalid character class: %" PRId64);
+static char e_value_too_large[] = N_("E951: \\% value too large");
// Since the out pointers in the list are always
// uninitialized, we use the pointers themselves
@@ -276,8 +276,8 @@ typedef struct {
colnr_T end_col;
} multi[NSUBEXP];
struct linepos {
- char_u *start;
- char_u *end;
+ uint8_t *start;
+ uint8_t *end;
} line[NSUBEXP];
} list;
colnr_T orig_start_col; // list.multi[0].start_col without \zs
@@ -296,7 +296,7 @@ struct nfa_pim_S {
regsubs_T subs; // submatch info, only party used
union {
lpos_T pos;
- char_u *ptr;
+ uint8_t *ptr;
} end; // where the match must end
};
@@ -354,7 +354,7 @@ static int nfa_ll_index = 0;
/// Initialize internal variables before NFA compilation.
///
/// @param re_flags @see vim_regcomp()
-static void nfa_regcomp_start(char_u *expr, int re_flags)
+static void nfa_regcomp_start(uint8_t *expr, int re_flags)
{
size_t postfix_size;
size_t nstate_max;
@@ -519,12 +519,12 @@ static int nfa_get_regstart(nfa_state_T *start, int depth)
// Figure out if the NFA state list contains just literal text and nothing
// else. If so return a string in allocated memory with what must match after
// regstart. Otherwise return NULL.
-static char_u *nfa_get_match_text(nfa_state_T *start)
+static uint8_t *nfa_get_match_text(nfa_state_T *start)
{
nfa_state_T *p = start;
int len = 0;
- char_u *ret;
- char_u *s;
+ uint8_t *ret;
+ uint8_t *s;
if (p->c != NFA_MOPEN) {
return NULL; // just in case
@@ -571,7 +571,7 @@ static void realloc_post_list(void)
// to the closing brace.
// Keep in mind that 'ignorecase' applies at execution time, thus [a-z] may
// need to be interpreted as [a-zA-Z].
-static int nfa_recognize_char_class(char_u *start, char_u *end, int extra_newl)
+static int nfa_recognize_char_class(uint8_t *start, uint8_t *end, int extra_newl)
{
#define CLASS_not 0x80
#define CLASS_af 0x40
@@ -582,7 +582,7 @@ static int nfa_recognize_char_class(char_u *start, char_u *end, int extra_newl)
#define CLASS_o9 0x02
#define CLASS_underscore 0x01
- char_u *p;
+ uint8_t *p;
int config = 0;
bool newl = extra_newl == true;
@@ -1788,9 +1788,9 @@ static int nfa_regatom(void)
int equiclass;
int collclass;
int got_coll_char;
- char_u *p;
- char_u *endp;
- char_u *old_regparse = (char_u *)regparse;
+ uint8_t *p;
+ uint8_t *endp;
+ uint8_t *old_regparse = (uint8_t *)regparse;
int extra = 0;
int emit_range;
int negated;
@@ -1873,7 +1873,7 @@ static int nfa_regatom(void)
case Magic('L'):
case Magic('u'):
case Magic('U'):
- p = (char_u *)vim_strchr((char *)classchars, no_Magic(c));
+ p = (uint8_t *)vim_strchr((char *)classchars, no_Magic(c));
if (p == NULL) {
if (extra == NFA_ADD_NL) {
semsg(_(e_ill_char_class), (int64_t)c);
@@ -1886,7 +1886,7 @@ static int nfa_regatom(void)
// When '.' is followed by a composing char ignore the dot, so that
// the composing char is matched here.
if (c == Magic('.') && utf_iscomposing(peekchr())) {
- old_regparse = (char_u *)regparse;
+ old_regparse = (uint8_t *)regparse;
c = getchr();
goto nfa_do_multibyte;
}
@@ -1932,7 +1932,7 @@ static int nfa_regatom(void)
return FAIL;
case Magic('~'): {
- char_u *lp;
+ uint8_t *lp;
// Previous substitute pattern.
// Generated as "\%(pattern\)".
@@ -1940,9 +1940,9 @@ static int nfa_regatom(void)
emsg(_(e_nopresub));
return FAIL;
}
- for (lp = (char_u *)reg_prev_sub; *lp != NUL; MB_CPTR_ADV(lp)) {
+ for (lp = (uint8_t *)reg_prev_sub; *lp != NUL; MB_CPTR_ADV(lp)) {
EMIT(utf_ptr2char((char *)lp));
- if (lp != (char_u *)reg_prev_sub) {
+ if (lp != (uint8_t *)reg_prev_sub) {
EMIT(NFA_CONCAT);
}
}
@@ -2217,13 +2217,13 @@ collection:
// - character classes NFA_CLASS_*
// - ranges, two characters followed by NFA_RANGE.
- p = (char_u *)regparse;
- endp = skip_anyof((char *)p);
+ p = (uint8_t *)regparse;
+ endp = (uint8_t *)skip_anyof((char *)p);
if (*endp == ']') {
// Try to reverse engineer character classes. For example,
// recognize that [0-9] stands for \d and [A-Za-z_] for \h,
// and perform the necessary substitutions in the NFA.
- int result = nfa_recognize_char_class((char_u *)regparse, endp, extra == NFA_ADD_NL);
+ int result = nfa_recognize_char_class((uint8_t *)regparse, endp, extra == NFA_ADD_NL);
if (result != FAIL) {
if (result >= NFA_FIRST_NL && result <= NFA_LAST_NL) {
EMIT(result - NFA_ADD_NL);
@@ -2255,7 +2255,7 @@ collection:
}
// Emit the OR branches for each character in the []
emit_range = false;
- while ((char_u *)regparse < endp) {
+ while ((uint8_t *)regparse < endp) {
int oldstartc = startc;
startc = -1;
got_coll_char = false;
@@ -2362,10 +2362,10 @@ collection:
// accepts "\t", "\e", etc., but only when the 'l' flag in
// 'cpoptions' is not included.
if (*regparse == '\\'
- && (char_u *)regparse + 1 <= endp
- && (vim_strchr(REGEXP_INRANGE, regparse[1]) != NULL
+ && (uint8_t *)regparse + 1 <= endp
+ && (vim_strchr(REGEXP_INRANGE, (uint8_t)regparse[1]) != NULL
|| (!reg_cpo_lit
- && vim_strchr(REGEXP_ABBR, regparse[1])
+ && vim_strchr(REGEXP_ABBR, (uint8_t)regparse[1])
!= NULL))) {
MB_PTR_ADV(regparse);
@@ -2927,7 +2927,7 @@ static int nfa_reg(int paren)
}
#ifdef REGEXP_DEBUG
-static char_u code[50];
+static uint8_t code[50];
static void nfa_set_code(int c)
{
@@ -3275,35 +3275,37 @@ static void nfa_set_code(int c)
}
static FILE *log_fd;
-static char_u e_log_open_failed[] =
+static uint8_t e_log_open_failed[] =
N_("Could not open temporary log file for writing, displaying on stderr... ");
// Print the postfix notation of the current regexp.
-static void nfa_postfix_dump(char_u *expr, int retval)
+static void nfa_postfix_dump(uint8_t *expr, int retval)
{
int *p;
FILE *f;
f = fopen(NFA_REGEXP_DUMP_LOG, "a");
- if (f != NULL) {
- fprintf(f, "\n-------------------------\n");
- if (retval == FAIL) {
- fprintf(f, ">>> NFA engine failed... \n");
- } else if (retval == OK) {
- fprintf(f, ">>> NFA engine succeeded !\n");
- }
- fprintf(f, "Regexp: \"%s\"\nPostfix notation (char): \"", expr);
- for (p = post_start; *p && p < post_ptr; p++) {
- nfa_set_code(*p);
- fprintf(f, "%s, ", code);
- }
- fprintf(f, "\"\nPostfix notation (int): ");
- for (p = post_start; *p && p < post_ptr; p++) {
- fprintf(f, "%d ", *p);
- }
- fprintf(f, "\n\n");
- fclose(f);
+ if (f == NULL) {
+ return;
}
+
+ fprintf(f, "\n-------------------------\n");
+ if (retval == FAIL) {
+ fprintf(f, ">>> NFA engine failed... \n");
+ } else if (retval == OK) {
+ fprintf(f, ">>> NFA engine succeeded !\n");
+ }
+ fprintf(f, "Regexp: \"%s\"\nPostfix notation (char): \"", expr);
+ for (p = post_start; *p && p < post_ptr; p++) {
+ nfa_set_code(*p);
+ fprintf(f, "%s, ", code);
+ }
+ fprintf(f, "\"\nPostfix notation (int): ");
+ for (p = post_start; *p && p < post_ptr; p++) {
+ fprintf(f, "%d ", *p);
+ }
+ fprintf(f, "\n\n");
+ fclose(f);
}
// Print the NFA starting with a root node "state".
@@ -3319,7 +3321,7 @@ static void nfa_print_state(FILE *debugf, nfa_state_T *state)
static void nfa_print_state2(FILE *debugf, nfa_state_T *state, garray_T *indent)
{
- char_u *p;
+ uint8_t *p;
if (state == NULL) {
return;
@@ -3328,10 +3330,10 @@ static void nfa_print_state2(FILE *debugf, nfa_state_T *state, garray_T *indent)
fprintf(debugf, "(%2d)", abs(state->id));
// Output indent
- p = (char_u *)indent->ga_data;
+ p = (uint8_t *)indent->ga_data;
if (indent->ga_len >= 3) {
int last = indent->ga_len - 3;
- char_u save[2];
+ uint8_t save[2];
strncpy(save, &p[last], 2); // NOLINT(runtime/printf)
memcpy(&p[last], "+-", 2);
@@ -3356,9 +3358,9 @@ static void nfa_print_state2(FILE *debugf, nfa_state_T *state, garray_T *indent)
// grow indent for state->out
indent->ga_len -= 1;
if (state->out1) {
- ga_concat(indent, (char_u *)"| ");
+ ga_concat(indent, (uint8_t *)"| ");
} else {
- ga_concat(indent, (char_u *)" ");
+ ga_concat(indent, (uint8_t *)" ");
}
ga_append(indent, NUL);
@@ -3366,7 +3368,7 @@ static void nfa_print_state2(FILE *debugf, nfa_state_T *state, garray_T *indent)
// replace last part of indent for state->out1
indent->ga_len -= 3;
- ga_concat(indent, (char_u *)" ");
+ ga_concat(indent, (uint8_t *)" ");
ga_append(indent, NUL);
nfa_print_state2(debugf, state->out1, indent);
@@ -3381,22 +3383,24 @@ static void nfa_dump(nfa_regprog_T *prog)
{
FILE *debugf = fopen(NFA_REGEXP_DUMP_LOG, "a");
- if (debugf != NULL) {
- nfa_print_state(debugf, prog->start);
+ if (debugf == NULL) {
+ return;
+ }
- if (prog->reganch) {
- fprintf(debugf, "reganch: %d\n", prog->reganch);
- }
- if (prog->regstart != NUL) {
- fprintf(debugf, "regstart: %c (decimal: %d)\n",
- prog->regstart, prog->regstart);
- }
- if (prog->match_text != NULL) {
- fprintf(debugf, "match_text: \"%s\"\n", prog->match_text);
- }
+ nfa_print_state(debugf, prog->start);
- fclose(debugf);
+ if (prog->reganch) {
+ fprintf(debugf, "reganch: %d\n", prog->reganch);
+ }
+ if (prog->regstart != NUL) {
+ fprintf(debugf, "regstart: %c (decimal: %d)\n",
+ prog->regstart, prog->regstart);
}
+ if (prog->match_text != NULL) {
+ fprintf(debugf, "match_text: \"%s\"\n", prog->match_text);
+ }
+
+ fclose(debugf);
}
#endif // REGEXP_DEBUG
@@ -4427,16 +4431,18 @@ static void clear_sub(regsub_T *sub)
static void copy_sub(regsub_T *to, regsub_T *from)
{
to->in_use = from->in_use;
- if (from->in_use > 0) {
- // Copy the match start and end positions.
- if (REG_MULTI) {
- memmove(&to->list.multi[0], &from->list.multi[0],
- sizeof(struct multipos) * (size_t)from->in_use);
- to->orig_start_col = from->orig_start_col;
- } else {
- memmove(&to->list.line[0], &from->list.line[0],
- sizeof(struct linepos) * (size_t)from->in_use);
- }
+ if (from->in_use <= 0) {
+ return;
+ }
+
+ // Copy the match start and end positions.
+ if (REG_MULTI) {
+ memmove(&to->list.multi[0], &from->list.multi[0],
+ sizeof(struct multipos) * (size_t)from->in_use);
+ to->orig_start_col = from->orig_start_col;
+ } else {
+ memmove(&to->list.line[0], &from->list.line[0],
+ sizeof(struct linepos) * (size_t)from->in_use);
}
}
@@ -4446,31 +4452,35 @@ static void copy_sub_off(regsub_T *to, regsub_T *from)
if (to->in_use < from->in_use) {
to->in_use = from->in_use;
}
- if (from->in_use > 1) {
- // Copy the match start and end positions.
- if (REG_MULTI) {
- memmove(&to->list.multi[1], &from->list.multi[1],
- sizeof(struct multipos) * (size_t)(from->in_use - 1));
- } else {
- memmove(&to->list.line[1], &from->list.line[1],
- sizeof(struct linepos) * (size_t)(from->in_use - 1));
- }
+ if (from->in_use <= 1) {
+ return;
+ }
+
+ // Copy the match start and end positions.
+ if (REG_MULTI) {
+ memmove(&to->list.multi[1], &from->list.multi[1],
+ sizeof(struct multipos) * (size_t)(from->in_use - 1));
+ } else {
+ memmove(&to->list.line[1], &from->list.line[1],
+ sizeof(struct linepos) * (size_t)(from->in_use - 1));
}
}
// Like copy_sub() but only do the end of the main match if \ze is present.
static void copy_ze_off(regsub_T *to, regsub_T *from)
{
- if (rex.nfa_has_zend) {
- if (REG_MULTI) {
- if (from->list.multi[0].end_lnum >= 0) {
- to->list.multi[0].end_lnum = from->list.multi[0].end_lnum;
- to->list.multi[0].end_col = from->list.multi[0].end_col;
- }
- } else {
- if (from->list.line[0].end != NULL) {
- to->list.line[0].end = from->list.line[0].end;
- }
+ if (!rex.nfa_has_zend) {
+ return;
+ }
+
+ if (REG_MULTI) {
+ if (from->list.multi[0].end_lnum >= 0) {
+ to->list.multi[0].end_lnum = from->list.multi[0].end_lnum;
+ to->list.multi[0].end_col = from->list.multi[0].end_col;
+ }
+ } else {
+ if (from->list.line[0].end != NULL) {
+ to->list.line[0].end = from->list.line[0].end;
}
}
}
@@ -4483,8 +4493,8 @@ static bool sub_equal(regsub_T *sub1, regsub_T *sub2)
int todo;
linenr_T s1;
linenr_T s2;
- char_u *sp1;
- char_u *sp2;
+ uint8_t *sp1;
+ uint8_t *sp2;
todo = sub1->in_use > sub2->in_use ? sub1->in_use : sub2->in_use;
if (REG_MULTI) {
@@ -4779,7 +4789,7 @@ static regsubs_T *addstate(nfa_list_T *l, nfa_state_T *state, regsubs_T *subs_ar
nfa_thread_T *thread;
struct multipos save_multipos;
int save_in_use;
- char_u *save_ptr;
+ uint8_t *save_ptr;
int i;
regsub_T *sub;
regsubs_T *subs = subs_arg;
@@ -5522,10 +5532,10 @@ static int recursive_regmatch(nfa_state_T *state, nfa_pim_T *pim, nfa_regprog_T
// bytes if possible.
if (state->val <= 0) {
if (REG_MULTI) {
- rex.line = reg_getline(--rex.lnum);
+ rex.line = (uint8_t *)reg_getline(--rex.lnum);
if (rex.line == NULL) {
// can't go before the first line
- rex.line = reg_getline(++rex.lnum);
+ rex.line = (uint8_t *)reg_getline(++rex.lnum);
}
}
rex.input = rex.line;
@@ -5533,10 +5543,10 @@ static int recursive_regmatch(nfa_state_T *state, nfa_pim_T *pim, nfa_regprog_T
if (REG_MULTI && (int)(rex.input - rex.line) < state->val) {
// Not enough bytes in this line, go to end of
// previous line.
- rex.line = reg_getline(--rex.lnum);
+ rex.line = (uint8_t *)reg_getline(--rex.lnum);
if (rex.line == NULL) {
// can't go before the first line
- rex.line = reg_getline(++rex.lnum);
+ rex.line = (uint8_t *)reg_getline(++rex.lnum);
rex.input = rex.line;
} else {
rex.input = rex.line + strlen((char *)rex.line);
@@ -5595,7 +5605,7 @@ static int recursive_regmatch(nfa_state_T *state, nfa_pim_T *pim, nfa_regprog_T
// restore position in input text
rex.lnum = save_reglnum;
if (REG_MULTI) {
- rex.line = reg_getline(rex.lnum);
+ rex.line = (uint8_t *)reg_getline(rex.lnum);
}
rex.input = rex.line + save_reginput_col;
if (result != NFA_TOO_EXPENSIVE) {
@@ -5772,7 +5782,7 @@ static int failure_chance(nfa_state_T *state, int depth)
// Skip until the char "c" we know a match must start with.
static int skip_to_start(int c, colnr_T *colp)
{
- const char_u *const s = cstrchr(rex.line + *colp, c);
+ const uint8_t *const s = (uint8_t *)cstrchr((char *)rex.line + *colp, c);
if (s == NULL) {
return FAIL;
}
@@ -5783,7 +5793,7 @@ static int skip_to_start(int c, colnr_T *colp)
// Check for a match with match_text.
// Called after skip_to_start() has found regstart.
// Returns zero for no match, 1 for a match.
-static long find_match_text(colnr_T *startcol, int regstart, char_u *match_text)
+static long find_match_text(colnr_T *startcol, int regstart, uint8_t *match_text)
{
#define PTR2LEN(x) utf_ptr2len(x)
@@ -5792,8 +5802,8 @@ static long find_match_text(colnr_T *startcol, int regstart, char_u *match_text)
for (;;) {
bool match = true;
- char_u *s1 = match_text;
- char_u *s2 = rex.line + col + regstart_len; // skip regstart
+ uint8_t *s1 = match_text;
+ uint8_t *s2 = rex.line + col + regstart_len; // skip regstart
while (*s1) {
int c1_len = PTR2LEN((char *)s1);
int c1 = utf_ptr2char((char *)s1);
@@ -6860,7 +6870,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
// Line may have been freed, get it again.
if (REG_MULTI) {
- rex.line = reg_getline(rex.lnum);
+ rex.line = (uint8_t *)reg_getline(rex.lnum);
rex.input = rex.line + col;
}
@@ -7298,15 +7308,15 @@ static long nfa_regtry(nfa_regprog_T *prog, colnr_T col, proftime_T *tm, int *ti
&& mpos->start_lnum == mpos->end_lnum
&& mpos->end_col >= mpos->start_col) {
re_extmatch_out->matches[i] =
- (char_u *)xstrnsave((char *)reg_getline(mpos->start_lnum) + mpos->start_col,
- (size_t)(mpos->end_col - mpos->start_col));
+ (uint8_t *)xstrnsave((char *)reg_getline(mpos->start_lnum) + mpos->start_col,
+ (size_t)(mpos->end_col - mpos->start_col));
}
} else {
struct linepos *lpos = &subs.synt.list.line[i];
if (lpos->start != NULL && lpos->end != NULL) {
re_extmatch_out->matches[i] =
- (char_u *)xstrnsave((char *)lpos->start, (size_t)(lpos->end - lpos->start));
+ (uint8_t *)xstrnsave((char *)lpos->start, (size_t)(lpos->end - lpos->start));
}
}
}
@@ -7325,7 +7335,7 @@ static long nfa_regtry(nfa_regprog_T *prog, colnr_T col, proftime_T *tm, int *ti
///
/// @return <= 0 if there is no match and number of lines contained in the
/// match otherwise.
-static long nfa_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm, int *timed_out)
+static long nfa_regexec_both(uint8_t *line, colnr_T startcol, proftime_T *tm, int *timed_out)
{
nfa_regprog_T *prog;
long retval = 0L;
@@ -7333,13 +7343,13 @@ static long nfa_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm, int
if (REG_MULTI) {
prog = (nfa_regprog_T *)rex.reg_mmatch->regprog;
- line = reg_getline((linenr_T)0); // relative to the cursor
+ line = (uint8_t *)reg_getline((linenr_T)0); // relative to the cursor
rex.reg_startpos = rex.reg_mmatch->startpos;
rex.reg_endpos = rex.reg_mmatch->endpos;
} else {
prog = (nfa_regprog_T *)rex.reg_match->regprog;
- rex.reg_startp = (char_u **)rex.reg_match->startp;
- rex.reg_endp = (char_u **)rex.reg_match->endp;
+ rex.reg_startp = (uint8_t **)rex.reg_match->startp;
+ rex.reg_endp = (uint8_t **)rex.reg_match->endp;
}
// Be paranoid...
@@ -7454,7 +7464,7 @@ theend:
// Compile a regular expression into internal code for the NFA matcher.
// Returns the program in allocated space. Returns NULL for an error.
-static regprog_T *nfa_regcomp(char_u *expr, int re_flags)
+static regprog_T *nfa_regcomp(uint8_t *expr, int re_flags)
{
nfa_regprog_T *prog = NULL;
int *postfix;
@@ -7501,7 +7511,7 @@ static regprog_T *nfa_regcomp(char_u *expr, int re_flags)
post2nfa(postfix, post_ptr, true);
// allocate the regprog with space for the compiled regexp
- size_t prog_size = sizeof(nfa_regprog_T) + sizeof(nfa_state_T) * (size_t)(nstate - 1);
+ size_t prog_size = offsetof(nfa_regprog_T, state) + sizeof(nfa_state_T) * (size_t)nstate;
prog = xmalloc(prog_size);
state_ptr = prog->state;
prog->re_in_use = false;
@@ -7554,11 +7564,13 @@ fail:
// Free a compiled regexp program, returned by nfa_regcomp().
static void nfa_regfree(regprog_T *prog)
{
- if (prog != NULL) {
- xfree(((nfa_regprog_T *)prog)->match_text);
- xfree(((nfa_regprog_T *)prog)->pattern);
- xfree(prog);
+ if (prog == NULL) {
+ return;
}
+
+ xfree(((nfa_regprog_T *)prog)->match_text);
+ xfree(((nfa_regprog_T *)prog)->pattern);
+ xfree(prog);
}
/// Match a regexp against a string.
@@ -7570,7 +7582,7 @@ static void nfa_regfree(regprog_T *prog)
/// @param col column to start looking for match
///
/// @return <= 0 for failure, number of lines contained in the match otherwise.
-static int nfa_regexec_nl(regmatch_T *rmp, char_u *line, colnr_T col, bool line_lbr)
+static int nfa_regexec_nl(regmatch_T *rmp, uint8_t *line, colnr_T col, bool line_lbr)
{
rex.reg_match = rmp;
rex.reg_mmatch = NULL;
diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c
index e009b883ca..b071e10cf9 100644
--- a/src/nvim/runtime.c
+++ b/src/nvim/runtime.c
@@ -9,7 +9,6 @@
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
-#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <uv.h>
@@ -27,6 +26,7 @@
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_eval.h"
+#include "nvim/garray.h"
#include "nvim/getchar.h"
#include "nvim/gettext.h"
#include "nvim/globals.h"
@@ -105,7 +105,7 @@ estack_T *estack_push(etype_T type, char *name, linenr_T lnum)
void estack_push_ufunc(ufunc_T *ufunc, linenr_T lnum)
{
estack_T *entry = estack_push(ETYPE_UFUNC,
- ufunc->uf_name_exp != NULL ? (char *)ufunc->uf_name_exp : ufunc->uf_name,
+ ufunc->uf_name_exp != NULL ? ufunc->uf_name_exp : ufunc->uf_name,
lnum);
if (entry != NULL) {
entry->es_info.ufunc = ufunc;
@@ -209,29 +209,56 @@ void runtime_init(void)
uv_mutex_init(&runtime_search_path_mutex);
}
-/// ":runtime [what] {name}"
+/// Get DIP_ flags from the [where] argument of a :runtime command.
+/// "*argp" is advanced to after the [where] argument.
+static int get_runtime_cmd_flags(char **argp, size_t where_len)
+{
+ char *arg = *argp;
+
+ if (where_len == 0) {
+ return 0;
+ }
+
+ if (strncmp(arg, "START", where_len) == 0) {
+ *argp = skipwhite(arg + where_len);
+ return DIP_START + DIP_NORTP;
+ }
+ if (strncmp(arg, "OPT", where_len) == 0) {
+ *argp = skipwhite(arg + where_len);
+ return DIP_OPT + DIP_NORTP;
+ }
+ if (strncmp(arg, "PACK", where_len) == 0) {
+ *argp = skipwhite(arg + where_len);
+ return DIP_START + DIP_OPT + DIP_NORTP;
+ }
+ if (strncmp(arg, "ALL", where_len) == 0) {
+ *argp = skipwhite(arg + where_len);
+ return DIP_START + DIP_OPT;
+ }
+
+ return 0;
+}
+
+/// ":runtime [where] {name}"
void ex_runtime(exarg_T *eap)
{
char *arg = eap->arg;
- char *p = skiptowhite(arg);
- size_t len = (size_t)(p - arg);
int flags = eap->forceit ? DIP_ALL : 0;
+ char *p = skiptowhite(arg);
+ flags += get_runtime_cmd_flags(&arg, (size_t)(p - arg));
+ source_runtime(arg, flags);
+}
- if (strncmp(arg, "START", len) == 0) {
- flags += DIP_START + DIP_NORTP;
- arg = skipwhite(arg + len);
- } else if (strncmp(arg, "OPT", len) == 0) {
- flags += DIP_OPT + DIP_NORTP;
- arg = skipwhite(arg + len);
- } else if (strncmp(arg, "PACK", len) == 0) {
- flags += DIP_START + DIP_OPT + DIP_NORTP;
- arg = skipwhite(arg + len);
- } else if (strncmp(arg, "ALL", len) == 0) {
- flags += DIP_START + DIP_OPT;
- arg = skipwhite(arg + len);
- }
+static int runtime_expand_flags;
- source_runtime(arg, flags);
+/// Set the completion context for the :runtime command.
+void set_context_in_runtime_cmd(expand_T *xp, const char *arg)
+{
+ char *p = skiptowhite(arg);
+ runtime_expand_flags
+ = *p != NUL ? get_runtime_cmd_flags((char **)&arg, (size_t)(p - arg)) : 0;
+ xp->xp_context = EXPAND_RUNTIME;
+ xp->xp_pattern = (char *)arg;
}
static void source_callback(char *fname, void *cookie)
@@ -822,12 +849,14 @@ static void source_all_matches(char *pat)
int num_files;
char **files;
- if (gen_expand_wildcards(1, &pat, &num_files, &files, EW_FILE) == OK) {
- for (int i = 0; i < num_files; i++) {
- (void)do_source(files[i], false, DOSO_NONE);
- }
- FreeWild(num_files, files);
+ if (gen_expand_wildcards(1, &pat, &num_files, &files, EW_FILE) != OK) {
+ return;
+ }
+
+ for (int i = 0; i < num_files; i++) {
+ (void)do_source(files[i], false, DOSO_NONE);
}
+ FreeWild(num_files, files);
}
/// Add the package directory to 'runtimepath'
@@ -1174,124 +1203,154 @@ void ex_packadd(exarg_T *eap)
}
}
-/// Expand color scheme, compiler or filetype names.
-/// Search from 'runtimepath':
-/// 'runtimepath'/{dirnames}/{pat}.vim
-/// When "flags" has DIP_START: search also from 'start' of 'packpath':
-/// 'packpath'/pack/ * /start/ * /{dirnames}/{pat}.vim
-/// When "flags" has DIP_OPT: search also from 'opt' of 'packpath':
-/// 'packpath'/pack/ * /opt/ * /{dirnames}/{pat}.vim
-/// When "flags" has DIP_LUA: search also performed for .lua files
-/// "dirnames" is an array with one or more directory names.
-int ExpandRTDir(char *pat, int flags, int *num_file, char ***file, char *dirnames[])
+static void ExpandRTDir_int(char *pat, size_t pat_len, int flags, bool keep_ext, garray_T *gap,
+ char *dirnames[])
{
- *num_file = 0;
- *file = NULL;
- size_t pat_len = strlen(pat);
-
- garray_T ga;
- ga_init(&ga, (int)sizeof(char *), 10);
-
- // TODO(bfredl): this is bullshit, exandpath should not reinvent path logic.
+ // TODO(bfredl): this is bullshit, expandpath should not reinvent path logic.
for (int i = 0; dirnames[i] != NULL; i++) {
- size_t size = strlen(dirnames[i]) + pat_len + 7;
- char *s = xmalloc(size);
- snprintf(s, size, "%s/%s*.vim", dirnames[i], pat);
- globpath(p_rtp, s, &ga, 0);
- if (flags & DIP_LUA) {
- snprintf(s, size, "%s/%s*.lua", dirnames[i], pat);
- globpath(p_rtp, s, &ga, 0);
+ const size_t buf_len = strlen(dirnames[i]) + pat_len + 31;
+ char *const buf = xmalloc(buf_len);
+ char *const tail = buf + 15;
+ const size_t tail_buflen = buf_len - 15;
+ int glob_flags = 0;
+ bool expand_dirs = false;
+
+ if (*dirnames[i] == NUL) { // empty dir used for :runtime
+ snprintf(tail, tail_buflen, "%s*.\\(vim\\|lua\\)", pat);
+ } else {
+ snprintf(tail, tail_buflen, "%s/%s*.\\(vim\\|lua\\)", dirnames[i], pat);
}
- xfree(s);
- }
- if (flags & DIP_START) {
- for (int i = 0; dirnames[i] != NULL; i++) {
- size_t size = strlen(dirnames[i]) + pat_len + 22;
- char *s = xmalloc(size);
- snprintf(s, size, "pack/*/start/*/%s/%s*.vim", dirnames[i], pat); // NOLINT
- globpath(p_pp, s, &ga, 0);
- if (flags & DIP_LUA) {
- snprintf(s, size, "pack/*/start/*/%s/%s*.lua", dirnames[i], pat); // NOLINT
- globpath(p_pp, s, &ga, 0);
- }
- xfree(s);
+expand:
+ if ((flags & DIP_NORTP) == 0) {
+ globpath(p_rtp, tail, gap, glob_flags, expand_dirs);
}
- for (int i = 0; dirnames[i] != NULL; i++) {
- size_t size = strlen(dirnames[i]) + pat_len + 22;
- char *s = xmalloc(size);
- snprintf(s, size, "start/*/%s/%s*.vim", dirnames[i], pat); // NOLINT
- globpath(p_pp, s, &ga, 0);
- if (flags & DIP_LUA) {
- snprintf(s, size, "start/*/%s/%s*.lua", dirnames[i], pat); // NOLINT
- globpath(p_pp, s, &ga, 0);
- }
- xfree(s);
+ if (flags & DIP_START) {
+ memcpy(tail - 15, "pack/*/start/*/", 15); // NOLINT
+ globpath(p_pp, tail - 15, gap, glob_flags, expand_dirs);
+ memcpy(tail - 8, "start/*/", 8); // NOLINT
+ globpath(p_pp, tail - 8, gap, glob_flags, expand_dirs);
}
- }
- if (flags & DIP_OPT) {
- for (int i = 0; dirnames[i] != NULL; i++) {
- size_t size = strlen(dirnames[i]) + pat_len + 20;
- char *s = xmalloc(size);
- snprintf(s, size, "pack/*/opt/*/%s/%s*.vim", dirnames[i], pat); // NOLINT
- globpath(p_pp, s, &ga, 0);
- if (flags & DIP_LUA) {
- snprintf(s, size, "pack/*/opt/*/%s/%s*.lua", dirnames[i], pat); // NOLINT
- globpath(p_pp, s, &ga, 0);
- }
- xfree(s);
+ if (flags & DIP_OPT) {
+ memcpy(tail - 13, "pack/*/opt/*/", 13); // NOLINT
+ globpath(p_pp, tail - 13, gap, glob_flags, expand_dirs);
+ memcpy(tail - 6, "opt/*/", 6); // NOLINT
+ globpath(p_pp, tail - 6, gap, glob_flags, expand_dirs);
}
- for (int i = 0; dirnames[i] != NULL; i++) {
- size_t size = strlen(dirnames[i]) + pat_len + 20;
- char *s = xmalloc(size);
- snprintf(s, size, "opt/*/%s/%s*.vim", dirnames[i], pat); // NOLINT
- globpath(p_pp, s, &ga, 0);
- if (flags & DIP_LUA) {
- snprintf(s, size, "opt/*/%s/%s*.lua", dirnames[i], pat); // NOLINT
- globpath(p_pp, s, &ga, 0);
- }
- xfree(s);
+ if (*dirnames[i] == NUL && !expand_dirs) {
+ // expand dir names in another round
+ snprintf(tail, tail_buflen, "%s*", pat);
+ glob_flags = WILD_ADD_SLASH;
+ expand_dirs = true;
+ goto expand;
+ }
+
+ xfree(buf);
+ }
+
+ int pat_pathsep_cnt = 0;
+ for (size_t i = 0; i < pat_len; i++) {
+ if (vim_ispathsep(pat[i])) {
+ pat_pathsep_cnt++;
}
}
- for (int i = 0; i < ga.ga_len; i++) {
- char *match = ((char **)ga.ga_data)[i];
+ for (int i = 0; i < gap->ga_len; i++) {
+ char *match = ((char **)gap->ga_data)[i];
char *s = match;
char *e = s + strlen(s);
- if (e - s > 4 && (STRNICMP(e - 4, ".vim", 4) == 0
- || ((flags & DIP_LUA)
- && STRNICMP(e - 4, ".lua", 4) == 0))) {
+ if (e - s > 4 && !keep_ext && (STRNICMP(e - 4, ".vim", 4) == 0
+ || STRNICMP(e - 4, ".lua", 4) == 0)) {
e -= 4;
- for (s = e; s > match; MB_PTR_BACK(match, s)) {
- if (vim_ispathsep(*s)) {
- break;
- }
- }
- s++;
*e = NUL;
+ }
+
+ int match_pathsep_cnt = (e > s && e[-1] == '/') ? -1 : 0;
+ for (s = e; s > match; MB_PTR_BACK(match, s)) {
+ if (vim_ispathsep(*s) && ++match_pathsep_cnt > pat_pathsep_cnt) {
+ break;
+ }
+ }
+ s++;
+ if (s != match) {
assert((e - s) + 1 >= 0);
memmove(match, s, (size_t)(e - s) + 1);
}
}
- if (GA_EMPTY(&ga)) {
- return FAIL;
+ if (GA_EMPTY(gap)) {
+ return;
}
// Sort and remove duplicates which can happen when specifying multiple
// directories in dirnames.
- ga_remove_duplicate_strings(&ga);
+ ga_remove_duplicate_strings(gap);
+}
+
+/// Expand color scheme, compiler or filetype names.
+/// Search from 'runtimepath':
+/// 'runtimepath'/{dirnames}/{pat}.(vim|lua)
+/// When "flags" has DIP_START: search also from "start" of 'packpath':
+/// 'packpath'/pack/*/start/*/{dirnames}/{pat}.(vim|lua)
+/// When "flags" has DIP_OPT: search also from "opt" of 'packpath':
+/// 'packpath'/pack/*/opt/*/{dirnames}/{pat}.(vim|lua)
+/// "dirnames" is an array with one or more directory names.
+int ExpandRTDir(char *pat, int flags, int *num_file, char ***file, char *dirnames[])
+{
+ *num_file = 0;
+ *file = NULL;
+
+ garray_T ga;
+ ga_init(&ga, (int)sizeof(char *), 10);
+
+ ExpandRTDir_int(pat, strlen(pat), flags, false, &ga, dirnames);
+
+ if (GA_EMPTY(&ga)) {
+ return FAIL;
+ }
*file = ga.ga_data;
*num_file = ga.ga_len;
return OK;
}
+/// Handle command line completion for :runtime command.
+int expand_runtime_cmd(char *pat, int *numMatches, char ***matches)
+{
+ *numMatches = 0;
+ *matches = NULL;
+
+ garray_T ga;
+ ga_init(&ga, sizeof(char *), 10);
+
+ const size_t pat_len = strlen(pat);
+ char *dirnames[] = { "", NULL };
+ ExpandRTDir_int(pat, pat_len, runtime_expand_flags, true, &ga, dirnames);
+
+ // Try to complete values for [where] argument when none was found.
+ if (runtime_expand_flags == 0) {
+ char *where_values[] = { "START", "OPT", "PACK", "ALL" };
+ for (size_t i = 0; i < ARRAY_SIZE(where_values); i++) {
+ if (strncmp(pat, where_values[i], pat_len) == 0) {
+ GA_APPEND(char *, &ga, xstrdup(where_values[i]));
+ }
+ }
+ }
+
+ if (GA_EMPTY(&ga)) {
+ return FAIL;
+ }
+
+ *matches = ga.ga_data;
+ *numMatches = ga.ga_len;
+ return OK;
+}
+
/// Expand loadplugin names:
-/// 'packpath'/pack/ * /opt/{pat}
+/// 'packpath'/pack/*/opt/{pat}
int ExpandPackAddDir(char *pat, int *num_file, char ***file)
{
garray_T ga;
@@ -1304,9 +1363,9 @@ int ExpandPackAddDir(char *pat, int *num_file, char ***file)
size_t buflen = pat_len + 26;
char *s = xmalloc(buflen);
snprintf(s, buflen, "pack/*/opt/%s*", pat); // NOLINT
- globpath(p_pp, s, &ga, 0);
+ globpath(p_pp, s, &ga, 0, true);
snprintf(s, buflen, "opt/%s*", pat); // NOLINT
- globpath(p_pp, s, &ga, 0);
+ globpath(p_pp, s, &ga, 0, true);
xfree(s);
for (int i = 0; i < ga.ga_len; i++) {
@@ -2161,12 +2220,17 @@ scriptitem_T *get_current_script_id(char **fnamep, sctx_T *ret_sctx)
/// ":scriptnames"
void ex_scriptnames(exarg_T *eap)
{
- if (eap->addr_count > 0) {
+ if (eap->addr_count > 0 || *eap->arg != NUL) {
// :script {scriptId}: edit the script
- if (eap->line2 < 1 || eap->line2 > script_items.ga_len) {
+ if (eap->addr_count > 0 && !SCRIPT_ID_VALID(eap->line2)) {
emsg(_(e_invarg));
} else {
- eap->arg = SCRIPT_ITEM(eap->line2).sn_name;
+ if (eap->addr_count > 0) {
+ eap->arg = SCRIPT_ITEM(eap->line2).sn_name;
+ } else {
+ expand_env(eap->arg, NameBuff, MAXPATHL);
+ eap->arg = NameBuff;
+ }
do_exedit(eap, NULL);
}
return;
diff --git a/src/nvim/runtime.h b/src/nvim/runtime.h
index de363020f8..97063b900c 100644
--- a/src/nvim/runtime.h
+++ b/src/nvim/runtime.h
@@ -105,7 +105,6 @@ typedef kvec_t(char *) CharVec;
#define DIP_NORTP 0x20 // do not use 'runtimepath'
#define DIP_NOAFTER 0x40 // skip "after" directories
#define DIP_AFTER 0x80 // only use "after" directories
-#define DIP_LUA 0x100 // also use ".lua" files
#define DIP_DIRFILE 0x200 // find both files and directories
#ifdef INCLUDE_GENERATED_DECLARATIONS
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index b18bf7ed6a..05da6e0ef1 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -295,52 +295,54 @@ bool get_keymap_str(win_T *wp, char *fmt, char *buf, int len)
return false;
}
- {
- buf_T *old_curbuf = curbuf;
- win_T *old_curwin = curwin;
- char *s;
-
- curbuf = wp->w_buffer;
- curwin = wp;
- STRCPY(buf, "b:keymap_name"); // must be writable
- emsg_skip++;
- s = p = eval_to_string(buf, NULL, false);
- emsg_skip--;
- curbuf = old_curbuf;
- curwin = old_curwin;
- if (p == NULL || *p == NUL) {
- if (wp->w_buffer->b_kmap_state & KEYMAP_LOADED) {
- p = wp->w_buffer->b_p_keymap;
- } else {
- p = "lang";
- }
- }
- if (vim_snprintf(buf, (size_t)len, fmt, p) > len - 1) {
- buf[0] = NUL;
+ buf_T *old_curbuf = curbuf;
+ win_T *old_curwin = curwin;
+ char *s;
+
+ curbuf = wp->w_buffer;
+ curwin = wp;
+ STRCPY(buf, "b:keymap_name"); // must be writable
+ emsg_skip++;
+ s = p = eval_to_string(buf, NULL, false);
+ emsg_skip--;
+ curbuf = old_curbuf;
+ curwin = old_curwin;
+ if (p == NULL || *p == NUL) {
+ if (wp->w_buffer->b_kmap_state & KEYMAP_LOADED) {
+ p = wp->w_buffer->b_p_keymap;
+ } else {
+ p = "lang";
}
- xfree(s);
}
+ if (vim_snprintf(buf, (size_t)len, fmt, p) > len - 1) {
+ buf[0] = NUL;
+ }
+ xfree(s);
return buf[0] != NUL;
}
/// Prepare for 'hlsearch' highlighting.
void start_search_hl(void)
{
- if (p_hls && !no_hlsearch) {
- end_search_hl(); // just in case it wasn't called before
- last_pat_prog(&screen_search_hl.rm);
- // Set the time limit to 'redrawtime'.
- screen_search_hl.tm = profile_setlimit(p_rdt);
+ if (!p_hls || no_hlsearch) {
+ return;
}
+
+ end_search_hl(); // just in case it wasn't called before
+ last_pat_prog(&screen_search_hl.rm);
+ // Set the time limit to 'redrawtime'.
+ screen_search_hl.tm = profile_setlimit(p_rdt);
}
/// Clean up for 'hlsearch' highlighting.
void end_search_hl(void)
{
- if (screen_search_hl.rm.regprog != NULL) {
- vim_regfree(screen_search_hl.rm.regprog);
- screen_search_hl.rm.regprog = NULL;
+ if (screen_search_hl.rm.regprog == NULL) {
+ return;
}
+
+ vim_regfree(screen_search_hl.rm.regprog);
+ screen_search_hl.rm.regprog = NULL;
}
/// Check if there should be a delay. Used before clearing or redrawing the
@@ -671,11 +673,13 @@ void clearmode(void)
static void recording_mode(int attr)
{
msg_puts_attr(_("recording"), attr);
- if (!shortmess(SHM_RECORDING)) {
- char s[4];
- snprintf(s, ARRAY_SIZE(s), " @%c", reg_recording);
- msg_puts_attr(s, attr);
+ if (shortmess(SHM_RECORDING)) {
+ return;
}
+
+ char s[4];
+ snprintf(s, ARRAY_SIZE(s), " @%c", reg_recording);
+ msg_puts_attr(s, attr);
}
void get_trans_bufname(buf_T *buf)
@@ -764,7 +768,6 @@ void comp_col(void)
/// Otherwise it depends on 'numberwidth' and the line count.
int number_width(win_T *wp)
{
- int n;
linenr_T lnum;
if (wp->w_p_rnu && !wp->w_p_nu) {
@@ -780,17 +783,13 @@ int number_width(win_T *wp)
}
wp->w_nrwidth_line_count = lnum;
- // make best estimate for 'statuscolumn'
+ // reset for 'statuscolumn'
if (*wp->w_p_stc != NUL) {
- char buf[MAXPATHL];
- wp->w_nrwidth_width = 0;
- n = build_statuscol_str(wp, true, false, lnum, 0, 0, NUL, buf, NULL, NULL);
- n = MAX(n, (wp->w_p_nu || wp->w_p_rnu) * (int)wp->w_p_nuw);
- wp->w_nrwidth_width = MIN(n, MAX_NUMBERWIDTH);
+ wp->w_nrwidth_width = (wp->w_p_nu || wp->w_p_rnu) * (int)wp->w_p_nuw;
return wp->w_nrwidth_width;
}
- n = 0;
+ int n = 0;
do {
lnum /= 10;
n++;
@@ -815,15 +814,15 @@ int number_width(win_T *wp)
/// Calls mb_cptr2char_adv(p) and returns the character.
/// If "p" starts with "\x", "\u" or "\U" the hex or unicode value is used.
/// Returns 0 for invalid hex or invalid UTF-8 byte.
-static int get_encoded_char_adv(const char_u **p)
+static int get_encoded_char_adv(const char **p)
{
- const char *s = (const char *)(*p);
+ const char *s = *p;
if (s[0] == '\\' && (s[1] == 'x' || s[1] == 'u' || s[1] == 'U')) {
int64_t num = 0;
for (int bytes = s[1] == 'x' ? 1 : s[1] == 'u' ? 2 : 4; bytes > 0; bytes--) {
*p += 2;
- int n = hexhex2nr((char *)(*p));
+ int n = hexhex2nr(*p);
if (n < 0) {
return 0;
}
@@ -952,7 +951,7 @@ char *set_chars_option(win_T *wp, char **varp, bool apply)
if (strncmp(p, tab[i].name, len) == 0
&& p[len] == ':'
&& p[len + 1] != NUL) {
- const char_u *s = (char_u *)p + len + 1;
+ const char *s = p + len + 1;
int c1 = get_encoded_char_adv(&s);
if (c1 == 0 || char2cells(c1) > 1) {
return e_invarg;
@@ -983,7 +982,7 @@ char *set_chars_option(win_T *wp, char **varp, bool apply)
*(tab[i].cp) = c1;
}
}
- p = (char *)s;
+ p = s;
break;
}
}
@@ -996,7 +995,7 @@ char *set_chars_option(win_T *wp, char **varp, bool apply)
&& strncmp(p, "multispace", len) == 0
&& p[len] == ':'
&& p[len + 1] != NUL) {
- const char_u *s = (char_u *)p + len + 1;
+ const char *s = p + len + 1;
if (round == 0) {
// Get length of lcs-multispace string in the first round
last_multispace = p;
@@ -1012,7 +1011,7 @@ char *set_chars_option(win_T *wp, char **varp, bool apply)
// lcs-multispace cannot be an empty string
return e_invarg;
}
- p = (char *)s;
+ p = s;
} else {
int multispace_pos = 0;
while (*s != NUL && *s != ',') {
@@ -1021,13 +1020,13 @@ char *set_chars_option(win_T *wp, char **varp, bool apply)
wp->w_p_lcs_chars.multispace[multispace_pos++] = c1;
}
}
- p = (char *)s;
+ p = s;
}
} else if (is_listchars
&& strncmp(p, "leadmultispace", len2) == 0
&& p[len2] == ':'
&& p[len2 + 1] != NUL) {
- const char_u *s = (char_u *)p + len2 + 1;
+ const char *s = p + len2 + 1;
if (round == 0) {
// get length of lcs-leadmultispace string in first round
last_lmultispace = p;
@@ -1043,7 +1042,7 @@ char *set_chars_option(win_T *wp, char **varp, bool apply)
// lcs-leadmultispace cannot be an empty string
return e_invarg;
}
- p = (char *)s;
+ p = s;
} else {
int multispace_pos = 0;
while (*s != NUL && *s != ',') {
@@ -1052,7 +1051,7 @@ char *set_chars_option(win_T *wp, char **varp, bool apply)
wp->w_p_lcs_chars.leadmultispace[multispace_pos++] = c1;
}
}
- p = (char *)s;
+ p = s;
}
} else {
return e_invarg;
diff --git a/src/nvim/search.c b/src/nvim/search.c
index 871d2f9a0a..eb5cc2e07f 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -133,7 +133,7 @@ typedef struct SearchedFile {
/// @param regmatch return: pattern and ignore-case flag
///
/// @return FAIL if failed, OK otherwise.
-int search_regcomp(char_u *pat, char_u **used_pat, int pat_save, int pat_use, int options,
+int search_regcomp(char *pat, char **used_pat, int pat_save, int pat_use, int options,
regmmatch_T *regmatch)
{
int magic;
@@ -158,11 +158,11 @@ int search_regcomp(char_u *pat, char_u **used_pat, int pat_save, int pat_use, in
rc_did_emsg = true;
return FAIL;
}
- pat = (char_u *)spats[i].pat;
+ pat = spats[i].pat;
magic = spats[i].magic;
no_smartcase = spats[i].no_scs;
} else if (options & SEARCH_HIS) { // put new pattern in history
- add_to_history(HIST_SEARCH, (char *)pat, true, NUL);
+ add_to_history(HIST_SEARCH, pat, true, NUL);
}
if (used_pat) {
@@ -171,9 +171,9 @@ int search_regcomp(char_u *pat, char_u **used_pat, int pat_save, int pat_use, in
xfree(mr_pattern);
if (curwin->w_p_rl && *curwin->w_p_rlc == 's') {
- mr_pattern = reverse_text((char *)pat);
+ mr_pattern = reverse_text(pat);
} else {
- mr_pattern = xstrdup((char *)pat);
+ mr_pattern = xstrdup(pat);
}
// Save the currently used pattern in the appropriate place,
@@ -181,17 +181,17 @@ int search_regcomp(char_u *pat, char_u **used_pat, int pat_save, int pat_use, in
if (!(options & SEARCH_KEEP) && (cmdmod.cmod_flags & CMOD_KEEPPATTERNS) == 0) {
// search or global command
if (pat_save == RE_SEARCH || pat_save == RE_BOTH) {
- save_re_pat(RE_SEARCH, (char *)pat, magic);
+ save_re_pat(RE_SEARCH, pat, magic);
}
// substitute or global command
if (pat_save == RE_SUBST || pat_save == RE_BOTH) {
- save_re_pat(RE_SUBST, (char *)pat, magic);
+ save_re_pat(RE_SUBST, pat, magic);
}
}
- regmatch->rmm_ic = ignorecase((char *)pat);
+ regmatch->rmm_ic = ignorecase(pat);
regmatch->rmm_maxcol = 0;
- regmatch->regprog = vim_regcomp((char *)pat, magic ? RE_MAGIC : 0);
+ regmatch->regprog = vim_regcomp(pat, magic ? RE_MAGIC : 0);
if (regmatch->regprog == NULL) {
return FAIL;
}
@@ -206,20 +206,22 @@ char *get_search_pat(void)
void save_re_pat(int idx, char *pat, int magic)
{
- if (spats[idx].pat != pat) {
- free_spat(&spats[idx]);
- spats[idx].pat = xstrdup(pat);
- spats[idx].magic = magic;
- spats[idx].no_scs = no_smartcase;
- spats[idx].timestamp = os_time();
- spats[idx].additional_data = NULL;
- last_idx = idx;
- // If 'hlsearch' set and search pat changed: need redraw.
- if (p_hls) {
- redraw_all_later(UPD_SOME_VALID);
- }
- set_no_hlsearch(false);
+ if (spats[idx].pat == pat) {
+ return;
+ }
+
+ free_spat(&spats[idx]);
+ spats[idx].pat = xstrdup(pat);
+ spats[idx].magic = magic;
+ spats[idx].no_scs = no_smartcase;
+ spats[idx].timestamp = os_time();
+ spats[idx].additional_data = NULL;
+ last_idx = idx;
+ // If 'hlsearch' set and search pat changed: need redraw.
+ if (p_hls) {
+ redraw_all_later(UPD_SOME_VALID);
}
+ set_no_hlsearch(false);
}
// Save the search patterns, so they can be restored later.
@@ -228,38 +230,42 @@ static int save_level = 0;
void save_search_patterns(void)
{
- if (save_level++ == 0) {
- saved_spats[0] = spats[0];
- if (spats[0].pat != NULL) {
- saved_spats[0].pat = xstrdup(spats[0].pat);
- }
- saved_spats[1] = spats[1];
- if (spats[1].pat != NULL) {
- saved_spats[1].pat = xstrdup(spats[1].pat);
- }
- if (mr_pattern == NULL) {
- saved_mr_pattern = NULL;
- } else {
- saved_mr_pattern = xstrdup(mr_pattern);
- }
- saved_spats_last_idx = last_idx;
- saved_spats_no_hlsearch = no_hlsearch;
+ if (save_level++ != 0) {
+ return;
+ }
+
+ saved_spats[0] = spats[0];
+ if (spats[0].pat != NULL) {
+ saved_spats[0].pat = xstrdup(spats[0].pat);
+ }
+ saved_spats[1] = spats[1];
+ if (spats[1].pat != NULL) {
+ saved_spats[1].pat = xstrdup(spats[1].pat);
}
+ if (mr_pattern == NULL) {
+ saved_mr_pattern = NULL;
+ } else {
+ saved_mr_pattern = xstrdup(mr_pattern);
+ }
+ saved_spats_last_idx = last_idx;
+ saved_spats_no_hlsearch = no_hlsearch;
}
void restore_search_patterns(void)
{
- if (--save_level == 0) {
- free_spat(&spats[0]);
- spats[0] = saved_spats[0];
- set_vv_searchforward();
- free_spat(&spats[1]);
- spats[1] = saved_spats[1];
- xfree(mr_pattern);
- mr_pattern = saved_mr_pattern;
- last_idx = saved_spats_last_idx;
- set_no_hlsearch(saved_spats_no_hlsearch);
+ if (--save_level != 0) {
+ return;
}
+
+ free_spat(&spats[0]);
+ spats[0] = saved_spats[0];
+ set_vv_searchforward();
+ free_spat(&spats[1]);
+ spats[1] = saved_spats[1];
+ xfree(mr_pattern);
+ mr_pattern = saved_mr_pattern;
+ last_idx = saved_spats_last_idx;
+ set_no_hlsearch(saved_spats_no_hlsearch);
}
static inline void free_spat(struct spat *const spat)
@@ -346,9 +352,9 @@ static void restore_incsearch_state(void)
search_match_lines = saved_search_match_lines;
}
-char_u *last_search_pattern(void)
+char *last_search_pattern(void)
{
- return (char_u *)spats[RE_SEARCH].pat;
+ return spats[RE_SEARCH].pat;
}
/// Return true when case should be ignored for search pattern "pat".
@@ -365,7 +371,7 @@ int ignorecase_opt(char *pat, int ic_in, int scs)
if (ic && !no_smartcase && scs
&& !(ctrl_x_mode_not_default()
&& curbuf->b_p_inf)) {
- ic = !pat_has_uppercase((char_u *)pat);
+ ic = !pat_has_uppercase(pat);
}
no_smartcase = false;
@@ -373,14 +379,14 @@ int ignorecase_opt(char *pat, int ic_in, int scs)
}
/// Returns true if pattern `pat` has an uppercase character.
-bool pat_has_uppercase(char_u *pat)
+bool pat_has_uppercase(char *pat)
FUNC_ATTR_NONNULL_ALL
{
- char *p = (char *)pat;
+ char *p = pat;
magic_T magic_val = MAGIC_ON;
// get the magicness of the pattern
- (void)skip_regexp_ex((char *)pat, NUL, magic_isset(), NULL, NULL, &magic_val);
+ (void)skip_regexp_ex(pat, NUL, magic_isset(), NULL, NULL, &magic_val);
while (*p != NUL) {
const int l = utfc_ptr2len(p);
@@ -431,7 +437,7 @@ int last_csearch_until(void)
return last_t_cmd == true;
}
-void set_last_csearch(int c, char_u *s, int len)
+void set_last_csearch(int c, char *s, int len)
{
*lastc = (char_u)c;
lastc_bytelen = len;
@@ -452,9 +458,9 @@ void set_csearch_until(int t_cmd)
last_t_cmd = t_cmd;
}
-char_u *last_search_pat(void)
+char *last_search_pat(void)
{
- return (char_u *)spats[last_idx].pat;
+ return spats[last_idx].pat;
}
// Reset search direction to forward. For "gd" and "gD" commands.
@@ -466,14 +472,14 @@ void reset_search_dir(void)
// Set the last search pattern. For ":let @/ =" and ShaDa file.
// Also set the saved search pattern, so that this works in an autocommand.
-void set_last_search_pat(const char_u *s, int idx, int magic, int setlast)
+void set_last_search_pat(const char *s, int idx, int magic, int setlast)
{
free_spat(&spats[idx]);
// An empty string means that nothing should be matched.
if (*s == NUL) {
spats[idx].pat = NULL;
} else {
- spats[idx].pat = xstrdup((char *)s);
+ spats[idx].pat = xstrdup(s);
}
spats[idx].timestamp = os_time();
spats[idx].additional_data = NULL;
@@ -513,7 +519,7 @@ void last_pat_prog(regmmatch_T *regmatch)
return;
}
emsg_off++; // So it doesn't beep if bad expr
- (void)search_regcomp((char_u *)"", NULL, 0, last_idx, SEARCH_KEEP, regmatch);
+ (void)search_regcomp("", NULL, 0, last_idx, SEARCH_KEEP, regmatch);
emsg_off--;
}
@@ -540,7 +546,7 @@ void last_pat_prog(regmmatch_T *regmatch)
/// @returns FAIL (zero) for failure, non-zero for success.
/// the index of the first matching
/// subpattern plus one; one if there was none.
-int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir, char_u *pat,
+int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir, char *pat,
long count, int options, int pat_use, searchit_arg_T *extra_arg)
{
int found;
@@ -1296,7 +1302,7 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char *pat, long count, i
}
c = searchit(curwin, curbuf, &pos, NULL, dirc == '/' ? FORWARD : BACKWARD,
- (char_u *)searchstr, count,
+ searchstr, count,
(spats[0].off.end * SEARCH_END
+ (options
& (SEARCH_KEEP + SEARCH_PEEK + SEARCH_HIS + SEARCH_MSG
@@ -2321,55 +2327,63 @@ void showmatch(int c)
if ((lpos = findmatch(NULL, NUL)) == NULL) { // no match, so beep
vim_beep(BO_MATCH);
- } else if (lpos->lnum >= curwin->w_topline
- && lpos->lnum < curwin->w_botline) {
- if (!curwin->w_p_wrap) {
- getvcol(curwin, lpos, NULL, &vcol, NULL);
- }
- if (curwin->w_p_wrap
- || (vcol >= curwin->w_leftcol
- && vcol < curwin->w_leftcol + curwin->w_width_inner)) {
- mpos = *lpos; // save the pos, update_screen() may change it
- save_cursor = curwin->w_cursor;
- save_so = *so;
- save_siso = *siso;
- // Handle "$" in 'cpo': If the ')' is typed on top of the "$",
- // stop displaying the "$".
- if (dollar_vcol >= 0 && dollar_vcol == curwin->w_virtcol) {
- dollar_vcol = -1;
- }
- curwin->w_virtcol++; // do display ')' just before "$"
- update_screen(); // show the new char first
-
- save_dollar_vcol = dollar_vcol;
- save_state = State;
- State = MODE_SHOWMATCH;
- ui_cursor_shape(); // may show different cursor shape
- curwin->w_cursor = mpos; // move to matching char
- *so = 0; // don't use 'scrolloff' here
- *siso = 0; // don't use 'sidescrolloff' here
- show_cursor_info(false);
- setcursor();
- ui_flush();
- // Restore dollar_vcol(), because setcursor() may call curs_rows()
- // which resets it if the matching position is in a previous line
- // and has a higher column number.
- dollar_vcol = save_dollar_vcol;
-
- // brief pause, unless 'm' is present in 'cpo' and a character is
- // available.
- if (vim_strchr(p_cpo, CPO_SHOWMATCH) != NULL) {
- os_delay((uint64_t)p_mat * 100L + 8, true);
- } else if (!char_avail()) {
- os_delay((uint64_t)p_mat * 100L + 9, false);
- }
- curwin->w_cursor = save_cursor; // restore cursor position
- *so = save_so;
- *siso = save_siso;
- State = save_state;
- ui_cursor_shape(); // may show different cursor shape
- }
+ return;
+ }
+
+ if (lpos->lnum < curwin->w_topline || lpos->lnum >= curwin->w_botline) {
+ return;
+ }
+
+ if (!curwin->w_p_wrap) {
+ getvcol(curwin, lpos, NULL, &vcol, NULL);
+ }
+
+ bool col_visible = curwin->w_p_wrap
+ || (vcol >= curwin->w_leftcol
+ && vcol < curwin->w_leftcol + curwin->w_width_inner);
+ if (!col_visible) {
+ return;
+ }
+
+ mpos = *lpos; // save the pos, update_screen() may change it
+ save_cursor = curwin->w_cursor;
+ save_so = *so;
+ save_siso = *siso;
+ // Handle "$" in 'cpo': If the ')' is typed on top of the "$",
+ // stop displaying the "$".
+ if (dollar_vcol >= 0 && dollar_vcol == curwin->w_virtcol) {
+ dollar_vcol = -1;
}
+ curwin->w_virtcol++; // do display ')' just before "$"
+ update_screen(); // show the new char first
+
+ save_dollar_vcol = dollar_vcol;
+ save_state = State;
+ State = MODE_SHOWMATCH;
+ ui_cursor_shape(); // may show different cursor shape
+ curwin->w_cursor = mpos; // move to matching char
+ *so = 0; // don't use 'scrolloff' here
+ *siso = 0; // don't use 'sidescrolloff' here
+ show_cursor_info(false);
+ setcursor();
+ ui_flush();
+ // Restore dollar_vcol(), because setcursor() may call curs_rows()
+ // which resets it if the matching position is in a previous line
+ // and has a higher column number.
+ dollar_vcol = save_dollar_vcol;
+
+ // brief pause, unless 'm' is present in 'cpo' and a character is
+ // available.
+ if (vim_strchr(p_cpo, CPO_SHOWMATCH) != NULL) {
+ os_delay((uint64_t)p_mat * 100L + 8, true);
+ } else if (!char_avail()) {
+ os_delay((uint64_t)p_mat * 100L + 9, false);
+ }
+ curwin->w_cursor = save_cursor; // restore cursor position
+ *so = save_so;
+ *siso = save_siso;
+ State = save_state;
+ ui_cursor_shape(); // may show different cursor shape
}
/// Find next search match under cursor, cursor at end.
@@ -2440,7 +2454,7 @@ int current_search(long count, bool forward)
result = searchit(curwin, curbuf, &pos, &end_pos,
(dir ? FORWARD : BACKWARD),
- (char_u *)spats[last_idx].pat, i ? count : 1,
+ spats[last_idx].pat, i ? count : 1,
SEARCH_KEEP | flags, RE_SEARCH, NULL);
p_ws = old_p_ws;
@@ -2527,7 +2541,7 @@ static int is_zero_width(char *pattern, int move, pos_T *cur, Direction directio
pattern = spats[last_idx].pat;
}
- if (search_regcomp((char_u *)pattern, NULL, RE_SEARCH, RE_SEARCH,
+ if (search_regcomp(pattern, NULL, RE_SEARCH, RE_SEARCH,
SEARCH_KEEP, &regmatch) == FAIL) {
return -1;
}
@@ -2542,7 +2556,7 @@ static int is_zero_width(char *pattern, int move, pos_T *cur, Direction directio
// accept a match at the cursor position
flag = SEARCH_START;
}
- if (searchit(curwin, curbuf, &pos, NULL, direction, (char_u *)pattern, 1,
+ if (searchit(curwin, curbuf, &pos, NULL, direction, pattern, 1,
SEARCH_KEEP + flag, RE_SEARCH, NULL) != FAIL) {
// Zero-width pattern should match somewhere, then we can check if
// start and end are in the same position.
@@ -2588,56 +2602,63 @@ static void cmdline_search_stat(int dirc, pos_T *pos, pos_T *cursor_pos, bool sh
update_search_stat(dirc, pos, cursor_pos, &stat, recompute, maxcount,
timeout);
- if (stat.cur > 0) {
- char t[SEARCH_STAT_BUF_LEN];
-
- if (curwin->w_p_rl && *curwin->w_p_rlc == 's') {
- if (stat.incomplete == 1) {
- vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[?/??]");
- } else if (stat.cnt > maxcount && stat.cur > maxcount) {
- vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[>%d/>%d]",
- maxcount, maxcount);
- } else if (stat.cnt > maxcount) {
- vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[>%d/%d]",
- maxcount, stat.cur);
- } else {
- vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[%d/%d]",
- stat.cnt, stat.cur);
- }
+ if (stat.cur <= 0) {
+ return;
+ }
+
+ char t[SEARCH_STAT_BUF_LEN];
+
+ if (curwin->w_p_rl && *curwin->w_p_rlc == 's') {
+ if (stat.incomplete == 1) {
+ vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[?/??]");
+ } else if (stat.cnt > maxcount && stat.cur > maxcount) {
+ vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[>%d/>%d]",
+ maxcount, maxcount);
+ } else if (stat.cnt > maxcount) {
+ vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[>%d/%d]",
+ maxcount, stat.cur);
} else {
- if (stat.incomplete == 1) {
- vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[?/??]");
- } else if (stat.cnt > maxcount && stat.cur > maxcount) {
- vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[>%d/>%d]",
- maxcount, maxcount);
- } else if (stat.cnt > maxcount) {
- vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[%d/>%d]",
- stat.cur, maxcount);
- } else {
- vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[%d/%d]",
- stat.cur, stat.cnt);
- }
+ vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[%d/%d]",
+ stat.cnt, stat.cur);
}
-
- size_t len = strlen(t);
- if (show_top_bot_msg && len + 2 < SEARCH_STAT_BUF_LEN) {
- memmove(t + 2, t, len);
- t[0] = 'W';
- t[1] = ' ';
- len += 2;
+ } else {
+ if (stat.incomplete == 1) {
+ vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[?/??]");
+ } else if (stat.cnt > maxcount && stat.cur > maxcount) {
+ vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[>%d/>%d]",
+ maxcount, maxcount);
+ } else if (stat.cnt > maxcount) {
+ vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[%d/>%d]",
+ stat.cur, maxcount);
+ } else {
+ vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[%d/%d]",
+ stat.cur, stat.cnt);
}
+ }
- memmove(msgbuf + strlen(msgbuf) - len, t, len);
- if (dirc == '?' && stat.cur == maxcount + 1) {
- stat.cur = -1;
- }
+ size_t len = strlen(t);
+ if (show_top_bot_msg && len + 2 < SEARCH_STAT_BUF_LEN) {
+ memmove(t + 2, t, len);
+ t[0] = 'W';
+ t[1] = ' ';
+ len += 2;
+ }
+
+ size_t msgbuf_len = strlen(msgbuf);
+ if (len > msgbuf_len) {
+ len = msgbuf_len;
+ }
+ memmove(msgbuf + msgbuf_len - len, t, len);
- // keep the message even after redraw, but don't put in history
- msg_hist_off = true;
- msg_ext_set_kind("search_count");
- give_warning(msgbuf, false);
- msg_hist_off = false;
+ if (dirc == '?' && stat.cur == maxcount + 1) {
+ stat.cur = -1;
}
+
+ // keep the message even after redraw, but don't put in history
+ msg_hist_off = true;
+ msg_ext_set_kind("search_count");
+ give_warning(msgbuf, false);
+ msg_hist_off = false;
}
// Add the search count information to "stat".
@@ -2942,7 +2963,7 @@ typedef struct {
#define FUZZY_MATCH_RECURSION_LIMIT 10
/// Compute a score for a fuzzy matched string. The matching character locations
-/// are in 'matches'.
+/// are in "matches".
static int fuzzy_match_compute_score(const char *const str, const int strSz,
const uint32_t *const matches, const int numMatches)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
@@ -3007,7 +3028,7 @@ static int fuzzy_match_compute_score(const char *const str, const int strSz,
return score;
}
-/// Perform a recursive search for fuzzy matching 'fuzpat' in 'str'.
+/// Perform a recursive search for fuzzy matching "fuzpat" in "str".
/// @return the number of matching characters.
static int fuzzy_match_recursive(const char *fuzpat, const char *str, uint32_t strIdx,
int *const outScore, const char *const strBegin, const int strLen,
@@ -3107,23 +3128,23 @@ static int fuzzy_match_recursive(const char *fuzpat, const char *str, uint32_t s
/// Uses char_u for match indices. Therefore patterns are limited to
/// MAX_FUZZY_MATCHES characters.
///
-/// @return true if 'pat_arg' matches 'str'. Also returns the match score in
-/// 'outScore' and the matching character positions in 'matches'.
-bool fuzzy_match(char_u *const str, const char_u *const pat_arg, const bool matchseq,
+/// @return true if "pat_arg" matches "str". Also returns the match score in
+/// "outScore" and the matching character positions in "matches".
+bool fuzzy_match(char *const str, const char *const pat_arg, const bool matchseq,
int *const outScore, uint32_t *const matches, const int maxMatches)
- FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+ FUNC_ATTR_NONNULL_ALL
{
- const int len = mb_charlen((char *)str);
+ const int len = mb_charlen(str);
bool complete = false;
int numMatches = 0;
*outScore = 0;
- char *const save_pat = xstrdup((char *)pat_arg);
+ char *const save_pat = xstrdup(pat_arg);
char *pat = save_pat;
char *p = pat;
- // Try matching each word in 'pat_arg' in 'str'
+ // Try matching each word in "pat_arg" in "str"
while (true) {
if (matchseq) {
complete = true;
@@ -3146,7 +3167,7 @@ bool fuzzy_match(char_u *const str, const char_u *const pat_arg, const bool matc
int score = 0;
int recursionCount = 0;
const int matchCount
- = fuzzy_match_recursive(pat, (char *)str, 0, &score, (char *)str, len, NULL,
+ = fuzzy_match_recursive(pat, str, 0, &score, str, len, NULL,
matches + numMatches,
maxMatches - numMatches, 0, &recursionCount);
if (matchCount == 0) {
@@ -3183,14 +3204,14 @@ static int fuzzy_match_item_compare(const void *const s1, const void *const s2)
return v1 == v2 ? (idx1 - idx2) : v1 > v2 ? -1 : 1;
}
-/// Fuzzy search the string 'str' in a list of 'items' and return the matching
-/// strings in 'fmatchlist'.
-/// If 'matchseq' is true, then for multi-word search strings, match all the
+/// Fuzzy search the string "str" in a list of "items" and return the matching
+/// strings in "fmatchlist".
+/// If "matchseq" is true, then for multi-word search strings, match all the
/// words in sequence.
-/// If 'items' is a list of strings, then search for 'str' in the list.
-/// If 'items' is a list of dicts, then either use 'key' to lookup the string
-/// for each item or use 'item_cb' Funcref function to get the string.
-/// If 'retmatchpos' is true, then return a list of positions where 'str'
+/// If "items" is a list of strings, then search for "str" in the list.
+/// If "items" is a list of dicts, then either use "key" to lookup the string
+/// for each item or use "item_cb" Funcref function to get the string.
+/// If "retmatchpos" is true, then return a list of positions where "str"
/// matches for each item.
static void fuzzy_match_in_list(list_T *const l, char *const str, const bool matchseq,
const char *const key, Callback *const item_cb,
@@ -3245,14 +3266,14 @@ static void fuzzy_match_in_list(list_T *const l, char *const str, const bool mat
}
int score;
- if (itemstr != NULL && fuzzy_match((char_u *)itemstr, (char_u *)str, matchseq, &score, matches,
+ if (itemstr != NULL && fuzzy_match(itemstr, str, matchseq, &score, matches,
MAX_FUZZY_MATCHES)) {
items[match_count].idx = (int)match_count;
items[match_count].item = li;
items[match_count].score = score;
// Copy the list of matching positions in itemstr to a list, if
- // 'retmatchpos' is set.
+ // "retmatchpos" is set.
if (retmatchpos) {
items[match_count].lmatchpos = tv_list_alloc(kListLenMayKnow);
int j = 0;
@@ -3326,8 +3347,8 @@ static void fuzzy_match_in_list(list_T *const l, char *const str, const bool mat
xfree(items);
}
-/// Do fuzzy matching. Returns the list of matched strings in 'rettv'.
-/// If 'retmatchpos' is true, also returns the matching character positions.
+/// Do fuzzy matching. Returns the list of matched strings in "rettv".
+/// If "retmatchpos" is true, also returns the matching character positions.
static void do_fuzzymatch(const typval_T *const argvars, typval_T *const rettv,
const bool retmatchpos)
FUNC_ATTR_NONNULL_ALL
@@ -3411,6 +3432,109 @@ void f_matchfuzzypos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
do_fuzzymatch(argvars, rettv, true);
}
+/// Same as fuzzy_match_item_compare() except for use with a string match
+static int fuzzy_match_str_compare(const void *const s1, const void *const s2)
+ FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE
+{
+ const int v1 = ((fuzmatch_str_T *)s1)->score;
+ const int v2 = ((fuzmatch_str_T *)s2)->score;
+ const int idx1 = ((fuzmatch_str_T *)s1)->idx;
+ const int idx2 = ((fuzmatch_str_T *)s2)->idx;
+
+ return v1 == v2 ? (idx1 - idx2) : v1 > v2 ? -1 : 1;
+}
+
+/// Sort fuzzy matches by score
+static void fuzzy_match_str_sort(fuzmatch_str_T *const fm, const int sz)
+ FUNC_ATTR_NONNULL_ALL
+{
+ // Sort the list by the descending order of the match score
+ qsort(fm, (size_t)sz, sizeof(fuzmatch_str_T), fuzzy_match_str_compare);
+}
+
+/// Same as fuzzy_match_item_compare() except for use with a function name
+/// string match. <SNR> functions should be sorted to the end.
+static int fuzzy_match_func_compare(const void *const s1, const void *const s2)
+ FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE
+{
+ const int v1 = ((fuzmatch_str_T *)s1)->score;
+ const int v2 = ((fuzmatch_str_T *)s2)->score;
+ const int idx1 = ((fuzmatch_str_T *)s1)->idx;
+ const int idx2 = ((fuzmatch_str_T *)s2)->idx;
+ const char *const str1 = ((fuzmatch_str_T *)s1)->str;
+ const char *const str2 = ((fuzmatch_str_T *)s2)->str;
+
+ if (*str1 != '<' && *str2 == '<') {
+ return -1;
+ }
+ if (*str1 == '<' && *str2 != '<') {
+ return 1;
+ }
+ return v1 == v2 ? (idx1 - idx2) : v1 > v2 ? -1 : 1;
+}
+
+/// Sort fuzzy matches of function names by score.
+/// <SNR> functions should be sorted to the end.
+static void fuzzy_match_func_sort(fuzmatch_str_T *const fm, const int sz)
+ FUNC_ATTR_NONNULL_ALL
+{
+ // Sort the list by the descending order of the match score
+ qsort(fm, (size_t)sz, sizeof(fuzmatch_str_T), fuzzy_match_func_compare);
+}
+
+/// Fuzzy match "pat" in "str".
+/// @returns 0 if there is no match. Otherwise, returns the match score.
+int fuzzy_match_str(char *const str, const char *const pat)
+ FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ if (str == NULL || pat == NULL) {
+ return 0;
+ }
+
+ int score = 0;
+ uint32_t matchpos[MAX_FUZZY_MATCHES];
+ fuzzy_match(str, pat, true, &score, matchpos, sizeof(matchpos) / sizeof(matchpos[0]));
+
+ return score;
+}
+
+/// Copy a list of fuzzy matches into a string list after sorting the matches by
+/// the fuzzy score. Frees the memory allocated for "fuzmatch".
+void fuzzymatches_to_strmatches(fuzmatch_str_T *const fuzmatch, char ***const matches,
+ const int count, const bool funcsort)
+ FUNC_ATTR_NONNULL_ARG(2)
+{
+ if (count <= 0) {
+ return;
+ }
+
+ *matches = xmalloc((size_t)count * sizeof(char *));
+
+ // Sort the list by the descending order of the match score
+ if (funcsort) {
+ fuzzy_match_func_sort(fuzmatch, count);
+ } else {
+ fuzzy_match_str_sort(fuzmatch, count);
+ }
+
+ for (int i = 0; i < count; i++) {
+ (*matches)[i] = fuzmatch[i].str;
+ }
+ xfree(fuzmatch);
+}
+
+/// Free a list of fuzzy string matches.
+void fuzmatch_str_free(fuzmatch_str_T *const fuzmatch, int count)
+{
+ if (count <= 0 || fuzmatch == NULL) {
+ return;
+ }
+ while (count--) {
+ xfree(fuzmatch[count].str);
+ }
+ xfree(fuzmatch);
+}
+
/// Get line "lnum" and copy it into "buf[LSIZE]".
/// The copy is made because the regexp may make the line invalid when using a
/// mark.
@@ -3534,9 +3658,9 @@ void find_pattern_in_path(char *ptr, Direction dir, size_t len, bool whole, bool
1L, p_fname);
} else {
// Use text after match with 'include'.
- new_fname = (char *)file_name_in_line((char_u *)incl_regmatch.endp[0], 0,
- FNAME_EXP|FNAME_INCL|FNAME_REL, 1L, (char_u *)p_fname,
- NULL);
+ new_fname = file_name_in_line(incl_regmatch.endp[0], 0,
+ FNAME_EXP|FNAME_INCL|FNAME_REL, 1L, p_fname,
+ NULL);
}
already_searched = false;
if (new_fname != NULL) {
diff --git a/src/nvim/search.h b/src/nvim/search.h
index 092098d5fd..2f140ba840 100644
--- a/src/nvim/search.h
+++ b/src/nvim/search.h
@@ -99,6 +99,14 @@ typedef struct searchstat {
int last_maxcount; // the max count of the last search
} searchstat_T;
+/// Fuzzy matched string list item. Used for fuzzy match completion. Items are
+/// usually sorted by "score". The "idx" member is used for stable-sort.
+typedef struct {
+ int idx;
+ char *str;
+ int score;
+} fuzmatch_str_T;
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "search.h.generated.h"
#endif
diff --git a/src/nvim/sha256.c b/src/nvim/sha256.c
index 72ef74b46c..db647f3ecb 100644
--- a/src/nvim/sha256.c
+++ b/src/nvim/sha256.c
@@ -32,10 +32,10 @@
}
#define PUT_UINT32(n, b, i) { \
- (b)[(i)] = (char_u)((n) >> 24); \
- (b)[(i) + 1] = (char_u)((n) >> 16); \
- (b)[(i) + 2] = (char_u)((n) >> 8); \
- (b)[(i) + 3] = (char_u)((n)); \
+ (b)[(i)] = (uint8_t)((n) >> 24); \
+ (b)[(i) + 1] = (uint8_t)((n) >> 16); \
+ (b)[(i) + 2] = (uint8_t)((n) >> 8); \
+ (b)[(i) + 3] = (uint8_t)((n)); \
}
void sha256_start(context_sha256_T *ctx)
@@ -53,7 +53,7 @@ void sha256_start(context_sha256_T *ctx)
ctx->state[7] = 0x5BE0CD19;
}
-static void sha256_process(context_sha256_T *ctx, const char_u data[SHA256_BUFFER_SIZE])
+static void sha256_process(context_sha256_T *ctx, const uint8_t data[SHA256_BUFFER_SIZE])
{
uint32_t temp1, temp2, W[SHA256_BUFFER_SIZE];
uint32_t A, B, C, D, E, F, G, H;
@@ -180,7 +180,7 @@ static void sha256_process(context_sha256_T *ctx, const char_u data[SHA256_BUFFE
ctx->state[7] += H;
}
-void sha256_update(context_sha256_T *ctx, const char_u *input, size_t length)
+void sha256_update(context_sha256_T *ctx, const uint8_t *input, size_t length)
{
if (length == 0) {
return;
@@ -198,7 +198,7 @@ void sha256_update(context_sha256_T *ctx, const char_u *input, size_t length)
size_t fill = SHA256_BUFFER_SIZE - left;
if (left && (length >= fill)) {
- memcpy((void *)(ctx->buffer + left), (void *)input, fill);
+ memcpy(ctx->buffer + left, input, fill);
sha256_process(ctx, ctx->buffer);
length -= fill;
input += fill;
@@ -212,22 +212,22 @@ void sha256_update(context_sha256_T *ctx, const char_u *input, size_t length)
}
if (length) {
- memcpy((void *)(ctx->buffer + left), (void *)input, length);
+ memcpy(ctx->buffer + left, input, length);
}
}
-static char_u sha256_padding[SHA256_BUFFER_SIZE] = {
+static uint8_t sha256_padding[SHA256_BUFFER_SIZE] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
-void sha256_finish(context_sha256_T *ctx, char_u digest[SHA256_SUM_SIZE])
+void sha256_finish(context_sha256_T *ctx, uint8_t digest[SHA256_SUM_SIZE])
{
uint32_t last, padn;
uint32_t high, low;
- char_u msglen[8];
+ uint8_t msglen[8];
high = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
low = (ctx->total[0] << 3);
@@ -265,7 +265,7 @@ void sha256_finish(context_sha256_T *ctx, char_u digest[SHA256_SUM_SIZE])
const char *sha256_bytes(const uint8_t *restrict buf, size_t buf_len, const uint8_t *restrict salt,
size_t salt_len)
{
- char_u sha256sum[SHA256_SUM_SIZE];
+ uint8_t sha256sum[SHA256_SUM_SIZE];
static char hexit[SHA256_BUFFER_SIZE + 1]; // buf size + NULL
context_sha256_T ctx;
@@ -309,8 +309,8 @@ bool sha256_self_test(void)
{
char output[SHA256_BUFFER_SIZE + 1]; // buf size + NULL
context_sha256_T ctx;
- char_u buf[1000];
- char_u sha256sum[SHA256_SUM_SIZE];
+ uint8_t buf[1000];
+ uint8_t sha256sum[SHA256_SUM_SIZE];
const char *hexit;
static bool sha256_self_tested = false;
diff --git a/src/nvim/sha256.h b/src/nvim/sha256.h
index a1d8f670d5..eeb4031509 100644
--- a/src/nvim/sha256.h
+++ b/src/nvim/sha256.h
@@ -12,7 +12,7 @@
typedef struct {
uint32_t total[2];
uint32_t state[8];
- char_u buffer[SHA256_BUFFER_SIZE];
+ uint8_t buffer[SHA256_BUFFER_SIZE];
} context_sha256_T;
#ifdef INCLUDE_GENERATED_DECLARATIONS
diff --git a/src/nvim/shada.c b/src/nvim/shada.c
index 754139a147..90a01aaf97 100644
--- a/src/nvim/shada.c
+++ b/src/nvim/shada.c
@@ -53,7 +53,6 @@
#include "nvim/search.h"
#include "nvim/shada.h"
#include "nvim/strings.h"
-#include "nvim/types.h"
#include "nvim/version.h"
#include "nvim/vim.h"
@@ -1483,7 +1482,7 @@ static char *shada_filename(const char *file)
if (p_shadafile != NULL && *p_shadafile != NUL) {
file = p_shadafile;
} else {
- if ((file = (char *)find_shada_parameter('n')) == NULL || *file == NUL) {
+ if ((file = 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
@@ -2668,8 +2667,6 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef
}
// Initialize jump list
- setpcmark();
- cleanup_jumplist(curwin, false);
wms->jumps_size = shada_init_jumps(wms->jumps, &removable_bufs);
const bool search_highlighted = !(no_hlsearch
@@ -4039,13 +4036,11 @@ static bool shada_removable(const char *name)
static inline size_t shada_init_jumps(PossiblyFreedShadaEntry *jumps,
khash_t(bufset) *const removable_bufs)
{
- if (!curwin->w_jumplistlen) {
- return 0;
- }
-
+ // Initialize jump list
size_t jumps_size = 0;
const void *jump_iter = NULL;
-
+ setpcmark();
+ cleanup_jumplist(curwin, false);
do {
xfmark_T fm;
jump_iter = mark_jumplist_iter(jump_iter, curwin, &fm);
@@ -4118,7 +4113,6 @@ void shada_encode_jumps(msgpack_sbuffer *const sbuf)
khash_t(bufset) removable_bufs = KHASH_EMPTY_TABLE(bufset);
find_removable_bufs(&removable_bufs);
PossiblyFreedShadaEntry jumps[JUMPLISTSIZE];
- cleanup_jumplist(curwin, true);
size_t jumps_size = shada_init_jumps(jumps, &removable_bufs);
msgpack_packer packer;
msgpack_packer_init(&packer, sbuf, msgpack_sbuffer_write);
diff --git a/src/nvim/sign.c b/src/nvim/sign.c
index e211b0069e..00e282b76e 100644
--- a/src/nvim/sign.c
+++ b/src/nvim/sign.c
@@ -99,16 +99,16 @@ static signgroup_T *sign_group_ref(const char *groupname)
hashitem_T *hi;
signgroup_T *group;
- hash = hash_hash((char_u *)groupname);
+ hash = hash_hash(groupname);
hi = hash_lookup(&sg_table, (char *)groupname, strlen(groupname), hash);
if (HASHITEM_EMPTY(hi)) {
// new group
- group = xmalloc(sizeof(signgroup_T) + strlen(groupname));
+ group = xmalloc(offsetof(signgroup_T, sg_name) + strlen(groupname) + 1);
STRCPY(group->sg_name, groupname);
group->sg_refcount = 1;
group->sg_next_sign_id = 1;
- hash_add_item(&sg_table, hi, (char_u *)group->sg_name, hash);
+ hash_add_item(&sg_table, hi, group->sg_name, hash);
} else {
// existing group
group = HI2SG(hi);
@@ -122,17 +122,17 @@ static signgroup_T *sign_group_ref(const char *groupname)
/// removed, then remove the group.
static void sign_group_unref(char *groupname)
{
- signgroup_T *group;
-
hashitem_T *hi = hash_find(&sg_table, groupname);
- if (!HASHITEM_EMPTY(hi)) {
- group = HI2SG(hi);
- group->sg_refcount--;
- if (group->sg_refcount == 0) {
- // All the signs in this group are removed
- hash_remove(&sg_table, hi);
- xfree(group);
- }
+ if (HASHITEM_EMPTY(hi)) {
+ return;
+ }
+
+ signgroup_T *group = HI2SG(hi);
+ group->sg_refcount--;
+ if (group->sg_refcount == 0) {
+ // All the signs in this group are removed
+ hash_remove(&sg_table, hi);
+ xfree(group);
}
}
diff --git a/src/nvim/sign_defs.h b/src/nvim/sign_defs.h
index 16e783aab7..7aa06ce48a 100644
--- a/src/nvim/sign_defs.h
+++ b/src/nvim/sign_defs.h
@@ -10,9 +10,9 @@
// Sign group
typedef struct signgroup_S {
- uint16_t sg_refcount; // number of signs in this group
- int sg_next_sign_id; // next sign id for this group
- char sg_name[1]; // sign group name
+ int sg_next_sign_id; ///< next sign id for this group
+ uint16_t sg_refcount; ///< number of signs in this group
+ char sg_name[1]; ///< sign group name, actually longer
} signgroup_T;
// Macros to get the sign group structure from the group name
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index 48aed9c6de..2204cda169 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -123,7 +123,7 @@ enum {
slang_T *first_lang = NULL;
// file used for "zG" and "zW"
-char_u *int_wordlist = NULL;
+char *int_wordlist = NULL;
// Structure to store info for word matching.
typedef struct matchinf_S {
@@ -131,9 +131,9 @@ typedef struct matchinf_S {
// pointers to original text to be checked
char *mi_word; // start of word being checked
- char_u *mi_end; // end of matching word so far
- char_u *mi_fend; // next char to be added to mi_fword
- char_u *mi_cend; // char after what was used for
+ char *mi_end; // end of matching word so far
+ char *mi_fend; // next char to be added to mi_fword
+ char *mi_cend; // char after what was used for
// mi_capflags
// case-folded text
@@ -161,12 +161,12 @@ typedef struct matchinf_S {
// for NOBREAK
int mi_result2; // "mi_result" without following word
- char_u *mi_end2; // "mi_end" without following word
+ char *mi_end2; // "mi_end" without following word
} matchinf_T;
// Structure used for the cookie argument of do_in_runtimepath().
typedef struct spelload_S {
- char_u sl_lang[MAXWLEN + 1]; // language name
+ char sl_lang[MAXWLEN + 1]; // language name
slang_T *sl_slang; // resulting slang_T struct
int sl_nobreak; // NOBREAK language found
} spelload_T;
@@ -214,7 +214,7 @@ char *repl_to = NULL;
///
/// @return the length of the word in bytes, also when it's OK, so that the
/// caller can skip over the word.
-size_t spell_check(win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, bool docount)
+size_t spell_check(win_T *wp, char *ptr, hlf_T *attrp, int *capcol, bool docount)
{
matchinf_T mi; // Most things are put in "mi" so that it can
// be passed to functions quickly.
@@ -226,7 +226,7 @@ size_t spell_check(win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, bool docou
// A word never starts at a space or a control character. Return quickly
// then, skipping over the character.
- if (*ptr <= ' ') {
+ if ((uint8_t)(*ptr) <= ' ') {
return 1;
}
@@ -242,23 +242,23 @@ size_t spell_check(win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, bool docou
// julifeest".
if (*ptr >= '0' && *ptr <= '9') {
if (*ptr == '0' && (ptr[1] == 'b' || ptr[1] == 'B')) {
- mi.mi_end = (char_u *)skipbin((char *)ptr + 2);
+ mi.mi_end = (char *)skipbin(ptr + 2);
} else if (*ptr == '0' && (ptr[1] == 'x' || ptr[1] == 'X')) {
- mi.mi_end = (char_u *)skiphex((char *)ptr + 2);
+ mi.mi_end = skiphex(ptr + 2);
} else {
- mi.mi_end = (char_u *)skipdigits((char *)ptr);
+ mi.mi_end = skipdigits(ptr);
}
nrlen = (size_t)(mi.mi_end - ptr);
}
// Find the normal end of the word (until the next non-word character).
- mi.mi_word = (char *)ptr;
+ mi.mi_word = ptr;
mi.mi_fend = ptr;
if (spell_iswordp(mi.mi_fend, wp)) {
bool this_upper = false; // init for gcc
if (use_camel_case) {
- int c = utf_ptr2char((char *)mi.mi_fend);
+ int c = utf_ptr2char(mi.mi_fend);
this_upper = SPELL_ISUPPER(c);
}
@@ -266,7 +266,7 @@ size_t spell_check(win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, bool docou
MB_PTR_ADV(mi.mi_fend);
if (use_camel_case) {
const bool prev_upper = this_upper;
- int c = utf_ptr2char((char *)mi.mi_fend);
+ int c = utf_ptr2char(mi.mi_fend);
this_upper = SPELL_ISUPPER(c);
camel_case = !prev_upper && this_upper;
}
@@ -275,7 +275,7 @@ size_t spell_check(win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, bool docou
if (capcol != NULL && *capcol == 0 && wp->w_s->b_cap_prog != NULL) {
// Check word starting with capital letter.
- int c = utf_ptr2char((char *)ptr);
+ int c = utf_ptr2char(ptr);
if (!SPELL_ISUPPER(c)) {
wrongcaplen = (size_t)(mi.mi_fend - ptr);
}
@@ -300,7 +300,7 @@ size_t spell_check(win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, bool docou
MB_PTR_ADV(mi.mi_fend);
}
- (void)spell_casefold(wp, ptr, (int)(mi.mi_fend - ptr), (char_u *)mi.mi_fword,
+ (void)spell_casefold(wp, ptr, (int)(mi.mi_fend - ptr), mi.mi_fword,
MAXWLEN + 1);
mi.mi_fwordlen = (int)strlen(mi.mi_fword);
@@ -344,7 +344,7 @@ size_t spell_check(win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, bool docou
// Count the word in the first language where it's found to be OK.
if (count_word && mi.mi_result == SP_OK) {
- count_common_word(mi.mi_lp->lp_slang, (char *)ptr,
+ count_common_word(mi.mi_lp->lp_slang, ptr,
(int)(mi.mi_end - ptr), 1);
count_word = false;
}
@@ -366,36 +366,36 @@ size_t spell_check(win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, bool docou
// Check for end of sentence.
regmatch.regprog = wp->w_s->b_cap_prog;
regmatch.rm_ic = false;
- int r = vim_regexec(&regmatch, (char *)ptr, 0);
+ int r = vim_regexec(&regmatch, ptr, 0);
wp->w_s->b_cap_prog = regmatch.regprog;
if (r) {
- *capcol = (int)(regmatch.endp[0] - (char *)ptr);
+ *capcol = (int)(regmatch.endp[0] - ptr);
}
}
- return (size_t)(utfc_ptr2len((char *)ptr));
+ return (size_t)(utfc_ptr2len(ptr));
} else if (mi.mi_end == ptr) {
// Always include at least one character. Required for when there
// is a mixup in "midword".
MB_PTR_ADV(mi.mi_end);
} else if (mi.mi_result == SP_BAD
&& LANGP_ENTRY(wp->w_s->b_langp, 0)->lp_slang->sl_nobreak) {
- char_u *p, *fp;
+ char *p, *fp;
int save_result = mi.mi_result;
// First language in 'spelllang' is NOBREAK. Find first position
// at which any word would be valid.
mi.mi_lp = LANGP_ENTRY(wp->w_s->b_langp, 0);
if (mi.mi_lp->lp_slang->sl_fidxs != NULL) {
- p = (char_u *)mi.mi_word;
- fp = (char_u *)mi.mi_fword;
+ p = mi.mi_word;
+ fp = mi.mi_fword;
for (;;) {
MB_PTR_ADV(p);
MB_PTR_ADV(fp);
if (p >= mi.mi_end) {
break;
}
- mi.mi_compoff = (int)(fp - (char_u *)mi.mi_fword);
+ mi.mi_compoff = (int)(fp - mi.mi_fword);
find_word(&mi, FIND_COMPOUND);
if (mi.mi_result != SP_BAD) {
mi.mi_end = p;
@@ -444,7 +444,7 @@ static void find_word(matchinf_T *mip, int mode)
// Check for word with matching case in keep-case tree.
ptr = mip->mi_word;
flen = 9999; // no case folding, always enough bytes
- byts = slang->sl_kbyts;
+ byts = (char_u *)slang->sl_kbyts;
idxs = slang->sl_kidxs;
if (mode == FIND_KEEPCOMPOUND) {
@@ -455,7 +455,7 @@ static void find_word(matchinf_T *mip, int mode)
// Check for case-folded in case-folded tree.
ptr = mip->mi_fword;
flen = mip->mi_fwordlen; // available case-folded bytes
- byts = slang->sl_fbyts;
+ byts = (char_u *)slang->sl_fbyts;
idxs = slang->sl_fidxs;
if (mode == FIND_PREFIX) {
@@ -575,7 +575,7 @@ static void find_word(matchinf_T *mip, int mode)
if (utf_head_off(ptr, ptr + wlen) > 0) {
continue; // not at first byte of character
}
- if (spell_iswordp((char_u *)ptr + wlen, mip->mi_win)) {
+ if (spell_iswordp(ptr + wlen, mip->mi_win)) {
if (slang->sl_compprog == NULL && !slang->sl_nobreak) {
continue; // next char is a word character
}
@@ -612,11 +612,11 @@ static void find_word(matchinf_T *mip, int mode)
// For keep-case tree the case is always right. For prefixes we
// don't bother to check.
if (mode == FIND_FOLDWORD) {
- if (mip->mi_cend != (char_u *)mip->mi_word + wlen) {
+ if (mip->mi_cend != mip->mi_word + wlen) {
// mi_capflags was set for a different word length, need
// to do it again.
- mip->mi_cend = (char_u *)mip->mi_word + wlen;
- mip->mi_capflags = captype((char_u *)mip->mi_word, mip->mi_cend);
+ mip->mi_cend = mip->mi_word + wlen;
+ mip->mi_capflags = captype(mip->mi_word, mip->mi_cend);
}
if (mip->mi_capflags == WF_KEEPCAP
@@ -629,7 +629,7 @@ static void find_word(matchinf_T *mip, int mode)
// mip->mi_prefarridx that find_prefix() filled.
c = valid_word_prefix(mip->mi_prefcnt, mip->mi_prefarridx,
(int)flags,
- (char_u *)mip->mi_word + mip->mi_cprefixlen, slang,
+ mip->mi_word + mip->mi_cprefixlen, slang,
false);
if (c == 0) {
continue;
@@ -664,7 +664,7 @@ static void find_word(matchinf_T *mip, int mode)
// For multi-byte chars check character length against
// COMPOUNDMIN.
if (slang->sl_compminlen > 0
- && mb_charlen_len((char_u *)mip->mi_word + mip->mi_compoff,
+ && mb_charlen_len(mip->mi_word + mip->mi_compoff,
wlen - mip->mi_compoff) < slang->sl_compminlen) {
continue;
}
@@ -687,7 +687,8 @@ static void find_word(matchinf_T *mip, int mode)
}
// Quickly check if compounding is possible with this flag.
- if (!byte_in_str(mip->mi_complen == 0 ? slang->sl_compstartflags : slang->sl_compallflags,
+ if (!byte_in_str(mip->mi_complen ==
+ 0 ? slang->sl_compstartflags : slang->sl_compallflags,
(int)((unsigned)flags >> 24))) {
continue;
}
@@ -712,7 +713,7 @@ static void find_word(matchinf_T *mip, int mode)
} else {
p = mip->mi_word + mip->mi_compoff;
}
- capflags = captype((char_u *)p, (char_u *)mip->mi_word + wlen);
+ capflags = captype(p, mip->mi_word + wlen);
if (capflags == WF_KEEPCAP || (capflags == WF_ALLCAP
&& (flags & WF_FIXCAP) != 0)) {
continue;
@@ -724,7 +725,7 @@ static void find_word(matchinf_T *mip, int mode)
// accept a no-caps word, even when the dictionary
// word specifies ONECAP.
MB_PTR_BACK(mip->mi_word, p);
- if (spell_iswordp_nmw((char_u *)p, mip->mi_win)
+ if (spell_iswordp_nmw(p, mip->mi_win)
? capflags == WF_ONECAP
: (flags & WF_ONECAP) != 0
&& capflags != WF_ONECAP) {
@@ -744,12 +745,12 @@ static void find_word(matchinf_T *mip, int mode)
if (slang->sl_compsylmax < MAXWLEN) {
// "fword" is only needed for checking syllables.
if (ptr == mip->mi_word) {
- (void)spell_casefold(mip->mi_win, (char_u *)ptr, wlen, (char_u *)fword, MAXWLEN);
+ (void)spell_casefold(mip->mi_win, ptr, wlen, fword, MAXWLEN);
} else {
xstrlcpy(fword, ptr, (size_t)endlen[endidxcnt] + 1);
}
}
- if (!can_compound(slang, (char *)fword, mip->mi_compflags)) {
+ if (!can_compound(slang, fword, mip->mi_compflags)) {
continue;
}
} else if (slang->sl_comprules != NULL
@@ -767,7 +768,7 @@ static void find_word(matchinf_T *mip, int mode)
if (!word_ends) {
int save_result = mip->mi_result;
- char_u *save_end = mip->mi_end;
+ char *save_end = mip->mi_end;
langp_T *save_lp = mip->mi_lp;
// Check that a valid word follows. If there is one and we
@@ -878,16 +879,16 @@ static void find_word(matchinf_T *mip, int mode)
if (nobreak_result == SP_BAD) {
if (mip->mi_result2 > res) {
mip->mi_result2 = res;
- mip->mi_end2 = (char_u *)mip->mi_word + wlen;
+ mip->mi_end2 = mip->mi_word + wlen;
} else if (mip->mi_result2 == res
- && mip->mi_end2 < (char_u *)mip->mi_word + wlen) {
- mip->mi_end2 = (char_u *)mip->mi_word + wlen;
+ && mip->mi_end2 < mip->mi_word + wlen) {
+ mip->mi_end2 = mip->mi_word + wlen;
}
} else if (mip->mi_result > res) {
mip->mi_result = res;
- mip->mi_end = (char_u *)mip->mi_word + wlen;
- } else if (mip->mi_result == res && mip->mi_end < (char_u *)mip->mi_word + wlen) {
- mip->mi_end = (char_u *)mip->mi_word + wlen;
+ mip->mi_end = mip->mi_word + wlen;
+ } else if (mip->mi_result == res && mip->mi_end < mip->mi_word + wlen) {
+ mip->mi_end = mip->mi_word + wlen;
}
if (mip->mi_result == SP_OK) {
@@ -930,15 +931,15 @@ bool match_checkcompoundpattern(char *ptr, int wlen, garray_T *gap)
bool can_compound(slang_T *slang, const char *word, const uint8_t *flags)
FUNC_ATTR_NONNULL_ALL
{
- char_u uflags[MAXWLEN * 2] = { 0 };
+ char uflags[MAXWLEN * 2] = { 0 };
if (slang->sl_compprog == NULL) {
return false;
}
// Need to convert the single byte flags to utf8 characters.
- char_u *p = uflags;
+ char *p = uflags;
for (int i = 0; flags[i] != NUL; i++) {
- p += utf_char2bytes(flags[i], (char *)p);
+ p += utf_char2bytes(flags[i], p);
}
*p = NUL;
p = uflags;
@@ -950,7 +951,7 @@ bool can_compound(slang_T *slang, const char *word, const uint8_t *flags)
// are too many syllables AND the number of compound words is above
// COMPOUNDWORDMAX then compounding is not allowed.
if (slang->sl_compsylmax < MAXWLEN
- && count_syllables(slang, (char_u *)word) > slang->sl_compsylmax) {
+ && count_syllables(slang, word) > slang->sl_compsylmax) {
return (int)strlen((char *)flags) < slang->sl_compmax;
}
return true;
@@ -963,7 +964,7 @@ bool can_compound(slang_T *slang, const char *word, const uint8_t *flags)
bool match_compoundrule(slang_T *slang, const char_u *compflags)
{
// loop over all the COMPOUNDRULE entries
- for (char_u *p = slang->sl_comprules; *p != NUL; p++) {
+ for (char_u *p = (char_u *)slang->sl_comprules; *p != NUL; p++) {
// loop over the flags in the compound word we have made, match
// them against the current rule entry
for (int i = 0;; i++) {
@@ -1013,7 +1014,7 @@ bool match_compoundrule(slang_T *slang, const char_u *compflags)
/// @param totprefcnt nr of prefix IDs
/// @param arridx idx in sl_pidxs[]
/// @param cond_req only use prefixes with a condition
-int valid_word_prefix(int totprefcnt, int arridx, int flags, char_u *word, slang_T *slang,
+int valid_word_prefix(int totprefcnt, int arridx, int flags, char *word, slang_T *slang,
bool cond_req)
{
int prefid = (int)((unsigned)flags >> 24);
@@ -1061,7 +1062,7 @@ static void find_prefix(matchinf_T *mip, int mode)
int wlen = 0;
slang_T *slang = mip->mi_lp->lp_slang;
- char_u *byts = slang->sl_pbyts;
+ char_u *byts = (char_u *)slang->sl_pbyts;
if (byts == NULL) {
return; // array is empty
}
@@ -1110,8 +1111,8 @@ static void find_prefix(matchinf_T *mip, int mode)
}
// Case-folded length may differ from original length.
- mip->mi_cprefixlen = nofold_len((char_u *)mip->mi_fword, mip->mi_prefixlen,
- (char_u *)mip->mi_word);
+ mip->mi_cprefixlen = nofold_len(mip->mi_fword, mip->mi_prefixlen,
+ mip->mi_word);
find_word(mip, FIND_PREFIX);
if (len == 0) {
@@ -1157,7 +1158,7 @@ static void find_prefix(matchinf_T *mip, int mode)
// Return the length of the folded chars in bytes.
static int fold_more(matchinf_T *mip)
{
- char_u *p = mip->mi_fend;
+ char *p = mip->mi_fend;
do {
MB_PTR_ADV(mip->mi_fend);
} while (*mip->mi_fend != NUL && spell_iswordp(mip->mi_fend, mip->mi_win));
@@ -1168,7 +1169,7 @@ static int fold_more(matchinf_T *mip)
}
(void)spell_casefold(mip->mi_win, p, (int)(mip->mi_fend - p),
- (char_u *)mip->mi_fword + mip->mi_fwordlen,
+ mip->mi_fword + mip->mi_fwordlen,
MAXWLEN - mip->mi_fwordlen);
int flen = (int)strlen(mip->mi_fword + mip->mi_fwordlen);
mip->mi_fwordlen += flen;
@@ -1319,7 +1320,7 @@ size_t spell_move_to(win_T *wp, int dir, bool allwords, bool curline, hlf_T *att
STRCPY(buf, line);
if (lnum < wp->w_buffer->b_ml.ml_line_count) {
spell_cat_line(buf + strlen(buf),
- (char_u *)ml_get_buf(wp->w_buffer, lnum + 1, false),
+ ml_get_buf(wp->w_buffer, lnum + 1, false),
MAXWLEN);
}
char *p = buf + skip;
@@ -1336,7 +1337,7 @@ size_t spell_move_to(win_T *wp, int dir, bool allwords, bool curline, hlf_T *att
// start of word
attr = HLF_COUNT;
- len = spell_check(wp, (char_u *)p, &attr, &capcol, false);
+ len = spell_check(wp, p, &attr, &capcol, false);
if (attr != HLF_COUNT) {
// We found a bad word. Check the attribute.
@@ -1480,27 +1481,29 @@ theend:
// "buf", blanking-out special characters. Copy less than "maxlen" bytes.
// Keep the blanks at the start of the next line, this is used in win_line()
// to skip those bytes if the word was OK.
-void spell_cat_line(char *buf, char_u *line, int maxlen)
+void spell_cat_line(char *buf, char *line, int maxlen)
{
- char_u *p = (char_u *)skipwhite((char *)line);
- while (vim_strchr("*#/\"\t", *p) != NULL) {
+ char_u *p = (char_u *)skipwhite(line);
+ while (vim_strchr("*#/\"\t", (uint8_t)(*p)) != NULL) {
p = (char_u *)skipwhite((char *)p + 1);
}
- if (*p != NUL) {
- // Only worth concatenating if there is something else than spaces to
- // concatenate.
- int n = (int)(p - line) + 1;
- if (n < maxlen - 1) {
- memset(buf, ' ', (size_t)n);
- xstrlcpy(buf + n, (char *)p, (size_t)(maxlen - n));
- }
+ if (*p == NUL) {
+ return;
+ }
+
+ // Only worth concatenating if there is something else than spaces to
+ // concatenate.
+ int n = (int)(p - (char_u *)line) + 1;
+ if (n < maxlen - 1) {
+ memset(buf, ' ', (size_t)n);
+ xstrlcpy(buf + n, (char *)p, (size_t)(maxlen - n));
}
}
// Load word list(s) for "lang" from Vim spell file(s).
// "lang" must be the language without the region: e.g., "en".
-static void spell_load_lang(char_u *lang)
+static void spell_load_lang(char *lang)
{
char fname_enc[85];
int r;
@@ -1520,18 +1523,18 @@ static void spell_load_lang(char_u *lang)
// autocommand may load it then.
for (int round = 1; round <= 2; round++) {
// Find the first spell file for "lang" in 'runtimepath' and load it.
- vim_snprintf((char *)fname_enc, sizeof(fname_enc) - 5,
+ vim_snprintf(fname_enc, sizeof(fname_enc) - 5,
"spell/%s.%s.spl", lang, spell_enc());
- r = do_in_runtimepath((char *)fname_enc, 0, spell_load_cb, &sl);
+ r = do_in_runtimepath(fname_enc, 0, spell_load_cb, &sl);
if (r == FAIL && *sl.sl_lang != NUL) {
// Try loading the ASCII version.
- vim_snprintf((char *)fname_enc, sizeof(fname_enc) - 5,
+ vim_snprintf(fname_enc, sizeof(fname_enc) - 5,
"spell/%s.ascii.spl", lang);
- r = do_in_runtimepath((char *)fname_enc, 0, spell_load_cb, &sl);
+ r = do_in_runtimepath(fname_enc, 0, spell_load_cb, &sl);
if (r == FAIL && *sl.sl_lang != NUL && round == 1
- && apply_autocmds(EVENT_SPELLFILEMISSING, (char *)lang,
+ && apply_autocmds(EVENT_SPELLFILEMISSING, lang,
curbuf->b_fname, false, curbuf)) {
continue;
}
@@ -1556,7 +1559,7 @@ static void spell_load_lang(char_u *lang)
} else if (sl.sl_slang != NULL) {
// At least one file was loaded, now load ALL the additions.
STRCPY(fname_enc + strlen(fname_enc) - 3, "add.spl");
- do_in_runtimepath((char *)fname_enc, DIP_ALL, spell_load_cb, &sl);
+ do_in_runtimepath(fname_enc, DIP_ALL, spell_load_cb, &sl);
}
curbuf->b_locked--;
@@ -1564,19 +1567,19 @@ static void spell_load_lang(char_u *lang)
// Return the encoding used for spell checking: Use 'encoding', except that we
// use "latin1" for "latin9". And limit to 60 characters (just in case).
-char_u *spell_enc(void)
+char *spell_enc(void)
{
if (strlen(p_enc) < 60 && strcmp(p_enc, "iso-8859-15") != 0) {
- return (char_u *)p_enc;
+ return p_enc;
}
- return (char_u *)"latin1";
+ return "latin1";
}
// Get the name of the .spl file for the internal wordlist into
// "fname[MAXPATHL]".
-static void int_wordlist_spl(char_u *fname)
+static void int_wordlist_spl(char *fname)
{
- vim_snprintf((char *)fname, MAXPATHL, SPL_FNAME_TMPL,
+ vim_snprintf(fname, MAXPATHL, SPL_FNAME_TMPL,
int_wordlist, spell_enc());
}
@@ -1700,18 +1703,20 @@ void slang_clear_sug(slang_T *lp)
static void spell_load_cb(char *fname, void *cookie)
{
spelload_T *slp = (spelload_T *)cookie;
- slang_T *slang = spell_load_file(fname, (char *)slp->sl_lang, NULL, false);
- if (slang != NULL) {
- // When a previously loaded file has NOBREAK also use it for the
- // ".add" files.
- if (slp->sl_nobreak && slang->sl_add) {
- slang->sl_nobreak = true;
- } else if (slang->sl_nobreak) {
- slp->sl_nobreak = true;
- }
+ slang_T *slang = spell_load_file(fname, slp->sl_lang, NULL, false);
+ if (slang == NULL) {
+ return;
+ }
- slp->sl_slang = slang;
+ // When a previously loaded file has NOBREAK also use it for the
+ // ".add" files.
+ if (slp->sl_nobreak && slang->sl_add) {
+ slang->sl_nobreak = true;
+ } else if (slang->sl_nobreak) {
+ slp->sl_nobreak = true;
}
+
+ slp->sl_slang = slang;
}
/// Add a word to the hashtable of common words.
@@ -1736,14 +1741,14 @@ void count_common_word(slang_T *lp, char *word, int len, uint8_t count)
}
wordcount_T *wc;
- hash_T hash = hash_hash((char_u *)p);
+ hash_T hash = hash_hash(p);
const size_t p_len = strlen(p);
hashitem_T *hi = hash_lookup(&lp->sl_wordcount, (const char *)p, p_len, hash);
if (HASHITEM_EMPTY(hi)) {
- wc = xmalloc(sizeof(wordcount_T) + p_len);
+ wc = xmalloc(offsetof(wordcount_T, wc_word) + p_len + 1);
memcpy(wc->wc_word, p, p_len + 1);
wc->wc_count = count;
- hash_add_item(&lp->sl_wordcount, hi, wc->wc_word, hash);
+ hash_add_item(&lp->sl_wordcount, hi, (char *)wc->wc_word, hash);
} else {
wc = HI2WC(hi);
wc->wc_count = (uint16_t)(wc->wc_count + count);
@@ -1755,9 +1760,9 @@ void count_common_word(slang_T *lp, char *word, int len, uint8_t count)
// Returns true if byte "n" appears in "str".
// Like strchr() but independent of locale.
-bool byte_in_str(char_u *str, int n)
+bool byte_in_str(uint8_t *str, int n)
{
- for (char_u *p = str; *p != NUL; p++) {
+ for (uint8_t *p = str; *p != NUL; p++) {
if (*p == n) {
return true;
}
@@ -1798,7 +1803,7 @@ int init_syl_tab(slang_T *slang)
// Count the number of syllables in "word".
// When "word" contains spaces the syllables after the last space are counted.
// Returns zero if syllables are not defines.
-static int count_syllables(slang_T *slang, const char_u *word)
+static int count_syllables(slang_T *slang, const char *word)
FUNC_ATTR_NONNULL_ALL
{
int cnt = 0;
@@ -1809,7 +1814,7 @@ static int count_syllables(slang_T *slang, const char_u *word)
return 0;
}
- for (const char *p = (char *)word; *p != NUL; p += len) {
+ for (const char *p = word; *p != NUL; p += len) {
// When running into a space reset counter.
if (*p == ' ') {
len = 1;
@@ -1893,11 +1898,11 @@ char *did_set_spelllang(win_T *wp)
// Loop over comma separated language names.
for (splp = spl_copy; *splp != NUL;) {
// Get one language name.
- copy_option_part(&splp, (char *)lang, MAXWLEN, ",");
+ copy_option_part(&splp, lang, MAXWLEN, ",");
region = NULL;
len = (int)strlen(lang);
- if (!valid_spelllang((char *)lang)) {
+ if (!valid_spelllang(lang)) {
continue;
}
@@ -1913,7 +1918,7 @@ char *did_set_spelllang(win_T *wp)
filename = true;
// Locate a region and remove it from the file name.
- p = vim_strchr(path_tail((char *)lang), '_');
+ p = vim_strchr(path_tail(lang), '_');
if (p != NULL && ASCII_ISALPHA(p[1]) && ASCII_ISALPHA(p[2])
&& !ASCII_ISALPHA(p[3])) {
xstrlcpy(region_cp, p + 1, 3);
@@ -1925,7 +1930,7 @@ char *did_set_spelllang(win_T *wp)
// Check if we loaded this language before.
for (slang = first_lang; slang != NULL; slang = slang->sl_next) {
- if (path_full_compare((char *)lang, slang->sl_fname, false, true)
+ if (path_full_compare(lang, slang->sl_fname, false, true)
== kEqualFiles) {
break;
}
@@ -1959,9 +1964,9 @@ char *did_set_spelllang(win_T *wp)
// If not found try loading the language now.
if (slang == NULL) {
if (filename) {
- (void)spell_load_file((char *)lang, (char *)lang, NULL, false);
+ (void)spell_load_file(lang, lang, NULL, false);
} else {
- spell_load_lang((char_u *)lang);
+ spell_load_lang(lang);
// SpellFileMissing autocommands may do anything, including
// destroying the buffer we are using or closing the window.
if (!bufref_valid(&bufref) || !win_valid_any_tab(wp)) {
@@ -1974,12 +1979,12 @@ char *did_set_spelllang(win_T *wp)
// Loop over the languages, there can be several files for "lang".
for (slang = first_lang; slang != NULL; slang = slang->sl_next) {
if (filename
- ? path_full_compare((char *)lang, slang->sl_fname, false, true) == kEqualFiles
+ ? path_full_compare(lang, slang->sl_fname, false, true) == kEqualFiles
: STRICMP(lang, slang->sl_name) == 0) {
region_mask = REGION_ALL;
if (!filename && region != NULL) {
// find region in sl_regions
- c = find_region(slang->sl_regions, (char_u *)region);
+ c = find_region(slang->sl_regions, region);
if (c == REGION_ALL) {
if (slang->sl_add) {
if (*slang->sl_regions != NUL) {
@@ -2022,17 +2027,17 @@ char *did_set_spelllang(win_T *wp)
if (int_wordlist == NULL) {
continue;
}
- int_wordlist_spl((char_u *)spf_name);
+ int_wordlist_spl(spf_name);
} else {
// One entry in 'spellfile'.
- copy_option_part(&spf, (char *)spf_name, MAXPATHL - 5, ",");
+ copy_option_part(&spf, spf_name, MAXPATHL - 5, ",");
STRCAT(spf_name, ".spl");
// If it was already found above then skip it.
for (c = 0; c < ga.ga_len; c++) {
p = LANGP_ENTRY(ga, c)->lp_slang->sl_fname;
if (p != NULL
- && path_full_compare((char *)spf_name, p, false, true) == kEqualFiles) {
+ && path_full_compare(spf_name, p, false, true) == kEqualFiles) {
break;
}
}
@@ -2043,7 +2048,7 @@ char *did_set_spelllang(win_T *wp)
// Check if it was loaded already.
for (slang = first_lang; slang != NULL; slang = slang->sl_next) {
- if (path_full_compare((char *)spf_name, slang->sl_fname, false, true)
+ if (path_full_compare(spf_name, slang->sl_fname, false, true)
== kEqualFiles) {
break;
}
@@ -2055,13 +2060,13 @@ char *did_set_spelllang(win_T *wp)
if (round == 0) {
STRCPY(lang, "internal wordlist");
} else {
- xstrlcpy(lang, path_tail((char *)spf_name), MAXWLEN + 1);
- p = vim_strchr((char *)lang, '.');
+ xstrlcpy(lang, path_tail(spf_name), MAXWLEN + 1);
+ p = vim_strchr(lang, '.');
if (p != NULL) {
*p = NUL; // truncate at ".encoding.add"
}
}
- slang = spell_load_file((char *)spf_name, (char *)lang, NULL, true);
+ slang = spell_load_file(spf_name, lang, NULL, true);
// If one of the languages has NOBREAK we assume the addition
// files also have this.
@@ -2073,7 +2078,7 @@ char *did_set_spelllang(win_T *wp)
region_mask = REGION_ALL;
if (use_region != NULL && !dont_use_region) {
// find region in sl_regions
- c = find_region(slang->sl_regions, (char_u *)use_region);
+ c = find_region(slang->sl_regions, use_region);
if (c != REGION_ALL) {
region_mask = 1 << c;
} else if (*slang->sl_regions != NUL) {
@@ -2185,7 +2190,7 @@ static void use_midword(slang_T *lp, win_T *wp)
// Find the region "region[2]" in "rp" (points to "sl_regions").
// Each region is simply stored as the two characters of its name.
// Returns the index if found (first is 0), REGION_ALL if not found.
-static int find_region(const char_u *rp, const char_u *region)
+static int find_region(const char *rp, const char *region)
{
int i;
@@ -2210,10 +2215,10 @@ static int find_region(const char_u *rp, const char_u *region)
/// @param[in] end End of word or NULL for NUL delimited string
///
/// @returns Case type of word
-int captype(char_u *word, const char_u *end)
+int captype(char *word, const char *end)
FUNC_ATTR_NONNULL_ARG(1)
{
- char_u *p;
+ char *p;
// find first letter
for (p = word; !spell_iswordp_nmw(p, curwin); MB_PTR_ADV(p)) {
@@ -2221,7 +2226,7 @@ int captype(char_u *word, const char_u *end)
return 0; // only non-word characters, illegal word
}
}
- int c = mb_ptr2char_adv((const char_u **)&p);
+ int c = mb_ptr2char_adv((const char **)&p);
bool allcap;
bool firstcap = allcap = SPELL_ISUPPER(c);
bool past_second = false; // past second word char
@@ -2230,7 +2235,7 @@ int captype(char_u *word, const char_u *end)
// But a word with an upper char only at start is a ONECAP.
for (; end == NULL ? *p != NUL : p < end; MB_PTR_ADV(p)) {
if (spell_iswordp_nmw(p, curwin)) {
- c = utf_ptr2char((char *)p);
+ c = utf_ptr2char(p);
if (!SPELL_ISUPPER(c)) {
// UUl -> KEEPCAP
if (past_second && allcap) {
@@ -2257,13 +2262,15 @@ int captype(char_u *word, const char_u *end)
// Delete the internal wordlist and its .spl file.
void spell_delete_wordlist(void)
{
- if (int_wordlist != NULL) {
- char_u fname[MAXPATHL] = { 0 };
- os_remove((char *)int_wordlist);
- int_wordlist_spl(fname);
- os_remove((char *)fname);
- XFREE_CLEAR(int_wordlist);
+ if (int_wordlist == NULL) {
+ return;
}
+
+ char fname[MAXPATHL] = { 0 };
+ os_remove(int_wordlist);
+ int_wordlist_spl(fname);
+ os_remove(fname);
+ XFREE_CLEAR(int_wordlist);
}
// Free all languages.
@@ -2331,10 +2338,12 @@ buf_T *open_spellbuf(void)
// Close the buffer used for spell info.
void close_spellbuf(buf_T *buf)
{
- if (buf != NULL) {
- ml_close(buf, true);
- xfree(buf);
+ if (buf == NULL) {
+ return;
}
+
+ ml_close(buf, true);
+ xfree(buf);
}
// Init the chartab used for spelling for ASCII.
@@ -2393,18 +2402,18 @@ void init_spell_chartab(void)
/// Thus this only works properly when past the first character of the word.
///
/// @param wp Buffer used.
-bool spell_iswordp(const char_u *p, const win_T *wp)
+bool spell_iswordp(const char *p, const win_T *wp)
FUNC_ATTR_NONNULL_ALL
{
- const int l = utfc_ptr2len((char *)p);
- const char_u *s = p;
+ const int l = utfc_ptr2len(p);
+ const char *s = p;
if (l == 1) {
// be quick for ASCII
- if (wp->w_s->b_spell_ismw[*p]) {
+ if (wp->w_s->b_spell_ismw[(uint8_t)(*p)]) {
s = p + 1; // skip a mid-word character
}
} else {
- int c = utf_ptr2char((char *)p);
+ int c = utf_ptr2char(p);
if (c < 256
? wp->w_s->b_spell_ismw[c]
: (wp->w_s->b_spell_ismw_mb != NULL
@@ -2413,20 +2422,20 @@ bool spell_iswordp(const char_u *p, const win_T *wp)
}
}
- int c = utf_ptr2char((char *)s);
+ int c = utf_ptr2char(s);
if (c > 255) {
- return spell_mb_isword_class(mb_get_class((char *)s), wp);
+ return spell_mb_isword_class(mb_get_class(s), wp);
}
return spelltab.st_isw[c];
}
// Returns true if "p" points to a word character.
// Unlike spell_iswordp() this doesn't check for "midword" characters.
-bool spell_iswordp_nmw(const char_u *p, win_T *wp)
+bool spell_iswordp_nmw(const char *p, win_T *wp)
{
- int c = utf_ptr2char((char *)p);
+ int c = utf_ptr2char(p);
if (c > 255) {
- return spell_mb_isword_class(mb_get_class((char *)p), wp);
+ return spell_mb_isword_class(mb_get_class(p), wp);
}
return spelltab.st_isw[c];
}
@@ -2471,7 +2480,7 @@ static bool spell_iswordp_w(const int *p, const win_T *wp)
// Uses the character definitions from the .spl file.
// When using a multi-byte 'encoding' the length may change!
// Returns FAIL when something wrong.
-int spell_casefold(const win_T *wp, char_u *str, int len, char_u *buf, int buflen)
+int spell_casefold(const win_T *wp, char *str, int len, char *buf, int buflen)
FUNC_ATTR_NONNULL_ALL
{
if (len >= buflen) {
@@ -2482,12 +2491,12 @@ int spell_casefold(const win_T *wp, char_u *str, int len, char_u *buf, int bufle
int outi = 0;
// Fold one character at a time.
- for (char_u *p = str; p < str + len;) {
+ for (char *p = str; p < str + len;) {
if (outi + MB_MAXBYTES > buflen) {
buf[outi] = NUL;
return FAIL;
}
- int c = mb_cptr2char_adv((const char_u **)&p);
+ int c = mb_cptr2char_adv((const char **)&p);
// Exception: greek capital sigma 0x03A3 folds to 0x03C3, except
// when it is the last character in a word, then it folds to
@@ -2502,7 +2511,7 @@ int spell_casefold(const win_T *wp, char_u *str, int len, char_u *buf, int bufle
c = SPELL_TOFOLD(c);
}
- outi += utf_char2bytes(c, (char *)buf + outi);
+ outi += utf_char2bytes(c, buf + outi);
}
buf[outi] = NUL;
@@ -2551,7 +2560,7 @@ bool check_need_cap(linenr_T lnum, colnr_T col)
char *p = line + endcol;
for (;;) {
MB_PTR_BACK(line, p);
- if (p == line || spell_iswordp_nmw((char_u *)p, curwin)) {
+ if (p == line || spell_iswordp_nmw(p, curwin)) {
break;
}
if (vim_regexec(&regmatch, p, 0)
@@ -2582,15 +2591,15 @@ void ex_spellrepall(exarg_T *eap)
int addlen = (int)(strlen(repl_to) - strlen(repl_from));
size_t frompatlen = strlen(repl_from) + 7;
- char_u *frompat = xmalloc(frompatlen);
- snprintf((char *)frompat, frompatlen, "\\V\\<%s\\>", repl_from);
+ char *frompat = xmalloc(frompatlen);
+ snprintf(frompat, frompatlen, "\\V\\<%s\\>", repl_from);
p_ws = false;
sub_nsubs = 0;
sub_nlines = 0;
curwin->w_cursor.lnum = 0;
while (!got_int) {
- if (do_search(NULL, '/', '/', (char *)frompat, 1L, SEARCH_KEEP, NULL) == 0
+ if (do_search(NULL, '/', '/', frompat, 1L, SEARCH_KEEP, NULL) == 0
|| u_save_cursor() == FAIL) {
break;
}
@@ -2600,11 +2609,11 @@ void ex_spellrepall(exarg_T *eap)
char *line = get_cursor_line_ptr();
if (addlen <= 0 || strncmp(line + curwin->w_cursor.col,
repl_to, strlen(repl_to)) != 0) {
- char_u *p = xmalloc(strlen(line) + (size_t)addlen + 1);
+ char *p = xmalloc(strlen(line) + (size_t)addlen + 1);
memmove(p, line, (size_t)curwin->w_cursor.col);
STRCPY(p + curwin->w_cursor.col, repl_to);
STRCAT(p, line + curwin->w_cursor.col + strlen(repl_from));
- ml_replace(curwin->w_cursor.lnum, (char *)p, false);
+ ml_replace(curwin->w_cursor.lnum, p, false);
changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col);
if (curwin->w_cursor.lnum != prev_lnum) {
@@ -2634,30 +2643,30 @@ void ex_spellrepall(exarg_T *eap)
/// @param[in] word source string to copy
/// @param[in,out] wcopy copied string, with case of first letter changed
/// @param[in] upper True to upper case, otherwise lower case
-void onecap_copy(char_u *word, char *wcopy, bool upper)
+void onecap_copy(char *word, char *wcopy, bool upper)
{
- char_u *p = word;
- int c = mb_cptr2char_adv((const char_u **)&p);
+ char *p = word;
+ int c = mb_cptr2char_adv((const char **)&p);
if (upper) {
c = SPELL_TOUPPER(c);
} else {
c = SPELL_TOFOLD(c);
}
int l = utf_char2bytes(c, wcopy);
- xstrlcpy(wcopy + l, (char *)p, (size_t)(MAXWLEN - l));
+ xstrlcpy(wcopy + l, p, (size_t)(MAXWLEN - l));
}
// Make a copy of "word" with all the letters upper cased into
// "wcopy[MAXWLEN]". The result is NUL terminated.
-void allcap_copy(char_u *word, char_u *wcopy)
+void allcap_copy(char *word, char *wcopy)
{
- char_u *d = wcopy;
- for (char_u *s = word; *s != NUL;) {
- int c = mb_cptr2char_adv((const char_u **)&s);
+ char_u *d = (char_u *)wcopy;
+ for (char *s = word; *s != NUL;) {
+ int c = mb_cptr2char_adv((const char **)&s);
if (c == 0xdf) {
c = 'S';
- if (d - wcopy >= MAXWLEN - 1) {
+ if (d - (char_u *)wcopy >= MAXWLEN - 1) {
break;
}
*d++ = (char_u)c;
@@ -2665,7 +2674,7 @@ void allcap_copy(char_u *word, char_u *wcopy)
c = SPELL_TOUPPER(c);
}
- if (d - wcopy >= MAXWLEN - MB_MAXBYTES) {
+ if (d - (char_u *)wcopy >= MAXWLEN - MB_MAXBYTES) {
break;
}
d += utf_char2bytes(c, (char *)d);
@@ -2675,9 +2684,9 @@ void allcap_copy(char_u *word, char_u *wcopy)
// Case-folding may change the number of bytes: Count nr of chars in
// fword[flen] and return the byte length of that many chars in "word".
-int nofold_len(char_u *fword, int flen, char_u *word)
+int nofold_len(char *fword, int flen, char *word)
{
- char_u *p;
+ char *p;
int i = 0;
for (p = fword; p < fword + flen; MB_PTR_ADV(p)) {
@@ -2690,14 +2699,14 @@ int nofold_len(char_u *fword, int flen, char_u *word)
}
// Copy "fword" to "cword", fixing case according to "flags".
-void make_case_word(char_u *fword, char_u *cword, int flags)
+void make_case_word(char *fword, char *cword, int flags)
{
if (flags & WF_ALLCAP) {
// Make it all upper-case
allcap_copy(fword, cword);
} else if (flags & WF_ONECAP) {
// Make the first letter upper-case
- onecap_copy(fword, (char *)cword, true);
+ onecap_copy(fword, cword, true);
} else {
// Use goodword as-is.
STRCPY(cword, fword);
@@ -2720,9 +2729,9 @@ char *eval_soundfold(const char *const word)
langp_T *const lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
if (!GA_EMPTY(&lp->lp_slang->sl_sal)) {
// soundfold the word
- char_u sound[MAXWLEN];
- spell_soundfold(lp->lp_slang, (char *)word, false, (char *)sound);
- return xstrdup((const char *)sound);
+ char sound[MAXWLEN];
+ spell_soundfold(lp->lp_slang, (char *)word, false, sound);
+ return xstrdup(sound);
}
}
}
@@ -2750,7 +2759,7 @@ void spell_soundfold(slang_T *slang, char *inword, bool folded, char *res)
{
if (slang->sl_sofo) {
// SOFOFROM and SOFOTO used
- spell_soundfold_sofo(slang, (char_u *)inword, (char_u *)res);
+ spell_soundfold_sofo(slang, inword, res);
} else {
char fword[MAXWLEN];
char *word;
@@ -2758,17 +2767,17 @@ void spell_soundfold(slang_T *slang, char *inword, bool folded, char *res)
if (folded) {
word = inword;
} else {
- (void)spell_casefold(curwin, (char_u *)inword, (int)strlen(inword), (char_u *)fword, MAXWLEN);
+ (void)spell_casefold(curwin, inword, (int)strlen(inword), fword, MAXWLEN);
word = fword;
}
- spell_soundfold_wsal(slang, (char_u *)word, (char_u *)res);
+ spell_soundfold_wsal(slang, word, res);
}
}
// Perform sound folding of "inword" into "res" according to SOFOFROM and
// SOFOTO lines.
-static void spell_soundfold_sofo(slang_T *slang, char_u *inword, char_u *res)
+static void spell_soundfold_sofo(slang_T *slang, char *inword, char *res)
{
int ri = 0;
@@ -2776,8 +2785,8 @@ static void spell_soundfold_sofo(slang_T *slang, char_u *inword, char_u *res)
// The sl_sal_first[] table contains the translation for chars up to
// 255, sl_sal the rest.
- for (char_u *s = inword; *s != NUL;) {
- int c = mb_cptr2char_adv((const char_u **)&s);
+ for (char *s = inword; *s != NUL;) {
+ int c = mb_cptr2char_adv((const char **)&s);
if (utf_class(c) == 0) {
c = ' ';
} else if (c < 256) {
@@ -2802,7 +2811,7 @@ static void spell_soundfold_sofo(slang_T *slang, char_u *inword, char_u *res)
}
if (c != NUL && c != prevc) {
- ri += utf_char2bytes(c, (char *)res + ri);
+ ri += utf_char2bytes(c, res + ri);
if (ri + MB_MAXBYTES > MAXWLEN) {
break;
}
@@ -2815,7 +2824,7 @@ static void spell_soundfold_sofo(slang_T *slang, char_u *inword, char_u *res)
// Turn "inword" into its sound-a-like equivalent in "res[MAXWLEN]".
// Multi-byte version of spell_soundfold().
-static void spell_soundfold_wsal(slang_T *slang, const char_u *inword, char_u *res)
+static void spell_soundfold_wsal(slang_T *slang, const char *inword, char *res)
{
salitem_T *smp = (salitem_T *)slang->sl_sal.ga_data;
int word[MAXWLEN] = { 0 };
@@ -2837,8 +2846,8 @@ static void spell_soundfold_wsal(slang_T *slang, const char_u *inword, char_u *r
// Remove accents, if wanted. We actually remove all non-word characters.
// But keep white space.
int wordlen = 0;
- for (const char_u *s = inword; *s != NUL;) {
- const char_u *t = s;
+ for (const char *s = (char *)inword; *s != NUL;) {
+ const char_u *t = (char_u *)s;
int c = mb_cptr2char_adv(&s);
if (slang->sl_rem_accents) {
if (utf_class(c) == 0) {
@@ -2849,7 +2858,7 @@ static void spell_soundfold_wsal(slang_T *slang, const char_u *inword, char_u *r
did_white = true;
} else {
did_white = false;
- if (!spell_iswordp_nmw(t, curwin)) {
+ if (!spell_iswordp_nmw((char *)t, curwin)) {
continue;
}
}
@@ -2906,7 +2915,7 @@ static void spell_soundfold_wsal(slang_T *slang, const char_u *inword, char_u *r
}
k++;
}
- char_u *s = smp[n].sm_rules;
+ char_u *s = (char_u *)smp[n].sm_rules;
pri = 5; // default priority
p0 = *s;
@@ -2983,7 +2992,7 @@ static void spell_soundfold_wsal(slang_T *slang, const char_u *inword, char_u *r
}
p0 = 5;
- s = smp[n0].sm_rules;
+ s = (char_u *)smp[n0].sm_rules;
while (*s == '-') {
// "k0" gets NOT reduced because
// "if (k0 == k)"
@@ -3024,7 +3033,7 @@ static void spell_soundfold_wsal(slang_T *slang, const char_u *inword, char_u *r
// replace string
ws = smp[n].sm_to_w;
- s = smp[n].sm_rules;
+ s = (char_u *)smp[n].sm_rules;
p0 = (vim_strchr((char *)s, '<') != NULL) ? 1 : 0;
if (p0 == 1 && z == 0) {
// rule with '<' is used
@@ -3102,7 +3111,7 @@ static void spell_soundfold_wsal(slang_T *slang, const char_u *inword, char_u *r
// Convert wide characters in "wres" to a multi-byte string in "res".
int l = 0;
for (int n = 0; n < reslen; n++) {
- l += utf_char2bytes(wres[n], (char *)res + l);
+ l += utf_char2bytes(wres[n], res + l);
if (l + MB_MAXBYTES > MAXWLEN) {
break;
}
@@ -3204,7 +3213,7 @@ void spell_dump_compl(char *pat, int ic, Direction *dir, int dumpflags_arg)
if (ic) {
dumpflags |= DUMPFLAG_ICASE;
} else {
- n = captype((char_u *)pat, NULL);
+ n = captype(pat, NULL);
if (n == WF_ONECAP) {
dumpflags |= DUMPFLAG_ONECAP;
} else if (n == WF_ALLCAP
@@ -3218,7 +3227,7 @@ void spell_dump_compl(char *pat, int ic, Direction *dir, int dumpflags_arg)
// regions or none at all.
for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len; lpi++) {
lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
- p = (char *)lp->lp_slang->sl_regions;
+ p = lp->lp_slang->sl_regions;
if (p[0] != 0) {
if (region_names == NULL) { // first language with regions
region_names = p;
@@ -3264,11 +3273,11 @@ void spell_dump_compl(char *pat, int ic, Direction *dir, int dumpflags_arg)
for (int round = 1; round <= 2; round++) {
if (round == 1) {
dumpflags &= ~DUMPFLAG_KEEPCASE;
- byts = (char *)slang->sl_fbyts;
+ byts = slang->sl_fbyts;
idxs = slang->sl_fidxs;
} else {
dumpflags |= DUMPFLAG_KEEPCASE;
- byts = (char *)slang->sl_kbyts;
+ byts = slang->sl_kbyts;
idxs = slang->sl_kidxs;
}
if (byts == NULL) {
@@ -3319,7 +3328,7 @@ void spell_dump_compl(char *pat, int ic, Direction *dir, int dumpflags_arg)
// Apply the prefix, if there is one.
if (c != 0) {
- lnum = dump_prefixes(slang, word, (char_u *)pat, dir,
+ lnum = dump_prefixes(slang, word, pat, dir,
dumpflags, flags, lnum);
}
}
@@ -3337,7 +3346,7 @@ void spell_dump_compl(char *pat, int ic, Direction *dir, int dumpflags_arg)
// ignore case...
assert(depth >= 0);
if (depth <= patlen
- && mb_strnicmp((char *)word, pat, (size_t)depth) != 0) {
+ && mb_strnicmp(word, pat, (size_t)depth) != 0) {
depth--;
}
}
@@ -3367,12 +3376,12 @@ static void dump_word(slang_T *slang, char *word, char *pat, Direction *dir, int
if ((dumpflags & DUMPFLAG_KEEPCASE) == 0 && (flags & WF_CAPMASK) != 0) {
// Need to fix case according to "flags".
- make_case_word((char_u *)word, (char_u *)cword, flags);
+ make_case_word(word, cword, flags);
p = cword;
} else {
p = word;
if ((dumpflags & DUMPFLAG_KEEPCASE)
- && ((captype((char_u *)word, NULL) & WF_KEEPCAP) == 0
+ && ((captype(word, NULL) & WF_KEEPCAP) == 0
|| (flags & WF_FIXCAP) != 0)) {
keepcap = true;
}
@@ -3436,8 +3445,8 @@ static void dump_word(slang_T *slang, char *word, char *pat, Direction *dir, int
/// @param flags flags with prefix ID
///
/// @return the updated line number.
-static linenr_T dump_prefixes(slang_T *slang, char *word, char_u *pat, Direction *dir,
- int dumpflags, int flags, linenr_T startlnum)
+static linenr_T dump_prefixes(slang_T *slang, char *word, char *pat, Direction *dir, int dumpflags,
+ int flags, linenr_T startlnum)
{
idx_T arridx[MAXWLEN];
int curi[MAXWLEN];
@@ -3450,11 +3459,11 @@ static linenr_T dump_prefixes(slang_T *slang, char *word, char_u *pat, Direction
// upper-case letter in word_up[].
int c = utf_ptr2char(word);
if (SPELL_TOUPPER(c) != c) {
- onecap_copy((char_u *)word, (char *)word_up, true);
+ onecap_copy(word, word_up, true);
has_word_up = true;
}
- char_u *byts = slang->sl_pbyts;
+ char_u *byts = (char_u *)slang->sl_pbyts;
idx_T *idxs = slang->sl_pidxs;
if (byts != NULL) { // array not is empty
// Loop over all prefixes, building them byte-by-byte in prefix[].
@@ -3484,10 +3493,10 @@ static linenr_T dump_prefixes(slang_T *slang, char *word, char_u *pat, Direction
}
curi[depth] += i - 1;
- c = valid_word_prefix(i, n, flags, (char_u *)word, slang, false);
+ c = valid_word_prefix(i, n, flags, word, slang, false);
if (c != 0) {
xstrlcpy(prefix + depth, word, (size_t)(MAXWLEN - depth));
- dump_word(slang, (char *)prefix, (char *)pat, dir, dumpflags,
+ dump_word(slang, prefix, pat, dir, dumpflags,
(c & WF_RAREPFX) ? (flags | WF_RARE) : flags, lnum);
if (lnum != 0) {
lnum++;
@@ -3498,11 +3507,10 @@ static linenr_T dump_prefixes(slang_T *slang, char *word, char_u *pat, Direction
// first letter is upper-case, but only if the prefix has
// a condition.
if (has_word_up) {
- c = valid_word_prefix(i, n, flags, (char_u *)word_up, slang,
- true);
+ c = valid_word_prefix(i, n, flags, word_up, slang, true);
if (c != 0) {
xstrlcpy(prefix + depth, word_up, (size_t)(MAXWLEN - depth));
- dump_word(slang, (char *)prefix, (char *)pat, dir, dumpflags,
+ dump_word(slang, prefix, pat, dir, dumpflags,
(c & WF_RAREPFX) ? (flags | WF_RARE) : flags, lnum);
if (lnum != 0) {
lnum++;
@@ -3524,9 +3532,9 @@ static linenr_T dump_prefixes(slang_T *slang, char *word, char_u *pat, Direction
// Move "p" to the end of word "start".
// Uses the spell-checking word characters.
-char_u *spell_to_word_end(char_u *start, win_T *win)
+char *spell_to_word_end(char *start, win_T *win)
{
- char_u *p = start;
+ char *p = start;
while (*p != NUL && spell_iswordp(p, win)) {
MB_PTR_ADV(p);
@@ -3545,8 +3553,8 @@ int spell_word_start(int startcol)
return startcol;
}
- char_u *line = (char_u *)get_cursor_line_ptr();
- char_u *p;
+ char *line = get_cursor_line_ptr();
+ char *p;
// Find a word character before "startcol".
for (p = line + startcol; p > line;) {
@@ -3588,7 +3596,7 @@ int expand_spelling(linenr_T lnum, char *pat, char ***matchp)
{
garray_T ga;
- spell_suggest_list(&ga, (char_u *)pat, 100, spell_expand_need_cap, true);
+ spell_suggest_list(&ga, pat, 100, spell_expand_need_cap, true);
*matchp = ga.ga_data;
return ga.ga_len;
}
@@ -3624,15 +3632,16 @@ char *did_set_spell_option(bool is_spellfile)
}
}
- if (errmsg == NULL) {
- FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if (wp->w_buffer == curbuf && wp->w_p_spell) {
- errmsg = did_set_spelllang(wp);
- break;
- }
- }
+ if (errmsg != NULL) {
+ return errmsg;
}
+ FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
+ if (wp->w_buffer == curbuf && wp->w_p_spell) {
+ errmsg = did_set_spelllang(wp);
+ break;
+ }
+ }
return errmsg;
}
diff --git a/src/nvim/spell_defs.h b/src/nvim/spell_defs.h
index 4d146a1706..726af7d698 100644
--- a/src/nvim/spell_defs.h
+++ b/src/nvim/spell_defs.h
@@ -80,11 +80,11 @@ typedef struct fromto_S {
// The info is split for quick processing by spell_soundfold().
// Note that "sm_oneof" and "sm_rules" point into sm_lead.
typedef struct salitem_S {
- char_u *sm_lead; // leading letters
- int sm_leadlen; // length of "sm_lead"
- char_u *sm_oneof; // letters from () or NULL
- char_u *sm_rules; // rules like ^, $, priority
- char_u *sm_to; // replacement.
+ char *sm_lead; // leading letters
+ int sm_leadlen; // length of "sm_lead"
+ char_u *sm_oneof; // letters from () or NULL
+ char *sm_rules; // rules like ^, $, priority
+ char *sm_to; // replacement.
int *sm_lead_w; // wide character copy of "sm_lead"
int *sm_oneof_w; // wide character copy of "sm_oneof"
int *sm_to_w; // wide character copy of "sm_to"
@@ -119,17 +119,17 @@ struct slang_S {
char *sl_fname; // name of .spl file
bool sl_add; // true if it's a .add file.
- char_u *sl_fbyts; // case-folded word bytes
+ char *sl_fbyts; // case-folded word bytes
long sl_fbyts_len; // length of sl_fbyts
idx_T *sl_fidxs; // case-folded word indexes
- char_u *sl_kbyts; // keep-case word bytes
+ char *sl_kbyts; // keep-case word bytes
idx_T *sl_kidxs; // keep-case word indexes
- char_u *sl_pbyts; // prefix tree word bytes
+ char *sl_pbyts; // prefix tree word bytes
idx_T *sl_pidxs; // prefix tree word indexes
char_u *sl_info; // infotext string or NULL
- char_u sl_regions[MAXREGIONS * 2 + 1];
+ char sl_regions[MAXREGIONS * 2 + 1];
// table with up to 8 region names plus NUL
char_u *sl_midword; // MIDWORD string or NULL
@@ -143,9 +143,9 @@ struct slang_S {
garray_T sl_comppat; // CHECKCOMPOUNDPATTERN items
regprog_T *sl_compprog; // COMPOUNDRULE turned into a regexp progrm
// (NULL when no compounding)
- char_u *sl_comprules; // all COMPOUNDRULE concatenated (or NULL)
- char_u *sl_compstartflags; // flags for first compound word
- char_u *sl_compallflags; // all flags for compound words
+ uint8_t *sl_comprules; // all COMPOUNDRULE concatenated (or NULL)
+ uint8_t *sl_compstartflags; // flags for first compound word
+ uint8_t *sl_compallflags; // all flags for compound words
bool sl_nobreak; // When true: no spaces between words
char_u *sl_syllable; // SYLLABLE repeatable chars or NULL
garray_T sl_syl_items; // syllable items
@@ -172,7 +172,7 @@ struct slang_S {
// Info from the .sug file. Loaded on demand.
time_t sl_sugtime; // timestamp for .sug file
- char_u *sl_sbyts; // soundfolded word bytes
+ char *sl_sbyts; // soundfolded word bytes
idx_T *sl_sidxs; // soundfolded word indexes
buf_T *sl_sugbuf; // buffer with word number table
bool sl_sugloaded; // true when .sug file was loaded or failed to
@@ -227,7 +227,7 @@ typedef struct {
extern slang_T *first_lang;
// file used for "zG" and "zW"
-extern char_u *int_wordlist;
+extern char *int_wordlist;
extern spelltab_T spelltab;
extern int did_set_spelltab;
diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c
index e6257aeca1..7b124ae6b6 100644
--- a/src/nvim/spellfile.c
+++ b/src/nvim/spellfile.c
@@ -270,10 +270,6 @@
#include "nvim/undo.h"
#include "nvim/vim.h"
-#ifndef UNIX // it's in os/unix_defs.h for Unix
-# include <time.h>
-#endif
-
// Special byte values for <byte>. Some are only used in the tree for
// postponed prefixes, some only in the other trees. This is a bit messy...
enum {
@@ -336,7 +332,7 @@ static char *msg_compressing = N_("Compressing word tree...");
// and .dic file.
// Main structure to store the contents of a ".aff" file.
typedef struct afffile_S {
- char_u *af_enc; // "SET", normalized, alloc'ed string or NULL
+ char *af_enc; // "SET", normalized, alloc'ed string or NULL
int af_flagtype; // AFT_CHAR, AFT_LONG, AFT_NUM or AFT_CAPLONG
unsigned af_rare; // RARE ID for rare word
unsigned af_keepcase; // KEEPCASE ID for keep-case word
@@ -364,12 +360,12 @@ typedef struct afffile_S {
typedef struct affentry_S affentry_T;
// Affix entry from ".aff" file. Used for prefixes and suffixes.
struct affentry_S {
- affentry_T *ae_next; // next affix with same name/number
- char *ae_chop; // text to chop off basic word (can be NULL)
- char *ae_add; // text to add to basic word (can be NULL)
- char_u *ae_flags; // flags on the affix (can be NULL)
- char_u *ae_cond; // condition (NULL for ".")
- regprog_T *ae_prog; // regexp program for ae_cond or NULL
+ affentry_T *ae_next; // next affix with same name/number
+ char *ae_chop; // text to chop off basic word (can be NULL)
+ char *ae_add; // text to add to basic word (can be NULL)
+ char *ae_flags; // flags on the affix (can be NULL)
+ char *ae_cond; // condition (NULL for ".")
+ regprog_T *ae_prog; // regexp program for ae_cond or NULL
char ae_compforbid; // COMPOUNDFORBIDFLAG found
char ae_comppermit; // COMPOUNDPERMITFLAG found
};
@@ -724,7 +720,7 @@ slang_T *spell_load_file(char *fname, char *lang, slang_T *old_lp, bool silent)
if (p == NULL) {
goto endFAIL;
}
- set_map_str(lp, (char_u *)p);
+ set_map_str(lp, p);
xfree(p);
break;
@@ -1004,8 +1000,8 @@ someerror:
// Need to put word counts in the word tries, so that we can find
// a word by its number.
- tree_count_words(slang->sl_fbyts, slang->sl_fidxs);
- tree_count_words(slang->sl_sbyts, slang->sl_sidxs);
+ tree_count_words((char_u *)slang->sl_fbyts, slang->sl_fidxs);
+ tree_count_words((char_u *)slang->sl_sbyts, slang->sl_sidxs);
nextone:
if (fd != NULL) {
@@ -1054,7 +1050,7 @@ static int read_region_section(FILE *fd, slang_T *lp, int len)
if (len > MAXREGIONS * 2) {
return SP_FORMERROR;
}
- SPELL_READ_NONNUL_BYTES((char *)lp->sl_regions, (size_t)len, fd,; ); // NOLINT(whitespace/parens)
+ SPELL_READ_NONNUL_BYTES(lp->sl_regions, (size_t)len, fd,; ); // NOLINT(whitespace/parens)
lp->sl_regions[len] = NUL;
return 0;
}
@@ -1064,12 +1060,12 @@ static int read_region_section(FILE *fd, slang_T *lp, int len)
// Return SP_*ERROR flags.
static int read_charflags_section(FILE *fd)
{
- char_u *flags;
+ char *flags;
char_u *fol;
int flagslen, follen;
// <charflagslen> <charflags>
- flags = read_cnt_string(fd, 1, &flagslen);
+ flags = (char *)read_cnt_string(fd, 1, &flagslen);
if (flagslen < 0) {
return flagslen;
}
@@ -1083,7 +1079,7 @@ static int read_charflags_section(FILE *fd)
// Set the word-char flags and fill SPELL_ISUPPER() table.
if (flags != NULL && fol != NULL) {
- set_spell_charflags(flags, flagslen, fol);
+ set_spell_charflags((char_u *)flags, flagslen, (char *)fol);
}
xfree(flags);
@@ -1219,7 +1215,7 @@ static int read_sal_section(FILE *fd, slang_T *slang)
return SP_TRUNCERROR;
}
p = xmalloc((size_t)ccnt + 2);
- smp->sm_lead = p;
+ smp->sm_lead = (char *)p;
// Read up to the first special char into sm_lead.
int i = 0;
@@ -1230,7 +1226,7 @@ static int read_sal_section(FILE *fd, slang_T *slang)
}
*p++ = (char_u)c;
}
- smp->sm_leadlen = (int)(p - smp->sm_lead);
+ smp->sm_leadlen = (int)(p - (char_u *)smp->sm_lead);
*p++ = NUL;
// Put (abc) chars in sm_oneof, if any.
@@ -1252,7 +1248,7 @@ static int read_sal_section(FILE *fd, slang_T *slang)
}
// Any following chars go in sm_rules.
- smp->sm_rules = p;
+ smp->sm_rules = (char *)p;
if (i < ccnt) {
// store the char we got while checking for end of sm_lead
*p++ = (char_u)c;
@@ -1267,7 +1263,7 @@ static int read_sal_section(FILE *fd, slang_T *slang)
*p++ = NUL;
// <saltolen> <salto>
- smp->sm_to = read_cnt_string(fd, 1, &ccnt);
+ smp->sm_to = (char *)read_cnt_string(fd, 1, &ccnt);
if (ccnt < 0) {
xfree(smp->sm_lead);
return ccnt;
@@ -1275,11 +1271,11 @@ static int read_sal_section(FILE *fd, slang_T *slang)
// convert the multi-byte strings to wide char strings
smp->sm_lead_w = mb_str2wide(smp->sm_lead);
- smp->sm_leadlen = mb_charlen((char *)smp->sm_lead);
+ smp->sm_leadlen = mb_charlen(smp->sm_lead);
if (smp->sm_oneof == NULL) {
smp->sm_oneof_w = NULL;
} else {
- smp->sm_oneof_w = mb_str2wide(smp->sm_oneof);
+ smp->sm_oneof_w = mb_str2wide((char *)smp->sm_oneof);
}
if (smp->sm_to == NULL) {
smp->sm_to_w = NULL;
@@ -1294,12 +1290,12 @@ static int read_sal_section(FILE *fd, slang_T *slang)
smp = &((salitem_T *)gap->ga_data)[gap->ga_len];
p = xmalloc(1);
p[0] = NUL;
- smp->sm_lead = p;
+ smp->sm_lead = (char *)p;
smp->sm_lead_w = mb_str2wide(smp->sm_lead);
smp->sm_leadlen = 0;
smp->sm_oneof = NULL;
smp->sm_oneof_w = NULL;
- smp->sm_rules = p;
+ smp->sm_rules = (char *)p;
smp->sm_to = NULL;
smp->sm_to_w = NULL;
gap->ga_len++;
@@ -1348,19 +1344,19 @@ static int read_words_section(FILE *fd, slang_T *lp, int len)
static int read_sofo_section(FILE *fd, slang_T *slang)
{
int cnt;
- char_u *from, *to;
+ char *from, *to;
int res;
slang->sl_sofo = true;
// <sofofromlen> <sofofrom>
- from = read_cnt_string(fd, 2, &cnt);
+ from = (char *)read_cnt_string(fd, 2, &cnt);
if (cnt < 0) {
return cnt;
}
// <sofotolen> <sofoto>
- to = read_cnt_string(fd, 2, &cnt);
+ to = (char *)read_cnt_string(fd, 2, &cnt);
if (cnt < 0) {
xfree(from);
return cnt;
@@ -1430,7 +1426,7 @@ static int read_compound(FILE *fd, slang_T *slang, int len)
return SP_TRUNCERROR;
}
todo -= 2;
- ga_init(gap, sizeof(char_u *), c);
+ ga_init(gap, sizeof(char *), c);
ga_grow(gap, c);
while (--c >= 0) {
((char **)(gap->ga_data))[gap->ga_len++] = (char *)read_cnt_string(fd, 1, &cnt);
@@ -1451,25 +1447,25 @@ static int read_compound(FILE *fd, slang_T *slang, int len)
// Conversion to utf-8 may double the size.
c = todo * 2 + 7;
c += todo * 2;
- char_u *pat = xmalloc((size_t)c);
+ char *pat = xmalloc((size_t)c);
// We also need a list of all flags that can appear at the start and one
// for all flags.
- char_u *cp = xmalloc((size_t)todo + 1);
+ uint8_t *cp = xmalloc((size_t)todo + 1);
slang->sl_compstartflags = cp;
*cp = NUL;
- char_u *ap = xmalloc((size_t)todo + 1);
+ uint8_t *ap = xmalloc((size_t)todo + 1);
slang->sl_compallflags = ap;
*ap = NUL;
// And a list of all patterns in their original form, for checking whether
// compounding may work in match_compoundrule(). This is freed when we
// encounter a wildcard, the check doesn't work then.
- char_u *crp = xmalloc((size_t)todo + 1);
+ uint8_t *crp = xmalloc((size_t)todo + 1);
slang->sl_comprules = crp;
- char_u *pp = pat;
+ char_u *pp = (char_u *)pat;
*pp++ = '^';
*pp++ = '\\';
*pp++ = '(';
@@ -1538,7 +1534,7 @@ static int read_compound(FILE *fd, slang_T *slang, int len)
*crp = NUL;
}
- slang->sl_compprog = vim_regcomp((char *)pat, RE_MAGIC + RE_STRING + RE_STRICT);
+ slang->sl_compprog = vim_regcomp(pat, RE_MAGIC + RE_STRING + RE_STRICT);
xfree(pat);
if (slang->sl_compprog == NULL) {
return SP_FORMERROR;
@@ -1549,10 +1545,10 @@ static int read_compound(FILE *fd, slang_T *slang, int len)
// Set the SOFOFROM and SOFOTO items in language "lp".
// Returns SP_*ERROR flags when there is something wrong.
-static int set_sofo(slang_T *lp, char_u *from, char_u *to)
+static int set_sofo(slang_T *lp, char *from, char *to)
{
- char_u *s;
- char_u *p;
+ char *s;
+ char *p;
// Use "sl_sal" as an array with 256 pointers to a list of wide
// characters. The index is the low byte of the character.
@@ -1567,7 +1563,7 @@ static int set_sofo(slang_T *lp, char_u *from, char_u *to)
// First count the number of items for each list. Temporarily use
// sl_sal_first[] for this.
for (p = from, s = to; *p != NUL && *s != NUL;) {
- const int c = mb_cptr2char_adv((const char_u **)&p);
+ const int c = mb_cptr2char_adv((const char **)&p);
MB_CPTR_ADV(s);
if (c >= 256) {
lp->sl_sal_first[c & 0xff]++;
@@ -1590,8 +1586,8 @@ static int set_sofo(slang_T *lp, char_u *from, char_u *to)
// list.
memset(lp->sl_sal_first, 0, sizeof(salfirst_T) * 256);
for (p = from, s = to; *p != NUL && *s != NUL;) {
- const int c = mb_cptr2char_adv((const char_u **)&p);
- const int i = mb_cptr2char_adv((const char_u **)&s);
+ const int c = mb_cptr2char_adv((const char **)&p);
+ const int i = mb_cptr2char_adv((const char **)&s);
if (c >= 256) {
// Append the from-to chars at the end of the list with
// the low byte.
@@ -1660,13 +1656,13 @@ static void set_sal_first(slang_T *lp)
// Turn a multi-byte string into a wide character string.
// Return it in allocated memory.
-static int *mb_str2wide(char_u *s)
+static int *mb_str2wide(char *s)
{
int i = 0;
- int *res = xmalloc(((size_t)mb_charlen((char *)s) + 1) * sizeof(int));
- for (char_u *p = s; *p != NUL;) {
- res[i++] = mb_ptr2char_adv((const char_u **)&p);
+ int *res = xmalloc(((size_t)mb_charlen(s) + 1) * sizeof(int));
+ for (char *p = s; *p != NUL;) {
+ res[i++] = mb_ptr2char_adv((const char **)&p);
}
res[i] = NUL;
@@ -1681,12 +1677,12 @@ static int *mb_str2wide(char_u *s)
/// @param prefixcnt when "prefixtree" is true: prefix count
///
/// @return zero when OK, SP_ value for an error.
-static int spell_read_tree(FILE *fd, char_u **bytsp, long *bytsp_len, idx_T **idxsp,
- bool prefixtree, int prefixcnt)
+static int spell_read_tree(FILE *fd, char **bytsp, long *bytsp_len, idx_T **idxsp, bool prefixtree,
+ int prefixcnt)
FUNC_ATTR_NONNULL_ARG(1, 2, 4)
{
int idx;
- char_u *bp;
+ char *bp;
idx_T *ip;
// The tree size was computed when writing the file, so that we can
@@ -1699,23 +1695,25 @@ static int spell_read_tree(FILE *fd, char_u **bytsp, long *bytsp_len, idx_T **id
// Invalid length, multiply with sizeof(int) would overflow.
return SP_FORMERROR;
}
- if (len > 0) {
- // Allocate the byte array.
- bp = xmalloc((size_t)len);
- *bytsp = bp;
- if (bytsp_len != NULL) {
- *bytsp_len = len;
- }
+ if (len <= 0) {
+ return 0;
+ }
- // Allocate the index array.
- ip = xcalloc((size_t)len, sizeof(*ip));
- *idxsp = ip;
+ // Allocate the byte array.
+ bp = xmalloc((size_t)len);
+ *bytsp = bp;
+ if (bytsp_len != NULL) {
+ *bytsp_len = len;
+ }
- // Recursively read the tree and store it in the array.
- idx = read_tree_node(fd, bp, ip, (int)len, 0, prefixtree, prefixcnt);
- if (idx < 0) {
- return idx;
- }
+ // Allocate the index array.
+ ip = xcalloc((size_t)len, sizeof(*ip));
+ *idxsp = ip;
+
+ // Recursively read the tree and store it in the array.
+ idx = read_tree_node(fd, (char_u *)bp, ip, (int)len, 0, prefixtree, prefixcnt);
+ if (idx < 0) {
+ return idx;
}
return 0;
}
@@ -1839,15 +1837,15 @@ static idx_T read_tree_node(FILE *fd, char_u *byts, idx_T *idxs, int maxidx, idx
/// Reload the spell file "fname" if it's loaded.
///
/// @param added_word invoked through "zg"
-static void spell_reload_one(char_u *fname, bool added_word)
+static void spell_reload_one(char *fname, bool added_word)
{
slang_T *slang;
bool didit = false;
for (slang = first_lang; slang != NULL; slang = slang->sl_next) {
- if (path_full_compare((char *)fname, slang->sl_fname, false, true) == kEqualFiles) {
+ if (path_full_compare(fname, slang->sl_fname, false, true) == kEqualFiles) {
slang_clear(slang);
- if (spell_load_file((char *)fname, NULL, slang, false) == NULL) {
+ if (spell_load_file(fname, NULL, slang, false) == NULL) {
// reloading failed, clear the language
slang_clear(slang);
}
@@ -2007,26 +2005,27 @@ static void spell_print_node(wordnode_T *node, int depth)
static void spell_print_tree(wordnode_T *root)
{
- if (root != NULL) {
- // Clear the "wn_u1.index" fields, used to remember what has been
- // done.
- spell_clear_flags(root);
-
- // Recursively print the tree.
- spell_print_node(root, 0);
+ if (root == NULL) {
+ return;
}
+
+ // Clear the "wn_u1.index" fields, used to remember what has been done.
+ spell_clear_flags(root);
+
+ // Recursively print the tree.
+ spell_print_node(root, 0);
}
#endif // SPELL_PRINTTREE
// Reads the affix file "fname".
// Returns an afffile_T, NULL for complete failure.
-static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
+static afffile_T *spell_read_aff(spellinfo_T *spin, char *fname)
{
FILE *fd;
- char_u rline[MAXLINELEN];
- char_u *line;
- char_u *pc = NULL;
+ char rline[MAXLINELEN];
+ char *line;
+ char *pc = NULL;
#define MAXITEMCNT 30
char *(items[MAXITEMCNT]);
int itemcnt;
@@ -2052,13 +2051,13 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
int compmax = 0; // COMPOUNDWORDMAX value
char *compflags = NULL; // COMPOUNDFLAG and COMPOUNDRULE
// concatenated
- char_u *midword = NULL; // MIDWORD value
- char_u *syllable = NULL; // SYLLABLE value
- char_u *sofofrom = NULL; // SOFOFROM value
- char_u *sofoto = NULL; // SOFOTO value
+ char *midword = NULL; // MIDWORD value
+ char *syllable = NULL; // SYLLABLE value
+ char *sofofrom = NULL; // SOFOFROM value
+ char *sofoto = NULL; // SOFOTO value
// Open the file.
- fd = os_fopen((char *)fname, "r");
+ fd = os_fopen(fname, "r");
if (fd == NULL) {
semsg(_(e_notopen), fname);
return NULL;
@@ -2086,7 +2085,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
hash_init(&aff->af_comp);
// Read all the lines in the file one by one.
- while (!vim_fgets((char *)rline, MAXLINELEN, fd) && !got_int) {
+ while (!vim_fgets(rline, MAXLINELEN, fd) && !got_int) {
line_breakcheck();
lnum++;
@@ -2098,7 +2097,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
// Convert from "SET" to 'encoding' when needed.
xfree(pc);
if (spin->si_conv.vc_type != CONV_NONE) {
- pc = (char_u *)string_convert(&spin->si_conv, (char *)rline, NULL);
+ pc = string_convert(&spin->si_conv, rline, NULL);
if (pc == NULL) {
smsg(_("Conversion failure for word in %s line %d: %s"),
fname, lnum, rline);
@@ -2113,7 +2112,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
// Split the line up in white separated items. Put a NUL after each
// item.
itemcnt = 0;
- for (p = (char *)line;;) {
+ for (p = line;;) {
while (*p != NUL && (uint8_t)(*p) <= ' ') { // skip white space and CR/NL
p++;
}
@@ -2144,9 +2143,9 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
if (itemcnt > 0) {
if (is_aff_rule(items, itemcnt, "SET", 2) && aff->af_enc == NULL) {
// Setup for conversion from "ENC" to 'encoding'.
- aff->af_enc = (char_u *)enc_canonize((char *)items[1]);
+ aff->af_enc = enc_canonize((char *)items[1]);
if (!spin->si_ascii
- && convert_setup(&spin->si_conv, (char *)aff->af_enc, p_enc) == FAIL) {
+ && convert_setup(&spin->si_conv, aff->af_enc, p_enc) == FAIL) {
smsg(_("Conversion in %s not supported: from %s to %s"),
fname, aff->af_enc, p_enc);
}
@@ -2191,57 +2190,47 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
STRCAT(p, items[1]);
spin->si_info = p;
} else if (is_aff_rule(items, itemcnt, "MIDWORD", 2) && midword == NULL) {
- midword = (char_u *)getroom_save(spin, items[1]);
+ midword = getroom_save(spin, items[1]);
} else if (is_aff_rule(items, itemcnt, "TRY", 2)) {
// ignored, we look in the tree for what chars may appear
} else if ((is_aff_rule(items, itemcnt, "RAR", 2) // TODO(vim): remove "RAR" later
|| is_aff_rule(items, itemcnt, "RARE", 2))
&& aff->af_rare == 0) {
- aff->af_rare = affitem2flag(aff->af_flagtype, (char_u *)items[1],
- fname, lnum);
+ aff->af_rare = affitem2flag(aff->af_flagtype, items[1], fname, lnum);
} else if ((is_aff_rule(items, itemcnt, "KEP", 2) // TODO(vim): remove "KEP" later
|| is_aff_rule(items, itemcnt, "KEEPCASE", 2))
&& aff->af_keepcase == 0) {
- aff->af_keepcase = affitem2flag(aff->af_flagtype, (char_u *)items[1],
- fname, lnum);
+ aff->af_keepcase = affitem2flag(aff->af_flagtype, items[1], fname, lnum);
} else if ((is_aff_rule(items, itemcnt, "BAD", 2)
|| is_aff_rule(items, itemcnt, "FORBIDDENWORD", 2))
&& aff->af_bad == 0) {
- aff->af_bad = affitem2flag(aff->af_flagtype, (char_u *)items[1],
- fname, lnum);
+ aff->af_bad = affitem2flag(aff->af_flagtype, items[1], fname, lnum);
} else if (is_aff_rule(items, itemcnt, "NEEDAFFIX", 2)
&& aff->af_needaffix == 0) {
- aff->af_needaffix = affitem2flag(aff->af_flagtype, (char_u *)items[1],
- fname, lnum);
+ aff->af_needaffix = affitem2flag(aff->af_flagtype, items[1], fname, lnum);
} else if (is_aff_rule(items, itemcnt, "CIRCUMFIX", 2)
&& aff->af_circumfix == 0) {
- aff->af_circumfix = affitem2flag(aff->af_flagtype, (char_u *)items[1],
- fname, lnum);
+ aff->af_circumfix = affitem2flag(aff->af_flagtype, items[1], fname, lnum);
} else if (is_aff_rule(items, itemcnt, "NOSUGGEST", 2)
&& aff->af_nosuggest == 0) {
- aff->af_nosuggest = affitem2flag(aff->af_flagtype, (char_u *)items[1],
- fname, lnum);
+ aff->af_nosuggest = affitem2flag(aff->af_flagtype, items[1], fname, lnum);
} else if ((is_aff_rule(items, itemcnt, "NEEDCOMPOUND", 2)
|| is_aff_rule(items, itemcnt, "ONLYINCOMPOUND", 2))
&& aff->af_needcomp == 0) {
- aff->af_needcomp = affitem2flag(aff->af_flagtype, (char_u *)items[1],
- fname, lnum);
+ aff->af_needcomp = affitem2flag(aff->af_flagtype, items[1], fname, lnum);
} else if (is_aff_rule(items, itemcnt, "COMPOUNDROOT", 2)
&& aff->af_comproot == 0) {
- aff->af_comproot = affitem2flag(aff->af_flagtype, (char_u *)items[1],
- fname, lnum);
+ aff->af_comproot = affitem2flag(aff->af_flagtype, items[1], fname, lnum);
} else if (is_aff_rule(items, itemcnt, "COMPOUNDFORBIDFLAG", 2)
&& aff->af_compforbid == 0) {
- aff->af_compforbid = affitem2flag(aff->af_flagtype, (char_u *)items[1],
- fname, lnum);
+ aff->af_compforbid = affitem2flag(aff->af_flagtype, items[1], fname, lnum);
if (aff->af_pref.ht_used > 0) {
smsg(_("Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in %s line %d"),
fname, lnum);
}
} else if (is_aff_rule(items, itemcnt, "COMPOUNDPERMITFLAG", 2)
&& aff->af_comppermit == 0) {
- aff->af_comppermit = affitem2flag(aff->af_flagtype, (char_u *)items[1],
- fname, lnum);
+ aff->af_comppermit = affitem2flag(aff->af_flagtype, items[1], fname, lnum);
if (aff->af_pref.ht_used > 0) {
smsg(_("Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in %s line %d"),
fname, lnum);
@@ -2330,7 +2319,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
}
} else if (is_aff_rule(items, itemcnt, "SYLLABLE", 2)
&& syllable == NULL) {
- syllable = (char_u *)getroom_save(spin, items[1]);
+ syllable = getroom_save(spin, items[1]);
} else if (is_aff_rule(items, itemcnt, "NOBREAK", 1)) {
spin->si_nobreak = true;
} else if (is_aff_rule(items, itemcnt, "NOSPLITSUGS", 1)) {
@@ -2375,8 +2364,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
} else {
// New affix letter.
cur_aff = getroom(spin, sizeof(*cur_aff), true);
- cur_aff->ah_flag = affitem2flag(aff->af_flagtype, (char_u *)items[1],
- fname, lnum);
+ cur_aff->ah_flag = affitem2flag(aff->af_flagtype, items[1], fname, lnum);
if (cur_aff->ah_flag == 0 || strlen(items[1]) >= AH_KEY_LEN) {
break;
}
@@ -2469,7 +2457,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
aff_entry->ae_add = getroom_save(spin, items[3]);
// Recognize flags on the affix: abcd/XYZ
- aff_entry->ae_flags = (char_u *)vim_strchr(aff_entry->ae_add, '/');
+ aff_entry->ae_flags = vim_strchr(aff_entry->ae_add, '/');
if (aff_entry->ae_flags != NULL) {
*aff_entry->ae_flags++ = NUL;
aff_process_flags(aff, aff_entry);
@@ -2484,15 +2472,15 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
cur_aff->ah_first = aff_entry;
if (strcmp(items[4], ".") != 0) {
- char_u buf[MAXLINELEN];
+ char buf[MAXLINELEN];
- aff_entry->ae_cond = (char_u *)getroom_save(spin, items[4]);
+ aff_entry->ae_cond = getroom_save(spin, items[4]);
if (*items[0] == 'P') {
- sprintf((char *)buf, "^%s", items[4]); // NOLINT(runtime/printf)
+ sprintf(buf, "^%s", items[4]); // NOLINT(runtime/printf)
} else {
- sprintf((char *)buf, "%s$", items[4]); // NOLINT(runtime/printf)
+ sprintf(buf, "%s$", items[4]); // NOLINT(runtime/printf)
}
- aff_entry->ae_prog = vim_regcomp((char *)buf, RE_MAGIC + RE_STRING + RE_STRICT);
+ aff_entry->ae_prog = vim_regcomp(buf, RE_MAGIC + RE_STRING + RE_STRICT);
if (aff_entry->ae_prog == NULL) {
smsg(_("Broken condition in %s line %d: %s"),
fname, lnum, items[4]);
@@ -2520,7 +2508,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
c_up = SPELL_TOUPPER(c);
if (c_up != c
&& (aff_entry->ae_cond == NULL
- || utf_ptr2char((char *)aff_entry->ae_cond) == c)) {
+ || utf_ptr2char(aff_entry->ae_cond) == c)) {
p = aff_entry->ae_add + strlen(aff_entry->ae_add);
MB_PTR_BACK(aff_entry->ae_add, p);
if (utf_ptr2char(p) == c_up) {
@@ -2532,13 +2520,13 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
// actual word, thus must check for the
// upper-case letter.
if (aff_entry->ae_cond != NULL) {
- char_u buf[MAXLINELEN];
- onecap_copy((char_u *)items[4], (char *)buf, true);
- aff_entry->ae_cond = (char_u *)getroom_save(spin, (char *)buf);
+ char buf[MAXLINELEN];
+ onecap_copy(items[4], buf, true);
+ aff_entry->ae_cond = getroom_save(spin, buf);
if (aff_entry->ae_cond != NULL) {
- sprintf((char *)buf, "^%s", aff_entry->ae_cond); // NOLINT(runtime/printf)
+ sprintf(buf, "^%s", aff_entry->ae_cond); // NOLINT(runtime/printf)
vim_regfree(aff_entry->ae_prog);
- aff_entry->ae_prog = vim_regcomp((char *)buf, RE_MAGIC + RE_STRING);
+ aff_entry->ae_prog = vim_regcomp(buf, RE_MAGIC + RE_STRING);
}
}
}
@@ -2553,7 +2541,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
// Find a previously used condition.
for (idx = spin->si_prefcond.ga_len - 1; idx >= 0; idx--) {
p = ((char **)spin->si_prefcond.ga_data)[idx];
- if (str_equal(p, (char *)aff_entry->ae_cond)) {
+ if (str_equal(p, aff_entry->ae_cond)) {
break;
}
}
@@ -2562,7 +2550,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
idx = spin->si_prefcond.ga_len;
pp = GA_APPEND_VIA_PTR(char_u *, &spin->si_prefcond);
*pp = (aff_entry->ae_cond == NULL) ?
- NULL : (char_u *)getroom_save(spin, (char *)aff_entry->ae_cond);
+ NULL : (char_u *)getroom_save(spin, aff_entry->ae_cond);
}
// Add the prefix to the prefix tree.
@@ -2608,7 +2596,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
} else if (is_aff_rule(items, itemcnt, "REP", 2)
|| is_aff_rule(items, itemcnt, "REPSAL", 2)) {
// Ignore REP/REPSAL count
- if (!isdigit(*items[1])) {
+ if (!isdigit((uint8_t)(*items[1]))) {
smsg(_("Expected REP(SAL) count in %s line %d"),
fname, lnum);
}
@@ -2643,7 +2631,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
if (!found_map) {
// First line contains the count.
found_map = true;
- if (!isdigit(*items[1])) {
+ if (!isdigit((uint8_t)(*items[1]))) {
smsg(_("Expected MAP count in %s line %d"),
fname, lnum);
}
@@ -2652,7 +2640,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
// Check that every character appears only once.
for (p = items[1]; *p != NUL;) {
- c = mb_ptr2char_adv((const char_u **)&p);
+ c = mb_ptr2char_adv((const char **)&p);
if ((!GA_EMPTY(&spin->si_map)
&& vim_strchr(spin->si_map.ga_data, c)
!= NULL)
@@ -2688,10 +2676,10 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
}
} else if (is_aff_rule(items, itemcnt, "SOFOFROM", 2)
&& sofofrom == NULL) {
- sofofrom = (char_u *)getroom_save(spin, items[1]);
+ sofofrom = getroom_save(spin, items[1]);
} else if (is_aff_rule(items, itemcnt, "SOFOTO", 2)
&& sofoto == NULL) {
- sofoto = (char_u *)getroom_save(spin, items[1]);
+ sofoto = getroom_save(spin, items[1]);
} else if (strcmp(items[0], "COMMON") == 0) {
int i;
@@ -2761,8 +2749,8 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
}
if (syllable != NULL) {
- aff_check_string(spin->si_syllable, (char *)syllable, "SYLLABLE");
- spin->si_syllable = (char *)syllable;
+ aff_check_string(spin->si_syllable, syllable, "SYLLABLE");
+ spin->si_syllable = syllable;
}
if (sofofrom != NULL || sofoto != NULL) {
@@ -2772,16 +2760,16 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
} else if (!GA_EMPTY(&spin->si_sal)) {
smsg(_("Both SAL and SOFO lines in %s"), fname);
} else {
- aff_check_string(spin->si_sofofr, (char *)sofofrom, "SOFOFROM");
- aff_check_string(spin->si_sofoto, (char *)sofoto, "SOFOTO");
- spin->si_sofofr = (char *)sofofrom;
- spin->si_sofoto = (char *)sofoto;
+ aff_check_string(spin->si_sofofr, sofofrom, "SOFOFROM");
+ aff_check_string(spin->si_sofoto, sofoto, "SOFOTO");
+ spin->si_sofofr = sofofrom;
+ spin->si_sofoto = sofoto;
}
}
if (midword != NULL) {
- aff_check_string(spin->si_midword, (char *)midword, "MIDWORD");
- spin->si_midword = (char *)midword;
+ aff_check_string(spin->si_midword, midword, "MIDWORD");
+ spin->si_midword = midword;
}
xfree(pc);
@@ -2802,18 +2790,18 @@ static bool is_aff_rule(char **items, int itemcnt, char *rulename, int mincount)
// ae_flags to ae_comppermit and ae_compforbid.
static void aff_process_flags(afffile_T *affile, affentry_T *entry)
{
- char_u *p;
+ char *p;
char_u *prevp;
unsigned flag;
if (entry->ae_flags != NULL
&& (affile->af_compforbid != 0 || affile->af_comppermit != 0)) {
for (p = entry->ae_flags; *p != NUL;) {
- prevp = p;
+ prevp = (char_u *)p;
flag = get_affitem(affile->af_flagtype, &p);
if (flag == affile->af_comppermit || flag == affile->af_compforbid) {
STRMOVE(prevp, (char *)p);
- p = prevp;
+ p = (char *)prevp;
if (flag == affile->af_comppermit) {
entry->ae_comppermit = true;
} else {
@@ -2843,10 +2831,10 @@ static bool spell_info_item(char *s)
// Turn an affix flag name into a number, according to the FLAG type.
// returns zero for failure.
-static unsigned affitem2flag(int flagtype, char_u *item, char_u *fname, int lnum)
+static unsigned affitem2flag(int flagtype, char *item, char *fname, int lnum)
{
unsigned res;
- char_u *p = item;
+ char *p = item;
res = get_affitem(flagtype, &p);
if (res == 0) {
@@ -2869,7 +2857,7 @@ static unsigned affitem2flag(int flagtype, char_u *item, char_u *fname, int lnum
// Get one affix name from "*pp" and advance the pointer.
// Returns ZERO_FLAG for "0".
// Returns zero for an error, still advances the pointer then.
-static unsigned get_affitem(int flagtype, char_u **pp)
+static unsigned get_affitem(int flagtype, char **pp)
{
int res;
@@ -2878,18 +2866,18 @@ static unsigned get_affitem(int flagtype, char_u **pp)
(*pp)++; // always advance, avoid getting stuck
return 0;
}
- res = getdigits_int((char **)pp, true, 0);
+ res = getdigits_int(pp, true, 0);
if (res == 0) {
res = ZERO_FLAG;
}
} else {
- res = mb_ptr2char_adv((const char_u **)pp);
+ res = mb_ptr2char_adv((const char **)pp);
if (flagtype == AFT_LONG || (flagtype == AFT_CAPLONG
&& res >= 'A' && res <= 'Z')) {
if (**pp == NUL) {
return 0;
}
- res = mb_ptr2char_adv((const char_u **)pp) + (res << 16);
+ res = mb_ptr2char_adv((const char **)pp) + (res << 16);
}
}
return (unsigned)res;
@@ -2927,13 +2915,13 @@ static void process_compflags(spellinfo_T *spin, afffile_T *aff, char *compflags
tp = (char_u *)p + strlen(p);
for (p = compflags; *p != NUL;) {
- if (vim_strchr("/?*+[]", *p) != NULL) {
+ if (vim_strchr("/?*+[]", (uint8_t)(*p)) != NULL) {
// Copy non-flag characters directly.
*tp++ = (char_u)(*p++);
} else {
// First get the flag number, also checks validity.
prevp = p;
- flag = get_affitem(aff->af_flagtype, (char_u **)&p);
+ flag = get_affitem(aff->af_flagtype, &p);
if (flag != 0) {
// Find the flag in the hashtable. If it was used before, use
// the existing ID. Otherwise add a new entry.
@@ -2978,22 +2966,22 @@ static void check_renumber(spellinfo_T *spin)
}
// Returns true if flag "flag" appears in affix list "afflist".
-static bool flag_in_afflist(int flagtype, char_u *afflist, unsigned flag)
+static bool flag_in_afflist(int flagtype, char *afflist, unsigned flag)
{
char *p;
unsigned n;
switch (flagtype) {
case AFT_CHAR:
- return vim_strchr((char *)afflist, (int)flag) != NULL;
+ return vim_strchr(afflist, (int)flag) != NULL;
case AFT_CAPLONG:
case AFT_LONG:
- for (p = (char *)afflist; *p != NUL;) {
- n = (unsigned)mb_ptr2char_adv((const char_u **)&p);
+ for (p = afflist; *p != NUL;) {
+ n = (unsigned)mb_ptr2char_adv((const char **)&p);
if ((flagtype == AFT_LONG || (n >= 'A' && n <= 'Z'))
&& *p != NUL) {
- n = (unsigned)mb_ptr2char_adv((const char_u **)&p) + (n << 16);
+ n = (unsigned)mb_ptr2char_adv((const char **)&p) + (n << 16);
}
if (n == flag) {
return true;
@@ -3002,7 +2990,7 @@ static bool flag_in_afflist(int flagtype, char_u *afflist, unsigned flag)
break;
case AFT_NUM:
- for (p = (char *)afflist; *p != NUL;) {
+ for (p = afflist; *p != NUL;) {
int digits = getdigits_int(&p, true, 0);
assert(digits >= 0);
n = (unsigned int)digits;
@@ -3053,13 +3041,13 @@ static bool str_equal(char *s1, char *s2)
/// They are stored case-folded.
static void add_fromto(spellinfo_T *spin, garray_T *gap, char *from, char *to)
{
- char_u word[MAXWLEN];
+ char word[MAXWLEN];
fromto_T *ftp = GA_APPEND_VIA_PTR(fromto_T, gap);
- (void)spell_casefold(curwin, (char_u *)from, (int)strlen(from), word, MAXWLEN);
- ftp->ft_from = getroom_save(spin, (char *)word);
- (void)spell_casefold(curwin, (char_u *)to, (int)strlen(to), word, MAXWLEN);
- ftp->ft_to = getroom_save(spin, (char *)word);
+ (void)spell_casefold(curwin, from, (int)strlen(from), word, MAXWLEN);
+ ftp->ft_from = getroom_save(spin, word);
+ (void)spell_casefold(curwin, to, (int)strlen(to), word, MAXWLEN);
+ ftp->ft_to = getroom_save(spin, word);
}
/// Converts a boolean argument in a SAL line to true or false;
@@ -3103,7 +3091,7 @@ static void spell_free_aff(afffile_T *aff)
// Read dictionary file "fname".
// Returns OK or FAIL;
-static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile)
+static int spell_read_dic(spellinfo_T *spin, char *fname, afffile_T *affile)
{
hashtab_T ht;
char line[MAXLINELEN];
@@ -3128,7 +3116,7 @@ static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile)
Timestamp last_msg_time = 0;
// Open the file.
- fd = os_fopen((char *)fname, "r");
+ fd = os_fopen(fname, "r");
if (fd == NULL) {
semsg(_(e_notopen), fname);
return FAIL;
@@ -3229,7 +3217,7 @@ static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile)
break;
}
- hash = hash_hash((char_u *)dw);
+ hash = hash_hash(dw);
hi = hash_lookup(&ht, (const char *)dw, strlen(dw), hash);
if (!HASHITEM_EMPTY(hi)) {
if (p_verbose > 0) {
@@ -3241,7 +3229,7 @@ static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile)
}
duplicate++;
} else {
- hash_add_item(&ht, hi, (char_u *)dw, hash);
+ hash_add_item(&ht, hi, dw, hash);
}
flags = 0;
@@ -3250,43 +3238,43 @@ static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile)
need_affix = false;
if (afflist != NULL) {
// Extract flags from the affix list.
- flags |= get_affix_flags(affile, afflist);
+ flags |= get_affix_flags(affile, (char *)afflist);
if (affile->af_needaffix != 0
- && flag_in_afflist(affile->af_flagtype, afflist,
+ && flag_in_afflist(affile->af_flagtype, (char *)afflist,
affile->af_needaffix)) {
need_affix = true;
}
if (affile->af_pfxpostpone) {
// Need to store the list of prefix IDs with the word.
- pfxlen = get_pfxlist(affile, afflist, store_afflist);
+ pfxlen = get_pfxlist(affile, (char *)afflist, store_afflist);
}
if (spin->si_compflags != NULL) {
// Need to store the list of compound flags with the word.
// Concatenate them to the list of prefix IDs.
- get_compflags(affile, afflist, store_afflist + pfxlen);
+ get_compflags(affile, (char *)afflist, store_afflist + pfxlen);
}
}
// Add the word to the word tree(s).
if (store_word(spin, dw, flags, spin->si_region,
- store_afflist, need_affix) == FAIL) {
+ (char *)store_afflist, need_affix) == FAIL) {
retval = FAIL;
}
if (afflist != NULL) {
// Find all matching suffixes and add the resulting words.
// Additionally do matching prefixes that combine.
- if (store_aff_word(spin, dw, afflist, affile,
+ if (store_aff_word(spin, dw, (char *)afflist, affile,
&affile->af_suff, &affile->af_pref,
CONDIT_SUF, flags, (char *)store_afflist, pfxlen) == FAIL) {
retval = FAIL;
}
// Find all matching prefixes and add the resulting words.
- if (store_aff_word(spin, dw, afflist, affile,
+ if (store_aff_word(spin, dw, (char *)afflist, affile,
&affile->af_pref, NULL,
CONDIT_SUF, flags, (char *)store_afflist, pfxlen) == FAIL) {
retval = FAIL;
@@ -3311,7 +3299,7 @@ static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile)
// Check for affix flags in "afflist" that are turned into word flags.
// Return WF_ flags.
-static int get_affix_flags(afffile_T *affile, char_u *afflist)
+static int get_affix_flags(afffile_T *affile, char *afflist)
{
int flags = 0;
@@ -3350,9 +3338,9 @@ static int get_affix_flags(afffile_T *affile, char_u *afflist)
// Used for PFXPOSTPONE.
// Put the resulting flags in "store_afflist[MAXWLEN]" with a terminating NUL
// and return the number of affixes.
-static int get_pfxlist(afffile_T *affile, char_u *afflist, char_u *store_afflist)
+static int get_pfxlist(afffile_T *affile, char *afflist, char_u *store_afflist)
{
- char_u *p;
+ char *p;
char *prevp;
int cnt = 0;
int id;
@@ -3360,11 +3348,11 @@ static int get_pfxlist(afffile_T *affile, char_u *afflist, char_u *store_afflist
hashitem_T *hi;
for (p = afflist; *p != NUL;) {
- prevp = (char *)p;
+ prevp = p;
if (get_affitem(affile->af_flagtype, &p) != 0) {
// A flag is a postponed prefix flag if it appears in "af_pref"
// and its ID is not zero.
- xstrlcpy(key, prevp, (size_t)(p - (char_u *)prevp) + 1);
+ xstrlcpy(key, prevp, (size_t)(p - prevp) + 1);
hi = hash_find(&affile->af_pref, (char *)key);
if (!HASHITEM_EMPTY(hi)) {
id = HI2AH(hi)->ah_newID;
@@ -3385,19 +3373,19 @@ static int get_pfxlist(afffile_T *affile, char_u *afflist, char_u *store_afflist
// Get the list of compound IDs from the affix list "afflist" that are used
// for compound words.
// Puts the flags in "store_afflist[]".
-static void get_compflags(afffile_T *affile, char_u *afflist, char_u *store_afflist)
+static void get_compflags(afffile_T *affile, char *afflist, char_u *store_afflist)
{
- char_u *p;
+ char *p;
char *prevp;
int cnt = 0;
char key[AH_KEY_LEN];
hashitem_T *hi;
for (p = afflist; *p != NUL;) {
- prevp = (char *)p;
+ prevp = p;
if (get_affitem(affile->af_flagtype, &p) != 0) {
// A flag is a compound flag if it appears in "af_comp".
- xstrlcpy(key, prevp, (size_t)(p - (char_u *)prevp) + 1);
+ xstrlcpy(key, prevp, (size_t)(p - prevp) + 1);
hi = hash_find(&affile->af_comp, (char *)key);
if (!HASHITEM_EMPTY(hi)) {
store_afflist[cnt++] = (char_u)HI2CI(hi)->ci_newID;
@@ -3426,7 +3414,7 @@ static void get_compflags(afffile_T *affile, char_u *afflist, char_u *store_affl
/// @param pfxlen nr of flags in "pfxlist" for prefixes, rest is compound flags
///
/// @return FAIL when out of memory.
-static int store_aff_word(spellinfo_T *spin, char *word, char_u *afflist, afffile_T *affile,
+static int store_aff_word(spellinfo_T *spin, char *word, char *afflist, afffile_T *affile,
hashtab_T *ht, hashtab_T *xht, int condit, int flags, char *pfxlist,
int pfxlen)
{
@@ -3437,7 +3425,7 @@ static int store_aff_word(spellinfo_T *spin, char *word, char_u *afflist, afffil
char newword[MAXWLEN];
int retval = OK;
int i, j;
- char_u *p;
+ char *p;
int use_flags;
char *use_pfxlist;
int use_pfxlen;
@@ -3476,7 +3464,7 @@ static int store_aff_word(spellinfo_T *spin, char *word, char_u *afflist, afffil
&& (ae->ae_chop == NULL
|| strlen(ae->ae_chop) < wordlen)
&& (ae->ae_prog == NULL
- || vim_regexec_prog(&ae->ae_prog, false, (char_u *)word, (colnr_T)0))
+ || vim_regexec_prog(&ae->ae_prog, false, word, (colnr_T)0))
&& (((condit & CONDIT_CFIX) == 0)
== ((condit & CONDIT_AFF) == 0
|| ae->ae_flags == NULL
@@ -3490,7 +3478,7 @@ static int store_aff_word(spellinfo_T *spin, char *word, char_u *afflist, afffil
} else {
xstrlcpy(newword, ae->ae_add, MAXWLEN);
}
- p = (char_u *)word;
+ p = word;
if (ae->ae_chop != NULL) {
// Skip chop string.
i = mb_charlen(ae->ae_chop);
@@ -3504,7 +3492,7 @@ static int store_aff_word(spellinfo_T *spin, char *word, char_u *afflist, afffil
xstrlcpy(newword, word, MAXWLEN);
if (ae->ae_chop != NULL) {
// Remove chop string.
- p = (char_u *)newword + strlen(newword);
+ p = newword + strlen(newword);
i = mb_charlen(ae->ae_chop);
for (; i > 0; i--) {
MB_PTR_BACK(newword, p);
@@ -3525,16 +3513,18 @@ static int store_aff_word(spellinfo_T *spin, char *word, char_u *afflist, afffil
// Extract flags from the affix list.
use_flags |= get_affix_flags(affile, ae->ae_flags);
- if (affile->af_needaffix != 0 && flag_in_afflist(affile->af_flagtype, ae->ae_flags,
- affile->af_needaffix)) {
+ if (affile->af_needaffix != 0
+ && flag_in_afflist(affile->af_flagtype, ae->ae_flags,
+ affile->af_needaffix)) {
need_affix = true;
}
// When there is a CIRCUMFIX flag the other affix
// must also have it and we don't add the word
// with one affix.
- if (affile->af_circumfix != 0 && flag_in_afflist(affile->af_flagtype, ae->ae_flags,
- affile->af_circumfix)) {
+ if (affile->af_circumfix != 0
+ && flag_in_afflist(affile->af_flagtype, ae->ae_flags,
+ affile->af_circumfix)) {
use_condit |= CONDIT_CFIX;
if ((condit & CONDIT_CFIX) == 0) {
need_affix = true;
@@ -3545,8 +3535,7 @@ static int store_aff_word(spellinfo_T *spin, char *word, char_u *afflist, afffil
|| spin->si_compflags != NULL) {
if (affile->af_pfxpostpone) {
// Get prefix IDS from the affix list.
- use_pfxlen = get_pfxlist(affile,
- ae->ae_flags, store_afflist);
+ use_pfxlen = get_pfxlist(affile, ae->ae_flags, store_afflist);
} else {
use_pfxlen = 0;
}
@@ -3624,7 +3613,7 @@ static int store_aff_word(spellinfo_T *spin, char *word, char_u *afflist, afffil
// Store the modified word.
if (store_word(spin, newword, use_flags,
- spin->si_region, (char_u *)use_pfxlist,
+ spin->si_region, use_pfxlist,
need_affix) == FAIL) {
retval = FAIL;
}
@@ -3669,7 +3658,7 @@ static int store_aff_word(spellinfo_T *spin, char *word, char_u *afflist, afffil
}
// Read a file with a list of words.
-static int spell_read_wordfile(spellinfo_T *spin, char_u *fname)
+static int spell_read_wordfile(spellinfo_T *spin, char *fname)
{
FILE *fd;
long lnum = 0;
@@ -3685,7 +3674,7 @@ static int spell_read_wordfile(spellinfo_T *spin, char_u *fname)
int regionmask;
// Open the file.
- fd = os_fopen((char *)fname, "r");
+ fd = os_fopen(fname, "r");
if (fd == NULL) {
semsg(_(e_notopen), fname);
return FAIL;
@@ -3695,7 +3684,7 @@ static int spell_read_wordfile(spellinfo_T *spin, char_u *fname)
spell_message(spin, IObuff);
// Read all the lines in the file one by one.
- while (!vim_fgets((char *)rline, MAXLINELEN, fd) && !got_int) {
+ while (!vim_fgets(rline, MAXLINELEN, fd) && !got_int) {
line_breakcheck();
lnum++;
@@ -3866,7 +3855,7 @@ static void *getroom(spellinfo_T *spin, size_t len, bool align)
if (bl == NULL || (size_t)bl->sb_used + len > SBLOCKSIZE) {
// Allocate a block of memory. It is not freed until much later.
- bl = xcalloc(1, (sizeof(sblock_T) + SBLOCKSIZE));
+ bl = xcalloc(1, offsetof(sblock_T, sb_data) + SBLOCKSIZE + 1);
bl->sb_next = spin->si_blocks;
spin->si_blocks = bl;
bl->sb_used = 0;
@@ -3935,11 +3924,11 @@ static bool valid_spell_word(const char *word, const char *end)
/// @param region supported region(s)
/// @param pfxlist list of prefix ids or null
/// @param need_affix only store word with affix id
-static int store_word(spellinfo_T *spin, char *word, int flags, int region, const char_u *pfxlist,
+static int store_word(spellinfo_T *spin, char *word, int flags, int region, const char *pfxlist,
bool need_affix)
{
int len = (int)strlen(word);
- int ct = captype((char_u *)word, (char_u *)word + len);
+ int ct = captype(word, word + len);
char_u foldword[MAXWLEN];
int res = OK;
@@ -3948,8 +3937,8 @@ static int store_word(spellinfo_T *spin, char *word, int flags, int region, cons
return FAIL;
}
- (void)spell_casefold(curwin, (char_u *)word, len, foldword, MAXWLEN);
- for (const char_u *p = pfxlist; res == OK; p++) {
+ (void)spell_casefold(curwin, word, len, (char *)foldword, MAXWLEN);
+ for (const char_u *p = (char_u *)pfxlist; res == OK; p++) {
if (!need_affix || (p != NULL && *p != NUL)) {
res = tree_add_word(spin, foldword, spin->si_foldroot, ct | flags,
region, p == NULL ? 0 : *p);
@@ -3961,7 +3950,7 @@ static int store_word(spellinfo_T *spin, char *word, int flags, int region, cons
spin->si_foldwcount++;
if (res == OK && (ct == WF_KEEPCAP || (flags & WF_KEEPCAP))) {
- for (const char_u *p = pfxlist; res == OK; p++) {
+ for (const char_u *p = (char_u *)pfxlist; res == OK; p++) {
if (!need_affix || (p != NULL && *p != NUL)) {
res = tree_add_word(spin, (char_u *)word, spin->si_keeproot, flags,
region, p == NULL ? 0 : *p);
@@ -4211,31 +4200,33 @@ static void wordtree_compress(spellinfo_T *spin, wordnode_T *root, const char *n
// Skip the root itself, it's not actually used. The first sibling is the
// start of the tree.
- if (root->wn_sibling != NULL) {
- hash_init(&ht);
- const long n = node_compress(spin, root->wn_sibling, &ht, &tot);
+ if (root->wn_sibling == NULL) {
+ return;
+ }
+
+ hash_init(&ht);
+ const long n = node_compress(spin, root->wn_sibling, &ht, &tot);
#ifndef SPELL_PRINTTREE
- if (spin->si_verbose || p_verbose > 2)
+ if (spin->si_verbose || p_verbose > 2)
#endif
- {
- if (tot > 1000000) {
- perc = (tot - n) / (tot / 100);
- } else if (tot == 0) {
- perc = 0;
- } else {
- perc = (tot - n) * 100 / tot;
- }
- vim_snprintf(IObuff, IOSIZE,
- _("Compressed %s of %ld nodes; %ld (%ld%%) remaining"),
- name, tot, tot - n, perc);
- spell_message(spin, IObuff);
+ {
+ if (tot > 1000000) {
+ perc = (tot - n) / (tot / 100);
+ } else if (tot == 0) {
+ perc = 0;
+ } else {
+ perc = (tot - n) * 100 / tot;
}
+ vim_snprintf(IObuff, IOSIZE,
+ _("Compressed %s of %ld nodes; %ld (%ld%%) remaining"),
+ name, tot, tot - n, perc);
+ spell_message(spin, IObuff);
+ }
#ifdef SPELL_PRINTTREE
- spell_print_tree(root->wn_sibling);
+ spell_print_tree(root->wn_sibling);
#endif
- hash_clear(&ht);
- }
+ hash_clear(&ht);
}
/// Compress a node, its siblings and its children, depth first.
@@ -4265,7 +4256,7 @@ static long node_compress(spellinfo_T *spin, wordnode_T *node, hashtab_T *ht, lo
compressed += node_compress(spin, child, ht, tot);
// Try to find an identical child.
- hash = hash_hash(child->wn_u1.hashkey);
+ hash = hash_hash((char *)child->wn_u1.hashkey);
hi = hash_lookup(ht, (const char *)child->wn_u1.hashkey,
strlen((char *)child->wn_u1.hashkey), hash);
if (!HASHITEM_EMPTY(hi)) {
@@ -4294,7 +4285,7 @@ static long node_compress(spellinfo_T *spin, wordnode_T *node, hashtab_T *ht, lo
} else {
// No other child has this hash value, add it to the
// hashtable.
- hash_add_item(ht, hi, child->wn_u1.hashkey, hash);
+ hash_add_item(ht, hi, (char *)child->wn_u1.hashkey, hash);
}
}
}
@@ -4901,10 +4892,12 @@ void ex_mkspell(exarg_T *eap)
}
// Expand all the remaining arguments (e.g., $VIMRUNTIME).
- if (get_arglist_exp(arg, &fcount, &fnames, false) == OK) {
- mkspell(fcount, fnames, ascii, eap->forceit, false);
- FreeWild(fcount, fnames);
+ if (get_arglist_exp(arg, &fcount, &fnames, false) != OK) {
+ return;
}
+
+ mkspell(fcount, fnames, ascii, eap->forceit, false);
+ FreeWild(fcount, fnames);
}
// Create the .sug file.
@@ -4974,7 +4967,7 @@ static void spell_make_sugfile(spellinfo_T *spin, char *wfname)
len = (int)strlen(fname);
fname[len - 2] = 'u';
fname[len - 1] = 'g';
- sug_write(spin, (char_u *)fname);
+ sug_write(spin, fname);
theend:
xfree(fname);
@@ -5008,7 +5001,7 @@ static int sug_filltree(spellinfo_T *spin, slang_T *slang)
// Go through the whole case-folded tree, soundfold each word and put it
// in the trie.
- byts = slang->sl_fbyts;
+ byts = (char_u *)slang->sl_fbyts;
idxs = slang->sl_fidxs;
arridx[0] = 0;
@@ -5199,10 +5192,10 @@ static int offset2bytes(int nr, char_u *buf)
}
// Write the .sug file in "fname".
-static void sug_write(spellinfo_T *spin, char_u *fname)
+static void sug_write(spellinfo_T *spin, char *fname)
{
// Create the file. Note that an existing file is silently overwritten!
- FILE *fd = os_fopen((char *)fname, "w");
+ FILE *fd = os_fopen(fname, "w");
if (fd == NULL) {
semsg(_(e_notopen), fname);
return;
@@ -5284,7 +5277,7 @@ theend:
/// @param added_word invoked through "zg"
static void mkspell(int fcount, char **fnames, bool ascii, bool over_write, bool added_word)
{
- char_u *fname = NULL;
+ char *fname = NULL;
char **innames;
int incount;
afffile_T *(afile[MAXREGIONS]);
@@ -5301,9 +5294,9 @@ static void mkspell(int fcount, char **fnames, bool ascii, bool over_write, bool
ga_init(&spin.si_rep, (int)sizeof(fromto_T), 20);
ga_init(&spin.si_repsal, (int)sizeof(fromto_T), 20);
ga_init(&spin.si_sal, (int)sizeof(fromto_T), 20);
- ga_init(&spin.si_map, (int)sizeof(char_u), 100);
- ga_init(&spin.si_comppat, (int)sizeof(char_u *), 20);
- ga_init(&spin.si_prefcond, (int)sizeof(char_u *), 50);
+ ga_init(&spin.si_map, (int)sizeof(char), 100);
+ ga_init(&spin.si_comppat, (int)sizeof(char *), 20);
+ ga_init(&spin.si_prefcond, (int)sizeof(char *), 50);
hash_init(&spin.si_commonwords);
spin.si_newcompID = 127; // start compound ID at first maximum
@@ -5325,14 +5318,14 @@ static void mkspell(int fcount, char **fnames, bool ascii, bool over_write, bool
// For ":mkspell path/vim" output file is "path/vim.latin1.spl".
incount = 1;
vim_snprintf(wfname, MAXPATHL, SPL_FNAME_TMPL,
- fnames[0], spin.si_ascii ? (char_u *)"ascii" : spell_enc());
+ fnames[0], spin.si_ascii ? "ascii" : spell_enc());
} else if (len > 4 && strcmp(fnames[0] + len - 4, ".spl") == 0) {
// Name ends in ".spl", use as the file name.
xstrlcpy(wfname, fnames[0], MAXPATHL);
} else {
// Name should be language, make the file name from it.
vim_snprintf(wfname, MAXPATHL, SPL_FNAME_TMPL,
- fnames[0], spin.si_ascii ? (char_u *)"ascii" : spell_enc());
+ fnames[0], spin.si_ascii ? "ascii" : spell_enc());
}
// Check for .ascii.spl.
@@ -5404,8 +5397,8 @@ static void mkspell(int fcount, char **fnames, bool ascii, bool over_write, bool
spin.si_conv.vc_type = CONV_NONE;
spin.si_region = 1 << i;
- vim_snprintf((char *)fname, MAXPATHL, "%s.aff", innames[i]);
- if (os_path_exists((char *)fname)) {
+ vim_snprintf(fname, MAXPATHL, "%s.aff", innames[i]);
+ if (os_path_exists(fname)) {
// Read the .aff file. Will init "spin->si_conv" based on the
// "SET" line.
afile[i] = spell_read_aff(&spin, fname);
@@ -5413,8 +5406,7 @@ static void mkspell(int fcount, char **fnames, bool ascii, bool over_write, bool
error = true;
} else {
// Read the .dic file and store the words in the trees.
- vim_snprintf((char *)fname, MAXPATHL, "%s.dic",
- innames[i]);
+ vim_snprintf(fname, MAXPATHL, "%s.dic", innames[i]);
if (spell_read_dic(&spin, fname, afile[i]) == FAIL) {
error = true;
}
@@ -5422,7 +5414,7 @@ static void mkspell(int fcount, char **fnames, bool ascii, bool over_write, bool
} else {
// No .aff file, try reading the file as a word list. Store
// the words in the trees.
- if (spell_read_wordfile(&spin, (char_u *)innames[i]) == FAIL) {
+ if (spell_read_wordfile(&spin, innames[i]) == FAIL) {
error = true;
}
}
@@ -5458,7 +5450,7 @@ static void mkspell(int fcount, char **fnames, bool ascii, bool over_write, bool
// If the file is loaded need to reload it.
if (!error) {
- spell_reload_one((char_u *)wfname, added_word);
+ spell_reload_one(wfname, added_word);
}
}
@@ -5534,11 +5526,11 @@ void spell_add_word(char *word, int len, SpellAddType what, int idx, bool undo)
buf_T *buf = NULL;
bool new_spf = false;
char *fname;
- char_u *fnamebuf = NULL;
+ char *fnamebuf = NULL;
char line[MAXWLEN * 2];
long fpos, fpos_next = 0;
int i;
- char_u *spf;
+ char *spf;
if (!valid_spell_word(word, word + len)) {
emsg(_(e_illegal_character_in_word));
@@ -5547,12 +5539,12 @@ void spell_add_word(char *word, int len, SpellAddType what, int idx, bool undo)
if (idx == 0) { // use internal wordlist
if (int_wordlist == NULL) {
- int_wordlist = (char_u *)vim_tempname();
+ int_wordlist = vim_tempname();
if (int_wordlist == NULL) {
return;
}
}
- fname = (char *)int_wordlist;
+ fname = int_wordlist;
} else {
// If 'spellfile' isn't set figure out a good default value.
if (*curwin->w_s->b_p_spf == NUL) {
@@ -5566,8 +5558,8 @@ void spell_add_word(char *word, int len, SpellAddType what, int idx, bool undo)
}
fnamebuf = xmalloc(MAXPATHL);
- for (spf = (char_u *)curwin->w_s->b_p_spf, i = 1; *spf != NUL; i++) {
- copy_option_part((char **)&spf, (char *)fnamebuf, MAXPATHL, ",");
+ for (spf = curwin->w_s->b_p_spf, i = 1; *spf != NUL; i++) {
+ copy_option_part(&spf, fnamebuf, MAXPATHL, ",");
if (i == idx) {
break;
}
@@ -5579,7 +5571,7 @@ void spell_add_word(char *word, int len, SpellAddType what, int idx, bool undo)
}
// Check that the user isn't editing the .add file somewhere.
- buf = buflist_findname_exp((char *)fnamebuf);
+ buf = buflist_findname_exp(fnamebuf);
if (buf != NULL && buf->b_ml.ml_mfp == NULL) {
buf = NULL;
}
@@ -5589,7 +5581,7 @@ void spell_add_word(char *word, int len, SpellAddType what, int idx, bool undo)
return;
}
- fname = (char *)fnamebuf;
+ fname = fnamebuf;
}
if (what == SPELL_ADD_BAD || undo) {
@@ -5690,82 +5682,84 @@ static void init_spellfile(void)
{
char *buf;
int l;
- char_u *fname;
- char_u *rtp;
- char_u *lend;
+ char *fname;
+ char *rtp;
+ char *lend;
bool aspath = false;
- char_u *lstart = (char_u *)curbuf->b_s.b_p_spl;
-
- if (*curwin->w_s->b_p_spl != NUL && !GA_EMPTY(&curwin->w_s->b_langp)) {
- buf = xmalloc(MAXPATHL);
-
- // Find the end of the language name. Exclude the region. If there
- // is a path separator remember the start of the tail.
- for (lend = (char_u *)curwin->w_s->b_p_spl; *lend != NUL
- && vim_strchr(",._", *lend) == NULL; lend++) {
- if (vim_ispathsep(*lend)) {
- aspath = true;
- lstart = lend + 1;
- }
+ char *lstart = curbuf->b_s.b_p_spl;
+
+ if (*curwin->w_s->b_p_spl == NUL || GA_EMPTY(&curwin->w_s->b_langp)) {
+ return;
+ }
+
+ buf = xmalloc(MAXPATHL);
+
+ // Find the end of the language name. Exclude the region. If there
+ // is a path separator remember the start of the tail.
+ for (lend = curwin->w_s->b_p_spl; *lend != NUL
+ && vim_strchr(",._", (uint8_t)(*lend)) == NULL; lend++) {
+ if (vim_ispathsep(*lend)) {
+ aspath = true;
+ lstart = lend + 1;
}
+ }
- // Loop over all entries in 'runtimepath'. Use the first one where we
- // are allowed to write.
- rtp = (char_u *)p_rtp;
- while (*rtp != NUL) {
+ // Loop over all entries in 'runtimepath'. Use the first one where we
+ // are allowed to write.
+ rtp = p_rtp;
+ while (*rtp != NUL) {
+ if (aspath) {
+ // Use directory of an entry with path, e.g., for
+ // "/dir/lg.utf-8.spl" use "/dir".
+ xstrlcpy(buf, curbuf->b_s.b_p_spl, (size_t)(lstart - curbuf->b_s.b_p_spl));
+ } else {
+ // Copy the path from 'runtimepath' to buf[].
+ copy_option_part(&rtp, buf, MAXPATHL, ",");
+ }
+ if (os_file_is_writable(buf) == 2) {
+ // Use the first language name from 'spelllang' and the
+ // encoding used in the first loaded .spl file.
if (aspath) {
- // Use directory of an entry with path, e.g., for
- // "/dir/lg.utf-8.spl" use "/dir".
- xstrlcpy(buf, curbuf->b_s.b_p_spl, (size_t)(lstart - (char_u *)curbuf->b_s.b_p_spl));
+ xstrlcpy(buf, curbuf->b_s.b_p_spl, (size_t)(lend - curbuf->b_s.b_p_spl + 1));
} else {
- // Copy the path from 'runtimepath' to buf[].
- copy_option_part((char **)&rtp, buf, MAXPATHL, ",");
- }
- if (os_file_is_writable(buf) == 2) {
- // Use the first language name from 'spelllang' and the
- // encoding used in the first loaded .spl file.
- if (aspath) {
- xstrlcpy(buf, curbuf->b_s.b_p_spl, (size_t)(lend - (char_u *)curbuf->b_s.b_p_spl + 1));
- } else {
- // Create the "spell" directory if it doesn't exist yet.
- l = (int)strlen(buf);
- vim_snprintf(buf + l, MAXPATHL - (size_t)l, "/spell");
- if (os_file_is_writable(buf) != 2) {
- os_mkdir(buf, 0755);
- }
-
- l = (int)strlen(buf);
- vim_snprintf(buf + l, MAXPATHL - (size_t)l,
- "/%.*s", (int)(lend - lstart), lstart);
+ // Create the "spell" directory if it doesn't exist yet.
+ l = (int)strlen(buf);
+ vim_snprintf(buf + l, MAXPATHL - (size_t)l, "/spell");
+ if (os_file_is_writable(buf) != 2) {
+ os_mkdir(buf, 0755);
}
+
l = (int)strlen(buf);
- fname = (char_u *)LANGP_ENTRY(curwin->w_s->b_langp, 0)
- ->lp_slang->sl_fname;
- vim_snprintf(buf + l, MAXPATHL - (size_t)l, ".%s.add",
- ((fname != NULL
- && strstr(path_tail((char *)fname), ".ascii.") != NULL)
- ? "ascii"
- : (const char *)spell_enc()));
- set_option_value_give_err("spellfile", 0L, (const char *)buf, OPT_LOCAL);
- break;
+ vim_snprintf(buf + l, MAXPATHL - (size_t)l,
+ "/%.*s", (int)(lend - lstart), lstart);
}
- aspath = false;
+ l = (int)strlen(buf);
+ fname = LANGP_ENTRY(curwin->w_s->b_langp, 0)
+ ->lp_slang->sl_fname;
+ vim_snprintf(buf + l, MAXPATHL - (size_t)l, ".%s.add",
+ ((fname != NULL
+ && strstr(path_tail(fname), ".ascii.") != NULL)
+ ? "ascii"
+ : (const char *)spell_enc()));
+ set_option_value_give_err("spellfile", 0L, buf, OPT_LOCAL);
+ break;
}
-
- xfree(buf);
+ aspath = false;
}
+
+ xfree(buf);
}
/// Set the spell character tables from strings in the .spl file.
///
/// @param cnt length of "flags"
-static void set_spell_charflags(const char_u *flags, int cnt, char_u *fol)
+static void set_spell_charflags(const char_u *flags, int cnt, char *fol)
{
// We build the new tables here first, so that we can compare with the
// previous one.
spelltab_T new_st;
int i;
- char_u *p = fol;
+ char *p = fol;
int c;
clear_spell_chartab(&new_st);
@@ -5777,7 +5771,7 @@ static void set_spell_charflags(const char_u *flags, int cnt, char_u *fol)
}
if (*p != NUL) {
- c = mb_ptr2char_adv((const char_u **)&p);
+ c = mb_ptr2char_adv((const char **)&p);
new_st.st_fold[i + 128] = (char_u)c;
if (i + 128 != c && new_st.st_isu[i + 128] && c < 256) {
new_st.st_upper[c] = (char_u)(i + 128);
@@ -5843,9 +5837,9 @@ static int write_spell_prefcond(FILE *fd, garray_T *gap, size_t *fwv)
}
// Use map string "map" for languages "lp".
-static void set_map_str(slang_T *lp, char_u *map)
+static void set_map_str(slang_T *lp, char *map)
{
- char_u *p;
+ char *p;
int headc = 0;
int c;
int i;
@@ -5866,7 +5860,7 @@ static void set_map_str(slang_T *lp, char_u *map)
// "aaa/bbb/ccc/". Fill sl_map_array[c] with the character before c and
// before the same slash. For characters above 255 sl_map_hash is used.
for (p = map; *p != NUL;) {
- c = mb_cptr2char_adv((const char_u **)&p);
+ c = mb_cptr2char_adv((const char **)&p);
if (c == '/') {
headc = 0;
} else {
@@ -5888,10 +5882,10 @@ static void set_map_str(slang_T *lp, char_u *map)
b[cl] = NUL;
utf_char2bytes(headc, b + cl + 1);
b[cl + 1 + headcl] = NUL;
- hash = hash_hash((char_u *)b);
+ hash = hash_hash(b);
hi = hash_lookup(&lp->sl_map_hash, (const char *)b, strlen(b), hash);
if (HASHITEM_EMPTY(hi)) {
- hash_add_item(&lp->sl_map_hash, hi, (char_u *)b, hash);
+ hash_add_item(&lp->sl_map_hash, hi, b, hash);
} else {
// This should have been checked when generating the .spl
// file.
diff --git a/src/nvim/spellsuggest.c b/src/nvim/spellsuggest.c
index aef26ef288..54b6f552b5 100644
--- a/src/nvim/spellsuggest.c
+++ b/src/nvim/spellsuggest.c
@@ -276,26 +276,27 @@ static int score_wordcount_adj(slang_T *slang, int score, char_u *word, bool spl
int newscore;
hashitem_T *hi = hash_find(&slang->sl_wordcount, (char *)word);
- if (!HASHITEM_EMPTY(hi)) {
- wc = HI2WC(hi);
- if (wc->wc_count < SCORE_THRES2) {
- bonus = SCORE_COMMON1;
- } else if (wc->wc_count < SCORE_THRES3) {
- bonus = SCORE_COMMON2;
- } else {
- bonus = SCORE_COMMON3;
- }
- if (split) {
- newscore = score - bonus / 2;
- } else {
- newscore = score - bonus;
- }
- if (newscore < 0) {
- return 0;
- }
- return newscore;
+ if (HASHITEM_EMPTY(hi)) {
+ return score;
+ }
+
+ wc = HI2WC(hi);
+ if (wc->wc_count < SCORE_THRES2) {
+ bonus = SCORE_COMMON1;
+ } else if (wc->wc_count < SCORE_THRES3) {
+ bonus = SCORE_COMMON2;
+ } else {
+ bonus = SCORE_COMMON3;
}
- return score;
+ if (split) {
+ newscore = score - bonus / 2;
+ } else {
+ newscore = score - bonus;
+ }
+ if (newscore < 0) {
+ return 0;
+ }
+ return newscore;
}
/// Like captype() but for a KEEPCAP word add ONECAP if the word starts with a
@@ -304,42 +305,45 @@ static int score_wordcount_adj(slang_T *slang, int score, char_u *word, bool spl
static int badword_captype(char_u *word, char_u *end)
FUNC_ATTR_NONNULL_ALL
{
- int flags = captype(word, end);
+ int flags = captype((char *)word, (char *)end);
int c;
int l, u;
bool first;
char_u *p;
- if (flags & WF_KEEPCAP) {
- // Count the number of UPPER and lower case letters.
- l = u = 0;
- first = false;
- for (p = word; p < end; MB_PTR_ADV(p)) {
- c = utf_ptr2char((char *)p);
- if (SPELL_ISUPPER(c)) {
- u++;
- if (p == word) {
- first = true;
- }
- } else {
- l++;
+ if (!(flags & WF_KEEPCAP)) {
+ return flags;
+ }
+
+ // Count the number of UPPER and lower case letters.
+ l = u = 0;
+ first = false;
+ for (p = word; p < end; MB_PTR_ADV(p)) {
+ c = utf_ptr2char((char *)p);
+ if (SPELL_ISUPPER(c)) {
+ u++;
+ if (p == word) {
+ first = true;
}
+ } else {
+ l++;
}
+ }
- // If there are more UPPER than lower case letters suggest an
- // ALLCAP word. Otherwise, if the first letter is UPPER then
- // suggest ONECAP. Exception: "ALl" most likely should be "All",
- // require three upper case letters.
- if (u > l && u > 2) {
- flags |= WF_ALLCAP;
- } else if (first) {
- flags |= WF_ONECAP;
- }
+ // If there are more UPPER than lower case letters suggest an
+ // ALLCAP word. Otherwise, if the first letter is UPPER then
+ // suggest ONECAP. Exception: "ALl" most likely should be "All",
+ // require three upper case letters.
+ if (u > l && u > 2) {
+ flags |= WF_ALLCAP;
+ } else if (first) {
+ flags |= WF_ONECAP;
+ }
- if (u >= 2 && l >= 2) { // maCARONI maCAroni
- flags |= WF_MIXCAP;
- }
+ if (u >= 2 && l >= 2) { // maCARONI maCAroni
+ flags |= WF_MIXCAP;
}
+
return flags;
}
@@ -483,6 +487,11 @@ void spell_suggest(int count)
}
badlen++;
end_visual_mode();
+ // make sure we don't include the NUL at the end of the line
+ line = get_cursor_line_ptr();
+ if (badlen > (int)strlen(line) - (int)curwin->w_cursor.col) {
+ badlen = (int)strlen(line) - (int)curwin->w_cursor.col;
+ }
// Find the start of the badly spelled word.
} else if (spell_move_to(curwin, FORWARD, true, true, NULL) == 0
|| curwin->w_cursor.col > prev_cursor.col) {
@@ -492,15 +501,15 @@ void spell_suggest(int count)
line = get_cursor_line_ptr();
p = (char_u *)line + curwin->w_cursor.col;
// Backup to before start of word.
- while (p > (char_u *)line && spell_iswordp_nmw(p, curwin)) {
+ while (p > (char_u *)line && spell_iswordp_nmw((char *)p, curwin)) {
MB_PTR_BACK(line, p);
}
// Forward to start of word.
- while (*p != NUL && !spell_iswordp_nmw(p, curwin)) {
+ while (*p != NUL && !spell_iswordp_nmw((char *)p, curwin)) {
MB_PTR_ADV(p);
}
- if (!spell_iswordp_nmw(p, curwin)) { // No word found.
+ if (!spell_iswordp_nmw((char *)p, curwin)) { // No word found.
beep_flush();
return;
}
@@ -673,13 +682,13 @@ void spell_suggest(int count)
///
/// @param maxcount maximum nr of suggestions
/// @param need_cap 'spellcapcheck' matched
-void spell_suggest_list(garray_T *gap, char_u *word, int maxcount, bool need_cap, bool interactive)
+void spell_suggest_list(garray_T *gap, char *word, int maxcount, bool need_cap, bool interactive)
{
suginfo_T sug;
suggest_T *stp;
char_u *wcopy;
- spell_find_suggest(word, 0, &sug, maxcount, false, need_cap, interactive);
+ spell_find_suggest((char_u *)word, 0, &sug, maxcount, false, need_cap, interactive);
// Make room in "gap".
ga_init(gap, sizeof(char_u *), sug.su_ga.ga_len + 1);
@@ -733,7 +742,7 @@ static void spell_find_suggest(char_u *badptr, int badlen, suginfo_T *su, int ma
if (badlen != 0) {
su->su_badlen = badlen;
} else {
- size_t tmplen = spell_check(curwin, (char_u *)su->su_badptr, &attr, NULL, false);
+ size_t tmplen = spell_check(curwin, su->su_badptr, &attr, NULL, false);
assert(tmplen <= INT_MAX);
su->su_badlen = (int)tmplen;
}
@@ -744,7 +753,7 @@ static void spell_find_suggest(char_u *badptr, int badlen, suginfo_T *su, int ma
su->su_badlen = MAXWLEN - 1; // just in case
}
xstrlcpy((char *)su->su_badword, su->su_badptr, (size_t)su->su_badlen + 1);
- (void)spell_casefold(curwin, (char_u *)su->su_badptr, su->su_badlen, (char_u *)su->su_fbadword,
+ (void)spell_casefold(curwin, su->su_badptr, su->su_badlen, su->su_fbadword,
MAXWLEN);
// TODO(vim): make this work if the case-folded text is longer than the
@@ -783,7 +792,7 @@ static void spell_find_suggest(char_u *badptr, int badlen, suginfo_T *su, int ma
// for that.
c = utf_ptr2char(su->su_badptr);
if (!SPELL_ISUPPER(c) && attr == HLF_COUNT) {
- make_case_word((char_u *)su->su_badword, (char_u *)buf, WF_ONECAP);
+ make_case_word((char *)su->su_badword, buf, WF_ONECAP);
add_suggestion(su, &su->su_ga, (char *)buf, su->su_badlen, SCORE_ICASE,
0, true, su->su_sallang, false);
}
@@ -895,8 +904,8 @@ static void spell_suggest_file(suginfo_T *su, char_u *fname)
// If the suggestion doesn't have specific case duplicate the case
// of the bad word.
- if (captype(p, NULL) == 0) {
- make_case_word(p, cword, su->su_badflags);
+ if (captype((char *)p, NULL) == 0) {
+ make_case_word((char *)p, (char *)cword, su->su_badflags);
p = cword;
}
@@ -1016,7 +1025,7 @@ static void suggest_try_special(suginfo_T *su)
// use that for the goodword too: "The the" -> "The".
c = su->su_fbadword[len];
su->su_fbadword[len] = NUL;
- make_case_word((char_u *)su->su_fbadword, word, su->su_badflags);
+ make_case_word(su->su_fbadword, (char *)word, su->su_badflags);
su->su_fbadword[len] = c;
// Give a soundalike score of 0, compute the score as if deleting one
@@ -1085,7 +1094,7 @@ static void suggest_try_change(suginfo_T *su)
STRCPY(fword, su->su_fbadword);
n = (int)strlen(fword);
p = su->su_badptr + su->su_badlen;
- (void)spell_casefold(curwin, (char_u *)p, (int)strlen(p), (char_u *)fword + n, MAXWLEN - n);
+ (void)spell_casefold(curwin, p, (int)strlen(p), fword + n, MAXWLEN - n);
// Make sure the resulting text is not longer than the original text.
n = (int)strlen(su->su_badptr);
@@ -1193,7 +1202,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
if (soundfold) {
// Going through the soundfold tree.
- byts = fbyts = slang->sl_sbyts;
+ byts = fbyts = (char_u *)slang->sl_sbyts;
idxs = fidxs = slang->sl_sidxs;
pbyts = NULL;
pidxs = NULL;
@@ -1202,9 +1211,9 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
} else {
// When there are postponed prefixes we need to use these first. At
// the end of the prefix we continue in the case-fold tree.
- fbyts = slang->sl_fbyts;
+ fbyts = (char_u *)slang->sl_fbyts;
fidxs = slang->sl_fidxs;
- pbyts = slang->sl_pbyts;
+ pbyts = (char_u *)slang->sl_pbyts;
pidxs = slang->sl_pidxs;
if (pbyts != NULL) {
byts = pbyts;
@@ -1258,7 +1267,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
if (depth < MAXWLEN - 1 && (byts[arridx] == 0 || n == STATE_NOPREFIX)) {
// Set su->su_badflags to the caps type at this position.
// Use the caps type until here for the prefix itself.
- n = nofold_len((char_u *)fword, sp->ts_fidx, (char_u *)su->su_badptr);
+ n = nofold_len(fword, sp->ts_fidx, su->su_badptr);
flags = badword_captype((char_u *)su->su_badptr, (char_u *)su->su_badptr + n);
su->su_badflags = badword_captype((char_u *)su->su_badptr + n,
(char_u *)su->su_badptr + su->su_badlen);
@@ -1276,8 +1285,8 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
// Move the prefix to preword[] with the right case
// and make find_keepcap_word() works.
tword[sp->ts_twordlen] = NUL;
- make_case_word((char_u *)tword + sp->ts_splitoff,
- (char_u *)preword + sp->ts_prewordlen, flags);
+ make_case_word(tword + sp->ts_splitoff,
+ preword + sp->ts_prewordlen, flags);
sp->ts_prewordlen = (char_u)strlen(preword);
sp->ts_splitoff = sp->ts_twordlen;
}
@@ -1305,7 +1314,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
fword_ends = (fword[sp->ts_fidx] == NUL
|| (soundfold
? ascii_iswhite(fword[sp->ts_fidx])
- : !spell_iswordp((char_u *)fword + sp->ts_fidx, curwin)));
+ : !spell_iswordp(fword + sp->ts_fidx, curwin)));
tword[sp->ts_twordlen] = NUL;
if (sp->ts_prefixdepth <= PFD_NOTSPECIAL
@@ -1320,7 +1329,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
for (c = 0; c < len && pbyts[n + c] == 0; c++) {}
if (c > 0) {
c = valid_word_prefix(c, n, flags,
- (char_u *)tword + sp->ts_splitoff, slang, false);
+ tword + sp->ts_splitoff, slang, false);
if (c == 0) {
break;
}
@@ -1359,7 +1368,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
== sp->ts_twordlen - sp->ts_splitoff
&& strncmp(fword + sp->ts_splitfidx,
tword + sp->ts_splitoff,
- sp->ts_fidx - sp->ts_splitfidx) == 0) {
+ (size_t)(sp->ts_fidx - sp->ts_splitfidx)) == 0) {
preword[sp->ts_prewordlen] = NUL;
newscore = score_wordcount_adj(slang, sp->ts_score,
(char_u *)preword + sp->ts_prewordlen,
@@ -1441,11 +1450,11 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
// When appending a compound word after a word character don't
// use Onecap.
- if (p != NULL && spell_iswordp_nmw((char_u *)p, curwin)) {
+ if (p != NULL && spell_iswordp_nmw(p, curwin)) {
c &= ~WF_ONECAP;
}
- make_case_word((char_u *)tword + sp->ts_splitoff,
- (char_u *)preword + sp->ts_prewordlen, c);
+ make_case_word(tword + sp->ts_splitoff,
+ preword + sp->ts_prewordlen, c);
}
if (!soundfold) {
@@ -1477,7 +1486,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
}
if (!spell_valid_case(su->su_badflags,
- captype((char_u *)preword + sp->ts_prewordlen, NULL))) {
+ captype(preword + sp->ts_prewordlen, NULL))) {
newscore += SCORE_ICASE;
}
}
@@ -1508,10 +1517,10 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
// char, e.g., "thes," -> "these".
p = fword + sp->ts_fidx;
MB_PTR_BACK(fword, p);
- if (!spell_iswordp((char_u *)p, curwin) && *preword != NUL) {
+ if (!spell_iswordp(p, curwin) && *preword != NUL) {
p = preword + strlen(preword);
MB_PTR_BACK(preword, p);
- if (spell_iswordp((char_u *)p, curwin)) {
+ if (spell_iswordp(p, curwin)) {
newscore += SCORE_NONWORD;
}
}
@@ -1531,10 +1540,10 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
if (su->su_badflags & WF_MIXCAP) {
// We really don't know if the word should be
// upper or lower case, add both.
- c = captype((char_u *)preword, NULL);
+ c = captype(preword, NULL);
if (c == 0 || c == WF_ALLCAP) {
- make_case_word((char_u *)tword + sp->ts_splitoff,
- (char_u *)preword + sp->ts_prewordlen,
+ make_case_word(tword + sp->ts_splitoff,
+ preword + sp->ts_prewordlen,
c == 0 ? WF_ALLCAP : 0);
add_suggestion(su, &su->su_ga, (char *)preword,
@@ -1673,7 +1682,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
// non-word character with a space. Always skip a
// character when the word ends. But only when the
// good word can end.
- if (((!try_compound && !spell_iswordp_nmw((char_u *)fword
+ if (((!try_compound && !spell_iswordp_nmw(fword
+ sp->ts_fidx,
curwin))
|| fword_ends)
@@ -1705,7 +1714,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
// set su->su_badflags to the caps type at this
// position
- n = nofold_len((char_u *)fword, sp->ts_fidx, (char_u *)su->su_badptr);
+ n = nofold_len(fword, sp->ts_fidx, su->su_badptr);
su->su_badflags = badword_captype((char_u *)su->su_badptr + n,
(char_u *)su->su_badptr + su->su_badlen);
@@ -2029,7 +2038,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
// Don't swap if the first character is not a word character.
// SWAP3 etc. also don't make sense then.
- if (!soundfold && !spell_iswordp((char_u *)p, curwin)) {
+ if (!soundfold && !spell_iswordp(p, curwin)) {
PROF_STORE(sp->ts_state)
sp->ts_state = STATE_REP_INI;
break;
@@ -2039,7 +2048,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
c = utf_ptr2char(p);
if (p[n] == NUL) {
c2 = NUL;
- } else if (!soundfold && !spell_iswordp((char_u *)p + n, curwin)) {
+ } else if (!soundfold && !spell_iswordp(p + n, curwin)) {
c2 = c; // don't swap non-word char
} else {
c2 = utf_ptr2char(p + n);
@@ -2099,7 +2108,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
c = utf_ptr2char(p);
fl = utf_ptr2len(p + n);
c2 = utf_ptr2char(p + n);
- if (!soundfold && !spell_iswordp((char_u *)p + n + fl, curwin)) {
+ if (!soundfold && !spell_iswordp(p + n + fl, curwin)) {
c3 = c; // don't swap non-word char
} else {
c3 = utf_ptr2char(p + n + fl);
@@ -2150,7 +2159,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
utf_char2bytes(c2, p + tl);
p = p + tl;
- if (!soundfold && !spell_iswordp((char_u *)p, curwin)) {
+ if (!soundfold && !spell_iswordp(p, curwin)) {
// Middle char is not a word char, skip the rotate. First and
// third char were already checked at swap and swap3.
PROF_STORE(sp->ts_state)
@@ -2394,7 +2403,7 @@ static void find_keepcap_word(slang_T *slang, char *fword, char *kword)
int c;
idx_T lo, hi, m;
char_u *p;
- char_u *byts = slang->sl_kbyts; // array with bytes of the words
+ char_u *byts = (char_u *)slang->sl_kbyts; // array with bytes of the words
idx_T *idxs = slang->sl_kidxs; // array with indexes
if (byts == NULL) {
@@ -2404,7 +2413,7 @@ static void find_keepcap_word(slang_T *slang, char *fword, char *kword)
}
// Make an all-cap version of "fword".
- allcap_copy((char_u *)fword, (char_u *)uword);
+ allcap_copy(fword, uword);
// Each character needs to be tried both case-folded and upper-case.
// All this gets very complicated if we keep in mind that changing case
@@ -2661,7 +2670,7 @@ static int stp_sal_score(suggest_T *stp, suginfo_T *su, slang_T *slang, char_u *
pbad = badsound;
} else {
// soundfold the bad word with more characters following
- (void)spell_casefold(curwin, (char_u *)su->su_badptr, stp->st_orglen, fword, MAXWLEN);
+ (void)spell_casefold(curwin, su->su_badptr, stp->st_orglen, (char *)fword, MAXWLEN);
// When joining two words the sound often changes a lot. E.g., "t he"
// sounds like "t h" while "the" sounds like "@". Avoid that by
@@ -2814,15 +2823,15 @@ static void add_sound_suggest(suginfo_T *su, char *goodword, int score, langp_T
// times with different scores. Since the following is quite slow only do
// the words that have a better score than before. Use a hashtable to
// remember the words that have been done.
- hash = hash_hash((char_u *)goodword);
+ hash = hash_hash(goodword);
const size_t goodword_len = strlen(goodword);
hi = hash_lookup(&slang->sl_sounddone, (const char *)goodword, goodword_len,
hash);
if (HASHITEM_EMPTY(hi)) {
- sft = xmalloc(sizeof(sftword_T) + goodword_len);
+ sft = xmalloc(offsetof(sftword_T, sft_word) + goodword_len + 1);
sft->sft_score = (int16_t)score;
memcpy(sft->sft_word, goodword, goodword_len + 1);
- hash_add_item(&slang->sl_sounddone, hi, sft->sft_word, hash);
+ hash_add_item(&slang->sl_sounddone, hi, (char *)sft->sft_word, hash);
} else {
sft = HI2SFT(hi);
if (score >= sft->sft_score) {
@@ -2846,7 +2855,7 @@ static void add_sound_suggest(suginfo_T *su, char *goodword, int score, langp_T
// previous wordnr.
orgnr += bytes2offset(&nrline);
- byts = slang->sl_fbyts;
+ byts = (char_u *)slang->sl_fbyts;
idxs = slang->sl_fidxs;
// Lookup the word "orgnr" one of the two tries.
@@ -2904,7 +2913,7 @@ badword:
flags |= su->su_badflags;
if ((flags & WF_CAPMASK) != 0) {
// Need to fix case according to "flags".
- make_case_word(theword, cword, flags);
+ make_case_word((char *)theword, (char *)cword, flags);
p = cword;
} else {
p = theword;
@@ -2984,7 +2993,7 @@ static int soundfold_find(slang_T *slang, char_u *word)
idx_T *idxs;
int wordnr = 0;
- byts = slang->sl_sbyts;
+ byts = (char_u *)slang->sl_sbyts;
idxs = slang->sl_sidxs;
for (;;) {
@@ -3220,7 +3229,7 @@ static void check_suggestions(suginfo_T *su, garray_T *gap)
xstrlcpy(longword + len, su->su_badptr + stp[i].st_orglen,
(size_t)(MAXWLEN - len + 1));
attr = HLF_COUNT;
- (void)spell_check(curwin, (char_u *)longword, &attr, NULL, false);
+ (void)spell_check(curwin, longword, &attr, NULL, false);
if (attr != HLF_COUNT) {
// Remove this entry.
xfree(stp[i].st_word);
@@ -3239,13 +3248,14 @@ static void add_banned(suginfo_T *su, char *word)
hash_T hash;
hashitem_T *hi;
- hash = hash_hash((char_u *)word);
+ hash = hash_hash(word);
const size_t word_len = strlen(word);
hi = hash_lookup(&su->su_banned, word, word_len, hash);
- if (HASHITEM_EMPTY(hi)) {
- s = xmemdupz(word, word_len);
- hash_add_item(&su->su_banned, hi, s, hash);
+ if (!HASHITEM_EMPTY(hi)) { // already present
+ return;
}
+ s = xmemdupz(word, word_len);
+ hash_add_item(&su->su_banned, hi, (char *)s, hash);
}
/// Recompute the score for all suggestions if sound-folding is possible. This
@@ -3312,21 +3322,23 @@ static int sug_compare(const void *s1, const void *s2)
static int cleanup_suggestions(garray_T *gap, int maxscore, int keep)
FUNC_ATTR_NONNULL_ALL
{
- if (gap->ga_len > 0) {
- // Sort the list.
- qsort(gap->ga_data, (size_t)gap->ga_len, sizeof(suggest_T), sug_compare);
+ if (gap->ga_len <= 0) {
+ return maxscore;
+ }
- // Truncate the list to the number of suggestions that will be displayed.
- if (gap->ga_len > keep) {
- suggest_T *const stp = &SUG(*gap, 0);
+ // Sort the list.
+ qsort(gap->ga_data, (size_t)gap->ga_len, sizeof(suggest_T), sug_compare);
- for (int i = keep; i < gap->ga_len; i++) {
- xfree(stp[i].st_word);
- }
- gap->ga_len = keep;
- if (keep >= 1) {
- return stp[keep - 1].st_score;
- }
+ // Truncate the list to the number of suggestions that will be displayed.
+ if (gap->ga_len > keep) {
+ suggest_T *const stp = &SUG(*gap, 0);
+
+ for (int i = keep; i < gap->ga_len; i++) {
+ xfree(stp[i].st_word);
+ }
+ gap->ga_len = keep;
+ if (keep >= 1) {
+ return stp[keep - 1].st_score;
}
}
return maxscore;
@@ -3580,12 +3592,12 @@ static int spell_edit_score(slang_T *slang, const char_u *badword, const char_u
// Get the characters from the multi-byte strings and put them in an
// int array for easy access.
badlen = 0;
- for (const char_u *p = badword; *p != NUL;) {
+ for (const char *p = (char *)badword; *p != NUL;) {
wbadword[badlen++] = mb_cptr2char_adv(&p);
}
wbadword[badlen++] = 0;
goodlen = 0;
- for (const char_u *p = goodword; *p != NUL;) {
+ for (const char *p = (char *)goodword; *p != NUL;) {
wgoodword[goodlen++] = mb_cptr2char_adv(&p);
}
wgoodword[goodlen++] = 0;
@@ -3686,12 +3698,12 @@ static int spell_edit_score_limit_w(slang_T *slang, const char_u *badword, const
// Get the characters from the multi-byte strings and put them in an
// int array for easy access.
bi = 0;
- for (const char_u *p = badword; *p != NUL;) {
+ for (const char *p = (char *)badword; *p != NUL;) {
wbadword[bi++] = mb_cptr2char_adv(&p);
}
wbadword[bi++] = 0;
gi = 0;
- for (const char_u *p = goodword; *p != NUL;) {
+ for (const char *p = (char *)goodword; *p != NUL;) {
wgoodword[gi++] = mb_cptr2char_adv(&p);
}
wgoodword[gi++] = 0;
diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c
index db3e3f91bf..6ad1f31143 100644
--- a/src/nvim/statusline.c
+++ b/src/nvim/statusline.c
@@ -31,12 +31,14 @@
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/move.h"
+#include "nvim/normal.h"
#include "nvim/option.h"
#include "nvim/optionstr.h"
#include "nvim/os/os.h"
#include "nvim/path.h"
#include "nvim/pos.h"
#include "nvim/screen.h"
+#include "nvim/sign_defs.h"
#include "nvim/statusline.h"
#include "nvim/strings.h"
#include "nvim/types.h"
@@ -229,8 +231,12 @@ void stl_fill_click_defs(StlClickDefinition *click_defs, StlClickRecord *click_r
};
for (int i = 0; click_recs[i].start != NULL; i++) {
len += vim_strnsize(buf, (int)(click_recs[i].start - buf));
- while (col < len) {
- click_defs[col++] = cur_click_def;
+ if (col < len) {
+ while (col < len) {
+ click_defs[col++] = cur_click_def;
+ }
+ } else {
+ xfree(cur_click_def.func);
}
buf = (char *)click_recs[i].start;
cur_click_def = click_recs[i].def;
@@ -240,8 +246,12 @@ void stl_fill_click_defs(StlClickDefinition *click_defs, StlClickRecord *click_r
cur_click_def.type = kStlClickDisabled;
}
}
- while (col < width) {
- click_defs[col++] = cur_click_def;
+ if (col < width) {
+ while (col < width) {
+ click_defs[col++] = cur_click_def;
+ }
+ } else {
+ xfree(cur_click_def.func);
}
}
@@ -713,7 +723,7 @@ void draw_tabline(void)
int len;
int attr_nosel = HL_ATTR(HLF_TP);
int attr_fill = HL_ATTR(HLF_TPF);
- char_u *p;
+ char *p;
int room;
int use_sep_chars = (t_colors < 8);
@@ -731,6 +741,10 @@ void draw_tabline(void)
return;
}
+ // Clear tab_page_click_defs: Clicking outside of tabs has no effect.
+ assert(tab_page_click_defs_size >= (size_t)Columns);
+ stl_clear_click_defs(tab_page_click_defs, tab_page_click_defs_size);
+
// Use the 'tabline' option if it's set.
if (*p_tal != NUL) {
win_redr_custom(NULL, false, false);
@@ -809,16 +823,16 @@ void draw_tabline(void)
get_trans_bufname(cwp->w_buffer);
shorten_dir(NameBuff);
len = vim_strsize(NameBuff);
- p = (char_u *)NameBuff;
+ p = NameBuff;
while (len > room) {
- len -= ptr2cells((char *)p);
+ len -= ptr2cells(p);
MB_PTR_ADV(p);
}
if (len > Columns - col - 1) {
len = Columns - col - 1;
}
- grid_puts_len(&default_grid, (char *)p, (int)strlen((char *)p), 0, col, attr);
+ grid_puts_len(&default_grid, p, (int)strlen(p), 0, col, attr);
col += len;
}
grid_putchar(&default_grid, ' ', 0, col++, attr);
@@ -868,29 +882,30 @@ void draw_tabline(void)
redraw_tabline = false;
}
-/// Build the 'statuscolumn' string for line "lnum". If "setnum" is true,
-/// update the "lnum" and "relnum" vim-variables for a new line.
+/// Build the 'statuscolumn' string for line "lnum". When "relnum" == -1,
+/// the v:lnum and v:relnum variables don't have to be updated.
///
/// @param hlrec HL attributes (can be NULL)
/// @param stcp Status column attributes (can be NULL)
/// @return The width of the built status column string for line "lnum"
-int build_statuscol_str(win_T *wp, bool setnum, bool wrap, linenr_T lnum, long relnum, int maxwidth,
- int fillchar, char *buf, stl_hlrec_t **hlrec, statuscol_T *stcp)
+int build_statuscol_str(win_T *wp, linenr_T lnum, long relnum, int maxwidth, int fillchar,
+ char *buf, stl_hlrec_t **hlrec, statuscol_T *stcp)
{
- if (setnum) {
+ bool fillclick = relnum >= 0 && lnum == wp->w_topline;
+
+ if (relnum >= 0) {
set_vim_var_nr(VV_LNUM, lnum);
set_vim_var_nr(VV_RELNUM, relnum);
}
- set_vim_var_bool(VV_WRAP, wrap);
StlClickRecord *clickrec;
char *stc = xstrdup(wp->w_p_stc);
- int width = build_stl_str_hl(wp, buf, MAXPATHL, stc, "statuscolumn", OPT_LOCAL,
- fillchar, maxwidth, hlrec, &clickrec, stcp);
+ int width = build_stl_str_hl(wp, buf, MAXPATHL, stc, "statuscolumn", OPT_LOCAL, fillchar,
+ maxwidth, hlrec, fillclick ? &clickrec : NULL, stcp);
xfree(stc);
- // Allocate and fill click def array if width has changed
- if (wp->w_status_click_defs_size != (size_t)width) {
+ // Only update click definitions once per window per redraw
+ if (fillclick) {
stl_clear_click_defs(wp->w_statuscol_click_defs, wp->w_statuscol_click_defs_size);
wp->w_statuscol_click_defs = stl_alloc_click_defs(wp->w_statuscol_click_defs, width,
&wp->w_statuscol_click_defs_size);
@@ -1322,7 +1337,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
}
stl_items[curitem].type = ClickFunc;
stl_items[curitem].start = out_p;
- stl_items[curitem].cmd = xmemdupz(t, (size_t)(fmt_p - t));
+ stl_items[curitem].cmd = tabtab ? xmemdupz(t, (size_t)(fmt_p - t)) : NULL;
stl_items[curitem].minwid = minwid;
fmt_p++;
curitem++;
@@ -1363,7 +1378,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
// An invalid item was specified.
// Continue processing on the next character of the format string.
- if (vim_strchr(STL_ALL, *fmt_p) == NULL) {
+ if (vim_strchr(STL_ALL, (uint8_t)(*fmt_p)) == NULL) {
fmt_p++;
continue;
}
@@ -1504,13 +1519,12 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
case STL_LINE:
// Overload %l with v:lnum for 'statuscolumn'
if (opt_name != NULL && strcmp(opt_name, "statuscolumn") == 0) {
- if (wp->w_p_nu) {
+ if (wp->w_p_nu && !get_vim_var_nr(VV_VIRTNUM)) {
num = get_vim_var_nr(VV_LNUM);
}
} else {
num = (wp->w_buffer->b_ml.ml_flags & ML_EMPTY) ? 0L : (long)(wp->w_cursor.lnum);
}
-
break;
case STL_NUMLINES:
@@ -1610,7 +1624,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
case STL_ROFLAG_ALT:
// Overload %r with v:relnum for 'statuscolumn'
if (opt_name != NULL && strcmp(opt_name, "statuscolumn") == 0) {
- if (wp->w_p_rnu) {
+ if (wp->w_p_rnu && !get_vim_var_nr(VV_VIRTNUM)) {
num = get_vim_var_nr(VV_RELNUM);
}
} else {
@@ -1678,7 +1692,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
vim_snprintf(buf_tmp, sizeof(buf_tmp), ",%s", wp->w_buffer->b_p_ft);
// Uppercase the file extension
for (char *t = buf_tmp; *t != 0; t++) {
- *t = (char)TOUPPER_LOC(*t);
+ *t = (char)TOUPPER_LOC((uint8_t)(*t));
}
str = buf_tmp;
}
@@ -1978,6 +1992,11 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
// the truncation point
for (int i = 0; i < itemcnt; i++) {
if (stl_items[i].start > trunc_p) {
+ for (int j = i; j < itemcnt; j++) {
+ if (stl_items[j].type == ClickFunc) {
+ XFREE_CLEAR(stl_items[j].cmd);
+ }
+ }
itemcnt = i;
break;
}
diff --git a/src/nvim/strings.c b/src/nvim/strings.c
index f0f9fbf51b..34b3c38103 100644
--- a/src/nvim/strings.c
+++ b/src/nvim/strings.c
@@ -167,7 +167,7 @@ char *vim_strsave_shellescape(const char *string, bool do_special, bool do_newli
// 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 = (char_u *)string; *p != NUL; MB_PTR_ADV(p)) {
+ for (const char *p = string; *p != NUL; MB_PTR_ADV(p)) {
#ifdef MSWIN
if (!p_ssl) {
if (*p == '"') {
@@ -185,7 +185,7 @@ char *vim_strsave_shellescape(const char *string, bool do_special, bool do_newli
length++; // insert backslash
}
}
- if (do_special && find_cmdline_var((char *)p, &l) >= 0) {
+ if (do_special && find_cmdline_var(p, &l) >= 0) {
length++; // insert backslash
p += l - 1;
}
@@ -270,7 +270,7 @@ char *vim_strsave_up(const char *string)
char *p1;
p1 = xstrdup(string);
- vim_strup((char_u *)p1);
+ vim_strup(p1);
return p1;
}
@@ -280,17 +280,17 @@ char *vim_strnsave_up(const char *string, size_t len)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL
{
char *p1 = xstrnsave(string, len);
- vim_strup((char_u *)p1);
+ vim_strup(p1);
return p1;
}
// ASCII lower-to-upper case translation, language independent.
-void vim_strup(char_u *p)
+void vim_strup(char *p)
FUNC_ATTR_NONNULL_ALL
{
- char_u c;
- while ((c = *p) != NUL) {
- *p++ = (char_u)(c < 'a' || c > 'z' ? c : c - 0x20);
+ uint8_t c;
+ while ((c = (uint8_t)(*p)) != NUL) {
+ *p++ = (char)(uint8_t)(c < 'a' || c > 'z' ? c : c - 0x20);
}
}
@@ -313,7 +313,7 @@ char *strcase_save(const char *const orig, bool upper)
int l = utf_ptr2len(p);
if (c == 0) {
// overlong sequence, use only the first byte
- c = (char_u)(*p);
+ c = (uint8_t)(*p);
l = 1;
}
int uc = upper ? mb_toupper(c) : mb_tolower(c);
@@ -372,7 +372,7 @@ int vim_stricmp(const char *s1, const char *s2)
int i;
for (;;) {
- i = (int)TOLOWER_LOC(*s1) - (int)TOLOWER_LOC(*s2);
+ i = (int)TOLOWER_LOC((uint8_t)(*s1)) - (int)TOLOWER_LOC((uint8_t)(*s2));
if (i != 0) {
return i; // this character different
}
@@ -396,7 +396,7 @@ int vim_strnicmp(const char *s1, const char *s2, size_t len)
int i;
while (len > 0) {
- i = (int)TOLOWER_LOC(*s1) - (int)TOLOWER_LOC(*s2);
+ i = (int)TOLOWER_LOC((uint8_t)(*s1)) - (int)TOLOWER_LOC((uint8_t)(*s2));
if (i != 0) {
return i; // this character different
}
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index 721cc7707a..49b63ad324 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -92,7 +92,7 @@ typedef struct syn_pattern {
} synpat_T;
typedef struct syn_cluster_S {
- char_u *scl_name; // syntax cluster name
+ char *scl_name; // syntax cluster name
char *scl_name_u; // uppercase of scl_name
int16_t *scl_list; // IDs in this syntax cluster
} syn_cluster_T;
@@ -721,10 +721,12 @@ static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid)
static void save_chartab(char *chartab)
{
- if (syn_block->b_syn_isk != empty_option) {
- memmove(chartab, syn_buf->b_chartab, (size_t)32);
- memmove(syn_buf->b_chartab, syn_win->w_s->b_syn_chartab, (size_t)32);
+ if (syn_block->b_syn_isk == empty_option) {
+ return;
}
+
+ memmove(chartab, syn_buf->b_chartab, (size_t)32);
+ memmove(syn_buf->b_chartab, syn_win->w_s->b_syn_chartab, (size_t)32);
}
static void restore_chartab(char *chartab)
@@ -737,22 +739,23 @@ static void restore_chartab(char *chartab)
/// Return true if the line-continuation pattern matches in line "lnum".
static int syn_match_linecont(linenr_T lnum)
{
- if (syn_block->b_syn_linecont_prog != NULL) {
- regmmatch_T regmatch;
- // chartab array for syn iskeyword
- char buf_chartab[32];
- save_chartab(buf_chartab);
+ if (syn_block->b_syn_linecont_prog == NULL) {
+ return false;
+ }
- regmatch.rmm_ic = syn_block->b_syn_linecont_ic;
- regmatch.regprog = syn_block->b_syn_linecont_prog;
- int r = syn_regexec(&regmatch, lnum, (colnr_T)0,
- IF_SYN_TIME(&syn_block->b_syn_linecont_time));
- syn_block->b_syn_linecont_prog = regmatch.regprog;
+ regmmatch_T regmatch;
+ // chartab array for syn iskeyword
+ char buf_chartab[32];
+ save_chartab(buf_chartab);
- restore_chartab(buf_chartab);
- return r;
- }
- return false;
+ regmatch.rmm_ic = syn_block->b_syn_linecont_ic;
+ regmatch.regprog = syn_block->b_syn_linecont_prog;
+ int r = syn_regexec(&regmatch, lnum, (colnr_T)0,
+ IF_SYN_TIME(&syn_block->b_syn_linecont_time));
+ syn_block->b_syn_linecont_prog = regmatch.regprog;
+
+ restore_chartab(buf_chartab);
+ return r;
}
// Prepare the current state for the start of a line.
@@ -873,14 +876,16 @@ static void syn_stack_free_block(synblock_T *block)
{
synstate_T *p;
- if (block->b_sst_array != NULL) {
- for (p = block->b_sst_first; p != NULL; p = p->sst_next) {
- clear_syn_state(p);
- }
- XFREE_CLEAR(block->b_sst_array);
- block->b_sst_first = NULL;
- block->b_sst_len = 0;
+ if (block->b_sst_array == NULL) {
+ return;
+ }
+
+ for (p = block->b_sst_first; p != NULL; p = p->sst_next) {
+ clear_syn_state(p);
}
+ XFREE_CLEAR(block->b_sst_array);
+ block->b_sst_first = NULL;
+ block->b_sst_len = 0;
}
// Free b_sst_array[] for buffer "buf".
// Used when syntax items changed to force resyncing everywhere.
@@ -1490,8 +1495,8 @@ int get_syntax_attr(const colnr_T col, bool *const can_spell, const bool keep_st
static int syn_current_attr(const bool syncing, const bool displaying, bool *const can_spell,
const bool keep_state)
{
- lpos_T endpos; // was: char_u *endp;
- lpos_T hl_startpos; // was: int hl_startcol;
+ lpos_T endpos;
+ lpos_T hl_startpos;
lpos_T hl_endpos;
lpos_T eos_pos; // end-of-start match (start region)
lpos_T eoe_pos; // end-of-end pattern
@@ -3416,8 +3421,8 @@ static void syn_list_one(const int id, const bool syncing, const bool link_only)
}
msg_putchar(' ');
if (spp->sp_sync_idx >= 0) {
- msg_outtrans((char *)highlight_group_name(SYN_ITEMS(curwin->w_s)
- [spp->sp_sync_idx].sp_syn.id - 1));
+ msg_outtrans(highlight_group_name(SYN_ITEMS(curwin->w_s)
+ [spp->sp_sync_idx].sp_syn.id - 1));
} else {
msg_puts("NONE");
}
@@ -3430,7 +3435,7 @@ static void syn_list_one(const int id, const bool syncing, const bool link_only)
(void)syn_list_header(did_header, 0, id, true);
msg_puts_attr("links to", attr);
msg_putchar(' ');
- msg_outtrans((char *)highlight_group_name(highlight_link_id(id - 1) - 1));
+ msg_outtrans(highlight_group_name(highlight_link_id(id - 1) - 1));
}
}
@@ -3453,7 +3458,7 @@ static void syn_list_cluster(int id)
// slight hack: roughly duplicate the guts of syn_list_header()
msg_putchar('\n');
- msg_outtrans((char *)SYN_CLSTR(curwin->w_s)[id].scl_name);
+ msg_outtrans(SYN_CLSTR(curwin->w_s)[id].scl_name);
if (msg_col >= endcol) { // output at least one space
endcol = msg_col + 1;
@@ -3490,9 +3495,9 @@ static void put_id_list(const char *const name, const int16_t *const list, const
int scl_id = *p - SYNID_CLUSTER;
msg_putchar('@');
- msg_outtrans((char *)SYN_CLSTR(curwin->w_s)[scl_id].scl_name);
+ msg_outtrans(SYN_CLSTR(curwin->w_s)[scl_id].scl_name);
} else {
- msg_outtrans((char *)highlight_group_name(*p - 1));
+ msg_outtrans(highlight_group_name(*p - 1));
}
if (p[1]) {
msg_putchar(',');
@@ -3514,7 +3519,7 @@ static void put_pattern(const char *const s, const int c, const synpat_T *const
if (last_matchgroup == 0) {
msg_outtrans("NONE");
} else {
- msg_outtrans((char *)highlight_group_name(last_matchgroup - 1));
+ msg_outtrans(highlight_group_name(last_matchgroup - 1));
}
msg_putchar(' ');
}
@@ -3524,7 +3529,7 @@ static void put_pattern(const char *const s, const int c, const synpat_T *const
msg_putchar(c);
// output the pattern, in between a char that is not in the pattern
- for (i = 0; vim_strchr(spp->sp_pattern, sepchars[i]) != NULL;) {
+ for (i = 0; vim_strchr(spp->sp_pattern, (uint8_t)sepchars[i]) != NULL;) {
if (sepchars[++i] == NUL) {
i = 0; // no good char found, just use the first one
break;
@@ -3731,7 +3736,7 @@ static void add_keyword(char *const name, const int id, const int flags,
sizeof(name_folded))
: name;
- keyentry_T *const kp = xmalloc(sizeof(keyentry_T) + strlen(name_ic));
+ keyentry_T *const kp = xmalloc(offsetof(keyentry_T, keyword) + strlen(name_ic) + 1);
STRCPY(kp->keyword, name_ic);
kp->k_syn.id = (int16_t)id;
kp->k_syn.inc_tag = current_syn_inc_tag;
@@ -3743,7 +3748,7 @@ static void add_keyword(char *const name, const int id, const int flags,
}
kp->next_list = copy_id_list(next_list);
- const hash_T hash = hash_hash((char_u *)kp->keyword);
+ const hash_T hash = hash_hash(kp->keyword);
hashtab_T *const ht = (curwin->w_s->b_syn_ic)
? &curwin->w_s->b_keywtab_ic
: &curwin->w_s->b_keywtab;
@@ -3757,7 +3762,7 @@ static void add_keyword(char *const name, const int id, const int flags,
if (HASHITEM_EMPTY(hi)) {
// new keyword, add to hashtable
kp->ke_next = NULL;
- hash_add_item(ht, hi, (char_u *)kp->keyword, hash);
+ hash_add_item(ht, hi, kp->keyword, hash);
} else {
// keyword already exists, prepend to list
kp->ke_next = HI2KE(hi);
@@ -4000,7 +4005,7 @@ static void syn_cmd_include(exarg_T *eap, int syncing)
// filename to include.
eap->argt |= (EX_XFILE | EX_NOSPC);
separate_nextcmd(eap);
- if (*eap->arg == '<' || *eap->arg == '$' || path_is_absolute((char_u *)eap->arg)) {
+ if (*eap->arg == '<' || *eap->arg == '$' || path_is_absolute(eap->arg)) {
// For an absolute path, "$VIM/..." or "<sfile>.." we ":source" the
// file. Need to expand the file name first. In other cases
// ":runtime!" is used.
@@ -4634,7 +4639,7 @@ static int syn_add_cluster(char *name)
syn_cluster_T *scp = GA_APPEND_VIA_PTR(syn_cluster_T,
&curwin->w_s->b_syn_clusters);
CLEAR_POINTER(scp);
- scp->scl_name = (char_u *)name;
+ scp->scl_name = name;
scp->scl_name_u = vim_strsave_up(name);
scp->scl_list = NULL;
@@ -5042,7 +5047,7 @@ static int get_id_list(char **const arg, const int keylen, int16_t **const list,
regmatch.rm_ic = true;
id = 0;
for (int i = highlight_num_groups(); --i >= 0;) {
- if (vim_regexec(&regmatch, (char *)highlight_group_name(i), (colnr_T)0)) {
+ if (vim_regexec(&regmatch, highlight_group_name(i), (colnr_T)0)) {
if (round == 2) {
// Got more items than expected; can happen
// when adding items that match:
@@ -5369,34 +5374,39 @@ void set_context_in_syntax_cmd(expand_T *xp, const char *arg)
include_link = 0;
include_default = 0;
+ if (*arg == NUL) {
+ return;
+ }
+
// (part of) subcommand already typed
- if (*arg != NUL) {
- const char *p = (const char *)skiptowhite(arg);
- if (*p != NUL) { // Past first word.
- xp->xp_pattern = skipwhite(p);
- if (*skiptowhite(xp->xp_pattern) != NUL) {
- xp->xp_context = EXPAND_NOTHING;
- } else if (STRNICMP(arg, "case", p - arg) == 0) {
- expand_what = EXP_CASE;
- } else if (STRNICMP(arg, "spell", p - arg) == 0) {
- expand_what = EXP_SPELL;
- } else if (STRNICMP(arg, "sync", p - arg) == 0) {
- expand_what = EXP_SYNC;
- } else if (STRNICMP(arg, "list", p - arg) == 0) {
- p = skipwhite(p);
- if (*p == '@') {
- expand_what = EXP_CLUSTER;
- } else {
- xp->xp_context = EXPAND_HIGHLIGHT;
- }
- } else if (STRNICMP(arg, "keyword", p - arg) == 0
- || STRNICMP(arg, "region", p - arg) == 0
- || STRNICMP(arg, "match", p - arg) == 0) {
- xp->xp_context = EXPAND_HIGHLIGHT;
- } else {
- xp->xp_context = EXPAND_NOTHING;
- }
+ const char *p = (const char *)skiptowhite(arg);
+ if (*p == NUL) {
+ return;
+ }
+
+ // past first world
+ xp->xp_pattern = skipwhite(p);
+ if (*skiptowhite(xp->xp_pattern) != NUL) {
+ xp->xp_context = EXPAND_NOTHING;
+ } else if (STRNICMP(arg, "case", p - arg) == 0) {
+ expand_what = EXP_CASE;
+ } else if (STRNICMP(arg, "spell", p - arg) == 0) {
+ expand_what = EXP_SPELL;
+ } else if (STRNICMP(arg, "sync", p - arg) == 0) {
+ expand_what = EXP_SYNC;
+ } else if (STRNICMP(arg, "list", p - arg) == 0) {
+ p = skipwhite(p);
+ if (*p == '@') {
+ expand_what = EXP_CLUSTER;
+ } else {
+ xp->xp_context = EXPAND_HIGHLIGHT;
}
+ } else if (STRNICMP(arg, "keyword", p - arg) == 0
+ || STRNICMP(arg, "region", p - arg) == 0
+ || STRNICMP(arg, "match", p - arg) == 0) {
+ xp->xp_context = EXPAND_HIGHLIGHT;
+ } else {
+ xp->xp_context = EXPAND_NOTHING;
}
}
@@ -5677,7 +5687,7 @@ static void syntime_report(void)
msg_puts(profile_msg(p->average));
msg_puts(" ");
msg_advance(50);
- msg_outtrans((char *)highlight_group_name(p->id - 1));
+ msg_outtrans(highlight_group_name(p->id - 1));
msg_puts(" ");
msg_advance(69);
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index 73aa6eb9ca..42618e8924 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -210,22 +210,20 @@ static Callback tfu_cb; // 'tagfunc' callback function
/// Reads the 'tagfunc' option value and convert that to a callback value.
/// Invoked when the 'tagfunc' option is set. The option value can be a name of
/// a function (string), or function(<name>) or funcref(<name>) or a lambda.
-int set_tagfunc_option(void)
+void set_tagfunc_option(char **errmsg)
{
callback_free(&tfu_cb);
callback_free(&curbuf->b_tfu_cb);
if (*curbuf->b_p_tfu == NUL) {
- return OK;
+ return;
}
if (option_set_callback_func(curbuf->b_p_tfu, &tfu_cb) == FAIL) {
- return FAIL;
+ *errmsg = e_invarg;
}
callback_copy(&curbuf->b_tfu_cb, &tfu_cb);
-
- return OK;
}
#if defined(EXITFREE)
@@ -1019,7 +1017,7 @@ static int add_llist_tags(char *tag, int num_matches, char **matches)
// Get the line number or the search pattern used to locate
// the tag.
lnum = 0;
- if (isdigit(*tagp.command)) {
+ if (isdigit((uint8_t)(*tagp.command))) {
// Line number is used to locate the tag
lnum = atol(tagp.command);
} else {
@@ -1199,7 +1197,7 @@ static void prepare_pats(pat_T *pats, int has_re)
} else {
for (pats->headlen = 0; pats->head[pats->headlen] != NUL; pats->headlen++) {
if (vim_strchr(magic_isset() ? ".[~*\\$" : "\\$",
- pats->head[pats->headlen]) != NULL) {
+ (uint8_t)pats->head[pats->headlen]) != NULL) {
break;
}
}
@@ -2078,10 +2076,10 @@ static void findtags_add_match(findtags_state_T *st, tagptrs_T *tagpp, findtags_
// the part that matters for comparing, more bytes may
// follow after it. E.g. help tags store the priority
// after the NUL.
- *hash = hash_hash((char_u *)mfp);
+ *hash = hash_hash(mfp);
hi = hash_lookup(&st->ht_match[mtt], (const char *)mfp, strlen(mfp), *hash);
if (HASHITEM_EMPTY(hi)) {
- hash_add_item(&st->ht_match[mtt], hi, (char_u *)mfp, *hash);
+ hash_add_item(&st->ht_match[mtt], hi, mfp, *hash);
GA_APPEND(char *, &st->ga_match[mtt], mfp);
st->match_count++;
} else {
@@ -2563,7 +2561,7 @@ int get_tagfname(tagname_T *tnp, int first, char *buf)
if (first) {
// Init. We make a copy of 'tags', because autocommands may change
// the value without notifying us.
- tnp->tn_tags = xstrdup((*curbuf->b_p_tags != NUL) ? curbuf->b_p_tags : (char *)p_tags);
+ tnp->tn_tags = xstrdup((*curbuf->b_p_tags != NUL) ? curbuf->b_p_tags : p_tags);
tnp->tn_np = tnp->tn_tags;
}
@@ -2573,7 +2571,7 @@ int get_tagfname(tagname_T *tnp, int first, char *buf)
// tnp->tn_did_filefind_init == true: find next file in this part.
for (;;) {
if (tnp->tn_did_filefind_init) {
- fname = (char *)vim_findfile(tnp->tn_search_ctx);
+ fname = vim_findfile(tnp->tn_search_ctx);
if (fname != NULL) {
break;
}
@@ -2593,7 +2591,7 @@ int get_tagfname(tagname_T *tnp, int first, char *buf)
buf[0] = NUL;
(void)copy_option_part(&tnp->tn_np, buf, MAXPATHL - 1, " ,");
- r_ptr = (char *)vim_findfile_stopdir(buf);
+ r_ptr = vim_findfile_stopdir(buf);
// move the filename one char forward and truncate the
// filepath with a NUL
filename = path_tail(buf);
@@ -2734,55 +2732,57 @@ static int parse_match(char *lbuf, tagptrs_T *tagp)
tagp->tagline = 0;
tagp->command_end = NULL;
- if (retval == OK) {
- // Try to find a kind field: "kind:<kind>" or just "<kind>"
- p = tagp->command;
- if (find_extra(&p) == OK) {
- tagp->command_end = p;
- if (p > tagp->command && p[-1] == '|') {
- tagp->command_end = p - 1; // drop trailing bar
- }
- p += 2; // skip ";\""
- if (*p++ == TAB) {
- // Accept ASCII alphabetic kind characters and any multi-byte
- // character.
- while (ASCII_ISALPHA(*p) || utfc_ptr2len(p) > 1) {
- if (strncmp(p, "kind:", 5) == 0) {
- tagp->tagkind = p + 5;
- } else if (strncmp(p, "user_data:", 10) == 0) {
- tagp->user_data = p + 10;
- } else if (strncmp(p, "line:", 5) == 0) {
- tagp->tagline = atoi(p + 5);
- }
- if (tagp->tagkind != NULL && tagp->user_data != NULL) {
- break;
- }
+ if (retval != OK) {
+ return retval;
+ }
- pc = vim_strchr(p, ':');
- pt = vim_strchr(p, '\t');
- if (pc == NULL || (pt != NULL && pc > pt)) {
- tagp->tagkind = p;
- }
- if (pt == NULL) {
- break;
- }
- p = pt;
- MB_PTR_ADV(p);
+ // Try to find a kind field: "kind:<kind>" or just "<kind>"
+ p = tagp->command;
+ if (find_extra(&p) == OK) {
+ tagp->command_end = p;
+ if (p > tagp->command && p[-1] == '|') {
+ tagp->command_end = p - 1; // drop trailing bar
+ }
+ p += 2; // skip ";\""
+ if (*p++ == TAB) {
+ // Accept ASCII alphabetic kind characters and any multi-byte
+ // character.
+ while (ASCII_ISALPHA(*p) || utfc_ptr2len(p) > 1) {
+ if (strncmp(p, "kind:", 5) == 0) {
+ tagp->tagkind = p + 5;
+ } else if (strncmp(p, "user_data:", 10) == 0) {
+ tagp->user_data = p + 10;
+ } else if (strncmp(p, "line:", 5) == 0) {
+ tagp->tagline = atoi(p + 5);
+ }
+ if (tagp->tagkind != NULL && tagp->user_data != NULL) {
+ break;
}
+
+ pc = vim_strchr(p, ':');
+ pt = vim_strchr(p, '\t');
+ if (pc == NULL || (pt != NULL && pc > pt)) {
+ tagp->tagkind = p;
+ }
+ if (pt == NULL) {
+ break;
+ }
+ p = pt;
+ MB_PTR_ADV(p);
}
}
- if (tagp->tagkind != NULL) {
- for (p = tagp->tagkind;
- *p && *p != '\t' && *p != '\r' && *p != '\n';
- MB_PTR_ADV(p)) {}
- tagp->tagkind_end = p;
- }
- if (tagp->user_data != NULL) {
- for (p = tagp->user_data;
- *p && *p != '\t' && *p != '\r' && *p != '\n';
- MB_PTR_ADV(p)) {}
- tagp->user_data_end = p;
- }
+ }
+ if (tagp->tagkind != NULL) {
+ for (p = tagp->tagkind;
+ *p && *p != '\t' && *p != '\r' && *p != '\n';
+ MB_PTR_ADV(p)) {}
+ tagp->tagkind_end = p;
+ }
+ if (tagp->user_data != NULL) {
+ for (p = tagp->user_data;
+ *p && *p != '\t' && *p != '\r' && *p != '\n';
+ MB_PTR_ADV(p)) {}
+ tagp->user_data_end = p;
}
return retval;
}
@@ -3331,86 +3331,88 @@ int get_tags(list_T *list, char *pat, char *buf_fname)
ret = find_tags(pat, &num_matches, &matches,
TAG_REGEXP | TAG_NOIC, MAXCOL, buf_fname);
- if (ret == OK && num_matches > 0) {
- for (i = 0; i < num_matches; i++) {
- int parse_result = parse_match(matches[i], &tp);
+ if (ret != OK || num_matches <= 0) {
+ return ret;
+ }
- // Avoid an unused variable warning in release builds.
- (void)parse_result;
- assert(parse_result == OK);
+ for (i = 0; i < num_matches; i++) {
+ int parse_result = parse_match(matches[i], &tp);
- is_static = test_for_static(&tp);
+ // Avoid an unused variable warning in release builds.
+ (void)parse_result;
+ assert(parse_result == OK);
- // Skip pseudo-tag lines.
- if (strncmp(tp.tagname, "!_TAG_", 6) == 0) {
- xfree(matches[i]);
- continue;
- }
+ is_static = test_for_static(&tp);
+
+ // Skip pseudo-tag lines.
+ if (strncmp(tp.tagname, "!_TAG_", 6) == 0) {
+ xfree(matches[i]);
+ continue;
+ }
+
+ dict = tv_dict_alloc();
+ tv_list_append_dict(list, dict);
- dict = tv_dict_alloc();
- tv_list_append_dict(list, dict);
-
- full_fname = tag_full_fname(&tp);
- if (add_tag_field(dict, "name", tp.tagname, tp.tagname_end) == FAIL
- || add_tag_field(dict, "filename", full_fname, NULL) == FAIL
- || add_tag_field(dict, "cmd", tp.command, tp.command_end) == FAIL
- || add_tag_field(dict, "kind", tp.tagkind,
- tp.tagkind ? tp.tagkind_end : NULL) == FAIL
- || tv_dict_add_nr(dict, S_LEN("static"), is_static) == FAIL) {
- ret = FAIL;
- }
-
- xfree(full_fname);
-
- if (tp.command_end != NULL) {
- for (char *p = tp.command_end + 3;
- *p != NUL && *p != '\n' && *p != '\r';
- MB_PTR_ADV(p)) {
- if (p == tp.tagkind
- || (p + 5 == tp.tagkind && strncmp(p, "kind:", 5) == 0)) {
- // skip "kind:<kind>" and "<kind>"
- p = tp.tagkind_end - 1;
- } else if (strncmp(p, "file:", 5) == 0) {
- // skip "file:" (static tag)
- p += 4;
- } else if (!ascii_iswhite(*p)) {
- char *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 != ':') {
+ full_fname = tag_full_fname(&tp);
+ if (add_tag_field(dict, "name", tp.tagname, tp.tagname_end) == FAIL
+ || add_tag_field(dict, "filename", full_fname, NULL) == FAIL
+ || add_tag_field(dict, "cmd", tp.command, tp.command_end) == FAIL
+ || add_tag_field(dict, "kind", tp.tagkind,
+ tp.tagkind ? tp.tagkind_end : NULL) == FAIL
+ || tv_dict_add_nr(dict, S_LEN("static"), is_static) == FAIL) {
+ ret = FAIL;
+ }
+
+ xfree(full_fname);
+
+ if (tp.command_end != NULL) {
+ for (char *p = tp.command_end + 3;
+ *p != NUL && *p != '\n' && *p != '\r';
+ MB_PTR_ADV(p)) {
+ if (p == tp.tagkind
+ || (p + 5 == tp.tagkind && strncmp(p, "kind:", 5) == 0)) {
+ // skip "kind:<kind>" and "<kind>"
+ p = tp.tagkind_end - 1;
+ } else if (strncmp(p, "file:", 5) == 0) {
+ // skip "file:" (static tag)
+ p += 4;
+ } else if (!ascii_iswhite(*p)) {
+ char *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 != ':') {
+ p++;
+ }
+ len = (int)(p - n);
+ if (*p == ':' && len > 0) {
+ s = ++p;
+ while (*p != NUL && (uint8_t)(*p) >= ' ') {
p++;
}
- len = (int)(p - n);
- if (*p == ':' && len > 0) {
- s = ++p;
- while (*p != NUL && (uint8_t)(*p) >= ' ') {
- p++;
- }
- n[len] = NUL;
- if (add_tag_field(dict, n, s, p) == FAIL) {
- ret = FAIL;
- }
- n[len] = ':';
- } else {
- // Skip field without colon.
- while (*p != NUL && (uint8_t)(*p) >= ' ') {
- p++;
- }
+ n[len] = NUL;
+ if (add_tag_field(dict, n, s, p) == FAIL) {
+ ret = FAIL;
}
- if (*p == NUL) {
- break;
+ n[len] = ':';
+ } else {
+ // Skip field without colon.
+ while (*p != NUL && (uint8_t)(*p) >= ' ') {
+ p++;
}
}
+ if (*p == NUL) {
+ break;
+ }
}
}
-
- xfree(matches[i]);
}
- xfree(matches);
+
+ xfree(matches[i]);
}
+ xfree(matches);
return ret;
}
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 106e92d43c..a52a34cd66 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -435,7 +435,7 @@ bool terminal_enter(void)
handle_T save_curwin = curwin->handle;
bool save_w_p_cul = curwin->w_p_cul;
char *save_w_p_culopt = NULL;
- char_u save_w_p_culopt_flags = curwin->w_p_culopt_flags;
+ uint8_t 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;
@@ -718,7 +718,7 @@ void terminal_paste(long count, char **y_array, size_t y_size)
}
vterm_keyboard_start_paste(curbuf->terminal->vt);
size_t buff_len = strlen(y_array[0]);
- char_u *buff = xmalloc(buff_len);
+ char *buff = xmalloc(buff_len);
for (int i = 0; i < count; i++) { // -V756
// feed the lines to the terminal
for (size_t j = 0; j < y_size; j++) {
@@ -731,18 +731,18 @@ void terminal_paste(long count, char **y_array, size_t y_size)
buff = xrealloc(buff, len);
buff_len = len;
}
- char_u *dst = buff;
- char_u *src = (char_u *)y_array[j];
+ char *dst = buff;
+ char *src = y_array[j];
while (*src != '\0') {
- len = (size_t)utf_ptr2len((char *)src);
- int c = utf_ptr2char((char *)src);
+ len = (size_t)utf_ptr2len(src);
+ int c = utf_ptr2char(src);
if (!is_filter_char(c)) {
memcpy(dst, src, len);
dst += len;
}
src += len;
}
- terminal_send(curbuf->terminal, (char *)buff, (size_t)(dst - buff));
+ terminal_send(curbuf->terminal, buff, (size_t)(dst - buff));
}
}
xfree(buff);
diff --git a/src/nvim/testdir/check.vim b/src/nvim/testdir/check.vim
index a188f7afa1..680a59006b 100644
--- a/src/nvim/testdir/check.vim
+++ b/src/nvim/testdir/check.vim
@@ -1,6 +1,8 @@
source shared.vim
source term_util.vim
+command -nargs=1 MissingFeature throw 'Skipped: ' .. <args> .. ' feature missing'
+
" Command to check for the presence of a feature.
command -nargs=1 CheckFeature call CheckFeature(<f-args>)
func CheckFeature(name)
@@ -8,7 +10,7 @@ func CheckFeature(name)
" throw 'Checking for non-existent feature ' .. a:name
" endif
if !has(a:name)
- throw 'Skipped: ' .. a:name .. ' feature missing'
+ MissingFeature a:name
endif
endfunc
diff --git a/src/nvim/testdir/runnvim.sh b/src/nvim/testdir/runnvim.sh
index 322265737a..3a0a94b6bf 100755
--- a/src/nvim/testdir/runnvim.sh
+++ b/src/nvim/testdir/runnvim.sh
@@ -30,6 +30,9 @@ main() {(
. "$CI_DIR/common/suite.sh"
. "$CI_DIR/common/test.sh"
+ # Redirect XDG_CONFIG_HOME so users local config doesn't interfere
+ export XDG_CONFIG_HOME="$root"
+
export VIMRUNTIME="$root/runtime"
if ! "$nvim_prg" \
-u NONE -i NONE \
diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim
index 704ff6ec55..83af0f6be0 100644
--- a/src/nvim/testdir/test_autocmd.vim
+++ b/src/nvim/testdir/test_autocmd.vim
@@ -629,6 +629,7 @@ func Test_WinScrolled_diff()
\ }, event)
call StopVimInTerminal(buf)
+ call delete('XscrollEvent')
endfunc
func Test_WinClosed()
@@ -2918,7 +2919,7 @@ func Test_autocmd_CmdWinEnter()
call term_sendkeys(buf, "q:")
call term_wait(buf)
call term_sendkeys(buf, ":echo b:dummy_var\<cr>")
- call WaitForAssert({-> assert_match('^This is a dummy', term_getline(buf, 6))}, 1000)
+ call WaitForAssert({-> assert_match('^This is a dummy', term_getline(buf, 6))}, 2000)
call term_sendkeys(buf, ":echo &buftype\<cr>")
call WaitForAssert({-> assert_notmatch('^nofile', term_getline(buf, 6))}, 1000)
call term_sendkeys(buf, ":echo winnr\<cr>")
diff --git a/src/nvim/testdir/test_breakindent.vim b/src/nvim/testdir/test_breakindent.vim
index 995683c68c..2e377aa434 100644
--- a/src/nvim/testdir/test_breakindent.vim
+++ b/src/nvim/testdir/test_breakindent.vim
@@ -856,7 +856,7 @@ func Test_breakindent20_list()
" check formatlistpat indent with different list level
" showbreak and sbr
- setl briopt=min:5,sbr,list:-1,shift:2
+ setl briopt=min:5,sbr,list:-1
setl showbreak=>
redraw!
let expect = [
@@ -869,6 +869,44 @@ func Test_breakindent20_list()
\ ]
let lines = s:screen_lines2(1, 6, 20)
call s:compare_lines(expect, lines)
+
+ " check formatlistpat indent with different list level
+ " showbreak sbr and shift
+ setl briopt=min:5,sbr,list:-1,shift:2
+ setl showbreak=>
+ redraw!
+ let expect = [
+ \ "* Congress shall ",
+ \ "> make no law ",
+ \ "*** Congress shall ",
+ \ "> make no law ",
+ \ "**** Congress shall ",
+ \ "> make no law ",
+ \ ]
+ let lines = s:screen_lines2(1, 6, 20)
+ call s:compare_lines(expect, lines)
+
+ " check breakindent works if breakindentopt=list:-1
+ " for a non list content
+ %delete _
+ call setline(1, [' Congress shall make no law',
+ \ ' Congress shall make no law',
+ \ ' Congress shall make no law'])
+ norm! 1gg
+ setl briopt=min:5,list:-1
+ setl showbreak=
+ redraw!
+ let expect = [
+ \ " Congress shall ",
+ \ " make no law ",
+ \ " Congress shall ",
+ \ " make no law ",
+ \ " Congress shall ",
+ \ " make no law ",
+ \ ]
+ let lines = s:screen_lines2(1, 6, 20)
+ call s:compare_lines(expect, lines)
+
call s:close_windows('set breakindent& briopt& linebreak& list& listchars& showbreak&')
endfunc
diff --git a/src/nvim/testdir/test_buffer.vim b/src/nvim/testdir/test_buffer.vim
index 549aa691c8..9220cc17b9 100644
--- a/src/nvim/testdir/test_buffer.vim
+++ b/src/nvim/testdir/test_buffer.vim
@@ -423,6 +423,12 @@ func Test_buf_pattern_invalid()
vsplit 00000000000000000000000000
silent! buf [0--]\&\zs*\zs*e
bwipe!
+
+ " similar case with different code path
+ split 0
+ edit ÿ
+ silent! buf [0--]\&\zs*\zs*0
+ bwipe!
endfunc
" Test for the 'maxmem' and 'maxmemtot' options
diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim
index 74a5d99ef9..cf1d56ae38 100644
--- a/src/nvim/testdir/test_cmdline.vim
+++ b/src/nvim/testdir/test_cmdline.vim
@@ -151,6 +151,14 @@ func Test_complete_wildmenu()
call assert_equal('"e Xdir1/Xdir2/1', @:)
cunmap <F2>
+ " Test for canceling the wild menu by pressing <PageDown> or <PageUp>.
+ " After this pressing <Left> or <Right> should not change the selection.
+ call feedkeys(":sign \<Tab>\<PageDown>\<Left>\<Right>\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"sign define', @:)
+ call histadd('cmd', 'TestWildMenu')
+ call feedkeys(":sign \<Tab>\<PageUp>\<Left>\<Right>\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"TestWildMenu', @:)
+
" cleanup
%bwipe
call delete('Xdir1', 'rf')
@@ -421,6 +429,7 @@ func Test_getcompletion()
call assert_true(matchcount > 0)
let matchcount = len(getcompletion('File.', 'menu'))
call assert_true(matchcount > 0)
+ source $VIMRUNTIME/delmenu.vim
endif
let l = getcompletion('v:n', 'var')
@@ -642,6 +651,22 @@ func Test_getcompletion()
call assert_fails('call getcompletion("abc", [])', 'E475:')
endfunc
+" Test for getcompletion() with "fuzzy" in 'wildoptions'
+func Test_getcompletion_wildoptions()
+ let save_wildoptions = &wildoptions
+ set wildoptions&
+ let l = getcompletion('space', 'option')
+ call assert_equal([], l)
+ let l = getcompletion('ier', 'command')
+ call assert_equal([], l)
+ set wildoptions=fuzzy
+ let l = getcompletion('space', 'option')
+ call assert_true(index(l, 'backspace') >= 0)
+ let l = getcompletion('ier', 'command')
+ call assert_true(index(l, 'compiler') >= 0)
+ let &wildoptions = save_wildoptions
+endfunc
+
func Test_fullcommand()
let tests = {
\ '': '',
@@ -2198,7 +2223,8 @@ func Test_wildmenu_dirstack()
endfunc
" Test for recalling newer or older cmdline from history with <Up>, <Down>,
-" <S-Up>, <S-Down>, <PageUp>, <PageDown>, <C-p>, or <C-n>.
+" <S-Up>, <S-Down>, <PageUp>, <PageDown>, <kPageUp>, <kPageDown>, <C-p>, or
+" <C-n>.
func Test_recalling_cmdline()
CheckFeature cmdline_hist
@@ -2206,17 +2232,18 @@ func Test_recalling_cmdline()
cnoremap <Plug>(save-cmdline) <Cmd>let g:cmdlines += [getcmdline()]<CR>
let histories = [
- \ {'name': 'cmd', 'enter': ':', 'exit': "\<Esc>"},
- \ {'name': 'search', 'enter': '/', 'exit': "\<Esc>"},
- \ {'name': 'expr', 'enter': ":\<C-r>=", 'exit': "\<Esc>\<Esc>"},
- \ {'name': 'input', 'enter': ":call input('')\<CR>", 'exit': "\<CR>"},
+ \ #{name: 'cmd', enter: ':', exit: "\<Esc>"},
+ \ #{name: 'search', enter: '/', exit: "\<Esc>"},
+ \ #{name: 'expr', enter: ":\<C-r>=", exit: "\<Esc>\<Esc>"},
+ \ #{name: 'input', enter: ":call input('')\<CR>", exit: "\<CR>"},
"\ TODO: {'name': 'debug', ...}
\]
let keypairs = [
- \ {'older': "\<Up>", 'newer': "\<Down>", 'prefixmatch': v:true},
- \ {'older': "\<S-Up>", 'newer': "\<S-Down>", 'prefixmatch': v:false},
- \ {'older': "\<PageUp>", 'newer': "\<PageDown>", 'prefixmatch': v:false},
- \ {'older': "\<C-p>", 'newer': "\<C-n>", 'prefixmatch': v:false},
+ \ #{older: "\<Up>", newer: "\<Down>", prefixmatch: v:true},
+ \ #{older: "\<S-Up>", newer: "\<S-Down>", prefixmatch: v:false},
+ \ #{older: "\<PageUp>", newer: "\<PageDown>", prefixmatch: v:false},
+ \ #{older: "\<kPageUp>", newer: "\<kPageDown>", prefixmatch: v:false},
+ \ #{older: "\<C-p>", newer: "\<C-n>", prefixmatch: v:false},
\]
let prefix = 'vi'
for h in histories
@@ -2331,6 +2358,11 @@ func Test_wildmenu_pum()
set tabline=%!MyTabLine()
set showtabline=2
endfunc
+
+ func DoFeedKeys()
+ let &wildcharm = char2nr("\t")
+ call feedkeys(":edit $VIMRUNTIME/\<Tab>\<Left>\<C-U>ab\<Tab>")
+ endfunc
[CODE]
call writefile(commands, 'Xtest')
@@ -2528,6 +2560,34 @@ func Test_wildmenu_pum()
call term_sendkeys(buf, "\<Esc>")
call VerifyScreenDump(buf, 'Test_wildmenu_pum_40', {})
+ " popup is cleared also when 'lazyredraw' is set
+ call term_sendkeys(buf, ":set showtabline=1 laststatus=1 lazyredraw\<CR>")
+ call term_sendkeys(buf, ":call DoFeedKeys()\<CR>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_41', {})
+ call term_sendkeys(buf, "\<Esc>")
+
+ " Pressing <PageDown> should scroll the menu downward
+ call term_sendkeys(buf, ":sign \<Tab>\<PageDown>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_42', {})
+ call term_sendkeys(buf, "\<PageDown>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_43', {})
+ call term_sendkeys(buf, "\<PageDown>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_44', {})
+ call term_sendkeys(buf, "\<PageDown>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_45', {})
+ call term_sendkeys(buf, "\<C-U>sign \<Tab>\<Down>\<Down>\<PageDown>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_46', {})
+
+ " Pressing <PageUp> should scroll the menu upward
+ call term_sendkeys(buf, "\<C-U>sign \<Tab>\<PageUp>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_47', {})
+ call term_sendkeys(buf, "\<PageUp>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_48', {})
+ call term_sendkeys(buf, "\<PageUp>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_49', {})
+ call term_sendkeys(buf, "\<PageUp>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_50', {})
+
call term_sendkeys(buf, "\<C-U>\<CR>")
call StopVimInTerminal(buf)
call delete('Xtest')
@@ -2551,6 +2611,30 @@ func Test_wildmenumode_with_pum()
cunmap <F2>
endfunc
+" Test for opening the cmdline completion popup menu from the terminal window.
+" The popup menu should be positioned correctly over the status line of the
+" bottom-most window.
+func Test_wildmenu_pum_from_terminal()
+ CheckRunVimInTerminal
+ let python = PythonProg()
+ call CheckPython(python)
+
+ %bw!
+ let cmds = ['set wildmenu wildoptions=pum']
+ let pcmd = python .. ' -c "import sys; sys.stdout.write(sys.stdin.read())"'
+ call add(cmds, "call term_start('" .. pcmd .. "')")
+ call writefile(cmds, 'Xtest')
+ let buf = RunVimInTerminal('-S Xtest', #{rows: 10})
+ call term_sendkeys(buf, "\r\r\r")
+ call term_wait(buf)
+ call term_sendkeys(buf, "\<C-W>:sign \<Tab>")
+ call term_wait(buf)
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_term_01', {})
+ call term_wait(buf)
+ call StopVimInTerminal(buf)
+ call delete('Xtest')
+endfunc
+
func Test_wildmenu_pum_clear_entries()
CheckRunVimInTerminal
@@ -2611,6 +2695,747 @@ func Test_cmdline_complete_dlist()
call assert_equal("\"dlist 10 /pat/ | chistory", @:)
endfunc
+" argument list (only for :argdel) fuzzy completion
+func Test_fuzzy_completion_arglist()
+ argadd change.py count.py charge.py
+ set wildoptions&
+ call feedkeys(":argdel cge\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"argdel cge', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":argdel cge\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"argdel change.py charge.py', @:)
+ %argdelete
+ set wildoptions&
+endfunc
+
+" autocmd group name fuzzy completion
+func Test_fuzzy_completion_autocmd()
+ set wildoptions&
+ augroup MyFuzzyGroup
+ augroup END
+ call feedkeys(":augroup mfg\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"augroup mfg', @:)
+ call feedkeys(":augroup My*p\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"augroup MyFuzzyGroup', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":augroup mfg\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"augroup MyFuzzyGroup', @:)
+ call feedkeys(":augroup My*p\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"augroup My*p', @:)
+ augroup! MyFuzzyGroup
+ set wildoptions&
+endfunc
+
+" buffer name fuzzy completion
+func Test_fuzzy_completion_bufname()
+ set wildoptions&
+ " Use a long name to reduce the risk of matching a random directory name
+ edit SomeRandomFileWithLetters.txt
+ enew
+ call feedkeys(":b SRFWL\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"b SRFWL', @:)
+ call feedkeys(":b S*FileWithLetters.txt\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"b SomeRandomFileWithLetters.txt', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":b SRFWL\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"b SomeRandomFileWithLetters.txt', @:)
+ call feedkeys(":b S*FileWithLetters.txt\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"b S*FileWithLetters.txt', @:)
+ %bw!
+ set wildoptions&
+endfunc
+
+" buffer name (full path) fuzzy completion
+func Test_fuzzy_completion_bufname_fullpath()
+ CheckUnix
+ set wildoptions&
+ call mkdir('Xcmd/Xstate/Xfile.js', 'p')
+ edit Xcmd/Xstate/Xfile.js
+ cd Xcmd/Xstate
+ enew
+ call feedkeys(":b CmdStateFile\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"b CmdStateFile', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":b CmdStateFile\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_match('Xcmd/Xstate/Xfile.js$', @:)
+ cd -
+ call delete('Xcmd', 'rf')
+ set wildoptions&
+endfunc
+
+" :behave suboptions fuzzy completion
+func Test_fuzzy_completion_behave()
+ set wildoptions&
+ call feedkeys(":behave xm\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"behave xm', @:)
+ call feedkeys(":behave xt*m\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"behave xterm', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":behave xm\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"behave xterm', @:)
+ call feedkeys(":behave xt*m\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"behave xt*m', @:)
+ let g:Sline = ''
+ call feedkeys(":behave win\<C-D>\<F4>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('mswin', g:Sline)
+ call assert_equal('"behave win', @:)
+ set wildoptions&
+endfunc
+
+" " colorscheme name fuzzy completion - NOT supported
+" func Test_fuzzy_completion_colorscheme()
+" endfunc
+
+" built-in command name fuzzy completion
+func Test_fuzzy_completion_cmdname()
+ set wildoptions&
+ call feedkeys(":sbwin\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"sbwin', @:)
+ call feedkeys(":sbr*d\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"sbrewind', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":sbwin\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"sbrewind', @:)
+ call feedkeys(":sbr*d\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"sbr*d', @:)
+ set wildoptions&
+endfunc
+
+" " compiler name fuzzy completion - NOT supported
+" func Test_fuzzy_completion_compiler()
+" endfunc
+
+" :cscope suboptions fuzzy completion
+func Test_fuzzy_completion_cscope()
+ CheckFeature cscope
+ set wildoptions&
+ call feedkeys(":cscope ret\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"cscope ret', @:)
+ call feedkeys(":cscope re*t\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"cscope reset', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":cscope ret\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"cscope reset', @:)
+ call feedkeys(":cscope re*t\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"cscope re*t', @:)
+ set wildoptions&
+endfunc
+
+" :diffget/:diffput buffer name fuzzy completion
+func Test_fuzzy_completion_diff()
+ new SomeBuffer
+ diffthis
+ new OtherBuffer
+ diffthis
+ set wildoptions&
+ call feedkeys(":diffget sbuf\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"diffget sbuf', @:)
+ call feedkeys(":diffput sbuf\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"diffput sbuf', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":diffget sbuf\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"diffget SomeBuffer', @:)
+ call feedkeys(":diffput sbuf\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"diffput SomeBuffer', @:)
+ %bw!
+ set wildoptions&
+endfunc
+
+" " directory name fuzzy completion - NOT supported
+" func Test_fuzzy_completion_dirname()
+" endfunc
+
+" environment variable name fuzzy completion
+func Test_fuzzy_completion_env()
+ set wildoptions&
+ call feedkeys(":echo $VUT\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"echo $VUT', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":echo $VUT\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"echo $VIMRUNTIME', @:)
+ set wildoptions&
+endfunc
+
+" autocmd event fuzzy completion
+func Test_fuzzy_completion_autocmd_event()
+ set wildoptions&
+ call feedkeys(":autocmd BWout\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"autocmd BWout', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":autocmd BWout\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"autocmd BufWipeout', @:)
+ set wildoptions&
+endfunc
+
+" vim expression fuzzy completion
+func Test_fuzzy_completion_expr()
+ let g:PerPlaceCount = 10
+ set wildoptions&
+ call feedkeys(":let c = ppc\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"let c = ppc', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":let c = ppc\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"let c = PerPlaceCount', @:)
+ set wildoptions&
+endfunc
+
+" " file name fuzzy completion - NOT supported
+" func Test_fuzzy_completion_filename()
+" endfunc
+
+" " files in path fuzzy completion - NOT supported
+" func Test_fuzzy_completion_filesinpath()
+" endfunc
+
+" " filetype name fuzzy completion - NOT supported
+" func Test_fuzzy_completion_filetype()
+" endfunc
+
+" user defined function name completion
+func Test_fuzzy_completion_userdefined_func()
+ set wildoptions&
+ call feedkeys(":call Test_f_u_f\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"call Test_f_u_f', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":call Test_f_u_f\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"call Test_fuzzy_completion_userdefined_func()', @:)
+ set wildoptions&
+endfunc
+
+" <SNR> functions should be sorted to the end
+func Test_fuzzy_completion_userdefined_snr_func()
+ func s:Sendmail()
+ endfunc
+ func SendSomemail()
+ endfunc
+ func S1e2n3dmail()
+ endfunc
+ set wildoptions=fuzzy
+ call feedkeys(":call sendmail\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"call SendSomemail() S1e2n3dmail() '
+ \ .. expand("<SID>") .. 'Sendmail()', @:)
+ set wildoptions&
+ delfunc s:Sendmail
+ delfunc SendSomemail
+ delfunc S1e2n3dmail
+endfunc
+
+" user defined command name completion
+func Test_fuzzy_completion_userdefined_cmd()
+ set wildoptions&
+ call feedkeys(":MsFeat\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"MsFeat', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":MsFeat\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"MissingFeature', @:)
+ set wildoptions&
+endfunc
+
+" " :help tag fuzzy completion - NOT supported
+" func Test_fuzzy_completion_helptag()
+" endfunc
+
+" highlight group name fuzzy completion
+func Test_fuzzy_completion_hlgroup()
+ set wildoptions&
+ call feedkeys(":highlight SKey\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"highlight SKey', @:)
+ call feedkeys(":highlight Sp*Key\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"highlight SpecialKey', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":highlight SKey\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"highlight SpecialKey', @:)
+ call feedkeys(":highlight Sp*Key\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"highlight Sp*Key', @:)
+ set wildoptions&
+endfunc
+
+" :history suboptions fuzzy completion
+func Test_fuzzy_completion_history()
+ set wildoptions&
+ call feedkeys(":history dg\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"history dg', @:)
+ call feedkeys(":history se*h\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"history search', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":history dg\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"history debug', @:)
+ call feedkeys(":history se*h\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"history se*h', @:)
+ set wildoptions&
+endfunc
+
+" :language locale name fuzzy completion
+func Test_fuzzy_completion_lang()
+ CheckUnix
+ set wildoptions&
+ call feedkeys(":lang psx\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"lang psx', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":lang psx\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"lang POSIX', @:)
+ set wildoptions&
+endfunc
+
+" :mapclear buffer argument fuzzy completion
+func Test_fuzzy_completion_mapclear()
+ set wildoptions&
+ call feedkeys(":mapclear buf\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"mapclear buf', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":mapclear buf\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"mapclear <buffer>', @:)
+ set wildoptions&
+endfunc
+
+" map name fuzzy completion
+func Test_fuzzy_completion_mapname()
+ " test regex completion works
+ set wildoptions=fuzzy
+ call feedkeys(":cnoremap <ex\<Tab> <esc> \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"cnoremap <expr> <esc> \<Tab>", @:)
+ nmap <plug>MyLongMap :p<CR>
+ call feedkeys(":nmap MLM\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"nmap <Plug>MyLongMap", @:)
+ call feedkeys(":nmap MLM \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"nmap MLM \t", @:)
+ call feedkeys(":nmap <F2> one two \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"nmap <F2> one two \t", @:)
+ " duplicate entries should be removed
+ vmap <plug>MyLongMap :<C-U>#<CR>
+ call feedkeys(":nmap MLM\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"nmap <Plug>MyLongMap", @:)
+ nunmap <plug>MyLongMap
+ vunmap <plug>MyLongMap
+ call feedkeys(":nmap ABC\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"nmap ABC\t", @:)
+ " results should be sorted by best match
+ nmap <Plug>format :
+ nmap <Plug>goformat :
+ nmap <Plug>TestFOrmat :
+ nmap <Plug>fendoff :
+ nmap <Plug>state :
+ nmap <Plug>FendingOff :
+ call feedkeys(":nmap <Plug>fo\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"nmap <Plug>format <Plug>TestFOrmat <Plug>FendingOff <Plug>goformat <Plug>fendoff", @:)
+ nunmap <Plug>format
+ nunmap <Plug>goformat
+ nunmap <Plug>TestFOrmat
+ nunmap <Plug>fendoff
+ nunmap <Plug>state
+ nunmap <Plug>FendingOff
+ set wildoptions&
+endfunc
+
+" abbreviation fuzzy completion
+func Test_fuzzy_completion_abbr()
+ set wildoptions=fuzzy
+ call feedkeys(":iabbr wait\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"iabbr <nowait>", @:)
+ iabbr WaitForCompletion WFC
+ call feedkeys(":iabbr fcl\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"iabbr WaitForCompletion", @:)
+ call feedkeys(":iabbr a1z\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"iabbr a1z\t", @:)
+
+ iunabbrev WaitForCompletion
+ set wildoptions&
+endfunc
+
+" menu name fuzzy completion
+func Test_fuzzy_completion_menu()
+ CheckFeature menu
+
+ source $VIMRUNTIME/menu.vim
+ set wildoptions&
+ call feedkeys(":menu pup\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"menu pup', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":menu pup\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"menu PopUp.', @:)
+
+ set wildoptions&
+ source $VIMRUNTIME/delmenu.vim
+endfunc
+
+" :messages suboptions fuzzy completion
+func Test_fuzzy_completion_messages()
+ set wildoptions&
+ call feedkeys(":messages clr\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"messages clr', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":messages clr\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"messages clear', @:)
+ set wildoptions&
+endfunc
+
+" :set option name fuzzy completion
+func Test_fuzzy_completion_option()
+ set wildoptions&
+ call feedkeys(":set brkopt\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"set brkopt', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":set brkopt\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"set breakindentopt', @:)
+ set wildoptions&
+ call feedkeys(":set fixeol\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"set fixendofline', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":set fixeol\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"set fixendofline', @:)
+ set wildoptions&
+endfunc
+
+" :set <term_option>
+func Test_fuzzy_completion_term_option()
+ throw 'Skipped: Nvim does not support term options'
+ set wildoptions&
+ call feedkeys(":set t_E\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"set t_EC', @:)
+ call feedkeys(":set <t_E\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"set <t_EC>', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":set t_E\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"set t_EC', @:)
+ call feedkeys(":set <t_E\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"set <t_EC>', @:)
+ set wildoptions&
+endfunc
+
+" " :packadd directory name fuzzy completion - NOT supported
+" func Test_fuzzy_completion_packadd()
+" endfunc
+
+" " shell command name fuzzy completion - NOT supported
+" func Test_fuzzy_completion_shellcmd()
+" endfunc
+
+" :sign suboptions fuzzy completion
+func Test_fuzzy_completion_sign()
+ set wildoptions&
+ call feedkeys(":sign ufe\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"sign ufe', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":sign ufe\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"sign undefine', @:)
+ set wildoptions&
+endfunc
+
+" :syntax suboptions fuzzy completion
+func Test_fuzzy_completion_syntax_cmd()
+ set wildoptions&
+ call feedkeys(":syntax kwd\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"syntax kwd', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":syntax kwd\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"syntax keyword', @:)
+ set wildoptions&
+endfunc
+
+" syntax group name fuzzy completion
+func Test_fuzzy_completion_syntax_group()
+ set wildoptions&
+ call feedkeys(":syntax list mpar\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"syntax list mpar', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":syntax list mpar\<Tab>\<C-B>\"\<CR>", 'tx')
+ " Fuzzy match prefers NvimParenthesis over MatchParen
+ " call assert_equal('"syntax list MatchParen', @:)
+ call assert_equal('"syntax list NvimParenthesis', @:)
+ set wildoptions&
+endfunc
+
+" :syntime suboptions fuzzy completion
+func Test_fuzzy_completion_syntime()
+ CheckFeature profile
+ set wildoptions&
+ call feedkeys(":syntime clr\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"syntime clr', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":syntime clr\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"syntime clear', @:)
+ set wildoptions&
+endfunc
+
+" " tag name fuzzy completion - NOT supported
+" func Test_fuzzy_completion_tagname()
+" endfunc
+
+" " tag name and file fuzzy completion - NOT supported
+" func Test_fuzzy_completion_tagfile()
+" endfunc
+
+" " user names fuzzy completion - how to test this functionality?
+" func Test_fuzzy_completion_username()
+" endfunc
+
+" user defined variable name fuzzy completion
+func Test_fuzzy_completion_userdefined_var()
+ let g:SomeVariable=10
+ set wildoptions&
+ call feedkeys(":let SVar\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"let SVar', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":let SVar\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"let SomeVariable', @:)
+ set wildoptions&
+endfunc
+
+" Test for sorting the results by the best match
+func Test_fuzzy_completion_cmd_sort_results()
+ %bw!
+ command T123format :
+ command T123goformat :
+ command T123TestFOrmat :
+ command T123fendoff :
+ command T123state :
+ command T123FendingOff :
+ set wildoptions=fuzzy
+ call feedkeys(":T123fo\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"T123format T123TestFOrmat T123FendingOff T123goformat T123fendoff', @:)
+ delcommand T123format
+ delcommand T123goformat
+ delcommand T123TestFOrmat
+ delcommand T123fendoff
+ delcommand T123state
+ delcommand T123FendingOff
+ %bw
+ set wildoptions&
+endfunc
+
+" Test for fuzzy completion of a command with lower case letters and a number
+func Test_fuzzy_completion_cmd_alnum()
+ command Foo2Bar :
+ set wildoptions=fuzzy
+ call feedkeys(":foo2\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"Foo2Bar', @:)
+ call feedkeys(":foo\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"Foo2Bar', @:)
+ call feedkeys(":bar\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"Foo2Bar', @:)
+ delcommand Foo2Bar
+ set wildoptions&
+endfunc
+
+" Test for command completion for a command starting with 'k'
+func Test_fuzzy_completion_cmd_k()
+ command KillKillKill :
+ set wildoptions&
+ call feedkeys(":killkill\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"killkill\<Tab>", @:)
+ set wildoptions=fuzzy
+ call feedkeys(":killkill\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"KillKillKill', @:)
+ delcom KillKillKill
+ set wildoptions&
+endfunc
+
+" Test for fuzzy completion for user defined custom completion function
+func Test_fuzzy_completion_custom_func()
+ func Tcompl(a, c, p)
+ return "format\ngoformat\nTestFOrmat\nfendoff\nstate"
+ endfunc
+ command -nargs=* -complete=custom,Tcompl Fuzzy :
+ set wildoptions&
+ call feedkeys(":Fuzzy fo\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"Fuzzy format", @:)
+ call feedkeys(":Fuzzy xy\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"Fuzzy xy", @:)
+ call feedkeys(":Fuzzy ttt\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"Fuzzy ttt", @:)
+ set wildoptions=fuzzy
+ call feedkeys(":Fuzzy \<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"Fuzzy format goformat TestFOrmat fendoff state", @:)
+ call feedkeys(":Fuzzy fo\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"Fuzzy format TestFOrmat goformat fendoff", @:)
+ call feedkeys(":Fuzzy xy\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"Fuzzy xy", @:)
+ call feedkeys(":Fuzzy ttt\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"Fuzzy TestFOrmat", @:)
+ delcom Fuzzy
+ set wildoptions&
+endfunc
+
+" Test for :breakadd argument completion
+func Test_cmdline_complete_breakadd()
+ call feedkeys(":breakadd \<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd expr file func here", @:)
+ call feedkeys(":breakadd \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd expr", @:)
+ call feedkeys(":breakadd \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd expr", @:)
+ call feedkeys(":breakadd he\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd here", @:)
+ call feedkeys(":breakadd he\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd here", @:)
+ call feedkeys(":breakadd abc\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd abc", @:)
+ call assert_equal(['expr', 'file', 'func', 'here'], getcompletion('', 'breakpoint'))
+ let l = getcompletion('not', 'breakpoint')
+ call assert_equal([], l)
+
+ " Test for :breakadd file [lnum] <file>
+ call writefile([], 'Xscript')
+ call feedkeys(":breakadd file Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd file Xscript", @:)
+ call feedkeys(":breakadd file Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd file Xscript", @:)
+ call feedkeys(":breakadd file 20 Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd file 20 Xscript", @:)
+ call feedkeys(":breakadd file 20 Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd file 20 Xscript", @:)
+ call feedkeys(":breakadd file 20x Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd file 20x Xsc\t", @:)
+ call feedkeys(":breakadd file 20\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd file 20\t", @:)
+ call feedkeys(":breakadd file 20x\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd file 20x\t", @:)
+ call feedkeys(":breakadd file Xscript \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd file Xscript ", @:)
+ call feedkeys(":breakadd file X1B2C3\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd file X1B2C3", @:)
+ call delete('Xscript')
+
+ " Test for :breakadd func [lnum] <function>
+ func Xbreak_func()
+ endfunc
+ call feedkeys(":breakadd func Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd func Xbreak_func", @:)
+ call feedkeys(":breakadd func Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd func Xbreak_func", @:)
+ call feedkeys(":breakadd func 20 Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd func 20 Xbreak_func", @:)
+ call feedkeys(":breakadd func 20 Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd func 20 Xbreak_func", @:)
+ call feedkeys(":breakadd func 20x Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd func 20x Xbr\t", @:)
+ call feedkeys(":breakadd func 20\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd func 20\t", @:)
+ call feedkeys(":breakadd func 20x\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd func 20x\t", @:)
+ call feedkeys(":breakadd func Xbreak_func \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd func Xbreak_func ", @:)
+ call feedkeys(":breakadd func X1B2C3\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd func X1B2C3", @:)
+ delfunc Xbreak_func
+
+ " Test for :breakadd expr <expression>
+ let g:Xtest_var = 10
+ call feedkeys(":breakadd expr Xtest\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd expr Xtest_var", @:)
+ call feedkeys(":breakadd expr Xtest\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd expr Xtest_var", @:)
+ call feedkeys(":breakadd expr Xtest_var \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd expr Xtest_var ", @:)
+ call feedkeys(":breakadd expr X1B2C3\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd expr X1B2C3", @:)
+ unlet g:Xtest_var
+
+ " Test for :breakadd here
+ call feedkeys(":breakadd here Xtest\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd here Xtest", @:)
+ call feedkeys(":breakadd here Xtest\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd here Xtest", @:)
+ call feedkeys(":breakadd here \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd here ", @:)
+endfunc
+
+" Test for :breakdel argument completion
+func Test_cmdline_complete_breakdel()
+ call feedkeys(":breakdel \<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel file func here", @:)
+ call feedkeys(":breakdel \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel file", @:)
+ call feedkeys(":breakdel \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel file", @:)
+ call feedkeys(":breakdel he\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel here", @:)
+ call feedkeys(":breakdel he\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel here", @:)
+ call feedkeys(":breakdel abc\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel abc", @:)
+
+ " Test for :breakdel file [lnum] <file>
+ call writefile([], 'Xscript')
+ call feedkeys(":breakdel file Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel file Xscript", @:)
+ call feedkeys(":breakdel file Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel file Xscript", @:)
+ call feedkeys(":breakdel file 20 Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel file 20 Xscript", @:)
+ call feedkeys(":breakdel file 20 Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel file 20 Xscript", @:)
+ call feedkeys(":breakdel file 20x Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel file 20x Xsc\t", @:)
+ call feedkeys(":breakdel file 20\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel file 20\t", @:)
+ call feedkeys(":breakdel file 20x\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel file 20x\t", @:)
+ call feedkeys(":breakdel file Xscript \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel file Xscript ", @:)
+ call feedkeys(":breakdel file X1B2C3\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel file X1B2C3", @:)
+ call delete('Xscript')
+
+ " Test for :breakdel func [lnum] <function>
+ func Xbreak_func()
+ endfunc
+ call feedkeys(":breakdel func Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel func Xbreak_func", @:)
+ call feedkeys(":breakdel func Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel func Xbreak_func", @:)
+ call feedkeys(":breakdel func 20 Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel func 20 Xbreak_func", @:)
+ call feedkeys(":breakdel func 20 Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel func 20 Xbreak_func", @:)
+ call feedkeys(":breakdel func 20x Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel func 20x Xbr\t", @:)
+ call feedkeys(":breakdel func 20\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel func 20\t", @:)
+ call feedkeys(":breakdel func 20x\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel func 20x\t", @:)
+ call feedkeys(":breakdel func Xbreak_func \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel func Xbreak_func ", @:)
+ call feedkeys(":breakdel func X1B2C3\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel func X1B2C3", @:)
+ delfunc Xbreak_func
+
+ " Test for :breakdel here
+ call feedkeys(":breakdel here Xtest\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel here Xtest", @:)
+ call feedkeys(":breakdel here Xtest\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel here Xtest", @:)
+ call feedkeys(":breakdel here \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel here ", @:)
+endfunc
+
+" Test for :scriptnames argument completion
+func Test_cmdline_complete_scriptnames()
+ set wildmenu
+ call writefile(['let a = 1'], 'Xa1b2c3.vim')
+ source Xa1b2c3.vim
+ call feedkeys(":script \<Tab>\<Left>\<Left>\<C-B>\"\<CR>", 'tx')
+ call assert_match("\"script .*Xa1b2c3.vim$", @:)
+ call feedkeys(":script \<Tab>\<Left>\<Left>\<C-B>\"\<CR>", 'tx')
+ call assert_match("\"script .*Xa1b2c3.vim$", @:)
+ call feedkeys(":script b2c3\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"script b2c3", @:)
+ call feedkeys(":script 2\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_match("\"script 2\<Tab>$", @:)
+ call feedkeys(":script \<Tab>\<Left>\<Left> \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_match("\"script .*Xa1b2c3.vim $", @:)
+ call feedkeys(":script \<Tab>\<Left>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"script ", @:)
+ call assert_match('Xa1b2c3.vim$', getcompletion('.*Xa1b2.*', 'scriptnames')[0])
+ call assert_equal([], getcompletion('Xa1b2', 'scriptnames'))
+ new
+ call feedkeys(":script \<Tab>\<Left>\<Left>\<CR>", 'tx')
+ call assert_equal('Xa1b2c3.vim', fnamemodify(@%, ':t'))
+ bw!
+ call delete('Xa1b2c3.vim')
+ set wildmenu&
+endfunc
+
" this was going over the end of IObuff
func Test_report_error_with_composing()
let caught = 'no'
@@ -2635,6 +3460,16 @@ func Test_cmdline_complete_substitute_short()
endfor
endfunc
+" Test for :! shell command argument completion
+func Test_cmdline_complete_bang_cmd_argument()
+ set wildoptions=fuzzy
+ call feedkeys(":!vim test_cmdline.\<Tab>\<C-B>\"\<CR>", 'xt')
+ call assert_equal('"!vim test_cmdline.vim', @:)
+ set wildoptions&
+ call feedkeys(":!vim test_cmdline.\<Tab>\<C-B>\"\<CR>", 'xt')
+ call assert_equal('"!vim test_cmdline.vim', @:)
+endfunc
+
func Check_completion()
call assert_equal('let a', getcmdline())
call assert_equal(6, getcmdpos())
diff --git a/src/nvim/testdir/test_const.vim b/src/nvim/testdir/test_const.vim
index 7f19085b16..4a6c8779dd 100644
--- a/src/nvim/testdir/test_const.vim
+++ b/src/nvim/testdir/test_const.vim
@@ -194,6 +194,14 @@ func Test_lockvar()
if 0 | lockvar x | endif
let x = 'again'
+
+ let val = [1, 2, 3]
+ lockvar 0 val
+ let val[0] = 9
+ call assert_equal([9, 2, 3], val)
+ call add(val, 4)
+ call assert_equal([9, 2, 3, 4], val)
+ call assert_fails('let val = [4, 5, 6]', 'E1122:')
endfunc
diff --git a/src/nvim/testdir/test_cursorline.vim b/src/nvim/testdir/test_cursorline.vim
index 47646125db..70f39a8601 100644
--- a/src/nvim/testdir/test_cursorline.vim
+++ b/src/nvim/testdir/test_cursorline.vim
@@ -319,7 +319,7 @@ func Test_cursorline_cursorbind_horizontal_scroll()
let lines =<< trim END
call setline(1, 'aa bb cc dd ee ff gg hh ii jj kk ll mm' ..
- \ ' nn oo pp qq rr ss tt uu vv ww xx yy zz')
+ \ ' nn oo pp qq rr ss tt uu vv ww xx yy zz')
set nowrap
" The following makes the cursor apparent on the screen dump
set sidescroll=1 cursorcolumn
diff --git a/src/nvim/testdir/test_debugger.vim b/src/nvim/testdir/test_debugger.vim
index 4609b9d2f9..f5177c8fb2 100644
--- a/src/nvim/testdir/test_debugger.vim
+++ b/src/nvim/testdir/test_debugger.vim
@@ -36,7 +36,7 @@ endfunc
" If the expected output argument is supplied, then check for it.
func RunDbgCmd(buf, cmd, ...)
call term_sendkeys(a:buf, a:cmd . "\r")
- call term_wait(a:buf)
+ call term_wait(a:buf, 20)
if a:0 != 0
let options = #{match: 'equal'}
diff --git a/src/nvim/testdir/test_edit.vim b/src/nvim/testdir/test_edit.vim
index fd54f77ccb..89a9179e60 100644
--- a/src/nvim/testdir/test_edit.vim
+++ b/src/nvim/testdir/test_edit.vim
@@ -336,8 +336,23 @@ func Test_edit_11_indentexpr()
endfunc
set indentexpr=s:NewIndentExpr()
call assert_equal(expand('<SID>') .. 'NewIndentExpr()', &indentexpr)
+ call assert_equal(expand('<SID>') .. 'NewIndentExpr()', &g:indentexpr)
set indentexpr=<SID>NewIndentExpr()
call assert_equal(expand('<SID>') .. 'NewIndentExpr()', &indentexpr)
+ call assert_equal(expand('<SID>') .. 'NewIndentExpr()', &g:indentexpr)
+ setlocal indentexpr=
+ setglobal indentexpr=s:NewIndentExpr()
+ call assert_equal(expand('<SID>') .. 'NewIndentExpr()', &g:indentexpr)
+ call assert_equal('', &indentexpr)
+ new
+ call assert_equal(expand('<SID>') .. 'NewIndentExpr()', &indentexpr)
+ bw!
+ setglobal indentexpr=<SID>NewIndentExpr()
+ call assert_equal(expand('<SID>') .. 'NewIndentExpr()', &g:indentexpr)
+ call assert_equal('', &indentexpr)
+ new
+ call assert_equal(expand('<SID>') .. 'NewIndentExpr()', &indentexpr)
+ bw!
set indentexpr&
bw!
diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim
index b065df68f7..88c25ab115 100644
--- a/src/nvim/testdir/test_filetype.vim
+++ b/src/nvim/testdir/test_filetype.vim
@@ -98,6 +98,7 @@ let s:filename_checks = {
\ 'cabalconfig': ['cabal.config'],
\ 'cabalproject': ['cabal.project', 'cabal.project.local'],
\ 'calendar': ['calendar', '/.calendar/file', '/share/calendar/any/calendar.file', '/share/calendar/calendar.file', 'any/share/calendar/any/calendar.file', 'any/share/calendar/calendar.file'],
+ \ 'capnp': ['file.capnp'],
\ 'catalog': ['catalog', 'sgml.catalogfile', 'sgml.catalog', 'sgml.catalog-file'],
\ 'cdl': ['file.cdl'],
\ 'cdrdaoconf': ['/etc/cdrdao.conf', '/etc/defaults/cdrdao', '/etc/default/cdrdao', '.cdrdao', 'any/etc/cdrdao.conf', 'any/etc/default/cdrdao', 'any/etc/defaults/cdrdao'],
@@ -122,7 +123,7 @@ let s:filename_checks = {
\ 'conaryrecipe': ['file.recipe'],
\ 'conf': ['auto.master'],
\ 'config': ['configure.in', 'configure.ac', '/etc/hostname.file', 'any/etc/hostname.file'],
- \ 'confini': ['/etc/pacman.conf', 'any/etc/pacman.conf', 'mpv.conf', 'any/.aws/config', 'any/.aws/credentials'],
+ \ 'confini': ['/etc/pacman.conf', 'any/etc/pacman.conf', 'mpv.conf', 'any/.aws/config', 'any/.aws/credentials', 'file.nmconnection'],
\ 'context': ['tex/context/any/file.tex', 'file.mkii', 'file.mkiv', 'file.mkvi', 'file.mkxl', 'file.mklx'],
\ 'cook': ['file.cook'],
\ 'cpp': ['file.cxx', 'file.c++', 'file.hh', 'file.hxx', 'file.hpp', 'file.ipp', 'file.moc', 'file.tcc', 'file.inl', 'file.tlh'],
@@ -180,6 +181,7 @@ let s:filename_checks = {
\ 'elixir': ['file.ex', 'file.exs', 'mix.lock'],
\ 'elm': ['file.elm'],
\ 'elmfilt': ['filter-rules'],
+ \ 'elsa': ['file.lc'],
\ 'elvish': ['file.elv'],
\ 'epuppet': ['file.epp'],
\ 'erlang': ['file.erl', 'file.hrl', 'file.yaws'],
@@ -293,13 +295,14 @@ let s:filename_checks = {
\ 'jq': ['file.jq'],
\ 'jovial': ['file.jov', 'file.j73', 'file.jovial'],
\ 'jproperties': ['file.properties', 'file.properties_xx', 'file.properties_xx_xx', 'some.properties_xx_xx_file', 'org.eclipse.xyz.prefs'],
- \ 'json': ['file.json', 'file.jsonp', 'file.json-patch', 'file.webmanifest', 'Pipfile.lock', 'file.ipynb', '.prettierrc', '.firebaserc', 'file.slnf'],
+ \ 'json': ['file.json', 'file.jsonp', 'file.json-patch', 'file.webmanifest', 'Pipfile.lock', 'file.ipynb', '.prettierrc', '.firebaserc', '.stylelintrc', 'file.slnf'],
\ 'json5': ['file.json5'],
\ 'jsonc': ['file.jsonc', '.babelrc', '.eslintrc', '.jsfmtrc', '.jshintrc', '.hintrc', '.swrc', 'jsconfig.json', 'tsconfig.json', 'tsconfig.test.json', 'tsconfig-test.json'],
\ 'jsonnet': ['file.jsonnet', 'file.libsonnet'],
\ 'jsp': ['file.jsp'],
\ 'julia': ['file.jl'],
\ 'kconfig': ['Kconfig', 'Kconfig.debug', 'Kconfig.file'],
+ \ 'kdl': ['file.kdl'],
\ 'kivy': ['file.kv'],
\ 'kix': ['file.kix'],
\ 'kotlin': ['file.kt', 'file.ktm', 'file.kts'],
@@ -580,6 +583,7 @@ let s:filename_checks = {
\ 'texmf': ['texmf.cnf'],
\ 'text': ['file.text', 'file.txt', 'README', 'LICENSE', 'COPYING', 'AUTHORS', '/usr/share/doc/bash-completion/AUTHORS', '/etc/apt/apt.conf.d/README', '/etc/Muttrc.d/README'],
\ 'tf': ['file.tf', '.tfrc', 'tfrc'],
+ \ 'thrift': ['file.thrift'],
\ 'tidy': ['.tidyrc', 'tidyrc', 'tidy.conf'],
\ 'tilde': ['file.t.html'],
\ 'tla': ['file.tla'],
@@ -653,7 +657,7 @@ let s:filename_checks = {
\ 'xsd': ['file.xsd'],
\ 'xslt': ['file.xsl', 'file.xslt'],
\ 'yacc': ['file.yy', 'file.yxx', 'file.y++'],
- \ 'yaml': ['file.yaml', 'file.yml', '.clang-format', '.clang-tidy'],
+ \ 'yaml': ['file.yaml', 'file.yml', '.clangd', '.clang-format', '.clang-tidy'],
\ 'yang': ['file.yang'],
\ 'z8a': ['file.z8a'],
\ 'zig': ['file.zig'],
diff --git a/src/nvim/testdir/test_fold.vim b/src/nvim/testdir/test_fold.vim
index 130ad9c7e1..9014948fb4 100644
--- a/src/nvim/testdir/test_fold.vim
+++ b/src/nvim/testdir/test_fold.vim
@@ -1305,6 +1305,7 @@ func Test_foldexpr_scriptlocal_func()
set foldmethod=expr foldexpr=s:FoldFunc()
redraw!
call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
+ call assert_equal(expand('<SID>') .. 'FoldFunc()', &g:foldexpr)
call assert_equal(1, g:FoldLnum)
set foldmethod& foldexpr=
bw!
@@ -1314,8 +1315,31 @@ func Test_foldexpr_scriptlocal_func()
set foldmethod=expr foldexpr=<SID>FoldFunc()
redraw!
call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
+ call assert_equal(expand('<SID>') .. 'FoldFunc()', &g:foldexpr)
call assert_equal(1, g:FoldLnum)
- set foldmethod& foldexpr=
+ bw!
+ call setline(1, 'abc')
+ setlocal foldmethod& foldexpr&
+ setglobal foldmethod=expr foldexpr=s:FoldFunc()
+ call assert_equal(expand('<SID>') .. 'FoldFunc()', &g:foldexpr)
+ call assert_equal('0', &foldexpr)
+ enew!
+ call setline(1, 'abc')
+ redraw!
+ call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
+ call assert_equal(1, g:FoldLnum)
+ bw!
+ call setline(1, 'abc')
+ setlocal foldmethod& foldexpr&
+ setglobal foldmethod=expr foldexpr=<SID>FoldFunc()
+ call assert_equal(expand('<SID>') .. 'FoldFunc()', &g:foldexpr)
+ call assert_equal('0', &foldexpr)
+ enew!
+ call setline(1, 'abc')
+ redraw!
+ call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
+ call assert_equal(1, g:FoldLnum)
+ set foldmethod& foldexpr&
delfunc s:FoldFunc
bw!
endfunc
@@ -1329,25 +1353,53 @@ func Test_foldtext_scriptlocal_func()
new | only
call setline(1, range(50))
let g:FoldTextArgs = []
- set foldmethod=manual
set foldtext=s:FoldText()
norm! 4Gzf4j
redraw!
call assert_equal(expand('<SID>') .. 'FoldText()', &foldtext)
+ call assert_equal(expand('<SID>') .. 'FoldText()', &g:foldtext)
call assert_equal([4, 8], g:FoldTextArgs)
set foldtext&
bw!
new | only
call setline(1, range(50))
let g:FoldTextArgs = []
- set foldmethod=manual
set foldtext=<SID>FoldText()
norm! 8Gzf4j
redraw!
call assert_equal(expand('<SID>') .. 'FoldText()', &foldtext)
+ call assert_equal(expand('<SID>') .. 'FoldText()', &g:foldtext)
call assert_equal([8, 12], g:FoldTextArgs)
set foldtext&
bw!
+ call setline(1, range(50))
+ let g:FoldTextArgs = []
+ setlocal foldtext&
+ setglobal foldtext=s:FoldText()
+ call assert_equal(expand('<SID>') .. 'FoldText()', &g:foldtext)
+ call assert_equal('foldtext()', &foldtext)
+ enew!
+ call setline(1, range(50))
+ norm! 12Gzf4j
+ redraw!
+ call assert_equal(expand('<SID>') .. 'FoldText()', &foldtext)
+ call assert_equal([12, 16], g:FoldTextArgs)
+ set foldtext&
+ bw!
+ call setline(1, range(50))
+ let g:FoldTextArgs = []
+ setlocal foldtext&
+ setglobal foldtext=<SID>FoldText()
+ call assert_equal(expand('<SID>') .. 'FoldText()', &g:foldtext)
+ call assert_equal('foldtext()', &foldtext)
+ enew!
+ call setline(1, range(50))
+ norm! 16Gzf4j
+ redraw!
+ call assert_equal(expand('<SID>') .. 'FoldText()', &foldtext)
+ call assert_equal([16, 20], g:FoldTextArgs)
+ set foldtext&
+ bw!
delfunc s:FoldText
endfunc
@@ -1483,4 +1535,17 @@ func Test_indent_with_L_command()
bwipe!
endfunc
+" Make sure that when there is a fold at the bottom of the buffer and a newline
+" character is appended to the line, the fold gets expanded (instead of the new
+" line not being part of the fold).
+func Test_expand_fold_at_bottom_of_buffer()
+ new
+ " create a fold on the only line
+ fold
+ execute "normal A\<CR>"
+ call assert_equal([1, 1], range(1, 2)->map('foldlevel(v:val)'))
+
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_gf.vim b/src/nvim/testdir/test_gf.vim
index e369645328..f09dbd72ce 100644
--- a/src/nvim/testdir/test_gf.vim
+++ b/src/nvim/testdir/test_gf.vim
@@ -234,6 +234,7 @@ func Test_includeexpr_scriptlocal_func()
endfunc
set includeexpr=s:IncludeFunc()
call assert_equal(expand('<SID>') .. 'IncludeFunc()', &includeexpr)
+ call assert_equal(expand('<SID>') .. 'IncludeFunc()', &g:includeexpr)
new | only
call setline(1, 'TestFile1')
let g:IncludeFname = ''
@@ -242,11 +243,35 @@ func Test_includeexpr_scriptlocal_func()
bw!
set includeexpr=<SID>IncludeFunc()
call assert_equal(expand('<SID>') .. 'IncludeFunc()', &includeexpr)
+ call assert_equal(expand('<SID>') .. 'IncludeFunc()', &g:includeexpr)
new | only
call setline(1, 'TestFile2')
let g:IncludeFname = ''
call assert_fails('normal! gf', 'E447:')
call assert_equal('TestFile2', g:IncludeFname)
+ bw!
+ setlocal includeexpr=
+ setglobal includeexpr=s:IncludeFunc()
+ call assert_equal(expand('<SID>') .. 'IncludeFunc()', &g:includeexpr)
+ call assert_equal('', &includeexpr)
+ new
+ call assert_equal(expand('<SID>') .. 'IncludeFunc()', &includeexpr)
+ call setline(1, 'TestFile3')
+ let g:IncludeFname = ''
+ call assert_fails('normal! gf', 'E447:')
+ call assert_equal('TestFile3', g:IncludeFname)
+ bw!
+ setlocal includeexpr=
+ setglobal includeexpr=<SID>IncludeFunc()
+ call assert_equal(expand('<SID>') .. 'IncludeFunc()', &g:includeexpr)
+ call assert_equal('', &includeexpr)
+ new
+ call assert_equal(expand('<SID>') .. 'IncludeFunc()', &includeexpr)
+ call setline(1, 'TestFile4')
+ let g:IncludeFname = ''
+ call assert_fails('normal! gf', 'E447:')
+ call assert_equal('TestFile4', g:IncludeFname)
+ bw!
set includeexpr&
delfunc s:IncludeFunc
bw!
diff --git a/src/nvim/testdir/test_ins_complete.vim b/src/nvim/testdir/test_ins_complete.vim
index 7a9392545e..ec1379a378 100644
--- a/src/nvim/testdir/test_ins_complete.vim
+++ b/src/nvim/testdir/test_ins_complete.vim
@@ -581,6 +581,33 @@ func Test_pum_with_folds_two_tabs()
call delete('Xpumscript')
endfunc
+func Test_pum_with_preview_win()
+ CheckScreendump
+
+ let lines =<< trim END
+ funct Omni_test(findstart, base)
+ if a:findstart
+ return col(".") - 1
+ endif
+ return [#{word: "one", info: "1info"}, #{word: "two", info: "2info"}, #{word: "three", info: "3info"}]
+ endfunc
+ set omnifunc=Omni_test
+ set completeopt+=longest
+ END
+
+ call writefile(lines, 'Xpreviewscript')
+ let buf = RunVimInTerminal('-S Xpreviewscript', #{rows: 12})
+ call term_wait(buf, 100)
+ call term_sendkeys(buf, "Gi\<C-X>\<C-O>")
+ call term_wait(buf, 200)
+ call term_sendkeys(buf, "\<C-N>")
+ call VerifyScreenDump(buf, 'Test_pum_with_preview_win', {})
+
+ call term_sendkeys(buf, "\<Esc>")
+ call StopVimInTerminal(buf)
+ call delete('Xpreviewscript')
+endfunc
+
" Test for inserting the tag search pattern in insert mode
func Test_ins_compl_tag_sft()
call writefile([
diff --git a/src/nvim/testdir/test_listdict.vim b/src/nvim/testdir/test_listdict.vim
index 8d7bede403..9ecd83265a 100644
--- a/src/nvim/testdir/test_listdict.vim
+++ b/src/nvim/testdir/test_listdict.vim
@@ -357,7 +357,7 @@ endfunc
" Locked variables
func Test_list_locked_var()
let expected = [
- \ [['0000-000', 'ppppppp'],
+ \ [['1000-000', 'ppppppF'],
\ ['0000-000', 'ppppppp'],
\ ['0000-000', 'ppppppp']],
\ [['1000-000', 'ppppppF'],
@@ -384,7 +384,7 @@ func Test_list_locked_var()
exe "unlockvar " . depth . " l"
endif
let ps = islocked("l").islocked("l[1]").islocked("l[1][1]").islocked("l[1][1][0]").'-'.islocked("l[2]").islocked("l[2]['6']").islocked("l[2]['6'][7]")
- call assert_equal(expected[depth][u][0], ps)
+ call assert_equal(expected[depth][u][0], ps, 'depth: ' .. depth)
let ps = ''
try
let l[1][1][0] = 99
@@ -428,7 +428,7 @@ func Test_list_locked_var()
catch
let ps .= 'F'
endtry
- call assert_equal(expected[depth][u][1], ps)
+ call assert_equal(expected[depth][u][1], ps, 'depth: ' .. depth)
endfor
endfor
call assert_fails("let x=islocked('a b')", 'E488:')
@@ -441,7 +441,7 @@ endfunc
" Unletting locked variables
func Test_list_locked_var_unlet()
let expected = [
- \ [['0000-000', 'ppppppp'],
+ \ [['1000-000', 'ppppppp'],
\ ['0000-000', 'ppppppp'],
\ ['0000-000', 'ppppppp']],
\ [['1000-000', 'ppFppFp'],
@@ -469,7 +469,7 @@ func Test_list_locked_var_unlet()
exe "unlockvar " . depth . " l"
endif
let ps = islocked("l").islocked("l[1]").islocked("l[1][1]").islocked("l[1][1][0]").'-'.islocked("l[2]").islocked("l[2]['6']").islocked("l[2]['6'][7]")
- call assert_equal(expected[depth][u][0], ps)
+ call assert_equal(expected[depth][u][0], ps, 'depth: ' .. depth)
let ps = ''
try
unlet l[2]['6'][7]
@@ -673,6 +673,9 @@ func Test_func_arg_list()
call s:arg_list_test(1, 2, [3, 4], {5: 6})
endfunc
+func Test_dict_item_locked()
+endfunc
+
" Tests for reverse(), sort(), uniq()
func Test_reverse_sort_uniq()
let l = ['-0', 'A11', 2, 2, 'xaaa', 4, 'foo', 'foo6', 'foo', [0, 1, 2], 'x8', [0, 1, 2], 1.5]
diff --git a/src/nvim/testdir/test_normal.vim b/src/nvim/testdir/test_normal.vim
index 7c90b444e5..2aaa1ff830 100644
--- a/src/nvim/testdir/test_normal.vim
+++ b/src/nvim/testdir/test_normal.vim
@@ -262,6 +262,7 @@ func Test_formatexpr_scriptlocal_func()
endfunc
set formatexpr=s:Format()
call assert_equal(expand('<SID>') .. 'Format()', &formatexpr)
+ call assert_equal(expand('<SID>') .. 'Format()', &g:formatexpr)
new | only
call setline(1, range(1, 40))
let g:FormatArgs = []
@@ -270,6 +271,7 @@ func Test_formatexpr_scriptlocal_func()
bw!
set formatexpr=<SID>Format()
call assert_equal(expand('<SID>') .. 'Format()', &formatexpr)
+ call assert_equal(expand('<SID>') .. 'Format()', &g:formatexpr)
new | only
call setline(1, range(1, 40))
let g:FormatArgs = []
@@ -277,6 +279,7 @@ func Test_formatexpr_scriptlocal_func()
call assert_equal([4, 2], g:FormatArgs)
bw!
let &formatexpr = 's:Format()'
+ call assert_equal(expand('<SID>') .. 'Format()', &g:formatexpr)
new | only
call setline(1, range(1, 40))
let g:FormatArgs = []
@@ -284,12 +287,55 @@ func Test_formatexpr_scriptlocal_func()
call assert_equal([6, 2], g:FormatArgs)
bw!
let &formatexpr = '<SID>Format()'
+ call assert_equal(expand('<SID>') .. 'Format()', &g:formatexpr)
new | only
call setline(1, range(1, 40))
let g:FormatArgs = []
normal! 8GVjgq
call assert_equal([8, 2], g:FormatArgs)
+ bw!
setlocal formatexpr=
+ setglobal formatexpr=s:Format()
+ call assert_equal(expand('<SID>') .. 'Format()', &g:formatexpr)
+ call assert_equal('', &formatexpr)
+ new
+ call assert_equal(expand('<SID>') .. 'Format()', &formatexpr)
+ call setline(1, range(1, 40))
+ let g:FormatArgs = []
+ normal! 10GVjgq
+ call assert_equal([10, 2], g:FormatArgs)
+ bw!
+ setglobal formatexpr=<SID>Format()
+ call assert_equal(expand('<SID>') .. 'Format()', &g:formatexpr)
+ call assert_equal('', &formatexpr)
+ new
+ call assert_equal(expand('<SID>') .. 'Format()', &formatexpr)
+ call setline(1, range(1, 40))
+ let g:FormatArgs = []
+ normal! 12GVjgq
+ call assert_equal([12, 2], g:FormatArgs)
+ bw!
+ let &g:formatexpr = 's:Format()'
+ call assert_equal(expand('<SID>') .. 'Format()', &g:formatexpr)
+ call assert_equal('', &formatexpr)
+ new
+ call assert_equal(expand('<SID>') .. 'Format()', &formatexpr)
+ call setline(1, range(1, 40))
+ let g:FormatArgs = []
+ normal! 14GVjgq
+ call assert_equal([14, 2], g:FormatArgs)
+ bw!
+ let &g:formatexpr = '<SID>Format()'
+ call assert_equal(expand('<SID>') .. 'Format()', &g:formatexpr)
+ call assert_equal('', &formatexpr)
+ new
+ call assert_equal(expand('<SID>') .. 'Format()', &formatexpr)
+ call setline(1, range(1, 40))
+ let g:FormatArgs = []
+ normal! 16GVjgq
+ call assert_equal([16, 2], g:FormatArgs)
+ bw!
+ set formatexpr=
delfunc s:Format
bw!
endfunc
diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim
index 11c2977a4e..f51de94bac 100644
--- a/src/nvim/testdir/test_options.vim
+++ b/src/nvim/testdir/test_options.vim
@@ -1238,6 +1238,30 @@ func Test_opt_cdhome()
set cdhome&
endfunc
+func Test_set_completion_2()
+ CheckOption termguicolors
+
+ " Test default option completion
+ set wildoptions=
+ call feedkeys(":set termg\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"set termguicolors', @:)
+
+ call feedkeys(":set notermg\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"set notermguicolors', @:)
+
+ " Test fuzzy option completion
+ set wildoptions=fuzzy
+ call feedkeys(":set termg\<C-A>\<C-B>\"\<CR>", 'tx')
+ " Nvim doesn't have 'termencoding'
+ " call assert_equal('"set termguicolors termencoding', @:)
+ call assert_equal('"set termguicolors', @:)
+
+ call feedkeys(":set notermg\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"set notermguicolors', @:)
+
+ set wildoptions=
+endfunc
+
func Test_switchbuf_reset()
set switchbuf=useopen
sblast
diff --git a/src/nvim/testdir/test_packadd.vim b/src/nvim/testdir/test_packadd.vim
index fcb8b8033b..3121b3b4d1 100644
--- a/src/nvim/testdir/test_packadd.vim
+++ b/src/nvim/testdir/test_packadd.vim
@@ -26,7 +26,7 @@ func Test_packadd()
let rtp_entries = split(rtp, ',')
for entry in rtp_entries
- if entry =~? '\<after\>'
+ if entry =~? '\<after\>'
let first_after_entry = entry
break
endif
@@ -186,15 +186,17 @@ func Test_packadd_symlink_dir2()
exec "silent !rmdir" top2_dir
endfunc
-" Check command-line completion for 'packadd'
+" Check command-line completion for :packadd
func Test_packadd_completion()
let optdir1 = &packpath . '/pack/mine/opt'
let optdir2 = &packpath . '/pack/candidate/opt'
call mkdir(optdir1 . '/pluginA', 'p')
call mkdir(optdir1 . '/pluginC', 'p')
+ call writefile([], optdir1 . '/unrelated')
call mkdir(optdir2 . '/pluginB', 'p')
call mkdir(optdir2 . '/pluginC', 'p')
+ call writefile([], optdir2 . '/unrelated')
let li = []
call feedkeys(":packadd \<Tab>')\<C-B>call add(li, '\<CR>", 't')
@@ -260,9 +262,9 @@ func Test_helptags()
helptags ALL
- let tags1 = readfile(docdir1 . '/tags')
+ let tags1 = readfile(docdir1 . '/tags')
call assert_match('look-here', tags1[0])
- let tags2 = readfile(docdir2 . '/tags')
+ let tags2 = readfile(docdir2 . '/tags')
call assert_match('look-away', tags2[0])
call assert_fails('helptags abcxyz', 'E150:')
@@ -358,4 +360,78 @@ func Test_runtime()
call assert_equal('runstartopt', g:sequence)
endfunc
+func Test_runtime_completion()
+ let rundir = &packpath . '/runtime/Aextra'
+ let startdir = &packpath . '/pack/mine/start/foo/Aextra'
+ let optdir = &packpath . '/pack/mine/opt/bar/Aextra'
+ call mkdir(rundir . '/Arunbaz', 'p')
+ call mkdir(startdir . '/Astartbaz', 'p')
+ call mkdir(optdir . '/Aoptbaz', 'p')
+ call writefile([], rundir . '/../Arunfoo.vim')
+ call writefile([], rundir . '/Arunbar.vim')
+ call writefile([], rundir . '/Aunrelated')
+ call writefile([], rundir . '/../Aunrelated')
+ call writefile([], startdir . '/../Astartfoo.vim')
+ call writefile([], startdir . '/Astartbar.vim')
+ call writefile([], startdir . '/Aunrelated')
+ call writefile([], startdir . '/../Aunrelated')
+ call writefile([], optdir . '/../Aoptfoo.vim')
+ call writefile([], optdir . '/Aoptbar.vim')
+ call writefile([], optdir . '/Aunrelated')
+ call writefile([], optdir . '/../Aunrelated')
+ exe 'set rtp=' . &packpath . '/runtime'
+
+ func Check_runtime_completion(arg, arg1, res)
+ call feedkeys(':runtime ' .. a:arg .. "\<C-A>\<C-B>\"\<CR>", 'xt')
+ call assert_equal('"runtime ' .. a:arg1 .. join(a:res), @:)
+ call assert_equal(a:res, getcompletion(a:arg, 'runtime'))
+ endfunc
+
+ call Check_runtime_completion('', '',
+ \ ['Aextra/', 'Arunfoo.vim', 'START', 'OPT', 'PACK', 'ALL'])
+ call Check_runtime_completion('S', '',
+ \ ['START'])
+ call Check_runtime_completion('O', '',
+ \ ['OPT'])
+ call Check_runtime_completion('P', '',
+ \ ['PACK'])
+ call Check_runtime_completion('A', '',
+ \ ['Aextra/', 'Arunfoo.vim', 'ALL'])
+ call Check_runtime_completion('Aextra/', '',
+ \ ['Aextra/Arunbar.vim', 'Aextra/Arunbaz/'])
+
+ call Check_runtime_completion('START ', 'START ',
+ \ ['Aextra/', 'Astartfoo.vim'])
+ call Check_runtime_completion('START A', 'START ',
+ \ ['Aextra/', 'Astartfoo.vim'])
+ call Check_runtime_completion('START Aextra/', 'START ',
+ \ ['Aextra/Astartbar.vim', 'Aextra/Astartbaz/'])
+
+ call Check_runtime_completion('OPT ', 'OPT ',
+ \ ['Aextra/', 'Aoptfoo.vim'])
+ call Check_runtime_completion('OPT A', 'OPT ',
+ \ ['Aextra/', 'Aoptfoo.vim'])
+ call Check_runtime_completion('OPT Aextra/', 'OPT ',
+ \ ['Aextra/Aoptbar.vim', 'Aextra/Aoptbaz/'])
+
+ call Check_runtime_completion('PACK ', 'PACK ',
+ \ ['Aextra/', 'Aoptfoo.vim', 'Astartfoo.vim'])
+ call Check_runtime_completion('PACK A', 'PACK ',
+ \ ['Aextra/', 'Aoptfoo.vim', 'Astartfoo.vim'])
+ call Check_runtime_completion('PACK Aextra/', 'PACK ',
+ \ ['Aextra/Aoptbar.vim', 'Aextra/Aoptbaz/',
+ \ 'Aextra/Astartbar.vim', 'Aextra/Astartbaz/'])
+
+ call Check_runtime_completion('ALL ', 'ALL ',
+ \ ['Aextra/', 'Aoptfoo.vim', 'Arunfoo.vim', 'Astartfoo.vim'])
+ call Check_runtime_completion('ALL A', 'ALL ',
+ \ ['Aextra/', 'Aoptfoo.vim', 'Arunfoo.vim', 'Astartfoo.vim'])
+ call Check_runtime_completion('ALL Aextra/', 'ALL ',
+ \ ['Aextra/Aoptbar.vim', 'Aextra/Aoptbaz/',
+ \ 'Aextra/Arunbar.vim', 'Aextra/Arunbaz/',
+ \ 'Aextra/Astartbar.vim', 'Aextra/Astartbaz/'])
+
+ delfunc Check_runtime_completion
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_profile.vim b/src/nvim/testdir/test_profile.vim
index 4225b91bc4..9165f7bace 100644
--- a/src/nvim/testdir/test_profile.vim
+++ b/src/nvim/testdir/test_profile.vim
@@ -403,6 +403,47 @@ func Test_profile_completion()
call feedkeys(":profile start test_prof\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_match('^"profile start.* test_profile\.vim', @:)
+
+ call feedkeys(":profile file test_prof\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_match('"profile file test_profile\.vim', @:)
+ call feedkeys(":profile file test_prof\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_match('"profile file test_profile\.vim', @:)
+ call feedkeys(":profile file test_prof \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_match('"profile file test_prof ', @:)
+ call feedkeys(":profile file X1B2C3\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_match('"profile file X1B2C3', @:)
+
+ func Xprof_test()
+ endfunc
+ call feedkeys(":profile func Xprof\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"profile func Xprof_test', @:)
+ call feedkeys(":profile func Xprof\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"profile func Xprof_test', @:)
+ call feedkeys(":profile func Xprof \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"profile func Xprof ', @:)
+ call feedkeys(":profile func X1B2C3\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"profile func X1B2C3', @:)
+
+ call feedkeys(":profdel \<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"profdel file func', @:)
+ call feedkeys(":profdel fu\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"profdel func', @:)
+ call feedkeys(":profdel he\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"profdel he', @:)
+ call feedkeys(":profdel here \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"profdel here ', @:)
+ call feedkeys(":profdel file test_prof\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"profdel file test_profile.vim', @:)
+ call feedkeys(":profdel file X1B2C3\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"profdel file X1B2C3', @:)
+ call feedkeys(":profdel func Xprof\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"profdel func Xprof_test', @:)
+ call feedkeys(":profdel func Xprof_test \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"profdel func Xprof_test ', @:)
+ call feedkeys(":profdel func X1B2C3\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"profdel func X1B2C3', @:)
+
+ delfunc Xprof_test
endfunc
func Test_profile_errors()
diff --git a/src/nvim/testdir/test_search.vim b/src/nvim/testdir/test_search.vim
index a9cad3ed44..885043accf 100644
--- a/src/nvim/testdir/test_search.vim
+++ b/src/nvim/testdir/test_search.vim
@@ -1377,6 +1377,22 @@ func Test_subst_word_under_cursor()
set noincsearch
endfunc
+func Test_search_skip_all_matches()
+ enew
+ call setline(1, ['no match here',
+ \ 'match this line',
+ \ 'nope',
+ \ 'match in this line',
+ \ 'last line',
+ \ ])
+ call cursor(1, 1)
+ let lnum = search('this', '', 0, 0, 'getline(".") =~ "this line"')
+ " Only check that no match is found. Previously it searched forever.
+ call assert_equal(0, lnum)
+
+ bwipe!
+endfunc
+
func Test_search_undefined_behaviour()
CheckFeature terminal
diff --git a/src/nvim/testdir/test_search_stat.vim b/src/nvim/testdir/test_search_stat.vim
index 77bd50ada2..1b2d854829 100644
--- a/src/nvim/testdir/test_search_stat.vim
+++ b/src/nvim/testdir/test_search_stat.vim
@@ -270,6 +270,29 @@ func Test_searchcount_fails()
call assert_fails('echo searchcount({"pos" : [1, 2, []]})', 'E745:')
endfunc
+func Test_search_stat_narrow_screen()
+ " This used to crash Vim
+ let save_columns = &columns
+ try
+ let after =<< trim [CODE]
+ set laststatus=2
+ set columns=16
+ set shortmess-=S showcmd
+ call setline(1, 'abc')
+ call feedkeys("/abc\<CR>:quit!\<CR>")
+ autocmd VimLeavePre * call writefile(["done"], "Xdone")
+ [CODE]
+
+ if !RunVim([], after, '--clean')
+ return
+ endif
+ call assert_equal("done", readfile("Xdone")[0])
+ call delete('Xdone')
+ finally
+ let &columns = save_columns
+ endtry
+endfunc
+
func Test_searchcount_in_statusline()
CheckScreendump
diff --git a/src/nvim/testdir/test_shell.vim b/src/nvim/testdir/test_shell.vim
new file mode 100644
index 0000000000..8b9c7a5b12
--- /dev/null
+++ b/src/nvim/testdir/test_shell.vim
@@ -0,0 +1,209 @@
+" Test for the shell related options ('shell', 'shellcmdflag', 'shellpipe',
+" 'shellquote', 'shellredir', 'shellxescape', and 'shellxquote')
+
+source check.vim
+source shared.vim
+
+func Test_shell_options()
+ " The expected value of 'shellcmdflag', 'shellpipe', 'shellquote',
+ " 'shellredir', 'shellxescape', 'shellxquote' for the supported shells.
+ let shells = []
+ if has('unix')
+ let shells += [['sh', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''],
+ \ ['ksh', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''],
+ \ ['mksh', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''],
+ \ ['zsh', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''],
+ \ ['zsh-beta', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''],
+ \ ['bash', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''],
+ \ ['fish', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''],
+ \ ['ash', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''],
+ \ ['dash', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''],
+ \ ['csh', '-c', '|& tee', '', '>&', '', ''],
+ \ ['tcsh', '-c', '|& tee', '', '>&', '', '']]
+ endif
+ if has('win32')
+ let shells += [['cmd', '/s /c', '>%s 2>&1', '', '>%s 2>&1', '', '"']]
+ endif
+
+ " start a new Vim instance with 'shell' set to each of the supported shells
+ " and check the default shell option settings
+ let after =<< trim END
+ let l = [&shell, &shellcmdflag, &shellpipe, &shellquote]
+ let l += [&shellredir, &shellxescape, &shellxquote]
+ call writefile([json_encode(l)], 'Xtestout')
+ qall!
+ END
+ for e in shells
+ if RunVim([], after, '--cmd "set shell=' .. e[0] .. '"')
+ call assert_equal(e, json_decode(readfile('Xtestout')[0]))
+ endif
+ endfor
+
+ " Test shellescape() for each of the shells.
+ for e in shells
+ exe 'set shell=' .. e[0]
+ if e[0] =~# '.*csh$' || e[0] =~# '.*csh.exe$'
+ let str1 = "'cmd \"arg1\" '\\''arg2'\\'' \\!%#'"
+ let str2 = "'cmd \"arg1\" '\\''arg2'\\'' \\\\!\\%\\#'"
+ elseif e[0] =~# '.*powershell$' || e[0] =~# '.*powershell.exe$'
+ let str1 = "'cmd \"arg1\" ''arg2'' !%#'"
+ let str2 = "'cmd \"arg1\" ''arg2'' \\!\\%\\#'"
+ else
+ let str1 = "'cmd \"arg1\" '\\''arg2'\\'' !%#'"
+ let str2 = "'cmd \"arg1\" '\\''arg2'\\'' \\!\\%\\#'"
+ endif
+ call assert_equal(str1, shellescape("cmd \"arg1\" 'arg2' !%#"), e[0])
+ call assert_equal(str2, shellescape("cmd \"arg1\" 'arg2' !%#", 1), e[0])
+
+ " Try running an external command with the shell.
+ if executable(e[0])
+ " set the shell options for the current 'shell'
+ let [&shellcmdflag, &shellpipe, &shellquote, &shellredir,
+ \ &shellxescape, &shellxquote] = e[1:6]
+ new
+ r !echo hello
+ call assert_equal('hello', substitute(getline(2), '\W', '', 'g'), e[0])
+ bwipe!
+ endif
+ endfor
+ set shell& shellcmdflag& shellpipe& shellquote&
+ set shellredir& shellxescape& shellxquote&
+ call delete('Xtestout')
+endfunc
+
+" Test for the 'shell' option
+func Test_shell()
+ throw 'Skipped: Nvim missing :shell currently'
+ CheckUnix
+ let save_shell = &shell
+ set shell=
+ let caught_e91 = 0
+ try
+ shell
+ catch /E91:/
+ let caught_e91 = 1
+ endtry
+ call assert_equal(1, caught_e91)
+ let &shell = save_shell
+endfunc
+
+" Test for the 'shellquote' option
+func Test_shellquote()
+ CheckUnix
+ set shellquote=#
+ set verbose=20
+ redir => v
+ silent! !echo Hello
+ redir END
+ set verbose&
+ set shellquote&
+ call assert_match(': "#echo Hello#"', v)
+endfunc
+
+" Test for the 'shellescape' option
+func Test_shellescape()
+ let save_shell = &shell
+ set shell=bash
+ call assert_equal("'text'", shellescape('text'))
+ call assert_equal("'te\"xt'", 'te"xt'->shellescape())
+ call assert_equal("'te'\\''xt'", shellescape("te'xt"))
+
+ call assert_equal("'te%xt'", shellescape("te%xt"))
+ call assert_equal("'te\\%xt'", shellescape("te%xt", 1))
+ call assert_equal("'te#xt'", shellescape("te#xt"))
+ call assert_equal("'te\\#xt'", shellescape("te#xt", 1))
+ call assert_equal("'te!xt'", shellescape("te!xt"))
+ call assert_equal("'te\\!xt'", shellescape("te!xt", 1))
+
+ call assert_equal("'te\nxt'", shellescape("te\nxt"))
+ call assert_equal("'te\\\nxt'", shellescape("te\nxt", 1))
+ set shell=tcsh
+ call assert_equal("'te\\!xt'", shellescape("te!xt"))
+ call assert_equal("'te\\\\!xt'", shellescape("te!xt", 1))
+ call assert_equal("'te\\\nxt'", shellescape("te\nxt"))
+ call assert_equal("'te\\\\\nxt'", shellescape("te\nxt", 1))
+
+ let &shell = save_shell
+endfunc
+
+" Test for 'shellslash'
+func Test_shellslash()
+ CheckOption shellslash
+ let save_shellslash = &shellslash
+ " The shell and cmdflag, and expected slash in tempname with shellslash set or
+ " unset. The assert checks the file separator before the leafname.
+ " ".*\\\\[^\\\\]*$"
+ let shells = [['cmd', '/c', '/', '/'],
+ \ ['powershell', '-Command', '/', '/'],
+ \ ['sh', '-c', '/', '/']]
+ for e in shells
+ exe 'set shell=' .. e[0] .. ' | set shellcmdflag=' .. e[1]
+ set noshellslash
+ let file = tempname()
+ call assert_match('^.\+' .. e[2] .. '[^' .. e[2] .. ']\+$', file, e[0] .. ' ' .. e[1] .. ' nossl')
+ set shellslash
+ let file = tempname()
+ call assert_match('^.\+' .. e[3] .. '[^' .. e[3] .. ']\+$', file, e[0] .. ' ' .. e[1] .. ' ssl')
+ endfor
+ let &shellslash = save_shellslash
+endfunc
+
+" Test for 'shellxquote'
+func Test_shellxquote()
+ CheckUnix
+
+ let save_shell = &shell
+ let save_sxq = &shellxquote
+ let save_sxe = &shellxescape
+
+ call writefile(['#!/bin/sh', 'echo "Cmd: [$*]" > Xlog'], 'Xtestshell')
+ call setfperm('Xtestshell', "r-x------")
+ set shell=./Xtestshell
+
+ set shellxquote=\\"
+ call feedkeys(":!pwd\<CR>\<CR>", 'xt')
+ call assert_equal(['Cmd: [-c "pwd"]'], readfile('Xlog'))
+
+ set shellxquote=(
+ call feedkeys(":!pwd\<CR>\<CR>", 'xt')
+ call assert_equal(['Cmd: [-c (pwd)]'], readfile('Xlog'))
+
+ set shellxquote=\\"(
+ call feedkeys(":!pwd\<CR>\<CR>", 'xt')
+ call assert_equal(['Cmd: [-c "(pwd)"]'], readfile('Xlog'))
+
+ set shellxescape=\"&<<()@^
+ set shellxquote=(
+ call feedkeys(":!pwd\"&<<{}@^\<CR>\<CR>", 'xt')
+ call assert_equal(['Cmd: [-c (pwd^"^&^<^<{}^@^^)]'], readfile('Xlog'))
+
+ let &shell = save_shell
+ let &shellxquote = save_sxq
+ let &shellxescape = save_sxe
+ call delete('Xtestshell')
+ call delete('Xlog')
+endfunc
+
+" Test for using the shell set in the $SHELL environment variable
+func Test_set_shell()
+ let after =<< trim [CODE]
+ call writefile([&shell], "Xtestout")
+ quit!
+ [CODE]
+
+ if has('win32')
+ let $SHELL = 'C:\with space\cmd.exe'
+ let expected = '"C:\with space\cmd.exe"'
+ else
+ let $SHELL = '/bin/with space/sh'
+ let expected = '"/bin/with space/sh"'
+ endif
+
+ if RunVimPiped([], after, '', '')
+ let lines = readfile('Xtestout')
+ call assert_equal(expected, lines[0])
+ endif
+ call delete('Xtestout')
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_spell.vim b/src/nvim/testdir/test_spell.vim
index a919156066..c840e834b9 100644
--- a/src/nvim/testdir/test_spell.vim
+++ b/src/nvim/testdir/test_spell.vim
@@ -531,8 +531,23 @@ func Test_spellsuggest_timeout()
call assert_fails('set spellsuggest=timeout:--9', 'E474:')
endfunc
+func Test_spellsuggest_visual_end_of_line()
+ let enc_save = &encoding
+ " set encoding=iso8859
+
+ " This was reading beyond the end of the line.
+ norm R00000000000
+ sil norm 0
+ sil! norm i00000)
+ sil! norm i00000)
+ call feedkeys("\<CR>")
+ norm z=
+
+ let &encoding = enc_save
+endfunc
+
func Test_spellinfo()
- throw 'skipped: Nvim does not support enc=latin1'
+ throw 'Skipped: Nvim does not support enc=latin1'
new
let runtime = substitute($VIMRUNTIME, '\\', '/', 'g')
diff --git a/src/nvim/testdir/test_startup.vim b/src/nvim/testdir/test_startup.vim
index 54b7636f69..1ee1d0dfe3 100644
--- a/src/nvim/testdir/test_startup.vim
+++ b/src/nvim/testdir/test_startup.vim
@@ -725,27 +725,6 @@ func Test_read_stdin()
call delete('Xtestout')
endfunc
-func Test_set_shell()
- let after =<< trim [CODE]
- call writefile([&shell], "Xtestout")
- quit!
- [CODE]
-
- if has('win32')
- let $SHELL = 'C:\with space\cmd.exe'
- let expected = '"C:\with space\cmd.exe"'
- else
- let $SHELL = '/bin/with space/sh'
- let expected = '"/bin/with space/sh"'
- endif
-
- if RunVimPiped([], after, '', '')
- let lines = readfile('Xtestout')
- call assert_equal(expected, lines[0])
- endif
- call delete('Xtestout')
-endfunc
-
func Test_progpath()
" Tests normally run with "./vim" or "../vim", these must have been expanded
" to a full path.
@@ -1064,7 +1043,7 @@ func Test_io_not_a_terminal()
\ 'Vim: Warning: Input is not from a terminal'], l)
endfunc
-" Test for --not-a-term avoiding escape codes.
+" Test for not being a term avoiding escape codes.
func Test_not_a_term()
CheckUnix
CheckNotGui
@@ -1075,18 +1054,14 @@ func Test_not_a_term()
let redir = &shellredir .. ' Xvimout'
endif
- " Without --not-a-term there are a few escape sequences.
- " This will take 2 seconds because of the missing --not-a-term
+ " As nvim checks the environment by itself there will be no escape sequences
+ " This will also happen to take two (2) seconds.
let cmd = GetVimProg() .. ' --cmd quit ' .. redir
exe "silent !" . cmd
- call assert_match("\<Esc>", readfile('Xvimout')->join())
+ call assert_notmatch("\e", readfile('Xvimout')->join())
call delete('Xvimout')
- " With --not-a-term there are no escape sequences.
- let cmd = GetVimProg() .. ' --not-a-term --cmd quit ' .. redir
- exe "silent !" . cmd
- call assert_notmatch("\<Esc>", readfile('Xvimout')->join())
- call delete('Xvimout')
+ " --not-a-term flag has thus been deleted
endfunc
diff --git a/src/nvim/testdir/test_substitute.vim b/src/nvim/testdir/test_substitute.vim
index 5fd30c7da7..c99a0d456d 100644
--- a/src/nvim/testdir/test_substitute.vim
+++ b/src/nvim/testdir/test_substitute.vim
@@ -1076,6 +1076,19 @@ func Test_sub_open_cmdline_win()
call delete('Xresult')
endfunc
+" This was editing a script file from the expression
+func Test_sub_edit_scriptfile()
+ new
+ norm o0000000000000000000000000000000000000000000000000000
+ func EditScript()
+ silent! scr! Xfile
+ endfunc
+ s/\%')/\=EditScript()
+
+ delfunc EditScript
+ bwipe!
+endfunc
+
" Test for the 2-letter and 3-letter :substitute commands
func Test_substitute_short_cmd()
new
diff --git a/src/nvim/testdir/test_system.vim b/src/nvim/testdir/test_system.vim
index bfa8a277bd..6c8373b335 100644
--- a/src/nvim/testdir/test_system.vim
+++ b/src/nvim/testdir/test_system.vim
@@ -142,40 +142,4 @@ func Test_system_with_shell_quote()
endtry
endfunc
-" Test for 'shellxquote'
-func Test_Shellxquote()
- CheckUnix
-
- let save_shell = &shell
- let save_sxq = &shellxquote
- let save_sxe = &shellxescape
-
- call writefile(['#!/bin/sh', 'echo "Cmd: [$*]" > Xlog'], 'Xtestshell')
- call setfperm('Xtestshell', "r-x------")
- set shell=./Xtestshell
-
- set shellxquote=\\"
- call feedkeys(":!pwd\<CR>\<CR>", 'xt')
- call assert_equal(['Cmd: [-c "pwd"]'], readfile('Xlog'))
-
- set shellxquote=(
- call feedkeys(":!pwd\<CR>\<CR>", 'xt')
- call assert_equal(['Cmd: [-c (pwd)]'], readfile('Xlog'))
-
- set shellxquote=\\"(
- call feedkeys(":!pwd\<CR>\<CR>", 'xt')
- call assert_equal(['Cmd: [-c "(pwd)"]'], readfile('Xlog'))
-
- set shellxescape=\"&<<()@^
- set shellxquote=(
- call feedkeys(":!pwd\"&<<{}@^\<CR>\<CR>", 'xt')
- call assert_equal(['Cmd: [-c (pwd^"^&^<^<{}^@^^)]'], readfile('Xlog'))
-
- let &shell = save_shell
- let &shellxquote = save_sxq
- let &shellxescape = save_sxe
- call delete('Xtestshell')
- call delete('Xlog')
-endfunc
-
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_taglist.vim b/src/nvim/testdir/test_taglist.vim
index 0387ef2bd8..75d28c3ec4 100644
--- a/src/nvim/testdir/test_taglist.vim
+++ b/src/nvim/testdir/test_taglist.vim
@@ -105,8 +105,8 @@ func Test_tagfiles()
help
let tf = tagfiles()
" Nvim: expectation(s) based on tags in build dir (added to &rtp).
- " Filter out the (non-existing) '../../../runtime/doc/tags'.
- call filter(tf, 'filereadable(v:val)')
+ " Filter out the '../../../runtime/doc/tags'.
+ call filter(tf, 'v:val != "../../../runtime/doc/tags"')
call assert_equal(1, len(tf))
call assert_equal(fnamemodify(expand('$BUILD_DIR/runtime/doc/tags'), ':p:gs?\\?/?'),
\ fnamemodify(tf[0], ':p:gs?\\?/?'))
diff --git a/src/nvim/testdir/test_utf8.vim b/src/nvim/testdir/test_utf8.vim
index 9146cf7ab3..e5f6d68720 100644
--- a/src/nvim/testdir/test_utf8.vim
+++ b/src/nvim/testdir/test_utf8.vim
@@ -167,6 +167,39 @@ func Test_setcellwidths()
call assert_equal(2, strwidth("\u1339"))
call assert_equal(1, strwidth("\u133a"))
+ for aw in ['single', 'double']
+ exe 'set ambiwidth=' . aw
+ " Handle \u0080 to \u009F as control chars even on MS-Windows.
+ set isprint=@,161-255
+
+ call setcellwidths([])
+ " Control chars
+ call assert_equal(4, strwidth("\u0081"))
+ call assert_equal(6, strwidth("\uFEFF"))
+ " Ambiguous width chars
+ call assert_equal((aw == 'single') ? 1 : 2, strwidth("\u00A1"))
+ call assert_equal((aw == 'single') ? 1 : 2, strwidth("\u2010"))
+
+ call setcellwidths([[0x81, 0x81, 1], [0xA1, 0xA1, 1],
+ \ [0x2010, 0x2010, 1], [0xFEFF, 0xFEFF, 1]])
+ " Control chars
+ call assert_equal(4, strwidth("\u0081"))
+ call assert_equal(6, strwidth("\uFEFF"))
+ " Ambiguous width chars
+ call assert_equal(1, strwidth("\u00A1"))
+ call assert_equal(1, strwidth("\u2010"))
+
+ call setcellwidths([[0x81, 0x81, 2], [0xA1, 0xA1, 2],
+ \ [0x2010, 0x2010, 2], [0xFEFF, 0xFEFF, 2]])
+ " Control chars
+ call assert_equal(4, strwidth("\u0081"))
+ call assert_equal(6, strwidth("\uFEFF"))
+ " Ambiguous width chars
+ call assert_equal(2, strwidth("\u00A1"))
+ call assert_equal(2, strwidth("\u2010"))
+ endfor
+ set ambiwidth& isprint&
+
call setcellwidths([])
call assert_fails('call setcellwidths(1)', 'E714:')
@@ -199,6 +232,26 @@ func Test_setcellwidths()
call setcellwidths([])
endfunc
+func Test_getcellwidths()
+ call setcellwidths([])
+ call assert_equal([], getcellwidths())
+
+ let widthlist = [
+ \ [0x1330, 0x1330, 2],
+ \ [9999, 10000, 1],
+ \ [0x1337, 0x1339, 2],
+ \]
+ let widthlistsorted = [
+ \ [0x1330, 0x1330, 2],
+ \ [0x1337, 0x1339, 2],
+ \ [9999, 10000, 1],
+ \]
+ call setcellwidths(widthlist)
+ call assert_equal(widthlistsorted, getcellwidths())
+
+ call setcellwidths([])
+endfunc
+
func Test_setcellwidths_dump()
CheckRunVimInTerminal
diff --git a/src/nvim/testdir/test_virtualedit.vim b/src/nvim/testdir/test_virtualedit.vim
index 2bf8c3fc77..20a5f87517 100644
--- a/src/nvim/testdir/test_virtualedit.vim
+++ b/src/nvim/testdir/test_virtualedit.vim
@@ -537,6 +537,19 @@ func Test_global_local_virtualedit()
set virtualedit&
endfunc
+func Test_virtualedit_setlocal()
+ enew
+ setglobal virtualedit=all
+ setlocal virtualedit=all
+ normal! l
+ redraw
+ setlocal virtualedit=none
+ call assert_equal(1, wincol())
+
+ setlocal virtualedit&
+ set virtualedit&
+endfunc
+
func Test_virtualedit_mouse()
let save_mouse = &mouse
set mouse=a
diff --git a/src/nvim/testdir/test_visual.vim b/src/nvim/testdir/test_visual.vim
index 14d62089cf..1e9629c2c4 100644
--- a/src/nvim/testdir/test_visual.vim
+++ b/src/nvim/testdir/test_visual.vim
@@ -1319,6 +1319,17 @@ func Test_visual_block_with_substitute()
endfunc
func Test_visual_reselect_with_count()
+ enew
+ call setline(1, ['aaaaaa', '✗ bbbb', '✗ bbbb'])
+ exe "normal! 2Gw\<C-V>jed"
+ exe "normal! gg0lP"
+ call assert_equal(['abbbbaaaaa', '✗bbbb ', '✗ '], getline(1, '$'))
+
+ exe "normal! 1vr."
+ call assert_equal(['a....aaaaa', '✗.... ', '✗ '], getline(1, '$'))
+
+ bwipe!
+
" this was causing an illegal memory access
let lines =<< trim END
diff --git a/src/nvim/testdir/test_writefile.vim b/src/nvim/testdir/test_writefile.vim
index 6d27407f82..6019cee193 100644
--- a/src/nvim/testdir/test_writefile.vim
+++ b/src/nvim/testdir/test_writefile.vim
@@ -896,6 +896,9 @@ endfunc
" link to the original file. The backup file should not be modified.
func Test_write_backup_symlink()
CheckUnix
+ call mkdir('Xbackup')
+ let save_backupdir = &backupdir
+ set backupdir=.,./Xbackup
call writefile(['1111'], 'Xfile')
silent !ln -s Xfile Xfile.bak
@@ -904,11 +907,18 @@ func Test_write_backup_symlink()
write
call assert_equal('link', getftype('Xfile.bak'))
call assert_equal('Xfile', resolve('Xfile.bak'))
+ " backup file should be created in the 'backup' directory
+ if !has('bsd')
+ " This check fails on FreeBSD
+ call assert_true(filereadable('./Xbackup/Xfile.bak'))
+ endif
set backup& backupcopy& backupext&
- close
+ %bw
call delete('Xfile')
call delete('Xfile.bak')
+ call delete('Xbackup', 'rf')
+ let &backupdir = save_backupdir
endfunc
" Test for ':write ++bin' and ':write ++nobin'
diff --git a/src/nvim/testing.c b/src/nvim/testing.c
index edb24c6dc5..b5921b3445 100644
--- a/src/nvim/testing.c
+++ b/src/nvim/testing.c
@@ -68,61 +68,62 @@ static void prepare_assert_error(garray_T *gap)
/// Append "p[clen]" to "gap", escaping unprintable characters.
/// Changes NL to \n, CR to \r, etc.
-static void ga_concat_esc(garray_T *gap, const char_u *p, int clen)
+static void ga_concat_esc(garray_T *gap, const char *p, int clen)
FUNC_ATTR_NONNULL_ALL
{
- char_u buf[NUMBUFLEN];
+ char buf[NUMBUFLEN];
if (clen > 1) {
memmove(buf, p, (size_t)clen);
buf[clen] = NUL;
- ga_concat(gap, (char *)buf);
- } else {
- switch (*p) {
- case BS:
- ga_concat(gap, "\\b"); break;
- case ESC:
- ga_concat(gap, "\\e"); break;
- case FF:
- ga_concat(gap, "\\f"); break;
- case NL:
- ga_concat(gap, "\\n"); break;
- case TAB:
- ga_concat(gap, "\\t"); break;
- case CAR:
- ga_concat(gap, "\\r"); break;
- case '\\':
- ga_concat(gap, "\\\\"); break;
- default:
- if (*p < ' ' || *p == 0x7f) {
- vim_snprintf((char *)buf, NUMBUFLEN, "\\x%02x", *p);
- ga_concat(gap, (char *)buf);
- } else {
- ga_append(gap, (char)(*p));
- }
- break;
+ ga_concat(gap, buf);
+ return;
+ }
+
+ switch (*p) {
+ case BS:
+ ga_concat(gap, "\\b"); break;
+ case ESC:
+ ga_concat(gap, "\\e"); break;
+ case FF:
+ ga_concat(gap, "\\f"); break;
+ case NL:
+ ga_concat(gap, "\\n"); break;
+ case TAB:
+ ga_concat(gap, "\\t"); break;
+ case CAR:
+ ga_concat(gap, "\\r"); break;
+ case '\\':
+ ga_concat(gap, "\\\\"); break;
+ default:
+ if ((uint8_t)(*p) < ' ' || *p == 0x7f) {
+ vim_snprintf(buf, NUMBUFLEN, "\\x%02x", *p);
+ ga_concat(gap, buf);
+ } else {
+ ga_append(gap, (uint8_t)(*p));
}
+ break;
}
}
/// Append "str" to "gap", escaping unprintable characters.
/// Changes NL to \n, CR to \r, etc.
-static void ga_concat_shorten_esc(garray_T *gap, const char_u *str)
+static void ga_concat_shorten_esc(garray_T *gap, const char *str)
FUNC_ATTR_NONNULL_ARG(1)
{
- char_u buf[NUMBUFLEN];
+ char buf[NUMBUFLEN];
if (str == NULL) {
ga_concat(gap, "NULL");
return;
}
- for (const char_u *p = str; *p != NUL; p++) {
+ for (const char *p = str; *p != NUL; p++) {
int same_len = 1;
- const char_u *s = p;
+ const char *s = p;
const int c = mb_ptr2char_adv(&s);
const int clen = (int)(s - p);
- while (*s != NUL && c == utf_ptr2char((char *)s)) {
+ while (*s != NUL && c == utf_ptr2char(s)) {
same_len++;
s += clen;
}
@@ -130,8 +131,8 @@ static void ga_concat_shorten_esc(garray_T *gap, const char_u *str)
ga_concat(gap, "\\[");
ga_concat_esc(gap, p, clen);
ga_concat(gap, " occurs ");
- vim_snprintf((char *)buf, NUMBUFLEN, "%d", same_len);
- ga_concat(gap, (char *)buf);
+ vim_snprintf(buf, NUMBUFLEN, "%d", same_len);
+ ga_concat(gap, buf);
ga_concat(gap, " times]");
p = s - 1;
} else {
@@ -141,10 +142,10 @@ static void ga_concat_shorten_esc(garray_T *gap, const char_u *str)
}
/// Fill "gap" with information about an assert error.
-static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, char_u *exp_str,
+static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, char *exp_str,
typval_T *exp_tv_arg, typval_T *got_tv_arg, assert_type_T atype)
{
- char_u *tofree;
+ char *tofree;
typval_T *exp_tv = exp_tv_arg;
typval_T *got_tv = got_tv_arg;
bool did_copy = false;
@@ -154,8 +155,8 @@ static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, char_u *exp_s
&& !(opt_msg_tv->v_type == VAR_STRING
&& (opt_msg_tv->vval.v_string == NULL
|| *opt_msg_tv->vval.v_string == NUL))) {
- tofree = (char_u *)encode_tv2echo(opt_msg_tv, NULL);
- ga_concat(gap, (char *)tofree);
+ tofree = encode_tv2echo(opt_msg_tv, NULL);
+ ga_concat(gap, tofree);
xfree(tofree);
ga_concat(gap, ": ");
}
@@ -218,7 +219,7 @@ static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, char_u *exp_s
}
}
- tofree = (char_u *)encode_tv2string(exp_tv, NULL);
+ tofree = encode_tv2string(exp_tv, NULL);
ga_concat_shorten_esc(gap, tofree);
xfree(tofree);
} else {
@@ -233,7 +234,7 @@ static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, char_u *exp_s
} else {
ga_concat(gap, " but got ");
}
- tofree = (char_u *)encode_tv2string(got_tv, NULL);
+ tofree = encode_tv2string(got_tv, NULL);
ga_concat_shorten_esc(gap, tofree);
xfree(tofree);
@@ -306,7 +307,7 @@ static int assert_bool(typval_T *argvars, bool is_true)
: kBoolVarFalse)))) {
prepare_assert_error(&ga);
fill_assert_error(&ga, &argvars[1],
- (char_u *)(is_true ? "True" : "False"),
+ is_true ? "True" : "False",
NULL, &argvars[0], ASSERT_OTHER);
assert_error(&ga);
ga_clear(&ga);
@@ -642,8 +643,8 @@ static int assert_inrange(typval_T *argvars)
garray_T ga;
prepare_assert_error(&ga);
if (argvars[3].v_type != VAR_UNKNOWN) {
- char_u *const tofree = (char_u *)encode_tv2string(&argvars[3], NULL);
- ga_concat(&ga, (char *)tofree);
+ char *const tofree = encode_tv2string(&argvars[3], NULL);
+ ga_concat(&ga, tofree);
xfree(tofree);
} else {
char msg[80];
@@ -671,7 +672,7 @@ static int assert_inrange(typval_T *argvars)
vim_snprintf(msg, sizeof(msg),
"range %" PRIdVARNUMBER " - %" PRIdVARNUMBER ",",
lower, upper); // -V576
- fill_assert_error(&ga, &argvars[3], (char_u *)msg, NULL, &argvars[2],
+ fill_assert_error(&ga, &argvars[3], msg, NULL, &argvars[2],
ASSERT_INRANGE);
assert_error(&ga);
ga_clear(&ga);
diff --git a/src/nvim/textformat.c b/src/nvim/textformat.c
index 4af629d091..e30580a748 100644
--- a/src/nvim/textformat.c
+++ b/src/nvim/textformat.c
@@ -127,13 +127,13 @@ void internal_format(int textwidth, int second_indent, int flags, bool format_on
// Don't break until after the comment leader
if (do_comments) {
- char_u *line = (char_u *)get_cursor_line_ptr();
- leader_len = get_leader_len((char *)line, NULL, false, true);
+ char *line = get_cursor_line_ptr();
+ leader_len = get_leader_len(line, NULL, false, true);
if (leader_len == 0 && curbuf->b_p_cin) {
// Check for a line comment after code.
- int comment_start = check_linecomment((char *)line);
+ int comment_start = check_linecomment(line);
if (comment_start != MAXCOL) {
- leader_len = get_leader_len((char *)line + comment_start, NULL, false, true);
+ leader_len = get_leader_len(line + comment_start, NULL, false, true);
if (leader_len != 0) {
leader_len += comment_start;
}
@@ -477,25 +477,25 @@ void internal_format(int textwidth, int second_indent, int flags, bool format_on
/// comment leader changes.
static int fmt_check_par(linenr_T lnum, int *leader_len, char **leader_flags, bool do_comments)
{
- char_u *flags = NULL; // init for GCC
- char_u *ptr;
+ char *flags = NULL; // init for GCC
+ char *ptr;
- ptr = (char_u *)ml_get(lnum);
+ ptr = ml_get(lnum);
if (do_comments) {
- *leader_len = get_leader_len((char *)ptr, leader_flags, false, true);
+ *leader_len = get_leader_len(ptr, leader_flags, false, true);
} else {
*leader_len = 0;
}
if (*leader_len > 0) {
// Search for 'e' flag in comment leader flags.
- flags = (char_u *)(*leader_flags);
+ flags = *leader_flags;
while (*flags && *flags != ':' && *flags != COM_END) {
flags++;
}
}
- return *skipwhite((char *)ptr + *leader_len) == NUL
+ return *skipwhite(ptr + *leader_len) == NUL
|| (*leader_len > 0 && *flags == COM_END)
|| startPS(lnum, NUL, false);
}
@@ -544,7 +544,8 @@ static bool same_leader(linenr_T lnum, int leader1_len, char *leader1_flags, int
return false;
}
if (*p == COM_START) {
- if (*(ml_get(lnum) + leader1_len) == NUL) {
+ int line_len = (int)strlen(ml_get(lnum));
+ if (line_len <= leader1_len) {
return false;
}
if (leader2_flags == NULL || leader2_len == 0) {
@@ -587,7 +588,7 @@ static bool same_leader(linenr_T lnum, int leader1_len, char *leader1_flags, int
/// false when the previous line is in the same paragraph.
static bool paragraph_start(linenr_T lnum)
{
- char_u *p;
+ char *p;
int leader_len = 0; // leader len of current line
char *leader_flags = NULL; // flags for leader of current line
int next_leader_len = 0; // leader len of next line
@@ -596,7 +597,7 @@ static bool paragraph_start(linenr_T lnum)
if (lnum <= 1) {
return true; // start of the file
}
- p = (char_u *)ml_get(lnum - 1);
+ p = ml_get(lnum - 1);
if (*p == NUL) {
return true; // after empty line
}
@@ -735,22 +736,24 @@ void check_auto_format(bool end_insert)
int c = ' ';
int cc;
- if (did_add_space) {
- cc = gchar_cursor();
- if (!WHITECHAR(cc)) {
- // Somehow the space was removed already.
+ if (!did_add_space) {
+ return;
+ }
+
+ cc = gchar_cursor();
+ if (!WHITECHAR(cc)) {
+ // Somehow the space was removed already.
+ did_add_space = false;
+ } else {
+ if (!end_insert) {
+ inc_cursor();
+ c = gchar_cursor();
+ dec_cursor();
+ }
+ if (c != NUL) {
+ // The space is no longer at the end of the line, delete it.
+ del_char(false);
did_add_space = false;
- } else {
- if (!end_insert) {
- inc_cursor();
- c = gchar_cursor();
- dec_cursor();
- }
- if (c != NUL) {
- // The space is no longer at the end of the line, delete it.
- del_char(false);
- did_add_space = false;
- }
}
}
}
diff --git a/src/nvim/textobject.c b/src/nvim/textobject.c
index ee6c39a8ba..8e786c271c 100644
--- a/src/nvim/textobject.c
+++ b/src/nvim/textobject.c
@@ -4,6 +4,7 @@
// textobject.c: functions for text objects
#include <stdbool.h>
+#include <stdint.h>
#include <stdio.h>
#include <string.h>
@@ -28,7 +29,6 @@
#include "nvim/search.h"
#include "nvim/strings.h"
#include "nvim/textobject.h"
-#include "nvim/types.h"
#include "nvim/vim.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -273,7 +273,7 @@ bool startPS(linenr_T lnum, int para, bool both)
return true;
}
if (*s == '.' && (inmacro(p_sections, s + 1)
- || (!para && inmacro((char *)p_para, s + 1)))) {
+ || (!para && inmacro(p_para, s + 1)))) {
return true;
}
return false;
@@ -1078,7 +1078,7 @@ static bool in_html_tag(bool end_tag)
if (inc(&pos) < 0) {
return false;
}
- c = *ml_get_pos(&pos);
+ c = (uint8_t)(*ml_get_pos(&pos));
if (c == '>') {
break;
}
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c
index b837a380d5..733aa25f03 100644
--- a/src/nvim/tui/input.c
+++ b/src/nvim/tui/input.c
@@ -8,31 +8,27 @@
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
-#include "nvim/api/vim.h"
#include "nvim/ascii.h"
-#include "nvim/autocmd.h"
#include "nvim/charset.h"
#include "nvim/event/defs.h"
-#include "nvim/event/multiqueue.h"
-#include "nvim/globals.h"
#include "nvim/log.h"
#include "nvim/macros.h"
#include "nvim/main.h"
#include "nvim/map.h"
#include "nvim/memory.h"
-#include "nvim/message.h"
#include "nvim/option.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
#include "nvim/tui/input.h"
#include "nvim/tui/input_defs.h"
#include "nvim/tui/tui.h"
+#include "nvim/types.h"
+#include "nvim/ui_client.h"
#ifdef MSWIN
# include "nvim/os/os_win_console.h"
#endif
#include "nvim/event/rstream.h"
#include "nvim/msgpack_rpc/channel.h"
-#include "nvim/ui.h"
#define KEY_BUFFER_SIZE 0xfff
@@ -121,14 +117,6 @@ static const struct kitty_key_map_entry {
static Map(KittyKey, cstr_t) kitty_key_map = MAP_INIT;
-#ifndef UNIT_TESTING
-typedef enum {
- kIncomplete = -1,
- kNotApplicable = 0,
- kComplete = 1,
-} HandleState;
-#endif
-
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "tui/input.c.generated.h"
#endif
@@ -153,19 +141,7 @@ void tinput_init(TermInput *input, Loop *loop)
kitty_key_map_entry[i].name);
}
- // If stdin is not a pty, switch to stderr. For cases like:
- // echo q | nvim -es
- // ls *.md | xargs nvim
-#ifdef MSWIN
- if (!os_isatty(input->in_fd)) {
- input->in_fd = os_get_conin_fd();
- }
-#else
- if (!os_isatty(input->in_fd) && os_isatty(STDERR_FILENO)) {
- input->in_fd = STDERR_FILENO;
- }
-#endif
- input_global_fd_init(input->in_fd);
+ input->in_fd = STDIN_FILENO;
const char *term = os_getenv("TERM");
if (!term) {
@@ -174,7 +150,7 @@ void tinput_init(TermInput *input, Loop *loop)
input->tk = termkey_new_abstract(term,
TERMKEY_FLAG_UTF8 | TERMKEY_FLAG_NOSTART);
- termkey_hook_terminfo_getstr(input->tk, input->tk_ti_hook_fn, NULL);
+ termkey_hook_terminfo_getstr(input->tk, input->tk_ti_hook_fn, input);
termkey_start(input->tk);
int curflags = termkey_get_canonflags(input->tk);
@@ -600,7 +576,7 @@ static void set_bg(char *bgvalue)
// ignored in the calculations.
//
// [1] https://en.wikipedia.org/wiki/Luma_%28video%29
-static HandleState handle_background_color(TermInput *input)
+HandleState handle_background_color(TermInput *input)
{
if (input->waiting_for_bg_response <= 0) {
return kNotApplicable;
@@ -671,7 +647,7 @@ static HandleState handle_background_color(TermInput *input)
bool is_dark = luminance < 0.5;
char *bgvalue = is_dark ? "dark" : "light";
DLOG("bg response: %s", bgvalue);
- ui_client_bg_respose = is_dark ? kTrue : kFalse;
+ ui_client_bg_response = is_dark ? kTrue : kFalse;
set_bg(bgvalue);
input->waiting_for_bg_response = 0;
} else if (!done && !bad) {
@@ -685,12 +661,6 @@ static HandleState handle_background_color(TermInput *input)
}
return kComplete;
}
-#ifdef UNIT_TESTING
-HandleState ut_handle_background_color(TermInput *input)
-{
- return handle_background_color(input);
-}
-#endif
static void handle_raw_buffer(TermInput *input, bool force)
{
diff --git a/src/nvim/tui/input.h b/src/nvim/tui/input.h
index 5df108b107..d33cea6383 100644
--- a/src/nvim/tui/input.h
+++ b/src/nvim/tui/input.h
@@ -40,18 +40,14 @@ typedef struct term_input {
TUIData *tui_data;
} TermInput;
-#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "tui/input.h.generated.h"
-#endif
-
-#ifdef UNIT_TESTING
typedef enum {
kIncomplete = -1,
kNotApplicable = 0,
kComplete = 1,
} HandleState;
-HandleState ut_handle_background_color(TermInput *input);
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "tui/input.h.generated.h"
#endif
#endif // NVIM_TUI_INPUT_H
diff --git a/src/nvim/tui/terminfo.c b/src/nvim/tui/terminfo.c
index 507e9df21e..d630a34ce2 100644
--- a/src/nvim/tui/terminfo.c
+++ b/src/nvim/tui/terminfo.c
@@ -7,12 +7,12 @@
#include <string.h>
#include <unibilium.h>
+#include "klib/kvec.h"
+#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
+#include "nvim/ascii.h"
#include "nvim/charset.h"
-#include "nvim/globals.h"
#include "nvim/memory.h"
-#include "nvim/message.h"
-#include "nvim/option.h"
#include "nvim/strings.h"
#include "nvim/tui/terminfo.h"
#include "nvim/tui/terminfo_defs.h"
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index 44f6718039..ceda3b2076 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -16,7 +16,6 @@
#include "klib/kvec.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
-#include "nvim/api/vim.h"
#include "nvim/ascii.h"
#include "nvim/cursor_shape.h"
#include "nvim/event/defs.h"
@@ -32,12 +31,10 @@
#include "nvim/main.h"
#include "nvim/mbyte.h"
#include "nvim/memory.h"
-#include "nvim/message.h"
#include "nvim/msgpack_rpc/channel.h"
-#include "nvim/option.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
-#include "nvim/os/signal.h"
+#include "nvim/ui_client.h"
#ifdef MSWIN
# include "nvim/os/os_win_console.h"
#endif
@@ -46,7 +43,6 @@
#include "nvim/tui/tui.h"
#include "nvim/ugrid.h"
#include "nvim/ui.h"
-#include "nvim/vim.h"
// Space reserved in two output buffers to make the cursor normal or invisible
// when flushing. No existing terminal will require 32 bytes to do that.
@@ -141,6 +137,7 @@ struct TUIData {
int enable_bracketed_paste, disable_bracketed_paste;
int enable_lr_margin, disable_lr_margin;
int enter_strikethrough_mode;
+ int enter_altfont_mode;
int set_rgb_foreground, set_rgb_background;
int set_cursor_color;
int reset_cursor_color;
@@ -255,6 +252,7 @@ static void terminfo_start(TUIData *tui)
tui->unibi_ext.enable_bracketed_paste = -1;
tui->unibi_ext.disable_bracketed_paste = -1;
tui->unibi_ext.enter_strikethrough_mode = -1;
+ tui->unibi_ext.enter_altfont_mode = -1;
tui->unibi_ext.enable_lr_margin = -1;
tui->unibi_ext.disable_lr_margin = -1;
tui->unibi_ext.enable_focus_reporting = -1;
@@ -460,7 +458,11 @@ static void tui_terminal_stop(TUIData *tui)
void tui_stop(TUIData *tui)
{
+ if (tui->stopped) {
+ return;
+ }
tui_terminal_stop(tui);
+ stream_set_blocking(tui->input.in_fd, true); // normalize stream (#2598)
tinput_destroy(&tui->input);
tui->stopped = true;
signal_watcher_close(&tui->winch_handle, NULL);
@@ -515,7 +517,7 @@ static bool attrs_differ(TUIData *tui, int id1, int id2, bool rgb)
return a1.cterm_fg_color != a2.cterm_fg_color
|| a1.cterm_bg_color != a2.cterm_bg_color
|| a1.cterm_ae_attr != a2.cterm_ae_attr
- || (a1.cterm_ae_attr & HL_ANY_UNDERLINE
+ || (a1.cterm_ae_attr & HL_UNDERLINE_MASK
&& a1.rgb_sp_color != a2.rgb_sp_color);
}
}
@@ -535,6 +537,7 @@ static void update_attrs(TUIData *tui, int attr_id)
bool reverse = attr & HL_INVERSE;
bool standout = attr & HL_STANDOUT;
bool strikethrough = attr & HL_STRIKETHROUGH;
+ bool altfont = attr & HL_ALTFONT;
bool underline;
bool undercurl;
@@ -542,13 +545,14 @@ static void update_attrs(TUIData *tui, int attr_id)
bool underdotted;
bool underdashed;
if (tui->unibi_ext.set_underline_style != -1) {
- underline = attr & HL_UNDERLINE;
- undercurl = attr & HL_UNDERCURL;
- underdouble = attr & HL_UNDERDOUBLE;
- underdashed = attr & HL_UNDERDASHED;
- underdotted = attr & HL_UNDERDOTTED;
+ int ul = attr & HL_UNDERLINE_MASK;
+ underline = ul == HL_UNDERLINE;
+ undercurl = ul == HL_UNDERCURL;
+ underdouble = ul == HL_UNDERDOUBLE;
+ underdashed = ul == HL_UNDERDASHED;
+ underdotted = ul == HL_UNDERDOTTED;
} else {
- underline = attr & HL_ANY_UNDERLINE;
+ underline = attr & HL_UNDERLINE_MASK;
undercurl = false;
underdouble = false;
underdotted = false;
@@ -593,6 +597,9 @@ static void update_attrs(TUIData *tui, int attr_id)
if (italic) {
unibi_out(tui, unibi_enter_italics_mode);
}
+ if (altfont && tui->unibi_ext.enter_altfont_mode != -1) {
+ unibi_out_ext(tui, tui->unibi_ext.enter_altfont_mode);
+ }
if (strikethrough && tui->unibi_ext.enter_strikethrough_mode != -1) {
unibi_out_ext(tui, tui->unibi_ext.enter_strikethrough_mode);
}
@@ -1342,7 +1349,7 @@ static void suspend_event(void **argv)
TUIData *tui = argv[0];
bool enable_mouse = tui->mouse_enabled;
tui_terminal_stop(tui);
- stream_set_blocking(input_global_fd(), true); // normalize stream (#2598)
+ stream_set_blocking(tui->input.in_fd, true); // normalize stream (#2598)
kill(0, SIGTSTP);
@@ -1351,7 +1358,7 @@ static void suspend_event(void **argv)
if (enable_mouse) {
tui_mouse_on(tui);
}
- stream_set_blocking(input_global_fd(), false); // libuv expects this
+ stream_set_blocking(tui->input.in_fd, false); // libuv expects this
}
#endif
@@ -2041,6 +2048,11 @@ static void augment_terminfo(TUIData *tui, const char *term, long vte_version, l
// to the ECMA-48 strikeout/crossed-out attributes.
tui->unibi_ext.enter_strikethrough_mode = unibi_find_ext_str(ut, "smxx");
+ // It should be pretty safe to always enable this, as terminals will ignore
+ // unrecognised SGR numbers.
+ tui->unibi_ext.enter_altfont_mode = (int)unibi_add_ext_str(ut, "ext.enter_altfont_mode",
+ "\x1b[11m");
+
// Dickey ncurses terminfo does not include the setrgbf and setrgbb
// capabilities, proposed by Rüdiger Sonderfeld on 2013-10-15. Adding
// them here when terminfo lacks them is an augmentation, not a fixup.
@@ -2238,12 +2250,12 @@ static void flush_buf(TUIData *tui)
///
/// @see tmux/tty-keys.c fe4e9470bb504357d073320f5d305b22663ee3fd
/// @see https://bugzilla.redhat.com/show_bug.cgi?id=142659
-static const char *tui_get_stty_erase(void)
+static const char *tui_get_stty_erase(int fd)
{
static char stty_erase[2] = { 0 };
#if defined(HAVE_TERMIOS_H)
struct termios t;
- if (tcgetattr(input_global_fd(), &t) != -1) {
+ if (tcgetattr(fd, &t) != -1) {
stty_erase[0] = (char)t.c_cc[VERASE];
stty_erase[1] = '\0';
DLOG("stty/termios:erase=%s", stty_erase);
@@ -2256,9 +2268,10 @@ static const char *tui_get_stty_erase(void)
/// @see TermInput.tk_ti_hook_fn
static const char *tui_tk_ti_getstr(const char *name, const char *value, void *data)
{
+ TermInput *input = data;
static const char *stty_erase = NULL;
if (stty_erase == NULL) {
- stty_erase = tui_get_stty_erase();
+ stty_erase = tui_get_stty_erase(input->in_fd);
}
if (strequal(name, "key_backspace")) {
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index b25fa04c8b..9f1cb87eb0 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -7,8 +7,8 @@
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
+#include <string.h>
-#include "auto/config.h"
#include "klib/kvec.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/ui.h"
@@ -17,8 +17,6 @@
#include "nvim/buffer_defs.h"
#include "nvim/cursor_shape.h"
#include "nvim/drawscreen.h"
-#include "nvim/event/defs.h"
-#include "nvim/event/loop.h"
#include "nvim/ex_getln.h"
#include "nvim/gettext.h"
#include "nvim/globals.h"
@@ -27,15 +25,14 @@
#include "nvim/highlight_defs.h"
#include "nvim/log.h"
#include "nvim/lua/executor.h"
-#include "nvim/main.h"
+#include "nvim/map.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/msgpack_rpc/channel.h"
#include "nvim/option.h"
#include "nvim/os/time.h"
#include "nvim/strings.h"
-#include "nvim/tui/tui.h"
#include "nvim/ui.h"
+#include "nvim/ui_client.h"
#include "nvim/ui_compositor.h"
#include "nvim/vim.h"
#include "nvim/window.h"
diff --git a/src/nvim/ui_client.c b/src/nvim/ui_client.c
index ff82fd3239..378c0e4831 100644
--- a/src/nvim/ui_client.c
+++ b/src/nvim/ui_client.c
@@ -6,15 +6,18 @@
#include <stdlib.h>
#include "nvim/api/private/helpers.h"
+#include "nvim/channel.h"
#include "nvim/eval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/event/loop.h"
-#include "nvim/event/multiqueue.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
#include "nvim/log.h"
#include "nvim/main.h"
#include "nvim/memory.h"
#include "nvim/msgpack_rpc/channel.h"
+#include "nvim/msgpack_rpc/channel_defs.h"
+#include "nvim/os/os_defs.h"
#include "nvim/tui/tui.h"
#include "nvim/ui.h"
#include "nvim/ui_client.h"
@@ -48,9 +51,16 @@ uint64_t ui_client_start_server(int argc, char **argv)
on_err, CALLBACK_NONE,
false, true, true, false, kChannelStdinPipe,
NULL, 0, 0, NULL, &exit_status);
+
+ // If stdin is not a pty, it is forwarded to the client.
+ // Replace stdin in the TUI process with the tty fd.
if (ui_client_forward_stdin) {
close(0);
- dup(2);
+#ifdef MSWIN
+ os_open_conin_fd();
+#else
+ dup(stderr_isatty ? STDERR_FILENO : STDOUT_FILENO);
+#endif
}
return channel->id;
@@ -74,8 +84,8 @@ void ui_client_run(bool remote_ui)
if (term) {
PUT(opts, "term_name", STRING_OBJ(cstr_to_string(term)));
}
- if (ui_client_bg_respose != kNone) {
- bool is_dark = (ui_client_bg_respose == kTrue);
+ if (ui_client_bg_response != kNone) {
+ bool is_dark = (ui_client_bg_response == kTrue);
PUT_C(opts, "term_background", STRING_OBJ(cstr_as_string(is_dark ? "dark" : "light")));
}
PUT_C(opts, "term_colors", INTEGER_OBJ(t_colors));
diff --git a/src/nvim/ui_client.h b/src/nvim/ui_client.h
index 24b8fad4cc..7e5f847039 100644
--- a/src/nvim/ui_client.h
+++ b/src/nvim/ui_client.h
@@ -1,11 +1,14 @@
#ifndef NVIM_UI_CLIENT_H
#define NVIM_UI_CLIENT_H
+#include <stdbool.h>
#include <stddef.h>
+#include <stdint.h>
#include "nvim/api/private/defs.h"
#include "nvim/grid_defs.h"
#include "nvim/macros.h"
+#include "nvim/types.h"
typedef struct {
const char *name;
@@ -28,17 +31,18 @@ EXTERN bool ui_client_attached INIT(= false);
/// Whether ui client has gotten a response about the bg color of the terminal,
/// kTrue=dark, kFalse=light, kNone=no response yet
-EXTERN TriState ui_client_bg_respose INIT(= kNone);
+EXTERN TriState ui_client_bg_response INIT(= kNone);
/// The ui client should forward its stdin to the nvim process
/// by convention, this uses fd=3 (next free number after stdio)
EXTERN bool ui_client_forward_stdin INIT(= false);
#define UI_CLIENT_STDIN_FD 3
+// uncrustify:off
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ui_client.h.generated.h"
-
# include "ui_events_client.h.generated.h"
#endif
+// uncrustify:on
#endif // NVIM_UI_CLIENT_H
diff --git a/src/nvim/ui_compositor.c b/src/nvim/ui_compositor.c
index ad44e2ca22..9ff9eabff8 100644
--- a/src/nvim/ui_compositor.c
+++ b/src/nvim/ui_compositor.c
@@ -24,7 +24,6 @@
#include "nvim/highlight_group.h"
#include "nvim/log.h"
#include "nvim/macros.h"
-#include "nvim/map.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/option_defs.h"
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index 85e261fc39..0f12c00f15 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -624,20 +624,20 @@ int u_savecommon(buf_T *buf, linenr_T top, linenr_T bot, linenr_T newbot, int re
// extra fields for uhp
#define UHP_SAVE_NR 1
-static char_u e_not_open[] = N_("E828: Cannot open undo file for writing: %s");
+static char e_not_open[] = N_("E828: Cannot open undo file for writing: %s");
/// Compute the hash for a buffer text into hash[UNDO_HASH_SIZE].
///
/// @param[in] buf The buffer used to compute the hash
/// @param[in] hash Array of size UNDO_HASH_SIZE in which to store the value of
/// the hash
-void u_compute_hash(buf_T *buf, char_u *hash)
+void u_compute_hash(buf_T *buf, uint8_t *hash)
{
context_sha256_T ctx;
sha256_start(&ctx);
for (linenr_T lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) {
char *p = ml_get_buf(buf, lnum, false);
- sha256_update(&ctx, (char_u *)p, (uint32_t)(strlen(p) + 1));
+ sha256_update(&ctx, (uint8_t *)p, strlen(p) + 1);
}
sha256_finish(&ctx, hash);
}
@@ -677,7 +677,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 ".".
- char *dirp = (char *)p_udir;
+ char *dirp = p_udir;
while (*dirp != NUL) {
size_t dir_len = copy_option_part(&dirp, dir_name, MAXPATHL, ",");
if (dir_len == 1 && dir_name[0] == '.') {
@@ -765,7 +765,7 @@ static void u_free_uhp(u_header_T *uhp)
/// @param hash The hash of the buffer contents
//
/// @returns false in case of an error.
-static bool serialize_header(bufinfo_T *bi, char_u *hash)
+static bool serialize_header(bufinfo_T *bi, uint8_t *hash)
FUNC_ATTR_NONNULL_ALL
{
buf_T *buf = bi->bi_buf;
@@ -788,7 +788,7 @@ static bool serialize_header(bufinfo_T *bi, char_u *hash)
undo_write_bytes(bi, (uintmax_t)buf->b_ml.ml_line_count, 4);
size_t len = buf->b_u_line_ptr ? strlen(buf->b_u_line_ptr) : 0;
undo_write_bytes(bi, len, 4);
- if (len > 0 && !undo_write(bi, (char_u *)buf->b_u_line_ptr, len)) {
+ if (len > 0 && !undo_write(bi, (uint8_t *)buf->b_u_line_ptr, len)) {
return false;
}
undo_write_bytes(bi, (uintmax_t)buf->b_u_line_lnum, 4);
@@ -1053,7 +1053,7 @@ static bool serialize_uep(bufinfo_T *bi, u_entry_T *uep)
if (!undo_write_bytes(bi, len, 4)) {
return false;
}
- if (len > 0 && !undo_write(bi, (char_u *)uep->ue_array[i], len)) {
+ if (len > 0 && !undo_write(bi, (uint8_t *)uep->ue_array[i], len)) {
return false;
}
}
@@ -1072,18 +1072,18 @@ static u_entry_T *unserialize_uep(bufinfo_T *bi, bool *error, const char *file_n
uep->ue_lcount = undo_read_4c(bi);
uep->ue_size = undo_read_4c(bi);
- char_u **array = NULL;
+ char **array = NULL;
if (uep->ue_size > 0) {
- if ((size_t)uep->ue_size < SIZE_MAX / sizeof(char_u *)) { // -V547
- array = xmalloc(sizeof(char_u *) * (size_t)uep->ue_size);
- memset(array, 0, sizeof(char_u *) * (size_t)uep->ue_size);
+ if ((size_t)uep->ue_size < SIZE_MAX / sizeof(char *)) { // -V547
+ array = xmalloc(sizeof(char *) * (size_t)uep->ue_size);
+ memset(array, 0, sizeof(char *) * (size_t)uep->ue_size);
}
}
- uep->ue_array = (char **)array;
+ uep->ue_array = array;
for (size_t i = 0; i < (size_t)uep->ue_size; i++) {
int line_len = undo_read_4c(bi);
- char_u *line;
+ char *line;
if (line_len >= 0) {
line = undo_read_string(bi, (size_t)line_len);
} else {
@@ -1150,7 +1150,7 @@ 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, uint8_t *const hash)
FUNC_ATTR_NONNULL_ARG(3, 4)
{
char *file_name;
@@ -1209,7 +1209,7 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf,
}
goto theend;
} else {
- char_u mbuf[UF_START_MAGIC_LEN];
+ char mbuf[UF_START_MAGIC_LEN];
ssize_t len = read_eintr(fd, mbuf, UF_START_MAGIC_LEN);
close(fd);
if (len < UF_START_MAGIC_LEN
@@ -1342,8 +1342,8 @@ write_error:
#ifdef HAVE_ACL
if (buf->b_ffname != NULL) {
// For systems that support ACL: get the ACL from the original file.
- vim_acl_T acl = os_get_acl((char_u *)buf->b_ffname);
- os_set_acl((char_u *)file_name, acl);
+ vim_acl_T acl = os_get_acl(buf->b_ffname);
+ os_set_acl(file_name, acl);
os_free_acl(acl);
}
#endif
@@ -1359,11 +1359,11 @@ 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 uint8_t *hash, const char *orig_name FUNC_ATTR_UNUSED)
FUNC_ATTR_NONNULL_ARG(2)
{
u_header_T **uhp_table = NULL;
- char_u *line_ptr = NULL;
+ char *line_ptr = NULL;
char *file_name;
if (name == NULL) {
@@ -1377,7 +1377,7 @@ void u_read_undo(char *name, const char_u *hash, const char_u *orig_name FUNC_AT
// owner of the text file or equal to the current user.
FileInfo file_info_orig;
FileInfo file_info_undo;
- if (os_fileinfo((const char *)orig_name, &file_info_orig)
+ if (os_fileinfo(orig_name, &file_info_orig)
&& 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()) {
@@ -1414,7 +1414,7 @@ void u_read_undo(char *name, const char_u *hash, const char_u *orig_name FUNC_AT
};
// Read the undo file header.
- char_u magic_buf[UF_START_MAGIC_LEN];
+ char magic_buf[UF_START_MAGIC_LEN];
if (fread(magic_buf, UF_START_MAGIC_LEN, 1, fp) != 1
|| memcmp(magic_buf, UF_START_MAGIC, UF_START_MAGIC_LEN) != 0) {
semsg(_("E823: Not an undo file: %s"), file_name);
@@ -1426,7 +1426,7 @@ void u_read_undo(char *name, const char_u *hash, const char_u *orig_name FUNC_AT
goto error;
}
- char_u read_hash[UNDO_HASH_SIZE];
+ uint8_t read_hash[UNDO_HASH_SIZE];
if (!undo_read(&bi, read_hash, UNDO_HASH_SIZE)) {
corruption_error("hash", file_name);
goto error;
@@ -1608,7 +1608,7 @@ void u_read_undo(char *name, const char_u *hash, const char_u *orig_name FUNC_AT
curbuf->b_u_oldhead = old_idx < 0 ? NULL : uhp_table[old_idx];
curbuf->b_u_newhead = new_idx < 0 ? NULL : uhp_table[new_idx];
curbuf->b_u_curhead = cur_idx < 0 ? NULL : uhp_table[cur_idx];
- curbuf->b_u_line_ptr = (char *)line_ptr;
+ curbuf->b_u_line_ptr = line_ptr;
curbuf->b_u_line_lnum = line_lnum;
curbuf->b_u_line_colnr = line_colnr;
curbuf->b_u_numhead = num_head;
@@ -1743,10 +1743,10 @@ static bool undo_read(bufinfo_T *bi, uint8_t *buffer, size_t size)
/// @param len can be zero to allocate an empty line.
///
/// @returns a pointer to allocated memory or NULL in case of an error.
-static uint8_t *undo_read_string(bufinfo_T *bi, size_t len)
+static char *undo_read_string(bufinfo_T *bi, size_t len)
{
- uint8_t *ptr = xmallocz(len);
- if (len > 0 && !undo_read(bi, ptr, len)) {
+ char *ptr = xmallocz(len);
+ if (len > 0 && !undo_read(bi, (uint8_t *)ptr, len)) {
xfree(ptr);
return NULL;
}
@@ -2238,7 +2238,7 @@ 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 **newarray = NULL;
linenr_T newlnum = MAXLNUM;
u_entry_T *nuep;
u_entry_T *newlist = NULL;
@@ -2316,13 +2316,13 @@ static void u_undoredo(int undo, bool do_buf_event)
// delete the lines between top and bot and save them in newarray
if (oldsize > 0) {
- newarray = xmalloc(sizeof(char_u *) * (size_t)oldsize);
+ newarray = xmalloc(sizeof(char *) * (size_t)oldsize);
// delete backwards, it goes faster in most cases
long i;
linenr_T lnum;
for (lnum = bot - 1, i = oldsize; --i >= 0; lnum--) {
// what can we do when we run out of memory?
- newarray[i] = (char_u *)u_save_line(lnum);
+ newarray[i] = u_save_line(lnum);
// remember we deleted the last line in the buffer, and a
// dummy empty line will be inserted
if (curbuf->b_ml.ml_line_count == 1) {
@@ -2348,7 +2348,7 @@ static void u_undoredo(int undo, bool do_buf_event)
}
xfree(uep->ue_array[i]);
}
- xfree((char_u *)uep->ue_array);
+ xfree(uep->ue_array);
}
// Adjust marks
@@ -2378,7 +2378,7 @@ static void u_undoredo(int undo, bool do_buf_event)
u_newcount += newsize;
u_oldcount += oldsize;
uep->ue_size = oldsize;
- uep->ue_array = (char **)newarray;
+ uep->ue_array = newarray;
uep->ue_bot = top + newsize + 1;
// insert this entry in front of the new entry list
@@ -2565,11 +2565,11 @@ static void u_undo_end(bool did_undo, bool absolute, bool quiet)
uhp = curbuf->b_u_newhead;
}
- char_u msgbuf[80];
+ char msgbuf[80];
if (uhp == NULL) {
*msgbuf = NUL;
} else {
- undo_fmt_time((char *)msgbuf, sizeof(msgbuf), uhp->uh_time);
+ undo_fmt_time(msgbuf, sizeof(msgbuf), uhp->uh_time);
}
{
@@ -2935,7 +2935,7 @@ static void u_freeentries(buf_T *buf, u_header_T *uhp, u_header_T **uhpp)
#ifdef U_DEBUG
uhp->uh_magic = 0;
#endif
- xfree((char_u *)uhp);
+ xfree(uhp);
buf->b_u_numhead--;
}
@@ -2945,11 +2945,11 @@ static void u_freeentry(u_entry_T *uep, long n)
while (n > 0) {
xfree(uep->ue_array[--n]);
}
- xfree((char_u *)uep->ue_array);
+ xfree(uep->ue_array);
#ifdef U_DEBUG
uep->ue_magic = 0;
#endif
- xfree((char_u *)uep);
+ xfree(uep);
}
/// invalidate the undo buffer; called when storage has already been released
@@ -2985,10 +2985,12 @@ void u_saveline(linenr_T lnum)
/// (this is used externally for crossing a line while in insert mode)
void u_clearline(void)
{
- if (curbuf->b_u_line_ptr != NULL) {
- XFREE_CLEAR(curbuf->b_u_line_ptr);
- curbuf->b_u_line_lnum = 0;
+ if (curbuf->b_u_line_ptr == NULL) {
+ return;
}
+
+ XFREE_CLEAR(curbuf->b_u_line_ptr);
+ curbuf->b_u_line_lnum = 0;
}
/// Implementation of the "U" command.
diff --git a/src/nvim/usercmd.c b/src/nvim/usercmd.c
index 883d7321d2..ef13f67e49 100644
--- a/src/nvim/usercmd.c
+++ b/src/nvim/usercmd.c
@@ -89,12 +89,15 @@ static const char *command_complete[] = {
[EXPAND_SYNTIME] = "syntime",
[EXPAND_SETTINGS] = "option",
[EXPAND_PACKADD] = "packadd",
+ [EXPAND_RUNTIME] = "runtime",
[EXPAND_SHELLCMD] = "shellcmd",
[EXPAND_SIGN] = "sign",
[EXPAND_TAGS] = "tag",
[EXPAND_TAGS_LISTFILES] = "tag_listfiles",
[EXPAND_USER] = "user",
[EXPAND_USER_VARS] = "var",
+ [EXPAND_BREAKPOINT] = "breakpoint",
+ [EXPAND_SCRIPTNAMES] = "scriptnames",
};
/// List of names of address types. Must be alphabetical for completion.
@@ -1422,7 +1425,7 @@ static size_t uc_check_code(char *code, size_t len, char *buf, ucmd_T *cmd, exar
ct_NONE,
} type = ct_NONE;
- if ((vim_strchr("qQfF", *p) != NULL) && p[1] == '-') {
+ if ((vim_strchr("qQfF", (uint8_t)(*p)) != NULL) && p[1] == '-') {
quote = (*p == 'q' || *p == 'Q') ? 1 : 2;
p += 2;
l -= 2;
@@ -1430,7 +1433,7 @@ static size_t uc_check_code(char *code, size_t len, char *buf, ucmd_T *cmd, exar
l++;
if (l <= 1) {
- type = ct_NONE;
+ // type = ct_NONE;
} else if (STRNICMP(p, "args>", l) == 0) {
type = ct_ARGS;
} else if (STRNICMP(p, "bang>", l) == 0) {
diff --git a/src/nvim/version.c b/src/nvim/version.c
index 92122b2523..3324ac2a94 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -29,6 +29,7 @@
#include "nvim/highlight_defs.h"
#include "nvim/lua/executor.h"
#include "nvim/mbyte.h"
+#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/option_defs.h"
#include "nvim/os/os_defs.h"
@@ -63,12 +64,6 @@ static char *features[] = {
"-acl",
#endif
-#if defined(HAVE_ICONV)
- "+iconv",
-#else
- "-iconv",
-#endif
-
"+tui",
NULL
};
@@ -800,7 +795,7 @@ static const int included_patches[] = {
1702,
1701,
// 1700,
- // 1699,
+ 1699,
1698,
1697,
1696,
@@ -1366,7 +1361,7 @@ static const int included_patches[] = {
// 1136,
1135,
1134,
- // 1133,
+ 1133,
1132,
1131,
1130,
@@ -1679,7 +1674,7 @@ static const int included_patches[] = {
823,
822,
821,
- // 820,
+ 820,
819,
818,
817,
@@ -2790,24 +2785,18 @@ void maybe_intro_message(void)
/// @param colon true for ":intro"
void intro_message(int colon)
{
- int i;
- long row;
- long blanklines;
- int sponsor;
- char *p;
static char *(lines[]) = {
N_(NVIM_VERSION_LONG),
"",
N_("Nvim is open source and freely distributable"),
- N_("https://neovim.io/#chat"),
+ "https://neovim.io/#chat",
"",
N_("type :help nvim<Enter> if you are new! "),
N_("type :checkhealth<Enter> to optimize Nvim"),
N_("type :q<Enter> to exit "),
N_("type :help<Enter> for help "),
"",
- N_("type :help news<Enter> to see changes in")
- " v" STR(NVIM_VERSION_MAJOR) "." STR(NVIM_VERSION_MINOR),
+ N_("type :help news<Enter> to see changes in v%s.%s"),
"",
N_("Help poor children in Uganda!"),
N_("type :help iccf<Enter> for information "),
@@ -2817,7 +2806,7 @@ void intro_message(int colon)
size_t lines_size = ARRAY_SIZE(lines);
assert(lines_size <= LONG_MAX);
- blanklines = Rows - ((long)lines_size - 1L);
+ long blanklines = Rows - ((long)lines_size - 1L);
// Don't overwrite a statusline. Depends on 'cmdheight'.
if (p_ls > 1) {
@@ -2830,17 +2819,27 @@ void intro_message(int colon)
// Show the sponsor and register message one out of four times, the Uganda
// message two out of four times.
- sponsor = (int)time(NULL);
+ int sponsor = (int)time(NULL);
sponsor = ((sponsor & 2) == 0) - ((sponsor & 4) == 0);
// start displaying the message lines after half of the blank lines
- row = blanklines / 2;
+ long row = blanklines / 2;
if (((row >= 2) && (Columns >= 50)) || colon) {
- for (i = 0; i < (int)ARRAY_SIZE(lines); i++) {
- p = lines[i];
+ for (int i = 0; i < (int)ARRAY_SIZE(lines); i++) {
+ char *p = lines[i];
+ char *mesg = NULL;
+ int mesg_size = 0;
- if (sponsor != 0) {
+ if (strstr(p, "news") != NULL) {
+ p = _(p);
+ mesg_size = snprintf(NULL, 0, p,
+ STR(NVIM_VERSION_MAJOR), STR(NVIM_VERSION_MINOR));
+ assert(mesg_size > 0);
+ mesg = xmallocz((size_t)mesg_size);
+ snprintf(mesg, (size_t)mesg_size + 1, p,
+ STR(NVIM_VERSION_MAJOR), STR(NVIM_VERSION_MINOR));
+ } else if (sponsor != 0) {
if (strstr(p, "children") != NULL) {
p = sponsor < 0
? N_("Sponsor Vim development!")
@@ -2849,15 +2848,25 @@ void intro_message(int colon)
p = sponsor < 0
? N_("type :help sponsor<Enter> for information ")
: N_("type :help register<Enter> for information ");
- } else if (strstr(p, "Orphans") != NULL) {
- p = N_("menu Help->Sponsor/Register for information ");
}
}
- if (*p != NUL) {
- do_intro_line(row, _(p), 0);
+ if (mesg == NULL) {
+ if (*p != NUL) {
+ mesg = _(p);
+ } else {
+ mesg = "";
+ }
+ }
+
+ if (*mesg != NUL) {
+ do_intro_line(row, mesg, 0);
}
row++;
+
+ if (mesg_size > 0) {
+ XFREE_CLEAR(mesg);
+ }
}
}
diff --git a/src/nvim/vim.h b/src/nvim/vim.h
index c395eb438c..3c765f8eb2 100644
--- a/src/nvim/vim.h
+++ b/src/nvim/vim.h
@@ -154,6 +154,9 @@ enum {
EXPAND_MAPCLEAR,
EXPAND_ARGLIST,
EXPAND_DIFF_BUFFERS,
+ EXPAND_BREAKPOINT,
+ EXPAND_SCRIPTNAMES,
+ EXPAND_RUNTIME,
EXPAND_CHECKHEALTH,
EXPAND_LUA,
};
diff --git a/src/nvim/viml/parser/expressions.c b/src/nvim/viml/parser/expressions.c
index 0b19526fa0..53224f2ee9 100644
--- a/src/nvim/viml/parser/expressions.c
+++ b/src/nvim/viml/parser/expressions.c
@@ -1826,7 +1826,7 @@ static void parse_quoted_string(ParserState *const pstate, ExprASTNode *const no
flags |= FSK_SIMPLIFY;
}
const size_t special_len = trans_special(&p, (size_t)(e - p),
- (char_u *)v_p, flags, false, NULL);
+ v_p, flags, false, NULL);
if (special_len != 0) {
v_p += special_len;
} else {
@@ -2497,7 +2497,6 @@ viml_pexpr_parse_bracket_closing_error:
NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeListLiteral);
*top_node_p = cur_node;
kvi_push(ast_stack, &cur_node->children);
- want_node = kENodeValue;
if (cur_pt == kEPTAssignment) {
// Additional assignment parse type allows to easily forbid nested
// lists.
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 2bcbef14b0..6b40ccdb84 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -11,12 +11,14 @@
#include <stdlib.h>
#include <string.h>
+#include "klib/kvec.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/arglist.h"
#include "nvim/ascii.h"
#include "nvim/autocmd.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/cursor.h"
#include "nvim/decoration.h"
@@ -59,6 +61,7 @@
#include "nvim/option.h"
#include "nvim/optionstr.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/path.h"
#include "nvim/plines.h"
#include "nvim/pos.h"
@@ -505,7 +508,7 @@ wingotofile:
CHECK_CMDWIN;
linenr_T lnum = -1;
- char *ptr = (char *)grab_file_name(Prenum1, &lnum);
+ char *ptr = grab_file_name(Prenum1, &lnum);
if (ptr != NULL) {
tabpage_T *oldtab = curtab;
win_T *oldwin = curwin;
@@ -753,20 +756,20 @@ void win_set_minimal_style(win_T *wp)
// Hide EOB region: use " " fillchar and cleared highlighting
if (wp->w_p_fcs_chars.eob != ' ') {
- char_u *old = (char_u *)wp->w_p_fcs;
+ char *old = wp->w_p_fcs;
wp->w_p_fcs = ((*old == NUL)
? xstrdup("eob: ")
- : concat_str((char *)old, ",eob: "));
- free_string_option((char *)old);
+ : concat_str(old, ",eob: "));
+ free_string_option(old);
}
// TODO(bfredl): this could use a highlight namespace directly,
// and avoid peculiarities around window options
- char_u *old = (char_u *)wp->w_p_winhl;
+ char *old = wp->w_p_winhl;
wp->w_p_winhl = ((*old == NUL)
? xstrdup("EndOfBuffer:")
- : concat_str((char *)old, ",EndOfBuffer:"));
- free_string_option((char *)old);
+ : concat_str(old, ",EndOfBuffer:"));
+ free_string_option(old);
parse_winhl_opt(wp);
// signcolumn: use 'auto'
@@ -2524,24 +2527,23 @@ void close_windows(buf_T *buf, bool keep_curwin)
RedrawingDisabled--;
}
-/// Check that the specified window is the last one.
-/// @param win counted even if floating
-///
-/// @return true if the specified window is the only window that exists,
-/// false if there is another, possibly in another tab page.
+/// Check if "win" is the last non-floating window that exists.
bool last_window(win_T *win) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
return one_window(win) && first_tabpage->tp_next == NULL;
}
-/// Check if current tab page contains no more than one window other than `aucmd_win[]`.
-/// @param counted_float counted even if floating, but not if it is `aucmd_win[]`
-bool one_window(win_T *counted_float) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+/// Check if "win" is the only non-floating window in the current tabpage.
+bool one_window(win_T *win) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
+ if (win->w_floating) {
+ return false;
+ }
+
bool seen_one = false;
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if (!is_aucmd_win(wp) && (!wp->w_floating || wp == counted_float)) {
+ if (!wp->w_floating) {
if (seen_one) {
return false;
}
@@ -2597,6 +2599,7 @@ static bool close_last_window_tabpage(win_T *win, bool free_buf, tabpage_T *prev
if (!ONE_WINDOW) {
return false;
}
+
buf_T *old_curbuf = curbuf;
Terminal *term = win->w_buffer ? win->w_buffer->terminal : NULL;
@@ -2614,8 +2617,8 @@ static bool close_last_window_tabpage(win_T *win, bool free_buf, tabpage_T *prev
goto_tabpage_tp(alt_tabpage(), false, true);
// save index for tabclosed event
- char_u prev_idx[NUMBUFLEN];
- snprintf((char *)prev_idx, NUMBUFLEN, "%i", tabpage_index(prev_curtab));
+ char prev_idx[NUMBUFLEN];
+ snprintf(prev_idx, NUMBUFLEN, "%i", tabpage_index(prev_curtab));
// Safety check: Autocommands may have closed the window when jumping
// to the other tab page.
@@ -4061,7 +4064,7 @@ void free_tabpage(tabpage_T *tp)
/// tabpage in case of 0.
/// @param filename Will be passed to apply_autocmds().
/// @return Was the new tabpage created successfully? FAIL or OK.
-int win_new_tabpage(int after, char_u *filename)
+int win_new_tabpage(int after, char *filename)
{
tabpage_T *old_curtab = curtab;
@@ -4124,7 +4127,7 @@ int win_new_tabpage(int after, char_u *filename)
apply_autocmds(EVENT_WINNEW, NULL, NULL, false, curbuf);
apply_autocmds(EVENT_WINENTER, NULL, NULL, false, curbuf);
- apply_autocmds(EVENT_TABNEW, (char *)filename, (char *)filename, false, curbuf);
+ apply_autocmds(EVENT_TABNEW, filename, filename, false, curbuf);
apply_autocmds(EVENT_TABENTER, NULL, NULL, false, curbuf);
return OK;
@@ -4142,12 +4145,13 @@ int may_open_tabpage(void)
{
int n = (cmdmod.cmod_tab == 0) ? postponed_split_tab : cmdmod.cmod_tab;
- if (n != 0) {
- cmdmod.cmod_tab = 0; // reset it to avoid doing it twice
- postponed_split_tab = 0;
- return win_new_tabpage(n, NULL);
+ if (n == 0) {
+ return FAIL;
}
- return FAIL;
+
+ cmdmod.cmod_tab = 0; // reset it to avoid doing it twice
+ postponed_split_tab = 0;
+ return win_new_tabpage(n, NULL);
}
// Create up to "maxcount" tabpages with empty windows.
@@ -4492,11 +4496,12 @@ void goto_tabpage_tp(tabpage_T *tp, bool trigger_enter_autocmds, bool trigger_le
/// @return true if the tab page is valid, false otherwise.
bool goto_tabpage_lastused(void)
{
- if (valid_tabpage(lastused_tabpage)) {
- goto_tabpage_tp(lastused_tabpage, true, true);
- return true;
+ if (!valid_tabpage(lastused_tabpage)) {
+ return false;
}
- return false;
+
+ goto_tabpage_tp(lastused_tabpage, true, true);
+ return true;
}
// Enter window "wp" in tab page "tp".
@@ -6754,7 +6759,7 @@ static void frame_add_height(frame_T *frp, int n)
// Get the file name at the cursor.
// If Visual mode is active, use the selected text if it's in one line.
// Returns the name in allocated memory, NULL for failure.
-char_u *grab_file_name(long count, linenr_T *file_lnum)
+char *grab_file_name(long count, linenr_T *file_lnum)
{
int options = FNAME_MESS | FNAME_EXP | FNAME_REL | FNAME_UNESC;
if (VIsual_active) {
@@ -6764,12 +6769,12 @@ char_u *grab_file_name(long count, linenr_T *file_lnum)
return NULL;
}
// Only recognize ":123" here
- if (file_lnum != NULL && ptr[len] == ':' && isdigit(ptr[len + 1])) {
+ if (file_lnum != NULL && ptr[len] == ':' && isdigit((uint8_t)ptr[len + 1])) {
char *p = ptr + len + 1;
*file_lnum = (linenr_T)getdigits_long(&p, false, 0);
}
- return (char_u *)find_file_name_in_path(ptr, len, options, count, curbuf->b_ffname);
+ return find_file_name_in_path(ptr, len, options, count, curbuf->b_ffname);
}
return file_name_at_cursor(options | FNAME_HYP, count, file_lnum);
}
@@ -6785,10 +6790,10 @@ char_u *grab_file_name(long count, linenr_T *file_lnum)
// FNAME_EXP expand to path
// FNAME_HYP check for hypertext link
// FNAME_INCL apply "includeexpr"
-char_u *file_name_at_cursor(int options, long count, linenr_T *file_lnum)
+char *file_name_at_cursor(int options, long count, linenr_T *file_lnum)
{
- return file_name_in_line((char_u *)get_cursor_line_ptr(),
- curwin->w_cursor.col, options, count, (char_u *)curbuf->b_ffname,
+ return file_name_in_line(get_cursor_line_ptr(),
+ curwin->w_cursor.col, options, count, curbuf->b_ffname,
file_lnum);
}
@@ -6796,11 +6801,11 @@ char_u *file_name_at_cursor(int options, long count, linenr_T *file_lnum)
/// @param file_lnum line number after the file name
///
/// @return the name of the file under or after ptr[col]. Otherwise like file_name_at_cursor().
-char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u *rel_fname,
- linenr_T *file_lnum)
+char *file_name_in_line(char *line, int col, int options, long count, char *rel_fname,
+ linenr_T *file_lnum)
{
// search forward for what could be the start of a file name
- char *ptr = (char *)line + col;
+ char *ptr = line + col;
while (*ptr != NUL && !vim_isfilec((uint8_t)(*ptr))) {
MB_PTR_ADV(ptr);
}
@@ -6817,8 +6822,8 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u
// Search backward for first char of the file name.
// Go one char back to ":" before "//" even when ':' is not in 'isfname'.
- while ((char_u *)ptr > line) {
- if ((len = (size_t)(utf_head_off((char *)line, ptr - 1))) > 0) {
+ while (ptr > line) {
+ if ((len = (size_t)(utf_head_off(line, ptr - 1))) > 0) {
ptr -= len + 1;
} else if (vim_isfilec((uint8_t)ptr[-1])
|| ((options & FNAME_HYP) && path_is_url(ptr - 1))) {
@@ -6833,7 +6838,7 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u
len = 0;
while (vim_isfilec((uint8_t)ptr[len]) || (ptr[len] == '\\' && ptr[len + 1] == ' ')
|| ((options & FNAME_HYP) && path_is_url(ptr + len))
- || (is_url && vim_strchr(":?&=", ptr[len]) != NULL)) {
+ || (is_url && vim_strchr(":?&=", (uint8_t)ptr[len]) != NULL)) {
// After type:// we also include :, ?, & and = as valid characters, so that
// http://google.com:8080?q=this&that=ok works.
if ((ptr[len] >= 'A' && ptr[len] <= 'Z')
@@ -6854,7 +6859,7 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u
// If there is trailing punctuation, remove it.
// But don't remove "..", could be a directory name.
- if (len > 2 && vim_strchr(".,:;!", ptr[len - 1]) != NULL
+ if (len > 2 && vim_strchr(".,:;!", (uint8_t)ptr[len - 1]) != NULL
&& ptr[len - 2] != '.') {
len--;
}
@@ -6875,17 +6880,17 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u
p = skipwhite(p);
}
if (*p != NUL) {
- if (!isdigit(*p)) {
+ if (!isdigit((uint8_t)(*p))) {
p++; // skip the separator
}
p = skipwhite(p);
- if (isdigit(*p)) {
+ if (isdigit((uint8_t)(*p))) {
*file_lnum = (linenr_T)getdigits_long(&p, false, 0);
}
}
}
- return (char_u *)find_file_name_in_path(ptr, len, options, count, (char *)rel_fname);
+ return find_file_name_in_path(ptr, len, options, count, rel_fname);
}
/// Add or remove a status line from window(s), according to the
@@ -7248,11 +7253,12 @@ static void clear_snapshot(tabpage_T *tp, int idx)
static void clear_snapshot_rec(frame_T *fr)
{
- if (fr != NULL) {
- clear_snapshot_rec(fr->fr_next);
- clear_snapshot_rec(fr->fr_child);
- xfree(fr);
+ if (fr == NULL) {
+ return;
}
+ clear_snapshot_rec(fr->fr_next);
+ clear_snapshot_rec(fr->fr_child);
+ xfree(fr);
}
/// Traverse a snapshot to find the previous curwin.
diff --git a/src/nvim/window.h b/src/nvim/window.h
index f348f102c9..4ab2bea60a 100644
--- a/src/nvim/window.h
+++ b/src/nvim/window.h
@@ -6,6 +6,7 @@
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
+#include "nvim/macros.h"
#include "nvim/mark.h"
#include "nvim/os/os.h"
#include "nvim/os/os_defs.h"
diff --git a/test/busted_runner.lua b/test/busted_runner.lua
new file mode 100644
index 0000000000..b195ce3cc5
--- /dev/null
+++ b/test/busted_runner.lua
@@ -0,0 +1 @@
+require 'busted.runner'({ standalone = false })
diff --git a/test/cmakeconfig/paths.lua.in b/test/cmakeconfig/paths.lua.in
index e3979981ba..a35dbe8901 100644
--- a/test/cmakeconfig/paths.lua.in
+++ b/test/cmakeconfig/paths.lua.in
@@ -6,8 +6,6 @@ for p in ("${TEST_INCLUDE_DIRS}" .. ";"):gmatch("[^;]+") do
end
module.test_build_dir = "${CMAKE_BINARY_DIR}"
-module.test_include_path = module.test_build_dir .. "/test/includes/post"
-module.test_libnvim_path = "${TEST_LIBNVIM_PATH}"
module.test_source_path = "${CMAKE_SOURCE_DIR}"
module.test_lua_prg = "${LUA_PRG}"
module.test_luajit_prg = ""
diff --git a/test/functional/api/highlight_spec.lua b/test/functional/api/highlight_spec.lua
index 541ac0ab63..7f044977cb 100644
--- a/test/functional/api/highlight_spec.lua
+++ b/test/functional/api/highlight_spec.lua
@@ -32,13 +32,16 @@ describe('API: highlight',function()
italic = true,
reverse = true,
underline = true,
- undercurl = true,
- underdouble = true,
- underdotted = true,
- underdashed = true,
strikethrough = true,
+ altfont = true,
nocombine = true,
}
+ local expected_undercurl = {
+ background = Screen.colors.Yellow,
+ foreground = Screen.colors.Red,
+ special = Screen.colors.Blue,
+ undercurl = true,
+ }
before_each(function()
clear()
@@ -59,9 +62,13 @@ describe('API: highlight',function()
eq('Invalid highlight id: 30000', string.match(emsg, 'Invalid.*'))
-- Test all highlight properties.
- command('hi NewHighlight gui=underline,bold,undercurl,underdouble,underdotted,underdashed,italic,reverse,strikethrough,nocombine')
+ command('hi NewHighlight gui=underline,bold,italic,reverse,strikethrough,altfont,nocombine')
eq(expected_rgb2, nvim("get_hl_by_id", hl_id, true))
+ -- Test undercurl
+ command('hi NewHighlight gui=undercurl')
+ eq(expected_undercurl, nvim("get_hl_by_id", hl_id, true))
+
-- Test nil argument.
err, emsg = pcall(meths.get_hl_by_id, { nil }, false)
eq(false, err)
@@ -207,17 +214,14 @@ describe("API: set highlight", function()
bold = true,
italic = true,
reverse = true,
- undercurl = true,
- underline = true,
underdashed = true,
- underdotted = true,
- underdouble = true,
strikethrough = true,
+ altfont = true,
cterm = {
italic = true,
reverse = true,
- undercurl = true,
strikethrough = true,
+ altfont = true,
nocombine = true,
}
}
@@ -227,20 +231,17 @@ describe("API: set highlight", function()
bold = true,
italic = true,
reverse = true,
- undercurl = true,
- underline = true,
underdashed = true,
- underdotted = true,
- underdouble = true,
strikethrough = true,
+ altfont = true,
}
local highlight3_result_cterm = {
background = highlight_color.ctermbg,
foreground = highlight_color.ctermfg,
italic = true,
reverse = true,
- undercurl = true,
strikethrough = true,
+ altfont = true,
nocombine = true,
}
@@ -296,7 +297,7 @@ describe("API: set highlight", function()
exec_capture('highlight Test_hl'))
meths.set_hl(0, 'Test_hl2', highlight3_config)
- eq('Test_hl2 xxx cterm=undercurl,italic,reverse,strikethrough,nocombine ctermfg=8 ctermbg=15 gui=bold,underline,undercurl,underdouble,underdotted,underdashed,italic,reverse,strikethrough guifg=#ff0000 guibg=#0032aa',
+ eq('Test_hl2 xxx cterm=italic,reverse,strikethrough,altfont,nocombine ctermfg=8 ctermbg=15 gui=bold,underdashed,italic,reverse,strikethrough,altfont guifg=#ff0000 guibg=#0032aa',
exec_capture('highlight Test_hl2'))
-- Colors are stored with the name they are defined, but
diff --git a/test/functional/api/server_notifications_spec.lua b/test/functional/api/server_notifications_spec.lua
index 833d54396b..53642858b2 100644
--- a/test/functional/api/server_notifications_spec.lua
+++ b/test/functional/api/server_notifications_spec.lua
@@ -1,4 +1,5 @@
local helpers = require('test.functional.helpers')(after_each)
+local assert_log = helpers.assert_log
local eq, clear, eval, command, nvim, next_msg =
helpers.eq, helpers.clear, helpers.eval, helpers.command, helpers.nvim,
helpers.next_msg
@@ -9,6 +10,8 @@ local is_ci = helpers.is_ci
local assert_alive = helpers.assert_alive
local skip = helpers.skip
+local testlog = 'Xtest-server-notify-log'
+
describe('notify', function()
local channel
@@ -17,6 +20,10 @@ describe('notify', function()
channel = nvim('get_api_info')[1]
end)
+ after_each(function()
+ os.remove(testlog)
+ end)
+
describe('passing a valid channel id', function()
it('sends the notification/args to the corresponding channel', function()
eval('rpcnotify('..channel..', "test-event", 1, 2, 3)')
@@ -72,8 +79,12 @@ describe('notify', function()
end)
it('unsubscribe non-existing event #8745', function()
+ clear{env={
+ NVIM_LOG_FILE=testlog,
+ }}
nvim('subscribe', 'event1')
nvim('unsubscribe', 'doesnotexist')
+ assert_log("tried to unsubscribe unknown event 'doesnotexist'", testlog, 10)
nvim('unsubscribe', 'event1')
assert_alive()
end)
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index aa2f46bb59..8fcdd9620b 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -166,7 +166,7 @@ describe('API', function()
echo nvim_exec('echo Avast_ye_hades(''ahoy!'')', 1)
]], true))
- eq('Vim(call):E5555: API call: Vim(echo):E121: Undefined variable: s:pirate',
+ matches('Vim%(echo%):E121: Undefined variable: s:pirate$',
pcall_err(request, 'nvim_exec', [[
let s:pirate = 'script-scoped varrrrr'
call nvim_exec('echo s:pirate', 1)
@@ -208,12 +208,12 @@ describe('API', function()
end)
it('execution error', function()
- eq('Vim:E492: Not an editor command: bogus_command',
+ eq('nvim_exec(): Vim:E492: Not an editor command: bogus_command',
pcall_err(request, 'nvim_exec', 'bogus_command', false))
eq('', nvim('eval', 'v:errmsg')) -- v:errmsg was not updated.
eq('', eval('v:exception'))
- eq('Vim(buffer):E86: Buffer 23487 does not exist',
+ eq('nvim_exec(): Vim(buffer):E86: Buffer 23487 does not exist',
pcall_err(request, 'nvim_exec', 'buffer 23487', false))
eq('', eval('v:errmsg')) -- v:errmsg was not updated.
eq('', eval('v:exception'))
@@ -485,7 +485,7 @@ describe('API', function()
throw 'wtf'
endfunction
]])
- eq('wtf', pcall_err(request, 'nvim_call_function', 'Foo', {}))
+ eq('function Foo, line 1: wtf', pcall_err(request, 'nvim_call_function', 'Foo', {}))
eq('', eval('v:exception'))
eq('', eval('v:errmsg')) -- v:errmsg was not updated.
end)
@@ -1807,9 +1807,11 @@ describe('API', function()
},
['jumps'] = eval(([[
- filter(map(getjumplist()[0], 'filter(
- { "f": expand("#".v:val.bufnr.":p"), "l": v:val.lnum },
- { k, v -> k != "l" || v != 1 })'), '!empty(v:val.f)')
+ filter(map(add(
+ getjumplist()[0], { 'bufnr': bufnr('%'), 'lnum': getcurpos()[1] }),
+ 'filter(
+ { "f": expand("#".v:val.bufnr.":p"), "l": v:val.lnum },
+ { k, v -> k != "l" || v != 1 })'), '!empty(v:val.f)')
]]):gsub('\n', '')),
['bufs'] = eval([[
@@ -3211,6 +3213,17 @@ describe('API', function()
'TextWithNoHighlight%#WarningMsg#TextWithWarningHighlight',
{ use_winbar = true, highlights = true }))
end)
+ it('no memory leak with click functions', function()
+ meths.eval_statusline('%@ClickFunc@StatusLineStringWithClickFunc%T', {})
+ eq({
+ str = 'StatusLineStringWithClickFunc',
+ width = 29
+ },
+ meths.eval_statusline(
+ '%@ClickFunc@StatusLineStringWithClickFunc%T',
+ {})
+ )
+ end)
end)
end)
describe('nvim_parse_cmd', function()
diff --git a/test/functional/autocmd/autocmd_spec.lua b/test/functional/autocmd/autocmd_spec.lua
index 90254b7415..fb5bab445c 100644
--- a/test/functional/autocmd/autocmd_spec.lua
+++ b/test/functional/autocmd/autocmd_spec.lua
@@ -9,6 +9,7 @@ local neq = helpers.neq
local eval = helpers.eval
local feed = helpers.feed
local clear = helpers.clear
+local matches = helpers.matches
local meths = helpers.meths
local pcall_err = helpers.pcall_err
local funcs = helpers.funcs
@@ -424,17 +425,50 @@ describe('autocmd', function()
end)
it('gives E814 when there are no other floating windows', function()
- eq('Vim(close):E814: Cannot close window, only autocmd window would remain',
+ eq('BufAdd Autocommands for "Xa.txt": Vim(close):E814: Cannot close window, only autocmd window would remain',
pcall_err(command, 'doautoall BufAdd'))
end)
it('gives E814 when there are other floating windows', function()
meths.open_win(0, true, {width = 10, height = 10, relative = 'editor', row = 10, col = 10})
- eq('Vim(close):E814: Cannot close window, only autocmd window would remain',
+ eq('BufAdd Autocommands for "Xa.txt": Vim(close):E814: Cannot close window, only autocmd window would remain',
pcall_err(command, 'doautoall BufAdd'))
end)
end)
+ it('closing `aucmd_win` using API gives E813', function()
+ exec_lua([[
+ vim.cmd('tabnew')
+ _G.buf = vim.api.nvim_create_buf(true, true)
+ ]])
+ matches('Vim:E813: Cannot close autocmd window$', pcall_err(exec_lua, [[
+ vim.api.nvim_buf_call(_G.buf, function()
+ local win = vim.api.nvim_get_current_win()
+ vim.api.nvim_win_close(win, true)
+ end)
+ ]]))
+ matches('Vim:E813: Cannot close autocmd window$', pcall_err(exec_lua, [[
+ vim.api.nvim_buf_call(_G.buf, function()
+ local win = vim.api.nvim_get_current_win()
+ vim.cmd('tabnext')
+ vim.api.nvim_win_close(win, true)
+ end)
+ ]]))
+ matches('Vim:E813: Cannot close autocmd window$', pcall_err(exec_lua, [[
+ vim.api.nvim_buf_call(_G.buf, function()
+ local win = vim.api.nvim_get_current_win()
+ vim.api.nvim_win_hide(win)
+ end)
+ ]]))
+ matches('Vim:E813: Cannot close autocmd window$', pcall_err(exec_lua, [[
+ vim.api.nvim_buf_call(_G.buf, function()
+ local win = vim.api.nvim_get_current_win()
+ vim.cmd('tabnext')
+ vim.api.nvim_win_hide(win)
+ end)
+ ]]))
+ end)
+
it(':doautocmd does not warn "No matching autocommands" #10689', function()
local screen = Screen.new(32, 3)
screen:attach()
@@ -476,14 +510,14 @@ describe('autocmd', function()
it('during RecordingLeave event', function()
command([[autocmd RecordingLeave * let v:event.regname = '']])
- eq('Vim(let):E46: Cannot change read-only variable "v:event.regname"',
+ eq('RecordingLeave Autocommands for "*": Vim(let):E46: Cannot change read-only variable "v:event.regname"',
pcall_err(command, 'normal! qqq'))
end)
it('during TermClose event', function()
command('autocmd TermClose * let v:event.status = 0')
command('terminal')
- eq('Vim(let):E46: Cannot change read-only variable "v:event.status"',
+ eq('TermClose Autocommands for "*": Vim(let):E46: Cannot change read-only variable "v:event.status"',
pcall_err(command, 'bdelete!'))
end)
end)
diff --git a/test/functional/autocmd/cmdline_spec.lua b/test/functional/autocmd/cmdline_spec.lua
index 60c29170e2..82fb9b9444 100644
--- a/test/functional/autocmd/cmdline_spec.lua
+++ b/test/functional/autocmd/cmdline_spec.lua
@@ -73,7 +73,7 @@ describe('cmdline autocommands', function()
{1:~ }|
{4: }|
: |
- {2:E5500: autocmd has thrown an exception: Vim(echoerr):FAIL} |
+ {2:CmdlineEnter Autocommands for "*": Vim(echoerr):FAIL} |
:^ |
]])
@@ -82,9 +82,9 @@ describe('cmdline autocommands', function()
|
{4: }|
: |
- {2:E5500: autocmd has thrown an exception: Vim(echoerr):FAIL} |
+ {2:CmdlineEnter Autocommands for "*": Vim(echoerr):FAIL} |
:put ='lorem ipsum' |
- {2:E5500: autocmd has thrown an exception: Vim(echoerr):very error} |
+ {2:CmdlineLeave Autocommands for "*": Vim(echoerr):very error} |
|
{3:Press ENTER or type command to continue}^ |
]])
@@ -111,9 +111,9 @@ describe('cmdline autocommands', function()
lorem ipsum |
{4: }|
: |
- {2:E5500: autocmd has thrown an exception: Vim(echoerr):FAIL} |
+ {2:CmdlineEnter Autocommands for "*": Vim(echoerr):FAIL} |
:put ='lorem ipsum' |
- {2:E5500: autocmd has thrown an exception: Vim(echoerr):change erreor} |
+ {2:CmdlineChanged Autocommands for "*": Vim(echoerr):change erreor} |
:put ='lorem ipsum'^ |
]])
@@ -123,9 +123,9 @@ describe('cmdline autocommands', function()
lorem ipsum |
{4: }|
: |
- {2:E5500: autocmd has thrown an exception: Vim(echoerr):FAIL} |
+ {2:CmdlineEnter Autocommands for "*": Vim(echoerr):FAIL} |
:put ='lorem ipsum' |
- {2:E5500: autocmd has thrown an exception: Vim(echoerr):change erreor} |
+ {2:CmdlineChanged Autocommands for "*": Vim(echoerr):change erreor} |
:put ='lorem ipsum^' |
]])
@@ -134,22 +134,22 @@ describe('cmdline autocommands', function()
screen:expect([[
{4: }|
: |
- {2:E5500: autocmd has thrown an exception: Vim(echoerr):FAIL} |
+ {2:CmdlineEnter Autocommands for "*": Vim(echoerr):FAIL} |
:put ='lorem ipsum' |
- {2:E5500: autocmd has thrown an exception: Vim(echoerr):change erreor} |
+ {2:CmdlineChanged Autocommands for "*": Vim(echoerr):change erreor} |
:put ='lorem ipsum.' |
- {2:E5500: autocmd has thrown an exception: Vim(echoerr):change erreor} |
+ {2:CmdlineChanged Autocommands for "*": Vim(echoerr):change erreor} |
:put ='lorem ipsum.^' |
]])
feed('<cr>')
screen:expect([[
:put ='lorem ipsum' |
- {2:E5500: autocmd has thrown an exception: Vim(echoerr):change erreor} |
+ {2:CmdlineChanged Autocommands for "*": Vim(echoerr):change erreor} |
:put ='lorem ipsum.' |
- {2:E5500: autocmd has thrown an exception: Vim(echoerr):change erreor} |
+ {2:CmdlineChanged Autocommands for "*": Vim(echoerr):change erreor} |
:put ='lorem ipsum.' |
- {2:E5500: autocmd has thrown an exception: Vim(echoerr):very error} |
+ {2:CmdlineLeave Autocommands for "*": Vim(echoerr):very error} |
|
{3:Press ENTER or type command to continue}^ |
]])
diff --git a/test/functional/autocmd/termxx_spec.lua b/test/functional/autocmd/termxx_spec.lua
index 4717b1fa2e..0a33f1b2ac 100644
--- a/test/functional/autocmd/termxx_spec.lua
+++ b/test/functional/autocmd/termxx_spec.lua
@@ -24,7 +24,7 @@ describe('autocmd TermClose', function()
local function test_termclose_delete_own_buf()
command('autocmd TermClose * bdelete!')
command('terminal')
- matches('^Vim%(bdelete%):E937: Attempt to delete a buffer that is in use: term://',
+ matches('^TermClose Autocommands for "%*": Vim%(bdelete%):E937: Attempt to delete a buffer that is in use: term://',
pcall_err(command, 'bdelete!'))
assert_alive()
end
diff --git a/test/functional/core/exit_spec.lua b/test/functional/core/exit_spec.lua
index 8cad7adfa6..05a69e1992 100644
--- a/test/functional/core/exit_spec.lua
+++ b/test/functional/core/exit_spec.lua
@@ -89,14 +89,14 @@ describe(':cquit', function()
end)
it('exits with redir msg for multiple exit codes after :cquit 1 2', function()
- test_cq('cquit 1 2', nil, 'Vim(cquit):E488: Trailing characters: 2: cquit 1 2')
+ test_cq('cquit 1 2', nil, 'nvim_exec(): Vim(cquit):E488: Trailing characters: 2: cquit 1 2')
end)
it('exits with redir msg for non-number exit code after :cquit X', function()
- test_cq('cquit X', nil, 'Vim(cquit):E488: Trailing characters: X: cquit X')
+ test_cq('cquit X', nil, 'nvim_exec(): Vim(cquit):E488: Trailing characters: X: cquit X')
end)
it('exits with redir msg for negative exit code after :cquit -1', function()
- test_cq('cquit -1', nil, 'Vim(cquit):E488: Trailing characters: -1: cquit -1')
+ test_cq('cquit -1', nil, 'nvim_exec(): Vim(cquit):E488: Trailing characters: -1: cquit -1')
end)
end)
diff --git a/test/functional/core/fileio_spec.lua b/test/functional/core/fileio_spec.lua
index ed37032f25..4e9891a4de 100644
--- a/test/functional/core/fileio_spec.lua
+++ b/test/functional/core/fileio_spec.lua
@@ -22,6 +22,7 @@ local tmpname = helpers.tmpname
local trim = helpers.trim
local currentdir = helpers.funcs.getcwd
local assert_alive = helpers.assert_alive
+local check_close = helpers.check_close
local expect_exit = helpers.expect_exit
local write_file = helpers.write_file
local Screen = require('test.functional.ui.screen')
@@ -34,7 +35,7 @@ describe('fileio', function()
before_each(function()
end)
after_each(function()
- expect_exit(command, ':qall!')
+ check_close()
os.remove('Xtest_startup_shada')
os.remove('Xtest_startup_file1')
os.remove('Xtest_startup_file1~')
@@ -270,7 +271,7 @@ describe('tmpdir', function()
end)
after_each(function()
- expect_exit(command, ':qall!')
+ check_close()
os.remove(testlog)
end)
@@ -294,9 +295,7 @@ describe('tmpdir', function()
clear({ env={ NVIM_LOG_FILE=testlog, TMPDIR=faketmp, } })
matches(tmproot_pat, funcs.stdpath('run')) -- Tickle vim_mktempdir().
-- Assert that broken tmpdir root was handled.
- retry(nil, 1000, function()
- assert_log('tempdir root not a directory', testlog, 100)
- end)
+ assert_log('tempdir root not a directory', testlog, 100)
-- "…/nvim.<user>/" has wrong permissions:
skip(is_os('win'), 'TODO(justinmk): need setfperm/getfperm on Windows. #8244')
@@ -307,9 +306,7 @@ describe('tmpdir', function()
clear({ env={ NVIM_LOG_FILE=testlog, TMPDIR=faketmp, } })
matches(tmproot_pat, funcs.stdpath('run')) -- Tickle vim_mktempdir().
-- Assert that broken tmpdir root was handled.
- retry(nil, 1000, function()
- assert_log('tempdir root has invalid permissions', testlog, 100)
- end)
+ assert_log('tempdir root has invalid permissions', testlog, 100)
end)
it('too long', function()
diff --git a/test/functional/core/log_spec.lua b/test/functional/core/log_spec.lua
index 3b1ccd9559..f682df4155 100644
--- a/test/functional/core/log_spec.lua
+++ b/test/functional/core/log_spec.lua
@@ -6,7 +6,6 @@ local eq = helpers.eq
local exec_lua = helpers.exec_lua
local expect_exit = helpers.expect_exit
local request = helpers.request
-local retry = helpers.retry
describe('log', function()
local testlog = 'Xtest_logging'
@@ -40,9 +39,7 @@ describe('log', function()
}})
local tid = _G._nvim_test_id
- retry(nil, 1000, function()
- assert_log(tid..'%.%d+%.%d +server_init:%d+: test log message', testlog, 100)
- end)
+ assert_log(tid..'%.%d+%.%d +server_init:%d+: test log message', testlog, 100)
exec_lua([[
local j1 = vim.fn.jobstart({ vim.v.progpath, '-es', '-V1', '+foochild', '+qa!' }, vim.empty_dict())
@@ -50,8 +47,6 @@ describe('log', function()
]])
-- Child Nvim spawned by jobstart() appends "/c" to parent name.
- retry(nil, 1000, function()
- assert_log('%.%d+%.%d/c +server_init:%d+: test log message', testlog, 100)
- end)
+ assert_log('%.%d+%.%d/c +server_init:%d+: test log message', testlog, 100)
end)
end)
diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua
index 9dabcd28b3..e9b47a0251 100644
--- a/test/functional/core/startup_spec.lua
+++ b/test/functional/core/startup_spec.lua
@@ -43,10 +43,8 @@ describe('startup', function()
it('--startuptime', function()
clear({ args = {'--startuptime', testfile}})
- retry(nil, 1000, function()
- assert_log('sourcing', testfile, 100)
- assert_log("require%('vim%._editor'%)", testfile, 100)
- end)
+ assert_log('sourcing', testfile, 100)
+ assert_log("require%('vim%._editor'%)", testfile, 100)
end)
it('-D does not hang #12647', function()
@@ -104,6 +102,13 @@ describe('startup', function()
end)
it('os.exit() sets Nvim exitcode', function()
+ -- tricky: LeakSanitizer triggers on os.exit() and disrupts the return value, disable it
+ exec_lua [[
+ local asan_options = os.getenv 'ASAN_OPTIONS'
+ if asan_options ~= nil and asan_options ~= '' then
+ vim.loop.os_setenv('ASAN_OPTIONS', asan_options..':detect_leaks=0')
+ end
+ ]]
-- nvim -l foo.lua -arg1 -- a b c
assert_l_out([[
bufs:
diff --git a/test/functional/editor/completion_spec.lua b/test/functional/editor/completion_spec.lua
index c503d7ebfb..22857efe5b 100644
--- a/test/functional/editor/completion_spec.lua
+++ b/test/functional/editor/completion_spec.lua
@@ -935,6 +935,9 @@ describe('completion', function()
eq({'api'}, funcs.getcompletion('vim.ap', 'lua'))
eq({'tbl_filter'}, funcs.getcompletion('vim.tbl_fil', 'lua'))
eq({'vim'}, funcs.getcompletion('print(vi', 'lua'))
+ -- fuzzy completion is not supported, so the result should be the same
+ command('set wildoptions+=fuzzy')
+ eq({'vim'}, funcs.getcompletion('vi', 'lua'))
end)
end)
diff --git a/test/functional/editor/mark_spec.lua b/test/functional/editor/mark_spec.lua
index f300fea3a0..b3b190ef79 100644
--- a/test/functional/editor/mark_spec.lua
+++ b/test/functional/editor/mark_spec.lua
@@ -40,59 +40,59 @@ describe('named marks', function()
it("errors when set out of range with :mark", function()
command("edit " .. file1)
local err = pcall_err(helpers.exec_capture, "1000mark x")
- eq("Vim(mark):E16: Invalid range: 1000mark x", err)
+ eq("nvim_exec(): Vim(mark):E16: Invalid range: 1000mark x", err)
end)
it("errors when set out of range with :k", function()
command("edit " .. file1)
local err = pcall_err(helpers.exec_capture, "1000kx")
- eq("Vim(k):E16: Invalid range: 1000kx", err)
+ eq("nvim_exec(): Vim(k):E16: Invalid range: 1000kx", err)
end)
it("errors on unknown mark name with :mark", function()
command("edit " .. file1)
local err = pcall_err(helpers.exec_capture, "mark #")
- eq("Vim(mark):E191: Argument must be a letter or forward/backward quote", err)
+ eq("nvim_exec(): Vim(mark):E191: Argument must be a letter or forward/backward quote", err)
end)
it("errors on unknown mark name with '", function()
command("edit " .. file1)
local err = pcall_err(helpers.exec_capture, "normal! '#")
- eq("Vim(normal):E78: Unknown mark", err)
+ eq("nvim_exec(): Vim(normal):E78: Unknown mark", err)
end)
it("errors on unknown mark name with `", function()
command("edit " .. file1)
local err = pcall_err(helpers.exec_capture, "normal! `#")
- eq("Vim(normal):E78: Unknown mark", err)
+ eq("nvim_exec(): Vim(normal):E78: Unknown mark", err)
end)
it("errors when moving to a mark that is not set with '", function()
command("edit " .. file1)
local err = pcall_err(helpers.exec_capture, "normal! 'z")
- eq("Vim(normal):E20: Mark not set", err)
+ eq("nvim_exec(): Vim(normal):E20: Mark not set", err)
err = pcall_err(helpers.exec_capture, "normal! '.")
- eq("Vim(normal):E20: Mark not set", err)
+ eq("nvim_exec(): Vim(normal):E20: Mark not set", err)
end)
it("errors when moving to a mark that is not set with `", function()
command("edit " .. file1)
local err = pcall_err(helpers.exec_capture, "normal! `z")
- eq("Vim(normal):E20: Mark not set", err)
+ eq("nvim_exec(): Vim(normal):E20: Mark not set", err)
err = pcall_err(helpers.exec_capture, "normal! `>")
- eq("Vim(normal):E20: Mark not set", err)
+ eq("nvim_exec(): Vim(normal):E20: Mark not set", err)
end)
it("errors when moving to a global mark that is not set with '", function()
command("edit " .. file1)
local err = pcall_err(helpers.exec_capture, "normal! 'Z")
- eq("Vim(normal):E20: Mark not set", err)
+ eq("nvim_exec(): Vim(normal):E20: Mark not set", err)
end)
it("errors when moving to a global mark that is not set with `", function()
command("edit " .. file1)
local err = pcall_err(helpers.exec_capture, "normal! `Z")
- eq("Vim(normal):E20: Mark not set", err)
+ eq("nvim_exec(): Vim(normal):E20: Mark not set", err)
end)
it("can move to them using '", function()
@@ -153,7 +153,7 @@ describe('named marks', function()
command("next")
command("bw! " .. file1 )
local err = pcall_err(helpers.exec_capture, "normal! 'A")
- eq("Vim(normal):E92: Buffer 1 not found", err)
+ eq("nvim_exec(): Vim(normal):E92: Buffer 1 not found", err)
os.remove(file1)
end)
diff --git a/test/functional/fixtures/fake-lsp-server.lua b/test/functional/fixtures/fake-lsp-server.lua
index aa47198f7a..db0c8c0c3f 100644
--- a/test/functional/fixtures/fake-lsp-server.lua
+++ b/test/functional/fixtures/fake-lsp-server.lua
@@ -927,10 +927,13 @@ function tests.basic_formatting()
}
end
--- Tests will be indexed by TEST_NAME
+-- Tests will be indexed by test_name
+local test_name = arg[1]
+local timeout = arg[2]
+assert(type(test_name) == 'string', 'test_name must be specified as first arg.')
local kill_timer = vim.loop.new_timer()
-kill_timer:start(_G.TIMEOUT or 1e3, 0, function()
+kill_timer:start(timeout or 1e3, 0, function()
kill_timer:stop()
kill_timer:close()
log('ERROR', 'LSP', 'TIMEOUT')
@@ -938,14 +941,11 @@ kill_timer:start(_G.TIMEOUT or 1e3, 0, function()
os.exit(100)
end)
-local test_name = _G.TEST_NAME -- lualint workaround
-assert(type(test_name) == 'string', 'TEST_NAME must be specified.')
local status, err = pcall(assert(tests[test_name], "Test not found"))
kill_timer:stop()
kill_timer:close()
if not status then
log('ERROR', 'LSP', tostring(err))
io.stderr:write(err)
- os.exit(101)
+ vim.cmd [[101cquit]]
end
-os.exit(0)
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index a14bedbbbd..6400db9f87 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -1,5 +1,4 @@
require('coxpcall')
-local busted = require('busted')
local luv = require('luv')
local lfs = require('lfs')
local mpack = require('mpack')
@@ -397,9 +396,12 @@ local function remove_args(args, args_rm)
return new_args
end
-function module.check_close(old_session)
+function module.check_close()
+ if not session then
+ return
+ end
local start_time = luv.now()
- old_session:close()
+ session:close()
luv.update_time() -- Update cached value of luv.now() (libuv: uv_now()).
local end_time = luv.now()
local delta = end_time - start_time
@@ -408,12 +410,13 @@ function module.check_close(old_session)
"This indicates a likely problem with the test even if it passed!\n")
io.stdout:flush()
end
+ session = nil
end
--- @param io_extra used for stdin_fd, see :help ui-option
function module.spawn(argv, merge, env, keep, io_extra)
- if session and not keep then
- module.check_close(session)
+ if not keep then
+ module.check_close()
end
local child_stream = ChildProcessStream.spawn(
@@ -430,28 +433,6 @@ function module.connect(file_or_address)
return Session.new(stream)
end
--- Calls fn() until it succeeds, up to `max` times or until `max_ms`
--- milliseconds have passed.
-function module.retry(max, max_ms, fn)
- assert(max == nil or max > 0)
- assert(max_ms == nil or max_ms > 0)
- local tries = 1
- local timeout = (max_ms and max_ms or 10000)
- local start_time = luv.now()
- while true do
- local status, result = pcall(fn)
- if status then
- return result
- end
- luv.update_time() -- Update cached value of luv.now() (libuv: uv_now()).
- if (max and tries >= max) or (luv.now() - start_time > timeout) then
- busted.fail(string.format("retry() attempts: %d\n%s", tries, tostring(result)), 2)
- end
- tries = tries + 1
- luv.sleep(20) -- Avoid hot loop...
- end
-end
-
-- Starts a new global Nvim session.
--
-- Parameters are interpreted as startup args, OR a map with these keys:
diff --git a/test/functional/legacy/055_list_and_dict_types_spec.lua b/test/functional/legacy/055_list_and_dict_types_spec.lua
index c0ff3ed17a..75294b3786 100644
--- a/test/functional/legacy/055_list_and_dict_types_spec.lua
+++ b/test/functional/legacy/055_list_and_dict_types_spec.lua
@@ -330,214 +330,6 @@ describe('list and dictionary types', function()
same list: 1]])
end)
- it('locked variables (part 1)', function()
- source([=[
- let l = []
- for depth in range(5)
- $put ='depth is ' . depth
- for u in range(3)
- unlet l
- let l = [0, [1, [2, 3]], {4: 5, 6: {7: 8}}]
- exe "lockvar " . depth . " l"
- if u == 1
- exe "unlockvar l"
- elseif u == 2
- exe "unlockvar " . depth . " l"
- endif
- let ps = islocked("l") . islocked("l[1]") . islocked("l[1][1]") .
- \ islocked("l[1][1][0]") . '-' . islocked("l[2]") .
- \ islocked("l[2]['6']") . islocked("l[2]['6'][7]")
- $put =ps
- let ps = ''
- try
- let l[1][1][0] = 99
- let ps .= 'p'
- catch
- let ps .= 'F'
- endtry
- try
- let l[1][1] = [99]
- let ps .= 'p'
- catch
- let ps .= 'F'
- endtry
- try
- let l[1] = [99]
- let ps .= 'p'
- catch
- let ps .= 'F'
- endtry
- try
- let l[2]['6'][7] = 99
- let ps .= 'p'
- catch
- let ps .= 'F'
- endtry
- try
- let l[2][6] = {99: 99}
- let ps .= 'p'
- catch
- let ps .= 'F'
- endtry
- try
- let l[2] = {99: 99}
- let ps .= 'p'
- catch
- let ps .= 'F'
- endtry
- try
- let l = [99]
- let ps .= 'p'
- catch
- let ps .= 'F'
- endtry
- $put =ps
- endfor
- endfor]=])
- expect([[
-
- depth is 0
- 0000-000
- ppppppp
- 0000-000
- ppppppp
- 0000-000
- ppppppp
- depth is 1
- 1000-000
- ppppppF
- 0000-000
- ppppppp
- 0000-000
- ppppppp
- depth is 2
- 1100-100
- ppFppFF
- 0000-000
- ppppppp
- 0000-000
- ppppppp
- depth is 3
- 1110-110
- pFFpFFF
- 0010-010
- pFppFpp
- 0000-000
- ppppppp
- depth is 4
- 1111-111
- FFFFFFF
- 0011-011
- FFpFFpp
- 0000-000
- ppppppp]])
- end)
-
- -- TODO In the original test the 5th line of this source() call was used.
- -- But now the test only passes if I comment it.
- it('unletting locked variables', function()
- source([=[
- let l = []
- for depth in range(5)
- $put ='depth is ' . depth
- for u in range(3)
- "unlet l
- let l = [0, [1, [2, 3]], {4: 5, 6: {7: 8}}]
- exe "lockvar " . depth . " l"
- if u == 1
- exe "unlockvar l"
- elseif u == 2
- exe "unlockvar " . depth . " l"
- endif
- let ps = islocked("l") . islocked("l[1]") . islocked("l[1][1]") .
- \ islocked("l[1][1][0]") . '-' . islocked("l[2]") .
- \ islocked("l[2]['6']") . islocked("l[2]['6'][7]")
- $put =ps
- let ps = ''
- try
- unlet l[2]['6'][7]
- let ps .= 'p'
- catch
- let ps .= 'F'
- endtry
- try
- unlet l[2][6]
- let ps .= 'p'
- catch
- let ps .= 'F'
- endtry
- try
- unlet l[2]
- let ps .= 'p'
- catch
- let ps .= 'F'
- endtry
- try
- unlet l[1][1][0]
- let ps .= 'p'
- catch
- let ps .= 'F'
- endtry
- try
- unlet l[1][1]
- let ps .= 'p'
- catch
- let ps .= 'F'
- endtry
- try
- unlet l[1]
- let ps .= 'p'
- catch
- let ps .= 'F'
- endtry
- try
- unlet l
- let ps .= 'p'
- catch
- let ps .= 'F'
- endtry
- $put =ps
- endfor
- endfor]=])
- expect([[
-
- depth is 0
- 0000-000
- ppppppp
- 0000-000
- ppppppp
- 0000-000
- ppppppp
- depth is 1
- 1000-000
- ppFppFp
- 0000-000
- ppppppp
- 0000-000
- ppppppp
- depth is 2
- 1100-100
- pFFpFFp
- 0000-000
- ppppppp
- 0000-000
- ppppppp
- depth is 3
- 1110-110
- FFFFFFp
- 0010-010
- FppFppp
- 0000-000
- ppppppp
- depth is 4
- 1111-111
- FFFFFFp
- 0011-011
- FppFppp
- 0000-000
- ppppppp]])
- end)
-
it('locked variables and :unlet or list / dict functions', function()
source([[
$put ='Locks and commands or functions:'
@@ -676,30 +468,6 @@ describe('list and dictionary types', function()
['a', 'b', 3]]=])
end)
- it('locked variables (part 2)', function()
- feed_command(
- 'let l = [1, 2, 3, 4]',
- 'lockvar! l',
- '$put =string(l)',
- 'unlockvar l[1]',
- 'unlet l[0:1]',
- '$put =string(l)',
- 'unlet l[1:2]',
- '$put =string(l)',
- 'unlockvar l[1]',
- 'let l[0:1] = [0, 1]',
- '$put =string(l)',
- 'let l[1:2] = [0, 1]',
- '$put =string(l)')
- expect([=[
-
- [1, 2, 3, 4]
- [1, 2, 3, 4]
- [1, 2, 3, 4]
- [1, 2, 3, 4]
- [1, 2, 3, 4]]=])
- end)
-
it(':lockvar/islocked() triggering script autoloading.', function()
source([[
set rtp+=test/functional/fixtures
diff --git a/test/functional/legacy/gf_spec.lua b/test/functional/legacy/gf_spec.lua
index f1b1790ba1..9f725446be 100644
--- a/test/functional/legacy/gf_spec.lua
+++ b/test/functional/legacy/gf_spec.lua
@@ -10,6 +10,7 @@ describe('gf', function()
it('is not allowed when buffer is locked', function()
command('au OptionSet diff norm! gf')
command([[call setline(1, ['Xfile1', 'line2', 'line3', 'line4'])]])
- eq('Vim(normal):E788: Not allowed to edit another buffer now', pcall_err(command, 'diffthis'))
+ eq('OptionSet Autocommands for "diff": Vim(normal):E788: Not allowed to edit another buffer now',
+ pcall_err(command, 'diffthis'))
end)
end)
diff --git a/test/functional/legacy/syn_attr_spec.lua b/test/functional/legacy/syn_attr_spec.lua
index 06e8427e27..e6573da5d3 100644
--- a/test/functional/legacy/syn_attr_spec.lua
+++ b/test/functional/legacy/syn_attr_spec.lua
@@ -4,10 +4,10 @@ local command = helpers.command
local eq = helpers.eq
local eval = helpers.eval
-before_each(clear)
-
-- oldtest: Test_missing_attr()
-it('synIDattr() works', function()
+describe('synIDattr()', function()
+ setup(clear)
+
local bool_attrs = {
'bold',
'italic',
@@ -22,39 +22,55 @@ it('synIDattr() works', function()
'nocombine',
}
- command('hi Mine cterm=NONE gui=NONE')
- eq('Mine', eval([[synIDattr(hlID("Mine"), "name")]]))
- for _, mode in ipairs({'cterm', 'gui'}) do
- eq('', eval(([[synIDattr("Mine"->hlID(), "bg", '%s')]]):format(mode)))
- eq('', eval(([[synIDattr("Mine"->hlID(), "fg", '%s')]]):format(mode)))
- eq('', eval(([[synIDattr("Mine"->hlID(), "sp", '%s')]]):format(mode)))
- for _, attr in ipairs(bool_attrs) do
- eq('', eval(([[synIDattr(hlID("Mine"), "%s", '%s')]]):format(attr, mode)))
- eq('', eval(([[synIDattr(hlID("Mine"), "%s", '%s')]]):format(attr, mode)))
- eq('', eval(([[synIDattr(hlID("Mine"), "%s", '%s')]]):format(attr, mode)))
+ describe(':hi Mine cterm=NONE gui=NONE', function()
+ setup(function()
+ command(':hi Mine cterm=NONE gui=NONE')
+ end)
+
+ it('"name"', function()
+ eq('Mine', eval([[synIDattr(hlID("Mine"), "name")]]))
+ end)
+
+ local function none_test(attr, mode)
+ it(('"%s"'):format(attr), function()
+ eq('', eval(([[synIDattr(hlID("Mine"), "%s", '%s')]]):format(attr, mode)))
+ end)
end
- eq('', eval(([[synIDattr(hlID("Mine"), "inverse", '%s')]]):format(mode)))
+
+ for _, mode in ipairs({'cterm', 'gui'}) do
+ describe(('"%s"'):format(mode), function()
+ for _, attr in ipairs(bool_attrs) do
+ none_test(attr, mode)
+ end
+ for _, attr in ipairs({'inverse', 'bg', 'fg', 'sp'}) do
+ none_test(attr, mode)
+ end
+ end)
+ end
+ end)
+
+ local function attr_test(attr1, attr2)
+ local cmd = (':hi Mine cterm=%s gui=%s'):format(attr1, attr2)
+ it(cmd, function()
+ command(cmd)
+ eq('1', eval(([[synIDattr("Mine"->hlID(), "%s", 'cterm')]]):format(attr1)))
+ eq('', eval(([[synIDattr(hlID("Mine"), "%s", 'cterm')]]):format(attr2)))
+ eq('', eval(([[synIDattr("Mine"->hlID(), "%s", 'gui')]]):format(attr1)))
+ eq('1', eval(([[synIDattr(hlID("Mine"), "%s", 'gui')]]):format(attr2)))
+ end)
end
for i, attr1 in ipairs(bool_attrs) do
local attr2 = bool_attrs[i - 1] or bool_attrs[#bool_attrs]
-
- command(('hi Mine cterm=%s gui=%s'):format(attr1, attr2))
- eq('1', eval(([[synIDattr(hlID("Mine"), "%s", 'cterm')]]):format(attr1)))
- eq('', eval(([[synIDattr(hlID("Mine"), "%s", 'cterm')]]):format(attr2)))
- eq('', eval(([[synIDattr("Mine"->hlID(), "%s", 'gui')]]):format(attr1)))
- eq('1', eval(([[synIDattr("Mine"->hlID(), "%s", 'gui')]]):format(attr2)))
-
- command(('hi Mine cterm=%s gui=%s'):format(attr2, attr1))
- eq('', eval(([[synIDattr("Mine"->hlID(), "%s", 'cterm')]]):format(attr1)))
- eq('1', eval(([[synIDattr("Mine"->hlID(), "%s", 'cterm')]]):format(attr2)))
- eq('1', eval(([[synIDattr(hlID("Mine"), "%s", 'gui')]]):format(attr1)))
- eq('', eval(([[synIDattr(hlID("Mine"), "%s", 'gui')]]):format(attr2)))
+ attr_test(attr1, attr2)
+ attr_test(attr2, attr1)
end
- command('hi Mine cterm=reverse gui=inverse')
- eq('1', eval([[synIDattr(hlID("Mine"), "reverse", 'cterm')]]))
- eq('1', eval([[synIDattr(hlID("Mine"), "inverse", 'cterm')]]))
- eq('1', eval([[synIDattr(hlID("Mine"), "reverse", 'gui')]]))
- eq('1', eval([[synIDattr(hlID("Mine"), "inverse", 'gui')]]))
+ it(':hi Mine cterm=reverse gui=inverse', function()
+ command(':hi Mine cterm=reverse gui=inverse')
+ eq('1', eval([[synIDattr(hlID("Mine"), "reverse", 'cterm')]]))
+ eq('1', eval([[synIDattr(hlID("Mine"), "inverse", 'cterm')]]))
+ eq('1', eval([[synIDattr(hlID("Mine"), "reverse", 'gui')]]))
+ eq('1', eval([[synIDattr(hlID("Mine"), "inverse", 'gui')]]))
+ end)
end)
diff --git a/test/functional/lua/runtime_spec.lua b/test/functional/lua/runtime_spec.lua
index e9c34c9228..884ef3ef8e 100644
--- a/test/functional/lua/runtime_spec.lua
+++ b/test/functional/lua/runtime_spec.lua
@@ -4,6 +4,7 @@ local clear = helpers.clear
local eq = helpers.eq
local eval = helpers.eval
local exec = helpers.exec
+local funcs = helpers.funcs
local mkdir_p = helpers.mkdir_p
local rmdir = helpers.rmdir
local write_file = helpers.write_file
@@ -17,6 +18,7 @@ describe('runtime:', function()
io.open(init, 'w'):close() -- touch init file
clear{args = {'-u', init}}
exec('set rtp+=' .. plug_dir)
+ exec('set completeslash=slash')
end)
teardown(function()
@@ -29,6 +31,7 @@ describe('runtime:', function()
after_each(function()
rmdir(plug_dir)
+ exec('bwipe!')
end)
describe('colors', function()
@@ -39,6 +42,9 @@ describe('runtime:', function()
mkdir_p(colorscheme_folder)
write_file(colorscheme_file, [[vim.g.lua_colorscheme = 1]])
+ eq({'new_colorscheme'}, funcs.getcompletion('new_c', 'color'))
+ eq({'colors/new_colorscheme.lua'}, funcs.getcompletion('colors/new_c', 'runtime'))
+
exec('colorscheme new_colorscheme')
eq(1, eval('g:lua_colorscheme'))
@@ -64,23 +70,26 @@ describe('runtime:', function()
it('loads lua compilers', function()
local compiler_file = compiler_folder .. sep .. 'new_compiler.lua'
mkdir_p(compiler_folder)
- write_file(compiler_file, [[vim.g.lua_compiler = 1]])
+ write_file(compiler_file, [[vim.b.lua_compiler = 1]])
+
+ eq({'new_compiler'}, funcs.getcompletion('new_c', 'compiler'))
+ eq({'compiler/new_compiler.lua'}, funcs.getcompletion('compiler/new_c', 'runtime'))
exec('compiler new_compiler')
- eq(1, eval('g:lua_compiler'))
+ eq(1, eval('b:lua_compiler'))
rmdir(compiler_folder)
end)
it('loads vim compilers when both lua and vim version exist', function()
local compiler_file = compiler_folder .. sep .. 'new_compiler'
mkdir_p(compiler_folder)
- write_file(compiler_file..'.vim', [[let g:compiler = 'vim']])
- write_file(compiler_file..'.lua', [[vim.g.compiler = 'lua']])
+ write_file(compiler_file..'.vim', [[let b:compiler = 'vim']])
+ write_file(compiler_file..'.lua', [[vim.b.compiler = 'lua']])
exec('compiler new_compiler')
- eq('vim', eval('g:compiler'))
+ eq('vim', eval('b:compiler'))
rmdir(compiler_folder)
end)
end)
@@ -91,10 +100,13 @@ describe('runtime:', function()
it('loads lua ftplugins', function()
local ftplugin_file = table.concat({ftplugin_folder , 'new-ft.lua'}, sep)
mkdir_p(ftplugin_folder)
- write_file(ftplugin_file , [[vim.g.lua_ftplugin = 1]])
+ write_file(ftplugin_file , [[vim.b.lua_ftplugin = 1]])
+
+ eq({'new-ft'}, funcs.getcompletion('new-f', 'filetype'))
+ eq({'ftplugin/new-ft.lua'}, funcs.getcompletion('ftplugin/new-f', 'runtime'))
exec [[set filetype=new-ft]]
- eq(1, eval('g:lua_ftplugin'))
+ eq(1, eval('b:lua_ftplugin'))
rmdir(ftplugin_folder)
end)
end)
@@ -105,10 +117,13 @@ describe('runtime:', function()
it('loads lua indents', function()
local indent_file = table.concat({indent_folder , 'new-ft.lua'}, sep)
mkdir_p(indent_folder)
- write_file(indent_file , [[vim.g.lua_indent = 1]])
+ write_file(indent_file , [[vim.b.lua_indent = 1]])
+
+ eq({'new-ft'}, funcs.getcompletion('new-f', 'filetype'))
+ eq({'indent/new-ft.lua'}, funcs.getcompletion('indent/new-f', 'runtime'))
exec [[set filetype=new-ft]]
- eq(1, eval('g:lua_indent'))
+ eq(1, eval('b:lua_indent'))
rmdir(indent_folder)
end)
end)
@@ -116,24 +131,33 @@ describe('runtime:', function()
describe('syntax', function()
local syntax_folder = table.concat({plug_dir, 'syntax'}, sep)
- it('loads lua syntaxes on filetype change', function()
+ before_each(function()
local syntax_file = table.concat({syntax_folder , 'my-lang.lua'}, sep)
mkdir_p(syntax_folder)
- write_file(syntax_file , [[vim.g.lua_syntax = 1]])
+ write_file(syntax_file , [[vim.b.current_syntax = 'my-lang']])
+ exec([[let b:current_syntax = '']])
+ end)
+ it('loads lua syntaxes on filetype change', function()
exec('set filetype=my-lang')
- eq(1, eval('g:lua_syntax'))
- rmdir(syntax_folder)
+ eq('my-lang', eval('b:current_syntax'))
end)
it('loads lua syntaxes on syntax change', function()
- local syntax_file = table.concat({syntax_folder , 'my-lang.lua'}, sep)
- mkdir_p(syntax_folder)
- write_file(syntax_file , [[vim.g.lua_syntax = 5]])
-
exec('set syntax=my-lang')
- eq(5, eval('g:lua_syntax'))
- rmdir(syntax_folder)
+ eq('my-lang', eval('b:current_syntax'))
+ end)
+
+ it('loads lua syntaxes for :ownsyntax', function()
+ exec('ownsyntax my-lang')
+ eq('my-lang', eval('w:current_syntax'))
+ eq('', eval('b:current_syntax'))
+ end)
+
+ it('lua syntaxes are included in cmdline completion', function()
+ eq({'my-lang'}, funcs.getcompletion('my-l', 'filetype'))
+ eq({'my-lang'}, funcs.getcompletion('my-l', 'syntax'))
+ eq({'syntax/my-lang.lua'}, funcs.getcompletion('syntax/my-l', 'runtime'))
end)
end)
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index 90eccc49c8..867f366d06 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -2,6 +2,7 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
+local nvim_prog = helpers.nvim_prog
local funcs = helpers.funcs
local meths = helpers.meths
local command = helpers.command
@@ -22,7 +23,6 @@ local remove_trace = helpers.remove_trace
local mkdir_p = helpers.mkdir_p
local rmdir = helpers.rmdir
local write_file = helpers.write_file
-local expect_exit = helpers.expect_exit
local poke_eventloop = helpers.poke_eventloop
local assert_alive = helpers.assert_alive
@@ -763,6 +763,20 @@ describe('lua stdlib', function()
pcall_err(exec_lua, code))
end)
+ it('vim.spairs', function()
+ local res = ''
+ local table = {
+ ccc=1,
+ bbb=2,
+ ddd=3,
+ aaa=4
+ }
+ for key, _ in vim.spairs(table) do
+ res = res .. key
+ end
+ matches('aaabbbcccddd', res)
+ end)
+
it('vim.call, vim.fn', function()
eq(true, exec_lua([[return vim.call('sin', 0.0) == 0.0 ]]))
eq(true, exec_lua([[return vim.fn.sin(0.0) == 0.0 ]]))
@@ -2910,9 +2924,14 @@ describe('lua: builtin modules', function()
end)
- it('does not work when disabled without runtime', function()
- clear{args={'--luamod-dev'}, env={VIMRUNTIME='fixtures/a'}}
- expect_exit(exec_lua, [[return vim.tbl_count {x=1,y=2}]])
+ it('fails when disabled without runtime', function()
+ clear()
+ command("let $VIMRUNTIME='fixtures/a'")
+ -- Use system([nvim,…]) instead of clear() to avoid stderr noise. #21844
+ local out = funcs.system({nvim_prog, '--clean', '--luamod-dev',
+ [[+call nvim_exec_lua('return vim.tbl_count {x=1,y=2}')]], '+qa!'}):gsub('\r\n', '\n')
+ eq(1, eval('v:shell_error'))
+ matches("'vim%.shared' not found", out)
end)
end)
diff --git a/test/functional/options/defaults_spec.lua b/test/functional/options/defaults_spec.lua
index c0d820f40e..84ec43f4cb 100644
--- a/test/functional/options/defaults_spec.lua
+++ b/test/functional/options/defaults_spec.lua
@@ -3,6 +3,7 @@ local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local assert_alive = helpers.assert_alive
+local assert_log = helpers.assert_log
local meths = helpers.meths
local command = helpers.command
local clear = helpers.clear
@@ -20,6 +21,8 @@ local tbl_contains = helpers.tbl_contains
local expect_exit = helpers.expect_exit
local is_os = helpers.is_os
+local testlog = 'Xtest-defaults-log'
+
describe('startup defaults', function()
describe(':filetype', function()
local function expect_filetype(expected)
@@ -275,6 +278,10 @@ describe('XDG defaults', function()
-- Need separate describe() blocks to not run clear() twice.
-- Do not put before_each() here for the same reasons.
+ after_each(function()
+ os.remove(testlog)
+ end)
+
it("&runtimepath data-dir matches stdpath('data') #9910", function()
clear()
local rtp = eval('split(&runtimepath, ",")')
@@ -337,6 +344,7 @@ describe('XDG defaults', function()
clear({
args_rm={'runtimepath'},
env={
+ NVIM_LOG_FILE=testlog,
XDG_CONFIG_HOME=(root_path .. ('/x'):rep(4096)),
XDG_CONFIG_DIRS=(root_path .. ('/a'):rep(2048)
.. env_sep.. root_path .. ('/b'):rep(2048)
@@ -351,6 +359,10 @@ describe('XDG defaults', function()
end)
it('are correctly set', function()
+ if not is_os('win') then
+ assert_log('Failed to start server: no such file or directory: /X/X/X', testlog, 10)
+ end
+
local vimruntime, libdir = vimruntime_and_libdir()
eq(((root_path .. ('/x'):rep(4096) .. '/nvim'
@@ -412,6 +424,7 @@ describe('XDG defaults', function()
clear({
args_rm={'runtimepath'},
env={
+ NVIM_LOG_FILE=testlog,
XDG_CONFIG_HOME='$XDG_DATA_HOME',
XDG_CONFIG_DIRS='$XDG_DATA_DIRS',
XDG_DATA_HOME='$XDG_CONFIG_HOME',
@@ -422,6 +435,10 @@ describe('XDG defaults', function()
end)
it('are not expanded', function()
+ if not is_os('win') then
+ assert_log('Failed to start server: no such file or directory: %$XDG_RUNTIME_DIR%/', testlog, 10)
+ end
+
local vimruntime, libdir = vimruntime_and_libdir()
eq((('$XDG_DATA_HOME/nvim'
.. ',$XDG_DATA_DIRS/nvim'
diff --git a/test/functional/plugin/lsp/helpers.lua b/test/functional/plugin/lsp/helpers.lua
index 028ccb9e2c..caab174b4d 100644
--- a/test/functional/plugin/lsp/helpers.lua
+++ b/test/functional/plugin/lsp/helpers.lua
@@ -80,17 +80,14 @@ M.fake_lsp_logfile = 'Xtest-fake-lsp.log'
local function fake_lsp_server_setup(test_name, timeout_ms, options, settings)
exec_lua([=[
lsp = require('vim.lsp')
- local test_name, fixture_filename, logfile, timeout, options, settings = ...
+ local test_name, fake_lsp_code, fake_lsp_logfile, timeout, options, settings = ...
TEST_RPC_CLIENT_ID = lsp.start_client {
cmd_env = {
- NVIM_LOG_FILE = logfile;
+ NVIM_LOG_FILE = fake_lsp_logfile;
NVIM_LUA_NOTRACK = "1";
};
cmd = {
- vim.v.progpath, '-Es', '-u', 'NONE', '--headless',
- "-c", string.format("lua TEST_NAME = %q", test_name),
- "-c", string.format("lua TIMEOUT = %d", timeout),
- "-c", "luafile "..fixture_filename,
+ vim.v.progpath, '-l', fake_lsp_code, test_name, tostring(timeout),
};
handlers = setmetatable({}, {
__index = function(t, method)
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index 93fada8a50..fd162961ff 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -46,16 +46,14 @@ describe('LSP', function()
local test_name = "basic_init"
exec_lua([=[
lsp = require('vim.lsp')
- local test_name, fixture_filename, logfile = ...
+ local test_name, fake_lsp_code, fake_lsp_logfile = ...
function test__start_client()
return lsp.start_client {
cmd_env = {
- NVIM_LOG_FILE = logfile;
+ NVIM_LOG_FILE = fake_lsp_logfile;
};
cmd = {
- vim.v.progpath, '-Es', '-u', 'NONE', '--headless',
- "-c", string.format("lua TEST_NAME = %q", test_name),
- "-c", "luafile "..fixture_filename;
+ vim.v.progpath, '-l', fake_lsp_code, test_name;
};
workspace_folders = {{
uri = 'file://' .. vim.loop.cwd(),
@@ -3432,6 +3430,38 @@ describe('LSP', function()
}
eq(expected_range, result[3].params.range)
end)
+ it('Aborts with notify if no clients support requested method', function()
+ exec_lua(create_server_definition)
+ exec_lua([[
+ vim.notify = function(msg, _)
+ notify_msg = msg
+ end
+ ]])
+ local fail_msg = "[LSP] Format request failed, no matching language servers."
+ local function check_notify(name, formatting, range_formatting)
+ local timeout_msg = "[LSP][" .. name .. "] timeout"
+ exec_lua([[
+ local formatting, range_formatting, name = ...
+ local server = _create_server({ capabilities = {
+ documentFormattingProvider = formatting,
+ documentRangeFormattingProvider = range_formatting,
+ }})
+ vim.lsp.start({ name = name, cmd = server.cmd })
+ notify_msg = nil
+ vim.lsp.buf.format({ name = name, timeout_ms = 1 })
+ ]], formatting, range_formatting, name)
+ eq(formatting and timeout_msg or fail_msg, exec_lua('return notify_msg'))
+ exec_lua([[
+ notify_msg = nil
+ vim.lsp.buf.format({ name = name, timeout_ms = 1, range = {start={1, 0}, ['end']={1, 0}}})
+ ]])
+ eq(range_formatting and timeout_msg or fail_msg, exec_lua('return notify_msg'))
+ end
+ check_notify("none", false, false)
+ check_notify("formatting", true, false)
+ check_notify("rangeFormatting", false, true)
+ check_notify("both", true, true)
+ end)
end)
describe('cmd', function()
it('can connect to lsp server via rpc.connect', function()
diff --git a/test/functional/plugin/man_spec.lua b/test/functional/plugin/man_spec.lua
index c6c7d2b03d..58da059be6 100644
--- a/test/functional/plugin/man_spec.lua
+++ b/test/functional/plugin/man_spec.lua
@@ -59,7 +59,7 @@ describe(':Man', function()
screen:expect([[
^this {b:is} {b:a} test |
- with {u:overstruck} text |
+ with {i:overstruck} text |
{eob:~ }|
{eob:~ }|
|
@@ -98,7 +98,7 @@ describe(':Man', function()
screen:expect([[
^this {b:is} {b:あ} test |
- with {u:överstrũck} te{i:xt¶} |
+ with {i:överstrũck} te{i:xt¶} |
{eob:~ }|
{eob:~ }|
|
@@ -115,7 +115,7 @@ describe(':Man', function()
screen:expect([[
{b:^_begins} |
{b:mid_dle} |
- {u:mid_dle} |
+ {i:mid_dle} |
{eob:~ }|
|
]])
diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua
index 228aaa6b23..1d9e7b8e11 100644
--- a/test/functional/terminal/tui_spec.lua
+++ b/test/functional/terminal/tui_spec.lua
@@ -7,7 +7,6 @@
local helpers = require('test.functional.helpers')(after_each)
local thelpers = require('test.functional.terminal.helpers')
local Screen = require('test.functional.ui.screen')
-local assert_alive = helpers.assert_alive
local eq = helpers.eq
local feed_command = helpers.feed_command
local feed_data = thelpers.feed_data
@@ -15,6 +14,7 @@ local clear = helpers.clear
local command = helpers.command
local dedent = helpers.dedent
local exec = helpers.exec
+local exec_lua = helpers.exec_lua
local testprg = helpers.testprg
local retry = helpers.retry
local nvim_prog = helpers.nvim_prog
@@ -77,7 +77,16 @@ describe('TUI', function()
it('rapid resize #7572 #7628', function()
-- Need buffer rows to provoke the behavior.
- feed_data(":edit test/functional/fixtures/bigfile.txt:")
+ feed_data(":edit test/functional/fixtures/bigfile.txt\n")
+ screen:expect([[
+ {1:0}000;<control>;Cc;0;BN;;;;;N;NULL;;;; |
+ 0001;<control>;Cc;0;BN;;;;;N;START OF HEADING;;;; |
+ 0002;<control>;Cc;0;BN;;;;;N;START OF TEXT;;;; |
+ 0003;<control>;Cc;0;BN;;;;;N;END OF TEXT;;;; |
+ {5:test/functional/fixtures/bigfile.txt }|
+ :edit test/functional/fixtures/bigfile.txt |
+ {3:-- TERMINAL --} |
+ ]])
command('call jobresize(b:terminal_job_id, 58, 9)')
command('call jobresize(b:terminal_job_id, 62, 13)')
command('call jobresize(b:terminal_job_id, 100, 42)')
@@ -94,7 +103,9 @@ describe('TUI', function()
command('call jobresize(b:terminal_job_id, 1, 4)')
screen:try_resize(57, 17)
command('call jobresize(b:terminal_job_id, 57, 17)')
- assert_alive()
+ retry(nil, nil, function()
+ eq({true, 57}, {child_session:request('nvim_win_get_width', 0)})
+ end)
end)
it('accepts resize while pager is active', function()
@@ -1298,6 +1309,7 @@ describe('TUI', function()
[7] = {reverse = true, foreground = Screen.colors.SeaGreen4},
[8] = {foreground = Screen.colors.SeaGreen4},
[9] = {bold = true, foreground = Screen.colors.Blue1},
+ [10] = {foreground = Screen.colors.Blue},
})
feed_data(':hi SpecialKey ctermfg=3 guifg=SeaGreen\n')
@@ -1318,9 +1330,9 @@ describe('TUI', function()
feed_data(':set termguicolors\n')
screen:expect([[
{7:^}{8:G} |
- {9:~ }|
- {9:~ }|
- {9:~ }|
+ {9:~}{10: }|
+ {9:~}{10: }|
+ {9:~}{10: }|
{3:[No Name] [+] }|
:set termguicolors |
{4:-- TERMINAL --} |
@@ -1495,6 +1507,11 @@ describe('TUI', function()
{3:-- TERMINAL --} |
]]}
end)
+
+ it('no assert failure on deadly signal #21896', function()
+ exec_lua([[vim.loop.kill(vim.fn.jobpid(vim.bo.channel), 'sigterm')]])
+ screen:expect({any = '%[Process exited 1%]'})
+ end)
end)
describe('TUI', function()
@@ -2399,9 +2416,7 @@ describe("TUI as a client", function()
clear()
local screen = thelpers.screen_setup(0,
string.format([=[["%s", "-u", "NONE", "-i", "NONE", "--server", "127.0.0.1:2436546", "--remote-ui"]]=],
- nvim_prog))
-
- screen:try_resize(60, 7)
+ nvim_prog), 60)
screen:expect([[
Remote ui failed to start: {MATCH:.*}|
diff --git a/test/functional/treesitter/language_spec.lua b/test/functional/treesitter/language_spec.lua
index 1db8381a93..df45c9b384 100644
--- a/test/functional/treesitter/language_spec.lua
+++ b/test/functional/treesitter/language_spec.lua
@@ -17,7 +17,7 @@ describe('treesitter language API', function()
pcall_err(exec_lua, "parser = vim.treesitter.get_parser(0, 'borklang')"))
-- actual message depends on platform
- matches("Failed to load parser: uv_dlopen: .+",
+ matches("Failed to load parser for language 'borklang': uv_dlopen: .+",
pcall_err(exec_lua, "parser = vim.treesitter.require_language('borklang', 'borkbork.so')"))
-- Should not throw an error when silent
@@ -31,6 +31,11 @@ describe('treesitter language API', function()
pcall_err(exec_lua, 'vim.treesitter.require_language("c", nil, false, "borklang")'))
end)
+ it('shows error for invalid language name', function()
+ eq(".../language.lua:0: '/foo/' is not a valid language name",
+ pcall_err(exec_lua, 'vim.treesitter.require_language("/foo/", nil, false)'))
+ end)
+
it('inspects language', function()
local keys, fields, symbols = unpack(exec_lua([[
local lang = vim.treesitter.inspect_language('c')
diff --git a/test/functional/ui/cmdline_highlight_spec.lua b/test/functional/ui/cmdline_highlight_spec.lua
index 33e375760e..eb5de693bd 100644
--- a/test/functional/ui/cmdline_highlight_spec.lua
+++ b/test/functional/ui/cmdline_highlight_spec.lua
@@ -335,17 +335,17 @@ describe('Command-line coloring', function()
:echo "«^ |
]])
end)
- it('does the right thing when errorring', function()
+ it('does the right thing when erroring', function()
set_color_cb('Echoerring')
start_prompt('e')
screen:expect([[
|
{EOB:~ }|
- {EOB:~ }|
{MSEP: }|
: |
{ERR:E5407: Callback has thrown an exception:}|
- {ERR: Vim(echoerr):HERE} |
+ {ERR: function DoPrompt[3]..Echoerring, line }|
+ {ERR:1: Vim(echoerr):HERE} |
:e^ |
]])
end)
@@ -400,10 +400,10 @@ describe('Command-line coloring', function()
screen:expect([[
|
{EOB:~ }|
- {EOB:~ }|
{MSEP: }|
: |
{ERR:E5407: Callback has thrown an exception:}|
+ {ERR: function DoPrompt[3]..Throwing, line 1:}|
{ERR: ABC} |
:e^ |
]])
diff --git a/test/functional/ui/fold_spec.lua b/test/functional/ui/fold_spec.lua
index bfa7167100..46a478c1ea 100644
--- a/test/functional/ui/fold_spec.lua
+++ b/test/functional/ui/fold_spec.lua
@@ -8,6 +8,7 @@ local expect = helpers.expect
local funcs = helpers.funcs
local meths = helpers.meths
local exec = helpers.exec
+local exec_lua = helpers.exec_lua
local assert_alive = helpers.assert_alive
@@ -1852,6 +1853,128 @@ describe("folded lines", function()
]])
end
end)
+
+ it('fold attached virtual lines are drawn correctly #21837', function()
+ funcs.setline(1, 'line 1')
+ funcs.setline(2, 'line 2')
+ funcs.setline(3, 'line 3')
+ funcs.setline(4, 'line 4')
+ feed("zfj")
+ exec_lua([[
+ local ns = vim.api.nvim_create_namespace("ns")
+ vim.api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_lines_above = true, virt_lines = {{{"virt_line above line 1", ""}}} })
+ vim.api.nvim_buf_set_extmark(0, ns, 1, 0, { virt_lines = {{{"virt_line below line 2", ""}}} })
+ vim.api.nvim_buf_set_extmark(0, ns, 2, 0, { virt_lines_above = true, virt_lines = {{{"virt_line above line 3", ""}}} })
+ vim.api.nvim_buf_set_extmark(0, ns, 3, 0, { virt_lines = {{{"virt_line below line 4", ""}}} })
+ ]])
+ if multigrid then
+ screen:expect([[
+ ## grid 1
+ [2:---------------------------------------------]|
+ [2:---------------------------------------------]|
+ [2:---------------------------------------------]|
+ [2:---------------------------------------------]|
+ [2:---------------------------------------------]|
+ [2:---------------------------------------------]|
+ [2:---------------------------------------------]|
+ [3:---------------------------------------------]|
+ ## grid 2
+ {5:^+-- 2 lines: line 1·························}|
+ virt_line above line 3 |
+ line 3 |
+ line 4 |
+ virt_line below line 4 |
+ {1:~ }|
+ {1:~ }|
+ ## grid 3
+ |
+ ]])
+ else
+ screen:expect([[
+ {5:^+-- 2 lines: line 1·························}|
+ virt_line above line 3 |
+ line 3 |
+ line 4 |
+ virt_line below line 4 |
+ {1:~ }|
+ {1:~ }|
+ |
+ ]])
+ end
+
+ feed('jzfj')
+ if multigrid then
+ screen:expect([[
+ ## grid 1
+ [2:---------------------------------------------]|
+ [2:---------------------------------------------]|
+ [2:---------------------------------------------]|
+ [2:---------------------------------------------]|
+ [2:---------------------------------------------]|
+ [2:---------------------------------------------]|
+ [2:---------------------------------------------]|
+ [3:---------------------------------------------]|
+ ## grid 2
+ {5:+-- 2 lines: line 1·························}|
+ {5:^+-- 2 lines: line 3·························}|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ## grid 3
+ |
+ ]])
+ else
+ screen:expect([[
+ {5:+-- 2 lines: line 1·························}|
+ {5:^+-- 2 lines: line 3·························}|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]])
+ end
+
+ feed('kzo<C-Y>')
+ funcs.setline(5, 'line 5')
+ if multigrid then
+ screen:expect([[
+ ## grid 1
+ [2:---------------------------------------------]|
+ [2:---------------------------------------------]|
+ [2:---------------------------------------------]|
+ [2:---------------------------------------------]|
+ [2:---------------------------------------------]|
+ [2:---------------------------------------------]|
+ [2:---------------------------------------------]|
+ [3:---------------------------------------------]|
+ ## grid 2
+ virt_line above line 1 |
+ ^line 1 |
+ line 2 |
+ virt_line below line 2 |
+ {5:+-- 2 lines: line 3·························}|
+ line 5 |
+ {1:~ }|
+ ## grid 3
+ |
+ ]])
+ else
+ screen:expect([[
+ virt_line above line 1 |
+ ^line 1 |
+ line 2 |
+ virt_line below line 2 |
+ {5:+-- 2 lines: line 3·························}|
+ line 5 |
+ {1:~ }|
+ |
+ ]])
+ end
+ end)
end
describe("with ext_multigrid", function()
diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua
index 78b2f52c1f..c681453294 100644
--- a/test/functional/ui/popupmenu_spec.lua
+++ b/test/functional/ui/popupmenu_spec.lua
@@ -945,6 +945,82 @@ describe('ui/ext_popupmenu', function()
}}
end)
+
+ it('does not interfere with mousemodel=popup', function()
+ exec([[
+ set mouse=a mousemodel=popup
+
+ aunmenu PopUp
+ menu PopUp.foo :let g:menustr = 'foo'<CR>
+ menu PopUp.bar :let g:menustr = 'bar'<CR>
+ menu PopUp.baz :let g:menustr = 'baz'<CR>
+ ]])
+ feed('o<C-r>=TestComplete()<CR>')
+ screen:expect{grid=[[
+ |
+ foo^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2:-- INSERT --} |
+ ]], popupmenu={
+ items=expected,
+ pos=0,
+ anchor={1,1,0},
+ }}
+
+ feed('<c-p>')
+ screen:expect{grid=[[
+ |
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2:-- INSERT --} |
+ ]], popupmenu={
+ items=expected,
+ pos=-1,
+ anchor={1,1,0},
+ }}
+
+ feed('<esc>')
+ screen:expect{grid=[[
+ |
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ feed('<RightMouse><0,0>')
+ screen:expect([[
+ |
+ {7:^foo } |
+ {7:bar }{1: }|
+ {7:baz }{1: }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]])
+ feed('<esc>')
+ screen:expect([[
+ |
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]])
+ end)
end)
@@ -968,6 +1044,7 @@ describe('builtin popupmenu', function()
[5] = {bold = true, foreground = Screen.colors.SeaGreen},
[6] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
[7] = {background = Screen.colors.Yellow}, -- Search
+ [8] = {foreground = Screen.colors.Red},
})
end)
@@ -1115,6 +1192,66 @@ describe('builtin popupmenu', function()
]])
end)
+ -- oldtest: Test_pum_with_preview_win()
+ it('preview window opened during completion', function()
+ exec([[
+ funct Omni_test(findstart, base)
+ if a:findstart
+ return col(".") - 1
+ endif
+ return [#{word: "one", info: "1info"}, #{word: "two", info: "2info"}, #{word: "three", info: "3info"}]
+ endfunc
+ set omnifunc=Omni_test
+ set completeopt+=longest
+ ]])
+ feed('Gi<C-X><C-O>')
+ screen:expect([[
+ ^ |
+ {n:one }{1: }|
+ {n:two }{1: }|
+ {n:three }{1: }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2:-- }{8:Back at original} |
+ ]])
+ feed('<C-N>')
+ screen:expect([[
+ 1info |
+ |
+ {1:~ }|
+ {3:[Scratch] [Preview] }|
+ one^ |
+ {s:one }{1: }|
+ {n:two }{1: }|
+ {n:three }{1: }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {4:[No Name] [+] }|
+ {2:-- }{5:match 1 of 3} |
+ ]])
+ end)
+
it('with vsplits', function()
insert('aaa aab aac\n')
feed(':vsplit<cr>')
@@ -2388,8 +2525,130 @@ describe('builtin popupmenu', function()
{1:~ }{n: xyz }{1: }|
:e あいう/123^ |
]])
+ feed('<Esc>')
- feed('<esc>')
+ -- Pressing <PageDown> should scroll the menu downward
+ feed(':sign <Tab><PageDown>')
+ screen:expect([[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }{n: define }{1: }|
+ {1:~ }{n: jump }{1: }|
+ {1:~ }{n: list }{1: }|
+ {1:~ }{n: place }{1: }|
+ {1:~ }{s: undefine }{1: }|
+ {1:~ }{n: unplace }{1: }|
+ :sign undefine^ |
+ ]])
+ feed('<PageDown>')
+ screen:expect([[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }{n: define }{1: }|
+ {1:~ }{n: jump }{1: }|
+ {1:~ }{n: list }{1: }|
+ {1:~ }{n: place }{1: }|
+ {1:~ }{n: undefine }{1: }|
+ {1:~ }{s: unplace }{1: }|
+ :sign unplace^ |
+ ]])
+ feed('<PageDown>')
+ screen:expect([[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }{n: define }{1: }|
+ {1:~ }{n: jump }{1: }|
+ {1:~ }{n: list }{1: }|
+ {1:~ }{n: place }{1: }|
+ {1:~ }{n: undefine }{1: }|
+ {1:~ }{n: unplace }{1: }|
+ :sign ^ |
+ ]])
+ feed('<PageDown>')
+ screen:expect([[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }{s: define }{1: }|
+ {1:~ }{n: jump }{1: }|
+ {1:~ }{n: list }{1: }|
+ {1:~ }{n: place }{1: }|
+ {1:~ }{n: undefine }{1: }|
+ {1:~ }{n: unplace }{1: }|
+ :sign define^ |
+ ]])
+ feed('<C-U>sign <Tab><Right><Right><PageDown>')
+ screen:expect([[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }{n: define }{1: }|
+ {1:~ }{n: jump }{1: }|
+ {1:~ }{n: list }{1: }|
+ {1:~ }{n: place }{1: }|
+ {1:~ }{n: undefine }{1: }|
+ {1:~ }{s: unplace }{1: }|
+ :sign unplace^ |
+ ]])
+
+ -- Pressing <PageUp> should scroll the menu upward
+ feed('<C-U>sign <Tab><PageUp>')
+ screen:expect([[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }{n: define }{1: }|
+ {1:~ }{n: jump }{1: }|
+ {1:~ }{n: list }{1: }|
+ {1:~ }{n: place }{1: }|
+ {1:~ }{n: undefine }{1: }|
+ {1:~ }{n: unplace }{1: }|
+ :sign ^ |
+ ]])
+ feed('<PageUp>')
+ screen:expect([[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }{n: define }{1: }|
+ {1:~ }{n: jump }{1: }|
+ {1:~ }{n: list }{1: }|
+ {1:~ }{n: place }{1: }|
+ {1:~ }{n: undefine }{1: }|
+ {1:~ }{s: unplace }{1: }|
+ :sign unplace^ |
+ ]])
+ feed('<PageUp>')
+ screen:expect([[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }{n: define }{1: }|
+ {1:~ }{s: jump }{1: }|
+ {1:~ }{n: list }{1: }|
+ {1:~ }{n: place }{1: }|
+ {1:~ }{n: undefine }{1: }|
+ {1:~ }{n: unplace }{1: }|
+ :sign jump^ |
+ ]])
+ feed('<PageUp>')
+ screen:expect([[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }{s: define }{1: }|
+ {1:~ }{n: jump }{1: }|
+ {1:~ }{n: list }{1: }|
+ {1:~ }{n: place }{1: }|
+ {1:~ }{n: undefine }{1: }|
+ {1:~ }{n: unplace }{1: }|
+ :sign define^ |
+ ]])
+
+ feed('<Esc>')
-- check positioning with multibyte char in pattern
command("e långfile1")
@@ -2583,6 +2842,26 @@ describe('builtin popupmenu', function()
]]}
end)
+ it('wildoptions=pum with a wrapped line in buffer vim-patch:8.2.4655', function()
+ screen:try_resize(32, 10)
+ meths.buf_set_lines(0, 0, -1, true, { ('a'):rep(100) })
+ command('set wildoptions+=pum')
+ feed('$')
+ feed(':sign <Tab>')
+ screen:expect([[
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ aaaa {s: define } |
+ {1:~ }{n: jump }{1: }|
+ {1:~ }{n: list }{1: }|
+ {1:~ }{n: place }{1: }|
+ {1:~ }{n: undefine }{1: }|
+ {1:~ }{n: unplace }{1: }|
+ :sign define^ |
+ ]])
+ end)
+
-- oldtest: Test_wildmenu_pum_clear_entries()
it('wildoptions=pum when using Ctrl-E as wildchar vim-patch:9.0.1030', function()
screen:try_resize(30, 10)
diff --git a/test/functional/ui/statuscolumn_spec.lua b/test/functional/ui/statuscolumn_spec.lua
index a9d796c10b..3233e6cd19 100644
--- a/test/functional/ui/statuscolumn_spec.lua
+++ b/test/functional/ui/statuscolumn_spec.lua
@@ -4,6 +4,8 @@ local clear = helpers.clear
local command = helpers.command
local eq = helpers.eq
local eval = helpers.eval
+local exec_lua = helpers.exec_lua
+local feed = helpers.feed
local meths = helpers.meths
local pcall_err = helpers.pcall_err
@@ -15,8 +17,8 @@ describe('statuscolumn', function()
screen:attach()
end)
- it('fails with invalid \'statuscolumn\'', function()
- command('set stc=%{v:relnum?v:relnum:(v:lnum==5?invalid:v:lnum)}\\ ')
+ it("fails with invalid 'statuscolumn'", function()
+ command([[set stc=%{v:relnum?v:relnum:(v:lnum==5?invalid:v:lnum)}\ ]])
screen:expect([[
4 aaaaa |
3 aaaaa |
@@ -38,8 +40,8 @@ describe('statuscolumn', function()
eq('', eval('&statuscolumn'))
end)
- it('widens with irregular \'statuscolumn\' width', function()
- command('set stc=%{v:relnum?v:relnum:(v:lnum==5?\'bbbbb\':v:lnum)}')
+ it("widens with irregular 'statuscolumn' width", function()
+ command([[set stc=%{v:relnum?v:relnum:(v:lnum==5?'bbbbb':v:lnum)}]])
command('norm 5G | redraw!')
screen:expect([[
1 aaaaa |
@@ -59,7 +61,7 @@ describe('statuscolumn', function()
]])
end)
- it('works with \'statuscolumn\'', function()
+ it("works with 'number' and 'relativenumber'", function()
command([[set stc=%{&nu?v:lnum:''}%=%{&rnu?'\ '.v:relnum:''}│]])
screen:expect([[
4 │aaaaa |
@@ -122,7 +124,7 @@ describe('statuscolumn', function()
command([[set stc=%{&nu?v:lnum:''}%=%{&rnu?'\ '.v:relnum:''}│]])
end)
- it('works with highlighted \'statuscolumn\'', function()
+ it("works with highlighted 'statuscolumn'", function()
command([[set stc=%#NonText#%{&nu?v:lnum:''}]] ..
[[%=%{&rnu&&(v:lnum%2)?'\ '.v:relnum:''}]] ..
[[%#LineNr#%{&rnu&&!(v:lnum%2)?'\ '.v:relnum:''}│]])
@@ -183,7 +185,7 @@ describe('statuscolumn', function()
end)
it('works with wrapped lines, signs and folds', function()
- command("set stc=%C%s%=%{v:wrap?'':v:lnum}│\\ ")
+ command([[set stc=%C%s%=%{v:virtnum?'':v:lnum}│\ ]])
command("call setline(1,repeat([repeat('aaaaa',10)],16))")
screen:set_default_attr_ids({
[0] = {bold = true, foreground = Screen.colors.Blue},
@@ -209,6 +211,8 @@ describe('statuscolumn', function()
{1:10│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{0:@@@}|
|
]])
+ command("set stc=%C%s%=%l│\\ ")
+ screen:expect_unchanged()
command('set signcolumn=auto:2 foldcolumn=auto')
command('sign define piet1 text=>> texthl=LineNr')
command('sign define piet2 text=>! texthl=NonText')
@@ -234,7 +238,7 @@ describe('statuscolumn', function()
]])
command('norm zf$')
-- Check that alignment works properly with signs after %=
- command("set stc=%C%=%{v:wrap?'':v:lnum}│%s\\ ")
+ command([[set stc=%C%=%{v:virtnum?'':v:lnum}│%s\ ]])
screen:expect([[
{2: }{1: 4│>>}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: │}{2: }{1: }aaaaaa |
@@ -269,7 +273,7 @@ describe('statuscolumn', function()
|
]])
-- v:lnum is the same value on wrapped lines
- command("set stc=%C%=%{v:lnum}│%s\\ ")
+ command([[set stc=%C%=%{v:lnum}│%s\ ]])
screen:expect([[
{2: }{1: 4│>>}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: 4│}{2: }{1: }aaaaaa |
@@ -287,7 +291,7 @@ describe('statuscolumn', function()
|
]])
-- v:relnum is the same value on wrapped lines
- command("set stc=%C%=\\ %{v:relnum}│%s\\ ")
+ command([[set stc=%C%=\ %{v:relnum}│%s\ ]])
screen:expect([[
{2: }{1: 4│>>}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: 4│}{2: }{1: }aaaaaa |
@@ -304,7 +308,7 @@ describe('statuscolumn', function()
{2: }{1: 2│}{2: }{1: }aaaaaa |
|
]])
- command("set stc=%C%=\\ %{v:wrap?'':v:relnum}│%s\\ ")
+ command([[set stc=%C%=\ %{v:virtnum?'':v:relnum}│%s\ ]])
screen:expect([[
{2: }{1: 4│>>}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: │}{2: }{1: }aaaaaa |
@@ -346,9 +350,34 @@ describe('statuscolumn', function()
{2: }{1: │}{2: }{1: }aaaaaaaaaaaaaaaaaaaa |
|
]])
+ -- Status column is re-evaluated for virt_lines, buffer line, and wrapped line
+ exec_lua([[
+ local ns = vim.api.nvim_create_namespace("ns")
+ vim.api.nvim_buf_set_extmark(0, ns, 5, 0, {
+ virt_lines_above = true, virt_lines = {{{"virt_line above", ""}}} })
+ vim.api.nvim_buf_set_extmark(0, ns, 4, 0, { virt_lines = {{{"virt_line", ""}}} })
+ ]])
+ command('set foldcolumn=0 signcolumn=no')
+ command([[set stc=%{v:virtnum<0?'virtual':(!v:virtnum?'buffer':'wrapped')}%=%{'\ '.v:virtnum.'\ '.v:lnum}]])
+ screen:expect([[
+ {1:buffer 0 4}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {1:wrapped 1 4}aaaaaaaa |
+ {1:buffer 0 5}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {1:wrapped 1 5}aaaaaaaa |
+ {1:virtual-2 5}virt_line |
+ {1:virtual-2 5}virt_line above |
+ {1:buffer 0 6}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {1:wrapped 1 6}aaaaaaaa |
+ {1:buffer 0 7}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {1:wrapped 1 7}aaaaaaaa |
+ {4:buffer 0 8}{5:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
+ {1:buffer 0 9}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {1:wrapped 1 9}aaaaaaaa |
+ |
+ ]])
end)
- it('works with \'statuscolumn\' clicks', function()
+ it("works with 'statuscolumn' clicks", function()
command('set mousemodel=extend')
command([[
function! MyClickFunc(minwid, clicks, button, mods)
@@ -385,25 +414,68 @@ describe('statuscolumn', function()
eq('', eval("g:testvar"))
end)
- it('fits maximum multibyte foldcolumn #21759', function()
- command('set stc=%C fdc=9 fillchars=foldsep:𒀀')
+ it('click labels do not leak memory', function()
+ command([[
+ set laststatus=2
+ setlocal statuscolumn=%0@MyClickFunc@abcd%T
+ 4vsplit
+ setlocal statusline=abcd
+ redrawstatus
+ setlocal statusline=
+ only
+ redraw
+ ]])
+ end)
+
+ it('works with foldcolumn', function()
+ -- Fits maximum multibyte foldcolumn #21759
+ command([[set stc=%C%=%l\ fdc=9 fillchars=foldsep:𒀀]])
for _ = 0,8 do command('norm zfjzo') end
+ -- 'statuscolumn' is not drawn for `virt_lines_leftcol` lines
+ exec_lua([[
+ local ns = vim.api.nvim_create_namespace("ns")
+ vim.api.nvim_buf_set_extmark(0, ns, 6, 0, {
+ virt_lines_leftcol = true, virt_lines = {{{"virt", ""}}} })
+ vim.api.nvim_buf_set_extmark(0, ns, 7, 0, {
+ virt_lines_leftcol = true, virt_lines = {{{"virt", ""}}} })
+ ]])
+ feed('lh') -- force update cursor row
screen:expect([[
- aaaaa |
- aaaaa |
- aaaaa |
- aaaaa |
- --------- ^aaaaa |
- 𒀀𒀀𒀀𒀀𒀀𒀀𒀀𒀀𒀀 aaaaa |
- aaaaa |
- aaaaa |
- aaaaa |
- aaaaa |
- aaaaa |
- aaaaa |
- aaaaa |
+ 4 aaaaa |
+ 5 aaaaa |
+ 6 aaaaa |
+ 7 aaaaa |
+ virt |
+ --------- 8 ^aaaaa |
+ virt |
+ 𒀀𒀀𒀀𒀀𒀀𒀀𒀀𒀀𒀀 9 aaaaa |
+ 10 aaaaa |
+ 11 aaaaa |
+ 12 aaaaa |
+ 13 aaaaa |
+ 14 aaaaa |
+ |
+ ]])
+ command('set stc=') -- also for the default sign column
+ screen:expect_unchanged()
+ -- 'statuscolumn' is not too wide with custom (bogus) fold column
+ command([[set stc=%{foldlevel(v:lnum)>0?repeat('-',foldlevel(v:lnum)):''}%=%l\ ]])
+ feed('Gd10Ggg<C-l>')
+ screen:expect([[
+ 1 ^aaaaa |
+ 2 aaaaa |
+ 3 aaaaa |
+ 4 aaaaa |
+ 5 aaaaa |
+ 6 aaaaa |
+ 7 aaaaa |
+ virt |
+ ---------8 aaaaa |
+ virt |
+ ---------9 aaaaa |
+ ~ |
+ ~ |
|
]])
end)
-
end)
diff --git a/test/functional/ui/statusline_spec.lua b/test/functional/ui/statusline_spec.lua
index 549ebbde06..1c184ff27d 100644
--- a/test/functional/ui/statusline_spec.lua
+++ b/test/functional/ui/statusline_spec.lua
@@ -164,6 +164,24 @@ describe('statusline clicks', function()
meths.input_mouse('right', 'press', '', 0, 6, 5)
eq('0 1 r', eval("g:testvar"))
end)
+
+ it('no memory leak with zero-width click labels', function()
+ command([[
+ let &stl = '%@Test@%T%@MyClickFunc@%=%T%@Test@'
+ ]])
+ meths.input_mouse('left', 'press', '', 0, 6, 0)
+ eq('0 1 l', eval("g:testvar"))
+ meths.input_mouse('right', 'press', '', 0, 6, 39)
+ eq('0 1 r', eval("g:testvar"))
+ end)
+
+ it('no memory leak with truncated click labels', function()
+ command([[
+ let &stl = '%@MyClickFunc@foo%X' .. repeat('a', 40) .. '%<t%@Test@bar%X%@Test@baz'
+ ]])
+ meths.input_mouse('left', 'press', '', 0, 6, 2)
+ eq('0 1 l', eval("g:testvar"))
+ end)
end)
describe('global statusline', function()
diff --git a/test/functional/ui/tabline_spec.lua b/test/functional/ui/tabline_spec.lua
index 0e35a03557..2cdec62d01 100644
--- a/test/functional/ui/tabline_spec.lua
+++ b/test/functional/ui/tabline_spec.lua
@@ -119,4 +119,10 @@ describe("tabline", function()
[2] = {bold = true, foreground = Screen.colors.Blue};
}}
end)
+
+ it('click definitions do not leak memory #21765', function()
+ command('set tabline=%@MyClickFunc@MyClickText%T')
+ command('set showtabline=2')
+ command('redrawtabline')
+ end)
end)
diff --git a/test/functional/vimscript/api_functions_spec.lua b/test/functional/vimscript/api_functions_spec.lua
index 8ca245f61a..c032ac3030 100644
--- a/test/functional/vimscript/api_functions_spec.lua
+++ b/test/functional/vimscript/api_functions_spec.lua
@@ -5,6 +5,7 @@ local neq, eq, command = helpers.neq, helpers.eq, helpers.command
local clear, curbufmeths = helpers.clear, helpers.curbufmeths
local exc_exec, expect, eval = helpers.exc_exec, helpers.expect, helpers.eval
local insert, pcall_err = helpers.insert, helpers.pcall_err
+local matches = helpers.matches
local meths = helpers.meths
describe('eval-API', function()
@@ -49,7 +50,7 @@ describe('eval-API', function()
it('cannot change texts if textlocked', function()
command("autocmd TextYankPost <buffer> ++once call nvim_buf_set_lines(0, 0, -1, v:false, [])")
- eq('Vim(call):E5555: API call: E565: Not allowed to change text or change window',
+ matches('Vim%(call%):E5555: API call: E565: Not allowed to change text or change window$',
pcall_err(command, "normal! yy"))
end)
diff --git a/test/functional/vimscript/ctx_functions_spec.lua b/test/functional/vimscript/ctx_functions_spec.lua
index d92a81c55b..5ee84a6d13 100644
--- a/test/functional/vimscript/ctx_functions_spec.lua
+++ b/test/functional/vimscript/ctx_functions_spec.lua
@@ -173,9 +173,9 @@ describe('context functions', function()
call('SaveSFuncs')
call('DeleteSFuncs')
- eq('Vim(call):E117: Unknown function: s:greet',
+ eq('function Greet, line 1: Vim(call):E117: Unknown function: s:greet',
pcall_err(command, [[call Greet('World')]]))
- eq('Vim(call):E117: Unknown function: s:greet_all',
+ eq('function GreetAll, line 1: Vim(call):E117: Unknown function: s:greet_all',
pcall_err(command, [[call GreetAll('World', 'One', 'Two', 'Three')]]))
call('RestoreFuncs')
@@ -287,9 +287,11 @@ describe('context functions', function()
local with_jumps = {
['jumps'] = eval(([[
- filter(map(getjumplist()[0], 'filter(
- { "f": expand("#".v:val.bufnr.":p"), "l": v:val.lnum },
- { k, v -> k != "l" || v != 1 })'), '!empty(v:val.f)')
+ filter(map(add(
+ getjumplist()[0], { 'bufnr': bufnr('%'), 'lnum': getcurpos()[1] }),
+ 'filter(
+ { "f": expand("#".v:val.bufnr.":p"), "l": v:val.lnum },
+ { k, v -> k != "l" || v != 1 })'), '!empty(v:val.f)')
]]):gsub('\n', ''))
}
diff --git a/test/functional/vimscript/exepath_spec.lua b/test/functional/vimscript/exepath_spec.lua
index 056f67e0ad..da3d61cbe0 100644
--- a/test/functional/vimscript/exepath_spec.lua
+++ b/test/functional/vimscript/exepath_spec.lua
@@ -5,21 +5,21 @@ local command = helpers.command
local exc_exec = helpers.exc_exec
local matches = helpers.matches
local is_os = helpers.is_os
+local set_shell_powershell = helpers.set_shell_powershell
+local eval = helpers.eval
+
+local find_dummies = function(ext_pat)
+ local tmp_path = eval('$PATH')
+ command('let $PATH = fnamemodify("./test/functional/fixtures/bin", ":p")')
+ matches('null' .. ext_pat, call('exepath', 'null'))
+ matches('true' .. ext_pat, call('exepath', 'true'))
+ matches('false' .. ext_pat, call('exepath', 'false'))
+ command("let $PATH = '"..tmp_path.."'")
+end
describe('exepath()', function()
before_each(clear)
- it('returns 1 for commands in $PATH', function()
- local exe = is_os('win') and 'ping' or 'ls'
- local ext_pat = is_os('win') and '%.EXE$' or '$'
- matches(exe .. ext_pat, call('exepath', exe))
- command('let $PATH = fnamemodify("./test/functional/fixtures/bin", ":p")')
- ext_pat = is_os('win') and '%.CMD$' or '$'
- matches('null' .. ext_pat, call('exepath', 'null'))
- matches('true' .. ext_pat, call('exepath', 'true'))
- matches('false' .. ext_pat, call('exepath', 'false'))
- end)
-
it('fails for invalid values', function()
for _, input in ipairs({'v:null', 'v:true', 'v:false', '{}', '[]'}) do
eq('Vim(call):E1174: String required for argument 1', exc_exec('call exepath('..input..')'))
@@ -32,11 +32,32 @@ describe('exepath()', function()
end)
if is_os('win') then
+ it('returns 1 for commands in $PATH (Windows)', function()
+ local exe = 'ping'
+ matches(exe .. '%.EXE$', call('exepath', exe))
+ end)
+
it('append extension if omitted', function()
local filename = 'cmd'
local pathext = '.exe'
clear({env={PATHEXT=pathext}})
eq(call('exepath', filename..pathext), call('exepath', filename))
end)
+
+ it('returns file WITH extension if files both with and without extension exist in $PATH', function()
+ local ext_pat = '%.CMD$'
+ find_dummies(ext_pat)
+ set_shell_powershell()
+ find_dummies(ext_pat)
+ end)
+ else
+ it('returns 1 for commands in $PATH (not Windows)', function()
+ local exe = 'ls'
+ matches(exe .. '$', call('exepath', exe))
+ end)
+
+ it('returns file WITHOUT extension if files both with and without extension exist in $PATH', function()
+ find_dummies('$')
+ end)
end
end)
diff --git a/test/functional/vimscript/server_spec.lua b/test/functional/vimscript/server_spec.lua
index 14c87d9d93..c89a0c4e93 100644
--- a/test/functional/vimscript/server_spec.lua
+++ b/test/functional/vimscript/server_spec.lua
@@ -1,4 +1,5 @@
local helpers = require('test.functional.helpers')(after_each)
+local assert_log = helpers.assert_log
local eq, neq, eval = helpers.eq, helpers.neq, helpers.eval
local clear, funcs, meths = helpers.clear, helpers.funcs, helpers.meths
local ok = helpers.ok
@@ -7,6 +8,8 @@ local pcall_err = helpers.pcall_err
local mkdir = helpers.mkdir
local is_os = helpers.is_os
+local testlog = 'Xtest-server-log'
+
local function clear_serverlist()
for _, server in pairs(funcs.serverlist()) do
funcs.serverstop(server)
@@ -14,6 +17,10 @@ local function clear_serverlist()
end
describe('server', function()
+ after_each(function()
+ os.remove(testlog)
+ end)
+
it('serverstart() stores sockets in $XDG_RUNTIME_DIR', function()
local dir = 'Xtest_xdg_run'
mkdir(dir)
@@ -74,13 +81,20 @@ describe('server', function()
end)
it('serverstop() returns false for invalid input', function()
- clear()
+ clear{env={
+ NVIM_LOG_FILE=testlog,
+ NVIM_LISTEN_ADDRESS='.',
+ }}
eq(0, eval("serverstop('')"))
eq(0, eval("serverstop('bogus-socket-name')"))
+ assert_log('Not listening on bogus%-socket%-name', testlog, 10)
end)
it('parses endpoints', function()
- clear()
+ clear{env={
+ NVIM_LOG_FILE=testlog,
+ NVIM_LISTEN_ADDRESS='.',
+ }}
clear_serverlist()
eq({}, funcs.serverlist())
@@ -104,6 +118,7 @@ describe('server', function()
if status then
table.insert(expected, v4)
pcall(funcs.serverstart, v4) -- exists already; ignore
+ assert_log('Failed to start server: address already in use: 127%.0%.0%.1', testlog, 10)
end
local v6 = '::1:12345'
@@ -111,6 +126,7 @@ describe('server', function()
if status then
table.insert(expected, v6)
pcall(funcs.serverstart, v6) -- exists already; ignore
+ assert_log('Failed to start server: address already in use: ::1', testlog, 10)
end
eq(expected, funcs.serverlist())
clear_serverlist()
diff --git a/test/helpers.lua b/test/helpers.lua
index 3fe4322501..82ff23bef8 100644
--- a/test/helpers.lua
+++ b/test/helpers.lua
@@ -1,6 +1,7 @@
require('test.compat')
local shared = require('vim.shared')
local assert = require('luassert')
+local busted = require('busted')
local luv = require('luv')
local lfs = require('lfs')
local relpath = require('pl.path').relpath
@@ -45,6 +46,28 @@ function module.sleep(ms)
luv.sleep(ms)
end
+-- Calls fn() until it succeeds, up to `max` times or until `max_ms`
+-- milliseconds have passed.
+function module.retry(max, max_ms, fn)
+ assert(max == nil or max > 0)
+ assert(max_ms == nil or max_ms > 0)
+ local tries = 1
+ local timeout = (max_ms and max_ms or 10000)
+ local start_time = luv.now()
+ while true do
+ local status, result = pcall(fn)
+ if status then
+ return result
+ end
+ luv.update_time() -- Update cached value of luv.now() (libuv: uv_now()).
+ if (max and tries >= max) or (luv.now() - start_time > timeout) then
+ busted.fail(string.format("retry() attempts: %d\n%s", tries, tostring(result)), 2)
+ end
+ tries = tries + 1
+ luv.sleep(20) -- Avoid hot loop...
+ end
+end
+
local check_logs_useless_lines = {
['Warning: noted but unhandled ioctl']=1,
['could cause spurious value errors to appear']=2,
@@ -87,6 +110,8 @@ end
--- Asserts that `pat` matches (or *not* if inverse=true) any line in the tail of `logfile`.
---
+--- Retries for 1 second in case of filesystem delay.
+---
---@param pat (string) Lua pattern to match lines in the log file
---@param logfile (string) Full path to log file (default=$NVIM_LOG_FILE)
---@param nrlines (number) Search up to this many log lines
@@ -96,18 +121,21 @@ function module.assert_log(pat, logfile, nrlines, inverse)
assert(logfile ~= nil, 'no logfile')
nrlines = nrlines or 10
inverse = inverse or false
- local lines = module.read_file_list(logfile, -nrlines) or {}
- local msg = string.format('Pattern %q %sfound in log (last %d lines): %s:\n%s',
- pat, (inverse and '' or 'not '), nrlines, logfile, ' '..table.concat(lines, '\n '))
- for _,line in ipairs(lines) do
- if line:match(pat) then
- if inverse then error(msg) else return end
+
+ module.retry(nil, 1000, function()
+ local lines = module.read_file_list(logfile, -nrlines) or {}
+ local msg = string.format('Pattern %q %sfound in log (last %d lines): %s:\n%s',
+ pat, (inverse and '' or 'not '), nrlines, logfile, ' '..table.concat(lines, '\n '))
+ for _,line in ipairs(lines) do
+ if line:match(pat) then
+ if inverse then error(msg) else return end
+ end
end
- end
- if not inverse then error(msg) end
+ if not inverse then error(msg) end
+ end)
end
---- Asserts that `pat` does NOT matche any line in the tail of `logfile`.
+--- Asserts that `pat` does NOT match any line in the tail of `logfile`.
---
--- @see assert_log
function module.assert_nolog(pat, logfile, nrlines)
diff --git a/test/includes/CMakeLists.txt b/test/includes/CMakeLists.txt
deleted file mode 100644
index 0d30736091..0000000000
--- a/test/includes/CMakeLists.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-file(GLOB_RECURSE PRE_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} pre/*.h)
-
-# We need to add the SDK directories on OS X, and perhaps other operating
-# systems.
-set(gen_cflags)
-foreach(gen_include ${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES})
- list(APPEND gen_cflags ${CMAKE_INCLUDE_FLAG_C}${gen_include})
-endforeach()
-
-get_directory_property(gen_cdefs COMPILE_DEFINITIONS)
-foreach(gen_cdef ${gen_cdefs})
- if(NOT ${gen_cdef} MATCHES "INCLUDE_GENERATED_DECLARATIONS")
- list(APPEND gen_cflags "-D${gen_cdef}")
- endif()
-endforeach()
-
-foreach(hfile ${PRE_HEADERS})
- string(REGEX REPLACE ^pre/ post/ post_hfile ${hfile})
- get_filename_component(hdir ${CMAKE_CURRENT_BINARY_DIR}/${post_hfile} DIRECTORY)
- file(MAKE_DIRECTORY ${hdir})
- add_custom_command(
- OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${post_hfile}
- COMMAND ${CMAKE_C_COMPILER} -std=c99 -E -P
- ${CMAKE_CURRENT_SOURCE_DIR}/${hfile}
- ${gen_cflags}
- -o ${CMAKE_CURRENT_BINARY_DIR}/${post_hfile})
- list(APPEND POST_HEADERS ${post_hfile})
-endforeach()
-
-add_custom_target(unittest-headers DEPENDS ${POST_HEADERS})
-set_target_properties(unittest-headers PROPERTIES FOLDER test)
diff --git a/test/unit/eval/typval_spec.lua b/test/unit/eval/typval_spec.lua
index 34dbf592a5..825377813d 100644
--- a/test/unit/eval/typval_spec.lua
+++ b/test/unit/eval/typval_spec.lua
@@ -1677,7 +1677,7 @@ describe('typval.c', function()
eq(nil, lib.tv_dict_find(nil, 'test', -1))
eq(nil, lib.tv_dict_find(nil, nil, 0))
end)
- itp('works with NULL key', function()
+ itp('works with empty key', function()
local lua_d = {
['']=0,
t=1,
@@ -1692,7 +1692,6 @@ describe('typval.c', function()
alloc_log:check({})
local dis = dict_items(d)
eq({0, '', dis['']}, {tv_dict_find(d, '', 0)})
- eq({0, '', dis['']}, {tv_dict_find(d, nil, 0)})
end)
itp('works with len properly', function()
local lua_d = {
@@ -1911,8 +1910,6 @@ describe('typval.c', function()
local d = dict(lua_d)
eq(lua_d, dct2tbl(d))
eq({{type='fref', fref='tr'}, true},
- {tv_dict_get_callback(d, nil, 0)})
- eq({{type='fref', fref='tr'}, true},
{tv_dict_get_callback(d, '', -1)})
eq({{type='none'}, true},
{tv_dict_get_callback(d, 'x', -1)})
@@ -2175,7 +2172,8 @@ describe('typval.c', function()
eq({a='TSET'}, dct2tbl(d1))
eq({a='TSET'}, dct2tbl(d2))
end)
- itp('disallows overriding builtin or user functions', function()
+ pending('disallows overriding builtin or user functions: here be the dragons', function()
+ -- pending: see TODO below
local d = dict()
d.dv_scope = lib.VAR_DEF_SCOPE
local f_lua = {
@@ -2196,6 +2194,7 @@ describe('typval.c', function()
local d5 = dict({Test=f_tv})
local d6 = dict({Test=p_tv})
eval0([[execute("function Test()\nendfunction")]])
+ -- TODO: test breaks at this point
tv_dict_extend(d, d2, 'force',
'E704: Funcref variable name must start with a capital: tr')
tv_dict_extend(d, d3, 'force',
@@ -2623,7 +2622,7 @@ describe('typval.c', function()
describe('check_lock()', function()
local function tv_check_lock(lock, name, name_len, emsg)
return check_emsg(function()
- return lib.var_check_lock(lock, name, name_len)
+ return lib.value_check_lock(lock, name, name_len)
end, emsg)
end
itp('works', function()
diff --git a/test/unit/helpers.lua b/test/unit/helpers.lua
index 29ea0235be..686af3b461 100644
--- a/test/unit/helpers.lua
+++ b/test/unit/helpers.lua
@@ -7,9 +7,6 @@ local global_helpers = require('test.helpers')
local assert = require('luassert')
local say = require('say')
-local posix = nil
-local syscall = nil
-
local check_cores = global_helpers.check_cores
local dedent = global_helpers.dedent
local neq = global_helpers.neq
@@ -78,7 +75,8 @@ local function child_cleanup_once(func, ...)
end
end
-local libnvim = nil
+-- Unittests are run from debug nvim binary in lua interpreter mode.
+local libnvim = ffi.C
local lib = setmetatable({}, {
__index = only_separate(function(_, idx)
@@ -90,8 +88,6 @@ local lib = setmetatable({}, {
})
local init = only_separate(function()
- -- load neovim shared library
- libnvim = ffi.load(Paths.test_libnvim_path)
for _, c in ipairs(child_calls_init) do
c.func(unpack(c.args))
end
@@ -373,122 +369,91 @@ local function to_cstr(string)
return cstr(#string + 1, string)
end
-local sc
-
-if posix ~= nil then
- sc = {
- fork = posix.fork,
- pipe = posix.pipe,
- read = posix.read,
- write = posix.write,
- close = posix.close,
- wait = posix.wait,
- exit = posix._exit,
- }
-elseif syscall ~= nil then
- sc = {
- fork = syscall.fork,
- pipe = function()
- local ret = {syscall.pipe()}
- return ret[3], ret[4]
- end,
- read = function(rd, len)
- return rd:read(nil, len)
- end,
- write = function(wr, s)
- return wr:write(s)
- end,
- close = function(p)
- return p:close()
- end,
- wait = syscall.wait,
- exit = syscall.exit,
- }
-else
- cimport_immediate('./test/unit/fixtures/posix.h')
- sc = {
- fork = function()
- return tonumber(ffi.C.fork())
- end,
- pipe = function()
- local ret = ffi.new('int[2]', {-1, -1})
- ffi.errno(0)
- local res = ffi.C.pipe(ret)
- if (res ~= 0) then
+cimport_immediate('./test/unit/fixtures/posix.h')
+local sc = {
+ fork = function()
+ return tonumber(ffi.C.fork())
+ end,
+ pipe = function()
+ local ret = ffi.new('int[2]', {-1, -1})
+ ffi.errno(0)
+ local res = ffi.C.pipe(ret)
+ if (res ~= 0) then
+ local err = ffi.errno(0)
+ assert(res == 0, ("pipe() error: %u: %s"):format(
+ err, ffi.string(ffi.C.strerror(err))))
+ end
+ assert(ret[0] ~= -1 and ret[1] ~= -1)
+ return ret[0], ret[1]
+ end,
+ read = function(rd, len)
+ local ret = ffi.new('char[?]', len, {0})
+ local total_bytes_read = 0
+ ffi.errno(0)
+ while total_bytes_read < len do
+ local bytes_read = tonumber(ffi.C.read(
+ rd,
+ ffi.cast('void*', ret + total_bytes_read),
+ len - total_bytes_read))
+ if bytes_read == -1 then
local err = ffi.errno(0)
- assert(res == 0, ("pipe() error: %u: %s"):format(
- err, ffi.string(ffi.C.strerror(err))))
- end
- assert(ret[0] ~= -1 and ret[1] ~= -1)
- return ret[0], ret[1]
- end,
- read = function(rd, len)
- local ret = ffi.new('char[?]', len, {0})
- local total_bytes_read = 0
- ffi.errno(0)
- while total_bytes_read < len do
- local bytes_read = tonumber(ffi.C.read(
- rd,
- ffi.cast('void*', ret + total_bytes_read),
- len - total_bytes_read))
- if bytes_read == -1 then
- local err = ffi.errno(0)
- if err ~= ffi.C.kPOSIXErrnoEINTR then
- assert(false, ("read() error: %u: %s"):format(
- err, ffi.string(ffi.C.strerror(err))))
- end
- elseif bytes_read == 0 then
- break
- else
- total_bytes_read = total_bytes_read + bytes_read
+ if err ~= ffi.C.kPOSIXErrnoEINTR then
+ assert(false, ("read() error: %u: %s"):format(
+ err, ffi.string(ffi.C.strerror(err))))
end
+ elseif bytes_read == 0 then
+ break
+ else
+ total_bytes_read = total_bytes_read + bytes_read
end
- return ffi.string(ret, total_bytes_read)
- end,
- write = function(wr, s)
- local wbuf = to_cstr(s)
- local total_bytes_written = 0
- ffi.errno(0)
- while total_bytes_written < #s do
- local bytes_written = tonumber(ffi.C.write(
- wr,
- ffi.cast('void*', wbuf + total_bytes_written),
- #s - total_bytes_written))
- if bytes_written == -1 then
- local err = ffi.errno(0)
- if err ~= ffi.C.kPOSIXErrnoEINTR then
- assert(false, ("write() error: %u: %s ('%s')"):format(
- err, ffi.string(ffi.C.strerror(err)), s))
- end
- elseif bytes_written == 0 then
- break
- else
- total_bytes_written = total_bytes_written + bytes_written
+ end
+ return ffi.string(ret, total_bytes_read)
+ end,
+ write = function(wr, s)
+ local wbuf = to_cstr(s)
+ local total_bytes_written = 0
+ ffi.errno(0)
+ while total_bytes_written < #s do
+ local bytes_written = tonumber(ffi.C.write(
+ wr,
+ ffi.cast('void*', wbuf + total_bytes_written),
+ #s - total_bytes_written))
+ if bytes_written == -1 then
+ local err = ffi.errno(0)
+ if err ~= ffi.C.kPOSIXErrnoEINTR then
+ assert(false, ("write() error: %u: %s ('%s')"):format(
+ err, ffi.string(ffi.C.strerror(err)), s))
end
+ elseif bytes_written == 0 then
+ break
+ else
+ total_bytes_written = total_bytes_written + bytes_written
end
- return total_bytes_written
- end,
- close = ffi.C.close,
- wait = function(pid)
- ffi.errno(0)
- while true do
- local r = ffi.C.waitpid(pid, nil, ffi.C.kPOSIXWaitWUNTRACED)
- if r == -1 then
- local err = ffi.errno(0)
- if err == ffi.C.kPOSIXErrnoECHILD then
- break
- elseif err ~= ffi.C.kPOSIXErrnoEINTR then
- assert(false, ("waitpid() error: %u: %s"):format(
- err, ffi.string(ffi.C.strerror(err))))
- end
- else
- assert(r == pid)
+ end
+ return total_bytes_written
+ end,
+ close = ffi.C.close,
+ wait = function(pid)
+ ffi.errno(0)
+ local stat_loc = ffi.new('int[1]', {0})
+ while true do
+ local r = ffi.C.waitpid(pid, stat_loc, ffi.C.kPOSIXWaitWUNTRACED)
+ if r == -1 then
+ local err = ffi.errno(0)
+ if err == ffi.C.kPOSIXErrnoECHILD then
+ break
+ elseif err ~= ffi.C.kPOSIXErrnoEINTR then
+ assert(false, ("waitpid() error: %u: %s"):format(
+ err, ffi.string(ffi.C.strerror(err))))
end
+ else
+ assert(r == pid)
end
- end,
- exit = ffi.C._exit,
- }
-end
+ end
+ return stat_loc[0]
+ end,
+ exit = ffi.C._exit,
+}
local function format_list(lst)
local ret = ''
@@ -730,18 +695,22 @@ local function check_child_err(rd)
end
end
-local function itp_parent(rd, pid, allow_failure)
- local err, emsg = pcall(check_child_err, rd)
- sc.wait(pid)
+local function itp_parent(rd, pid, allow_failure, location)
+ local ok, emsg = pcall(check_child_err, rd)
+ local status = sc.wait(pid)
sc.close(rd)
- if not err then
+ if not ok then
if allow_failure then
- io.stderr:write('Errorred out:\n' .. tostring(emsg) .. '\n')
+ io.stderr:write('Errorred out ('..status..'):\n' .. tostring(emsg) .. '\n')
os.execute([[
sh -c "source ci/common/test.sh
check_core_dumps --delete \"]] .. Paths.test_luajit_prg .. [[\""]])
else
- error(emsg)
+ error(tostring(emsg)..'\nexit code: '..status)
+ end
+ elseif status ~= 0 then
+ if not allow_failure then
+ error("child process errored out with status "..status.."!\n\n"..location)
end
end
end
@@ -758,6 +727,11 @@ local function gen_itp(it)
-- FIXME Fix tests with this true
return
end
+
+ -- Pre-emptively calculating error location, wasteful, ugh!
+ -- But the way this code messes around with busted implies the real location is strictly
+ -- not available in the parent when an actual error occurs. so we have to do this here.
+ local location = debug.traceback()
it(name, function()
local rd, wr = sc.pipe()
child_pid = sc.fork()
@@ -768,7 +742,7 @@ local function gen_itp(it)
sc.close(wr)
local saved_child_pid = child_pid
child_pid = nil
- itp_parent(rd, saved_child_pid, allow_failure)
+ itp_parent(rd, saved_child_pid, allow_failure, location)
end
end)
end
diff --git a/test/unit/tui_spec.lua b/test/unit/tui_spec.lua
index 15b019edd1..192e35a485 100644
--- a/test/unit/tui_spec.lua
+++ b/test/unit/tui_spec.lua
@@ -9,9 +9,10 @@ local cinput = cimport("./src/nvim/tui/input.h")
local rbuffer = cimport("./test/unit/fixtures/rbuffer.h")
local globals = cimport("./src/nvim/globals.h")
local multiqueue = cimport("./test/unit/fixtures/multiqueue.h")
+local ui_client = cimport("./src/nvim/ui_client.h")
itp('handle_background_color', function()
- local handle_background_color = cinput.ut_handle_background_color
+ local handle_background_color = cinput.handle_background_color
local term_input = ffi.new('TermInput', {})
local events = globals.main_loop.thread_events
local kIncomplete = cinput.kIncomplete
@@ -34,10 +35,8 @@ itp('handle_background_color', function()
eq(kComplete, handle_background_color(term_input))
eq(0, term_input.waiting_for_bg_response)
eq(0, multiqueue.multiqueue_size(events))
-
- local event = multiqueue.multiqueue_get(events)
- local bg_event = ffi.cast("Event*", event.argv[1])
- eq(bg, ffi.string(bg_event.argv[0]))
+ eq(bg, ({[0]="light", [1] = "dark", [-1] = "none"})
+ [tonumber(ui_client.ui_client_bg_response)])
-- Buffer has been consumed.
eq(0, rbuf.size)
@@ -114,9 +113,7 @@ itp('handle_background_color', function()
eq(kComplete, handle_background_color(term_input))
eq(0, term_input.waiting_for_bg_response)
- local event = multiqueue.multiqueue_get(events)
- local bg_event = ffi.cast("Event*", event.argv[1])
- eq('light', ffi.string(bg_event.argv[0]))
+ eq(0, tonumber(ui_client.ui_client_bg_response))
eq(0, multiqueue.multiqueue_size(events))
eq(0, rbuf.size)
@@ -133,9 +130,7 @@ itp('handle_background_color', function()
eq(kComplete, handle_background_color(term_input))
eq(0, term_input.waiting_for_bg_response)
- event = multiqueue.multiqueue_get(events)
- bg_event = ffi.cast("Event*", event.argv[1])
- eq('light', ffi.string(bg_event.argv[0]))
+ eq(0, tonumber(ui_client.ui_client_bg_response))
eq(0, multiqueue.multiqueue_size(events))
eq(0, rbuf.size)
@@ -161,7 +156,7 @@ itp('handle_background_color', function()
eq(kComplete, handle_background_color(term_input))
eq(0, term_input.waiting_for_bg_response)
- eq(1, multiqueue.multiqueue_size(events))
+ eq(0, multiqueue.multiqueue_size(events))
eq(3, rbuf.size)
rbuffer.rbuffer_consumed(rbuf, rbuf.size)
end)