diff options
265 files changed, 7084 insertions, 4310 deletions
diff --git a/.builds/freebsd.yml b/.builds/freebsd.yml deleted file mode 100644 index 4be49fd153..0000000000 --- a/.builds/freebsd.yml +++ /dev/null @@ -1,45 +0,0 @@ -image: freebsd/latest - -packages: -- cmake -- gmake -- ninja -- libtool -- automake -- pkgconf -- unzip -- wget -- gettext -- python -- libffi -- gdb - -sources: -- https://github.com/neovim/neovim - -environment: - SOURCEHUT: 1 - LANG: en_US.UTF-8 - CMAKE_EXTRA_FLAGS: -DCI_BUILD=ON -DMIN_LOG_LEVEL=3 - -tasks: -- should-run: | - if ! git -C neovim diff --name-only HEAD^! | grep -E -v "^(.github|runtime/doc/.*)" >/dev/null; then - echo "Skipping build because only ignored files were changed" - complete-build - fi -- build-deps: | - cd neovim - gmake deps -- build: | - cd neovim - gmake CMAKE_BUILD_TYPE=RelWithDebInfo CMAKE_EXTRA_FLAGS="${CMAKE_EXTRA_FLAGS}" nvim -- functionaltest: | - cd neovim - gmake functionaltest -- unittest: | - cd neovim - gmake unittest -- oldtest: | - cd neovim - gmake oldtest diff --git a/.builds/openbsd.yml b/.builds/openbsd.yml deleted file mode 100644 index b5799e424b..0000000000 --- a/.builds/openbsd.yml +++ /dev/null @@ -1,49 +0,0 @@ -# sourcehut CI: https://builds.sr.ht/~jmk/neovim - -image: openbsd/latest - -packages: -- autoconf-2.71 -- automake-1.16.3 -- cmake -- gettext-runtime -- gettext-tools -- gmake -- libtool -- ninja -- unzip-6.0p14 -- gdb - -sources: -- https://github.com/neovim/neovim - -environment: - SOURCEHUT: 1 - LC_CTYPE: en_US.UTF-8 - CMAKE_EXTRA_FLAGS: -DCI_BUILD=ON -DMIN_LOG_LEVEL=3 - -tasks: -- should-run: | - if ! git -C neovim diff --name-only HEAD^! | grep -E -v "^(.github|runtime/doc/.*)" >/dev/null; then - echo "Skipping build because only ignored files were changed" - complete-build - fi -- build-deps: | - export AUTOCONF_VERSION=2.71 - export AUTOMAKE_VERSION=1.16 - mkdir neovim/.deps - cd neovim/.deps - cmake -G Ninja ../cmake.deps/ - cmake --build . --config RelWithDebInfo -- build: | - mkdir neovim/build - cd neovim/build - cmake -G Ninja $CMAKE_EXTRA_FLAGS .. - cmake --build . --config RelWithDebInfo - ./bin/nvim --version -- functionaltest: | - cd neovim/build - cmake --build . --config RelWithDebInfo --target functionaltest -- oldtest: | - cd neovim - gmake oldtest diff --git a/.cirrus.yml b/.cirrus.yml new file mode 100644 index 0000000000..af67170235 --- /dev/null +++ b/.cirrus.yml @@ -0,0 +1,29 @@ +env: + CIRRUS_CLONE_DEPTH: '1' + LANG: en_US.UTF-8 + CMAKE_EXTRA_FLAGS: -DCI_BUILD=ON -DMIN_LOG_LEVEL=3 + +freebsd_task: + name: FreeBSD + only_if: $BRANCH != "master" + freebsd_instance: + image_family: freebsd-13-1 + timeout_in: 30m + install_script: + - pkg update -f + - pkg install -y cmake gmake ninja libtool automake pkgconf unzip wget gettext python libffi git + build_deps_script: + - gmake deps + build_script: + - gmake CMAKE_EXTRA_FLAGS="${CMAKE_EXTRA_FLAGS}" nvim + workaround_script: + # Run tests as user "cirrus" instead of root. This is required for the + # permission-related tests to work correctly. + - pw useradd cirrus -m + - chown -R cirrus:cirrus . + functionaltest_script: + - sudo -u cirrus gmake functionaltest + unittest_script: + - sudo -u cirrus gmake unittest + oldtest_script: + - sudo -u cirrus gmake oldtest diff --git a/.github/labeler.yml b/.github/labeler.yml index e86c7aabe8..b4f6f054cb 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -13,6 +13,7 @@ - src/nvim/lua/treesitter.* - runtime/lua/vim/treesitter.lua - runtime/lua/vim/treesitter/* + - runtime/queries/**/* "diagnostic": - runtime/lua/vim/diagnostic.lua diff --git a/.github/scripts/reviews.js b/.github/scripts/reviews.js index 0f14707179..c76f25b7da 100644 --- a/.github/scripts/reviews.js +++ b/.github/scripts/reviews.js @@ -14,9 +14,11 @@ module.exports = async ({github, context}) => { if (labels.includes('build')) { reviewers.add("jamessan") + reviewers.add("justinmk") } if (labels.includes('ci')) { + reviewers.add("dundargoc") reviewers.add("jamessan") } @@ -53,17 +55,14 @@ module.exports = async ({github, context}) => { reviewers.add("gpanders") } - if (labels.includes('gui')) { - reviewers.add("glacambre") - reviewers.add("smolck") - } - if (labels.includes('lsp')) { reviewers.add("mfussenegger") + reviewers.add("glepnir") } if (labels.includes('treesitter')) { reviewers.add("bfredl") + reviewers.add("clason") reviewers.add("vigoux") } diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d6933e9330..5e0ea5e5f4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -228,15 +228,29 @@ jobs: gh release create stable $PRERELEASE --notes-file "$RUNNER_TEMP/notes.md" --title "$SUBJECT" --target $GITHUB_SHA nvim-macos/* nvim-linux64/* appimage/* nvim-win64/* fi publish-winget: - needs: publish # run after publish job is finished - # publish to winget only on stable releases - if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.tag_name != 'nightly') - runs-on: windows-latest # action can only be run on windows + needs: publish + runs-on: windows-latest steps: - - uses: vedantmgoyal2009/winget-releaser@latest + - if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.tag_name != 'nightly') + name: Publish stable + uses: vedantmgoyal2009/winget-releaser@latest with: identifier: Neovim.Neovim - # the latter one is a fallback value, reference: - # https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value release-tag: ${{ github.event.inputs.tag_name || github.ref }} token: ${{ secrets.WINGET_TOKEN }} + - if: github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && github.event.inputs.tag_name == 'nightly') + name: Get nightly version + id: get-version + run: | + Invoke-WebRequest https://github.com/neovim/neovim/releases/download/nightly/nvim-win64.msi -OutFile setup.msi + Install-Module -Name 'Carbon.Windows.Installer' -Force + $VERSION = (Get-CMsi (Resolve-Path .\setup.msi).Path).ProductVersion + echo "::set-output name=version::$VERSION" + - if: github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && github.event.inputs.tag_name == 'nightly') + name: Publish nightly + uses: vedantmgoyal2009/winget-releaser@latest + with: + identifier: Neovim.Neovim.Nightly + version: ${{ steps.get-version.outputs.version }} + release-tag: nightly + token: ${{ secrets.WINGET_TOKEN }} diff --git a/.gitignore b/.gitignore index 11479346c7..be43c5cd90 100644 --- a/.gitignore +++ b/.gitignore @@ -73,3 +73,5 @@ tags # vim patches /vim-*.patch + +/CMakeUserPresets.json diff --git a/CMakeLists.txt b/CMakeLists.txt index d3764f4a99..1a1b0c6391 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -273,7 +273,7 @@ if(MSVC) # XXX: /W4 gives too many warnings. #3241 add_compile_options(/W3) add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE) - add_definitions(-DWIN32) + add_definitions(-DMSWIN) else() add_compile_options(-Wall -Wextra -pedantic -Wno-unused-parameter -Wstrict-prototypes -std=gnu99 -Wshadow -Wconversion @@ -320,6 +320,7 @@ endif() if(MINGW) # Use POSIX compatible stdio in Mingw add_definitions(-D__USE_MINGW_ANSI_STDIO) + add_definitions(-DMSWIN) endif() if(WIN32) # Windows Vista is the minimum supported version diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000000..b2c93792b0 --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,95 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "base", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build", + "hidden": true + }, + { + "name": "default", + "displayName": "RelWithDebInfo", + "description": "Enables optimizations (-Og or -O2) with debug information", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo" + }, + "inherits": [ + "base" + ] + }, + { + "name": "debug", + "displayName": "Debug", + "description": "Disables optimizations (-O0), enables debug information", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug" + }, + "inherits": [ + "base" + ] + }, + { + "name": "release", + "displayName": "Release", + "description": "Same as RelWithDebInfo, but disables debug information", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release" + }, + "inherits": [ + "base" + ] + }, + { + "name": "windows-default", + "displayName": "Windows x64 RelWithDebInfo", + "description": "Sets Ninja generator, enables optimizations with debug information for x64", + "generator": "Ninja", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo" + }, + "architecture": { + "value": "x64", + "strategy": "external" + }, + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "hostOS": [ + "Windows" + ] + } + }, + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + }, + "inherits": [ + "base" + ] + } + ], + "buildPresets": [ + { + "name": "default", + "configurePreset": "default" + }, + { + "name": "debug", + "configurePreset": "debug" + }, + { + "name": "release", + "configurePreset": "release" + }, + { + "name": "windows-default", + "configurePreset": "windows-default", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + } + } + ] +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 558d0986db..b3adf13318 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -111,7 +111,7 @@ the VCS/git logs more valuable. The general structure of a commit message is: ### Automated builds (CI) -Each pull request must pass the automated builds on [sourcehut] and [GitHub Actions]. +Each pull request must pass the automated builds on [Cirrus CI] and [GitHub Actions]. - CI builds are compiled with [`-Werror`][gcc-warnings], so compiler warnings will fail the build. @@ -125,20 +125,7 @@ Each pull request must pass the automated builds on [sourcehut] and [GitHub Acti - The [lint](#lint) build checks modified lines _and their immediate neighbors_, to encourage incrementally updating the legacy style to meet our [style](#style). (See [#3174][3174] for background.) -- CI for freebsd and openbsd runs on [sourcehut]. - - To get a backtrace on freebsd (after connecting via ssh): - ```sh - sudo pkg install tmux # If you want tmux. - lldb build/bin/nvim -c nvim.core - - # To get a full backtrace: - # 1. Rebuild with debug info. - rm -rf nvim.core build - gmake CMAKE_BUILD_TYPE=RelWithDebInfo CMAKE_EXTRA_FLAGS="-DCI_BUILD=ON -DMIN_LOG_LEVEL=3" nvim - # 2. Run the failing test to generate a new core file. - TEST_FILE=test/functional/foo.lua gmake functionaltest - lldb build/bin/nvim -c nvim.core - ``` +- CI for FreeBSD runs on [Cirrus CI]. ### Clang scan-build @@ -321,6 +308,7 @@ as context, use the `-W` argument as well. [1820]: https://github.com/neovim/neovim/pull/1820 [3174]: https://github.com/neovim/neovim/issues/3174 [ASan]: http://clang.llvm.org/docs/AddressSanitizer.html +[Cirrus CI]: https://cirrus-ci.com/github/neovim/neovim [Clang report]: https://neovim.io/doc/reports/clang/ [GitHub Actions]: https://github.com/neovim/neovim/actions [clangd]: https://clangd.llvm.org @@ -345,7 +333,6 @@ as context, use the `-W` argument as well. [pr-ready]: https://docs.github.com/en/github/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-stage-of-a-pull-request [review-checklist]: https://github.com/neovim/neovim/wiki/Code-review-checklist [run-tests]: https://github.com/neovim/neovim/blob/master/test/README.md#running-tests -[sourcehut]: https://builds.sr.ht/~jmk [style-guide]: https://neovim.io/doc/user/dev_style.html#dev-style [uncrustify]: http://uncrustify.sourceforge.net/ [wiki-contribute-help]: https://github.com/neovim/neovim/wiki/contribute-%3Ahelp @@ -7,7 +7,6 @@ [Twitter](https://twitter.com/Neovim) [](https://github.com/neovim/neovim/actions?query=workflow%3ACI+branch%3Amaster+event%3Apush) -[](https://codecov.io/gh/neovim/neovim) [](https://scan.coverity.com/projects/2227) [](https://neovim.io/doc/reports/clang) [](https://neovim.io/doc/reports/pvs/PVS-studio.html.d) diff --git a/cmake.deps/CMakeLists.txt b/cmake.deps/CMakeLists.txt index 885aa9c64c..0eccfb6f0b 100644 --- a/cmake.deps/CMakeLists.txt +++ b/cmake.deps/CMakeLists.txt @@ -173,12 +173,12 @@ set(UNIBILIUM_SHA256 29815283c654277ef77a3adcc8840db79ddbb20a0f0b0c8f648bd8cd49a 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-RC1.tar.gz) -set(LIBVTERM_SHA256 441d1c372b84a0df12525100ab06c0366260fb4f6252abd1665ee4fa571b5134) +set(LIBVTERM_URL https://www.leonerd.org.uk/code/libvterm/libvterm-0.3.tar.gz) +set(LIBVTERM_SHA256 61eb0d6628c52bdf02900dfd4468aa86a1a7125228bab8a67328981887483358) -set(LUV_VERSION 1.44.2-0) -set(LUV_URL https://github.com/luvit/luv/archive/1.44.2-0.tar.gz) -set(LUV_SHA256 44ccda27035bfe683e6325a2a93f2c254be1eb76bde6efc2bd37c56a7af7b00a) +set(LUV_VERSION 1.44.2-1) +set(LUV_URL https://github.com/luvit/luv/archive/1.44.2-1.tar.gz) +set(LUV_SHA256 f8c69908e17ec8ab370253d1508e23deaecfc0c4752d2efb77e427e579501104) set(LUA_COMPAT53_URL https://github.com/keplerproject/lua-compat-5.3/archive/v0.9.tar.gz) set(LUA_COMPAT53_SHA256 ad05540d2d96a48725bb79a1def35cf6652a4e2ec26376e2617c8ce2baa6f416) @@ -204,11 +204,11 @@ set(LIBICONV_SHA256 ccf536620a45458d26ba83887a983b96827001e92a13847b45e4925cc891 set(TREESITTER_C_URL https://github.com/tree-sitter/tree-sitter-c/archive/v0.20.2.tar.gz) set(TREESITTER_C_SHA256 af66fde03feb0df4faf03750102a0d265b007e5d957057b6b293c13116a70af2 ) -set(TREESITTER_LUA_URL https://github.com/MunifTanjim/tree-sitter-lua/archive/v0.0.12.tar.gz) -set(TREESITTER_LUA_SHA256 b6d7c6d04e9101a2e589d25f1d61668301e776c0b8defa6eae8dd86272e9e7c3) +set(TREESITTER_LUA_URL https://github.com/MunifTanjim/tree-sitter-lua/archive/v0.0.13.tar.gz) +set(TREESITTER_LUA_SHA256 564594fe0ffd2f2fb3578a15019b723e1bc94ac82cb6a0103a6b3b9ddcc6f315) -set(TREESITTER_VIM_URL https://github.com/vigoux/tree-sitter-viml/archive/v0.1.0.tar.gz) -set(TREESITTER_VIM_SHA256 ea64fa211ccc7197669017b55911fdb56e8d4b6de96ba25c32b9586ec1c4f4c5) +set(TREESITTER_VIM_URL https://github.com/vigoux/tree-sitter-viml/archive/v0.2.0.tar.gz) +set(TREESITTER_VIM_SHA256 608dcc31a7948cb66ae7f45494620e2e9face1af75598205541f80d782ec4501) set(TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/v0.20.7.tar.gz) set(TREESITTER_SHA256 b355e968ec2d0241bbd96748e00a9038f83968f85d822ecb9940cbe4c42e182e) diff --git a/cmake/GenerateVersion.cmake b/cmake/GenerateVersion.cmake index 6118d8cba7..a7a72fe0bb 100644 --- a/cmake/GenerateVersion.cmake +++ b/cmake/GenerateVersion.cmake @@ -7,15 +7,11 @@ set(NVIM_VERSION_MEDIUM "v${NVIM_VERSION_MAJOR}.${NVIM_VERSION_MINOR}.${NVIM_VERSION_PATCH}${NVIM_VERSION_PRERELEASE}") execute_process( - COMMAND git describe --first-parent --dirty + COMMAND git describe --first-parent --dirty --always OUTPUT_VARIABLE GIT_TAG - ERROR_VARIABLE ERR - RESULT_VARIABLE RES -) + RESULT_VARIABLE RES) -if(NOT RES EQUAL 0) - message(STATUS "Git tag extraction failed:\n" " ${GIT_TAG}${ERR}" ) - # This will only be executed once since the file will get generated afterwards. +if(RES AND NOT RES EQUAL 0) message(STATUS "Using NVIM_VERSION_MEDIUM: ${NVIM_VERSION_MEDIUM}") file(WRITE "${OUTPUT}" "${NVIM_VERSION_STRING}") return() diff --git a/contrib/flake.lock b/contrib/flake.lock index b72e1f8d5f..48f5f0115a 100644 --- a/contrib/flake.lock +++ b/contrib/flake.lock @@ -2,11 +2,11 @@ "nodes": { "flake-utils": { "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "lastModified": 1659877975, + "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", "owner": "numtide", "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", "type": "github" }, "original": { @@ -17,11 +17,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1646254136, - "narHash": "sha256-8nQx02tTzgYO21BP/dy5BCRopE8OwE8Drsw98j+Qoaw=", + "lastModified": 1662019588, + "narHash": "sha256-oPEjHKGGVbBXqwwL+UjsveJzghWiWV0n9ogo1X6l4cw=", "owner": "nixos", "repo": "nixpkgs", - "rev": "3e072546ea98db00c2364b81491b893673267827", + "rev": "2da64a81275b68fdad38af669afeda43d401e94b", "type": "github" }, "original": { diff --git a/contrib/flake.nix b/contrib/flake.nix index a1072674ba..ef3174dda1 100644 --- a/contrib/flake.nix +++ b/contrib/flake.nix @@ -23,24 +23,25 @@ }); # a development binary to help debug issues - neovim-debug = let - stdenv = if pkgs.stdenv.isLinux then pkgs.llvmPackages_latest.stdenv else pkgs.stdenv; - in + neovim-debug = + let + stdenv = if pkgs.stdenv.isLinux then pkgs.llvmPackages_latest.stdenv else pkgs.stdenv; + in ((neovim.override { - lua = pkgs.luajit; - inherit stdenv; - }).overrideAttrs (oa: { + lua = pkgs.luajit; + inherit stdenv; + }).overrideAttrs (oa: { - dontStrip = true; - NIX_CFLAGS_COMPILE = " -ggdb -Og"; + dontStrip = true; + NIX_CFLAGS_COMPILE = " -ggdb -Og"; - cmakeBuildType = "Debug"; - cmakeFlags = oa.cmakeFlags ++ [ - "-DMIN_LOG_LEVEL=0" - ]; + cmakeBuildType = "Debug"; + cmakeFlags = oa.cmakeFlags ++ [ + "-DMIN_LOG_LEVEL=0" + ]; - disallowedReferences = []; - })); + disallowedReferences = [ ]; + })); # for neovim developers, beware of the slow binary neovim-developer = @@ -68,70 +69,71 @@ inherit system; }; - pythonEnv = pkgs.python3.withPackages(ps: [ + lua = pkgs.lua5_1; + + pythonEnv = pkgs.python3.withPackages (ps: [ ps.msgpack - ps.flake8 # for 'make pylint' + ps.flake8 # for 'make pylint' ]); in rec { packages = with pkgs; { + default = neovim; inherit neovim neovim-debug neovim-developer; }; checks = { - pylint = pkgs.runCommandNoCC "pylint" { - nativeBuildInputs = [ pythonEnv ]; - preferLocalBuild = true; + pylint = pkgs.runCommandNoCC "pylint" + { + nativeBuildInputs = [ pythonEnv ]; + preferLocalBuild = true; } "make -C ${./..} pylint > $out"; - shlint = pkgs.runCommandNoCC "shlint" { - nativeBuildInputs = [ pkgs.shellcheck ]; - preferLocalBuild = true; + shlint = pkgs.runCommandNoCC "shlint" + { + nativeBuildInputs = [ pkgs.shellcheck ]; + preferLocalBuild = true; } "make -C ${./..} shlint > $out"; }; + # kept for backwards-compatibility defaultPackage = pkgs.neovim; - apps = { - nvim = flake-utils.lib.mkApp { drv = pkgs.neovim; name = "nvim"; }; - nvim-debug = flake-utils.lib.mkApp { drv = pkgs.neovim-debug; name = "nvim"; }; - }; - - defaultApp = apps.nvim; - - devShell = let - in - pkgs.neovim-developer.overrideAttrs(oa: { - - buildInputs = with pkgs; oa.buildInputs ++ [ - cmake - pythonEnv - include-what-you-use # for scripts/check-includes.py - jq # jq for scripts/vim-patch.sh -r - shellcheck # for `make shlint` - doxygen # for script/gen_vimdoc.py - clang-tools # for clangd to find the correct headers - ]; + devShells = { + default = pkgs.neovim-developer.overrideAttrs (oa: { + + buildInputs = with pkgs; oa.buildInputs ++ [ + cmake + lua.pkgs.luacheck + sumneko-lua-language-server + pythonEnv + include-what-you-use # for scripts/check-includes.py + jq # jq for scripts/vim-patch.sh -r + shellcheck # for `make shlint` + doxygen # for script/gen_vimdoc.py + clang-tools # for clangd to find the correct headers + ]; - shellHook = oa.shellHook + '' - export NVIM_PYTHON_LOG_LEVEL=DEBUG - export NVIM_LOG_FILE=/tmp/nvim.log - export ASAN_SYMBOLIZER_PATH=${pkgs.llvm_11}/bin/llvm-symbolizer - - # ASAN_OPTIONS=detect_leaks=1 - export ASAN_OPTIONS="log_path=./test.log:abort_on_error=1" - export UBSAN_OPTIONS=print_stacktrace=1 - mkdir -p build/runtime/parser - # nvim looks into CMAKE_INSTALL_DIR. Hack to avoid errors - # when running the functionaltests - mkdir -p outputs/out/share/nvim/syntax - touch outputs/out/share/nvim/syntax/syntax.vim - - # for treesitter functionaltests - mkdir -p runtime/parser - cp -f ${pkgs.tree-sitter.builtGrammars.tree-sitter-c}/parser runtime/parser/c.so - ''; - }); - }); + shellHook = oa.shellHook + '' + export NVIM_PYTHON_LOG_LEVEL=DEBUG + export NVIM_LOG_FILE=/tmp/nvim.log + export ASAN_SYMBOLIZER_PATH=${pkgs.llvm_11}/bin/llvm-symbolizer + + # ASAN_OPTIONS=detect_leaks=1 + export ASAN_OPTIONS="log_path=./test.log:abort_on_error=1" + export UBSAN_OPTIONS=print_stacktrace=1 + mkdir -p build/runtime/parser + # nvim looks into CMAKE_INSTALL_DIR. Hack to avoid errors + # when running the functionaltests + mkdir -p outputs/out/share/nvim/syntax + touch outputs/out/share/nvim/syntax/syntax.vim + + # for treesitter functionaltests + mkdir -p runtime/parser + cp -f ${pkgs.tree-sitter.builtGrammars.tree-sitter-c}/parser runtime/parser/c.so + ''; + }); + }; + }); } diff --git a/runtime/colors/lunaperche.vim b/runtime/colors/lunaperche.vim index b717ca7855..159e04cc0b 100644 --- a/runtime/colors/lunaperche.vim +++ b/runtime/colors/lunaperche.vim @@ -4,7 +4,7 @@ " Maintainer: Maxim Kim <habamax@gmail.com> " Website: https://www.github.com/vim/colorschemes " License: Vim License (see `:help license`) -" Last Updated: Sat 03 Sep 2022 14:31:51 MSK +" Last Updated: Fri 16 Sep 2022 13:15:33 MSK " Generated by Colortemplate v2.2.0 @@ -26,12 +26,15 @@ hi! link fugitiveUnstagedModifier PreProc hi! link fugitiveHash Constant hi! link diffFile PreProc hi! link markdownHeadingDelimiter Special -hi! link rstSectionDelimiter PreProc -hi! link rstDirective Special +hi! link rstSectionDelimiter Statement +hi! link rstDirective PreProc hi! link rstHyperlinkReference Special -hi! link rstFieldName Special +hi! link rstFieldName Constant hi! link rstDelimiter Special hi! link rstInterpretedText Special +hi! link rstCodeBlock Normal +hi! link rstLiteralBlock rstCodeBlock +hi! link markdownUrl String hi! link colortemplateKey Statement hi! link xmlTagName Statement hi! link javaScriptFunction Statement @@ -92,6 +95,20 @@ hi! link phpOperator Normal hi! link phpVarSelector Special hi! link phpMemberSelector Special hi! link phpDocCustomTags phpDocTags +hi! link javaExternal Statement +hi! link javaType Statement +hi! link javaScopeDecl Statement +hi! link javaClassDecl Statement +hi! link javaStorageClass Statement +hi! link javaDocParam PreProc +hi! link csStorage Statement +hi! link csAccessModifier Statement +hi! link csClass Statement +hi! link csModifier Statement +hi! link csAsyncModifier Statement +hi! link csLogicSymbols Normal +hi! link csClassType Normal +hi! link csType Statement hi! link Terminal Normal hi! link StatuslineTerm Statusline hi! link StatuslineTermNC StatuslineNC @@ -101,7 +118,7 @@ hi! link MessageWindow PMenu hi! link PopupNotification Todo if &background ==# 'dark' if (has('termguicolors') && &termguicolors) || has('gui_running') - let g:terminal_ansi_colors = ['#000000', '#af5f5f', '#5faf5f', '#af875f', '#5f87af', '#d787af', '#5fafaf', '#c6c6c6', '#767676', '#ff5f5f', '#5fd75f', '#ffd787', '#87afd7', '#ffafd7', '#5fd7d7', '#ffffff'] + let g:terminal_ansi_colors = ['#000000', '#af5f5f', '#5faf5f', '#af875f', '#5f87af', '#d787d7', '#5fafaf', '#c6c6c6', '#767676', '#ff5f5f', '#5fd75f', '#ffd787', '#5fafff', '#ff87ff', '#5fd7d7', '#ffffff'] endif hi Normal guifg=#c6c6c6 guibg=#000000 gui=NONE cterm=NONE hi Statusline guifg=#c6c6c6 guibg=#000000 gui=bold,reverse cterm=bold,reverse @@ -112,7 +129,7 @@ if &background ==# 'dark' hi TabLineSel guifg=#ffffff guibg=#000000 gui=bold cterm=bold hi ToolbarLine guifg=NONE guibg=NONE gui=NONE ctermfg=NONE ctermbg=NONE cterm=NONE hi ToolbarButton guifg=#000000 guibg=#ffffff gui=NONE cterm=NONE - hi QuickFixLine guifg=#000000 guibg=#87afd7 gui=NONE cterm=NONE + hi QuickFixLine guifg=#000000 guibg=#5fafff gui=NONE cterm=NONE hi CursorLineNr guifg=#ffffff guibg=NONE gui=bold cterm=bold hi LineNr guifg=#585858 guibg=NONE gui=NONE cterm=NONE hi NonText guifg=#585858 guibg=NONE gui=NONE cterm=NONE @@ -128,7 +145,7 @@ if &background ==# 'dark' hi ErrorMsg guifg=#ffffff guibg=#ff5f5f gui=NONE cterm=NONE hi ModeMsg guifg=#ffd787 guibg=NONE gui=reverse cterm=reverse hi MoreMsg guifg=#5fd75f guibg=NONE gui=NONE cterm=NONE - hi Question guifg=#ffafd7 guibg=NONE gui=NONE cterm=NONE + hi Question guifg=#ff87ff guibg=NONE gui=NONE cterm=NONE hi WarningMsg guifg=#ff5f5f guibg=NONE gui=NONE cterm=NONE hi Todo guifg=#5fd7d7 guibg=#000000 gui=reverse cterm=reverse hi Search guifg=#000000 guibg=#ffd787 gui=NONE cterm=NONE @@ -137,7 +154,7 @@ if &background ==# 'dark' hi WildMenu guifg=#000000 guibg=#ffd787 gui=bold cterm=bold hi debugPC guifg=#5f87af guibg=NONE gui=reverse cterm=reverse hi debugBreakpoint guifg=#5fafaf guibg=NONE gui=reverse cterm=reverse - hi Cursor guifg=#ffffff guibg=#000000 gui=reverse cterm=reverse + hi Cursor guifg=NONE guibg=NONE gui=reverse ctermfg=NONE ctermbg=NONE cterm=reverse hi lCursor guifg=#ff5fff guibg=#000000 gui=reverse cterm=reverse hi Visual guifg=#ffffff guibg=#005f87 gui=NONE cterm=NONE hi MatchParen guifg=#c5e7c5 guibg=#000000 gui=reverse cterm=reverse @@ -149,17 +166,18 @@ if &background ==# 'dark' hi SpellBad guifg=NONE guibg=NONE guisp=#ff5f5f gui=undercurl ctermfg=NONE ctermbg=NONE cterm=NONE hi SpellCap guifg=NONE guibg=NONE guisp=#5fafaf gui=undercurl ctermfg=NONE ctermbg=NONE cterm=NONE hi SpellLocal guifg=NONE guibg=NONE guisp=#5faf5f gui=undercurl ctermfg=NONE ctermbg=NONE cterm=NONE - hi SpellRare guifg=NONE guibg=NONE guisp=#ffafd7 gui=undercurl ctermfg=NONE ctermbg=NONE cterm=NONE - hi Comment guifg=#87afd7 guibg=NONE gui=NONE cterm=NONE - hi Constant guifg=#ffd787 guibg=NONE gui=NONE cterm=NONE + hi SpellRare guifg=NONE guibg=NONE guisp=#ff87ff gui=undercurl ctermfg=NONE ctermbg=NONE cterm=NONE + hi Comment guifg=#5fafff guibg=NONE gui=NONE cterm=NONE + hi Constant guifg=#ff87ff guibg=NONE gui=NONE cterm=NONE + hi String guifg=#ffd787 guibg=NONE gui=NONE cterm=NONE hi Identifier guifg=NONE guibg=NONE gui=NONE ctermfg=NONE ctermbg=NONE cterm=NONE - hi Statement guifg=#eeeeee guibg=NONE gui=bold cterm=bold - hi Type guifg=#5fd75f guibg=NONE gui=bold cterm=bold - hi PreProc guifg=#af875f guibg=NONE gui=NONE cterm=NONE + hi Statement guifg=#e4e4e4 guibg=NONE gui=bold cterm=bold + hi Type guifg=#5fd75f guibg=NONE gui=NONE cterm=NONE + hi PreProc guifg=#5fd7d7 guibg=NONE gui=NONE cterm=NONE hi Special guifg=#5fafaf guibg=NONE gui=NONE cterm=NONE hi Underlined guifg=NONE guibg=NONE gui=underline ctermfg=NONE ctermbg=NONE cterm=underline hi Title guifg=NONE guibg=NONE gui=bold ctermfg=NONE ctermbg=NONE cterm=bold - hi Directory guifg=#5fd7d7 guibg=NONE gui=bold cterm=bold + hi Directory guifg=#5fafff guibg=NONE gui=bold cterm=bold hi Conceal guifg=NONE guibg=NONE gui=NONE ctermfg=NONE ctermbg=NONE cterm=NONE hi Ignore guifg=NONE guibg=NONE gui=NONE ctermfg=NONE ctermbg=NONE cterm=NONE hi DiffAdd guifg=#000000 guibg=#af87af gui=NONE cterm=NONE @@ -168,8 +186,8 @@ if &background ==# 'dark' hi DiffDelete guifg=#d78787 guibg=NONE gui=NONE cterm=NONE hi diffAdded guifg=#5fd75f guibg=NONE gui=NONE cterm=NONE hi diffRemoved guifg=#d78787 guibg=NONE gui=NONE cterm=NONE - hi diffSubname guifg=#ffafd7 guibg=NONE gui=NONE cterm=NONE - hi dirType guifg=#d787af guibg=NONE gui=NONE cterm=NONE + hi diffSubname guifg=#ff87ff guibg=NONE gui=NONE cterm=NONE + hi dirType guifg=#d787d7 guibg=NONE gui=NONE cterm=NONE hi dirPermissionUser guifg=#5faf5f guibg=NONE gui=NONE cterm=NONE hi dirPermissionGroup guifg=#af875f guibg=NONE gui=NONE cterm=NONE hi dirPermissionOther guifg=#5fafaf guibg=NONE gui=NONE cterm=NONE @@ -177,7 +195,7 @@ if &background ==# 'dark' hi dirGroup guifg=#767676 guibg=NONE gui=NONE cterm=NONE hi dirTime guifg=#767676 guibg=NONE gui=NONE cterm=NONE hi dirSize guifg=#ffd787 guibg=NONE gui=NONE cterm=NONE - hi dirSizeMod guifg=#d787af guibg=NONE gui=NONE cterm=NONE + hi dirSizeMod guifg=#d787d7 guibg=NONE gui=NONE cterm=NONE hi FilterMenuDirectorySubtle guifg=#878787 guibg=NONE gui=NONE cterm=NONE hi dirFilterMenuBookmarkPath guifg=#878787 guibg=NONE gui=NONE cterm=NONE hi dirFilterMenuHistoryPath guifg=#878787 guibg=NONE gui=NONE cterm=NONE @@ -186,7 +204,7 @@ if &background ==# 'dark' else " Light background if (has('termguicolors') && &termguicolors) || has('gui_running') - let g:terminal_ansi_colors = ['#000000', '#870000', '#008700', '#875f00', '#005faf', '#870087', '#005f5f', '#808080', '#767676', '#d70000', '#87d787', '#d7d787', '#0087d7', '#af00af', '#00afaf', '#ffffff'] + let g:terminal_ansi_colors = ['#000000', '#af0000', '#008700', '#af5f00', '#005fd7', '#af00af', '#005f5f', '#808080', '#767676', '#d70000', '#87d787', '#ffd787', '#0087d7', '#ff00ff', '#008787', '#ffffff'] endif hi Normal guifg=#000000 guibg=#ffffff gui=NONE cterm=NONE hi Statusline guifg=#ffffff guibg=#000000 gui=bold cterm=bold @@ -211,40 +229,41 @@ else hi SignColumn guifg=NONE guibg=NONE gui=NONE ctermfg=NONE ctermbg=NONE cterm=NONE hi Error guifg=#ffffff guibg=#d70000 gui=NONE cterm=NONE hi ErrorMsg guifg=#ffffff guibg=#d70000 gui=NONE cterm=NONE - hi ModeMsg guifg=#d7d787 guibg=#000000 gui=reverse cterm=reverse + hi ModeMsg guifg=#ffd787 guibg=#000000 gui=reverse cterm=reverse hi MoreMsg guifg=#008700 guibg=NONE gui=bold cterm=bold - hi Question guifg=#870087 guibg=NONE gui=bold cterm=bold + hi Question guifg=#af00af guibg=NONE gui=bold cterm=bold hi WarningMsg guifg=#d70000 guibg=NONE gui=bold cterm=bold - hi Todo guifg=#005f5f guibg=#ffffff gui=reverse cterm=reverse - hi Search guifg=#000000 guibg=#d7d787 gui=NONE cterm=NONE + hi Todo guifg=#008787 guibg=#ffffff gui=reverse cterm=reverse + hi Search guifg=#000000 guibg=#ffd787 gui=NONE cterm=NONE hi IncSearch guifg=#000000 guibg=#87d787 gui=NONE cterm=NONE hi CurSearch guifg=#000000 guibg=#87d787 gui=NONE cterm=NONE - hi WildMenu guifg=#000000 guibg=#d7d787 gui=bold cterm=bold - hi debugPC guifg=#005faf guibg=NONE gui=reverse cterm=reverse + hi WildMenu guifg=#000000 guibg=#ffd787 gui=bold cterm=bold + hi debugPC guifg=#005fd7 guibg=NONE gui=reverse cterm=reverse hi debugBreakpoint guifg=#005f5f guibg=NONE gui=reverse cterm=reverse - hi Cursor guifg=#000000 guibg=#ffffff gui=reverse cterm=reverse + hi Cursor guifg=NONE guibg=NONE gui=reverse ctermfg=NONE ctermbg=NONE cterm=reverse hi lCursor guifg=#ff00ff guibg=#000000 gui=reverse cterm=reverse hi Visual guifg=#ffffff guibg=#5f87af gui=NONE cterm=NONE hi MatchParen guifg=NONE guibg=#c5e7c5 gui=NONE cterm=NONE - hi VisualNOS guifg=#ffffff guibg=#00afaf gui=NONE cterm=NONE + hi VisualNOS guifg=#ffffff guibg=#008787 gui=NONE cterm=NONE hi CursorLine guifg=NONE guibg=#e4e4e4 gui=NONE cterm=NONE hi CursorColumn guifg=NONE guibg=#e4e4e4 gui=NONE cterm=NONE hi Folded guifg=#767676 guibg=#eeeeee gui=NONE cterm=NONE hi ColorColumn guifg=NONE guibg=#eeeeee gui=NONE cterm=NONE - hi SpellBad guifg=NONE guibg=NONE guisp=#870000 gui=undercurl ctermfg=NONE ctermbg=NONE cterm=NONE + hi SpellBad guifg=NONE guibg=NONE guisp=#af0000 gui=undercurl ctermfg=NONE ctermbg=NONE cterm=NONE hi SpellCap guifg=NONE guibg=NONE guisp=#005f5f gui=undercurl ctermfg=NONE ctermbg=NONE cterm=NONE hi SpellLocal guifg=NONE guibg=NONE guisp=#008700 gui=undercurl ctermfg=NONE ctermbg=NONE cterm=NONE - hi SpellRare guifg=NONE guibg=NONE guisp=#af00af gui=undercurl ctermfg=NONE ctermbg=NONE cterm=NONE - hi Comment guifg=#005faf guibg=NONE gui=NONE cterm=NONE - hi Constant guifg=#870000 guibg=NONE gui=NONE cterm=NONE + hi SpellRare guifg=NONE guibg=NONE guisp=#ff00ff gui=undercurl ctermfg=NONE ctermbg=NONE cterm=NONE + hi Comment guifg=#005fd7 guibg=NONE gui=NONE cterm=NONE + hi Constant guifg=#af00af guibg=NONE gui=NONE cterm=NONE + hi String guifg=#af5f00 guibg=NONE gui=NONE cterm=NONE hi Identifier guifg=NONE guibg=NONE gui=NONE ctermfg=NONE ctermbg=NONE cterm=NONE hi Statement guifg=#000000 guibg=NONE gui=bold cterm=bold - hi Type guifg=#008700 guibg=NONE gui=bold cterm=bold - hi PreProc guifg=#875f00 guibg=NONE gui=NONE cterm=NONE - hi Special guifg=#005f5f guibg=NONE gui=NONE cterm=NONE + hi Type guifg=#008700 guibg=NONE gui=NONE cterm=NONE + hi PreProc guifg=#005f5f guibg=NONE gui=NONE cterm=NONE + hi Special guifg=#008787 guibg=NONE gui=NONE cterm=NONE hi Underlined guifg=NONE guibg=NONE gui=underline ctermfg=NONE ctermbg=NONE cterm=underline hi Title guifg=NONE guibg=NONE gui=bold ctermfg=NONE ctermbg=NONE cterm=bold - hi Directory guifg=#005faf guibg=NONE gui=bold cterm=bold + hi Directory guifg=#005fd7 guibg=NONE gui=bold cterm=bold hi Conceal guifg=NONE guibg=NONE gui=NONE ctermfg=NONE ctermbg=NONE cterm=NONE hi Ignore guifg=NONE guibg=NONE gui=NONE ctermfg=NONE ctermbg=NONE cterm=NONE hi DiffAdd guifg=#000000 guibg=#d7afd7 gui=NONE cterm=NONE @@ -253,22 +272,22 @@ else hi DiffDelete guifg=#870000 guibg=NONE gui=NONE cterm=NONE hi diffAdded guifg=#008700 guibg=NONE gui=NONE cterm=NONE hi diffRemoved guifg=#d70000 guibg=NONE gui=NONE cterm=NONE - hi diffSubname guifg=#870087 guibg=NONE gui=NONE cterm=NONE + hi diffSubname guifg=#af00af guibg=NONE gui=NONE cterm=NONE hi dirType guifg=#005f5f guibg=NONE gui=NONE cterm=NONE - hi dirPermissionUser guifg=#875f00 guibg=NONE gui=NONE cterm=NONE + hi dirPermissionUser guifg=#af5f00 guibg=NONE gui=NONE cterm=NONE hi dirPermissionGroup guifg=#008700 guibg=NONE gui=NONE cterm=NONE - hi dirPermissionOther guifg=#870087 guibg=NONE gui=NONE cterm=NONE + hi dirPermissionOther guifg=#af00af guibg=NONE gui=NONE cterm=NONE hi dirOwner guifg=#808080 guibg=NONE gui=NONE cterm=NONE hi dirGroup guifg=#808080 guibg=NONE gui=NONE cterm=NONE hi dirTime guifg=#808080 guibg=NONE gui=NONE cterm=NONE - hi dirSize guifg=#870000 guibg=NONE gui=NONE cterm=NONE + hi dirSize guifg=#af0000 guibg=NONE gui=NONE cterm=NONE hi dirSizeMod guifg=#005f5f guibg=NONE gui=NONE cterm=NONE hi dirLink guifg=#008700 guibg=NONE gui=bold cterm=bold hi dirFilterMenuBookmarkPath guifg=#626262 guibg=NONE gui=NONE cterm=NONE hi dirFilterMenuHistoryPath guifg=#626262 guibg=NONE gui=NONE cterm=NONE hi FilterMenuDirectorySubtle guifg=#626262 guibg=NONE gui=NONE cterm=NONE hi FilterMenuLineNr guifg=#626262 guibg=NONE gui=NONE cterm=NONE - hi CocSearch guifg=#870000 guibg=NONE gui=NONE cterm=NONE + hi CocSearch guifg=#af0000 guibg=NONE gui=NONE cterm=NONE endif if s:t_Co >= 256 @@ -285,12 +304,15 @@ if s:t_Co >= 256 hi! link fugitiveHash Constant hi! link diffFile PreProc hi! link markdownHeadingDelimiter Special - hi! link rstSectionDelimiter PreProc - hi! link rstDirective Special + hi! link rstSectionDelimiter Statement + hi! link rstDirective PreProc hi! link rstHyperlinkReference Special - hi! link rstFieldName Special + hi! link rstFieldName Constant hi! link rstDelimiter Special hi! link rstInterpretedText Special + hi! link rstCodeBlock Normal + hi! link rstLiteralBlock rstCodeBlock + hi! link markdownUrl String hi! link colortemplateKey Statement hi! link xmlTagName Statement hi! link javaScriptFunction Statement @@ -351,6 +373,20 @@ if s:t_Co >= 256 hi! link phpVarSelector Special hi! link phpMemberSelector Special hi! link phpDocCustomTags phpDocTags + hi! link javaExternal Statement + hi! link javaType Statement + hi! link javaScopeDecl Statement + hi! link javaClassDecl Statement + hi! link javaStorageClass Statement + hi! link javaDocParam PreProc + hi! link csStorage Statement + hi! link csAccessModifier Statement + hi! link csClass Statement + hi! link csModifier Statement + hi! link csAsyncModifier Statement + hi! link csLogicSymbols Normal + hi! link csClassType Normal + hi! link csType Statement hi! link Terminal Normal hi! link StatuslineTerm Statusline hi! link StatuslineTermNC StatuslineNC @@ -368,7 +404,7 @@ if s:t_Co >= 256 hi TabLineSel ctermfg=231 ctermbg=16 cterm=bold hi ToolbarLine ctermfg=NONE ctermbg=NONE cterm=NONE hi ToolbarButton ctermfg=16 ctermbg=231 cterm=NONE - hi QuickFixLine ctermfg=16 ctermbg=110 cterm=NONE + hi QuickFixLine ctermfg=16 ctermbg=75 cterm=NONE hi CursorLineNr ctermfg=231 ctermbg=NONE cterm=bold hi LineNr ctermfg=240 ctermbg=NONE cterm=NONE hi NonText ctermfg=240 ctermbg=NONE cterm=NONE @@ -384,7 +420,7 @@ if s:t_Co >= 256 hi ErrorMsg ctermfg=231 ctermbg=203 cterm=NONE hi ModeMsg ctermfg=222 ctermbg=NONE cterm=reverse hi MoreMsg ctermfg=77 ctermbg=NONE cterm=NONE - hi Question ctermfg=218 ctermbg=NONE cterm=NONE + hi Question ctermfg=213 ctermbg=NONE cterm=NONE hi WarningMsg ctermfg=203 ctermbg=NONE cterm=NONE hi Todo ctermfg=116 ctermbg=16 cterm=reverse hi Search ctermfg=16 ctermbg=222 cterm=NONE @@ -403,17 +439,18 @@ if s:t_Co >= 256 hi SpellBad ctermfg=203 ctermbg=NONE cterm=underline hi SpellCap ctermfg=73 ctermbg=NONE cterm=underline hi SpellLocal ctermfg=77 ctermbg=NONE cterm=underline - hi SpellRare ctermfg=218 ctermbg=NONE cterm=underline - hi Comment ctermfg=110 ctermbg=NONE cterm=NONE - hi Constant ctermfg=222 ctermbg=NONE cterm=NONE + hi SpellRare ctermfg=213 ctermbg=NONE cterm=underline + hi Comment ctermfg=75 ctermbg=NONE cterm=NONE + hi Constant ctermfg=213 ctermbg=NONE cterm=NONE + hi String ctermfg=222 ctermbg=NONE cterm=NONE hi Identifier ctermfg=NONE ctermbg=NONE cterm=NONE - hi Statement ctermfg=255 ctermbg=NONE cterm=bold - hi Type ctermfg=77 ctermbg=NONE cterm=bold - hi PreProc ctermfg=137 ctermbg=NONE cterm=NONE + hi Statement ctermfg=254 ctermbg=NONE cterm=bold + hi Type ctermfg=77 ctermbg=NONE cterm=NONE + hi PreProc ctermfg=116 ctermbg=NONE cterm=NONE hi Special ctermfg=73 ctermbg=NONE cterm=NONE hi Underlined ctermfg=NONE ctermbg=NONE cterm=underline hi Title ctermfg=NONE ctermbg=NONE cterm=bold - hi Directory ctermfg=116 ctermbg=NONE cterm=bold + hi Directory ctermfg=75 ctermbg=NONE cterm=bold hi Conceal ctermfg=NONE ctermbg=NONE cterm=NONE hi Ignore ctermfg=NONE ctermbg=NONE cterm=NONE hi DiffAdd ctermfg=16 ctermbg=139 cterm=NONE @@ -422,8 +459,8 @@ if s:t_Co >= 256 hi DiffDelete ctermfg=174 ctermbg=NONE cterm=NONE hi diffAdded ctermfg=77 ctermbg=NONE cterm=NONE hi diffRemoved ctermfg=174 ctermbg=NONE cterm=NONE - hi diffSubname ctermfg=218 ctermbg=NONE cterm=NONE - hi dirType ctermfg=175 ctermbg=NONE cterm=NONE + hi diffSubname ctermfg=213 ctermbg=NONE cterm=NONE + hi dirType ctermfg=176 ctermbg=NONE cterm=NONE hi dirPermissionUser ctermfg=71 ctermbg=NONE cterm=NONE hi dirPermissionGroup ctermfg=137 ctermbg=NONE cterm=NONE hi dirPermissionOther ctermfg=73 ctermbg=NONE cterm=NONE @@ -431,7 +468,7 @@ if s:t_Co >= 256 hi dirGroup ctermfg=243 ctermbg=NONE cterm=NONE hi dirTime ctermfg=243 ctermbg=NONE cterm=NONE hi dirSize ctermfg=222 ctermbg=NONE cterm=NONE - hi dirSizeMod ctermfg=175 ctermbg=NONE cterm=NONE + hi dirSizeMod ctermfg=176 ctermbg=NONE cterm=NONE hi FilterMenuDirectorySubtle ctermfg=102 ctermbg=NONE cterm=NONE hi dirFilterMenuBookmarkPath ctermfg=102 ctermbg=NONE cterm=NONE hi dirFilterMenuHistoryPath ctermfg=102 ctermbg=NONE cterm=NONE @@ -462,38 +499,39 @@ if s:t_Co >= 256 hi SignColumn ctermfg=NONE ctermbg=NONE cterm=NONE hi Error ctermfg=231 ctermbg=160 cterm=NONE hi ErrorMsg ctermfg=231 ctermbg=160 cterm=NONE - hi ModeMsg ctermfg=186 ctermbg=16 cterm=reverse + hi ModeMsg ctermfg=222 ctermbg=16 cterm=reverse hi MoreMsg ctermfg=28 ctermbg=NONE cterm=bold - hi Question ctermfg=90 ctermbg=NONE cterm=bold + hi Question ctermfg=127 ctermbg=NONE cterm=bold hi WarningMsg ctermfg=160 ctermbg=NONE cterm=bold - hi Todo ctermfg=23 ctermbg=231 cterm=reverse - hi Search ctermfg=16 ctermbg=186 cterm=NONE + hi Todo ctermfg=30 ctermbg=231 cterm=reverse + hi Search ctermfg=16 ctermbg=222 cterm=NONE hi IncSearch ctermfg=16 ctermbg=114 cterm=NONE hi CurSearch ctermfg=16 ctermbg=114 cterm=NONE - hi WildMenu ctermfg=16 ctermbg=186 cterm=bold - hi debugPC ctermfg=25 ctermbg=NONE cterm=reverse + hi WildMenu ctermfg=16 ctermbg=222 cterm=bold + hi debugPC ctermfg=26 ctermbg=NONE cterm=reverse hi debugBreakpoint ctermfg=23 ctermbg=NONE cterm=reverse hi Visual ctermfg=231 ctermbg=67 cterm=NONE hi MatchParen ctermfg=30 ctermbg=231 cterm=reverse - hi VisualNOS ctermfg=231 ctermbg=37 cterm=NONE + hi VisualNOS ctermfg=231 ctermbg=30 cterm=NONE hi CursorLine ctermfg=NONE ctermbg=254 cterm=NONE hi CursorColumn ctermfg=NONE ctermbg=254 cterm=NONE hi Folded ctermfg=243 ctermbg=255 cterm=NONE hi ColorColumn ctermfg=NONE ctermbg=255 cterm=NONE - hi SpellBad ctermfg=88 ctermbg=NONE cterm=underline + hi SpellBad ctermfg=124 ctermbg=NONE cterm=underline hi SpellCap ctermfg=23 ctermbg=NONE cterm=underline hi SpellLocal ctermfg=28 ctermbg=NONE cterm=underline hi SpellRare ctermfg=133 ctermbg=NONE cterm=underline - hi Comment ctermfg=25 ctermbg=NONE cterm=NONE - hi Constant ctermfg=88 ctermbg=NONE cterm=NONE + hi Comment ctermfg=26 ctermbg=NONE cterm=NONE + hi Constant ctermfg=127 ctermbg=NONE cterm=NONE + hi String ctermfg=130 ctermbg=NONE cterm=NONE hi Identifier ctermfg=NONE ctermbg=NONE cterm=NONE hi Statement ctermfg=16 ctermbg=NONE cterm=bold - hi Type ctermfg=28 ctermbg=NONE cterm=bold - hi PreProc ctermfg=94 ctermbg=NONE cterm=NONE - hi Special ctermfg=23 ctermbg=NONE cterm=NONE + hi Type ctermfg=28 ctermbg=NONE cterm=NONE + hi PreProc ctermfg=23 ctermbg=NONE cterm=NONE + hi Special ctermfg=30 ctermbg=NONE cterm=NONE hi Underlined ctermfg=NONE ctermbg=NONE cterm=underline hi Title ctermfg=NONE ctermbg=NONE cterm=bold - hi Directory ctermfg=25 ctermbg=NONE cterm=bold + hi Directory ctermfg=26 ctermbg=NONE cterm=bold hi Conceal ctermfg=NONE ctermbg=NONE cterm=NONE hi Ignore ctermfg=NONE ctermbg=NONE cterm=NONE hi DiffAdd ctermfg=16 ctermbg=182 cterm=NONE @@ -502,22 +540,22 @@ if s:t_Co >= 256 hi DiffDelete ctermfg=88 ctermbg=NONE cterm=NONE hi diffAdded ctermfg=28 ctermbg=NONE cterm=NONE hi diffRemoved ctermfg=160 ctermbg=NONE cterm=NONE - hi diffSubname ctermfg=90 ctermbg=NONE cterm=NONE + hi diffSubname ctermfg=127 ctermbg=NONE cterm=NONE hi dirType ctermfg=23 ctermbg=NONE cterm=NONE - hi dirPermissionUser ctermfg=94 ctermbg=NONE cterm=NONE + hi dirPermissionUser ctermfg=130 ctermbg=NONE cterm=NONE hi dirPermissionGroup ctermfg=28 ctermbg=NONE cterm=NONE - hi dirPermissionOther ctermfg=90 ctermbg=NONE cterm=NONE + hi dirPermissionOther ctermfg=127 ctermbg=NONE cterm=NONE hi dirOwner ctermfg=244 ctermbg=NONE cterm=NONE hi dirGroup ctermfg=244 ctermbg=NONE cterm=NONE hi dirTime ctermfg=244 ctermbg=NONE cterm=NONE - hi dirSize ctermfg=88 ctermbg=NONE cterm=NONE + hi dirSize ctermfg=124 ctermbg=NONE cterm=NONE hi dirSizeMod ctermfg=23 ctermbg=NONE cterm=NONE hi dirLink ctermfg=28 ctermbg=NONE cterm=bold hi dirFilterMenuBookmarkPath ctermfg=241 ctermbg=NONE cterm=NONE hi dirFilterMenuHistoryPath ctermfg=241 ctermbg=NONE cterm=NONE hi FilterMenuDirectorySubtle ctermfg=241 ctermbg=NONE cterm=NONE hi FilterMenuLineNr ctermfg=241 ctermbg=NONE cterm=NONE - hi CocSearch ctermfg=88 ctermbg=NONE cterm=NONE + hi CocSearch ctermfg=124 ctermbg=NONE cterm=NONE endif unlet s:t_Co finish @@ -571,15 +609,16 @@ if s:t_Co >= 16 hi SpellLocal ctermfg=green ctermbg=NONE cterm=underline hi SpellRare ctermfg=magenta ctermbg=NONE cterm=underline hi Comment ctermfg=blue ctermbg=NONE cterm=NONE - hi Constant ctermfg=yellow ctermbg=NONE cterm=NONE + hi Constant ctermfg=magenta ctermbg=NONE cterm=NONE + hi String ctermfg=yellow ctermbg=NONE cterm=NONE hi Identifier ctermfg=NONE ctermbg=NONE cterm=NONE hi Statement ctermfg=grey ctermbg=NONE cterm=bold - hi Type ctermfg=green ctermbg=NONE cterm=bold - hi PreProc ctermfg=darkyellow ctermbg=NONE cterm=NONE + hi Type ctermfg=green ctermbg=NONE cterm=NONE + hi PreProc ctermfg=cyan ctermbg=NONE cterm=NONE hi Special ctermfg=darkcyan ctermbg=NONE cterm=NONE hi Underlined ctermfg=NONE ctermbg=NONE cterm=underline hi Title ctermfg=NONE ctermbg=NONE cterm=bold - hi Directory ctermfg=cyan ctermbg=NONE cterm=bold + hi Directory ctermfg=blue ctermbg=NONE cterm=bold hi Conceal ctermfg=NONE ctermbg=NONE cterm=NONE hi Ignore ctermfg=NONE ctermbg=NONE cterm=NONE hi DiffAdd ctermfg=black ctermbg=darkmagenta cterm=NONE @@ -632,7 +671,7 @@ if s:t_Co >= 16 hi MoreMsg ctermfg=darkgreen ctermbg=NONE cterm=bold hi Question ctermfg=darkmagenta ctermbg=NONE cterm=bold hi WarningMsg ctermfg=red ctermbg=NONE cterm=bold - hi Todo ctermfg=darkcyan ctermbg=white cterm=reverse + hi Todo ctermfg=cyan ctermbg=white cterm=reverse hi Search ctermfg=black ctermbg=yellow cterm=NONE hi IncSearch ctermfg=black ctermbg=green cterm=NONE hi CurSearch ctermfg=black ctermbg=green cterm=NONE @@ -651,12 +690,13 @@ if s:t_Co >= 16 hi SpellLocal ctermfg=darkgreen ctermbg=NONE cterm=underline hi SpellRare ctermfg=magenta ctermbg=NONE cterm=underline hi Comment ctermfg=darkblue ctermbg=NONE cterm=NONE - hi Constant ctermfg=darkred ctermbg=NONE cterm=NONE + hi Constant ctermfg=darkmagenta ctermbg=NONE cterm=NONE + hi String ctermfg=darkyellow ctermbg=NONE cterm=NONE hi Identifier ctermfg=NONE ctermbg=NONE cterm=NONE hi Statement ctermfg=black ctermbg=NONE cterm=bold - hi Type ctermfg=darkgreen ctermbg=NONE cterm=bold - hi PreProc ctermfg=darkyellow ctermbg=NONE cterm=NONE - hi Special ctermfg=darkcyan ctermbg=NONE cterm=NONE + hi Type ctermfg=darkgreen ctermbg=NONE cterm=NONE + hi PreProc ctermfg=darkcyan ctermbg=NONE cterm=NONE + hi Special ctermfg=cyan ctermbg=NONE cterm=NONE hi Underlined ctermfg=NONE ctermbg=NONE cterm=underline hi Title ctermfg=NONE ctermbg=NONE cterm=bold hi Directory ctermfg=darkblue ctermbg=NONE cterm=bold @@ -707,7 +747,7 @@ if s:t_Co >= 8 hi FoldColumn ctermfg=black ctermbg=NONE cterm=NONE hi EndOfBuffer ctermfg=black ctermbg=NONE cterm=NONE hi SpecialKey ctermfg=black ctermbg=NONE cterm=NONE - hi Pmenu ctermfg=black ctermbg=grey cterm=NONE + hi Pmenu ctermfg=NONE ctermbg=grey cterm=NONE hi PmenuThumb ctermfg=NONE ctermbg=darkgreen cterm=NONE hi PmenuSbar ctermfg=NONE ctermbg=NONE cterm=NONE hi PmenuSel ctermfg=black ctermbg=darkcyan cterm=NONE @@ -725,7 +765,7 @@ if s:t_Co >= 8 hi WildMenu ctermfg=black ctermbg=darkyellow cterm=bold hi debugPC ctermfg=darkblue ctermbg=NONE cterm=reverse hi debugBreakpoint ctermfg=darkcyan ctermbg=NONE cterm=reverse - hi Visual ctermfg=black ctermbg=darkblue cterm=NONE + hi Visual ctermfg=NONE ctermbg=NONE cterm=reverse hi MatchParen ctermfg=darkcyan ctermbg=black cterm=reverse hi VisualNOS ctermfg=black ctermbg=darkcyan cterm=NONE hi CursorLine ctermfg=NONE ctermbg=NONE cterm=underline @@ -740,12 +780,12 @@ if s:t_Co >= 8 hi Constant ctermfg=darkred ctermbg=NONE cterm=NONE hi Identifier ctermfg=NONE ctermbg=NONE cterm=NONE hi Statement ctermfg=grey ctermbg=NONE cterm=bold - hi Type ctermfg=darkgreen ctermbg=NONE cterm=bold - hi PreProc ctermfg=darkyellow ctermbg=NONE cterm=NONE + hi Type ctermfg=darkgreen ctermbg=NONE cterm=NONE + hi PreProc ctermfg=darkcyan ctermbg=NONE cterm=NONE hi Special ctermfg=darkcyan ctermbg=NONE cterm=NONE hi Underlined ctermfg=NONE ctermbg=NONE cterm=underline hi Title ctermfg=NONE ctermbg=NONE cterm=bold - hi Directory ctermfg=darkcyan ctermbg=NONE cterm=bold + hi Directory ctermfg=darkblue ctermbg=NONE cterm=bold hi Conceal ctermfg=NONE ctermbg=NONE cterm=NONE hi Ignore ctermfg=NONE ctermbg=NONE cterm=NONE hi DiffAdd ctermfg=black ctermbg=darkmagenta cterm=NONE @@ -770,10 +810,10 @@ if s:t_Co >= 8 hi FoldColumn ctermfg=black ctermbg=NONE cterm=NONE hi EndOfBuffer ctermfg=black ctermbg=NONE cterm=NONE hi SpecialKey ctermfg=black ctermbg=NONE cterm=NONE - hi Pmenu ctermfg=grey ctermbg=black cterm=NONE + hi Pmenu ctermfg=NONE ctermbg=black cterm=NONE hi PmenuThumb ctermfg=NONE ctermbg=darkgreen cterm=NONE hi PmenuSbar ctermfg=NONE ctermbg=NONE cterm=NONE - hi PmenuSel ctermfg=black ctermbg=darkcyan cterm=NONE + hi PmenuSel ctermfg=NONE ctermbg=darkcyan cterm=NONE hi SignColumn ctermfg=NONE ctermbg=NONE cterm=NONE hi Error ctermfg=grey ctermbg=darkred cterm=NONE hi ErrorMsg ctermfg=grey ctermbg=darkred cterm=NONE @@ -788,7 +828,7 @@ if s:t_Co >= 8 hi WildMenu ctermfg=black ctermbg=darkyellow cterm=bold hi debugPC ctermfg=darkblue ctermbg=NONE cterm=reverse hi debugBreakpoint ctermfg=darkcyan ctermbg=NONE cterm=reverse - hi Visual ctermfg=grey ctermbg=darkblue cterm=NONE + hi Visual ctermfg=NONE ctermbg=NONE cterm=reverse hi MatchParen ctermfg=darkcyan ctermbg=grey cterm=reverse hi VisualNOS ctermfg=black ctermbg=darkcyan cterm=NONE hi CursorLine ctermfg=NONE ctermbg=NONE cterm=underline @@ -803,12 +843,12 @@ if s:t_Co >= 8 hi Constant ctermfg=darkred ctermbg=NONE cterm=NONE hi Identifier ctermfg=NONE ctermbg=NONE cterm=NONE hi Statement ctermfg=black ctermbg=NONE cterm=bold - hi Type ctermfg=darkgreen ctermbg=NONE cterm=bold - hi PreProc ctermfg=darkyellow ctermbg=NONE cterm=NONE + hi Type ctermfg=darkgreen ctermbg=NONE cterm=NONE + hi PreProc ctermfg=darkcyan ctermbg=NONE cterm=NONE hi Special ctermfg=darkcyan ctermbg=NONE cterm=NONE hi Underlined ctermfg=NONE ctermbg=NONE cterm=underline hi Title ctermfg=black ctermbg=NONE cterm=bold - hi Directory ctermfg=darkcyan ctermbg=NONE cterm=bold + hi Directory ctermfg=darkblue ctermbg=NONE cterm=bold hi Conceal ctermfg=NONE ctermbg=NONE cterm=NONE hi Ignore ctermfg=NONE ctermbg=NONE cterm=NONE hi DiffAdd ctermfg=black ctermbg=darkmagenta cterm=NONE @@ -899,14 +939,14 @@ endif " Color: color03 #AF875F 137 darkyellow " Color: color11 #FFD787 222 yellow " Color: color04 #5F87AF 67 darkblue -" Color: color12 #87AFD7 110 blue -" Color: color05 #D787AF 175 darkmagenta -" Color: color13 #FFAFD7 218 magenta +" Color: color12 #5FAFFF 75 blue +" Color: color05 #D787D7 176 darkmagenta +" Color: color13 #FF87FF 213 magenta " Color: color06 #5FAFAF 73 darkcyan " Color: color14 #5FD7D7 116 cyan " Color: color07 #C6C6C6 251 grey " Color: color15 #FFFFFF 231 white -" Color: colorDimWhite #EEEEEE 255 grey +" Color: colorDimWhite #E4E4E4 254 grey " Color: colorLine #262626 235 darkgrey " Color: colorB #1C1C1C 234 darkgrey " Color: colorNonT #585858 240 grey @@ -927,18 +967,18 @@ endif " Background: light " Color: color00 #000000 16 black " Color: color08 #767676 243 darkgrey -" Color: color01 #870000 88 darkred +" Color: color01 #AF0000 124 darkred " Color: color09 #D70000 160 red " Color: color02 #008700 28 darkgreen " Color: color10 #87D787 114 green -" Color: color03 #875F00 94 darkyellow -" Color: color11 #D7D787 186 yellow -" Color: color04 #005FAF 25 darkblue +" Color: color03 #AF5F00 130 darkyellow +" Color: color11 #FFD787 222 yellow +" Color: color04 #005FD7 26 darkblue " Color: color12 #0087D7 32 blue -" Color: color05 #870087 90 darkmagenta -" Color: color13 #AF00AF 133 magenta +" Color: color05 #AF00AF 127 darkmagenta +" Color: color13 #FF00FF 133 magenta " Color: color06 #005F5F 23 darkcyan -" Color: color14 #00AFAF 37 cyan +" Color: color14 #008787 30 cyan " Color: color07 #808080 244 grey " Color: color15 #FFFFFF 231 white " Color: colorLine #E4E4E4 254 grey diff --git a/runtime/colors/pablo.vim b/runtime/colors/pablo.vim index f404951b2a..dc3e496853 100644 --- a/runtime/colors/pablo.vim +++ b/runtime/colors/pablo.vim @@ -3,7 +3,7 @@ " Maintainer: Original maintainerRon Aaron <ron@ronware.org> " Website: https://github.com/vim/colorschemes " License: Same as Vim -" Last Updated: Sun 04 Sep 2022 09:53:40 MSK +" Last Updated: Wed 14 Sep 2022 19:05:27 MSK " Generated by Colortemplate v2.2.0 @@ -280,7 +280,6 @@ if s:t_Co >= 8 hi SpellLocal ctermfg=darkmagenta ctermbg=darkyellow cterm=reverse hi SpellRare ctermfg=darkgreen ctermbg=NONE cterm=reverse hi Comment ctermfg=grey ctermbg=NONE cterm=bold - hi Comment ctermfg=darkgrey ctermbg=NONE cterm=NONE hi Constant ctermfg=darkcyan ctermbg=NONE cterm=bold hi Identifier ctermfg=darkcyan ctermbg=NONE cterm=NONE hi Statement ctermfg=darkyellow ctermbg=NONE cterm=bold diff --git a/runtime/colors/quiet.vim b/runtime/colors/quiet.vim index 9e81ba3857..aecc69619b 100644 --- a/runtime/colors/quiet.vim +++ b/runtime/colors/quiet.vim @@ -4,7 +4,7 @@ " Maintainer: neutaaaaan <neutaaaaan-gh@protonmail.com> " Website: https://github.com/vim/colorschemes " License: Vim License (see `:help license`)` -" Last Updated: Fri 02 Sep 2022 09:55:30 MSK +" Last Updated: Fri 16 Sep 2022 09:52:50 MSK " Generated by Colortemplate v2.2.0 @@ -61,8 +61,8 @@ if &background ==# 'dark' hi DiffChange guifg=#87afd7 guibg=#080808 gui=reverse cterm=reverse hi DiffDelete guifg=#d75f5f guibg=#080808 gui=reverse cterm=reverse hi DiffText guifg=#d787d7 guibg=#080808 gui=reverse cterm=reverse - hi Directory guifg=#dadada guibg=#080808 gui=NONE cterm=NONE - hi EndOfBuffer guifg=#dadada guibg=#080808 gui=NONE cterm=NONE + hi Directory guifg=#dadada guibg=NONE gui=NONE cterm=NONE + hi EndOfBuffer guifg=#dadada guibg=NONE gui=NONE cterm=NONE hi ErrorMsg guifg=#dadada guibg=#080808 gui=reverse cterm=reverse hi FoldColumn guifg=#707070 guibg=NONE gui=NONE cterm=NONE hi Folded guifg=#707070 guibg=#080808 gui=NONE cterm=NONE @@ -86,13 +86,13 @@ if &background ==# 'dark' hi SpellLocal guifg=#d787d7 guibg=NONE guisp=#d787d7 gui=undercurl cterm=underline hi SpellRare guifg=#00afaf guibg=NONE guisp=#00afaf gui=undercurl cterm=underline hi StatusLine guifg=#080808 guibg=#dadada gui=bold cterm=bold - hi StatusLineNC guifg=#707070 guibg=#080808 gui=underline cterm=underline - hi TabLine guifg=#707070 guibg=#080808 gui=underline cterm=underline + hi StatusLineNC guifg=#707070 guibg=#080808 gui=reverse cterm=reverse + hi TabLine guifg=#707070 guibg=#080808 gui=reverse cterm=reverse hi TabLineFill guifg=#dadada guibg=NONE gui=NONE cterm=NONE hi TabLineSel guifg=#080808 guibg=#dadada gui=bold cterm=bold - hi Title guifg=#dadada guibg=NONE gui=NONE cterm=NONE + hi Title guifg=NONE guibg=NONE gui=NONE ctermfg=NONE ctermbg=NONE cterm=NONE hi VertSplit guifg=#707070 guibg=#080808 gui=NONE cterm=NONE - hi Visual guifg=NONE guibg=NONE gui=reverse ctermfg=NONE ctermbg=NONE cterm=reverse + hi Visual guifg=#ffaf00 guibg=#080808 gui=reverse cterm=reverse hi VisualNOS guifg=NONE guibg=#303030 gui=NONE cterm=NONE hi WarningMsg guifg=#dadada guibg=NONE gui=NONE cterm=NONE hi WildMenu guifg=#00afff guibg=#080808 gui=bold cterm=bold @@ -155,9 +155,9 @@ else hi TabLine guifg=#080808 guibg=#a8a8a8 gui=NONE cterm=NONE hi TabLineFill guifg=#080808 guibg=#d7d7d7 gui=NONE cterm=NONE hi TabLineSel guifg=#eeeeee guibg=#080808 gui=bold cterm=bold - hi Title guifg=#080808 guibg=NONE gui=NONE cterm=NONE + hi Title guifg=NONE guibg=NONE gui=NONE ctermfg=NONE ctermbg=NONE cterm=NONE hi VertSplit guifg=#626262 guibg=#d7d7d7 gui=NONE cterm=NONE - hi Visual guifg=NONE guibg=NONE gui=reverse ctermfg=NONE ctermbg=NONE cterm=reverse + hi Visual guifg=#ffaf00 guibg=#080808 gui=reverse cterm=reverse hi VisualNOS guifg=NONE guibg=#eeeeee gui=NONE cterm=NONE hi WarningMsg guifg=#080808 guibg=NONE gui=NONE cterm=NONE hi WildMenu guifg=#080808 guibg=#eeeeee gui=bold cterm=bold @@ -190,8 +190,8 @@ if s:t_Co >= 256 hi DiffChange ctermfg=110 ctermbg=232 cterm=reverse hi DiffDelete ctermfg=167 ctermbg=232 cterm=reverse hi DiffText ctermfg=176 ctermbg=232 cterm=reverse - hi Directory ctermfg=253 ctermbg=232 cterm=NONE - hi EndOfBuffer ctermfg=253 ctermbg=232 cterm=NONE + hi Directory ctermfg=253 ctermbg=NONE cterm=NONE + hi EndOfBuffer ctermfg=253 ctermbg=NONE cterm=NONE hi ErrorMsg ctermfg=253 ctermbg=232 cterm=reverse hi FoldColumn ctermfg=242 ctermbg=NONE cterm=NONE hi Folded ctermfg=242 ctermbg=232 cterm=NONE @@ -215,13 +215,13 @@ if s:t_Co >= 256 hi SpellLocal ctermfg=176 ctermbg=NONE cterm=underline hi SpellRare ctermfg=37 ctermbg=NONE cterm=underline hi StatusLine ctermfg=232 ctermbg=253 cterm=bold - hi StatusLineNC ctermfg=242 ctermbg=232 cterm=underline - hi TabLine ctermfg=242 ctermbg=232 cterm=underline + hi StatusLineNC ctermfg=242 ctermbg=232 cterm=reverse + hi TabLine ctermfg=242 ctermbg=232 cterm=reverse hi TabLineFill ctermfg=253 ctermbg=NONE cterm=NONE hi TabLineSel ctermfg=232 ctermbg=253 cterm=bold - hi Title ctermfg=253 ctermbg=NONE cterm=NONE + hi Title ctermfg=NONE ctermbg=NONE cterm=NONE hi VertSplit ctermfg=242 ctermbg=232 cterm=NONE - hi Visual ctermfg=NONE ctermbg=NONE cterm=reverse + hi Visual ctermfg=214 ctermbg=232 cterm=reverse hi VisualNOS ctermfg=NONE ctermbg=236 cterm=NONE hi WarningMsg ctermfg=253 ctermbg=NONE cterm=NONE hi WildMenu ctermfg=39 ctermbg=232 cterm=bold @@ -281,9 +281,9 @@ if s:t_Co >= 256 hi TabLine ctermfg=232 ctermbg=248 cterm=NONE hi TabLineFill ctermfg=232 ctermbg=188 cterm=NONE hi TabLineSel ctermfg=255 ctermbg=232 cterm=bold - hi Title ctermfg=232 ctermbg=NONE cterm=NONE + hi Title ctermfg=NONE ctermbg=NONE cterm=NONE hi VertSplit ctermfg=241 ctermbg=188 cterm=NONE - hi Visual ctermfg=NONE ctermbg=NONE cterm=reverse + hi Visual ctermfg=214 ctermbg=232 cterm=reverse hi VisualNOS ctermfg=NONE ctermbg=255 cterm=NONE hi WarningMsg ctermfg=232 ctermbg=NONE cterm=NONE hi WildMenu ctermfg=232 ctermbg=255 cterm=bold @@ -350,7 +350,7 @@ if s:t_Co >= 16 hi TabLineSel ctermfg=NONE ctermbg=NONE cterm=bold,reverse hi Title ctermfg=NONE ctermbg=NONE cterm=NONE hi VertSplit ctermfg=NONE ctermbg=NONE cterm=NONE - hi Visual ctermfg=NONE ctermbg=NONE cterm=reverse + hi Visual ctermfg=darkyellow ctermbg=black cterm=reverse hi VisualNOS ctermfg=NONE ctermbg=NONE cterm=NONE hi WarningMsg ctermfg=NONE ctermbg=NONE cterm=standout hi WildMenu ctermfg=NONE ctermbg=NONE cterm=bold @@ -412,7 +412,7 @@ if s:t_Co >= 16 hi TabLineSel ctermfg=NONE ctermbg=NONE cterm=bold,reverse hi Title ctermfg=NONE ctermbg=NONE cterm=NONE hi VertSplit ctermfg=NONE ctermbg=NONE cterm=NONE - hi Visual ctermfg=NONE ctermbg=NONE cterm=reverse + hi Visual ctermfg=darkyellow ctermbg=black cterm=reverse hi VisualNOS ctermfg=NONE ctermbg=NONE cterm=NONE hi WarningMsg ctermfg=NONE ctermbg=NONE cterm=standout hi WildMenu ctermfg=NONE ctermbg=NONE cterm=bold @@ -479,7 +479,7 @@ if s:t_Co >= 8 hi TabLineSel ctermfg=NONE ctermbg=NONE cterm=bold,reverse hi Title ctermfg=NONE ctermbg=NONE cterm=NONE hi VertSplit ctermfg=NONE ctermbg=NONE cterm=NONE - hi Visual ctermfg=NONE ctermbg=NONE cterm=reverse + hi Visual ctermfg=darkyellow ctermbg=black cterm=reverse hi VisualNOS ctermfg=NONE ctermbg=NONE cterm=NONE hi WarningMsg ctermfg=NONE ctermbg=NONE cterm=standout hi WildMenu ctermfg=NONE ctermbg=NONE cterm=bold @@ -541,7 +541,7 @@ if s:t_Co >= 8 hi TabLineSel ctermfg=NONE ctermbg=NONE cterm=bold,reverse hi Title ctermfg=NONE ctermbg=NONE cterm=NONE hi VertSplit ctermfg=NONE ctermbg=NONE cterm=NONE - hi Visual ctermfg=NONE ctermbg=NONE cterm=reverse + hi Visual ctermfg=darkyellow ctermbg=black cterm=reverse hi VisualNOS ctermfg=NONE ctermbg=NONE cterm=NONE hi WarningMsg ctermfg=NONE ctermbg=NONE cterm=standout hi WildMenu ctermfg=NONE ctermbg=NONE cterm=bold @@ -652,7 +652,7 @@ endif " Color: diffred #d75f5f 167 darkred " Color: diffgreen #00af00 34 darkgreen " Color: diffblue #87afd7 110 darkblue -" Color: diffpink #d787d7 176 darkmagenta +" Color: diffpink #d787d7 176 darkmagenta " Color: uipink #ff00af 199 magenta " Color: uilime #afff00 154 green " Color: uiteal #00ffaf 49 green diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index 00a3759936..7e55bb8f4e 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -3378,7 +3378,10 @@ nvim_get_autocmds({*opts}) *nvim_get_autocmds()* • event (string|array): event or events to match against |autocmd-events|. • pattern (string|array): pattern or patterns to match against - |autocmd-pattern|. + |autocmd-pattern|. Cannot be used with {buffer} + • buffer: Buffer number or list of buffer numbers for buffer + local autocommands |autocmd-buflocal|. Cannot be used with + {pattern} Return: ~ Array of autocommands matching the criteria, with each item containing diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 57b41c664b..7b1a50c1fb 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -277,6 +277,8 @@ join({list} [, {sep}]) String join {list} items into one String json_decode({expr}) any Convert {expr} from JSON json_encode({expr}) String Convert {expr} to JSON keys({dict}) List keys in {dict} +keytrans({string}) String translate internal keycodes to a form + that can be used by |:map| len({expr}) Number the length of {expr} libcall({lib}, {func}, {arg}) String call {func} in library {lib} with {arg} libcallnr({lib}, {func}, {arg}) Number idem, but return a Number @@ -526,6 +528,8 @@ uniq({list} [, {func} [, {dict}]]) List remove adjacent duplicates from a list values({dict}) List values in {dict} virtcol({expr}) Number screen column of cursor or mark +virtcol2col({winid}, {lnum}, {col}) + Number byte index of a character on screen visualmode([expr]) String last visual mode used wait({timeout}, {condition} [, {interval}]) Number Wait until {condition} is satisfied @@ -4535,6 +4539,16 @@ keys({dict}) *keys()* Can also be used as a |method|: > mydict->keys() +keytrans({string}) *keytrans()* + Turn the internal byte representation of keys into a form that + can be used for |:map|. E.g. > + :let xx = "\<C-Home>" + :echo keytrans(xx) +< <C-Home> + + Can also be used as a |method|: > + "\<C-Home>"->keytrans() + < *len()* *E701* len({expr}) The result is a Number, which is the length of the argument. When {expr} is a String or a Number the length in bytes is @@ -5620,12 +5634,19 @@ nvim_...({...}) *E5555* *nvim_...()* *eval-api* or({expr}, {expr}) *or()* Bitwise OR on the two arguments. The arguments are converted to a number. A List, Dict or Float argument causes an error. + Also see `and()` and `xor()`. Example: > :let bits = or(bits, 0x80) < Can also be used as a |method|: > :let bits = bits->or(0x80) -pathshorten({expr} [, {len}]) *pathshorten()* +< Rationale: The reason this is a function and not using the "|" + character like many languages, is that Vi has always used "|" + to separate commands. In many places it would not be clear if + "|" is an operator or a command separator. + + +pathshorten({path} [, {len}]) *pathshorten()* Shorten directory names in the path {path} and return the result. The tail, the file name, is kept as-is. The other components in the path are reduced to {len} letters in length. @@ -8831,6 +8852,26 @@ virtcol({expr}) *virtcol()* < Can also be used as a |method|: > GetPos()->virtcol() +virtcol2col({winid}, {lnum}, {col}) *virtcol2col()* + The result is a Number, which is the byte index of the + character in window {winid} at buffer line {lnum} and virtual + column {col}. + + If {col} is greater than the last virtual column in line + {lnum}, then the byte index of the character at the last + virtual column is returned. + + The {winid} argument can be the window number or the + |window-ID|. If this is zero, then the current window is used. + + Returns -1 if the window {winid} doesn't exist or the buffer + line {lnum} or virtual column {col} is invalid. + + See also |screenpos()|, |virtcol()| and |col()|. + + Can also be used as a |method|: > + GetWinid()->virtcol2col(lnum, col) + visualmode([{expr}]) *visualmode()* The result is a String, which describes the last Visual mode used in the current buffer. Initially it returns an empty @@ -9262,6 +9303,7 @@ writefile({object}, {fname} [, {flags}]) xor({expr}, {expr}) *xor()* Bitwise XOR on the two arguments. The arguments are converted to a number. A List, Dict or Float argument causes an error. + Also see `and()` and `or()`. Example: > :let bits = xor(bits, 0x80) < diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt index a4ff4474e6..bed5cb26d7 100644 --- a/runtime/doc/change.txt +++ b/runtime/doc/change.txt @@ -1130,11 +1130,20 @@ used. If you do need it you can use |p| with another register. E.g., yank the text to copy, Visually select the text to replace and use "0p . You can repeat this as many times as you like, and the unnamed register will be changed each time. - -When you use a blockwise Visual mode command and yank only a single line into -a register, a paste on a visual selected area will paste that single line on -each of the selected lines (thus replacing the blockwise selected region by a -block of the pasted line). + *blockwise-put* +When a register contains text from one line (characterwise), using a +blockwise Visual selection, putting that register will paste that text +repeatedly in each of the selected lines, thus replacing the blockwise +selected region by multiple copies of the register text. For example: + - yank the word "TEXT" into a register with `yw` + - select a visual block, marked with "v" in this text: + aaavvaaa + bbbvvbbb + cccvvccc + - press `p`, results in: + aaaTEXTaaa + bbbTEXTbbb + cccTEXTccc *blockwise-register* If you use a blockwise Visual mode command to get the text into the register, diff --git a/runtime/doc/diagnostic.txt b/runtime/doc/diagnostic.txt index e1b52746be..78254c6f2b 100644 --- a/runtime/doc/diagnostic.txt +++ b/runtime/doc/diagnostic.txt @@ -295,10 +295,18 @@ option in the "signs" table of |vim.diagnostic.config()| or 10 if unset). EVENTS *diagnostic-events* *DiagnosticChanged* -DiagnosticChanged After diagnostics have changed. +DiagnosticChanged After diagnostics have changed. When used from Lua, + the new diagnostics are passed to the autocmcd + callback in the "data" table. Example: > - autocmd DiagnosticChanged * lua vim.diagnostic.setqflist({ open = false }) + + vim.api.nvim_create_autocmd('DiagnosticChanged', { + callback = function(args) + local diagnostics = args.data.diagnostics + vim.pretty_print(diagnostics) + end, + }) < ============================================================================== Lua module: vim.diagnostic *diagnostic-api* diff --git a/runtime/doc/intro.txt b/runtime/doc/intro.txt index ae80935032..a5630dabaa 100644 --- a/runtime/doc/intro.txt +++ b/runtime/doc/intro.txt @@ -416,6 +416,10 @@ one always works. To get a literal "<lt>" in a mapping: > :map <C-L> <lt>lt> +The notation can be used in a double quoted strings, using "\<" at the start, +e.g. "\<C-Space>". This results in a special key code. To convert this back +to readable text use `keytrans()`. + ============================================================================== Modes, introduction *vim-modes-intro* *vim-modes* diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index a3d21cc6f7..00aaf759e2 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -1962,8 +1962,9 @@ rpc_response_error({code}, {message}, {data}) *vim.lsp.rpc.start()* start({cmd}, {cmd_args}, {dispatchers}, {extra_spawn_params}) Starts an LSP server process and create an LSP RPC client object to - interact with it. Communication with the server is currently limited to - stdio. + interact with it. Communication with the spawned process happens via + stdio. For communication via TCP, spawn a process manually and use + |vim.lsp.rpc.connect| Parameters: ~ {cmd} (string) Command to start the LSP server. diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index 35badb13b1..a6a51c1e36 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -1587,7 +1587,7 @@ defaulttable({create}) *vim.defaulttable()* They mimic defaultdict in python. - If `create` is `nil`, this will create a defaulttable whose constructor + If {create} is `nil`, this will create a defaulttable whose constructor function is this function, effectively allowing to create nested tables on the fly: > @@ -2082,7 +2082,10 @@ add({filetypes}) *vim.filetype.add()* Filename patterns can specify an optional priority to resolve cases when a file path matches multiple patterns. Higher priorities are matched first. - When omitted, the priority defaults to 0. + When omitted, the priority defaults to 0. A pattern can contain + environment variables of the form "${SOME_VAR}" that will be automatically + expanded. If the environment variable is not set, the pattern won't be + matched. See $VIMRUNTIME/lua/vim/filetype.lua for more examples. @@ -2112,6 +2115,8 @@ add({filetypes}) *vim.filetype.add()* ['.*/etc/foo/.*'] = 'fooscript', -- Using an optional priority ['.*/etc/foo/.*%.conf'] = { 'dosini', { priority = 10 } }, + -- A pattern containing an environment variable + ['${XDG_CONFIG_HOME}/foo/git'] = 'git', ['README.(a+)$'] = function(path, bufnr, ext) if ext == 'md' then return 'markdown' @@ -2212,7 +2217,7 @@ del({modes}, {lhs}, {opts}) *vim.keymap.del()* < Parameters: ~ - {opts} (table) A table of optional arguments: + {opts} (table|nil) A table of optional arguments: • buffer: (number or boolean) Remove a mapping from the given buffer. When "true" or 0, use the current buffer. @@ -2257,7 +2262,7 @@ set({mode}, {lhs}, {rhs}, {opts}) *vim.keymap.set()* {lhs} (string) Left-hand side |{lhs}| of the mapping. {rhs} string|function Right-hand side |{rhs}| of the mapping. Can also be a Lua function. - {opts} (table) A table of |:map-arguments|. + {opts} (table|nil) A table of |:map-arguments|. • Accepts options accepted by the {opts} parameter in |nvim_set_keymap()|, with the following notable differences: • replace_keycodes: Defaults to `true` if "expr" is `true`. @@ -2323,8 +2328,10 @@ find({names}, {opts}) *vim.fs.find()* specifying {type} to be "file" or "directory", respectively. Parameters: ~ - {names} (string|table) Names of the files and directories to find. - Must be base names, paths and globs are not supported. + {names} (string|table|fun(name: string): boolean) Names of the files + and directories to find. Must be base names, paths and globs + are not supported. If a function it is called per file and + dir within the traversed directories to test if they match. {opts} (table) Optional keyword arguments: • path (string): Path to begin searching from. If omitted, the current working directory is used. diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 110f7400e6..14b7eb2d71 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1337,7 +1337,8 @@ A jump table for the options with a short description can be found at |Q_op|. page can have a different value. When 'cmdheight' is zero, there is no command-line unless it is being - used. Some informative messages will not be displayed, any other + used. The command-line will cover the last line of the screen when + shown. Some informative messages will not be displayed, any other messages will cause the |hit-enter| prompt. Expect some other unexpected behavior too. diff --git a/runtime/doc/spell.txt b/runtime/doc/spell.txt index 23d5905ec3..15aa0117ec 100644 --- a/runtime/doc/spell.txt +++ b/runtime/doc/spell.txt @@ -1583,7 +1583,7 @@ CHECKCOMPOUNDTRIPLE (Hunspell) *spell-CHECKCOMPOUNDTRIPLE* Forbid three identical characters when compounding. Not supported. -CHECKSHARPS (Hunspell)) *spell-CHECKSHARPS* +CHECKSHARPS (Hunspell) *spell-CHECKSHARPS* SS letter pair in uppercased (German) words may be upper case sharp s (ß). Not supported. diff --git a/runtime/doc/tagsrch.txt b/runtime/doc/tagsrch.txt index 2485290667..82deb0fa0c 100644 --- a/runtime/doc/tagsrch.txt +++ b/runtime/doc/tagsrch.txt @@ -870,13 +870,15 @@ like |CTRL-]|. The function used for generating the taglist is specified by setting the 'tagfunc' option. The function will be called with three arguments: - a:pattern The tag identifier or pattern used during the tag search. - a:flags String containing flags to control the function behavior. - a:info Dict containing the following entries: + pattern The tag identifier or pattern used during the tag search. + flags String containing flags to control the function behavior. + info Dict containing the following entries: buf_ffname Full filename which can be used for priority. user_data Custom data String, if stored in the tag stack previously by tagfunc. +Note that "a:" needs to be prepended to the argument name when using it. + Currently up to three flags may be passed to the tag function: 'c' The function was invoked by a normal command being processed (mnemonic: the tag function may use the context around the diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index 0a48b435b6..eda1a5e496 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -4,77 +4,75 @@ NVIM REFERENCE MANUAL -Tree-sitter integration *treesitter* +Treesitter integration *treesitter* - Type |gO| to see the table of contents. - ------------------------------------------------------------------------------- -VIM.TREESITTER *lua-treesitter* +Nvim integrates the `tree-sitter` library for incremental parsing of buffers: +https://tree-sitter.github.io/tree-sitter/ -Nvim integrates the tree-sitter library for incremental parsing of buffers. +WARNING: Treesitter support is still experimental and subject to frequent +changes. This documentation may also not fully reflect the latest changes. - *vim.treesitter.language_version* -The latest parser ABI version that is supported by the bundled tree-sitter -library. - - *vim.treesitter.minimum_language_version* -The earliest parser ABI version that is supported by the bundled tree-sitter -library. + Type |gO| to see the table of contents. -Parser files *treesitter-parsers* +============================================================================== +PARSER FILES *treesitter-parsers* Parsers are the heart of tree-sitter. They are libraries that tree-sitter will -search for in the `parser` runtime directory. Currently Nvim does not provide -the tree-sitter parsers, instead these must be built separately, for instance -using the tree-sitter utility. The only exception is a C parser being included -in official builds for testing purposes. Parsers are searched for as -`parser/{lang}.*` in any 'runtimepath' directory. +search for in the `parser` runtime directory. By default, Nvim bundles only +parsers for C, Lua, and Vimscript, but parsers can be installed manually or +via a plugin like https://github.com/nvim-treesitter/nvim-treesitter. +Parsers are searched for as `parser/{lang}.*` in any 'runtimepath' directory. +If multiple parsers for the same language are found, the first one is used. +(This typically implies the priority "user config > plugins > bundled". A parser can also be loaded manually using a full path: > vim.treesitter.require_language("python", "/path/to/python.so") +< +============================================================================== +LANGUAGE TREES *treesitter-languagetree* + *LanguageTree* -<Create a parser for a buffer and a given language (if another plugin uses the -same buffer/language combination, it will be safely reused). Use > +As buffers can contain multiple languages (e.g., Vimscript commands in a Lua +file), multiple parsers may be needed to parse the full buffer. These are +combined in a |LanguageTree| object. - parser = vim.treesitter.get_parser(bufnr, lang) +To create a LanguageTree (parser object) for a buffer and a given language, +use > -<`bufnr=0` can be used for current buffer. `lang` will default to 'filetype'. + tsparser = vim.treesitter.get_parser(bufnr, lang) +< +`bufnr=0` can be used for current buffer. `lang` will default to 'filetype'. Currently, the parser will be retained for the lifetime of a buffer but this is subject to change. A plugin should keep a reference to the parser object as long as it wants incremental updates. - -Parser methods *lua-treesitter-parser* - -tsparser:parse() *tsparser:parse()* Whenever you need to access the current syntax tree, parse the buffer: > - tstree = parser:parse() - -<This will return a table of immutable trees that represent the current state -of the buffer. When the plugin wants to access the state after a (possible) -edit it should call `parse()` again. If the buffer wasn't edited, the same tree -will be returned again without extra work. If the buffer was parsed before, -incremental parsing will be done of the changed parts. - -Note: to use the parser directly inside a |nvim_buf_attach| Lua callback, you -must call `get_parser()` before you register your callback. But preferably + tstree = tsparser:parse() +< +This will return a table of immutable |lua-treesitter-tree|s that represent the +current state of the buffer. When the plugin wants to access the state after a +(possible) edit it should call `parse()` again. If the buffer wasn't edited, +the same tree will be returned again without extra work. If the buffer was +parsed before, incremental parsing will be done of the changed parts. + +Note: To use the parser directly inside a |nvim_buf_attach/)| Lua callback, you +must call |get_parser()| before you register your callback. But preferably parsing shouldn't be done directly in the change callback anyway as they will be very frequent. Rather a plugin that does any kind of analysis on a tree should use a timer to throttle too frequent updates. -tsparser:set_included_regions({region_list}) *tsparser:set_included_regions()* - Changes the regions the parser should consider. This is used for language - injection. {region_list} should be of the form (all zero-based): > - { - {node1, node2}, - ... - } -< - `node1` and `node2` are both considered part of the same region and will - be parsed together with the parser in the same context. +See |lua-treesitter-languagetree| for the list of available methods. + +============================================================================== +TREESITTER TREES *treesitter-tree* + *tstree* + +A "treesitter tree" represents the parsed contents of a buffer, which can be +used to perform further analysis. It is a |luaref-userdata| reference to an +object held by the tree-sitter library. -Tree methods *lua-treesitter-tree* +An instance `tstree` of a treesitter tree supports the following methods. tstree:root() *tstree:root()* Return the root node of this tree. @@ -82,8 +80,15 @@ tstree:root() *tstree:root()* tstree:copy() *tstree:copy()* Returns a copy of the `tstree`. +============================================================================== +TREESITTER NODES *treesitter-node* + *tsnode* + +A "treesitter node" represents one specific element of the parsed contents of +a buffer, which can be captured by a |Query| for, e.g., highlighting. It is a +|luaref-userdata| reference to an object held by the tree-sitter library. -Node methods *lua-treesitter-node* +An instance `tsnode` of a treesitter node supports the following methods. tsnode:parent() *tsnode:parent()* Get the node's immediate parent. @@ -160,10 +165,10 @@ tsnode:id() *tsnode:id()* Get an unique identifier for the node inside its own tree. No guarantees are made about this identifier's internal representation, - except for being a primitive lua type with value equality (so not a + except for being a primitive Lua type with value equality (so not a table). Presently it is a (non-printable) string. - Note: the id is not guaranteed to be unique for nodes from different + Note: The `id` is not guaranteed to be unique for nodes from different trees. *tsnode:descendant_for_range()* @@ -176,121 +181,93 @@ tsnode:named_descendant_for_range({start_row}, {start_col}, {end_row}, {end_col} Get the smallest named node within this node that spans the given range of (row, column) positions -Query *lua-treesitter-query* - -Tree-sitter queries are supported, they are a way to do pattern-matching over -a tree, using a simple to write lisp-like format. See -https://tree-sitter.github.io/tree-sitter/using-parsers#query-syntax for more -information on how to write queries. - -Note: The predicates listed in the web page above differ from those Neovim -supports. See |lua-treesitter-predicates| for a complete list of predicates -supported by Neovim. - +============================================================================== +TREESITTER QUERIES *treesitter-query* + +Treesitter queries are a way to extract information about a parsed |tstree|, +e.g., for the purpose of highlighting. Briefly, a `query` consists of one or +more patterns. A `pattern` is defined over node types in the syntax tree. A +`match` corresponds to specific elements of the syntax tree which match a +pattern. Patterns may optionally define captures and predicates. A `capture` +allows you to associate names with a specific node in a pattern. A `predicate` +adds arbitrary metadata and conditional data to a match. + +Queries are written in a lisp-like language documented in +https://tree-sitter.github.io/tree-sitter/using-parsers#query-syntax +Note: The predicates listed there page differ from those Nvim supports. See +|treesitter-predicates| for a complete list of predicates supported by Nvim. + +Nvim looks for queries as `*.scm` files in a `queries` directory under +`runtimepath`, where each file contains queries for a specific language and +purpose, e.g., `queries/lua/highlights.scm` for highlighting Lua files. By default, the first query on `runtimepath` is used (which usually implies that user config takes precedence over plugins, which take precedence over queries bundled with Neovim). If a query should extend other queries instead -of replacing them, use the `; extends` modeline below. +of replacing them, use |treesitter-query-modeline-extends|. -A `query` consists of one or more patterns. A `pattern` is defined over node -types in the syntax tree. A `match` corresponds to specific elements of the -syntax tree which match a pattern. Patterns may optionally define captures -and predicates. A `capture` allows you to associate names with a specific -node in a pattern. A `predicate` adds arbitrary metadata and conditional data -to a match. +See |lua-treesitter-query| for the list of available methods for working with +treesitter queries from Lua. -Neovim supports to customize the behavior of the queries using a set of -"modelines", that is comments in the queries starting with `;`. Here are the -currently supported modeline alternatives: - `inherits: {lang}...` - Specifies that this query should inherit the queries from {lang}. - This will recursively descend in the queries of {lang} unless wrapped - in parentheses: `({lang})`. +TREESITTER QUERY PREDICATES *treesitter-predicates* - `extends` - Specifies that this query should be used as an extension for the - query, i.e. that it should be merged with the others. - Note: the order of the extensions, and the query that will be used as - a base depends on your 'runtimepath' value. +Predicates are special scheme nodes that are evaluated to conditionally capture +nodes. For example, the |eq?| predicate can be used as follows: > -Note: these modeline comments must be at the top of the query, but can be -repeated, for example, the following modeline blocks are all valid: -> - ;; inherits: foo,bar - ;; extends - - ;; extends - ;; - ;; inherits: baz -< - -Treesitter Query Predicates *lua-treesitter-predicates* - -When writing queries for treesitter, one might use `predicates`, that is, -special scheme nodes that are evaluated to verify things on a captured node -for example, the |eq?| predicate : > ((identifier) @foo (#eq? @foo "foo")) +< +to only match identifier corresponding to the `"foo"` text. -This will only match identifier corresponding to the `"foo"` text. -Here is a list of built-in predicates : +The following predicates are built in: - `eq?` *ts-predicate-eq?* - This predicate will check text correspondence between nodes or - strings: > + `eq?` *treesitter-predicate-eq?* + Match a string against the text corresponding to a node: > ((identifier) @foo (#eq? @foo "foo")) ((node1) @left (node2) @right (#eq? @left @right)) < - `match?` *ts-predicate-match?* - `vim-match?` *ts-predicate-vim-match?* - This will match if the provided vim regex matches the text - corresponding to a node: > + `match?` *treesitter-predicate-match?* + `vim-match?` *treesitter-predicate-vim-match?* + Match a |regexp| against the text corresponding to a node: > ((identifier) @constant (#match? @constant "^[A-Z_]+$")) -< Note: the `^` and `$` anchors will respectively match the start and - end of the node's text. +< Note: The `^` and `$` anchors will match the start and end of the + node's text. - `lua-match?` *ts-predicate-lua-match?* - This will match the same way than |match?| but using lua regexes. + `lua-match?` *treesitter-predicate-lua-match?* + Match a |lua-pattern| against the text corresponding to a node, + similar to `match?` - `contains?` *ts-predicate-contains?* - Will check if any of the following arguments appears in the text - corresponding to the node: > + `contains?` *treesitter-predicate-contains?* + Match a string against parts of the text corresponding to a node: > ((identifier) @foo (#contains? @foo "foo")) ((identifier) @foo-bar (#contains @foo-bar "foo" "bar")) < - `any-of?` *ts-predicate-any-of?* - Will check if the text is the same as any of the following arguments: > + `any-of?` *treesitter-predicate-any-of?* + Match any of the given strings against the text corresponding to + a node: > ((identifier) @foo (#any-of? @foo "foo" "bar")) < This is the recommended way to check if the node matches one of many - keywords for example, as it has been optimized for this. -< + keywords, as it has been optimized for this. + *lua-treesitter-not-predicate* Each predicate has a `not-` prefixed predicate that is just the negation of the predicate. - *vim.treesitter.query.add_predicate()* -vim.treesitter.query.add_predicate({name}, {handler}) +Further predicates can be added via `vim.treesitter.query.`|add_predicate()|. +Use `vim.treesitter.query.`|list_predicates()| to list all available +predicates. -This adds a predicate with the name {name} to be used in queries. -{handler} should be a function whose signature will be : > - handler(match, pattern, bufnr, predicate) -< - *vim.treesitter.query.list_predicates()* -vim.treesitter.query.list_predicates() -This lists the currently available predicates to use in queries. +TREESITTER QUERY DIRECTIVES *treesitter-directives* -Treesitter Query Directive *lua-treesitter-directives* +Treesitter directives store metadata for a node or match and perform side +effects. For example, the |set!| predicate sets metadata on the match or node: > -Treesitter queries can also contain `directives`. Directives store metadata -for a node or match and perform side effects. For example, the |set!| -predicate sets metadata on the match or node : > ((identifier) @foo (#set! "type" "parameter")) +< +The following directives are built in: -Built-in directives: - - `set!` *ts-directive-set!* + `set!` *treesitter-directive-set!* Sets key/value metadata for a specific match or capture. Value is accessible as either `metadata[key]` (match specific) or `metadata[capture_id][key]` (capture specific). @@ -304,7 +281,7 @@ Built-in directives: ((identifier) @foo (#set! @foo "kind" "parameter")) ((node1) @left (node2) @right (#set! "type" "pair")) < - `offset!` *ts-directive-offset!* + `offset!` *treesitter-directive-offset!* Takes the range of the captured node and applies an offset. This will generate a new range object for the captured node as `metadata[capture_id].range`. @@ -320,51 +297,74 @@ Built-in directives: ((identifier) @constant (#offset! @constant 0 1 0 -1)) < -Treesitter syntax highlighting (WIP) *lua-treesitter-highlight* +Further directives can be added via `vim.treesitter.query.`|add_directive()|. +Use `vim.treesitter.query.`|list_directives()| to list all available +directives. -NOTE: This is a partially implemented feature, and not usable as a default -solution yet. What is documented here is a temporary interface intended -for those who want to experiment with this feature and contribute to -its development. -Highlights are defined in the same query format as in the tree-sitter -highlight crate, with some limitations and additions. Set a highlight query -for a buffer with this code: > +TREESITTER QUERY MODELINES *treesitter-query-modeline* - local query = [[ - "for" @keyword - "if" @keyword - "return" @keyword +Neovim supports to customize the behavior of the queries using a set of +"modelines", that is comments in the queries starting with `;`. Here are the +currently supported modeline alternatives: - (string_literal) @string - (number_literal) @number - (comment) @comment + `inherits: {lang}...` *treesitter-query-modeline-inherits* + Specifies that this query should inherit the queries from {lang}. + This will recursively descend in the queries of {lang} unless wrapped + in parentheses: `({lang})`. + Note: This is meant to be used to include queries from another + language. If you want your query to extend the queries of the same + language, use `extends`. - (preproc_function_def name: (identifier) @function) + `extends` *treesitter-query-modeline-extends* + Specifies that this query should be used as an extension for the + query, i.e. that it should be merged with the others. + Note: The order of the extensions, and the query that will be used as + a base depends on your 'runtimepath' value. + +Note: These modeline comments must be at the top of the query, but can be +repeated, for example, the following two modeline blocks are both valid: > + + ;; inherits: foo,bar + ;; extends - ; ... more definitions - ]] + ;; extends + ;; + ;; inherits: baz +< +============================================================================== +TREESITTER SYNTAX HIGHLIGHTING *treesitter-highlight* - highlighter = vim.treesitter.TSHighlighter.new(query, bufnr, lang) - -- alternatively, to use the current buffer and its filetype: - -- highlighter = vim.treesitter.TSHighlighter.new(query) +Syntax highlighting is specified through queries named `highlights.scm`, +which match a |tsnode| in the parsed |tstree| to a `capture` that can be +assigned a highlight group. For example, the query > - -- Don't recreate the highlighter for the same buffer, instead - -- modify the query like this: - local query2 = [[ ... ]] - highlighter:set_query(query2) + (parameters (identifier) @parameter) +< +matches any `identifier` node inside a function `parameter` node (e.g., the +`bar` in `foo(bar)`) to the capture named `@parameter`. It is also possible to +match literal expressions (provided the parser returns them): > + "return" @keyword.return +< +Assuming a suitable parser and `highlights.scm` query is found in runtimepath, +treesitter highlighting for the current buffer can be enabled simply via +|vim.treesitter.start()|. - *lua-treesitter-highlight-groups* + *treesitter-highlight-groups* The capture names, with `@` included, are directly usable as highlight groups. +For many commonly used captures, the corresponding highlight groups are linked +to Nvim's standard |highlight-groups| by default but can be overridden in +colorschemes. + A fallback system is implemented, so that more specific groups fallback to -more generic ones. For instance, in a language that has separate doc -comments, `@comment.doc` could be used. If this group is not defined, the -highlighting for an ordinary `@comment` is used. This way, existing color -schemes already work out of the box, but it is possible to add -more specific variants for queries that make them available. +more generic ones. For instance, in a language that has separate doc comments, +`@comment.doc` could be used. If this group is not defined, the highlighting +for an ordinary `@comment` is used. This way, existing color schemes already +work out of the box, but it is possible to add more specific variants for +queries that make them available. -As an additional rule, captures highlights can always be specialized by +As an additional rule, capture highlights can always be specialized by language, by appending the language name after an additional dot. For instance, to highlight comments differently per language: > @@ -372,47 +372,75 @@ instance, to highlight comments differently per language: > hi @comment.lua @guifg=DarkBlue hi link @comment.doc.java String < -It is possible to use custom highlight groups. As an example, if we -define the `@warning` group: > + *treesitter-highlight-spell* +The special `@spell` capture can be used to indicate that a node should be +spell checked by Nvim's builtin |spell| checker. For example, the following +capture marks comments as to be checked: > - hi link @warning WarningMsg + (comment) @spell < -the following query warns of a binary expression with two -identical identifiers, highlighting both as |hl-WarningMsg|: > + *treesitter-highlight-conceal* +Treesitter highlighting supports |conceal| via the `conceal` metadata. By +convention, nodes to be concealed are captured as `@conceal`, but any capture +can be used. For example, the following query can be used to hide code block +delimiters in Markdown: > - ((binary_expression left: (identifier) @warning.left right: (identifier) @warning.right) - (eq? @warning.left @warning.right)) + (fenced_code_block_delimiter) @conceal (#set! conceal "") < -Treesitter Highlighting Priority *lua-treesitter-highlight-priority* +It is also possible to replace a node with a single character, which (unlike +legacy syntax) can be given a custom highlight. For example, the following +(ill-advised) query replaces the `!=` operator by a Unicode glyph, which is +still highlighted the same as other operators: > -Tree-sitter uses |nvim_buf_set_extmark()| to set highlights with a default + "!=" @operator (#set! conceal "≠") +< +Conceals specified in this way respect |conceallevel|. + + *treesitter-highlight-priority* +Treesitter uses |nvim_buf_set_extmark()| to set highlights with a default priority of 100. This enables plugins to set a highlighting priority lower or higher than tree-sitter. It is also possible to change the priority of an individual query pattern manually by setting its `"priority"` metadata attribute: > - ( - (super_important_node) @ImportantHighlight - ; Give the whole query highlight priority higher than the default (100) - (set! "priority" 105) - ) + (super_important_node) @ImportantHighlight (#set! "priority" 105) < +============================================================================== +VIM.TREESITTER *lua-treesitter* + +The remainder of this document is a reference manual for the `vim.treesitter` +Lua module, which is the main interface for Nvim's tree-sitter integration. +Most of the following content is automatically generated from the function +documentation. + + + *vim.treesitter.language_version* +The latest parser ABI version that is supported by the bundled tree-sitter +library. + + *vim.treesitter.minimum_language_version* +The earliest parser ABI version that is supported by the bundled tree-sitter +library. ============================================================================== Lua module: vim.treesitter *lua-treesitter-core* get_captures_at_cursor({winnr}) *get_captures_at_cursor()* - Gets a list of captures under the cursor + Returns a list of highlight capture names under the cursor Parameters: ~ {winnr} (number|nil) Window handle or 0 for current window (default) Return: ~ - (table) Named node under the cursor + string[] List of capture names *get_captures_at_position()* get_captures_at_position({bufnr}, {row}, {col}) - Gets a list of captures for a given cursor position + Returns a list of highlight captures at the given position + + Each capture is represented by a table containing the capture name as a + string as well as a table of metadata (`priority`, `conceal`, ...; empty + if none are defined). Parameters: ~ {bufnr} (number) Buffer number (0 for current buffer) @@ -420,20 +448,21 @@ get_captures_at_position({bufnr}, {row}, {col}) {col} (number) Position column Return: ~ - (table) Table of captures + table[] List of captures `{ capture = "capture name", metadata = { ... + } }` get_node_at_cursor({winnr}) *get_node_at_cursor()* - Gets the smallest named node under the cursor + Returns the smallest named node under the cursor Parameters: ~ {winnr} (number|nil) Window handle or 0 for current window (default) Return: ~ - (string) Named node under the cursor + (string) Name of node under the cursor *get_node_at_position()* get_node_at_position({bufnr}, {row}, {col}, {opts}) - Gets the smallest named node at position + Returns the smallest named node at the given position Parameters: ~ {bufnr} (number) Buffer number (0 for current buffer) @@ -444,56 +473,59 @@ get_node_at_position({bufnr}, {row}, {col}, {opts}) (default true) Return: ~ - (table) Named node under the cursor + userdata |tsnode| under the cursor get_node_range({node_or_range}) *get_node_range()* - Get the node's range or unpack a range table + Returns the node's range or an unpacked range table Parameters: ~ - {node_or_range} (table) + {node_or_range} (userdata|table) |tsnode| or table of positions Return: ~ - (table) start_row, start_col, end_row, end_col + (table) `{ start_row, start_col, end_row, end_col }` get_parser({bufnr}, {lang}, {opts}) *get_parser()* - Gets the parser for this bufnr / ft combination. + Returns the parser for a specific buffer and filetype and attaches it to + the buffer - If needed this will create the parser. Unconditionally attach the provided - callback + If needed, this will create the parser. Parameters: ~ {bufnr} (number|nil) Buffer the parser should be tied to (default: current buffer) - {lang} (string) |nil Filetype of this parser (default: buffer + {lang} (string|nil) Filetype of this parser (default: buffer filetype) {opts} (table|nil) Options to pass to the created language tree Return: ~ - (table) Parser object + LanguageTree |LanguageTree| object to use for parsing get_string_parser({str}, {lang}, {opts}) *get_string_parser()* - Gets a string parser + Returns a string parser Parameters: ~ - {str} The string to parse - {lang} The language of this string - {opts} Options to pass to the created language tree + {str} (string) Text to parse + {lang} (string) Language of this string + {opts} (table|nil) Options to pass to the created language tree + + Return: ~ + LanguageTree |LanguageTree| object to use for parsing is_ancestor({dest}, {source}) *is_ancestor()* Determines whether a node is the ancestor of another Parameters: ~ - {dest} (table) Possible ancestor - {source} (table) Possible descendant node + {dest} userdata Possible ancestor |tsnode| + {source} userdata Possible descendant |tsnode| Return: ~ - (boolean) True if dest is an ancestor of source + (boolean) True if {dest} is an ancestor of {source} is_in_node_range({node}, {line}, {col}) *is_in_node_range()* Determines whether (line, col) position is in node range Parameters: ~ - {node} (table) Node defining the range + {node} userdata |tsnode| defining the range {line} (number) Line (0-based) {col} (number) Column (0-based) @@ -504,30 +536,29 @@ node_contains({node}, {range}) *node_contains()* Determines if a node contains a range Parameters: ~ - {node} (table) + {node} userdata |tsnode| {range} (table) Return: ~ - (boolean) True if the node contains the range + (boolean) True if the {node} contains the {range} start({bufnr}, {lang}) *start()* - Start treesitter highlighting for a buffer + Starts treesitter highlighting for a buffer - Can be used in an ftplugin or FileType autocommand + Can be used in an ftplugin or FileType autocommand. Note: By default, disables regex syntax highlighting, which may be required for some plugins. In this case, add `vim.bo.syntax = 'on'` after the call to `start`. - Example: -> + Example: > - vim.api.nvim_create_autocmd( 'FileType', { pattern = 'tex', - callback = function(args) - vim.treesitter.start(args.buf, 'latex') - vim.bo[args.buf].syntax = 'on' -- only if additional legacy syntax is needed - end - }) + vim.api.nvim_create_autocmd( 'FileType', { pattern = 'tex', + callback = function(args) + vim.treesitter.start(args.buf, 'latex') + vim.bo[args.buf].syntax = 'on' -- only if additional legacy syntax is needed + end + }) < Parameters: ~ @@ -537,7 +568,7 @@ start({bufnr}, {lang}) *start()* filetype) stop({bufnr}) *stop()* - Stop treesitter highlighting for a buffer + Stops treesitter highlighting for a buffer Parameters: ~ {bufnr} (number|nil) Buffer to stop highlighting (default: current @@ -545,7 +576,7 @@ stop({bufnr}) *stop()* ============================================================================== -Lua module: vim.treesitter.language *treesitter-language* +Lua module: vim.treesitter.language *lua-treesitter-language* inspect_language({lang}) *inspect_language()* Inspects the provided language. @@ -554,26 +585,32 @@ inspect_language({lang}) *inspect_language()* names, ... Parameters: ~ - {lang} The language. + {lang} (string) Language + + Return: ~ + (table) *require_language()* require_language({lang}, {path}, {silent}, {symbol_name}) - Asserts that the provided language is installed, and optionally provide a - path for the parser + Asserts that a parser for the language {lang} is installed. - Parsers are searched in the `parser` runtime directory. + Parsers are searched in the `parser` runtime directory, or the provided + {path} Parameters: ~ - {lang} (string) The language the parser should parse + {lang} (string) Language the parser should parse {path} (string|nil) Optional path the parser is located at {silent} (boolean|nil) Don't throw an error if language not found {symbol_name} (string|nil) Internal symbol name for the language to load + Return: ~ + (boolean) If the specified language is installed + ============================================================================== -Lua module: vim.treesitter.query *treesitter-query* +Lua module: vim.treesitter.query *lua-treesitter-query* add_directive({name}, {handler}, {force}) *add_directive()* Adds a new directive to be used in queries @@ -584,65 +621,74 @@ add_directive({name}, {handler}, {force}) *add_directive()* `metadata[capture_id].key = value` Parameters: ~ - {name} the name of the directive, without leading # - {handler} the handler function to be used signature will be (match, - pattern, bufnr, predicate, metadata) + {name} (string) Name of the directive, without leading # + {handler} function(match:string, pattern:string, bufnr:number, + predicate:function, metadata:table) add_predicate({name}, {handler}, {force}) *add_predicate()* Adds a new predicate to be used in queries Parameters: ~ - {name} the name of the predicate, without leading # - {handler} the handler function to be used signature will be (match, - pattern, bufnr, predicate) + {name} (string) Name of the predicate, without leading # + {handler} function(match:string, pattern:string, bufnr:number, + predicate:function) get_node_text({node}, {source}, {opts}) *get_node_text()* Gets the text corresponding to a given node Parameters: ~ - {node} (table) The node - {source} (table) The buffer or string from which the node is + {node} userdata |tsnode| + {source} (number|string) Buffer or string from which the {node} is extracted - {opts} (table) Optional parameters. - • concat: (boolean default true) Concatenate result in a - string + {opts} (table|nil) Optional parameters. + • concat: (boolean) Concatenate result in a string (default + true) + + Return: ~ + (string[]|string) get_query({lang}, {query_name}) *get_query()* Returns the runtime query {query_name} for {lang}. Parameters: ~ - {lang} The language to use for the query - {query_name} The name of the query (i.e. "highlights") + {lang} (string) Language to use for the query + {query_name} (string) Name of the query (e.g. 'highlights') Return: ~ - The corresponding query, parsed. + Query Parsed query *get_query_files()* get_query_files({lang}, {query_name}, {is_included}) Gets the list of files used to make up a query Parameters: ~ - {lang} The language - {query_name} The name of the query to load - {is_included} Internal parameter, most of the time left as `nil` + {lang} (string) Language to get query for + {query_name} (string) Name of the query to load (e.g., 'highlights') + {is_included} (boolean|nil) Internal parameter, most of the time left + as `nil` + + Return: ~ + string[] query_files List of files to load for given query and + language list_directives() *list_directives()* Lists the currently available directives to use in queries. Return: ~ - The list of supported directives. + string[] List of supported directives. list_predicates() *list_predicates()* + Lists the currently available predicates to use in queries. + Return: ~ - The list of supported predicates. + string[] List of supported predicates. parse_query({lang}, {query}) *parse_query()* Parse {query} as a string. (If the query is in a file, the caller should read the contents into a string before calling). - Returns a `Query` (see |lua-treesitter-query|) object which can be used to - search nodes in the syntax tree for the patterns defined in {query} using - `iter_*` methods below. + Returns a `Query` (see |lua-treesitter-query|) object which can be used to search nodes in + the syntax tree for the patterns defined in {query} using `iter_*` methods below. Exposes `info` and `captures` with additional context about {query}. • `captures` contains the list of unique capture names defined in {query}. @@ -650,106 +696,109 @@ parse_query({lang}, {query}) *parse_query()* • `info.patterns` contains information about predicates. Parameters: ~ - {lang} (string) The language - {query} (string) A string containing the query (s-expr syntax) + {lang} (string) Language to use for the query + {query} (string) Query in s-expr syntax Return: ~ - The query + Query Parsed query *Query:iter_captures()* Query:iter_captures({self}, {node}, {source}, {start}, {stop}) Iterate over all captures from all matches inside {node} - {source} is needed if the query contains predicates, then the caller must + {source} is needed if the query contains predicates; then the caller must ensure to use a freshly parsed tree consistent with the current text of the buffer (if relevant). {start_row} and {end_row} can be used to limit matches inside a row range (this is typically used with root node as the - node, i e to get syntax highlight matches in the current viewport). When - omitted the start and end row values are used from the given node. + {node}, i.e., to get syntax highlight matches in the current viewport). + When omitted, the {start} and {end} row values are used from the given + node. - The iterator returns three values, a numeric id identifying the capture, + The iterator returns three values: a numeric id identifying the capture, the captured node, and metadata from any directives processing the match. - The following example shows how to get captures by name: -> - - for id, node, metadata in query:iter_captures(tree:root(), bufnr, first, last) do - local name = query.captures[id] -- name of the capture in the query - -- typically useful info about the node: - local type = node:type() -- type of the captured node - local row1, col1, row2, col2 = node:range() -- range of the capture - ... use the info here ... - end + The following example shows how to get captures by name: > + + for id, node, metadata in query:iter_captures(tree:root(), bufnr, first, last) do + local name = query.captures[id] -- name of the capture in the query + -- typically useful info about the node: + local type = node:type() -- type of the captured node + local row1, col1, row2, col2 = node:range() -- range of the capture + ... use the info here ... + end < Parameters: ~ - {node} The node under which the search will occur - {source} The source buffer or string to extract text from - {start} The starting line of the search - {stop} The stopping line of the search (end-exclusive) + {node} userdata |tsnode| under which the search will occur + {source} (number|string) Source buffer or string to extract text from + {start} (number) Starting line for the search + {stop} (number) Stopping line for the search (end-exclusive) {self} Return: ~ - The matching capture id - The captured node + (number) capture Matching capture id + (table) capture_node Capture for {node} + (table) metadata for the {capture} *Query:iter_matches()* Query:iter_matches({self}, {node}, {source}, {start}, {stop}) Iterates the matches of self on a given range. - Iterate over all matches within a node. The arguments are the same as for - |query:iter_captures()| but the iterated values are different: an + Iterate over all matches within a {node}. The arguments are the same as + for |query:iter_captures()| but the iterated values are different: an (1-based) index of the pattern in the query, a table mapping capture indices to nodes, and metadata from any directives processing the match. - If the query has more than one pattern the capture table might be sparse, - and e.g. `pairs()` method should be used over `ipairs`. Here an example - iterating over all captures in every match: -> + If the query has more than one pattern, the capture table might be sparse + and e.g. `pairs()` method should be used over `ipairs` . Here is an example iterating over all captures in every match: > - for pattern, match, metadata in cquery:iter_matches(tree:root(), bufnr, first, last) do - for id, node in pairs(match) do - local name = query.captures[id] - -- `node` was captured by the `name` capture in the match + for pattern, match, metadata in cquery:iter_matches(tree:root(), bufnr, first, last) do + for id, node in pairs(match) do + local name = query.captures[id] + -- `node` was captured by the `name` capture in the match - local node_data = metadata[id] -- Node level metadata + local node_data = metadata[id] -- Node level metadata - ... use the info here ... - end - end + ... use the info here ... + end + end < Parameters: ~ - {node} The node under which the search will occur - {source} The source buffer or string to search - {start} The starting line of the search - {stop} The stopping line of the search (end-exclusive) + {node} userdata |tsnode| under which the search will occur + {source} (number|string) Source buffer or string to search + {start} (number) Starting line for the search + {stop} (number) Stopping line for the search (end-exclusive) {self} Return: ~ - The matching pattern id - The matching match + (number) pattern id + (table) match + (table) metadata set_query({lang}, {query_name}, {text}) *set_query()* - Sets the runtime query {query_name} for {lang} + Sets the runtime query named {query_name} for {lang} This allows users to override any runtime files and/or configuration set by plugins. Parameters: ~ - {lang} string: The language to use for the query - {query_name} string: The name of the query (i.e. "highlights") - {text} string: The query text (unparsed). + {lang} (string) Language to use for the query + {query_name} (string) Name of the query (e.g., 'highlights') + {text} (string) Query text (unparsed). ============================================================================== -Lua module: vim.treesitter.highlighter *treesitter-highlighter* +Lua module: vim.treesitter.highlighter *lua-treesitter-highlighter* new({tree}, {opts}) *highlighter.new()* Creates a new highlighter using Parameters: ~ - {tree} The language tree to use for highlighting - {opts} Table used to configure the highlighter - • queries: Table to overwrite queries used by the highlighter + {tree} LanguageTree |LanguageTree| parser object to use for highlighting + {opts} (table|nil) Configuration of the highlighter: + • queries table overwrite queries used by the highlighter + + Return: ~ + TSHighlighter Created highlighter object TSHighlighter:destroy({self}) *TSHighlighter:destroy()* Removes all internal references to the highlighter @@ -757,25 +806,9 @@ TSHighlighter:destroy({self}) *TSHighlighter:destroy()* Parameters: ~ {self} -TSHighlighter:get_query({self}, {lang}) *TSHighlighter:get_query()* - Gets the query used for - - Parameters: ~ - {lang} A language used by the highlighter. - {self} - ============================================================================== -Lua module: vim.treesitter.languagetree *treesitter-languagetree* - -LanguageTree:add_child({self}, {lang}) *LanguageTree:add_child()* - Adds a child language to this tree. - - If the language already exists as a child, it will first be removed. - - Parameters: ~ - {lang} The language to add. - {self} +Lua module: vim.treesitter.languagetree *lua-treesitter-languagetree* LanguageTree:children({self}) *LanguageTree:children()* Returns a map of language to child tree. @@ -784,15 +817,17 @@ LanguageTree:children({self}) *LanguageTree:children()* {self} LanguageTree:contains({self}, {range}) *LanguageTree:contains()* - Determines whether {range} is contained in this language tree + Determines whether {range} is contained in the |LanguageTree|. Parameters: ~ - {range} A range, that is a `{ start_line, start_col, end_line, - end_col }` table. + {range} (table) `{ start_line, start_col, end_line, end_col }` {self} + Return: ~ + (boolean) + LanguageTree:destroy({self}) *LanguageTree:destroy()* - Destroys this language tree and all its children. + Destroys this |LanguageTree| and all its children. Any cleanup logic should be performed here. @@ -803,22 +838,21 @@ LanguageTree:destroy({self}) *LanguageTree:destroy()* *LanguageTree:for_each_child()* LanguageTree:for_each_child({self}, {fn}, {include_self}) - Invokes the callback for each LanguageTree and it's children recursively + Invokes the callback for each |LanguageTree| and its children recursively Parameters: ~ - {fn} The function to invoke. This is invoked with arguments - (tree: LanguageTree, lang: string) - {include_self} Whether to include the invoking tree in the results. + {fn} function(tree: LanguageTree, lang: string) + {include_self} (boolean) Whether to include the invoking tree in the + results {self} LanguageTree:for_each_tree({self}, {fn}) *LanguageTree:for_each_tree()* - Invokes the callback for each treesitter trees recursively. + Invokes the callback for each |LanguageTree| recursively. - Note, this includes the invoking language tree's trees as well. + Note: This includes the invoking tree's child trees as well. Parameters: ~ - {fn} The callback to invoke. The callback is invoked with arguments - (tree: TSTree, languageTree: LanguageTree) + {fn} function(tree: TSTree, languageTree: LanguageTree) {self} LanguageTree:included_regions({self}) *LanguageTree:included_regions()* @@ -847,23 +881,29 @@ LanguageTree:lang({self}) *LanguageTree:lang()* *LanguageTree:language_for_range()* LanguageTree:language_for_range({self}, {range}) - Gets the appropriate language that contains {range} + Gets the appropriate language that contains {range}. Parameters: ~ - {range} A text range, see |LanguageTree:contains| + {range} (table) `{ start_line, start_col, end_line, end_col }` {self} + Return: ~ + LanguageTree Managing {range} + *LanguageTree:named_node_for_range()* LanguageTree:named_node_for_range({self}, {range}, {opts}) - Gets the smallest named node that contains {range} + Gets the smallest named node that contains {range}. Parameters: ~ - {range} (table) A text range - {opts} (table) Options table - {opts.ignore_injections} (boolean) (default true) Ignore injected - languages. + {range} (table) `{ start_line, start_col, end_line, end_col }` + {opts} (table|nil) Optional keyword arguments: + • ignore_injections boolean Ignore injected languages + (default true) {self} + Return: ~ + userdata|nil Found |tsnode| + LanguageTree:parse({self}) *LanguageTree:parse()* Parses all defined regions using a treesitter parser for the language this tree represents. This will run the injection query for this language to @@ -872,12 +912,16 @@ LanguageTree:parse({self}) *LanguageTree:parse()* Parameters: ~ {self} + Return: ~ + userdata[] Table of parsed |tstree| + (table) Change list + LanguageTree:register_cbs({self}, {cbs}) *LanguageTree:register_cbs()* - Registers callbacks for the parser. + Registers callbacks for the |LanguageTree|. Parameters: ~ {cbs} (table) An |nvim_buf_attach()|-like table argument with the - following keys : + following handlers: • `on_bytes` : see |nvim_buf_attach()|, but this will be called after the parsers callback. • `on_changedtree` : a callback that will be called every time the tree has syntactical changes. It will only be passed one @@ -889,35 +933,6 @@ LanguageTree:register_cbs({self}, {cbs}) *LanguageTree:register_cbs()* the tree. {self} -LanguageTree:remove_child({self}, {lang}) *LanguageTree:remove_child()* - Removes a child language from this tree. - - Parameters: ~ - {lang} The language to remove. - {self} - - *LanguageTree:set_included_regions()* -LanguageTree:set_included_regions({self}, {regions}) - Sets the included regions that should be parsed by this parser. A region - is a set of nodes and/or ranges that will be parsed in the same context. - - For example, `{ { node1 }, { node2} }` is two separate regions. This will - be parsed by the parser in two different contexts... thus resulting in two - separate trees. - - `{ { node1, node2 } }` is a single region consisting of two nodes. This - will be parsed by the parser in a single context... thus resulting in a - single tree. - - This allows for embedded languages to be parsed together across different - nodes, which is useful for templating languages like ERB and EJS. - - Note, this call invalidates the tree and requires it to be parsed again. - - Parameters: ~ - {regions} (table) list of regions this tree should manage and parse. - {self} - LanguageTree:source({self}) *LanguageTree:source()* Returns the source content of the language tree (bufnr or string). @@ -926,15 +941,18 @@ LanguageTree:source({self}) *LanguageTree:source()* *LanguageTree:tree_for_range()* LanguageTree:tree_for_range({self}, {range}, {opts}) - Gets the tree that contains {range} + Gets the tree that contains {range}. Parameters: ~ - {range} (table) A text range - {opts} (table) Options table - {opts.ignore_injections} (boolean) (default true) Ignore injected - languages. + {range} (table) `{ start_line, start_col, end_line, end_col }` + {opts} (table|nil) Optional keyword arguments: + • ignore_injections boolean Ignore injected languages + (default true) {self} + Return: ~ + userdata|nil Contained |tstree| + LanguageTree:trees({self}) *LanguageTree:trees()* Returns all trees this language tree contains. Does not include child languages. @@ -943,16 +961,20 @@ LanguageTree:trees({self}) *LanguageTree:trees()* {self} new({source}, {lang}, {opts}) *languagetree.new()* - Represents a single treesitter parser for a language. The language can - contain child languages with in its range, hence the tree. + A |LanguageTree| holds the treesitter parser for a given language {lang} + used to parse a buffer. As the buffer may contain injected languages, the LanguageTree needs to store parsers for these child languages as well (which in turn + may contain child languages themselves, hence the name). Parameters: ~ - {source} Can be a bufnr or a string of text to parse - {lang} The language this tree represents - {opts} Options table - {opts.injections} A table of language to injection query strings. - This is useful for overriding the built-in runtime - file searching for the injection language query per - language. + {source} (number|string) Buffer or a string of text to parse + {lang} (string) Root language this tree represents + {opts} (table|nil) Optional keyword arguments: + • injections table Mapping language to injection query + strings. This is useful for overriding the built-in + runtime file searching for the injection language query + per language. + + Return: ~ + LanguageTree |LanguageTree| parser object vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl: diff --git a/runtime/doc/userfunc.txt b/runtime/doc/userfunc.txt index 39c246e21d..c015b12c27 100644 --- a/runtime/doc/userfunc.txt +++ b/runtime/doc/userfunc.txt @@ -12,7 +12,7 @@ This is introduced in section |41.7| of the user manual. ============================================================================== -1. Defining a fuction ~ +1. Defining a function ~ *define-function* New functions can be defined. These can be called just like builtin functions. The function executes a sequence of Ex commands. Normal mode @@ -20,7 +20,7 @@ commands can be executed with the |:normal| command. The function name must start with an uppercase letter, to avoid confusion with builtin functions. To prevent from using the same name in different scripts -make them script-local. If you do use a global function the avoid obvious, +make them script-local. If you do use a global function then avoid obvious, short names. A good habit is to start the function name with the name of the script, e.g., "HTMLcolor()". @@ -287,7 +287,7 @@ This function can then be called with: > < ============================================================================== -2. Calling a fuction ~ +2. Calling a function ~ *:cal* *:call* *E107* *E117* :[range]cal[l] {name}([arguments]) Call a function. The name of the function and its arguments diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index 76c2f8454f..1aa9aaa0c4 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -604,6 +604,8 @@ String manipulation: *string-functions* fnameescape() escape a file name for use with a Vim command tr() translate characters from one set to another strtrans() translate a string to make it printable + keytrans() translate internal keycodes to a form that + can be used by |:map| tolower() turn a string to lowercase toupper() turn a string to uppercase charclass() class of a character @@ -745,6 +747,7 @@ Cursor and mark position: *cursor-functions* *mark-functions* screencol() get screen column of the cursor screenrow() get screen row of the cursor screenpos() screen row and col of a text character + virtcol2col() byte index of a text character on screen getcurpos() get position of the cursor getpos() get position of cursor, mark, etc. setpos() set position of cursor, mark, etc. diff --git a/runtime/filetype.vim b/runtime/filetype.vim index 4fea421ece..4de1720c75 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -1,7 +1,7 @@ " Vim support file to detect file types " " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last Change: 2022 Jul 5 +" Last Change: 2022 Sep 11 " Only run this if enabled if !exists("do_legacy_filetype") @@ -300,6 +300,9 @@ au BufNewFile,BufRead cfengine.conf setf cfengine " ChaiScript au BufRead,BufNewFile *.chai setf chaiscript +" Chatito +au BufNewFile,BufRead *.chatito setf chatito + " Comshare Dimension Definition Language au BufNewFile,BufRead *.cdl setf cdl @@ -449,6 +452,9 @@ endif " Lynx config files au BufNewFile,BufRead lynx.cfg setf lynx +" LyRiCs +au BufNewFile,BufRead *.lrc setf lyrics + " Modula-3 configuration language (must be before *.cfg and *makefile) au BufNewFile,BufRead *.quake,cm3.cfg setf m3quake au BufNewFile,BufRead m3makefile,m3overrides setf m3build @@ -721,9 +727,16 @@ au BufNewFile,BufRead *.git/worktrees/*/config.worktree setf gitconfig au BufNewFile,BufRead .gitmodules,*.git/modules/*/config setf gitconfig if !empty($XDG_CONFIG_HOME) au BufNewFile,BufRead $XDG_CONFIG_HOME/git/config setf gitconfig + au BufNewFile,BufRead $XDG_CONFIG_HOME/git/attributes setf gitattributes + au BufNewFile,BufRead $XDG_CONFIG_HOME/git/ignore setf gitignore endif -au BufNewFile,BufRead git-rebase-todo setf gitrebase -au BufRead,BufNewFile .gitsendemail.msg.?????? setf gitsendemail +au BufNewFile,BufRead .gitattributes,*.git/info/attributes setf gitattributes +au BufNewFile,BufRead */.config/git/attributes setf gitattributes +au BufNewFile,BufRead */etc/gitattributes setf gitattributes +au BufNewFile,BufRead .gitignore,*.git/info/exclude setf gitignore +au BufNewFile,BufRead */.config/git/ignore setf gitignore +au BufNewFile,BufRead git-rebase-todo setf gitrebase +au BufRead,BufNewFile .gitsendemail.msg.?????? setf gitsendemail au BufNewFile,BufRead *.git/* \ if getline(1) =~# '^\x\{40,\}\>\|^ref: ' | \ setf git | @@ -868,11 +881,11 @@ au BufNewFile,BufRead *.htt,*.htb setf httest " i3 au BufNewFile,BufRead */i3/config setf i3config -au BufNewFile,BufRead */.i3/config setf i3config +au BufNewFile,BufRead */.i3/config setf i3config " sway au BufNewFile,BufRead */sway/config setf swayconfig -au BufNewFile,BufRead */.sway/config setf swayconfig +au BufNewFile,BufRead */.sway/config setf swayconfig " Icon au BufNewFile,BufRead *.icn setf icon @@ -1320,7 +1333,7 @@ au BufNewFile,BufRead *.or setf openroad au BufNewFile,BufRead *.[Oo][Pp][Ll] setf opl " OpenSCAD -au BufNewFile,BufRead *.scad setf openscad +au BufNewFile,BufRead *.scad setf openscad " Oracle config file au BufNewFile,BufRead *.ora setf ora @@ -1395,7 +1408,8 @@ au BufNewFile,BufRead *.pod setf pod " Also Phtml (was used for PHP 2 in the past). " Also .ctp for Cake template file. " Also .phpt for php tests. -au BufNewFile,BufRead *.php,*.php\d,*.phtml,*.ctp,*.phpt setf php +" Also .theme for Drupal theme files. +au BufNewFile,BufRead *.php,*.php\d,*.phtml,*.ctp,*.phpt,*.theme setf php " PHP config au BufNewFile,BufRead php.ini-* setf dosini @@ -1716,6 +1730,9 @@ au BufNewFile,BufRead *.sdl,*.pr setf sdl " sed au BufNewFile,BufRead *.sed setf sed +" SubRip +au BufNewFile,BufRead *.srt setf srt + " svelte au BufNewFile,BufRead *.svelte setf svelte @@ -2101,6 +2118,9 @@ au BufNewFile,BufRead */.config/upstart/*.override setf upstart " Vala au BufNewFile,BufRead *.vala setf vala +" VDF +au BufNewFile,BufRead *.vdf setf vdf + " VDM au BufRead,BufNewFile *.vdmpp,*.vpp setf vdmpp au BufRead,BufNewFile *.vdmrt setf vdmrt @@ -2575,6 +2595,9 @@ au BufNewFile,BufRead *.txt \| setf text \| endif +" Blueprint markup files +au BufNewFile,BufRead *.blp setf blueprint + if !exists('g:did_load_ftdetect') " Use the filetype detect plugins. They may overrule any of the previously " detected filetypes. diff --git a/runtime/ftplugin/crontab.vim b/runtime/ftplugin/crontab.vim new file mode 100644 index 0000000000..8dac007ccc --- /dev/null +++ b/runtime/ftplugin/crontab.vim @@ -0,0 +1,16 @@ +" Vim filetype plugin +" Language: crontab +" Maintainer: Keith Smiley <keithbsmiley@gmail.com> +" Last Change: 2022 Sep 11 + +" Only do this when not done yet for this buffer +if exists("b:did_ftplugin") + finish +endif + +" Don't load another plugin for this buffer +let b:did_ftplugin = 1 + +let b:undo_ftplugin = "setl commentstring<" + +setlocal commentstring=#\ %s diff --git a/runtime/ftplugin/gitattributes.vim b/runtime/ftplugin/gitattributes.vim new file mode 100644 index 0000000000..2025d009d2 --- /dev/null +++ b/runtime/ftplugin/gitattributes.vim @@ -0,0 +1,13 @@ +" Vim filetype plugin +" Language: git attributes +" Maintainer: ObserverOfTime <chronobserver@disroot.org> +" Last Change: 2022 Sep 08 + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +setl comments=:# commentstring=#\ %s + +let b:undo_ftplugin = 'setl com< cms<' diff --git a/runtime/ftplugin/gitignore.vim b/runtime/ftplugin/gitignore.vim new file mode 100644 index 0000000000..3502dd2717 --- /dev/null +++ b/runtime/ftplugin/gitignore.vim @@ -0,0 +1,13 @@ +" Vim filetype plugin +" Language: git ignore +" Maintainer: ObserverOfTime <chronobserver@disroot.org> +" Last Change: 2022 Sep 10 + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +setl comments=:# commentstring=#\ %s + +let b:undo_ftplugin = 'setl com< cms<' diff --git a/runtime/ftplugin/jsonnet.vim b/runtime/ftplugin/jsonnet.vim new file mode 100644 index 0000000000..1e621e1867 --- /dev/null +++ b/runtime/ftplugin/jsonnet.vim @@ -0,0 +1,17 @@ +" Vim filetype plugin +" Language: Jsonnet +" Maintainer: Cezary Drożak <cezary@drozak.net> +" URL: https://github.com/google/vim-jsonnet +" Last Change: 2022-09-08 + +" Only do this when not done yet for this buffer +if exists("b:did_ftplugin") + finish +endif + +" Don't load another plugin for this buffer +let b:did_ftplugin = 1 + +setlocal commentstring=//\ %s + +let b:undo_ftplugin = "setlocal commentstring<" diff --git a/runtime/ftplugin/lua.vim b/runtime/ftplugin/lua.vim index 2604257594..aaa61f71d9 100644 --- a/runtime/ftplugin/lua.vim +++ b/runtime/ftplugin/lua.vim @@ -1,46 +1,46 @@ " Vim filetype plugin file. -" Language: Lua +" Language: Lua " Maintainer: Doug Kearns <dougkearns@gmail.com> " Previous Maintainer: Max Ischenko <mfi@ukr.net> -" Last Change: 2021 Nov 15 +" Contributor: Dorai Sitaram <ds26@gte.com> +" Last Change: 2022 Sep 05 -" Only do this when not done yet for this buffer if exists("b:did_ftplugin") finish endif - -" Don't load another plugin for this buffer let b:did_ftplugin = 1 let s:cpo_save = &cpo set cpo&vim -" Set 'formatoptions' to break comment lines but not other lines, and insert -" the comment leader when hitting <CR> or using "o". +setlocal comments=:-- +setlocal commentstring=--\ %s setlocal formatoptions-=t formatoptions+=croql -setlocal comments=:-- -setlocal commentstring=--%s +let &l:define = '\<function\|\<local\%(\s\+function\)\=' + setlocal suffixesadd=.lua -let b:undo_ftplugin = "setlocal fo< com< cms< sua<" +let b:undo_ftplugin = "setlocal cms< com< def< fo< sua<" if exists("loaded_matchit") && !exists("b:match_words") let b:match_ignorecase = 0 let b:match_words = - \ '\<\%(do\|function\|if\)\>:' . - \ '\<\%(return\|else\|elseif\)\>:' . - \ '\<end\>,' . - \ '\<repeat\>:\<until\>,' . - \ '\%(--\)\=\[\(=*\)\[:]\1]' - let b:undo_ftplugin .= " | unlet! b:match_words b:match_ignorecase" + \ '\<\%(do\|function\|if\)\>:' .. + \ '\<\%(return\|else\|elseif\)\>:' .. + \ '\<end\>,' .. + \ '\<repeat\>:\<until\>,' .. + \ '\%(--\)\=\[\(=*\)\[:]\1]' + let b:undo_ftplugin ..= " | unlet! b:match_words b:match_ignorecase" endif if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter") - let b:browsefilter = "Lua Source Files (*.lua)\t*.lua\n" . - \ "All Files (*.*)\t*.*\n" - let b:undo_ftplugin .= " | unlet! b:browsefilter" + let b:browsefilter = "Lua Source Files (*.lua)\t*.lua\n" .. + \ "All Files (*.*)\t*.*\n" + let b:undo_ftplugin ..= " | unlet! b:browsefilter" endif let &cpo = s:cpo_save unlet s:cpo_save + +" vim: nowrap sw=2 sts=2 ts=8 noet: diff --git a/runtime/ftplugin/lynx.vim b/runtime/ftplugin/lynx.vim new file mode 100644 index 0000000000..b76c69f0ae --- /dev/null +++ b/runtime/ftplugin/lynx.vim @@ -0,0 +1,29 @@ +" Vim filetype plugin file +" Language: Lynx Web Browser Configuration +" Maintainer: Doug Kearns <dougkearns@gmail.com> +" Last Change: 2022 Sep 09 + +if exists("b:did_ftplugin") + finish +endif +let b:did_ftplugin = 1 + +let s:cpo_save = &cpo +set cpo&vim + +setlocal comments=:# +setlocal commentstring=#\ %s +setlocal formatoptions-=t formatoptions+=croql + +let b:undo_ftplugin = "setl cms< com< fo<" + +if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter") + let b:browsefilter = "Lynx Configuration Files (lynx.cfg .lynxrc)\tlynx.cfg;.lynxrc\n" .. + \ "All Files (*.*)\t*.*\n" + let b:undo_ftplugin ..= " | unlet! b:browsefilter" +endif + +let &cpo = s:cpo_save +unlet s:cpo_save + +" vim: nowrap sw=2 sts=2 ts=8 noet: diff --git a/runtime/ftplugin/sh.vim b/runtime/ftplugin/sh.vim index 93a46f63e2..b6fdb8f3e2 100644 --- a/runtime/ftplugin/sh.vim +++ b/runtime/ftplugin/sh.vim @@ -1,12 +1,12 @@ " Vim filetype plugin file -" Language: sh -" -" This runtime file is looking for a new maintainer. -" -" Former maintainer: Dan Sharp -" Last Changed: 20 Jan 2009 - -if exists("b:did_ftplugin") | finish | endif +" Language: sh +" Maintainer: Doug Kearns <dougkearns@gmail.com> +" Previous Maintainer: Dan Sharp +" Last Change: 2022 Sep 07 + +if exists("b:did_ftplugin") + finish +endif let b:did_ftplugin = 1 " Make sure the continuation lines below do not cause problems in @@ -14,28 +14,35 @@ let b:did_ftplugin = 1 let s:save_cpo = &cpo set cpo-=C -setlocal commentstring=#%s +setlocal comments=:# +setlocal commentstring=#\ %s +setlocal formatoptions-=t formatoptions+=croql + +let b:undo_ftplugin = "setl com< cms< fo<" " Shell: thanks to Johannes Zellner -if exists("loaded_matchit") - let s:sol = '\%(;\s*\|^\s*\)\@<=' " start of line - let b:match_words = - \ s:sol.'if\>:' . s:sol.'elif\>:' . s:sol.'else\>:' . s:sol. 'fi\>,' . - \ s:sol.'\%(for\|while\)\>:' . s:sol. 'done\>,' . - \ s:sol.'case\>:' . s:sol. 'esac\>' +if exists("loaded_matchit") && !exists("b:match_words") + let b:match_ignorecase = 0 + let s:sol = '\%(;\s*\|^\s*\)\@<=' " start of line + let b:match_words = + \ s:sol .. 'if\>:' .. s:sol.'elif\>:' .. s:sol.'else\>:' .. s:sol .. 'fi\>,' .. + \ s:sol .. '\%(for\|while\)\>:' .. s:sol .. 'done\>,' .. + \ s:sol .. 'case\>:' .. s:sol .. 'esac\>' + unlet s:sol + let b:undo_ftplugin ..= " | unlet! b:match_ignorecase b:match_words" endif " Change the :browse e filter to primarily show shell-related files. -if has("gui_win32") - let b:browsefilter="Bourne Shell Scripts (*.sh)\t*.sh\n" . - \ "Korn Shell Scripts (*.ksh)\t*.ksh\n" . - \ "Bash Shell Scripts (*.bash)\t*.bash\n" . - \ "All Files (*.*)\t*.*\n" +if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter") + let b:browsefilter = "Bourne Shell Scripts (*.sh)\t*.sh\n" .. + \ "Korn Shell Scripts (*.ksh)\t*.ksh\n" .. + \ "Bash Shell Scripts (*.bash)\t*.bash\n" .. + \ "All Files (*.*)\t*.*\n" + let b:undo_ftplugin ..= " | unlet! b:browsefilter" endif -" Undo the stuff we changed. -let b:undo_ftplugin = "setlocal cms< | unlet! b:browsefilter b:match_words" - " Restore the saved compatibility options. let &cpo = s:save_cpo unlet s:save_cpo + +" vim: nowrap sw=2 sts=2 ts=8 noet: diff --git a/runtime/ftplugin/vdf.vim b/runtime/ftplugin/vdf.vim new file mode 100644 index 0000000000..973d7c0e48 --- /dev/null +++ b/runtime/ftplugin/vdf.vim @@ -0,0 +1,14 @@ +" Vim filetype plugin +" Language: Valve Data Format +" Maintainer: ObserverOfTime <chronobserver@disroot.org> +" Last Change: 2022 Sep 15 + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +setl comments=:// commentstring=//\ %s +setl foldmethod=syntax + +let b:undo_ftplugin = 'setl com< cms< fdm<' diff --git a/runtime/ftplugin/vim.vim b/runtime/ftplugin/vim.vim index 772899cb42..82a4b13f9f 100644 --- a/runtime/ftplugin/vim.vim +++ b/runtime/ftplugin/vim.vim @@ -1,7 +1,7 @@ " Vim filetype plugin " Language: Vim " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last Change: 2022 Aug 4 +" Last Change: 2022 Sep 09 " Only do this when not done yet for this buffer if exists("b:did_ftplugin") diff --git a/runtime/ftplugin/zimbu.vim b/runtime/ftplugin/zimbu.vim index e365ccf07e..cbe2f55572 100644 --- a/runtime/ftplugin/zimbu.vim +++ b/runtime/ftplugin/zimbu.vim @@ -1,7 +1,7 @@ " Vim filetype plugin file " Language: Zimbu " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last Change: 2021 Nov 12 +" Last Change: 2022 Sep 07 " Only do this when not done yet for this buffer if exists("b:did_ftplugin") @@ -28,7 +28,7 @@ endif " Set 'comments' to format dashed lists in comments. " And to keep Zudocu comment characters. -setlocal comments=sO:#\ -,mO:#\ \ ,:#=,:#-,:#%,:# +setlocal comments=sO:#\ -,mO:#\ \ ,exO:#/,s:/*,m:\ ,ex:*/,:#=,:#-,:#%,:# setlocal errorformat^=%f\ line\ %l\ col\ %c:\ %m,ERROR:\ %m diff --git a/runtime/ftplugin/zsh.vim b/runtime/ftplugin/zsh.vim index 34410f1c62..0ca8077305 100644 --- a/runtime/ftplugin/zsh.vim +++ b/runtime/ftplugin/zsh.vim @@ -2,7 +2,7 @@ " Language: Zsh shell script " Maintainer: Christian Brabandt <cb@256bit.org> " Previous Maintainer: Nikolai Weibull <now@bitwi.se> -" Latest Revision: 2020-09-01 +" Latest Revision: 2021-04-03 " License: Vim (see :h license) " Repository: https://github.com/chrisbra/vim-zsh diff --git a/runtime/indent/json.vim b/runtime/indent/json.vim index 09c7d7a85a..510f7e8f42 100644 --- a/runtime/indent/json.vim +++ b/runtime/indent/json.vim @@ -3,6 +3,7 @@ " Maintainer: Eli Parra <eli@elzr.com> https://github.com/elzr/vim-json " Last Change: 2020 Aug 30 " https://github.com/jakar/vim-json/commit/20b650e22aa750c4ab6a66aa646bdd95d7cd548a#diff-e81fc111b2052e306d126bd9989f7b7c +" 2022 Sep 07: b:undo_indent added by Doug Kearns " Original Author: Rogerz Zhang <rogerz.zhang at gmail.com> http://github.com/rogerz/vim-json " Acknowledgement: Based off of vim-javascript maintained by Darrick Wiebe " http://www.vim.org/scripts/script.php?script_id=2765 @@ -22,6 +23,8 @@ setlocal nosmartindent setlocal indentexpr=GetJSONIndent(v:lnum) setlocal indentkeys=0{,0},0),0[,0],!^F,o,O,e +let b:undo_indent = "setl inde< indk< si<" + " Only define the function once. if exists("*GetJSONIndent") finish diff --git a/runtime/indent/lua.vim b/runtime/indent/lua.vim index 604cd333c9..0d1f934a03 100644 --- a/runtime/indent/lua.vim +++ b/runtime/indent/lua.vim @@ -3,6 +3,7 @@ " Maintainer: Marcus Aurelius Farias <marcus.cf 'at' bol.com.br> " First Author: Max Ischenko <mfi 'at' ukr.net> " Last Change: 2017 Jun 13 +" 2022 Sep 07: b:undo_indent added by Doug Kearns " Only load this indent file when no other was loaded. if exists("b:did_indent") @@ -18,6 +19,8 @@ setlocal indentkeys+=0=end,0=until setlocal autoindent +let b:undo_indent = "setlocal autoindent< indentexpr< indentkeys<" + " Only define the function once. if exists("*GetLuaIndent") finish diff --git a/runtime/lua/man.lua b/runtime/lua/man.lua index 82ed0305f7..88535321ac 100644 --- a/runtime/lua/man.lua +++ b/runtime/lua/man.lua @@ -1,5 +1,3 @@ -require('vim.compat') - local api, fn = vim.api, vim.fn local find_arg = '-w' @@ -23,13 +21,15 @@ local function man_system(cmd, silent) local done = false local exit_code - local handle = vim.loop.spawn(cmd[1], { + local handle + handle = vim.loop.spawn(cmd[1], { args = vim.list_slice(cmd, 2), stdio = { nil, stdout, stderr }, }, function(code) exit_code = code stdout:close() stderr:close() + handle:close() done = true end) @@ -54,7 +54,7 @@ local function man_system(cmd, silent) if not done then if handle then - vim.loop.shutdown(handle) + handle:close() stdout:close() stderr:close() end diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index 4f7d8cccd5..98dbe0779b 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -727,6 +727,7 @@ function M.set(namespace, bufnr, diagnostics, opts) vim.api.nvim_exec_autocmds('DiagnosticChanged', { modeline = false, buffer = bufnr, + data = { diagnostics = diagnostics }, }) end @@ -1425,6 +1426,7 @@ function M.reset(namespace, bufnr) vim.api.nvim_exec_autocmds('DiagnosticChanged', { modeline = false, buffer = iter_bufnr, + data = { diagnostics = {} }, }) end end diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index fc2bcdabd2..5f58da7a34 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -177,6 +177,7 @@ local extension = { bbappend = 'bitbake', bbclass = 'bitbake', bl = 'blank', + blp = 'blueprint', bsd = 'bsdl', bsdl = 'bsdl', bst = 'bst', @@ -201,6 +202,7 @@ local extension = { return require('vim.filetype.detect').change(bufnr) end, chs = 'chaskell', + chatito = 'chatito', chopro = 'chordpro', crd = 'chordpro', crdpro = 'chordpro', @@ -610,6 +612,7 @@ local extension = { nse = 'lua', rockspec = 'lua', lua = 'lua', + lrc = 'lyrics', m = function(path, bufnr) return require('vim.filetype.detect').m(bufnr) end, @@ -746,6 +749,7 @@ local extension = { php = 'php', phpt = 'php', phtml = 'php', + theme = 'php', pike = 'pike', pmod = 'pike', rcp = 'pilrc', @@ -957,6 +961,7 @@ local extension = { srec = 'srec', mot = 'srec', ['s19'] = 'srec', + srt = 'srt', st = 'st', imata = 'stata', ['do'] = 'stata', @@ -1018,6 +1023,7 @@ local extension = { dsm = 'vb', ctl = 'vb', vbs = 'vb', + vdf = 'vdf', vdmpp = 'vdmpp', vpp = 'vdmpp', vdmrt = 'vdmrt', @@ -1290,7 +1296,6 @@ local filename = { WORKSPACE = 'bzl', BUILD = 'bzl', ['cabal.project'] = 'cabalproject', - [vim.env.HOME .. '/cabal.config'] = 'cabalconfig', ['cabal.config'] = 'cabalconfig', calendar = 'calendar', catalog = 'catalog', @@ -1383,6 +1388,8 @@ local filename = { ['EDIT_DESCRIPTION'] = 'gitcommit', ['.gitconfig'] = 'gitconfig', ['.gitmodules'] = 'gitconfig', + ['.gitattributes'] = 'gitattributes', + ['.gitignore'] = 'gitignore', ['gitolite.conf'] = 'gitolite', ['git-rebase-todo'] = 'gitrebase', gkrellmrc = 'gkrellmrc', @@ -1696,6 +1703,7 @@ local pattern = { ['.*/meta%-.*/conf/.*%.conf'] = 'bitbake', ['bzr_log%..*'] = 'bzr', ['.*enlightenment/.*%.cfg'] = 'c', + ['${HOME}/cabal%.config'] = 'cabalconfig', ['cabal%.project%..*'] = starsetf('cabalproject'), ['.*/%.calendar/.*'] = starsetf('calendar'), ['.*/share/calendar/.*/calendar%..*'] = starsetf('calendar'), @@ -1820,26 +1828,21 @@ local pattern = { ['.*/%.config/git/config'] = 'gitconfig', ['.*%.git/config%.worktree'] = 'gitconfig', ['.*%.git/worktrees/.*/config%.worktree'] = 'gitconfig', - ['.*/git/config'] = function(path, bufnr) - if vim.env.XDG_CONFIG_HOME and path:find(vim.env.XDG_CONFIG_HOME .. '/git/config') then - return 'gitconfig' - end - end, + ['${XDG_CONFIG_HOME}/git/config'] = 'gitconfig', + ['.*%.git/info/attributes'] = 'gitattributes', + ['.*/etc/gitattributes'] = 'gitattributes', + ['.*/%.config/git/attributes'] = 'gitattributes', + ['${XDG_CONFIG_HOME}/git/attributes'] = 'gitattributes', + ['.*%.git/info/exclude'] = 'gitignore', + ['.*/%.config/git/ignore'] = 'gitignore', + ['${XDG_CONFIG_HOME}/git/ignore'] = 'gitignore', ['%.gitsendemail%.msg%.......'] = 'gitsendemail', ['gkrellmrc_.'] = 'gkrellmrc', ['.*/usr/.*/gnupg/options%.skel'] = 'gpg', ['.*/%.gnupg/options'] = 'gpg', ['.*/%.gnupg/gpg%.conf'] = 'gpg', - ['.*/options'] = function(path, bufnr) - if vim.env.GNUPGHOME and path:find(vim.env.GNUPGHOME .. '/options') then - return 'gpg' - end - end, - ['.*/gpg%.conf'] = function(path, bufnr) - if vim.env.GNUPGHOME and path:find(vim.env.GNUPGHOME .. '/gpg%.conf') then - return 'gpg' - end - end, + ['${GNUPGHOME}/options'] = 'gpg', + ['${GNUPGHOME}/gpg%.conf'] = 'gpg', ['.*/etc/group'] = 'group', ['.*/etc/gshadow'] = 'group', ['.*/etc/group%.edit'] = 'group', @@ -1853,7 +1856,7 @@ local pattern = { ['.*/etc/grub%.conf'] = 'grub', -- gtkrc* and .gtkrc* ['%.?gtkrc.*'] = starsetf('gtkrc'), - [vim.env.VIMRUNTIME .. '/doc/.*%.txt'] = 'help', + ['${VIMRUNTIME}/doc/.*%.txt'] = 'help', ['hg%-editor%-.*%.txt'] = 'hgcommit', ['.*/etc/host%.conf'] = 'hostconf', ['.*/etc/hosts%.deny'] = 'hostsaccess', @@ -2257,6 +2260,9 @@ end --- Filename patterns can specify an optional priority to resolve cases when a --- file path matches multiple patterns. Higher priorities are matched first. --- When omitted, the priority defaults to 0. +--- A pattern can contain environment variables of the form "${SOME_VAR}" that will +--- be automatically expanded. If the environment variable is not set, the pattern +--- won't be matched. --- --- See $VIMRUNTIME/lua/vim/filetype.lua for more examples. --- @@ -2285,6 +2291,8 @@ end --- ['.*/etc/foo/.*'] = 'fooscript', --- -- Using an optional priority --- ['.*/etc/foo/.*%.conf'] = { 'dosini', { priority = 10 } }, +--- -- A pattern containing an environment variable +--- ['${XDG_CONFIG_HOME}/foo/git'] = 'git', --- ['README.(%a+)$'] = function(path, bufnr, ext) --- if ext == 'md' then --- return 'markdown' @@ -2358,8 +2366,28 @@ local function dispatch(ft, path, bufnr, ...) end end +-- Lookup table/cache for patterns that contain an environment variable pattern, e.g. ${SOME_VAR}. +local expand_env_lookup = {} + ---@private local function match_pattern(name, path, tail, pat) + if expand_env_lookup[pat] == nil then + expand_env_lookup[pat] = pat:find('%${') ~= nil + end + if expand_env_lookup[pat] then + local return_early + pat = pat:gsub('%${(%S-)}', function(env) + -- If an environment variable is present in the pattern but not set, there is no match + if not vim.env[env] then + return_early = true + return nil + end + return vim.env[env] + end) + if return_early then + return false + end + end -- If the pattern contains a / match against the full path, otherwise just the tail local fullpat = '^' .. pat .. '$' local matches diff --git a/runtime/lua/vim/fs.lua b/runtime/lua/vim/fs.lua index ce845eda15..7bd635d8b6 100644 --- a/runtime/lua/vim/fs.lua +++ b/runtime/lua/vim/fs.lua @@ -76,8 +76,11 @@ end --- The search can be narrowed to find only files or or only directories by --- specifying {type} to be "file" or "directory", respectively. --- ----@param names (string|table) Names of the files and directories to find. Must ---- be base names, paths and globs are not supported. +---@param names (string|table|fun(name: string): boolean) Names of the files +--- and directories to find. +--- Must be base names, paths and globs are not supported. +--- If a function it is called per file and dir within the +--- traversed directories to test if they match. ---@param opts (table) Optional keyword arguments: --- - path (string): Path to begin searching from. If --- omitted, the current working directory is used. @@ -98,7 +101,7 @@ end function M.find(names, opts) opts = opts or {} vim.validate({ - names = { names, { 's', 't' } }, + names = { names, { 's', 't', 'f' } }, path = { opts.path, 's', true }, upward = { opts.upward, 'b', true }, stop = { opts.stop, 's', true }, @@ -123,18 +126,31 @@ function M.find(names, opts) end if opts.upward then - ---@private - local function test(p) - local t = {} - for _, name in ipairs(names) do - local f = p .. '/' .. name - local stat = vim.loop.fs_stat(f) - if stat and (not opts.type or opts.type == stat.type) then - t[#t + 1] = f + local test + + if type(names) == 'function' then + test = function(p) + local t = {} + for name, type in M.dir(p) do + if names(name) and (not opts.type or opts.type == type) then + table.insert(t, p .. '/' .. name) + end end + return t end + else + test = function(p) + local t = {} + for _, name in ipairs(names) do + local f = p .. '/' .. name + local stat = vim.loop.fs_stat(f) + if stat and (not opts.type or opts.type == stat.type) then + t[#t + 1] = f + end + end - return t + return t + end end for _, match in ipairs(test(path)) do @@ -162,17 +178,25 @@ function M.find(names, opts) break end - for other, type in M.dir(dir) do + for other, type_ in M.dir(dir) do local f = dir .. '/' .. other - for _, name in ipairs(names) do - if name == other and (not opts.type or opts.type == type) then + if type(names) == 'function' then + if names(other) and (not opts.type or opts.type == type_) then if add(f) then return matches end end + else + for _, name in ipairs(names) do + if name == other and (not opts.type or opts.type == type_) then + if add(f) then + return matches + end + end + end end - if type == 'directory' then + if type_ == 'directory' then dirs[#dirs + 1] = f end end diff --git a/runtime/lua/vim/keymap.lua b/runtime/lua/vim/keymap.lua index 219de16b5c..af41794c53 100644 --- a/runtime/lua/vim/keymap.lua +++ b/runtime/lua/vim/keymap.lua @@ -36,17 +36,17 @@ local keymap = {} ---@param lhs string Left-hand side |{lhs}| of the mapping. ---@param rhs string|function Right-hand side |{rhs}| of the mapping. Can also be a Lua function. -- ----@param opts table A table of |:map-arguments|. ---- + Accepts options accepted by the {opts} parameter in |nvim_set_keymap()|, ---- with the following notable differences: ---- - replace_keycodes: Defaults to `true` if "expr" is `true`. ---- - noremap: Always overridden with the inverse of "remap" (see below). ---- + In addition to those options, the table accepts the following keys: ---- - buffer: (number or boolean) Add a mapping to the given buffer. ---- When `0` or `true`, use the current buffer. ---- - remap: (boolean) Make the mapping recursive. ---- This is the inverse of the "noremap" option from |nvim_set_keymap()|. ---- Defaults to `false`. +---@param opts table|nil A table of |:map-arguments|. +--- + Accepts options accepted by the {opts} parameter in |nvim_set_keymap()|, +--- with the following notable differences: +--- - replace_keycodes: Defaults to `true` if "expr" is `true`. +--- - noremap: Always overridden with the inverse of "remap" (see below). +--- + In addition to those options, the table accepts the following keys: +--- - buffer: (number or boolean) Add a mapping to the given buffer. +--- When `0` or `true`, use the current buffer. +--- - remap: (boolean) Make the mapping recursive. +--- This is the inverse of the "noremap" option from |nvim_set_keymap()|. +--- Defaults to `false`. ---@see |nvim_set_keymap()| function keymap.set(mode, lhs, rhs, opts) vim.validate({ @@ -57,7 +57,6 @@ function keymap.set(mode, lhs, rhs, opts) }) opts = vim.deepcopy(opts) or {} - local is_rhs_luaref = type(rhs) == 'function' mode = type(mode) == 'string' and { mode } or mode if opts.expr and opts.replace_keycodes ~= false then @@ -73,7 +72,7 @@ function keymap.set(mode, lhs, rhs, opts) opts.remap = nil end - if is_rhs_luaref then + if type(rhs) == 'function' then opts.callback = rhs rhs = '' end @@ -99,9 +98,9 @@ end --- --- vim.keymap.del({'n', 'i', 'v'}, '<leader>w', { buffer = 5 }) --- </pre> ----@param opts table A table of optional arguments: ---- - buffer: (number or boolean) Remove a mapping from the given buffer. ---- When "true" or 0, use the current buffer. +---@param opts table|nil A table of optional arguments: +--- - buffer: (number or boolean) Remove a mapping from the given buffer. +--- When "true" or 0, use the current buffer. ---@see |vim.keymap.set()| --- function keymap.del(modes, lhs, opts) diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 1dc1a045fd..22933d8143 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1147,33 +1147,34 @@ function lsp.start_client(config) local namespace = vim.lsp.diagnostic.get_namespace(client_id) vim.diagnostic.reset(namespace, bufnr) - end) - client_ids[client_id] = nil - end - if vim.tbl_isempty(client_ids) then - vim.schedule(function() - unset_defaults(bufnr) + client_ids[client_id] = nil + if vim.tbl_isempty(client_ids) then + unset_defaults(bufnr) + end end) end end - local client = active_clients[client_id] and active_clients[client_id] - or uninitialized_clients[client_id] - active_clients[client_id] = nil - uninitialized_clients[client_id] = nil - -- Client can be absent if executable starts, but initialize fails - -- init/attach won't have happened - if client then - changetracking.reset(client) - end - if code ~= 0 or (signal ~= 0 and signal ~= 15) then - local msg = - string.format('Client %s quit with exit code %s and signal %s', client_id, code, signal) - vim.schedule(function() + -- Schedule the deletion of the client object so that it exists in the execution of LspDetach + -- autocommands + vim.schedule(function() + local client = active_clients[client_id] and active_clients[client_id] + or uninitialized_clients[client_id] + active_clients[client_id] = nil + uninitialized_clients[client_id] = nil + + -- Client can be absent if executable starts, but initialize fails + -- init/attach won't have happened + if client then + changetracking.reset(client) + end + if code ~= 0 or (signal ~= 0 and signal ~= 15) then + local msg = + string.format('Client %s quit with exit code %s and signal %s', client_id, code, signal) vim.notify(msg, vim.log.levels.WARN) - end) - end + end + end) end -- Start the RPC client. @@ -1644,6 +1645,7 @@ function lsp.buf_attach_client(bufnr, client_id) if vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'openClose') then client.notify('textDocument/didClose', params) end + client.attached_buffers[bufnr] = nil end) util.buf_versions[bufnr] = nil all_buffer_active_clients[bufnr] = nil diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index 70f838f34d..755c0ffc6f 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -405,8 +405,7 @@ function Client:handle_body(body) { status = status, result = result, err = err } ) if status then - if not (result or err) then - -- TODO this can be a problem if `null` is sent for result. needs vim.NIL + if result == nil and err == nil then error( string.format( 'method %q: either a result or an error must be sent to the server in response', @@ -635,7 +634,8 @@ local function connect(host, port) end --- Starts an LSP server process and create an LSP RPC client object to ---- interact with it. Communication with the server is currently limited to stdio. +--- interact with it. Communication with the spawned process happens via stdio. For +--- communication via TCP, spawn a process manually and use |vim.lsp.rpc.connect| --- ---@param cmd (string) Command to start the LSP server. ---@param cmd_args (table) List of additional string arguments to pass to {cmd}. diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 283099bbcf..1909dbd4d1 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -459,35 +459,52 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding) text = split(text_edit.newText, '\n', true), } - -- Some LSP servers may return +1 range of the buffer content but nvim_buf_set_text can't accept it so we should fix it here. local max = api.nvim_buf_line_count(bufnr) - if max <= e.start_row or max <= e.end_row then - local len = #(get_line(bufnr, max - 1) or '') - if max <= e.start_row then - e.start_row = max - 1 - e.start_col = len - table.insert(e.text, 1, '') - end + -- If the whole edit is after the lines in the buffer we can simply add the new text to the end + -- of the buffer. + if max <= e.start_row then + api.nvim_buf_set_lines(bufnr, max, max, false, e.text) + else + local last_line_len = #(get_line(bufnr, math.min(e.end_row, max - 1)) or '') + -- Some LSP servers may return +1 range of the buffer content but nvim_buf_set_text can't + -- accept it so we should fix it here. if max <= e.end_row then e.end_row = max - 1 - e.end_col = len + e.end_col = last_line_len + has_eol_text_edit = true + else + -- If the replacement is over the end of a line (i.e. e.end_col is out of bounds and the + -- replacement text ends with a newline We can likely assume that the replacement is assumed + -- to be meant to replace the newline with another newline and we need to make sure this + -- doens't add an extra empty line. E.g. when the last line to be replaced contains a '\r' + -- in the file some servers (clangd on windows) will include that character in the line + -- while nvim_buf_set_text doesn't count it as part of the line. + if + e.end_col > last_line_len + and #text_edit.newText > 0 + and string.sub(text_edit.newText, -1) == '\n' + then + table.remove(e.text, #e.text) + end end - has_eol_text_edit = true - end - api.nvim_buf_set_text(bufnr, e.start_row, e.start_col, e.end_row, e.end_col, e.text) - - -- Fix cursor position. - local row_count = (e.end_row - e.start_row) + 1 - if e.end_row < cursor.row then - cursor.row = cursor.row + (#e.text - row_count) - is_cursor_fixed = true - elseif e.end_row == cursor.row and e.end_col <= cursor.col then - cursor.row = cursor.row + (#e.text - row_count) - cursor.col = #e.text[#e.text] + (cursor.col - e.end_col) - if #e.text == 1 then - cursor.col = cursor.col + e.start_col + -- Make sure we don't go out of bounds for e.end_col + e.end_col = math.min(last_line_len, e.end_col) + + api.nvim_buf_set_text(bufnr, e.start_row, e.start_col, e.end_row, e.end_col, e.text) + + -- Fix cursor position. + local row_count = (e.end_row - e.start_row) + 1 + if e.end_row < cursor.row then + cursor.row = cursor.row + (#e.text - row_count) + is_cursor_fixed = true + elseif e.end_row == cursor.row and e.end_col <= cursor.col then + cursor.row = cursor.row + (#e.text - row_count) + cursor.col = #e.text[#e.text] + (cursor.col - e.end_col) + if #e.text == 1 then + cursor.col = cursor.col + e.start_col + end + is_cursor_fixed = true end - is_cursor_fixed = true end end diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 59cb669609..de5f7240aa 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -720,7 +720,7 @@ end --- --- They mimic defaultdict in python. --- ---- If @p create is @c nil, this will create a defaulttable whose constructor function is +--- If {create} is `nil`, this will create a defaulttable whose constructor function is --- this function, effectively allowing to create nested tables on the fly: --- --- <pre> diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index d93c485dfe..04e12cbe0b 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -25,15 +25,15 @@ setmetatable(M, { end, }) ---- Creates a new parser. +--- Creates a new parser --- ---- It is not recommended to use this, use vim.treesitter.get_parser() instead. +--- It is not recommended to use this; use |get_parser()| instead. --- ---@param bufnr string Buffer the parser will be tied to (0 for current buffer) ---@param lang string Language of the parser ----@param opts table|nil Options to pass to the created language tree +---@param opts (table|nil) Options to pass to the created language tree --- ----@returns table Created parser object +---@return LanguageTree |LanguageTree| object to use for parsing function M._create_parser(bufnr, lang, opts) language.require_language(lang) if bufnr == 0 then @@ -73,16 +73,15 @@ function M._create_parser(bufnr, lang, opts) return self end ---- Gets the parser for this bufnr / ft combination. +--- Returns the parser for a specific buffer and filetype and attaches it to the buffer --- ---- If needed this will create the parser. ---- Unconditionally attach the provided callback +--- If needed, this will create the parser. --- ----@param bufnr number|nil Buffer the parser should be tied to (default: current buffer) ----@param lang string |nil Filetype of this parser (default: buffer filetype) ----@param opts table|nil Options to pass to the created language tree +---@param bufnr (number|nil) Buffer the parser should be tied to (default: current buffer) +---@param lang (string|nil) Filetype of this parser (default: buffer filetype) +---@param opts (table|nil) Options to pass to the created language tree --- ----@returns table Parser object +---@return LanguageTree |LanguageTree| object to use for parsing function M.get_parser(bufnr, lang, opts) opts = opts or {} @@ -102,11 +101,13 @@ function M.get_parser(bufnr, lang, opts) return parsers[bufnr] end ---- Gets a string parser +--- Returns a string parser --- ----@param str The string to parse ----@param lang The language of this string ----@param opts Options to pass to the created language tree +---@param str string Text to parse +---@param lang string Language of this string +---@param opts (table|nil) Options to pass to the created language tree +--- +---@return LanguageTree |LanguageTree| object to use for parsing function M.get_string_parser(str, lang, opts) vim.validate({ str = { str, 'string' }, @@ -119,10 +120,10 @@ end --- Determines whether a node is the ancestor of another --- ----@param dest table Possible ancestor ----@param source table Possible descendant node +---@param dest userdata Possible ancestor |tsnode| +---@param source userdata Possible descendant |tsnode| --- ----@returns (boolean) True if dest is an ancestor of source +---@return boolean True if {dest} is an ancestor of {source} function M.is_ancestor(dest, source) if not (dest and source) then return false @@ -140,11 +141,11 @@ function M.is_ancestor(dest, source) return false end ---- Get the node's range or unpack a range table +--- Returns the node's range or an unpacked range table --- ----@param node_or_range table +---@param node_or_range (userdata|table) |tsnode| or table of positions --- ----@returns table start_row, start_col, end_row, end_col +---@return table `{ start_row, start_col, end_row, end_col }` function M.get_node_range(node_or_range) if type(node_or_range) == 'table' then return unpack(node_or_range) @@ -153,13 +154,13 @@ function M.get_node_range(node_or_range) end end ----Determines whether (line, col) position is in node range +--- Determines whether (line, col) position is in node range --- ----@param node table Node defining the range +---@param node userdata |tsnode| defining the range ---@param line number Line (0-based) ---@param col number Column (0-based) --- ----@returns (boolean) True if the position is in node range +---@return boolean True if the position is in node range function M.is_in_node_range(node, line, col) local start_line, start_col, end_line, end_col = M.get_node_range(node) if line >= start_line and line <= end_line then @@ -177,11 +178,12 @@ function M.is_in_node_range(node, line, col) end end ----Determines if a node contains a range ----@param node table +--- Determines if a node contains a range +--- +---@param node userdata |tsnode| ---@param range table --- ----@returns (boolean) True if the node contains the range +---@return boolean True if the {node} contains the {range} function M.node_contains(node, range) local start_row, start_col, end_row, end_col = node:range() local start_fits = start_row < range[1] or (start_row == range[1] and start_col <= range[2]) @@ -190,16 +192,16 @@ function M.node_contains(node, range) return start_fits and end_fits end ----Gets a list of captures for a given cursor position ----@param bufnr number Buffer number (0 for current buffer) ----@param row number Position row ----@param col number Position column +--- Returns a list of highlight captures at the given position +--- +--- Each capture is represented by a table containing the capture name as a string as +--- well as a table of metadata (`priority`, `conceal`, ...; empty if none are defined). --- ---@param bufnr number Buffer number (0 for current buffer) ---@param row number Position row ---@param col number Position column --- ----@returns (table) Table of captures +---@return table[] List of captures `{ capture = "capture name", metadata = { ... } }` function M.get_captures_at_position(bufnr, row, col) if bufnr == 0 then bufnr = a.nvim_get_current_buf() @@ -238,7 +240,7 @@ function M.get_captures_at_position(bufnr, row, col) if M.is_in_node_range(node, row, col) then local c = q._query.captures[capture] -- name of the capture in the query if c ~= nil then - table.insert(matches, { capture = c, priority = metadata.priority }) + table.insert(matches, { capture = c, metadata = metadata }) end end end @@ -246,11 +248,11 @@ function M.get_captures_at_position(bufnr, row, col) return matches end ----Gets a list of captures under the cursor +--- Returns a list of highlight capture names under the cursor --- ----@param winnr number|nil Window handle or 0 for current window (default) +---@param winnr (number|nil) Window handle or 0 for current window (default) --- ----@returns (table) Named node under the cursor +---@return string[] List of capture names function M.get_captures_at_cursor(winnr) winnr = winnr or 0 local bufnr = a.nvim_win_get_buf(winnr) @@ -267,7 +269,7 @@ function M.get_captures_at_cursor(winnr) return captures end ---- Gets the smallest named node at position +--- Returns the smallest named node at the given position --- ---@param bufnr number Buffer number (0 for current buffer) ---@param row number Position row @@ -275,7 +277,7 @@ end ---@param opts table Optional keyword arguments: --- - ignore_injections boolean Ignore injected languages (default true) --- ----@returns (table) Named node under the cursor +---@return userdata |tsnode| under the cursor function M.get_node_at_position(bufnr, row, col, opts) if bufnr == 0 then bufnr = a.nvim_get_current_buf() @@ -290,11 +292,11 @@ function M.get_node_at_position(bufnr, row, col, opts) return root_lang_tree:named_node_for_range(ts_range, opts) end ---- Gets the smallest named node under the cursor +--- Returns the smallest named node under the cursor --- ----@param winnr number|nil Window handle or 0 for current window (default) +---@param winnr (number|nil) Window handle or 0 for current window (default) --- ----@returns (string) Named node under the cursor +---@return string Name of node under the cursor function M.get_node_at_cursor(winnr) winnr = winnr or 0 local bufnr = a.nvim_win_get_buf(winnr) @@ -304,15 +306,14 @@ function M.get_node_at_cursor(winnr) :type() end ---- Start treesitter highlighting for a buffer +--- Starts treesitter highlighting for a buffer --- ---- Can be used in an ftplugin or FileType autocommand +--- Can be used in an ftplugin or FileType autocommand. --- --- Note: By default, disables regex syntax highlighting, which may be required for some plugins. --- In this case, add ``vim.bo.syntax = 'on'`` after the call to `start`. --- --- Example: ---- --- <pre> --- vim.api.nvim_create_autocmd( 'FileType', { pattern = 'tex', --- callback = function(args) @@ -322,8 +323,8 @@ end --- }) --- </pre> --- ----@param bufnr number|nil Buffer to be highlighted (default: current buffer) ----@param lang string|nil Language of the parser (default: buffer filetype) +---@param bufnr (number|nil) Buffer to be highlighted (default: current buffer) +---@param lang (string|nil) Language of the parser (default: buffer filetype) function M.start(bufnr, lang) bufnr = bufnr or a.nvim_get_current_buf() @@ -334,9 +335,9 @@ function M.start(bufnr, lang) vim.b[bufnr].ts_highlight = true end ----Stop treesitter highlighting for a buffer +--- Stops treesitter highlighting for a buffer --- ----@param bufnr number|nil Buffer to stop highlighting (default: current buffer) +---@param bufnr (number|nil) Buffer to stop highlighting (default: current buffer) function M.stop(bufnr) bufnr = bufnr or a.nvim_get_current_buf() diff --git a/runtime/lua/vim/treesitter/health.lua b/runtime/lua/vim/treesitter/health.lua index 3bd59ca282..4995c80a02 100644 --- a/runtime/lua/vim/treesitter/health.lua +++ b/runtime/lua/vim/treesitter/health.lua @@ -3,7 +3,7 @@ local ts = vim.treesitter --- Lists the parsers currently installed --- ----@return A list of parsers +---@return string[] list of parser files function M.list_parsers() return vim.api.nvim_get_runtime_file('parser/*', true) end diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index 1e625eddb8..83a26aff13 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -2,6 +2,7 @@ local a = vim.api local query = require('vim.treesitter.query') -- support reload for quick experimentation +---@class TSHighlighter local TSHighlighter = rawget(vim.treesitter, 'TSHighlighter') or {} TSHighlighter.__index = TSHighlighter @@ -45,9 +46,10 @@ end --- Creates a new highlighter using @param tree --- ----@param tree The language tree to use for highlighting ----@param opts Table used to configure the highlighter ---- - queries: Table to overwrite queries used by the highlighter +---@param tree LanguageTree |LanguageTree| parser object to use for highlighting +---@param opts (table|nil) Configuration of the highlighter: +--- - queries table overwrite queries used by the highlighter +---@return TSHighlighter Created highlighter object function TSHighlighter.new(tree, opts) local self = setmetatable({}, TSHighlighter) @@ -149,8 +151,10 @@ function TSHighlighter:on_changedtree(changes) end --- Gets the query used for @param lang ---- ----@param lang A language used by the highlighter. +-- +---@private +---@param lang string Language used by the highlighter. +---@return Query function TSHighlighter:get_query(lang) if not self._queries[lang] then self._queries[lang] = TSHighlighterQuery.new(lang) diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua index d14b825603..c92d63b8c4 100644 --- a/runtime/lua/vim/treesitter/language.lua +++ b/runtime/lua/vim/treesitter/language.lua @@ -2,14 +2,15 @@ local a = vim.api local M = {} ---- Asserts that the provided language is installed, and optionally provide a path for the parser +--- Asserts that a parser for the language {lang} is installed. --- ---- Parsers are searched in the `parser` runtime directory. +--- Parsers are searched in the `parser` runtime directory, or the provided {path} --- ----@param lang string The language the parser should parse ----@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 +---@param lang string Language the parser should parse +---@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 +---@return boolean If the specified language is installed function M.require_language(lang, path, silent, symbol_name) if vim._ts_has_language(lang) then return true @@ -42,7 +43,8 @@ end --- --- Inspecting provides some useful information on the language like node names, ... --- ----@param lang The language. +---@param lang string Language +---@return table function M.inspect_language(lang) M.require_language(lang) return vim._ts_inspect_language(lang) diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index 70317a9f94..e9d70c4204 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -2,19 +2,35 @@ local a = vim.api local query = require('vim.treesitter.query') local language = require('vim.treesitter.language') +---@class LanguageTree +---@field _callbacks function[] Callback handlers +---@field _children LanguageTree[] Injected languages +---@field _injection_query table Queries defining injected languages +---@field _opts table Options +---@field _parser userdata Parser for language +---@field _regions table List of regions this tree should manage and parse +---@field _lang string Language name +---@field _regions table +---@field _source (number|string) Buffer or string to parse +---@field _trees userdata[] Reference to parsed |tstree| (one for each language) +---@field _valid boolean If the parsed tree is valid + local LanguageTree = {} LanguageTree.__index = LanguageTree ---- Represents a single treesitter parser for a language. ---- The language can contain child languages with in its range, ---- hence the tree. +--- A |LanguageTree| holds the treesitter parser for a given language {lang} used +--- to parse a buffer. As the buffer may contain injected languages, the LanguageTree +--- needs to store parsers for these child languages as well (which in turn may contain +--- child languages themselves, hence the name). --- ----@param source Can be a bufnr or a string of text to parse ----@param lang The language this tree represents ----@param opts Options table ----@param opts.injections A table of language to injection query strings. ---- This is useful for overriding the built-in runtime file ---- searching for the injection language query per language. +---@param source (number|string) Buffer or a string of text to parse +---@param lang string Root language this tree represents +---@param opts (table|nil) Optional keyword arguments: +--- - injections table Mapping language to injection query strings. +--- This is useful for overriding the built-in +--- runtime file searching for the injection language +--- query per language. +---@return LanguageTree |LanguageTree| parser object function LanguageTree.new(source, lang, opts) language.require_language(lang) opts = opts or {} @@ -94,6 +110,9 @@ end --- for the language this tree represents. --- This will run the injection query for this language to --- determine if any child languages should be created. +--- +---@return userdata[] Table of parsed |tstree| +---@return table Change list function LanguageTree:parse() if self._valid then return self._trees @@ -167,10 +186,10 @@ function LanguageTree:parse() return self._trees, changes end ---- Invokes the callback for each LanguageTree and it's children recursively +--- Invokes the callback for each |LanguageTree| and its children recursively --- ----@param fn The function to invoke. This is invoked with arguments (tree: LanguageTree, lang: string) ----@param include_self Whether to include the invoking tree in the results. +---@param fn function(tree: LanguageTree, lang: string) +---@param include_self boolean Whether to include the invoking tree in the results function LanguageTree:for_each_child(fn, include_self) if include_self then fn(self, self._lang) @@ -181,12 +200,11 @@ function LanguageTree:for_each_child(fn, include_self) end end ---- Invokes the callback for each treesitter trees recursively. +--- Invokes the callback for each |LanguageTree| recursively. --- ---- Note, this includes the invoking language tree's trees as well. +--- Note: This includes the invoking tree's child trees as well. --- ----@param fn The callback to invoke. The callback is invoked with arguments ---- (tree: TSTree, languageTree: LanguageTree) +---@param fn function(tree: TSTree, languageTree: LanguageTree) function LanguageTree:for_each_tree(fn) for _, tree in ipairs(self._trees) do fn(tree, self) @@ -197,11 +215,13 @@ function LanguageTree:for_each_tree(fn) end end ---- Adds a child language to this tree. +--- Adds a child language to this |LanguageTree|. --- --- If the language already exists as a child, it will first be removed. --- ----@param lang The language to add. +---@private +---@param lang string Language to add. +---@return LanguageTree Injected |LanguageTree| function LanguageTree:add_child(lang) if self._children[lang] then self:remove_child(lang) @@ -215,9 +235,10 @@ function LanguageTree:add_child(lang) return self._children[lang] end ---- Removes a child language from this tree. +--- Removes a child language from this |LanguageTree|. --- ----@param lang The language to remove. +---@private +---@param lang string Language to remove. function LanguageTree:remove_child(lang) local child = self._children[lang] @@ -229,12 +250,11 @@ function LanguageTree:remove_child(lang) end end ---- Destroys this language tree and all its children. +--- Destroys this |LanguageTree| and all its children. --- --- Any cleanup logic should be performed here. --- ---- Note: ---- This DOES NOT remove this tree from a parent. Instead, +--- Note: This DOES NOT remove this tree from a parent. Instead, --- `remove_child` must be called on the parent to remove it. function LanguageTree:destroy() -- Cleanup here @@ -243,23 +263,24 @@ function LanguageTree:destroy() end end ---- Sets the included regions that should be parsed by this parser. +--- Sets the included regions that should be parsed by this |LanguageTree|. --- A region is a set of nodes and/or ranges that will be parsed in the same context. --- ---- For example, `{ { node1 }, { node2} }` is two separate regions. ---- This will be parsed by the parser in two different contexts... thus resulting +--- For example, `{ { node1 }, { node2} }` contains two separate regions. +--- They will be parsed by the parser in two different contexts, thus resulting --- in two separate trees. --- ---- `{ { node1, node2 } }` is a single region consisting of two nodes. ---- This will be parsed by the parser in a single context... thus resulting +--- On the other hand, `{ { node1, node2 } }` is a single region consisting of +--- two nodes. This will be parsed by the parser in a single context, thus resulting --- in a single tree. --- --- This allows for embedded languages to be parsed together across different --- nodes, which is useful for templating languages like ERB and EJS. --- ---- Note, this call invalidates the tree and requires it to be parsed again. +--- Note: This call invalidates the tree and requires it to be parsed again. --- ----@param regions (table) list of regions this tree should manage and parse. +---@private +---@param regions table List of regions this tree should manage and parse. function LanguageTree:set_included_regions(regions) -- Transform the tables from 4 element long to 6 element long (with byte offset) for _, region in ipairs(regions) do @@ -288,7 +309,7 @@ function LanguageTree:set_included_regions(regions) -- Trees are no longer valid now that we have changed regions. -- TODO(vigoux,steelsojka): Look into doing this smarter so we can use some of the -- old trees for incremental parsing. Currently, this only - -- effects injected languages. + -- affects injected languages. self._trees = {} self:invalidate() end @@ -493,8 +514,8 @@ function LanguageTree:_on_detach(...) self:_do_callback('detach', ...) end ---- Registers callbacks for the parser. ----@param cbs table An |nvim_buf_attach()|-like table argument with the following keys : +--- Registers callbacks for the |LanguageTree|. +---@param cbs table An |nvim_buf_attach()|-like table argument with the following handlers: --- - `on_bytes` : see |nvim_buf_attach()|, but this will be called _after_ the parsers callback. --- - `on_changedtree` : a callback that will be called every time the tree has syntactical changes. --- It will only be passed one argument, which is a table of the ranges (as node ranges) that @@ -536,9 +557,10 @@ local function tree_contains(tree, range) return start_fits and end_fits end ---- Determines whether {range} is contained in this language tree +--- Determines whether {range} is contained in the |LanguageTree|. --- ----@param range A range, that is a `{ start_line, start_col, end_line, end_col }` table. +---@param range table `{ start_line, start_col, end_line, end_col }` +---@return boolean function LanguageTree:contains(range) for _, tree in pairs(self._trees) do if tree_contains(tree, range) then @@ -549,11 +571,12 @@ function LanguageTree:contains(range) return false end ---- Gets the tree that contains {range} +--- Gets the tree that contains {range}. --- ----@param range table A text range ----@param opts table Options table ----@param opts.ignore_injections boolean (default true) Ignore injected languages. +---@param range table `{ start_line, start_col, end_line, end_col }` +---@param opts table|nil Optional keyword arguments: +--- - ignore_injections boolean Ignore injected languages (default true) +---@return userdata|nil Contained |tstree| function LanguageTree:tree_for_range(range, opts) opts = opts or {} local ignore = vim.F.if_nil(opts.ignore_injections, true) @@ -577,19 +600,21 @@ function LanguageTree:tree_for_range(range, opts) return nil end ---- Gets the smallest named node that contains {range} +--- Gets the smallest named node that contains {range}. --- ----@param range table A text range ----@param opts table Options table ----@param opts.ignore_injections boolean (default true) Ignore injected languages. +---@param range table `{ start_line, start_col, end_line, end_col }` +---@param opts table|nil Optional keyword arguments: +--- - ignore_injections boolean Ignore injected languages (default true) +---@return userdata|nil Found |tsnode| function LanguageTree:named_node_for_range(range, opts) local tree = self:tree_for_range(range, opts) return tree:root():named_descendant_for_range(unpack(range)) end ---- Gets the appropriate language that contains {range} +--- Gets the appropriate language that contains {range}. --- ----@param range A text range, see |LanguageTree:contains| +---@param range table `{ start_line, start_col, end_line, end_col }` +---@return LanguageTree Managing {range} function LanguageTree:language_for_range(range) for _, child in pairs(self._children) do if child:contains(range) then diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index 2f6227af8e..d1dc29969b 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -3,6 +3,11 @@ local language = require('vim.treesitter.language') -- query: pattern matching on trees -- predicate matching is implemented in lua +-- +---@class Query +---@field captures string[] List of captures used in query +---@field info table Contains used queries, predicates, directives +---@field query userdata Parsed query local Query = {} Query.__index = Query @@ -34,11 +39,24 @@ local function safe_read(filename, read_quantifier) return content end +---@private +--- Adds {ilang} to {base_langs}, only if {ilang} is different than {lang} +--- +---@return boolean true If lang == ilang +local function add_included_lang(base_langs, lang, ilang) + if lang == ilang then + return true + end + table.insert(base_langs, ilang) + return false +end + --- Gets the list of files used to make up a query --- ----@param lang The language ----@param query_name The name of the query to load ----@param is_included Internal parameter, most of the time left as `nil` +---@param lang string Language to get query for +---@param query_name string Name of the query to load (e.g., 'highlights') +---@param is_included (boolean|nil) Internal parameter, most of the time left as `nil` +---@return string[] query_files List of files to load for given query and language function M.get_query_files(lang, query_name, is_included) local query_path = string.format('queries/%s/%s.scm', lang, query_name) local lang_files = dedupe_files(a.nvim_get_runtime_file(query_path, true)) @@ -84,10 +102,14 @@ function M.get_query_files(lang, query_name, is_included) if is_optional then if not is_included then - table.insert(base_langs, incllang:sub(2, #incllang - 1)) + if add_included_lang(base_langs, lang, incllang:sub(2, #incllang - 1)) then + extension = true + end end else - table.insert(base_langs, incllang) + if add_included_lang(base_langs, lang, incllang) then + extension = true + end end end elseif modeline:match(EXTENDS_FORMAT) then @@ -134,24 +156,24 @@ local explicit_queries = setmetatable({}, { end, }) ---- Sets the runtime query {query_name} for {lang} +--- Sets the runtime query named {query_name} for {lang} --- --- This allows users to override any runtime files and/or configuration --- set by plugins. --- ----@param lang string: The language to use for the query ----@param query_name string: The name of the query (i.e. "highlights") ----@param text string: The query text (unparsed). +---@param lang string Language to use for the query +---@param query_name string Name of the query (e.g., 'highlights') +---@param text string Query text (unparsed). function M.set_query(lang, query_name, text) explicit_queries[lang][query_name] = M.parse_query(lang, text) end --- Returns the runtime query {query_name} for {lang}. --- ----@param lang The language to use for the query ----@param query_name The name of the query (i.e. "highlights") +---@param lang string Language to use for the query +---@param query_name string Name of the query (e.g. 'highlights') --- ----@return The corresponding query, parsed. +---@return Query Parsed query function M.get_query(lang, query_name) if explicit_queries[lang][query_name] then return explicit_queries[lang][query_name] @@ -182,10 +204,10 @@ end) --- -` info.captures` also points to `captures`. --- - `info.patterns` contains information about predicates. --- ----@param lang string The language ----@param query string A string containing the query (s-expr syntax) +---@param lang string Language to use for the query +---@param query string Query in s-expr syntax --- ----@returns The query +---@return Query Parsed query function M.parse_query(lang, query) language.require_language(lang) local cached = query_cache[lang][query] @@ -203,10 +225,11 @@ end --- Gets the text corresponding to a given node --- ----@param node table The node ----@param source table The buffer or string from which the node is extracted ----@param opts table Optional parameters. ---- - concat: (boolean default true) Concatenate result in a string +---@param node userdata |tsnode| +---@param source (number|string) Buffer or string from which the {node} is extracted +---@param opts (table|nil) Optional parameters. +--- - concat: (boolean) Concatenate result in a string (default true) +---@return (string[]|string) function M.get_node_text(node, source, opts) opts = opts or {} local concat = vim.F.if_nil(opts.concat, true) @@ -394,9 +417,8 @@ local directive_handlers = { --- Adds a new predicate to be used in queries --- ----@param name the name of the predicate, without leading # ----@param handler the handler function to be used ---- signature will be (match, pattern, bufnr, predicate) +---@param name string Name of the predicate, without leading # +---@param handler function(match:string, pattern:string, bufnr:number, predicate:function) function M.add_predicate(name, handler, force) if predicate_handlers[name] and not force then error(string.format('Overriding %s', name)) @@ -412,9 +434,8 @@ end --- can set node level data by using the capture id on the --- metadata table `metadata[capture_id].key = value` --- ----@param name the name of the directive, without leading # ----@param handler the handler function to be used ---- signature will be (match, pattern, bufnr, predicate, metadata) +---@param name string Name of the directive, without leading # +---@param handler function(match:string, pattern:string, bufnr:number, predicate:function, metadata:table) function M.add_directive(name, handler, force) if directive_handlers[name] and not force then error(string.format('Overriding %s', name)) @@ -424,12 +445,13 @@ function M.add_directive(name, handler, force) end --- Lists the currently available directives to use in queries. ----@return The list of supported directives. +---@return string[] List of supported directives. function M.list_directives() return vim.tbl_keys(directive_handlers) end ----@return The list of supported predicates. +--- Lists the currently available predicates to use in queries. +---@return string[] List of supported predicates. function M.list_predicates() return vim.tbl_keys(predicate_handlers) end @@ -516,17 +538,16 @@ end --- Iterate over all captures from all matches inside {node} --- ---- {source} is needed if the query contains predicates, then the caller +--- {source} is needed if the query contains predicates; then the caller --- must ensure to use a freshly parsed tree consistent with the current --- text of the buffer (if relevant). {start_row} and {end_row} can be used to limit --- matches inside a row range (this is typically used with root node ---- as the node, i e to get syntax highlight matches in the current ---- viewport). When omitted the start and end row values are used from the given node. +--- as the {node}, i.e., to get syntax highlight matches in the current +--- viewport). When omitted, the {start} and {end} row values are used from the given node. --- ---- The iterator returns three values, a numeric id identifying the capture, +--- The iterator returns three values: a numeric id identifying the capture, --- the captured node, and metadata from any directives processing the match. --- The following example shows how to get captures by name: ---- --- <pre> --- for id, node, metadata in query:iter_captures(tree:root(), bufnr, first, last) do --- local name = query.captures[id] -- name of the capture in the query @@ -537,13 +558,14 @@ end --- end --- </pre> --- ----@param node The node under which the search will occur ----@param source The source buffer or string to extract text from ----@param start The starting line of the search ----@param stop The stopping line of the search (end-exclusive) +---@param node userdata |tsnode| under which the search will occur +---@param source (number|string) Source buffer or string to extract text from +---@param start number Starting line for the search +---@param stop number Stopping line for the search (end-exclusive) --- ----@returns The matching capture id ----@returns The captured node +---@return number capture Matching capture id +---@return table capture_node Capture for {node} +---@return table metadata for the {capture} function Query:iter_captures(node, source, start, stop) if type(source) == 'number' and source == 0 then source = vim.api.nvim_get_current_buf() @@ -573,14 +595,13 @@ end --- Iterates the matches of self on a given range. --- ---- Iterate over all matches within a node. The arguments are the same as +--- Iterate over all matches within a {node}. The arguments are the same as --- for |query:iter_captures()| but the iterated values are different: --- an (1-based) index of the pattern in the query, a table mapping --- capture indices to nodes, and metadata from any directives processing the match. ---- If the query has more than one pattern the capture table might be sparse, +--- If the query has more than one pattern, the capture table might be sparse --- and e.g. `pairs()` method should be used over `ipairs`. ---- Here an example iterating over all captures in every match: ---- +--- Here is an example iterating over all captures in every match: --- <pre> --- for pattern, match, metadata in cquery:iter_matches(tree:root(), bufnr, first, last) do --- for id, node in pairs(match) do @@ -594,13 +615,14 @@ end --- end --- </pre> --- ----@param node The node under which the search will occur ----@param source The source buffer or string to search ----@param start The starting line of the search ----@param stop The stopping line of the search (end-exclusive) +---@param node userdata |tsnode| under which the search will occur +---@param source (number|string) Source buffer or string to search +---@param start number Starting line for the search +---@param stop number Stopping line for the search (end-exclusive) --- ----@returns The matching pattern id ----@returns The matching match +---@return number pattern id +---@return table match +---@return table metadata function Query:iter_matches(node, source, start, stop) if type(source) == 'number' and source == 0 then source = vim.api.nvim_get_current_buf() diff --git a/runtime/optwin.vim b/runtime/optwin.vim index 02cf573ea3..9e2a616f80 100644 --- a/runtime/optwin.vim +++ b/runtime/optwin.vim @@ -1,7 +1,7 @@ " These commands create the option window. " " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last Change: 2022 Apr 07 +" Last Change: 2022 Sep 11 " If there already is an option window, jump to that one. let buf = bufnr('option-window') diff --git a/runtime/queries/vim/highlights.scm b/runtime/queries/vim/highlights.scm index 1bbaebef01..3d1729b2cd 100644 --- a/runtime/queries/vim/highlights.scm +++ b/runtime/queries/vim/highlights.scm @@ -40,7 +40,7 @@ (parameters (identifier) @parameter) (default_parameter (identifier) @parameter) -[ (bang) (spread) (at) ] @punctuation.special +[ (bang) (spread) ] @punctuation.special [ (no_option) (inv_option) (default_option) (option_name) ] @variable.builtin [ @@ -92,6 +92,12 @@ "topleft" "botright" (unknown_command_name) + "edit" + "enew" + "find" + "ex" + "visual" + "view" ] @keyword (map_statement cmd: _ @keyword) (command_name) @function.macro @@ -125,11 +131,6 @@ "<unique>" ] @constant.builtin -(hl_attribute - key: _ @property - val: _ @constant) - -(hl_group) @variable (augroup_name) @namespace (au_event) @constant @@ -137,6 +138,12 @@ ;; Highlight command +(hl_attribute + key: _ @property + val: _ @constant) + +(hl_group) @type + (highlight_statement [ "default" "link" @@ -145,12 +152,19 @@ ;; Command command +(command) @string + (command_attribute name: _ @property val: (behavior name: _ @constant val: (identifier)? @function)?) +;; Edit command +(plus_plus_opt + val: _? @constant) @property +(plus_cmd "+" @property) @property + ;; Runtime command (runtime_statement (where) @keyword.operator) @@ -161,12 +175,10 @@ ;; Literals -(string_literal) @string -(string_literal) @spell +(string_literal) @string @spell (integer_literal) @number (float_literal) @float -(comment) @comment -(comment) @spell +(comment) @comment @spell (pattern) @string.special (pattern_multi) @string.regex (filename) @string diff --git a/runtime/syntax/gdscript.vim b/runtime/syntax/gdscript.vim index e9295a411d..48af153513 100644 --- a/runtime/syntax/gdscript.vim +++ b/runtime/syntax/gdscript.vim @@ -18,8 +18,6 @@ syn keyword gdscriptRepeat for while break continue syn keyword gdscriptOperator is as not and or in -syn match gdscriptClass "\v<\u\w+>" -syn match gdscriptConstant "\<[_A-Z]\+[0-9_A-Z]*\>" syn match gdscriptBlockStart ":\s*$" syn keyword gdscriptKeyword null self owner parent tool @@ -33,14 +31,16 @@ syn keyword gdscriptStatement onready syn keyword gdscriptStatement class_name extends syn keyword gdscriptType void bool int float String contained +syn match gdscriptType ":\s*\zs\h\w*" contained +syn match gdscriptType "->\s*\zs\h\w*" contained syn keyword gdscriptStatement var nextgroup=gdscriptTypeDecl skipwhite syn keyword gdscriptStatement const nextgroup=gdscriptTypeDecl skipwhite -syn match gdscriptTypeDecl "\h\w*\s*:\s*\h\w*" contains=gdscriptOperator,gdscriptType,gdscriptClass contained skipwhite -syn match gdscriptTypeDecl "->\s*\h\w*" contains=gdscriptOperator,gdscriptType,gdscriptClass skipwhite +syn match gdscriptTypeDecl "\h\w*\s*:\s*\h\w*" contains=gdscriptType contained skipwhite +syn match gdscriptTypeDecl "->\s*\h\w*" contains=gdscriptType skipwhite syn keyword gdscriptStatement export nextgroup=gdscriptExportTypeDecl skipwhite -syn match gdscriptExportTypeDecl "(.\{-}[,)]" contains=gdscriptOperator,gdscriptType,gdscriptClass contained skipwhite +syn match gdscriptExportTypeDecl "(.\{-}[,)]" contains=gdscriptOperator,gdscriptType contained skipwhite syn keyword gdscriptStatement setget nextgroup=gdscriptSetGet,gdscriptSetGetSeparator skipwhite syn match gdscriptSetGet "\h\w*" nextgroup=gdscriptSetGetSeparator display contained skipwhite @@ -84,8 +84,6 @@ hi def link gdscriptOperator Operator hi def link gdscriptRepeat Repeat hi def link gdscriptSetGet Function hi def link gdscriptFunctionName Function -hi def link gdscriptClass Type -hi def link gdscriptConstant Constant hi def link gdscriptBuiltinStruct Typedef hi def link gdscriptComment Comment hi def link gdscriptString String diff --git a/runtime/syntax/gitattributes.vim b/runtime/syntax/gitattributes.vim new file mode 100644 index 0000000000..b6d997f45d --- /dev/null +++ b/runtime/syntax/gitattributes.vim @@ -0,0 +1,63 @@ +" Vim syntax file +" Language: git attributes +" Maintainer: ObserverOfTime <chronobserver@disroot.org> +" Filenames: .gitattributes, *.git/info/attributes +" Last Change: 2022 Sep 09 + +if exists('b:current_syntax') + finish +endif + +let s:cpo_save = &cpoptions +set cpoptions&vim + +" Comment +syn keyword gitattributesTodo contained TODO FIXME XXX +syn match gitattributesComment /^\s*#.*/ contains=gitattributesTodo + +" Pattern +syn match gitattributesPattern /^\s*#\@!\(".\+"\|\S\+\)/ skipwhite + \ nextgroup=gitattributesAttrPrefixed,gitattributesAttrAssigned skipwhite + \ contains=gitattributesGlob,gitattributesRange,gitattributesSeparator +syn match gitattributesGlob /\\\@1<![?*]/ contained +syn match gitattributesRange /\\\@1<!\[.\{-}\]/ contained +syn match gitattributesSeparator '/' contained + +" Attribute +syn match gitattributesAttrPrefixed /[!-]\?[A-Za-z0-9_.][-A-Za-z0-9_.]*/ + \ transparent contained skipwhite + \ nextgroup=gitattributesAttrPrefixed,gitattributesAttrAssigned + \ contains=gitattributesPrefix,gitattributesName +syn match gitattributesAttrAssigned /[A-Za-z0-9_.][-A-Za-z0-9_.]*=\S\+/ + \ transparent contained skipwhite + \ nextgroup=gitattributesAttrPrefixed,gitattributesAttrAssigned + \ contains=gitattributesName,gitattributesAssign,gitattributesBoolean,gitattributesString +syn match gitattributesName /[A-Za-z0-9_.][-A-Za-z0-9_.]*/ + \ contained nextgroup=gitattributesAssign +syn match gitattributesPrefix /[!-]/ contained + \ nextgroup=gitAttributesName +syn match gitattributesAssign '=' contained + \ nextgroup=gitattributesBoolean,gitattributesString +syn match gitattributesString /=\@1<=\S\+/ contained +syn keyword gitattributesBoolean true false contained + +" Macro +syn match gitattributesMacro /^\s*\[attr\]\s*\S\+/ + \ nextgroup=gitattributesAttribute skipwhite + +hi def link gitattributesAssign Operator +hi def link gitattributesBoolean Boolean +hi def link gitattributesComment Comment +hi def link gitattributesGlob Special +hi def link gitattributesMacro Define +hi def link gitattributesName Identifier +hi def link gitattributesPrefix SpecialChar +hi def link gitattributesRange Special +hi def link gitattributesSeparator Delimiter +hi def link gitattributesString String +hi def link gitattributesTodo Todo + +let b:current_syntax = 'gitattributes' + +let &cpoptions = s:cpo_save +unlet s:cpo_save diff --git a/runtime/syntax/gitignore.vim b/runtime/syntax/gitignore.vim new file mode 100644 index 0000000000..8e6d098acd --- /dev/null +++ b/runtime/syntax/gitignore.vim @@ -0,0 +1,29 @@ +" Vim syntax file +" Language: git ignore +" Maintainer: ObserverOfTime <chronobserver@disroot.org> +" Filenames: .gitignore, *.git/info/exclude +" Last Change: 2022 Sep 10 + +if exists('b:current_syntax') + finish +endif + +" Comment +syn keyword gitignoreTodo contained TODO FIXME XXX +syn match gitignoreComment /^#.*/ contains=gitignoreTodo + +" Pattern +syn match gitignorePattern /^#\@!.*$/ contains=gitignoreNegation,gitignoreGlob,gitignoreRange,gitignoreSeparator +syn match gitignoreNegation /^!/ contained +syn match gitignoreGlob /\\\@1<![?*]/ contained +syn match gitignoreRange /\\\@1<!\[.\{-}\]/ contained +syn match gitignoreSeparator '/' contained + +hi def link gitignoreComment Comment +hi def link gitignoreGlob Special +hi def link gitignoreNegation SpecialChar +hi def link gitignoreRange Special +hi def link gitignoreSeparator Delimiter +hi def link gitignoreTodo Todo + +let b:current_syntax = 'gitignore' diff --git a/runtime/syntax/lua.vim b/runtime/syntax/lua.vim index b398e2e5c6..9c5a490582 100644 --- a/runtime/syntax/lua.vim +++ b/runtime/syntax/lua.vim @@ -1,11 +1,12 @@ " Vim syntax file -" Language: Lua 4.0, Lua 5.0, Lua 5.1 and Lua 5.2 -" Maintainer: Marcus Aurelius Farias <masserahguard-lua 'at' yahoo com> -" First Author: Carlos Augusto Teixeira Mendes <cmendes 'at' inf puc-rio br> -" Last Change: 2022 Mar 31 -" Options: lua_version = 4 or 5 -" lua_subversion = 0 (4.0, 5.0) or 1 (5.1) or 2 (5.2) -" default 5.2 +" Language: Lua 4.0, Lua 5.0, Lua 5.1, Lua 5.2 and Lua 5.3 +" Maintainer: Marcus Aurelius Farias <masserahguard-lua 'at' yahoo com> +" First Author: Carlos Augusto Teixeira Mendes <cmendes 'at' inf puc-rio br> +" Last Change: 2022 Sep 07 +" Options: lua_version = 4 or 5 +" lua_subversion = 0 (for 4.0 or 5.0) +" or 1, 2, 3 (for 5.1, 5.2 or 5.3) +" the default is 5.3 " quit when a syntax file was already loaded if exists("b:current_syntax") @@ -16,70 +17,78 @@ let s:cpo_save = &cpo set cpo&vim if !exists("lua_version") - " Default is lua 5.2 + " Default is lua 5.3 let lua_version = 5 - let lua_subversion = 2 + let lua_subversion = 3 elseif !exists("lua_subversion") - " lua_version exists, but lua_subversion doesn't. So, set it to 0 + " lua_version exists, but lua_subversion doesn't. In this case set it to 0 let lua_subversion = 0 endif syn case match " syncing method -syn sync minlines=100 +syn sync minlines=1000 -" Comments -syn keyword luaTodo contained TODO FIXME XXX -syn match luaComment "--.*$" contains=luaTodo,@Spell -if lua_version == 5 && lua_subversion == 0 - syn region luaComment matchgroup=luaComment start="--\[\[" end="\]\]" contains=luaTodo,luaInnerComment,@Spell - syn region luaInnerComment contained transparent start="\[\[" end="\]\]" -elseif lua_version > 5 || (lua_version == 5 && lua_subversion >= 1) - " Comments in Lua 5.1: --[[ ... ]], [=[ ... ]=], [===[ ... ]===], etc. - syn region luaComment matchgroup=luaComment start="--\[\z(=*\)\[" end="\]\z1\]" contains=luaTodo,@Spell +if lua_version >= 5 + syn keyword luaMetaMethod __add __sub __mul __div __pow __unm __concat + syn keyword luaMetaMethod __eq __lt __le + syn keyword luaMetaMethod __index __newindex __call + syn keyword luaMetaMethod __metatable __mode __gc __tostring endif -" First line may start with #! -syn match luaComment "\%^#!.*" +if lua_version > 5 || (lua_version == 5 && lua_subversion >= 1) + syn keyword luaMetaMethod __mod __len +endif + +if lua_version > 5 || (lua_version == 5 && lua_subversion >= 2) + syn keyword luaMetaMethod __pairs +endif + +if lua_version > 5 || (lua_version == 5 && lua_subversion >= 3) + syn keyword luaMetaMethod __idiv __name + syn keyword luaMetaMethod __band __bor __bxor __bnot __shl __shr +endif + +if lua_version > 5 || (lua_version == 5 && lua_subversion >= 4) + syn keyword luaMetaMethod __close +endif " catch errors caused by wrong parenthesis and wrong curly brackets or " keywords placed outside their respective blocks -syn region luaParen transparent start='(' end=')' contains=ALLBUT,luaParenError,luaTodo,luaSpecial,luaIfThen,luaElseifThen,luaElse,luaThenEnd,luaBlock,luaLoopBlock,luaIn,luaStatement -syn region luaTableBlock transparent matchgroup=luaTable start="{" end="}" contains=ALLBUT,luaBraceError,luaTodo,luaSpecial,luaIfThen,luaElseifThen,luaElse,luaThenEnd,luaBlock,luaLoopBlock,luaIn,luaStatement +syn region luaParen transparent start='(' end=')' contains=TOP,luaParenError syn match luaParenError ")" -syn match luaBraceError "}" +syn match luaError "}" syn match luaError "\<\%(end\|else\|elseif\|then\|until\|in\)\>" -" function ... end -syn region luaFunctionBlock transparent matchgroup=luaFunction start="\<function\>" end="\<end\>" contains=ALLBUT,luaTodo,luaSpecial,luaElseifThen,luaElse,luaThenEnd,luaIn +" Function declaration +syn region luaFunctionBlock transparent matchgroup=luaFunction start="\<function\>" end="\<end\>" contains=TOP -" if ... then -syn region luaIfThen transparent matchgroup=luaCond start="\<if\>" end="\<then\>"me=e-4 contains=ALLBUT,luaTodo,luaSpecial,luaElseifThen,luaElse,luaIn nextgroup=luaThenEnd skipwhite skipempty +" else +syn keyword luaCondElse matchgroup=luaCond contained containedin=luaCondEnd else " then ... end -syn region luaThenEnd contained transparent matchgroup=luaCond start="\<then\>" end="\<end\>" contains=ALLBUT,luaTodo,luaSpecial,luaThenEnd,luaIn +syn region luaCondEnd contained transparent matchgroup=luaCond start="\<then\>" end="\<end\>" contains=TOP " elseif ... then -syn region luaElseifThen contained transparent matchgroup=luaCond start="\<elseif\>" end="\<then\>" contains=ALLBUT,luaTodo,luaSpecial,luaElseifThen,luaElse,luaThenEnd,luaIn +syn region luaCondElseif contained containedin=luaCondEnd transparent matchgroup=luaCond start="\<elseif\>" end="\<then\>" contains=TOP -" else -syn keyword luaElse contained else +" if ... then +syn region luaCondStart transparent matchgroup=luaCond start="\<if\>" end="\<then\>"me=e-4 contains=TOP nextgroup=luaCondEnd skipwhite skipempty " do ... end -syn region luaBlock transparent matchgroup=luaStatement start="\<do\>" end="\<end\>" contains=ALLBUT,luaTodo,luaSpecial,luaElseifThen,luaElse,luaThenEnd,luaIn - +syn region luaBlock transparent matchgroup=luaStatement start="\<do\>" end="\<end\>" contains=TOP " repeat ... until -syn region luaLoopBlock transparent matchgroup=luaRepeat start="\<repeat\>" end="\<until\>" contains=ALLBUT,luaTodo,luaSpecial,luaElseifThen,luaElse,luaThenEnd,luaIn +syn region luaRepeatBlock transparent matchgroup=luaRepeat start="\<repeat\>" end="\<until\>" contains=TOP " while ... do -syn region luaLoopBlock transparent matchgroup=luaRepeat start="\<while\>" end="\<do\>"me=e-2 contains=ALLBUT,luaTodo,luaSpecial,luaIfThen,luaElseifThen,luaElse,luaThenEnd,luaIn nextgroup=luaBlock skipwhite skipempty +syn region luaWhile transparent matchgroup=luaRepeat start="\<while\>" end="\<do\>"me=e-2 contains=TOP nextgroup=luaBlock skipwhite skipempty " for ... do and for ... in ... do -syn region luaLoopBlock transparent matchgroup=luaRepeat start="\<for\>" end="\<do\>"me=e-2 contains=ALLBUT,luaTodo,luaSpecial,luaIfThen,luaElseifThen,luaElse,luaThenEnd nextgroup=luaBlock skipwhite skipempty +syn region luaFor transparent matchgroup=luaRepeat start="\<for\>" end="\<do\>"me=e-2 contains=TOP nextgroup=luaBlock skipwhite skipempty -syn keyword luaIn contained in +syn keyword luaFor contained containedin=luaFor in " other keywords syn keyword luaStatement return local break @@ -87,35 +96,59 @@ if lua_version > 5 || (lua_version == 5 && lua_subversion >= 2) syn keyword luaStatement goto syn match luaLabel "::\I\i*::" endif + +" operators syn keyword luaOperator and or not + +if (lua_version == 5 && lua_subversion >= 3) || lua_version > 5 + syn match luaSymbolOperator "[#<>=~^&|*/%+-]\|\.\{2,3}" +elseif lua_version == 5 && (lua_subversion == 1 || lua_subversion == 2) + syn match luaSymbolOperator "[#<>=~^*/%+-]\|\.\{2,3}" +else + syn match luaSymbolOperator "[<>=~^*/+-]\|\.\{2,3}" +endif + +" comments +syn keyword luaTodo contained TODO FIXME XXX +syn match luaComment "--.*$" contains=luaTodo,@Spell +if lua_version == 5 && lua_subversion == 0 + syn region luaComment matchgroup=luaCommentDelimiter start="--\[\[" end="\]\]" contains=luaTodo,luaInnerComment,@Spell + syn region luaInnerComment contained transparent start="\[\[" end="\]\]" +elseif lua_version > 5 || (lua_version == 5 && lua_subversion >= 1) + " Comments in Lua 5.1: --[[ ... ]], [=[ ... ]=], [===[ ... ]===], etc. + syn region luaComment matchgroup=luaCommentDelimiter start="--\[\z(=*\)\[" end="\]\z1\]" contains=luaTodo,@Spell +endif + +" first line may start with #! +syn match luaComment "\%^#!.*" + syn keyword luaConstant nil if lua_version > 4 syn keyword luaConstant true false endif -" Strings -if lua_version < 5 - syn match luaSpecial contained "\\[\\abfnrtv\'\"]\|\\[[:digit:]]\{,3}" -elseif lua_version == 5 +" strings +syn match luaSpecial contained #\\[\\abfnrtv'"[\]]\|\\[[:digit:]]\{,3}# +if lua_version == 5 if lua_subversion == 0 - syn match luaSpecial contained #\\[\\abfnrtv'"[\]]\|\\[[:digit:]]\{,3}# - syn region luaString2 matchgroup=luaString start=+\[\[+ end=+\]\]+ contains=luaString2,@Spell + syn region luaString2 matchgroup=luaStringDelimiter start=+\[\[+ end=+\]\]+ contains=luaString2,@Spell else - if lua_subversion == 1 - syn match luaSpecial contained #\\[\\abfnrtv'"]\|\\[[:digit:]]\{,3}# - else " Lua 5.2 - syn match luaSpecial contained #\\[\\abfnrtvz'"]\|\\x[[:xdigit:]]\{2}\|\\[[:digit:]]\{,3}# + if lua_subversion >= 2 + syn match luaSpecial contained #\\z\|\\x[[:xdigit:]]\{2}# + endif + if lua_subversion >= 3 + syn match luaSpecial contained #\\u{[[:xdigit:]]\+}# endif - syn region luaString2 matchgroup=luaString start="\[\z(=*\)\[" end="\]\z1\]" contains=@Spell + syn region luaString2 matchgroup=luaStringDelimiter start="\[\z(=*\)\[" end="\]\z1\]" contains=@Spell endif endif -syn region luaString start=+'+ end=+'+ skip=+\\\\\|\\'+ contains=luaSpecial,@Spell -syn region luaString start=+"+ end=+"+ skip=+\\\\\|\\"+ contains=luaSpecial,@Spell +syn region luaString matchgroup=luaStringDelimiter start=+'+ end=+'+ skip=+\\\\\|\\'+ contains=luaSpecial,@Spell +syn region luaString matchgroup=luaStringDelimiter start=+"+ end=+"+ skip=+\\\\\|\\"+ contains=luaSpecial,@Spell " integer number syn match luaNumber "\<\d\+\>" " floating point number, with dot, optional exponent -syn match luaNumber "\<\d\+\.\d*\%([eE][-+]\=\d\+\)\=\>" +syn match luaNumber "\<\d\+\.\d*\%([eE][-+]\=\d\+\)\=" " floating point number, starting with a dot, optional exponent syn match luaNumber "\.\d\+\%([eE][-+]\=\d\+\)\=\>" " floating point number, without dot, with exponent @@ -130,8 +163,15 @@ if lua_version >= 5 endif endif +" tables +syn region luaTableBlock transparent matchgroup=luaTable start="{" end="}" contains=TOP,luaStatement + +" methods +syntax match luaFunc ":\@<=\k\+" + +" built-in functions syn keyword luaFunc assert collectgarbage dofile error next -syn keyword luaFunc print rawget rawset tonumber tostring type _VERSION +syn keyword luaFunc print rawget rawset self tonumber tostring type _VERSION if lua_version == 4 syn keyword luaFunc _ALERT _ERRORMESSAGE gcinfo @@ -168,30 +208,26 @@ elseif lua_version == 5 syn match luaFunc /\<package\.loaded\>/ syn match luaFunc /\<package\.loadlib\>/ syn match luaFunc /\<package\.path\>/ + syn match luaFunc /\<package\.preload\>/ if lua_subversion == 1 syn keyword luaFunc getfenv setfenv syn keyword luaFunc loadstring module unpack syn match luaFunc /\<package\.loaders\>/ - syn match luaFunc /\<package\.preload\>/ syn match luaFunc /\<package\.seeall\>/ - elseif lua_subversion == 2 + elseif lua_subversion >= 2 syn keyword luaFunc _ENV rawlen syn match luaFunc /\<package\.config\>/ syn match luaFunc /\<package\.preload\>/ syn match luaFunc /\<package\.searchers\>/ syn match luaFunc /\<package\.searchpath\>/ - syn match luaFunc /\<bit32\.arshift\>/ - syn match luaFunc /\<bit32\.band\>/ - syn match luaFunc /\<bit32\.bnot\>/ - syn match luaFunc /\<bit32\.bor\>/ - syn match luaFunc /\<bit32\.btest\>/ - syn match luaFunc /\<bit32\.bxor\>/ - syn match luaFunc /\<bit32\.extract\>/ - syn match luaFunc /\<bit32\.lrotate\>/ - syn match luaFunc /\<bit32\.lshift\>/ - syn match luaFunc /\<bit32\.replace\>/ - syn match luaFunc /\<bit32\.rrotate\>/ - syn match luaFunc /\<bit32\.rshift\>/ + endif + + if lua_subversion >= 3 + syn match luaFunc /\<coroutine\.isyieldable\>/ + endif + if lua_subversion >= 4 + syn keyword luaFunc warn + syn match luaFunc /\<coroutine\.close\>/ endif syn match luaFunc /\<coroutine\.running\>/ endif @@ -200,6 +236,7 @@ elseif lua_version == 5 syn match luaFunc /\<coroutine\.status\>/ syn match luaFunc /\<coroutine\.wrap\>/ syn match luaFunc /\<coroutine\.yield\>/ + syn match luaFunc /\<string\.byte\>/ syn match luaFunc /\<string\.char\>/ syn match luaFunc /\<string\.dump\>/ @@ -218,6 +255,18 @@ elseif lua_version == 5 syn match luaFunc /\<string\.match\>/ syn match luaFunc /\<string\.reverse\>/ endif + if lua_subversion >= 3 + syn match luaFunc /\<string\.pack\>/ + syn match luaFunc /\<string\.packsize\>/ + syn match luaFunc /\<string\.unpack\>/ + syn match luaFunc /\<utf8\.char\>/ + syn match luaFunc /\<utf8\.charpattern\>/ + syn match luaFunc /\<utf8\.codes\>/ + syn match luaFunc /\<utf8\.codepoint\>/ + syn match luaFunc /\<utf8\.len\>/ + syn match luaFunc /\<utf8\.offset\>/ + endif + if lua_subversion == 0 syn match luaFunc /\<table\.getn\>/ syn match luaFunc /\<table\.setn\>/ @@ -225,19 +274,40 @@ elseif lua_version == 5 syn match luaFunc /\<table\.foreachi\>/ elseif lua_subversion == 1 syn match luaFunc /\<table\.maxn\>/ - elseif lua_subversion == 2 + elseif lua_subversion >= 2 syn match luaFunc /\<table\.pack\>/ syn match luaFunc /\<table\.unpack\>/ + if lua_subversion >= 3 + syn match luaFunc /\<table\.move\>/ + endif endif syn match luaFunc /\<table\.concat\>/ - syn match luaFunc /\<table\.sort\>/ syn match luaFunc /\<table\.insert\>/ + syn match luaFunc /\<table\.sort\>/ syn match luaFunc /\<table\.remove\>/ + + if lua_subversion == 2 + syn match luaFunc /\<bit32\.arshift\>/ + syn match luaFunc /\<bit32\.band\>/ + syn match luaFunc /\<bit32\.bnot\>/ + syn match luaFunc /\<bit32\.bor\>/ + syn match luaFunc /\<bit32\.btest\>/ + syn match luaFunc /\<bit32\.bxor\>/ + syn match luaFunc /\<bit32\.extract\>/ + syn match luaFunc /\<bit32\.lrotate\>/ + syn match luaFunc /\<bit32\.lshift\>/ + syn match luaFunc /\<bit32\.replace\>/ + syn match luaFunc /\<bit32\.rrotate\>/ + syn match luaFunc /\<bit32\.rshift\>/ + endif + syn match luaFunc /\<math\.abs\>/ syn match luaFunc /\<math\.acos\>/ syn match luaFunc /\<math\.asin\>/ syn match luaFunc /\<math\.atan\>/ - syn match luaFunc /\<math\.atan2\>/ + if lua_subversion < 3 + syn match luaFunc /\<math\.atan2\>/ + endif syn match luaFunc /\<math\.ceil\>/ syn match luaFunc /\<math\.sin\>/ syn match luaFunc /\<math\.cos\>/ @@ -251,25 +321,36 @@ elseif lua_version == 5 if lua_subversion == 0 syn match luaFunc /\<math\.mod\>/ syn match luaFunc /\<math\.log10\>/ - else - if lua_subversion == 1 - syn match luaFunc /\<math\.log10\>/ - endif + elseif lua_subversion == 1 + syn match luaFunc /\<math\.log10\>/ + endif + if lua_subversion >= 1 syn match luaFunc /\<math\.huge\>/ syn match luaFunc /\<math\.fmod\>/ syn match luaFunc /\<math\.modf\>/ - syn match luaFunc /\<math\.cosh\>/ - syn match luaFunc /\<math\.sinh\>/ - syn match luaFunc /\<math\.tanh\>/ + if lua_subversion == 1 || lua_subversion == 2 + syn match luaFunc /\<math\.cosh\>/ + syn match luaFunc /\<math\.sinh\>/ + syn match luaFunc /\<math\.tanh\>/ + endif endif - syn match luaFunc /\<math\.pow\>/ syn match luaFunc /\<math\.rad\>/ syn match luaFunc /\<math\.sqrt\>/ - syn match luaFunc /\<math\.frexp\>/ - syn match luaFunc /\<math\.ldexp\>/ + if lua_subversion < 3 + syn match luaFunc /\<math\.pow\>/ + syn match luaFunc /\<math\.frexp\>/ + syn match luaFunc /\<math\.ldexp\>/ + else + syn match luaFunc /\<math\.maxinteger\>/ + syn match luaFunc /\<math\.mininteger\>/ + syn match luaFunc /\<math\.tointeger\>/ + syn match luaFunc /\<math\.type\>/ + syn match luaFunc /\<math\.ult\>/ + endif syn match luaFunc /\<math\.random\>/ syn match luaFunc /\<math\.randomseed\>/ syn match luaFunc /\<math\.pi\>/ + syn match luaFunc /\<io\.close\>/ syn match luaFunc /\<io\.flush\>/ syn match luaFunc /\<io\.input\>/ @@ -284,6 +365,7 @@ elseif lua_version == 5 syn match luaFunc /\<io\.tmpfile\>/ syn match luaFunc /\<io\.type\>/ syn match luaFunc /\<io\.write\>/ + syn match luaFunc /\<os\.clock\>/ syn match luaFunc /\<os\.date\>/ syn match luaFunc /\<os\.difftime\>/ @@ -295,6 +377,7 @@ elseif lua_version == 5 syn match luaFunc /\<os\.setlocale\>/ syn match luaFunc /\<os\.time\>/ syn match luaFunc /\<os\.tmpname\>/ + syn match luaFunc /\<debug\.debug\>/ syn match luaFunc /\<debug\.gethook\>/ syn match luaFunc /\<debug\.getinfo\>/ @@ -307,53 +390,49 @@ elseif lua_version == 5 if lua_subversion == 1 syn match luaFunc /\<debug\.getfenv\>/ syn match luaFunc /\<debug\.setfenv\>/ + endif + if lua_subversion >= 1 syn match luaFunc /\<debug\.getmetatable\>/ syn match luaFunc /\<debug\.setmetatable\>/ syn match luaFunc /\<debug\.getregistry\>/ - elseif lua_subversion == 2 - syn match luaFunc /\<debug\.getmetatable\>/ - syn match luaFunc /\<debug\.setmetatable\>/ - syn match luaFunc /\<debug\.getregistry\>/ - syn match luaFunc /\<debug\.getuservalue\>/ - syn match luaFunc /\<debug\.setuservalue\>/ - syn match luaFunc /\<debug\.upvalueid\>/ - syn match luaFunc /\<debug\.upvaluejoin\>/ - endif - if lua_subversion >= 3 - "https://www.lua.org/manual/5.3/manual.html#6.5 - syn match luaFunc /\<utf8\.char\>/ - syn match luaFunc /\<utf8\.charpattern\>/ - syn match luaFunc /\<utf8\.codes\>/ - syn match luaFunc /\<utf8\.codepoint\>/ - syn match luaFunc /\<utf8\.len\>/ - syn match luaFunc /\<utf8\.offset\>/ + if lua_subversion >= 2 + syn match luaFunc /\<debug\.getuservalue\>/ + syn match luaFunc /\<debug\.setuservalue\>/ + syn match luaFunc /\<debug\.upvalueid\>/ + syn match luaFunc /\<debug\.upvaluejoin\>/ + endif + if lua_subversion >= 4 + syn match luaFunc /\<debug.setcstacklimit\>/ + endif endif endif " Define the default highlighting. " Only when an item doesn't have highlighting yet -hi def link luaStatement Statement -hi def link luaRepeat Repeat -hi def link luaFor Repeat -hi def link luaString String -hi def link luaString2 String -hi def link luaNumber Number -hi def link luaOperator Operator -hi def link luaIn Operator -hi def link luaConstant Constant -hi def link luaCond Conditional -hi def link luaElse Conditional -hi def link luaFunction Function -hi def link luaComment Comment -hi def link luaTodo Todo -hi def link luaTable Structure -hi def link luaError Error -hi def link luaParenError Error -hi def link luaBraceError Error -hi def link luaSpecial SpecialChar -hi def link luaFunc Identifier -hi def link luaLabel Label +hi def link luaStatement Statement +hi def link luaRepeat Repeat +hi def link luaFor Repeat +hi def link luaString String +hi def link luaString2 String +hi def link luaStringDelimiter luaString +hi def link luaNumber Number +hi def link luaOperator Operator +hi def link luaSymbolOperator luaOperator +hi def link luaConstant Constant +hi def link luaCond Conditional +hi def link luaCondElse Conditional +hi def link luaFunction Function +hi def link luaMetaMethod Function +hi def link luaComment Comment +hi def link luaCommentDelimiter luaComment +hi def link luaTodo Todo +hi def link luaTable Structure +hi def link luaError Error +hi def link luaParenError Error +hi def link luaSpecial SpecialChar +hi def link luaFunc Identifier +hi def link luaLabel Label let b:current_syntax = "lua" diff --git a/runtime/syntax/lyrics.vim b/runtime/syntax/lyrics.vim new file mode 100644 index 0000000000..42a288b51b --- /dev/null +++ b/runtime/syntax/lyrics.vim @@ -0,0 +1,43 @@ +" Vim syntax file +" Language: LyRiCs +" Maintainer: ObserverOfTime <chronobserver@disroot.org> +" Filenames: *.lrc +" Last Change: 2022 Sep 18 + +if exists('b:current_syntax') + finish +endif + +let s:cpo_save = &cpoptions +set cpoptions&vim + +syn case ignore + +" Errors +syn match lrcError /^.\+$/ + +" ID tags +syn match lrcTag /^\s*\[\a\+:.\+\]\s*$/ contains=lrcTagName,lrcTagValue +syn match lrcTagName contained nextgroup=lrcTagValue + \ /\[\zs\(al\|ar\|au\|by\|encoding\|la\|id\|length\|offset\|re\|ti\|ve\)\ze:/ +syn match lrcTagValue /:\zs.\+\ze\]/ contained + +" Lyrics +syn match lrcLyricTime /^\s*\[\d\d:\d\d\.\d\d\]/ + \ contains=lrcNumber nextgroup=lrcLyricLine +syn match lrcLyricLine /.*$/ contained contains=lrcWordTime,@Spell +syn match lrcWordTime /<\d\d:\d\d\.\d\d>/ contained contains=lrcNumber,@NoSpell +syn match lrcNumber /[+-]\=\d\+/ contained + +hi def link lrcLyricTime Label +hi def link lrcNumber Number +hi def link lrcTag PreProc +hi def link lrcTagName Identifier +hi def link lrcTagValue String +hi def link lrcWordTime Special +hi def link lrcError Error + +let b:current_syntax = 'lyrics' + +let &cpoptions = s:cpo_save +unlet s:cpo_save diff --git a/runtime/syntax/srt.vim b/runtime/syntax/srt.vim new file mode 100644 index 0000000000..12fb264d8e --- /dev/null +++ b/runtime/syntax/srt.vim @@ -0,0 +1,62 @@ +" Vim syntax file +" Language: SubRip +" Maintainer: ObserverOfTime <chronobserver@disroot.org> +" Filenames: *.srt +" Last Change: 2022 Sep 12 + +if exists('b:current_syntax') + finish +endif + +syn spell toplevel + +syn cluster srtSpecial contains=srtBold,srtItalics,srtStrikethrough,srtUnderline,srtFont,srtTag,srtEscape + +" Number +syn match srtNumber /^\d\+$/ contains=@NoSpell + +" Range +syn match srtRange /\d\d:\d\d:\d\d[,.]\d\d\d --> \d\d:\d\d:\d\d[,.]\d\d\d/ skipwhite contains=srtArrow,srtTime nextgroup=srtCoordinates +syn match srtArrow /-->/ contained contains=@NoSpell +syn match srtTime /\d\d:\d\d:\d\d[,.]\d\d\d/ contained contains=@NoSpell +syn match srtCoordinates /X1:\d\+ X2:\d\+ Y1:\d\+ Y2:\d\+/ contained contains=@NoSpell + +" Bold +syn region srtBold matchgroup=srtFormat start=+<b>+ end=+</b>+ contains=@srtSpecial +syn region srtBold matchgroup=srtFormat start=+{b}+ end=+{/b}+ contains=@srtSpecial + +" Italics +syn region srtItalics matchgroup=srtFormat start=+<i>+ end=+</i>+ contains=@srtSpecial +syn region srtItalics matchgroup=srtFormat start=+{i}+ end=+{/i}+ contains=@srtSpecial + +" Strikethrough +syn region srtStrikethrough matchgroup=srtFormat start=+<s>+ end=+</s>+ contains=@srtSpecial +syn region srtStrikethrough matchgroup=srtFormat start=+{s}+ end=+{/s}+ contains=@srtSpecial + +" Underline +syn region srtUnderline matchgroup=srtFormat start=+<u>+ end=+</u>+ contains=@srtSpecial +syn region srtUnderline matchgroup=srtFormat start=+{u}+ end=+{/u}+ contains=@srtSpecial + +" Font +syn region srtFont matchgroup=srtFormat start=+<font[^>]\{-}>+ end=+</font>+ contains=@srtSpecial + +" ASS tags +syn match srtTag /{\\[^}]\{1,}}/ contains=@NoSpell + +" Special characters +syn match srtEscape /\\[nNh]/ contains=@NoSpell + +hi def link srtArrow Delimiter +hi def link srtCoordinates Label +hi def link srtEscape SpecialChar +hi def link srtFormat Special +hi def link srtNumber Number +hi def link srtTag PreProc +hi def link srtTime String + +hi srtBold cterm=bold gui=bold +hi srtItalics cterm=italic gui=italic +hi srtStrikethrough cterm=strikethrough gui=strikethrough +hi srtUnderline cterm=underline gui=underline + +let b:current_syntax = 'srt' diff --git a/runtime/syntax/vdf.vim b/runtime/syntax/vdf.vim new file mode 100644 index 0000000000..c690b706ea --- /dev/null +++ b/runtime/syntax/vdf.vim @@ -0,0 +1,54 @@ +" Vim syntax file +" Language: Valve Data Format +" Maintainer: ObserverOfTime <chronobserver@disroot.org> +" Filenames: *.vdf +" Last Change: 2022 Sep 15 + +if exists('b:current_syntax') + finish +endif + +let s:cpo_save = &cpoptions +set cpoptions&vim + +" Comment +syn keyword vdfTodo contained TODO FIXME XXX +syn match vdfComment +//.*+ contains=vdfTodo + +" Macro +syn match vdfMacro /^\s*#.*/ + +" Tag +syn region vdfTag start=/"/ skip=/\\"/ end=/"/ + \ nextgroup=vdfValue skipwhite oneline + +" Section +syn region vdfSection matchgroup=vdfBrace + \ start=/{/ end=/}/ transparent fold + \ contains=vdfTag,vdfSection,vdfComment,vdfConditional + +" Conditional +syn match vdfConditional /\[\$\w\{1,1021}\]/ nextgroup=vdfTag + +" Value +syn region vdfValue start=/"/ skip=/\\"/ end=/"/ + \ oneline contained contains=vdfVariable,vdfNumber,vdfEscape +syn region vdfVariable start=/%/ skip=/\\%/ end=/%/ oneline contained +syn match vdfEscape /\\[nt\\"]/ contained +syn match vdfNumber /"-\?\d\+"/ contained + +hi def link vdfBrace Delimiter +hi def link vdfComment Comment +hi def link vdfConditional Constant +hi def link vdfEscape SpecialChar +hi def link vdfMacro Macro +hi def link vdfNumber Number +hi def link vdfTag Keyword +hi def link vdfTodo Todo +hi def link vdfValue String +hi def link vdfVariable Identifier + +let b:current_syntax = 'vdf' + +let &cpoptions = s:cpo_save +unlet s:cpo_save diff --git a/runtime/syntax/zsh.vim b/runtime/syntax/zsh.vim index bab89b916e..69671c59ca 100644 --- a/runtime/syntax/zsh.vim +++ b/runtime/syntax/zsh.vim @@ -2,7 +2,7 @@ " Language: Zsh shell script " Maintainer: Christian Brabandt <cb@256bit.org> " Previous Maintainer: Nikolai Weibull <now@bitwi.se> -" Latest Revision: 2020-11-21 +" Latest Revision: 2022-07-26 " License: Vim (see :h license) " Repository: https://github.com/chrisbra/vim-zsh @@ -19,9 +19,9 @@ function! s:ContainedGroup() " vim-pandoc syntax defines the @langname cluster for embedded syntax languages " However, if no syntax is defined yet, `syn list @zsh` will return " "No syntax items defined", so make sure the result is actually a valid syn cluster - for cluster in ['markdownHighlightzsh', 'zsh'] + for cluster in ['markdownHighlight_zsh', 'zsh'] try - " markdown syntax defines embedded clusters as @markdownhighlight<lang>, + " markdown syntax defines embedded clusters as @markdownhighlight_<lang>, " pandoc just uses @<lang>, so check both for both clusters let a=split(execute('syn list @'. cluster), "\n") if len(a) == 2 && a[0] =~# '^---' && a[1] =~? cluster @@ -48,17 +48,28 @@ syn match zshPOSIXQuoted '\\u[0-9a-fA-F]\{1,4}' syn match zshPOSIXQuoted '\\U[1-9a-fA-F]\{1,8}' syn region zshString matchgroup=zshStringDelimiter start=+"+ end=+"+ - \ contains=zshQuoted,@zshDerefs,@zshSubst fold + \ contains=zshQuoted,@zshDerefs,@zshSubstQuoted fold syn region zshString matchgroup=zshStringDelimiter start=+'+ end=+'+ fold syn region zshPOSIXString matchgroup=zshStringDelimiter start=+\$'+ \ skip=+\\[\\']+ end=+'+ contains=zshPOSIXQuoted,zshQuoted syn match zshJobSpec '%\(\d\+\|?\=\w\+\|[%+-]\)' +syn match zshNumber '[+-]\=\<\d\+\>' +syn match zshNumber '[+-]\=\<0x\x\+\>' +syn match zshNumber '[+-]\=\<0\o\+\>' +syn match zshNumber '[+-]\=\d\+#[-+]\=\w\+\>' +syn match zshNumber '[+-]\=\d\+\.\d\+\>' + syn keyword zshPrecommand noglob nocorrect exec command builtin - time syn keyword zshDelimiter do done end -syn keyword zshConditional if then elif else fi case in esac select +syn keyword zshConditional if then elif else fi esac select + +syn keyword zshCase case nextgroup=zshCaseWord skipwhite +syn match zshCaseWord /\S\+/ nextgroup=zshCaseIn skipwhite contained transparent +syn keyword zshCaseIn in nextgroup=zshCasePattern skipwhite skipnl contained +syn match zshCasePattern /\S[^)]*)/ contained syn keyword zshRepeat while until repeat @@ -73,9 +84,13 @@ syn match zshFunction '^\s*\k\+\ze\s*()' syn match zshOperator '||\|&&\|;\|&!\=' -syn match zshRedir '\d\=\(<\|<>\|<<<\|<&\s*[0-9p-]\=\)' -syn match zshRedir '\d\=\(>\|>>\|>&\s*[0-9p-]\=\|&>\|>>&\|&>>\)[|!]\=' -syn match zshRedir '|&\=' + " <<<, <, <>, and variants. +syn match zshRedir '\d\=\(<<<\|<&\s*[0-9p-]\=\|<>\?\)' + " >, >>, and variants. +syn match zshRedir '\d\=\(>&\s*[0-9p-]\=\|&>>\?\|>>\?&\?\)[|!]\=' + " | and |&, but only if it's not preceeded or + " followed by a | to avoid matching ||. +syn match zshRedir '|\@1<!|&\=|\@!' syn region zshHereDoc matchgroup=zshRedir \ start='<\@<!<<\s*\z([^<]\S*\)' @@ -125,7 +140,7 @@ syn keyword zshCommands alias autoload bg bindkey break bye cap cd \ enable eval exec exit export false fc fg \ functions getcap getln getopts hash history \ jobs kill let limit log logout popd print - \ printf pushd pushln pwd r read + \ printf prompt pushd pushln pwd r read \ rehash return sched set setcap shift \ source stat suspend test times trap true \ ttyctl type ulimit umask unalias unfunction @@ -139,10 +154,120 @@ syn case ignore syn match zshOptStart \ /\v^\s*%(%(un)?setopt|set\s+[-+]o)/ \ nextgroup=zshOption skipwhite -syn match zshOption nextgroup=zshOption,zshComment skipwhite contained /\v - \ <%(no_?)?%( - \ auto_?cd|auto_?pushd|cdable_?vars|cd_?silent|chase_?dots|chase_?links|posix_?cd|pushd_?ignore_?dups|pushd_?minus|pushd_?silent|pushd_?to_?home|always_?last_?prompt|always_?to_?end|auto_?list|auto_?menu|auto_?name_?dirs|auto_?param_?keys|auto_?param_?slash|auto_?remove_?slash|bash_?auto_?list|complete_?aliases|complete_?in_?word|glob_?complete|hash_?list_?all|list_?ambiguous|list_?beep|list_?packed|list_?rows_?first|list_?types|menu_?complete|rec_?exact|bad_?pattern|bare_?glob_?qual|brace_?ccl|case_?glob|case_?match|case_?paths|csh_?null_?glob|equals|extended_?glob|force_?float|glob|glob_?assign|glob_?dots|glob_?star_?short|glob_?subst|hist_?subst_?pattern|ignore_?braces|ignore_?close_?braces|ksh_?glob|magic_?equal_?subst|mark_?dirs|multibyte|nomatch|null_?glob|numeric_?glob_?sort|rc_?expand_?param|rematch_?pcre|sh_?glob|unset|warn_?create_?global|warn_?nested_?var|warnnestedvar|append_?history|bang_?hist|extended_?history|hist_?allow_?clobber|hist_?beep|hist_?expire_?dups_?first|hist_?fcntl_?lock|hist_?find_?no_?dups|hist_?ignore_?all_?dups|hist_?ignore_?dups|hist_?ignore_?space|hist_?lex_?words|hist_?no_?functions|hist_?no_?store|hist_?reduce_?blanks|hist_?save_?by_?copy|hist_?save_?no_?dups|hist_?verify|inc_?append_?history|inc_?append_?history_?time|share_?history|all_?export|global_?export|global_?rcs|rcs|aliases|clobber|clobber_?empty|correct|correct_?all|dvorak|flow_?control|ignore_?eof|interactive_?comments|hash_?cmds|hash_?dirs|hash_?executables_?only|mail_?warning|path_?dirs|path_?script|print_?eight_?bit|print_?exit_?value|rc_?quotes|rm_?star_?silent|rm_?star_?wait|short_?loops|short_?repeat|sun_?keyboard_?hack|auto_?continue|auto_?resume|bg_?nice|check_?jobs|check_?running_?jobs|hup|long_?list_?jobs|monitor|notify|posix_?jobs|prompt_?bang|prompt_?cr|prompt_?sp|prompt_?percent|prompt_?subst|transient_?rprompt|alias_?func_?def|c_?bases|c_?precedences|debug_?before_?cmd|err_?exit|err_?return|eval_?lineno|exec|function_?argzero|local_?loops|local_?options|local_?patterns|local_?traps|multi_?func_?def|multios|octal_?zeroes|pipe_?fail|source_?trace|typeset_?silent|typeset_?to_?unset|verbose|xtrace|append_?create|bash_?rematch|bsd_?echo|continue_?on_?error|csh_?junkie_?history|csh_?junkie_?loops|csh_?junkie_?quotes|csh_?nullcmd|ksh_?arrays|ksh_?autoload|ksh_?option_?print|ksh_?typeset|ksh_?zero_?subscript|posix_?aliases|posix_?argzero|posix_?builtins|posix_?identifiers|posix_?strings|posix_?traps|sh_?file_?expansion|sh_?nullcmd|sh_?option_?letters|sh_?word_?split|traps_?async|interactive|login|privileged|restricted|shin_?stdin|single_?command|beep|combining_?chars|emacs|overstrike|single_?line_?zle|vi|zle|brace_?expand|dot_?glob|hash_?all|hist_?append|hist_?expand|log|mail_?warn|one_?cmd|physical|prompt_?vars|stdin|track_?all|no_?match - \)>/ +syn keyword zshOption nextgroup=zshOption,zshComment skipwhite contained + \ auto_cd no_auto_cd autocd noautocd auto_pushd no_auto_pushd autopushd noautopushd cdable_vars + \ no_cdable_vars cdablevars nocdablevars cd_silent no_cd_silent cdsilent nocdsilent chase_dots + \ no_chase_dots chasedots nochasedots chase_links no_chase_links chaselinks nochaselinks posix_cd + \ posixcd no_posix_cd noposixcd pushd_ignore_dups no_pushd_ignore_dups pushdignoredups + \ nopushdignoredups pushd_minus no_pushd_minus pushdminus nopushdminus pushd_silent no_pushd_silent + \ pushdsilent nopushdsilent pushd_to_home no_pushd_to_home pushdtohome nopushdtohome + \ always_last_prompt no_always_last_prompt alwayslastprompt noalwayslastprompt always_to_end + \ no_always_to_end alwaystoend noalwaystoend auto_list no_auto_list autolist noautolist auto_menu + \ no_auto_menu automenu noautomenu auto_name_dirs no_auto_name_dirs autonamedirs noautonamedirs + \ auto_param_keys no_auto_param_keys autoparamkeys noautoparamkeys auto_param_slash + \ no_auto_param_slash autoparamslash noautoparamslash auto_remove_slash no_auto_remove_slash + \ autoremoveslash noautoremoveslash bash_auto_list no_bash_auto_list bashautolist nobashautolist + \ complete_aliases no_complete_aliases completealiases nocompletealiases complete_in_word + \ no_complete_in_word completeinword nocompleteinword glob_complete no_glob_complete globcomplete + \ noglobcomplete hash_list_all no_hash_list_all hashlistall nohashlistall list_ambiguous + \ no_list_ambiguous listambiguous nolistambiguous list_beep no_list_beep listbeep nolistbeep + \ list_packed no_list_packed listpacked nolistpacked list_rows_first no_list_rows_first listrowsfirst + \ nolistrowsfirst list_types no_list_types listtypes nolisttypes menu_complete no_menu_complete + \ menucomplete nomenucomplete rec_exact no_rec_exact recexact norecexact bad_pattern no_bad_pattern + \ badpattern nobadpattern bare_glob_qual no_bare_glob_qual bareglobqual nobareglobqual brace_ccl + \ no_brace_ccl braceccl nobraceccl case_glob no_case_glob caseglob nocaseglob case_match + \ no_case_match casematch nocasematch case_paths no_case_paths casepaths nocasepaths csh_null_glob + \ no_csh_null_glob cshnullglob nocshnullglob equals no_equals noequals extended_glob no_extended_glob + \ extendedglob noextendedglob force_float no_force_float forcefloat noforcefloat glob no_glob noglob + \ glob_assign no_glob_assign globassign noglobassign glob_dots no_glob_dots globdots noglobdots + \ glob_star_short no_glob_star_short globstarshort noglobstarshort glob_subst no_glob_subst globsubst + \ noglobsubst hist_subst_pattern no_hist_subst_pattern histsubstpattern nohistsubstpattern + \ ignore_braces no_ignore_braces ignorebraces noignorebraces ignore_close_braces + \ no_ignore_close_braces ignoreclosebraces noignoreclosebraces ksh_glob no_ksh_glob kshglob nokshglob + \ magic_equal_subst no_magic_equal_subst magicequalsubst nomagicequalsubst mark_dirs no_mark_dirs + \ markdirs nomarkdirs multibyte no_multibyte nomultibyte nomatch no_nomatch nonomatch null_glob + \ no_null_glob nullglob nonullglob numeric_glob_sort no_numeric_glob_sort numericglobsort + \ nonumericglobsort rc_expand_param no_rc_expand_param rcexpandparam norcexpandparam rematch_pcre + \ no_rematch_pcre rematchpcre norematchpcre sh_glob no_sh_glob shglob noshglob unset no_unset nounset + \ warn_create_global no_warn_create_global warncreateglobal nowarncreateglobal warn_nested_var + \ no_warn_nested_var warnnestedvar no_warnnestedvar append_history no_append_history appendhistory + \ noappendhistory bang_hist no_bang_hist banghist nobanghist extended_history no_extended_history + \ extendedhistory noextendedhistory hist_allow_clobber no_hist_allow_clobber histallowclobber + \ nohistallowclobber hist_beep no_hist_beep histbeep nohistbeep hist_expire_dups_first + \ no_hist_expire_dups_first histexpiredupsfirst nohistexpiredupsfirst hist_fcntl_lock + \ no_hist_fcntl_lock histfcntllock nohistfcntllock hist_find_no_dups no_hist_find_no_dups + \ histfindnodups nohistfindnodups hist_ignore_all_dups no_hist_ignore_all_dups histignorealldups + \ nohistignorealldups hist_ignore_dups no_hist_ignore_dups histignoredups nohistignoredups + \ hist_ignore_space no_hist_ignore_space histignorespace nohistignorespace hist_lex_words + \ no_hist_lex_words histlexwords nohistlexwords hist_no_functions no_hist_no_functions + \ histnofunctions nohistnofunctions hist_no_store no_hist_no_store histnostore nohistnostore + \ hist_reduce_blanks no_hist_reduce_blanks histreduceblanks nohistreduceblanks hist_save_by_copy + \ no_hist_save_by_copy histsavebycopy nohistsavebycopy hist_save_no_dups no_hist_save_no_dups + \ histsavenodups nohistsavenodups hist_verify no_hist_verify histverify nohistverify + \ inc_append_history no_inc_append_history incappendhistory noincappendhistory + \ inc_append_history_time no_inc_append_history_time incappendhistorytime noincappendhistorytime + \ share_history no_share_history sharehistory nosharehistory all_export no_all_export allexport + \ noallexport global_export no_global_export globalexport noglobalexport global_rcs no_global_rcs + \ globalrcs noglobalrcs rcs no_rcs norcs aliases no_aliases noaliases clobber no_clobber noclobber + \ clobber_empty no_clobber_empty clobberempty noclobberempty correct no_correct nocorrect correct_all + \ no_correct_all correctall nocorrectall dvorak no_dvorak nodvorak flow_control no_flow_control + \ flowcontrol noflowcontrol ignore_eof no_ignore_eof ignoreeof noignoreeof interactive_comments + \ no_interactive_comments interactivecomments nointeractivecomments hash_cmds no_hash_cmds hashcmds + \ nohashcmds hash_dirs no_hash_dirs hashdirs nohashdirs hash_executables_only + \ no_hash_executables_only hashexecutablesonly nohashexecutablesonly mail_warning no_mail_warning + \ mailwarning nomailwarning path_dirs no_path_dirs pathdirs nopathdirs path_script no_path_script + \ pathscript nopathscript print_eight_bit no_print_eight_bit printeightbit noprinteightbit + \ print_exit_value no_print_exit_value printexitvalue noprintexitvalue rc_quotes no_rc_quotes + \ rcquotes norcquotes rm_star_silent no_rm_star_silent rmstarsilent normstarsilent rm_star_wait + \ no_rm_star_wait rmstarwait normstarwait short_loops no_short_loops shortloops noshortloops + \ short_repeat no_short_repeat shortrepeat noshortrepeat sun_keyboard_hack no_sun_keyboard_hack + \ sunkeyboardhack nosunkeyboardhack auto_continue no_auto_continue autocontinue noautocontinue + \ auto_resume no_auto_resume autoresume noautoresume bg_nice no_bg_nice bgnice nobgnice check_jobs + \ no_check_jobs checkjobs nocheckjobs check_running_jobs no_check_running_jobs checkrunningjobs + \ nocheckrunningjobs hup no_hup nohup long_list_jobs no_long_list_jobs longlistjobs nolonglistjobs + \ monitor no_monitor nomonitor notify no_notify nonotify posix_jobs posixjobs no_posix_jobs + \ noposixjobs prompt_bang no_prompt_bang promptbang nopromptbang prompt_cr no_prompt_cr promptcr + \ nopromptcr prompt_sp no_prompt_sp promptsp nopromptsp prompt_percent no_prompt_percent + \ promptpercent nopromptpercent prompt_subst no_prompt_subst promptsubst nopromptsubst + \ transient_rprompt no_transient_rprompt transientrprompt notransientrprompt alias_func_def + \ no_alias_func_def aliasfuncdef noaliasfuncdef c_bases no_c_bases cbases nocbases c_precedences + \ no_c_precedences cprecedences nocprecedences debug_before_cmd no_debug_before_cmd debugbeforecmd + \ nodebugbeforecmd err_exit no_err_exit errexit noerrexit err_return no_err_return errreturn + \ noerrreturn eval_lineno no_eval_lineno evallineno noevallineno exec no_exec noexec function_argzero + \ no_function_argzero functionargzero nofunctionargzero local_loops no_local_loops localloops + \ nolocalloops local_options no_local_options localoptions nolocaloptions local_patterns + \ no_local_patterns localpatterns nolocalpatterns local_traps no_local_traps localtraps nolocaltraps + \ multi_func_def no_multi_func_def multifuncdef nomultifuncdef multios no_multios nomultios + \ octal_zeroes no_octal_zeroes octalzeroes nooctalzeroes pipe_fail no_pipe_fail pipefail nopipefail + \ source_trace no_source_trace sourcetrace nosourcetrace typeset_silent no_typeset_silent + \ typesetsilent notypesetsilent typeset_to_unset no_typeset_to_unset typesettounset notypesettounset + \ verbose no_verbose noverbose xtrace no_xtrace noxtrace append_create no_append_create appendcreate + \ noappendcreate bash_rematch no_bash_rematch bashrematch nobashrematch bsd_echo no_bsd_echo bsdecho + \ nobsdecho continue_on_error no_continue_on_error continueonerror nocontinueonerror + \ csh_junkie_history no_csh_junkie_history cshjunkiehistory nocshjunkiehistory csh_junkie_loops + \ no_csh_junkie_loops cshjunkieloops nocshjunkieloops csh_junkie_quotes no_csh_junkie_quotes + \ cshjunkiequotes nocshjunkiequotes csh_nullcmd no_csh_nullcmd cshnullcmd nocshnullcmd ksh_arrays + \ no_ksh_arrays ksharrays noksharrays ksh_autoload no_ksh_autoload kshautoload nokshautoload + \ ksh_option_print no_ksh_option_print kshoptionprint nokshoptionprint ksh_typeset no_ksh_typeset + \ kshtypeset nokshtypeset ksh_zero_subscript no_ksh_zero_subscript kshzerosubscript + \ nokshzerosubscript posix_aliases no_posix_aliases posixaliases noposixaliases posix_argzero + \ no_posix_argzero posixargzero noposixargzero posix_builtins no_posix_builtins posixbuiltins + \ noposixbuiltins posix_identifiers no_posix_identifiers posixidentifiers noposixidentifiers + \ posix_strings no_posix_strings posixstrings noposixstrings posix_traps no_posix_traps posixtraps + \ noposixtraps sh_file_expansion no_sh_file_expansion shfileexpansion noshfileexpansion sh_nullcmd + \ no_sh_nullcmd shnullcmd noshnullcmd sh_option_letters no_sh_option_letters shoptionletters + \ noshoptionletters sh_word_split no_sh_word_split shwordsplit noshwordsplit traps_async + \ no_traps_async trapsasync notrapsasync interactive no_interactive nointeractive login no_login + \ nologin privileged no_privileged noprivileged restricted no_restricted norestricted shin_stdin + \ no_shin_stdin shinstdin noshinstdin single_command no_single_command singlecommand nosinglecommand + \ beep no_beep nobeep combining_chars no_combining_chars combiningchars nocombiningchars emacs + \ no_emacs noemacs overstrike no_overstrike nooverstrike single_line_zle no_single_line_zle + \ singlelinezle nosinglelinezle vi no_vi novi zle no_zle nozle brace_expand no_brace_expand + \ braceexpand nobraceexpand dot_glob no_dot_glob dotglob nodotglob hash_all no_hash_all hashall + \ nohashall hist_append no_hist_append histappend nohistappend hist_expand no_hist_expand histexpand + \ nohistexpand log no_log nolog mail_warn no_mail_warn mailwarn nomailwarn one_cmd no_one_cmd onecmd + \ noonecmd physical no_physical nophysical prompt_vars no_prompt_vars promptvars nopromptvars stdin + \ no_stdin nostdin track_all no_track_all trackall notrackall syn case match syn keyword zshTypes float integer local typeset declare private readonly @@ -150,15 +275,12 @@ syn keyword zshTypes float integer local typeset declare private read " XXX: this may be too much " syn match zshSwitches '\s\zs--\=[a-zA-Z0-9-]\+' -syn match zshNumber '[+-]\=\<\d\+\>' -syn match zshNumber '[+-]\=\<0x\x\+\>' -syn match zshNumber '[+-]\=\<0\o\+\>' -syn match zshNumber '[+-]\=\d\+#[-+]\=\w\+\>' -syn match zshNumber '[+-]\=\d\+\.\d\+\>' - " TODO: $[...] is the same as $((...)), so add that as well. syn cluster zshSubst contains=zshSubst,zshOldSubst,zshMathSubst +syn cluster zshSubstQuoted contains=zshSubstQuoted,zshOldSubst,zshMathSubst exe 'syn region zshSubst matchgroup=zshSubstDelim transparent start=/\$(/ skip=/\\)/ end=/)/ contains='.s:contained. ' fold' +exe 'syn region zshSubstQuoted matchgroup=zshSubstDelim transparent start=/\$(/ skip=/\\)/ end=/)/ contains='.s:contained. ' fold' +syn region zshSubstQuoted matchgroup=zshSubstDelim start='\${' skip='\\}' end='}' contains=@zshSubst,zshBrackets,zshQuoted fold syn region zshParentheses transparent start='(' skip='\\)' end=')' fold syn region zshGlob start='(#' end=')' syn region zshMathSubst matchgroup=zshSubstDelim transparent @@ -201,6 +323,8 @@ hi def link zshJobSpec Special hi def link zshPrecommand Special hi def link zshDelimiter Keyword hi def link zshConditional Conditional +hi def link zshCase zshConditional +hi def link zshCaseIn zshCase hi def link zshException Exception hi def link zshRepeat Repeat hi def link zshKeyword Keyword @@ -223,6 +347,7 @@ hi def link zshTypes Type hi def link zshSwitches Special hi def link zshNumber Number hi def link zshSubst PreProc +hi def link zshSubstQuoted zshSubst hi def link zshMathSubst zshSubst hi def link zshOldSubst zshSubst hi def link zshSubstDelim zshSubst diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py index 23ed0e3f08..766c420c7d 100755 --- a/scripts/gen_vimdoc.py +++ b/scripts/gen_vimdoc.py @@ -260,7 +260,7 @@ CONFIG = { 'helptag_fmt': lambda name: ( '*lua-treesitter-core*' if name.lower() == 'treesitter' - else f'*treesitter-{name.lower()}*'), + else f'*lua-treesitter-{name.lower()}*'), 'fn_helptag_fmt': lambda fstem, name: ( f'*{name}()*' if name != 'new' diff --git a/src/clint.py b/src/clint.py index 0556f53372..c4ddbf706e 100755 --- a/src/clint.py +++ b/src/clint.py @@ -2700,7 +2700,7 @@ def CheckLanguage(filename, clean_lines, linenum, error): if match: error(filename, linenum, 'runtime/printf', 4, 'Use xstrlcat or snprintf instead of %s' % match.group(1)) - if not Search(r'eval/typval\.[ch]$', filename): + if not Search(r'eval/typval\.[ch]$|eval/typval_defs\.h$', filename): match = Search(r'(?:\.|->)' r'(?:lv_(?:first|last|refcount|len|watch|idx(?:_item)?' r'|copylist|lock)' diff --git a/src/man/nvim.1 b/src/man/nvim.1 index 9f35014ee8..457d785365 100644 --- a/src/man/nvim.1 +++ b/src/man/nvim.1 @@ -200,7 +200,8 @@ Skip loading plugins. Implied by .Cm -u NONE . .It Fl -clean -Mimic a fresh install of Nvim. Skip loading non-builtin plugins and shada (viminfo) file. +Start Nvim with "factory defaults" (no user config and plugins, no shada). +.Ic ":help --clean" .It Fl o Ns Op Ar N Open .Ar N diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c index 1cf0211f43..ac4cb953b8 100644 --- a/src/nvim/api/autocmd.c +++ b/src/nvim/api/autocmd.c @@ -59,6 +59,9 @@ static int64_t next_autocmd_id = 1; /// - group (string|integer): the autocommand group name or id to match against. /// - event (string|array): event or events to match against |autocmd-events|. /// - pattern (string|array): pattern or patterns to match against |autocmd-pattern|. +/// Cannot be used with {buffer} +/// - buffer: Buffer number or list of buffer numbers for buffer local autocommands +/// |autocmd-buflocal|. Cannot be used with {pattern} /// @return Array of autocommands matching the criteria, with each item /// containing the following fields: /// - id (number): the autocommand id (only when defined with the API). @@ -240,7 +243,7 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err) assert(pattern_filters[i]); char *pat = pattern_filters[i]; - int patlen = (int)STRLEN(pat); + int patlen = (int)strlen(pat); if (aupat_is_buflocal(pat, patlen)) { aupat_normalize_buflocal_pat(pattern_buflocal, diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index 11715a49dc..ed0907e8f8 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -105,7 +105,7 @@ Dictionary nvim_parse_cmd(String str, Dictionary opts, Error *err) // Parse arguments Array args = ARRAY_DICT_INIT; - size_t length = STRLEN(ea.arg); + size_t length = strlen(ea.arg); // For nargs = 1 or '?', pass the entire argument list as a single argument, // otherwise split arguments by whitespace. @@ -591,15 +591,15 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error if (*mods.split.data.string.data == NUL) { // Empty string, do nothing. - } else if (STRCMP(mods.split.data.string.data, "aboveleft") == 0 - || STRCMP(mods.split.data.string.data, "leftabove") == 0) { + } else if (strcmp(mods.split.data.string.data, "aboveleft") == 0 + || strcmp(mods.split.data.string.data, "leftabove") == 0) { cmdinfo.cmdmod.cmod_split |= WSP_ABOVE; - } else if (STRCMP(mods.split.data.string.data, "belowright") == 0 - || STRCMP(mods.split.data.string.data, "rightbelow") == 0) { + } else if (strcmp(mods.split.data.string.data, "belowright") == 0 + || strcmp(mods.split.data.string.data, "rightbelow") == 0) { cmdinfo.cmdmod.cmod_split |= WSP_BELOW; - } else if (STRCMP(mods.split.data.string.data, "topleft") == 0) { + } else if (strcmp(mods.split.data.string.data, "topleft") == 0) { cmdinfo.cmdmod.cmod_split |= WSP_TOP; - } else if (STRCMP(mods.split.data.string.data, "botright") == 0) { + } else if (strcmp(mods.split.data.string.data, "botright") == 0) { cmdinfo.cmdmod.cmod_split |= WSP_BOT; } else { VALIDATION_ERROR("Invalid value for 'mods.split'"); @@ -938,7 +938,7 @@ void nvim_buf_del_user_command(Buffer buffer, String name, Error *err) for (int i = 0; i < gap->ga_len; i++) { ucmd_T *cmd = USER_CMD_GA(gap, i); - if (!STRCMP(name.data, cmd->uc_name)) { + if (!strcmp(name.data, cmd->uc_name)) { free_ucmd(cmd); gap->ga_len -= 1; diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index ae051d8cab..edcea52838 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -742,7 +742,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer line = buf->b_ml.ml_line_count; } } else if (line < buf->b_ml.ml_line_count) { - len = ephemeral ? MAXCOL : STRLEN(ml_get_buf(buf, (linenr_T)line + 1, false)); + len = ephemeral ? MAXCOL : strlen(ml_get_buf(buf, (linenr_T)line + 1, false)); } if (col == -1) { @@ -761,7 +761,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer if (col2 >= 0) { if (line2 >= 0 && line2 < buf->b_ml.ml_line_count) { - len = ephemeral ? MAXCOL : STRLEN(ml_get_buf(buf, (linenr_T)line2 + 1, false)); + len = ephemeral ? MAXCOL : strlen(ml_get_buf(buf, (linenr_T)line2 + 1, false)); } else if (line2 == buf->b_ml.ml_line_count) { // We are trying to add an extmark past final newline len = 0; @@ -1106,7 +1106,7 @@ static int init_sign_text(char **sign_text, char *text) { char *s; - char *endp = text + (int)STRLEN(text); + char *endp = text + (int)strlen(text); // Count cells and check for non-printable chars int cells = 0; diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 1534e547b0..45c20d07e1 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -122,7 +122,7 @@ static char *mpack_array_dyn16(char **buf) static void mpack_str(char **buf, const char *str) { assert(sizeof(schar_T) - 1 < 0x20); - size_t len = STRLEN(str); + size_t len = strlen(str); mpack_w(buf, 0xa0 | len); memcpy(*buf, str, len); *buf += len; @@ -845,7 +845,7 @@ static void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startc for (size_t i = 0; i < ncells; i++) { repeat++; if (i == ncells - 1 || attrs[i] != attrs[i + 1] - || STRCMP(chunk[i], chunk[i + 1])) { + || strcmp(chunk[i], chunk[i + 1])) { if (UI_BUF_SIZE - BUF_POS(data) < 2 * (1 + 2 + sizeof(schar_T) + 5 + 5)) { // close to overflowing the redraw buffer. finish this event, // flush, and start a new "grid_line" event at the current position. diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 95c9919522..ad9ed72f43 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1882,7 +1882,7 @@ Object nvim_get_proc(Integer pid, Error *err) api_set_error(err, kErrorTypeException, "Invalid pid: %" PRId64, pid); return NIL; } -#ifdef WIN32 +#ifdef MSWIN rvobj.data.dictionary = os_proc_info((int)pid); if (rvobj.data.dictionary.size == 0) { // Process not found. return NIL; diff --git a/src/nvim/api/vimscript.c b/src/nvim/api/vimscript.c index f6d0e39327..71209c9ab6 100644 --- a/src/nvim/api/vimscript.c +++ b/src/nvim/api/vimscript.c @@ -204,10 +204,10 @@ static Object _call_function(String fn, Array args, dict_T *self, Error *err) try_start(); typval_T rettv; funcexe_T funcexe = FUNCEXE_INIT; - funcexe.firstline = curwin->w_cursor.lnum; - funcexe.lastline = curwin->w_cursor.lnum; - funcexe.evaluate = true; - funcexe.selfdict = self; + funcexe.fe_firstline = curwin->w_cursor.lnum; + funcexe.fe_lastline = curwin->w_cursor.lnum; + funcexe.fe_evaluate = true; + funcexe.fe_selfdict = self; // call_func() retval is deceptive, ignore it. Instead we set `msg_list` // (see above) to capture abort-causing non-exception errors. (void)call_func(fn.data, (int)fn.size, &rettv, (int)args.size, @@ -304,7 +304,7 @@ Object nvim_call_dict_function(Object dict, String fn, Array args, Error *err) } fn = (String) { .data = di->di_tv.vval.v_string, - .size = STRLEN(di->di_tv.vval.v_string), + .size = strlen(di->di_tv.vval.v_string), }; } diff --git a/src/nvim/arglist.c b/src/nvim/arglist.c index 0000636417..02e3a99aab 100644 --- a/src/nvim/arglist.c +++ b/src/nvim/arglist.c @@ -633,7 +633,7 @@ void ex_argdedupe(exarg_T *eap FUNC_ATTR_UNUSED) { for (int i = 0; i < ARGCOUNT; i++) { for (int j = i + 1; j < ARGCOUNT; j++) { - if (FNAMECMP(ARGLIST[i].ae_fname, ARGLIST[j].ae_fname) == 0) { + if (path_fnamecmp(ARGLIST[i].ae_fname, ARGLIST[j].ae_fname) == 0) { xfree(ARGLIST[j].ae_fname); memmove(ARGLIST + j, ARGLIST + j + 1, (size_t)(ARGCOUNT - j - 1) * sizeof(aentry_T)); diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c index 635875b16f..644f892f3c 100644 --- a/src/nvim/autocmd.c +++ b/src/nvim/autocmd.c @@ -266,7 +266,7 @@ static void au_show_for_event(int group, event_T event, char *pat) // normalize pat into standard "<buffer>#N" form aupat_normalize_buflocal_pat(buflocal_pat, pat, patlen, aupat_get_buflocal_nr(pat, patlen)); pat = (char *)buflocal_pat; - patlen = (int)STRLEN(buflocal_pat); + patlen = (int)strlen(buflocal_pat); } assert(*pat != NUL); @@ -725,7 +725,7 @@ int check_ei(void) char *au_event_disable(char *what) { char *save_ei = xstrdup(p_ei); - char *new_ei = xstrnsave(p_ei, STRLEN(p_ei) + STRLEN(what)); + char *new_ei = xstrnsave(p_ei, strlen(p_ei) + strlen(what)); if (*what == ',' && *p_ei == NUL) { STRCPY(new_ei, what + 1); } else { @@ -957,7 +957,7 @@ int do_autocmd_event(event_T event, char *pat, bool once, int nested, char *cmd, aupat_normalize_buflocal_pat(buflocal_pat, pat, patlen, buflocal_nr); pat = buflocal_pat; - patlen = (int)STRLEN(buflocal_pat); + patlen = (int)strlen(buflocal_pat); } if (delete) { @@ -1018,7 +1018,7 @@ int autocmd_register(int64_t id, event_T event, char *pat, int patlen, int group int findgroup; char buflocal_pat[BUFLOCAL_PAT_LEN]; // for "<buffer=X>" - if (patlen > (int)STRLEN(pat)) { + if (patlen > (int)strlen(pat)) { return FAIL; } @@ -1039,7 +1039,7 @@ int autocmd_register(int64_t id, event_T event, char *pat, int patlen, int group aupat_normalize_buflocal_pat(buflocal_pat, pat, patlen, buflocal_nr); pat = buflocal_pat; - patlen = (int)STRLEN(buflocal_pat); + patlen = (int)strlen(buflocal_pat); } // always goes at or after the last one, so start at the end. @@ -1193,7 +1193,7 @@ size_t aucmd_pattern_length(char *pat) return (size_t)(endpat - pat); } - return STRLEN(pat); + return strlen(pat); } char *aucmd_next_pattern(char *pat, size_t patlen) @@ -1445,7 +1445,6 @@ win_found: } aucmd_win_used = false; - last_status(false); // may need to remove last status line if (!valid_tabpage_win(curtab)) { // no valid window in current tabpage @@ -2012,7 +2011,7 @@ void auto_next_pat(AutoPatCmd *apc, int stop_at_last) s = _("%s Autocommands for \"%s\""); const size_t sourcing_name_len - = (STRLEN(s) + strlen(name) + (size_t)ap->patlen + 1); + = (strlen(s) + strlen(name) + (size_t)ap->patlen + 1); char *const namep = xmalloc(sourcing_name_len); snprintf(namep, sourcing_name_len, s, name, ap->pat); @@ -2396,7 +2395,7 @@ bool au_exists(const char *const arg) FUNC_ATTR_WARN_UNUSED_RESULT } // if pattern is "<buffer>", special handling is needed which uses curbuf - // for pattern "<buffer=N>, FNAMECMP() will work fine + // for pattern "<buffer=N>, path_fnamecmp() will work fine if (pattern != NULL && STRICMP(pattern, "<buffer>") == 0) { buflocal_buf = curbuf; } @@ -2404,12 +2403,12 @@ bool au_exists(const char *const arg) FUNC_ATTR_WARN_UNUSED_RESULT // Check if there is an autocommand with the given pattern. for (; ap != NULL; ap = ap->next) { // only use a pattern when it has not been removed and has commands. - // For buffer-local autocommands, FNAMECMP() works fine. + // For buffer-local autocommands, path_fnamecmp() works fine. if (ap->pat != NULL && ap->cmds != NULL && (group == AUGROUP_ALL || ap->group == group) && (pattern == NULL || (buflocal_buf == NULL - ? FNAMECMP(ap->pat, pattern) == 0 + ? path_fnamecmp(ap->pat, pattern) == 0 : ap->buflocal_nr == buflocal_buf->b_fnum))) { retval = true; break; diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 8f23102e2e..85f79deb2f 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -2170,7 +2170,7 @@ int buflist_findpat(const char *pattern, const char *pattern_end, bool unlisted, if (pat == NULL) { return -1; } - patend = pat + STRLEN(pat) - 1; + patend = pat + strlen(pat) - 1; toggledollar = (patend > pat && *patend == '$'); // First try finding a listed buffer. If not found and "unlisted" @@ -2284,7 +2284,7 @@ int ExpandBufnames(char *pat, int *num_file, char ***file, int options) // Make a copy of "pat" and change "^" to "\(^\|[\/]\)". if (*pat == '^') { - patc = xmalloc(STRLEN(pat) + 11); + patc = xmalloc(strlen(pat) + 11); STRCPY(patc, "\\(^\\|[\\/]\\)"); STRCPY(patc + 11, pat + 1); } else { @@ -2733,7 +2733,7 @@ void buflist_list(exarg_T *eap) IObuff[len++] = ' '; } while (--i > 0 && len < IOSIZE - 18); if (vim_strchr(eap->arg, 't') && buf->b_last_used) { - undo_fmt_time(IObuff + len, (size_t)(IOSIZE - len), buf->b_last_used); + undo_fmt_time((char_u *)IObuff + len, (size_t)(IOSIZE - len), buf->b_last_used); } else { vim_snprintf((char *)IObuff + len, (size_t)(IOSIZE - len), _("line %" PRId64), buf == curbuf ? (int64_t)curwin->w_cursor.lnum : (int64_t)buflist_findlnum(buf)); @@ -2965,7 +2965,7 @@ static bool otherfile_buf(buf_T *buf, char *ffname, FileID *file_id_p, bool file if (ffname == NULL || *ffname == NUL || buf->b_ffname == NULL) { return true; } - if (FNAMECMP(ffname, buf->b_ffname) == 0) { + if (path_fnamecmp(ffname, buf->b_ffname) == 0) { return false; } { @@ -3037,7 +3037,7 @@ void fileinfo(int fullname, int shorthelp, int dont_truncate) if (fullname > 1) { // 2 CTRL-G: include buffer number vim_snprintf(buffer, IOSIZE, "buf %d: ", curbuf->b_fnum); - p = buffer + STRLEN(buffer); + p = buffer + strlen(buffer); } else { p = buffer; } @@ -3096,7 +3096,7 @@ void fileinfo(int fullname, int shorthelp, int dont_truncate) (int64_t)curbuf->b_ml.ml_line_count, n); validate_virtcol(); - len = STRLEN(buffer); + len = strlen(buffer); col_print(buffer + len, IOSIZE - len, (int)curwin->w_cursor.col + 1, (int)curwin->w_virtcol + 1); } @@ -3305,7 +3305,7 @@ void maketitle(void) } *icon_str = NUL; // Truncate name at 100 bytes. - len = (int)STRLEN(buf_p); + len = (int)strlen(buf_p); if (len > 100) { len -= 100; len += utf_cp_tail_off(buf_p, buf_p + len) + 1; @@ -3335,7 +3335,7 @@ static bool value_change(char *str, char **last) FUNC_ATTR_WARN_UNUSED_RESULT { if ((str == NULL) != (*last == NULL) - || (str != NULL && *last != NULL && STRCMP(str, *last) != 0)) { + || (str != NULL && *last != NULL && strcmp(str, *last) != 0)) { xfree(*last); if (str == NULL) { *last = NULL; @@ -3412,7 +3412,7 @@ bool append_arg_number(win_T *wp, char *buf, int buflen, bool add_file) return false; } - char *p = buf + STRLEN(buf); // go to the end of the buffer + char *p = buf + strlen(buf); // go to the end of the buffer // Early out if the string is getting too long if (p - buf + 35 >= buflen) { @@ -3448,7 +3448,7 @@ void fname_expand(buf_T *buf, char **ffname, char **sfname) } *ffname = fix_fname((*ffname)); // expand to full path -#ifdef WIN32 +#ifdef MSWIN if (!buf->b_p_bin) { // If the file name is a shortcut file, use the file it links to. char *rfname = os_resolve_shortcut((const char *)(*ffname)); @@ -4159,7 +4159,7 @@ bool buf_contents_changed(buf_T *buf) if (buf->b_ml.ml_line_count == curbuf->b_ml.ml_line_count) { differ = false; for (linenr_T lnum = 1; lnum <= curbuf->b_ml.ml_line_count; lnum++) { - if (STRCMP(ml_get_buf(buf, lnum, false), ml_get(lnum)) != 0) { + if (strcmp(ml_get_buf(buf, lnum, false), ml_get(lnum)) != 0) { differ = true; break; } diff --git a/src/nvim/change.c b/src/nvim/change.c index f4568fc617..ab550259c8 100644 --- a/src/nvim/change.c +++ b/src/nvim/change.c @@ -544,7 +544,7 @@ void save_file_ff(buf_T *buf) // Only use free/alloc when necessary, they take time. if (buf->b_start_fenc == NULL - || STRCMP(buf->b_start_fenc, buf->b_p_fenc) != 0) { + || strcmp(buf->b_start_fenc, buf->b_p_fenc) != 0) { xfree(buf->b_start_fenc); buf->b_start_fenc = xstrdup(buf->b_p_fenc); } @@ -582,14 +582,14 @@ bool file_ff_differs(buf_T *buf, bool ignore_empty) if (buf->b_start_fenc == NULL) { return *buf->b_p_fenc != NUL; } - return STRCMP(buf->b_start_fenc, buf->b_p_fenc) != 0; + return strcmp(buf->b_start_fenc, buf->b_p_fenc) != 0; } /// Insert string "p" at the cursor position. Stops at a NUL byte. /// Handles Replace mode and multi-byte characters. void ins_bytes(char *p) { - ins_bytes_len(p, STRLEN(p)); + ins_bytes_len(p, strlen(p)); } /// Insert string "p" with length "len" at the cursor position. @@ -632,7 +632,7 @@ void ins_char_bytes(char *buf, size_t charlen) size_t col = (size_t)curwin->w_cursor.col; linenr_T lnum = curwin->w_cursor.lnum; char *oldp = ml_get(lnum); - size_t linelen = STRLEN(oldp) + 1; // length of old line including NUL + size_t linelen = strlen(oldp) + 1; // length of old line including NUL // The lengths default to the values for when not replacing. size_t oldlen = 0; // nr of bytes inserted @@ -731,7 +731,7 @@ void ins_char_bytes(char *buf, size_t charlen) /// Caller must have prepared for undo. void ins_str(char *s) { - int newlen = (int)STRLEN(s); + int newlen = (int)strlen(s); linenr_T lnum = curwin->w_cursor.lnum; if (virtual_active() && curwin->w_cursor.coladd > 0) { @@ -740,7 +740,7 @@ void ins_str(char *s) colnr_T col = curwin->w_cursor.col; char *oldp = ml_get(lnum); - int oldlen = (int)STRLEN(oldp); + int oldlen = (int)strlen(oldp); char *newp = xmalloc((size_t)oldlen + (size_t)newlen + 1); if (col > 0) { @@ -798,7 +798,7 @@ int del_bytes(colnr_T count, bool fixpos_arg, bool use_delcombine) colnr_T col = curwin->w_cursor.col; bool fixpos = fixpos_arg; char *oldp = ml_get(lnum); - colnr_T oldlen = (colnr_T)STRLEN(oldp); + colnr_T oldlen = (colnr_T)strlen(oldp); // Can't do anything when the cursor is on the NUL after the line. if (col >= oldlen) { @@ -962,7 +962,7 @@ int copy_indent(int size, char *src) if (p == NULL) { // Allocate memory for the result: the copied indent, new indent // and the rest of the line. - line_len = (int)STRLEN(get_cursor_line_ptr()) + 1; + line_len = (int)strlen(get_cursor_line_ptr()) + 1; assert(ind_len + line_len >= 0); size_t line_size; STRICT_ADD(ind_len, line_len, &line_size, size_t); @@ -1072,7 +1072,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment) p = skipwhite(p_extra); first_char = (unsigned char)(*p); } - extra_len = (int)STRLEN(p_extra); + extra_len = (int)strlen(p_extra); saved_char = *p_extra; *p_extra = NUL; } @@ -1155,7 +1155,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment) } } else { // Not a comment line // Find last non-blank in line - p = ptr + STRLEN(ptr) - 1; + p = ptr + strlen(ptr) - 1; while (p > ptr && ascii_iswhite(*p)) { p--; } @@ -1205,7 +1205,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment) while ((ptr[0] == '#' || was_backslashed) && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) { - if (*ptr && ptr[STRLEN(ptr) - 1] == '\\') { + if (*ptr && ptr[strlen(ptr) - 1] == '\\') { was_backslashed = true; } else { was_backslashed = false; @@ -1331,7 +1331,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment) if (lead_len > 0) { if (current_flag == COM_START) { lead_repl = (char *)lead_middle; - lead_repl_len = (int)STRLEN(lead_middle); + lead_repl_len = (int)strlen(lead_middle); } // If we have hit RETURN immediately after the start @@ -1641,7 +1641,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment) if (flags & OPENLINE_COM_LIST && second_line_indent > 0) { int i; int padding = second_line_indent - - (newindent + (int)STRLEN(leader)); + - (newindent + (int)strlen(leader)); // Here whitespace is inserted after the comment char. // Below, set_indent(newindent, SIN_INSERT) will insert the @@ -1755,7 +1755,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment) } ml_replace(curwin->w_cursor.lnum, saved_line, false); - int new_len = (int)STRLEN(saved_line); + int new_len = (int)strlen(saved_line); // TODO(vigoux): maybe there is issues there with expandtabs ? int cols_spliced = 0; @@ -1795,7 +1795,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment) if (did_append) { changed_lines(curwin->w_cursor.lnum, 0, curwin->w_cursor.lnum, 1L, true); // bail out and just get the final length of the line we just manipulated - bcount_t extra = (bcount_t)STRLEN(ml_get(curwin->w_cursor.lnum)); + bcount_t extra = (bcount_t)strlen(ml_get(curwin->w_cursor.lnum)); extmark_splice(curbuf, (int)curwin->w_cursor.lnum - 1, 0, 0, 0, 0, 1, 0, 1 + extra, kExtmarkUndo); } @@ -2084,7 +2084,7 @@ int get_last_leader_offset(char *line, char **flags) char part_buf[COM_MAX_LEN]; // buffer for one option part // Repeat to match several nested comment strings. - int i = (int)STRLEN(line); + int i = (int)strlen(line); while (--i >= lower_check_bound) { // scan through the 'comments' option for a match int found_one = false; @@ -2171,7 +2171,7 @@ int get_last_leader_offset(char *line, char **flags) while (ascii_iswhite(*com_leader)) { com_leader++; } - len1 = (int)STRLEN(com_leader); + len1 = (int)strlen(com_leader); for (list = curbuf->b_p_com; *list;) { char *flags_save = list; @@ -2185,7 +2185,7 @@ int get_last_leader_offset(char *line, char **flags) while (ascii_iswhite(*string)) { string++; } - len2 = (int)STRLEN(string); + len2 = (int)strlen(string); if (len2 == 0) { continue; } diff --git a/src/nvim/channel.c b/src/nvim/channel.c index 5910053025..7c5bc1c410 100644 --- a/src/nvim/channel.c +++ b/src/nvim/channel.c @@ -14,7 +14,7 @@ #include "nvim/msgpack_rpc/server.h" #include "nvim/os/fs.h" #include "nvim/os/shell.h" -#ifdef WIN32 +#ifdef MSWIN # include "nvim/os/os_win_console.h" # include "nvim/os/pty_conpty_win.h" #endif @@ -492,7 +492,7 @@ uint64_t channel_from_stdio(bool rpc, CallbackReader on_output, const char **err int stdin_dup_fd = STDIN_FILENO; int stdout_dup_fd = STDOUT_FILENO; -#ifdef WIN32 +#ifdef MSWIN // Strangely, ConPTY doesn't work if stdin and stdout are pipes. So replace // stdin and stdout with CONIN$ and CONOUT$, respectively. if (embedded_mode && os_has_conpty_working()) { diff --git a/src/nvim/charset.c b/src/nvim/charset.c index 693ff90179..0cc2189948 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -268,7 +268,7 @@ int buf_init_chartab(buf_T *buf, int global) void trans_characters(char *buf, int bufsize) { char_u *trs; // translated character - int len = (int)STRLEN(buf); // length of string needing translation + int len = (int)strlen(buf); // length of string needing translation int room = bufsize - len; // room in buffer after string while (*buf != 0) { @@ -1078,7 +1078,7 @@ void getvvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *e // Cannot put the cursor on part of a wide character. char *ptr = ml_get_buf(wp->w_buffer, pos->lnum, false); - if (pos->col < (colnr_T)STRLEN(ptr)) { + if (pos->col < (colnr_T)strlen(ptr)) { int c = utf_ptr2char(ptr + pos->col); if ((c != TAB) && vim_isprintc(c)) { endadd = (colnr_T)(char2cells(c) - 1); @@ -1157,7 +1157,7 @@ char *skipwhite(const char *const p) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET { - return skipwhite_len(p, STRLEN(p)); + return skipwhite_len(p, strlen(p)); } /// Like `skipwhite`, but skip up to `len` characters. diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c index 3f624c77f3..65b07cc17b 100644 --- a/src/nvim/cmdexpand.c +++ b/src/nvim/cmdexpand.c @@ -66,8 +66,8 @@ static int compl_selected; static int sort_func_compare(const void *s1, const void *s2) { - char_u *p1 = *(char_u **)s1; - char_u *p2 = *(char_u **)s2; + char *p1 = *(char **)s1; + char *p2 = *(char **)s2; if (*p1 != '<' && *p2 == '<') { return -1; @@ -75,7 +75,7 @@ static int sort_func_compare(const void *s1, const void *s2) if (*p1 == '<' && *p2 != '<') { return 1; } - return STRCMP(p1, p2); + return strcmp(p1, p2); } static void ExpandEscape(expand_T *xp, char_u *str, int numfiles, char **files, int options) @@ -361,7 +361,7 @@ static char *ExpandOne_start(int mode, expand_T *xp, char *str, int options) // expand_wildcards, only need to check the first two. non_suf_match = 0; for (int i = 0; i < 2; i++) { - if (match_suffix((char_u *)xp->xp_files[i])) { + if (match_suffix(xp->xp_files[i])) { non_suf_match++; } } @@ -511,7 +511,7 @@ char *ExpandOne(expand_T *xp, char *str, char *orig, int options, int mode) if (mode == WILD_ALL && xp->xp_numfiles > 0 && !got_int) { size_t len = 0; for (i = 0; i < xp->xp_numfiles; i++) { - len += STRLEN(xp->xp_files[i]) + 1; + len += strlen(xp->xp_files[i]) + 1; } ss = xmalloc(len); *ss = NUL; @@ -672,7 +672,7 @@ int showmatches(expand_T *xp, int wildmenu) for (k = i; k < num_files; k += lines) { if (xp->xp_context == EXPAND_TAGS_LISTFILES) { msg_outtrans_attr(files_found[k], HL_ATTR(HLF_D)); - p = (char_u *)files_found[k] + STRLEN(files_found[k]) + 1; + p = (char_u *)files_found[k] + strlen(files_found[k]) + 1; msg_advance(maxlen + 1); msg_puts((const char *)p); msg_advance(maxlen + 3); @@ -1148,7 +1148,7 @@ static void set_context_for_wildcard_arg(exarg_T *eap, const char *arg, bool use // A full match ~user<Tab> will be replaced by user's home // directory i.e. something like ~user<Tab> -> /home/user/ if (*p == NUL && p > (const char *)xp->xp_pattern + 1 - && match_user((char_u *)xp->xp_pattern + 1) >= 1) { + && match_user(xp->xp_pattern + 1) >= 1) { xp->xp_context = EXPAND_USER; xp->xp_pattern++; } @@ -2280,7 +2280,7 @@ static void ExpandGeneric(expand_T *xp, regmatch_T *regmatch, int *num_file, cha (*file)[count++] = str; if (func == get_menu_names) { // Test for separator added by get_menu_names(). - str += STRLEN(str) - 1; + str += strlen(str) - 1; if (*str == '\001') { *str = '.'; } @@ -2294,8 +2294,7 @@ static void ExpandGeneric(expand_T *xp, regmatch_T *regmatch, int *num_file, cha || xp->xp_context == EXPAND_FUNCTIONS || xp->xp_context == EXPAND_USER_FUNC) { // <SNR> functions should be sorted to the end. - qsort((void *)(*file), (size_t)(*num_file), sizeof(char_u *), - sort_func_compare); + qsort((void *)(*file), (size_t)(*num_file), sizeof(char *), sort_func_compare); } else { sort_strings(*file, *num_file); } @@ -2363,7 +2362,7 @@ static void expand_shellcmd(char *filepat, int *num_file, char ***file, int flag for (s = path;; s = e) { e = vim_strchr(s, ENV_SEPCHAR); if (e == NULL) { - e = s + STRLEN(s); + e = s + strlen(s); } if (*s == NUL) { @@ -2387,7 +2386,7 @@ static void expand_shellcmd(char *filepat, int *num_file, char ***file, int flag } STRLCPY(buf, s, l + 1); add_pathsep(buf); - l = STRLEN(buf); + l = strlen(buf); STRLCPY(buf + l, pat, MAXPATHL - l); // Expand matches in one directory of $PATH. @@ -2494,7 +2493,7 @@ static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, int *num_file, for (char *s = retstr; *s != NUL; s = e) { e = vim_strchr(s, '\n'); if (e == NULL) { - e = s + STRLEN(s); + e = s + strlen(s); } const char keep = *e; *e = NUL; @@ -2585,7 +2584,7 @@ void globpath(char *path, char *file, garray_T *ga, int expand_options) while (*path != NUL) { // Copy one item of the path to buf[] and concatenate the file name. copy_option_part(&path, (char *)buf, MAXPATHL, ","); - if (STRLEN(buf) + STRLEN(file) + 2 < MAXPATHL) { + if (STRLEN(buf) + strlen(file) + 2 < MAXPATHL) { add_pathsep((char *)buf); STRCAT(buf, file); // NOLINT @@ -2865,14 +2864,14 @@ void f_getcompletion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (strcmp(type, "cmdline") == 0) { set_one_cmd_context(&xpc, pattern); - xpc.xp_pattern_len = STRLEN(xpc.xp_pattern); - xpc.xp_col = (int)STRLEN(pattern); + xpc.xp_pattern_len = strlen(xpc.xp_pattern); + xpc.xp_col = (int)strlen(pattern); goto theend; } ExpandInit(&xpc); xpc.xp_pattern = (char *)pattern; - xpc.xp_pattern_len = STRLEN(xpc.xp_pattern); + xpc.xp_pattern_len = strlen(xpc.xp_pattern); xpc.xp_context = cmdcomplete_str_to_type(type); if (xpc.xp_context == EXPAND_NOTHING) { semsg(_(e_invarg2), type); @@ -2881,17 +2880,17 @@ void f_getcompletion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (xpc.xp_context == EXPAND_MENUS) { set_context_in_menu_cmd(&xpc, "menu", xpc.xp_pattern, false); - xpc.xp_pattern_len = STRLEN(xpc.xp_pattern); + xpc.xp_pattern_len = strlen(xpc.xp_pattern); } if (xpc.xp_context == EXPAND_CSCOPE) { set_context_in_cscope_cmd(&xpc, (const char *)xpc.xp_pattern, CMD_cscope); - xpc.xp_pattern_len = STRLEN(xpc.xp_pattern); + 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); + xpc.xp_pattern_len = strlen(xpc.xp_pattern); } theend: diff --git a/src/nvim/cmdhist.c b/src/nvim/cmdhist.c index 38353f44b5..5a59f09113 100644 --- a/src/nvim/cmdhist.c +++ b/src/nvim/cmdhist.c @@ -91,7 +91,7 @@ static char *(history_names[]) = { char *get_history_arg(expand_T *xp, int idx) { const char *short_names = ":=@>?/"; - const int short_names_count = (int)STRLEN(short_names); + const int short_names_count = (int)strlen(short_names); const int history_name_count = ARRAY_SIZE(history_names) - 1; if (idx < short_names_count) { @@ -186,7 +186,7 @@ static inline void clear_hist_entry(histentry_T *hisptr) /// If 'move_to_front' is true, matching entry is moved to end of history. /// /// @param move_to_front Move the entry to the front if it exists -static int in_history(int type, char_u *str, int move_to_front, int sep) +static int in_history(int type, char *str, int move_to_front, int sep) { int last_i = -1; @@ -201,8 +201,8 @@ static int in_history(int type, char_u *str, int move_to_front, int sep) // For search history, check that the separator character matches as // well. - char_u *p = (char_u *)history[type][i].hisstr; - if (STRCMP(str, p) == 0 + char *p = history[type][i].hisstr; + if (strcmp(str, p) == 0 && (type != HIST_SEARCH || sep == p[STRLEN(p) + 1])) { if (!move_to_front) { return true; @@ -217,7 +217,7 @@ static int in_history(int type, char_u *str, int move_to_front, int sep) if (last_i >= 0) { list_T *const list = history[type][i].additional_elements; - str = (char_u *)history[type][i].hisstr; + str = history[type][i].hisstr; while (i != hisidx[type]) { if (++i >= hislen) { i = 0; @@ -227,7 +227,7 @@ static int in_history(int type, char_u *str, int move_to_front, int sep) } tv_list_unref(list); history[type][i].hisnum = ++hisnum[type]; - history[type][i].hisstr = (char *)str; + history[type][i].hisstr = str; history[type][i].timestamp = os_time(); history[type][i].additional_elements = NULL; return true; @@ -304,7 +304,7 @@ void add_to_history(int histype, char *new_entry, int in_map, int sep) } last_maptick = -1; } - if (!in_history(histype, (char_u *)new_entry, true, sep)) { + if (!in_history(histype, new_entry, true, sep)) { if (++hisidx[histype] == hislen) { hisidx[histype] = 0; } @@ -312,7 +312,7 @@ void add_to_history(int histype, char *new_entry, int in_map, int sep) hist_free_entry(hisptr); // Store the separator after the NUL of the string. - size_t len = STRLEN(new_entry); + size_t len = strlen(new_entry); hisptr->hisstr = xstrnsave(new_entry, len + 2); hisptr->timestamp = os_time(); hisptr->additional_elements = NULL; @@ -644,8 +644,8 @@ void ex_history(exarg_T *eap) snprintf((char *)IObuff, IOSIZE, "%c%6d ", i == idx ? '>' : ' ', hist[i].hisnum); if (vim_strsize(hist[i].hisstr) > Columns - 10) { - trunc_string(hist[i].hisstr, (char *)IObuff + STRLEN(IObuff), - Columns - 10, IOSIZE - (int)STRLEN(IObuff)); + trunc_string(hist[i].hisstr, (char *)IObuff + strlen(IObuff), + Columns - 10, IOSIZE - (int)strlen(IObuff)); } else { STRCAT(IObuff, hist[i].hisstr); } diff --git a/src/nvim/cursor.c b/src/nvim/cursor.c index cd651fcf4c..6c0475822b 100644 --- a/src/nvim/cursor.c +++ b/src/nvim/cursor.c @@ -67,7 +67,7 @@ int coladvance_force(colnr_T wcol) /// Try to advance the Cursor to the specified screen column. /// If virtual editing: fine tune the cursor position. /// Note that all virtual positions off the end of a line should share -/// a curwin->w_cursor.col value (n.b. this is equal to STRLEN(line)), +/// a curwin->w_cursor.col value (n.b. this is equal to strlen(line)), /// beginning at coladd 0. /// /// @return OK if desired column is reached, FAIL if not @@ -346,7 +346,7 @@ void check_cursor_col_win(win_T *win) colnr_T oldcoladd = win->w_cursor.col + win->w_cursor.coladd; unsigned int cur_ve_flags = get_ve_flags(); - colnr_T len = (colnr_T)STRLEN(ml_get_buf(win->w_buffer, win->w_cursor.lnum, false)); + colnr_T len = (colnr_T)strlen(ml_get_buf(win->w_buffer, win->w_cursor.lnum, false)); if (len == 0) { win->w_cursor.col = 0; } else if (win->w_cursor.col >= len) { @@ -412,7 +412,7 @@ void check_visual_pos(void) VIsual.col = 0; VIsual.coladd = 0; } else { - int len = (int)STRLEN(ml_get(VIsual.lnum)); + int len = (int)strlen(ml_get(VIsual.lnum)); if (VIsual.col > len) { VIsual.col = len; diff --git a/src/nvim/cursor_shape.c b/src/nvim/cursor_shape.c index 73ad99876a..6f4f17659a 100644 --- a/src/nvim/cursor_shape.c +++ b/src/nvim/cursor_shape.c @@ -220,7 +220,7 @@ char *parse_shape_opt(int what) endp = vim_strchr(p, '-'); if (commap == NULL) { // last part if (endp == NULL) { - endp = p + STRLEN(p); // find end of part + endp = p + strlen(p); // find end of part } } else if (endp > commap || endp == NULL) { endp = commap; diff --git a/src/nvim/debugger.c b/src/nvim/debugger.c index b720628e33..8adeb19082 100644 --- a/src/nvim/debugger.c +++ b/src/nvim/debugger.c @@ -128,10 +128,15 @@ void do_debug(char *cmd) ignore_script = true; } + // don't debug any function call, e.g. from an expresion mapping + n = debug_break_level; + debug_break_level = -1; + xfree(cmdline); cmdline = getcmdline_prompt('>', NULL, 0, EXPAND_NOTHING, NULL, CALLBACK_NONE); + debug_break_level = n; if (typeahead_saved) { restore_typeahead(&typeaheadbuf); ignore_script = save_ignore_script; @@ -646,7 +651,7 @@ void ex_breakdel(exarg_T *eap) for (int i = 0; i < gap->ga_len; i++) { bpi = &DEBUGGY(gap, i); if (bp->dbg_type == bpi->dbg_type - && STRCMP(bp->dbg_name, bpi->dbg_name) == 0 + && strcmp(bp->dbg_name, bpi->dbg_name) == 0 && (bp->dbg_lnum == bpi->dbg_lnum || (bp->dbg_lnum == 0 && (best_lnum == 0 diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c index 778f9293fb..5a1708a57c 100644 --- a/src/nvim/decoration.c +++ b/src/nvim/decoration.c @@ -75,12 +75,11 @@ void decor_redraw(buf_T *buf, int row1, int row2, Decoration *decor) } if (decor && decor_virt_pos(*decor)) { - redraw_buf_line_later(buf, row1 + 1); + redraw_buf_line_later(buf, row1 + 1, false); } if (decor && kv_size(decor->virt_lines)) { - redraw_buf_line_later(buf, MIN(buf->b_ml.ml_line_count, - row1 + 1 + (decor->virt_lines_above?0:1))); + redraw_buf_line_later(buf, row1 + 1 + (decor->virt_lines_above?0:1), true); } } diff --git a/src/nvim/diff.c b/src/nvim/diff.c index 69883966ab..9446d35630 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -592,9 +592,9 @@ static void diff_check_unchanged(tabpage_T *tp, diff_T *dp) break; } - if (diff_cmp((char_u *)line_org, (char_u *)ml_get_buf(tp->tp_diffbuf[i_new], - dp->df_lnum[i_new] + off_new, - false)) != 0) { + if (diff_cmp(line_org, ml_get_buf(tp->tp_diffbuf[i_new], + dp->df_lnum[i_new] + off_new, + false)) != 0) { break; } } @@ -729,7 +729,7 @@ static int diff_write_buffer(buf_T *buf, diffin_T *din) // xdiff requires one big block of memory with all the text. for (linenr_T lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) { - len += (long)STRLEN(ml_get_buf(buf, lnum, false)) + 1; + len += (long)strlen(ml_get_buf(buf, lnum, false)) + 1; } char_u *ptr = try_malloc((size_t)len); if (ptr == NULL) { @@ -1128,7 +1128,7 @@ static int diff_file(diffio_T *dio) return diff_file_internal(dio); } else { const size_t len = (strlen(tmp_orig) + strlen(tmp_new) + strlen(tmp_diff) - + STRLEN(p_srr) + 27); + + strlen(p_srr) + 27); char *const cmd = xmalloc(len); // We don't want $DIFF_OPTIONS to get in the way. @@ -1267,7 +1267,7 @@ void ex_diffpatch(exarg_T *eap) emsg(_("E816: Cannot read patch output")); } else { if (curbuf->b_fname != NULL) { - newname = xstrnsave(curbuf->b_fname, STRLEN(curbuf->b_fname) + 4); + newname = xstrnsave(curbuf->b_fname, strlen(curbuf->b_fname) + 4); STRCAT(newname, ".new"); } @@ -1429,7 +1429,7 @@ void diff_win_options(win_T *wp, int addbuf) free_string_option(wp->w_p_fdc); wp->w_p_fdc = xstrdup("2"); assert(diff_foldcolumn >= 0 && diff_foldcolumn <= 9); - snprintf(wp->w_p_fdc, STRLEN(wp->w_p_fdc) + 1, "%d", diff_foldcolumn); + snprintf(wp->w_p_fdc, strlen(wp->w_p_fdc) + 1, "%d", diff_foldcolumn); wp->w_p_fen = true; wp->w_p_fdl = 0; foldUpdateAll(wp); @@ -1923,8 +1923,8 @@ static bool diff_equal_entry(diff_T *dp, int idx1, int idx2) char *line = xstrdup(ml_get_buf(curtab->tp_diffbuf[idx1], dp->df_lnum[idx1] + i, false)); - int cmp = diff_cmp((char_u *)line, (char_u *)ml_get_buf(curtab->tp_diffbuf[idx2], - dp->df_lnum[idx2] + i, false)); + int cmp = diff_cmp(line, ml_get_buf(curtab->tp_diffbuf[idx2], + dp->df_lnum[idx2] + i, false)); xfree(line); if (cmp != 0) { @@ -1968,23 +1968,23 @@ static bool diff_equal_char(const char_u *const p1, const char_u *const p2, int /// @param s2 The second string /// /// @return on-zero if the two strings are different. -static int diff_cmp(char_u *s1, char_u *s2) +static int diff_cmp(char *s1, char *s2) { if ((diff_flags & DIFF_IBLANK) - && (*(char_u *)skipwhite((char *)s1) == NUL || *skipwhite((char *)s2) == NUL)) { + && (*(char_u *)skipwhite(s1) == NUL || *skipwhite(s2) == NUL)) { return 0; } if ((diff_flags & (DIFF_ICASE | ALL_WHITE_DIFF)) == 0) { - return STRCMP(s1, s2); + return strcmp(s1, s2); } if ((diff_flags & DIFF_ICASE) && !(diff_flags & ALL_WHITE_DIFF)) { return mb_stricmp((const char *)s1, (const char *)s2); } - char *p1 = (char *)s1; - char *p2 = (char *)s2; + char *p1 = s1; + char *p2 = s2; // Ignore white space changes and possibly ignore case. while (*p1 != NUL && *p2 != NUL) { @@ -2356,8 +2356,8 @@ bool diff_find_change(win_T *wp, linenr_T lnum, int *startp, int *endp) // Search for end of difference, if any. if ((line_org[si_org] != NUL) || (line_new[si_new] != NUL)) { - ei_org = (int)STRLEN(line_org); - ei_new = (int)STRLEN(line_new); + ei_org = (int)strlen(line_org); + ei_new = (int)strlen(line_new); while (ei_org >= *startp && ei_new >= si_new @@ -2564,7 +2564,7 @@ void ex_diffgetput(exarg_T *eap) } } else { // Buffer number or pattern given. Ignore trailing white space. - p = eap->arg + STRLEN(eap->arg); + p = eap->arg + strlen(eap->arg); while (p > eap->arg && ascii_iswhite(p[-1])) { p--; } diff --git a/src/nvim/digraph.c b/src/nvim/digraph.c index 8e31d3feab..c0e7a6250e 100644 --- a/src/nvim/digraph.c +++ b/src/nvim/digraph.c @@ -1926,7 +1926,7 @@ void f_digraph_get(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (digraphs == NULL) { return; } - if (STRLEN(digraphs) != 2) { + if (strlen(digraphs) != 2) { semsg(_(e_digraph_must_be_just_two_characters_str), digraphs); return; } @@ -2036,7 +2036,7 @@ char *keymap_init(void) // Source the keymap file. It will contain a ":loadkeymap" command // which will call ex_loadkeymap() below. - buflen = STRLEN(curbuf->b_p_keymap) + STRLEN(p_enc) + 14; + buflen = strlen(curbuf->b_p_keymap) + strlen(p_enc) + 14; buf = xmalloc(buflen); // try finding "keymap/'keymap'_'encoding'.vim" in 'runtimepath' @@ -2102,7 +2102,7 @@ void ex_loadkeymap(exarg_T *eap) s = skiptowhite(p); kp->to = xstrnsave(p, (size_t)(s - p)); - if ((STRLEN(kp->from) + STRLEN(kp->to) >= KMAP_LLEN) + if ((strlen(kp->from) + strlen(kp->to) >= KMAP_LLEN) || (*kp->from == NUL) || (*kp->to == NUL)) { if (*kp->to == NUL) { diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 9de8b9996a..5c3fa3d3b0 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -894,7 +894,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } else { // Long line, use only the last SPWORDLEN bytes. nextlinecol = (int)v - SPWORDLEN; - memmove(nextline, line + nextlinecol, SPWORDLEN); // -V512 + memmove(nextline, line + nextlinecol, SPWORDLEN); // -V1086 nextline_idx = SPWORDLEN + 1; } } @@ -2638,6 +2638,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // When the window is too narrow draw all "@" lines. if (draw_state != WL_LINE && filler_todo <= 0) { win_draw_end(wp, '@', ' ', true, row, wp->w_grid.rows, HLF_AT); + set_empty_rows(wp, row); row = endrow; } diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c index 5b83821927..c95f3f3550 100644 --- a/src/nvim/drawscreen.c +++ b/src/nvim/drawscreen.c @@ -389,6 +389,10 @@ int update_screen(int type) diff_redraw(true); } + // TODO(bfredl): completely get rid of using update_screen(UPD_XX_VALID) + // to redraw curwin + int curwin_type = MIN(type, UPD_NOT_VALID); + if (must_redraw) { if (type < must_redraw) { // use maximal type type = must_redraw; @@ -445,9 +449,11 @@ int update_screen(int type) } if (msg_use_msgsep()) { msg_grid.throttled = false; + bool was_invalidated = false; + // UPD_CLEAR is already handled if (type == UPD_NOT_VALID && !ui_has(kUIMultigrid) && msg_scrolled) { - ui_comp_set_screen_valid(false); + was_invalidated = ui_comp_set_screen_valid(false); for (int i = valid; i < Rows - p_ch; i++) { grid_clear_line(&default_grid, default_grid.line_offset[i], Columns, false); @@ -457,6 +463,8 @@ int update_screen(int type) continue; } if (W_ENDROW(wp) > valid) { + // TODO(bfredl): too pessimistic. type could be UPD_NOT_VALID + // only because windows that are above the separator. wp->w_redr_type = MAX(wp->w_redr_type, UPD_NOT_VALID); } if (!is_stl_global && W_ENDROW(wp) + wp->w_status_height > valid) { @@ -469,9 +477,16 @@ int update_screen(int type) } msg_grid_set_pos(Rows - (int)p_ch, false); msg_grid_invalid = false; + if (was_invalidated) { + // screen was only invalid for the msgarea part. + // @TODO(bfredl): using the same "valid" flag + // for both messages and floats moving is bit of a mess. + ui_comp_set_screen_valid(true); + } } else if (type != UPD_CLEAR) { if (msg_scrolled > Rows - 5) { // redrawing is faster type = UPD_NOT_VALID; + curwin_type = UPD_NOT_VALID; } else { check_for_delay(false); grid_ins_lines(&default_grid, 0, msg_scrolled, Rows, 0, Columns); @@ -506,7 +521,7 @@ int update_screen(int type) need_wait_return = false; } - win_ui_flush(); + win_ui_flush(true); msg_ext_check_clear(); // reset cmdline_row now (may have been changed temporarily) @@ -553,6 +568,8 @@ int update_screen(int type) // Force redraw when width of 'number' or 'relativenumber' column // changes. + // TODO(bfredl): special casing curwin here is SÅ JÄVLA BULL. + // Either this should be done for all windows or not at all. if (curwin->w_redr_type < UPD_NOT_VALID && curwin->w_nrwidth != ((curwin->w_p_nu || curwin->w_p_rnu) ? number_width(curwin) : 0)) { @@ -560,22 +577,25 @@ int update_screen(int type) } // Only start redrawing if there is really something to do. - if (type == UPD_INVERTED) { + // TODO(bfredl): more curwin special casing to get rid of. + // Change update_screen(UPD_INVERTED) to a wrapper function + // perhaps? + if (curwin_type == UPD_INVERTED) { update_curswant(); } - if (curwin->w_redr_type < type - && !((type == UPD_VALID + if (curwin->w_redr_type < curwin_type + && !((curwin_type == UPD_VALID && curwin->w_lines[0].wl_valid && curwin->w_topfill == curwin->w_old_topfill && curwin->w_botfill == curwin->w_old_botfill && curwin->w_topline == curwin->w_lines[0].wl_lnum) - || (type == UPD_INVERTED + || (curwin_type == UPD_INVERTED && VIsual_active && curwin->w_old_cursor_lnum == curwin->w_cursor.lnum && curwin->w_old_visual_mode == VIsual_mode && (curwin->w_valid & VALID_VIRTCOL) && curwin->w_old_curswant == curwin->w_curswant))) { - curwin->w_redr_type = type; + curwin->w_redr_type = curwin_type; } // Redraw the tab pages line if needed. @@ -998,6 +1018,9 @@ win_update_start: bool scrolled_down = false; // true when scrolled down when w_topline got smaller a bit bool top_to_mod = false; // redraw above mod_top + int bot_scroll_start = 999; // first line that needs to be redrawn due to + // scrolling. only used for EOB + int row; // current window row to display linenr_T lnum; // current buffer lnum to display int idx; // current index in w_lines[] @@ -1022,7 +1045,9 @@ win_update_start: type = wp->w_redr_type; if (type >= UPD_NOT_VALID) { + // TODO(bfredl): should only be implied for CLEAR, not NOT_VALID! wp->w_redr_status = true; + wp->w_lines_valid = 0; } @@ -1173,6 +1198,7 @@ win_update_start: mod_bot = MAXLNUM; } } + wp->w_redraw_top = 0; // reset for next time wp->w_redraw_bot = 0; @@ -1243,6 +1269,7 @@ win_update_start: // If not the last window, delete the lines at the bottom. // win_ins_lines may fail when the terminal can't do it. win_scroll_lines(wp, 0, i); + bot_scroll_start = 0; if (wp->w_lines_valid != 0) { // Need to update rows that are new, stop at the // first one that scrolled down. @@ -1303,6 +1330,7 @@ win_update_start: if (row > 0) { win_scroll_lines(wp, 0, -row); bot_start = wp->w_grid.rows - row; + bot_scroll_start = bot_start; } if ((row == 0 || bot_start < 999) && wp->w_lines_valid != 0) { // Skip the lines (below the deleted lines) that are still @@ -1448,7 +1476,7 @@ win_update_start: pos.lnum += cursor_above ? 1 : -1) { colnr_T t; - pos.col = (colnr_T)STRLEN(ml_get_buf(wp->w_buffer, pos.lnum, false)); + pos.col = (colnr_T)strlen(ml_get_buf(wp->w_buffer, pos.lnum, false)); getvvcol(wp, &pos, NULL, NULL, &t); if (toc < t) { toc = t; @@ -1680,6 +1708,7 @@ win_update_start: // need to redraw until the end of the window. // Inserting/deleting lines has no use. bot_start = 0; + bot_scroll_start = 0; } else { // Able to count old number of rows: Count new window // rows, and may insert/delete lines @@ -1710,6 +1739,7 @@ win_update_start: } else { win_scroll_lines(wp, row, xtra_rows); bot_start = wp->w_grid.rows + xtra_rows; + bot_scroll_start = bot_start; } } else if (xtra_rows > 0) { // May scroll text down. If there is not enough @@ -1719,6 +1749,7 @@ win_update_start: mod_bot = MAXLNUM; } else { win_scroll_lines(wp, row + old_rows, xtra_rows); + bot_scroll_start = 0; if (top_end > row + old_rows) { // Scrolled the part at the top that requires // updating down. @@ -1908,6 +1939,7 @@ win_update_start: wp->w_botline = lnum; } else { win_draw_end(wp, '@', ' ', true, srow, wp->w_grid.rows, HLF_AT); + set_empty_rows(wp, srow); wp->w_botline = lnum; } } else { @@ -1928,8 +1960,18 @@ win_update_start: // Make sure the rest of the screen is blank. // write the "eob" character from 'fillchars' to rows that aren't part // of the file. - win_draw_end(wp, wp->w_p_fcs_chars.eob, ' ', false, row, wp->w_grid.rows, + // TODO(bfredl): just keep track of the valid EOB area from last redraw? + int lastline = bot_scroll_start; + if (mid_end >= row) { + lastline = MIN(lastline, mid_start); + } + if (mod_bot > buf->b_ml.ml_line_count + 1) { + lastline = 0; + } + + win_draw_end(wp, wp->w_p_fcs_chars.eob, ' ', false, MAX(lastline, row), wp->w_grid.rows, HLF_EOB); + set_empty_rows(wp, row); } kvi_destroy(line_providers); @@ -2041,12 +2083,14 @@ void redraw_buf_later(buf_T *buf, int type) } } -void redraw_buf_line_later(buf_T *buf, linenr_T line) +void redraw_buf_line_later(buf_T *buf, linenr_T line, bool force) { FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { - if (wp->w_buffer == buf - && line >= wp->w_topline && line < wp->w_botline) { - redrawWinline(wp, line); + if (wp->w_buffer == buf) { + redrawWinline(wp, MIN(line, buf->b_ml.ml_line_count)); + if (force && line > buf->b_ml.ml_line_count) { + wp->w_redraw_bot = line; + } } } } diff --git a/src/nvim/edit.c b/src/nvim/edit.c index f7a16abfb2..a165078bdf 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -1773,7 +1773,7 @@ void truncate_spaces(char *line) int i; // find start of trailing white space - for (i = (int)STRLEN(line) - 1; i >= 0 && ascii_iswhite(line[i]); i--) { + for (i = (int)strlen(line) - 1; i >= 0 && ascii_iswhite(line[i]); i--) { if (State & REPLACE_FLAG) { replace_join(0); // remove a NUL from the replace stack } @@ -2676,7 +2676,7 @@ int stuff_inserted(int c, long count, int no_esc) // when the last char is either "0" or "^" it will be quoted if no ESC // comes after it OR if it will inserted more than once and "ptr" // starts with ^D. -- Acevedo - last_ptr = (esc_ptr ? esc_ptr : ptr + STRLEN(ptr)) - 1; + last_ptr = (esc_ptr ? esc_ptr : ptr + strlen(ptr)) - 1; if (last_ptr >= ptr && (*last_ptr == '0' || *last_ptr == '^') && (no_esc || (*ptr == Ctrl_D && count > 1))) { last = *last_ptr; @@ -2938,7 +2938,7 @@ static void replace_do_bs(int limit_col) } (void)del_char_after_col(limit_col); if (l_State & VREPLACE_FLAG) { - orig_len = (int)STRLEN(get_cursor_pos_ptr()); + orig_len = (int)strlen(get_cursor_pos_ptr()); } replace_push(cc); replace_pop_ins(); @@ -3856,7 +3856,7 @@ static bool ins_bs(int c, int mode, int *inserted_space_p) return false; } Insstart.lnum--; - Insstart.col = (colnr_T)STRLEN(ml_get(Insstart.lnum)); + Insstart.col = (colnr_T)strlen(ml_get(Insstart.lnum)); } // In replace mode: // cc < 0: NL was inserted, delete it @@ -4674,7 +4674,7 @@ bool ins_eol(int c) // NL in reverse insert will always start in the end of current line. if (revins_on) { - curwin->w_cursor.col += (colnr_T)STRLEN(get_cursor_pos_ptr()); + curwin->w_cursor.col += (colnr_T)strlen(get_cursor_pos_ptr()); } AppendToRedobuff(NL_STR); @@ -4951,7 +4951,7 @@ static char_u *do_insert_char_pre(int c) // Get the value of v:char. It may be empty or more than one // character. Only use it when changed, otherwise continue with the // original character to avoid breaking autoindent. - if (STRCMP(buf, get_vim_var_str(VV_CHAR)) != 0) { + if (strcmp(buf, get_vim_var_str(VV_CHAR)) != 0) { res = xstrdup(get_vim_var_str(VV_CHAR)); } } diff --git a/src/nvim/eval.c b/src/nvim/eval.c index aa2849279e..c2a7b6bba5 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -358,7 +358,7 @@ void eval_init(void) for (size_t i = 0; i < ARRAY_SIZE(vimvars); i++) { struct vimvar *p = &vimvars[i]; - assert(STRLEN(p->vv_name) <= VIMVAR_KEY_LEN); + assert(strlen(p->vv_name) <= VIMVAR_KEY_LEN); STRCPY(p->vv_di.di_key, p->vv_name); if (p->vv_flags & VV_RO) { p->vv_di.di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; @@ -578,7 +578,7 @@ void var_redir_str(char *value, int value_len) int len; if (value_len == -1) { - len = (int)STRLEN(value); // Append the entire string + len = (int)strlen(value); // Append the entire string } else { len = value_len; // Append only "value_len" characters } @@ -757,7 +757,7 @@ int eval_expr_typval(const typval_T *expr, typval_T *argv, int argc, typval_T *r if (s == NULL || *s == NUL) { return FAIL; } - funcexe.evaluate = true; + funcexe.fe_evaluate = true; if (call_func(s, -1, rettv, argc, argv, &funcexe) == FAIL) { return FAIL; } @@ -767,8 +767,8 @@ int eval_expr_typval(const typval_T *expr, typval_T *argv, int argc, typval_T *r if (s == NULL || *s == NUL) { return FAIL; } - funcexe.evaluate = true; - funcexe.partial = partial; + funcexe.fe_evaluate = true; + funcexe.fe_partial = partial; if (call_func(s, -1, rettv, argc, argv, &funcexe) == FAIL) { return FAIL; } @@ -1078,7 +1078,7 @@ int call_vim_function(const char *func, int argc, typval_T *argv, typval_T *rett FUNC_ATTR_NONNULL_ALL { int ret; - int len = (int)STRLEN(func); + int len = (int)strlen(func); partial_T *pt = NULL; if (len >= 6 && !memcmp(func, "v:lua.", 6)) { @@ -1093,10 +1093,10 @@ int call_vim_function(const char *func, int argc, typval_T *argv, typval_T *rett rettv->v_type = VAR_UNKNOWN; // tv_clear() uses this. funcexe_T funcexe = FUNCEXE_INIT; - funcexe.firstline = curwin->w_cursor.lnum; - funcexe.lastline = curwin->w_cursor.lnum; - funcexe.evaluate = true; - funcexe.partial = pt; + funcexe.fe_firstline = curwin->w_cursor.lnum; + funcexe.fe_lastline = curwin->w_cursor.lnum; + funcexe.fe_evaluate = true; + funcexe.fe_partial = pt; ret = call_func(func, len, rettv, argc, argv, &funcexe); fail: @@ -1667,7 +1667,7 @@ void set_var_lval(lval_T *lp, char *endp, typval_T *rettv, int copy, const bool // handle +=, -=, *=, /=, %= and .= di = NULL; - if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name), + if (get_var_tv(lp->ll_name, (int)strlen(lp->ll_name), &tv, &di, true, false) == OK) { if ((di == NULL || (!var_check_ro(di->di_flags, lp->ll_name, TV_CSTRING) @@ -1960,7 +1960,7 @@ void set_context_for_expression(expand_T *xp, char *arg, cmdidx_T cmdidx) xp->xp_context = EXPAND_USER_VARS; if (strpbrk(arg, "\"'+-*/%.=!?~|&$([<>,#") == NULL) { // ":let var1 var2 ...": find last space. - for (p = arg + STRLEN(arg); p >= arg;) { + for (p = arg + strlen(arg); p >= arg;) { xp->xp_pattern = p; MB_PTR_BACK(arg, p); if (ascii_iswhite(*p)) { @@ -2077,7 +2077,7 @@ static size_t varnamebuflen = 0; char *cat_prefix_varname(int prefix, const char *name) FUNC_ATTR_NONNULL_ALL { - size_t len = STRLEN(name) + 3; + size_t len = strlen(name) + 3; if (len > varnamebuflen) { xfree(varnamebuf); @@ -2227,11 +2227,11 @@ static int eval_func(char **const arg, char *const name, const int name_len, typ // Invoke the function. funcexe_T funcexe = FUNCEXE_INIT; - funcexe.firstline = curwin->w_cursor.lnum; - funcexe.lastline = curwin->w_cursor.lnum; - funcexe.evaluate = evaluate; - funcexe.partial = partial; - funcexe.basetv = basetv; + funcexe.fe_firstline = curwin->w_cursor.lnum; + funcexe.fe_lastline = curwin->w_cursor.lnum; + funcexe.fe_evaluate = evaluate; + funcexe.fe_partial = partial; + funcexe.fe_basetv = basetv; int ret = get_func_tv((char_u *)s, len, rettv, arg, &funcexe); xfree(s); @@ -3211,12 +3211,12 @@ static int call_func_rettv(char **const arg, typval_T *const rettv, const bool e } funcexe_T funcexe = FUNCEXE_INIT; - funcexe.firstline = curwin->w_cursor.lnum; - funcexe.lastline = curwin->w_cursor.lnum; - funcexe.evaluate = evaluate; - funcexe.partial = pt; - funcexe.selfdict = selfdict; - funcexe.basetv = basetv; + funcexe.fe_firstline = curwin->w_cursor.lnum; + funcexe.fe_lastline = curwin->w_cursor.lnum; + funcexe.fe_evaluate = evaluate; + funcexe.fe_partial = pt; + funcexe.fe_selfdict = selfdict; + funcexe.fe_basetv = basetv; const int ret = get_func_tv((char_u *)funcname, is_lua ? (int)(*arg - funcname) : -1, rettv, arg, &funcexe); @@ -3828,7 +3828,7 @@ static int get_string_tv(char **arg, typval_T *rettv, int evaluate) if (p[1] != '*') { flags |= FSK_SIMPLIFY; } - extra = trans_special((const char_u **)&p, STRLEN(p), (char_u *)name, flags, false, NULL); + extra = trans_special((const char_u **)&p, strlen(p), (char_u *)name, flags, false, NULL); if (extra != 0) { name += extra; if (name >= rettv->vval.v_string + len) { @@ -3998,13 +3998,11 @@ failret: bool func_equal(typval_T *tv1, typval_T *tv2, bool ic) { // empty and NULL function name considered the same - char_u *s1 = - (char_u *)(tv1->v_type == VAR_FUNC ? tv1->vval.v_string : partial_name(tv1->vval.v_partial)); + char *s1 = tv1->v_type == VAR_FUNC ? tv1->vval.v_string : partial_name(tv1->vval.v_partial); if (s1 != NULL && *s1 == NUL) { s1 = NULL; } - char_u *s2 = - (char_u *)(tv2->v_type == VAR_FUNC ? tv2->vval.v_string : partial_name(tv2->vval.v_partial)); + char *s2 = tv2->v_type == VAR_FUNC ? tv2->vval.v_string : partial_name(tv2->vval.v_partial); if (s2 != NULL && *s2 == NUL) { s2 = NULL; } @@ -4012,7 +4010,7 @@ bool func_equal(typval_T *tv1, typval_T *tv2, bool ic) if (s1 != s2) { return false; } - } else if (STRCMP(s1, s2) != 0) { + } else if (strcmp(s1, s2) != 0) { return false; } @@ -5021,7 +5019,7 @@ void common_function(typval_T *argvars, typval_T *rettv, bool is_funcref) // printable text. snprintf(sid_buf, sizeof(sid_buf), "<SNR>%" PRId64 "_", (int64_t)current_sctx.sc_sid); - name = xmalloc(STRLEN(sid_buf) + STRLEN(s + off) + 1); + name = xmalloc(strlen(sid_buf) + strlen(s + off) + 1); STRCPY(name, sid_buf); STRCAT(name, s + off); } else { @@ -5596,10 +5594,10 @@ void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append, const typval_T if (!append && lnum <= curbuf->b_ml.ml_line_count) { // Existing line, replace it. - int old_len = (int)STRLEN(ml_get(lnum)); + int old_len = (int)strlen(ml_get(lnum)); if (u_savesub(lnum) == OK && ml_replace(lnum, (char *)line, true) == OK) { - inserted_bytes(lnum, 0, old_len, (int)STRLEN(line)); + inserted_bytes(lnum, 0, old_len, (int)strlen(line)); if (is_curbuf && lnum == curwin->w_cursor.lnum) { check_cursor_col(); } @@ -5840,7 +5838,7 @@ bool callback_call(Callback *const callback, const int argcount_in, typval_T *co switch (callback->type) { case kCallbackFuncref: name = callback->data.funcref; - int len = (int)STRLEN(name); + int len = (int)strlen(name); if (len >= 6 && !memcmp(name, "v:lua.", 6)) { name += 6; len = check_luafunc_name(name, false); @@ -5871,10 +5869,10 @@ bool callback_call(Callback *const callback, const int argcount_in, typval_T *co } funcexe_T funcexe = FUNCEXE_INIT; - funcexe.firstline = curwin->w_cursor.lnum; - funcexe.lastline = curwin->w_cursor.lnum; - funcexe.evaluate = true; - funcexe.partial = partial; + funcexe.fe_firstline = curwin->w_cursor.lnum; + funcexe.fe_lastline = curwin->w_cursor.lnum; + funcexe.fe_evaluate = true; + funcexe.fe_partial = partial; return call_func(name, -1, rettv, argcount_in, argvars_in, &funcexe); } @@ -6367,14 +6365,14 @@ pos_T *var2fpos(const typval_T *const tv, const bool dollar_lnum, int *const ret if (charcol) { len = mb_charlen((char_u *)ml_get(pos.lnum)); } else { - len = (int)STRLEN(ml_get(pos.lnum)); + len = (int)strlen(ml_get(pos.lnum)); } // We accept "$" for the column number: last column. listitem_T *li = tv_list_find(l, 1L); if (li != NULL && TV_LIST_ITEM_TV(li)->v_type == VAR_STRING && TV_LIST_ITEM_TV(li)->vval.v_string != NULL - && STRCMP(TV_LIST_ITEM_TV(li)->vval.v_string, "$") == 0) { + && strcmp(TV_LIST_ITEM_TV(li)->vval.v_string, "$") == 0) { pos.col = len + 1; } @@ -6453,7 +6451,7 @@ pos_T *var2fpos(const typval_T *const tv, const bool dollar_lnum, int *const ret if (charcol) { pos.col = (colnr_T)mb_charlen((char_u *)get_cursor_line_ptr()); } else { - pos.col = (colnr_T)STRLEN(get_cursor_line_ptr()); + pos.col = (colnr_T)strlen(get_cursor_line_ptr()); } } return &pos; @@ -6623,7 +6621,7 @@ int get_name_len(const char **const arg, char **alias, bool evaluate, bool verbo } *alias = temp_string; *arg = (const char *)skipwhite(p); - return (int)STRLEN(temp_string); + return (int)strlen(temp_string); } len += get_id_len(arg); @@ -6749,7 +6747,7 @@ static char *make_expanded_name(const char *in_start, char *expr_start, char *ex char *temp_result = eval_to_string(expr_start + 1, &nextcmd, false); if (temp_result != NULL && nextcmd == NULL) { - retval = xmalloc(STRLEN(temp_result) + (size_t)(expr_start - in_start) + retval = xmalloc(strlen(temp_result) + (size_t)(expr_start - in_start) + (size_t)(in_end - expr_end) + 1); STRCPY(retval, in_start); STRCAT(retval, temp_result); @@ -7017,7 +7015,7 @@ char *set_cmdarg(exarg_T *eap, char *oldarg) len += 10; // " ++ff=unix" } if (eap->force_enc != 0) { - len += STRLEN(eap->cmd + eap->force_enc) + 7; + len += strlen(eap->cmd + eap->force_enc) + 7; } if (eap->bad_char != 0) { len += 7 + 4; // " ++bad=" + "keep" or "drop" @@ -7039,20 +7037,20 @@ char *set_cmdarg(exarg_T *eap, char *oldarg) } if (eap->force_ff != 0) { - snprintf(newval + STRLEN(newval), newval_len, " ++ff=%s", + snprintf(newval + strlen(newval), newval_len, " ++ff=%s", eap->force_ff == 'u' ? "unix" : eap->force_ff == 'd' ? "dos" : "mac"); } if (eap->force_enc != 0) { - snprintf(newval + STRLEN(newval), newval_len, " ++enc=%s", + snprintf(newval + strlen(newval), newval_len, " ++enc=%s", eap->cmd + eap->force_enc); } if (eap->bad_char == BAD_KEEP) { - STRCPY(newval + STRLEN(newval), " ++bad=keep"); + STRCPY(newval + strlen(newval), " ++bad=keep"); } else if (eap->bad_char == BAD_DROP) { - STRCPY(newval + STRLEN(newval), " ++bad=drop"); + STRCPY(newval + strlen(newval), " ++bad=drop"); } else if (eap->bad_char != 0) { - snprintf(newval + STRLEN(newval), newval_len, " ++bad=%c", + snprintf(newval + strlen(newval), newval_len, " ++bad=%c", eap->bad_char); } vimvars[VV_CMDARG].vv_str = newval; @@ -7822,7 +7820,7 @@ bool script_autoload(const char *const name, const size_t name_len, const bool r // "autoload/", it's always the same. int i = 0; for (; i < ga_loaded.ga_len; i++) { - if (STRCMP(((char **)ga_loaded.ga_data)[i] + 9, scriptname + 9) == 0) { + if (strcmp(((char **)ga_loaded.ga_data)[i] + 9, scriptname + 9) == 0) { break; } } @@ -8075,7 +8073,7 @@ repeat: // Append a path separator to a directory. if (os_isdir(*fnamep)) { // Make room for one or two extra characters. - *fnamep = xstrnsave(*fnamep, STRLEN(*fnamep) + 2); + *fnamep = xstrnsave(*fnamep, strlen(*fnamep) + 2); xfree(*bufp); // free any allocated file name *bufp = *fnamep; add_pathsep(*fnamep); @@ -8115,11 +8113,11 @@ repeat: home_replace(NULL, s, dirname, MAXPATHL, true); xfree(s); } - size_t namelen = STRLEN(dirname); + size_t namelen = strlen(dirname); // Do not call shorten_fname() here since it removes the prefix // even though the path does not have a prefix. - if (FNAMENCMP(p, dirname, namelen) == 0) { + if (path_fnamencmp(p, dirname, namelen) == 0) { p += namelen; if (vim_ispathsep(*p)) { while (*p && vim_ispathsep(*p)) { @@ -8151,7 +8149,7 @@ repeat: } char *tail = path_tail(*fnamep); - *fnamelen = STRLEN(*fnamep); + *fnamelen = strlen(*fnamep); // ":h" - head, remove "/file_name", can be repeated // Don't remove the first "/" or "c:\" @@ -8268,7 +8266,7 @@ repeat: *usedlen = (size_t)(p + 1 - src); s = do_string_sub(str, pat, sub, NULL, flags); *fnamep = s; - *fnamelen = STRLEN(s); + *fnamelen = strlen(s); xfree(*bufp); *bufp = s; didit = true; @@ -8296,7 +8294,7 @@ repeat: } xfree(*bufp); *bufp = *fnamep = p; - *fnamelen = STRLEN(p); + *fnamelen = strlen(p); *usedlen += 2; } @@ -8327,11 +8325,11 @@ char *do_string_sub(char *str, char *pat, char *sub, typval_T *expr, char *flags regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING); if (regmatch.regprog != NULL) { char *tail = str; - char *end = str + STRLEN(str); + char *end = str + strlen(str); while (vim_regexec_nl(®match, (char_u *)str, (colnr_T)(tail - str))) { // Skip empty match except for first match. if (regmatch.startp[0] == regmatch.endp[0]) { - if ((char_u *)zero_width == regmatch.startp[0]) { + if (zero_width == regmatch.startp[0]) { // avoid getting stuck on a match with an empty string int i = utfc_ptr2len(tail); memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i); @@ -8339,7 +8337,7 @@ char *do_string_sub(char *str, char *pat, char *sub, typval_T *expr, char *flags tail += i; continue; } - zero_width = (char *)regmatch.startp[0]; + zero_width = regmatch.startp[0]; } // Get some space for a temporary buffer to do the substitution @@ -8352,14 +8350,14 @@ char *do_string_sub(char *str, char *pat, char *sub, typval_T *expr, char *flags (regmatch.endp[0] - regmatch.startp[0]))); // copy the text up to where the match is - int i = (int)(regmatch.startp[0] - (char_u *)tail); + 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(®match, (char_u *)sub, expr, (char_u *)ga.ga_data + ga.ga_len + i, sublen, REGSUB_COPY | REGSUB_MAGIC); ga.ga_len += i + sublen - 1; - tail = (char *)regmatch.endp[0]; + tail = regmatch.endp[0]; if (*tail == NUL) { break; } @@ -8493,9 +8491,9 @@ typval_T eval_call_provider(char *provider, char *method, list_T *arguments, boo tv_list_ref(arguments); funcexe_T funcexe = FUNCEXE_INIT; - funcexe.firstline = curwin->w_cursor.lnum; - funcexe.lastline = curwin->w_cursor.lnum; - funcexe.evaluate = true; + funcexe.fe_firstline = curwin->w_cursor.lnum; + funcexe.fe_lastline = curwin->w_cursor.lnum; + funcexe.fe_evaluate = true; (void)call_func(func, name_len, &rettv, 2, argvars, &funcexe); tv_list_unref(arguments); @@ -8602,7 +8600,7 @@ void ex_checkhealth(exarg_T *eap) return; } - size_t bufsize = STRLEN(eap->arg) + sizeof("call health#check('')"); + size_t bufsize = strlen(eap->arg) + sizeof("call health#check('')"); char *buf = xmalloc(bufsize); snprintf(buf, bufsize, "call health#check('%s')", eap->arg); @@ -8628,8 +8626,8 @@ void invoke_prompt_callback(void) } char *text = ml_get(lnum); char *prompt = (char *)prompt_text(); - if (STRLEN(text) >= STRLEN(prompt)) { - text += STRLEN(prompt); + if (strlen(text) >= strlen(prompt)) { + text += strlen(prompt); } argv[0].v_type = VAR_STRING; argv[0].vval.v_string = xstrdup(text); diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 3e89489459..837fef23f4 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -236,6 +236,7 @@ return { json_decode={args=1, base=1}, json_encode={args=1, base=1}, keys={args=1, base=1}, + keytrans={args=1, base=1}, last_buffer_nr={}, -- obsolete len={args=1, base=1}, libcall={args=3, base=3}, @@ -425,6 +426,7 @@ return { uniq={args={1, 3}, base=1}, values={args=1, base=1}, virtcol={args=1, base=1}, + virtcol2col={args=3, base=1}, visualmode={args={0, 1}}, wait={args={2,3}}, wildmenumode={}, diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c index bb514fba47..599bbae0f5 100644 --- a/src/nvim/eval/encode.c +++ b/src/nvim/eval/encode.c @@ -219,7 +219,7 @@ bool encode_vim_list_to_buf(const list_T *const list, size_t *const ret_len, cha } len++; if (TV_LIST_ITEM_TV(li)->vval.v_string != NULL) { - len += STRLEN(TV_LIST_ITEM_TV(li)->vval.v_string); + len += strlen(TV_LIST_ITEM_TV(li)->vval.v_string); } }); if (len) { @@ -281,7 +281,7 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s state->offset = 0; state->li_length = (TV_LIST_ITEM_TV(state->li)->vval.v_string == NULL ? 0 - : STRLEN(TV_LIST_ITEM_TV(state->li)->vval.v_string)); + : strlen(TV_LIST_ITEM_TV(state->li)->vval.v_string)); } } *read_bytes = nbuf; diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 408b6e6cb5..9ba2ce2365 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -195,15 +195,15 @@ int call_internal_func(const char_u *const fname, const int argcount, typval_T * { const EvalFuncDef *const fdef = find_internal_func((const char *)fname); if (fdef == NULL) { - return ERROR_UNKNOWN; + return FCERR_UNKNOWN; } else if (argcount < fdef->min_argc) { - return ERROR_TOOFEW; + return FCERR_TOOFEW; } else if (argcount > fdef->max_argc) { - return ERROR_TOOMANY; + return FCERR_TOOMANY; } argvars[argcount].v_type = VAR_UNKNOWN; fdef->func(argvars, rettv, fdef->data); - return ERROR_NONE; + return FCERR_NONE; } /// Invoke a method for base->method(). @@ -213,13 +213,13 @@ int call_internal_method(const char_u *const fname, const int argcount, typval_T { const EvalFuncDef *const fdef = find_internal_func((const char *)fname); if (fdef == NULL) { - return ERROR_UNKNOWN; + return FCERR_UNKNOWN; } else if (fdef->base_arg == BASE_NONE) { - return ERROR_NOTMETHOD; + return FCERR_NOTMETHOD; } else if (argcount + 1 < fdef->min_argc) { - return ERROR_TOOFEW; + return FCERR_TOOFEW; } else if (argcount + 1 > fdef->max_argc) { - return ERROR_TOOMANY; + return FCERR_TOOMANY; } typval_T argv[MAX_FUNC_ARGS + 1]; @@ -231,7 +231,7 @@ int call_internal_method(const char_u *const fname, const int argcount, typval_T argv[argcount + 1].v_type = VAR_UNKNOWN; fdef->func(argv, rettv, fdef->data); - return ERROR_NONE; + return FCERR_NONE; } /// @return true for a non-zero Number and a non-empty String. @@ -423,7 +423,7 @@ static buf_T *find_buffer(typval_T *avar) FOR_ALL_BUFFERS(bp) { if (bp->b_fname != NULL && (path_with_url(bp->b_fname) || bt_nofilename(bp)) - && STRCMP(bp->b_fname, avar->vval.v_string) == 0) { + && strcmp(bp->b_fname, avar->vval.v_string) == 0) { buf = bp; break; } @@ -840,7 +840,7 @@ static void get_col(typval_T *argvars, typval_T *rettv, bool charcol) if (fp->col == MAXCOL) { // '> can be MAXCOL, get the length of the line then if (fp->lnum <= curbuf->b_ml.ml_line_count) { - col = (colnr_T)STRLEN(ml_get(fp->lnum)) + 1; + col = (colnr_T)strlen(ml_get(fp->lnum)) + 1; } else { col = MAXCOL; } @@ -1344,7 +1344,7 @@ static void f_debugbreak(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (pid == 0) { emsg(_(e_invarg)); } else { -#ifdef WIN32 +#ifdef MSWIN HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, pid); if (hProcess != NULL) { @@ -1695,7 +1695,7 @@ static void f_environ(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) char c = env[i][len]; env[i][len] = NUL; -#ifdef WIN32 +#ifdef MSWIN // Upper-case all the keys for Windows so we can detect duplicates char *const key = strcase_save(str, true); #else @@ -1772,7 +1772,7 @@ static void f_eventhandler(typval_T *argvars, typval_T *rettv, EvalFuncData fptr /// "executable()" function static void f_executable(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - if (tv_check_for_string(&argvars[0]) == FAIL) { + if (tv_check_for_string_arg(argvars, 0) == FAIL) { return; } @@ -1901,7 +1901,7 @@ static void f_win_execute(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// "exepath()" function static void f_exepath(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - if (tv_check_for_nonempty_string(&argvars[0]) == FAIL) { + if (tv_check_for_nonempty_string_arg(argvars, 0) == FAIL) { return; } @@ -3532,7 +3532,7 @@ static void f_has(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) #ifdef UNIX "unix", #endif -#if defined(WIN32) +#if defined(MSWIN) "win32", #endif #ifdef _WIN64 @@ -4257,7 +4257,7 @@ static void f_jobresize(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } static const char *ignored_env_vars[] = { -#ifndef WIN32 +#ifndef MSWIN "COLUMNS", "LINES", "TERMCAP", @@ -4269,7 +4269,7 @@ static const char *ignored_env_vars[] = { /// According to comments in src/win/process.c of libuv, Windows has a few /// "essential" environment variables. static const char *required_env_vars[] = { -#ifdef WIN32 +#ifdef MSWIN "HOMEDRIVE", "HOMEPATH", "LOGONSERVER", @@ -4308,7 +4308,7 @@ static dict_T *create_environment(const dictitem_T *job_env, const bool clear_en tv_dict_item_remove(env, dv); } } -#ifndef WIN32 +#ifndef MSWIN // Set COLORTERM to "truecolor" if termguicolors is set and 256 // otherwise, but only if it was set in the parent terminal at all dictitem_T *dv = tv_dict_find(env, S_LEN("COLORTERM")); @@ -4343,7 +4343,7 @@ static dict_T *create_environment(const dictitem_T *job_env, const bool clear_en } if (job_env) { -#ifdef WIN32 +#ifdef MSWIN TV_DICT_ITER(job_env->di_tv.vval.v_dict, var, { // Always use upper-case keys for Windows so we detect duplicate keys char *const key = strcase_save((const char *)var->di_key, true); @@ -4443,7 +4443,7 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) return; } -#ifdef WIN32 +#ifdef MSWIN if (pty && overlapped) { semsg(_(e_invarg2), "job cannot have both 'pty' and 'overlapped' options set"); @@ -4673,6 +4673,20 @@ static void f_json_encode(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) rettv->vval.v_string = encode_tv2json(&argvars[0], NULL); } +/// "keytrans()" function +static void f_keytrans(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + rettv->v_type = VAR_STRING; + if (tv_check_for_string_arg(argvars, 0) == FAIL + || argvars[0].vval.v_string == NULL) { + return; + } + // Need to escape K_SPECIAL for mb_unescape(). + char *escaped = vim_strsave_escape_ks(argvars[0].vval.v_string); + rettv->vval.v_string = str2special_save(escaped, true, true); + xfree(escaped); +} + /// "last_buffer_nr()" function. static void f_last_buffer_nr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { @@ -4984,9 +4998,9 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, li = TV_LIST_ITEM_NEXT(l, li); idx++; } else { - startcol = (colnr_T)(regmatch.startp[0] - + utfc_ptr2len((char *)regmatch.startp[0]) - str); - if (startcol > (colnr_T)len || str + startcol <= regmatch.startp[0]) { + startcol = (colnr_T)((char_u *)regmatch.startp[0] + + utfc_ptr2len(regmatch.startp[0]) - str); + if (startcol > (colnr_T)len || str + startcol <= (char_u *)regmatch.startp[0]) { match = false; break; } @@ -5005,8 +5019,8 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, const size_t rd = (size_t)(regmatch.endp[0] - regmatch.startp[0]); TV_LIST_ITEM_TV(li1)->vval.v_string = xmemdupz((const char *)regmatch.startp[0], rd); - TV_LIST_ITEM_TV(li3)->vval.v_number = (varnumber_T)(regmatch.startp[0] - expr); - TV_LIST_ITEM_TV(li4)->vval.v_number = (varnumber_T)(regmatch.endp[0] - expr); + TV_LIST_ITEM_TV(li3)->vval.v_number = (varnumber_T)((char_u *)regmatch.startp[0] - expr); + TV_LIST_ITEM_TV(li4)->vval.v_number = (varnumber_T)(regmatch.endp[0] - (char *)expr); if (l != NULL) { TV_LIST_ITEM_TV(li2)->vval.v_number = (varnumber_T)idx; } @@ -5041,10 +5055,10 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, } else { if (type == kSomeMatch) { rettv->vval.v_number = - (varnumber_T)(regmatch.startp[0] - str); + (varnumber_T)((char_u *)regmatch.startp[0] - str); } else { rettv->vval.v_number = - (varnumber_T)(regmatch.endp[0] - str); + (varnumber_T)(regmatch.endp[0] - (char *)str); } rettv->vval.v_number += (varnumber_T)(str - expr); } @@ -6225,8 +6239,8 @@ static void f_rename(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) rettv->vval.v_number = -1; } else { char buf[NUMBUFLEN]; - rettv->vval.v_number = vim_rename((const char_u *)tv_get_string(&argvars[0]), - (const char_u *)tv_get_string_buf(&argvars[1], buf)); + rettv->vval.v_number = vim_rename(tv_get_string(&argvars[0]), + tv_get_string_buf(&argvars[1], buf)); } } @@ -6272,7 +6286,7 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { rettv->v_type = VAR_STRING; const char *fname = tv_get_string(&argvars[0]); -#ifdef WIN32 +#ifdef MSWIN char *v = os_resolve_shortcut(fname); if (v == NULL) { if (os_is_reparse_point_include(fname)) { @@ -6484,8 +6498,8 @@ static void f_reduce(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } funcexe_T funcexe = FUNCEXE_INIT; - funcexe.evaluate = true; - funcexe.partial = partial; + funcexe.fe_evaluate = true; + funcexe.fe_partial = partial; typval_T initial; typval_T argv[3]; @@ -7057,32 +7071,6 @@ static void f_screencol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) rettv->vval.v_number = ui_current_col() + 1; } -/// "screenpos({winid}, {lnum}, {col})" function -static void f_screenpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - tv_dict_alloc_ret(rettv); - dict_T *dict = rettv->vval.v_dict; - - win_T *wp = find_win_by_nr_or_id(&argvars[0]); - if (wp == NULL) { - return; - } - - pos_T pos = { - .lnum = (linenr_T)tv_get_number(&argvars[1]), - .col = (colnr_T)tv_get_number(&argvars[2]) - 1, - .coladd = 0 - }; - int row = 0; - int scol = 0, ccol = 0, ecol = 0; - textpos2screenpos(wp, &pos, &row, &scol, &ccol, &ecol, false); - - tv_dict_add_nr(dict, S_LEN("row"), row); - tv_dict_add_nr(dict, S_LEN("col"), scol); - tv_dict_add_nr(dict, S_LEN("curscol"), ccol); - tv_dict_add_nr(dict, S_LEN("endcol"), ecol); -} - /// "screenrow()" function static void f_screenrow(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { @@ -7808,7 +7796,7 @@ free_lstval: if (strval == NULL) { return; } - write_reg_contents_ex(regname, strval, (ssize_t)STRLEN(strval), + write_reg_contents_ex(regname, strval, (ssize_t)strlen(strval), append, yank_type, (colnr_T)block_len); } if (pointreg != 0) { @@ -8193,11 +8181,11 @@ static void f_split(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) break; } // Advance to just after the match. - if (regmatch.endp[0] > (char_u *)str) { + if (regmatch.endp[0] > str) { col = 0; } else { // Don't get stuck at the same match. - col = utfc_ptr2len((char *)regmatch.endp[0]); + col = utfc_ptr2len(regmatch.endp[0]); } str = (const char *)regmatch.endp[0]; } @@ -8377,7 +8365,7 @@ static void f_strgetchar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) return; } - const size_t len = STRLEN(str); + const size_t len = strlen(str); size_t byteidx = 0; while (charidx >= 0 && byteidx < len) { @@ -8483,7 +8471,7 @@ static void f_strwidth(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) static void f_strcharpart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { const char *const p = tv_get_string(&argvars[0]); - const size_t slen = STRLEN(p); + const size_t slen = strlen(p); int nbyte = 0; bool error = false; @@ -8623,7 +8611,7 @@ static void f_strridx(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) return; // Type error; errmsg already given. } - const size_t haystack_len = STRLEN(haystack); + const size_t haystack_len = strlen(haystack); ptrdiff_t end_idx; if (argvars[2].v_type != VAR_UNKNOWN) { // Third argument: upper limit for index. @@ -8754,7 +8742,7 @@ static void f_synID(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) int id = 0; if (!transerr && lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count - && col >= 0 && (size_t)col < STRLEN(ml_get(lnum))) { + && col >= 0 && (size_t)col < strlen(ml_get(lnum))) { id = syn_get_id(curwin, lnum, col, trans, NULL, false); } @@ -8820,7 +8808,7 @@ static void f_synIDattr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } break; case 'u': - if (STRLEN(what) >= 9) { + if (strlen(what) >= 9) { if (TOLOWER_ASC(what[5]) == 'l') { // underline p = highlight_has_attr(id, HL_UNDERLINE, modec); @@ -8879,7 +8867,7 @@ static void f_synconcealed(typval_T *argvars, typval_T *rettv, EvalFuncData fptr CLEAR_FIELD(str); if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count && col >= 0 - && (size_t)col <= STRLEN(ml_get(lnum)) && curwin->w_p_cole > 0) { + && (size_t)col <= strlen(ml_get(lnum)) && curwin->w_p_cole > 0) { (void)syn_get_id(curwin, lnum, col, false, NULL, false); syntax_flags = get_syntax_info(&matchid); @@ -8916,7 +8904,7 @@ static void f_synstack(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count && col >= 0 - && (size_t)col <= STRLEN(ml_get(lnum))) { + && (size_t)col <= strlen(ml_get(lnum))) { tv_list_alloc_ret(rettv, kListLenMayKnow); (void)syn_get_id(curwin, lnum, col, false, NULL, true); @@ -9470,7 +9458,7 @@ static void f_trim(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } } - const char *tail = head + STRLEN(head); + const char *tail = head + strlen(head); if (dir == 0 || dir == 2) { // Trim trailing characters for (; tail > head; tail = prev) { @@ -9578,7 +9566,7 @@ static void f_virtcol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (fp->col < 0) { fp->col = 0; } else { - const size_t len = STRLEN(ml_get(fp->lnum)); + const size_t len = strlen(ml_get(fp->lnum)); if (fp->col > (colnr_T)len) { fp->col = (colnr_T)len; } diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index f6b97fe05b..f9aed7a966 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -40,6 +40,13 @@ # include "eval/typval.c.generated.h" #endif +static char e_string_required_for_argument_nr[] + = N_("E1174: String required for argument %d"); +static char e_non_empty_string_required_for_argument_nr[] + = N_("E1142: Non-empty string required for argument %d"); +static char e_number_required_for_argument_nr[] + = N_("E1210: Number required for argument %d"); + bool tv_in_free_unref_items = false; // TODO(ZyX-I): Remove DICT_MAXNEST, make users be non-recursive instead @@ -1016,7 +1023,7 @@ static int item_compare(const void *s1, const void *s2, bool keep_zero) if (sortinfo->item_compare_lc) { res = strcoll(p1, p2); } else { - res = sortinfo->item_compare_ic ? STRICMP(p1, p2): STRCMP(p1, p2); + res = sortinfo->item_compare_ic ? STRICMP(p1, p2): strcmp(p1, p2); } } else { double n1, n2; @@ -1079,9 +1086,9 @@ static int item_compare2(const void *s1, const void *s2, bool keep_zero) rettv.v_type = VAR_UNKNOWN; // tv_clear() uses this funcexe_T funcexe = FUNCEXE_INIT; - funcexe.evaluate = true; - funcexe.partial = partial; - funcexe.selfdict = sortinfo->item_compare_selfdict; + funcexe.fe_evaluate = true; + funcexe.fe_partial = partial; + funcexe.fe_selfdict = sortinfo->item_compare_selfdict; res = call_func(func_name, -1, &rettv, 2, argv, &funcexe); tv_clear(&argv[0]); tv_clear(&argv[1]); @@ -1568,7 +1575,7 @@ bool tv_callback_equal(const Callback *cb1, const Callback *cb2) } switch (cb1->type) { case kCallbackFuncref: - return STRCMP(cb1->data.funcref, cb2->data.funcref) == 0; + return strcmp(cb1->data.funcref, cb2->data.funcref) == 0; case kCallbackPartial: // FIXME: this is inconsistent with tv_equal but is needed for precision // maybe change dictwatcheradd to return a watcher id instead? @@ -3800,31 +3807,50 @@ float_T tv_get_float(const typval_T *const tv) return 0; } -// Give an error and return FAIL unless "tv" is a string. -int tv_check_for_string(const typval_T *const tv) +/// Give an error and return FAIL unless "args[idx]" is a string. +int tv_check_for_string_arg(const typval_T *const args, const int idx) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE { - if (tv->v_type != VAR_STRING) { - emsg(_(e_stringreq)); + if (args[idx].v_type != VAR_STRING) { + semsg(_(e_string_required_for_argument_nr), idx + 1); return FAIL; } return OK; } -// Give an error and return FAIL unless "tv" is a non-empty string. -int tv_check_for_nonempty_string(const typval_T *const tv) +/// Give an error and return FAIL unless "args[idx]" is a non-empty string. +int tv_check_for_nonempty_string_arg(const typval_T *const args, const int idx) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE { - if (tv_check_for_string(tv) == FAIL) { + if (tv_check_for_string_arg(args, idx) == FAIL) { + return FAIL; + } + if (args[idx].vval.v_string == NULL || *args[idx].vval.v_string == NUL) { + semsg(_(e_non_empty_string_required_for_argument_nr), idx + 1); return FAIL; } - if (tv->vval.v_string == NULL || *tv->vval.v_string == NUL) { - emsg(_(e_non_empty_string_required)); + return OK; +} + +/// Give an error and return FAIL unless "args[idx]" is a number. +int tv_check_for_number_arg(const typval_T *const args, const int idx) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + if (args[idx].v_type != VAR_NUMBER) { + semsg(_(e_number_required_for_argument_nr), idx + 1); return FAIL; } return OK; } +/// Check for an optional number argument at "idx" +int tv_check_for_opt_number_arg(const typval_T *const args, const int idx) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + return (args[idx].v_type == VAR_UNKNOWN + || tv_check_for_number_arg(args, idx) != FAIL) ? OK : FAIL; +} + /// Get the string value of a "stringish" VimL object. /// /// @param[in] tv Object to get value of. diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index 6373ead1a3..0a4adc1f53 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -2,405 +2,19 @@ #define NVIM_EVAL_TYPVAL_H #include <assert.h> -#include <inttypes.h> #include <stdbool.h> #include <stddef.h> #include <string.h> +#include "nvim/eval/typval_defs.h" #include "nvim/func_attr.h" -#include "nvim/garray.h" #include "nvim/gettext.h" -#include "nvim/hashtab.h" -#include "nvim/lib/queue.h" #include "nvim/macros.h" #include "nvim/mbyte_defs.h" #include "nvim/message.h" -#include "nvim/pos.h" // for linenr_T -#include "nvim/types.h" -#ifdef LOG_LIST_ACTIONS -# include "nvim/memory.h" -#endif - -/// Type used for VimL VAR_NUMBER values -typedef int64_t varnumber_T; -typedef uint64_t uvarnumber_T; - -/// Refcount for dict or list that should not be freed -enum { DO_NOT_FREE_CNT = (INT_MAX / 2), }; - -/// Additional values for tv_list_alloc() len argument -enum ListLenSpecials { - /// List length is not known in advance - /// - /// To be used when there is neither a way to know how many elements will be - /// needed nor are any educated guesses. - kListLenUnknown = -1, - /// List length *should* be known, but is actually not - /// - /// All occurrences of this value should be eventually removed. This is for - /// the case when the only reason why list length is not known is that it - /// would be hard to code without refactoring, but refactoring is needed. - kListLenShouldKnow = -2, - /// List length may be known in advance, but it requires too much effort - /// - /// To be used when it looks impractical to determine list length. - kListLenMayKnow = -3, -}; - -/// Maximal possible value of varnumber_T variable -#define VARNUMBER_MAX INT64_MAX -#define UVARNUMBER_MAX UINT64_MAX - -/// Minimal possible value of varnumber_T variable -#define VARNUMBER_MIN INT64_MIN - -/// %d printf format specifier for varnumber_T -#define PRIdVARNUMBER PRId64 - -typedef struct listvar_S list_T; -typedef struct dictvar_S dict_T; -typedef struct partial_S partial_T; -typedef struct blobvar_S blob_T; - -typedef struct ufunc ufunc_T; - -typedef enum { - kCallbackNone = 0, - kCallbackFuncref, - kCallbackPartial, - kCallbackLua, -} CallbackType; - -typedef struct { - union { - char *funcref; - partial_T *partial; - LuaRef luaref; - } data; - CallbackType type; -} Callback; - -#define CALLBACK_INIT { .type = kCallbackNone } -#define CALLBACK_NONE ((Callback)CALLBACK_INIT) - -/// Structure holding dictionary watcher -typedef struct dict_watcher { - Callback callback; - char *key_pattern; - size_t key_pattern_len; - QUEUE node; - bool busy; // prevent recursion if the dict is changed in the callback - bool needs_free; -} DictWatcher; - -/// Bool variable values -typedef enum { - kBoolVarFalse, ///< v:false - kBoolVarTrue, ///< v:true -} BoolVarValue; - -/// Special variable values -typedef enum { - kSpecialVarNull, ///< v:null -} SpecialVarValue; - -/// Variable lock status for typval_T.v_lock -typedef enum { - VAR_UNLOCKED = 0, ///< Not locked. - VAR_LOCKED = 1, ///< User lock, can be unlocked. - VAR_FIXED = 2, ///< Locked forever. -} VarLockStatus; - -/// VimL variable types, for use in typval_T.v_type -typedef enum { - VAR_UNKNOWN = 0, ///< Unknown (unspecified) value. - VAR_NUMBER, ///< Number, .v_number is used. - VAR_STRING, ///< String, .v_string is used. - VAR_FUNC, ///< Function reference, .v_string is used as function name. - VAR_LIST, ///< List, .v_list is used. - VAR_DICT, ///< Dictionary, .v_dict is used. - VAR_FLOAT, ///< Floating-point value, .v_float is used. - VAR_BOOL, ///< true, false - VAR_SPECIAL, ///< Special value (null), .v_special - ///< is used. - VAR_PARTIAL, ///< Partial, .v_partial is used. - VAR_BLOB, ///< Blob, .v_blob is used. -} VarType; - -/// Structure that holds an internal variable value -typedef struct { - VarType v_type; ///< Variable type. - VarLockStatus v_lock; ///< Variable lock status. - union typval_vval_union { - varnumber_T v_number; ///< Number, for VAR_NUMBER. - BoolVarValue v_bool; ///< Bool value, for VAR_BOOL - SpecialVarValue v_special; ///< Special value, for VAR_SPECIAL. - float_T v_float; ///< Floating-point number, for VAR_FLOAT. - char *v_string; ///< String, for VAR_STRING and VAR_FUNC, can be NULL. - list_T *v_list; ///< List for VAR_LIST, can be NULL. - dict_T *v_dict; ///< Dictionary for VAR_DICT, can be NULL. - partial_T *v_partial; ///< Closure: function with args. - blob_T *v_blob; ///< Blob for VAR_BLOB, can be NULL. - } vval; ///< Actual value. -} typval_T; - -/// Values for (struct dictvar_S).dv_scope -typedef enum { - VAR_NO_SCOPE = 0, ///< Not a scope dictionary. - VAR_SCOPE = 1, ///< Scope dictionary which requires prefix (a:, v:, …). - VAR_DEF_SCOPE = 2, ///< Scope dictionary which may be accessed without prefix - ///< (l:, g:). -} ScopeType; - -/// Structure to hold an item of a list -typedef struct listitem_S listitem_T; - -struct listitem_S { - listitem_T *li_next; ///< Next item in list. - listitem_T *li_prev; ///< Previous item in list. - typval_T li_tv; ///< Item value. -}; - -/// Structure used by those that are using an item in a list -typedef struct listwatch_S listwatch_T; - -struct listwatch_S { - listitem_T *lw_item; ///< Item being watched. - listwatch_T *lw_next; ///< Next watcher. -}; - -/// Structure to hold info about a list -/// Order of members is optimized to reduce padding. -struct listvar_S { - listitem_T *lv_first; ///< First item, NULL if none. - listitem_T *lv_last; ///< Last item, NULL if none. - listwatch_T *lv_watch; ///< First watcher, NULL if none. - listitem_T *lv_idx_item; ///< When not NULL item at index "lv_idx". - list_T *lv_copylist; ///< Copied list used by deepcopy(). - list_T *lv_used_next; ///< next list in used lists list. - list_T *lv_used_prev; ///< Previous list in used lists list. - int lv_refcount; ///< Reference count. - int lv_len; ///< Number of items. - int lv_idx; ///< Index of a cached item, used for optimising repeated l[idx]. - int lv_copyID; ///< ID used by deepcopy(). - VarLockStatus lv_lock; ///< Zero, VAR_LOCKED, VAR_FIXED. - - LuaRef lua_table_ref; -}; - -// Static list with 10 items. Use tv_list_init_static10() to initialize. -typedef struct { - list_T sl_list; // must be first - listitem_T sl_items[10]; -} staticList10_T; - -#define TV_LIST_STATIC10_INIT { \ - .sl_list = { \ - .lv_first = NULL, \ - .lv_last = NULL, \ - .lv_refcount = 0, \ - .lv_len = 0, \ - .lv_watch = NULL, \ - .lv_idx_item = NULL, \ - .lv_lock = VAR_FIXED, \ - .lv_used_next = NULL, \ - .lv_used_prev = NULL, \ - }, \ -} - -#define TV_DICTITEM_STRUCT(...) \ - struct { \ - typval_T di_tv; /* Structure that holds scope dictionary itself. */ \ - uint8_t di_flags; /* Flags. */ \ - char_u di_key[__VA_ARGS__]; /* Key value. */ \ - } - -/// Structure to hold a scope dictionary -/// -/// @warning Must be compatible with dictitem_T. -/// -/// For use in find_var_in_ht to pretend that it found dictionary item when it -/// finds scope dictionary. -typedef TV_DICTITEM_STRUCT(1) ScopeDictDictItem; - -/// Structure to hold an item of a Dictionary -/// -/// @warning Must be compatible with ScopeDictDictItem. -/// -/// Also used for a variable. -typedef TV_DICTITEM_STRUCT() dictitem_T; - -/// Flags for dictitem_T.di_flags -typedef enum { - DI_FLAGS_RO = 1, ///< Read-only value - DI_FLAGS_RO_SBX = 2, ///< Value, read-only in the sandbox - DI_FLAGS_FIX = 4, ///< Fixed value: cannot be :unlet or remove()d. - DI_FLAGS_LOCK = 8, ///< Locked value. - DI_FLAGS_ALLOC = 16, ///< Separately allocated. -} DictItemFlags; - -/// Structure representing a Dictionary -struct dictvar_S { - VarLockStatus dv_lock; ///< Whole dictionary lock status. - ScopeType dv_scope; ///< Non-zero (#VAR_SCOPE, #VAR_DEF_SCOPE) if - ///< dictionary represents a scope (i.e. g:, l: …). - int dv_refcount; ///< Reference count. - int dv_copyID; ///< ID used when recursivery traversing a value. - hashtab_T dv_hashtab; ///< Hashtab containing all items. - dict_T *dv_copydict; ///< Copied dict used by deepcopy(). - dict_T *dv_used_next; ///< Next dictionary in used dictionaries list. - dict_T *dv_used_prev; ///< Previous dictionary in used dictionaries list. - QUEUE watchers; ///< Dictionary key watchers set by user code. - - LuaRef lua_table_ref; -}; - -/// Structure to hold info about a Blob -struct blobvar_S { - garray_T bv_ga; ///< Growarray with the data. - int bv_refcount; ///< Reference count. - VarLockStatus bv_lock; ///< VAR_UNLOCKED, VAR_LOCKED, VAR_FIXED. -}; - -/// Type used for script ID -typedef int scid_T; -/// Format argument for scid_T -#define PRIdSCID "d" - -// SCript ConteXt (SCTX): identifies a script line. -// When sourcing a script "sc_lnum" is zero, "sourcing_lnum" is the current -// line number. When executing a user function "sc_lnum" is the line where the -// function was defined, "sourcing_lnum" is the line number inside the -// function. When stored with a function, mapping, option, etc. "sc_lnum" is -// the line number in the script "sc_sid". -typedef struct { - scid_T sc_sid; // script ID - int sc_seq; // sourcing sequence number - linenr_T sc_lnum; // line number -} sctx_T; - -/// Maximum number of function arguments -#define MAX_FUNC_ARGS 20 -/// Short variable name length -#define VAR_SHORT_LEN 20 -/// Number of fixed variables used for arguments -#define FIXVAR_CNT 12 - -// Structure to hold info for a function that is currently being executed. -typedef struct funccall_S funccall_T; - -struct funccall_S { - ufunc_T *func; ///< Function being called. - int linenr; ///< Next line to be executed. - int returned; ///< ":return" used. - /// Fixed variables for arguments. - TV_DICTITEM_STRUCT(VAR_SHORT_LEN + 1) fixvar[FIXVAR_CNT]; - dict_T l_vars; ///< l: local function variables. - ScopeDictDictItem l_vars_var; ///< Variable for l: scope. - dict_T l_avars; ///< a: argument variables. - ScopeDictDictItem l_avars_var; ///< Variable for a: scope. - list_T l_varlist; ///< List for a:000. - listitem_T l_listitems[MAX_FUNC_ARGS]; ///< List items for a:000. - typval_T *rettv; ///< Return value. - linenr_T breakpoint; ///< Next line with breakpoint or zero. - int dbg_tick; ///< Debug_tick when breakpoint was set. - int level; ///< Top nesting level of executed function. - proftime_T prof_child; ///< Time spent in a child. - funccall_T *caller; ///< Calling function or NULL; or next funccal in - ///< list pointed to by previous_funccal. - int fc_refcount; ///< Number of user functions that reference this funccall. - int fc_copyID; ///< CopyID used for garbage collection. - garray_T fc_funcs; ///< List of ufunc_T* which keep a reference to "func". -}; - -/// Structure to hold info for a user function. -struct ufunc { - int uf_varargs; ///< variable nr of arguments - int uf_flags; - int uf_calls; ///< nr of active calls - bool uf_cleared; ///< func_clear() was already called - garray_T uf_args; ///< arguments - garray_T uf_def_args; ///< default argument expressions - garray_T uf_lines; ///< function lines - int uf_profiling; ///< true when func is being profiled - int uf_prof_initialized; - LuaRef uf_luaref; ///< lua callback, used if (uf_flags & FC_LUAREF) - // Profiling the function as a whole. - int uf_tm_count; ///< nr of calls - proftime_T uf_tm_total; ///< time spent in function + children - proftime_T uf_tm_self; ///< time spent in function itself - proftime_T uf_tm_children; ///< time spent in children this call - // Profiling the function per line. - int *uf_tml_count; ///< nr of times line was executed - proftime_T *uf_tml_total; ///< time spent in a line + children - proftime_T *uf_tml_self; ///< time spent in a line itself - proftime_T uf_tml_start; ///< start time for current line - proftime_T uf_tml_children; ///< time spent in children for this line - proftime_T uf_tml_wait; ///< start wait time for current line - int uf_tml_idx; ///< index of line being timed; -1 if none - int uf_tml_execed; ///< line being timed was executed - sctx_T uf_script_ctx; ///< SCTX where function was defined, - ///< 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 - ///< "<SNR>" as a string, otherwise NULL - char_u uf_name[]; ///< Name of function (actual size equals name); - ///< can start with <SNR>123_ - ///< (<SNR> is K_SPECIAL KS_EXTRA KE_SNR) -}; - -struct partial_S { - int pt_refcount; ///< Reference count. - char *pt_name; ///< Function name; when NULL use pt_func->name. - ufunc_T *pt_func; ///< Function pointer; when NULL lookup function with pt_name. - bool pt_auto; ///< When true the partial was created by using dict.member - ///< in handle_subscript(). - int pt_argc; ///< Number of arguments. - typval_T *pt_argv; ///< Arguments in allocated array. - dict_T *pt_dict; ///< Dict for "self". -}; - -/// Structure used for explicit stack while garbage collecting hash tables -typedef struct ht_stack_S { - hashtab_T *ht; - struct ht_stack_S *prev; -} ht_stack_T; - -/// Structure used for explicit stack while garbage collecting lists -typedef struct list_stack_S { - list_T *list; - struct list_stack_S *prev; -} list_stack_T; - -/// Structure representing one list item, used for sort array. -typedef struct { - listitem_T *item; ///< Sorted list item. - int idx; ///< Sorted list item index. -} ListSortItem; - -typedef int (*ListSorter)(const void *, const void *); #ifdef LOG_LIST_ACTIONS - -/// List actions log entry -typedef struct { - uintptr_t l; ///< List log entry belongs to. - uintptr_t li1; ///< First list item log entry belongs to, if applicable. - uintptr_t li2; ///< Second list item log entry belongs to, if applicable. - int len; ///< List length when log entry was created. - const char *action; ///< Logged action. -} ListLogEntry; - -typedef struct list_log ListLog; - -/// List actions log -struct list_log { - ListLog *next; ///< Next chunk or NULL. - size_t capacity; ///< Number of entries in current chunk. - size_t size; ///< Current chunk size. - ListLogEntry entries[]; ///< Actual log entries. -}; +# include "nvim/memory.h" extern ListLog *list_log_first; ///< First list log chunk, NULL if missing extern ListLog *list_log_last; ///< Last list log chunk @@ -780,12 +394,6 @@ static inline void tv_init(typval_T *const tv) } } -#define TV_INITIAL_VALUE \ - ((typval_T) { \ - .v_type = VAR_UNKNOWN, \ - .v_lock = VAR_UNLOCKED, \ - }) - /// Empty string /// /// Needed for hack which allows not allocating empty string and still not @@ -884,9 +492,6 @@ static inline bool tv_get_float_chk(const typval_T *const tv, float_T *const ret_f) REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT; -// FIXME circular dependency, cannot import message.h. -bool semsg(const char *const fmt, ...); - /// Get the float value /// /// Raises an error if object is not number or floating-point. diff --git a/src/nvim/eval/typval_defs.h b/src/nvim/eval/typval_defs.h new file mode 100644 index 0000000000..1c0a438751 --- /dev/null +++ b/src/nvim/eval/typval_defs.h @@ -0,0 +1,399 @@ +#ifndef NVIM_EVAL_TYPVAL_DEFS_H +#define NVIM_EVAL_TYPVAL_DEFS_H + +#include <inttypes.h> +#include <limits.h> + +#include "nvim/garray.h" +#include "nvim/hashtab.h" +#include "nvim/lib/queue.h" +#include "nvim/pos.h" +#include "nvim/types.h" + +/// Type used for VimL VAR_NUMBER values +typedef int64_t varnumber_T; +typedef uint64_t uvarnumber_T; + +/// Refcount for dict or list that should not be freed +enum { DO_NOT_FREE_CNT = (INT_MAX / 2), }; + +/// Additional values for tv_list_alloc() len argument +enum ListLenSpecials { + /// List length is not known in advance + /// + /// To be used when there is neither a way to know how many elements will be + /// needed nor are any educated guesses. + kListLenUnknown = -1, + /// List length *should* be known, but is actually not + /// + /// All occurrences of this value should be eventually removed. This is for + /// the case when the only reason why list length is not known is that it + /// would be hard to code without refactoring, but refactoring is needed. + kListLenShouldKnow = -2, + /// List length may be known in advance, but it requires too much effort + /// + /// To be used when it looks impractical to determine list length. + kListLenMayKnow = -3, +}; + +/// Maximal possible value of varnumber_T variable +#define VARNUMBER_MAX INT64_MAX +#define UVARNUMBER_MAX UINT64_MAX + +/// Minimal possible value of varnumber_T variable +#define VARNUMBER_MIN INT64_MIN + +/// %d printf format specifier for varnumber_T +#define PRIdVARNUMBER PRId64 + +typedef struct listvar_S list_T; +typedef struct dictvar_S dict_T; +typedef struct partial_S partial_T; +typedef struct blobvar_S blob_T; + +typedef struct ufunc ufunc_T; + +typedef enum { + kCallbackNone = 0, + kCallbackFuncref, + kCallbackPartial, + kCallbackLua, +} CallbackType; + +typedef struct { + union { + char *funcref; + partial_T *partial; + LuaRef luaref; + } data; + CallbackType type; +} Callback; + +#define CALLBACK_INIT { .type = kCallbackNone } +#define CALLBACK_NONE ((Callback)CALLBACK_INIT) + +/// Structure holding dictionary watcher +typedef struct dict_watcher { + Callback callback; + char *key_pattern; + size_t key_pattern_len; + QUEUE node; + bool busy; // prevent recursion if the dict is changed in the callback + bool needs_free; +} DictWatcher; + +/// Bool variable values +typedef enum { + kBoolVarFalse, ///< v:false + kBoolVarTrue, ///< v:true +} BoolVarValue; + +/// Special variable values +typedef enum { + kSpecialVarNull, ///< v:null +} SpecialVarValue; + +/// Variable lock status for typval_T.v_lock +typedef enum { + VAR_UNLOCKED = 0, ///< Not locked. + VAR_LOCKED = 1, ///< User lock, can be unlocked. + VAR_FIXED = 2, ///< Locked forever. +} VarLockStatus; + +/// VimL variable types, for use in typval_T.v_type +typedef enum { + VAR_UNKNOWN = 0, ///< Unknown (unspecified) value. + VAR_NUMBER, ///< Number, .v_number is used. + VAR_STRING, ///< String, .v_string is used. + VAR_FUNC, ///< Function reference, .v_string is used as function name. + VAR_LIST, ///< List, .v_list is used. + VAR_DICT, ///< Dictionary, .v_dict is used. + VAR_FLOAT, ///< Floating-point value, .v_float is used. + VAR_BOOL, ///< true, false + VAR_SPECIAL, ///< Special value (null), .v_special is used. + VAR_PARTIAL, ///< Partial, .v_partial is used. + VAR_BLOB, ///< Blob, .v_blob is used. +} VarType; + +/// Structure that holds an internal variable value +typedef struct { + VarType v_type; ///< Variable type. + VarLockStatus v_lock; ///< Variable lock status. + union typval_vval_union { + varnumber_T v_number; ///< Number, for VAR_NUMBER. + BoolVarValue v_bool; ///< Bool value, for VAR_BOOL + SpecialVarValue v_special; ///< Special value, for VAR_SPECIAL. + float_T v_float; ///< Floating-point number, for VAR_FLOAT. + char *v_string; ///< String, for VAR_STRING and VAR_FUNC, can be NULL. + list_T *v_list; ///< List for VAR_LIST, can be NULL. + dict_T *v_dict; ///< Dictionary for VAR_DICT, can be NULL. + partial_T *v_partial; ///< Closure: function with args. + blob_T *v_blob; ///< Blob for VAR_BLOB, can be NULL. + } vval; ///< Actual value. +} typval_T; + +#define TV_INITIAL_VALUE \ + ((typval_T) { \ + .v_type = VAR_UNKNOWN, \ + .v_lock = VAR_UNLOCKED, \ + }) + +/// Values for (struct dictvar_S).dv_scope +typedef enum { + VAR_NO_SCOPE = 0, ///< Not a scope dictionary. + VAR_SCOPE = 1, ///< Scope dictionary which requires prefix (a:, v:, …). + VAR_DEF_SCOPE = 2, ///< Scope dictionary which may be accessed without prefix + ///< (l:, g:). +} ScopeType; + +/// Structure to hold an item of a list +typedef struct listitem_S listitem_T; + +struct listitem_S { + listitem_T *li_next; ///< Next item in list. + listitem_T *li_prev; ///< Previous item in list. + typval_T li_tv; ///< Item value. +}; + +/// Structure used by those that are using an item in a list +typedef struct listwatch_S listwatch_T; + +struct listwatch_S { + listitem_T *lw_item; ///< Item being watched. + listwatch_T *lw_next; ///< Next watcher. +}; + +/// Structure to hold info about a list +/// Order of members is optimized to reduce padding. +struct listvar_S { + listitem_T *lv_first; ///< First item, NULL if none. + listitem_T *lv_last; ///< Last item, NULL if none. + listwatch_T *lv_watch; ///< First watcher, NULL if none. + listitem_T *lv_idx_item; ///< When not NULL item at index "lv_idx". + list_T *lv_copylist; ///< Copied list used by deepcopy(). + list_T *lv_used_next; ///< next list in used lists list. + list_T *lv_used_prev; ///< Previous list in used lists list. + int lv_refcount; ///< Reference count. + int lv_len; ///< Number of items. + int lv_idx; ///< Index of a cached item, used for optimising repeated l[idx]. + int lv_copyID; ///< ID used by deepcopy(). + VarLockStatus lv_lock; ///< Zero, VAR_LOCKED, VAR_FIXED. + + LuaRef lua_table_ref; +}; + +/// Static list with 10 items. Use tv_list_init_static10() to initialize. +typedef struct { + list_T sl_list; // must be first + listitem_T sl_items[10]; +} staticList10_T; + +#define TV_LIST_STATIC10_INIT { \ + .sl_list = { \ + .lv_first = NULL, \ + .lv_last = NULL, \ + .lv_refcount = 0, \ + .lv_len = 0, \ + .lv_watch = NULL, \ + .lv_idx_item = NULL, \ + .lv_lock = VAR_FIXED, \ + .lv_used_next = NULL, \ + .lv_used_prev = NULL, \ + }, \ +} + +#define TV_DICTITEM_STRUCT(...) \ + struct { \ + typval_T di_tv; /* Structure that holds scope dictionary itself. */ \ + uint8_t di_flags; /* Flags. */ \ + char_u di_key[__VA_ARGS__]; /* Key value. */ \ + } + +/// Structure to hold a scope dictionary +/// +/// @warning Must be compatible with dictitem_T. +/// +/// For use in find_var_in_ht to pretend that it found dictionary item when it +/// finds scope dictionary. +typedef TV_DICTITEM_STRUCT(1) ScopeDictDictItem; + +/// Structure to hold an item of a Dictionary +/// +/// @warning Must be compatible with ScopeDictDictItem. +/// +/// Also used for a variable. +typedef TV_DICTITEM_STRUCT() dictitem_T; + +/// Flags for dictitem_T.di_flags +typedef enum { + DI_FLAGS_RO = 1, ///< Read-only value + DI_FLAGS_RO_SBX = 2, ///< Value, read-only in the sandbox + DI_FLAGS_FIX = 4, ///< Fixed value: cannot be :unlet or remove()d. + DI_FLAGS_LOCK = 8, ///< Locked value. + DI_FLAGS_ALLOC = 16, ///< Separately allocated. +} DictItemFlags; + +/// Structure representing a Dictionary +struct dictvar_S { + VarLockStatus dv_lock; ///< Whole dictionary lock status. + ScopeType dv_scope; ///< Non-zero (#VAR_SCOPE, #VAR_DEF_SCOPE) if + ///< dictionary represents a scope (i.e. g:, l: …). + int dv_refcount; ///< Reference count. + int dv_copyID; ///< ID used when recursivery traversing a value. + hashtab_T dv_hashtab; ///< Hashtab containing all items. + dict_T *dv_copydict; ///< Copied dict used by deepcopy(). + dict_T *dv_used_next; ///< Next dictionary in used dictionaries list. + dict_T *dv_used_prev; ///< Previous dictionary in used dictionaries list. + QUEUE watchers; ///< Dictionary key watchers set by user code. + + LuaRef lua_table_ref; +}; + +/// Structure to hold info about a Blob +struct blobvar_S { + garray_T bv_ga; ///< Growarray with the data. + int bv_refcount; ///< Reference count. + VarLockStatus bv_lock; ///< VAR_UNLOCKED, VAR_LOCKED, VAR_FIXED. +}; + +/// Type used for script ID +typedef int scid_T; +/// Format argument for scid_T +#define PRIdSCID "d" + +/// SCript ConteXt (SCTX): identifies a script line. +/// When sourcing a script "sc_lnum" is zero, "sourcing_lnum" is the current +/// line number. When executing a user function "sc_lnum" is the line where the +/// function was defined, "sourcing_lnum" is the line number inside the +/// function. When stored with a function, mapping, option, etc. "sc_lnum" is +/// the line number in the script "sc_sid". +typedef struct { + scid_T sc_sid; ///< script ID + int sc_seq; ///< sourcing sequence number + linenr_T sc_lnum; ///< line number +} sctx_T; + +/// Maximum number of function arguments +enum { MAX_FUNC_ARGS = 20, }; +/// Short variable name length +enum { VAR_SHORT_LEN = 20, }; +/// Number of fixed variables used for arguments +enum { FIXVAR_CNT = 12, }; + +/// Structure to hold info for a function that is currently being executed. +typedef struct funccall_S funccall_T; + +struct funccall_S { + ufunc_T *func; ///< Function being called. + int linenr; ///< Next line to be executed. + int returned; ///< ":return" used. + /// Fixed variables for arguments. + TV_DICTITEM_STRUCT(VAR_SHORT_LEN + 1) fixvar[FIXVAR_CNT]; + dict_T l_vars; ///< l: local function variables. + ScopeDictDictItem l_vars_var; ///< Variable for l: scope. + dict_T l_avars; ///< a: argument variables. + ScopeDictDictItem l_avars_var; ///< Variable for a: scope. + list_T l_varlist; ///< List for a:000. + listitem_T l_listitems[MAX_FUNC_ARGS]; ///< List items for a:000. + typval_T *rettv; ///< Return value. + linenr_T breakpoint; ///< Next line with breakpoint or zero. + int dbg_tick; ///< debug_tick when breakpoint was set. + int level; ///< Top nesting level of executed function. + proftime_T prof_child; ///< Time spent in a child. + funccall_T *caller; ///< Calling function or NULL; or next funccal in + ///< list pointed to by previous_funccal. + int fc_refcount; ///< Number of user functions that reference this funccall. + int fc_copyID; ///< CopyID used for garbage collection. + garray_T fc_funcs; ///< List of ufunc_T* which keep a reference to "func". +}; + +/// Structure to hold info for a user function. +struct ufunc { + int uf_varargs; ///< variable nr of arguments + int uf_flags; + int uf_calls; ///< nr of active calls + bool uf_cleared; ///< func_clear() was already called + garray_T uf_args; ///< arguments + garray_T uf_def_args; ///< default argument expressions + garray_T uf_lines; ///< function lines + int uf_profiling; ///< true when func is being profiled + int uf_prof_initialized; + LuaRef uf_luaref; ///< lua callback, used if (uf_flags & FC_LUAREF) + // Profiling the function as a whole. + int uf_tm_count; ///< nr of calls + proftime_T uf_tm_total; ///< time spent in function + children + proftime_T uf_tm_self; ///< time spent in function itself + proftime_T uf_tm_children; ///< time spent in children this call + // Profiling the function per line. + int *uf_tml_count; ///< nr of times line was executed + proftime_T *uf_tml_total; ///< time spent in a line + children + proftime_T *uf_tml_self; ///< time spent in a line itself + proftime_T uf_tml_start; ///< start time for current line + proftime_T uf_tml_children; ///< time spent in children for this line + proftime_T uf_tml_wait; ///< start wait time for current line + int uf_tml_idx; ///< index of line being timed; -1 if none + int uf_tml_execed; ///< line being timed was executed + sctx_T uf_script_ctx; ///< SCTX where function was defined, + ///< 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 + ///< "<SNR>" as a string, otherwise NULL + char_u uf_name[]; ///< Name of function (actual size equals name); + ///< can start with <SNR>123_ + ///< (<SNR> is K_SPECIAL KS_EXTRA KE_SNR) +}; + +struct partial_S { + int pt_refcount; ///< Reference count. + char *pt_name; ///< Function name; when NULL use pt_func->name. + ufunc_T *pt_func; ///< Function pointer; when NULL lookup function with pt_name. + bool pt_auto; ///< When true the partial was created by using dict.member + ///< in handle_subscript(). + int pt_argc; ///< Number of arguments. + typval_T *pt_argv; ///< Arguments in allocated array. + dict_T *pt_dict; ///< Dict for "self". +}; + +/// Structure used for explicit stack while garbage collecting hash tables +typedef struct ht_stack_S { + hashtab_T *ht; + struct ht_stack_S *prev; +} ht_stack_T; + +/// Structure used for explicit stack while garbage collecting lists +typedef struct list_stack_S { + list_T *list; + struct list_stack_S *prev; +} list_stack_T; + +/// Structure representing one list item, used for sort array. +typedef struct { + listitem_T *item; ///< Sorted list item. + int idx; ///< Sorted list item index. +} ListSortItem; + +typedef int (*ListSorter)(const void *, const void *); + +#ifdef LOG_LIST_ACTIONS +/// List actions log entry +typedef struct { + uintptr_t l; ///< List log entry belongs to. + uintptr_t li1; ///< First list item log entry belongs to, if applicable. + uintptr_t li2; ///< Second list item log entry belongs to, if applicable. + int len; ///< List length when log entry was created. + const char *action; ///< Logged action. +} ListLogEntry; + +typedef struct list_log ListLog; + +/// List actions log +struct list_log { + ListLog *next; ///< Next chunk or NULL. + size_t capacity; ///< Number of entries in current chunk. + size_t size; ///< Current chunk size. + ListLogEntry entries[]; ///< Actual log entries. +}; +#endif + +#endif // NVIM_EVAL_TYPVAL_DEFS_H diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index a899e1579b..f28af5a6cc 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -111,7 +111,7 @@ static int get_function_args(char **argp, char_u endchar, garray_T *newargs, int // Check for duplicate argument name. for (i = 0; i < newargs->ga_len; i++) { - if (STRCMP(((char **)(newargs->ga_data))[i], arg) == 0) { + if (strcmp(((char **)(newargs->ga_data))[i], arg) == 0) { semsg(_("E853: Duplicate argument name: %s"), arg); xfree(arg); goto err_ret; @@ -425,12 +425,12 @@ int get_func_tv(const char_u *name, int len, typval_T *rettv, char **arg, funcex // Get the arguments. argp = *arg; while (argcount < MAX_FUNC_ARGS - - (funcexe->partial == NULL ? 0 : funcexe->partial->pt_argc)) { + - (funcexe->fe_partial == NULL ? 0 : funcexe->fe_partial->pt_argc)) { argp = skipwhite(argp + 1); // skip the '(' or ',' if (*argp == ')' || *argp == ',' || *argp == NUL) { break; } - if (eval1(&argp, &argvars[argcount], funcexe->evaluate) == FAIL) { + if (eval1(&argp, &argvars[argcount], funcexe->fe_evaluate) == FAIL) { ret = FAIL; break; } @@ -524,18 +524,18 @@ static char *fname_trans_sid(const char *const name, char *const fname_buf, char int i = 3; if (eval_fname_sid(name)) { // "<SID>" or "s:" if (current_sctx.sc_sid <= 0) { - *error = ERROR_SCRIPT; + *error = FCERR_SCRIPT; } else { snprintf(fname_buf + i, (size_t)(FLEN_FIXED + 1 - i), "%" PRId64 "_", (int64_t)current_sctx.sc_sid); - i = (int)STRLEN(fname_buf); + i = (int)strlen(fname_buf); } } - if ((size_t)i + STRLEN(name + llen) < FLEN_FIXED) { + if ((size_t)i + strlen(name + llen) < FLEN_FIXED) { STRCPY(fname_buf + i, name + llen); fname = fname_buf; } else { - fname = xmalloc((size_t)i + STRLEN(name + llen) + 1); + fname = xmalloc((size_t)i + strlen(name + llen) + 1); *tofree = fname; memmove(fname, fname_buf, (size_t)i); STRCPY(fname + i, name + llen); @@ -1199,6 +1199,34 @@ static bool func_name_refcount(char_u *name) return isdigit(*name) || *name == '<'; } +/// Call a user function after checking the arguments. +static int call_user_func_check(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, + funcexe_T *funcexe, dict_T *selfdict) + FUNC_ATTR_NONNULL_ARG(1, 3, 4, 5) +{ + if (fp->uf_flags & FC_LUAREF) { + return typval_exec_lua_callable(fp->uf_luaref, argcount, argvars, rettv); + } + + if ((fp->uf_flags & FC_RANGE) && funcexe->fe_doesrange != NULL) { + *funcexe->fe_doesrange = true; + } + int error; + if (argcount < fp->uf_args.ga_len - fp->uf_def_args.ga_len) { + error = FCERR_TOOFEW; + } else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len) { + error = FCERR_TOOMANY; + } else if ((fp->uf_flags & FC_DICT) && selfdict == NULL) { + error = FCERR_DICT; + } else { + // Call the user function. + call_user_func(fp, argcount, argvars, rettv, funcexe->fe_firstline, funcexe->fe_lastline, + (fp->uf_flags & FC_DICT) ? selfdict : NULL); + error = FCERR_NONE; + } + return error; +} + static funccal_entry_T *funccal_stack = NULL; /// Save the current function call pointer, and set it to NULL. @@ -1339,11 +1367,11 @@ int func_call(char_u *name, typval_T *args, partial_T *partial, dict_T *selfdict }); funcexe_T funcexe = FUNCEXE_INIT; - funcexe.firstline = curwin->w_cursor.lnum; - funcexe.lastline = curwin->w_cursor.lnum; - funcexe.evaluate = true; - funcexe.partial = partial; - funcexe.selfdict = selfdict; + funcexe.fe_firstline = curwin->w_cursor.lnum; + funcexe.fe_lastline = curwin->w_cursor.lnum; + funcexe.fe_evaluate = true; + funcexe.fe_partial = partial; + funcexe.fe_selfdict = selfdict; r = call_func((char *)name, -1, rettv, argc, argv, &funcexe); func_call_skip_call: @@ -1361,27 +1389,27 @@ static void user_func_error(int error, const char_u *name) FUNC_ATTR_NONNULL_ALL { switch (error) { - case ERROR_UNKNOWN: + case FCERR_UNKNOWN: emsg_funcname(N_("E117: Unknown function: %s"), name); break; - case ERROR_NOTMETHOD: + case FCERR_NOTMETHOD: emsg_funcname(N_("E276: Cannot use function as a method: %s"), name); break; - case ERROR_DELETED: + case FCERR_DELETED: emsg_funcname(N_("E933: Function was deleted: %s"), name); break; - case ERROR_TOOMANY: + case FCERR_TOOMANY: emsg_funcname(_(e_toomanyarg), name); break; - case ERROR_TOOFEW: + case FCERR_TOOFEW: emsg_funcname(N_("E119: Not enough arguments for function: %s"), name); break; - case ERROR_SCRIPT: + case FCERR_SCRIPT: emsg_funcname(N_("E120: Using <SID> not in a script context: %s"), name); break; - case ERROR_DICT: + case FCERR_DICT: emsg_funcname(N_("E725: Calling dict function without Dictionary: %s"), name); break; @@ -1421,7 +1449,7 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t FUNC_ATTR_NONNULL_ARG(1, 3, 5, 6) { int ret = FAIL; - int error = ERROR_NONE; + int error = FCERR_NONE; ufunc_T *fp = NULL; char fname_buf[FLEN_FIXED + 1]; char *tofree = NULL; @@ -1429,12 +1457,12 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t char *name = NULL; int argcount = argcount_in; typval_T *argvars = argvars_in; - dict_T *selfdict = funcexe->selfdict; + dict_T *selfdict = funcexe->fe_selfdict; typval_T argv[MAX_FUNC_ARGS + 1]; // used when "partial" or - // "funcexe->basetv" is not NULL + // "funcexe->fe_basetv" is not NULL int argv_clear = 0; int argv_base = 0; - partial_T *partial = funcexe->partial; + partial_T *partial = funcexe->fe_partial; // Initialize rettv so that it is safe for caller to invoke clear_tv(rettv) // even when call_func() returns FAIL. @@ -1453,8 +1481,8 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t fname = fname_trans_sid(name, (char *)fname_buf, &tofree, &error); } - if (funcexe->doesrange != NULL) { - *funcexe->doesrange = false; + if (funcexe->fe_doesrange != NULL) { + *funcexe->fe_doesrange = false; } if (partial != NULL) { @@ -1464,10 +1492,10 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t if (partial->pt_dict != NULL && (selfdict == NULL || !partial->pt_auto)) { selfdict = partial->pt_dict; } - if (error == ERROR_NONE && partial->pt_argc > 0) { + if (error == FCERR_NONE && partial->pt_argc > 0) { for (argv_clear = 0; argv_clear < partial->pt_argc; argv_clear++) { if (argv_clear + argcount_in >= MAX_FUNC_ARGS) { - error = ERROR_TOOMANY; + error = FCERR_TOOMANY; goto theend; } tv_copy(&partial->pt_argv[argv_clear], &argv[argv_clear]); @@ -1480,7 +1508,7 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t } } - if (error == ERROR_NONE && funcexe->evaluate) { + if (error == FCERR_NONE && funcexe->fe_evaluate) { char *rfname = fname; // Ignore "g:" before a function name. @@ -1490,12 +1518,12 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t rettv->v_type = VAR_NUMBER; // default rettv is number zero rettv->vval.v_number = 0; - error = ERROR_UNKNOWN; + error = FCERR_UNKNOWN; if (is_luafunc(partial)) { if (len > 0) { - error = ERROR_NONE; - argv_add_base(funcexe->basetv, &argvars, &argcount, argv, &argv_base); + error = FCERR_NONE; + argv_add_base(funcexe->fe_basetv, &argvars, &argcount, argv, &argv_base); nlua_typval_call(funcname, (size_t)len, argvars, argcount, rettv); } else { // v:lua was called directly; show its name in the emsg @@ -1516,47 +1544,29 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t fp = find_func((char_u *)rfname); } // Try loading a package. - if (fp == NULL && script_autoload((const char *)rfname, STRLEN(rfname), + 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); } if (fp != NULL && (fp->uf_flags & FC_DELETED)) { - error = ERROR_DELETED; - } else if (fp != NULL && (fp->uf_flags & FC_LUAREF)) { - error = typval_exec_lua_callable(fp->uf_luaref, argcount, argvars, rettv); + error = FCERR_DELETED; } else if (fp != NULL) { - if (funcexe->argv_func != NULL) { + if (funcexe->fe_argv_func != NULL) { // postponed filling in the arguments, do it now - argcount = funcexe->argv_func(argcount, argvars, argv_clear, - fp->uf_args.ga_len); + argcount = funcexe->fe_argv_func(argcount, argvars, argv_clear, fp); } - argv_add_base(funcexe->basetv, &argvars, &argcount, argv, &argv_base); + argv_add_base(funcexe->fe_basetv, &argvars, &argcount, argv, &argv_base); - if (fp->uf_flags & FC_RANGE && funcexe->doesrange != NULL) { - *funcexe->doesrange = true; - } - if (argcount < fp->uf_args.ga_len - fp->uf_def_args.ga_len) { - error = ERROR_TOOFEW; - } else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len) { - error = ERROR_TOOMANY; - } else if ((fp->uf_flags & FC_DICT) && selfdict == NULL) { - error = ERROR_DICT; - } else { - // Call the user function. - call_user_func(fp, argcount, argvars, rettv, funcexe->firstline, - funcexe->lastline, - (fp->uf_flags & FC_DICT) ? selfdict : NULL); - error = ERROR_NONE; - } + error = call_user_func_check(fp, argcount, argvars, rettv, funcexe, selfdict); } - } else if (funcexe->basetv != NULL) { + } 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, - funcexe->basetv); + funcexe->fe_basetv); } else { // Find the function name in the table, call its implementation. error = call_internal_func((char_u *)fname, argcount, argvars, rettv); @@ -1571,7 +1581,7 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t // update that flag first to make aborting() reliable. update_force_abort(); } - if (error == ERROR_NONE) { + if (error == FCERR_NONE) { ret = OK; } @@ -2167,7 +2177,7 @@ void ex_function(exarg_T *eap) theline = line_arg; p = vim_strchr(theline, '\n'); if (p == NULL) { - line_arg += STRLEN(line_arg); + line_arg += strlen(line_arg); } else { *p = NUL; line_arg = p + 1; @@ -2209,16 +2219,16 @@ void ex_function(exarg_T *eap) if (heredoc_trimmed == NULL || (is_heredoc && skipwhite(theline) == theline) || STRNCMP(theline, heredoc_trimmed, - STRLEN(heredoc_trimmed)) == 0) { + strlen(heredoc_trimmed)) == 0) { if (heredoc_trimmed == NULL) { p = theline; } else if (is_heredoc) { p = skipwhite(theline) == theline - ? theline : theline + STRLEN(heredoc_trimmed); + ? theline : theline + strlen(heredoc_trimmed); } else { - p = theline + STRLEN(heredoc_trimmed); + p = theline + strlen(heredoc_trimmed); } - if (STRCMP(p, skip_until) == 0) { + if (strcmp(p, skip_until) == 0) { XFREE_CLEAR(skip_until); XFREE_CLEAR(heredoc_trimmed); do_concat = true; @@ -2383,7 +2393,7 @@ void ex_function(exarg_T *eap) // If there are no errors, add the function if (fudi.fd_dict == NULL) { - v = find_var((const char *)name, STRLEN(name), &ht, false); + v = find_var((const char *)name, strlen(name), &ht, false); if (v != NULL && v->di_tv.v_type == VAR_FUNC) { emsg_funcname(N_("E707: Function name conflicts with variable: %s"), (char_u *)name); @@ -2458,11 +2468,11 @@ void ex_function(exarg_T *eap) // Check that the autoload name matches the script name. int j = FAIL; if (SOURCING_NAME != NULL) { - scriptname = (char_u *)autoload_name((const char *)name, STRLEN(name)); + scriptname = (char_u *)autoload_name((const char *)name, strlen(name)); p = vim_strchr((char *)scriptname, '/'); plen = (int)STRLEN(p); slen = (int)STRLEN(SOURCING_NAME); - if (slen > plen && FNAMECMP(p, SOURCING_NAME + slen - plen) == 0) { + if (slen > plen && path_fnamecmp(p, SOURCING_NAME + slen - plen) == 0) { j = OK; } xfree(scriptname); @@ -2474,7 +2484,7 @@ void ex_function(exarg_T *eap) } } - fp = xcalloc(1, offsetof(ufunc_T, uf_name) + STRLEN(name) + 1); + fp = xcalloc(1, offsetof(ufunc_T, uf_name) + strlen(name) + 1); if (fudi.fd_dict != NULL) { if (fudi.fd_di == NULL) { @@ -2632,7 +2642,7 @@ char *get_user_func_name(expand_T *xp, int idx) return (char *)fp->uf_name; // Prevent overflow. } - cat_func_name(IObuff, fp); + cat_func_name((char_u *)IObuff, fp); if (xp->xp_context != EXPAND_USER_FUNC) { STRCAT(IObuff, "("); if (!fp->uf_varargs && GA_EMPTY(&fp->uf_args)) { @@ -2941,12 +2951,12 @@ void ex_call(exarg_T *eap) arg = startarg; funcexe_T funcexe = FUNCEXE_INIT; - funcexe.firstline = eap->line1; - funcexe.lastline = eap->line2; - funcexe.doesrange = &doesrange; - funcexe.evaluate = true; - funcexe.partial = partial; - funcexe.selfdict = fudi.fd_dict; + funcexe.fe_firstline = eap->line1; + funcexe.fe_lastline = eap->line2; + funcexe.fe_doesrange = &doesrange; + funcexe.fe_evaluate = true; + funcexe.fe_partial = partial; + funcexe.fe_selfdict = fudi.fd_dict; if (get_func_tv(name, -1, &rettv, (char **)&arg, &funcexe) == FAIL) { failed = true; break; @@ -3085,7 +3095,7 @@ char *get_return_cmd(void *rettv) STRCPY(IObuff, ":return "); STRLCPY(IObuff + 8, s, IOSIZE - 8); - if (STRLEN(s) + 8 >= IOSIZE) { + if (strlen(s) + 8 >= IOSIZE) { STRCPY(IObuff + IOSIZE - 4, "..."); } xfree(tofree); @@ -3515,7 +3525,7 @@ bool set_ref_in_func(char_u *name, ufunc_T *fp_in, int copyID) { ufunc_T *fp = fp_in; funccall_T *fc; - int error = ERROR_NONE; + int error = FCERR_NONE; char_u fname_buf[FLEN_FIXED + 1]; char_u *tofree = NULL; char_u *fname; diff --git a/src/nvim/eval/userfunc.h b/src/nvim/eval/userfunc.h index 9811f2afb3..4098622a14 100644 --- a/src/nvim/eval/userfunc.h +++ b/src/nvim/eval/userfunc.h @@ -38,44 +38,43 @@ struct funccal_entry { /// errors for when calling a function typedef enum { - ERROR_UNKNOWN = 0, - ERROR_TOOMANY, - ERROR_TOOFEW, - ERROR_SCRIPT, - ERROR_DICT, - ERROR_NONE, - ERROR_OTHER, - ERROR_BOTH, - ERROR_DELETED, - ERROR_NOTMETHOD, + FCERR_UNKNOWN = 0, + FCERR_TOOMANY = 1, + FCERR_TOOFEW = 2, + FCERR_SCRIPT = 3, + FCERR_DICT = 4, + FCERR_NONE = 5, + FCERR_OTHER = 6, + FCERR_DELETED = 7, + FCERR_NOTMETHOD = 8, ///< function cannot be used as a method } FnameTransError; /// Used in funcexe_T. Returns the new argcount. -typedef int (*ArgvFunc)(int current_argcount, typval_T *argv, int argskip, - int called_func_argcount); +typedef int (*ArgvFunc)(int current_argcount, typval_T *argv, int partial_argcount, + ufunc_T *called_func); /// Structure passed between functions dealing with function call execution. typedef struct { - ArgvFunc argv_func; ///< when not NULL, can be used to fill in arguments only - ///< when the invoked function uses them - linenr_T firstline; ///< first line of range - linenr_T lastline; ///< last line of range - bool *doesrange; ///< [out] if not NULL: function handled range - bool evaluate; ///< actually evaluate expressions - partial_T *partial; ///< for extra arguments - dict_T *selfdict; ///< Dictionary for "self" - typval_T *basetv; ///< base for base->method() + ArgvFunc fe_argv_func; ///< when not NULL, can be used to fill in arguments only + ///< when the invoked function uses them + linenr_T fe_firstline; ///< first line of range + linenr_T fe_lastline; ///< last line of range + bool *fe_doesrange; ///< [out] if not NULL: function handled range + bool fe_evaluate; ///< actually evaluate expressions + partial_T *fe_partial; ///< for extra arguments + dict_T *fe_selfdict; ///< Dictionary for "self" + typval_T *fe_basetv; ///< base for base->method() } funcexe_T; #define FUNCEXE_INIT (funcexe_T) { \ - .argv_func = NULL, \ - .firstline = 0, \ - .lastline = 0, \ - .doesrange = NULL, \ - .evaluate = false, \ - .partial = NULL, \ - .selfdict = NULL, \ - .basetv = NULL, \ + .fe_argv_func = NULL, \ + .fe_firstline = 0, \ + .fe_lastline = 0, \ + .fe_doesrange = NULL, \ + .fe_evaluate = false, \ + .fe_partial = NULL, \ + .fe_selfdict = NULL, \ + .fe_basetv = NULL, \ } #define FUNCARG(fp, j) ((char **)(fp->uf_args.ga_data))[j] diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index ba58254bdd..1c07fc4d45 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -113,7 +113,7 @@ static list_T *heredoc_get(exarg_T *eap, char *cmd) && STRNCMP(theline, *eap->cmdlinep, marker_indent_len) == 0) { mi = marker_indent_len; } - if (STRCMP(marker, theline + mi) == 0) { + if (strcmp(marker, theline + mi) == 0) { xfree(theline); break; } @@ -710,7 +710,7 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo } } if (p != NULL) { - write_reg_contents(*arg == '@' ? '"' : *arg, p, (ssize_t)STRLEN(p), false); + write_reg_contents(*arg == '@' ? '"' : *arg, p, (ssize_t)strlen(p), false); arg_end = arg + 1; } xfree(ptofree); @@ -1801,7 +1801,7 @@ void f_setbufvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) // reset notion of buffer aucmd_restbuf(&aco); } else { - const size_t varname_len = STRLEN(varname); + const size_t varname_len = strlen(varname); char *const bufvarname = xmalloc(varname_len + 3); buf_T *const save_curbuf = curbuf; curbuf = buf; diff --git a/src/nvim/event/libuv_process.c b/src/nvim/event/libuv_process.c index 0251ea9957..f012bacdd9 100644 --- a/src/nvim/event/libuv_process.c +++ b/src/nvim/event/libuv_process.c @@ -25,7 +25,7 @@ int libuv_process_spawn(LibuvProcess *uvproc) uvproc->uvopts.file = proc->argv[0]; uvproc->uvopts.args = proc->argv; uvproc->uvopts.flags = UV_PROCESS_WINDOWS_HIDE; -#ifdef WIN32 +#ifdef MSWIN // libuv collapses the argv to a CommandLineToArgvW()-style string. cmd.exe // expects a different syntax (must be prepared by the caller before now). if (os_shell_is_cmdexe(proc->argv[0])) { @@ -55,7 +55,7 @@ int libuv_process_spawn(LibuvProcess *uvproc) if (!proc->in.closed) { uvproc->uvstdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE; -#ifdef WIN32 +#ifdef MSWIN uvproc->uvstdio[0].flags |= proc->overlapped ? UV_OVERLAPPED_PIPE : 0; #endif uvproc->uvstdio[0].data.stream = STRUCT_CAST(uv_stream_t, @@ -64,7 +64,7 @@ int libuv_process_spawn(LibuvProcess *uvproc) if (!proc->out.closed) { uvproc->uvstdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; -#ifdef WIN32 +#ifdef MSWIN // pipe must be readable for IOCP to work on Windows. uvproc->uvstdio[1].flags |= proc->overlapped ? (UV_READABLE_PIPE | UV_OVERLAPPED_PIPE) : 0; @@ -113,7 +113,7 @@ static void close_cb(uv_handle_t *handle) static void exit_cb(uv_process_t *handle, int64_t status, int term_signal) { Process *proc = handle->data; -#if defined(WIN32) +#if defined(MSWIN) // Use stored/expected signal. term_signal = proc->exit_signal; #endif diff --git a/src/nvim/event/loop.c b/src/nvim/event/loop.c index 1b5cc23b09..3329cbd574 100644 --- a/src/nvim/event/loop.c +++ b/src/nvim/event/loop.c @@ -31,41 +31,57 @@ void loop_init(Loop *loop, void *data) loop->poll_timer.data = xmalloc(sizeof(bool)); // "timeout expired" flag } -/// Processes one `Loop.uv` event (at most). -/// Processes all `Loop.fast_events` events. -/// Does NOT process `Loop.events`, that is an application-specific decision. +/// Process `Loop.uv` events with a timeout. /// /// @param loop -/// @param ms 0: non-blocking poll. -/// >0: timeout after `ms`. -/// <0: wait forever. -/// @returns true if `ms` timeout was reached -bool loop_poll_events(Loop *loop, int ms) +/// @param ms 0: non-blocking poll. +/// > 0: timeout after `ms`. +/// < 0: wait forever. +/// @param once true: process at most one `Loop.uv` event. +/// false: process until `ms` timeout (only has effect if `ms` > 0). +/// @return true if `ms` > 0 and was reached +bool loop_uv_run(Loop *loop, int ms, bool once) { if (loop->recursive++) { abort(); // Should not re-enter uv_run } uv_run_mode mode = UV_RUN_ONCE; - bool timeout_expired = false; + bool *timeout_expired = loop->poll_timer.data; + *timeout_expired = false; if (ms > 0) { - *((bool *)loop->poll_timer.data) = false; // reset "timeout expired" flag - // Dummy timer to ensure UV_RUN_ONCE does not block indefinitely for I/O. + // This timer ensures UV_RUN_ONCE does not block indefinitely for I/O. uv_timer_start(&loop->poll_timer, timer_cb, (uint64_t)ms, (uint64_t)ms); } else if (ms == 0) { // For ms == 0, do a non-blocking event poll. mode = UV_RUN_NOWAIT; } - uv_run(&loop->uv, mode); + do { // -V1044 + uv_run(&loop->uv, mode); + } while (ms > 0 && !once && !*timeout_expired); // -V560 if (ms > 0) { - timeout_expired = *((bool *)loop->poll_timer.data); uv_timer_stop(&loop->poll_timer); } loop->recursive--; // Can re-enter uv_run now + return *timeout_expired; +} + +/// Processes one `Loop.uv` event (at most). +/// Processes all `Loop.fast_events` events. +/// Does NOT process `Loop.events`, that is an application-specific decision. +/// +/// @param loop +/// @param ms 0: non-blocking poll. +/// > 0: timeout after `ms`. +/// < 0: wait forever. +/// @return true if `ms` > 0 and was reached +bool loop_poll_events(Loop *loop, int ms) +{ + bool timeout_expired = loop_uv_run(loop, ms, true); multiqueue_process_events(loop->fast_events); return timeout_expired; } diff --git a/src/nvim/event/stream.c b/src/nvim/event/stream.c index b34fd73d52..bfb7a551b9 100644 --- a/src/nvim/event/stream.c +++ b/src/nvim/event/stream.c @@ -10,7 +10,7 @@ #include "nvim/log.h" #include "nvim/macros.h" #include "nvim/rbuffer.h" -#ifdef WIN32 +#ifdef MSWIN # include "nvim/os/os_win_console.h" #endif @@ -60,7 +60,7 @@ void stream_init(Loop *loop, Stream *stream, int fd, uv_stream_t *uvstream) stream->uv.idle.data = stream; } else { assert(type == UV_NAMED_PIPE || type == UV_TTY); -#ifdef WIN32 +#ifdef MSWIN if (type == UV_TTY) { uv_tty_init(&loop->uv, &stream->uv.tty, fd, 0); uv_tty_set_mode(&stream->uv.tty, UV_TTY_MODE_RAW); @@ -75,7 +75,7 @@ void stream_init(Loop *loop, Stream *stream, int fd, uv_stream_t *uvstream) uv_pipe_init(&loop->uv, &stream->uv.pipe, 0); uv_pipe_open(&stream->uv.pipe, fd); stream->uvstream = STRUCT_CAST(uv_stream_t, &stream->uv.pipe); -#ifdef WIN32 +#ifdef MSWIN } #endif } @@ -109,7 +109,7 @@ void stream_close(Stream *stream, stream_close_cb on_stream_close, void *data) stream->close_cb = on_stream_close; stream->close_cb_data = data; -#ifdef WIN32 +#ifdef MSWIN if (UV_TTY == uv_guess_handle(stream->fd)) { // Undo UV_TTY_MODE_RAW from stream_init(). #10801 uv_tty_set_mode(&stream->uv.tty, UV_TTY_MODE_NORMAL); diff --git a/src/nvim/event/stream.h b/src/nvim/event/stream.h index 02e816b4be..b580d3c33d 100644 --- a/src/nvim/event/stream.h +++ b/src/nvim/event/stream.h @@ -35,7 +35,7 @@ struct stream { uv_pipe_t pipe; uv_tcp_t tcp; uv_idle_t idle; -#ifdef WIN32 +#ifdef MSWIN uv_tty_t tty; #endif } uv; diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 12920d932d..462212c4ce 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -330,7 +330,7 @@ static int linelen(int *has_tab) first = skipwhite(line); // find the character after the last non-blank character - for (last = first + STRLEN(first); + for (last = first + strlen(first); last > first && ascii_iswhite(last[-1]); last--) {} char save = *last; *last = NUL; @@ -379,7 +379,7 @@ static int string_compare(const void *s1, const void *s2) FUNC_ATTR_NONNULL_ALL if (sort_lc) { return strcoll((char *)s1, (char *)s2); } - return sort_ic ? STRICMP(s1, s2) : STRCMP(s1, s2); + return sort_ic ? STRICMP(s1, s2) : strcmp(s1, s2); } static int sort_compare(const void *s1, const void *s2) @@ -550,7 +550,7 @@ void ex_sort(exarg_T *eap) // Also get the longest line length for allocating "sortbuf". for (lnum = eap->line1; lnum <= eap->line2; lnum++) { s = ml_get(lnum); - len = (int)STRLEN(s); + len = (int)strlen(s); if (maxlen < len) { maxlen = len; } @@ -559,10 +559,10 @@ void ex_sort(exarg_T *eap) end_col = len; if (regmatch.regprog != NULL && vim_regexec(®match, s, 0)) { if (sort_rx) { - start_col = (colnr_T)(regmatch.startp[0] - (char_u *)s); - end_col = (colnr_T)(regmatch.endp[0] - (char_u *)s); + start_col = (colnr_T)(regmatch.startp[0] - s); + end_col = (colnr_T)(regmatch.endp[0] - s); } else { - start_col = (colnr_T)(regmatch.endp[0] - (char_u *)s); + start_col = (colnr_T)(regmatch.endp[0] - s); } } else if (regmatch.regprog != NULL) { end_col = 0; @@ -651,7 +651,7 @@ void ex_sort(exarg_T *eap) } s = ml_get(get_lnum); - size_t bytelen = STRLEN(s) + 1; // include EOL in bytelen + size_t bytelen = strlen(s) + 1; // include EOL in bytelen old_count += (bcount_t)bytelen; if (!unique || i == 0 || string_compare(s, sortbuf1) != 0) { // Copy the line into a buffer, it may become invalid in @@ -796,7 +796,7 @@ void ex_retab(exarg_T *eap) // len is actual number of white characters used len = num_spaces + num_tabs; - old_len = (long)STRLEN(ptr); + old_len = (long)strlen(ptr); const long new_len = old_len - col + start_col + len + 1; if (new_len <= 0 || new_len >= MAXCOL) { emsg(_(e_resulting_text_too_long)); @@ -1142,9 +1142,9 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out bool ins_prevcmd = forceit; trailarg = arg; do { - len = STRLEN(trailarg) + 1; + len = strlen(trailarg) + 1; if (newcmd != NULL) { - len += STRLEN(newcmd); + len += strlen(newcmd); } if (ins_prevcmd) { if (prevcmd == NULL) { @@ -1152,7 +1152,7 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out xfree(newcmd); return; } - len += STRLEN(prevcmd); + len += strlen(prevcmd); } t = xmalloc(len); *t = NUL; @@ -1162,7 +1162,7 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out if (ins_prevcmd) { STRCAT(t, prevcmd); } - p = t + STRLEN(t); + p = t + strlen(t); STRCAT(t, trailarg); xfree(newcmd); newcmd = t; @@ -1201,7 +1201,7 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out } // Add quotes around the command, for shells that need them. if (*p_shq != NUL) { - newcmd = xmalloc(STRLEN(prevcmd) + 2 * STRLEN(p_shq) + 1); + newcmd = xmalloc(strlen(prevcmd) + 2 * STRLEN(p_shq) + 1); STRCPY(newcmd, p_shq); STRCAT(newcmd, prevcmd); STRCAT(newcmd, p_shq); @@ -1535,30 +1535,30 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp) { bool is_fish_shell = #if defined(UNIX) - STRNCMP(invocation_path_tail(p_sh, NULL), "fish", 4) == 0; + STRNCMP(invocation_path_tail((char_u *)p_sh, NULL), "fish", 4) == 0; #else false; #endif - bool is_pwsh = STRNCMP(invocation_path_tail(p_sh, NULL), "pwsh", 4) == 0 - || STRNCMP(invocation_path_tail(p_sh, NULL), "powershell", 10) == 0; + bool is_pwsh = STRNCMP(invocation_path_tail((char_u *)p_sh, NULL), "pwsh", 4) == 0 + || STRNCMP(invocation_path_tail((char_u *)p_sh, NULL), "powershell", 10) == 0; - size_t len = STRLEN(cmd) + 1; // At least enough space for cmd + NULL. + size_t len = strlen(cmd) + 1; // At least enough space for cmd + NULL. len += is_fish_shell ? sizeof("begin; " "; end") - 1 : is_pwsh ? sizeof("Start-Process ") : sizeof("(" ")") - 1; if (itmp != NULL) { - len += is_pwsh ? STRLEN(itmp) + sizeof(" -RedirectStandardInput ") - : STRLEN(itmp) + sizeof(" { " " < " " } ") - 1; + len += is_pwsh ? strlen(itmp) + sizeof(" -RedirectStandardInput ") + : strlen(itmp) + sizeof(" { " " < " " } ") - 1; } if (otmp != NULL) { - len += STRLEN(otmp) + STRLEN(p_srr) + 2; // two extra spaces (" "), + len += strlen(otmp) + strlen(p_srr) + 2; // two extra spaces (" "), } const char *const cmd_args = strchr(cmd, ' '); len += (is_pwsh && cmd_args) - ? STRLEN(" -ArgumentList ") + 2 // two extra quotes + ? strlen(" -ArgumentList ") + 2 // two extra quotes : 0; char *const buf = xmalloc(len); @@ -1568,7 +1568,7 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp) if (cmd_args == NULL) { xstrlcat(buf, cmd, len); } else { - xstrlcpy(buf + STRLEN(buf), cmd, (size_t)(cmd_args - cmd + 1)); + xstrlcpy(buf + strlen(buf), cmd, (size_t)(cmd_args - cmd + 1)); xstrlcat(buf, " -ArgumentList \"", len); xstrlcat(buf, cmd_args + 1, len); // +1 to skip the leading space. xstrlcat(buf, "\"", len); @@ -2372,7 +2372,7 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum if ((command != NULL || newlnum > (linenr_T)0) && *get_vim_var_str(VV_SWAPCOMMAND) == NUL) { // Set v:swapcommand for the SwapExists autocommands. - const size_t len = (command != NULL) ? STRLEN(command) + 3 : 30; + const size_t len = (command != NULL) ? strlen(command) + 3 : 30; char *const p = xmalloc(len); if (command != NULL) { vim_snprintf(p, len, ":%s\r", command); @@ -2941,7 +2941,7 @@ void ex_append(exarg_T *eap) } p = vim_strchr(eap->nextcmd, NL); if (p == NULL) { - p = eap->nextcmd + STRLEN(eap->nextcmd); + p = eap->nextcmd + strlen(eap->nextcmd); } theline = xstrnsave(eap->nextcmd, (size_t)(p - eap->nextcmd)); if (*p != NUL) { @@ -3258,7 +3258,7 @@ static bool sub_joining_lines(exarg_T *eap, char *pat, char *sub, char *cmd, boo // TODO(vim): find a generic solution to make line-joining operations more // efficient, avoid allocating a string that grows in size. if (pat != NULL - && STRCMP(pat, "\\n") == 0 + && strcmp(pat, "\\n") == 0 && *sub == NUL && (*cmd == NUL || (cmd[1] == NUL && (*cmd == 'g' @@ -3329,7 +3329,7 @@ static char *sub_grow_buf(char **new_start, int needed_len) // Check if the temporary buffer is long enough to do the // substitution into. If not, make it larger (with a bit // extra to avoid too many calls to xmalloc()/free()). - size_t len = STRLEN(*new_start); + size_t len = strlen(*new_start); needed_len += (int)len; if (needed_len > new_start_len) { new_start_len = needed_len + 50; @@ -3616,13 +3616,6 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T } } - const bool cmdheight0 = !ui_has_messages(); - if (cmdheight0) { - // If cmdheight is 0, cmdheight must be set to 1 when we enter command line. - set_option_value("ch", 1L, NULL, 0); - redraw_statuslines(); - } - // Check for a match on each line. // If preview: limit to max('cmdwinheight', viewport). linenr_T line2 = eap->line2; @@ -3777,7 +3770,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T // we continue looking for a match on the next line. // Avoids that ":s/\nB\@=//gc" get stuck. if (nmatch > 1) { - matchcol = (colnr_T)STRLEN(sub_firstline); + matchcol = (colnr_T)strlen(sub_firstline); nmatch = 1; skip_match = true; } @@ -3878,7 +3871,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T // Position the cursor relative to the end of the line, the // previous substitute may have inserted or deleted characters // before the cursor. - len_change = (int)STRLEN(new_line) - (int)STRLEN(orig_line); + len_change = (int)strlen(new_line) - (int)strlen(orig_line); curwin->w_cursor.col += len_change; ml_replace(lnum, new_line, false); } @@ -3887,6 +3880,10 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T - regmatch.startpos[0].lnum; search_match_endcol = regmatch.endpos[0].col + len_change; + if (search_match_lines == 0 && search_match_endcol == 0) { + // highlight at least one character for /^/ + search_match_endcol = 1; + } highlight_match = true; update_topline(curwin); @@ -3910,7 +3907,9 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T msg_no_more = false; msg_scroll = (int)i; show_cursor_info(true); - ui_cursor_goto(msg_row, msg_col); + if (!ui_has(kUIMessages)) { + ui_cursor_goto(msg_row, msg_col); + } RedrawingDisabled = temp; no_mapping++; // don't map this key @@ -3971,7 +3970,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T // Avoids that ":%s/\nB\@=//gc" and ":%s/\n/,\r/gc" // get stuck when pressing 'n'. if (nmatch > 1) { - matchcol = (colnr_T)STRLEN(sub_firstline); + matchcol = (colnr_T)strlen(sub_firstline); skip_match = true; } goto skip; @@ -4081,7 +4080,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T } size_t copy_len = (size_t)(regmatch.startpos[0].col - copycol); new_end = sub_grow_buf(&new_start, - (colnr_T)STRLEN(p1) - regmatch.endpos[0].col + (colnr_T)strlen(p1) - regmatch.endpos[0].col + (colnr_T)copy_len + sublen + 1); // copy the text up to the part that matched @@ -4115,7 +4114,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T bcount_t replaced_bytes = 0; lpos_T start = regmatch.startpos[0], end = regmatch.endpos[0]; for (i = 0; i < nmatch - 1; i++) { - replaced_bytes += (bcount_t)STRLEN(ml_get((linenr_T)(lnum_start + i))) + 1; + replaced_bytes += (bcount_t)strlen(ml_get((linenr_T)(lnum_start + i))) + 1; } replaced_bytes += end.col - start.col; @@ -4158,7 +4157,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T p1 += utfc_ptr2len(p1) - 1; } } - colnr_T new_endcol = (colnr_T)STRLEN(new_start); + colnr_T new_endcol = (colnr_T)strlen(new_start); current_match.end.col = new_endcol; current_match.end.lnum = lnum; @@ -4214,8 +4213,8 @@ skip: // have changed the number of characters. Same for // "prev_matchcol". STRCAT(new_start, sub_firstline + copycol); - matchcol = (colnr_T)STRLEN(sub_firstline) - matchcol; - prev_matchcol = (colnr_T)STRLEN(sub_firstline) + matchcol = (colnr_T)strlen(sub_firstline) - matchcol; + prev_matchcol = (colnr_T)strlen(sub_firstline) - prev_matchcol; if (u_savesub(lnum) != OK) { @@ -4260,8 +4259,8 @@ skip: xfree(sub_firstline); // free the temp buffer sub_firstline = new_start; new_start = NULL; - matchcol = (colnr_T)STRLEN(sub_firstline) - matchcol; - prev_matchcol = (colnr_T)STRLEN(sub_firstline) + matchcol = (colnr_T)strlen(sub_firstline) - matchcol; + prev_matchcol = (colnr_T)strlen(sub_firstline) - prev_matchcol; copycol = 0; } @@ -4366,7 +4365,7 @@ skip: beginline(BL_WHITE | BL_FIX); } } - if (!cmdpreview && !do_sub_msg(subflags.do_count) && subflags.do_ask) { + if (!cmdpreview && !do_sub_msg(subflags.do_count) && subflags.do_ask && p_ch > 0) { msg(""); } } else { @@ -4381,7 +4380,9 @@ skip: emsg(_(e_interr)); } else if (got_match) { // did find something but nothing substituted - msg(""); + if (p_ch > 0) { + msg(""); + } } else if (subflags.do_error) { // nothing found semsg(_(e_patnotf2), get_search_pat()); @@ -4414,11 +4415,6 @@ skip: } } - if (cmdheight0) { - // Restore cmdheight - set_option_value("ch", 0L, NULL, 0); - } - kv_destroy(preview_lines.subresults); return retv; #undef ADJUST_SUB_FIRSTLNUM diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index e551cbee0b..1248251556 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -703,7 +703,7 @@ void ex_compiler(exarg_T *eap) do_cmdline_cmd("echo globpath(&rtp, 'compiler/*.vim')"); // NOLINT do_cmdline_cmd("echo globpath(&rtp, 'compiler/*.lua')"); // NOLINT } else { - size_t bufsize = STRLEN(eap->arg) + 14; + size_t bufsize = strlen(eap->arg) + 14; buf = xmalloc(bufsize); if (eap->forceit) { // ":compiler! {name}" sets global options diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index e32eb860ce..b01a262f84 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -1302,7 +1302,7 @@ static void parse_register(exarg_T *eap) if (!eap->skip) { set_expr_line(xstrdup(eap->arg)); } - eap->arg += STRLEN(eap->arg); + eap->arg += strlen(eap->arg); } eap->arg = skipwhite(eap->arg); } @@ -1536,7 +1536,7 @@ static int execute_cmd0(int *retv, exarg_T *eap, char **errormsg, bool preview) || eap->cmdidx == CMD_bunload) { p = skiptowhite_esc(eap->arg); } else { - p = eap->arg + STRLEN(eap->arg); + p = eap->arg + strlen(eap->arg); while (p > eap->arg && ascii_iswhite(p[-1])) { p--; } @@ -2824,7 +2824,7 @@ bool checkforcmd(char **pp, char *cmd, int len) /// invisible otherwise. static void append_command(char *cmd) { - size_t len = STRLEN(IObuff); + size_t len = strlen(IObuff); char *s = cmd; char *d; @@ -2836,12 +2836,12 @@ static void append_command(char *cmd) } STRCAT(IObuff, ": "); d = (char *)IObuff + STRLEN(IObuff); - while (*s != NUL && (char_u *)d - IObuff + 5 < IOSIZE) { + while (*s != NUL && d - IObuff + 5 < IOSIZE) { if ((char_u)s[0] == 0xc2 && (char_u)s[1] == 0xa0) { s += 2; STRCPY(d, "<a0>"); d += 4; - } else if ((char_u *)d - IObuff + utfc_ptr2len(s) + 1 >= IOSIZE) { + } else if (d - IObuff + utfc_ptr2len(s) + 1 >= IOSIZE) { break; } else { mb_copy_char((const char **)&s, &d); @@ -3657,7 +3657,7 @@ char *replace_makeprg(exarg_T *eap, char *arg, char **cmdlinep) // Don't do it when ":vimgrep" is used for ":grep". if ((eap->cmdidx == CMD_make || eap->cmdidx == CMD_lmake || isgrep) && !grep_internal(eap->cmdidx)) { - const char *program = isgrep ? (*curbuf->b_p_gp == NUL ? (char *)p_gp : curbuf->b_p_gp) + 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); arg = skipwhite(arg); @@ -3666,7 +3666,7 @@ char *replace_makeprg(exarg_T *eap, char *arg, char **cmdlinep) // Replace $* by given arguments if ((new_cmdline = strrep(program, "$*", arg)) == NULL) { // No $* in arg, build "<makeprg> <arg>" instead - new_cmdline = xmalloc(STRLEN(program) + STRLEN(arg) + 2); + new_cmdline = xmalloc(strlen(program) + strlen(arg) + 2); STRCPY(new_cmdline, program); STRCAT(new_cmdline, " "); STRCAT(new_cmdline, arg); @@ -3805,7 +3805,7 @@ int expand_filename(exarg_T *eap, char **cmdlinep, char **errormsgp) p = NULL; } if (p != NULL) { - (void)repl_cmdline(eap, eap->arg, STRLEN(eap->arg), p, cmdlinep); + (void)repl_cmdline(eap, eap->arg, strlen(eap->arg), p, cmdlinep); } } @@ -3833,7 +3833,7 @@ int expand_filename(exarg_T *eap, char **cmdlinep, char **errormsgp) if (p == NULL) { return FAIL; } - (void)repl_cmdline(eap, eap->arg, STRLEN(eap->arg), p, cmdlinep); + (void)repl_cmdline(eap, eap->arg, strlen(eap->arg), p, cmdlinep); xfree(p); } } @@ -3851,10 +3851,10 @@ static char *repl_cmdline(exarg_T *eap, char *src, size_t srclen, char *repl, ch // The new command line is build in new_cmdline[]. // First allocate it. // Careful: a "+cmd" argument may have been NUL terminated. - size_t len = STRLEN(repl); - size_t i = (size_t)(src - *cmdlinep) + STRLEN(src + srclen) + len + 3; + size_t len = strlen(repl); + size_t i = (size_t)(src - *cmdlinep) + strlen(src + srclen) + len + 3; if (eap->nextcmd != NULL) { - i += STRLEN(eap->nextcmd); // add space for next command + i += strlen(eap->nextcmd); // add space for next command } char *new_cmdline = xmalloc(i); size_t offset = (size_t)(src - *cmdlinep); @@ -3872,7 +3872,7 @@ static char *repl_cmdline(exarg_T *eap, char *src, size_t srclen, char *repl, ch src = new_cmdline + i; // remember where to continue if (eap->nextcmd != NULL) { // append next command - i = STRLEN(new_cmdline) + 1; + i = strlen(new_cmdline) + 1; STRCPY(new_cmdline + i, eap->nextcmd); eap->nextcmd = new_cmdline + i; } @@ -4114,9 +4114,9 @@ static int get_tabpage_arg(exarg_T *eap) tab_number = (int)getdigits(&p, false, tab_number); if (relative == 0) { - if (STRCMP(p, "$") == 0) { + if (strcmp(p, "$") == 0) { tab_number = LAST_TAB_NR; - } else if (STRCMP(p, "#") == 0) { + } else if (strcmp(p, "#") == 0) { if (valid_tabpage(lastused_tabpage)) { tab_number = tabpage_index(lastused_tabpage); } else { @@ -4913,7 +4913,7 @@ void ex_splitview(exarg_T *eap) } if (eap->cmdidx == CMD_sfind || eap->cmdidx == CMD_tabfind) { - fname = (char *)find_file_in_path((char_u *)eap->arg, STRLEN(eap->arg), + fname = (char *)find_file_in_path((char_u *)eap->arg, strlen(eap->arg), FNAME_MESS, true, (char_u *)curbuf->b_ffname); if (fname == NULL) { goto theend; @@ -5106,7 +5106,7 @@ 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((char_u *)eap->arg, STRLEN(eap->arg), + char *fname = (char *)find_file_in_path((char_u *)eap->arg, strlen(eap->arg), FNAME_MESS, true, (char_u *)curbuf->b_ffname); if (eap->addr_count > 0) { // Repeat finding the file "count" times. This matters when it @@ -5480,7 +5480,7 @@ bool changedir_func(char *new_dir, CdScope scope) char *pdir = NULL; // ":cd -": Change to previous directory - if (STRCMP(new_dir, "-") == 0) { + if (strcmp(new_dir, "-") == 0) { pdir = get_prevdir(scope); if (pdir == NULL) { emsg(_("E186: No previous directory")); @@ -6089,14 +6089,22 @@ static void ex_redrawstatus(exarg_T *eap) int r = RedrawingDisabled; int p = p_lz; - RedrawingDisabled = 0; - p_lz = false; if (eap->forceit) { status_redraw_all(); } else { status_redraw_curbuf(); } - update_screen(VIsual_active ? UPD_INVERTED : 0); + if (msg_scrolled && (State & MODE_CMDLINE)) { + return; // redraw later + } + + RedrawingDisabled = 0; + p_lz = false; + if (State & MODE_CMDLINE) { + redraw_statuslines(); + } else { + update_screen(VIsual_active ? UPD_INVERTED : 0); + } RedrawingDisabled = r; p_lz = p; ui_flush(); @@ -6292,7 +6300,7 @@ static void ex_normal(exarg_T *eap) } } if (len > 0) { - arg = xmalloc(STRLEN(eap->arg) + (size_t)len + 1); + arg = xmalloc(strlen(eap->arg) + (size_t)len + 1); len = 0; for (p = eap->arg; *p != NUL; p++) { arg[len++] = *p; @@ -6471,7 +6479,7 @@ static void ex_findpat(exarg_T *eap) } } if (!eap->skip) { - find_pattern_in_path((char_u *)eap->arg, 0, STRLEN(eap->arg), whole, !eap->forceit, + find_pattern_in_path((char_u *)eap->arg, 0, strlen(eap->arg), whole, !eap->forceit, *eap->cmd == 'd' ? FIND_DEFINE : FIND_ANY, n, action, eap->line1, eap->line2); } @@ -6612,7 +6620,7 @@ ssize_t find_cmdline_var(const char_u *src, size_t *usedlen) }; for (size_t i = 0; i < ARRAY_SIZE(spec_str); i++) { - size_t len = STRLEN(spec_str[i]); + size_t len = strlen(spec_str[i]); if (STRNCMP(src, spec_str[i], len) == 0) { *usedlen = len; assert(i <= SSIZE_MAX); @@ -6712,7 +6720,7 @@ char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnum valid = 0; // Must have ":p:h" to be valid } else { result = curbuf->b_fname; - tilde_file = STRCMP(result, "~") == 0; + tilde_file = strcmp(result, "~") == 0; } break; @@ -6766,7 +6774,7 @@ char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnum valid = 0; // Must have ":p:h" to be valid } else { result = buf->b_fname; - tilde_file = STRCMP(result, "~") == 0; + tilde_file = strcmp(result, "~") == 0; } } break; @@ -6879,7 +6887,7 @@ char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnum } // Length of new string. - resultlen = STRLEN(result); + resultlen = strlen(result); // Remove the file name extension. if (src[*usedlen] == '<') { (*usedlen)++; @@ -6942,11 +6950,11 @@ char *expand_sfile(char *arg) p += srclen; continue; } - size_t len = STRLEN(result) - srclen + STRLEN(repl) + 1; + size_t len = strlen(result) - srclen + strlen(repl) + 1; char *newres = xmalloc(len); memmove(newres, result, (size_t)(p - result)); STRCPY(newres + (p - result), repl); - len = STRLEN(newres); + len = strlen(newres); STRCAT(newres, p + srclen); xfree(repl); xfree(result); @@ -6986,12 +6994,12 @@ void dialog_msg(char *buff, char *format, char *fname) /// ":behave {mswin,xterm}" static void ex_behave(exarg_T *eap) { - if (STRCMP(eap->arg, "mswin") == 0) { + if (strcmp(eap->arg, "mswin") == 0) { set_option_value_give_err("selection", 0L, "exclusive", 0); set_option_value_give_err("selectmode", 0L, "mouse,key", 0); set_option_value_give_err("mousemodel", 0L, "popup", 0); set_option_value_give_err("keymodel", 0L, "startsel,stopsel", 0); - } else if (STRCMP(eap->arg, "xterm") == 0) { + } else if (strcmp(eap->arg, "xterm") == 0) { set_option_value_give_err("selection", 0L, "inclusive", 0); set_option_value_give_err("selectmode", 0L, "", 0); set_option_value_give_err("mousemodel", 0L, "extend", 0); @@ -7041,7 +7049,7 @@ static void ex_filetype(exarg_T *eap) } break; } - if (STRCMP(arg, "on") == 0 || STRCMP(arg, "detect") == 0) { + if (strcmp(arg, "on") == 0 || strcmp(arg, "detect") == 0) { if (*arg == 'o' || !filetype_detect) { source_runtime(FILETYPE_FILE, DIP_ALL); filetype_detect = kTrue; @@ -7058,7 +7066,7 @@ static void ex_filetype(exarg_T *eap) (void)do_doautocmd("filetypedetect BufRead", true, NULL); do_modelines(0); } - } else if (STRCMP(arg, "off") == 0) { + } else if (strcmp(arg, "off") == 0) { if (plugin || indent) { if (plugin) { source_runtime(FTPLUGOF_FILE, DIP_ALL); diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c index f40149d07a..c2648b9bfc 100644 --- a/src/nvim/ex_eval.c +++ b/src/nvim/ex_eval.c @@ -376,13 +376,13 @@ char *get_exception_string(void *value, except_type_T type, char *cmdname, int * *should_free = true; mesg = ((msglist_T *)value)->throw_msg; if (cmdname != NULL && *cmdname != NUL) { - size_t cmdlen = STRLEN(cmdname); - ret = xstrnsave("Vim(", 4 + cmdlen + 2 + STRLEN(mesg)); + size_t cmdlen = strlen(cmdname); + ret = xstrnsave("Vim(", 4 + cmdlen + 2 + strlen(mesg)); STRCPY(&ret[4], cmdname); STRCPY(&ret[4 + cmdlen], "):"); val = ret + 4 + cmdlen + 2; } else { - ret = xstrnsave("Vim:", 4 + STRLEN(mesg)); + ret = xstrnsave("Vim:", 4 + strlen(mesg)); val = ret + 4; } @@ -410,7 +410,7 @@ char *get_exception_string(void *value, except_type_T type, char *cmdname, int * STRCAT(val, p); p[-2] = NUL; - snprintf(val + STRLEN(p), strlen(" (%s)"), " (%s)", &mesg[1]); + snprintf(val + strlen(p), strlen(" (%s)"), " (%s)", &mesg[1]); p[-2] = '"'; } break; diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index cf95287d61..2a91e9c672 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -599,24 +599,6 @@ static void finish_incsearch_highlighting(int gotesc, incsearch_state_T *s, bool /// @param init_ccline clear ccline first static uint8_t *command_line_enter(int firstc, long count, int indent, bool init_ccline) { - const bool cmdheight0 = !ui_has_messages(); - - if (cmdheight0) { - const long save_so = lastwin->w_p_so; - - // If cmdheight is 0, cmdheight must be set to 1 when we enter the - // command line. Set "made_cmdheight_nonzero" and reset 'scrolloff' to - // avoid scrolling the last window. - made_cmdheight_nonzero = true; - - lastwin->w_p_so = 0; - set_option_value("ch", 1L, NULL, 0); - update_screen(UPD_VALID); // redraw the screen NOW - - made_cmdheight_nonzero = false; - lastwin->w_p_so = save_so; - } - // can be invoked recursively, identify each level static int cmdline_level = 0; cmdline_level++; @@ -865,12 +847,18 @@ static uint8_t *command_line_enter(int firstc, long count, int indent, bool init // If the line is too long, clear it, so ruler and shown command do // not get printed in the middle of it. msg_check(); + if (p_ch == 0 && !ui_has(kUIMessages)) { + if (must_redraw < UPD_VALID) { + must_redraw = UPD_VALID; + } + } msg_scroll = s->save_msg_scroll; redir_off = false; if (!tl_ret && ERROR_SET(&err)) { msg_putchar('\n'); - msg_printf_attr(HL_ATTR(HLF_E)|MSG_HIST, (char *)e_autocmd_err, err.msg); + semsg(e_autocmd_err, err.msg); + did_emsg = false; api_clear_error(&err); } @@ -910,17 +898,6 @@ theend: ccline.cmdbuff = NULL; } - if (cmdheight0) { - made_cmdheight_nonzero = true; - - // Restore cmdheight - set_option_value("ch", 0L, NULL, 0); - // Redraw is needed for command line completion - redraw_all_later(UPD_NOT_VALID); - - made_cmdheight_nonzero = false; - } - return p; } @@ -1411,7 +1388,7 @@ static int may_do_command_line_next_incsearch(int firstc, long count, incsearch_ static void command_line_next_histidx(CommandLineState *s, bool next_match) { - int j = (int)STRLEN(s->lookfor); + int j = (int)strlen(s->lookfor); for (;;) { // one step backwards if (!next_match) { @@ -1920,7 +1897,7 @@ static int command_line_handle_key(CommandLineState *s) STRCPY(ccline.cmdbuff, p); } - ccline.cmdpos = ccline.cmdlen = (int)STRLEN(ccline.cmdbuff); + ccline.cmdpos = ccline.cmdlen = (int)strlen(ccline.cmdbuff); redrawcmd(); return command_line_changed(s); } @@ -2005,7 +1982,7 @@ static int command_line_handle_key(CommandLineState *s) } else { int j = utf_char2bytes(s->c, (char *)IObuff); IObuff[j] = NUL; // exclude composing chars - put_on_cmdline(IObuff, j, true); + put_on_cmdline((char_u *)IObuff, j, true); } return command_line_changed(s); } @@ -2027,7 +2004,7 @@ static int command_line_not_changed(CommandLineState *s) /// as a trailing \|, which can happen while typing a pattern. static int empty_pattern(char *p) { - size_t n = STRLEN(p); + size_t n = strlen(p); // remove trailing \v and the like while (n >= 2 && p[n - 2] == '\\' @@ -2408,6 +2385,7 @@ static int command_line_changed(CommandLineState *s) // Trigger CmdlineChanged autocommands. do_autocmd_cmdlinechanged(s->firstc > 0 ? s->firstc : '-'); + const bool prev_cmdpreview = cmdpreview; if (s->firstc == ':' && current_sctx.sc_sid == 0 // only if interactive && *p_icm != NUL // 'inccommand' is set @@ -2416,10 +2394,11 @@ static int command_line_changed(CommandLineState *s) && !vpeekc_any() && cmdpreview_may_show(s)) { // 'inccommand' preview has been shown. - } else if (cmdpreview) { - cmdpreview = false; - update_screen(UPD_SOME_VALID); // Clear 'inccommand' preview. } else { + cmdpreview = false; + if (prev_cmdpreview) { + update_screen(UPD_SOME_VALID); // Clear 'inccommand' preview. + } if (s->xpc.xp_context == EXPAND_NOTHING && (KeyTyped || vpeekc() == NUL)) { may_do_incsearch_highlighting(s->firstc, s->count, &s->is_state); } @@ -2803,7 +2782,7 @@ static void color_expr_cmdline(const CmdlineInfo *const colored_ccline, ParserLine parser_lines[] = { { .data = (const char *)colored_ccline->cmdbuff, - .size = STRLEN(colored_ccline->cmdbuff), + .size = strlen(colored_ccline->cmdbuff), .allocated = false, }, { NULL, 0, false }, @@ -2881,7 +2860,7 @@ static bool color_cmdline(CmdlineInfo *colored_ccline) // Check whether result of the previous call is still valid. if (ccline_colors->prompt_id == colored_ccline->prompt_id && ccline_colors->cmdbuff != NULL - && STRCMP(ccline_colors->cmdbuff, colored_ccline->cmdbuff) == 0) { + && strcmp(ccline_colors->cmdbuff, colored_ccline->cmdbuff) == 0) { return ret; } @@ -3377,7 +3356,7 @@ void unputcmdline(void) } // Put the given string, of the given length, onto the command line. -// If len is -1, then STRLEN() is used to calculate the length. +// If len is -1, then strlen() is used to calculate the length. // If 'redraw' is true then the new part of the command line, and the remaining // part will be redrawn, otherwise it will not. If this function is called // twice in a row, then 'redraw' should be false and redrawcmd() should be @@ -3716,6 +3695,9 @@ void compute_cmdrow(void) cmdline_row = wp->w_winrow + wp->w_height + wp->w_hsep_height + wp->w_status_height + global_stl_height(); } + if (cmdline_row == Rows) { + cmdline_row--; + } lines_left = cmdline_row; } @@ -3863,7 +3845,7 @@ 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_u *p = xmalloc(strlen(*pp) + 2); p[0] = '\\'; STRCPY(p + 1, *pp); xfree(*pp); @@ -4010,7 +3992,7 @@ static int set_cmdline_str(const char *str, int pos) return 1; } - int len = (int)STRLEN(str); + int len = (int)strlen(str); realloc_cmdbuff(len + 1); p->cmdlen = len; STRCPY(p->cmdbuff, str); @@ -4050,8 +4032,8 @@ static int set_cmdline_pos(int pos) /// "setcmdline()" function void f_setcmdline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - if (argvars[0].v_type != VAR_STRING || argvars[0].vval.v_string == NULL) { - emsg(_(e_stringreq)); + if (tv_check_for_string_arg(argvars, 0) == FAIL + || tv_check_for_opt_number_arg(argvars, 1) == FAIL) { return; } @@ -4347,7 +4329,7 @@ static int open_cmdwin(void) ccline.cmdpos = 0; cmdwin_result = Ctrl_C; } else { - ccline.cmdlen = (int)STRLEN(ccline.cmdbuff); + ccline.cmdlen = (int)strlen(ccline.cmdbuff); ccline.cmdbufflen = ccline.cmdlen + 1; ccline.cmdpos = curwin->w_cursor.col; if (ccline.cmdpos > ccline.cmdlen) { @@ -4420,7 +4402,7 @@ char *script_get(exarg_T *const eap, size_t *const lenp) const char *const cmd = (const char *)eap->arg; if (cmd[0] != '<' || cmd[1] != '<' || eap->getline == NULL) { - *lenp = STRLEN(eap->arg); + *lenp = strlen(eap->arg); return eap->skip ? NULL : xmemdupz(eap->arg, *lenp); } diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c index 5416be651d..d9adf84acc 100644 --- a/src/nvim/file_search.c +++ b/src/nvim/file_search.c @@ -112,7 +112,7 @@ typedef struct ff_visited { FileID file_id; // The memory for this struct is allocated according to the length of // ffv_fname. - char_u ffv_fname[1]; // actually longer + char ffv_fname[1]; // actually longer } ff_visited_T; // We might have to manage several visited lists during a search. @@ -433,16 +433,16 @@ void *vim_findfile_init(char *path, char *filename, char *stopdirs, int level, i } // create an absolute path - if (STRLEN(search_ctx->ffsc_start_dir) - + STRLEN(search_ctx->ffsc_fix_path) + 3 >= MAXPATHL) { + if (strlen(search_ctx->ffsc_start_dir) + + strlen(search_ctx->ffsc_fix_path) + 3 >= MAXPATHL) { emsg(_(e_pathtoolong)); goto error_return; } STRCPY(ff_expand_buffer, search_ctx->ffsc_start_dir); add_pathsep(ff_expand_buffer); { - size_t eb_len = STRLEN(ff_expand_buffer); - char_u *buf = xmalloc(eb_len + STRLEN(search_ctx->ffsc_fix_path) + 1); + size_t eb_len = strlen(ff_expand_buffer); + char_u *buf = xmalloc(eb_len + strlen(search_ctx->ffsc_fix_path) + 1); STRCPY(buf, ff_expand_buffer); STRCPY(buf + eb_len, search_ctx->ffsc_fix_path); @@ -463,16 +463,16 @@ void *vim_findfile_init(char *path, char *filename, char *stopdirs, int level, i xfree(buf); goto error_return; } - STRLCAT(ff_expand_buffer, search_ctx->ffsc_fix_path, eb_len + (size_t)len + 1); + xstrlcat(ff_expand_buffer, search_ctx->ffsc_fix_path, eb_len + (size_t)len + 1); add_pathsep(ff_expand_buffer); } else { - len = (int)STRLEN(search_ctx->ffsc_fix_path); + len = (int)strlen(search_ctx->ffsc_fix_path); } if (search_ctx->ffsc_wc_path != NULL) { wc_path = xstrdup(search_ctx->ffsc_wc_path); - temp = xmalloc(STRLEN(search_ctx->ffsc_wc_path) - + STRLEN(search_ctx->ffsc_fix_path + len) + temp = xmalloc(strlen(search_ctx->ffsc_wc_path) + + strlen(search_ctx->ffsc_fix_path + len) + 1); STRCPY(temp, search_ctx->ffsc_fix_path + len); STRCAT(temp, search_ctx->ffsc_wc_path); @@ -569,7 +569,7 @@ char_u *vim_findfile(void *search_ctx_arg) // store the end of the start dir -- needed for upward search if (search_ctx->ffsc_start_dir != NULL) { - path_end = (char_u *)&search_ctx->ffsc_start_dir[STRLEN(search_ctx->ffsc_start_dir)]; + path_end = (char_u *)&search_ctx->ffsc_start_dir[strlen(search_ctx->ffsc_start_dir)]; } // upward search loop @@ -652,7 +652,7 @@ char_u *vim_findfile(void *search_ctx_arg) // if we have a start dir copy it in if (!vim_isAbsName(stackp->ffs_fix_path) && search_ctx->ffsc_start_dir) { - if (STRLEN(search_ctx->ffsc_start_dir) + 1 >= MAXPATHL) { + if (strlen(search_ctx->ffsc_start_dir) + 1 >= MAXPATHL) { ff_free_stack_element(stackp); goto fail; } @@ -758,8 +758,8 @@ char_u *vim_findfile(void *search_ctx_arg) continue; // not a directory } // prepare the filename to be checked for existence below - if (STRLEN(stackp->ffs_filearray[i]) + 1 - + STRLEN(search_ctx->ffsc_file_to_search) >= MAXPATHL) { + if (strlen(stackp->ffs_filearray[i]) + 1 + + strlen(search_ctx->ffsc_file_to_search) >= MAXPATHL) { ff_free_stack_element(stackp); goto fail; } @@ -813,8 +813,7 @@ char_u *vim_findfile(void *search_ctx_arg) } if (os_dirname((char_u *)ff_expand_buffer, MAXPATHL) == OK) { - p = path_shorten_fname(file_path, - (char_u *)ff_expand_buffer); + p = (char_u *)path_shorten_fname((char *)file_path, ff_expand_buffer); if (p != NULL) { STRMOVE(file_path, p); } @@ -859,8 +858,8 @@ char_u *vim_findfile(void *search_ctx_arg) if (STRNCMP(stackp->ffs_wc_path, "**", 2) == 0) { for (int i = stackp->ffs_filearray_cur; i < stackp->ffs_filearray_size; i++) { - if (FNAMECMP(stackp->ffs_filearray[i], - stackp->ffs_fix_path) == 0) { + if (path_fnamecmp(stackp->ffs_filearray[i], + (char *)stackp->ffs_fix_path) == 0) { continue; // don't repush same directory } if (!os_isdir(stackp->ffs_filearray[i])) { @@ -883,9 +882,9 @@ char_u *vim_findfile(void *search_ctx_arg) ff_stack_T *sptr; // is the last starting directory in the stop list? - if (ff_path_in_stoplist((char_u *)search_ctx->ffsc_start_dir, + if (ff_path_in_stoplist(search_ctx->ffsc_start_dir, (int)(path_end - (char_u *)search_ctx->ffsc_start_dir), - (char_u **)search_ctx->ffsc_stopdirs_v) == true) { + search_ctx->ffsc_stopdirs_v) == true) { break; } @@ -903,8 +902,8 @@ char_u *vim_findfile(void *search_ctx_arg) break; } - if (STRLEN(search_ctx->ffsc_start_dir) + 1 - + STRLEN(search_ctx->ffsc_fix_path) >= MAXPATHL) { + if (strlen(search_ctx->ffsc_start_dir) + 1 + + strlen(search_ctx->ffsc_fix_path) >= MAXPATHL) { goto fail; } STRCPY(file_path, search_ctx->ffsc_start_dir); @@ -981,7 +980,7 @@ static ff_visited_list_hdr_T *ff_get_visited_list(char *filename, if (*list_headp != NULL) { retptr = *list_headp; while (retptr != NULL) { - if (FNAMECMP(filename, retptr->ffvl_filename) == 0) { + if (path_fnamecmp(filename, retptr->ffvl_filename) == 0) { #ifdef FF_VERBOSE if (p_verbose >= 5) { verbose_enter_scroll(); @@ -1080,7 +1079,7 @@ static int ff_check_visited(ff_visited_T **visited_list, char *fname, char *wc_p // check against list of already visited files for (vp = *visited_list; vp != NULL; vp = vp->ffv_next) { - if ((url && FNAMECMP(vp->ffv_fname, ff_expand_buffer) == 0) + if ((url && path_fnamecmp(vp->ffv_fname, ff_expand_buffer) == 0) || (!url && vp->file_id_valid && os_fileid_equal(&(vp->file_id), &file_id))) { // are the wildcard parts equal @@ -1092,7 +1091,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(sizeof(ff_visited_T) + strlen(ff_expand_buffer)); if (!url) { vp->file_id_valid = true; @@ -1224,7 +1223,7 @@ static void ff_clear(ff_search_ctx_T *search_ctx) /// check if the given path is in the stopdirs /// /// @return true if yes else false -static int ff_path_in_stoplist(char_u *path, int path_len, char_u **stopdirs_v) +static int ff_path_in_stoplist(char *path, int path_len, char **stopdirs_v) { int i = 0; @@ -1243,12 +1242,12 @@ static int ff_path_in_stoplist(char_u *path, int path_len, char_u **stopdirs_v) // match for parent directory. So '/home' also matches // '/home/rks'. Check for PATHSEP in stopdirs_v[i], else // '/home/r' would also match '/home/rks' - if (FNAMENCMP(stopdirs_v[i], path, path_len) == 0 + if (path_fnamencmp(stopdirs_v[i], path, (size_t)path_len) == 0 && vim_ispathsep(stopdirs_v[i][path_len])) { return true; } } else { - if (FNAMECMP(stopdirs_v[i], path) == 0) { + if (path_fnamecmp(stopdirs_v[i], path) == 0) { return true; } } @@ -1379,7 +1378,7 @@ char_u *find_file_in_path_option(char_u *ptr, size_t len, int options, int first if (vim_isAbsName((char_u *)ff_file_to_find) // "..", "../path", "." and "./path": don't use the path_option || rel_to_curdir -#if defined(WIN32) +#if defined(MSWIN) // handle "\tmp" as absolute path || vim_ispathsep(ff_file_to_find[0]) // handle "c:name" as absolute path @@ -1398,7 +1397,7 @@ char_u *find_file_in_path_option(char_u *ptr, size_t len, int options, int first // When FNAME_REL flag given first use the directory of the file. // Otherwise or when this fails use the current directory. for (int run = 1; run <= 2; run++) { - size_t l = STRLEN(ff_file_to_find); + size_t l = strlen(ff_file_to_find); if (run == 1 && rel_to_curdir && (options & FNAME_REL) @@ -1406,7 +1405,7 @@ char_u *find_file_in_path_option(char_u *ptr, size_t len, int options, int first && STRLEN(rel_fname) + l < MAXPATHL) { STRCPY(NameBuff, rel_fname); STRCPY(path_tail((char *)NameBuff), ff_file_to_find); - l = STRLEN(NameBuff); + l = strlen(NameBuff); } else { STRCPY(NameBuff, ff_file_to_find); run = 2; diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 0d8eec1023..d391e19964 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -116,8 +116,10 @@ struct bw_info { #endif static char *e_auchangedbuf = N_("E812: Autocommands changed buffer or buffer name"); +static char e_no_matching_autocommands_for_buftype_str_buffer[] + = N_("E676: No matching autocommands for buftype=%s buffer"); -void filemess(buf_T *buf, char_u *name, char_u *s, int attr) +void filemess(buf_T *buf, char *name, char *s, int attr) { int msg_scroll_save; @@ -126,7 +128,7 @@ void filemess(buf_T *buf, char_u *name, char_u *s, int attr) } add_quoted_fname((char *)IObuff, IOSIZE - 100, buf, (const char *)name); // Avoid an over-long translation to cause trouble. - STRLCAT(IObuff, s, IOSIZE); + xstrlcat(IObuff, s, IOSIZE); // For the first message may have to start a new line. // For further ones overwrite the previous one, reset msg_scroll before // calling filemess(). @@ -346,11 +348,11 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip, } // If the name is too long we might crash further on, quit here. if (fname != NULL && *fname != NUL) { - size_t namelen = STRLEN(fname); + size_t namelen = strlen(fname); // If the name is too long we might crash further on, quit here. if (namelen >= MAXPATHL) { - filemess(curbuf, (char_u *)fname, (char_u *)_("Illegal file name"), 0); + filemess(curbuf, fname, _("Illegal file name"), 0); msg_end(); msg_scroll = msg_save; return FAIL; @@ -361,7 +363,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip, // swap file may destroy it! Reported on MS-DOS and Win 95. if (after_pathsep(fname, fname + namelen)) { if (!silent) { - filemess(curbuf, (char_u *)fname, (char_u *)_(msg_is_a_directory), 0); + filemess(curbuf, fname, _(msg_is_a_directory), 0); } msg_end(); msg_scroll = msg_save; @@ -383,10 +385,10 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip, ) { if (S_ISDIR(perm)) { if (!silent) { - filemess(curbuf, (char_u *)fname, (char_u *)_(msg_is_a_directory), 0); + filemess(curbuf, fname, _(msg_is_a_directory), 0); } } else { - filemess(curbuf, (char_u *)fname, (char_u *)_("is not a file"), 0); + filemess(curbuf, fname, _("is not a file"), 0); } msg_end(); msg_scroll = msg_save; @@ -475,9 +477,9 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip, } if (!silent) { if (dir_of_file_exists((char_u *)fname)) { - filemess(curbuf, (char_u *)sfname, (char_u *)new_file_message(), 0); + filemess(curbuf, sfname, new_file_message(), 0); } else { - filemess(curbuf, (char_u *)sfname, (char_u *)_("[New DIRECTORY]"), 0); + filemess(curbuf, sfname, _("[New DIRECTORY]"), 0); } } // Even though this is a new file, it might have been @@ -497,15 +499,15 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip, } return OK; // a new file is not an error } else { - filemess(curbuf, (char_u *)sfname, (char_u *)((fd == UV_EFBIG) ? _("[File too big]") : + filemess(curbuf, sfname, ((fd == UV_EFBIG) ? _("[File too big]") : #if defined(UNIX) && defined(EOVERFLOW) - // libuv only returns -errno - // in Unix and in Windows - // open() does not set - // EOVERFLOW - (fd == -EOVERFLOW) ? _("[File too big]") : + // libuv only returns -errno + // in Unix and in Windows + // open() does not set + // EOVERFLOW + (fd == -EOVERFLOW) ? _("[File too big]") : #endif - _("[Permission Denied]")), 0); + _("[Permission Denied]")), 0); curbuf->b_p_ro = true; // must use "w!" now } @@ -661,7 +663,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip, if (!recoverymode && !filtering && !(flags & READ_DUMMY) && !silent) { if (!read_stdin && !read_buffer) { - filemess(curbuf, (char_u *)sfname, (char_u *)"", 0); + filemess(curbuf, sfname, "", 0); } } @@ -806,11 +808,11 @@ retry: // Conversion may be required when the encoding of the file is different // from 'encoding' or 'encoding' is UTF-16, UCS-2 or UCS-4. fio_flags = 0; - converted = need_conversion((char_u *)fenc); + converted = need_conversion(fenc); if (converted) { // "ucs-bom" means we need to check the first bytes of the file // for a BOM. - if (STRCMP(fenc, ENC_UCSBOM) == 0) { + if (strcmp(fenc, ENC_UCSBOM) == 0) { fio_flags = FIO_UCSBOM; } else { // Check if UCS-2/4 or Latin1 to UTF-8 conversion needs to be @@ -1673,7 +1675,7 @@ failed: if (read_stdin) { close(fd); if (stdin_fd < 0) { -#ifndef WIN32 +#ifndef MSWIN // On Unix, use stderr for stdin, makes shell commands work. vim_ignored = dup(2); #else @@ -1728,7 +1730,7 @@ failed: if (got_int) { if (!(flags & READ_DUMMY)) { - filemess(curbuf, (char_u *)sfname, (char_u *)_(e_interr), 0); + filemess(curbuf, sfname, _(e_interr), 0); if (newfile) { curbuf->b_p_ro = true; // must use "w!" now } @@ -1782,12 +1784,12 @@ failed: c = true; } if (conv_error != 0) { - sprintf((char *)IObuff + STRLEN(IObuff), - _("[CONVERSION ERROR in line %" PRId64 "]"), (int64_t)conv_error); + snprintf(IObuff + strlen(IObuff), IOSIZE - strlen(IObuff), + _("[CONVERSION ERROR in line %" PRId64 "]"), (int64_t)conv_error); c = true; } else if (illegal_byte > 0) { - sprintf((char *)IObuff + STRLEN(IObuff), - _("[ILLEGAL BYTE in line %" PRId64 "]"), (int64_t)illegal_byte); + snprintf(IObuff + strlen(IObuff), IOSIZE - strlen(IObuff), + _("[ILLEGAL BYTE in line %" PRId64 "]"), (int64_t)illegal_byte); c = true; } else if (error) { STRCAT(IObuff, _("[READ ERRORS]")); @@ -1958,7 +1960,7 @@ static linenr_T readfile_linenr(linenr_T linecnt, char_u *p, char_u *endp) void prep_exarg(exarg_T *eap, const buf_T *buf) FUNC_ATTR_NONNULL_ALL { - const size_t cmd_len = 15 + STRLEN(buf->b_p_fenc); + const size_t cmd_len = 15 + strlen(buf->b_p_fenc); eap->cmd = xmalloc(cmd_len); snprintf(eap->cmd, cmd_len, "e ++enc=%s", buf->b_p_fenc); @@ -2022,7 +2024,7 @@ static char *next_fenc(char **pp, bool *alloced) p = vim_strchr((*pp), ','); if (p == NULL) { r = enc_canonize(*pp); - *pp += STRLEN(*pp); + *pp += strlen(*pp); } else { r = xstrnsave(*pp, (size_t)(p - *pp)); *pp = p + 1; @@ -2203,7 +2205,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en } // Avoid a crash for a long name. - if (STRLEN(fname) >= MAXPATHL) { + if (strlen(fname) >= MAXPATHL) { emsg(_(e_longname)); return FAIL; } @@ -2253,7 +2255,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en fname = sfname; #endif - if (buf->b_ffname != NULL && FNAMECMP(ffname, buf->b_ffname) == 0) { + if (buf->b_ffname != NULL && path_fnamecmp(ffname, buf->b_ffname) == 0) { overwriting = true; } else { overwriting = false; @@ -2366,7 +2368,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en no_wait_return--; msg_scroll = msg_save; if (nofile_err) { - emsg(_("E676: No matching autocommands for acwrite buffer")); + semsg(_(e_no_matching_autocommands_for_buftype_str_buffer), curbuf->b_p_bt); } if (nofile_err @@ -2455,9 +2457,9 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en #ifndef UNIX (char_u *)sfname, #else - (char_u *)fname, + fname, #endif - (char_u *)"", 0); // show that we are busy + "", 0); // show that we are busy } msg_scroll = false; // always overwrite the file message now @@ -2596,7 +2598,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en STRCPY(IObuff, fname); for (i = 4913;; i += 123) { char *tail = path_tail((char *)IObuff); - size_t size = (size_t)((char_u *)tail - IObuff); + size_t size = (size_t)(tail - IObuff); snprintf(tail, IOSIZE - size, "%d", i); if (!os_fileinfo_link((char *)IObuff, &file_info)) { break; @@ -2733,7 +2735,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); + wp = backup + strlen(backup) - 1 - strlen(backup_ext); if (wp < backup) { // empty file name ??? wp = backup; } @@ -2861,7 +2863,7 @@ nobackup: // delete an existing one, try to use another name. // Change one character, just before the extension. if (!p_bk && os_path_exists(backup)) { - p = backup + STRLEN(backup) - 1 - STRLEN(backup_ext); + p = backup + strlen(backup) - 1 - strlen(backup_ext); if (p < backup) { // empty file name ??? p = backup; } @@ -2884,7 +2886,7 @@ nobackup: // If the renaming of the original file to the backup file // works, quit here. /// - if (vim_rename((char_u *)fname, (char_u *)backup) == 0) { + if (vim_rename(fname, backup) == 0) { break; } @@ -2952,7 +2954,7 @@ nobackup: } // Check if the file needs to be converted. - converted = need_conversion((char_u *)fenc); + converted = need_conversion(fenc); // Check if UTF-8 to UCS-2/4 or Latin1 conversion needs to be done. Or // Latin1 to Unicode conversion. This is handled in buf_write_bytes(). @@ -3100,7 +3102,7 @@ restore_backup: // In that case we leave the copy around. // If file does not exist, put the copy in its place if (!os_path_exists(fname)) { - vim_rename((char_u *)backup, (char_u *)fname); + vim_rename(backup, fname); } // if original file does exist throw away the copy if (os_path_exists(fname)) { @@ -3108,7 +3110,7 @@ restore_backup: } } else { // try to put the original file back - vim_rename((char_u *)backup, (char_u *)fname); + vim_rename(backup, fname); } } @@ -3172,7 +3174,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, (char_u *)ptr + 1, (uint32_t)(strlen(ptr + 1) + 1)); } while ((c = *++ptr) != NUL) { if (c == NL) { @@ -3375,7 +3377,7 @@ restore_backup: end = 1; // success } } else { - if (vim_rename((char_u *)backup, (char_u *)fname) == 0) { + if (vim_rename(backup, fname) == 0) { end = 1; } } @@ -3471,7 +3473,7 @@ restore_backup: if (org == NULL) { emsg(_("E205: Patchmode: can't save original file")); } else if (!os_path_exists(org)) { - vim_rename((char_u *)backup, (char_u *)org); + vim_rename(backup, org); XFREE_CLEAR(backup); // don't delete the file #ifdef UNIX os_file_settime(org, @@ -3716,20 +3718,20 @@ void msg_add_lines(int insert_space, long lnum, off_T nchars) { char_u *p; - p = IObuff + STRLEN(IObuff); + p = (char_u *)IObuff + STRLEN(IObuff); if (insert_space) { *p++ = ' '; } if (shortmess(SHM_LINES)) { - vim_snprintf((char *)p, (size_t)(IOSIZE - (p - IObuff)), "%" PRId64 "L, %" PRId64 "B", + vim_snprintf((char *)p, (size_t)(IOSIZE - (p - (char_u *)IObuff)), "%" PRId64 "L, %" PRId64 "B", (int64_t)lnum, (int64_t)nchars); } else { - vim_snprintf((char *)p, (size_t)(IOSIZE - (p - IObuff)), + vim_snprintf((char *)p, (size_t)(IOSIZE - (p - (char_u *)IObuff)), NGETTEXT("%" PRId64 " line, ", "%" PRId64 " lines, ", lnum), (int64_t)lnum); p += STRLEN(p); - vim_snprintf((char *)p, (size_t)(IOSIZE - (p - IObuff)), + vim_snprintf((char *)p, (size_t)(IOSIZE - (p - (char_u *)IObuff)), NGETTEXT("%" PRId64 " byte", "%" PRId64 " bytes", nchars), (int64_t)nchars); } @@ -4028,21 +4030,21 @@ static bool ucs2bytes(unsigned c, char_u **pp, int flags) FUNC_ATTR_NONNULL_ALL /// @param fenc file encoding to check /// /// @return true if conversion is required -static bool need_conversion(const char_u *fenc) +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) { + if (*fenc == NUL || strcmp(p_enc, fenc) == 0) { same_encoding = true; fenc_flags = 0; } 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(fenc); + fenc_flags = get_fio_flags((char_u *)fenc); same_encoding = (enc_flags != 0 && fenc_flags == enc_flags); } if (same_encoding) { @@ -4189,7 +4191,7 @@ void shorten_buf_fname(buf_T *buf, char_u *dirname, int force) if (buf->b_sfname != buf->b_ffname) { XFREE_CLEAR(buf->b_sfname); } - p = (char *)path_shorten_fname((char_u *)buf->b_ffname, dirname); + p = path_shorten_fname(buf->b_ffname, (char *)dirname); if (p != NULL) { buf->b_sfname = xstrdup(p); buf->b_fname = buf->b_sfname; @@ -4481,7 +4483,7 @@ int put_time(FILE *fd, time_t time_) /// function will (attempts to?) copy the file across if rename fails -- webb /// /// @return -1 for failure, 0 for success -int vim_rename(const char_u *from, const char_u *to) +int vim_rename(const char *from, const char *to) FUNC_ATTR_NONNULL_ALL { int fd_in; @@ -4498,8 +4500,8 @@ int vim_rename(const char_u *from, const char_u *to) // When the names are identical, there is nothing to do. When they refer // to the same file (ignoring case and slash/backslash differences) but // the file name differs we need to go through a temp file. - if (FNAMECMP(from, to) == 0) { - if (p_fic && (STRCMP(path_tail((char *)from), path_tail((char *)to)) + if (path_fnamecmp(from, to) == 0) { + if (p_fic && (strcmp(path_tail((char *)from), path_tail((char *)to)) != 0)) { use_tmp_file = true; } else { @@ -4527,7 +4529,7 @@ int vim_rename(const char_u *from, const char_u *to) // Find a name that doesn't exist and is in the same directory. // Rename "from" to "tempname" and then rename "tempname" to "to". - if (STRLEN(from) >= MAXPATHL - 5) { + if (strlen(from) >= MAXPATHL - 5) { return -1; } STRCPY(tempname, from); @@ -4536,13 +4538,13 @@ int vim_rename(const char_u *from, const char_u *to) snprintf(tail, (size_t)((MAXPATHL + 1) - (tail - (char *)tempname - 1)), "%d", n); if (!os_path_exists((char *)tempname)) { - if (os_rename(from, tempname) == OK) { - if (os_rename(tempname, to) == OK) { + if (os_rename((char_u *)from, tempname) == OK) { + if (os_rename(tempname, (char_u *)to) == OK) { return 0; } // Strange, the second step failed. Try moving the // file back and return failure. - (void)os_rename(tempname, from); + (void)os_rename(tempname, (char_u *)from); return -1; } // If it fails for one temp name it will most likely fail @@ -4560,15 +4562,15 @@ int vim_rename(const char_u *from, const char_u *to) os_remove((char *)to); // First try a normal rename, return if it works. - if (os_rename(from, to) == OK) { + if (os_rename((char_u *)from, (char_u *)to) == OK) { return 0; } // Rename() failed, try copying the file. - perm = os_getperm((const char *)from); + perm = os_getperm(from); #ifdef HAVE_ACL // For systems that support ACL: get the ACL from the original file. - acl = mch_get_acl(from); + acl = mch_get_acl((char_u *)from); #endif fd_in = os_open((char *)from, O_RDONLY, 0); if (fd_in < 0) { @@ -4621,7 +4623,7 @@ int vim_rename(const char_u *from, const char_u *to) os_setperm((const char *)to, perm); #endif #ifdef HAVE_ACL - mch_set_acl(to, acl); + mch_set_acl((char_u *)to, acl); mch_free_acl(acl); #endif if (errmsg != NULL) { @@ -4745,7 +4747,7 @@ int buf_check_timestamp(buf_T *buf) FUNC_ATTR_NONNULL_ALL { int retval = 0; - char_u *path; + char *path; char *mesg = NULL; char *mesg2 = ""; bool helpmesg = false; @@ -4760,7 +4762,7 @@ 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_u *s; + char *s; char *reason; bufref_T bufref; @@ -4835,12 +4837,12 @@ int buf_check_timestamp(buf_T *buf) if (!bufref_valid(&bufref)) { emsg(_("E246: FileChangedShell autocommand deleted buffer")); } - s = (char_u *)get_vim_var_str(VV_FCS_CHOICE); - if (STRCMP(s, "reload") == 0 && *reason != 'd') { + s = get_vim_var_str(VV_FCS_CHOICE); + if (strcmp(s, "reload") == 0 && *reason != 'd') { reload = RELOAD_NORMAL; - } else if (STRCMP(s, "edit") == 0) { + } else if (strcmp(s, "edit") == 0) { reload = RELOAD_DETECT; - } else if (STRCMP(s, "ask") == 0) { + } else if (strcmp(s, "ask") == 0) { n = false; } else { return 2; @@ -4888,11 +4890,11 @@ int buf_check_timestamp(buf_T *buf) } if (mesg != NULL) { - path = (char_u *)home_replace_save(buf, buf->b_fname); + path = home_replace_save(buf, buf->b_fname); if (!helpmesg) { mesg2 = ""; } - const size_t tbuf_len = STRLEN(path) + STRLEN(mesg) + STRLEN(mesg2) + 2; + const size_t tbuf_len = strlen(path) + strlen(mesg) + strlen(mesg2) + 2; char *const tbuf = xmalloc(tbuf_len); snprintf(tbuf, tbuf_len, mesg, path); // Set warningmsg here, before the unimportant and output-specific @@ -5489,7 +5491,7 @@ char *file_pat_to_reg_pat(const char *pat, const char *pat_end, char *allow_dirs *allow_dirs = false; } if (pat_end == NULL) { - pat_end = pat + STRLEN(pat); + pat_end = pat + strlen(pat); } if (pat_end == pat) { diff --git a/src/nvim/fold.c b/src/nvim/fold.c index 2e8d282ede..d46470d413 100644 --- a/src/nvim/fold.c +++ b/src/nvim/fold.c @@ -996,7 +996,7 @@ void foldAdjustVisual(void) } if (hasFolding(end->lnum, NULL, &end->lnum)) { ptr = ml_get(end->lnum); - end->col = (colnr_T)STRLEN(ptr); + end->col = (colnr_T)strlen(ptr); if (end->col > 0 && *p_sel == 'o') { end->col--; } @@ -1589,7 +1589,7 @@ static void foldAddMarker(buf_T *buf, pos_T pos, const char *marker, size_t mark if (u_save(lnum - 1, lnum + 1) == OK) { // Check if the line ends with an unclosed comment skip_comment(line, false, false, &line_is_comment); - newline = xmalloc(line_len + markerlen + STRLEN(cms) + 1); + newline = xmalloc(line_len + markerlen + strlen(cms) + 1); STRCPY(newline, line); // Append the marker to the end of the line if (p == NULL || line_is_comment) { @@ -1599,7 +1599,7 @@ static void foldAddMarker(buf_T *buf, pos_T pos, const char *marker, size_t mark STRCPY(newline + line_len, cms); memcpy(newline + line_len + (p - cms), marker, markerlen); STRCPY(newline + line_len + (p - cms) + markerlen, p + 2); - added = markerlen + STRLEN(cms) - 2; + added = markerlen + strlen(cms) - 2; } ml_replace_buf(buf, lnum, newline, false); if (added) { @@ -1655,14 +1655,14 @@ static void foldDelMarker(buf_T *buf, linenr_T lnum, char *marker, size_t marker char *cms2 = strstr(cms, "%s"); if (p - line >= cms2 - cms && STRNCMP(p - (cms2 - cms), cms, cms2 - cms) == 0 - && STRNCMP(p + len, cms2 + 2, STRLEN(cms2 + 2)) == 0) { + && STRNCMP(p + len, cms2 + 2, strlen(cms2 + 2)) == 0) { p -= cms2 - cms; - len += STRLEN(cms) - 2; + len += strlen(cms) - 2; } } if (u_save(lnum - 1, lnum + 1) == OK) { // Make new line: text-before-marker + text-after-marker - char *newline = xmalloc(STRLEN(line) - len + 1); + char *newline = xmalloc(strlen(line) - len + 1); assert(p >= line); memcpy(newline, line, (size_t)(p - line)); STRCPY(newline + (p - line), p + len); @@ -1789,7 +1789,7 @@ static void foldtext_cleanup(char *str) { // Ignore leading and trailing white space in 'commentstring'. char *cms_start = skipwhite(curbuf->b_p_cms); - size_t cms_slen = STRLEN(cms_start); + size_t cms_slen = strlen(cms_start); while (cms_slen > 0 && ascii_iswhite(cms_start[cms_slen - 1])) { cms_slen--; } @@ -2985,7 +2985,7 @@ static void parseMarker(win_T *wp) { foldendmarker = vim_strchr(wp->w_p_fmr, ','); foldstartmarkerlen = (size_t)(foldendmarker++ - wp->w_p_fmr); - foldendmarkerlen = STRLEN(foldendmarker); + foldendmarkerlen = strlen(foldendmarker); } // foldlevelMarker() {{{2 @@ -3262,13 +3262,13 @@ void f_foldtext(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } int count = foldend - foldstart + 1; char *txt = NGETTEXT("+-%s%3ld line: ", "+-%s%3ld lines: ", count); - size_t len = STRLEN(txt) - + STRLEN(dashes) // for %s + size_t len = strlen(txt) + + strlen(dashes) // for %s + 20 // for %3ld + STRLEN(s); // concatenated char *r = xmalloc(len); snprintf(r, len, txt, dashes, count); - len = STRLEN(r); + len = strlen(r); STRCAT(r, s); // remove 'foldmarker' and 'commentstring' foldtext_cleanup(r + len); diff --git a/src/nvim/garray.c b/src/nvim/garray.c index 1afabe4e10..6c63ce5a7c 100644 --- a/src/nvim/garray.c +++ b/src/nvim/garray.c @@ -123,7 +123,7 @@ void ga_remove_duplicate_strings(garray_T *gap) // loop over the growing array in reverse for (int i = gap->ga_len - 1; i > 0; i--) { - if (FNAMECMP(fnames[i - 1], fnames[i]) == 0) { + if (path_fnamecmp(fnames[i - 1], fnames[i]) == 0) { xfree(fnames[i]); // close the gap (move all strings one slot lower) @@ -198,7 +198,7 @@ void ga_concat(garray_T *gap, const char *restrict s) return; } - ga_concat_len(gap, s, STRLEN(s)); + ga_concat_len(gap, s, strlen(s)); } /// Concatenate a string to a growarray which contains characters diff --git a/src/nvim/generators/gen_declarations.lua b/src/nvim/generators/gen_declarations.lua index c7d5a1a191..bf1adaeee3 100755 --- a/src/nvim/generators/gen_declarations.lua +++ b/src/nvim/generators/gen_declarations.lua @@ -218,7 +218,7 @@ local footer = [[ local non_static = header .. [[ #ifndef DLLEXPORT -# ifdef WIN32 +# ifdef MSWIN # define DLLEXPORT __declspec(dllexport) # else # define DLLEXPORT diff --git a/src/nvim/generators/gen_options.lua b/src/nvim/generators/gen_options.lua index 0454c54faf..24b4739fc7 100644 --- a/src/nvim/generators/gen_options.lua +++ b/src/nvim/generators/gen_options.lua @@ -115,7 +115,7 @@ local value_dumpers = { } local get_value = function(v) - return '(char_u *) ' .. value_dumpers[type(v)](v) + return '(char *) ' .. value_dumpers[type(v)](v) end local get_defaults = function(d,n) diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 0f0e3aece1..fd0acce25f 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -148,7 +148,7 @@ static char_u *get_buffcont(buffheader_T *buffer, int dozero) // compute the total length of the string for (const buffblock_T *bp = buffer->bh_first.b_next; bp != NULL; bp = bp->b_next) { - count += STRLEN(bp->b_str); + count += strlen(bp->b_str); } if (count || dozero) { @@ -225,13 +225,13 @@ static void add_buff(buffheader_T *const buf, const char *const s, ptrdiff_t sle } else if (buf->bh_index != 0) { memmove(buf->bh_first.b_next->b_str, buf->bh_first.b_next->b_str + buf->bh_index, - STRLEN(buf->bh_first.b_next->b_str + buf->bh_index) + 1); + strlen(buf->bh_first.b_next->b_str + buf->bh_index) + 1); } buf->bh_index = 0; size_t len; if (buf->bh_space >= (size_t)slen) { - len = STRLEN(buf->bh_curr->b_str); + len = strlen(buf->bh_curr->b_str); STRLCPY(buf->bh_curr->b_str + len, s, slen + 1); buf->bh_space -= (size_t)slen; } else { @@ -259,7 +259,7 @@ static void delete_buff_tail(buffheader_T *buf, int slen) if (buf->bh_curr == NULL) { return; // nothing to delete } - len = (int)STRLEN(buf->bh_curr->b_str); + len = (int)strlen(buf->bh_curr->b_str); if (len >= slen) { buf->bh_curr->b_str[len - slen] = NUL; buf->bh_space += (size_t)slen; @@ -845,7 +845,7 @@ int ins_typebuf(char *str, int noremap, int offset, bool nottyped, bool silent) typebuf.tb_change_cnt = 1; } - addlen = (int)STRLEN(str); + addlen = (int)strlen(str); if (offset == 0 && addlen <= typebuf.tb_off) { // Easy case: there is room in front of typebuf.tb_buf[typebuf.tb_off] @@ -1655,9 +1655,10 @@ static void getchar_common(typval_T *argvars, typval_T *rettv) no_mapping++; allow_keys++; for (;;) { - // Position the cursor. Needed after a message that ends in a space, - // or if event processing caused a redraw. - ui_cursor_goto(msg_row, msg_col); + if (msg_col > 0) { + // Position the cursor. Needed after a message that ends in a space. + ui_cursor_goto(msg_row, msg_col); + } if (argvars[0].v_type == VAR_UNKNOWN) { // getchar(): blocking wait. @@ -1665,7 +1666,7 @@ static void getchar_common(typval_T *argvars, typval_T *rettv) if (!char_avail()) { // flush output before waiting ui_flush(); - (void)os_inchar(NULL, 0, -1, 0, main_loop.events); + (void)os_inchar(NULL, 0, -1, typebuf.tb_change_cnt, main_loop.events); if (!multiqueue_empty(main_loop.events)) { state_handle_k_event(); continue; @@ -1695,12 +1696,6 @@ static void getchar_common(typval_T *argvars, typval_T *rettv) no_mapping--; allow_keys--; - if (!ui_has_messages()) { - // redraw the screen after getchar() - update_screen(UPD_NOT_VALID); - clear_cmdline = true; - } - set_vim_var_nr(VV_MOUSE_WIN, 0); set_vim_var_nr(VV_MOUSE_WINID, 0); set_vim_var_nr(VV_MOUSE_LNUM, 0); diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 84c01e0140..578ed478c6 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -23,7 +23,7 @@ #define MSG_BUF_CLEN (MSG_BUF_LEN / 6) // cell length (worst case: utf-8 // takes 6 bytes for one cell) -#ifdef WIN32 +#ifdef MSWIN # define _PATHSEPSTR "\\" #else # define _PATHSEPSTR "/" @@ -670,7 +670,7 @@ EXTERN bool cmd_silent INIT(= false); // don't echo the command line EXTERN int swap_exists_action INIT(= SEA_NONE); ///< For dialog when swap file already exists. EXTERN bool swap_exists_did_quit INIT(= false); ///< Selected "quit" at the dialog. -EXTERN char_u IObuff[IOSIZE]; ///< Buffer for sprintf, I/O, etc. +EXTERN char IObuff[IOSIZE]; ///< Buffer for sprintf, I/O, etc. EXTERN char NameBuff[MAXPATHL]; ///< Buffer for expanding file names EXTERN char msg_buf[MSG_BUF_LEN]; ///< Small buffer for messages EXTERN char os_buf[ ///< Buffer for the os/ layer @@ -1071,7 +1071,4 @@ EXTERN char windowsVersion[20] INIT(= { 0 }); EXTERN int exit_need_delay INIT(= 0); -// Set when 'cmdheight' is changed from zero to one temporarily. -EXTERN bool made_cmdheight_nonzero INIT(= false); - #endif // NVIM_GLOBALS_H diff --git a/src/nvim/grid.c b/src/nvim/grid.c index 22445b9ec7..2b73ff895d 100644 --- a/src/nvim/grid.c +++ b/src/nvim/grid.c @@ -46,14 +46,14 @@ void grid_adjust(ScreenGrid **grid, int *row_off, int *col_off) } /// Put a unicode char, and up to MAX_MCO composing chars, in a screen cell. -int schar_from_cc(char_u *p, int c, int u8cc[MAX_MCO]) +int schar_from_cc(char *p, int c, int u8cc[MAX_MCO]) { - int len = utf_char2bytes(c, (char *)p); + int len = utf_char2bytes(c, p); for (int i = 0; i < MAX_MCO; i++) { if (u8cc[i] == 0) { break; } - len += utf_char2bytes(u8cc[i], (char *)p + len); + len += utf_char2bytes(u8cc[i], p + len); } p[len] = 0; return len; @@ -140,7 +140,7 @@ void grid_getbytes(ScreenGrid *grid, int row, int col, char_u *bytes, int *attrp 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]); + schar_copy((char *)bytes, grid->chars[off]); } } @@ -171,11 +171,11 @@ void grid_puts_line_start(ScreenGrid *grid, int row) put_dirty_grid = grid; } -void grid_put_schar(ScreenGrid *grid, int row, int col, char_u *schar, int attr) +void grid_put_schar(ScreenGrid *grid, int row, int col, char *schar, int attr) { assert(put_dirty_row == row); size_t off = grid->line_offset[row] + (size_t)col; - if (grid->attrs[off] != attr || schar_cmp(grid->chars[off], schar)) { + if (grid->attrs[off] != attr || schar_cmp(grid->chars[off], schar) || rdb_flags & RDB_NODELTA) { schar_copy(grid->chars[off], schar); grid->attrs[off] = attr; @@ -280,7 +280,8 @@ void grid_puts_len(ScreenGrid *grid, char *text, int textlen, int row, int col, need_redraw = schar_cmp(grid->chars[off], buf) || (mbyte_cells == 2 && grid->chars[off + 1][0] != 0) || grid->attrs[off] != attr - || exmode_active; + || exmode_active + || rdb_flags & RDB_NODELTA; if (need_redraw) { // When at the end of the text and overwriting a two-cell @@ -412,8 +413,7 @@ void grid_fill(ScreenGrid *grid, int start_row, int end_row, int start_col, int size_t lineoff = grid->line_offset[row]; for (col = start_col; col < end_col; col++) { size_t off = lineoff + (size_t)col; - if (schar_cmp(grid->chars[off], sc) - || grid->attrs[off] != attr) { + if (schar_cmp(grid->chars[off], sc) || grid->attrs[off] != attr || rdb_flags & RDB_NODELTA) { schar_copy(grid->chars[off], sc); grid->attrs[off] = attr; if (dirty_first == INT_MAX) { @@ -605,7 +605,8 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol, int cle while (col < clear_width) { if (grid->chars[off_to][0] != ' ' || grid->chars[off_to][1] != NUL - || grid->attrs[off_to] != bg_attr) { + || grid->attrs[off_to] != bg_attr + || rdb_flags & RDB_NODELTA) { grid->chars[off_to][0] = ' '; grid->chars[off_to][1] = NUL; grid->attrs[off_to] = bg_attr; diff --git a/src/nvim/grid.h b/src/nvim/grid.h index 6a93bf3d90..0e79183c14 100644 --- a/src/nvim/grid.h +++ b/src/nvim/grid.h @@ -29,30 +29,30 @@ EXTERN sattr_T *linebuf_attr INIT(= NULL); // screen grid. /// Put a ASCII character in a screen cell. -static inline void schar_from_ascii(char_u *p, const char c) +static inline void schar_from_ascii(char *p, const char c) { - p[0] = (char_u)c; + p[0] = c; p[1] = 0; } /// Put a unicode character in a screen cell. -static inline int schar_from_char(char_u *p, int c) +static inline int schar_from_char(char *p, int c) { - int len = utf_char2bytes(c, (char *)p); + int len = utf_char2bytes(c, p); p[len] = NUL; return len; } /// compare the contents of two screen cells. -static inline int schar_cmp(char_u *sc1, char_u *sc2) +static inline int schar_cmp(char *sc1, char *sc2) { - return strncmp((char *)sc1, (char *)sc2, sizeof(schar_T)); + return strncmp(sc1, sc2, sizeof(schar_T)); } /// copy the contents of screen cell `sc2` into cell `sc1` -static inline void schar_copy(char_u *sc1, char_u *sc2) +static inline void schar_copy(char *sc1, char *sc2) { - xstrlcpy((char *)sc1, (char *)sc2, sizeof(schar_T)); + xstrlcpy(sc1, sc2, sizeof(schar_T)); } #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/grid_defs.h b/src/nvim/grid_defs.h index 9252b8a371..57b3817bc6 100644 --- a/src/nvim/grid_defs.h +++ b/src/nvim/grid_defs.h @@ -10,7 +10,7 @@ #define MAX_MCO 6 // fixed value for 'maxcombine' // The characters and attributes drawn on grids. -typedef char_u schar_T[(MAX_MCO + 1) * 4 + 1]; +typedef char schar_T[(MAX_MCO + 1) * 4 + 1]; typedef int sattr_T; enum { diff --git a/src/nvim/hardcopy.c b/src/nvim/hardcopy.c index 903349dcae..c46f95b64f 100644 --- a/src/nvim/hardcopy.c +++ b/src/nvim/hardcopy.c @@ -663,7 +663,7 @@ void ex_hardcopy(exarg_T *eap) // Estimate the total lines to be printed for (lnum = eap->line1; lnum <= eap->line2; lnum++) { - bytes_to_print += STRLEN(skipwhite((char *)ml_get(lnum))); + bytes_to_print += strlen(skipwhite(ml_get(lnum))); } if (bytes_to_print == 0) { msg(_("No text to be printed")); @@ -734,17 +734,17 @@ void ex_hardcopy(exarg_T *eap) sprintf((char *)IObuff, _("Printing page %d (%zu%%)"), page_count + 1 + side, prtpos.bytes_printed * 100 / bytes_to_print); - if (!mch_print_begin_page(IObuff)) { + if (!mch_print_begin_page((char_u *)IObuff)) { goto print_fail; } if (settings.n_collated_copies > 1) { - sprintf((char *)IObuff + STRLEN(IObuff), - _(" Copy %d of %d"), - collated_copies + 1, - settings.n_collated_copies); + snprintf(IObuff + strlen(IObuff), IOSIZE - strlen(IObuff), + _(" Copy %d of %d"), + collated_copies + 1, + settings.n_collated_copies); } - prt_message(IObuff); + prt_message((char_u *)IObuff); // Output header if required if (prt_header_height() > 0) { @@ -759,7 +759,7 @@ void ex_hardcopy(exarg_T *eap) if (prtpos.column == 0) { // finished a file line prtpos.bytes_printed += - STRLEN(skipwhite((char *)ml_get(prtpos.file_line))); + strlen(skipwhite(ml_get(prtpos.file_line))); if (++prtpos.file_line > eap->line2) { break; // reached the end } @@ -798,13 +798,13 @@ void ex_hardcopy(exarg_T *eap) vim_snprintf((char *)IObuff, IOSIZE, _("Printed: %s"), settings.jobname); - prt_message(IObuff); + prt_message((char_u *)IObuff); } print_fail: if (got_int || settings.user_abort) { - sprintf((char *)IObuff, "%s", _("Printing aborted")); - prt_message(IObuff); + snprintf(IObuff, IOSIZE, "%s", _("Printing aborted")); + prt_message((char_u *)IObuff); } mch_print_end(&settings); @@ -1278,7 +1278,7 @@ static void prt_write_file_raw_len(char_u *buffer, size_t bytes) static void prt_write_file(char *buffer) { - prt_write_file_len((char_u *)buffer, STRLEN(buffer)); + prt_write_file_len((char_u *)buffer, strlen(buffer)); } static void prt_write_file_len(char_u *buffer, size_t bytes) @@ -1475,7 +1475,7 @@ static void prt_resource_name(char *filename, void *cookie) { char_u *resource_filename = cookie; - if (STRLEN(filename) >= MAXPATHL) { + if (strlen(filename) >= MAXPATHL) { *resource_filename = NUL; } else { STRCPY(resource_filename, filename); @@ -1493,8 +1493,8 @@ static int prt_find_resource(char *name, struct prt_ps_resource_S *resource) // Look for named resource file in runtimepath STRCPY(buffer, "print"); add_pathsep(buffer); - STRLCAT(buffer, name, MAXPATHL); - STRLCAT(buffer, ".ps", MAXPATHL); + xstrlcat(buffer, name, MAXPATHL); + xstrlcat(buffer, ".ps", MAXPATHL); resource->filename[0] = NUL; retval = (do_in_runtimepath(buffer, 0, prt_resource_name, resource->filename) && resource->filename[0] != NUL); @@ -1653,14 +1653,14 @@ static bool prt_open_resource(struct prt_ps_resource_S *resource) int offset = 0; if (prt_resfile_strncmp(offset, PRT_RESOURCE_HEADER, - (int)STRLEN(PRT_RESOURCE_HEADER)) != 0) { + (int)strlen(PRT_RESOURCE_HEADER)) != 0) { semsg(_("E618: file \"%s\" is not a PostScript resource file"), resource->filename); return false; } // Skip over any version numbers and following ws - offset += (int)STRLEN(PRT_RESOURCE_HEADER); + offset += (int)strlen(PRT_RESOURCE_HEADER); offset = prt_resfile_skip_nonws(offset); if (offset == -1) { return false; @@ -1670,22 +1670,22 @@ static bool prt_open_resource(struct prt_ps_resource_S *resource) return false; } if (prt_resfile_strncmp(offset, PRT_RESOURCE_RESOURCE, - (int)STRLEN(PRT_RESOURCE_RESOURCE)) != 0) { + (int)strlen(PRT_RESOURCE_RESOURCE)) != 0) { semsg(_("E619: file \"%s\" is not a supported PostScript resource file"), resource->filename); return false; } - offset += (int)STRLEN(PRT_RESOURCE_RESOURCE); + offset += (int)strlen(PRT_RESOURCE_RESOURCE); // Decide type of resource in the file if (prt_resfile_strncmp(offset, PRT_RESOURCE_PROCSET, - (int)STRLEN(PRT_RESOURCE_PROCSET)) == 0) { + (int)strlen(PRT_RESOURCE_PROCSET)) == 0) { resource->type = PRT_RESOURCE_TYPE_PROCSET; } else if (prt_resfile_strncmp(offset, PRT_RESOURCE_ENCODING, - (int)STRLEN(PRT_RESOURCE_ENCODING)) == 0) { + (int)strlen(PRT_RESOURCE_ENCODING)) == 0) { resource->type = PRT_RESOURCE_TYPE_ENCODING; } else if (prt_resfile_strncmp(offset, PRT_RESOURCE_CMAP, - (int)STRLEN(PRT_RESOURCE_CMAP)) == 0) { + (int)strlen(PRT_RESOURCE_CMAP)) == 0) { resource->type = PRT_RESOURCE_TYPE_CMAP; } else { semsg(_("E619: file \"%s\" is not a supported PostScript resource file"), @@ -2021,7 +2021,7 @@ static int prt_match_encoding(char *p_encoding, struct prt_ps_mbfont_S *p_cmap, *pp_mbenc = NULL; // Look for recognised encoding - enc_len = (int)STRLEN(p_encoding); + enc_len = (int)strlen(p_encoding); p_mbenc = p_cmap->encodings; for (mbenc = 0; mbenc < p_cmap->num_encodings; mbenc++) { if (STRNICMP(p_mbenc->encoding, p_encoding, enc_len) == 0) { @@ -2044,7 +2044,7 @@ static int prt_match_charset(char *p_charset, struct prt_ps_mbfont_S *p_cmap, if (*p_charset == NUL) { p_charset = p_cmap->defcs; } - char_len = (int)STRLEN(p_charset); + char_len = (int)strlen(p_charset); p_mbchar = p_cmap->charsets; for (mbchar = 0; mbchar < p_cmap->num_charsets; mbchar++) { if (STRNICMP(p_mbchar->charset, p_charset, char_len) == 0) { @@ -2135,8 +2135,8 @@ int mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit) } // CMap name ends with (optional) encoding name and -H for horizontal - if (p_mbenc->cmap_encoding != NULL && STRLEN(prt_cmap) - + STRLEN(p_mbenc->cmap_encoding) + 3 < sizeof(prt_cmap)) { + if (p_mbenc->cmap_encoding != NULL && strlen(prt_cmap) + + strlen(p_mbenc->cmap_encoding) + 3 < sizeof(prt_cmap)) { STRCAT(prt_cmap, p_mbenc->cmap_encoding); STRCAT(prt_cmap, "-"); } @@ -2200,7 +2200,7 @@ int mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit) paper_strlen = 2; } for (i = 0; i < (int)PRT_MEDIASIZE_LEN; i++) { - if (STRLEN(prt_mediasize[i].name) == (unsigned)paper_strlen + if (strlen(prt_mediasize[i].name) == (unsigned)paper_strlen && STRNICMP(prt_mediasize[i].name, paper_name, paper_strlen) == 0) { break; diff --git a/src/nvim/hashtab.c b/src/nvim/hashtab.c index 308f64f011..3d0ab192b9 100644 --- a/src/nvim/hashtab.c +++ b/src/nvim/hashtab.c @@ -87,7 +87,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((char_u *)key)); } /// Like hash_find, but key is not NUL-terminated diff --git a/src/nvim/help.c b/src/nvim/help.c index 235f64744a..a24b17e34e 100644 --- a/src/nvim/help.c +++ b/src/nvim/help.c @@ -75,7 +75,7 @@ void ex_help(exarg_T *eap) } // remove trailing blanks - p = arg + STRLEN(arg) - 1; + p = arg + strlen(arg) - 1; while (p > arg && ascii_iswhite(*p) && p[-1] != '\\') { *p-- = NUL; } @@ -95,7 +95,7 @@ void ex_help(exarg_T *eap) if (n != FAIL && lang != NULL) { // Find first item with the requested language. for (i = 0; i < num_matches; i++) { - len = (int)STRLEN(matches[i]); + len = (int)strlen(matches[i]); if (len > 3 && matches[i][len - 3] == '@' && STRICMP(matches[i] + len - 2, lang) == 0) { break; @@ -219,7 +219,7 @@ void ex_helpclose(exarg_T *eap) /// @return NULL if not found. char *check_help_lang(char *arg) { - int len = (int)STRLEN(arg); + int len = (int)strlen(arg); if (len >= 3 && arg[len - 3] == '@' && ASCII_ISALPHA(arg[len - 2]) && ASCII_ISALPHA(arg[len - 1])) { @@ -278,7 +278,7 @@ int help_heuristic(char *matched_string, int offset, int wrong_case) if (matched_string[0] == '+' && matched_string[1] != NUL) { offset += 100; } - return 100 * num_letters + (int)STRLEN(matched_string) + offset; + return 100 * num_letters + (int)strlen(matched_string) + offset; } /// Compare functions for qsort() below, that checks the help heuristics number @@ -367,7 +367,7 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep // the table, it is taken literally (but ~ is escaped). Otherwise '?' // is recognized as a wildcard. for (i = (int)ARRAY_SIZE(expr_table); --i >= 0;) { - if (STRCMP(arg + 5, expr_table[i]) == 0) { + if (strcmp(arg + 5, expr_table[i]) == 0) { for (int si = 0, di = 0;; si++) { if (arg[si] == '~') { d[di++] = '\\'; @@ -384,7 +384,7 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep // Recognize a few exceptions to the rule. Some strings that contain // '*'are changed to "star", otherwise '*' is recognized as a wildcard. for (i = 0; except_tbl[i][0] != NULL; i++) { - if (STRCMP(arg, except_tbl[i][0]) == 0) { + if (strcmp(arg, except_tbl[i][0]) == 0) { STRCPY(d, except_tbl[i][1]); break; } @@ -428,7 +428,7 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep // completion. // Insert a backslash before '~', '$' and '.' to avoid their // special meaning. - if ((char_u *)d - IObuff > IOSIZE - 10) { // getting too long!? + if (d - IObuff > IOSIZE - 10) { // getting too long!? break; } switch (*s) { @@ -459,7 +459,7 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep if (*s < ' ' || (*s == '^' && s[1] && (ASCII_ISALPHA(s[1]) || vim_strchr("?@[\\]^", s[1]) != NULL))) { - if ((char_u *)d > IObuff && d[-1] != '_' && d[-1] != '\\') { + if (d > IObuff && d[-1] != '_' && d[-1] != '\\') { *d++ = '_'; // prepend a '_' to make x_CTRL-x } STRCPY(d, "CTRL-"); @@ -513,18 +513,18 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep *d = NUL; if (*IObuff == '`') { - if ((char_u *)d > IObuff + 2 && d[-1] == '`') { + if (d > IObuff + 2 && d[-1] == '`') { // remove the backticks from `command` - memmove(IObuff, IObuff + 1, STRLEN(IObuff)); + memmove(IObuff, IObuff + 1, strlen(IObuff)); d[-2] = NUL; - } else if ((char_u *)d > IObuff + 3 && d[-2] == '`' && d[-1] == ',') { + } else if (d > IObuff + 3 && d[-2] == '`' && d[-1] == ',') { // remove the backticks and comma from `command`, - memmove(IObuff, IObuff + 1, STRLEN(IObuff)); + memmove(IObuff, IObuff + 1, strlen(IObuff)); d[-3] = NUL; - } else if ((char_u *)d > IObuff + 4 && d[-3] == '`' + } else if (d > IObuff + 4 && d[-3] == '`' && d[-2] == '\\' && d[-1] == '.') { // remove the backticks and dot from `command`\. - memmove(IObuff, IObuff + 1, STRLEN(IObuff)); + memmove(IObuff, IObuff + 1, strlen(IObuff)); d[-4] = NUL; } } @@ -556,8 +556,8 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep /// tag matches it. Otherwise remove "@en" if "en" is the only language. void cleanup_help_tags(int num_file, char **file) { - char_u buf[4]; - char_u *p = buf; + char buf[4]; + char_u *p = (char_u *)buf; if (p_hlg[0] != NUL && (p_hlg[0] != 'e' || p_hlg[1] != 'n')) { *p++ = '@'; @@ -567,17 +567,17 @@ void cleanup_help_tags(int num_file, char **file) *p = NUL; for (int i = 0; i < num_file; i++) { - int len = (int)STRLEN(file[i]) - 3; + int len = (int)strlen(file[i]) - 3; if (len <= 0) { continue; } - if (STRCMP(file[i] + len, "@en") == 0) { + if (strcmp(file[i] + len, "@en") == 0) { // Sorting on priority means the same item in another language may // be anywhere. Search all items for a match up to the "@en". int j; for (j = 0; j < num_file; j++) { if (j != i - && (int)STRLEN(file[j]) == len + 3 + && (int)strlen(file[j]) == len + 3 && STRNCMP(file[i], file[j], len + 1) == 0) { break; } @@ -591,11 +591,11 @@ void cleanup_help_tags(int num_file, char **file) if (*buf != NUL) { for (int i = 0; i < num_file; i++) { - int len = (int)STRLEN(file[i]) - 3; + int len = (int)strlen(file[i]) - 3; if (len <= 0) { continue; } - if (STRCMP(file[i] + len, buf) == 0) { + if (strcmp(file[i] + len, buf) == 0) { // remove the default language file[i][len] = NUL; } @@ -615,7 +615,7 @@ void prepare_help_buffer(void) // latin1 word characters (for translated help files). // Only set it when needed, buf_init_chartab() is some work. char *p = "!-~,^*,^|,^\",192-255"; - if (STRCMP(curbuf->b_p_isk, p) != 0) { + if (strcmp(curbuf->b_p_isk, p) != 0) { set_string_option_direct("isk", -1, p, OPT_FREE|OPT_LOCAL, 0); check_buf_options(curbuf); (void)buf_init_chartab(curbuf, false); @@ -650,7 +650,7 @@ void fix_help_buffer(void) bool in_example = false; // Set filetype to "help". - if (STRCMP(curbuf->b_p_ft, "help") != 0) { + if (strcmp(curbuf->b_p_ft, "help") != 0) { curbuf->b_ro_locked++; set_option_value_give_err("ft", 0L, "help", OPT_LOCAL); curbuf->b_ro_locked--; @@ -687,8 +687,8 @@ void fix_help_buffer(void) // In the "help.txt" and "help.abx" file, add the locally added help // files. This uses the very first line in the help file. char *const fname = path_tail(curbuf->b_fname); - if (FNAMECMP(fname, "help.txt") == 0 - || (FNAMENCMP(fname, "help.", 5) == 0 + if (path_fnamecmp(fname, "help.txt") == 0 + || (path_fnamencmp(fname, "help.", 5) == 0 && ASCII_ISALPHA(fname[5]) && ASCII_ISALPHA(fname[6]) && TOLOWER_ASC(fname[7]) == 'x' @@ -715,8 +715,8 @@ void fix_help_buffer(void) // Find all "doc/ *.txt" files in this directory. if (!add_pathsep((char *)NameBuff) - || STRLCAT(NameBuff, "doc/*.??[tx]", // NOLINT - sizeof(NameBuff)) >= MAXPATHL) { + || xstrlcat(NameBuff, "doc/*.??[tx]", // NOLINT + sizeof(NameBuff)) >= MAXPATHL) { emsg(_(e_fnametoolong)); continue; } @@ -746,18 +746,18 @@ void fix_help_buffer(void) if (e1 == NULL || e2 == NULL) { continue; } - if (FNAMECMP(e1, ".txt") != 0 - && FNAMECMP(e1, fname + 4) != 0) { + if (path_fnamecmp(e1, ".txt") != 0 + && path_fnamecmp(e1, fname + 4) != 0) { // Not .txt and not .abx, remove it. XFREE_CLEAR(fnames[i1]); continue; } if (e1 - f1 != e2 - f2 - || FNAMENCMP(f1, f2, e1 - f1) != 0) { + || path_fnamencmp(f1, f2, (size_t)(e1 - f1)) != 0) { continue; } - if (FNAMECMP(e1, ".txt") == 0 - && FNAMECMP(e2, fname + 4) == 0) { + if (path_fnamecmp(e1, ".txt") == 0 + && path_fnamecmp(e2, fname + 4) == 0) { // use .abx instead of .txt XFREE_CLEAR(fnames[i1]); } @@ -772,7 +772,7 @@ void fix_help_buffer(void) if (fd == NULL) { continue; } - vim_fgets(IObuff, IOSIZE, fd); + vim_fgets((char_u *)IObuff, IOSIZE, fd); if (IObuff[0] == '*' && (s = vim_strchr((char *)IObuff + 1, '*')) != NULL) { @@ -819,7 +819,7 @@ void fix_help_buffer(void) convert_setup(&vc, NULL, NULL); ml_append(lnum, cp, (colnr_T)0, false); - if ((char_u *)cp != IObuff) { + if (cp != IObuff) { xfree(cp); } lnum++; @@ -871,8 +871,8 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool // Find all *.txt files. size_t dirlen = STRLCPY(NameBuff, dir, sizeof(NameBuff)); if (dirlen >= MAXPATHL - || STRLCAT(NameBuff, "/**/*", sizeof(NameBuff)) >= MAXPATHL // NOLINT - || STRLCAT(NameBuff, ext, sizeof(NameBuff)) >= MAXPATHL) { + || xstrlcat(NameBuff, "/**/*", sizeof(NameBuff)) >= MAXPATHL // NOLINT + || xstrlcat(NameBuff, ext, sizeof(NameBuff)) >= MAXPATHL) { emsg(_(e_fnametoolong)); return; } @@ -896,7 +896,7 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool // Do this before scanning through all the files. memcpy(NameBuff, dir, dirlen + 1); if (!add_pathsep((char *)NameBuff) - || STRLCAT(NameBuff, tagfname, sizeof(NameBuff)) >= MAXPATHL) { + || xstrlcat(NameBuff, tagfname, sizeof(NameBuff)) >= MAXPATHL) { emsg(_(e_fnametoolong)); return; } @@ -915,7 +915,7 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool ga_init(&ga, (int)sizeof(char_u *), 100); if (add_help_tags || path_full_compare("$VIMRUNTIME/doc", dir, false, true) == kEqualFiles) { - size_t s_len = 18 + STRLEN(tagfname); + size_t s_len = 18 + strlen(tagfname); s = xmalloc(s_len); snprintf(s, s_len, "help-tags\t%s\t1\n", tagfname); GA_APPEND(char *, &ga, s); @@ -931,7 +931,7 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool const char *const fname = files[fi] + dirlen + 1; bool firstline = true; - while (!vim_fgets(IObuff, IOSIZE, fd) && !got_int) { + while (!vim_fgets((char_u *)IObuff, IOSIZE, fd) && !got_int) { if (firstline) { // Detect utf-8 file by a non-ASCII char in the first line. TriState this_utf8 = kNone; @@ -974,12 +974,12 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool // characters, there is white space before it and is // followed by a white character or end-of-line. if (s == p2 - && ((char_u *)p1 == IObuff || p1[-1] == ' ' || p1[-1] == '\t') + && (p1 == IObuff || p1[-1] == ' ' || p1[-1] == '\t') && (vim_strchr(" \t\n\r", s[1]) != NULL || s[1] == '\0')) { *p2 = '\0'; p1++; - size_t s_len= (size_t)(p2 - p1) + STRLEN(fname) + 2; + size_t s_len= (size_t)(p2 - p1) + strlen(fname) + 2; s = xmalloc(s_len); GA_APPEND(char *, &ga, s); snprintf(s, s_len, "%s\t%s", p1, fname); @@ -1067,7 +1067,7 @@ static void do_helptags(char *dirname, bool add_help_tags, bool ignore_writeerr) // Get a list of all files in the help directory and in subdirectories. STRLCPY(NameBuff, dirname, sizeof(NameBuff)); if (!add_pathsep((char *)NameBuff) - || STRLCAT(NameBuff, "**", sizeof(NameBuff)) >= MAXPATHL) { + || xstrlcat(NameBuff, "**", sizeof(NameBuff)) >= MAXPATHL) { emsg(_(e_fnametoolong)); return; } @@ -1087,7 +1087,7 @@ static void do_helptags(char *dirname, bool add_help_tags, bool ignore_writeerr) int j; ga_init(&ga, 1, 10); for (int i = 0; i < filecount; i++) { - len = (int)STRLEN(files[i]); + len = (int)strlen(files[i]); if (len <= 4) { continue; } @@ -1162,7 +1162,7 @@ void ex_helptags(exarg_T *eap) eap->arg = skipwhite(eap->arg + 3); } - if (STRCMP(eap->arg, "ALL") == 0) { + if (strcmp(eap->arg, "ALL") == 0) { do_in_path(p_rtp, "doc", DIP_ALL + DIP_DIR, helptags_cb, &add_help_tags); } else { ExpandInit(&xpc); diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index e42cb66422..d507f07bca 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -407,7 +407,7 @@ void update_ns_hl(int ns_id) int *hl_attrs = **alloc; for (int hlf = 0; hlf < HLF_COUNT; hlf++) { - int id = syn_check_group(hlf_names[hlf], STRLEN(hlf_names[hlf])); + int id = syn_check_group(hlf_names[hlf], strlen(hlf_names[hlf])); bool optional = (hlf == HLF_INACTIVE || hlf == HLF_NFLOAT); hl_attrs[hlf] = hl_get_ui_attr(ns_id, hlf, id, optional); } diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c index 7e5fd52243..fed39c6ed7 100644 --- a/src/nvim/highlight_group.c +++ b/src/nvim/highlight_group.c @@ -791,7 +791,7 @@ void set_hl_group(int id, HlAttrs attrs, Dict(highlight) *dict, int link_id) g->sg_attr = hl_get_syn_attr(0, id, attrs); // 'Normal' is special - if (STRCMP(g->sg_name_u, "NORMAL") == 0) { + if (strcmp(g->sg_name_u, "NORMAL") == 0) { cterm_normal_fg_color = g->sg_cterm_fg; cterm_normal_bg_color = g->sg_cterm_bg; normal_fg = g->sg_rgb_fg; @@ -988,7 +988,7 @@ 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); + 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)) { @@ -1084,7 +1084,7 @@ void do_highlight(const char *line, const bool forceit, const bool init) int i; while (arg[off] != NUL) { for (i = ARRAY_SIZE(hl_attr_table); --i >= 0;) { - len = (int)STRLEN(hl_name_table[i]); + len = (int)strlen(hl_name_table[i]); if (STRNICMP(arg + off, hl_name_table[i], len) == 0) { attr |= hl_attr_table[i]; off += len; @@ -1119,9 +1119,9 @@ void do_highlight(const char *line, const bool forceit, const bool init) hl_table[idx].sg_gui = attr; } } - } else if (STRCMP(key, "FONT") == 0) { + } else if (strcmp(key, "FONT") == 0) { // in non-GUI fonts are simply ignored - } else if (STRCMP(key, "CTERMFG") == 0 || STRCMP(key, "CTERMBG") == 0) { + } else if (strcmp(key, "CTERMFG") == 0 || strcmp(key, "CTERMBG") == 0) { if (!init || !(hl_table[idx].sg_set & SG_CTERM)) { if (!init) { hl_table[idx].sg_set |= SG_CTERM; @@ -1239,7 +1239,7 @@ void do_highlight(const char *line, const bool forceit, const bool init) if (is_normal_group) { normal_fg = hl_table[idx].sg_rgb_fg; } - } else if (STRCMP(key, "GUIBG") == 0) { + } else if (strcmp(key, "GUIBG") == 0) { int *indexp = &hl_table[idx].sg_rgb_bg_idx; if (!init || !(hl_table[idx].sg_set & SG_GUI)) { @@ -1250,7 +1250,7 @@ void do_highlight(const char *line, const bool forceit, const bool init) RgbValue old_color = hl_table[idx].sg_rgb_bg; int old_idx = hl_table[idx].sg_rgb_bg_idx; - if (STRCMP(arg, "NONE") != 0) { + if (strcmp(arg, "NONE") != 0) { hl_table[idx].sg_rgb_bg = name_to_color(arg, indexp); } else { hl_table[idx].sg_rgb_bg = -1; @@ -1519,7 +1519,7 @@ static bool highlight_list_arg(const int id, bool didh, const int type, int iarg } } - (void)syn_list_header(didh, vim_strsize((char *)ts) + (int)STRLEN(name) + 1, id, false); + (void)syn_list_header(didh, vim_strsize((char *)ts) + (int)strlen(name) + 1, id, false); didh = true; if (!got_int) { if (*name != NUL) { @@ -1723,7 +1723,7 @@ int syn_name2id(const char *name) // if we look up @aaa.bbb, we have to consider @aaa as well return syn_check_group(name, strlen(name)); } else { - return syn_name2id_len(name, STRLEN(name)); + return syn_name2id_len(name, strlen(name)); } } @@ -2007,7 +2007,7 @@ void highlight_changed(void) /// 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])); + id = syn_check_group(hlf_names[hlf], strlen(hlf_names[hlf])); if (id == 0) { abort(); } diff --git a/src/nvim/if_cscope.c b/src/nvim/if_cscope.c index 719899d0b8..a23fa22da2 100644 --- a/src/nvim/if_cscope.c +++ b/src/nvim/if_cscope.c @@ -415,7 +415,7 @@ static int cs_add_common(char *arg1, char *arg2, char *flags) fname = xmalloc(MAXPATHL + 1); expand_env(arg1, fname, MAXPATHL); - size_t len = STRLEN(fname); + size_t len = strlen(fname); fbuf = fname; (void)modify_fname(":p", false, &usedlen, &fname, &fbuf, &len); if (fname == NULL) { @@ -768,7 +768,7 @@ err_closing: #if defined(UNIX) (void)snprintf(cmd, len, "exec %s -dl -f %s", prog, csinfo[i].fname); #else - // WIN32 + // MS-Windows (void)snprintf(cmd, len, "%s -dl -f %s", prog, csinfo[i].fname); #endif if (csinfo[i].ppath != NULL) { @@ -820,7 +820,7 @@ err_closing: } #else - // WIN32 + // MS-Windows // Create a new process to run cscope and use pipes to talk with it GetStartupInfo(&si); si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; @@ -1180,7 +1180,7 @@ static cscmd_T *cs_lookup_cmd(exarg_T *eap) } // Store length of eap->arg before it gets modified by strtok(). - eap_arg_len = (int)STRLEN(eap->arg); + eap_arg_len = (int)strlen(eap->arg); if ((stok = strtok(eap->arg, (const char *)" ")) == NULL) { // NOLINT(runtime/threadsafe_fn) return NULL; diff --git a/src/nvim/indent.c b/src/nvim/indent.c index af5bcd7d2a..0f7a5a8e44 100644 --- a/src/nvim/indent.c +++ b/src/nvim/indent.c @@ -721,7 +721,7 @@ int get_number_indent(linenr_T lnum) // start matching for the flp beyond any comment leader... if (vim_regexec(®match, ml_get(lnum) + lead_len, (colnr_T)0)) { pos.lnum = lnum; - pos.col = (colnr_T)(*regmatch.endp - (char_u *)ml_get(lnum)); + pos.col = (colnr_T)(*regmatch.endp - ml_get(lnum)); pos.coladd = 0; } vim_regfree(regmatch.regprog); diff --git a/src/nvim/indent_c.c b/src/nvim/indent_c.c index c7f37790b6..5eed2601d5 100644 --- a/src/nvim/indent_c.c +++ b/src/nvim/indent_c.c @@ -204,7 +204,7 @@ bool cin_is_cinword(const char *line) { bool retval = false; - size_t cinw_len = STRLEN(curbuf->b_p_cinw) + 1; + size_t cinw_len = strlen(curbuf->b_p_cinw) + 1; char_u *cinw_buf = xmalloc(cinw_len); line = skipwhite((char *)line); @@ -485,7 +485,7 @@ bool cin_isscopedecl(const char_u *p) { const char_u *s = cin_skipcomment(p); - const size_t cinsd_len = STRLEN(curbuf->b_p_cinsd) + 1; + const size_t cinsd_len = strlen(curbuf->b_p_cinsd) + 1; char_u *cinsd_buf = xmalloc(cinsd_len); bool found = false; @@ -1322,7 +1322,7 @@ static int cin_ends_in(const char_u *s, const char_u *find, const char_u *ignore /// Return true when "s" starts with "word" and then a non-ID character. static int cin_starts_with(const char_u *s, const char *word) { - int l = (int)STRLEN(word); + int l = (int)strlen(word); return STRNCMP(s, word, l) == 0 && !vim_isIDc(s[l]); } @@ -1901,7 +1901,7 @@ int get_c_indent(void) // For unknown reasons the cursor might be past the end of the line, thus // check for that. if ((State & MODE_INSERT) - && curwin->w_cursor.col < (colnr_T)STRLEN(linecopy) + && curwin->w_cursor.col < (colnr_T)strlen(linecopy) && linecopy[curwin->w_cursor.col] == ')') { linecopy[curwin->w_cursor.col] = NUL; } @@ -2010,17 +2010,17 @@ int get_c_indent(void) (void)copy_option_part(&p, lead_end, COM_MAX_LEN, ","); if (what == COM_START) { STRCPY(lead_start, lead_end); - lead_start_len = (int)STRLEN(lead_start); + lead_start_len = (int)strlen(lead_start); start_off = off; start_align = align; } else if (what == COM_MIDDLE) { STRCPY(lead_middle, lead_end); - lead_middle_len = (int)STRLEN(lead_middle); + lead_middle_len = (int)strlen(lead_middle); } else if (what == COM_END) { // If our line starts with the middle comment string, line it // up with the comment opener per the 'comments' option. if (STRNCMP(theline, lead_middle, lead_middle_len) == 0 - && STRNCMP(theline, lead_end, STRLEN(lead_end)) != 0) { + && STRNCMP(theline, lead_end, strlen(lead_end)) != 0) { done = true; if (curwin->w_cursor.lnum > 1) { // If the start comment string matches in the previous @@ -2051,7 +2051,7 @@ int get_c_indent(void) // If our line starts with the end comment string, line it up // with the middle comment if (STRNCMP(theline, lead_middle, lead_middle_len) != 0 - && STRNCMP(theline, lead_end, STRLEN(lead_end)) == 0) { + && STRNCMP(theline, lead_end, strlen(lead_end)) == 0) { amount = get_indent_lnum(curwin->w_cursor.lnum - 1); // XXX if (off != 0) { diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c index 686461ce60..a4b0d68ffe 100644 --- a/src/nvim/insexpand.c +++ b/src/nvim/insexpand.c @@ -652,7 +652,7 @@ static char_u *ins_compl_infercase_gettext(char_u *str, int char_len, int compl_ ga_grow(&gap, IOSIZE); *p = NUL; STRCPY(gap.ga_data, IObuff); - gap.ga_len = (int)STRLEN(IObuff); + gap.ga_len = (int)strlen(IObuff); } else { p += utf_char2bytes(wca[i++], p); } @@ -665,7 +665,7 @@ static char_u *ins_compl_infercase_gettext(char_u *str, int char_len, int compl_ } *p = NUL; - return IObuff; + return (char_u *)IObuff; } /// This is like ins_compl_add(), but if 'ic' and 'inf' are set, then the @@ -775,7 +775,7 @@ static int ins_compl_add(char *const str, int len, char *const fname, char *cons return FAIL; } if (len < 0) { - len = (int)STRLEN(str); + len = (int)strlen(str); } // If the same match is already present, don't add it. @@ -784,7 +784,7 @@ static int ins_compl_add(char *const str, int len, char *const fname, char *cons do { if (!match_at_original_text(match) && STRNCMP(match->cp_str, str, len) == 0 - && ((int)STRLEN(match->cp_str) <= len || match->cp_str[len] == NUL)) { + && ((int)strlen(match->cp_str) <= len || match->cp_str[len] == NUL)) { FREE_CPTEXT(cptext, cptext_allocated); return NOTDONE; } @@ -811,7 +811,7 @@ static int ins_compl_add(char *const str, int len, char *const fname, char *cons if (fname != NULL && compl_curr_match != NULL && compl_curr_match->cp_fname != NULL - && STRCMP(fname, compl_curr_match->cp_fname) == 0) { + && strcmp(fname, compl_curr_match->cp_fname) == 0) { match->cp_fname = compl_curr_match->cp_fname; } else if (fname != NULL) { match->cp_fname = xstrdup(fname); @@ -997,7 +997,7 @@ bool ins_compl_has_shown_match(void) bool ins_compl_long_shown_match(void) { return compl_shown_match != NULL && compl_shown_match->cp_str != NULL - && (colnr_T)STRLEN(compl_shown_match->cp_str) > curwin->w_cursor.col - compl_col; + && (colnr_T)strlen(compl_shown_match->cp_str) > curwin->w_cursor.col - compl_col; } /// Set variables that store noselect and noinsert behavior from the @@ -1124,7 +1124,7 @@ static int ins_compl_build_pum(void) XFREE_CLEAR(compl_leader); } - const int lead_len = compl_leader != NULL ? (int)STRLEN(compl_leader) : 0; + const int lead_len = compl_leader != NULL ? (int)strlen(compl_leader) : 0; do { if (!match_at_original_text(compl) @@ -1332,7 +1332,7 @@ static void ins_compl_dictionaries(char_u *dict_start, char_u *pat, int flags, i // backticks (for security, the 'dict' option may have been set in // a modeline). copy_option_part(&dict, buf, LSIZE, ","); - if (!thesaurus && STRCMP(buf, "spell") == 0) { + if (!thesaurus && strcmp(buf, "spell") == 0) { count = -1; } else if (vim_strchr(buf, '`') != NULL || expand_wildcards(1, &buf, &count, &files, @@ -1349,7 +1349,7 @@ static void ins_compl_dictionaries(char_u *dict_start, char_u *pat, int flags, i } else { ptr = pat; } - spell_dump_compl(ptr, regmatch.rm_ic, &dir, 0); + spell_dump_compl((char *)ptr, regmatch.rm_ic, &dir, 0); } else if (count > 0) { // avoid warning for using "files" uninit ins_compl_files(count, files, thesaurus, flags, ®match, (char_u *)buf, &dir); @@ -1443,20 +1443,20 @@ static void ins_compl_files(int count, char **files, int thesaurus, int flags, r while (!got_int && !compl_interrupted && !vim_fgets(buf, LSIZE, fp)) { ptr = buf; while (vim_regexec(regmatch, (char *)buf, (colnr_T)(ptr - buf))) { - ptr = regmatch->startp[0]; + ptr = (char_u *)regmatch->startp[0]; if (ctrl_x_mode_line_or_eval()) { ptr = find_line_end(ptr); } else { ptr = find_word_end(ptr); } - add_r = ins_compl_add_infercase(regmatch->startp[0], - (int)(ptr - regmatch->startp[0]), + add_r = ins_compl_add_infercase((char_u *)regmatch->startp[0], + (int)(ptr - (char_u *)regmatch->startp[0]), p_ic, (char_u *)files[i], *dir, false); if (thesaurus) { // For a thesaurus, add all the words in the line ptr = buf; add_r = thesaurus_add_words_in_line(files[i], &ptr, *dir, - regmatch->startp[0]); + (char_u *)regmatch->startp[0]); } if (add_r == OK) { // if dir was BACKWARD then honor it just once @@ -2588,15 +2588,15 @@ static void get_complete_info(list_T *what_list, dict_T *retdict) ; item = TV_LIST_ITEM_NEXT(what_list, item)) { const char *what = tv_get_string(TV_LIST_ITEM_TV(item)); - if (STRCMP(what, "mode") == 0) { + if (strcmp(what, "mode") == 0) { what_flag |= CI_WHAT_MODE; - } else if (STRCMP(what, "pum_visible") == 0) { + } else if (strcmp(what, "pum_visible") == 0) { what_flag |= CI_WHAT_PUM_VISIBLE; - } else if (STRCMP(what, "items") == 0) { + } else if (strcmp(what, "items") == 0) { what_flag |= CI_WHAT_ITEMS; - } else if (STRCMP(what, "selected") == 0) { + } else if (strcmp(what, "selected") == 0) { what_flag |= CI_WHAT_SELECTED; - } else if (STRCMP(what, "inserted") == 0) { + } else if (strcmp(what, "inserted") == 0) { what_flag |= CI_WHAT_INSERTED; } } @@ -2724,7 +2724,7 @@ static int process_next_cpt_value(ins_compl_next_state_T *st, int *compl_type_ar // buffer, so that word at start of buffer is found // correctly. st->first_match_pos.lnum = st->ins_buf->b_ml.ml_line_count; - st->first_match_pos.col = (colnr_T)STRLEN(ml_get(st->first_match_pos.lnum)); + st->first_match_pos.col = (colnr_T)strlen(ml_get(st->first_match_pos.lnum)); } st->last_match_pos = st->first_match_pos; compl_type = 0; @@ -2806,7 +2806,7 @@ done: static void get_next_include_file_completion(int compl_type) { find_pattern_in_path((char_u *)compl_pattern, compl_direction, - STRLEN(compl_pattern), false, false, + strlen(compl_pattern), false, false, ((compl_type == CTRL_X_PATH_DEFINES && !(compl_cont_status & CONT_SOL)) ? FIND_DEFINE : FIND_ANY), @@ -2889,7 +2889,7 @@ static void get_next_cmdline_completion(void) char **matches; int num_matches; if (expand_cmdline(&compl_xp, (char_u *)compl_pattern, - (int)STRLEN(compl_pattern), + (int)strlen(compl_pattern), &num_matches, &matches) == EXPAND_OK) { ins_compl_add_matches(num_matches, matches, false); } @@ -2980,7 +2980,7 @@ static char_u *ins_comp_get_next_word_or_line(buf_T *ins_buf, pos_T *cur_match_p *cont_s_ipos = true; } IObuff[len] = NUL; - ptr = IObuff; + ptr = (char_u *)IObuff; } if (len == compl_length) { return NULL; @@ -3810,7 +3810,7 @@ static int get_filename_compl_info(char_u *line, int startcol, colnr_T curs_col) static int get_cmdline_compl_info(char *line, colnr_T curs_col) { compl_pattern = xstrnsave(line, (size_t)curs_col); - set_cmd_context(&compl_xp, (char_u *)compl_pattern, (int)STRLEN(compl_pattern), curs_col, false); + set_cmd_context(&compl_xp, (char_u *)compl_pattern, (int)strlen(compl_pattern), curs_col, false); if (compl_xp.xp_context == EXPAND_UNSUCCESSFUL || compl_xp.xp_context == EXPAND_NOTHING) { // No completion possible, use an empty pattern to get a diff --git a/src/nvim/keycodes.c b/src/nvim/keycodes.c index a3763ea9bb..9ec37fd564 100644 --- a/src/nvim/keycodes.c +++ b/src/nvim/keycodes.c @@ -539,7 +539,7 @@ char_u *get_special_key_name(int c, int modifiers) } } } else { // use name of special key - size_t len = STRLEN(key_names_table[table_idx].name); + size_t len = strlen(key_names_table[table_idx].name); if ((int)len + idx + 2 <= MAX_KEY_NAME_LEN) { STRCPY(string + idx, key_names_table[table_idx].name); @@ -1050,7 +1050,7 @@ 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 *res = xmalloc(strlen(p) * 4 + 1); char_u *d = res; for (char_u *s = (char_u *)p; *s != NUL;) { if (s[0] == K_SPECIAL && s[1] != NUL && s[2] != NUL) { diff --git a/src/nvim/locale.c b/src/nvim/locale.c index 3e0774c096..c472d9ba66 100644 --- a/src/nvim/locale.c +++ b/src/nvim/locale.c @@ -270,7 +270,7 @@ void ex_language(exarg_T *eap) static char **locales = NULL; // Array of all available locales -# ifndef WIN32 +# ifndef MSWIN static bool did_init_locales = false; /// @return an array of strings for all available locales + NULL for the @@ -311,7 +311,7 @@ static char **find_locales(void) /// Lazy initialization of all available locales. static void init_locales(void) { -# ifndef WIN32 +# ifndef MSWIN if (!did_init_locales) { did_init_locales = true; locales = find_locales(); diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 857e2111d6..6063414a02 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -248,7 +248,7 @@ static int nlua_luv_thread_common_cfpcall(lua_State *lstate, int nargs, int nres mch_errmsg(e_outofmem); mch_errmsg("\n"); lua_close(lstate); -#ifdef WIN32 +#ifdef MSWIN ExitThread(0); #else pthread_exit(0); @@ -673,7 +673,7 @@ static bool nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL lua_setfield(lstate, -2, "debug"); lua_pop(lstate, 1); -#ifdef WIN32 +#ifdef MSWIN // os.getenv lua_getglobal(lstate, "os"); lua_pushcfunction(lstate, &nlua_getenv); @@ -1044,12 +1044,12 @@ static int nlua_debug(lua_State *lstate) if (input.v_type != VAR_STRING || input.vval.v_string == NULL || *input.vval.v_string == NUL - || STRCMP(input.vval.v_string, "cont") == 0) { + || strcmp(input.vval.v_string, "cont") == 0) { tv_clear(&input); return 0; } if (luaL_loadbuffer(lstate, (const char *)input.vval.v_string, - STRLEN(input.vval.v_string), "=(debug command)")) { + strlen(input.vval.v_string), "=(debug command)")) { nlua_error(lstate, _("E5115: Error while loading debug string: %.*s")); } else if (nlua_pcall(lstate, 0, 0)) { nlua_error(lstate, _("E5116: Error while calling debug string: %.*s")); @@ -1110,9 +1110,9 @@ int nlua_call(lua_State *lstate) try_start(); typval_T rettv; funcexe_T funcexe = FUNCEXE_INIT; - funcexe.firstline = curwin->w_cursor.lnum; - funcexe.lastline = curwin->w_cursor.lnum; - funcexe.evaluate = true; + funcexe.fe_firstline = curwin->w_cursor.lnum; + funcexe.fe_lastline = curwin->w_cursor.lnum; + funcexe.fe_evaluate = true; // call_func() retval is deceptive, ignore it. Instead we set `msg_list` // (TRY_WRAP) to capture abort-causing non-exception errors. (void)call_func((char *)name, (int)name_len, &rettv, nargs, vim_args, &funcexe); @@ -1201,7 +1201,7 @@ static int nlua_empty_dict_tostring(lua_State *lstate) return 1; } -#ifdef WIN32 +#ifdef MSWIN /// os.getenv: override os.getenv to maintain coherency. #9681 /// /// uv_os_setenv uses SetEnvironmentVariableW which does not update _environ. @@ -1435,12 +1435,12 @@ int typval_exec_lua_callable(LuaRef lua_cb, int argcount, typval_T *argvars, typ if (nlua_pcall(lstate, argcount, 1)) { nlua_print(lstate); - return ERROR_OTHER; + return FCERR_OTHER; } nlua_pop_typval(lstate, rettv); - return ERROR_NONE; + return FCERR_NONE; } /// Execute Lua string @@ -1641,7 +1641,7 @@ void ex_luado(exarg_T *const eap) break; } if (lua_isstring(lstate, -1)) { - size_t old_line_len = STRLEN(old_line); + size_t old_line_len = strlen(old_line); size_t new_line_len; const char *const new_line = lua_tolstring(lstate, -1, &new_line_len); @@ -1658,7 +1658,7 @@ void ex_luado(exarg_T *const eap) } lua_pop(lstate, 1); check_cursor(); - update_screen(UPD_NOT_VALID); + redraw_curbuf_later(UPD_NOT_VALID); } /// Run lua file @@ -2001,7 +2001,7 @@ int nlua_do_ucmd(ucmd_T *cmd, exarg_T *eap, bool preview) // Split args by unescaped whitespace |<f-args>| (nargs dependent) if (cmd->uc_argt & EX_NOSPC) { - if ((cmd->uc_argt & EX_NEEDARG) || STRLEN(eap->arg)) { + if ((cmd->uc_argt & EX_NEEDARG) || strlen(eap->arg)) { // For commands where nargs is 1 or "?" and argument is passed, fargs = { args } lua_rawseti(lstate, -2, 1); } else { @@ -2011,7 +2011,7 @@ int nlua_do_ucmd(ucmd_T *cmd, exarg_T *eap, bool preview) } else if (eap->args == NULL) { // For commands with more than one possible argument, split if argument list isn't available. lua_pop(lstate, 1); // Pop the reference of opts.args - size_t length = STRLEN(eap->arg); + size_t length = strlen(eap->arg); size_t end = 0; size_t len = 0; int i = 1; diff --git a/src/nvim/lua/stdlib.c b/src/nvim/lua/stdlib.c index e3d6a7eec8..9b1890403e 100644 --- a/src/nvim/lua/stdlib.c +++ b/src/nvim/lua/stdlib.c @@ -60,8 +60,8 @@ static int regex_match(lua_State *lstate, regprog_T **prog, char_u *str) *prog = rm.regprog; if (match) { - lua_pushinteger(lstate, (lua_Integer)(rm.startp[0] - str)); - lua_pushinteger(lstate, (lua_Integer)(rm.endp[0] - str)); + lua_pushinteger(lstate, (lua_Integer)(rm.startp[0] - (char *)str)); + lua_pushinteger(lstate, (lua_Integer)(rm.endp[0] - (char *)str)); return 2; } return 0; @@ -499,7 +499,7 @@ static int nlua_iconv(lua_State *lstate) vimconv_T vimconv; vimconv.vc_type = CONV_NONE; - convert_setup_ext(&vimconv, from, false, to, false); + convert_setup_ext(&vimconv, (char *)from, false, (char *)to, false); char_u *ret = (char_u *)string_convert(&vimconv, (char *)str, &str_len); diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c index 971a47f8c9..f3c67e265f 100644 --- a/src/nvim/lua/treesitter.c +++ b/src/nvim/lua/treesitter.c @@ -834,7 +834,7 @@ static int node_field(lua_State *L) do { const char *current_field = ts_tree_cursor_current_field_name(&cursor); - if (current_field != NULL && !STRCMP(field_name, current_field)) { + if (current_field != NULL && !strcmp(field_name, current_field)) { push_node(L, ts_tree_cursor_current_node(&cursor), 1); // [table, node] lua_rawseti(L, -2, (int)++curr_index); } diff --git a/src/nvim/macros.h b/src/nvim/macros.h index 1024ca5015..9b7562e86f 100644 --- a/src/nvim/macros.h +++ b/src/nvim/macros.h @@ -86,7 +86,7 @@ // mch_open_rw(): invoke os_open() with third argument for user R/W. #if defined(UNIX) // open in rw------- mode # define MCH_OPEN_RW(n, f) os_open((n), (f), (mode_t)0600) -#elif defined(WIN32) +#elif defined(MSWIN) # define MCH_OPEN_RW(n, f) os_open((n), (f), S_IREAD | S_IWRITE) #else # define MCH_OPEN_RW(n, f) os_open((n), (f), 0) @@ -178,14 +178,14 @@ // Type of uv_buf_t.len is platform-dependent. // Related: https://github.com/libuv/libuv/pull/1236 -#if defined(WIN32) +#if defined(MSWIN) # define UV_BUF_LEN(x) (ULONG)(x) #else # define UV_BUF_LEN(x) (x) #endif // Type of read()/write() `count` param is platform-dependent. -#if defined(WIN32) +#if defined(MSWIN) # define IO_COUNT(x) (unsigned)(x) #else # define IO_COUNT(x) (x) diff --git a/src/nvim/main.c b/src/nvim/main.c index a73c465042..1119cee6ad 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -71,7 +71,7 @@ #include "nvim/version.h" #include "nvim/vim.h" #include "nvim/window.h" -#ifdef WIN32 +#ifdef MSWIN # include "nvim/os/os_win_console.h" #endif #include "nvim/api/private/defs.h" @@ -84,7 +84,7 @@ #include "nvim/msgpack_rpc/helpers.h" #include "nvim/msgpack_rpc/server.h" #include "nvim/os/signal.h" -#ifndef WIN32 +#ifndef MSWIN # include "nvim/os/pty_process_unix.h" #endif #include "nvim/api/extmark.h" @@ -168,7 +168,7 @@ void early_init(mparm_T *paramp) runtime_init(); highlight_init(); -#ifdef WIN32 +#ifdef MSWIN OSVERSIONINFO ovi; ovi.dwOSVersionInfoSize = sizeof(ovi); GetVersionEx(&ovi); @@ -210,13 +210,13 @@ void early_init(mparm_T *paramp) #ifdef MAKE_LIB int nvim_main(int argc, char **argv); // silence -Wmissing-prototypes int nvim_main(int argc, char **argv) -#elif defined(WIN32) +#elif defined(MSWIN) int wmain(int argc, wchar_t **argv_w) // multibyte args on Windows. #7060 #else int main(int argc, char **argv) #endif { -#if defined(WIN32) && !defined(MAKE_LIB) +#if defined(MSWIN) && !defined(MAKE_LIB) char **argv = xmalloc((size_t)argc * sizeof(char *)); for (int i = 0; i < argc; i++) { char *buf = NULL; @@ -582,7 +582,7 @@ int main(int argc, char **argv) // Main loop: never returns. normal_enter(false, false); -#if defined(WIN32) && !defined(MAKE_LIB) +#if defined(MSWIN) && !defined(MAKE_LIB) xfree(argv); #endif return 0; @@ -1156,7 +1156,7 @@ static void command_line_scan(mparm_T *parmp) p_verbose = get_number_arg(argv[0], &argv_idx, 10); if (argv[0][argv_idx] != NUL) { set_option_value_give_err("verbosefile", 0L, argv[0] + argv_idx, 0); - argv_idx = (int)STRLEN(argv[0]); + argv_idx = (int)strlen(argv[0]); } break; case 'w': // "-w{number}" set window height @@ -1226,7 +1226,7 @@ static void command_line_scan(mparm_T *parmp) a = argv[0]; } - size_t s_size = STRLEN(a) + 9; + size_t s_size = strlen(a) + 9; char *s = xmalloc(s_size); snprintf(s, s_size, "so %s", a); parmp->cmds_tofree[parmp->n_commands] = true; @@ -1273,7 +1273,7 @@ scripterror: int error; if (strequal(argv[0], "-")) { const int stdin_dup_fd = os_dup(STDIN_FILENO); -#ifdef WIN32 +#ifdef MSWIN // Replace the original stdin with the console input handle. os_replace_stdin_to_conin(); #endif @@ -1375,7 +1375,7 @@ scripterror: // If there is a "+123" or "-c" command, set v:swapcommand to the first one. if (parmp->n_commands > 0) { - const size_t swcmd_len = STRLEN(parmp->commands[0]) + 3; + const size_t swcmd_len = strlen(parmp->commands[0]) + 3; char *const swcmd = xmalloc(swcmd_len); snprintf(swcmd, swcmd_len, ":%s\r", parmp->commands[0]); set_vim_var_string(VV_SWAPCOMMAND, swcmd, -1); @@ -1426,7 +1426,7 @@ static void check_and_set_isatty(mparm_T *paramp) stdout_isatty = paramp->output_isatty = os_isatty(STDOUT_FILENO); paramp->err_isatty = os_isatty(STDERR_FILENO); -#ifndef WIN32 +#ifndef MSWIN int tty_fd = paramp->input_isatty ? STDIN_FILENO : (paramp->output_isatty @@ -1451,7 +1451,7 @@ static void init_path(const char *exename) set_vim_var_string(VV_PROGPATH, exepath, -1); set_vim_var_string(VV_PROGNAME, path_tail(exename), -1); -#ifdef WIN32 +#ifdef MSWIN // Append the process start directory to $PATH, so that ":!foo" finds tools // shipped with Windows package. This also mimics SearchPath(). os_setenv_append_path(exepath); @@ -2108,6 +2108,7 @@ static void usage(void) mch_msg(_(" -V[N][file] Verbose [level][file]\n")); mch_msg("\n"); mch_msg(_(" --api-info Write msgpack-encoded API metadata to stdout\n")); + mch_msg(_(" --clean \"Factory defaults\" (skip user config and plugins, shada)\n")); mch_msg(_(" --embed Use stdin/stdout as a msgpack-rpc channel\n")); mch_msg(_(" --headless Don't start a user interface\n")); mch_msg(_(" --listen <address> Serve RPC API from this address\n")); diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c index 94b432a553..a10146c110 100644 --- a/src/nvim/mapping.c +++ b/src/nvim/mapping.c @@ -262,7 +262,7 @@ static bool set_maparg_lhs_rhs(const char *const orig_lhs, const size_t orig_lhs if (replaced == NULL) { return false; } - mapargs->lhs_len = STRLEN(replaced); + mapargs->lhs_len = strlen(replaced); STRLCPY(mapargs->lhs, replaced, sizeof(mapargs->lhs)); if (did_simplify) { replaced = replace_termcodes(orig_lhs, orig_lhs_len, &bufarg, flags | REPTERM_NO_SIMPLIFY, @@ -270,7 +270,7 @@ static bool set_maparg_lhs_rhs(const char *const orig_lhs, const size_t orig_lhs if (replaced == NULL) { return false; } - mapargs->alt_lhs_len = STRLEN(replaced); + mapargs->alt_lhs_len = strlen(replaced); STRLCPY(mapargs->alt_lhs, replaced, sizeof(mapargs->alt_lhs)); } else { mapargs->alt_lhs_len = 0; @@ -299,7 +299,7 @@ static void set_maparg_rhs(const char *const orig_rhs, const size_t orig_rhs_len char *rhs_buf = NULL; char *replaced = replace_termcodes(orig_rhs, orig_rhs_len, &rhs_buf, REPTERM_DO_LT, NULL, cpo_flags); - mapargs->rhs_len = STRLEN(replaced); + mapargs->rhs_len = strlen(replaced); // NB: replace_termcodes may produce an empty string even if orig_rhs is non-empty // (e.g. a single ^V, see :h map-empty-rhs) mapargs->rhs_is_noop = orig_rhs_len != 0 && mapargs->rhs_len == 0; @@ -709,7 +709,7 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev, } } else { // do we have a match? if (round) { // second round: Try unmap "rhs" string - n = (int)STRLEN(mp->m_str); + n = (int)strlen(mp->m_str); p = (char_u *)mp->m_str; } else { n = mp->m_keylen; @@ -971,12 +971,12 @@ static int get_map_mode(char **cmdp, bool forceit) /// Clear all mappings (":mapclear") or abbreviations (":abclear"). /// "abbr" should be false for mappings, true for abbreviations. /// This function used to be called map_clear(). -static void do_mapclear(char *cmdp, char_u *arg, int forceit, int abbr) +static void do_mapclear(char *cmdp, char *arg, int forceit, int abbr) { int mode; int local; - local = (STRCMP(arg, "<buffer>") == 0); + local = (strcmp(arg, "<buffer>") == 0); if (!local && *arg != NUL) { emsg(_(e_invarg)); return; @@ -1350,7 +1350,7 @@ int ExpandMappings(regmatch_T *regmatch, int *num_file, char ***file) char **ptr3 = ptr1 + count; while (ptr2 < ptr3) { - if (STRCMP(*ptr1, *ptr2)) { + if (strcmp(*ptr1, *ptr2)) { *++ptr1 = *ptr2++; } else { xfree(*ptr2++); @@ -2091,7 +2091,7 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact) const int mode = get_map_mode((char **)&which, 0); char_u *keys_simplified - = (char_u *)replace_termcodes(keys, STRLEN(keys), &keys_buf, flags, &did_simplify, + = (char_u *)replace_termcodes(keys, strlen(keys), &keys_buf, flags, &did_simplify, CPO_TO_CPO_FLAGS); mapblock_T *mp = NULL; int buffer_local; @@ -2101,7 +2101,7 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact) // When the lhs is being simplified the not-simplified keys are // preferred for printing, like in do_map(). (void)replace_termcodes(keys, - STRLEN(keys), + strlen(keys), &alt_keys_buf, flags | REPTERM_NO_SIMPLIFY, NULL, CPO_TO_CPO_FLAGS); rhs = check_map((char_u *)alt_keys_buf, mode, exact, false, abbr, &mp, &buffer_local, &rhs_lua); @@ -2457,13 +2457,13 @@ void ex_unmap(exarg_T *eap) /// ":mapclear" and friends. void ex_mapclear(exarg_T *eap) { - do_mapclear(eap->cmd, (char_u *)eap->arg, eap->forceit, false); + do_mapclear(eap->cmd, eap->arg, eap->forceit, false); } /// ":abclear" and friends. void ex_abclear(exarg_T *eap) { - do_mapclear(eap->cmd, (char_u *)eap->arg, true, true); + do_mapclear(eap->cmd, eap->arg, true, true); } /// Set, tweak, or remove a mapping in a mode. Acts as the implementation for diff --git a/src/nvim/mark.c b/src/nvim/mark.c index a6d0a68323..83ac61f7d2 100644 --- a/src/nvim/mark.c +++ b/src/nvim/mark.c @@ -658,15 +658,15 @@ static void fname2fnum(xfmark_T *fm) int len; expand_env("~/", NameBuff, MAXPATHL); - len = (int)STRLEN(NameBuff); + len = (int)strlen(NameBuff); STRLCPY(NameBuff + len, fm->fname + 2, MAXPATHL - len); } else { STRLCPY(NameBuff, fm->fname, MAXPATHL); } // Try to shorten the file name. - os_dirname(IObuff, IOSIZE); - p = path_shorten_fname((char_u *)NameBuff, IObuff); + os_dirname((char_u *)IObuff, IOSIZE); + p = (char_u *)path_shorten_fname(NameBuff, (char *)IObuff); // buflist_new() will call fmarks_check_names() (void)buflist_new((char *)NameBuff, (char *)p, (linenr_T)1, 0); @@ -686,21 +686,21 @@ void fmarks_check_names(buf_T *buf) } for (i = 0; i < NGLOBALMARKS; i++) { - fmarks_check_one(&namedfm[i], name, buf); + fmarks_check_one(&namedfm[i], (char *)name, buf); } FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { for (i = 0; i < wp->w_jumplistlen; i++) { - fmarks_check_one(&wp->w_jumplist[i], name, buf); + fmarks_check_one(&wp->w_jumplist[i], (char *)name, buf); } } } -static void fmarks_check_one(xfmark_T *fm, char_u *name, buf_T *buf) +static void fmarks_check_one(xfmark_T *fm, char *name, buf_T *buf) { if (fm->fmark.fnum == 0 && fm->fname != NULL - && FNAMECMP(name, fm->fname) == 0) { + && path_fnamecmp(name, fm->fname) == 0) { fm->fmark.fnum = buf->b_fnum; XFREE_CLEAR(fm->fname); } diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c index 83b0609052..33d652a51f 100644 --- a/src/nvim/mbyte.c +++ b/src/nvim/mbyte.c @@ -338,13 +338,13 @@ enc_alias_table[] = { NULL, 0 } }; -// Find encoding "name" in the list of canonical encoding names. -// Returns -1 if not found. -static int enc_canon_search(const char_u *name) +/// Find encoding "name" in the list of canonical encoding names. +/// Returns -1 if not found. +static int enc_canon_search(const char *name) FUNC_ATTR_PURE { for (int i = 0; i < IDX_COUNT; i++) { - if (STRCMP(name, enc_canon_table[i].name) == 0) { + if (strcmp(name, enc_canon_table[i].name) == 0) { return i; } } @@ -356,7 +356,7 @@ static int enc_canon_search(const char_u *name) int enc_canon_props(const char_u *name) FUNC_ATTR_PURE { - int i = enc_canon_search(name); + int i = enc_canon_search((char *)name); if (i >= 0) { return enc_canon_table[i].prop; } else if (STRNCMP(name, "2byte-", 6) == 0) { @@ -379,7 +379,7 @@ int bomb_size(void) if (curbuf->b_p_bomb && !curbuf->b_p_bin) { if (*curbuf->b_p_fenc == NUL - || STRCMP(curbuf->b_p_fenc, "utf-8") == 0) { + || strcmp(curbuf->b_p_fenc, "utf-8") == 0) { n = 3; } else if (STRNCMP(curbuf->b_p_fenc, "ucs-2", 5) == 0 || STRNCMP(curbuf->b_p_fenc, "utf-16", 6) == 0) { @@ -1350,7 +1350,7 @@ static int utf_strnicmp(const char_u *s1, const char_u *s2, size_t n1, size_t n2 return n1 == 0 ? -1 : 1; } -#ifdef WIN32 +#ifdef MSWIN # ifndef CP_UTF8 # define CP_UTF8 65001 // magic number from winnls.h # endif @@ -1457,7 +1457,7 @@ void mb_utflen(const char_u *s, size_t len, size_t *codepoints, size_t *codeunit { size_t count = 0, extra = 0; size_t clen; - for (size_t i = 0; i < len && s[i] != NUL; i += clen) { + for (size_t i = 0; i < len; i += clen) { 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 @@ -1479,7 +1479,7 @@ ssize_t mb_utf_index_to_bytes(const char_u *s, size_t len, size_t index, bool us if (index == 0) { return 0; } - for (i = 0; i < len && s[i] != NUL; i += clen) { + for (i = 0; i < len; i += clen) { 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 @@ -1556,7 +1556,7 @@ void show_utf8(void) sprintf((char *)IObuff + rlen, "%02x ", (line[i] == NL) ? NUL : line[i]); // NUL is stored as NL clen--; - rlen += (int)STRLEN(IObuff + rlen); + rlen += (int)strlen(IObuff + rlen); if (rlen > IOSIZE - 20) { break; } @@ -2115,7 +2115,7 @@ char *enc_canonize(char *enc) FUNC_ATTR_NONNULL_RET { char *p, *s; - if (STRCMP(enc, "default") == 0) { + if (strcmp(enc, "default") == 0) { // Use the default encoding as found by set_init_1(). return xstrdup(fenc_default); } @@ -2159,12 +2159,12 @@ char *enc_canonize(char *enc) } int i; - if (enc_canon_search((char_u *)p) >= 0) { + if (enc_canon_search(p) >= 0) { // canonical name can be used unmodified if (p != r) { STRMOVE(r, p); } - } else if ((i = enc_alias_search((char_u *)p)) >= 0) { + } else if ((i = enc_alias_search(p)) >= 0) { // alias recognized, get canonical name xfree(r); r = xstrdup(enc_canon_table[i].name); @@ -2174,12 +2174,12 @@ char *enc_canonize(char *enc) /// Search for an encoding alias of "name". /// Returns -1 when not found. -static int enc_alias_search(const char_u *name) +static int enc_alias_search(const char *name) { int i; for (i = 0; enc_alias_table[i].name != NULL; i++) { - if (STRCMP(name, enc_alias_table[i].name) == 0) { + if (strcmp(name, enc_alias_table[i].name) == 0) { return enc_alias_table[i].canon; } } @@ -2390,12 +2390,12 @@ static char_u *iconv_string(const vimconv_T *const vcp, char_u *str, size_t slen /// @return FAIL when conversion is not supported, OK otherwise. int convert_setup(vimconv_T *vcp, char *from, char *to) { - return convert_setup_ext(vcp, (char_u *)from, true, (char_u *)to, true); + return convert_setup_ext(vcp, from, true, to, true); } /// As convert_setup(), but only when from_unicode_is_utf8 is true will all /// "from" unicode charsets be considered utf-8. Same for "to". -int convert_setup_ext(vimconv_T *vcp, char_u *from, bool from_unicode_is_utf8, char_u *to, +int convert_setup_ext(vimconv_T *vcp, char *from, bool from_unicode_is_utf8, char *to, bool to_unicode_is_utf8) { int from_prop; @@ -2413,12 +2413,12 @@ int convert_setup_ext(vimconv_T *vcp, char_u *from, bool from_unicode_is_utf8, c // No conversion when one of the names is empty or they are equal. if (from == NULL || *from == NUL || to == NULL || *to == NUL - || STRCMP(from, to) == 0) { + || strcmp(from, to) == 0) { return OK; } - from_prop = enc_canon_props(from); - to_prop = enc_canon_props(to); + from_prop = enc_canon_props((char_u *)from); + to_prop = enc_canon_props((char_u *)to); if (from_unicode_is_utf8) { from_is_utf8 = from_prop & ENC_UNICODE; } else { @@ -2448,8 +2448,8 @@ int convert_setup_ext(vimconv_T *vcp, char_u *from, bool from_unicode_is_utf8, c #ifdef HAVE_ICONV else { // NOLINT(readability/braces) // Use iconv() for conversion. - vcp->vc_fd = (iconv_t)my_iconv_open(to_is_utf8 ? (char_u *)"utf-8" : to, - from_is_utf8 ? (char_u *)"utf-8" : from); + 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); if (vcp->vc_fd != (iconv_t)-1) { vcp->vc_type = CONV_ICONV; vcp->vc_factor = 4; // could be longer too... @@ -2793,7 +2793,7 @@ void f_setcellwidths(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) void f_charclass(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - if (tv_check_for_string(&argvars[0]) == FAIL + if (tv_check_for_string_arg(argvars, 0) == FAIL || argvars[0].vval.v_string == NULL) { return; } diff --git a/src/nvim/memline.c b/src/nvim/memline.c index e6cb1b79fc..56342942db 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -227,9 +227,6 @@ typedef enum { int ml_open(buf_T *buf) { bhdr_T *hp = NULL; - ZERO_BL *b0p; - PTR_BL *pp; - DATA_BL *dp; // init fields in memline struct buf->b_ml.ml_stack_size = 0; // no stack yet @@ -269,7 +266,7 @@ int ml_open(buf_T *buf) iemsg(_("E298: Didn't get block nr 0?")); goto error; } - b0p = hp->bh_data; + ZERO_BL *b0p = hp->bh_data; b0p->b0_id[0] = BLOCK0_ID0; b0p->b0_id[1] = BLOCK0_ID1; @@ -309,7 +306,7 @@ int ml_open(buf_T *buf) iemsg(_("E298: Didn't get block nr 1?")); goto error; } - pp = hp->bh_data; + PTR_BL *pp = hp->bh_data; pp->pb_count = 1; pp->pb_pointer[0].pe_bnum = 2; pp->pb_pointer[0].pe_page_count = 1; @@ -324,7 +321,7 @@ int ml_open(buf_T *buf) goto error; } - dp = hp->bh_data; + DATA_BL *dp = hp->bh_data; dp->db_index[0] = --dp->db_txt_start; // at end of block dp->db_free -= 1 + (unsigned)INDEX_SIZE; dp->db_line_count = 1; @@ -348,11 +345,8 @@ error: void ml_setname(buf_T *buf) { bool success = false; - memfile_T *mfp; - char_u *fname; - char *dirp; - mfp = buf->b_ml.ml_mfp; + memfile_T *mfp = buf->b_ml.ml_mfp; if (mfp->mf_fd < 0) { // there is no swap file yet // When 'updatecount' is 0 and 'noswapfile' there is no swap file. // For help files we will make a swap file now. @@ -363,13 +357,13 @@ void ml_setname(buf_T *buf) } // Try all directories in the 'directory' option. - dirp = p_dir; + char *dirp = p_dir; bool found_existing_dir = false; for (;;) { if (*dirp == NUL) { // tried all directories, fail break; } - fname = (char_u *)findswapname(buf, &dirp, mfp->mf_fname, &found_existing_dir); + char *fname = findswapname(buf, &dirp, mfp->mf_fname, &found_existing_dir); // alloc's fname if (dirp == NULL) { // out of memory break; @@ -379,7 +373,7 @@ void ml_setname(buf_T *buf) } // if the file name is the same we don't have to do anything - if (FNAMECMP(fname, mfp->mf_fname) == 0) { + if (path_fnamecmp(fname, mfp->mf_fname) == 0) { xfree(fname); success = true; break; @@ -391,10 +385,10 @@ void ml_setname(buf_T *buf) } // try to rename the swap file - if (vim_rename((char_u *)mfp->mf_fname, fname) == 0) { + if (vim_rename(mfp->mf_fname, fname) == 0) { success = true; mf_free_fnames(mfp); - mf_set_fnames(mfp, (char *)fname); + mf_set_fnames(mfp, fname); ml_upd_block0(buf, UB_SAME_DIR); break; } @@ -432,11 +426,7 @@ void ml_open_files(void) /// and the memfile will be in memory only (no recovery possible). void ml_open_file(buf_T *buf) { - memfile_T *mfp; - char_u *fname; - char *dirp; - - mfp = buf->b_ml.ml_mfp; + memfile_T *mfp = buf->b_ml.ml_mfp; if (mfp == NULL || mfp->mf_fd >= 0 || !buf->b_p_swf || (cmdmod.cmod_flags & CMOD_NOSWAPFILE) || buf->terminal) { @@ -445,7 +435,7 @@ void ml_open_file(buf_T *buf) // For a spell buffer use a temp file name. if (buf->b_spell) { - fname = (char_u *)vim_tempname(); + char *fname = vim_tempname(); if (fname != NULL) { (void)mf_open_file(mfp, (char *)fname); // consumes fname! } @@ -454,7 +444,7 @@ void ml_open_file(buf_T *buf) } // Try all directories in 'directory' option. - dirp = p_dir; + char *dirp = p_dir; bool found_existing_dir = false; for (;;) { if (*dirp == NUL) { @@ -463,14 +453,14 @@ void ml_open_file(buf_T *buf) // There is a small chance that between choosing the swap file name // and creating it, another Vim creates the file. In that case the // creation will fail and we will use another directory. - fname = (char_u *)findswapname(buf, &dirp, NULL, &found_existing_dir); + char *fname = findswapname(buf, &dirp, NULL, &found_existing_dir); if (dirp == NULL) { break; // out of memory } if (fname == NULL) { continue; } - if (mf_open_file(mfp, (char *)fname) == OK) { // consumes fname! + if (mf_open_file(mfp, fname) == OK) { // consumes fname! ml_upd_block0(buf, UB_SAME_DIR); // Flush block zero, so others can read it @@ -580,21 +570,19 @@ static bool ml_check_b0_strings(ZERO_BL *b0p) return (memchr(b0p->b0_version, NUL, 10) && memchr(b0p->b0_uname, NUL, B0_UNAME_SIZE) && memchr(b0p->b0_hname, NUL, B0_HNAME_SIZE) - && memchr(b0p->b0_fname, NUL, B0_FNAME_SIZE_CRYPT)); // -V512 + && memchr(b0p->b0_fname, NUL, B0_FNAME_SIZE_CRYPT)); // -V1086 } /// Update the timestamp or the B0_SAME_DIR flag of the .swp file. static void ml_upd_block0(buf_T *buf, upd_block0_T what) { - memfile_T *mfp; bhdr_T *hp; - ZERO_BL *b0p; - mfp = buf->b_ml.ml_mfp; + memfile_T *mfp = buf->b_ml.ml_mfp; if (mfp == NULL || (hp = mf_get(mfp, 0, 1)) == NULL) { return; } - b0p = hp->bh_data; + ZERO_BL *b0p = hp->bh_data; if (ml_check_b0_id(b0p) == FAIL) { iemsg(_("E304: ml_upd_block0(): Didn't get block 0??")); } else { @@ -627,7 +615,7 @@ static void set_b0_fname(ZERO_BL *b0p, buf_T *buf) if (b0p->b0_fname[0] == '~') { // If there is no user name or it is too long, don't use "~/" int retval = os_get_username(uname, B0_UNAME_SIZE); - size_t ulen = STRLEN(uname); + size_t ulen = strlen(uname); size_t flen = STRLEN(b0p->b0_fname); if (retval == FAIL || ulen + flen > B0_FNAME_SIZE_CRYPT - 1) { STRLCPY(b0p->b0_fname, buf->b_ffname, B0_FNAME_SIZE_CRYPT); @@ -675,10 +663,9 @@ static void set_b0_dir_flag(ZERO_BL *b0p, buf_T *buf) /// When there is room, add the 'fileencoding' to block zero. static void add_b0_fenc(ZERO_BL *b0p, buf_T *buf) { - int n; - int size = B0_FNAME_SIZE_NOCRYPT; + const int size = B0_FNAME_SIZE_NOCRYPT; - n = (int)STRLEN(buf->b_p_fenc); + int n = (int)strlen(buf->b_p_fenc); if ((int)STRLEN(b0p->b0_fname) + n + 1 > size) { b0p->b0_flags &= (uint8_t) ~B0_HAS_FENC; } else { @@ -697,7 +684,6 @@ void ml_recover(bool checkext) { buf_T *buf = NULL; memfile_T *mfp = NULL; - char *fname; char *fname_used = NULL; bhdr_T *hp = NULL; ZERO_BL *b0p; @@ -706,37 +692,22 @@ void ml_recover(bool checkext) PTR_BL *pp; DATA_BL *dp; infoptr_T *ip; - blocknr_T bnum; - int len; bool directly; - linenr_T lnum; char *p; - int i; - long error; - bool cannot_open; - linenr_T line_count; - bool has_error; - int idx; - int top; - int txt_start; - off_T size; - int called_from_main; bool serious_error = true; - long mtime; - int attr; int orig_file_status = NOTDONE; recoverymode = true; - called_from_main = (curbuf->b_ml.ml_mfp == NULL); - attr = HL_ATTR(HLF_E); + int called_from_main = (curbuf->b_ml.ml_mfp == NULL); + int attr = HL_ATTR(HLF_E); // If the file name ends in ".s[a-w][a-z]" we assume this is the swap file. // Otherwise a search is done to find the swap file(s). - fname = curbuf->b_fname; + char *fname = curbuf->b_fname; if (fname == NULL) { // When there is no file name fname = ""; } - len = (int)STRLEN(fname); + 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 @@ -752,6 +723,7 @@ void ml_recover(bool checkext) semsg(_("E305: No swap file found for %s"), fname); goto theend; } + int i; if (len == 1) { // one swap file found, use it i = 1; } else { // several swap files found, choose @@ -857,6 +829,7 @@ void ml_recover(bool checkext) msg_end(); goto theend; } + off_T size; if ((size = vim_lseek(mfp->mf_fd, (off_T)0L, SEEK_END)) <= 0) { mfp->mf_blocknr_max = 0; // no file or empty file } else { @@ -894,7 +867,7 @@ void ml_recover(bool checkext) // check date of swap file and original file FileInfo org_file_info; FileInfo swp_file_info; - mtime = char_to_long(b0p->b0_mtime); + long mtime = char_to_long(b0p->b0_mtime); if (curbuf->b_ffname != NULL && os_fileinfo(curbuf->b_ffname, &org_file_info) && ((os_fileinfo(mfp->mf_fname, &swp_file_info) @@ -940,21 +913,17 @@ void ml_recover(bool checkext) } unchanged(curbuf, true, true); - bnum = 1; // start with block 1 + blocknr_T bnum = 1; // start with block 1 unsigned page_count = 1; // which is 1 page - lnum = 0; // append after line 0 in curbuf - line_count = 0; - idx = 0; // start with first index in block 1 - error = 0; + linenr_T lnum = 0; // append after line 0 in curbuf + linenr_T line_count = 0; + int idx = 0; // start with first index in block 1 + long error = 0; buf->b_ml.ml_stack_top = 0; // -V1048 buf->b_ml.ml_stack = NULL; buf->b_ml.ml_stack_size = 0; // -V1048 - if (curbuf->b_ffname == NULL) { - cannot_open = true; - } else { - cannot_open = false; - } + bool cannot_open = (curbuf->b_ffname == NULL); serious_error = false; for (; !got_int; line_breakcheck()) { @@ -975,7 +944,7 @@ void ml_recover(bool checkext) if (pp->pb_id == PTR_ID) { // it is a pointer block // check line count when using pointer block first time if (idx == 0 && line_count != 0) { - for (i = 0; i < (int)pp->pb_count; i++) { + for (int i = 0; i < (int)pp->pb_count; i++) { line_count -= pp->pb_pointer[i].pe_line_count; } if (line_count != 0) { @@ -1014,7 +983,7 @@ void ml_recover(bool checkext) } // going one block deeper in the tree - top = ml_add_stack(buf); // new entry in stack + int top = ml_add_stack(buf); // new entry in stack ip = &(buf->b_ml.ml_stack[top]); ip->ip_bnum = bnum; ip->ip_index = idx; @@ -1039,7 +1008,7 @@ void ml_recover(bool checkext) } else { // it is a data block // Append all the lines in this block - has_error = false; + bool has_error = false; // check length of block // if wrong, use length in pointer block if (page_count * mfp->mf_page_size != dp->db_txt_end) { @@ -1065,8 +1034,8 @@ void ml_recover(bool checkext) has_error = true; } - for (i = 0; i < dp->db_line_count; i++) { - txt_start = (dp->db_index[i] & DB_INDEX_MASK); + for (int i = 0; i < dp->db_line_count; i++) { + int txt_start = (dp->db_index[i] & DB_INDEX_MASK); if (txt_start <= (int)HEADER_SIZE || txt_start >= (int)dp->db_txt_end) { p = "???"; @@ -1110,7 +1079,7 @@ void ml_recover(bool checkext) for (idx = 1; idx <= lnum; idx++) { // Need to copy one line, fetching the other one may flush it. p = xstrdup(ml_get(idx)); - i = STRCMP(p, ml_get(idx + lnum)); + int i = strcmp(p, ml_get(idx + lnum)); xfree(p); if (i != 0) { changed_internal(); @@ -1191,12 +1160,9 @@ int recover_names(char_u *fname, int list, int nr, char **fname_out) int num_names; char *(names[6]); char_u *tail; - char_u *p; - int num_files; + char *p; int file_count = 0; char **files; - char *dirp; - char_u *dir_name; char_u *fname_res = NULL; #ifdef HAVE_READLINK char_u fname_buf[MAXPATHL]; @@ -1221,8 +1187,8 @@ int recover_names(char_u *fname, int list, int nr, char **fname_out) // Do the loop for every directory in 'directory'. // First allocate some memory to put the directory name in. - dir_name = xmalloc(STRLEN(p_dir) + 1); - dirp = p_dir; + char *dir_name = xmalloc(strlen(p_dir) + 1); + char *dirp = p_dir; while (*dirp) { // Isolate a directory name from *dirp and put it in dir_name (we know // it is large enough, so use 31000 for length). @@ -1238,7 +1204,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, fname_res, true); + num_names = recov_file_names(names, (char *)fname_res, true); } } else { // check directory dir_name if (fname == NULL) { @@ -1261,11 +1227,12 @@ int recover_names(char_u *fname, int list, int nr, char **fname_out) tail = (char_u *)path_tail((char *)fname_res); tail = (char_u *)concat_fnames((char *)dir_name, (char *)tail, true); } - num_names = recov_file_names(names, tail, false); + num_names = recov_file_names(names, (char *)tail, false); xfree(tail); } } + int num_files; if (num_names == 0) { num_files = 0; } else if (expand_wildcards(num_names, names, &num_files, &files, @@ -1291,7 +1258,7 @@ int recover_names(char_u *fname, int list, int nr, char **fname_out) // remove swapfile name of the current buffer, it must be ignored if (curbuf->b_ml.ml_mfp != NULL - && (p = (char_u *)curbuf->b_ml.ml_mfp->mf_fname) != NULL) { + && (p = curbuf->b_ml.ml_mfp->mf_fname) != NULL) { for (int i = 0; i < num_files; i++) { // Do not expand wildcards, on Windows would try to expand // "%tmp%" in "%tmp%file" @@ -1440,9 +1407,12 @@ static time_t swapfile_info(char_u *fname) msg_puts(_(" owned by: ")); msg_outtrans(uname); msg_puts(_(" dated: ")); - } else -#endif + } else { + msg_puts(_(" dated: ")); + } +#else msg_puts(_(" dated: ")); +#endif x = file_info.stat.st_mtim.tv_sec; char ctime_buf[50]; msg_puts(os_ctime_r(&x, ctime_buf, sizeof(ctime_buf))); @@ -1513,7 +1483,6 @@ static time_t swapfile_info(char_u *fname) static bool swapfile_unchanged(char *fname) { struct block0 b0; - int ret = true; // Swap file must exist. if (!os_path_exists(fname)) { @@ -1530,6 +1499,8 @@ static bool swapfile_unchanged(char *fname) return false; } + bool ret = true; + // the ID and magic number must be correct if (ml_check_b0_id(&b0) == FAIL || b0_magic_wrong(&b0)) { ret = false; @@ -1553,7 +1524,7 @@ static bool swapfile_unchanged(char *fname) return ret; } -static int recov_file_names(char **names, char_u *path, int prepend_dot) +static int recov_file_names(char **names, char *path, int prepend_dot) FUNC_ATTR_NONNULL_ALL { int num_names = 0; @@ -1561,7 +1532,7 @@ static int recov_file_names(char **names, char_u *path, int prepend_dot) // May also add the file name with a dot prepended, for swap file in same // dir as original file. if (prepend_dot) { - names[num_names] = modname((char *)path, ".sw?", true); + names[num_names] = modname(path, ".sw?", true); if (names[num_names] == NULL) { return num_names; } @@ -1569,14 +1540,14 @@ static int recov_file_names(char **names, char_u *path, int prepend_dot) } // Form the normal swap file name pattern by appending ".sw?". - names[num_names] = concat_fnames((char *)path, ".sw?", false); + names[num_names] = concat_fnames(path, ".sw?", false); if (num_names >= 1) { // check if we have the same name twice - char_u *p = (char_u *)names[num_names - 1]; + char *p = names[num_names - 1]; int i = (int)STRLEN(names[num_names - 1]) - (int)STRLEN(names[num_names]); if (i > 0) { p += i; // file name has been expanded to full path } - if (STRCMP(p, names[num_names]) != 0) { + if (strcmp(p, names[num_names]) != 0) { num_names++; } else { xfree(names[num_names]); @@ -1637,10 +1608,7 @@ void ml_sync_all(int check_file, int check_char, bool do_fsync) /// @param message if true, the success of preserving is reported. void ml_preserve(buf_T *buf, int message, bool do_fsync) { - bhdr_T *hp; - linenr_T lnum; memfile_T *mfp = buf->b_ml.ml_mfp; - int status; int got_int_save = got_int; if (mfp == NULL || mfp->mf_fname == NULL) { @@ -1656,7 +1624,7 @@ void ml_preserve(buf_T *buf, int message, bool do_fsync) ml_flush_line(buf); // flush buffered line (void)ml_find_line(buf, (linenr_T)0, ML_FLUSH); // flush locked block - status = mf_sync(mfp, MFS_ALL | (do_fsync ? MFS_FLUSH : 0)); + int status = mf_sync(mfp, MFS_ALL | (do_fsync ? MFS_FLUSH : 0)); // stack is invalid after mf_sync(.., MFS_ALL) buf->b_ml.ml_stack_top = 0; @@ -1672,9 +1640,9 @@ void ml_preserve(buf_T *buf, int message, bool do_fsync) // ml_find_line() does the work by translating the negative block numbers // when getting the first line of each data block. if (mf_need_trans(mfp) && !got_int) { - lnum = 1; + linenr_T lnum = 1; while (mf_need_trans(mfp) && lnum <= buf->b_ml.ml_line_count) { - hp = ml_find_line(buf, lnum, ML_FIND); + bhdr_T *hp = ml_find_line(buf, lnum, ML_FIND); if (hp == NULL) { status = FAIL; goto theend; @@ -1740,9 +1708,6 @@ int gchar_pos(pos_T *pos) char *ml_get_buf(buf_T *buf, linenr_T lnum, bool will_change) FUNC_ATTR_NONNULL_ALL { - bhdr_T *hp; - DATA_BL *dp; - char *ptr; static int recursive = 0; static char questions[4]; @@ -1779,6 +1744,7 @@ errorret: // Find the data block containing the line. // This also fills the stack with the blocks from the root to the data // block and releases any locked block. + bhdr_T *hp; if ((hp = ml_find_line(buf, lnum, ML_FIND)) == NULL) { if (recursive == 0) { // Avoid giving this message for a recursive call, may happen @@ -1793,10 +1759,9 @@ errorret: goto errorret; } - dp = hp->bh_data; + DATA_BL *dp = hp->bh_data; - ptr = (char *)dp + - ((dp->db_index[lnum - buf->b_ml.ml_locked_low]) & DB_INDEX_MASK); + char *ptr = (char *)dp + (dp->db_index[lnum - buf->b_ml.ml_locked_low] & DB_INDEX_MASK); buf->b_ml.ml_line_ptr = (char_u *)ptr; buf->b_ml.ml_line_lnum = lnum; buf->b_ml.ml_flags &= ~ML_LINE_DIRTY; @@ -1872,17 +1837,6 @@ int ml_append_buf(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, bool new static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, bool newfile, int mark) { - int i; - int line_count; // number of indexes in current block - int offset; - int from, to; - int page_count; - int db_idx; // index for lnum in data block - bhdr_T *hp; - DATA_BL *dp; - PTR_BL *pp; - infoptr_T *ip; - // lnum out of range if (lnum > buf->b_ml.ml_line_count || buf->b_ml.ml_mfp == NULL) { return FAIL; @@ -1903,6 +1857,7 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b // find the data block containing the previous line // This also fills the stack with the blocks from the root to the data block // This also releases any locked block. + bhdr_T *hp; if ((hp = ml_find_line(buf, lnum == 0 ? (linenr_T)1 : lnum, ML_INSERT)) == NULL) { return FAIL; @@ -1910,15 +1865,16 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b buf->b_ml.ml_flags &= ~ML_EMPTY; + int db_idx; // index for lnum in data block if (lnum == 0) { // got line one instead, correct db_idx db_idx = -1; // careful, it is negative! } else { db_idx = lnum - buf->b_ml.ml_locked_low; } - // get line count before the insertion - line_count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low; + // get line count (number of indexes in current block) before the insertion + int line_count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low; - dp = hp->bh_data; + DATA_BL *dp = hp->bh_data; // If // - there is not enough room in the current block @@ -1957,6 +1913,7 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b if (line_count > db_idx + 1) { // if there are following lines // Offset is the start of the previous line. // This will become the character just after the new line. + int offset; if (db_idx < 0) { offset = (int)dp->db_txt_end; } else { @@ -1965,7 +1922,7 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b memmove((char *)dp + dp->db_txt_start, (char *)dp + dp->db_txt_start + len, (size_t)offset - (dp->db_txt_start + (size_t)len)); - for (i = line_count - 1; i > db_idx; i--) { + for (int i = line_count - 1; i > db_idx; i--) { dp->db_index[i + 1] = dp->db_index[i] - (unsigned)len; } dp->db_index[db_idx + 1] = (unsigned)(offset - len); @@ -2038,7 +1995,7 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b } } - page_count = ((space_needed + (int)HEADER_SIZE) + page_size - 1) / page_size; + int page_count = ((space_needed + (int)HEADER_SIZE) + page_size - 1) / page_size; hp_new = ml_new_data(mfp, newfile, page_count); if (db_idx < 0) { // left block is new hp_left = hp_new; @@ -2078,12 +2035,12 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b memmove((char *)dp_right + dp_right->db_txt_start, (char *)dp_left + dp_left->db_txt_start, (size_t)data_moved); - offset = (int)(dp_right->db_txt_start - dp_left->db_txt_start); + int offset = (int)(dp_right->db_txt_start - dp_left->db_txt_start); dp_left->db_txt_start += (unsigned)data_moved; dp_left->db_free += (unsigned)total_moved; // update indexes in the new block - for (to = line_count_right, from = db_idx + 1; + for (int to = line_count_right, from = db_idx + 1; from < line_count_left; from++, to++) { dp_right->db_index[to] = dp->db_index[from] + (unsigned)offset; } @@ -2138,14 +2095,13 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b (void)ml_find_line(buf, (linenr_T)0, ML_FLUSH); // flush data block // update pointer blocks for the new data block - for (stack_idx = buf->b_ml.ml_stack_top - 1; stack_idx >= 0; - --stack_idx) { - ip = &(buf->b_ml.ml_stack[stack_idx]); + for (stack_idx = buf->b_ml.ml_stack_top - 1; stack_idx >= 0; stack_idx--) { + infoptr_T *ip = &(buf->b_ml.ml_stack[stack_idx]); pb_idx = ip->ip_index; if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL) { return FAIL; } - pp = hp->bh_data; // must be pointer block + PTR_BL *pp = hp->bh_data; // must be pointer block if (pp->pb_id != PTR_ID) { iemsg(_("E317: pointer block id wrong 3")); mf_put(mfp, hp, false, false); @@ -2258,11 +2214,11 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b // recompute line counts line_count_right = 0; - for (i = 0; i < (int)pp_new->pb_count; i++) { + for (int i = 0; i < (int)pp_new->pb_count; i++) { line_count_right += pp_new->pb_pointer[i].pe_line_count; } line_count_left = 0; - for (i = 0; i < (int)pp->pb_count; i++) { + for (int i = 0; i < (int)pp->pb_count; i++) { line_count_left += pp->pb_pointer[i].pe_line_count; } @@ -2296,8 +2252,9 @@ void ml_add_deleted_len_buf(buf_T *buf, char_u *ptr, ssize_t len) if (inhibit_delete_count) { return; } - if (len == -1) { - len = (ssize_t)STRLEN(ptr); + ssize_t maxlen = (ssize_t)STRLEN(ptr); + if (len == -1 || len > maxlen) { + len = maxlen; } curbuf->deleted_bytes += (size_t)len + 1; curbuf->deleted_bytes2 += (size_t)len + 1; @@ -2378,18 +2335,6 @@ int ml_delete(linenr_T lnum, bool message) static int ml_delete_int(buf_T *buf, linenr_T lnum, bool message) { - bhdr_T *hp; - memfile_T *mfp; - DATA_BL *dp; - PTR_BL *pp; - infoptr_T *ip; - int count; // number of entries in block - int idx; - int stack_idx; - int line_start; - long line_size; - int i; - if (lnum < 1 || lnum > buf->b_ml.ml_line_count) { return FAIL; } @@ -2404,7 +2349,7 @@ static int ml_delete_int(buf_T *buf, linenr_T lnum, bool message) set_keep_msg(_(no_lines_msg), 0); } - i = ml_replace((linenr_T)1, "", true); + int i = ml_replace((linenr_T)1, "", true); buf->b_ml.ml_flags |= ML_EMPTY; return i; @@ -2413,23 +2358,25 @@ static int ml_delete_int(buf_T *buf, linenr_T lnum, bool message) // find the data block containing the line // This also fills the stack with the blocks from the root to the data block // This also releases any locked block. - mfp = buf->b_ml.ml_mfp; + memfile_T *mfp = buf->b_ml.ml_mfp; if (mfp == NULL) { return FAIL; } + bhdr_T *hp; if ((hp = ml_find_line(buf, lnum, ML_DELETE)) == NULL) { return FAIL; } - dp = hp->bh_data; - // compute line count before the delete - count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low + 2; - idx = lnum - buf->b_ml.ml_locked_low; + DATA_BL *dp = hp->bh_data; + // compute line count (number of entries in block) before the delete + int count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low + 2; + int idx = lnum - buf->b_ml.ml_locked_low; buf->b_ml.ml_line_count--; - line_start = ((dp->db_index[idx]) & DB_INDEX_MASK); + int line_start = ((dp->db_index[idx]) & DB_INDEX_MASK); + long line_size; if (idx == 0) { // first line in block, text at the end line_size = dp->db_txt_end - (unsigned)line_start; } else { @@ -2451,15 +2398,14 @@ static int ml_delete_int(buf_T *buf, linenr_T lnum, bool message) mf_free(mfp, hp); // free the data block buf->b_ml.ml_locked = NULL; - for (stack_idx = buf->b_ml.ml_stack_top - 1; stack_idx >= 0; - --stack_idx) { + for (int stack_idx = buf->b_ml.ml_stack_top - 1; stack_idx >= 0; stack_idx--) { buf->b_ml.ml_stack_top = 0; // stack is invalid when failing - ip = &(buf->b_ml.ml_stack[stack_idx]); + infoptr_T *ip = &(buf->b_ml.ml_stack[stack_idx]); idx = ip->ip_index; if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL) { return FAIL; } - pp = hp->bh_data; // must be pointer block + PTR_BL *pp = hp->bh_data; // must be pointer block if (pp->pb_id != PTR_ID) { iemsg(_("E317: pointer block id wrong 4")); mf_put(mfp, hp, false, false); @@ -2496,7 +2442,7 @@ static int ml_delete_int(buf_T *buf, linenr_T lnum, bool message) // delete the index by moving the next indexes backwards // Adjust the indexes for the text movement. - for (i = idx; i < count - 1; i++) { + for (int i = idx; i < count - 1; i++) { dp->db_index[i] = dp->db_index[i + 1] + (unsigned)line_size; } @@ -2515,8 +2461,6 @@ static int ml_delete_int(buf_T *buf, linenr_T lnum, bool message) /// set the B_MARKED flag for line 'lnum' void ml_setmarked(linenr_T lnum) { - bhdr_T *hp; - DATA_BL *dp; // invalid line number if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count || curbuf->b_ml.ml_mfp == NULL) { @@ -2529,10 +2473,11 @@ void ml_setmarked(linenr_T lnum) // find the data block containing the line // This also fills the stack with the blocks from the root to the data block // This also releases any locked block. + bhdr_T *hp; if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL) { return; // give error message? } - dp = hp->bh_data; + DATA_BL *dp = hp->bh_data; dp->db_index[lnum - curbuf->b_ml.ml_locked_low] |= DB_MARKED; curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY; } @@ -2540,27 +2485,23 @@ void ml_setmarked(linenr_T lnum) /// find the first line with its B_MARKED flag set linenr_T ml_firstmarked(void) { - bhdr_T *hp; - DATA_BL *dp; - linenr_T lnum; - int i; - if (curbuf->b_ml.ml_mfp == NULL) { return (linenr_T)0; } // The search starts with lowest_marked line. This is the last line where // a mark was found, adjusted by inserting/deleting lines. - for (lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count;) { + for (linenr_T lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count;) { // Find the data block containing the line. // This also fills the stack with the blocks from the root to the data // block This also releases any locked block. + bhdr_T *hp; if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL) { return (linenr_T)0; // give error message? } - dp = hp->bh_data; + DATA_BL *dp = hp->bh_data; - for (i = lnum - curbuf->b_ml.ml_locked_low; + for (int i = lnum - curbuf->b_ml.ml_locked_low; lnum <= curbuf->b_ml.ml_locked_high; i++, lnum++) { if ((dp->db_index[i]) & DB_MARKED) { (dp->db_index[i]) &= DB_INDEX_MASK; @@ -2577,26 +2518,22 @@ linenr_T ml_firstmarked(void) /// clear all DB_MARKED flags void ml_clearmarked(void) { - bhdr_T *hp; - DATA_BL *dp; - linenr_T lnum; - int i; - if (curbuf->b_ml.ml_mfp == NULL) { // nothing to do return; } // The search starts with line lowest_marked. - for (lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count;) { + for (linenr_T lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count;) { // Find the data block containing the line. // This also fills the stack with the blocks from the root to the data // block and releases any locked block. + bhdr_T *hp; if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL) { return; // give error message? } - dp = hp->bh_data; + DATA_BL *dp = hp->bh_data; - for (i = lnum - curbuf->b_ml.ml_locked_low; + for (int i = lnum - curbuf->b_ml.ml_locked_low; lnum <= curbuf->b_ml.ml_locked_high; i++, lnum++) { if ((dp->db_index[i]) & DB_MARKED) { (dp->db_index[i]) &= DB_INDEX_MASK; @@ -2622,18 +2559,6 @@ size_t ml_flush_deleted_bytes(buf_T *buf, size_t *codepoints, size_t *codeunits) /// flush ml_line if necessary static void ml_flush_line(buf_T *buf) { - bhdr_T *hp; - DATA_BL *dp; - linenr_T lnum; - char_u *new_line; - char_u *old_line; - colnr_T new_len; - int old_len; - int extra; - int idx; - int start; - int count; - int i; static bool entered = false; if (buf->b_ml.ml_line_lnum == 0 || buf->b_ml.ml_mfp == NULL) { @@ -2648,29 +2573,30 @@ static void ml_flush_line(buf_T *buf) buf->flush_count++; - lnum = buf->b_ml.ml_line_lnum; - new_line = buf->b_ml.ml_line_ptr; + linenr_T lnum = buf->b_ml.ml_line_lnum; + char_u *new_line = buf->b_ml.ml_line_ptr; - hp = ml_find_line(buf, lnum, ML_FIND); + bhdr_T *hp = ml_find_line(buf, lnum, ML_FIND); if (hp == NULL) { siemsg(_("E320: Cannot find line %" PRId64), (int64_t)lnum); } else { - dp = hp->bh_data; - idx = lnum - buf->b_ml.ml_locked_low; - start = ((dp->db_index[idx]) & DB_INDEX_MASK); - old_line = (char_u *)dp + start; + DATA_BL *dp = hp->bh_data; + int idx = lnum - buf->b_ml.ml_locked_low; + int start = ((dp->db_index[idx]) & DB_INDEX_MASK); + char_u *old_line = (char_u *)dp + start; + int old_len; if (idx == 0) { // line is last in block old_len = (int)dp->db_txt_end - start; } else { // text of previous line follows old_len = (int)(dp->db_index[idx - 1] & DB_INDEX_MASK) - start; } - new_len = (colnr_T)STRLEN(new_line) + 1; - extra = new_len - old_len; // negative if lines gets smaller + colnr_T new_len = (colnr_T)STRLEN(new_line) + 1; + int extra = new_len - old_len; // negative if lines gets smaller // if new line fits in data block, replace directly if ((int)dp->db_free >= extra) { // if the length changes and there are following lines - count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low + 1; + int count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low + 1; if (extra != 0 && idx < count - 1) { // move text of following lines memmove((char *)dp + dp->db_txt_start - extra, @@ -2678,7 +2604,7 @@ static void ml_flush_line(buf_T *buf) (size_t)(start - (int)dp->db_txt_start)); // adjust pointers of this and following lines - for (i = idx + 1; i < count; i++) { + for (int i = idx + 1; i < count; i++) { dp->db_index[i] -= (unsigned)extra; } } @@ -2755,20 +2681,11 @@ static bhdr_T *ml_new_ptr(memfile_T *mfp) /// @return NULL for failure, pointer to block header otherwise static bhdr_T *ml_find_line(buf_T *buf, linenr_T lnum, int action) { - DATA_BL *dp; PTR_BL *pp; - infoptr_T *ip; bhdr_T *hp; - memfile_T *mfp; - linenr_T t; - blocknr_T bnum, bnum2; - int dirty; - linenr_T low, high; int top; - int page_count; - int idx; - mfp = buf->b_ml.ml_mfp; + memfile_T *mfp = buf->b_ml.ml_mfp; // If there is a locked block check if the wanted line is in it. // If not, flush and release the locked block. @@ -2805,14 +2722,15 @@ static bhdr_T *ml_find_line(buf_T *buf, linenr_T lnum, int action) return NULL; } - bnum = 1; // start at the root of the tree - page_count = 1; - low = 1; - high = buf->b_ml.ml_line_count; + blocknr_T bnum = 1; // start at the root of the tree + blocknr_T bnum2; + int page_count = 1; + linenr_T low = 1; + linenr_T high = buf->b_ml.ml_line_count; if (action == ML_FIND) { // first try stack entries for (top = buf->b_ml.ml_stack_top - 1; top >= 0; top--) { - ip = &(buf->b_ml.ml_stack[top]); + infoptr_T *ip = &(buf->b_ml.ml_stack[top]); if (ip->ip_low <= lnum && ip->ip_high >= lnum) { bnum = ip->ip_bnum; low = ip->ip_low; @@ -2840,7 +2758,7 @@ static bhdr_T *ml_find_line(buf_T *buf, linenr_T lnum, int action) high--; } - dp = hp->bh_data; + DATA_BL *dp = hp->bh_data; if (dp->db_id == DATA_ID) { // data block buf->b_ml.ml_locked = hp; buf->b_ml.ml_locked_low = low; @@ -2857,15 +2775,16 @@ static bhdr_T *ml_find_line(buf_T *buf, linenr_T lnum, int action) } top = ml_add_stack(buf); // add new entry to stack - ip = &(buf->b_ml.ml_stack[top]); + infoptr_T *ip = &(buf->b_ml.ml_stack[top]); ip->ip_bnum = bnum; ip->ip_low = low; ip->ip_high = high; ip->ip_index = -1; // index not known yet - dirty = false; + bool dirty = false; + int idx; for (idx = 0; idx < (int)pp->pb_count; idx++) { - t = pp->pb_pointer[idx].pe_line_count; + linenr_T t = pp->pb_pointer[idx].pe_line_count; CHECK(t == 0, _("pe_line_count is zero")); if ((low += t) > lnum) { ip->ip_index = idx; @@ -2951,18 +2870,15 @@ static int ml_add_stack(buf_T *buf) /// Count is the number of lines added, negative if lines have been deleted. static void ml_lineadd(buf_T *buf, int count) { - int idx; - infoptr_T *ip; - PTR_BL *pp; memfile_T *mfp = buf->b_ml.ml_mfp; - bhdr_T *hp; - for (idx = buf->b_ml.ml_stack_top - 1; idx >= 0; idx--) { - ip = &(buf->b_ml.ml_stack[idx]); + for (int idx = buf->b_ml.ml_stack_top - 1; idx >= 0; idx--) { + infoptr_T *ip = &(buf->b_ml.ml_stack[idx]); + bhdr_T *hp; if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL) { break; } - pp = hp->bh_data; // must be pointer block + PTR_BL *pp = hp->bh_data; // must be pointer block if (pp->pb_id != PTR_ID) { mf_put(mfp, hp, false, false); iemsg(_("E317: pointer block id wrong 2")); @@ -2985,7 +2901,6 @@ static void ml_lineadd(buf_T *buf, int count) int resolve_symlink(const char *fname, char *buf) { char tmp[MAXPATHL]; - int ret; int depth = 0; if (fname == NULL) { @@ -3002,7 +2917,7 @@ int resolve_symlink(const char *fname, char *buf) return FAIL; } - ret = (int)readlink(tmp, buf, MAXPATHL - 1); + int ret = (int)readlink(tmp, buf, MAXPATHL - 1); if (ret <= 0) { if (errno == EINVAL || errno == ENOENT) { // Found non-symlink or not existing file, stop here. @@ -3029,7 +2944,7 @@ int resolve_symlink(const char *fname, char *buf) STRCPY(tmp, buf); } else { char_u *tail = (char_u *)path_tail(tmp); - if (STRLEN(tail) + STRLEN(buf) >= MAXPATHL) { + if (STRLEN(tail) + strlen(buf) >= MAXPATHL) { return FAIL; } STRCPY(tail, buf); @@ -3048,7 +2963,6 @@ int resolve_symlink(const char *fname, char *buf) /// @return pointer to allocated memory or NULL. char_u *makeswapname(char_u *fname, char_u *ffname, buf_T *buf, char_u *dir_name) { - char_u *r, *s; char_u *fname_res = fname; #ifdef HAVE_READLINK char_u fname_buf[MAXPATHL]; @@ -3061,11 +2975,11 @@ char_u *makeswapname(char_u *fname, char_u *ffname, buf_T *buf, char_u *dir_name #endif int len = (int)STRLEN(dir_name); - s = dir_name + len; + char_u *s = dir_name + len; if (after_pathsep((char *)dir_name, (char *)s) && len > 1 && s[-1] == s[-2]) { // Ends with '//', Use Full path - r = NULL; + char_u *r = NULL; s = (char_u *)make_percent_swname((char *)dir_name, (char *)fname_res); if (s != NULL) { r = (char_u *)modname((char *)s, ".swp", false); @@ -3075,8 +2989,8 @@ char_u *makeswapname(char_u *fname, char_u *ffname, buf_T *buf, char_u *dir_name } // Prepend a '.' to the swap file name for the current directory. - r = (char_u *)modname((char *)fname_res, ".swp", - dir_name[0] == '.' && dir_name[1] == NUL); + char_u *r = (char_u *)modname((char *)fname_res, ".swp", + dir_name[0] == '.' && dir_name[1] == NUL); if (r == NULL) { // out of memory return NULL; } @@ -3100,12 +3014,9 @@ char_u *makeswapname(char_u *fname, char_u *ffname, buf_T *buf, char_u *dir_name /// @param dname don't use "dirname", it is a global for Alpha char *get_file_in_dir(char *fname, char *dname) { - char *t; - char *tail; char *retval; - int save_char; - tail = path_tail(fname); + char *tail = path_tail(fname); if (dname[0] == '.' && dname[1] == NUL) { retval = xstrdup(fname); @@ -3113,10 +3024,10 @@ char *get_file_in_dir(char *fname, char *dname) if (tail == fname) { // no path before file name retval = concat_fnames(dname + 2, tail, true); } else { - save_char = (uint8_t)(*tail); + char save_char = *tail; *tail = NUL; - t = concat_fnames(fname, dname + 2, true); - *tail = (char)save_char; + char *t = concat_fnames(fname, dname + 2, true); + *tail = save_char; retval = concat_fnames(t, tail, true); xfree(t); } @@ -3240,20 +3151,18 @@ static int do_swapexists(buf_T *buf, char_u *fname) static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_existing_dir) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1, 2, 4) { - char *fname; size_t n; - char *dir_name; char *buf_fname = buf->b_fname; // Isolate a directory name from *dirp and put it in dir_name. // First allocate some memory to put the directory name in. const size_t dir_len = strlen(*dirp) + 1; - dir_name = xmalloc(dir_len); + char *dir_name = xmalloc(dir_len); (void)copy_option_part(dirp, dir_name, dir_len, ","); // we try different names until we find one that does not exist yet - fname = (char *)makeswapname((char_u *)buf_fname, (char_u *)buf->b_ffname, buf, - (char_u *)dir_name); + char *fname = (char *)makeswapname((char_u *)buf_fname, (char_u *)buf->b_ffname, buf, + (char_u *)dir_name); for (;;) { if (fname == NULL) { // must be out of memory @@ -3273,7 +3182,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_ } // A file name equal to old_fname is OK to use. - if (old_fname != NULL && FNAMECMP(fname, old_fname) == 0) { + if (old_fname != NULL && path_fnamecmp(fname, old_fname) == 0) { break; } @@ -3298,14 +3207,14 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_ // buffer don't compare the directory names, they can // have a different mountpoint. if (b0.b0_flags & B0_SAME_DIR) { - if (FNAMECMP(path_tail((char *)buf->b_ffname), - path_tail((char *)b0.b0_fname)) != 0 + if (path_fnamecmp(path_tail(buf->b_ffname), + path_tail((char *)b0.b0_fname)) != 0 || !same_directory((char_u *)fname, (char_u *)buf->b_ffname)) { // Symlinks may point to the same file even // when the name differs, need to check the // inode too. expand_env((char *)b0.b0_fname, NameBuff, MAXPATHL); - if (fnamecmp_ino((char_u *)buf->b_ffname, (char_u *)NameBuff, + if (fnamecmp_ino(buf->b_ffname, NameBuff, char_to_long(b0.b0_ino))) { differ = true; } @@ -3314,7 +3223,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_ // The name in the swap file may be // "~user/path/file". Expand it first. expand_env((char *)b0.b0_fname, NameBuff, MAXPATHL); - if (fnamecmp_ino((char_u *)buf->b_ffname, (char_u *)NameBuff, + if (fnamecmp_ino(buf->b_ffname, NameBuff, char_to_long(b0.b0_ino))) { differ = true; } @@ -3519,24 +3428,24 @@ static int b0_magic_wrong(ZERO_BL *b0p) /// /// @param fname_c current file name /// @param fname_s file name from swap file -static bool fnamecmp_ino(char_u *fname_c, char_u *fname_s, long ino_block0) +static bool fnamecmp_ino(char *fname_c, char *fname_s, long ino_block0) { uint64_t ino_c = 0; // ino of current file uint64_t ino_s; // ino of file from swap file - char_u buf_c[MAXPATHL]; // full path of fname_c - char_u buf_s[MAXPATHL]; // full path of fname_s + char buf_c[MAXPATHL]; // full path of fname_c + char buf_s[MAXPATHL]; // full path of fname_s int retval_c; // flag: buf_c valid int retval_s; // flag: buf_s valid FileInfo file_info; - if (os_fileinfo((char *)fname_c, &file_info)) { + if (os_fileinfo(fname_c, &file_info)) { ino_c = os_fileinfo_inode(&file_info); } // First we try to get the inode from the file name, because the inode in // the swap file may be outdated. If that fails (e.g. this path is not // valid on this machine), use the inode from block 0. - if (os_fileinfo((char *)fname_s, &file_info)) { + if (os_fileinfo(fname_s, &file_info)) { ino_s = os_fileinfo_inode(&file_info); } else { ino_s = (uint64_t)ino_block0; @@ -3548,17 +3457,17 @@ static bool fnamecmp_ino(char_u *fname_c, char_u *fname_s, long ino_block0) // One of the inode numbers is unknown, try a forced vim_FullName() and // compare the file names. - retval_c = vim_FullName((char *)fname_c, (char *)buf_c, MAXPATHL, true); - retval_s = vim_FullName((char *)fname_s, (char *)buf_s, MAXPATHL, true); + retval_c = vim_FullName(fname_c, (char *)buf_c, MAXPATHL, true); + retval_s = vim_FullName(fname_s, (char *)buf_s, MAXPATHL, true); if (retval_c == OK && retval_s == OK) { - return STRCMP(buf_c, buf_s) != 0; + return strcmp(buf_c, buf_s) != 0; } // Can't compare inodes or file names, guess that the files are different, // unless both appear not to exist at all, then compare with the file name // in the swap file. if (ino_s == 0 && ino_c == 0 && retval_c == FAIL && retval_s == FAIL) { - return STRCMP(fname_c, fname_s) != 0; + return strcmp(fname_c, fname_s) != 0; } return true; } diff --git a/src/nvim/memory.c b/src/nvim/memory.c index 03cfde6160..61c43d8f99 100644 --- a/src/nvim/memory.c +++ b/src/nvim/memory.c @@ -821,9 +821,9 @@ void free_all_mem(void) decor_free_all_mem(); - nlua_free_all_mem(); ui_free_all_mem(); ui_comp_free_all_mem(); + nlua_free_all_mem(); // should be last, in case earlier free functions deallocates arenas arena_free_reuse_blks(); diff --git a/src/nvim/menu.c b/src/nvim/menu.c index 7a08a4d6f6..57116170aa 100644 --- a/src/nvim/menu.c +++ b/src/nvim/menu.c @@ -177,7 +177,7 @@ void ex_menu(exarg_T *eap) // Change sensitivity of the menu. // For the PopUp menu, remove a menu for each mode separately. // Careful: menu_enable_recurse() changes menu_path. - if (STRCMP(menu_path, "*") == 0) { // meaning: do all menus + if (strcmp(menu_path, "*") == 0) { // meaning: do all menus menu_path = ""; } @@ -193,7 +193,7 @@ void ex_menu(exarg_T *eap) menu_enable_recurse(*root_menu_ptr, menu_path, modes, enable); } else if (unmenu) { // Delete menu(s). - if (STRCMP(menu_path, "*") == 0) { // meaning: remove all menus + if (strcmp(menu_path, "*") == 0) { // meaning: remove all menus menu_path = ""; } @@ -220,7 +220,7 @@ void ex_menu(exarg_T *eap) map_buf = NULL; // Menu tips are plain text. } else { map_buf = NULL; - map_to = replace_termcodes(map_to, STRLEN(map_to), &map_buf, + map_to = replace_termcodes(map_to, strlen(map_to), &map_buf, REPTERM_DO_LT, NULL, CPO_TO_CPO_FLAGS); } menuarg.modes = modes; @@ -286,7 +286,7 @@ static int add_menu_path(const char *const menu_path, vimmenu_T *menuarg, const // Get name of this element in the menu hierarchy, and the simplified // name (without mnemonic and accelerator text). next_name = menu_name_skip(name); - map_to = menutrans_lookup(name, (int)STRLEN(name)); + map_to = menutrans_lookup(name, (int)strlen(name)); if (map_to != NULL) { en_name = name; name = map_to; @@ -424,7 +424,7 @@ static int add_menu_path(const char *const menu_path, vimmenu_T *menuarg, const } if (c != 0) { - menu->strings[i] = xmalloc(STRLEN(call_data) + 5); + menu->strings[i] = xmalloc(strlen(call_data) + 5); menu->strings[i][0] = c; if (d == 0) { STRCPY(menu->strings[i] + 1, call_data); @@ -433,7 +433,7 @@ static int add_menu_path(const char *const menu_path, vimmenu_T *menuarg, const STRCPY(menu->strings[i] + 2, call_data); } if (c == Ctrl_C) { - int len = (int)STRLEN(menu->strings[i]); + int len = (int)strlen(menu->strings[i]); menu->strings[i][len] = Ctrl_BSL; menu->strings[i][len + 1] = Ctrl_G; @@ -685,8 +685,7 @@ static dict_T *menu_get_recursive(const vimmenu_T *menu, int modes) if ((menu->modes & modes & (1 << bit)) != 0) { dict_T *impl = tv_dict_alloc(); tv_dict_add_allocated_str(impl, S_LEN("rhs"), - str2special_save(menu->strings[bit], - false, false)); + str2special_save(menu->strings[bit], false, false)); tv_dict_add_nr(impl, S_LEN("silent"), menu->silent[bit]); tv_dict_add_nr(impl, S_LEN("enabled"), (menu->enabled & (1 << bit)) ? 1 : 0); @@ -1054,7 +1053,7 @@ char *get_menu_names(expand_T *xp, int idx) while (menu != NULL && (menu_is_hidden(menu->dname) || (expand_emenu && menu_is_separator(menu->dname)) - || menu->dname[STRLEN(menu->dname) - 1] == '.')) { + || menu->dname[strlen(menu->dname) - 1] == '.')) { menu = menu->next; } @@ -1276,7 +1275,7 @@ static char *get_menu_mode_str(int modes) // Returns the name in allocated memory. static char *popup_mode_name(char *name, int idx) { - size_t len = STRLEN(name); + size_t len = strlen(name); assert(len >= 4); char *mode_chars = menu_mode_chars[idx]; @@ -1365,7 +1364,7 @@ bool menu_is_toolbar(const char *const name) /// with '-' int menu_is_separator(char *name) { - return name[0] == '-' && name[STRLEN(name) - 1] == '-'; + return name[0] == '-' && name[strlen(name) - 1] == '-'; } /// True if a popup menu or starts with \ref MNU_HIDDEN_CHAR diff --git a/src/nvim/message.c b/src/nvim/message.c index 63012900df..0b9cbfe474 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -321,7 +321,7 @@ bool msg_attr_keep(const char *s, int attr, bool keep, bool multiline) || (*s != '<' && last_msg_hist != NULL && last_msg_hist->msg != NULL - && STRCMP(s, last_msg_hist->msg))) { + && strcmp(s, last_msg_hist->msg))) { add_msg_hist(s, -1, attr, multiline); } @@ -433,7 +433,7 @@ void trunc_string(char *s, char *buf, int room_in, int buflen) } // Last part: End of the string. - half = i = (int)STRLEN(s); + half = i = (int)strlen(s); for (;;) { do { half = half - utf_head_off(s, s + half - 1) - 1; @@ -449,7 +449,7 @@ void trunc_string(char *s, char *buf, int room_in, int buflen) if (i <= e + 3) { // text fits without truncating if (s != buf) { - len = (int)STRLEN(s); + len = (int)strlen(s); if (len >= buflen) { len = buflen - 1; } @@ -463,7 +463,7 @@ void trunc_string(char *s, char *buf, int room_in, int buflen) } else if (e + 3 < buflen) { // set the middle and copy the last part memmove(buf + e, "...", (size_t)3); - len = (int)STRLEN(s + i) + 1; + len = (int)strlen(s + i) + 1; if (len >= buflen - e - 3) { len = buflen - e - 3 - 1; } @@ -553,7 +553,7 @@ static char *get_emsg_source(void) } const char *const p = _("Error detected while processing %s:"); - const size_t buf_len = STRLEN(sname) + strlen(p) + 1; + const size_t buf_len = strlen(sname) + strlen(p) + 1; char *const buf = xmalloc(buf_len); snprintf(buf, buf_len, p, sname); xfree(tofree); @@ -596,10 +596,10 @@ void msg_source(int attr) } recursive = true; - msg_scroll = true; // this will take more than one line no_wait_return++; char *p = get_emsg_source(); if (p != NULL) { + msg_scroll = true; // this will take more than one line msg_attr(p, attr); xfree(p); } @@ -739,7 +739,7 @@ static bool emsg_multiline(const char *s, bool multiline) } // Display name and line number for the source of the error. - // Sets "msg_scroll". + msg_scroll = true; msg_source(attr); // Display the error message itself. @@ -909,7 +909,7 @@ char *msg_may_trunc(bool force, char *s) room = (Rows - cmdline_row - 1) * Columns + sc_col - 1; if ((force || (shortmess(SHM_TRUNC) && !exmode_active)) - && (int)STRLEN(s) - room > 0 && p_ch > 0) { + && (int)STRLEN(s) - room > 0) { int size = vim_strsize(s); // There may be room anyway when there are multibyte chars. @@ -936,15 +936,6 @@ void hl_msg_free(HlMessage hl_msg) kv_destroy(hl_msg); } -#define LINE_BUFFER_SIZE 4096 - -void add_hl_msg_hist(HlMessage hl_msg) -{ - if (kv_size(hl_msg)) { - add_msg_hist_multiattr(NULL, 0, 0, true, hl_msg); - } -} - /// @param[in] len Length of s or -1. static void add_msg_hist(const char *s, int len, int attr, bool multiline) { @@ -968,7 +959,7 @@ static void add_msg_hist_multiattr(const char *s, int len, int attr, bool multil struct msg_hist *p = xmalloc(sizeof(struct msg_hist)); if (s) { if (len < 0) { - len = (int)STRLEN(s); + len = (int)strlen(s); } // remove leading and trailing newlines while (len > 0 && *s == '\n') { @@ -978,7 +969,7 @@ static void add_msg_hist_multiattr(const char *s, int len, int attr, bool multil while (len > 0 && s[len - 1] == '\n') { len--; } - p->msg = (char_u *)xmemdupz(s, (size_t)len); + p->msg = xmemdupz(s, (size_t)len); } else { p->msg = NULL; } @@ -1028,7 +1019,7 @@ void ex_messages(void *const eap_p) struct msg_hist *p; int c = 0; - if (STRCMP(eap->arg, "clear") == 0) { + if (strcmp(eap->arg, "clear") == 0) { int keep = eap->addr_count == 0 ? 0 : eap->line2; while (msg_hist_len > keep) { @@ -1095,7 +1086,7 @@ void ex_messages(void *const eap_p) if (kv_size(p->multiattr)) { msg_multiattr(p->multiattr, p->kind, false); } else if (p->msg != NULL) { - msg_attr_keep((char *)p->msg, p->attr, false, p->multiline); + msg_attr_keep(p->msg, p->attr, false, p->multiline); } } msg_hist_off = false; @@ -1401,9 +1392,7 @@ void msg_start(void) need_fileinfo = false; } - const bool no_msg_area = !ui_has_messages(); - - if (need_clr_eos || (no_msg_area && redrawing_cmdline)) { + if (need_clr_eos || (p_ch == 0 && redrawing_cmdline)) { // Halfway an ":echo" command and getting an (error) message: clear // any text from the command. need_clr_eos = false; @@ -1411,12 +1400,14 @@ void msg_start(void) } if (!msg_scroll && full_screen) { // overwrite last message + if (cmdline_row >= Rows && !ui_has(kUIMessages)) { + msg_scroll_up(false, true); + msg_scrolled++; + cmdline_row = Rows - 1; + } msg_row = cmdline_row; msg_col = cmdmsg_rl ? Columns - 1 : 0; - if (no_msg_area && get_cmdprompt() == NULL) { - msg_row -= 1; - } - } else if (msg_didout || no_msg_area) { // start message on next line + } else if (msg_didout || (p_ch == 0 && !ui_has(kUIMessages))) { // start message on next line msg_putchar('\n'); did_return = true; cmdline_row = msg_row; @@ -1506,7 +1497,7 @@ int msg_outtrans(char *str) int msg_outtrans_attr(const char *str, int attr) { - return msg_outtrans_len_attr(str, (int)STRLEN(str), attr); + return msg_outtrans_len_attr(str, (int)strlen(str), attr); } int msg_outtrans_len(const char *str, int len) @@ -1588,7 +1579,7 @@ int msg_outtrans_len_attr(const char *msgstr, int len, int attr) } plain_start = str + 1; msg_puts_attr((const char *)s, attr == 0 ? HL_ATTR(HLF_8) : attr); - retval += (int)STRLEN(s); + retval += (int)strlen(s); } else { retval++; } @@ -1681,8 +1672,8 @@ int msg_outtrans_special(const char *strstart, bool from, int maxlen) /// Used for lhs or rhs of mappings. /// /// @param[in] str String to convert. -/// @param[in] replace_spaces Convert spaces into `<Space>`, normally used fo -/// lhs, but not rhs. +/// @param[in] replace_spaces Convert spaces into `<Space>`, normally used for +/// lhs of mapping and keytrans(), but not rhs. /// @param[in] replace_lt Convert `<` into `<lt>`. /// /// @return [allocated] Converted string. @@ -1704,8 +1695,8 @@ char *str2special_save(const char *const str, const bool replace_spaces, const b /// Convert character, replacing key with printable representation. /// /// @param[in,out] sp String to convert. Is advanced to the next key code. -/// @param[in] replace_spaces Convert spaces into <Space>, normally used for -/// lhs, but not rhs. +/// @param[in] replace_spaces Convert spaces into `<Space>`, normally used for +/// lhs of mapping and keytrans(), but not rhs. /// @param[in] replace_lt Convert `<` into `<lt>`. /// /// @return Converted key code, in a static buffer. Buffer is always one and the @@ -1819,7 +1810,7 @@ void msg_prt_line(char *s, int list) if (list) { // find start of trailing whitespace if (curwin->w_p_lcs_chars.trail) { - trail = s + STRLEN(s); + trail = s + strlen(s); while (trail > s && ascii_iswhite(trail[-1])) { trail--; } @@ -2003,7 +1994,7 @@ void msg_puts_title(const char *s) /// Does not handle multi-byte characters! void msg_outtrans_long_attr(char *longstr, int attr) { - msg_outtrans_long_len_attr(longstr, (int)STRLEN(longstr), attr); + msg_outtrans_long_len_attr(longstr, (int)strlen(longstr), attr); } void msg_outtrans_long_len_attr(char *longstr, int len, int attr) @@ -2062,7 +2053,7 @@ void msg_puts_attr_len(const char *const str, const ptrdiff_t len, int attr) overflow = true; } } else { - overflow = msg_scrolled != 0; + overflow = msg_scrolled > (p_ch == 0 ? 1 : 0); } if (overflow && !msg_scrolled_ign && strcmp(str, "\r") != 0) { @@ -2186,7 +2177,7 @@ static void msg_puts_display(const char *str, int maxlen, int attr, int recurse) // Scroll the screen up one line. bool has_last_char = ((uint8_t)(*s) >= ' ' && !cmdmsg_rl); - msg_scroll_up(!has_last_char); + msg_scroll_up(!has_last_char, false); msg_row = Rows - 2; if (msg_col >= Columns) { // can happen after screen resize @@ -2343,14 +2334,14 @@ bool message_filtered(char *msg) /// including horizontal separator int msg_scrollsize(void) { - return msg_scrolled + (int)p_ch + 1; + return msg_scrolled + (int)p_ch + ((p_ch > 0 || msg_scrolled > 1) ? 1 : 0); } bool msg_use_msgsep(void) { // the full-screen scroll behavior doesn't really make sense with // 'ext_multigrid' - return (dy_flags & DY_MSGSEP) || ui_has(kUIMultigrid); + return (dy_flags & DY_MSGSEP) || p_ch == 0 || ui_has(kUIMultigrid); } bool msg_do_throttle(void) @@ -2359,7 +2350,7 @@ bool msg_do_throttle(void) } /// Scroll the screen up one line for displaying the next message line. -void msg_scroll_up(bool may_throttle) +void msg_scroll_up(bool may_throttle, bool zerocmd) { if (may_throttle && msg_do_throttle()) { msg_grid.throttled = true; @@ -2367,7 +2358,13 @@ void msg_scroll_up(bool may_throttle) msg_did_scroll = true; if (msg_use_msgsep()) { if (msg_grid_pos > 0) { - msg_grid_set_pos(msg_grid_pos - 1, true); + msg_grid_set_pos(msg_grid_pos - 1, !zerocmd); + + // When displaying the first line with cmdheight=0, we need to draw over + // the existing last line of the screen. + if (zerocmd && msg_grid.chars) { + grid_clear_line(&msg_grid, msg_grid.line_offset[0], msg_grid.cols, false); + } } else { grid_del_lines(&msg_grid, 0, 1, msg_grid.rows, 0, msg_grid.cols); memmove(msg_grid.dirty_col, msg_grid.dirty_col + 1, @@ -2378,8 +2375,7 @@ void msg_scroll_up(bool may_throttle) grid_del_lines(&msg_grid_adj, 0, 1, Rows, 0, Columns); } - grid_fill(&msg_grid_adj, Rows - 1, Rows, 0, Columns, ' ', ' ', - HL_ATTR(HLF_MSG)); + grid_fill(&msg_grid_adj, Rows - 1, Rows, 0, Columns, ' ', ' ', HL_ATTR(HLF_MSG)); } /// Send throttled message output to UI clients @@ -2950,6 +2946,11 @@ static int do_more_prompt(int typed_char) } } else { // First display any text that we scrolled back. + // if p_ch=0 we need to allocate a line for "press enter" messages! + if (cmdline_row >= Rows && !ui_has(kUIMessages)) { + msg_scroll_up(true, false); + msg_scrolled++; + } while (toscroll > 0 && mp_last != NULL) { if (msg_do_throttle() && !msg_grid.throttled) { // Tricky: we redraw at one line higher than usual. Therefore @@ -2958,7 +2959,7 @@ static int do_more_prompt(int typed_char) msg_grid_scroll_discount++; } // scroll up, display line at bottom - msg_scroll_up(true); + msg_scroll_up(true, false); inc_msg_scrolled(); grid_fill(&msg_grid_adj, Rows - 2, Rows - 1, 0, Columns, ' ', ' ', HL_ATTR(HLF_MSG)); @@ -3002,7 +3003,7 @@ static int do_more_prompt(int typed_char) return retval; } -#if defined(WIN32) +#if defined(MSWIN) void mch_errmsg(char *str) { assert(str != NULL); @@ -3029,7 +3030,7 @@ void mch_msg(char *str) xfree(utf16str); } } -#endif // WIN32 +#endif // MSWIN /// Put a character on the screen at the current message position and advance /// to the next position. Only for printable ASCII! @@ -3094,7 +3095,7 @@ void repeat_message(void) /// Skip this when ":silent" was used, no need to clear for redirection. void msg_clr_eos(void) { - if (msg_silent == 0 && p_ch > 0) { + if (msg_silent == 0) { msg_clr_eos_force(); } } @@ -3116,12 +3117,10 @@ void msg_clr_eos_force(void) msg_row = msg_grid_pos; } - if (ui_has_messages()) { - grid_fill(&msg_grid_adj, msg_row, msg_row + 1, msg_startcol, msg_endcol, - ' ', ' ', HL_ATTR(HLF_MSG)); - grid_fill(&msg_grid_adj, msg_row + 1, Rows, 0, Columns, - ' ', ' ', HL_ATTR(HLF_MSG)); - } + grid_fill(&msg_grid_adj, msg_row, msg_row + 1, msg_startcol, msg_endcol, + ' ', ' ', HL_ATTR(HLF_MSG)); + grid_fill(&msg_grid_adj, msg_row + 1, Rows, 0, Columns, + ' ', ' ', HL_ATTR(HLF_MSG)); redraw_cmdline = true; // overwritten the command line if (msg_row < Rows - 1 || msg_col == (cmdmsg_rl ? Columns : 0)) { @@ -3291,7 +3290,7 @@ static void redir_write(const char *const str, const ptrdiff_t maxlen) } } - size_t len = maxlen == -1 ? STRLEN(s) : (size_t)maxlen; + size_t len = maxlen == -1 ? strlen(s) : (size_t)maxlen; if (capture_ga) { ga_concat_len(capture_ga, str, len); } @@ -3633,9 +3632,9 @@ static char *console_dialog_alloc(const char *message, char *buttons, bool has_h MB_PTR_ADV(r); } - len += (int)(STRLEN(message) + len += (int)(strlen(message) + 2 // for the NL's - + STRLEN(buttons) + + strlen(buttons) + 3); // for the ": " and NUL lenhotkey++; // for the NUL @@ -3685,7 +3684,7 @@ static void copy_hotkeys_and_msg(const char *message, char *buttons, int default *confirm_msg = '\n'; STRCPY(confirm_msg + 1, message); - char *msgp = confirm_msg + 1 + STRLEN(message); + char *msgp = confirm_msg + 1 + strlen(message); // Define first default hotkey. Keep the hotkey string NUL // terminated to avoid reading past the end. @@ -3709,7 +3708,7 @@ static void copy_hotkeys_and_msg(const char *message, char *buttons, int default *msgp++ = ' '; // '\n' -> ', ' // Advance to next hotkey and set default hotkey - hotkeys_ptr += STRLEN(hotkeys_ptr); + hotkeys_ptr += strlen(hotkeys_ptr); hotkeys_ptr[copy_char(r + 1, hotkeys_ptr, true)] = NUL; if (default_button_idx) { diff --git a/src/nvim/message.h b/src/nvim/message.h index 4dba26f958..811e621c11 100644 --- a/src/nvim/message.h +++ b/src/nvim/message.h @@ -36,7 +36,7 @@ typedef kvec_t(HlMessageChunk) HlMessage; /// Message history for `:messages` typedef struct msg_hist { struct msg_hist *next; ///< Next message. - char_u *msg; ///< Message text. + char *msg; ///< Message text. const char *kind; ///< Message kind (for msg_ext) int attr; ///< Message highlighting. bool multiline; ///< Multiline message. diff --git a/src/nvim/move.c b/src/nvim/move.c index 0e2550352d..481746881b 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -21,12 +21,15 @@ #include "nvim/diff.h" #include "nvim/drawscreen.h" #include "nvim/edit.h" +#include "nvim/eval.h" +#include "nvim/eval/typval.h" #include "nvim/fold.h" #include "nvim/getchar.h" #include "nvim/grid.h" #include "nvim/highlight.h" #include "nvim/mbyte.h" #include "nvim/memline.h" +#include "nvim/mouse.h" #include "nvim/move.h" #include "nvim/option.h" #include "nvim/plines.h" @@ -977,6 +980,62 @@ void textpos2screenpos(win_T *wp, pos_T *pos, int *rowp, int *scolp, int *ccolp, *ecolp = ecol + coloff; } +/// "screenpos({winid}, {lnum}, {col})" function +void f_screenpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + tv_dict_alloc_ret(rettv); + dict_T *dict = rettv->vval.v_dict; + + win_T *wp = find_win_by_nr_or_id(&argvars[0]); + if (wp == NULL) { + return; + } + + pos_T pos = { + .lnum = (linenr_T)tv_get_number(&argvars[1]), + .col = (colnr_T)tv_get_number(&argvars[2]) - 1, + .coladd = 0 + }; + int row = 0; + int scol = 0, ccol = 0, ecol = 0; + textpos2screenpos(wp, &pos, &row, &scol, &ccol, &ecol, false); + + tv_dict_add_nr(dict, S_LEN("row"), row); + tv_dict_add_nr(dict, S_LEN("col"), scol); + tv_dict_add_nr(dict, S_LEN("curscol"), ccol); + tv_dict_add_nr(dict, S_LEN("endcol"), ecol); +} + +/// "virtcol2col({winid}, {lnum}, {col})" function +void f_virtcol2col(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + rettv->vval.v_number = -1; + + if (tv_check_for_number_arg(argvars, 0) == FAIL + || tv_check_for_number_arg(argvars, 1) == FAIL + || tv_check_for_number_arg(argvars, 2) == FAIL) { + return; + } + + win_T *wp = find_win_by_nr_or_id(&argvars[0]); + if (wp == NULL) { + return; + } + + bool error = false; + linenr_T lnum = (linenr_T)tv_get_number_chk(&argvars[1], &error); + if (error || lnum < 0 || lnum > wp->w_buffer->b_ml.ml_line_count) { + return; + } + + int screencol = (int)tv_get_number_chk(&argvars[2], &error); + if (error || screencol < 0) { + return; + } + + rettv->vval.v_number = vcol2col(wp, lnum, screencol); +} + /// Scroll the current window down by "line_count" logical lines. "CTRL-Y" /// /// @param line_count number of lines to scroll diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c index 532e684f93..81b58764d7 100644 --- a/src/nvim/msgpack_rpc/server.c +++ b/src/nvim/msgpack_rpc/server.c @@ -94,7 +94,7 @@ char *server_address_new(const char *name) { static uint32_t count = 0; char fmt[ADDRESS_MAX_SIZE]; -#ifdef WIN32 +#ifdef MSWIN int r = snprintf(fmt, sizeof(fmt), "\\\\.\\pipe\\%s.%" PRIu64 ".%" PRIu32, name ? name : "nvim", os_get_pid(), count++); #else @@ -173,7 +173,7 @@ int server_start(const char *addr) ((SocketWatcher **)watchers.ga_data)[watchers.ga_len++] = watcher; // Update v:servername, if not set. - if (STRLEN(get_vim_var_str(VV_SEND_SERVER)) == 0) { + if (strlen(get_vim_var_str(VV_SEND_SERVER)) == 0) { set_vservername(&watchers); } diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 2fe482d8aa..95665053b3 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -1807,7 +1807,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent) return false; } jump_flags = 0; - if (STRCMP(p_mousem, "popup_setpos") == 0) { + if (strcmp(p_mousem, "popup_setpos") == 0) { // First set the cursor position before showing the popup // menu. if (VIsual_active) { @@ -2752,7 +2752,7 @@ bool add_to_showcmd(int c) STRCPY(p, "<20>"); } size_t old_len = STRLEN(showcmd_buf); - size_t extra_len = STRLEN(p); + size_t extra_len = strlen(p); size_t limit = ui_has(kUIMessages) ? SHOWCMD_BUFLEN - 1 : SHOWCMD_COLS; if (old_len + extra_len > limit) { size_t overflow = old_len + extra_len - limit; @@ -2817,7 +2817,8 @@ void pop_showcmd(void) static void display_showcmd(void) { - if (!ui_has_messages()) { + if (p_ch == 0 && !ui_has(kUIMessages)) { + // TODO(bfredl): would be nice to show in global statusline, perhaps return; } @@ -4057,7 +4058,7 @@ static void nv_colon(cmdarg_T *cap) } 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)) + (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); @@ -4164,7 +4165,7 @@ void do_nv_ident(int c1, int c2) /// 'K' normal-mode command. Get the command to lookup the keyword under the /// cursor. -static size_t nv_K_getcmd(cmdarg_T *cap, char_u *kp, bool kp_help, bool kp_ex, char **ptr_arg, +static size_t nv_K_getcmd(cmdarg_T *cap, char *kp, bool kp_help, bool kp_ex, char **ptr_arg, size_t n, char *buf, size_t buf_size) { if (kp_help) { @@ -4201,8 +4202,8 @@ static size_t nv_K_getcmd(cmdarg_T *cap, char_u *kp, bool kp_help, bool kp_ex, c // When a count is given, turn it into a range. Is this // really what we want? - bool isman = (STRCMP(kp, "man") == 0); - bool isman_s = (STRCMP(kp, "man -s") == 0); + bool isman = (strcmp(kp, "man") == 0); + bool isman_s = (strcmp(kp, "man -s") == 0); if (cap->count0 != 0 && !(isman || isman_s)) { snprintf(buf, buf_size, ".,.+%" PRId64, (int64_t)(cap->count0 - 1)); } @@ -4216,7 +4217,7 @@ static size_t nv_K_getcmd(cmdarg_T *cap, char_u *kp, bool kp_help, bool kp_ex, c } STRCAT(buf, " "); if (cap->count0 != 0 && (isman || isman_s)) { - snprintf(buf + STRLEN(buf), buf_size - STRLEN(buf), "%" PRId64, + snprintf(buf + strlen(buf), buf_size - strlen(buf), "%" PRId64, (int64_t)cap->count0); STRCAT(buf, " "); } @@ -4234,12 +4235,12 @@ static size_t nv_K_getcmd(cmdarg_T *cap, char_u *kp, bool kp_help, bool kp_ex, c static void nv_ident(cmdarg_T *cap) { char *ptr = NULL; - char_u *p; + char *p; size_t n = 0; // init for GCC int cmdchar; bool g_cmd; // "g" command bool tag_cmd = false; - char_u *aux_ptr; + char *aux_ptr; if (cap->cmdchar == 'g') { // "g*", "g#", "g]" and "gCTRL-]" cmdchar = cap->nchar; @@ -4275,14 +4276,14 @@ 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_u *kp = *curbuf->b_p_kp == NUL ? p_kp : (char_u *)curbuf->b_p_kp; // 'keywordprg' - bool kp_help = (*kp == NUL || STRCMP(kp, ":he") == 0 || STRCMP(kp, ":help") == 0); + char *kp = *curbuf->b_p_kp == NUL ? (char *)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 return; } bool kp_ex = (*kp == ':'); // 'keywordprg' is an ex command - size_t buf_size = n * 2 + 30 + STRLEN(kp); + size_t buf_size = n * 2 + 30 + strlen(kp); char *buf = xmalloc(buf_size); buf[0] = NUL; @@ -4336,45 +4337,45 @@ static void nv_ident(cmdarg_T *cap) ptr = xstrnsave(ptr, n); if (kp_ex) { // Escape the argument properly for an Ex command - p = (char_u *)vim_strsave_fnameescape((const char *)ptr, VSE_NONE); + p = vim_strsave_fnameescape((const char *)ptr, VSE_NONE); } else { // Escape the argument properly for a shell command - p = vim_strsave_shellescape((char_u *)ptr, true, true); + p = (char *)vim_strsave_shellescape((char_u *)ptr, true, true); } xfree(ptr); - char *newbuf = xrealloc(buf, STRLEN(buf) + STRLEN(p) + 1); + char *newbuf = xrealloc(buf, strlen(buf) + strlen(p) + 1); buf = newbuf; STRCAT(buf, p); xfree(p); } else { if (cmdchar == '*') { - aux_ptr = (char_u *)(p_magic ? "/.*~[^$\\" : "/^$\\"); + aux_ptr = (p_magic ? "/.*~[^$\\" : "/^$\\"); } else if (cmdchar == '#') { - aux_ptr = (char_u *)(p_magic ? "/?.*~[^$\\" : "/?^$\\"); + aux_ptr = (p_magic ? "/?.*~[^$\\" : "/?^$\\"); } else if (tag_cmd) { if (curbuf->b_help) { // ":help" handles unescaped argument - aux_ptr = (char_u *)""; + aux_ptr = ""; } else { - aux_ptr = (char_u *)"\\|\"\n["; + aux_ptr = "\\|\"\n["; } } else { - aux_ptr = (char_u *)"\\|\"\n*?["; + aux_ptr = "\\|\"\n*?["; } - p = (char_u *)buf + STRLEN(buf); + p = buf + STRLEN(buf); while (n-- > 0) { // put a backslash before \ and some others - if (vim_strchr((char *)aux_ptr, *ptr) != NULL) { + if (vim_strchr(aux_ptr, *ptr) != NULL) { *p++ = '\\'; } // When current byte is a part of multibyte character, copy all // bytes of that character. const size_t len = (size_t)(utfc_ptr2len(ptr) - 1); for (size_t i = 0; i < len && n > 0; i++, n--) { - *p++ = (char_u)(*ptr++); + *p++ = *ptr++; } - *p++ = (char_u)(*ptr++); + *p++ = *ptr++; } *p = NUL; } @@ -4426,7 +4427,7 @@ bool get_visual_text(cmdarg_T *cap, char **pp, size_t *lenp) } if (VIsual_mode == 'V') { *pp = get_cursor_line_ptr(); - *lenp = STRLEN(*pp); + *lenp = strlen(*pp); } else { if (lt(curwin->w_cursor, VIsual)) { *pp = (char *)ml_get_pos(&curwin->w_cursor); @@ -6151,7 +6152,7 @@ static void nv_gi_cmd(cmdarg_T *cap) if (curbuf->b_last_insert.mark.lnum != 0) { curwin->w_cursor = curbuf->b_last_insert.mark; check_cursor_lnum(); - int i = (int)STRLEN(get_cursor_line_ptr()); + int i = (int)strlen(get_cursor_line_ptr()); if (curwin->w_cursor.col > (colnr_T)i) { if (virtual_active()) { curwin->w_cursor.coladd += curwin->w_cursor.col - i; @@ -6834,7 +6835,7 @@ bool unadjust_for_sel(void) mark_mb_adjustpos(curbuf, pp); } else if (pp->lnum > 1) { pp->lnum--; - pp->col = (colnr_T)STRLEN(ml_get(pp->lnum)); + pp->col = (colnr_T)strlen(ml_get(pp->lnum)); return true; } } @@ -6971,7 +6972,7 @@ void set_cursor_for_append_to_line(void) coladvance(MAXCOL); State = save_State; } else { - curwin->w_cursor.col += (colnr_T)STRLEN(get_cursor_pos_ptr()); + curwin->w_cursor.col += (colnr_T)strlen(get_cursor_pos_ptr()); } } diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 10e957287e..6391644f83 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -896,7 +896,6 @@ int do_record(int c) { char_u *p; static int regname; - static bool changed_cmdheight = false; yankreg_T *old_y_previous; int retval; @@ -907,18 +906,11 @@ int do_record(int c) retval = FAIL; } else { reg_recording = c; + // TODO(bfredl): showmode based messaging is currently missing with cmdheight=0 showmode(); regname = c; retval = OK; - if (!ui_has_messages()) { - // Enable macro indicator temporarily - set_option_value("ch", 1L, NULL, 0); - update_screen(UPD_VALID); - - changed_cmdheight = true; - } - apply_autocmds(EVENT_RECORDINGENTER, NULL, NULL, false, curbuf); } } else { // stop recording @@ -948,7 +940,7 @@ int do_record(int c) restore_v_event(dict, &save_v_event); reg_recorded = reg_recording; reg_recording = 0; - if (ui_has(kUIMessages)) { + if (p_ch == 0 || ui_has(kUIMessages)) { showmode(); } else { msg(""); @@ -964,12 +956,6 @@ int do_record(int c) y_previous = old_y_previous; } - - if (changed_cmdheight) { - // Restore cmdheight - set_option_value("ch", 0L, NULL, 0); - redraw_all_later(UPD_CLEAR); - } } return retval; } @@ -1975,6 +1961,8 @@ static int op_replace(oparg_T *oap, int c) // TODO(bfredl): we could batch all the splicing // done on the same line, at least while (ltoreq(curwin->w_cursor, oap->end)) { + bool done = false; + n = gchar_cursor(); if (n != NUL) { int new_byte_len = utf_char2len(c); @@ -1987,6 +1975,7 @@ static int op_replace(oparg_T *oap, int c) oap->end.col += new_byte_len - old_byte_len; } replace_character(c); + done = true; } else { if (n == TAB) { int end_vcol = 0; @@ -2002,9 +1991,14 @@ static int op_replace(oparg_T *oap, int c) getvpos(&oap->end, end_vcol); } } - pbyte(curwin->w_cursor, c); + // with "coladd" set may move to just after a TAB + if (gchar_cursor() != NUL) { + pbyte(curwin->w_cursor, c); + done = true; + } } - } else if (virtual_op && curwin->w_cursor.lnum == oap->end.lnum) { + } + if (!done && virtual_op && curwin->w_cursor.lnum == oap->end.lnum) { int virtcols = oap->end.coladd; if (curwin->w_cursor.lnum == oap->start.lnum @@ -2260,7 +2254,7 @@ void op_insert(oparg_T *oap, long count1) if (oap->op_type == OP_APPEND) { firstline += bd.textlen; } - pre_textlen = (long)STRLEN(firstline); + pre_textlen = (long)strlen(firstline); } if (oap->op_type == OP_APPEND) { @@ -2386,7 +2380,7 @@ void op_insert(oparg_T *oap, long count1) // Subsequent calls to ml_get() flush the firstline data - take a // copy of the required string. firstline = ml_get(oap->start.lnum); - const size_t len = STRLEN(firstline); + const size_t len = strlen(firstline); colnr_T add = bd.textcol; colnr_T offset = 0; // offset when cursor was moved in insert mode if (oap->op_type == OP_APPEND) { @@ -2408,7 +2402,7 @@ void op_insert(oparg_T *oap, long count1) } else { firstline += add; } - ins_len = (long)STRLEN(firstline) - pre_textlen - offset; + ins_len = (long)strlen(firstline) - pre_textlen - offset; if (pre_textlen >= 0 && ins_len > 0) { ins_text = xstrnsave(firstline, (size_t)ins_len); // block handled here @@ -2992,7 +2986,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) // curwin->w_cursor.col marks the byte position of the cursor in the // currunt line. It increases up to a max of - // STRLEN(ml_get(curwin->w_cursor.lnum)). With 'virtualedit' and the + // strlen(ml_get(curwin->w_cursor.lnum)). With 'virtualedit' and the // cursor past the end of the line, curwin->w_cursor.coladd is // incremented instead of curwin->w_cursor.col. char_u *cursor_pos = (char_u *)get_cursor_pos_ptr(); @@ -3174,7 +3168,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) goto end; } - yanklen = (int)STRLEN(y_array[0]); + yanklen = (int)strlen(y_array[0]); if (cur_ve_flags == VE_ALL && y_type == kMTCharWise) { if (gchar_cursor() == TAB) { @@ -3259,7 +3253,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) } // get the old line and advance to the position to insert at oldp = get_cursor_line_ptr(); - oldlen = STRLEN(oldp); + oldlen = strlen(oldp); chartabsize_T cts; init_chartabsize_arg(&cts, curwin, curwin->w_cursor.lnum, 0, oldp, oldp); @@ -3292,7 +3286,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) } } - yanklen = (int)STRLEN(y_array[i]); + yanklen = (int)strlen(y_array[i]); if ((flags & PUT_BLOCK_INNER) == 0) { // calculate number of spaces required to fill right side of @@ -3380,7 +3374,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) curwin->w_cursor.col++; // in Insert mode we might be after the NUL, correct for that - len = (colnr_T)STRLEN(get_cursor_line_ptr()); + len = (colnr_T)strlen(get_cursor_line_ptr()); if (curwin->w_cursor.col > len) { curwin->w_cursor.col = len; } @@ -3444,7 +3438,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) totlen = (size_t)(count * yanklen); do { oldp = ml_get(lnum); - oldlen = STRLEN(oldp); + oldlen = strlen(oldp); if (lnum > start_lnum) { pos_T pos = { .lnum = lnum, @@ -3515,8 +3509,8 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) // Then append y_array[0] to first line. lnum = new_cursor.lnum; ptr = ml_get(lnum) + col; - totlen = STRLEN(y_array[y_size - 1]); - newp = xmalloc((size_t)(STRLEN(ptr) + totlen + 1)); + totlen = strlen(y_array[y_size - 1]); + newp = xmalloc((size_t)(strlen(ptr) + totlen + 1)); STRCPY(newp, y_array[y_size - 1]); STRCAT(newp, ptr); // insert second line @@ -3550,7 +3544,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) curwin->w_cursor.lnum = lnum; ptr = ml_get(lnum); if (cnt == count && i == y_size - 1) { - lendiff = (int)STRLEN(ptr); + lendiff = (int)strlen(ptr); } if (*ptr == '#' && preprocs_left()) { indent = 0; // Leave # lines at start @@ -3567,7 +3561,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) curwin->w_cursor = old_pos; // remember how many chars were removed if (cnt == count && i == y_size - 1) { - lendiff -= (int)STRLEN(ml_get(lnum)); + lendiff -= (int)strlen(ml_get(lnum)); } } } @@ -3577,9 +3571,9 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) if (y_type == kMTCharWise || (y_type == kMTLineWise && flags & PUT_LINE_SPLIT)) { for (i = 0; i < y_size - 1; i++) { - totsize += (bcount_t)STRLEN(y_array[i]) + 1; + totsize += (bcount_t)strlen(y_array[i]) + 1; } - lastsize = (int)STRLEN(y_array[y_size - 1]); + lastsize = (int)strlen(y_array[y_size - 1]); totsize += lastsize; } if (y_type == kMTCharWise) { @@ -3623,7 +3617,7 @@ error: // Put the '] mark on the first byte of the last inserted character. // Correct the length for change in indent. curbuf->b_op_end.lnum = new_lnum; - len = STRLEN(y_array[y_size - 1]); + len = strlen(y_array[y_size - 1]); col = (colnr_T)len - lendiff; if (col > 1) { curbuf->b_op_end.col = col - 1; @@ -4019,7 +4013,7 @@ int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions if (t == 0 && setmark && (cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) { // Set the '[ mark. curwin->w_buffer->b_op_start.lnum = curwin->w_cursor.lnum; - curwin->w_buffer->b_op_start.col = (colnr_T)STRLEN(curr); + curwin->w_buffer->b_op_start.col = (colnr_T)strlen(curr); } if (remove_comments) { // We don't want to remove the comment leader if the @@ -4065,7 +4059,7 @@ int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions 0, spaces[t], spaces[t], kExtmarkUndo); } - currsize = (int)STRLEN(curr); + currsize = (int)strlen(curr); sumsize += currsize + spaces[t]; endcurr1 = endcurr2 = NUL; if (insert_space && currsize > 0) { @@ -4130,7 +4124,7 @@ int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions if (insert_space && t > 1) { curr = skipwhite(curr); } - currsize = (int)STRLEN(curr); + currsize = (int)strlen(curr); } ml_replace(curwin->w_cursor.lnum, newp, false); @@ -4362,20 +4356,20 @@ void op_addsub(oparg_T *oap, linenr_T Prenum1, bool g_cmd) } else if (oap->motion_type == kMTLineWise) { curwin->w_cursor.col = 0; pos.col = 0; - length = (colnr_T)STRLEN(ml_get(pos.lnum)); + length = (colnr_T)strlen(ml_get(pos.lnum)); } else { // oap->motion_type == kMTCharWise if (pos.lnum == oap->start.lnum && !oap->inclusive) { dec(&(oap->end)); } - length = (colnr_T)STRLEN(ml_get(pos.lnum)); + length = (colnr_T)strlen(ml_get(pos.lnum)); pos.col = 0; if (pos.lnum == oap->start.lnum) { pos.col += oap->start.col; length -= oap->start.col; } if (pos.lnum == oap->end.lnum) { - length = (int)STRLEN(ml_get(oap->end.lnum)); + length = (int)strlen(ml_get(oap->end.lnum)); if (oap->end.col >= length) { oap->end.col = length - 1; } @@ -4923,7 +4917,7 @@ void *get_reg_contents(int regname, int flags) // Compute length of resulting string. size_t len = 0; for (size_t i = 0; i < reg->y_size; i++) { - len += STRLEN(reg->y_array[i]); + len += strlen(reg->y_array[i]); // Insert a newline between lines and after last line if // y_type is kMTLineWise. if (reg->y_type == kMTLineWise || i < reg->y_size - 1) { @@ -4937,7 +4931,7 @@ void *get_reg_contents(int regname, int flags) len = 0; for (size_t i = 0; i < reg->y_size; i++) { STRCPY(retval + len, reg->y_array[i]); - len += STRLEN(retval + len); + len += strlen(retval + len); // Insert a NL between lines and after the last line if y_type is // kMTLineWise. @@ -5039,7 +5033,7 @@ void write_reg_contents_ex(int name, const char *str, ssize_t len, bool must_app MotionType yank_type, colnr_T block_len) { if (len < 0) { - len = (ssize_t)STRLEN(str); + len = (ssize_t)strlen(str); } // Special case: '/' search pattern @@ -5059,7 +5053,7 @@ void write_reg_contents_ex(int name, const char *str, ssize_t len, bool must_app semsg(_(e_nobufnr), (int64_t)num); } } else { - buf = buflist_findnr(buflist_findpat(str, str + STRLEN(str), + buf = buflist_findnr(buflist_findpat(str, str + strlen(str), true, false, false)); } if (buf == NULL) { @@ -5186,7 +5180,7 @@ static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type, const char *str, } // When appending, copy the previous line and free it after. - size_t extra = append ? STRLEN(pp[--lnum]) : 0; + size_t extra = append ? strlen(pp[--lnum]) : 0; char *s = xmallocz(line_len + extra); if (extra > 0) { memcpy(s, pp[lnum], extra); @@ -5486,7 +5480,7 @@ void cursor_pos_info(dict_T *dict) bom_count = bomb_size(); if (dict == NULL && bom_count > 0) { - const size_t len = STRLEN(IObuff); + const size_t len = strlen(IObuff); vim_snprintf((char *)IObuff + len, IOSIZE - len, _("(+%" PRId64 " for BOM)"), (int64_t)bom_count); } @@ -5845,10 +5839,10 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) if (lt(VIsual, curwin->w_cursor)) { VIsual.col = 0; curwin->w_cursor.col = - (colnr_T)STRLEN(ml_get(curwin->w_cursor.lnum)); + (colnr_T)strlen(ml_get(curwin->w_cursor.lnum)); } else { curwin->w_cursor.col = 0; - VIsual.col = (colnr_T)STRLEN(ml_get(VIsual.lnum)); + VIsual.col = (colnr_T)strlen(ml_get(VIsual.lnum)); } VIsual_mode = 'v'; } else if (VIsual_mode == 'v') { @@ -5878,7 +5872,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) || oap->motion_type == kMTLineWise) && hasFolding(curwin->w_cursor.lnum, NULL, &curwin->w_cursor.lnum)) { - curwin->w_cursor.col = (colnr_T)STRLEN(get_cursor_line_ptr()); + curwin->w_cursor.col = (colnr_T)strlen(get_cursor_line_ptr()); } } oap->end = curwin->w_cursor; @@ -5896,7 +5890,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) curwin->w_cursor.col = 0; } if (hasFolding(oap->start.lnum, NULL, &oap->start.lnum)) { - oap->start.col = (colnr_T)STRLEN(ml_get(oap->start.lnum)); + oap->start.col = (colnr_T)strlen(ml_get(oap->start.lnum)); } } oap->end = oap->start; @@ -6080,7 +6074,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) if (inindent(0)) { oap->motion_type = kMTLineWise; } else { - oap->end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum)); + oap->end.col = (colnr_T)strlen(ml_get(oap->end.lnum)); if (oap->end.col) { oap->end.col--; oap->inclusive = true; @@ -6474,7 +6468,7 @@ bool prepare_yankreg_from_object(yankreg_T *reg, String regtype, size_t lines) void finish_yankreg_from_object(yankreg_T *reg, bool clipboard_adjust) { - if (reg->y_size > 0 && STRLEN(reg->y_array[reg->y_size - 1]) == 0) { + if (reg->y_size > 0 && strlen(reg->y_array[reg->y_size - 1]) == 0) { // a known-to-be charwise yank might have a final linebreak // but otherwise there is no line after the final newline if (reg->y_type != kMTCharWise) { @@ -6495,7 +6489,7 @@ void finish_yankreg_from_object(yankreg_T *reg, bool clipboard_adjust) if (reg->y_type == kMTBlockWise) { size_t maxlen = 0; for (size_t i = 0; i < reg->y_size; i++) { - size_t rowlen = STRLEN(reg->y_array[i]); + size_t rowlen = strlen(reg->y_array[i]); if (rowlen > maxlen) { maxlen = rowlen; } @@ -6582,7 +6576,7 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet) reg->y_array[tv_idx++] = xstrdupnul((const char *)TV_LIST_ITEM_TV(li)->vval.v_string); }); - if (reg->y_size > 0 && STRLEN(reg->y_array[reg->y_size - 1]) == 0) { + if (reg->y_size > 0 && strlen(reg->y_array[reg->y_size - 1]) == 0) { // a known-to-be charwise yank might have a final linebreak // but otherwise there is no line after the final newline if (reg->y_type != kMTCharWise) { @@ -6601,7 +6595,7 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet) if (reg->y_type == kMTBlockWise) { size_t maxlen = 0; for (size_t i = 0; i < reg->y_size; i++) { - size_t rowlen = STRLEN(reg->y_array[i]); + size_t rowlen = strlen(reg->y_array[i]); if (rowlen > maxlen) { maxlen = rowlen; } @@ -6851,13 +6845,13 @@ bcount_t get_region_bytecount(buf_T *buf, linenr_T start_lnum, linenr_T end_lnum return end_col - start_col; } const char *first = (const char *)ml_get_buf(buf, start_lnum, false); - bcount_t deleted_bytes = (bcount_t)STRLEN(first) - start_col + 1; + bcount_t deleted_bytes = (bcount_t)strlen(first) - start_col + 1; for (linenr_T i = 1; i <= end_lnum - start_lnum - 1; i++) { if (start_lnum + i > max_lnum) { return deleted_bytes; } - deleted_bytes += (bcount_t)STRLEN(ml_get_buf(buf, start_lnum + i, false)) + 1; + deleted_bytes += (bcount_t)strlen(ml_get_buf(buf, start_lnum + i, false)) + 1; } if (end_lnum > max_lnum) { return deleted_bytes; diff --git a/src/nvim/option.c b/src/nvim/option.c index e54e6080f0..2a45f3b38b 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -83,7 +83,7 @@ #include "nvim/undo.h" #include "nvim/vim.h" #include "nvim/window.h" -#ifdef WIN32 +#ifdef MSWIN # include "nvim/os/pty_conpty_win.h" #endif #include "nvim/api/extmark.h" @@ -156,7 +156,7 @@ typedef struct vimoption { // buffer-local option: global value idopt_T indir; // global option: PV_NONE; // local option: indirect option index - char_u *def_val; // default values for variable (neovim!!) + char *def_val; // default values for variable (neovim!!) LastSet last_set; // script in which the option was last set } vimoption_T; @@ -173,6 +173,13 @@ typedef struct vimoption { #define OPTION_COUNT ARRAY_SIZE(options) +typedef enum { + OP_NONE = 0, + OP_ADDING, ///< "opt+=arg" + OP_PREPENDING, ///< "opt^=arg" + OP_REMOVING, ///< "opt-=arg" +} set_op_T; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "option.c.generated.h" #endif @@ -290,7 +297,7 @@ void set_init_1(bool clean_arg) buf[j] = NUL; opt_idx = findoption("cdpath"); if (opt_idx >= 0) { - options[opt_idx].def_val = buf; + options[opt_idx].def_val = (char *)buf; options[opt_idx].flags |= P_DEF_ALLOCED; } else { xfree(buf); // cannot happen @@ -384,7 +391,7 @@ void set_init_1(bool clean_arg) && options[opt_idx].var != NULL) { p = _(*(char **)options[opt_idx].var); } else { - p = (char *)option_expand(opt_idx, NULL); + p = option_expand(opt_idx, NULL); } if (p != NULL) { p = xstrdup(p); @@ -392,7 +399,7 @@ void set_init_1(bool clean_arg) if (options[opt_idx].flags & P_DEF_ALLOCED) { xfree(options[opt_idx].def_val); } - options[opt_idx].def_val = (char_u *)p; + options[opt_idx].def_val = p; options[opt_idx].flags |= P_DEF_ALLOCED; } } @@ -449,12 +456,12 @@ static void set_option_default(int opt_idx, int opt_flags) // freeing and allocating the value. if (options[opt_idx].indir != PV_NONE) { set_string_option_direct(NULL, opt_idx, - (char *)options[opt_idx].def_val, opt_flags, 0); + options[opt_idx].def_val, opt_flags, 0); } else { if ((opt_flags & OPT_FREE) && (flags & P_ALLOCED)) { free_string_option(*(char **)(varp)); } - *(char_u **)varp = options[opt_idx].def_val; + *(char **)varp = options[opt_idx].def_val; options[opt_idx].flags &= ~P_ALLOCED; } } else if (flags & P_NUM) { @@ -533,9 +540,7 @@ static void set_string_default(const char *name, char *val, bool allocated) xfree(options[opt_idx].def_val); } - options[opt_idx].def_val = allocated - ? (char_u *)val - : (char_u *)xstrdup(val); + options[opt_idx].def_val = allocated ? val : xstrdup(val); options[opt_idx].flags |= P_DEF_ALLOCED; } } @@ -579,7 +584,7 @@ void set_number_default(char *name, long val) opt_idx = findoption(name); if (opt_idx >= 0) { - options[opt_idx].def_val = (char_u *)(intptr_t)val; + options[opt_idx].def_val = (char *)(intptr_t)val; } } @@ -594,7 +599,7 @@ void free_all_options(void) free_string_option(*(char **)options[i].var); } if (options[i].flags & P_DEF_ALLOCED) { - free_string_option((char *)options[i].def_val); + free_string_option(options[i].def_val); } } else if (options[i].var != VAR_WIN && (options[i].flags & P_STRING)) { // buffer-local option: free global value @@ -648,7 +653,7 @@ void set_init_3(void) : !(options[idx_sp].flags & P_WAS_SET); size_t len = 0; - char *p = (char *)invocation_path_tail(p_sh, &len); + char *p = (char *)invocation_path_tail((char_u *)p_sh, &len); p = xstrnsave(p, len); { @@ -656,34 +661,34 @@ void set_init_3(void) // Default for p_sp is "| tee", for p_srr is ">". // For known shells it is changed here to include stderr. // - if (FNAMECMP(p, "csh") == 0 - || FNAMECMP(p, "tcsh") == 0) { + if (path_fnamecmp(p, "csh") == 0 + || path_fnamecmp(p, "tcsh") == 0) { if (do_sp) { p_sp = "|& tee"; - options[idx_sp].def_val = (char_u *)p_sp; + options[idx_sp].def_val = p_sp; } if (do_srr) { p_srr = ">&"; - options[idx_srr].def_val = (char_u *)p_srr; + options[idx_srr].def_val = p_srr; } - } else if (FNAMECMP(p, "sh") == 0 - || FNAMECMP(p, "ksh") == 0 - || FNAMECMP(p, "mksh") == 0 - || FNAMECMP(p, "pdksh") == 0 - || FNAMECMP(p, "zsh") == 0 - || FNAMECMP(p, "zsh-beta") == 0 - || FNAMECMP(p, "bash") == 0 - || FNAMECMP(p, "fish") == 0 - || FNAMECMP(p, "ash") == 0 - || FNAMECMP(p, "dash") == 0) { + } else if (path_fnamecmp(p, "sh") == 0 + || path_fnamecmp(p, "ksh") == 0 + || path_fnamecmp(p, "mksh") == 0 + || path_fnamecmp(p, "pdksh") == 0 + || path_fnamecmp(p, "zsh") == 0 + || path_fnamecmp(p, "zsh-beta") == 0 + || path_fnamecmp(p, "bash") == 0 + || path_fnamecmp(p, "fish") == 0 + || path_fnamecmp(p, "ash") == 0 + || path_fnamecmp(p, "dash") == 0) { // Always use POSIX shell style redirection if we reach this if (do_sp) { p_sp = "2>&1| tee"; - options[idx_sp].def_val = (char_u *)p_sp; + options[idx_sp].def_val = p_sp; } if (do_srr) { p_srr = ">%s 2>&1"; - options[idx_srr].def_val = (char_u *)p_srr; + options[idx_srr].def_val = p_srr; } } xfree(p); @@ -747,12 +752,12 @@ void set_title_defaults(void) // not need to be contacted. idx1 = findoption("title"); if (idx1 >= 0 && !(options[idx1].flags & P_WAS_SET)) { - options[idx1].def_val = (char_u *)(intptr_t)0; + options[idx1].def_val = 0; p_title = 0; } idx1 = findoption("icon"); if (idx1 >= 0 && !(options[idx1].flags & P_WAS_SET)) { - options[idx1].def_val = (char_u *)(intptr_t)0; + options[idx1].def_val = 0; p_icon = 0; } } @@ -772,6 +777,349 @@ void ex_set(exarg_T *eap) (void)do_set(eap->arg, flags); } +/// 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 **arg, int nextchar, set_op_T op_arg, + uint32_t flags, char *varp_arg, char *errbuf, size_t errbuflen, + int *value_checked, char **errmsg) +{ + set_op_T op = op_arg; + char *varp = varp_arg; + char *save_arg = NULL; + char *s = NULL; + char_u *oldval = NULL; // previous value if *varp + char *newval; + char_u *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; + unsigned newlen; + int comma; + char whichwrap[80]; + + // When using ":set opt=val" for a global option + // with a local value the local value will be + // reset, use the global value here. + if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0 + && ((int)options[opt_idx].indir & PV_BOTH)) { + varp = (char *)options[opt_idx].var; + } + + // The old value is kept until we are sure that the new value is valid. + oldval = *(char_u **)varp; + + if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) { + origval_l = *(char_u **)get_varp_scope(&(options[opt_idx]), OPT_LOCAL); + origval_g = *(char_u **)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL); + + // A global-local string option might have an empty option as value to + // indicate that the global value should be used. + if (((int)options[opt_idx].indir & PV_BOTH) && origval_l == (char_u *)empty_option) { + origval_l = origval_g; + } + } + + // 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)) { + origval = *(char_u **)get_varp(&options[opt_idx]); + } else { + origval = oldval; + } + + if (nextchar == '&') { // set to default val + newval = options[opt_idx].def_val; + // expand environment variables and ~ since the default value was + // already expanded, only required when an environment variable was set + // later + if (newval == NULL) { + newval = empty_option; + } else if (!(options[opt_idx].flags & P_NO_DEF_EXP)) { + s = option_expand(opt_idx, newval); + if (s == NULL) { + s = newval; + } + newval = xstrdup(s); + } else { + newval = xstrdup(newval); + } + } else if (nextchar == '<') { // set to global val + newval = xstrdup(*(char **)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL)); + } else { + (*arg)++; // jump to after the '=' or ':' + + // Set 'keywordprg' to ":help" if an empty + // value was passed to :set by the user. + // Misuse errbuf[] for the resulting string. + if (varp == (char *)&p_kp && (**arg == NUL || **arg == ' ')) { + STRCPY(errbuf, ":help"); + save_arg = *arg; + *arg = errbuf; + } 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_u **)varp; + } + if (origval_l == oldval) { + origval_l = *(char_u **)varp; + } + if (origval_g == oldval) { + origval_g = *(char_u **)varp; + } + oldval = *(char_u **)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)++; + } + + // Copy the new string into allocated memory. + // Can't use set_string_option_direct(), because we need to remove the + // backslashes. + + // get a bit too much + newlen = (unsigned)strlen(*arg) + 1; + if (op != OP_NONE) { + newlen += (unsigned)STRLEN(origval) + 1; + } + newval = xmalloc(newlen); + s = newval; + + // Copy the string, skip over escaped chars. + // For MS-Windows backslashes before normal file name characters + // are not removed, and keep backslash at start, for "\\machine\path", + // but do remove it for "\\\\machine\\path". + // The reverse is found in ExpandOldSetting(). + while (**arg && !ascii_iswhite(**arg)) { + if (**arg == '\\' && (*arg)[1] != NUL +#ifdef BACKSLASH_IN_FILENAME + && !((flags & P_EXPAND) + && vim_isfilec((*arg)[1]) + && !ascii_iswhite((*arg)[1]) + && ((*arg)[1] != '\\' + || (s == newval && (*arg)[2] != '\\'))) +#endif + ) { + (*arg)++; // remove backslash + } + int i = utfc_ptr2len(*arg); + if (i > 1) { + // copy multibyte char + memmove(s, *arg, (size_t)i); + *arg += i; + s += i; + } else { + *s++ = *(*arg)++; + } + } + *s = NUL; + + // Expand environment variables and ~. + // Don't do it when adding without inserting a comma. + if (op == OP_NONE || (flags & P_COMMA)) { + s = option_expand(opt_idx, newval); + if (s != NULL) { + xfree(newval); + newlen = (unsigned)strlen(s) + 1; + if (op != OP_NONE) { + newlen += (unsigned)STRLEN(origval) + 1; + } + newval = xmalloc(newlen); + STRCPY(newval, s); + } + } + + // locate newval[] in origval[] when removing it + // and when adding to avoid duplicates + int len = 0; + if (op == OP_REMOVING || (flags & P_NODUP)) { + len = (int)STRLEN(newval); + s = (char *)find_dup_item(origval, (char_u *)newval, flags); + + // do not add if already there + if ((op == OP_ADDING || op == OP_PREPENDING) && s != NULL) { + op = OP_NONE; + STRCPY(newval, origval); + } + + // if no duplicate, move pointer to end of original value + if (s == NULL) { + s = (char *)origval + (int)STRLEN(origval); + } + } + + // concatenate the two strings; add a ',' if needed + if (op == OP_ADDING || op == OP_PREPENDING) { + comma = ((flags & P_COMMA) && *origval != NUL && *newval != NUL); + if (op == OP_ADDING) { + len = (int)STRLEN(origval); + // Strip a trailing comma, would get 2. + if (comma && len > 1 + && (flags & P_ONECOMMA) == P_ONECOMMA + && origval[len - 1] == ',' + && origval[len - 2] != '\\') { + len--; + } + memmove(newval + len + comma, newval, strlen(newval) + 1); + memmove(newval, origval, (size_t)len); + } else { + len = (int)strlen(newval); + STRMOVE(newval + len + comma, origval); + } + if (comma) { + newval[len] = ','; + } + } + + // Remove newval[] from origval[]. (Note: "len" has been set above and + // is used here). + if (op == OP_REMOVING) { + STRCPY(newval, origval); + if (*s) { + // may need to remove a comma + if (flags & P_COMMA) { + if (s == (char *)origval) { + // include comma after string + if (s[len] == ',') { + len++; + } + } else { + // include comma before string + s--; + len++; + } + } + STRMOVE(newval + (s - (char *)origval), s + len); + } + } + + if (flags & P_FLAGLIST) { + // Remove flags that appear twice. + for (s = newval; *s;) { + // if options have P_FLAGLIST and P_ONECOMMA such as + // 'whichwrap' + if (flags & P_ONECOMMA) { + if (*s != ',' && *(s + 1) == ',' + && vim_strchr(s + 2, *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) { + STRMOVE(s, s + 1); + continue; + } + } + s++; + } + } + + if (save_arg != NULL) { // number for 'whichwrap' + *arg = save_arg; + } + } + + // Set the new value. + *(char_u **)(varp) = (char_u *)newval; + + // origval may be freed by did_set_string_option(), make a copy. + saved_origval = (origval != NULL) ? xstrdup((char *)origval) : NULL; + saved_origval_l = (origval_l != NULL) ? xstrdup((char *)origval_l) : NULL; + 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; + + { + uint32_t *p = insecure_flag(curwin, opt_idx, opt_flags); + const int secure_saved = secure; + + // When an option is set in the sandbox, from a modeline or in secure + // mode, then deal with side effects in secure mode. Also when the + // value was set with the P_INSECURE flag and is not completely + // replaced. + if ((opt_flags & OPT_MODELINE) + || sandbox != 0 + || (op != OP_NONE && (*p & P_INSECURE))) { + secure = 1; + } + + // Handle side effects, and set the global value for ":set" on local + // options. Note: when setting 'syntax' or 'filetype' autocommands may + // be triggered that can cause havoc. + *errmsg = did_set_string_option(opt_idx, (char **)varp, (char *)oldval, + errbuf, errbuflen, + opt_flags, value_checked); + + secure = secure_saved; + } + + if (*errmsg == NULL) { + if (!starting) { + trigger_optionsset_string(opt_idx, opt_flags, saved_origval, saved_origval_l, + saved_origval_g, saved_newval); + } + if (options[opt_idx].flags & P_UI_OPTION) { + ui_call_option_set(cstr_as_string(options[opt_idx].fullname), + STRING_OBJ(cstr_as_string(saved_newval))); + } + } + xfree(saved_origval); + xfree(saved_origval_l); + xfree(saved_origval_g); + xfree(saved_newval); + + return *errmsg == NULL ? OK : FAIL; +} + /// Parse 'arg' for option settings. /// /// 'arg' may be IObuff, but only when no errors can be present and option @@ -803,9 +1151,7 @@ int do_set(char *arg, int opt_flags) uint32_t flags; // flags for current option char *varp = NULL; // pointer to variable for current option int did_show = false; // already showed one value - int adding; // "opt+=arg" - int prepending; // "opt^=arg" - int removing; // "opt-=arg" + set_op_T op = 0; if (*arg == NUL) { showoptions(0, opt_flags); @@ -892,18 +1238,16 @@ int do_set(char *arg, int opt_flags) len++; } - adding = false; - prepending = false; - removing = false; + op = OP_NONE; if (arg[len] != NUL && arg[len + 1] == '=') { if (arg[len] == '+') { - adding = true; // "+=" + op = OP_ADDING; // "+=" len++; } else if (arg[len] == '^') { - prepending = true; // "^=" + op = OP_PREPENDING; // "^=" len++; } else if (arg[len] == '-') { - removing = true; // "-=" + op = OP_REMOVING; // "-=" len++; } } @@ -1026,7 +1370,6 @@ int do_set(char *arg, int opt_flags) errmsg = e_trailing; } } else { - int value_is_replaced = !prepending && !adding && !removing; int value_checked = false; if (flags & P_BOOL) { // boolean @@ -1115,368 +1458,26 @@ int do_set(char *arg, int opt_flags) goto skip; } - if (adding) { + if (op == OP_ADDING) { value = *(long *)varp + value; } - if (prepending) { + if (op == OP_PREPENDING) { value = *(long *)varp * value; } - if (removing) { + 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. - char_u *save_arg = NULL; - char *s = NULL; - char_u *oldval = NULL; // previous value if *varp - char *newval; - char_u *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; - unsigned newlen; - int comma; - - // When using ":set opt=val" for a global option - // with a local value the local value will be - // reset, use the global value here. - if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0 - && ((int)options[opt_idx].indir & PV_BOTH)) { - varp = (char *)options[opt_idx].var; - } - - // The old value is kept until we are sure that the - // new value is valid. - oldval = *(char_u **)varp; - - if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) { - origval_l = *(char_u **)get_varp_scope(&(options[opt_idx]), OPT_LOCAL); - origval_g = *(char_u **)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL); - - // A global-local string option might have an empty - // option as value to indicate that the global - // value should be used. - if (((int)options[opt_idx].indir & PV_BOTH) && origval_l == (char_u *)empty_option) { - origval_l = origval_g; - } - } - - // 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)) { - origval = *(char_u **)get_varp(&options[opt_idx]); - } else { - origval = oldval; - } - - if (nextchar == '&') { // set to default val - newval = (char *)options[opt_idx].def_val; - // expand environment variables and ~ since the - // default value was already expanded, only - // required when an environment variable was set - // later - if (newval == NULL) { - newval = empty_option; - } else if (!(options[opt_idx].flags & P_NO_DEF_EXP)) { - s = (char *)option_expand(opt_idx, (char_u *)newval); - if (s == NULL) { - s = newval; - } - newval = xstrdup(s); - } else { - newval = xstrdup(newval); - } - } else if (nextchar == '<') { // set to global val - newval = xstrdup(*(char **)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL)); - } else { - arg++; // jump to after the '=' or ':' - - // Set 'keywordprg' to ":help" if an empty - // value was passed to :set by the user. - // Misuse errbuf[] for the resulting string. - if (varp == (char *)&p_kp && (*arg == NUL || *arg == ' ')) { - STRCPY(errbuf, ":help"); - save_arg = (char_u *)arg; - arg = errbuf; - } else if (varp == (char *)&p_bs && ascii_isdigit(**(char_u **)varp)) { - // Convert 'backspace' number to string, for - // adding, prepending and removing string. - 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_u **)varp; - } - if (origval_l == oldval) { - origval_l = *(char_u **)varp; - } - if (origval_g == oldval) { - origval_g = *(char_u **)varp; - } - oldval = *(char_u **)varp; - } else if (varp == (char *)&p_ww && ascii_isdigit(*arg)) { - // Convert 'whichwrap' number to string, for - // backwards compatibility with Vim 3.0. - // Misuse errbuf[] for the resulting string. - *errbuf = NUL; - i = getdigits_int(&arg, true, 0); - if (i & 1) { - STRLCAT(errbuf, "b,", sizeof(errbuf)); - } - if (i & 2) { - STRLCAT(errbuf, "s,", sizeof(errbuf)); - } - if (i & 4) { - STRLCAT(errbuf, "h,l,", sizeof(errbuf)); - } - if (i & 8) { - STRLCAT(errbuf, "<,>,", sizeof(errbuf)); - } - if (i & 16) { - STRLCAT(errbuf, "[,],", sizeof(errbuf)); - } - save_arg = (char_u *)arg; - arg = errbuf; - } else if (*arg == '>' - && (varp == (char *)&p_dir - || varp == (char *)&p_bdir)) { - // Remove '>' before 'dir' and 'bdir', for - // backwards compatibility with version 3.0 - arg++; - } - - // Copy the new string into allocated memory. - // Can't use set_string_option_direct(), because - // we need to remove the backslashes. - - // get a bit too much - newlen = (unsigned)STRLEN(arg) + 1; - if (adding || prepending || removing) { - newlen += (unsigned)STRLEN(origval) + 1; - } - newval = xmalloc(newlen); - s = newval; - - // Copy the string, skip over escaped chars. - // For WIN32 backslashes before normal - // file name characters are not removed, and keep - // backslash at start, for "\\machine\path", but - // do remove it for "\\\\machine\\path". - // The reverse is found in ExpandOldSetting(). - while (*arg && !ascii_iswhite(*arg)) { - if (*arg == '\\' && arg[1] != NUL -#ifdef BACKSLASH_IN_FILENAME - && !((flags & P_EXPAND) - && vim_isfilec(arg[1]) - && !ascii_iswhite(arg[1]) - && (arg[1] != '\\' - || (s == newval - && arg[2] != '\\'))) -#endif - ) { - arg++; // remove backslash - } - i = utfc_ptr2len(arg); - if (i > 1) { - // copy multibyte char - memmove(s, arg, (size_t)i); - arg += i; - s += i; - } else { - *s++ = *arg++; - } - } - *s = NUL; - - // Expand environment variables and ~. - // Don't do it when adding without inserting a - // comma. - if (!(adding || prepending || removing) - || (flags & P_COMMA)) { - s = (char *)option_expand(opt_idx, (char_u *)newval); - if (s != NULL) { - xfree(newval); - newlen = (unsigned)STRLEN(s) + 1; - if (adding || prepending || removing) { - newlen += (unsigned)STRLEN(origval) + 1; - } - newval = xmalloc(newlen); - STRCPY(newval, s); - } - } - - // locate newval[] in origval[] when removing it - // and when adding to avoid duplicates - i = 0; // init for GCC - if (removing || (flags & P_NODUP)) { - i = (int)STRLEN(newval); - s = (char *)find_dup_item(origval, (char_u *)newval, flags); - - // do not add if already there - if ((adding || prepending) && s != NULL) { - prepending = false; - adding = false; - STRCPY(newval, origval); - } - - // if no duplicate, move pointer to end of - // original value - if (s == NULL) { - s = (char *)origval + (int)STRLEN(origval); - } - } - - // concatenate the two strings; add a ',' if - // needed - if (adding || prepending) { - comma = ((flags & P_COMMA) && *origval != NUL - && *newval != NUL); - if (adding) { - i = (int)STRLEN(origval); - // Strip a trailing comma, would get 2. - if (comma && i > 1 - && (flags & P_ONECOMMA) == P_ONECOMMA - && origval[i - 1] == ',' - && origval[i - 2] != '\\') { - i--; - } - memmove(newval + i + comma, newval, - STRLEN(newval) + 1); - memmove(newval, origval, (size_t)i); - } else { - i = (int)STRLEN(newval); - STRMOVE(newval + i + comma, origval); - } - if (comma) { - newval[i] = ','; - } - } - - // Remove newval[] from origval[]. (Note: "i" has - // been set above and is used here). - if (removing) { - STRCPY(newval, origval); - if (*s) { - // may need to remove a comma - if (flags & P_COMMA) { - if (s == (char *)origval) { - // include comma after string - if (s[i] == ',') { - i++; - } - } else { - // include comma before string - s--; - i++; - } - } - STRMOVE(newval + (s - (char *)origval), s + i); - } - } - - if (flags & P_FLAGLIST) { - // Remove flags that appear twice. - for (s = newval; *s;) { - // if options have P_FLAGLIST and P_ONECOMMA such as - // 'whichwrap' - if (flags & P_ONECOMMA) { - if (*s != ',' && *(s + 1) == ',' - && vim_strchr(s + 2, *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) { - STRMOVE(s, s + 1); - continue; - } - } - s++; - } - } - - if (save_arg != NULL) { // number for 'whichwrap' - arg = (char *)save_arg; - } - } - - // Set the new value. - *(char_u **)(varp) = (char_u *)newval; - - // origval may be freed by - // did_set_string_option(), make a copy. - saved_origval = (origval != NULL) ? xstrdup((char *)origval) : 0; - saved_origval_l = (origval_l != NULL) ? xstrdup((char *)origval_l) : 0; - saved_origval_g = (origval_g != NULL) ? xstrdup((char *)origval_g) : 0; - - // newval (and varp) may become invalid if the - // buffer is closed by autocommands. - saved_newval = (newval != NULL) ? xstrdup(newval) : 0; - - { - uint32_t *p = insecure_flag(curwin, opt_idx, opt_flags); - const int secure_saved = secure; - - // When an option is set in the sandbox, from a - // modeline or in secure mode, then deal with side - // effects in secure mode. Also when the value was - // set with the P_INSECURE flag and is not - // completely replaced. - if ((opt_flags & OPT_MODELINE) - || sandbox != 0 - || (!value_is_replaced && (*p & P_INSECURE))) { - secure = 1; - } - - // Handle side effects, and set the global value - // for ":set" on local options. Note: when setting - // 'syntax' or 'filetype' autocommands may be - // triggered that can cause havoc. - errmsg = did_set_string_option(opt_idx, (char **)varp, (char *)oldval, - errbuf, sizeof(errbuf), - opt_flags, &value_checked); - - secure = secure_saved; - } - - if (errmsg == NULL) { - if (!starting) { - trigger_optionsset_string(opt_idx, opt_flags, saved_origval, saved_origval_l, - saved_origval_g, saved_newval); - } - if (options[opt_idx].flags & P_UI_OPTION) { - ui_call_option_set(cstr_as_string(options[opt_idx].fullname), - STRING_OBJ(cstr_as_string(saved_newval))); + 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; } - } - xfree(saved_origval); - xfree(saved_origval_l); - xfree(saved_origval_g); - xfree(saved_newval); - - // If error detected, print the error message. - if (errmsg != NULL) { - goto skip; + break; } } else { // key code option(FIXME(tarruda): Show a warning or something @@ -1485,7 +1486,7 @@ int do_set(char *arg, int opt_flags) } if (opt_idx >= 0) { - did_set_option(opt_idx, opt_flags, value_is_replaced, value_checked); + did_set_option(opt_idx, opt_flags, op == OP_NONE, value_checked); } } @@ -1509,7 +1510,7 @@ skip: if (errmsg != NULL) { STRLCPY(IObuff, _(errmsg), IOSIZE); - i = (int)STRLEN(IObuff) + 2; + i = (int)strlen(IObuff) + 2; if (i + (arg - startarg) < IOSIZE) { // append the argument with the error STRCAT(IObuff, ": "); @@ -1683,7 +1684,7 @@ char_u *find_shada_parameter(int type) /// These string options cannot be indirect! /// If "val" is NULL expand the current value of the option. /// Return pointer to NameBuff, or NULL when not expanded. -static char_u *option_expand(int opt_idx, char_u *val) +static char *option_expand(int opt_idx, char *val) { // if option doesn't need expansion nothing to do if (!(options[opt_idx].flags & P_EXPAND) || options[opt_idx].var == NULL) { @@ -1691,12 +1692,12 @@ static char_u *option_expand(int opt_idx, char_u *val) } if (val == NULL) { - val = *(char_u **)options[opt_idx].var; + val = *(char **)options[opt_idx].var; } // If val is longer than MAXPATHL no meaningful expansion can be done, // expand_env() would truncate the string. - if (val == NULL || STRLEN(val) > MAXPATHL) { + if (val == NULL || strlen(val) > MAXPATHL) { return NULL; } @@ -1704,15 +1705,15 @@ static char_u *option_expand(int opt_idx, char_u *val) // Escape spaces when expanding 'tags', they are used to separate file // names. // For 'spellsuggest' expand after "file:". - expand_env_esc(val, (char_u *)NameBuff, MAXPATHL, + expand_env_esc((char_u *)val, (char_u *)NameBuff, MAXPATHL, (char_u **)options[opt_idx].var == &p_tags, false, (char_u **)options[opt_idx].var == (char_u **)&p_sps ? (char_u *)"file:" : NULL); - if (STRCMP(NameBuff, val) == 0) { // they are the same + if (strcmp(NameBuff, val) == 0) { // they are the same return NULL; } - return (char_u *)NameBuff; + return NameBuff; } /// After setting various option values: recompute variables that depend on @@ -1893,15 +1894,16 @@ void set_option_sctx_idx(int opt_idx, int opt_flags, sctx_T script_ctx) int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0; int indir = (int)options[opt_idx].indir; nlua_set_sctx(&script_ctx); - const LastSet last_set = { - .script_ctx = { - script_ctx.sc_sid, - script_ctx.sc_seq, - script_ctx.sc_lnum + SOURCING_LNUM - }, - current_channel_id + LastSet last_set = { + .script_ctx = script_ctx, + .channel_id = current_channel_id, }; + // Modeline already has the line number set. + if (!(opt_flags & OPT_MODELINE)) { + last_set.script_ctx.sc_lnum += SOURCING_LNUM; + } + // Remember where the option was set. For local options need to do that // in the buffer or window structure. if (both || (opt_flags & OPT_GLOBAL) || (indir & (PV_BUF|PV_WIN)) == 0) { @@ -2133,7 +2135,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va // Arabic requires a utf-8 encoding, inform the user if it's not // set. - if (STRCMP(p_enc, "utf-8") != 0) { + if (strcmp(p_enc, "utf-8") != 0) { static char *w_arabic = N_("W17: Arabic requires UTF-8, do ':set encoding=utf-8'"); msg_source(HL_ATTR(HLF_W)); @@ -2572,9 +2574,10 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf, Rows = (int)p_lines; Columns = (int)p_columns; check_screensize(); - if (cmdline_row > Rows - p_ch && Rows > p_ch) { - assert(p_ch >= 0 && Rows - p_ch <= INT_MAX); - cmdline_row = (int)(Rows - p_ch); + int new_row = (int)(Rows - MAX(p_ch, 1)); + if (cmdline_row > new_row && Rows > p_ch) { + assert(p_ch >= 0 && new_row <= INT_MAX); + cmdline_row = new_row; } } if (p_window >= Rows || !option_was_set("window")) { @@ -2755,10 +2758,10 @@ int findoption_len(const char *const arg, const size_t len) } else { // Nvim: handle option aliases. if (STRNCMP(options[opt_idx].fullname, "viminfo", 7) == 0) { - if (STRLEN(options[opt_idx].fullname) == 7) { + if (strlen(options[opt_idx].fullname) == 7) { return findoption_len("shada", 5); } - assert(STRCMP(options[opt_idx].fullname, "viminfofile") == 0); + assert(strcmp(options[opt_idx].fullname, "viminfofile") == 0); return findoption_len("shadafile", 9); } } @@ -3276,7 +3279,7 @@ static void showoptions(int all, int opt_flags) len = 1; // a toggle option fits always } else { option_value2string(p, opt_flags); - len = (int)STRLEN(p->fullname) + vim_strsize((char *)NameBuff) + 1; + len = (int)strlen(p->fullname) + vim_strsize((char *)NameBuff) + 1; } if ((len <= INC - GAP && run == 1) || (len > INC - GAP && run == 2)) { @@ -3329,7 +3332,7 @@ static int optval_default(vimoption_T *p, char_u *varp) return *(int *)varp == (int)(intptr_t)p->def_val; } // P_STRING - return STRCMP(*(char_u **)varp, p->def_val) == 0; + return strcmp(*(char **)varp, p->def_val) == 0; } /// Send update to UIs with values of UI relevant options @@ -3560,14 +3563,12 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char **valuep, uint64_ if (valuep == &p_pt) { 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_u *)str2special((const char **)&s, false, false), 2) == FAIL) { return FAIL; } } } else if ((flags & P_EXPAND) != 0) { - size_t size = (size_t)STRLEN(*valuep) + 1; + size_t size = (size_t)strlen(*valuep) + 1; // replace home directory in the whole option value into "buf" buf = xmalloc(size); @@ -5309,7 +5310,7 @@ char_u *get_showbreak_value(win_T *const win) if (win->w_p_sbr == NULL || *win->w_p_sbr == NUL) { return (char_u *)p_sbr; } - if (STRCMP(win->w_p_sbr, "NONE") == 0) { + if (strcmp(win->w_p_sbr, "NONE") == 0) { return (char_u *)empty_option; } return (char_u *)win->w_p_sbr; @@ -5455,13 +5456,13 @@ size_t copy_option_part(char **option, char *buf, size_t maxlen, char *sep_chars /// Return true when 'shell' has "csh" in the tail. int csh_like_shell(void) { - return strstr(path_tail((char *)p_sh), "csh") != NULL; + return strstr(path_tail(p_sh), "csh") != NULL; } /// Return true when 'shell' has "fish" in the tail. bool fish_like_shell(void) { - return strstr(path_tail((char *)p_sh), "fish") != NULL; + return strstr(path_tail(p_sh), "fish") != NULL; } /// Return the number of requested sign columns, based on current @@ -5619,7 +5620,7 @@ static Dictionary vimoption2dict(vimoption_T *opt) const char *type; Object def; // TODO(bfredl): do you even nocp? - char_u *def_val = opt->def_val; + char_u *def_val = (char_u *)opt->def_val; if (opt->flags & P_STRING) { type = "string"; def = CSTR_TO_OBJ(def_val ? (char *)def_val : ""); diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index 031a853c0c..e8cf338cf1 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -97,7 +97,7 @@ typedef enum { // Default values for 'errorformat'. // The "%f|%l| %m" one is used for when the contents of the quickfix window is // written to a file. -#ifdef WIN32 +#ifdef MSWIN # define DFLT_EFM \ "%f(%l) \\=: %t%*\\D%n: %m,%*[^\"]\"%f\"%*\\D%l: %m,%f(%l) \\=: %m,%*[^ ] %f %l: %m,%f:%l:%c:%m,%f(%l):%m,%f:%l:%m,%f|%l| %m" #else @@ -503,7 +503,7 @@ EXTERN int p_eb; // 'errorbells' EXTERN char_u *p_ef; // 'errorfile' EXTERN char *p_efm; // 'errorformat' EXTERN char *p_gefm; // 'grepformat' -EXTERN char_u *p_gp; // 'grepprg' +EXTERN char *p_gp; // 'grepprg' EXTERN int p_eol; ///< 'endofline' EXTERN char *p_ei; // 'eventignore' EXTERN int p_et; ///< 'expandtab' @@ -684,11 +684,11 @@ EXTERN unsigned ssop_flags; #define SSOP_TERMINAL 0x10000 #define SSOP_SKIP_RTP 0x20000 -EXTERN char_u *p_sh; // 'shell' +EXTERN char *p_sh; // 'shell' EXTERN char_u *p_shcf; // 'shellcmdflag' EXTERN char *p_sp; // 'shellpipe' EXTERN char_u *p_shq; // 'shellquote' -EXTERN char_u *p_sxq; // 'shellxquote' +EXTERN char *p_sxq; // 'shellxquote' EXTERN char_u *p_sxe; // 'shellxescape' EXTERN char *p_srr; // 'shellredir' EXTERN int p_stmp; // 'shelltemp' diff --git a/src/nvim/options.lua b/src/nvim/options.lua index 1d9a821e20..aa643eec36 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -1014,7 +1014,7 @@ return { expand=true, varname='p_gp', defaults={ - condition='WIN32', + condition='MSWIN', -- Add an extra file name so that grep will always -- insert a file name in the match line. */ if_true="findstr /n $* nul", @@ -1276,7 +1276,7 @@ return { deny_duplicates=true, varname='p_isi', defaults={ - condition='WIN32', + condition='MSWIN', if_true="@,48-57,_,128-167,224-235", if_false="@,48-57,_,192-255" } @@ -2100,7 +2100,7 @@ return { expand=true, varname='p_sh', defaults={ - condition='WIN32', + condition='MSWIN', if_true="cmd.exe", if_false="sh" } @@ -2112,7 +2112,7 @@ return { secure=true, varname='p_shcf', defaults={ - condition='WIN32', + condition='MSWIN', if_true="/s /c", if_false="-c" } @@ -2124,7 +2124,7 @@ return { secure=true, varname='p_sp', defaults={ - condition='WIN32', + condition='MSWIN', if_true=">%s 2>&1", if_false="| tee", } @@ -2144,7 +2144,7 @@ return { secure=true, varname='p_srr', defaults={ - condition='WIN32', + condition='MSWIN', if_true=">%s 2>&1", if_false=">" } @@ -2171,7 +2171,7 @@ return { secure=true, varname='p_sxq', defaults={ - condition='WIN32', + condition='MSWIN', if_true="\"", if_false="", } diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 8581dae7a3..7278b1a12d 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -464,7 +464,7 @@ static char *check_mousescroll(char *string) for (;;) { char *end = vim_strchr(string, ','); - size_t length = end ? (size_t)(end - string) : STRLEN(string); + size_t length = end ? (size_t)(end - string) : strlen(string); // Both "ver:" and "hor:" are 4 bytes long. // They should be followed by at least one digit. @@ -532,7 +532,7 @@ static int check_signcolumn(char *val) } // check for 'auto:<NUMBER>-<NUMBER>' - if (STRLEN(val) == 8 + if (strlen(val) == 8 && !STRNCMP(val, "auto:", 5) && ascii_isdigit(val[5]) && val[6] == '-' @@ -683,7 +683,7 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf } } } else if (varp == &p_bex || varp == &p_pm) { // 'backupext' and 'patchmode' - if (STRCMP(*p_bex == '.' ? p_bex + 1 : p_bex, + if (strcmp(*p_bex == '.' ? p_bex + 1 : p_bex, *p_pm == '.' ? p_pm + 1 : p_pm) == 0) { errmsg = e_backupext_and_patchmode_are_equal; } @@ -731,7 +731,7 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf } } } else if (varp == &p_hl) { // 'highlight' - if (STRCMP(*varp, HIGHLIGHT_INIT) != 0) { + if (strcmp(*varp, HIGHLIGHT_INIT) != 0) { errmsg = e_unsupportedoption; } } else if (varp == &p_jop) { // 'jumpoptions' @@ -823,13 +823,13 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf } if (errmsg == NULL) { - // canonize the value, so that STRCMP() can be used on it + // 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) { + if (strcmp(p_enc, "utf-8") != 0) { errmsg = e_unsupportedoption; } else { spell_reload(); @@ -1258,7 +1258,7 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf if (*p_pt) { p = NULL; (void)replace_termcodes(p_pt, - STRLEN(p_pt), + strlen(p_pt), &p, REPTERM_FROM_PART | REPTERM_DO_LT, NULL, CPO_TO_CPO_FLAGS); if (p != NULL) { @@ -1358,7 +1358,7 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf } else { if (opt_strings_flags(ve, p_ve_values, flags, true) != OK) { errmsg = e_invarg; - } else if (STRCMP(p_ve, oldval) != 0) { + } else if (strcmp(p_ve, oldval) != 0) { // Recompute cursor position in case the new 've' setting // changes something. validate_virtcol(); @@ -1393,7 +1393,7 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf if (!valid_filetype(*varp)) { errmsg = e_invarg; } else { - value_changed = STRCMP(oldval, *varp) != 0; + 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. @@ -1403,7 +1403,7 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf if (!valid_filetype(*varp)) { errmsg = e_invarg; } else { - value_changed = STRCMP(oldval, *varp) != 0; + 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. @@ -1641,7 +1641,7 @@ static int opt_strings_flags(char *val, char **values, unsigned *flagp, bool lis return FAIL; } - size_t len = STRLEN(values[i]); + size_t len = strlen(values[i]); if (STRNCMP(values[i], val, len) == 0 && ((list && val[len] == ',') || val[len] == NUL)) { val += len + (val[len] == ','); diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c index 2f2a8c7fdc..bd79b43574 100644 --- a/src/nvim/os/env.c +++ b/src/nvim/os/env.c @@ -20,7 +20,7 @@ #include "nvim/version.h" #include "nvim/vim.h" -#ifdef WIN32 +#ifdef MSWIN # include "nvim/mbyte.h" // for utf8_to_utf16, utf16_to_utf8 #endif @@ -128,7 +128,7 @@ int os_setenv(const char *name, const char *value, int overwrite) if (name[0] == '\0') { return -1; } -#ifdef WIN32 +#ifdef MSWIN if (!overwrite && os_getenv(name) != NULL) { return 0; } @@ -143,7 +143,7 @@ int os_setenv(const char *name, const char *value, int overwrite) #endif uv_mutex_lock(&mutex); int r; -#ifdef WIN32 +#ifdef MSWIN // libintl uses getenv() for LC_ALL/LANG/etc., so we must use _putenv_s(). if (striequal(name, "LC_ALL") || striequal(name, "LANGUAGE") || striequal(name, "LANG") || striequal(name, "LC_MESSAGES")) { @@ -186,7 +186,7 @@ int os_unsetenv(const char *name) size_t os_get_fullenv_size(void) { size_t len = 0; -#ifdef _WIN32 +#ifdef MSWIN wchar_t *envstrings = GetEnvironmentStringsW(); wchar_t *p = envstrings; size_t l; @@ -235,7 +235,7 @@ void os_free_fullenv(char **env) /// @param env_size size of `env`, @see os_fullenv_size void os_copy_fullenv(char **env, size_t env_size) { -#ifdef _WIN32 +#ifdef MSWIN wchar_t *envstrings = GetEnvironmentStringsW(); if (!envstrings) { return; @@ -280,7 +280,7 @@ void os_copy_fullenv(char **env, size_t env_size) /// @return [allocated] environment variable's value, or NULL char *os_getenvname_at_index(size_t index) { -#ifdef _WIN32 +#ifdef MSWIN wchar_t *envstrings = GetEnvironmentStringsW(); if (!envstrings) { return NULL; @@ -347,7 +347,7 @@ char *os_getenvname_at_index(size_t index) /// @return the process ID. int64_t os_get_pid(void) { -#ifdef _WIN32 +#ifdef MSWIN return (int64_t)GetCurrentProcessId(); #else return (int64_t)getpid(); @@ -368,7 +368,7 @@ void os_get_hostname(char *hostname, size_t size) } else { xstrlcpy(hostname, vutsname.nodename, size); } -#elif defined(WIN32) +#elif defined(MSWIN) wchar_t host_utf16[MAX_COMPUTERNAME_LENGTH + 1]; DWORD host_wsize = sizeof(host_utf16) / sizeof(host_utf16[0]); if (GetComputerNameW(host_utf16, &host_wsize) == 0) { @@ -418,7 +418,7 @@ void init_homedir(void) const char *var = os_getenv("HOME"); -#ifdef WIN32 +#ifdef MSWIN // Typically, $HOME is not defined on Windows, unless the user has // specifically defined it for Vim's sake. However, on Windows NT // platforms, $HOMEDRIVE and $HOMEPATH are automatically defined for @@ -451,7 +451,7 @@ void init_homedir(void) var = NULL; const char *exp = os_getenv(os_buf); if (exp != NULL && *exp != NUL - && STRLEN(exp) + STRLEN(p) < MAXPATHL) { + && strlen(exp) + strlen(p) < MAXPATHL) { vim_snprintf(os_buf, MAXPATHL, "%s%s", exp, p + 1); var = os_buf; } @@ -476,7 +476,7 @@ void init_homedir(void) // Change to the directory and get the actual path. This resolves // links. Don't do it when we can't return. if (os_dirname((char_u *)os_buf, MAXPATHL) == OK && os_chdir(os_buf) == 0) { - if (!os_chdir(var) && os_dirname(IObuff, IOSIZE) == OK) { + if (!os_chdir(var) && os_dirname((char_u *)IObuff, IOSIZE) == OK) { var = (char *)IObuff; } if (os_chdir(os_buf) != 0) { @@ -800,11 +800,11 @@ static char *vim_version_dir(const char *vimdir) /// @return The new pend including dirname or just pend static char *remove_tail(char *path, char *pend, char *dirname) { - size_t len = STRLEN(dirname); + size_t len = strlen(dirname); char *new_tail = pend - len - 1; if (new_tail >= path - && FNAMENCMP((char_u *)new_tail, (char_u *)dirname, len) == 0 + && path_fnamencmp(new_tail, dirname, len) == 0 && (new_tail == path || after_pathsep(path, new_tail))) { return new_tail; } @@ -900,7 +900,7 @@ char *vim_getenv(const char *name) // init_path() should have been called before now. assert(get_vim_var_str(VV_PROGPATH)[0] != NUL); -#ifdef WIN32 +#ifdef MSWIN if (strcmp(name, "HOME") == 0) { return xstrdup(homedir); } @@ -1056,7 +1056,7 @@ size_t home_replace(const buf_T *const buf, const char *src, char *const dst, si } const char *homedir_env = os_getenv("HOME"); -#ifdef WIN32 +#ifdef MSWIN if (homedir_env == NULL) { homedir_env = os_getenv("USERPROFILE"); } @@ -1098,7 +1098,7 @@ size_t home_replace(const buf_T *const buf, const char *src, char *const dst, si size_t len = dirlen; for (;;) { if (len - && FNAMENCMP(src, (char_u *)p, len) == 0 + && path_fnamencmp(src, p, len) == 0 && (vim_ispathsep(src[len]) || (!one && (src[len] == ',' || src[len] == ' ')) || src[len] == NUL)) { @@ -1146,7 +1146,7 @@ char *home_replace_save(buf_T *buf, const char *src) { size_t len = 3; // space for "~/" and trailing NUL if (src != NULL) { // just in case - len += STRLEN(src); + len += strlen(src); } char *dst = xmalloc(len); home_replace(buf, src, dst, len, true); @@ -1174,7 +1174,7 @@ char *get_env_name(expand_T *xp, int idx) bool os_setenv_append_path(const char *fname) FUNC_ATTR_NONNULL_ALL { -#ifdef WIN32 +#ifdef MSWIN // 8191 (plus NUL) is considered the practical maximum. # define MAX_ENVPATHLEN 8192 #else diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 158c22efaf..68e96eea6e 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -27,7 +27,7 @@ #include "nvim/path.h" #include "nvim/strings.h" -#ifdef WIN32 +#ifdef MSWIN # include "nvim/mbyte.h" // for utf8_to_utf16, utf16_to_utf8 #endif @@ -151,7 +151,7 @@ bool os_isdir(const char *name) int os_nodetype(const char *name) FUNC_ATTR_NONNULL_ALL { -#ifndef WIN32 // Unix +#ifndef MSWIN // Unix uv_stat_t statbuf; if (0 != os_stat(name, &statbuf)) { return NODE_NORMAL; // File doesn't exist. @@ -241,7 +241,7 @@ bool os_can_exe(const char *name, char **abspath, bool use_path) FUNC_ATTR_NONNULL_ARG(1) { if (!use_path || gettail_dir(name) != name) { -#ifdef WIN32 +#ifdef MSWIN if (is_executable_ext(name, abspath)) { #else // Must have path separator, cannot execute files in the current directory. @@ -270,7 +270,7 @@ static bool is_executable(const char *name, char **abspath) return false; } -#ifdef WIN32 +#ifdef MSWIN // Windows does not have exec bit; just check if the file exists and is not // a directory. const bool ok = S_ISREG(mode); @@ -287,7 +287,7 @@ static bool is_executable(const char *name, char **abspath) return ok; } -#ifdef WIN32 +#ifdef MSWIN /// Checks if file `name` is executable under any of these conditions: /// - extension is in $PATHEXT and `name` is executable /// - result of any $PATHEXT extension appended to `name` is executable @@ -351,7 +351,7 @@ static bool is_executable_in_path(const char *name, char **abspath) return false; } -#ifdef WIN32 +#ifdef MSWIN // Prepend ".;" to $PATH. size_t pathlen = strlen(path_env); char *path = memcpy(xmallocz(pathlen + 2), "." ENV_SEPSTR, 2); @@ -374,7 +374,7 @@ static bool is_executable_in_path(const char *name, char **abspath) STRLCPY(buf, p, e - p + 1); append_path(buf, name, buf_len); -#ifdef WIN32 +#ifdef MSWIN if (is_executable_ext(buf, abspath)) { #else if (is_executable(buf, abspath)) { @@ -446,7 +446,7 @@ FILE *os_fopen(const char *path, const char *flags) default: abort(); } -#ifdef WIN32 +#ifdef MSWIN if (flags[1] == 'b') { iflags |= O_BINARY; } @@ -1208,7 +1208,7 @@ char *os_realpath(const char *name, char *buf) return result == kLibuvSuccess ? buf : NULL; } -#ifdef WIN32 +#ifdef MSWIN # include <shlobj.h> /// When "fname" is the name of a shortcut (*.lnk) resolve the file it points diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c index ea9f31d776..fc7390a303 100644 --- a/src/nvim/os/input.c +++ b/src/nvim/os/input.c @@ -38,6 +38,8 @@ 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 #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/input.c.generated.h" @@ -97,13 +99,25 @@ static void create_cursorhold_event(bool events_enabled) multiqueue_put(main_loop.events, cursorhold_event, 0); } +static void restart_cursorhold_wait(int tb_change_cnt) +{ + cursorhold_time = 0; + cursorhold_tb_change_cnt = tb_change_cnt; +} + /// Low level input function /// /// wait until either the input buffer is non-empty or, if `events` is not NULL /// until `events` is non-empty. int os_inchar(uint8_t *buf, int maxlen, int ms, int tb_change_cnt, MultiQueue *events) { + // This check is needed so that feeding typeahead from RPC can prevent CursorHold. + if (tb_change_cnt != cursorhold_tb_change_cnt) { + restart_cursorhold_wait(tb_change_cnt); + } + if (maxlen && rbuffer_size(input_buffer)) { + restart_cursorhold_wait(tb_change_cnt); return (int)rbuffer_read(input_buffer, (char *)buf, (size_t)maxlen); } @@ -118,18 +132,22 @@ int os_inchar(uint8_t *buf, int maxlen, int ms, int tb_change_cnt, MultiQueue *e return 0; } } else { - if ((result = inbuf_poll((int)p_ut, events)) == kInputNone) { + uint64_t wait_start = os_hrtime(); + cursorhold_time = MIN(cursorhold_time, (int)p_ut); + if ((result = inbuf_poll((int)p_ut - cursorhold_time, events)) == kInputNone) { if (read_stream.closed && silent_mode) { // Drained eventloop & initial input; exit silent/batch-mode (-es/-Es). read_error_exit(); } - + restart_cursorhold_wait(tb_change_cnt); if (trigger_cursorhold() && !typebuf_changed(tb_change_cnt)) { create_cursorhold_event(events == main_loop.events); } else { before_blocking(); result = inbuf_poll(-1, events); } + } else { + cursorhold_time += (int)((os_hrtime() - wait_start) / 1000000); } } @@ -141,6 +159,7 @@ int os_inchar(uint8_t *buf, int maxlen, int ms, int tb_change_cnt, MultiQueue *e } if (maxlen && rbuffer_size(input_buffer)) { + restart_cursorhold_wait(tb_change_cnt); // Safe to convert rbuffer_read to int, it will never overflow since we use // relatively small buffers. return (int)rbuffer_read(input_buffer, (char *)buf, (size_t)maxlen); diff --git a/src/nvim/os/os_defs.h b/src/nvim/os/os_defs.h index a4361859ec..a30e16eeba 100644 --- a/src/nvim/os/os_defs.h +++ b/src/nvim/os/os_defs.h @@ -7,7 +7,7 @@ #include <sys/stat.h> #include <sys/types.h> -#ifdef WIN32 +#ifdef MSWIN # include "nvim/os/win_defs.h" #else # include "nvim/os/unix_defs.h" @@ -43,7 +43,7 @@ /// Converts system error code to libuv error code. #define os_translate_sys_error uv_translate_sys_error -#ifdef WIN32 +#ifdef MSWIN # define os_strtok strtok_s #else # define os_strtok strtok_r diff --git a/src/nvim/os/process.c b/src/nvim/os/process.c index e70bc71961..28aea08595 100644 --- a/src/nvim/os/process.c +++ b/src/nvim/os/process.c @@ -8,7 +8,7 @@ #include <uv.h> // for HANDLE (win32) -#ifdef WIN32 +#ifdef MSWIN # include <tlhelp32.h> // for CreateToolhelp32Snapshot #endif @@ -38,7 +38,7 @@ # include "os/process.c.generated.h" #endif -#ifdef WIN32 +#ifdef MSWIN static bool os_proc_tree_kill_rec(HANDLE process, int sig) { if (process == NULL) { @@ -114,7 +114,7 @@ int os_proc_children(int ppid, int **proc_list, size_t *proc_count) *proc_list = NULL; *proc_count = 0; -#ifdef WIN32 +#ifdef MSWIN PROCESSENTRY32 pe; // Snapshot of all processes. @@ -215,7 +215,7 @@ int os_proc_children(int ppid, int **proc_list, size_t *proc_count) return 0; } -#ifdef WIN32 +#ifdef MSWIN /// Gets various properties of the process identified by `pid`. /// /// @param pid Process to inspect. diff --git a/src/nvim/os/pty_process.h b/src/nvim/os/pty_process.h index 94923499ca..07d346be22 100644 --- a/src/nvim/os/pty_process.h +++ b/src/nvim/os/pty_process.h @@ -1,7 +1,7 @@ #ifndef NVIM_OS_PTY_PROCESS_H #define NVIM_OS_PTY_PROCESS_H -#ifdef WIN32 +#ifdef MSWIN # include "nvim/os/pty_process_win.h" #else # include "nvim/os/pty_process_unix.h" diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c index 25f51f89a9..ca3e32e871 100644 --- a/src/nvim/os/shell.c +++ b/src/nvim/os/shell.c @@ -129,7 +129,7 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in bool is_fish_shell = #if defined(UNIX) - STRNCMP(invocation_path_tail(p_sh, NULL), "fish", 4) == 0; + STRNCMP(invocation_path_tail((char_u *)p_sh, NULL), "fish", 4) == 0; #else false; #endif @@ -178,18 +178,18 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in // STYLE_ECHO: space separated. // A shell we don't know, stay safe and use "echo". if (num_pat == 1 && *pat[0] == '`' - && (len = STRLEN(pat[0])) > 2 + && (len = strlen(pat[0])) > 2 && *(pat[0] + len - 1) == '`') { shell_style = STYLE_BT; } else if ((len = STRLEN(p_sh)) >= 3) { - if (STRCMP(p_sh + len - 3, "csh") == 0) { + if (strcmp(p_sh + len - 3, "csh") == 0) { shell_style = STYLE_GLOB; - } else if (STRCMP(p_sh + len - 3, "zsh") == 0) { + } else if (strcmp(p_sh + len - 3, "zsh") == 0) { shell_style = STYLE_PRINT; } } if (shell_style == STYLE_ECHO - && strstr(path_tail((char *)p_sh), "sh") != NULL) { + && strstr(path_tail(p_sh), "sh") != NULL) { shell_style = STYLE_VIMGLOB; } @@ -198,7 +198,7 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in // Worst case: "unset nonomatch; print -N >" plus two is 29 len = STRLEN(tempname) + 29; if (shell_style == STYLE_VIMGLOB) { - len += STRLEN(sh_vimglob_func); + len += strlen(sh_vimglob_func); } for (i = 0; i < num_pat; i++) { @@ -519,7 +519,7 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in continue; } - p = xmalloc(STRLEN((*file)[i]) + 1 + dir); + p = xmalloc(strlen((*file)[i]) + 1 + dir); STRCPY(p, (*file)[i]); if (dir) { add_pathsep((char *)p); // add '/' to a directory name @@ -555,11 +555,11 @@ 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(p_shcf, NULL) : 0); + size_t argc = tokenize((char_u *)p_sh, NULL) + (cmd ? tokenize(p_shcf, NULL) : 0); char **rv = xmalloc((argc + 4) * sizeof(*rv)); // Split 'shell' - size_t i = tokenize(p_sh, rv); + size_t i = tokenize((char_u *)p_sh, rv); if (extra_args) { rv[i++] = xstrdup(extra_args); // Push a copy of `extra_args` @@ -700,7 +700,7 @@ int call_shell(char_u *cmd, ShellOpts opts, char_u *extra_shell_arg) if (p_verbose > 3) { verbose_enter(); - smsg(_("Executing command: \"%s\""), cmd == NULL ? p_sh : cmd); + smsg(_("Executing command: \"%s\""), cmd == NULL ? p_sh : (char *)cmd); msg_putchar('\n'); verbose_leave(); } @@ -1316,17 +1316,17 @@ static char *shell_xescape_xquote(const char *cmd) } const char *ecmd = cmd; - if (*p_sxe != NUL && STRCMP(p_sxq, "(") == 0) { + if (*p_sxe != NUL && strcmp(p_sxq, "(") == 0) { ecmd = (char *)vim_strsave_escaped_ext((char_u *)cmd, p_sxe, '^', false); } - size_t ncmd_size = strlen(ecmd) + STRLEN(p_sxq) * 2 + 1; + size_t ncmd_size = strlen(ecmd) + strlen(p_sxq) * 2 + 1; char *ncmd = xmalloc(ncmd_size); // When 'shellxquote' is ( append ). // When 'shellxquote' is "( append )". - if (STRCMP(p_sxq, "(") == 0) { + if (strcmp(p_sxq, "(") == 0) { vim_snprintf(ncmd, ncmd_size, "(%s)", ecmd); - } else if (STRCMP(p_sxq, "\"(") == 0) { + } else if (strcmp(p_sxq, "\"(") == 0) { vim_snprintf(ncmd, ncmd_size, "\"(%s)\"", ecmd); } else { vim_snprintf(ncmd, ncmd_size, "%s%s%s", p_sxq, ecmd, p_sxq); diff --git a/src/nvim/os/signal.c b/src/nvim/os/signal.c index e592570966..9aa8d8051b 100644 --- a/src/nvim/os/signal.c +++ b/src/nvim/os/signal.c @@ -4,7 +4,7 @@ #include <assert.h> #include <stdbool.h> #include <uv.h> -#ifndef WIN32 +#ifndef MSWIN # include <signal.h> // for sigset_t #endif @@ -34,7 +34,7 @@ static bool rejecting_deadly; void signal_init(void) { -#ifndef WIN32 +#ifndef MSWIN // Ensure a clean slate by unblocking all signals. For example, if SIGCHLD is // blocked, libuv may hang after spawning a subprocess on Linux. #5230 sigset_t mask; diff --git a/src/nvim/os/stdpaths.c b/src/nvim/os/stdpaths.c index 59d315d44c..31d85ac2eb 100644 --- a/src/nvim/os/stdpaths.c +++ b/src/nvim/os/stdpaths.c @@ -21,7 +21,7 @@ static const char *xdg_env_vars[] = { [kXDGDataDirs] = "XDG_DATA_DIRS", }; -#ifdef WIN32 +#ifdef MSWIN static const char *const xdg_defaults_env_vars[] = { [kXDGConfigHome] = "LOCALAPPDATA", [kXDGDataHome] = "LOCALAPPDATA", @@ -37,7 +37,7 @@ static const char *const xdg_defaults_env_vars[] = { /// /// Used in case environment variables contain nothing. Need to be expanded. static const char *const xdg_defaults[] = { -#ifdef WIN32 +#ifdef MSWIN [kXDGConfigHome] = "~\\AppData\\Local", [kXDGDataHome] = "~\\AppData\\Local", [kXDGCacheHome] = "~\\AppData\\Local\\Temp", @@ -69,7 +69,7 @@ char *stdpaths_get_xdg_var(const XDGVarType idx) const char *env_val = os_getenv(env); -#ifdef WIN32 +#ifdef MSWIN if (env_val == NULL && xdg_defaults_env_vars[idx] != NULL) { env_val = os_getenv(xdg_defaults_env_vars[idx]); } @@ -107,7 +107,7 @@ char *get_xdg_home(const XDGVarType idx) { char *dir = stdpaths_get_xdg_var(idx); if (dir) { -#if defined(WIN32) +#if defined(MSWIN) dir = concat_fnames_realloc(dir, ((idx == kXDGDataHome || idx == kXDGStateHome) ? "nvim-data" : "nvim"), diff --git a/src/nvim/os/tty.c b/src/nvim/os/tty.c index 126b1b0044..1b15613a93 100644 --- a/src/nvim/os/tty.c +++ b/src/nvim/os/tty.c @@ -12,7 +12,7 @@ # include "os/tty.c.generated.h" #endif -#ifdef WIN32 +#ifdef MSWIN # if !defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING) # define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 # endif diff --git a/src/nvim/os/users.c b/src/nvim/os/users.c index bd34e917b2..33e6563c4c 100644 --- a/src/nvim/os/users.c +++ b/src/nvim/os/users.c @@ -14,7 +14,7 @@ #ifdef HAVE_PWD_H # include <pwd.h> #endif -#ifdef WIN32 +#ifdef MSWIN # include <lm.h> #endif @@ -56,7 +56,7 @@ int os_get_usernames(garray_T *users) } endpwent(); } -#elif defined(WIN32) +#elif defined(MSWIN) { DWORD nusers = 0, ntotal = 0, i; PUSER_INFO_0 uinfo; @@ -93,7 +93,7 @@ int os_get_usernames(garray_T *users) for (i = 0; i < users->ga_len; i++) { char *local_user = ((char **)users->ga_data)[i]; - if (STRCMP(local_user, user_env) == 0) { + if (strcmp(local_user, user_env) == 0) { break; } } @@ -208,14 +208,14 @@ char *get_users(expand_T *xp, int idx) /// @return 0 if name does not match any user name. /// 1 if name partially matches the beginning of a user name. /// 2 is name fully matches a user name. -int match_user(char_u *name) +int match_user(char *name) { - int n = (int)STRLEN(name); + int n = (int)strlen(name); int result = 0; init_users(); for (int i = 0; i < ga_users.ga_len; i++) { - if (STRCMP(((char_u **)ga_users.ga_data)[i], name) == 0) { + if (strcmp(((char **)ga_users.ga_data)[i], name) == 0) { return 2; // full match } if (STRNCMP(((char_u **)ga_users.ga_data)[i], name, n) == 0) { diff --git a/src/nvim/os/win_defs.h b/src/nvim/os/win_defs.h index 1ae86d6bbe..4f8a242a51 100644 --- a/src/nvim/os/win_defs.h +++ b/src/nvim/os/win_defs.h @@ -1,7 +1,7 @@ #ifndef NVIM_OS_WIN_DEFS_H #define NVIM_OS_WIN_DEFS_H -#ifndef WIN32 +#ifndef MSWIN # error Header must be included only when compiling for Windows. #endif diff --git a/src/nvim/path.c b/src/nvim/path.c index accd7badbb..d1a7e14c9f 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -73,7 +73,7 @@ FileComparison path_full_compare(char *const s1, char *const s2, const bool chec if (checkname) { vim_FullName(exp1, full1, MAXPATHL, false); vim_FullName(s2, full2, MAXPATHL, false); - if (FNAMECMP(full1, full2) == 0) { + if (path_fnamecmp(full1, full2) == 0) { return kEqualFileNames; } } @@ -190,7 +190,7 @@ const char *path_next_component(const char *fname) /// - 1 otherwise int path_head_length(void) { -#ifdef WIN32 +#ifdef MSWIN return 3; #else return 1; @@ -205,7 +205,7 @@ int path_head_length(void) /// - False otherwise bool is_path_head(const char_u *path) { -#ifdef WIN32 +#ifdef MSWIN return isalpha(path[0]) && path[1] == ':'; #else return vim_ispathsep(*path); @@ -219,7 +219,7 @@ char *get_past_head(const char *path) { const char *retval = path; -#ifdef WIN32 +#ifdef MSWIN // May skip "c:" if (is_path_head((char_u *)path)) { retval = path + 2; @@ -331,6 +331,12 @@ bool dir_of_file_exists(char_u *fname) /// Compare two file names /// +/// On some systems case in a file name does not matter, on others it does. +/// +/// @note Does not account for maximum name lengths and things like "../dir", +/// thus it is not 100% accurate. OS may also use different algorithm for +/// case-insensitive comparison. +/// /// Handles '/' and '\\' correctly and deals with &fileignorecase option. /// /// @param[in] fname1 First file name. @@ -575,7 +581,7 @@ bool path_has_exp_wildcard(const char_u *p) static size_t path_expand(garray_T *gap, const char_u *path, int flags) FUNC_ATTR_NONNULL_ALL { - return do_path_expand(gap, path, 0, flags, false); + return do_path_expand(gap, (char *)path, 0, flags, false); } static const char *scandir_next_with_dots(Directory *dir) @@ -596,7 +602,7 @@ static const char *scandir_next_with_dots(Directory *dir) /// Implementation of path_expand(). /// /// Chars before `path + wildoff` do not get expanded. -static size_t do_path_expand(garray_T *gap, const char_u *path, size_t wildoff, int flags, +static size_t do_path_expand(garray_T *gap, const char *path, size_t wildoff, int flags, bool didstar) FUNC_ATTR_NONNULL_ALL { @@ -623,20 +629,20 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, size_t wildoff, char_u *p = buf; char_u *s = buf; char_u *e = NULL; - const char_u *path_end = path; + const char_u *path_end = (char_u *)path; while (*path_end != NUL) { // May ignore a wildcard that has a backslash before it; it will // be removed by rem_backslash() or file_pat_to_reg_pat() below. - if (path_end >= path + wildoff && rem_backslash((char *)path_end)) { + if (path_end >= (char_u *)path + wildoff && rem_backslash((char *)path_end)) { *p++ = *path_end++; } else if (vim_ispathsep_nocolon(*path_end)) { if (e != NULL) { break; } s = p + 1; - } else if (path_end >= path + wildoff + } else if (path_end >= (char_u *)path + wildoff && (vim_strchr("*?[{~$", *path_end) != NULL -#ifndef WIN32 +#ifndef MSWIN || (!p_fic && (flags & EW_ICASE) && mb_isalpha(utf_ptr2char((char *)path_end))) #endif )) { @@ -704,7 +710,7 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, size_t wildoff, && *path_end == '/') { STRCPY(s, path_end + 1); stardepth++; - (void)do_path_expand(gap, buf, (size_t)(s - buf), flags, true); + (void)do_path_expand(gap, (char *)buf, (size_t)(s - buf), flags, true); stardepth--; } *s = NUL; @@ -713,17 +719,17 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, size_t wildoff, char *dirpath = (*buf == NUL ? "." : (char *)buf); if (os_file_is_readable(dirpath) && os_scandir(&dir, dirpath)) { // Find all matching entries. - char_u *name; + char *name; scandir_next_with_dots(NULL); // initialize - while (!got_int && (name = (char_u *)scandir_next_with_dots(&dir)) != NULL) { + while (!got_int && (name = (char *)scandir_next_with_dots(&dir)) != NULL) { if ((name[0] != '.' || starts_with_dot || ((flags & EW_DODOT) && name[1] != NUL && (name[1] != '.' || name[2] != NUL))) // -V557 - && ((regmatch.regprog != NULL && vim_regexec(®match, (char *)name, 0)) + && ((regmatch.regprog != NULL && vim_regexec(®match, name, 0)) || ((flags & EW_NOTWILD) - && FNAMENCMP(path + (s - buf), name, e - s) == 0))) { + && path_fnamencmp(path + (s - buf), name, (size_t)(e - s)) == 0))) { STRCPY(s, name); len = STRLEN(buf); @@ -733,7 +739,7 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, size_t wildoff, STRCPY(buf + len, "/**"); // NOLINT STRCPY(buf + len + 3, path_end); stardepth++; - (void)do_path_expand(gap, buf, len + 1, flags, true); + (void)do_path_expand(gap, (char *)buf, len + 1, flags, true); stardepth--; } @@ -741,7 +747,7 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, size_t wildoff, if (path_has_exp_wildcard(path_end)) { // handle more wildcards // need to expand another component of the path // remove backslashes for the remaining components only - (void)do_path_expand(gap, buf, len + 1, flags, false); + (void)do_path_expand(gap, (char *)buf, len + 1, flags, false); } else { FileInfo file_info; @@ -797,21 +803,21 @@ static int find_previous_pathsep(char_u *path, char_u **psep) /// Returns true if "maybe_unique" is unique wrt other_paths in "gap". /// "maybe_unique" is the end portion of "((char_u **)gap->ga_data)[i]". -static bool is_unique(char_u *maybe_unique, garray_T *gap, int i) +static bool is_unique(char *maybe_unique, garray_T *gap, int i) { - char_u **other_paths = (char_u **)gap->ga_data; + char **other_paths = gap->ga_data; for (int j = 0; j < gap->ga_len; j++) { if (j == i) { continue; // don't compare it with itself } - size_t candidate_len = STRLEN(maybe_unique); - size_t other_path_len = STRLEN(other_paths[j]); + size_t candidate_len = strlen(maybe_unique); + size_t other_path_len = strlen(other_paths[j]); if (other_path_len < candidate_len) { continue; // it's different when it's shorter } - char_u *rival = other_paths[j] + other_path_len - candidate_len; - if (FNAMECMP(maybe_unique, rival) == 0 + char *rival = other_paths[j] + other_path_len - candidate_len; + if (path_fnamecmp(maybe_unique, rival) == 0 && (rival == other_paths[j] || vim_ispathsep(*(rival - 1)))) { return false; // match } @@ -843,7 +849,7 @@ static void expand_path_option(char_u *curdir, garray_T *gap) } char_u *p = (char_u *)path_tail(curbuf->b_ffname); size_t len = (size_t)(p - (char_u *)curbuf->b_ffname); - if (len + STRLEN(buf) >= MAXPATHL) { + if (len + strlen(buf) >= MAXPATHL) { continue; } if (buf[1] == NUL) { @@ -860,7 +866,7 @@ static void expand_path_option(char_u *curdir, garray_T *gap) } else if (!path_is_absolute((char_u *)buf)) { // Expand relative path to their full path equivalent size_t len = STRLEN(curdir); - if (len + STRLEN(buf) + 3 > MAXPATHL) { + if (len + strlen(buf) + 3 > MAXPATHL) { continue; } STRMOVE(buf + len + 1, buf); @@ -891,7 +897,7 @@ static char_u *get_path_cutoff(char_u *fname, garray_T *gap) int j = 0; while ((fname[j] == path_part[i][j] -#ifdef WIN32 +#ifdef MSWIN || (vim_ispathsep(fname[j]) && vim_ispathsep(path_part[i][j])) #endif ) // NOLINT(whitespace/parens) @@ -950,9 +956,9 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern) return; } - char_u *curdir = xmalloc(MAXPATHL); - os_dirname(curdir, MAXPATHL); - expand_path_option(curdir, &path_ga); + char *curdir = xmalloc(MAXPATHL); + os_dirname((char_u *)curdir, MAXPATHL); + expand_path_option((char_u *)curdir, &path_ga); in_curdir = xcalloc((size_t)gap->ga_len, sizeof(char_u *)); @@ -964,7 +970,7 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern) char *path_cutoff; len = STRLEN(path); - is_in_curdir = FNAMENCMP(curdir, path, dir_end - path) == 0 + is_in_curdir = path_fnamencmp(curdir, path, (size_t)(dir_end - path)) == 0 && curdir[dir_end - path] == NUL; if (is_in_curdir) { in_curdir[i] = xstrdup(path); @@ -980,19 +986,19 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern) && vim_ispathsep_nocolon(pattern[2]) && path_cutoff != NULL && vim_regexec(®match, path_cutoff, (colnr_T)0) - && is_unique((char_u *)path_cutoff, gap, i)) { + && is_unique(path_cutoff, gap, i)) { sort_again = true; - memmove(path, path_cutoff, STRLEN(path_cutoff) + 1); + memmove(path, path_cutoff, strlen(path_cutoff) + 1); } else { // Here all files can be reached without path, so get shortest // unique path. We start at the end of the path. */ pathsep_p = path + len - 1; while (find_previous_pathsep((char_u *)path, (char_u **)&pathsep_p)) { if (vim_regexec(®match, pathsep_p + 1, (colnr_T)0) - && is_unique((char_u *)pathsep_p + 1, gap, i) + && is_unique(pathsep_p + 1, gap, i) && path_cutoff != NULL && pathsep_p + 1 >= path_cutoff) { sort_again = true; - memmove(path, pathsep_p + 1, STRLEN(pathsep_p)); + memmove(path, pathsep_p + 1, strlen(pathsep_p)); break; } } @@ -1009,7 +1015,7 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern) // c:\foo\bar\file.txt c:\foo\bar .\file.txt // /file.txt / /file.txt // c:\file.txt c:\ .\file.txt - short_name = (char *)path_shorten_fname((char_u *)path, curdir); + short_name = path_shorten_fname(path, curdir); if (short_name != NULL && short_name > path + 1) { STRCPY(path, "."); add_pathsep(path); @@ -1030,16 +1036,16 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern) // If the {filename} is not unique, change it to ./{filename}. // Else reduce it to {filename} - short_name = (char *)path_shorten_fname((char_u *)path, curdir); + short_name = path_shorten_fname(path, curdir); if (short_name == NULL) { short_name = path; } - if (is_unique((char_u *)short_name, gap, i)) { + if (is_unique(short_name, gap, i)) { STRCPY(fnames[i], short_name); continue; } - rel_path = xmalloc(STRLEN(short_name) + STRLEN(PATHSEPSTR) + 2); + rel_path = xmalloc(strlen(short_name) + strlen(PATHSEPSTR) + 2); STRCPY(rel_path, "."); add_pathsep(rel_path); STRCAT(rel_path, short_name); @@ -1266,12 +1272,12 @@ int gen_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, i } } - // If there are wildcards: Expand file names and add each match to - // the list. If there is no match, and EW_NOTFOUND is given, add - // the pattern. - // If there are no wildcards: Add the file name if it exists or - // when EW_NOTFOUND is given. - if (path_has_exp_wildcard(p)) { + // If there are wildcards or case-insensitive expansion is + // required: Expand file names and add each match to the list. If + // there is no match, and EW_NOTFOUND is given, add the pattern. + // Otherwise: Add the file name if it exists or when EW_NOTFOUND is + // given. + if (path_has_exp_wildcard(p) || (flags & EW_ICASE)) { if ((flags & EW_PATH) && !path_is_absolute(p) && !(p[0] == '.' @@ -1354,7 +1360,7 @@ static int expand_backtick(garray_T *gap, char *pat, int flags) int cnt = 0; // Create the command: lop off the backticks. - char *cmd = xstrnsave(pat + 1, STRLEN(pat) - 2); + char *cmd = xstrnsave(pat + 1, strlen(pat) - 2); if (*cmd == '=') { // `={expr}`: Expand expression buffer = eval_to_string(cmd + 1, &p, true); @@ -1409,7 +1415,7 @@ void slash_adjust(char_u *p) if (*p == '`') { // don't replace backslash in backtick quoted strings - const size_t len = STRLEN(p); + const size_t len = strlen(p); if (len > 2 && *(p + len - 1) == '`') { return; } @@ -1672,7 +1678,7 @@ char *find_file_name_in_path(char *ptr, size_t len, int options, long count, cha tofree = eval_includeexpr(ptr, len); if (tofree != NULL) { ptr = tofree; - len = STRLEN(ptr); + len = strlen(ptr); } } @@ -1687,7 +1693,7 @@ char *find_file_name_in_path(char *ptr, size_t len, int options, long count, cha tofree = eval_includeexpr(ptr, len); if (tofree != NULL) { ptr = tofree; - len = STRLEN(ptr); + len = strlen(ptr); file_name = (char *)find_file_in_path((char_u *)ptr, len, options & ~FNAME_MESS, true, (char_u *)rel_fname); } @@ -1810,7 +1816,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 WIN32 +#ifdef MSWIN slash_adjust((char_u *)buf); #endif return FAIL; @@ -1825,7 +1831,7 @@ int vim_FullName(const char *fname, char *buf, size_t len, bool force) if (rv == FAIL) { xstrlcpy(buf, fname, len); // something failed; use the filename } -#ifdef WIN32 +#ifdef MSWIN slash_adjust((char_u *)buf); #endif return rv; @@ -2037,7 +2043,7 @@ char_u *path_try_shorten_fname(char_u *full_path) char_u *p = full_path; if (os_dirname(dirname, MAXPATHL) == OK) { - p = path_shorten_fname(full_path, dirname); + p = (char_u *)path_shorten_fname((char *)full_path, (char *)dirname); if (p == NULL || *p == NUL) { p = full_path; } @@ -2053,27 +2059,27 @@ char_u *path_try_shorten_fname(char_u *full_path) /// @return /// - Pointer into `full_path` if shortened. /// - NULL if no shorter name is possible. -char_u *path_shorten_fname(char_u *full_path, char_u *dir_name) +char *path_shorten_fname(char *full_path, char *dir_name) { if (full_path == NULL) { return NULL; } assert(dir_name != NULL); - size_t len = STRLEN(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(dir_name)) { + if (len == (size_t)path_head_length() && is_path_head((char_u *)dir_name)) { return full_path + len; } // If full_path and dir_name do not match, it's impossible to make one // relative to the other. - if (FNAMENCMP(dir_name, full_path, len) != 0) { + if (path_fnamencmp(dir_name, full_path, len) != 0) { return NULL; } - char_u *p = full_path + len; + char_u *p = (char_u *)full_path + len; // If *p is not pointing to a path separator, this means that full_path's // last directory name is longer than *dir_name's last directory, so they @@ -2082,7 +2088,7 @@ char_u *path_shorten_fname(char_u *full_path, char_u *dir_name) return NULL; } - return p + 1; + return (char *)p + 1; } /// Invoke expand_wildcards() for one pattern @@ -2200,7 +2206,7 @@ int expand_wildcards(int num_pat, char **pat, int *num_files, char ***files, int if (*num_files > 1 && !got_int) { non_suf_match = 0; for (i = 0; i < *num_files; i++) { - if (!match_suffix((char_u *)(*files)[i])) { + if (!match_suffix((*files)[i])) { // Move the name without matching suffix to the front of the list. p = (char_u *)(*files)[i]; for (j = i; j > non_suf_match; j--) { @@ -2220,27 +2226,27 @@ int expand_wildcards(int num_pat, char **pat, int *num_files, char ***files, int return retval; } -/// Return true if "fname" matches with an entry in 'suffixes'. -int match_suffix(char_u *fname) +/// @return true if "fname" matches with an entry in 'suffixes'. +int match_suffix(char *fname) { #define MAXSUFLEN 30 // maximum length of a file suffix - char_u suf_buf[MAXSUFLEN]; + char suf_buf[MAXSUFLEN]; - size_t fnamelen = STRLEN(fname); + size_t fnamelen = strlen(fname); size_t setsuflen = 0; for (char_u *setsuf = p_su; *setsuf;) { setsuflen = copy_option_part((char **)&setsuf, (char *)suf_buf, MAXSUFLEN, ".,"); if (setsuflen == 0) { - char_u *tail = (char_u *)path_tail((char *)fname); + char *tail = path_tail(fname); // empty entry: match name without a '.' - if (vim_strchr((char *)tail, '.') == NULL) { + if (vim_strchr(tail, '.') == NULL) { setsuflen = 1; break; } } else { if (fnamelen >= setsuflen - && FNAMENCMP(suf_buf, fname + fnamelen - setsuflen, setsuflen) == 0) { + && path_fnamencmp(suf_buf, fname + fnamelen - setsuflen, setsuflen) == 0) { break; } setsuflen = 0; @@ -2350,7 +2356,7 @@ static int path_to_absolute(const char *fname, char *buf, size_t len, int force) // expand it if forced or not an absolute path if (force || !path_is_absolute((char_u *)fname)) { p = strrchr(fname, '/'); -#ifdef WIN32 +#ifdef MSWIN if (p == NULL) { p = strrchr(fname, '\\'); } @@ -2386,7 +2392,7 @@ static int path_to_absolute(const char *fname, char *buf, size_t len, int force) /// @return `true` if "fname" is absolute. int path_is_absolute(const char_u *fname) { -#ifdef WIN32 +#ifdef MSWIN if (*fname == NUL) { return false; } @@ -2434,8 +2440,8 @@ void path_guess_exepath(const char *argv0, char *buf, size_t bufsize) continue; } STRLCPY(NameBuff, dir, dir_len + 1); - STRLCAT(NameBuff, PATHSEPSTR, sizeof(NameBuff)); - STRLCAT(NameBuff, argv0, sizeof(NameBuff)); + xstrlcat(NameBuff, PATHSEPSTR, sizeof(NameBuff)); + xstrlcat(NameBuff, argv0, sizeof(NameBuff)); if (os_can_exe((char *)NameBuff, NULL, false)) { xstrlcpy(buf, (char *)NameBuff, bufsize); return; diff --git a/src/nvim/popupmenu.c b/src/nvim/popupmenu.c index 4de3713f4f..5483c9cb94 100644 --- a/src/nvim/popupmenu.c +++ b/src/nvim/popupmenu.c @@ -542,7 +542,7 @@ void pum_redraw(void) size++; } } - grid_puts_len(&pum_grid, rt, (int)STRLEN(rt), row, grid_col - size + 1, attr); + grid_puts_len(&pum_grid, rt, (int)strlen(rt), row, grid_col - size + 1, attr); xfree(rt_start); xfree(st); grid_col -= width; diff --git a/src/nvim/profile.c b/src/nvim/profile.c index cded231c85..50a8a371f5 100644 --- a/src/nvim/profile.c +++ b/src/nvim/profile.c @@ -291,23 +291,23 @@ void ex_profile(exarg_T *eap) set_vim_var_nr(VV_PROFILING, 1L); } else if (do_profiling == PROF_NONE) { emsg(_("E750: First use \":profile start {fname}\"")); - } else if (STRCMP(eap->arg, "stop") == 0) { + } else if (strcmp(eap->arg, "stop") == 0) { profile_dump(); do_profiling = PROF_NONE; set_vim_var_nr(VV_PROFILING, 0L); profile_reset(); - } else if (STRCMP(eap->arg, "pause") == 0) { + } else if (strcmp(eap->arg, "pause") == 0) { if (do_profiling == PROF_YES) { pause_time = profile_start(); } do_profiling = PROF_PAUSED; - } else if (STRCMP(eap->arg, "continue") == 0) { + } else if (strcmp(eap->arg, "continue") == 0) { if (do_profiling == PROF_PAUSED) { pause_time = profile_end(pause_time); profile_set_wait(profile_add(profile_get_wait(), pause_time)); } do_profiling = PROF_YES; - } else if (STRCMP(eap->arg, "dump") == 0) { + } else if (strcmp(eap->arg, "dump") == 0) { profile_dump(); } else { // The rest is similar to ":breakadd". @@ -728,7 +728,7 @@ static void script_dump_profile(FILE *fd) // Keep going till the end of file, so that trailing // continuation lines are listed. for (int i = 0;; i++) { - if (vim_fgets(IObuff, IOSIZE, sfd)) { + if (vim_fgets((char_u *)IObuff, IOSIZE, sfd)) { break; } // When a line has been truncated, append NL, taking care diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index cd2dd4b89c..eeba7fe3c3 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -548,9 +548,9 @@ static void free_efm_list(efm_T **efm_first) /// a regular expression pattern. static size_t efm_regpat_bufsz(char *efm) { - size_t sz = (FMT_PATTERNS * 3) + (STRLEN(efm) << 2); + size_t sz = (FMT_PATTERNS * 3) + (strlen(efm) << 2); for (int i = FMT_PATTERNS - 1; i >= 0;) { - sz += STRLEN(fmt_pat[i--].pattern); + sz += strlen(fmt_pat[i--].pattern); } #ifdef BACKSLASH_IN_FILENAME sz += 12; // "%f" can become twelve chars longer (see efm_to_regpat) @@ -652,7 +652,7 @@ static int qf_get_next_str_line(qfstate_T *state) } char *p = vim_strchr(p_str, '\n'); - size_t len = (p != NULL) ? (size_t)(p - p_str) + 1 : STRLEN(p_str); + size_t len = (p != NULL) ? (size_t)(p - p_str) + 1 : strlen(p_str); if (len > IOSIZE - 2) { state->linebuf = qf_grow_linebuf(state, len); @@ -688,7 +688,7 @@ static int qf_get_next_list_line(qfstate_T *state) return QF_END_OF_INPUT; } - size_t len = STRLEN(TV_LIST_ITEM_TV(p_li)->vval.v_string); + size_t len = strlen(TV_LIST_ITEM_TV(p_li)->vval.v_string); if (len > IOSIZE - 2) { state->linebuf = qf_grow_linebuf(state, len); } else { @@ -713,7 +713,7 @@ static int qf_get_next_buf_line(qfstate_T *state) char *p_buf = ml_get_buf(state->buf, state->buflnum, false); state->buflnum += 1; - size_t len = STRLEN(p_buf); + size_t len = strlen(p_buf); if (len > IOSIZE - 2) { state->linebuf = qf_grow_linebuf(state, len); } else { @@ -738,7 +738,7 @@ retry: } bool discard = false; - state->linelen = STRLEN(IObuff); + state->linelen = strlen(IObuff); if (state->linelen == IOSIZE - 1 && !(IObuff[state->linelen - 1] == '\n')) { // The current line exceeds IObuff, continue reading using growbuf @@ -761,7 +761,7 @@ retry: } break; } - state->linelen = STRLEN(state->growbuf + growbuflen); + state->linelen = strlen(state->growbuf + growbuflen); growbuflen += state->linelen; if (state->growbuf[growbuflen - 1] == '\n') { break; @@ -786,7 +786,7 @@ retry: } break; } - if (STRLEN(IObuff) < IOSIZE - 1 || IObuff[IOSIZE - 2] == '\n') { + if (strlen(IObuff) < IOSIZE - 1 || IObuff[IOSIZE - 2] == '\n') { break; } } @@ -1098,7 +1098,7 @@ static int qf_init_ext(qf_info_T *qi, int qf_idx, const char *restrict efile, bu // If the errorformat didn't change between calls, then reuse the previously // parsed values. - if (last_efm == NULL || (STRCMP(last_efm, efm) != 0)) { + if (last_efm == NULL || (strcmp(last_efm, efm) != 0)) { // free the previously parsed data XFREE_CLEAR(last_efm); free_efm_list(&fmt_first); @@ -1175,7 +1175,7 @@ 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; + size_t len = strlen(title) + 1; char *p = xmallocz(len); qfl->qf_title = p; @@ -1242,10 +1242,10 @@ static int qf_parse_fmt_f(regmatch_T *rmp, int midx, qffields_T *fields, int pre } // Expand ~/file and $HOME/file to full path. - char c = (char)(*rmp->endp[midx]); + char c = *rmp->endp[midx]; *rmp->endp[midx] = NUL; - expand_env((char *)rmp->startp[midx], fields->namebuf, CMDBUFFSIZE); - *rmp->endp[midx] = (char_u)c; + expand_env(rmp->startp[midx], fields->namebuf, CMDBUFFSIZE); + *rmp->endp[midx] = c; // For separate filename patterns (%O, %P and %Q), the specified file // should exist. @@ -1264,7 +1264,7 @@ static int qf_parse_fmt_n(regmatch_T *rmp, int midx, qffields_T *fields) if (rmp->startp[midx] == NULL) { return QF_FAIL; } - fields->enr = (int)atol((char *)rmp->startp[midx]); + fields->enr = (int)atol(rmp->startp[midx]); return QF_OK; } @@ -1275,7 +1275,7 @@ static int qf_parse_fmt_l(regmatch_T *rmp, int midx, qffields_T *fields) if (rmp->startp[midx] == NULL) { return QF_FAIL; } - fields->lnum = (linenr_T)atol((char *)rmp->startp[midx]); + fields->lnum = (linenr_T)atol(rmp->startp[midx]); return QF_OK; } @@ -1286,7 +1286,7 @@ static int qf_parse_fmt_e(regmatch_T *rmp, int midx, qffields_T *fields) if (rmp->startp[midx] == NULL) { return QF_FAIL; } - fields->end_lnum = (linenr_T)atol((char *)rmp->startp[midx]); + fields->end_lnum = (linenr_T)atol(rmp->startp[midx]); return QF_OK; } @@ -1297,7 +1297,7 @@ static int qf_parse_fmt_c(regmatch_T *rmp, int midx, qffields_T *fields) if (rmp->startp[midx] == NULL) { return QF_FAIL; } - fields->col = (int)atol((char *)rmp->startp[midx]); + fields->col = (int)atol(rmp->startp[midx]); return QF_OK; } @@ -1308,7 +1308,7 @@ static int qf_parse_fmt_k(regmatch_T *rmp, int midx, qffields_T *fields) if (rmp->startp[midx] == NULL) { return QF_FAIL; } - fields->end_col = (int)atol((char *)rmp->startp[midx]); + fields->end_col = (int)atol(rmp->startp[midx]); return QF_OK; } @@ -1319,7 +1319,7 @@ static int qf_parse_fmt_t(regmatch_T *rmp, int midx, qffields_T *fields) if (rmp->startp[midx] == NULL) { return QF_FAIL; } - fields->type = (char)(*rmp->startp[midx]); + fields->type = *rmp->startp[midx]; return QF_OK; } @@ -1360,7 +1360,7 @@ static int qf_parse_fmt_r(regmatch_T *rmp, int midx, char **tail) if (rmp->startp[midx] == NULL) { return QF_FAIL; } - *tail = (char *)rmp->startp[midx]; + *tail = rmp->startp[midx]; return QF_OK; } @@ -1372,7 +1372,7 @@ static int qf_parse_fmt_p(regmatch_T *rmp, int midx, qffields_T *fields) return QF_FAIL; } fields->col = 0; - for (char *match_ptr = (char *)rmp->startp[midx]; (char_u *)match_ptr != rmp->endp[midx]; + for (char *match_ptr = rmp->startp[midx]; match_ptr != rmp->endp[midx]; match_ptr++) { fields->col++; if (*match_ptr == TAB) { @@ -1392,7 +1392,7 @@ static int qf_parse_fmt_v(regmatch_T *rmp, int midx, qffields_T *fields) if (rmp->startp[midx] == NULL) { return QF_FAIL; } - fields->col = (int)atol((char *)rmp->startp[midx]); + fields->col = (int)atol(rmp->startp[midx]); fields->use_viscol = true; return QF_OK; } @@ -1409,7 +1409,7 @@ static int qf_parse_fmt_s(regmatch_T *rmp, int midx, qffields_T *fields) len = CMDBUFFSIZE - 5; } STRCPY(fields->pattern, "^\\V"); - STRLCAT(fields->pattern, rmp->startp[midx], len + 4); + xstrlcat(fields->pattern, rmp->startp[midx], len + 4); fields->pattern[len + 3] = '\\'; fields->pattern[len + 4] = '$'; fields->pattern[len + 5] = NUL; @@ -1424,11 +1424,11 @@ static int qf_parse_fmt_o(regmatch_T *rmp, int midx, qffields_T *fields) return QF_FAIL; } size_t len = (size_t)(rmp->endp[midx] - rmp->startp[midx]); - size_t dsize = STRLEN(fields->module) + len + 1; + size_t dsize = strlen(fields->module) + len + 1; if (dsize > CMDBUFFSIZE) { dsize = CMDBUFFSIZE; } - STRLCAT(fields->module, rmp->startp[midx], dsize); + xstrlcat(fields->module, rmp->startp[midx], dsize); return QF_OK; } @@ -1609,8 +1609,8 @@ static int qf_parse_multiline_pfx(int idx, qf_list_T *qfl, qffields_T *fields) return QF_FAIL; } if (*fields->errmsg) { - size_t textlen = STRLEN(qfprev->qf_text); - size_t errlen = STRLEN(fields->errmsg); + size_t textlen = strlen(qfprev->qf_text); + size_t errlen = strlen(fields->errmsg); qfprev->qf_text = xrealloc(qfprev->qf_text, textlen + errlen + 2); qfprev->qf_text[textlen] = '\n'; STRCPY(qfprev->qf_text + textlen + 1, fields->errmsg); @@ -2085,7 +2085,7 @@ static int qf_get_fnum(qf_list_T *qfl, char *directory, char *fname) } if (qf_last_bufname != NULL - && STRCMP(bufname, qf_last_bufname) == 0 + && strcmp(bufname, qf_last_bufname) == 0 && bufref_valid(&qf_last_bufref)) { buf = qf_last_bufref.br_buf; xfree(ptr); @@ -2791,7 +2791,7 @@ static void qf_jump_print_msg(qf_info_T *qi, int qf_index, qfline_T *qf_ptr, buf qf_ptr->qf_cleared ? _(" (line deleted)") : "", qf_types(qf_ptr->qf_type, qf_ptr->qf_nr)); // Add the message, skipping leading whitespace and newlines. - int len = (int)STRLEN(IObuff); + int len = (int)strlen(IObuff); qf_fmt_text(skipwhite(qf_ptr->qf_text), (char *)IObuff + len, IOSIZE - len); // Output the message. Overwrite to avoid scrolling when the 'O' @@ -3064,7 +3064,7 @@ static void qf_list_entry(qfline_T *qfp, int qf_idx, bool cursel) } else { qf_range_text(qfp, (char *)IObuff, IOSIZE); } - vim_snprintf((char *)IObuff + STRLEN(IObuff), IOSIZE, "%s", qf_types(qfp->qf_type, qfp->qf_nr)); + vim_snprintf((char *)IObuff + strlen(IObuff), IOSIZE, "%s", qf_types(qfp->qf_type, qfp->qf_nr)); msg_puts_attr((const char *)IObuff, qfLineAttr); msg_puts_attr(":", qfSepAttr); if (qfp->qf_pattern != NULL) { @@ -3074,9 +3074,9 @@ static void qf_list_entry(qfline_T *qfp, int qf_idx, bool cursel) } msg_puts(" "); - char_u *tbuf = IObuff; + char *tbuf = IObuff; size_t tbuflen = IOSIZE; - size_t len = STRLEN(qfp->qf_text) + 3; + size_t len = strlen(qfp->qf_text) + 3; if (len > IOSIZE) { tbuf = xmalloc(len); @@ -3088,8 +3088,8 @@ static void qf_list_entry(qfline_T *qfp, int qf_idx, bool cursel) // with ^^^^. qf_fmt_text((fname != NULL || qfp->qf_lnum != 0) ? skipwhite(qfp->qf_text) : qfp->qf_text, - (char *)tbuf, (int)tbuflen); - msg_prt_line((char *)tbuf, false); + tbuf, (int)tbuflen); + msg_prt_line(tbuf, false); if (tbuf != IObuff) { xfree(tbuf); @@ -3198,18 +3198,18 @@ static void qf_fmt_text(const char *restrict text, char *restrict buf, int bufsi static void qf_range_text(const qfline_T *qfp, char *buf, int bufsize) { vim_snprintf(buf, (size_t)bufsize, "%" PRIdLINENR, qfp->qf_lnum); - int len = (int)STRLEN(buf); + int len = (int)strlen(buf); if (qfp->qf_end_lnum > 0 && qfp->qf_lnum != qfp->qf_end_lnum) { vim_snprintf(buf + len, (size_t)(bufsize - len), "-%" PRIdLINENR, qfp->qf_end_lnum); - len += (int)STRLEN(buf + len); + len += (int)strlen(buf + len); } if (qfp->qf_col > 0) { vim_snprintf(buf + len, (size_t)(bufsize - len), " col %d", qfp->qf_col); - len += (int)STRLEN(buf + len); + len += (int)strlen(buf + len); if (qfp->qf_end_col > 0 && qfp->qf_col != qfp->qf_end_col) { vim_snprintf(buf + len, (size_t)(bufsize - len), "-%d", qfp->qf_end_col); - len += (int)STRLEN(buf + len); + len += (int)strlen(buf + len); } } buf[len] = NUL; @@ -3230,13 +3230,13 @@ static void qf_msg(qf_info_T *qi, int which, char *lead) count); if (title != NULL) { - size_t len = STRLEN(buf); + size_t len = strlen(buf); if (len < 34) { memset(buf + len, ' ', 34 - len); buf[34] = NUL; } - STRLCAT(buf, title, IOSIZE); + xstrlcat(buf, title, IOSIZE); } trunc_string(buf, buf, Columns - 1, IOSIZE); msg(buf); @@ -3915,7 +3915,7 @@ static int qf_buf_add_line(qf_list_T *qfl, buf_T *buf, linenr_T lnum, const qfli int len; if (qfp->qf_module != NULL) { STRLCPY(IObuff, qfp->qf_module, IOSIZE); - len = (int)STRLEN(IObuff); + len = (int)strlen(IObuff); } else if (qfp->qf_fnum != 0 && (errbuf = buflist_findnr(qfp->qf_fnum)) != NULL && errbuf->b_fname != NULL) { @@ -3935,7 +3935,7 @@ static int qf_buf_add_line(qf_list_T *qfl, buf_T *buf, linenr_T lnum, const qfli } STRLCPY(IObuff, errbuf->b_fname, IOSIZE); } - len = (int)STRLEN(IObuff); + len = (int)strlen(IObuff); } else { len = 0; } @@ -3944,14 +3944,14 @@ static int qf_buf_add_line(qf_list_T *qfl, buf_T *buf, linenr_T lnum, const qfli } if (qfp->qf_lnum > 0) { qf_range_text(qfp, (char *)IObuff + len, IOSIZE - len); - len += (int)STRLEN(IObuff + len); + len += (int)strlen(IObuff + len); snprintf((char *)IObuff + len, (size_t)(IOSIZE - len), "%s", qf_types(qfp->qf_type, qfp->qf_nr)); - len += (int)STRLEN(IObuff + len); + len += (int)strlen(IObuff + len); } else if (qfp->qf_pattern != NULL) { qf_fmt_text(qfp->qf_pattern, (char *)IObuff + len, IOSIZE - len); - len += (int)STRLEN(IObuff + len); + len += (int)strlen(IObuff + len); } if (len < IOSIZE - 2) { IObuff[len++] = '|'; @@ -3965,7 +3965,7 @@ static int qf_buf_add_line(qf_list_T *qfl, buf_T *buf, linenr_T lnum, const qfli (char *)IObuff + len, IOSIZE - len); } - if (ml_append_buf(buf, lnum, IObuff, + if (ml_append_buf(buf, lnum, (char_u *)IObuff, (colnr_T)STRLEN(IObuff) + 1, false) == FAIL) { return FAIL; } @@ -4180,8 +4180,7 @@ int grep_internal(cmdidx_T cmdidx) || cmdidx == CMD_lgrep || cmdidx == CMD_grepadd || cmdidx == CMD_lgrepadd) - && STRCMP("internal", - *curbuf->b_p_gp == NUL ? p_gp : (char_u *)curbuf->b_p_gp) == 0; + && strcmp("internal", *curbuf->b_p_gp == NUL ? p_gp : curbuf->b_p_gp) == 0; } // Return the make/grep autocmd name. @@ -4211,9 +4210,9 @@ static char *make_get_auname(cmdidx_T cmdidx) static char *make_get_fullcmd(const char *makecmd, const char *fname) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET { - size_t len = STRLEN(p_shq) * 2 + STRLEN(makecmd) + 1; + size_t len = STRLEN(p_shq) * 2 + strlen(makecmd) + 1; if (*p_sp != NUL) { - len += STRLEN(p_sp) + STRLEN(fname) + 3; + len += strlen(p_sp) + strlen(fname) + 3; } char *const cmd = xmalloc(len); snprintf(cmd, len, "%s%s%s", (char *)p_shq, (char *)makecmd, (char *)p_shq); @@ -4343,9 +4342,9 @@ static char *get_mef_name(void) } else { off += 19; } - name = xmalloc(STRLEN(p_mef) + 30); + name = xmalloc(strlen(p_mef) + 30); STRCPY(name, p_mef); - snprintf(name + (p - p_mef), STRLEN(name), "%d%d", start, off); + snprintf(name + (p - p_mef), strlen(name), "%d%d", start, off); STRCAT(name, p + 2); // Don't accept a symbolic link, it's a security risk. FileInfo file_info; @@ -5138,7 +5137,7 @@ static bool vgr_match_buflines(qf_list_T *qfl, char *fname, buf_T *buf, char *sp FUNC_ATTR_NONNULL_ARG(1, 3, 4, 5, 6) { bool found_match = false; - const size_t pat_len = STRLEN(spat); + const size_t pat_len = strlen(spat); for (linenr_T lnum = 1; lnum <= buf->b_ml.ml_line_count && *tomatch > 0; lnum++) { colnr_T col = 0; @@ -5175,7 +5174,7 @@ static bool vgr_match_buflines(qf_list_T *qfl, char *fname, buf_T *buf, char *sp break; } col = regmatch->endpos[0].col + (col == regmatch->endpos[0].col); - if (col > (colnr_T)STRLEN(ml_get_buf(buf, lnum, false))) { + if (col > (colnr_T)strlen(ml_get_buf(buf, lnum, false))) { break; } } @@ -5218,7 +5217,7 @@ static bool vgr_match_buflines(qf_list_T *qfl, char *fname, buf_T *buf, char *sp break; } col = (colnr_T)matches[pat_len - 1] + col + 1; - if (col > (colnr_T)STRLEN(str)) { + if (col > (colnr_T)strlen(str)) { break; } } @@ -5417,7 +5416,7 @@ static int vgr_process_files(win_T *wp, qf_info_T *qi, vgr_args_T *cmd_args, boo // directory we jumped to below. if (buf == *first_match_buf && *target_dir == NULL - && STRCMP(dirname_start, dirname_now) != 0) { + && strcmp(dirname_start, dirname_now) != 0) { *target_dir = xstrdup(dirname_now); } @@ -5540,7 +5539,7 @@ static void restore_start_dir(char *dirname_start) char *dirname_now = xmalloc(MAXPATHL); os_dirname((char_u *)dirname_now, MAXPATHL); - if (STRCMP(dirname_start, dirname_now) != 0) { + if (strcmp(dirname_start, dirname_now) != 0) { // If the directory has changed, change it back by building up an // appropriate ex command and executing it. exarg_T ea = { @@ -6498,7 +6497,7 @@ static int qf_setprop_curidx(qf_info_T *qi, qf_list_T *qfl, const dictitem_T *di // If the specified index is '$', then use the last entry if (di->di_tv.v_type == VAR_STRING && di->di_tv.vval.v_string != NULL - && STRCMP(di->di_tv.vval.v_string, "$") == 0) { + && strcmp(di->di_tv.vval.v_string, "$") == 0) { newidx = qfl->qf_count; } else { // Otherwise use the specified index @@ -6949,11 +6948,11 @@ static void hgr_search_file(qf_list_T *qfl, char *fname, regmatch_T *p_regmatch) } linenr_T lnum = 1; - while (!vim_fgets(IObuff, IOSIZE, fd) && !got_int) { + while (!vim_fgets((char_u *)IObuff, IOSIZE, fd) && !got_int) { char *line = (char *)IObuff; if (vim_regexec(p_regmatch, line, (colnr_T)0)) { - int l = (int)STRLEN(line); + int l = (int)strlen(line); // remove trailing CR, LF, spaces, etc. while (l > 0 && line[l - 1] <= ' ') { @@ -6968,8 +6967,8 @@ static void hgr_search_file(qf_list_T *qfl, char *fname, regmatch_T *p_regmatch) line, lnum, 0, - (int)(p_regmatch->startp[0] - (char_u *)line) + 1, // col - (int)(p_regmatch->endp[0] - (char_u *)line) + (int)(p_regmatch->startp[0] - line) + 1, // col + (int)(p_regmatch->endp[0] - line) + 1, // end_col false, // vis_col NULL, // search pattern @@ -6978,13 +6977,13 @@ static void hgr_search_file(qf_list_T *qfl, char *fname, regmatch_T *p_regmatch) true) // valid == QF_FAIL) { got_int = true; - if ((char_u *)line != IObuff) { + if (line != IObuff) { xfree(line); } break; } } - if ((char_u *)line != IObuff) { + if (line != IObuff) { xfree(line); } lnum++; @@ -7010,9 +7009,9 @@ static void hgr_search_files_in_dir(qf_list_T *qfl, char *dirname, regmatch_T *p for (int fi = 0; fi < fcount && !got_int; fi++) { // Skip files for a different language. if (lang != NULL - && STRNICMP(lang, fnames[fi] + STRLEN(fnames[fi]) - 3, 2) != 0 + && STRNICMP(lang, fnames[fi] + strlen(fnames[fi]) - 3, 2) != 0 && !(STRNICMP(lang, "en", 2) == 0 - && STRNICMP("txt", fnames[fi] + STRLEN(fnames[fi]) - 3, 3) + && STRNICMP("txt", fnames[fi] + strlen(fnames[fi]) - 3, 3) == 0)) { continue; } diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index a94f91d103..e87382ff7c 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -227,8 +227,8 @@ static int get_char_class(char **pp) if ((*pp)[1] == ':') { for (i = 0; i < (int)ARRAY_SIZE(class_names); i++) { - if (STRNCMP(*pp + 2, class_names[i], STRLEN(class_names[i])) == 0) { - *pp += STRLEN(class_names[i]) + 2; + if (STRNCMP(*pp + 2, class_names[i], strlen(class_names[i])) == 0) { + *pp += strlen(class_names[i]) + 2; return i; } } @@ -1545,8 +1545,8 @@ char *regtilde(char *source, int magic, bool preview) if ((*p == '~' && magic) || (*p == '\\' && *(p + 1) == '~' && !magic)) { if (reg_prev_sub != NULL) { // length = len(newsub) - 1 + len(prev_sub) + 1 - prevlen = (int)STRLEN(reg_prev_sub); - tmpsub = xmalloc(STRLEN(newsub) + (size_t)prevlen); + prevlen = (int)strlen(reg_prev_sub); + tmpsub = xmalloc(strlen(newsub) + (size_t)prevlen); // copy prefix len = (int)(p - newsub); // not including ~ memmove(tmpsub, newsub, (size_t)len); @@ -1605,12 +1605,12 @@ static regsubmatch_T rsm; // can only be used when can_f_submatch is true /// Put the submatches in "argv[argskip]" which is a list passed into /// call_func() by vim_regsub_both(). -static int fill_submatch_list(int argc FUNC_ATTR_UNUSED, typval_T *argv, int argskip, int argcount) +static int fill_submatch_list(int argc FUNC_ATTR_UNUSED, typval_T *argv, int argskip, ufunc_T *fp) FUNC_ATTR_NONNULL_ALL { typval_T *listarg = argv + argskip; - if (argcount == argskip) { + if (!fp->uf_varargs && fp->uf_args.ga_len <= argskip) { // called function doesn't take a submatches argument return argskip; } @@ -1621,11 +1621,11 @@ static int fill_submatch_list(int argc FUNC_ATTR_UNUSED, typval_T *argv, int arg // There are always 10 list items in staticList10_T. listitem_T *li = tv_list_first(listarg->vval.v_list); for (int i = 0; i < 10; i++) { - char *s = (char *)rsm.sm_match->startp[i]; + char *s = rsm.sm_match->startp[i]; if (s == NULL || rsm.sm_match->endp[i] == NULL) { s = NULL; } else { - s = xstrnsave(s, (size_t)(rsm.sm_match->endp[i] - (char_u *)s)); + s = xstrnsave(s, (size_t)(rsm.sm_match->endp[i] - s)); } TV_LIST_ITEM_TV(li)->v_type = VAR_STRING; TV_LIST_ITEM_TV(li)->vval.v_string = s; @@ -1767,7 +1767,7 @@ static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest, int des if (copy) { if (eval_result[nested] != NULL) { STRCPY(dest, eval_result[nested]); - dst += STRLEN(eval_result[nested]); + dst += strlen(eval_result[nested]); XFREE_CLEAR(eval_result[nested]); } } else { @@ -1803,8 +1803,8 @@ static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest, int des argv[0].v_type = VAR_LIST; argv[0].vval.v_list = &matchList.sl_list; funcexe_T funcexe = FUNCEXE_INIT; - funcexe.argv_func = fill_submatch_list; - funcexe.evaluate = true; + funcexe.fe_argv_func = fill_submatch_list; + funcexe.fe_evaluate = true; if (expr->v_type == VAR_FUNC) { s = (char_u *)expr->vval.v_string; call_func((char *)s, -1, &rettv, 1, argv, &funcexe); @@ -1812,7 +1812,7 @@ static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest, int des partial_T *partial = expr->vval.v_partial; s = (char_u *)partial_name(partial); - funcexe.partial = partial; + funcexe.fe_partial = partial; call_func((char *)s, -1, &rettv, 1, argv, &funcexe); } if (tv_list_len(&matchList.sl_list) > 0) { @@ -1865,7 +1865,7 @@ static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest, int des eval_result[nested] = (char *)s; } - dst += STRLEN(eval_result[nested]); + dst += strlen(eval_result[nested]); } can_f_submatch = prev_can_f_submatch; @@ -2006,11 +2006,11 @@ static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest, int des } } } else { - s = rex.reg_match->startp[no]; + s = (char_u *)rex.reg_match->startp[no]; if (rex.reg_match->endp[no] == NULL) { s = NULL; } else { - len = (int)(rex.reg_match->endp[no] - s); + len = (int)(rex.reg_match->endp[no] - (char *)s); } } if (s != NULL) { @@ -2172,7 +2172,7 @@ char *reg_submatch(int no) } else { // Multiple lines: take start line from start col, middle // lines completely and end line up to end col. - len = (ssize_t)STRLEN(s); + len = (ssize_t)strlen(s); if (round == 2) { STRCPY(retval, s); retval[len] = '\n'; @@ -2184,7 +2184,7 @@ char *reg_submatch(int no) if (round == 2) { STRCPY(retval + len, s); } - len += (ssize_t)STRLEN(s); + len += (ssize_t)strlen(s); if (round == 2) { retval[len] = '\n'; } @@ -2206,11 +2206,11 @@ char *reg_submatch(int no) } } } else { - s = (char *)rsm.sm_match->startp[no]; + s = rsm.sm_match->startp[no]; if (s == NULL || rsm.sm_match->endp[no] == NULL) { retval = NULL; } else { - retval = xstrnsave(s, (size_t)(rsm.sm_match->endp[no] - (char_u *)s)); + retval = xstrnsave(s, (size_t)(rsm.sm_match->endp[no] - s)); } } diff --git a/src/nvim/regexp_bt.c b/src/nvim/regexp_bt.c index 63e4dd5b7e..ac33fc0f13 100644 --- a/src/nvim/regexp_bt.c +++ b/src/nvim/regexp_bt.c @@ -5028,8 +5028,8 @@ static long bt_regexec_both(char_u *line, colnr_T col, proftime_T *tm, int *time rex.reg_endpos = rex.reg_mmatch->endpos; } else { prog = (bt_regprog_T *)rex.reg_match->regprog; - rex.reg_startp = rex.reg_match->startp; - rex.reg_endp = rex.reg_match->endp; + rex.reg_startp = (char_u **)rex.reg_match->startp; + rex.reg_endp = (char_u **)rex.reg_match->endp; } // Be paranoid... @@ -5594,7 +5594,7 @@ static char_u *regprop(char_u *op) case MOPEN + 7: case MOPEN + 8: case MOPEN + 9: - sprintf(buf + STRLEN(buf), "MOPEN%d", OP(op) - MOPEN); + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "MOPEN%d", OP(op) - MOPEN); p = NULL; break; case MCLOSE + 0: @@ -5609,7 +5609,7 @@ static char_u *regprop(char_u *op) case MCLOSE + 7: case MCLOSE + 8: case MCLOSE + 9: - sprintf(buf + STRLEN(buf), "MCLOSE%d", OP(op) - MCLOSE); + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "MCLOSE%d", OP(op) - MCLOSE); p = NULL; break; case BACKREF + 1: @@ -5621,7 +5621,7 @@ static char_u *regprop(char_u *op) case BACKREF + 7: case BACKREF + 8: case BACKREF + 9: - sprintf(buf + STRLEN(buf), "BACKREF%d", OP(op) - BACKREF); + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "BACKREF%d", OP(op) - BACKREF); p = NULL; break; case NOPEN: @@ -5639,7 +5639,7 @@ static char_u *regprop(char_u *op) case ZOPEN + 7: case ZOPEN + 8: case ZOPEN + 9: - sprintf(buf + STRLEN(buf), "ZOPEN%d", OP(op) - ZOPEN); + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "ZOPEN%d", OP(op) - ZOPEN); p = NULL; break; case ZCLOSE + 1: @@ -5651,7 +5651,7 @@ static char_u *regprop(char_u *op) case ZCLOSE + 7: case ZCLOSE + 8: case ZCLOSE + 9: - sprintf(buf + STRLEN(buf), "ZCLOSE%d", OP(op) - ZCLOSE); + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "ZCLOSE%d", OP(op) - ZCLOSE); p = NULL; break; case ZREF + 1: @@ -5663,7 +5663,7 @@ static char_u *regprop(char_u *op) case ZREF + 7: case ZREF + 8: case ZREF + 9: - sprintf(buf + STRLEN(buf), "ZREF%d", OP(op) - ZREF); + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "ZREF%d", OP(op) - ZREF); p = NULL; break; case STAR: @@ -5703,7 +5703,8 @@ static char_u *regprop(char_u *op) case BRACE_COMPLEX + 7: case BRACE_COMPLEX + 8: case BRACE_COMPLEX + 9: - sprintf(buf + STRLEN(buf), "BRACE_COMPLEX%d", OP(op) - BRACE_COMPLEX); + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "BRACE_COMPLEX%d", + OP(op) - BRACE_COMPLEX); p = NULL; break; case MULTIBYTECODE: @@ -5713,7 +5714,7 @@ static char_u *regprop(char_u *op) p = "NEWL"; break; default: - sprintf(buf + STRLEN(buf), "corrupt %d", OP(op)); + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "corrupt %d", OP(op)); p = NULL; break; } diff --git a/src/nvim/regexp_defs.h b/src/nvim/regexp_defs.h index 5d7175b89a..b24ed350e8 100644 --- a/src/nvim/regexp_defs.h +++ b/src/nvim/regexp_defs.h @@ -140,8 +140,8 @@ typedef struct { */ typedef struct { regprog_T *regprog; - char_u *startp[NSUBEXP]; - char_u *endp[NSUBEXP]; + char *startp[NSUBEXP]; + char *endp[NSUBEXP]; bool rm_ic; } regmatch_T; diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c index ea11398c30..fbd4e26c75 100644 --- a/src/nvim/regexp_nfa.c +++ b/src/nvim/regexp_nfa.c @@ -7402,8 +7402,8 @@ static long nfa_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm, int rex.reg_endpos = rex.reg_mmatch->endpos; } else { prog = (nfa_regprog_T *)rex.reg_match->regprog; - rex.reg_startp = rex.reg_match->startp; - rex.reg_endp = rex.reg_match->endp; + rex.reg_startp = (char_u **)rex.reg_match->startp; + rex.reg_endp = (char_u **)rex.reg_match->endp; } // Be paranoid... diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index a38f743081..935bf4c507 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -250,7 +250,7 @@ int do_in_path(char *path, char *name, int flags, DoInRuntimepathCB callback, vo while (*rtp != NUL && ((flags & DIP_ALL) || !did_one)) { // Copy the path from 'runtimepath' to buf[]. copy_option_part(&rtp, buf, MAXPATHL, ","); - size_t buflen = STRLEN(buf); + size_t buflen = strlen(buf); // Skip after or non-after directories. if (flags & (DIP_NOAFTER | DIP_AFTER)) { @@ -265,9 +265,9 @@ int do_in_path(char *path, char *name, int flags, DoInRuntimepathCB callback, vo if (name == NULL) { (*callback)(buf, cookie); did_one = true; - } else if (buflen + STRLEN(name) + 2 < MAXPATHL) { + } else if (buflen + strlen(name) + 2 < MAXPATHL) { add_pathsep(buf); - tail = buf + STRLEN(buf); + tail = buf + strlen(buf); // Loop over all patterns in "name" char *np = name; @@ -397,10 +397,10 @@ int do_in_cached_path(char *name, int flags, DoInRuntimepathCB callback, void *c if (name == NULL) { (*callback)(item.path, cookie); - } else if (buflen + STRLEN(name) + 2 < MAXPATHL) { + } else if (buflen + strlen(name) + 2 < MAXPATHL) { STRCPY(buf, item.path); add_pathsep(buf); - tail = buf + STRLEN(buf); + tail = buf + strlen(buf); // Loop over all patterns in "name" char *np = name; @@ -545,7 +545,7 @@ int do_in_path_and_pp(char *path, char *name, int flags, DoInRuntimepathCB callb if ((done == FAIL || (flags & DIP_ALL)) && (flags & DIP_START)) { char *start_dir = "pack/*/start/*/%s%s"; // NOLINT - size_t len = STRLEN(start_dir) + STRLEN(name) + 6; + size_t len = strlen(start_dir) + strlen(name) + 6; char *s = xmallocz(len); // TODO(bfredl): get rid of random allocations char *suffix = (flags & DIP_AFTER) ? "after/" : ""; @@ -556,7 +556,7 @@ int do_in_path_and_pp(char *path, char *name, int flags, DoInRuntimepathCB callb if (done == FAIL || (flags & DIP_ALL)) { start_dir = "start/*/%s%s"; // NOLINT - len = STRLEN(start_dir) + STRLEN(name) + 6; + len = strlen(start_dir) + strlen(name) + 6; s = xmallocz(len); vim_snprintf(s, len, start_dir, suffix, name); @@ -568,7 +568,7 @@ int do_in_path_and_pp(char *path, char *name, int flags, DoInRuntimepathCB callb if ((done == FAIL || (flags & DIP_ALL)) && (flags & DIP_OPT)) { char *opt_dir = "pack/*/opt/*/%s"; // NOLINT - size_t len = STRLEN(opt_dir) + STRLEN(name); + size_t len = strlen(opt_dir) + strlen(name); char *s = xmallocz(len); vim_snprintf(s, len, opt_dir, name); @@ -578,7 +578,7 @@ int do_in_path_and_pp(char *path, char *name, int flags, DoInRuntimepathCB callb if (done == FAIL || (flags & DIP_ALL)) { opt_dir = "opt/*/%s"; // NOLINT - len = STRLEN(opt_dir) + STRLEN(name); + len = strlen(opt_dir) + strlen(name); s = xmallocz(len); vim_snprintf(s, len, opt_dir, name); @@ -630,13 +630,13 @@ static void expand_pack_entry(RuntimeSearchPath *search_path, Map(String, handle static char buf[MAXPATHL]; char *(start_pat[]) = { "/pack/*/start/*", "/start/*" }; // NOLINT for (int i = 0; i < 2; i++) { - if (pack_entry_len + STRLEN(start_pat[i]) + 1 > sizeof buf) { + if (pack_entry_len + strlen(start_pat[i]) + 1 > sizeof buf) { continue; } STRLCPY(buf, pack_entry, sizeof buf); STRLCPY(buf + pack_entry_len, start_pat[i], sizeof buf - pack_entry_len); expand_rtp_entry(search_path, rtp_used, buf, false); - size_t after_size = STRLEN(buf) + 7; + size_t after_size = strlen(buf) + 7; char *after = xmallocz(after_size); xstrlcpy(after, buf, after_size); xstrlcat(after, "/after", after_size); @@ -651,7 +651,7 @@ static bool path_is_after(char *buf, size_t buflen) // "after" dir in SOME codepaths not not in ALL codepaths. return buflen >= 5 && (!(buflen >= 6) || vim_ispathsep(buf[buflen - 6])) - && STRCMP(buf + buflen - 5, "after") == 0; + && strcmp(buf + buflen - 5, "after") == 0; } RuntimeSearchPath runtime_search_path_build(void) @@ -669,7 +669,7 @@ RuntimeSearchPath runtime_search_path_build(void) char *cur_entry = entry; copy_option_part(&entry, buf, MAXPATHL, ","); - String the_entry = { .data = cur_entry, .size = STRLEN(buf) }; + String the_entry = { .data = cur_entry, .size = strlen(buf) }; kv_push(pack_entries, the_entry); map_put(String, handle_T)(&pack_used, the_entry, 0); @@ -679,7 +679,7 @@ RuntimeSearchPath runtime_search_path_build(void) for (rtp_entry = p_rtp; *rtp_entry != NUL;) { char *cur_entry = rtp_entry; copy_option_part(&rtp_entry, buf, MAXPATHL, ","); - size_t buflen = STRLEN(buf); + size_t buflen = strlen(buf); if (path_is_after(buf, buflen)) { rtp_entry = cur_entry; @@ -713,7 +713,7 @@ RuntimeSearchPath runtime_search_path_build(void) // "after" dirs in rtp for (; *rtp_entry != NUL;) { copy_option_part(&rtp_entry, buf, MAXPATHL, ","); - expand_rtp_entry(&search_path, &rtp_used, buf, path_is_after(buf, STRLEN(buf))); + expand_rtp_entry(&search_path, &rtp_used, buf, path_is_after(buf, strlen(buf))); } // strings are not owned @@ -891,7 +891,7 @@ static int add_pack_dir_to_rtp(char *fname, bool is_pack) if (insp == NULL) { // Both "fname" and "after" not found, append at the end. - insp = (const char *)p_rtp + STRLEN(p_rtp); + insp = (const char *)p_rtp + strlen(p_rtp); } // check if rtp/pack/name/start/name/after exists @@ -901,8 +901,8 @@ static int add_pack_dir_to_rtp(char *fname, bool is_pack) afterlen = strlen(afterdir) + 1; // add one for comma } - const size_t oldlen = STRLEN(p_rtp); - const size_t addlen = STRLEN(fname) + 1; // add one for comma + const size_t oldlen = strlen(p_rtp); + const size_t addlen = strlen(fname) + 1; // add one for comma const size_t new_rtp_capacity = oldlen + addlen + afterlen + 1; // add one for NUL ------------------------------------------^ char *const new_rtp = try_malloc(new_rtp_capacity); @@ -969,7 +969,7 @@ static int load_pack_plugin(bool opt, char *fname) static const char *ftpat = "%s/ftdetect/*.vim"; // NOLINT char *const ffname = fix_fname(fname); - size_t len = strlen(ffname) + STRLEN(ftpat); + size_t len = strlen(ffname) + strlen(ftpat); char *pat = xmallocz(len); vim_snprintf(pat, len, "%s/plugin/**/*.vim", ffname); // NOLINT @@ -1061,11 +1061,11 @@ static void add_pack_start_dir(char *fname, void *cookie) static char buf[MAXPATHL]; char *(start_pat[]) = { "/start/*", "/pack/*/start/*" }; // NOLINT for (int i = 0; i < 2; i++) { - if (STRLEN(fname) + STRLEN(start_pat[i]) + 1 > MAXPATHL) { + if (strlen(fname) + strlen(start_pat[i]) + 1 > MAXPATHL) { continue; } STRLCPY(buf, fname, MAXPATHL); - STRLCAT(buf, start_pat[i], sizeof buf); + xstrlcat(buf, start_pat[i], sizeof buf); if (pack_has_entries(buf)) { add_pack_dir_to_rtp(buf, true); } @@ -1140,7 +1140,7 @@ void ex_packadd(exarg_T *eap) continue; } - const size_t len = STRLEN(plugpat) + STRLEN(eap->arg) + 5; + const size_t len = strlen(plugpat) + strlen(eap->arg) + 5; char *pat = xmallocz(len); vim_snprintf(pat, len, plugpat, round == 1 ? "start" : "opt", eap->arg); // The first round don't give a "not found" error, in the second round @@ -1166,14 +1166,14 @@ int ExpandRTDir(char *pat, int flags, int *num_file, char ***file, char *dirname { *num_file = 0; *file = NULL; - size_t pat_len = STRLEN(pat); + 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. for (int i = 0; dirnames[i] != NULL; i++) { - size_t size = STRLEN(dirnames[i]) + pat_len + 7; + 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); @@ -1186,7 +1186,7 @@ int ExpandRTDir(char *pat, int flags, int *num_file, char ***file, char *dirname if (flags & DIP_START) { for (int i = 0; dirnames[i] != NULL; i++) { - size_t size = STRLEN(dirnames[i]) + pat_len + 22; + 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); @@ -1198,7 +1198,7 @@ int ExpandRTDir(char *pat, int flags, int *num_file, char ***file, char *dirname } for (int i = 0; dirnames[i] != NULL; i++) { - size_t size = STRLEN(dirnames[i]) + pat_len + 22; + 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); @@ -1212,7 +1212,7 @@ int ExpandRTDir(char *pat, int flags, int *num_file, char ***file, char *dirname if (flags & DIP_OPT) { for (int i = 0; dirnames[i] != NULL; i++) { - size_t size = STRLEN(dirnames[i]) + pat_len + 20; + 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); @@ -1224,7 +1224,7 @@ int ExpandRTDir(char *pat, int flags, int *num_file, char ***file, char *dirname } for (int i = 0; dirnames[i] != NULL; i++) { - size_t size = STRLEN(dirnames[i]) + pat_len + 20; + 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); @@ -1239,7 +1239,7 @@ int ExpandRTDir(char *pat, int flags, int *num_file, char ***file, char *dirname for (int i = 0; i < ga.ga_len; i++) { char *match = ((char **)ga.ga_data)[i]; char *s = match; - char *e = s + STRLEN(s); + char *e = s + strlen(s); if (e - s > 4 && (STRNICMP(e - 4, ".vim", 4) == 0 || ((flags & DIP_LUA) && STRNICMP(e - 4, ".lua", 4) == 0))) { @@ -1277,7 +1277,7 @@ int ExpandPackAddDir(char *pat, int *num_file, char ***file) *num_file = 0; *file = NULL; - size_t pat_len = STRLEN(pat); + size_t pat_len = strlen(pat); ga_init(&ga, (int)sizeof(char *), 10); size_t buflen = pat_len + 26; @@ -1291,7 +1291,7 @@ int ExpandPackAddDir(char *pat, int *num_file, char ***file) for (int i = 0; i < ga.ga_len; i++) { char *match = ((char **)ga.ga_data)[i]; s = path_tail(match); - memmove(match, s, STRLEN(s) + 1); + memmove(match, s, strlen(s) + 1); } if (GA_EMPTY(&ga)) { @@ -1451,7 +1451,7 @@ static inline char *add_dir(char *dest, const char *const dir, const size_t dir_ if (!after_pathsep(dest - 1, dest)) { *dest++ = PATHSEP; } -#if defined(WIN32) +#if defined(MSWIN) size_t size = (type == kXDGDataHome ? sizeof("nvim-data") - 1 : NVIM_SIZE); memmove(dest, (type == kXDGDataHome ? "nvim-data" : "nvim"), size); dest += size; @@ -1521,7 +1521,7 @@ char *runtimepath_default(bool clean_arg) if (data_home != NULL) { data_len = strlen(data_home); if (data_len != 0) { -#if defined(WIN32) +#if defined(MSWIN) size_t nvim_size = (sizeof("nvim-data") - 1); #else size_t nvim_size = NVIM_SIZE; @@ -1664,7 +1664,7 @@ int source_level(void *cookie) /// If possible the handle is closed on exec(). static FILE *fopen_noinh_readbin(char *filename) { -#ifdef WIN32 +#ifdef MSWIN int fd_tmp = os_open(filename, O_RDONLY | O_BINARY | O_NOINHERIT, 0); #else int fd_tmp = os_open(filename, O_RDONLY, 0); @@ -1728,7 +1728,7 @@ typedef struct { static char *get_str_line(int c, void *cookie, int indent, bool do_concat) { GetStrLineCookie *p = cookie; - if (STRLEN(p->buf) <= p->offset) { + if (strlen(p->buf) <= p->offset) { return NULL; } const char *line = p->buf + p->offset; @@ -2121,7 +2121,7 @@ scriptitem_T *get_current_script_id(char **fnamep, sctx_T *ret_sctx) // - If a script is deleted and another script is written, with a // different name, the inode may be re-used. si = &SCRIPT_ITEM(script_sctx.sc_sid); - if (si->sn_name != NULL && FNAMECMP(si->sn_name, *fnamep) == 0) { + if (si->sn_name != NULL && path_fnamecmp(si->sn_name, *fnamep) == 0) { // Found it! break; } @@ -2290,7 +2290,7 @@ char *getsourceline(int c, void *cookie, int indent, bool do_concat) ga_init(&ga, (int)sizeof(char), 400); ga_concat(&ga, line); while (sp->nextline != NULL - && concat_continued_line(&ga, 400, sp->nextline, STRLEN(sp->nextline))) { + && concat_continued_line(&ga, 400, sp->nextline, strlen(sp->nextline))) { xfree(sp->nextline); sp->nextline = get_one_sourceline(sp); } @@ -2353,7 +2353,7 @@ retry: break; } - len = ga.ga_len + (int)STRLEN(buf + ga.ga_len); + len = ga.ga_len + (int)strlen(buf + ga.ga_len); #ifdef USE_CRNL // Ignore a trailing CTRL-Z, when in Dos mode. Only recognize the // CTRL-Z by its own, or after a NL. diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 8e10f2d62d..1af93f061c 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -155,8 +155,6 @@ void win_draw_end(win_T *wp, int c1, int c2, bool draw_margin, int row, int endr } else { grid_fill(&wp->w_grid, row, endrow, n, wp->w_grid.cols, c1, c2, attr); } - - set_empty_rows(wp, row); } /// Compute the width of the foldcolumn. Based on 'foldcolumn' and how much @@ -442,7 +440,7 @@ void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int match, i // Put the wildmenu just above the command line. If there is // no room, scroll the screen one line up. if (cmdline_row == Rows - 1) { - msg_scroll_up(false); + msg_scroll_up(false, false); msg_scrolled++; } else { cmdline_row++; @@ -1022,7 +1020,7 @@ void draw_tabline(void) if (modified || wincount > 1) { if (wincount > 1) { vim_snprintf((char *)NameBuff, MAXPATHL, "%d", wincount); - len = (int)STRLEN(NameBuff); + len = (int)strlen(NameBuff); if (col + len >= Columns - 3) { break; } @@ -1173,7 +1171,9 @@ bool redrawing(void) /// Return true if printing messages should currently be done. bool messaging(void) { - return !(p_lz && char_avail() && !KeyTyped) && ui_has_messages(); + // TODO(bfredl): with general support for "async" messages with p_ch, + // this should be re-enabled. + return !(p_lz && char_avail() && !KeyTyped) && (p_ch > 0 || ui_has(kUIMessages)); } #define COL_RULER 17 // columns needed by standard ruler @@ -1394,7 +1394,7 @@ char *set_chars_option(win_T *wp, char **varp, bool apply) while (*p) { int i; for (i = 0; i < entries; i++) { - const size_t len = STRLEN(tab[i].name); + const size_t len = strlen(tab[i].name); if (STRNCMP(p, tab[i].name, len) == 0 && p[len] == ':' && p[len + 1] != NUL) { @@ -1436,8 +1436,8 @@ char *set_chars_option(win_T *wp, char **varp, bool apply) } if (i == entries) { - const size_t len = STRLEN("multispace"); - const size_t len2 = STRLEN("leadmultispace"); + const size_t len = strlen("multispace"); + const size_t len2 = strlen("leadmultispace"); if (is_listchars && STRNCMP(p, "multispace", len) == 0 && p[len] == ':' diff --git a/src/nvim/search.c b/src/nvim/search.c index e2df31c04f..336dd50292 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -817,7 +817,7 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir, if (endpos.col == 0) { if (pos->lnum > 1) { // just in case pos->lnum--; - pos->col = (colnr_T)STRLEN(ml_get_buf(buf, pos->lnum, false)); + pos->col = (colnr_T)strlen(ml_get_buf(buf, pos->lnum, false)); } } else { pos->col--; @@ -934,7 +934,7 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir, // A pattern like "\n\zs" may go past the last line. if (pos->lnum > buf->b_ml.ml_line_count) { pos->lnum = buf->b_ml.ml_line_count; - pos->col = (int)STRLEN(ml_get_buf(buf, pos->lnum, false)); + pos->col = (int)strlen(ml_get_buf(buf, pos->lnum, false)); if (pos->col > 0) { pos->col--; } @@ -1085,7 +1085,7 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char_u *pat, long count, p = (char_u *)skip_regexp((char *)pat, search_delim, p_magic, &strcopy); if (strcopy != (char *)ps) { // made a copy of "pat" to change "\?" to "?" - searchcmdlen += (int)(STRLEN(pat) - STRLEN(strcopy)); + searchcmdlen += (int)(STRLEN(pat) - strlen(strcopy)); pat = (char_u *)strcopy; searchstr = (char_u *)strcopy; } @@ -2444,7 +2444,7 @@ int current_search(long count, bool forward) } else { // try again from end of buffer // searching backwards, so set pos to last line and col pos.lnum = curwin->w_buffer->b_ml.ml_line_count; - pos.col = (colnr_T)STRLEN(ml_get(curwin->w_buffer->b_ml.ml_line_count)); + pos.col = (colnr_T)strlen(ml_get(curwin->w_buffer->b_ml.ml_line_count)); } } } @@ -3508,14 +3508,14 @@ void find_pattern_in_path(char_u *ptr, Direction dir, size_t len, bool whole, bo if (inc_opt != NULL && strstr(inc_opt, "\\zs") != NULL) { // Use text from '\zs' to '\ze' (or end) of 'include'. - new_fname = (char_u *)find_file_name_in_path((char *)incl_regmatch.startp[0], + new_fname = (char_u *)find_file_name_in_path(incl_regmatch.startp[0], (size_t)(incl_regmatch.endp[0] - incl_regmatch.startp[0]), FNAME_EXP|FNAME_INCL|FNAME_REL, 1L, (char *)p_fname); } else { // Use text after match with 'include'. - new_fname = file_name_in_line(incl_regmatch.endp[0], 0, + new_fname = file_name_in_line((char_u *)incl_regmatch.endp[0], 0, FNAME_EXP|FNAME_INCL|FNAME_REL, 1L, p_fname, NULL); } already_searched = false; @@ -3583,19 +3583,19 @@ void find_pattern_in_path(char_u *ptr, Direction dir, size_t len, bool whole, bo if (inc_opt != NULL && strstr(inc_opt, "\\zs") != NULL) { // pattern contains \zs, use the match - p = incl_regmatch.startp[0]; + p = (char_u *)incl_regmatch.startp[0]; i = (int)(incl_regmatch.endp[0] - incl_regmatch.startp[0]); } else { // find the file name after the end of the match - for (p = incl_regmatch.endp[0]; + for (p = (char_u *)incl_regmatch.endp[0]; *p && !vim_isfilec(*p); p++) {} for (i = 0; vim_isfilec(p[i]); i++) {} } if (i == 0) { // Nothing found, use the rest of the line. - p = incl_regmatch.endp[0]; + p = (char_u *)incl_regmatch.endp[0]; i = (int)STRLEN(p); } else if (p > line) { // Avoid checking before the start of the line, can @@ -3681,7 +3681,7 @@ search_line: // Pattern must be first identifier after 'define', so skip // to that position before checking for match of pattern. Also // don't let it match beyond the end of this identifier. - p = def_regmatch.endp[0]; + p = (char_u *)def_regmatch.endp[0]; while (*p && !vim_iswordc(*p)) { p++; } @@ -3706,7 +3706,7 @@ search_line: } else if (regmatch.regprog != NULL && vim_regexec(®match, (char *)line, (colnr_T)(p - line))) { matched = true; - startp = regmatch.startp[0]; + startp = (char_u *)regmatch.startp[0]; // Check if the line is not a comment line (unless we are // looking for a define). A line starting with "# define" // is not considered to be a comment line. @@ -3810,7 +3810,7 @@ search_line: cont_s_ipos = true; } IObuff[i] = NUL; - aux = IObuff; + aux = (char_u *)IObuff; if (i == ins_compl_len()) { goto exit_matched; diff --git a/src/nvim/sha256.c b/src/nvim/sha256.c index 53c9cb7c81..012f145875 100644 --- a/src/nvim/sha256.c +++ b/src/nvim/sha256.c @@ -17,7 +17,7 @@ #include <stdio.h> // for snprintf(). #include "nvim/sha256.h" // for context_sha256_T -#include "nvim/vim.h" // for STRCPY()/STRLEN(). +#include "nvim/vim.h" // for STRCPY()/strlen(). #ifdef INCLUDE_GENERATED_DECLARATIONS # include "sha256.c.generated.h" diff --git a/src/nvim/shada.c b/src/nvim/shada.c index 312c30e4a9..f735829030 100644 --- a/src/nvim/shada.c +++ b/src/nvim/shada.c @@ -752,7 +752,7 @@ static int open_shada_file_for_reading(const char *const fname, ShaDaReadDef *sd return error; } - assert(STRCMP(p_enc, "utf-8") == 0); + assert(strcmp(p_enc, "utf-8") == 0); return 0; } @@ -884,7 +884,7 @@ static const void *shada_hist_iter(const void *const iter, const uint8_t history .histtype = history_type, .string = hist_he.hisstr, .sep = (char)(history_type == HIST_SEARCH - ? hist_he.hisstr[STRLEN(hist_he.hisstr) + 1] + ? hist_he.hisstr[strlen(hist_he.hisstr) + 1] : 0), .additional_elements = hist_he.additional_elements, } @@ -1053,7 +1053,7 @@ static buf_T *find_buffer(khash_t(fnamebufs) *const fname_bufs, const char *cons kh_key(fname_bufs, k) = xstrdup(fname); FOR_ALL_BUFFERS(buf) { if (buf->b_ffname != NULL) { - if (FNAMECMP(fname, buf->b_ffname) == 0) { + if (path_fnamecmp(fname, buf->b_ffname) == 0) { kh_val(fname_bufs, k) = buf; return buf; } @@ -1313,9 +1313,9 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags) MERGE_JUMPS(curwin->w_jumplistlen, curwin->w_jumplist, xfmark_T, fmark.timestamp, fmark.mark, cur_entry, (buf == NULL - ? (jl_entry.fname != NULL - && STRCMP(fm.fname, jl_entry.fname) == 0) - : fm.fmark.fnum == jl_entry.fmark.fnum), + ? (jl_entry.fname != NULL + && strcmp(fm.fname, jl_entry.fname) == 0) + : fm.fmark.fnum == jl_entry.fmark.fnum), free_xfmark, SDE_TO_XFMARK, ADJUST_IDX, DUMMY_AFTERFREE); #undef SDE_TO_XFMARK #undef ADJUST_IDX @@ -3098,7 +3098,7 @@ shada_write_file_nomerge: {} } } #endif - if (vim_rename((char_u *)tempname, (char_u *)fname) == -1) { + if (vim_rename(tempname, fname) == -1) { semsg(_(RNERR "Can't rename ShaDa file from %s to %s!"), tempname, fname); } else { @@ -4000,7 +4000,7 @@ static bool shada_removable(const char *name) (void)copy_option_part(&p, part, ARRAY_SIZE(part), ", "); if (part[0] == 'r') { home_replace(NULL, part + 1, (char *)NameBuff, MAXPATHL, true); - size_t n = STRLEN(NameBuff); + size_t n = strlen(NameBuff); if (mb_strnicmp(NameBuff, new_name, n) == 0) { retval = true; break; diff --git a/src/nvim/sign.c b/src/nvim/sign.c index 7d931a853b..6f13dd2f06 100644 --- a/src/nvim/sign.c +++ b/src/nvim/sign.c @@ -78,15 +78,15 @@ static signgroup_T *sign_group_ref(const char *groupname) signgroup_T *group; hash = hash_hash((char_u *)groupname); - hi = hash_lookup(&sg_table, (char *)groupname, STRLEN(groupname), hash); + 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(sizeof(signgroup_T) + strlen(groupname)); STRCPY(group->sg_name, groupname); group->sg_refcount = 1; group->sg_next_sign_id = 1; - hash_add_item(&sg_table, hi, group->sg_name, hash); + hash_add_item(&sg_table, hi, (char_u *)group->sg_name, hash); } else { // existing group group = HI2SG(hi); @@ -119,10 +119,10 @@ static void sign_group_unref(char *groupname) /// or in a named group. If 'group' is '*', then the sign is part of the group. static bool sign_in_group(sign_entry_T *sign, const char *group) { - return ((group != NULL && STRCMP(group, "*") == 0) + return ((group != NULL && strcmp(group, "*") == 0) || (group == NULL && sign->se_group == NULL) || (group != NULL && sign->se_group != NULL - && STRCMP(group, sign->se_group->sg_name) == 0)); + && strcmp(group, sign->se_group->sg_name) == 0)); } /// Get the next free sign identifier in the specified group @@ -557,7 +557,7 @@ static linenr_T buf_delsign(buf_T *buf, linenr_T atlnum, int id, char *group) sign_group_unref((char *)sign->se_group->sg_name); } xfree(sign); - redraw_buf_line_later(buf, lnum); + redraw_buf_line_later(buf, lnum, false); // Check whether only one sign needs to be deleted // If deleting a sign with a specific identifier in a particular // group or deleting any sign at a particular line number, delete @@ -784,7 +784,7 @@ static int sign_cmd_idx(char *begin_cmd, char *end_cmd) *end_cmd = NUL; for (idx = 0;; idx++) { - if (cmds[idx] == NULL || STRCMP(begin_cmd, cmds[idx]) == 0) { + if (cmds[idx] == NULL || strcmp(begin_cmd, cmds[idx]) == 0) { break; } } @@ -801,7 +801,7 @@ static sign_T *sign_find(const char *name, sign_T **sp_prev) *sp_prev = NULL; } for (sp = first_sign; sp != NULL; sp = sp->sn_next) { - if (STRCMP(sp->sn_name, name) == 0) { + if (strcmp(sp->sn_name, name) == 0) { break; } if (sp_prev != NULL) { @@ -868,7 +868,7 @@ static int sign_define_init_text(sign_T *sp, char *text) int cells; size_t len; - endp = text + (int)STRLEN(text); + endp = text + (int)strlen(text); for (s = text; s + 1 < endp; s++) { if (*s == '\\') { // Remove a backslash, so that it is possible @@ -951,7 +951,7 @@ static int sign_define_by_name(char *name, char *icon, char *linehl, char *text, if (*linehl == NUL) { sp->sn_line_hl = 0; } else { - sp->sn_line_hl = syn_check_group(linehl, STRLEN(linehl)); + sp->sn_line_hl = syn_check_group(linehl, strlen(linehl)); } } @@ -959,7 +959,7 @@ static int sign_define_by_name(char *name, char *icon, char *linehl, char *text, if (*texthl == NUL) { sp->sn_text_hl = 0; } else { - sp->sn_text_hl = syn_check_group(texthl, STRLEN(texthl)); + sp->sn_text_hl = syn_check_group(texthl, strlen(texthl)); } } @@ -967,7 +967,7 @@ static int sign_define_by_name(char *name, char *icon, char *linehl, char *text, if (*culhl == NUL) { sp->sn_cul_hl = 0; } else { - sp->sn_cul_hl = syn_check_group(culhl, STRLEN(culhl)); + sp->sn_cul_hl = syn_check_group(culhl, strlen(culhl)); } } @@ -975,7 +975,7 @@ static int sign_define_by_name(char *name, char *icon, char *linehl, char *text, if (*numhl == NUL) { sp->sn_num_hl = 0; } else { - sp->sn_num_hl = syn_check_group(numhl, STRLEN(numhl)); + sp->sn_num_hl = syn_check_group(numhl, strlen(numhl)); } } @@ -1034,7 +1034,7 @@ static int sign_place(int *sign_id, const char *sign_group, const char *sign_nam } for (sp = first_sign; sp != NULL; sp = sp->sn_next) { - if (STRCMP(sp->sn_name, sign_name) == 0) { + if (strcmp(sp->sn_name, sign_name) == 0) { break; } } @@ -1062,7 +1062,7 @@ static int sign_place(int *sign_id, const char *sign_group, const char *sign_nam lnum = buf_change_sign_type(buf, *sign_id, (char *)sign_group, sp->sn_typenr, prio); } if (lnum > 0) { - redraw_buf_line_later(buf, lnum); + redraw_buf_line_later(buf, lnum, false); // When displaying signs in the 'number' column, if the width of the // number column is less than 2, then force recomputing the width. @@ -1093,7 +1093,7 @@ static int sign_unplace(int sign_id, char *sign_group, buf_T *buf, linenr_T atln if (lnum == 0) { return FAIL; } - redraw_buf_line_later(buf, lnum); + redraw_buf_line_later(buf, lnum, false); } // When all the signs in a buffer are removed, force recomputing the @@ -1139,7 +1139,7 @@ static linenr_T sign_jump(int sign_id, char *sign_group, buf_T *buf) emsg(_("E934: Cannot jump to a buffer that does not have a name")); return -1; } - size_t cmdlen = STRLEN(buf->b_fname) + 24; + size_t cmdlen = strlen(buf->b_fname) + 24; char *cmd = xmallocz(cmdlen); snprintf(cmd, cmdlen, "e +%" PRId64 " %s", (int64_t)lnum, buf->b_fname); diff --git a/src/nvim/sign_defs.h b/src/nvim/sign_defs.h index f1184202e7..16e783aab7 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_u sg_name[1]; // sign group name + 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 } 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 7f07d2ff2c..53fa920358 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -109,7 +109,7 @@ #include "nvim/syntax.h" // for syn_get_id, syntax_present #include "nvim/types.h" // for char_u #include "nvim/undo.h" // for u_save_cursor -#include "nvim/vim.h" // for curwin, STRLEN, STRLCPY, STRNCMP +#include "nvim/vim.h" // for curwin, strlen, STRLCPY, STRNCMP // Result values. Lower number is accepted over higher one. #define SP_BANNED (-1) @@ -369,7 +369,7 @@ size_t spell_check(win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, bool docou int r = vim_regexec(®match, (char *)ptr, 0); wp->w_s->b_cap_prog = regmatch.regprog; if (r) { - *capcol = (int)(regmatch.endp[0] - ptr); + *capcol = (int)(regmatch.endp[0] - (char *)ptr); } } @@ -1550,7 +1550,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"); + STRCPY(fname_enc + strlen(fname_enc) - 3, "add.spl"); do_in_runtimepath((char *)fname_enc, DIP_ALL, spell_load_cb, &sl); } } @@ -1559,7 +1559,7 @@ static void spell_load_lang(char_u *lang) // use "latin1" for "latin9". And limit to 60 characters (just in case). char_u *spell_enc(void) { - if (STRLEN(p_enc) < 60 && STRCMP(p_enc, "iso-8859-15") != 0) { + if (STRLEN(p_enc) < 60 && strcmp(p_enc, "iso-8859-15") != 0) { return (char_u *)p_enc; } return (char_u *)"latin1"; @@ -1843,19 +1843,19 @@ char *did_set_spelllang(win_T *wp) { garray_T ga; char *splp; - char_u *region; - char_u region_cp[3]; + char *region; + char region_cp[3]; bool filename; int region_mask; slang_T *slang; int c; - char_u lang[MAXWLEN + 1]; - char_u spf_name[MAXPATHL]; + char lang[MAXWLEN + 1]; + char spf_name[MAXPATHL]; int len; - char_u *p; + char *p; int round; char *spf; - char_u *use_region = NULL; + char *use_region = NULL; bool dont_use_region = false; bool nobreak = false; langp_T *lp, *lp2; @@ -1888,13 +1888,13 @@ char *did_set_spelllang(win_T *wp) // Get one language name. copy_option_part(&splp, (char *)lang, MAXWLEN, ","); region = NULL; - len = (int)STRLEN(lang); + len = (int)strlen(lang); if (!valid_spelllang((char *)lang)) { continue; } - if (STRCMP(lang, "cjk") == 0) { + if (strcmp(lang, "cjk") == 0) { wp->w_s->b_cjk = 1; continue; } @@ -1902,11 +1902,11 @@ char *did_set_spelllang(win_T *wp) // If the name ends in ".spl" use it as the name of the spell file. // If there is a region name let "region" point to it and remove it // from the name. - if (len > 4 && FNAMECMP(lang + len - 4, ".spl") == 0) { + if (len > 4 && path_fnamecmp(lang + len - 4, ".spl") == 0) { filename = true; // Locate a region and remove it from the file name. - p = (char_u *)vim_strchr(path_tail((char *)lang), '_'); + p = vim_strchr(path_tail((char *)lang), '_'); if (p != NULL && ASCII_ISALPHA(p[1]) && ASCII_ISALPHA(p[2]) && !ASCII_ISALPHA(p[3])) { STRLCPY(region_cp, p + 1, 3); @@ -1943,7 +1943,7 @@ char *did_set_spelllang(win_T *wp) if (region != NULL) { // If the region differs from what was used before then don't // use it for 'spellfile'. - if (use_region != NULL && STRCMP(region, use_region) != 0) { + if (use_region != NULL && strcmp(region, use_region) != 0) { dont_use_region = true; } use_region = region; @@ -1954,7 +1954,7 @@ char *did_set_spelllang(win_T *wp) if (filename) { (void)spell_load_file((char *)lang, (char *)lang, NULL, false); } else { - spell_load_lang(lang); + spell_load_lang((char_u *)lang); // SpellFileMissing autocommands may do anything, including // destroying the buffer we are using... if (!bufref_valid(&bufref)) { @@ -1972,7 +1972,7 @@ char *did_set_spelllang(win_T *wp) region_mask = REGION_ALL; if (!filename && region != NULL) { // find region in sl_regions - c = find_region(slang->sl_regions, region); + c = find_region(slang->sl_regions, (char_u *)region); if (c == REGION_ALL) { if (slang->sl_add) { if (*slang->sl_regions != NUL) { @@ -2015,7 +2015,7 @@ char *did_set_spelllang(win_T *wp) if (int_wordlist == NULL) { continue; } - int_wordlist_spl(spf_name); + int_wordlist_spl((char_u *)spf_name); } else { // One entry in 'spellfile'. copy_option_part(&spf, (char *)spf_name, MAXPATHL - 5, ","); @@ -2023,9 +2023,9 @@ char *did_set_spelllang(win_T *wp) // If it was already found above then skip it. for (c = 0; c < ga.ga_len; c++) { - p = (char_u *)LANGP_ENTRY(ga, c)->lp_slang->sl_fname; + p = LANGP_ENTRY(ga, c)->lp_slang->sl_fname; if (p != NULL - && path_full_compare((char *)spf_name, (char *)p, false, true) == kEqualFiles) { + && path_full_compare((char *)spf_name, p, false, true) == kEqualFiles) { break; } } @@ -2049,7 +2049,7 @@ char *did_set_spelllang(win_T *wp) STRCPY(lang, "internal wordlist"); } else { STRLCPY(lang, path_tail((char *)spf_name), MAXWLEN + 1); - p = (char_u *)vim_strchr((char *)lang, '.'); + p = vim_strchr((char *)lang, '.'); if (p != NULL) { *p = NUL; // truncate at ".encoding.add" } @@ -2066,7 +2066,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, use_region); + c = find_region(slang->sl_regions, (char_u *)use_region); if (c != REGION_ALL) { region_mask = 1 << c; } else if (*slang->sl_regions != NUL) { @@ -2165,7 +2165,7 @@ static void use_midword(slang_T *lp, win_T *wp) wp->w_s->b_spell_ismw_mb = xstrnsave(p, (size_t)l); } else { // Append multi-byte chars to "b_spell_ismw_mb". - const int n = (int)STRLEN(wp->w_s->b_spell_ismw_mb); + const int n = (int)strlen(wp->w_s->b_spell_ismw_mb); char *bp = xstrnsave(wp->w_s->b_spell_ismw_mb, (size_t)n + (size_t)l); xfree(wp->w_s->b_spell_ismw_mb); wp->w_s->b_spell_ismw_mb = bp; @@ -2548,7 +2548,7 @@ bool check_need_cap(linenr_T lnum, colnr_T col) break; } if (vim_regexec(®match, (char *)p, 0) - && regmatch.endp[0] == line + endcol) { + && (char_u *)regmatch.endp[0] == line + endcol) { need_cap = true; break; } @@ -2572,9 +2572,9 @@ void ex_spellrepall(exarg_T *eap) emsg(_("E752: No previous spell replacement")); return; } - int addlen = (int)(STRLEN(repl_to) - STRLEN(repl_from)); + int addlen = (int)(strlen(repl_to) - strlen(repl_from)); - size_t frompatlen = STRLEN(repl_from) + 7; + size_t frompatlen = strlen(repl_from) + 7; char_u *frompat = xmalloc(frompatlen); snprintf((char *)frompat, frompatlen, "\\V\\<%s\\>", repl_from); p_ws = false; @@ -2592,11 +2592,11 @@ void ex_spellrepall(exarg_T *eap) // when changing "etc" to "etc.". char_u *line = (char_u *)get_cursor_line_ptr(); if (addlen <= 0 || STRNCMP(line + curwin->w_cursor.col, - repl_to, STRLEN(repl_to)) != 0) { + repl_to, strlen(repl_to)) != 0) { char_u *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)); + STRCAT(p, line + curwin->w_cursor.col + strlen(repl_from)); ml_replace(curwin->w_cursor.lnum, (char *)p, false); changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col); @@ -2606,7 +2606,7 @@ void ex_spellrepall(exarg_T *eap) } sub_nsubs++; } - curwin->w_cursor.col += (colnr_T)STRLEN(repl_to); + curwin->w_cursor.col += (colnr_T)strlen(repl_to); } p_ws = save_ws; @@ -3171,23 +3171,23 @@ void ex_spelldump(exarg_T *eap) /// @param ic ignore case /// @param dir direction for adding matches /// @param dumpflags_arg DUMPFLAG_* -void spell_dump_compl(char_u *pat, int ic, Direction *dir, int dumpflags_arg) +void spell_dump_compl(char *pat, int ic, Direction *dir, int dumpflags_arg) { langp_T *lp; slang_T *slang; idx_T arridx[MAXWLEN]; int curi[MAXWLEN]; - char_u word[MAXWLEN]; + char word[MAXWLEN]; int c; - char_u *byts; + char *byts; idx_T *idxs; linenr_T lnum = 0; int depth; int n; int flags; - char_u *region_names = NULL; // region names being used + char *region_names = NULL; // region names being used bool do_region = true; // dump region names and numbers - char_u *p; + char *p; int dumpflags = dumpflags_arg; int patlen; @@ -3197,11 +3197,11 @@ void spell_dump_compl(char_u *pat, int ic, Direction *dir, int dumpflags_arg) if (ic) { dumpflags |= DUMPFLAG_ICASE; } else { - n = captype(pat, NULL); + n = captype((char_u *)pat, NULL); if (n == WF_ONECAP) { dumpflags |= DUMPFLAG_ONECAP; } else if (n == WF_ALLCAP - && (int)STRLEN(pat) > utfc_ptr2len((char *)pat)) { + && (int)STRLEN(pat) > utfc_ptr2len(pat)) { dumpflags |= DUMPFLAG_ALLCAP; } } @@ -3211,11 +3211,11 @@ void spell_dump_compl(char_u *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 = lp->lp_slang->sl_regions; + p = (char *)lp->lp_slang->sl_regions; if (p[0] != 0) { if (region_names == NULL) { // first language with regions region_names = p; - } else if (STRCMP(region_names, p) != 0) { + } else if (strcmp(region_names, p) != 0) { do_region = false; // region names are different break; } @@ -3247,7 +3247,7 @@ void spell_dump_compl(char_u *pat, int ic, Direction *dir, int dumpflags_arg) // When matching with a pattern and there are no prefixes only use // parts of the tree that match "pat". if (pat != NULL && slang->sl_pbyts == NULL) { - patlen = (int)STRLEN(pat); + patlen = (int)strlen(pat); } else { patlen = -1; } @@ -3257,11 +3257,11 @@ void spell_dump_compl(char_u *pat, int ic, Direction *dir, int dumpflags_arg) for (int round = 1; round <= 2; round++) { if (round == 1) { dumpflags &= ~DUMPFLAG_KEEPCASE; - byts = slang->sl_fbyts; + byts = (char *)slang->sl_fbyts; idxs = slang->sl_fidxs; } else { dumpflags |= DUMPFLAG_KEEPCASE; - byts = slang->sl_kbyts; + byts = (char *)slang->sl_kbyts; idxs = slang->sl_kidxs; } if (byts == NULL) { @@ -3281,7 +3281,7 @@ void spell_dump_compl(char_u *pat, int ic, Direction *dir, int dumpflags_arg) // Do one more byte at this node. n = arridx[depth] + curi[depth]; curi[depth]++; - c = byts[n]; + c = (uint8_t)byts[n]; if (c == 0 || depth >= MAXWLEN - 1) { // End of word or reached maximum length, deal with the // word. @@ -3304,7 +3304,7 @@ void spell_dump_compl(char_u *pat, int ic, Direction *dir, int dumpflags_arg) // when it's the first one. c = (int)((unsigned)flags >> 24); if (c == 0 || curi[depth] == 2) { - dump_word(slang, word, pat, dir, + dump_word(slang, (char_u *)word, (char_u *)pat, dir, dumpflags, flags, lnum); if (pat == NULL) { lnum++; @@ -3313,13 +3313,13 @@ void spell_dump_compl(char_u *pat, int ic, Direction *dir, int dumpflags_arg) // Apply the prefix, if there is one. if (c != 0) { - lnum = dump_prefixes(slang, word, pat, dir, + lnum = dump_prefixes(slang, (char_u *)word, (char_u *)pat, dir, dumpflags, flags, lnum); } } } else { // Normal char, go one level deeper. - word[depth++] = (char_u)c; + word[depth++] = (char)c; arridx[depth] = idxs[n]; curi[depth] = 1; @@ -3331,7 +3331,7 @@ void spell_dump_compl(char_u *pat, int ic, Direction *dir, int dumpflags_arg) // ignore case... assert(depth >= 0); if (depth <= patlen - && mb_strnicmp((char *)word, (char *)pat, (size_t)depth) != 0) { + && mb_strnicmp((char *)word, pat, (size_t)depth) != 0) { depth--; } } @@ -3407,7 +3407,7 @@ static void dump_word(slang_T *slang, char_u *word, char_u *pat, Direction *dir, if (!HASHITEM_EMPTY(hi)) { vim_snprintf((char *)IObuff, IOSIZE, "%s\t%d", tw, HI2WC(hi)->wc_count); - p = IObuff; + p = (char_u *)IObuff; } } @@ -3611,9 +3611,9 @@ char *did_set_spell_option(bool is_spellfile) char *errmsg = NULL; if (is_spellfile) { - int l = (int)STRLEN(curwin->w_s->b_p_spf); + int l = (int)strlen(curwin->w_s->b_p_spf); if (l > 0 - && (l < 4 || STRCMP(curwin->w_s->b_p_spf + l - 4, ".add") != 0)) { + && (l < 4 || strcmp(curwin->w_s->b_p_spf + l - 4, ".add") != 0)) { errmsg = e_invarg; } } diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index e6e56d615c..611c43e85e 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -355,12 +355,12 @@ struct affentry_S { // Affix header from ".aff" file. Used for af_pref and af_suff. typedef struct affheader_S { - char_u ah_key[AH_KEY_LEN]; // key for hashtab == name of affix + char ah_key[AH_KEY_LEN]; // key for hashtab == name of affix unsigned ah_flag; // affix name as number, uses "af_flagtype" int ah_newID; // prefix ID after renumbering; 0 if not used int ah_combine; // suffix may combine with prefix int ah_follows; // another affix block should be following - affentry_T *ah_first; // first affix entry + affentry_T *ah_first; // first affix entry } affheader_T; #define HI2AH(hi) ((affheader_T *)(hi)->hi_key) @@ -895,7 +895,7 @@ void suggest_load_files(void) slang->sl_sugloaded = true; dotp = strrchr(slang->sl_fname, '.'); - if (dotp == NULL || FNAMECMP(dotp, ".spl") != 0) { + if (dotp == NULL || path_fnamecmp(dotp, ".spl") != 0) { continue; } STRCPY(dotp, ".sug"); @@ -2102,7 +2102,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname) } items[itemcnt++] = p; // A few items have arbitrary text argument, don't split them. - if (itemcnt == 2 && spell_info_item((char_u *)items[0])) { + if (itemcnt == 2 && spell_info_item(items[0])) { while ((uint8_t)(*p) >= ' ' || *p == TAB) { // skip until CR/NL p++; } @@ -2130,11 +2130,11 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname) spin->si_conv.vc_fail = true; } else if (is_aff_rule(items, itemcnt, "FLAG", 2) && aff->af_flagtype == AFT_CHAR) { - if (STRCMP(items[1], "long") == 0) { + if (strcmp(items[1], "long") == 0) { aff->af_flagtype = AFT_LONG; - } else if (STRCMP(items[1], "num") == 0) { + } else if (strcmp(items[1], "num") == 0) { aff->af_flagtype = AFT_NUM; - } else if (STRCMP(items[1], "caplong") == 0) { + } else if (strcmp(items[1], "caplong") == 0) { aff->af_flagtype = AFT_CAPLONG; } else { smsg(_("Invalid value for FLAG in %s line %d: %s"), @@ -2154,11 +2154,11 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname) smsg(_("FLAG after using flags in %s line %d: %s"), fname, lnum, items[1]); } - } else if (spell_info_item((char_u *)items[0]) && itemcnt > 1) { + } else if (spell_info_item(items[0]) && itemcnt > 1) { p = getroom(spin, (spin->si_info == NULL ? 0 : STRLEN(spin->si_info)) - + STRLEN(items[0]) - + STRLEN(items[1]) + 3, false); + + strlen(items[0]) + + strlen(items[1]) + 3, false); if (spin->si_info != NULL) { STRCPY(p, spin->si_info); STRCAT(p, "\n"); @@ -2231,7 +2231,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname) && compflags == NULL) { // Turn flag "c" into COMPOUNDRULE compatible string "c+", // "Na" into "Na+", "1234" into "1234+". - p = getroom(spin, STRLEN(items[1]) + 2, false); + p = getroom(spin, strlen(items[1]) + 2, false); STRCPY(p, items[1]); STRCAT(p, "+"); compflags = (char_u *)p; @@ -2247,7 +2247,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname) if (compflags != NULL || *skipdigits((char *)items[1]) != NUL) { // Concatenate this string to previously defined ones, // using a slash to separate them. - l = (int)STRLEN(items[1]) + 1; + l = (int)strlen(items[1]) + 1; if (compflags != NULL) { l += (int)STRLEN(compflags) + 1; } @@ -2299,8 +2299,8 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname) // Only add the couple if it isn't already there. for (i = 0; i < gap->ga_len - 1; i += 2) { - if (STRCMP(((char **)(gap->ga_data))[i], items[1]) == 0 - && STRCMP(((char **)(gap->ga_data))[i + 1], items[2]) == 0) { + if (strcmp(((char **)(gap->ga_data))[i], items[1]) == 0 + && strcmp(((char **)(gap->ga_data))[i + 1], items[2]) == 0) { break; } } @@ -2324,8 +2324,8 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname) aff->af_pfxpostpone = true; } else if (is_aff_rule(items, itemcnt, "IGNOREEXTRA", 1)) { aff->af_ignoreextra = true; - } else if ((STRCMP(items[0], "PFX") == 0 - || STRCMP(items[0], "SFX") == 0) + } else if ((strcmp(items[0], "PFX") == 0 + || strcmp(items[0], "SFX") == 0) && aff_todo == 0 && itemcnt >= 4) { int lasti = 4; @@ -2358,7 +2358,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname) cur_aff = getroom(spin, sizeof(*cur_aff), true); cur_aff->ah_flag = affitem2flag(aff->af_flagtype, (char_u *)items[1], fname, lnum); - if (cur_aff->ah_flag == 0 || STRLEN(items[1]) >= AH_KEY_LEN) { + if (cur_aff->ah_flag == 0 || strlen(items[1]) >= AH_KEY_LEN) { break; } if (cur_aff->ah_flag == aff->af_bad @@ -2375,14 +2375,14 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname) fname, lnum, items[1]); } STRCPY(cur_aff->ah_key, items[1]); - hash_add(tp, cur_aff->ah_key); + hash_add(tp, (char_u *)cur_aff->ah_key); cur_aff->ah_combine = (*items[2] == 'Y'); } // Check for the "S" flag, which apparently means that another // block with the same affix name is following. - if (itemcnt > lasti && STRCMP(items[lasti], "S") == 0) { + if (itemcnt > lasti && strcmp(items[lasti], "S") == 0) { lasti++; cur_aff->ah_follows = true; } else { @@ -2398,7 +2398,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname) smsg(_(e_afftrailing), fname, lnum, items[lasti]); } - if (STRCMP(items[2], "Y") != 0 && STRCMP(items[2], "N") != 0) { + if (strcmp(items[2], "Y") != 0 && strcmp(items[2], "N") != 0) { smsg(_("Expected Y or N in %s line %d: %s"), fname, lnum, items[2]); } @@ -2421,10 +2421,10 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname) } aff_todo = atoi((char *)items[3]); - } else if ((STRCMP(items[0], "PFX") == 0 - || STRCMP(items[0], "SFX") == 0) + } else if ((strcmp(items[0], "PFX") == 0 + || strcmp(items[0], "SFX") == 0) && aff_todo > 0 - && STRCMP(cur_aff->ah_key, items[1]) == 0 + && strcmp(cur_aff->ah_key, items[1]) == 0 && itemcnt >= 5) { affentry_T *aff_entry; bool upper = false; @@ -2434,7 +2434,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname) // mean mistakes go unnoticed. Require a comment-starter. // Hunspell uses a "-" item. if (itemcnt > lasti && *items[lasti] != '#' - && (STRCMP(items[lasti], "-") != 0 + && (strcmp(items[lasti], "-") != 0 || itemcnt != lasti + 1)) { smsg(_(e_afftrailing), fname, lnum, items[lasti]); } @@ -2443,10 +2443,10 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname) aff_todo--; aff_entry = getroom(spin, sizeof(*aff_entry), true); - if (STRCMP(items[2], "0") != 0) { + if (strcmp(items[2], "0") != 0) { aff_entry->ae_chop = (char_u *)getroom_save(spin, (char_u *)items[2]); } - if (STRCMP(items[3], "0") != 0) { + if (strcmp(items[3], "0") != 0) { aff_entry->ae_add = (char_u *)getroom_save(spin, (char_u *)items[3]); // Recognize flags on the affix: abcd/XYZ @@ -2464,7 +2464,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname) aff_entry->ae_next = cur_aff->ah_first; cur_aff->ah_first = aff_entry; - if (STRCMP(items[4], ".") != 0) { + if (strcmp(items[4], ".") != 0) { char_u buf[MAXLINELEN]; aff_entry->ae_cond = (char_u *)getroom_save(spin, (char_u *)items[4]); @@ -2536,7 +2536,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((char_u *)p, aff_entry->ae_cond)) { + if (str_equal(p, (char *)aff_entry->ae_cond)) { break; } } @@ -2595,8 +2595,8 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname) smsg(_("Expected REP(SAL) count in %s line %d"), fname, lnum); } - } else if ((STRCMP(items[0], "REP") == 0 - || STRCMP(items[0], "REPSAL") == 0) + } else if ((strcmp(items[0], "REP") == 0 + || strcmp(items[0], "REPSAL") == 0) && itemcnt >= 3) { // REP/REPSAL item // Myspell ignores extra arguments, we require it starts with @@ -2656,16 +2656,16 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname) if (do_sal) { // SAL item (sounds-a-like) // Either one of the known keys or a from-to pair. - if (STRCMP(items[1], "followup") == 0) { - spin->si_followup = sal_to_bool((char_u *)items[2]); - } else if (STRCMP(items[1], "collapse_result") == 0) { - spin->si_collapse = sal_to_bool((char_u *)items[2]); - } else if (STRCMP(items[1], "remove_accents") == 0) { - spin->si_rem_accents = sal_to_bool((char_u *)items[2]); + if (strcmp(items[1], "followup") == 0) { + spin->si_followup = sal_to_bool(items[2]); + } else if (strcmp(items[1], "collapse_result") == 0) { + spin->si_collapse = sal_to_bool(items[2]); + } else if (strcmp(items[1], "remove_accents") == 0) { + spin->si_rem_accents = sal_to_bool(items[2]); } else { // when "to" is "_" it means empty add_fromto(spin, &spin->si_sal, (char_u *)items[1], - STRCMP(items[2], "_") == 0 ? (char_u *)"" + strcmp(items[2], "_") == 0 ? (char_u *)"" : (char_u *)items[2]); } } @@ -2675,7 +2675,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname) } else if (is_aff_rule(items, itemcnt, "SOFOTO", 2) && sofoto == NULL) { sofoto = (char_u *)getroom_save(spin, (char_u *)items[1]); - } else if (STRCMP(items[0], "COMMON") == 0) { + } else if (strcmp(items[0], "COMMON") == 0) { int i; for (i = 1; i < itemcnt; i++) { @@ -2744,7 +2744,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname) } if (syllable != NULL) { - aff_check_string(spin->si_syllable, syllable, "SYLLABLE"); + aff_check_string((char *)spin->si_syllable, (char *)syllable, "SYLLABLE"); spin->si_syllable = syllable; } @@ -2755,15 +2755,15 @@ 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, sofofrom, "SOFOFROM"); - aff_check_string(spin->si_sofoto, sofoto, "SOFOTO"); + aff_check_string((char *)spin->si_sofofr, (char *)sofofrom, "SOFOFROM"); + aff_check_string((char *)spin->si_sofoto, (char *)sofoto, "SOFOTO"); spin->si_sofofr = sofofrom; spin->si_sofoto = sofoto; } } if (midword != NULL) { - aff_check_string(spin->si_midword, midword, "MIDWORD"); + aff_check_string((char *)spin->si_midword, (char *)midword, "MIDWORD"); spin->si_midword = midword; } @@ -2776,7 +2776,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname) /// a comment is following after item "mincount". static bool is_aff_rule(char **items, int itemcnt, char *rulename, int mincount) { - return STRCMP(items[0], rulename) == 0 + return strcmp(items[0], rulename) == 0 && (itemcnt == mincount || (itemcnt > mincount && items[mincount][0] == '#')); } @@ -2813,15 +2813,15 @@ static void aff_process_flags(afffile_T *affile, affentry_T *entry) } } -// Returns true if "s" is the name of an info item in the affix file. -static bool spell_info_item(char_u *s) +/// @return true if "s" is the name of an info item in the affix file. +static bool spell_info_item(char *s) { - return STRCMP(s, "NAME") == 0 - || STRCMP(s, "HOME") == 0 - || STRCMP(s, "VERSION") == 0 - || STRCMP(s, "AUTHOR") == 0 - || STRCMP(s, "EMAIL") == 0 - || STRCMP(s, "COPYRIGHT") == 0; + return strcmp(s, "NAME") == 0 + || strcmp(s, "HOME") == 0 + || strcmp(s, "VERSION") == 0 + || strcmp(s, "AUTHOR") == 0 + || strcmp(s, "EMAIL") == 0 + || strcmp(s, "COPYRIGHT") == 0; } // Turn an affix flag name into a number, according to the FLAG type. @@ -3013,23 +3013,23 @@ static void aff_check_number(int spinval, int affval, char *name) } } -// Give a warning when "spinval" and "affval" strings are set and not the same. -static void aff_check_string(char_u *spinval, char_u *affval, char *name) +/// Give a warning when "spinval" and "affval" strings are set and not the same. +static void aff_check_string(char *spinval, char *affval, char *name) { - if (spinval != NULL && STRCMP(spinval, affval) != 0) { + if (spinval != NULL && strcmp(spinval, affval) != 0) { smsg(_("%s value differs from what is used in another .aff file"), name); } } -// Returns true if strings "s1" and "s2" are equal. Also consider both being -// NULL as equal. -static bool str_equal(char_u *s1, char_u *s2) +/// @return true if strings "s1" and "s2" are equal. Also consider both being +/// NULL as equal. +static bool str_equal(char *s1, char *s2) { if (s1 == NULL || s2 == NULL) { return s1 == s2; } - return STRCMP(s1, s2) == 0; + return strcmp(s1, s2) == 0; } // Add a from-to item to "gap". Used for REP and SAL items. @@ -3045,10 +3045,10 @@ static void add_fromto(spellinfo_T *spin, garray_T *gap, char_u *from, char_u *t ftp->ft_to = (char_u *)getroom_save(spin, word); } -// Converts a boolean argument in a SAL line to true or false; -static bool sal_to_bool(char_u *s) +/// Converts a boolean argument in a SAL line to true or false; +static bool sal_to_bool(char *s) { - return STRCMP(s, "1") == 0 || STRCMP(s, "true") == 0; + return strcmp(s, "1") == 0 || strcmp(s, "true") == 0; } // Free the structure filled by spell_read_aff(). @@ -4337,13 +4337,13 @@ static bool node_equal(wordnode_T *n1, wordnode_T *n2) return p1 == NULL && p2 == NULL; } -// Function given to qsort() to sort the REP items on "from" string. +/// Function given to qsort() to sort the REP items on "from" string. static int rep_compare(const void *s1, const void *s2) { fromto_T *p1 = (fromto_T *)s1; fromto_T *p2 = (fromto_T *)s2; - return STRCMP(p1->ft_from, p2->ft_from); + return strcmp((char *)p1->ft_from, (char *)p2->ft_from); } /// Write the Vim .spl file "fname". @@ -4640,7 +4640,7 @@ static int write_vim_spell(spellinfo_T *spin, char *fname) size_t l = STRLEN(spin->si_compflags); assert(spin->si_comppat.ga_len >= 0); for (size_t i = 0; i < (size_t)spin->si_comppat.ga_len; i++) { - l += STRLEN(((char **)(spin->si_comppat.ga_data))[i]) + 1; + l += strlen(((char **)(spin->si_comppat.ga_data))[i]) + 1; } put_bytes(fd, l + 7, 4); // <sectionlen> @@ -4652,9 +4652,9 @@ static int write_vim_spell(spellinfo_T *spin, char *fname) put_bytes(fd, (uintmax_t)spin->si_comppat.ga_len, 2); // <comppatcount> for (size_t i = 0; i < (size_t)spin->si_comppat.ga_len; i++) { char *p = ((char **)(spin->si_comppat.ga_data))[i]; - assert(STRLEN(p) < INT_MAX); - putc((int)STRLEN(p), fd); // <comppatlen> - fwv &= fwrite(p, STRLEN(p), 1, fd); // <comppattext> + assert(strlen(p) < INT_MAX); + putc((int)strlen(p), fd); // <comppatlen> + fwv &= fwrite(p, strlen(p), 1, fd); // <comppattext> } // <compflags> fwv &= fwrite(spin->si_compflags, STRLEN(spin->si_compflags), 1, fd); @@ -5299,7 +5299,7 @@ static void mkspell(int fcount, char **fnames, bool ascii, bool over_write, bool if (fcount >= 1) { len = (int)STRLEN(fnames[0]); - if (fcount == 1 && len > 4 && STRCMP(fnames[0] + len - 4, ".add") == 0) { + if (fcount == 1 && len > 4 && strcmp(fnames[0] + len - 4, ".add") == 0) { // For ":mkspell path/en.latin1.add" output file is // "path/en.latin1.add.spl". incount = 1; @@ -5309,7 +5309,7 @@ static void mkspell(int fcount, char **fnames, bool ascii, bool over_write, bool incount = 1; vim_snprintf(wfname, MAXPATHL, SPL_FNAME_TMPL, fnames[0], spin.si_ascii ? (char_u *)"ascii" : spell_enc()); - } else if (len > 4 && STRCMP(fnames[0] + len - 4, ".spl") == 0) { + } else if (len > 4 && strcmp(fnames[0] + len - 4, ".spl") == 0) { // Name ends in ".spl", use as the file name. STRLCPY(wfname, fnames[0], MAXPATHL); } else { @@ -5355,8 +5355,8 @@ static void mkspell(int fcount, char **fnames, bool ascii, bool over_write, bool afile[i] = NULL; if (incount > 1) { - len = (int)STRLEN(innames[i]); - if (STRLEN(path_tail((char *)innames[i])) < 5 + len = (int)strlen(innames[i]); + if (strlen(path_tail(innames[i])) < 5 || innames[i][len - 3] != '_') { semsg(_("E755: Invalid region in %s"), innames[i]); goto theend; diff --git a/src/nvim/spellsuggest.c b/src/nvim/spellsuggest.c index c38fa2b24f..f2a0da188e 100644 --- a/src/nvim/spellsuggest.c +++ b/src/nvim/spellsuggest.c @@ -66,7 +66,7 @@ typedef struct suginfo_S { /// One word suggestion. Used in "si_ga". typedef struct { char *st_word; ///< suggested word, allocated string - int st_wordlen; ///< STRLEN(st_word) + int st_wordlen; ///< strlen(st_word) int st_orglen; ///< length of replaced text int st_score; ///< lower is better int st_altscore; ///< used when st_score compares equal @@ -354,7 +354,7 @@ int spell_check_sps(void) { char *p; char *s; - char_u buf[MAXPATHL]; + char buf[MAXPATHL]; int f; sps_flags = 0; @@ -370,11 +370,11 @@ int spell_check_sps(void) if (*s != NUL && !ascii_isdigit(*s)) { f = -1; } - } else if (STRCMP(buf, "best") == 0) { + } else if (strcmp(buf, "best") == 0) { f = SPS_BEST; - } else if (STRCMP(buf, "fast") == 0) { + } else if (strcmp(buf, "fast") == 0) { f = SPS_FAST; - } else if (STRCMP(buf, "double") == 0) { + } else if (strcmp(buf, "double") == 0) { f = SPS_DOUBLE; } else if (STRNCMP(buf, "expr:", 5) != 0 && STRNCMP(buf, "file:", 5) != 0 @@ -533,7 +533,7 @@ void spell_suggest(int count) } vim_snprintf((char *)IObuff, IOSIZE, "%2d", i + 1); if (cmdmsg_rl) { - rl_mirror(IObuff); + rl_mirror((char_u *)IObuff); } msg_puts((const char *)IObuff); @@ -559,7 +559,7 @@ void spell_suggest(int count) } if (cmdmsg_rl) { // Mirror the numbers, but keep the leading space. - rl_mirror(IObuff + 1); + rl_mirror((char_u *)IObuff + 1); } msg_advance(30); msg_puts((const char *)IObuff); @@ -1114,7 +1114,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so { char_u tword[MAXWLEN]; // good word collected so far trystate_T stack[MAXWLEN]; - char_u preword[MAXWLEN * 3] = { 0 }; // word found with proper case; + char preword[MAXWLEN * 3] = { 0 }; // word found with proper case; // concatenation of prefix compound // words and split word. NUL terminated // when going deeper but not when coming @@ -1241,7 +1241,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so // and make find_keepcap_word() works. tword[sp->ts_twordlen] = NUL; make_case_word(tword + sp->ts_splitoff, - preword + sp->ts_prewordlen, flags); + (char_u *)preword + sp->ts_prewordlen, flags); sp->ts_prewordlen = (char_u)STRLEN(preword); sp->ts_splitoff = sp->ts_twordlen; } @@ -1326,7 +1326,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so sp->ts_fidx - sp->ts_splitfidx) == 0) { preword[sp->ts_prewordlen] = NUL; newscore = score_wordcount_adj(slang, sp->ts_score, - preword + sp->ts_prewordlen, + (char_u *)preword + sp->ts_prewordlen, sp->ts_prewordlen > 0); // Add the suggestion if the score isn't too bad. if (newscore <= su->su_maxscore) { @@ -1362,13 +1362,13 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so sp->ts_twordlen - sp->ts_splitoff + 1); // Verify CHECKCOMPOUNDPATTERN rules. - if (match_checkcompoundpattern(preword, sp->ts_prewordlen, + if (match_checkcompoundpattern((char_u *)preword, sp->ts_prewordlen, &slang->sl_comppat)) { compound_ok = false; } if (compound_ok) { - p = preword; + p = (char_u *)preword; while (*skiptowhite((char *)p) != NUL) { p = (char_u *)skipwhite(skiptowhite((char *)p)); } @@ -1381,7 +1381,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so } // Get pointer to last char of previous word. - p = preword + sp->ts_prewordlen; + p = (char_u *)preword + sp->ts_prewordlen; MB_PTR_BACK(preword, p); } } @@ -1394,7 +1394,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so } else if (flags & WF_KEEPCAP) { // Must find the word in the keep-case tree. find_keepcap_word(slang, tword + sp->ts_splitoff, - preword + sp->ts_prewordlen); + (char_u *)preword + sp->ts_prewordlen); } else { // Include badflags: If the badword is onecap or allcap // use that for the goodword too. But if the badword is @@ -1413,14 +1413,14 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so c &= ~WF_ONECAP; } make_case_word(tword + sp->ts_splitoff, - preword + sp->ts_prewordlen, c); + (char_u *)preword + sp->ts_prewordlen, c); } if (!soundfold) { // Don't use a banned word. It may appear again as a good // word, thus remember it. if (flags & WF_BANNED) { - add_banned(su, preword + sp->ts_prewordlen); + add_banned(su, (char_u *)preword + sp->ts_prewordlen); break; } if ((sp->ts_complen == sp->ts_compsplit @@ -1445,7 +1445,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so } if (!spell_valid_case(su->su_badflags, - captype(preword + sp->ts_prewordlen, NULL))) { + captype((char_u *)preword + sp->ts_prewordlen, NULL))) { newscore += SCORE_ICASE; } } @@ -1457,7 +1457,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so && compound_ok) { // The badword also ends: add suggestions. #ifdef DEBUG_TRIEWALK - if (soundfold && STRCMP(preword, "smwrd") == 0) { + if (soundfold && strcmp(preword, "smwrd") == 0) { int j; // print the stack of changes that brought us here @@ -1470,14 +1470,14 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so if (soundfold) { // For soundfolded words we need to find the original // words, the edit distance and then add them. - add_sound_suggest(su, preword, sp->ts_score, lp); + add_sound_suggest(su, (char_u *)preword, sp->ts_score, lp); } else if (sp->ts_fidx > 0) { // Give a penalty when changing non-word char to word // char, e.g., "thes," -> "these". p = fword + sp->ts_fidx; MB_PTR_BACK(fword, p); if (!spell_iswordp(p, curwin) && *preword != NUL) { - p = preword + STRLEN(preword); + p = (char_u *)preword + STRLEN(preword); MB_PTR_BACK(preword, p); if (spell_iswordp(p, curwin)) { newscore += SCORE_NONWORD; @@ -1487,7 +1487,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so // Give a bonus to words seen before. score = score_wordcount_adj(slang, sp->ts_score + newscore, - preword + sp->ts_prewordlen, + (char_u *)preword + sp->ts_prewordlen, sp->ts_prewordlen > 0); // Add the suggestion if the score isn't too bad. @@ -1499,10 +1499,10 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so if (su->su_badflags & WF_MIXCAP) { // We really don't know if the word should be // upper or lower case, add both. - c = captype(preword, NULL); + c = captype((char_u *)preword, NULL); if (c == 0 || c == WF_ALLCAP) { make_case_word(tword + sp->ts_splitoff, - preword + sp->ts_prewordlen, + (char_u *)preword + sp->ts_prewordlen, c == 0 ? WF_ALLCAP : 0); add_suggestion(su, &su->su_ga, (char *)preword, @@ -1589,7 +1589,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so && (flags & WF_NEEDCOMP)) { break; } - p = preword; + p = (char_u *)preword; while (*skiptowhite((char *)p) != NUL) { p = (char_u *)skipwhite(skiptowhite((char *)p)); } @@ -1607,7 +1607,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so // Give a bonus to words seen before. newscore = score_wordcount_adj(slang, newscore, - preword + sp->ts_prewordlen, true); + (char_u *)preword + sp->ts_prewordlen, true); } if (TRY_DEEPER(su, stack, depth, newscore)) { @@ -1633,7 +1633,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so if (!try_compound && !fword_ends) { STRCAT(preword, " "); } - sp->ts_prewordlen = (char_u)STRLEN(preword); + sp->ts_prewordlen = (char_u)strlen(preword); sp->ts_splitoff = sp->ts_twordlen; sp->ts_splitfidx = sp->ts_fidx; @@ -2515,8 +2515,8 @@ static void score_combine(suginfo_T *su) garray_T *gap; langp_T *lp; suggest_T *stp; - char_u *p; - char_u badsound[MAXWLEN]; + char *p; + char badsound[MAXWLEN]; int round; slang_T *slang = NULL; @@ -2526,11 +2526,11 @@ static void score_combine(suginfo_T *su) if (!GA_EMPTY(&lp->lp_slang->sl_sal)) { // soundfold the bad word slang = lp->lp_slang; - spell_soundfold(slang, su->su_fbadword, true, badsound); + spell_soundfold(slang, su->su_fbadword, true, (char_u *)badsound); for (int i = 0; i < su->su_ga.ga_len; i++) { stp = &SUG(su->su_ga, i); - stp->st_altscore = stp_sal_score(stp, su, slang, badsound); + stp->st_altscore = stp_sal_score(stp, su, slang, (char_u *)badsound); if (stp->st_altscore == SCORE_MAXMAX) { stp->st_score = (stp->st_score * 3 + SCORE_BIG) / 4; } else { @@ -2578,10 +2578,10 @@ static void score_combine(suginfo_T *su) gap = round == 1 ? &su->su_ga : &su->su_sga; if (i < gap->ga_len) { // Don't add a word if it's already there. - p = (char_u *)SUG(*gap, i).st_word; + p = SUG(*gap, i).st_word; int j; for (j = 0; j < ga.ga_len; j++) { - if (STRCMP(stp[j].st_word, p) == 0) { + if (strcmp(stp[j].st_word, p) == 0) { break; } } @@ -2659,7 +2659,7 @@ static int stp_sal_score(suggest_T *stp, suginfo_T *su, slang_T *slang, char_u * // Sound-fold the word and compute the score for the difference. spell_soundfold(slang, pgood, false, goodsound); - return soundalike_score(goodsound, pbad); + return soundalike_score((char *)goodsound, (char *)pbad); } /// structure used to store soundfolded words that add_sound_suggest() has @@ -3070,7 +3070,7 @@ static void add_suggestion(suginfo_T *su, garray_T *gap, const char *goodword, i // Minimize "badlen" for consistency. Avoids that changing "the the" to // "thee the" is added next to changing the first "the" the "thee". - const char *pgood = goodword + STRLEN(goodword); + const char *pgood = goodword + strlen(goodword); char_u *pbad = su->su_badptr + badlenarg; for (;;) { goodlen = (int)(pgood - goodword); @@ -3306,15 +3306,15 @@ static int cleanup_suggestions(garray_T *gap, int maxscore, int keep) /// /// @param goodstart sound-folded good word /// @param badstart sound-folded bad word -static int soundalike_score(char_u *goodstart, char_u *badstart) +static int soundalike_score(char *goodstart, char *badstart) { - char_u *goodsound = goodstart; - char_u *badsound = badstart; + char *goodsound = goodstart; + char *badsound = badstart; int goodlen; int badlen; int n; - char_u *pl, *ps; - char_u *pl2, *ps2; + char *pl, *ps; + char *pl2, *ps2; int score = 0; // Adding/inserting "*" at the start (word starts with vowel) shouldn't be @@ -3345,8 +3345,8 @@ static int soundalike_score(char_u *goodstart, char_u *badstart) } } - goodlen = (int)STRLEN(goodsound); - badlen = (int)STRLEN(badsound); + goodlen = (int)strlen(goodsound); + badlen = (int)strlen(badsound); // Return quickly if the lengths are too different to be fixed by two // changes. @@ -3379,7 +3379,7 @@ static int soundalike_score(char_u *goodstart, char_u *badstart) ps++; } // strings must be equal after second delete - if (STRCMP(pl + 1, ps) == 0) { + if (strcmp(pl + 1, ps) == 0) { return score + SCORE_DEL * 2; } @@ -3403,12 +3403,12 @@ static int soundalike_score(char_u *goodstart, char_u *badstart) // 2: delete then swap, then rest must be equal if (pl2[0] == ps2[1] && pl2[1] == ps2[0] - && STRCMP(pl2 + 2, ps2 + 2) == 0) { + && strcmp(pl2 + 2, ps2 + 2) == 0) { return score + SCORE_DEL + SCORE_SWAP; } // 3: delete then substitute, then the rest must be equal - if (STRCMP(pl2 + 1, ps2 + 1) == 0) { + if (strcmp(pl2 + 1, ps2 + 1) == 0) { return score + SCORE_DEL + SCORE_SUBST; } @@ -3421,7 +3421,7 @@ static int soundalike_score(char_u *goodstart, char_u *badstart) ps2++; } // delete a char and then strings must be equal - if (STRCMP(pl2 + 1, ps2) == 0) { + if (strcmp(pl2 + 1, ps2) == 0) { return score + SCORE_SWAP + SCORE_DEL; } } @@ -3434,7 +3434,7 @@ static int soundalike_score(char_u *goodstart, char_u *badstart) ps2++; } // delete a char and then strings must be equal - if (STRCMP(pl2 + 1, ps2) == 0) { + if (strcmp(pl2 + 1, ps2) == 0) { return score + SCORE_SUBST + SCORE_DEL; } @@ -3462,12 +3462,12 @@ static int soundalike_score(char_u *goodstart, char_u *badstart) } // 3: swap and swap again if (pl2[0] == ps2[1] && pl2[1] == ps2[0] - && STRCMP(pl2 + 2, ps2 + 2) == 0) { + && strcmp(pl2 + 2, ps2 + 2) == 0) { return score + SCORE_SWAP + SCORE_SWAP; } // 4: swap and substitute - if (STRCMP(pl2 + 1, ps2 + 1) == 0) { + if (strcmp(pl2 + 1, ps2 + 1) == 0) { return score + SCORE_SWAP + SCORE_SUBST; } } @@ -3485,12 +3485,12 @@ static int soundalike_score(char_u *goodstart, char_u *badstart) // 6: substitute and swap if (pl2[0] == ps2[1] && pl2[1] == ps2[0] - && STRCMP(pl2 + 2, ps2 + 2) == 0) { + && strcmp(pl2 + 2, ps2 + 2) == 0) { return score + SCORE_SUBST + SCORE_SWAP; } // 7: substitute and substitute - if (STRCMP(pl2 + 1, ps2 + 1) == 0) { + if (strcmp(pl2 + 1, ps2 + 1) == 0) { return score + SCORE_SUBST + SCORE_SUBST; } @@ -3501,7 +3501,7 @@ static int soundalike_score(char_u *goodstart, char_u *badstart) pl2++; ps2++; } - if (STRCMP(pl2 + 1, ps2) == 0) { + if (strcmp(pl2 + 1, ps2) == 0) { return score + SCORE_INS + SCORE_DEL; } @@ -3512,7 +3512,7 @@ static int soundalike_score(char_u *goodstart, char_u *badstart) pl2++; ps2++; } - if (STRCMP(pl2, ps2 + 1) == 0) { + if (strcmp(pl2, ps2 + 1) == 0) { return score + SCORE_INS + SCORE_DEL; } diff --git a/src/nvim/state.c b/src/nvim/state.c index 61740800a1..8b07c484e6 100644 --- a/src/nvim/state.c +++ b/src/nvim/state.c @@ -65,7 +65,7 @@ getkey: // Call `os_inchar` directly to block for events or user input without // consuming anything from `input_buffer`(os/input.c) or calling the // mapping engine. - (void)os_inchar(NULL, 0, -1, 0, main_loop.events); + (void)os_inchar(NULL, 0, -1, typebuf.tb_change_cnt, main_loop.events); // If an event was put into the queue, we send K_EVENT directly. if (!multiqueue_empty(main_loop.events)) { key = K_EVENT; @@ -237,7 +237,7 @@ void may_trigger_modechanged(void) char pattern_buf[2 * MODE_MAX_LENGTH]; get_mode(curr_mode); - if (STRCMP(curr_mode, last_mode) == 0) { + if (strcmp(curr_mode, last_mode) == 0) { return; } diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c index 5f686ef96f..33c5c3a347 100644 --- a/src/nvim/statusline.c +++ b/src/nvim/statusline.c @@ -80,10 +80,11 @@ void win_redr_status(win_T *wp) p = (char_u *)NameBuff; len = (int)STRLEN(p); - if (bt_help(wp->w_buffer) - || wp->w_p_pvw - || bufIsChanged(wp->w_buffer) - || wp->w_buffer->b_p_ro) { + if ((bt_help(wp->w_buffer) + || wp->w_p_pvw + || bufIsChanged(wp->w_buffer) + || wp->w_buffer->b_p_ro) + && len < MAXPATHL - 1) { *(p + len++) = ' '; } if (bt_help(wp->w_buffer)) { @@ -100,7 +101,7 @@ void win_redr_status(win_T *wp) } if (wp->w_buffer->b_p_ro) { snprintf((char *)p + len, MAXPATHL - (size_t)len, "%s", _("[RO]")); - // len += (int)STRLEN(p + len); // dead assignment + // len += (int)strlen(p + len); // dead assignment } this_ru_col = ru_col - (Columns - width); @@ -137,9 +138,9 @@ void win_redr_status(win_T *wp) this_ru_col + col, fillchar, fillchar, attr); if (get_keymap_str(wp, "<%s>", (char *)NameBuff, MAXPATHL) - && this_ru_col - len > (int)(STRLEN(NameBuff) + 1)) { + && this_ru_col - len > (int)(strlen(NameBuff) + 1)) { grid_puts(&default_grid, NameBuff, row, - (int)((size_t)this_ru_col - STRLEN(NameBuff) - 1), attr); + (int)((size_t)this_ru_col - strlen(NameBuff) - 1), attr); } win_redr_ruler(wp, true); @@ -266,7 +267,7 @@ void win_redr_ruler(win_T *wp, bool always) off = 0; } - if (!part_of_status && !ui_has_messages()) { + if (!part_of_status && p_ch == 0 && !ui_has(kUIMessages)) { return; } @@ -286,7 +287,7 @@ void win_redr_ruler(win_T *wp, bool always) vim_snprintf(buffer, RULER_BUF_LEN, "%" PRId64 ",", (wp->w_buffer->b_ml.ml_flags & ML_EMPTY) ? (int64_t)0L : (int64_t)wp->w_cursor.lnum); - size_t len = STRLEN(buffer); + size_t len = strlen(buffer); col_print(buffer + len, RULER_BUF_LEN - len, empty_line ? 0 : (int)wp->w_cursor.col + 1, (int)virtcol + 1); @@ -294,7 +295,7 @@ void win_redr_ruler(win_T *wp, bool always) // Add a "50%" if there is room for it. // On the last line, don't print in the last column (scrolls the // screen up on some terminals). - int i = (int)STRLEN(buffer); + int i = (int)strlen(buffer); get_rel_pos(wp, buffer + i + 1, RULER_BUF_LEN - i - 1); int o = i + vim_strsize(buffer + i + 1); if (wp->w_status_height == 0 && !is_stl_global) { // can't use last char of screen @@ -344,7 +345,7 @@ void win_redr_ruler(win_T *wp, bool always) ScreenGrid *grid = part_of_status ? &default_grid : &msg_grid_adj; grid_puts(grid, buffer, row, this_ru_col + off, attr); grid_fill(grid, row, row + 1, - this_ru_col + off + (int)STRLEN(buffer), off + width, fillchar, + this_ru_col + off + (int)strlen(buffer), off + width, fillchar, fillchar, attr); } @@ -717,7 +718,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, int use_san // Get the byte value now, in case we need it below. This is more // efficient than making a copy of the line. int byteval; - const size_t len = STRLEN(line_ptr); + const size_t len = strlen(line_ptr); if (wp->w_cursor.col > (colnr_T)len) { // Line may have changed since checking the cursor column, or the lnum // was adjusted above. @@ -1190,8 +1191,8 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, int use_san && strchr((const char *)str, '%') != NULL && evaldepth < MAX_STL_EVAL_DEPTH) { size_t parsed_usefmt = (size_t)(block_start - usefmt); - size_t str_length = STRLEN(str); - size_t fmt_length = STRLEN(fmt_p); + size_t str_length = strlen(str); + size_t fmt_length = strlen(fmt_p); size_t new_fmt_len = parsed_usefmt + str_length + fmt_length + 3; char *new_fmt = xmalloc(new_fmt_len * sizeof(char)); char *new_fmt_p = new_fmt; @@ -1328,7 +1329,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, int use_san // in the temporary buffer // (including the brackets and null terminating character) if (*wp->w_buffer->b_p_ft != NUL - && STRLEN(wp->w_buffer->b_p_ft) < TMPLEN - 3) { + && strlen(wp->w_buffer->b_p_ft) < TMPLEN - 3) { vim_snprintf(buf_tmp, sizeof(buf_tmp), "[%s]", wp->w_buffer->b_p_ft); str = buf_tmp; @@ -1341,7 +1342,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, int use_san // in the temporary buffer // (including the comma and null terminating character) if (*wp->w_buffer->b_p_ft != NUL - && STRLEN(wp->w_buffer->b_p_ft) < TMPLEN - 2) { + && strlen(wp->w_buffer->b_p_ft) < TMPLEN - 2) { 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++) { @@ -1561,7 +1562,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, int use_san // Advance the output buffer position to the end of the // number we just printed - out_p += STRLEN(out_p); + out_p += strlen(out_p); // Otherwise, there was nothing to print so mark the item as empty } else { @@ -1669,7 +1670,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, int use_san if (width + 1 < maxwidth) { // Advance the pointer to the end of the string - trunc_p = trunc_p + STRLEN(trunc_p); + trunc_p = trunc_p + strlen(trunc_p); } // Fill up for half a double-wide character. @@ -1705,7 +1706,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, int use_san // add characters at the separate marker (if there is one) to // fill up the available space. } else if (width < maxwidth - && STRLEN(out) + (size_t)(maxwidth - width) + 1 < outlen) { + && strlen(out) + (size_t)(maxwidth - width) + 1 < outlen) { // Find how many separators there are, which we will use when // figuring out how many groups there are. int num_separators = 0; diff --git a/src/nvim/strings.c b/src/nvim/strings.c index 04f9311d7e..10173fac1d 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -186,7 +186,7 @@ char_u *vim_strsave_shellescape(const char_u *string, bool do_special, bool do_n // First count the number of extra bytes required. size_t length = STRLEN(string) + 3; // two quotes and a trailing NUL for (const char_u *p = string; *p != NUL; MB_PTR_ADV(p)) { -#ifdef WIN32 +#ifdef MSWIN if (!p_ssl) { if (*p == '"') { length++; // " -> "" @@ -217,7 +217,7 @@ char_u *vim_strsave_shellescape(const char_u *string, bool do_special, bool do_n d = (char *)escaped_string; // add opening quote -#ifdef WIN32 +#ifdef MSWIN if (!p_ssl) { *d++ = '"'; } else @@ -225,7 +225,7 @@ char_u *vim_strsave_shellescape(const char_u *string, bool do_special, bool do_n *d++ = '\''; for (const char *p = (char *)string; *p != NUL;) { -#ifdef WIN32 +#ifdef MSWIN if (!p_ssl) { if (*p == '"') { *d++ = '"'; @@ -269,7 +269,7 @@ char_u *vim_strsave_shellescape(const char_u *string, bool do_special, bool do_n } // add terminating quote and finish with a NUL -#ifdef WIN32 +#ifdef MSWIN if (!p_ssl) { *d++ = '"'; } else @@ -341,7 +341,7 @@ char *strcase_save(const char *const orig, bool upper) int newl = utf_char2len(uc); if (newl != l) { // TODO(philix): use xrealloc() in strcase_save() - char *s = xmalloc(STRLEN(res) + (size_t)(1 + newl - l)); + char *s = xmalloc(strlen(res) + (size_t)(1 + newl - l)); memcpy(s, res, (size_t)(p - res)); STRCPY(s + (p - res) + newl, p + l); p = s + (p - res); @@ -460,7 +460,7 @@ char *vim_strchr(const char *const string, const int c) static int sort_compare(const void *s1, const void *s2) FUNC_ATTR_NONNULL_ALL { - return STRCMP(*(char **)s1, *(char **)s2); + return strcmp(*(char **)s1, *(char **)s2); } void sort_strings(char **files, int count) @@ -504,8 +504,8 @@ bool has_non_ascii_len(const char *const s, const size_t len) char *concat_str(const char *restrict str1, const char *restrict str2) FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL { - size_t l = STRLEN(str1); - char *dest = xmalloc(l + STRLEN(str2) + 1); + size_t l = strlen(str1); + char *dest = xmalloc(l + strlen(str2) + 1); STRCPY(dest, str1); STRCPY(dest + l, str2); return dest; @@ -1473,7 +1473,7 @@ char *reverse_text(char *s) FUNC_ATTR_NONNULL_RET { // Reverse the pattern. - size_t len = STRLEN(s); + size_t len = strlen(s); char *rev = xmalloc(len + 1); size_t rev_i = len; for (size_t s_i = 0; s_i < len; s_i++) { @@ -1498,7 +1498,7 @@ char *reverse_text(char *s) char *strrep(const char *src, const char *what, const char *rep) { char *pos = (char *)src; - size_t whatlen = STRLEN(what); + size_t whatlen = strlen(what); // Count occurrences size_t count = 0; @@ -1511,8 +1511,8 @@ char *strrep(const char *src, const char *what, const char *rep) return NULL; } - size_t replen = STRLEN(rep); - char *ret = xmalloc(STRLEN(src) + count * (replen - whatlen) + 1); + size_t replen = strlen(rep); + char *ret = xmalloc(strlen(src) + count * (replen - whatlen) + 1); char *ptr = ret; while ((pos = strstr(src, what)) != NULL) { size_t idx = (size_t)(pos - src); diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index 1daeebd7b9..575d475b87 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -98,7 +98,7 @@ typedef struct syn_pattern { typedef struct syn_cluster_S { char_u *scl_name; // syntax cluster name - char_u *scl_name_u; // uppercase of scl_name + char *scl_name_u; // uppercase of scl_name int16_t *scl_list; // IDs in this syntax cluster } syn_cluster_T; @@ -2295,7 +2295,7 @@ static void update_si_end(stateitem_T *sip, int startcol, bool force) // a "oneline" never continues in the next line sip->si_ends = true; sip->si_m_endpos.lnum = current_lnum; - sip->si_m_endpos.col = (colnr_T)STRLEN(syn_getcurline()); + sip->si_m_endpos.col = (colnr_T)strlen(syn_getcurline()); } else { // continues in the next line sip->si_ends = false; @@ -2646,7 +2646,7 @@ static void syn_add_start_off(lpos_T *result, regmmatch_T *regmatch, synpat_T *s if (result->lnum > syn_buf->b_ml.ml_line_count) { // a "\n" at the end of the pattern may take us below the last line result->lnum = syn_buf->b_ml.ml_line_count; - col = (int)STRLEN(ml_get_buf(syn_buf, result->lnum, false)); + col = (int)strlen(ml_get_buf(syn_buf, result->lnum, false)); } if (off != 0) { base = (char_u *)ml_get_buf(syn_buf, result->lnum, false); @@ -3734,11 +3734,11 @@ static void add_keyword(char *const name, const int id, const int flags, { char name_folded[MAXKEYWLEN + 1]; const char *const name_ic = (curwin->w_s->b_syn_ic) - ? (char *)str_foldcase((char_u *)name, (int)STRLEN(name), (char_u *)name_folded, + ? (char *)str_foldcase((char_u *)name, (int)strlen(name), (char_u *)name_folded, sizeof(name_folded)) : name; - keyentry_T *const kp = xmalloc(sizeof(keyentry_T) + STRLEN(name_ic)); + keyentry_T *const kp = xmalloc(sizeof(keyentry_T) + strlen(name_ic)); STRCPY(kp->keyword, name_ic); kp->k_syn.id = (int16_t)id; kp->k_syn.inc_tag = current_syn_inc_tag; @@ -3918,7 +3918,7 @@ static char *get_syn_options(char *arg, syn_opt_arg_T *opt, int *conceal_char, i return NULL; } gname = xstrnsave(gname_start, (size_t)(arg - gname_start)); - if (STRCMP(gname, "NONE") == 0) { + if (strcmp(gname, "NONE") == 0) { *opt->sync_idx = NONE_IDX; } else { syn_id = syn_name2id(gname); @@ -4063,7 +4063,7 @@ static void syn_cmd_keyword(exarg_T *eap, int syncing) } if (syn_id != 0) { // Allocate a buffer, for removing backslashes in the keyword. - keyword_copy = xmalloc(STRLEN(rest) + 1); + keyword_copy = xmalloc(strlen(rest) + 1); } if (keyword_copy != NULL) { syn_opt_arg.flags = 0; @@ -4099,7 +4099,7 @@ static void syn_cmd_keyword(exarg_T *eap, int syncing) syn_incl_toplevel(syn_id, &syn_opt_arg.flags); // 2: Add an entry for each keyword. - for (kw = keyword_copy; --cnt >= 0; kw += STRLEN(kw) + 1) { + for (kw = keyword_copy; --cnt >= 0; kw += strlen(kw) + 1) { for (p = vim_strchr(kw, '[');;) { if (p != NULL) { *p = NUL; @@ -4306,13 +4306,13 @@ static void syn_cmd_region(exarg_T *eap, int syncing) } xfree(key); key = vim_strnsave_up(rest, (size_t)(key_end - rest)); - if (STRCMP(key, "MATCHGROUP") == 0) { + if (strcmp(key, "MATCHGROUP") == 0) { item = ITEM_MATCHGROUP; - } else if (STRCMP(key, "START") == 0) { + } else if (strcmp(key, "START") == 0) { item = ITEM_START; - } else if (STRCMP(key, "END") == 0) { + } else if (strcmp(key, "END") == 0) { item = ITEM_END; - } else if (STRCMP(key, "SKIP") == 0) { + } else if (strcmp(key, "SKIP") == 0) { if (pat_ptrs[ITEM_SKIP] != NULL) { // One skip pattern allowed. illegal = true; break; @@ -4584,7 +4584,7 @@ static int syn_scl_name2id(char *name) int i; for (i = curwin->w_s->b_syn_clusters.ga_len; --i >= 0;) { if (SYN_CLSTR(curwin->w_s)[i].scl_name_u != NULL - && STRCMP(name_u, SYN_CLSTR(curwin->w_s)[i].scl_name_u) == 0) { + && strcmp(name_u, SYN_CLSTR(curwin->w_s)[i].scl_name_u) == 0) { break; } } @@ -4642,7 +4642,7 @@ static int syn_add_cluster(char *name) &curwin->w_s->b_syn_clusters); CLEAR_POINTER(scp); scp->scl_name = (char_u *)name; - scp->scl_name_u = vim_strsave_up((char_u *)name); + scp->scl_name_u = (char *)vim_strsave_up((char_u *)name); scp->scl_list = NULL; if (STRICMP(name, "Spell") == 0) { @@ -4847,7 +4847,7 @@ static void syn_cmd_sync(exarg_T *eap, int syncing) next_arg = skipwhite(arg_end); xfree(key); key = vim_strnsave_up(arg_start, (size_t)(arg_end - arg_start)); - if (STRCMP(key, "CCOMMENT") == 0) { + if (strcmp(key, "CCOMMENT") == 0) { if (!eap->skip) { curwin->w_s->b_syn_sync_flags |= SF_CCOMMENT; } @@ -4886,12 +4886,12 @@ static void syn_cmd_sync(exarg_T *eap, int syncing) curwin->w_s->b_syn_sync_minlines = n; } } - } else if (STRCMP(key, "FROMSTART") == 0) { + } else if (strcmp(key, "FROMSTART") == 0) { if (!eap->skip) { curwin->w_s->b_syn_sync_minlines = MAXLNUM; curwin->w_s->b_syn_sync_maxlines = 0; } - } else if (STRCMP(key, "LINECONT") == 0) { + } else if (strcmp(key, "LINECONT") == 0) { if (*next_arg == NUL) { // missing pattern illegal = true; break; @@ -4930,11 +4930,11 @@ static void syn_cmd_sync(exarg_T *eap, int syncing) next_arg = skipwhite(arg_end + 1); } else { eap->arg = next_arg; - if (STRCMP(key, "MATCH") == 0) { + if (strcmp(key, "MATCH") == 0) { syn_cmd_match(eap, true); - } else if (STRCMP(key, "REGION") == 0) { + } else if (strcmp(key, "REGION") == 0) { syn_cmd_region(eap, true); - } else if (STRCMP(key, "CLEAR") == 0) { + } else if (strcmp(key, "CLEAR") == 0) { syn_cmd_clear(eap, true); } else { illegal = true; @@ -4997,10 +4997,10 @@ static int get_id_list(char **const arg, const int keylen, int16_t **const list, for (end = p; *end && !ascii_iswhite(*end) && *end != ','; end++) {} char *const name = xmalloc((size_t)(end - p) + 3); // leave room for "^$" STRLCPY(name + 1, p, end - p + 1); - if (STRCMP(name + 1, "ALLBUT") == 0 - || STRCMP(name + 1, "ALL") == 0 - || STRCMP(name + 1, "TOP") == 0 - || STRCMP(name + 1, "CONTAINED") == 0) { + if (strcmp(name + 1, "ALLBUT") == 0 + || strcmp(name + 1, "ALL") == 0 + || strcmp(name + 1, "TOP") == 0 + || strcmp(name + 1, "CONTAINED") == 0) { if (TOUPPER_ASC(**arg) != 'C') { semsg(_("E407: %s not allowed here"), name + 1); failed = true; @@ -5280,7 +5280,7 @@ void ex_syntax(exarg_T *eap) semsg(_("E410: Invalid :syntax subcommand: %s"), subcmd_name); break; } - if (STRCMP(subcmd_name, subcommands[i].name) == 0) { + if (strcmp(subcmd_name, subcommands[i].name) == 0) { eap->arg = skipwhite(subcmd_end); (subcommands[i].func)(eap, false); break; @@ -5566,13 +5566,13 @@ int syn_get_foldlevel(win_T *wp, linenr_T lnum) // ":syntime". void ex_syntime(exarg_T *eap) { - if (STRCMP(eap->arg, "on") == 0) { + if (strcmp(eap->arg, "on") == 0) { syn_time_on = true; - } else if (STRCMP(eap->arg, "off") == 0) { + } else if (strcmp(eap->arg, "off") == 0) { syn_time_on = false; - } else if (STRCMP(eap->arg, "clear") == 0) { + } else if (strcmp(eap->arg, "clear") == 0) { syntime_clear(); - } else if (STRCMP(eap->arg, "report") == 0) { + } else if (strcmp(eap->arg, "report") == 0) { syntime_report(); } else { semsg(_(e_invarg2), eap->arg); diff --git a/src/nvim/tag.c b/src/nvim/tag.c index 8be752239c..a8d8eebb0d 100644 --- a/src/nvim/tag.c +++ b/src/nvim/tag.c @@ -52,8 +52,7 @@ // Structure to hold pointers to various items in a tag line. typedef struct tag_pointers { // filled in by parse_tag_line(): - char_u *tagname; // start of tag name (skip "file:") - // + char *tagname; // start of tag name (skip "file:") char_u *tagname_end; // char after tag name char_u *fname; // first char of file name char_u *fname_end; // char after file name @@ -225,7 +224,7 @@ bool do_tag(char *tag, int type, int count, int forceit, int verbose) )) { if (g_do_tagpreview != 0) { if (ptag_entry.tagname != NULL - && STRCMP(ptag_entry.tagname, tag) == 0) { + && strcmp(ptag_entry.tagname, tag) == 0) { // Jumping to same tag: keep the current match, so that // the CursorHold autocommand example works. cur_match = ptag_entry.cur_match; @@ -429,7 +428,7 @@ bool do_tag(char *tag, int type, int count, int forceit, int verbose) } else { name = tag; } - other_name = (tagmatchname == NULL || STRCMP(tagmatchname, name) != 0); + other_name = (tagmatchname == NULL || strcmp(tagmatchname, name) != 0); if (new_tag || (cur_match >= num_matches && max_num_matches != MAXCOL) || other_name) { @@ -487,7 +486,7 @@ bool do_tag(char *tag, int type, int count, int forceit, int verbose) parse_match(matches[j], &tagp); for (i = idx; i < new_num_matches; i++) { parse_match(new_matches[i], &tagp2); - if (STRCMP(tagp.tagname, tagp2.tagname) == 0) { + if (strcmp(tagp.tagname, tagp2.tagname) == 0) { char_u *p = (char_u *)new_matches[i]; for (k = i; k > idx; k--) { new_matches[k] = new_matches[k - 1]; @@ -683,7 +682,7 @@ static void print_tag_list(int new_tag, int use_tagstack, int num_matches, char // Assume that the first match indicates how long the tags can // be, and align the file names to that. parse_match(matches[0], &tagp); - taglen = (int)(tagp.tagname_end - tagp.tagname + 2); + taglen = (int)(tagp.tagname_end - (char_u *)tagp.tagname + 2); if (taglen < 18) { taglen = 18; } @@ -719,8 +718,8 @@ static void print_tag_list(int new_tag, int use_tagstack, int num_matches, char (int)(tagp.tagkind_end - tagp.tagkind)); } msg_advance(13); - msg_outtrans_len_attr((char *)tagp.tagname, - (int)(tagp.tagname_end - tagp.tagname), + msg_outtrans_len_attr(tagp.tagname, + (int)(tagp.tagname_end - (char_u *)tagp.tagname), HL_ATTR(HLF_T)); msg_putchar(' '); taglen_advance(taglen); @@ -877,7 +876,7 @@ static int add_llist_tags(char_u *tag, int num_matches, char **matches) parse_match(matches[i], &tagp); // Save the tag name - len = (int)(tagp.tagname_end - tagp.tagname); + len = (int)(tagp.tagname_end - (char_u *)tagp.tagname); if (len > 128) { len = 128; } @@ -1191,7 +1190,7 @@ static int find_tagfunc_tags(char_u *pat, garray_T *ga, int *match_count, int fl res_kind = NULL; TV_DICT_ITER(TV_LIST_ITEM_TV(li)->vval.v_dict, di, { - const char_u *dict_key = di->di_key; + const char *dict_key = (char *)di->di_key; typval_T *tv = &di->di_tv; if (tv->v_type != VAR_STRING || tv->vval.v_string == NULL) { @@ -1199,26 +1198,26 @@ static int find_tagfunc_tags(char_u *pat, garray_T *ga, int *match_count, int fl } len += strlen(tv->vval.v_string) + 1; // Space for "\tVALUE" - if (!STRCMP(dict_key, "name")) { + if (!strcmp(dict_key, "name")) { res_name = tv->vval.v_string; continue; } - if (!STRCMP(dict_key, "filename")) { + if (!strcmp(dict_key, "filename")) { res_fname = (char_u *)tv->vval.v_string; continue; } - if (!STRCMP(dict_key, "cmd")) { + if (!strcmp(dict_key, "cmd")) { res_cmd = (char_u *)tv->vval.v_string; continue; } has_extra = 1; - if (!STRCMP(dict_key, "kind")) { + if (!strcmp(dict_key, "kind")) { res_kind = (char_u *)tv->vval.v_string; continue; } // Other elements will be stored as "\tKEY:VALUE" // Allocate space for the key and the colon - len += STRLEN(dict_key) + 1; + len += strlen(dict_key) + 1; }); if (has_extra) { @@ -1260,22 +1259,22 @@ static int find_tagfunc_tags(char_u *pat, garray_T *ga, int *match_count, int fl } TV_DICT_ITER(TV_LIST_ITEM_TV(li)->vval.v_dict, di, { - const char_u *dict_key = di->di_key; + const char *dict_key = (char *)di->di_key; typval_T *tv = &di->di_tv; if (tv->v_type != VAR_STRING || tv->vval.v_string == NULL) { continue; } - if (!STRCMP(dict_key, "name")) { + if (!strcmp(dict_key, "name")) { continue; } - if (!STRCMP(dict_key, "filename")) { + if (!strcmp(dict_key, "filename")) { continue; } - if (!STRCMP(dict_key, "cmd")) { + if (!strcmp(dict_key, "cmd")) { continue; } - if (!STRCMP(dict_key, "kind")) { + if (!strcmp(dict_key, "kind")) { continue; } @@ -1814,7 +1813,7 @@ parse_line: // This speeds up tag searching a lot! if (orgpat.headlen) { CLEAR_FIELD(tagp); - tagp.tagname = lbuf; + tagp.tagname = (char *)lbuf; tagp.tagname_end = (char_u *)vim_strchr((char *)lbuf, TAB); if (tagp.tagname_end == NULL) { // Corrupted tag line. @@ -1824,7 +1823,7 @@ parse_line: // Skip this line if the length of the tag is different and // there is no regexp, or the tag is too short. - cmplen = (int)(tagp.tagname_end - tagp.tagname); + cmplen = (int)(tagp.tagname_end - (char_u *)tagp.tagname); if (p_tl != 0 && cmplen > p_tl) { // adjust for 'taglength' cmplen = (int)p_tl; } @@ -1846,7 +1845,7 @@ parse_line: // Compare the current tag with the searched tag. if (sortic) { - tagcmp = tag_strnicmp(tagp.tagname, orgpat.head, + tagcmp = tag_strnicmp((char_u *)tagp.tagname, orgpat.head, (size_t)cmplen); } else { tagcmp = STRNCMP(tagp.tagname, orgpat.head, cmplen); @@ -1877,7 +1876,7 @@ parse_line: search_info.low_char = TOUPPER_ASC(tagp.tagname[0]); } else { - search_info.low_char = tagp.tagname[0]; + search_info.low_char = (uint8_t)tagp.tagname[0]; } continue; } @@ -1889,7 +1888,7 @@ parse_line: search_info.high_char = TOUPPER_ASC(tagp.tagname[0]); } else { - search_info.high_char = tagp.tagname[0]; + search_info.high_char = (uint8_t)tagp.tagname[0]; } continue; } @@ -1898,7 +1897,7 @@ parse_line: break; } else if (state == TS_SKIP_BACK) { assert(cmplen >= 0); - if (mb_strnicmp((char *)tagp.tagname, (char *)orgpat.head, (size_t)cmplen) != 0) { + if (mb_strnicmp(tagp.tagname, (char *)orgpat.head, (size_t)cmplen) != 0) { state = TS_STEP_FORWARD; } else { // Have to skip back more. Restore the curr_offset @@ -1908,7 +1907,7 @@ parse_line: continue; } else if (state == TS_STEP_FORWARD) { assert(cmplen >= 0); - if (mb_strnicmp((char *)tagp.tagname, (char *)orgpat.head, (size_t)cmplen) != 0) { + if (mb_strnicmp(tagp.tagname, (char *)orgpat.head, (size_t)cmplen) != 0) { if ((off_T)vim_ftell(fp) > search_info.match_offset) { break; // past last match } else { @@ -1919,7 +1918,7 @@ parse_line: // skip this match if it can't match assert(cmplen >= 0); } - if (mb_strnicmp((char *)tagp.tagname, (char *)orgpat.head, (size_t)cmplen) != 0) { + if (mb_strnicmp(tagp.tagname, (char *)orgpat.head, (size_t)cmplen) != 0) { continue; } @@ -1943,7 +1942,7 @@ parse_line: // First try matching with the pattern literally (also when it is // a regexp). - cmplen = (int)(tagp.tagname_end - tagp.tagname); + cmplen = (int)(tagp.tagname_end - (char_u *)tagp.tagname); if (p_tl != 0 && cmplen > p_tl) { // adjust for 'taglength' cmplen = (int)p_tl; } @@ -1953,7 +1952,7 @@ parse_line: } else { if (orgpat.regmatch.rm_ic) { assert(cmplen >= 0); - match = mb_strnicmp((char *)tagp.tagname, (char *)orgpat.pat, (size_t)cmplen) == 0; + match = mb_strnicmp(tagp.tagname, (char *)orgpat.pat, (size_t)cmplen) == 0; if (match) { match_no_ic = (STRNCMP(tagp.tagname, orgpat.pat, cmplen) == 0); @@ -1970,12 +1969,12 @@ parse_line: cc = *tagp.tagname_end; *tagp.tagname_end = NUL; - match = vim_regexec(&orgpat.regmatch, (char *)tagp.tagname, (colnr_T)0); + match = vim_regexec(&orgpat.regmatch, tagp.tagname, (colnr_T)0); if (match) { matchoff = (int)(orgpat.regmatch.startp[0] - tagp.tagname); if (orgpat.regmatch.rm_ic) { orgpat.regmatch.rm_ic = false; - match_no_ic = vim_regexec(&orgpat.regmatch, (char *)tagp.tagname, (colnr_T)0); + match_no_ic = vim_regexec(&orgpat.regmatch, tagp.tagname, (colnr_T)0); orgpat.regmatch.rm_ic = true; } } @@ -2029,7 +2028,7 @@ parse_line: // detecting duplicates. // The format is {tagname}@{lang}NUL{heuristic}NUL *tagp.tagname_end = NUL; - len = (size_t)(tagp.tagname_end - tagp.tagname); + len = (size_t)(tagp.tagname_end - (char_u *)tagp.tagname); mfp = xmalloc(sizeof(char) + len + 10 + ML_EXTRA + 1); p = (char_u *)mfp; @@ -2037,7 +2036,7 @@ parse_line: p[len] = '@'; STRCPY(p + len + 1, help_lang); snprintf((char *)p + len + 1 + ML_EXTRA, STRLEN(p) + len + 1 + ML_EXTRA, "%06d", - help_heuristic((char *)tagp.tagname, + help_heuristic(tagp.tagname, match_re ? matchoff : 0, !match_no_ic) + help_pri); @@ -2063,7 +2062,7 @@ parse_line: } get_it_again = false; } else { - len = (size_t)(tagp.tagname_end - tagp.tagname); + len = (size_t)(tagp.tagname_end - (char_u *)tagp.tagname); mfp = xmalloc(sizeof(char) + len + 1); STRLCPY(mfp, tagp.tagname, len + 1); @@ -2306,7 +2305,7 @@ int get_tagfname(tagname_T *tnp, int first, char *buf) simplify_filename((char_u *)buf); for (int i = 0; i < tag_fnames.ga_len; i++) { - if (STRCMP(buf, ((char **)(tag_fnames.ga_data))[i]) == 0) { + if (strcmp(buf, ((char **)(tag_fnames.ga_data))[i]) == 0) { return FAIL; // avoid duplicate file names } } @@ -2394,7 +2393,7 @@ static int parse_tag_line(char_u *lbuf, tagptrs_T *tagp) char_u *p; // Isolate the tagname, from lbuf up to the first white - tagp->tagname = lbuf; + tagp->tagname = (char *)lbuf; p = (char_u *)vim_strchr((char *)lbuf, TAB); if (p == NULL) { return FAIL; @@ -3015,7 +3014,7 @@ int expand_tags(int tagnames, char_u *pat, int *num_file, char ***file) size_t len; parse_match((*file)[i], &t_p); - len = (size_t)(t_p.tagname_end - t_p.tagname); + len = (size_t)(t_p.tagname_end - (char_u *)t_p.tagname); if (len > name_buf_size - 3) { char_u *buf; @@ -3112,7 +3111,7 @@ int get_tags(list_T *list, char_u *pat, char_u *buf_fname) tv_list_append_dict(list, dict); full_fname = tag_full_fname(&tp); - if (add_tag_field(dict, "name", (char *)tp.tagname, (char *)tp.tagname_end) == FAIL + if (add_tag_field(dict, "name", tp.tagname, (char *)tp.tagname_end) == FAIL || add_tag_field(dict, "filename", (char *)full_fname, NULL) == FAIL || add_tag_field(dict, "cmd", (char *)tp.command, (char *)tp.command_end) == FAIL || add_tag_field(dict, "kind", (char *)tp.tagkind, diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index 744579217b..326c868be8 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -234,7 +234,7 @@ Terminal *terminal_open(buf_T *buf, TerminalOptions opts) set_option_value("wrap", false, NULL, OPT_LOCAL); set_option_value("list", false, NULL, OPT_LOCAL); if (buf->b_ffname != NULL) { - buf_set_term_title(buf, buf->b_ffname, strlen((char *)buf->b_ffname)); + buf_set_term_title(buf, buf->b_ffname, strlen(buf->b_ffname)); } RESET_BINDING(curwin); // Reset cursor in current window. @@ -428,7 +428,7 @@ bool terminal_enter(void) long save_w_p_so = curwin->w_p_so; long save_w_p_siso = curwin->w_p_siso; if (curwin->w_p_cul && curwin->w_p_culopt_flags & CULOPT_NBR) { - if (STRCMP(curwin->w_p_culopt, "number")) { + if (strcmp(curwin->w_p_culopt, "number")) { save_w_p_culopt = curwin->w_p_culopt; curwin->w_p_culopt = xstrdup("number"); } @@ -693,7 +693,7 @@ void terminal_paste(long count, char **y_array, size_t y_size) return; } vterm_keyboard_start_paste(curbuf->terminal->vt); - size_t buff_len = STRLEN(y_array[0]); + size_t buff_len = strlen(y_array[0]); char_u *buff = xmalloc(buff_len); for (int i = 0; i < count; i++) { // -V756 // feed the lines to the terminal @@ -702,7 +702,7 @@ void terminal_paste(long count, char **y_array, size_t y_size) // terminate the previous line terminal_send(curbuf->terminal, "\n", 1); } - size_t len = STRLEN(y_array[j]); + size_t len = strlen(y_array[j]); if (len > buff_len) { buff = xrealloc(buff, len); buff_len = len; diff --git a/src/nvim/testdir/setup.vim b/src/nvim/testdir/setup.vim index 472ed4ca14..f895287469 100644 --- a/src/nvim/testdir/setup.vim +++ b/src/nvim/testdir/setup.vim @@ -45,6 +45,11 @@ mapclear! aunmenu * tlunmenu * +" roughly equivalent to test_setmouse() in Vim +func Ntest_setmouse(row, col) + call nvim_input_mouse('move', '', '', 0, a:row - 1, a:col - 1) +endfunc + " Prevent Nvim log from writing to stderr. let $NVIM_LOG_FILE = exists($NVIM_LOG_FILE) ? $NVIM_LOG_FILE : 'Xnvim.log' diff --git a/src/nvim/testdir/test_assert.vim b/src/nvim/testdir/test_assert.vim index fdd8b0bef6..8723a0a38d 100644 --- a/src/nvim/testdir/test_assert.vim +++ b/src/nvim/testdir/test_assert.vim @@ -278,19 +278,18 @@ func Test_assert_with_msg() endfunc func Test_mouse_position() - throw 'Skipped: Nvim does not have test_setmouse()' let save_mouse = &mouse set mouse=a new call setline(1, ['line one', 'line two']) call assert_equal([0, 1, 1, 0], getpos('.')) - call test_setmouse(1, 5) + call Ntest_setmouse(1, 5) call feedkeys("\<LeftMouse>", "xt") call assert_equal([0, 1, 5, 0], getpos('.')) - call test_setmouse(2, 20) + call Ntest_setmouse(2, 20) call feedkeys("\<LeftMouse>", "xt") call assert_equal([0, 2, 8, 0], getpos('.')) - call test_setmouse(5, 1) + call Ntest_setmouse(5, 1) call feedkeys("\<LeftMouse>", "xt") call assert_equal([0, 2, 1, 0], getpos('.')) bwipe! diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim index 3064b199d9..1be2d11034 100644 --- a/src/nvim/testdir/test_autocmd.vim +++ b/src/nvim/testdir/test_autocmd.vim @@ -533,7 +533,9 @@ func Test_BufReadCmdNofile() \ 'acwrite', \ 'quickfix', \ 'help', + "\ 'terminal', \ 'prompt', + "\ 'popup', \ ] new somefile exe 'set buftype=' .. val @@ -650,7 +652,9 @@ func Test_BufEnter() \ 'acwrite', \ 'quickfix', \ 'help', + "\ 'terminal', \ 'prompt', + "\ 'popup', \ ] new somefile exe 'set buftype=' .. val diff --git a/src/nvim/testdir/test_clientserver.vim b/src/nvim/testdir/test_clientserver.vim index 66ee776a90..a4ebce5af9 100644 --- a/src/nvim/testdir/test_clientserver.vim +++ b/src/nvim/testdir/test_clientserver.vim @@ -64,8 +64,8 @@ func Test_client_server() " the GUI and check that the remote command still works. " Need to wait for the GUI to start up, otherwise the send hangs in trying " to send to the terminal window. - if has('gui_athena') || has('gui_motif') - " For those GUIs, ignore the 'failed to create input context' error. + if has('gui_motif') + " For this GUI ignore the 'failed to create input context' error. call remote_send(name, ":call test_ignore_error('E285') | gui -f\<CR>") else call remote_send(name, ":gui -f\<CR>") diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim index e40ff65051..60f6930c35 100644 --- a/src/nvim/testdir/test_cmdline.vim +++ b/src/nvim/testdir/test_cmdline.vim @@ -127,6 +127,60 @@ func Test_wildmenu_screendump() call delete('XTest_wildmenu') endfunc +func Test_redraw_in_autocmd() + CheckScreendump + + let lines =<< trim END + set cmdheight=2 + autocmd CmdlineChanged * redraw + END + call writefile(lines, 'XTest_redraw', 'D') + + let buf = RunVimInTerminal('-S XTest_redraw', {'rows': 8}) + call term_sendkeys(buf, ":for i in range(3)\<CR>") + call VerifyScreenDump(buf, 'Test_redraw_in_autocmd_1', {}) + + call term_sendkeys(buf, "let i =") + call VerifyScreenDump(buf, 'Test_redraw_in_autocmd_2', {}) + + " clean up + call term_sendkeys(buf, "\<CR>") + call StopVimInTerminal(buf) +endfunc + +func Test_redrawstatus_in_autocmd() + CheckScreendump + + let lines =<< trim END + set laststatus=2 + set statusline=%=:%{getcmdline()} + autocmd CmdlineChanged * redrawstatus + END + call writefile(lines, 'XTest_redrawstatus', 'D') + + let buf = RunVimInTerminal('-S XTest_redrawstatus', {'rows': 8}) + " :redrawstatus is postponed if messages have scrolled + call term_sendkeys(buf, ":echo \"one\\ntwo\\nthree\\nfour\"\<CR>") + call term_sendkeys(buf, ":foobar") + call VerifyScreenDump(buf, 'Test_redrawstatus_in_autocmd_1', {}) + " it is not postponed if messages have not scrolled + call term_sendkeys(buf, "\<Esc>:for in in range(3)") + call VerifyScreenDump(buf, 'Test_redrawstatus_in_autocmd_2', {}) + " with cmdheight=1 messages have scrolled when typing :endfor + call term_sendkeys(buf, "\<CR>:endfor") + call VerifyScreenDump(buf, 'Test_redrawstatus_in_autocmd_3', {}) + call term_sendkeys(buf, "\<CR>:set cmdheight=2\<CR>") + " with cmdheight=2 messages haven't scrolled when typing :for or :endfor + call term_sendkeys(buf, ":for in in range(3)") + call VerifyScreenDump(buf, 'Test_redrawstatus_in_autocmd_4', {}) + call term_sendkeys(buf, "\<CR>:endfor") + call VerifyScreenDump(buf, 'Test_redrawstatus_in_autocmd_5', {}) + + " clean up + call term_sendkeys(buf, "\<CR>") + call StopVimInTerminal(buf) +endfunc + func Test_changing_cmdheight() CheckScreendump @@ -2226,8 +2280,8 @@ func Test_setcmdline() call assert_equal(a:pos, getcmdpos()) call assert_fails('call setcmdline("' .. a:text .. '", -1)', 'E487:') - call assert_fails('call setcmdline({}, 0)', 'E928:') - call assert_fails('call setcmdline("' .. a:text .. '", {})', 'E728:') + call assert_fails('call setcmdline({}, 0)', 'E1174:') + call assert_fails('call setcmdline("' .. a:text .. '", {})', 'E1210:') return '' endfunc diff --git a/src/nvim/testdir/test_cursor_func.vim b/src/nvim/testdir/test_cursor_func.vim index f13842edc8..2e625f2388 100644 --- a/src/nvim/testdir/test_cursor_func.vim +++ b/src/nvim/testdir/test_cursor_func.vim @@ -373,4 +373,26 @@ func Test_setcursorcharpos() %bw! endfunc +" Test for virtcol2col() +func Test_virtcol2col() + new + call setline(1, ["a\tb\tc"]) + call assert_equal(1, virtcol2col(0, 1, 1)) + call assert_equal(2, virtcol2col(0, 1, 2)) + call assert_equal(2, virtcol2col(0, 1, 8)) + call assert_equal(3, virtcol2col(0, 1, 9)) + call assert_equal(4, virtcol2col(0, 1, 10)) + call assert_equal(4, virtcol2col(0, 1, 16)) + call assert_equal(5, virtcol2col(0, 1, 17)) + call assert_equal(-1, virtcol2col(10, 1, 1)) + call assert_equal(-1, virtcol2col(0, 10, 1)) + call assert_equal(-1, virtcol2col(0, -1, 1)) + call assert_equal(-1, virtcol2col(0, 1, -1)) + call assert_equal(5, virtcol2col(0, 1, 20)) + call assert_fails('echo virtcol2col("0", 1, 20)', 'E1210:') + call assert_fails('echo virtcol2col(0, "1", 20)', 'E1210:') + call assert_fails('echo virtcol2col(0, 1, "1")', 'E1210:') + bw! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_edit.vim b/src/nvim/testdir/test_edit.vim index 679b877ef6..9783ed19a7 100644 --- a/src/nvim/testdir/test_edit.vim +++ b/src/nvim/testdir/test_edit.vim @@ -1228,15 +1228,11 @@ func Test_edit_MOUSE() call assert_equal(24, line('w0')) call assert_equal([0, 24, 2, 0], getpos('.')) - " call test_setmouse(4, 3) - call nvim_input_mouse('left', 'press', '', 0, 3, 2) " set mouse position - call getchar() " discard mouse event but keep mouse position + call Ntest_setmouse(4, 3) call feedkeys("A\<LeftMouse>\<esc>", 'tnix') call assert_equal([0, 27, 2, 0], getpos('.')) set mousemodel=extend - " call test_setmouse(5, 3) - call nvim_input_mouse('right', 'press', '', 0, 4, 2) " set mouse position - call getchar() " discard mouse event but keep mouse position + call Ntest_setmouse(5, 3) call feedkeys("A\<RightMouse>\<esc>\<esc>", 'tnix') call assert_equal([0, 28, 2, 0], getpos('.')) set mousemodel& @@ -1931,4 +1927,76 @@ func Test_read_invalid() set encoding=utf-8 endfunc +" Test for the 'revins' option +func Test_edit_revins() + CheckFeature rightleft + new + set revins + exe "normal! ione\ttwo three" + call assert_equal("eerht owt\teno", getline(1)) + call setline(1, "one\ttwo three") + normal! gg$bi a + call assert_equal("one\ttwo a three", getline(1)) + exe "normal! $bi\<BS>\<BS>" + call assert_equal("one\ttwo a ree", getline(1)) + exe "normal! 0wi\<C-W>" + call assert_equal("one\t a ree", getline(1)) + exe "normal! 0wi\<C-U>" + call assert_equal("one\t ", getline(1)) + " newline in insert mode starts at the end of the line + call setline(1, 'one two three') + exe "normal! wi\nfour" + call assert_equal(['one two three', 'ruof'], getline(1, '$')) + set revins& + bw! +endfunc + +" Test for getting the character of the line below after "p" +func Test_edit_put_CTRL_E() + " set encoding=latin1 + new + let @" = '' + sil! norm orggRx + sil! norm pr + call assert_equal(['r', 'r'], getline(1, 2)) + bwipe! + set encoding=utf-8 +endfunc + +" Test toggling of input method. See :help i_CTRL-^ +func Test_edit_CTRL_hat() + CheckFeature xim + + " FIXME: test fails with Motif GUI. + " test also fails when running in the GUI. + CheckFeature gui_gtk + CheckNotGui + + new + + call assert_equal(0, &iminsert) + call feedkeys("i\<C-^>", 'xt') + call assert_equal(2, &iminsert) + call feedkeys("i\<C-^>", 'xt') + call assert_equal(0, &iminsert) + + bwipe! +endfunc + +" Weird long file name was going over the end of NameBuff +func Test_edit_overlong_file_name() + CheckUnix + + file 0000000000000000000000000000 + file %%%%%%%%%%%%%%%%%%%%%%%%%% + file %%%%%% + set readonly + set ls=2 + + redraw! + set noreadonly ls& + bwipe! +endfunc + + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_excmd.vim b/src/nvim/testdir/test_excmd.vim index 9a9e5c546b..7692d4fc55 100644 --- a/src/nvim/testdir/test_excmd.vim +++ b/src/nvim/testdir/test_excmd.vim @@ -230,7 +230,6 @@ endfunc " Test for the :language command func Test_language_cmd() CheckNotMSWindows " FIXME: why does this fail on Windows CI? - CheckNotBSD " FIXME: why does this fail on OpenBSD CI? CheckFeature multi_lang call assert_fails('language ctype non_existing_lang', 'E197:') @@ -663,6 +662,12 @@ func Sandbox_tests() if has('unix') call assert_fails('cd `pwd`', 'E48:') endif + " some options cannot be changed in a sandbox + call assert_fails('set exrc', 'E48:') + call assert_fails('set cdpath', 'E48:') + if has('xim') && has('gui_gtk') + call assert_fails('set imstyle', 'E48:') + endif endfunc func Test_sandbox() diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index 8448154bfa..e3e698aa60 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -88,6 +88,7 @@ let s:filename_checks = { \ 'bindzone': ['named.root', '/bind/db.file', '/named/db.file', 'any/bind/db.file', 'any/named/db.file'], \ 'bitbake': ['file.bb', 'file.bbappend', 'file.bbclass', 'build/conf/local.conf', 'meta/conf/layer.conf', 'build/conf/bbappend.conf', 'meta-layer/conf/distro/foo.conf'], \ 'blank': ['file.bl'], + \ 'blueprint': ['file.blp'], \ 'bsdl': ['file.bsd', 'file.bsdl'], \ 'bst': ['file.bst'], \ 'bzl': ['file.bazel', 'file.bzl', 'WORKSPACE'], @@ -107,6 +108,7 @@ let s:filename_checks = { \ 'ch': ['file.chf'], \ 'chaiscript': ['file.chai'], \ 'chaskell': ['file.chs'], + \ 'chatito': ['file.chatito'], \ 'chill': ['file..ch'], \ 'chordpro': ['file.chopro', 'file.crd', 'file.cho', 'file.crdpro', 'file.chordpro'], \ 'cl': ['file.eni'], @@ -213,8 +215,10 @@ let s:filename_checks = { \ 'gedcom': ['file.ged', 'lltxxxxx.txt', '/tmp/lltmp', '/tmp/lltmp-file', 'any/tmp/lltmp', 'any/tmp/lltmp-file'], \ 'gemtext': ['file.gmi', 'file.gemini'], \ 'gift': ['file.gift'], + \ 'gitattributes': ['file.git/info/attributes', '.gitattributes', '/.config/git/attributes', '/etc/gitattributes', '/usr/local/etc/gitattributes', 'some.git/info/attributes'], \ 'gitcommit': ['COMMIT_EDITMSG', 'MERGE_MSG', 'TAG_EDITMSG', 'NOTES_EDITMSG', 'EDIT_DESCRIPTION'], \ 'gitconfig': ['file.git/config', 'file.git/config.worktree', 'file.git/worktrees/x/config.worktree', '.gitconfig', '.gitmodules', 'file.git/modules//config', '/.config/git/config', '/etc/gitconfig', '/usr/local/etc/gitconfig', '/etc/gitconfig.d/file', 'any/etc/gitconfig.d/file', '/.gitconfig.d/file', 'any/.config/git/config', 'any/.gitconfig.d/file', 'some.git/config', 'some.git/modules/any/config'], + \ 'gitignore': ['file.git/info/exclude', '.gitignore', '/.config/git/ignore', 'some.git/info/exclude'], \ 'gitolite': ['gitolite.conf', '/gitolite-admin/conf/file', 'any/gitolite-admin/conf/file'], \ 'gitrebase': ['git-rebase-todo'], \ 'gitsendemail': ['.gitsendemail.msg.xxxxxx'], @@ -324,6 +328,7 @@ let s:filename_checks = { \ 'lss': ['file.lss'], \ 'lua': ['file.lua', 'file.rockspec', 'file.nse'], \ 'lynx': ['lynx.cfg'], + \ 'lyrics': ['file.lrc'], \ 'm3build': ['m3makefile', 'm3overrides'], \ 'm3quake': ['file.quake', 'cm3.cfg'], \ 'm4': ['file.at'], @@ -408,7 +413,7 @@ let s:filename_checks = { \ 'perl': ['file.plx', 'file.al', 'file.psgi', 'gitolite.rc', '.gitolite.rc', 'example.gitolite.rc'], \ 'pf': ['pf.conf'], \ 'pfmain': ['main.cf'], - \ 'php': ['file.php', 'file.php9', 'file.phtml', 'file.ctp', 'file.phpt'], + \ 'php': ['file.php', 'file.php9', 'file.phtml', 'file.ctp', 'file.phpt', 'file.theme'], \ 'pike': ['file.pike', 'file.pmod'], \ 'pilrc': ['file.rcp'], \ 'pine': ['.pinerc', 'pinerc', '.pinercex', 'pinercex'], @@ -527,13 +532,14 @@ let s:filename_checks = { \ 'squid': ['squid.conf'], \ 'squirrel': ['file.nut'], \ 'srec': ['file.s19', 'file.s28', 'file.s37', 'file.mot', 'file.srec'], + \ 'srt': ['file.srt'], \ 'sshconfig': ['ssh_config', '/.ssh/config', '/etc/ssh/ssh_config.d/file.conf', 'any/etc/ssh/ssh_config.d/file.conf', 'any/.ssh/config', 'any/.ssh/file.conf'], \ 'sshdconfig': ['sshd_config', '/etc/ssh/sshd_config.d/file.conf', 'any/etc/ssh/sshd_config.d/file.conf'], \ 'st': ['file.st'], \ 'stata': ['file.ado', 'file.do', 'file.imata', 'file.mata'], \ 'stp': ['file.stp'], \ 'sudoers': ['any/etc/sudoers', 'sudoers.tmp', '/etc/sudoers', 'any/etc/sudoers.d/file'], - \ 'supercollider': ['file.quark'], + \ 'supercollider': ['file.quark'], \ 'surface': ['file.sface'], \ 'svelte': ['file.svelte'], \ 'svg': ['file.svg'], @@ -590,6 +596,7 @@ let s:filename_checks = { \ 'usw2kagtlog': ['usw2kagt.log', 'USW2KAGT.LOG', 'usw2kagt.file.log', 'USW2KAGT.FILE.LOG', 'file.usw2kagt.log', 'FILE.USW2KAGT.LOG'], \ 'vala': ['file.vala'], \ 'vb': ['file.sba', 'file.vb', 'file.vbs', 'file.dsm', 'file.ctl'], + \ 'vdf': ['file.vdf'], \ 'vdmpp': ['file.vpp', 'file.vdmpp'], \ 'vdmrt': ['file.vdmrt'], \ 'vdmsl': ['file.vdm', 'file.vdmsl'], @@ -1351,7 +1358,7 @@ func Test_mod_file() unlet g:filetype_mod bwipe! - " RAPID header start with a line containing only "%%%", + " RAPID header start with a line containing only "%%%", " but is not always present. call writefile(['%%%'], 'modfile.mod') split modfile.mod @@ -1367,7 +1374,7 @@ func Test_mod_file() bwipe! call delete('modfile.Mod') - " RAPID is not case sensitive, embedded spaces, sysmodule, + " RAPID is not case sensitive, embedded spaces, sysmodule, " file starts with empty line(s). call writefile(['', 'MODULE rapidmödüle (SYSMODULE,NOSTEPIN)'], 'modfile.MOD') split modfile.MOD @@ -1495,7 +1502,7 @@ func Test_prg_file() unlet g:filetype_prg bwipe! - " RAPID header start with a line containing only "%%%", + " RAPID header start with a line containing only "%%%", " but is not always present. call writefile(['%%%'], 'prgfile.prg') split prgfile.prg @@ -1511,7 +1518,7 @@ func Test_prg_file() bwipe! call delete('prgfile.Prg') - " RAPID is not case sensitive, embedded spaces, sysmodule, + " RAPID is not case sensitive, embedded spaces, sysmodule, " file starts with empty line(s). call writefile(['', 'MODULE rapidmödüle (SYSMODULE,NOSTEPIN)'], 'prgfile.PRG') split prgfile.PRG @@ -1622,7 +1629,7 @@ func Test_sys_file() unlet g:filetype_sys bwipe! - " RAPID header start with a line containing only "%%%", + " RAPID header start with a line containing only "%%%", " but is not always present. call writefile(['%%%'], 'sysfile.sys') split sysfile.sys @@ -1638,7 +1645,7 @@ func Test_sys_file() bwipe! call delete('sysfile.Sys') - " RAPID is not case sensitive, embedded spaces, sysmodule, + " RAPID is not case sensitive, embedded spaces, sysmodule, " file starts with empty line(s). call writefile(['', 'MODULE rapidmödüle (SYSMODULE,NOSTEPIN)'], 'sysfile.SYS') split sysfile.SYS diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim index 99ac6ae32c..7ad0cb5884 100644 --- a/src/nvim/testdir/test_functions.vim +++ b/src/nvim/testdir/test_functions.vim @@ -462,6 +462,12 @@ func Test_tolower() " invalid memory. call tolower("\xC0\x80\xC0") call tolower("123\xC0\x80\xC0") + + " Test in latin1 encoding + let save_enc = &encoding + " set encoding=latin1 + call assert_equal("abc", tolower("ABC")) + let &encoding = save_enc endfunc func Test_toupper() @@ -533,6 +539,12 @@ func Test_toupper() " invalid memory. call toupper("\xC0\x80\xC0") call toupper("123\xC0\x80\xC0") + + " Test in latin1 encoding + let save_enc = &encoding + " set encoding=latin1 + call assert_equal("ABC", toupper("abc")) + let &encoding = save_enc endfunc func Test_tr() @@ -1096,6 +1108,10 @@ func Test_filewritable() call assert_equal(0, filewritable('doesnotexist')) + call mkdir('Xdir') + call assert_equal(2, filewritable('Xdir')) + call delete('Xdir', 'd') + call delete('Xfilewritable') bw! endfunc @@ -1270,15 +1286,11 @@ func Test_inputlist() call assert_equal(2, c) " Use mouse to make a selection - " call test_setmouse(&lines - 3, 2) - call nvim_input_mouse('left', 'press', '', 0, &lines - 4, 1) " set mouse position - call getchar() " discard mouse event but keep mouse position + call Ntest_setmouse(&lines - 3, 2) call feedkeys(":let c = inputlist(['Select color:', '1. red', '2. green', '3. blue'])\<cr>\<LeftMouse>", 'tx') call assert_equal(1, c) " Mouse click outside of the list - " call test_setmouse(&lines - 6, 2) - call nvim_input_mouse('left', 'press', '', 0, &lines - 7, 1) " set mouse position - call getchar() " discard mouse event but keep mouse position + call Ntest_setmouse(&lines - 6, 2) call feedkeys(":let c = inputlist(['Select color:', '1. red', '2. green', '3. blue'])\<cr>\<LeftMouse>", 'tx') call assert_equal(-2, c) @@ -1537,13 +1549,12 @@ func Test_getchar() call assert_equal(0, getchar(0)) call setline(1, 'xxxx') - " call test_setmouse(1, 3) - " let v:mouse_win = 9 - " let v:mouse_winid = 9 - " let v:mouse_lnum = 9 - " let v:mouse_col = 9 - " call feedkeys("\<S-LeftMouse>", '') - call nvim_input_mouse('left', 'press', 'S', 0, 0, 2) + call Ntest_setmouse(1, 3) + let v:mouse_win = 9 + let v:mouse_winid = 9 + let v:mouse_lnum = 9 + let v:mouse_col = 9 + call feedkeys("\<S-LeftMouse>", '') call assert_equal("\<S-LeftMouse>", getchar()) call assert_equal(1, v:mouse_win) call assert_equal(win_getid(1), v:mouse_winid) @@ -1887,7 +1898,9 @@ func Test_bufadd_bufload() \ ['acwrite', 1], \ ['quickfix', 0], \ ['help', 1], + "\ ['terminal', 0], \ ['prompt', 0], + "\ ['popup', 0], \ ] bwipe! XotherName let buf = bufadd('XotherName') @@ -1907,6 +1920,32 @@ func Test_eval() call assert_fails("call eval('5 a')", 'E488:') endfunc +" Test for the keytrans() function +func Test_keytrans() + call assert_equal('<Space>', keytrans(' ')) + call assert_equal('<lt>', keytrans('<')) + call assert_equal('<lt>Tab>', keytrans('<Tab>')) + call assert_equal('<Tab>', keytrans("\<Tab>")) + call assert_equal('<C-V>', keytrans("\<C-V>")) + call assert_equal('<BS>', keytrans("\<BS>")) + call assert_equal('<Home>', keytrans("\<Home>")) + call assert_equal('<C-Home>', keytrans("\<C-Home>")) + call assert_equal('<M-Home>', keytrans("\<M-Home>")) + call assert_equal('<C-Space>', keytrans("\<C-Space>")) + call assert_equal('<M-Space>', keytrans("\<*M-Space>")) + call assert_equal('<M-x>', "\<*M-x>"->keytrans()) + call assert_equal('<C-I>', "\<*C-I>"->keytrans()) + call assert_equal('<S-3>', "\<*S-3>"->keytrans()) + call assert_equal('π', 'π'->keytrans()) + call assert_equal('<M-π>', "\<M-π>"->keytrans()) + call assert_equal('ě', 'ě'->keytrans()) + call assert_equal('<M-ě>', "\<M-ě>"->keytrans()) + call assert_equal('', ''->keytrans()) + call assert_equal('', v:_null_string->keytrans()) + call assert_fails('call keytrans(1)', 'E1174:') + call assert_fails('call keytrans()', 'E119:') +endfunc + " Test for the nr2char() function func Test_nr2char() " set encoding=latin1 @@ -1949,9 +1988,7 @@ endfunc func Test_getmousepos() enew! call setline(1, "\t\t\t1234") - " call test_setmouse(1, 1) - call nvim_input_mouse('left', 'press', '', 0, 0, 0) - call getchar() " wait for and consume the mouse press + call Ntest_setmouse(1, 1) call assert_equal(#{ \ screenrow: 1, \ screencol: 1, @@ -1961,9 +1998,7 @@ func Test_getmousepos() \ line: 1, \ column: 1, \ }, getmousepos()) - " call test_setmouse(1, 25) - call nvim_input_mouse('left', 'press', '', 0, 0, 24) - call getchar() " wait for and consume the mouse press + call Ntest_setmouse(1, 25) call assert_equal(#{ \ screenrow: 1, \ screencol: 25, @@ -1973,9 +2008,7 @@ func Test_getmousepos() \ line: 1, \ column: 4, \ }, getmousepos()) - " call test_setmouse(1, 50) - call nvim_input_mouse('left', 'press', '', 0, 0, 49) - call getchar() " wait for and consume the mouse press + call Ntest_setmouse(1, 50) call assert_equal(#{ \ screenrow: 1, \ screencol: 50, @@ -1988,9 +2021,7 @@ func Test_getmousepos() " If the mouse is positioned past the last buffer line, "line" and "column" " should act like it's positioned on the last buffer line. - " call test_setmouse(2, 25) - call nvim_input_mouse('left', 'press', '', 0, 1, 24) - call getchar() " wait for and consume the mouse press + call Ntest_setmouse(2, 25) call assert_equal(#{ \ screenrow: 2, \ screencol: 25, @@ -2000,9 +2031,7 @@ func Test_getmousepos() \ line: 1, \ column: 4, \ }, getmousepos()) - " call test_setmouse(2, 50) - call nvim_input_mouse('left', 'press', '', 0, 1, 49) - call getchar() " wait for and consume the mouse press + call Ntest_setmouse(2, 50) call assert_equal(#{ \ screenrow: 2, \ screencol: 50, @@ -2026,6 +2055,8 @@ func Test_glob() " Sort output of glob() otherwise we end up with different " ordering depending on whether file system is case-sensitive. call assert_equal(['XGLOB2', 'Xglob1'], sort(glob('Xglob[12]', 0, 1))) + " wildignorecase shall be applied even when the pattern contains no wildcards. + call assert_equal('XGLOB2', glob('xglob2')) set wildignorecase& call delete('Xglob1') diff --git a/src/nvim/testdir/test_help.vim b/src/nvim/testdir/test_help.vim index dbb36facee..19c0fcd820 100644 --- a/src/nvim/testdir/test_help.vim +++ b/src/nvim/testdir/test_help.vim @@ -141,6 +141,17 @@ func Test_helptag_cmd() call delete('Xdir', 'rf') endfunc +" Test for setting the 'helpheight' option in the help window +func Test_help_window_height() + let &cmdheight = &lines - 24 + set helpheight=10 + help + set helpheight=14 + call assert_equal(14, winheight(0)) + set helpheight& cmdheight=1 + close +endfunc + func Test_help_long_argument() try exe 'help \%' .. repeat('0', 1021) diff --git a/src/nvim/testdir/test_highlight.vim b/src/nvim/testdir/test_highlight.vim index 8e808a00d0..e84c45c635 100644 --- a/src/nvim/testdir/test_highlight.vim +++ b/src/nvim/testdir/test_highlight.vim @@ -722,7 +722,7 @@ func Test_1_highlight_Normalgroup_exists() elseif has('gui_gtk2') || has('gui_gnome') || has('gui_gtk3') " expect is DEFAULT_FONT of gui_gtk_x11.c call assert_match('hi Normal\s*font=Monospace 10', hlNormal) - elseif has('gui_motif') || has('gui_athena') + elseif has('gui_motif') " expect is DEFAULT_FONT of gui_x11.c call assert_match('hi Normal\s*font=7x13', hlNormal) elseif has('win32') diff --git a/src/nvim/testdir/test_mapping.vim b/src/nvim/testdir/test_mapping.vim index e1d0b9a9ba..bde3624adf 100644 --- a/src/nvim/testdir/test_mapping.vim +++ b/src/nvim/testdir/test_mapping.vim @@ -975,6 +975,21 @@ func Test_abbreviate_multi_byte() bwipe! endfunc +" Test for abbreviations with 'latin1' encoding +func Test_abbreviate_latin1_encoding() + " set encoding=latin1 + call assert_fails('abbr ab#$c ABC', 'E474:') + new + iabbr <buffer> #i #include + iabbr <buffer> ## #enddef + exe "normal i#i\<C-]>" + call assert_equal('#include', getline(1)) + exe "normal 0Di##\<C-]>" + call assert_equal('#enddef', getline(1)) + %bw! + set encoding=utf-8 +endfunc ++ " Test for <Plug> always being mapped, even when used with "noremap". func Test_plug_remap() let g:foo = 0 @@ -1006,15 +1021,14 @@ func Test_plug_remap() endfunc func Test_mouse_drag_mapped_start_select() - CheckFunction test_setmouse set mouse=a set selectmode=key,mouse func ClickExpr() - call test_setmouse(1, 1) + call Ntest_setmouse(1, 1) return "\<LeftMouse>" endfunc func DragExpr() - call test_setmouse(1, 2) + call Ntest_setmouse(1, 2) return "\<LeftDrag>" endfunc nnoremap <expr> <F2> ClickExpr() @@ -1036,14 +1050,13 @@ endfunc " Test for mapping <LeftDrag> in Insert mode func Test_mouse_drag_insert_map() - CheckFunction test_setmouse set mouse=a func ClickExpr() - call test_setmouse(1, 1) + call Ntest_setmouse(1, 1) return "\<LeftMouse>" endfunc func DragExpr() - call test_setmouse(1, 2) + call Ntest_setmouse(1, 2) return "\<LeftDrag>" endfunc inoremap <expr> <F2> ClickExpr() @@ -1129,4 +1142,14 @@ func Test_map_after_timed_out_nop() call delete('Xtest_map_after_timed_out_nop') endfunc +func Test_using_past_typeahead() + nnoremap :00 0 + exe "norm :set \x80\xfb0=0\<CR>" + exe "sil norm :0\x0f\<C-U>\<CR>" + + exe "norm :set \x80\xfb0=\<CR>" + nunmap :00 +endfunc + + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_messages.vim b/src/nvim/testdir/test_messages.vim index 3a607ff533..2672fcb69d 100644 --- a/src/nvim/testdir/test_messages.vim +++ b/src/nvim/testdir/test_messages.vim @@ -171,6 +171,38 @@ func Test_echospace() set ruler& showcmd& endfunc +func Test_warning_scroll() + CheckRunVimInTerminal + let lines =<< trim END + call test_override('ui_delay', 50) + set noruler + set readonly + undo + END + call writefile(lines, 'XTestWarningScroll', 'D') + let buf = RunVimInTerminal('', #{rows: 8}) + + " When the warning comes from a script, messages are scrolled so that the + " stacktrace is visible. + call term_sendkeys(buf, ":source XTestWarningScroll\n") + " only match the final colon in the line that shows the source + call WaitForAssert({-> assert_match(':$', term_getline(buf, 5))}) + call WaitForAssert({-> assert_equal('line 4:W10: Warning: Changing a readonly file', term_getline(buf, 6))}) + call WaitForAssert({-> assert_equal('Already at oldest change', term_getline(buf, 7))}) + call WaitForAssert({-> assert_equal('Press ENTER or type command to continue', term_getline(buf, 8))}) + call term_sendkeys(buf, "\n") + + " When the warning does not come from a script, messages are not scrolled. + call term_sendkeys(buf, ":enew\n") + call term_sendkeys(buf, ":set readonly\n") + call term_sendkeys(buf, 'u') + call WaitForAssert({-> assert_equal('W10: Warning: Changing a readonly file', term_getline(buf, 8))}) + call WaitForAssert({-> assert_equal('Already at oldest change', term_getline(buf, 8))}) + + " clean up + call StopVimInTerminal(buf) +endfunc + " Test more-prompt (see :help more-prompt). func Test_message_more() CheckRunVimInTerminal @@ -326,7 +358,8 @@ func Test_quit_long_message() echom range(9999)->join("\x01") END call writefile(content, 'Xtest_quit_message') - let buf = RunVimInTerminal('-S Xtest_quit_message', #{rows: 6}) + let buf = RunVimInTerminal('-S Xtest_quit_message', #{rows: 6, wait_for_ruler: 0}) + call WaitForAssert({-> assert_match('^-- More --', term_getline(buf, 6))}) call term_sendkeys(buf, "q") call VerifyScreenDump(buf, 'Test_quit_long_message', {}) @@ -398,7 +431,7 @@ func Test_cmdheight_zero() " Check change/restore cmdheight when macro call feedkeys("qa", "xt") - call assert_equal(1, &cmdheight) + call assert_equal(0, &cmdheight) call feedkeys("q", "xt") call assert_equal(0, &cmdheight) diff --git a/src/nvim/testdir/test_mksession.vim b/src/nvim/testdir/test_mksession.vim index 8ec408e62e..ccc775560f 100644 --- a/src/nvim/testdir/test_mksession.vim +++ b/src/nvim/testdir/test_mksession.vim @@ -942,6 +942,19 @@ func Test_mkvimrc() endfor call s:ClearMappings() + + " the 'pastetoggle', 'wildchar' and 'wildcharm' option values should be + " stored as key names in the vimrc file + set pastetoggle=<F5> + set wildchar=<F6> + set wildcharm=<F7> + call assert_fails('mkvimrc Xtestvimrc') + mkvimrc! Xtestvimrc + call assert_notequal(-1, index(readfile('Xtestvimrc'), 'set pastetoggle=<F5>')) + call assert_notequal(-1, index(readfile('Xtestvimrc'), 'set wildchar=<F6>')) + call assert_notequal(-1, index(readfile('Xtestvimrc'), 'set wildcharm=<F7>')) + set pastetoggle& wildchar& wildcharm& + call delete('Xtestvimrc') endfunc diff --git a/src/nvim/testdir/test_modeline.vim b/src/nvim/testdir/test_modeline.vim index b3fe79f545..613722fdbd 100644 --- a/src/nvim/testdir/test_modeline.vim +++ b/src/nvim/testdir/test_modeline.vim @@ -1,5 +1,7 @@ " Tests for parsing the modeline. +source check.vim + func Test_modeline_invalid() " This was reading allocated memory in the past. call writefile(['vi:0', 'nothing'], 'Xmodeline') @@ -281,6 +283,88 @@ func Test_modeline_fails_modelineexpr() call s:modeline_fails('titlestring', 'titlestring=Something()', 'E992:') endfunc +func Test_modeline_setoption_verbose() + let modeline = &modeline + set modeline + + let lines =<< trim END + 1 vim:ts=2 + 2 two + 3 three + 4 four + 5 five + 6 six + 7 seven + 8 eight + END + call writefile(lines, 'Xmodeline') + edit Xmodeline + let info = split(execute('verbose set tabstop?'), "\n") + call assert_match('^\s*Last set from modeline line 1$', info[-1]) + bwipe! + + let lines =<< trim END + 1 one + 2 two + 3 three + 4 vim:ts=4 + 5 five + 6 six + 7 seven + 8 eight + END + call writefile(lines, 'Xmodeline') + edit Xmodeline + let info = split(execute('verbose set tabstop?'), "\n") + call assert_match('^\s*Last set from modeline line 4$', info[-1]) + bwipe! + + let lines =<< trim END + 1 one + 2 two + 3 three + 4 four + 5 five + 6 six + 7 seven + 8 vim:ts=8 + END + call writefile(lines, 'Xmodeline') + edit Xmodeline + let info = split(execute('verbose set tabstop?'), "\n") + call assert_match('^\s*Last set from modeline line 8$', info[-1]) + bwipe! + + let &modeline = modeline + call delete('Xmodeline') +endfunc + +" Test for the 'modeline' default value in compatible and non-compatible modes +" for root and non-root accounts +func Test_modeline_default() + " set compatible + " call assert_false(&modeline) + set nocompatible + call assert_equal(IsRoot() ? 0 : 1, &modeline) + " set compatible&vi + " call assert_false(&modeline) + set compatible&vim + call assert_equal(IsRoot() ? 0 : 1, &modeline) + set compatible& modeline& +endfunc + +" Some options cannot be set from the modeline when 'diff' option is set +func Test_modeline_diff_buffer() + call writefile(['vim: diff foldmethod=marker wrap'], 'Xfile') + set foldmethod& nowrap + new Xfile + call assert_equal('manual', &foldmethod) + call assert_false(&wrap) + set wrap& + call delete('Xfile') + bw +endfunc + func Test_modeline_disable() set modeline call writefile(['vim: sw=2', 'vim: nomodeline', 'vim: sw=3'], 'Xmodeline_disable') diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim index 655d537336..952975df32 100644 --- a/src/nvim/testdir/test_options.vim +++ b/src/nvim/testdir/test_options.vim @@ -22,6 +22,21 @@ func Test_whichwrap() set whichwrap=h,h,h call assert_equal('h', &whichwrap) + " For compatibility with Vim 3.0 and before, number values are also + " supported for 'whichwrap' + set whichwrap=1 + call assert_equal('b', &whichwrap) + set whichwrap=2 + call assert_equal('s', &whichwrap) + set whichwrap=4 + call assert_equal('h,l', &whichwrap) + set whichwrap=8 + call assert_equal('<,>', &whichwrap) + set whichwrap=16 + call assert_equal('[,]', &whichwrap) + set whichwrap=31 + call assert_equal('b,s,h,l,<,>,[,]', &whichwrap) + set whichwrap& endfunc @@ -267,6 +282,15 @@ func Test_set_completion() call feedkeys(":set fileencodings:\<C-A>\<C-B>\"\<CR>", 'tx') call assert_equal('"set fileencodings:ucs-bom,utf-8,default,latin1', @:) + " Expand key codes. + " call feedkeys(":set <H\<C-A>\<C-B>\"\<CR>", 'tx') + " call assert_equal('"set <Help> <Home>', @:) + + " Expand terminal options. + " call feedkeys(":set t_A\<C-A>\<C-B>\"\<CR>", 'tx') + " call assert_equal('"set t_AB t_AF t_AU t_AL', @:) + " call assert_fails('call feedkeys(":set <t_afoo>=\<C-A>\<CR>", "xt")', 'E474:') + " Expand directories. call feedkeys(":set cdpath=./\<C-A>\<C-B>\"\<CR>", 'tx') call assert_match('./samples/ ', @:) @@ -362,6 +386,15 @@ func Test_set_errors() call assert_fails('set winminwidth=10 winwidth=9', 'E592:') call assert_fails("set showbreak=\x01", 'E595:') call assert_fails('set t_foo=', 'E846:') + call assert_fails('set tabstop??', 'E488:') + call assert_fails('set wrapscan!!', 'E488:') + call assert_fails('set tabstop&&', 'E488:') + call assert_fails('set wrapscan<<', 'E488:') + call assert_fails('set wrapscan=1', 'E474:') + call assert_fails('set autoindent@', 'E488:') + call assert_fails('set wildchar=<abc>', 'E474:') + call assert_fails('set cmdheight=1a', 'E521:') + call assert_fails('set invcmdheight', 'E474:') if has('python') || has('python3') call assert_fails('set pyxversion=6', 'E474:') endif @@ -385,6 +418,7 @@ func Test_set_errors() set nomodifiable call assert_fails('set fileencoding=latin1', 'E21:') set modifiable& + " call assert_fails('set t_#-&', 'E522:') endfunc func CheckWasSet(name) @@ -845,6 +879,108 @@ func Test_debug_option() set debug& endfunc +" Test for the default CDPATH option +func Test_opt_default_cdpath() + CheckFeature file_in_path + let after =<< trim [CODE] + call assert_equal(',/path/to/dir1,/path/to/dir2', &cdpath) + call writefile(v:errors, 'Xtestout') + qall + [CODE] + if has('unix') + let $CDPATH='/path/to/dir1:/path/to/dir2' + else + let $CDPATH='/path/to/dir1;/path/to/dir2' + endif + if RunVim([], after, '') + call assert_equal([], readfile('Xtestout')) + call delete('Xtestout') + endif +endfunc + +" Test for setting keycodes using set +func Test_opt_set_keycode() + call assert_fails('set <t_k1=l', 'E474:') + call assert_fails('set <Home=l', 'E474:') + set <t_k9>=abcd + " call assert_equal('abcd', &t_k9) + set <t_k9>& + set <F9>=xyz + " call assert_equal('xyz', &t_k9) + set <t_k9>& +endfunc + +" Test for changing options in a sandbox +func Test_opt_sandbox() + for opt in ['backupdir', 'cdpath', 'exrc'] + call assert_fails('sandbox set ' .. opt .. '?', 'E48:') + endfor +endfunc + +" Test for setting an option with local value to global value +func Test_opt_local_to_global() + setglobal equalprg=gprg + setlocal equalprg=lprg + call assert_equal('gprg', &g:equalprg) + call assert_equal('lprg', &l:equalprg) + call assert_equal('lprg', &equalprg) + set equalprg< + call assert_equal('', &l:equalprg) + call assert_equal('gprg', &equalprg) + setglobal equalprg=gnewprg + setlocal equalprg=lnewprg + setlocal equalprg< + call assert_equal('gnewprg', &l:equalprg) + call assert_equal('gnewprg', &equalprg) + set equalprg& + + " Test for setting the global/local value of a boolean option + setglobal autoread + setlocal noautoread + call assert_false(&autoread) + set autoread< + call assert_true(&autoread) + setglobal noautoread + setlocal autoread + setlocal autoread< + call assert_false(&autoread) + set autoread& +endfunc + +func Test_set_in_sandbox() + " Some boolean options cannot be set in sandbox, some can. + call assert_fails('sandbox set modelineexpr', 'E48:') + sandbox set number + call assert_true(&number) + set number& + + " Some boolean options cannot be set in sandbox, some can. + if has('python') || has('python3') + call assert_fails('sandbox set pyxversion=3', 'E48:') + endif + sandbox set tabstop=4 + call assert_equal(4, &tabstop) + set tabstop& + + " Some string options cannot be set in sandbox, some can. + call assert_fails('sandbox set backupdir=/tmp', 'E48:') + sandbox set filetype=perl + call assert_equal('perl', &filetype) + set filetype& +endfunc + +" Test for incrementing, decrementing and multiplying a number option value +func Test_opt_num_op() + set shiftwidth=4 + set sw+=2 + call assert_equal(6, &sw) + set sw-=2 + call assert_equal(4, &sw) + set sw^=2 + call assert_equal(8, &sw) + set shiftwidth& +endfunc + " Test for setting option values using v:false and v:true func Test_opt_boolean() set number& @@ -981,6 +1117,64 @@ func Test_opt_reset_scroll() call delete('Xscroll') endfunc +" Test for setting an option to a Vi or Vim default +func Test_opt_default() + throw 'Skipped: Nvim has different defaults' + set formatoptions&vi + call assert_equal('vt', &formatoptions) + set formatoptions&vim + call assert_equal('tcq', &formatoptions) +endfunc + +" Test for the 'cmdheight' option +func Test_cmdheight() + %bw! + let ht = &lines + set cmdheight=9999 + call assert_equal(1, winheight(0)) + call assert_equal(ht - 1, &cmdheight) + set cmdheight& +endfunc + +" To specify a control character as a option value, '^' can be used +func Test_opt_control_char() + set wildchar=^v + call assert_equal("\<C-V>", nr2char(&wildchar)) + set wildcharm=^r + call assert_equal("\<C-R>", nr2char(&wildcharm)) + " Bug: This doesn't work for the 'cedit' and 'termwinkey' options + set wildchar& wildcharm& +endfunc + +" Test for the 'errorbells' option +func Test_opt_errorbells() + set errorbells + call assert_beeps('s/a1b2/x1y2/') + set noerrorbells +endfunc + +func Test_opt_scrolljump() + help + resize 10 + + " Test with positive 'scrolljump'. + set scrolljump=2 + norm! Lj + call assert_equal({'lnum':11, 'leftcol':0, 'col':0, 'topfill':0, + \ 'topline':3, 'coladd':0, 'skipcol':0, 'curswant':0}, + \ winsaveview()) + + " Test with negative 'scrolljump' (percentage of window height). + set scrolljump=-40 + norm! ggLj + call assert_equal({'lnum':11, 'leftcol':0, 'col':0, 'topfill':0, + \ 'topline':5, 'coladd':0, 'skipcol':0, 'curswant':0}, + \ winsaveview()) + + set scrolljump& + bw +endfunc + " Test for the 'cdhome' option func Test_opt_cdhome() if has('unix') || has('vms') diff --git a/src/nvim/testdir/test_paste.vim b/src/nvim/testdir/test_paste.vim new file mode 100644 index 0000000000..dad3c2c6a0 --- /dev/null +++ b/src/nvim/testdir/test_paste.vim @@ -0,0 +1,76 @@ + +" Test for 'pastetoggle' +func Test_pastetoggle() + new + set pastetoggle=<F4> + set nopaste + call feedkeys("iHello\<F4>", 'xt') + call assert_true(&paste) + call feedkeys("i\<F4>", 'xt') + call assert_false(&paste) + call assert_equal('Hello', getline(1)) + " command-line completion for 'pastetoggle' value + call feedkeys(":set pastetoggle=\<Tab>\<C-B>\"\<CR>", 'xt') + call assert_equal('"set pastetoggle=<F4>', @:) + set pastetoggle& + bwipe! +endfunc + +" Test for restoring option values when 'paste' is disabled +func Test_paste_opt_restore() + set autoindent expandtab ruler showmatch + if has('rightleft') + set revins hkmap + endif + set smarttab softtabstop=3 textwidth=27 wrapmargin=12 + if has('vartabs') + set varsofttabstop=10,20 + endif + + " enabling 'paste' should reset the above options + set paste + call assert_false(&autoindent) + call assert_false(&expandtab) + if has('rightleft') + call assert_false(&revins) + call assert_false(&hkmap) + endif + call assert_false(&ruler) + call assert_false(&showmatch) + call assert_false(&smarttab) + call assert_equal(0, &softtabstop) + call assert_equal(0, &textwidth) + call assert_equal(0, &wrapmargin) + if has('vartabs') + call assert_equal('', &varsofttabstop) + endif + + " disabling 'paste' should restore the option values + set nopaste + call assert_true(&autoindent) + call assert_true(&expandtab) + if has('rightleft') + call assert_true(&revins) + call assert_true(&hkmap) + endif + call assert_true(&ruler) + call assert_true(&showmatch) + call assert_true(&smarttab) + call assert_equal(3, &softtabstop) + call assert_equal(27, &textwidth) + call assert_equal(12, &wrapmargin) + if has('vartabs') + call assert_equal('10,20', &varsofttabstop) + endif + + set autoindent& expandtab& ruler& showmatch& + if has('rightleft') + set revins& hkmap& + endif + set smarttab& softtabstop& textwidth& wrapmargin& + if has('vartabs') + set varsofttabstop& + endif +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_quotestar.vim b/src/nvim/testdir/test_quotestar.vim index e3ca141328..6a6719da8b 100644 --- a/src/nvim/testdir/test_quotestar.vim +++ b/src/nvim/testdir/test_quotestar.vim @@ -98,7 +98,7 @@ func Do_test_quotestar_for_x11() " Running in a terminal and the GUI is available: Tell the server to open " the GUI and check that the remote command still works. - if has('gui_athena') || has('gui_motif') + if has('gui_motif') " For those GUIs, ignore the 'failed to create input context' error. call remote_send(name, ":call test_ignore_error('E285') | gui -f\<CR>") else diff --git a/src/nvim/testdir/test_set.vim b/src/nvim/testdir/test_set.vim index 2b1e9eeee0..7215772a00 100644 --- a/src/nvim/testdir/test_set.vim +++ b/src/nvim/testdir/test_set.vim @@ -26,4 +26,23 @@ function Test_set_add() let &wig = wig_save endfunction + +" :set, :setlocal, :setglobal without arguments show values of options. +func Test_set_no_arg() + set textwidth=79 + let a = execute('set') + call assert_match("^\n--- Options ---\n.*textwidth=79\\>", a) + set textwidth& + + setlocal textwidth=78 + let a = execute('setlocal') + call assert_match("^\n--- Local option values ---\n.*textwidth=78\\>", a) + setlocal textwidth& + + setglobal textwidth=77 + let a = execute('setglobal') + call assert_match("^\n--- Global option values ---\n.*textwidth=77\\>", a) + setglobal textwidth& +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_startup.vim b/src/nvim/testdir/test_startup.vim index 880ca62685..b30a5e7edb 100644 --- a/src/nvim/testdir/test_startup.vim +++ b/src/nvim/testdir/test_startup.vim @@ -431,7 +431,7 @@ endfunction " Test the -reverse and +reverse arguments (for GUI only). func Test_reverse() CheckCanRunGui - CheckAnyOf Feature:gui_gtk Feature:gui_motif Feature:gui_athena + CheckAnyOf Feature:gui_gtk Feature:gui_motif let after =<< trim [CODE] call writefile([&background], "Xtest_reverse") @@ -452,7 +452,7 @@ endfunc " Test the -background and -foreground arguments (for GUI only). func Test_background_foreground() CheckCanRunGui - CheckAnyOf Feature:gui_gtk Feature:gui_motif Feature:gui_athena + CheckAnyOf Feature:gui_gtk Feature:gui_motif " Is there a better way to check the effect of -background & -foreground " other than merely looking at &background (dark or light)? @@ -479,7 +479,7 @@ func Test_font() if has('gui_gtk') let font = 'Courier 14' - elseif has('gui_motif') || has('gui_athena') + elseif has('gui_motif') let font = '-misc-fixed-bold-*' else throw 'Skipped: test does not set a valid font for this GUI' @@ -501,10 +501,10 @@ endfunc " Test the -geometry argument (for GUI only). func Test_geometry() CheckCanRunGui - CheckAnyOf Feature:gui_gtk Feature:gui_motif Feature:gui_athena + CheckAnyOf Feature:gui_gtk Feature:gui_motif - if has('gui_motif') || has('gui_athena') - " FIXME: With GUI Athena or Motif, the value of getwinposx(), + if has('gui_motif') + " FIXME: With GUI Motif the value of getwinposx(), " getwinposy() and getwinpos() do not match exactly the " value given in -geometry. Why? " So only check &columns and &lines for those GUIs. @@ -533,7 +533,7 @@ endfunc " Test the -iconic argument (for GUI only). func Test_iconic() CheckCanRunGui - CheckAnyOf Feature:gui_gtk Feature:gui_motif Feature:gui_athena + CheckAnyOf Feature:gui_gtk Feature:gui_motif call RunVim([], [], '-f -g -iconic -cq') diff --git a/src/nvim/testdir/test_substitute.vim b/src/nvim/testdir/test_substitute.vim index b3a80072d9..88a3c13d65 100644 --- a/src/nvim/testdir/test_substitute.vim +++ b/src/nvim/testdir/test_substitute.vim @@ -1,6 +1,8 @@ " Tests for the substitute (:s) command source shared.vim +source check.vim +source screendump.vim func Test_multiline_subst() enew! @@ -637,12 +639,16 @@ endfunc func SubReplacer(text, submatches) return a:text .. a:submatches[0] .. a:text endfunc +func SubReplacerVar(text, ...) + return a:text .. a:1[0] .. a:text +endfunc func SubReplacer20(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, submatches) return a:t3 .. a:submatches[0] .. a:t11 endfunc func Test_substitute_partial() call assert_equal('1foo2foo3', substitute('123', '2', function('SubReplacer', ['foo']), 'g')) + call assert_equal('1foo2foo3', substitute('123', '2', function('SubReplacerVar', ['foo']), 'g')) " 19 arguments plus one is just OK let Replacer = function('SubReplacer20', repeat(['foo'], 19)) @@ -668,6 +674,21 @@ func Test_sub_cmd_9() bw! endfunc +func Test_sub_highlight_zero_match() + CheckRunVimInTerminal + + let lines =<< trim END + call setline(1, ['one', 'two', 'three']) + END + call writefile(lines, 'XscriptSubHighlight', 'D') + let buf = RunVimInTerminal('-S XscriptSubHighlight', #{rows: 8, cols: 60}) + call term_sendkeys(buf, ":%s/^/ /c\<CR>") + call VerifyScreenDump(buf, 'Test_sub_highlight_zer_match_1', {}) + + call term_sendkeys(buf, "\<Esc>") + call StopVimInTerminal(buf) +endfunc + func Test_nocatch_sub_failure_handling() " normal error results in all replacements func Foo() diff --git a/src/nvim/testdir/test_system.vim b/src/nvim/testdir/test_system.vim index 18692f42c9..bfa8a277bd 100644 --- a/src/nvim/testdir/test_system.vim +++ b/src/nvim/testdir/test_system.vim @@ -141,3 +141,41 @@ func Test_system_with_shell_quote() call delete('Xdir with spaces', 'rf') 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_termcodes.vim b/src/nvim/testdir/test_termcodes.vim index eda485c512..99bc2d1d37 100644 --- a/src/nvim/testdir/test_termcodes.vim +++ b/src/nvim/testdir/test_termcodes.vim @@ -1,4 +1,30 @@ +" Test for translation of special key codes (<xF1>, <xF2>, etc.) +func Test_Keycode_Translation() + let keycodes = [ + \ ["<xUp>", "<Up>"], + \ ["<xDown>", "<Down>"], + \ ["<xLeft>", "<Left>"], + \ ["<xRight>", "<Right>"], + \ ["<xHome>", "<Home>"], + \ ["<xEnd>", "<End>"], + \ ["<zHome>", "<Home>"], + \ ["<zEnd>", "<End>"], + \ ["<xF1>", "<F1>"], + \ ["<xF2>", "<F2>"], + \ ["<xF3>", "<F3>"], + \ ["<xF4>", "<F4>"], + \ ["<S-xF1>", "<S-F1>"], + \ ["<S-xF2>", "<S-F2>"], + \ ["<S-xF3>", "<S-F3>"], + \ ["<S-xF4>", "<S-F4>"]] + for [k1, k2] in keycodes + exe "nnoremap " .. k1 .. " 2wx" + call assert_true(maparg(k1, 'n', 0, 1).lhs == k2) + exe "nunmap " .. k1 + endfor +endfunc + " Test for terminal keycodes that doesn't have termcap entries func Test_special_term_keycodes() new diff --git a/src/nvim/testdir/test_vartabs.vim b/src/nvim/testdir/test_vartabs.vim index 68fe15ff93..0acd7fc1e5 100644 --- a/src/nvim/testdir/test_vartabs.vim +++ b/src/nvim/testdir/test_vartabs.vim @@ -429,4 +429,18 @@ func Test_varsofttabstop() close! endfunc +" Setting 'shiftwidth' to a negative value, should set it to either the value +" of 'tabstop' (if 'vartabstop' is not set) or to the first value in +" 'vartabstop' +func Test_shiftwidth_vartabstop() + throw 'Skipped: Nvim removed this behavior in #6377' + setlocal tabstop=7 vartabstop= + call assert_fails('set shiftwidth=-1', 'E487:') + call assert_equal(7, &shiftwidth) + setlocal tabstop=7 vartabstop=5,7,10 + call assert_fails('set shiftwidth=-1', 'E487:') + call assert_equal(5, &shiftwidth) + setlocal shiftwidth& vartabstop& tabstop& +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_virtualedit.vim b/src/nvim/testdir/test_virtualedit.vim index 522ca17675..e712896562 100644 --- a/src/nvim/testdir/test_virtualedit.vim +++ b/src/nvim/testdir/test_virtualedit.vim @@ -481,4 +481,53 @@ func Test_global_local_virtualedit() set virtualedit& endfunc +func Test_virtualedit_mouse() + let save_mouse = &mouse + set mouse=a + set virtualedit=all + new + + call setline(1, ["text\tword"]) + redraw + call Ntest_setmouse(1, 4) + call feedkeys("\<LeftMouse>", "xt") + call assert_equal([0, 1, 4, 0, 4], getcurpos()) + call Ntest_setmouse(1, 5) + call feedkeys("\<LeftMouse>", "xt") + call assert_equal([0, 1, 5, 0, 5], getcurpos()) + call Ntest_setmouse(1, 6) + call feedkeys("\<LeftMouse>", "xt") + call assert_equal([0, 1, 5, 1, 6], getcurpos()) + call Ntest_setmouse(1, 7) + call feedkeys("\<LeftMouse>", "xt") + call assert_equal([0, 1, 5, 2, 7], getcurpos()) + call Ntest_setmouse(1, 8) + call feedkeys("\<LeftMouse>", "xt") + call assert_equal([0, 1, 5, 3, 8], getcurpos()) + call Ntest_setmouse(1, 9) + call feedkeys("\<LeftMouse>", "xt") + call assert_equal([0, 1, 6, 0, 9], getcurpos()) + call Ntest_setmouse(1, 15) + call feedkeys("\<LeftMouse>", "xt") + call assert_equal([0, 1, 10, 2, 15], getcurpos()) + + bwipe! + let &mouse = save_mouse + set virtualedit& +endfunc + +" this was replacing the NUL at the end of the line +func Test_virtualedit_replace_after_tab() + new + s/\v/ 0 + set ve=all + let @" = '' + sil! norm vPvr0 + + call assert_equal("\t0", getline(1)) + set ve& + bwipe! +endfunc + + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_window_cmd.vim b/src/nvim/testdir/test_window_cmd.vim index 1f9d6b59b7..b64f44360b 100644 --- a/src/nvim/testdir/test_window_cmd.vim +++ b/src/nvim/testdir/test_window_cmd.vim @@ -433,7 +433,15 @@ func Test_window_width() call assert_inrange(ww1, ww1 + 1, ww2) call assert_inrange(ww3, ww3 + 1, ww2) - bw Xa Xb Xc + " when the current window width is less than the new 'winwidth', the current + " window width should be increased. + enew | only + split + 10vnew + set winwidth=15 + call assert_equal(15, winwidth(0)) + + %bw! endfunc func Test_equalalways_on_close() diff --git a/src/nvim/testdir/test_writefile.vim b/src/nvim/testdir/test_writefile.vim index a8735bcaf1..adc05ab979 100644 --- a/src/nvim/testdir/test_writefile.vim +++ b/src/nvim/testdir/test_writefile.vim @@ -216,6 +216,12 @@ func Test_saveas() syntax off %bw! call delete('Xsaveas.pl') + + " :saveas fails for "nofile" buffer + set buftype=nofile + call assert_fails('saveas Xsafile', 'E676: No matching autocommands for buftype=nofile buffer') + + bwipe! endfunc func Test_write_errors() diff --git a/src/nvim/testing.c b/src/nvim/testing.c index 4a252dca3e..348d5c6e29 100644 --- a/src/nvim/testing.c +++ b/src/nvim/testing.c @@ -419,7 +419,7 @@ static int assert_equalfile(typval_T *argvars) line2[lineidx] = NUL; ga_concat(&ga, " after \""); ga_concat(&ga, line1); - if (STRCMP(line1, line2) != 0) { + if (strcmp(line1, line2) != 0) { ga_concat(&ga, "\" vs \""); ga_concat(&ga, line2); } diff --git a/src/nvim/textformat.c b/src/nvim/textformat.c index 5c53f84700..25728ef0f1 100644 --- a/src/nvim/textformat.c +++ b/src/nvim/textformat.c @@ -431,7 +431,7 @@ void internal_format(int textwidth, int second_indent, int flags, bool format_on // Check if cursor is not past the NUL off the line, cindent // may have added or removed indent. curwin->w_cursor.col += startcol; - len = (colnr_T)STRLEN(get_cursor_line_ptr()); + len = (colnr_T)strlen(get_cursor_line_ptr()); if (curwin->w_cursor.col > len) { curwin->w_cursor.col = len; } @@ -644,7 +644,7 @@ void auto_format(bool trailblank, bool prev_line) // in 'formatoptions' and there is a single character before the cursor. // Otherwise the line would be broken and when typing another non-white // next they are not joined back together. - wasatend = (pos.col == (colnr_T)STRLEN(old)); + wasatend = (pos.col == (colnr_T)strlen(old)); if (*old != NUL && !trailblank && wasatend) { dec_cursor(); cc = gchar_cursor(); @@ -698,7 +698,7 @@ void auto_format(bool trailblank, bool prev_line) // formatted. if (!wasatend && has_format_option(FO_WHITE_PAR)) { new = get_cursor_line_ptr(); - len = (colnr_T)STRLEN(new); + len = (colnr_T)strlen(new); if (curwin->w_cursor.col == len) { pnew = xstrnsave(new, (size_t)len + 2); pnew[len] = ' '; @@ -1115,7 +1115,7 @@ void format_lines(linenr_T line_count, bool avoid_fex) } first_par_line = false; // If the line is getting long, format it next time - if (STRLEN(get_cursor_line_ptr()) > (size_t)max_len) { + if (strlen(get_cursor_line_ptr()) > (size_t)max_len) { force_format = true; } else { force_format = false; diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c index 728520c20c..998e8cfed0 100644 --- a/src/nvim/tui/input.c +++ b/src/nvim/tui/input.c @@ -15,7 +15,7 @@ #include "nvim/tui/input.h" #include "nvim/tui/tui.h" #include "nvim/vim.h" -#ifdef WIN32 +#ifdef MSWIN # include "nvim/os/os_win_console.h" #endif #include "nvim/event/rstream.h" @@ -143,7 +143,7 @@ void tinput_init(TermInput *input, Loop *loop) // If stdin is not a pty, switch to stderr. For cases like: // echo q | nvim -es // ls *.md | xargs nvim -#ifdef WIN32 +#ifdef MSWIN if (!os_isatty(input->in_fd)) { input->in_fd = os_get_conin_fd(); } diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index 471a3fb859..5a331463e3 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -31,7 +31,7 @@ #include "nvim/os/tty.h" #include "nvim/ui.h" #include "nvim/vim.h" -#ifdef WIN32 +#ifdef MSWIN # include "nvim/os/os_win_console.h" #endif #include "nvim/cursor_shape.h" @@ -263,7 +263,7 @@ static void terminfo_start(UI *ui) data->input.tui_data = data; const char *term = os_getenv("TERM"); -#ifdef WIN32 +#ifdef MSWIN os_tty_guess_term(&term, data->out_fd); os_setenv("TERM", term, 1); // Old os_getenv() pointer is invalid after os_setenv(), fetch it again. @@ -353,7 +353,7 @@ static void terminfo_start(UI *ui) if (ret) { ELOG("uv_tty_init failed: %s", uv_strerror(ret)); } -#ifdef WIN32 +#ifdef MSWIN ret = uv_tty_set_mode(&data->output_handle.tty, UV_TTY_MODE_RAW); if (ret) { ELOG("uv_tty_set_mode failed: %s", uv_strerror(ret)); @@ -1616,7 +1616,7 @@ static void unibi_goto(UI *ui, int row, int col) memset(&vars, 0, sizeof(vars)); \ data->cork = true; \ retry: \ - unibi_format(vars, vars + 26, str, data->params, out, ui, NULL, NULL); \ + unibi_format(vars, vars + 26, str, data->params, out, ui, pad, ui); \ if (data->overflow) { \ data->bufpos = orig_pos; \ flush_buf(ui); \ @@ -1647,6 +1647,7 @@ static void out(void *ctx, const char *str, size_t len) if (len > available) { if (data->cork) { + // Called by unibi_format(): avoid flush_buf() halfway an escape sequence. data->overflow = true; return; } else { @@ -1658,6 +1659,30 @@ static void out(void *ctx, const char *str, size_t len) data->bufpos += len; } +/// Called by unibi_format() for padding instructions. +/// The following parameter descriptions are extracted from unibi_format(3) and terminfo(5). +/// +/// @param ctx the same as `ctx2` passed to unibi_format() +/// @param delay the delay in tenths of milliseconds +/// @param scale padding is proportional to the number of lines affected +/// @param force padding is mandatory +static void pad(void *ctx, size_t delay, int scale FUNC_ATTR_UNUSED, int force) +{ + if (!force) { + return; + } + + UI *ui = ctx; + TUIData *data = ui->data; + + if (data->overflow) { + return; + } + + flush_buf(ui); + loop_uv_run(data->loop, (int)(delay / 10), false); +} + static void unibi_set_if_empty(unibi_term *ut, enum unibi_string str, const char *val) { if (!unibi_get_str(ut, str)) { @@ -1810,7 +1835,7 @@ static void patch_terminfo_bugs(TUIData *data, const char *term, const char *col } } -#ifdef WIN32 +#ifdef MSWIN // XXX: workaround libuv implicit LF => CRLF conversion. #10558 unibi_set_str(ut, unibi_cursor_down, "\x1b[B"); #endif @@ -2164,7 +2189,7 @@ static void augment_terminfo(TUIData *data, const char *term, long vte_version, data->unibi_ext.set_underline_style = unibi_find_ext_str(ut, "Smulx"); if (data->unibi_ext.set_underline_style == -1) { int ext_bool_Su = unibi_find_ext_bool(ut, "Su"); // used by kitty - if (vte_version >= 5102 + if (vte_version >= 5102 || konsolev >= 221170 || (ext_bool_Su != -1 && unibi_get_ext_bool(ut, (size_t)ext_bool_Su))) { data->unibi_ext.set_underline_style = (int)unibi_add_ext_str(ut, "ext.set_underline_style", diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 911eefadd8..2c9510bf34 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -510,7 +510,7 @@ void ui_flush(void) return; } cmdline_ui_flush(); - win_ui_flush(); + win_ui_flush(false); msg_ext_ui_flush(); msg_scroll_flush(); @@ -614,12 +614,6 @@ bool ui_has(UIExtension ext) return ui_ext[ext]; } -/// Returns true if the UI has messages area. -bool ui_has_messages(void) -{ - return p_ch > 0 || ui_has(kUIMessages); -} - Array ui_array(void) { Array all_uis = ARRAY_DICT_INIT; diff --git a/src/nvim/ui_compositor.c b/src/nvim/ui_compositor.c index 2fb70eae8a..f23615180e 100644 --- a/src/nvim/ui_compositor.c +++ b/src/nvim/ui_compositor.c @@ -485,6 +485,10 @@ static void compose_debug(Integer startrow, Integer endrow, Integer startcol, In endcol = MIN(endcol, default_grid.cols); int attr = syn_id2attr(syn_id); + if (delay) { + debug_delay(endrow - startrow); + } + for (int row = (int)startrow; row < endrow; row++) { ui_composed_call_raw_line(1, row, startcol, startcol, endcol, attr, false, (const schar_T *)linebuf, @@ -586,12 +590,14 @@ static void ui_comp_raw_line(UI *ui, Integer grid, Integer row, Integer startcol /// The screen is invalid and will soon be cleared /// /// Don't redraw floats until screen is cleared -void ui_comp_set_screen_valid(bool valid) +bool ui_comp_set_screen_valid(bool valid) { + bool old_val = valid_screen; valid_screen = valid; if (!valid) { msg_sep_row = -1; } + return old_val; } static void ui_comp_msg_set_pos(UI *ui, Integer grid, Integer row, Boolean scrolled, @@ -610,7 +616,7 @@ static void ui_comp_msg_set_pos(UI *ui, Integer grid, Integer row, Boolean scrol if (row > msg_current_row && ui_comp_should_draw()) { compose_area(MAX(msg_current_row - 1, 0), row, 0, default_grid.cols); } else if (row < msg_current_row && ui_comp_should_draw() - && msg_current_row < Rows) { + && (msg_current_row < Rows || (scrolled && !msg_was_scrolled))) { int delta = msg_current_row - (int)row; if (msg_grid.blending) { int first_row = MAX((int)row - (scrolled?1:0), 0); diff --git a/src/nvim/undo.c b/src/nvim/undo.c index ab14f4d4ea..0a5a3133df 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -567,7 +567,7 @@ int u_savecommon(buf_T *buf, linenr_T top, linenr_T bot, linenr_T newbot, int re u_freeentry(uep, i); return FAIL; } - uep->ue_array[i] = (char_u *)u_save_line_buf(buf, lnum++); + uep->ue_array[i] = u_save_line_buf(buf, lnum++); } } else { uep->ue_array = NULL; @@ -771,7 +771,7 @@ static bool serialize_header(bufinfo_T *bi, char_u *hash) // Write buffer-specific data. 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; + 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)) { return false; @@ -1034,11 +1034,11 @@ static bool serialize_uep(bufinfo_T *bi, u_entry_T *uep) undo_write_bytes(bi, (uintmax_t)uep->ue_size, 4); for (size_t i = 0; i < (size_t)uep->ue_size; i++) { - size_t len = STRLEN(uep->ue_array[i]); + size_t len = strlen(uep->ue_array[i]); if (!undo_write_bytes(bi, len, 4)) { return false; } - if (len > 0 && !undo_write(bi, uep->ue_array[i], len)) { + if (len > 0 && !undo_write(bi, (char_u *)uep->ue_array[i], len)) { return false; } } @@ -1064,7 +1064,7 @@ static u_entry_T *unserialize_uep(bufinfo_T *bi, bool *error, const char *file_n memset(array, 0, sizeof(char_u *) * (size_t)uep->ue_size); } } - uep->ue_array = array; + uep->ue_array = (char **)array; for (size_t i = 0; i < (size_t)uep->ue_size; i++) { int line_len = undo_read_4c(bi); @@ -2283,7 +2283,7 @@ static void u_undoredo(int undo, bool do_buf_event) // line. long i; for (i = 0; i < newsize && i < oldsize; i++) { - if (STRCMP(uep->ue_array[i], ml_get(top + 1 + (linenr_T)i)) != 0) { + if (strcmp(uep->ue_array[i], ml_get(top + 1 + (linenr_T)i)) != 0) { break; } } @@ -2327,9 +2327,9 @@ static void u_undoredo(int undo, bool do_buf_event) // If the file is empty, there is an empty line 1 that we // should get rid of, by replacing it with the new line if (empty_buffer && lnum == 0) { - ml_replace((linenr_T)1, (char *)uep->ue_array[i], true); + ml_replace((linenr_T)1, uep->ue_array[i], true); } else { - ml_append(lnum, (char *)uep->ue_array[i], (colnr_T)0, false); + ml_append(lnum, uep->ue_array[i], (colnr_T)0, false); } xfree(uep->ue_array[i]); } @@ -2363,7 +2363,7 @@ static void u_undoredo(int undo, bool do_buf_event) u_newcount += newsize; u_oldcount += oldsize; uep->ue_size = oldsize; - uep->ue_array = newarray; + uep->ue_array = (char **)newarray; uep->ue_bot = top + newsize + 1; // insert this entry in front of the new entry list @@ -2636,9 +2636,9 @@ void ex_undolist(exarg_T *eap) if (uhp->uh_prev.ptr == NULL && uhp->uh_walk != nomark && uhp->uh_walk != mark) { vim_snprintf((char *)IObuff, IOSIZE, "%6ld %7d ", uhp->uh_seq, changes); - undo_fmt_time(IObuff + STRLEN(IObuff), IOSIZE - STRLEN(IObuff), uhp->uh_time); + undo_fmt_time((char_u *)IObuff + STRLEN(IObuff), IOSIZE - STRLEN(IObuff), uhp->uh_time); if (uhp->uh_save_nr > 0) { - while (STRLEN(IObuff) < 33) { + while (strlen(IObuff) < 33) { STRCAT(IObuff, " "); } vim_snprintf_add((char *)IObuff, IOSIZE, " %3ld", uhp->uh_save_nr); @@ -2744,7 +2744,7 @@ void u_find_first_changed(void) linenr_T lnum; for (lnum = 1; lnum < curbuf->b_ml.ml_line_count && lnum <= uep->ue_size; lnum++) { - if (STRCMP(ml_get_buf(curbuf, lnum, false), uep->ue_array[lnum - 1]) != 0) { + if (strcmp(ml_get_buf(curbuf, lnum, false), uep->ue_array[lnum - 1]) != 0) { clearpos(&(uhp->uh_cursor)); uhp->uh_cursor.lnum = lnum; return; @@ -2995,7 +2995,7 @@ void u_undoline(void) ml_replace(curbuf->b_u_line_lnum, curbuf->b_u_line_ptr, true); changed_bytes(curbuf->b_u_line_lnum, 0); extmark_splice_cols(curbuf, (int)curbuf->b_u_line_lnum - 1, 0, (colnr_T)STRLEN(oldp), - (colnr_T)STRLEN(curbuf->b_u_line_ptr), kExtmarkUndo); + (colnr_T)strlen(curbuf->b_u_line_ptr), kExtmarkUndo); xfree(curbuf->b_u_line_ptr); curbuf->b_u_line_ptr = (char *)oldp; diff --git a/src/nvim/undo_defs.h b/src/nvim/undo_defs.h index 4b64f97919..7c065c540b 100644 --- a/src/nvim/undo_defs.h +++ b/src/nvim/undo_defs.h @@ -21,11 +21,11 @@ typedef struct { typedef struct u_entry u_entry_T; struct u_entry { - u_entry_T *ue_next; // pointer to next entry in list + u_entry_T *ue_next; // pointer to next entry in list linenr_T ue_top; // number of line above undo block linenr_T ue_bot; // number of line below undo block linenr_T ue_lcount; // linecount when u_save called - char_u **ue_array; // array of lines in undo block + char **ue_array; // array of lines in undo block long ue_size; // number of lines in ue_array #ifdef U_DEBUG int ue_magic; // magic number to check allocation diff --git a/src/nvim/usercmd.c b/src/nvim/usercmd.c index 3726273d28..c3cf0b6df8 100644 --- a/src/nvim/usercmd.c +++ b/src/nvim/usercmd.c @@ -280,7 +280,7 @@ char *get_user_commands(expand_T *xp FUNC_ATTR_UNUSED, int idx) char *name = USER_CMD(idx)->uc_name; for (int i = 0; i < buf->b_ucmds.ga_len; i++) { - if (STRCMP(name, USER_CMD_GA(&buf->b_ucmds, i)->uc_name) == 0) { + if (strcmp(name, USER_CMD_GA(&buf->b_ucmds, i)->uc_name) == 0) { // global command is overruled by buffer-local one return ""; } @@ -435,7 +435,7 @@ static void uc_list(char *name, size_t name_len) } msg_outtrans_attr(cmd->uc_name, HL_ATTR(HLF_D)); - len = (int)STRLEN(cmd->uc_name) + 4; + len = (int)strlen(cmd->uc_name) + 4; do { msg_putchar(' '); @@ -476,14 +476,14 @@ static void uc_list(char *name, size_t name_len) // -count=N snprintf((char *)IObuff + len, IOSIZE, "%" PRId64 "c", (int64_t)cmd->uc_def); - len += (int)STRLEN(IObuff + len); + len += (int)strlen(IObuff + len); } else if (a & EX_DFLALL) { IObuff[len++] = '%'; } else if (cmd->uc_def >= 0) { // -range=N snprintf((char *)IObuff + len, IOSIZE, "%" PRId64 "", (int64_t)cmd->uc_def); - len += (int)STRLEN(IObuff + len); + len += (int)strlen(IObuff + len); } else { IObuff[len++] = '.'; } @@ -498,7 +498,7 @@ static void uc_list(char *name, size_t name_len) if (addr_type_complete[j].expand != ADDR_LINES && addr_type_complete[j].expand == cmd->uc_addr_type) { STRCPY(IObuff + len, addr_type_complete[j].shortname); - len += (int)STRLEN(IObuff + len); + len += (int)strlen(IObuff + len); break; } } @@ -511,7 +511,7 @@ static void uc_list(char *name, size_t name_len) char *cmd_compl = get_command_complete(cmd->uc_compl); if (cmd_compl != NULL) { STRCPY(IObuff + len, get_command_complete(cmd->uc_compl)); - len += (int)STRLEN(IObuff + len); + len += (int)strlen(IObuff + len); } do { @@ -559,7 +559,7 @@ int parse_addr_type_arg(char *value, int vallen, cmd_addr_T *addr_type_arg) int i, a, b; for (i = 0; addr_type_complete[i].expand != ADDR_NONE; i++) { - a = (int)STRLEN(addr_type_complete[i].name) == vallen; + a = (int)strlen(addr_type_complete[i].name) == vallen; b = STRNCMP(value, addr_type_complete[i].name, vallen) == 0; if (a && b) { *addr_type_arg = addr_type_complete[i].expand; @@ -607,7 +607,7 @@ int parse_compl_arg(const char *value, int vallen, int *complp, uint32_t *argt, if (get_command_complete(i) == NULL) { continue; } - if ((int)STRLEN(command_complete[i]) == valend + if ((int)strlen(command_complete[i]) == valend && STRNCMP(value, command_complete[i], valend) == 0) { *complp = i; if (i == EXPAND_BUFFERS) { @@ -816,7 +816,7 @@ int uc_add_command(char *name, size_t name_len, const char *rep, uint32_t argt, char *rep_buf = NULL; garray_T *gap; - replace_termcodes(rep, STRLEN(rep), &rep_buf, 0, NULL, CPO_TO_CPO_FLAGS); + replace_termcodes(rep, strlen(rep), &rep_buf, 0, NULL, CPO_TO_CPO_FLAGS); if (rep_buf == NULL) { // Can't replace termcodes - try using the string as is rep_buf = xstrdup(rep); @@ -837,7 +837,7 @@ int uc_add_command(char *name, size_t name_len, const char *rep, uint32_t argt, size_t len; cmd = USER_CMD_GA(gap, i); - len = STRLEN(cmd->uc_name); + len = strlen(cmd->uc_name); cmp = STRNCMP(name, cmd->uc_name, name_len); if (cmp == 0) { if (name_len < len) { @@ -1006,7 +1006,7 @@ void ex_delcommand(exarg_T *eap) for (;;) { for (i = 0; i < gap->ga_len; i++) { cmd = USER_CMD_GA(gap, i); - res = STRCMP(arg, cmd->uc_name); + res = strcmp(arg, cmd->uc_name); if (res <= 0) { break; } @@ -1198,7 +1198,7 @@ static char *uc_split_args(char *arg, char **args, size_t *arglens, size_t argc, static size_t add_cmd_modifier(char *buf, char *mod_str, bool *multi_mods) { - size_t result = STRLEN(mod_str); + size_t result = strlen(mod_str); if (*multi_mods) { result++; } @@ -1405,13 +1405,13 @@ static size_t uc_check_code(char *code, size_t len, char *buf, ucmd_T *cmd, exar switch (quote) { case 0: // No quoting, no splitting - result = STRLEN(eap->arg); + result = strlen(eap->arg); if (buf != NULL) { STRCPY(buf, eap->arg); } break; case 1: // Quote, but don't split - result = STRLEN(eap->arg) + 2; + result = strlen(eap->arg) + 2; for (p = eap->arg; *p; p++) { if (*p == '\\' || *p == '"') { result++; @@ -1475,7 +1475,7 @@ static size_t uc_check_code(char *code, size_t len, char *buf, ucmd_T *cmd, exar size_t num_len; snprintf(num_buf, sizeof(num_buf), "%" PRId64, (int64_t)num); - num_len = STRLEN(num_buf); + num_len = strlen(num_buf); result = num_len; if (quote) { @@ -1637,7 +1637,7 @@ int do_ucmd(exarg_T *eap, bool preview) break; } - totlen += STRLEN(p); // Add on the trailing characters + totlen += strlen(p); // Add on the trailing characters buf = xmalloc(totlen + 1); } diff --git a/src/nvim/vim.h b/src/nvim/vim.h index ec8d6ab153..5b7ff7ba52 100644 --- a/src/nvim/vim.h +++ b/src/nvim/vim.h @@ -205,7 +205,6 @@ enum { FOLD_TEXT_LEN = 51, }; //!< buffer size for get_foldtext() #define STRCPY(d, s) strcpy((char *)(d), (char *)(s)) #define STRNCPY(d, s, n) strncpy((char *)(d), (char *)(s), (size_t)(n)) #define STRLCPY(d, s, n) xstrlcpy((char *)(d), (char *)(s), (size_t)(n)) -#define STRCMP(d, s) strcmp((char *)(d), (char *)(s)) #define STRNCMP(d, s, n) strncmp((char *)(d), (char *)(s), (size_t)(n)) #ifdef HAVE_STRCASECMP # define STRICMP(d, s) strcasecmp((char *)(d), (char *)(s)) @@ -231,7 +230,6 @@ enum { FOLD_TEXT_LEN = 51, }; //!< buffer size for get_foldtext() #endif #define STRCAT(d, s) strcat((char *)(d), (char *)(s)) // NOLINT(runtime/printf) -#define STRLCAT(d, s, n) xstrlcat((char *)(d), (char *)(s), (size_t)(n)) // Character used as separated in autoload function/variable names. #define AUTOLOAD_CHAR '#' @@ -246,23 +244,6 @@ enum { FOLD_TEXT_LEN = 51, }; //!< buffer size for get_foldtext() #include "nvim/path.h" -/// Compare file names -/// -/// On some systems case in a file name does not matter, on others it does. -/// -/// @note Does not account for maximum name lengths and things like "../dir", -/// thus it is not 100% accurate. OS may also use different algorithm for -/// case-insensitive comparison. -/// -/// @param[in] x First file name to compare. -/// @param[in] y Second file name to compare. -/// -/// @return 0 for equal file names, non-zero otherwise. -#define FNAMECMP(x, y) path_fnamecmp((const char *)(x), (const char *)(y)) -#define FNAMENCMP(x, y, n) path_fnamencmp((const char *)(x), \ - (const char *)(y), \ - (size_t)(n)) - // Enums need a typecast to be used as array index. #define HL_ATTR(n) hl_attr_active[(int)(n)] @@ -275,7 +256,7 @@ enum { FOLD_TEXT_LEN = 51, }; //!< buffer size for get_foldtext() // functions of these names. The declarations would break if the defines had // been seen at that stage. But it must be before globals.h, where error_ga // is declared. -#ifndef WIN32 +#ifndef MSWIN # define mch_errmsg(str) fprintf(stderr, "%s", (str)) # define mch_msg(str) printf("%s", (str)) #endif diff --git a/src/nvim/window.c b/src/nvim/window.c index 63a6eb9fb6..236663dfea 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -746,7 +746,7 @@ void win_set_minimal_style(win_T *wp) parse_winhl_opt(wp); // signcolumn: use 'auto' - if (wp->w_p_scl[0] != 'a' || STRLEN(wp->w_p_scl) >= 8) { + if (wp->w_p_scl[0] != 'a' || strlen(wp->w_p_scl) >= 8) { free_string_option(wp->w_p_scl); wp->w_p_scl = xstrdup("auto"); } @@ -871,8 +871,9 @@ int win_fdccol_count(win_T *wp) } } -void ui_ext_win_position(win_T *wp) +void ui_ext_win_position(win_T *wp, bool validate) { + wp->w_pos_changed = false; if (!wp->w_floating) { ui_call_win_pos(wp->w_grid_alloc.handle, wp->handle, wp->w_winrow, wp->w_wincol, wp->w_width, wp->w_height); @@ -910,6 +911,11 @@ void ui_ext_win_position(win_T *wp) grid->handle, row, col, c.focusable, wp->w_grid_alloc.zindex); } else { + bool valid = (wp->w_redr_type == 0); + if (!valid && !validate) { + wp->w_pos_changed = true; + return; + } // TODO(bfredl): ideally, compositor should work like any multigrid UI // and use standard win_pos events. bool east = c.anchor & kFloatAnchorEast; @@ -923,7 +929,6 @@ void ui_ext_win_position(win_T *wp) comp_col = MAX(MIN(comp_col, Columns - wp->w_width_outer), 0); wp->w_winrow = comp_row; wp->w_wincol = comp_col; - bool valid = (wp->w_redr_type == 0); ui_comp_put_grid(&wp->w_grid_alloc, comp_row, comp_col, wp->w_height_outer, wp->w_width_outer, valid, false); ui_check_cursor_grid(wp->w_grid_alloc.handle); @@ -2459,7 +2464,8 @@ void close_windows(buf_T *buf, bool keep_curwin) for (tp = first_tabpage; tp != NULL; tp = nexttp) { nexttp = tp->tp_next; if (tp != curtab) { - FOR_ALL_WINDOWS_IN_TAB(wp, tp) { + // Start from tp_lastwin to close floating windows with the same buffer first. + for (win_T *wp = tp->tp_lastwin; wp != NULL; wp = wp->w_prev) { if (wp->w_buffer == buf && !(wp->w_closing || wp->w_buffer->b_locked > 0)) { win_close_othertab(wp, false, tp); @@ -2849,12 +2855,12 @@ int win_close(win_T *win, bool free_buf, bool force) check_cursor(); } - // If last window has a status line now and we don't want one, - // remove the status line. Do this before win_equal(), because - // it may change the height of a window. - last_status(false); - if (!was_floating) { + // If last window has a status line now and we don't want one, + // remove the status line. Do this before win_equal(), because + // it may change the height of a window. + last_status(false); + if (!curwin->w_floating && p_ea && (*p_ead == 'b' || *p_ead == dir)) { // If the frame of the closed window contains the new current window, // only resize that frame. Otherwise resize all windows. @@ -2898,7 +2904,10 @@ int win_close(win_T *win, bool free_buf, bool force) } curwin->w_pos_changed = true; - redraw_all_later(UPD_NOT_VALID); + if (!was_floating) { + // TODO(bfredl): how about no? + redraw_all_later(UPD_NOT_VALID); + } return OK; } @@ -5413,7 +5422,7 @@ void win_setheight_win(int height, win_T *win) if (win->w_floating) { win->w_float_config.height = height; win_config_float(win, win->w_float_config); - redraw_later(win, UPD_NOT_VALID); + redraw_later(win, UPD_VALID); } else { frame_setheight(win->w_frame, height + win->w_hsep_height + win->w_status_height); @@ -6059,6 +6068,9 @@ void win_new_height(win_T *wp, int height) wp->w_height = height; wp->w_pos_changed = true; win_set_inner_size(wp, true); + if (wp->w_status_height) { + wp->w_redr_status = true; + } } void scroll_to_fraction(win_T *wp, int prev_height) @@ -6193,11 +6205,10 @@ void win_set_inner_size(win_T *wp, bool valid_cursor) // There is no point in adjusting the scroll position when exiting. Some // values might be invalid. - // Skip scroll_to_fraction() when 'cmdheight' was set to one from zero. - if (!exiting && !made_cmdheight_nonzero && valid_cursor) { + if (!exiting && valid_cursor) { scroll_to_fraction(wp, prev_height); } - redraw_later(wp, UPD_NOT_VALID); // UPD_SOME_VALID?? + redraw_later(wp, UPD_SOME_VALID); } if (width != wp->w_width_inner) { @@ -6467,10 +6478,10 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u // Also accept " line 999" with and without the same translation as // used in last_set_msg(). p = ptr + len; - if (STRNCMP(p, line_english, STRLEN(line_english)) == 0) { - p += STRLEN(line_english); - } else if (STRNCMP(p, line_transl, STRLEN(line_transl)) == 0) { - p += STRLEN(line_transl); + if (STRNCMP(p, line_english, strlen(line_english)) == 0) { + p += strlen(line_english); + } else if (STRNCMP(p, line_transl, strlen(line_transl)) == 0) { + p += strlen(line_transl); } else { p = skipwhite(p); } @@ -6609,7 +6620,6 @@ static void last_status_rec(frame_T *fr, bool statusline, bool is_stl_global) wp->w_hsep_height = 0; comp_col(); } - redraw_all_later(UPD_SOME_VALID); } else { // For a column or row frame, recursively call this function for all child frames FOR_ALL_FRAMES(fp, fr->fr_child) { @@ -7337,16 +7347,16 @@ void get_framelayout(const frame_T *fr, list_T *l, bool outer) } } -void win_ui_flush(void) +void win_ui_flush(bool validate) { FOR_ALL_TAB_WINDOWS(tp, wp) { if (wp->w_pos_changed && wp->w_grid_alloc.chars != NULL) { if (tp == curtab) { - ui_ext_win_position(wp); + ui_ext_win_position(wp, validate); } else { ui_call_win_hide(wp->w_grid_alloc.handle); + wp->w_pos_changed = false; } - wp->w_pos_changed = false; } if (tp == curtab) { ui_ext_win_viewport(wp); diff --git a/src/nvim/window.h b/src/nvim/window.h index 3137035b25..a564a0cfad 100644 --- a/src/nvim/window.h +++ b/src/nvim/window.h @@ -45,8 +45,8 @@ typedef struct { do { \ win_T *const wp_ = (wp); \ const pos_T curpos_ = wp_->w_cursor; \ - char_u cwd_[MAXPATHL]; \ - char_u autocwd_[MAXPATHL]; \ + char cwd_[MAXPATHL]; \ + char autocwd_[MAXPATHL]; \ bool apply_acd_ = false; \ int cwd_status_ = FAIL; \ /* Getting and setting directory can be slow on some systems, only do */ \ @@ -56,13 +56,13 @@ typedef struct { && (curwin->w_localdir != NULL || wp->w_localdir != NULL \ || (curtab != tp && (curtab->tp_localdir != NULL || tp->tp_localdir != NULL)) \ || p_acd)) { \ - cwd_status_ = os_dirname(cwd_, MAXPATHL); \ + cwd_status_ = os_dirname((char_u *)cwd_, MAXPATHL); \ } \ /* If 'acd' is set, check we are using that directory. If yes, then */ \ /* apply 'acd' afterwards, otherwise restore the current directory. */ \ if (cwd_status_ == OK && p_acd) { \ do_autochdir(); \ - apply_acd_ = os_dirname(autocwd_, MAXPATHL) == OK && STRCMP(cwd_, autocwd_) == 0; \ + apply_acd_ = os_dirname((char_u *)autocwd_, MAXPATHL) == OK && strcmp(cwd_, autocwd_) == 0; \ } \ switchwin_T switchwin_; \ if (switch_win_noblock(&switchwin_, wp_, (tp), true) == OK) { \ @@ -73,7 +73,7 @@ typedef struct { if (apply_acd_) { \ do_autochdir(); \ } else if (cwd_status_ == OK) { \ - os_chdir((char *)cwd_); \ + os_chdir(cwd_); \ } \ /* Update the status line if the cursor moved. */ \ if (win_valid(wp_) && !equalpos(curpos_, wp_->w_cursor)) { \ diff --git a/runtime/lua/vim/compat.lua b/test/compat.lua index 2c9786d491..2c9786d491 100644 --- a/runtime/lua/vim/compat.lua +++ b/test/compat.lua diff --git a/test/functional/api/server_notifications_spec.lua b/test/functional/api/server_notifications_spec.lua index 1c00f001ff..1c554b05a3 100644 --- a/test/functional/api/server_notifications_spec.lua +++ b/test/functional/api/server_notifications_spec.lua @@ -7,6 +7,7 @@ local exec_lua = helpers.exec_lua local retry = helpers.retry local isCI = helpers.isCI local assert_alive = helpers.assert_alive +local uname = helpers.uname describe('notify', function() local channel @@ -78,6 +79,9 @@ describe('notify', function() end) it('cancels stale events on channel close', function() + if uname() == 'freebsd' then + pending('Failing FreeBSD test') + end if isCI() then pending('hangs on CI #14083 #15251') return diff --git a/test/functional/autocmd/cursorhold_spec.lua b/test/functional/autocmd/cursorhold_spec.lua index 506b688853..b04bd5233a 100644 --- a/test/functional/autocmd/cursorhold_spec.lua +++ b/test/functional/autocmd/cursorhold_spec.lua @@ -2,30 +2,82 @@ local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local eq = helpers.eq -local eval = helpers.eval local feed = helpers.feed local retry = helpers.retry -local source = helpers.source +local exec = helpers.source local sleep = helpers.sleep +local meths = helpers.meths -describe('CursorHoldI', function() - before_each(clear) +before_each(clear) + +describe('CursorHold', function() + before_each(function() + exec([[ + let g:cursorhold = 0 + augroup test + au CursorHold * let g:cursorhold += 1 + augroup END + ]]) + end) + + it('is triggered correctly #12587', function() + local function test_cursorhold(fn, early) + local ut = 2 + -- if testing with small 'updatetime' fails, double its value and test again + retry(10, nil, function() + ut = ut * 2 + meths.set_option('updatetime', ut) + feed('0') -- reset did_cursorhold + meths.set_var('cursorhold', 0) + sleep(ut / 4) + fn() + eq(0, meths.get_var('cursorhold')) + sleep(ut / 2) + fn() + eq(0, meths.get_var('cursorhold')) + sleep(ut / 2) + eq(early, meths.get_var('cursorhold')) + sleep(ut / 4 * 3) + eq(1, meths.get_var('cursorhold')) + end) + end + local ignore_key = meths.replace_termcodes('<Ignore>', true, true, true) + test_cursorhold(function() end, 1) + test_cursorhold(function() feed('') end, 1) + test_cursorhold(function() meths.feedkeys('', 'n', true) end, 1) + test_cursorhold(function() feed('<Ignore>') end, 0) + test_cursorhold(function() meths.feedkeys(ignore_key, 'n', true) end, 0) + end) + + it("reducing 'updatetime' while waiting for CursorHold #20241", function() + meths.set_option('updatetime', 10000) + feed('0') -- reset did_cursorhold + meths.set_var('cursorhold', 0) + sleep(50) + eq(0, meths.get_var('cursorhold')) + meths.set_option('updatetime', 20) + sleep(10) + eq(1, meths.get_var('cursorhold')) + end) +end) + +describe('CursorHoldI', function() -- NOTE: since this test uses RPC it is not necessary to trigger the initial -- issue (#3757) via timer's or RPC callbacks in the first place. it('is triggered after input', function() - source([[ - set updatetime=1 + exec([[ + set updatetime=1 - let g:cursorhold = 0 - augroup test - au CursorHoldI * let g:cursorhold += 1 - augroup END + let g:cursorhold = 0 + augroup test + au CursorHoldI * let g:cursorhold += 1 + augroup END ]]) feed('ifoo') retry(5, nil, function() sleep(1) - eq(1, eval('g:cursorhold')) + eq(1, meths.get_var('cursorhold')) end) end) end) diff --git a/test/functional/core/fileio_spec.lua b/test/functional/core/fileio_spec.lua index a4d22685e8..e71131dcf8 100644 --- a/test/functional/core/fileio_spec.lua +++ b/test/functional/core/fileio_spec.lua @@ -23,6 +23,7 @@ local iswin = helpers.iswin local assert_alive = helpers.assert_alive local expect_exit = helpers.expect_exit local write_file = helpers.write_file +local uname = helpers.uname describe('fileio', function() before_each(function() @@ -83,6 +84,9 @@ describe('fileio', function() end) it('backup #9709', function() + if uname() == 'freebsd' then + pending('Failing FreeBSD test') + end clear({ args={ '-i', 'Xtest_startup_shada', '--cmd', 'set directory=Xtest_startup_swapdir' } }) @@ -102,6 +106,9 @@ describe('fileio', function() end) it('backup with full path #11214', function() + if uname() == 'freebsd' then + pending('Failing FreeBSD test') + end clear() mkdir('Xtest_backupdir') command('set backup') diff --git a/test/functional/core/remote_spec.lua b/test/functional/core/remote_spec.lua index d7bd075eb2..846d79abf3 100644 --- a/test/functional/core/remote_spec.lua +++ b/test/functional/core/remote_spec.lua @@ -3,6 +3,7 @@ local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local command = helpers.command local eq = helpers.eq +local exec_lua = helpers.exec_lua local expect = helpers.expect local funcs = helpers.funcs local insert = helpers.insert @@ -48,8 +49,8 @@ describe('Remote', function() -- our incoming --remote calls. local client_starter = spawn(new_argv(), false, nil, true) set_session(client_starter) - local client_job_id = funcs.jobstart(client_argv) - eq({ 0 }, funcs.jobwait({client_job_id})) + -- Call jobstart() and jobwait() in the same RPC request to reduce flakiness. + eq({ 0 }, exec_lua([[return vim.fn.jobwait({ vim.fn.jobstart(...) })]], client_argv)) client_starter:close() set_session(server) end @@ -121,8 +122,8 @@ describe('Remote', function() -- the event loop. If the server event loop is blocked, it can't process -- our incoming --remote calls. clear() - local bogus_job_id = funcs.jobstart(bogus_argv) - eq({2}, funcs.jobwait({bogus_job_id})) + -- Call jobstart() and jobwait() in the same RPC request to reduce flakiness. + eq({ 2 }, exec_lua([[return vim.fn.jobwait({ vim.fn.jobstart(...) })]], bogus_argv)) end it('bogus subcommand', function() run_and_check_exit_code('--remote-bogus') diff --git a/test/functional/ex_cmds/write_spec.lua b/test/functional/ex_cmds/write_spec.lua index 32fe397c03..14035a4341 100644 --- a/test/functional/ex_cmds/write_spec.lua +++ b/test/functional/ex_cmds/write_spec.lua @@ -9,6 +9,7 @@ local feed_command = helpers.feed_command local funcs = helpers.funcs local meths = helpers.meths local iswin = helpers.iswin +local uname = helpers.uname local fname = 'Xtest-functional-ex_cmds-write' local fname_bak = fname .. '~' @@ -52,6 +53,9 @@ describe(':write', function() end) it('&backupcopy=no replaces symlink with new file', function() + if uname() == 'freebsd' then + pending('Failing FreeBSD test') + end command('set backupcopy=no') write_file('test_bkc_file.txt', 'content0') if iswin() then @@ -91,6 +95,9 @@ describe(':write', function() end) it('errors out correctly', function() + if uname() == 'freebsd' then + pending('Failing FreeBSD test') + end command('let $HOME=""') eq(funcs.fnamemodify('.', ':p:h'), funcs.fnamemodify('.', ':p:h:~')) -- Message from check_overwrite diff --git a/test/functional/fixtures/printenv-test.c b/test/functional/fixtures/printenv-test.c index 0e68129543..295b4f04c3 100644 --- a/test/functional/fixtures/printenv-test.c +++ b/test/functional/fixtures/printenv-test.c @@ -3,13 +3,13 @@ #include <stdio.h> -#ifdef WIN32 +#ifdef MSWIN # include <windows.h> #else # include <stdlib.h> #endif -#ifdef WIN32 +#ifdef MSWIN int wmain(int argc, wchar_t **argv) #else int main(int argc, char **argv) @@ -19,7 +19,7 @@ int main(int argc, char **argv) return 1; } -#ifdef WIN32 +#ifdef MSWIN wchar_t *value = _wgetenv(argv[1]); if (value == NULL) { return 1; diff --git a/test/functional/fixtures/start/nvim-leftpad/lua/async_leftpad.lua b/test/functional/fixtures/start/nvim-leftpad/lua/async_leftpad.lua index a312572c5b..45226ce24b 100644 --- a/test/functional/fixtures/start/nvim-leftpad/lua/async_leftpad.lua +++ b/test/functional/fixtures/start/nvim-leftpad/lua/async_leftpad.lua @@ -1,3 +1,5 @@ return function (val, res) - vim.loop.new_async(function() _G[res] = require'leftpad'(val) end):send() + local handle + handle = vim.loop.new_async(function() _G[res] = require'leftpad'(val) handle:close() end) + handle:send() end diff --git a/test/functional/fixtures/tty-test.c b/test/functional/fixtures/tty-test.c index 4438b73a22..6ee7715021 100644 --- a/test/functional/fixtures/tty-test.c +++ b/test/functional/fixtures/tty-test.c @@ -5,7 +5,7 @@ #include <stdio.h> #include <stdlib.h> #include <uv.h> -#ifdef _WIN32 +#ifdef MSWIN # include <windows.h> #else # include <unistd.h> @@ -23,7 +23,7 @@ uv_tty_t tty_out; bool owns_tty(void); // silence -Wmissing-prototypes bool owns_tty(void) { -#ifdef _WIN32 +#ifdef MSWIN // XXX: We need to make proper detect owns tty // HWND consoleWnd = GetConsoleWindow(); // DWORD dwProcessId; @@ -38,14 +38,14 @@ bool owns_tty(void) static void walk_cb(uv_handle_t *handle, void *arg) { if (!uv_is_closing(handle)) { -#ifdef WIN32 +#ifdef MSWIN uv_tty_set_mode(&tty, UV_TTY_MODE_NORMAL); #endif uv_close(handle, NULL); } } -#ifndef WIN32 +#ifndef MSWIN static void sig_handler(int signum) { switch (signum) { @@ -64,7 +64,7 @@ static void sig_handler(int signum) } #endif -#ifdef WIN32 +#ifdef MSWIN static void sigwinch_cb(uv_signal_t *handle, int signum) { int width, height; @@ -102,7 +102,7 @@ static void read_cb(uv_stream_t *stream, ssize_t cnt, const uv_buf_t *buf) uv_write_t req; uv_buf_t b = { .base = buf->base, -#ifdef WIN32 +#ifdef MSWIN .len = (ULONG)cnt #else .len = (size_t)cnt @@ -171,7 +171,7 @@ int main(int argc, char **argv) uv_prepare_t prepare; uv_prepare_init(uv_default_loop(), &prepare); uv_prepare_start(&prepare, prepare_cb); -#ifndef WIN32 +#ifndef MSWIN uv_tty_init(uv_default_loop(), &tty, fileno(stderr), 1); #else uv_tty_init(uv_default_loop(), &tty, fileno(stdin), 1); @@ -182,7 +182,7 @@ int main(int argc, char **argv) uv_tty_set_mode(&tty, UV_TTY_MODE_RAW); tty.data = &interrupted; uv_read_start(STRUCT_CAST(uv_stream_t, &tty), alloc_cb, read_cb); -#ifndef WIN32 +#ifndef MSWIN struct sigaction sa; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; @@ -196,7 +196,7 @@ int main(int argc, char **argv) #endif uv_run(uv_default_loop(), UV_RUN_DEFAULT); -#ifndef WIN32 +#ifndef MSWIN // XXX: Without this the SIGHUP handler is skipped on some systems. sleep(100); #endif diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index d672037a1e..eff54b6d4a 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -380,10 +380,23 @@ local function remove_args(args, args_rm) return new_args end +function module.check_close(old_session) + local start_time = luv.now() + old_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 + if delta > 500 then + print("nvim took " .. delta .. " milliseconds to exit after last test\n".. + "This indicates a likely problem with the test even if it passed!\n") + io.stdout:flush() + end +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 - session:close() + module.check_close(session) end local child_stream = ChildProcessStream.spawn( diff --git a/test/functional/legacy/cmdline_spec.lua b/test/functional/legacy/cmdline_spec.lua index 99d2d0f30e..49e3825693 100644 --- a/test/functional/legacy/cmdline_spec.lua +++ b/test/functional/legacy/cmdline_spec.lua @@ -140,6 +140,115 @@ describe('cmdline', function() :^ | ]]) end) + + -- oldtest: Test_redraw_in_autocmd() + it('cmdline cursor position is correct after :redraw with cmdheight=2', function() + local screen = Screen.new(30, 6) + screen:set_default_attr_ids({ + [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText + }) + screen:attach() + exec([[ + set cmdheight=2 + autocmd CmdlineChanged * redraw + ]]) + feed(':for i in range(3)<CR>') + screen:expect([[ + | + {0:~ }| + {0:~ }| + {0:~ }| + :for i in range(3) | + : ^ | + ]]) + feed(':let i =') + -- Note: this may still be considered broken, ref #18140 + screen:expect([[ + | + {0:~ }| + {0:~ }| + {0:~ }| + : :let i =^ | + | + ]]) + end) + + -- oldtest: Test_redrawstatus_in_autocmd() + it(':redrawstatus in cmdline mode', function() + local screen = Screen.new(60, 8) + screen:set_default_attr_ids({ + [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText + [1] = {bold = true, reverse = true}, -- MsgSeparator, StatusLine + }) + screen:attach() + exec([[ + set laststatus=2 + set statusline=%=:%{getcmdline()} + autocmd CmdlineChanged * redrawstatus + set display-=msgsep + ]]) + -- :redrawstatus is postponed if messages have scrolled + feed([[:echo "one\ntwo\nthree\nfour"<CR>]]) + feed(':foobar') + screen:expect([[ + {0:~ }| + {0:~ }| + {1: :echo "one\ntwo\nthree\nfour"}| + one | + two | + three | + four | + :foobar^ | + ]]) + -- it is not postponed if messages have not scrolled + feed('<Esc>:for in in range(3)') + screen:expect([[ + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {1: :for in in range(3)}| + :for in in range(3)^ | + ]]) + -- with cmdheight=1 messages have scrolled when typing :endfor + feed('<CR>:endfor') + screen:expect([[ + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {1: :for in in range(3)}| + :for in in range(3) | + : :endfor^ | + ]]) + feed('<CR>:set cmdheight=2<CR>') + -- with cmdheight=2 messages haven't scrolled when typing :for or :endfor + feed(':for in in range(3)') + screen:expect([[ + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {1: :for in in range(3)}| + :for in in range(3)^ | + | + ]]) + feed('<CR>:endfor') + screen:expect([[ + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {1: ::endfor}| + :for in in range(3) | + : :endfor^ | + ]]) + end) end) describe('cmdwin', function() diff --git a/test/functional/legacy/messages_spec.lua b/test/functional/legacy/messages_spec.lua index 159cf7a551..c76ce62ef0 100644 --- a/test/functional/legacy/messages_spec.lua +++ b/test/functional/legacy/messages_spec.lua @@ -10,6 +10,43 @@ before_each(clear) describe('messages', function() local screen + -- oldtest: Test_warning_scroll() + it('a warning causes scrolling if and only if it has a stacktrace', function() + screen = Screen.new(75, 6) + screen:set_default_attr_ids({ + [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText + [1] = {bold = true, foreground = Screen.colors.SeaGreen}, -- MoreMsg + [2] = {bold = true, reverse = true}, -- MsgSeparator + [3] = {foreground = Screen.colors.Red}, -- WarningMsg + }) + screen:attach() + + -- When the warning comes from a script, messages are scrolled so that the + -- stacktrace is visible. + -- It is a bit hard to assert the screen when sourcing a script, so skip this part. + + -- When the warning does not come from a script, messages are not scrolled. + command('enew') + command('set readonly') + feed('u') + screen:expect({grid = [[ + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {3:W10: Warning: Changing a readonly file}^ | + ]], timeout = 500}) + screen:expect([[ + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + Already at oldest change | + ]]) + end) + describe('more prompt', function() before_each(function() screen = Screen.new(75, 6) diff --git a/test/functional/legacy/080_substitute_spec.lua b/test/functional/legacy/substitute_spec.lua index faeb61e3af..f3ce343680 100644 --- a/test/functional/legacy/080_substitute_spec.lua +++ b/test/functional/legacy/substitute_spec.lua @@ -3,11 +3,13 @@ -- Test for *:s%* on :substitute. local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') local feed, insert = helpers.feed, helpers.insert +local exec = helpers.exec local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect local eq, eval = helpers.eq, helpers.eval -describe('substitue()', function() +describe('substitute()', function() before_each(clear) -- The original test contained several TEST_X lines to delimit different @@ -132,7 +134,7 @@ describe('substitue()', function() end) end) -describe(':substitue', function() +describe(':substitute', function() before_each(clear) it('with \\ze and \\zs and confirmation dialog (TEST_8)', function() @@ -159,4 +161,29 @@ describe(':substitue', function() feed('yyq') -- For the dialog of the previous :s command. expect('XXx') end) + + it('first char is highlighted with confirmation dialog and empty match', function() + local screen = Screen.new(60, 8) + screen:set_default_attr_ids({ + [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText + [1] = {reverse = true}, -- IncSearch + [2] = {bold = true, foreground = Screen.colors.SeaGreen}, -- MoreMsg + }) + screen:attach() + exec([[ + set nohlsearch noincsearch + call setline(1, ['one', 'two', 'three']) + ]]) + feed(':%s/^/ /c<CR>') + screen:expect([[ + {1:o}ne | + two | + three | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {2:replace with (y/n/a/q/l/^E/^Y)?}^ | + ]]) + end) end) diff --git a/test/functional/lua/diagnostic_spec.lua b/test/functional/lua/diagnostic_spec.lua index 1514dadca8..28a8679205 100644 --- a/test/functional/lua/diagnostic_spec.lua +++ b/test/functional/lua/diagnostic_spec.lua @@ -1983,19 +1983,26 @@ end) end) it('triggers the autocommand when diagnostics are set', function() - eq(true, exec_lua [[ + eq({true, true}, exec_lua [[ -- Set a different buffer as current to test that <abuf> is being set properly in -- DiagnosticChanged callbacks local tmp = vim.api.nvim_create_buf(false, true) vim.api.nvim_set_current_buf(tmp) - vim.g.diagnostic_autocmd_triggered = 0 - vim.cmd('autocmd DiagnosticChanged * let g:diagnostic_autocmd_triggered = +expand("<abuf>")') + local triggered = {} + vim.api.nvim_create_autocmd('DiagnosticChanged', { + callback = function(args) + triggered = {args.buf, #args.data.diagnostics} + end, + }) vim.api.nvim_buf_set_name(diagnostic_bufnr, "test | test") vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { make_error('Diagnostic', 0, 0, 0, 0) }) - return vim.g.diagnostic_autocmd_triggered == diagnostic_bufnr + return { + triggered[1] == diagnostic_bufnr, + triggered[2] == 1, + } ]]) end) diff --git a/test/functional/lua/fs_spec.lua b/test/functional/lua/fs_spec.lua index 2bcc84db0f..3123ec324c 100644 --- a/test/functional/lua/fs_spec.lua +++ b/test/functional/lua/fs_spec.lua @@ -78,6 +78,23 @@ describe('vim.fs', function() return vim.fs.find(nvim, { path = dir, type = 'file' }) ]], test_build_dir, nvim_prog_basename)) end) + + it('accepts predicate as names', function() + eq({test_build_dir}, exec_lua([[ + local dir = ... + local opts = { path = dir, upward = true, type = 'directory' } + return vim.fs.find(function(x) return x == 'build' end, opts) + ]], nvim_dir)) + eq({nvim_prog}, exec_lua([[ + local dir, nvim = ... + return vim.fs.find(function(x) return x == nvim end, { path = dir, type = 'file' }) + ]], test_build_dir, nvim_prog_basename)) + eq({}, exec_lua([[ + local dir = ... + local opts = { path = dir, upward = true, type = 'directory' } + return vim.fs.find(function(x) return x == 'no-match' end, opts) + ]], nvim_dir)) + end) end) describe('normalize()', function() diff --git a/test/functional/lua/ui_event_spec.lua b/test/functional/lua/ui_event_spec.lua index 294222ad13..57ffcf7b4e 100644 --- a/test/functional/lua/ui_event_spec.lua +++ b/test/functional/lua/ui_event_spec.lua @@ -105,4 +105,16 @@ describe('vim.ui_attach', function() } end) + + it('does not crash on exit', function() + helpers.funcs.system({ + helpers.nvim_prog, + '-u', 'NONE', + '-i', 'NONE', + '--cmd', [[ lua ns = vim.api.nvim_create_namespace 'testspace' ]], + '--cmd', [[ lua vim.ui_attach(ns, {ext_popupmenu=true}, function() end) ]], + '--cmd', 'quitall!', + }) + eq(0, helpers.eval('v:shell_error')) + end) end) diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index 2466e9cc31..3184f01ef4 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -158,17 +158,20 @@ describe('lua stdlib', function() end) it("vim.str_utfindex/str_byteindex", function() - exec_lua([[_G.test_text = "xy åäö ɧ 汉语 ↥ 🤦x🦄 å بِيَّ"]]) - local indicies32 = {[0]=0,1,2,3,5,7,9,10,12,13,16,19,20,23,24,28,29,33,34,35,37,38,40,42,44,46,48} - local indicies16 = {[0]=0,1,2,3,5,7,9,10,12,13,16,19,20,23,24,28,28,29,33,33,34,35,37,38,40,42,44,46,48} + exec_lua([[_G.test_text = "xy åäö ɧ 汉语 ↥ 🤦x🦄 å بِيَّ\000ъ"]]) + local indicies32 = {[0]=0,1,2,3,5,7,9,10,12,13,16,19,20,23,24,28,29,33,34,35,37,38,40,42,44,46,48,49,51} + local indicies16 = {[0]=0,1,2,3,5,7,9,10,12,13,16,19,20,23,24,28,28,29,33,33,34,35,37,38,40,42,44,46,48,49,51} for i,k in pairs(indicies32) do eq(k, exec_lua("return vim.str_byteindex(_G.test_text, ...)", i), i) end for i,k in pairs(indicies16) do eq(k, exec_lua("return vim.str_byteindex(_G.test_text, ..., true)", i), i) end + matches(": index out of range$", pcall_err(exec_lua, "return vim.str_byteindex(_G.test_text, ...)", #indicies32 + 1)) + matches(": index out of range$", pcall_err(exec_lua, "return vim.str_byteindex(_G.test_text, ..., true)", #indicies16 + 1)) local i32, i16 = 0, 0 - for k = 0,48 do + local len = 51 + for k = 0,len do if indicies32[i32] < k then i32 = i32 + 1 end @@ -180,6 +183,7 @@ describe('lua stdlib', function() end eq({i32, i16}, exec_lua("return {vim.str_utfindex(_G.test_text, ...)}", k), k) end + matches(": index out of range$", pcall_err(exec_lua, "return vim.str_utfindex(_G.test_text, ...)", len + 1)) end) it("vim.str_utf_start", function() @@ -788,6 +792,11 @@ describe('lua stdlib', function() local x = vim.fn.VarArg(function() return 'foo' end, function() return 'bar' end) return #x == 2 and x[1]() == 'foo' and x[2]() == 'bar' ]])) + + -- Test for #20211 + eq('a (b) c', exec_lua([[ + return vim.fn.substitute('a b c', 'b', function(m) return '(' .. m[1] .. ')' end, 'g') + ]])) end) it('vim.fn should error when calling API function', function() @@ -1029,6 +1038,7 @@ describe('lua stdlib', function() vim.g.AddCounter = add_counter vim.g.GetCounter = get_counter vim.g.funcs = {add = add_counter, get = get_counter} + vim.g.AddParens = function(s) return '(' .. s .. ')' end ]] eq(0, eval('g:GetCounter()')) @@ -1044,6 +1054,7 @@ describe('lua stdlib', function() eq(5, exec_lua([[return vim.g.funcs.get()]])) exec_lua([[vim.api.nvim_get_var('funcs').add()]]) eq(6, exec_lua([[return vim.api.nvim_get_var('funcs').get()]])) + eq('((foo))', eval([['foo'->AddParens()->AddParens()]])) exec_lua [[ local counter = 0 @@ -1052,6 +1063,7 @@ describe('lua stdlib', function() vim.api.nvim_set_var('AddCounter', add_counter) vim.api.nvim_set_var('GetCounter', get_counter) vim.api.nvim_set_var('funcs', {add = add_counter, get = get_counter}) + vim.api.nvim_set_var('AddParens', function(s) return '(' .. s .. ')' end) ]] eq(0, eval('g:GetCounter()')) @@ -1067,6 +1079,7 @@ describe('lua stdlib', function() eq(5, exec_lua([[return vim.g.funcs.get()]])) exec_lua([[vim.api.nvim_get_var('funcs').add()]]) eq(6, exec_lua([[return vim.api.nvim_get_var('funcs').get()]])) + eq('((foo))', eval([['foo'->AddParens()->AddParens()]])) exec([[ function Test() @@ -1133,6 +1146,7 @@ describe('lua stdlib', function() vim.b.AddCounter = add_counter vim.b.GetCounter = get_counter vim.b.funcs = {add = add_counter, get = get_counter} + vim.b.AddParens = function(s) return '(' .. s .. ')' end ]] eq(0, eval('b:GetCounter()')) @@ -1148,6 +1162,7 @@ describe('lua stdlib', function() eq(5, exec_lua([[return vim.b.funcs.get()]])) exec_lua([[vim.api.nvim_buf_get_var(0, 'funcs').add()]]) eq(6, exec_lua([[return vim.api.nvim_buf_get_var(0, 'funcs').get()]])) + eq('((foo))', eval([['foo'->b:AddParens()->b:AddParens()]])) exec_lua [[ local counter = 0 @@ -1156,6 +1171,7 @@ describe('lua stdlib', function() vim.api.nvim_buf_set_var(0, 'AddCounter', add_counter) vim.api.nvim_buf_set_var(0, 'GetCounter', get_counter) vim.api.nvim_buf_set_var(0, 'funcs', {add = add_counter, get = get_counter}) + vim.api.nvim_buf_set_var(0, 'AddParens', function(s) return '(' .. s .. ')' end) ]] eq(0, eval('b:GetCounter()')) @@ -1171,6 +1187,7 @@ describe('lua stdlib', function() eq(5, exec_lua([[return vim.b.funcs.get()]])) exec_lua([[vim.api.nvim_buf_get_var(0, 'funcs').add()]]) eq(6, exec_lua([[return vim.api.nvim_buf_get_var(0, 'funcs').get()]])) + eq('((foo))', eval([['foo'->b:AddParens()->b:AddParens()]])) exec([[ function Test() @@ -1227,6 +1244,7 @@ describe('lua stdlib', function() vim.w.AddCounter = add_counter vim.w.GetCounter = get_counter vim.w.funcs = {add = add_counter, get = get_counter} + vim.w.AddParens = function(s) return '(' .. s .. ')' end ]] eq(0, eval('w:GetCounter()')) @@ -1242,6 +1260,7 @@ describe('lua stdlib', function() eq(5, exec_lua([[return vim.w.funcs.get()]])) exec_lua([[vim.api.nvim_win_get_var(0, 'funcs').add()]]) eq(6, exec_lua([[return vim.api.nvim_win_get_var(0, 'funcs').get()]])) + eq('((foo))', eval([['foo'->w:AddParens()->w:AddParens()]])) exec_lua [[ local counter = 0 @@ -1250,6 +1269,7 @@ describe('lua stdlib', function() vim.api.nvim_win_set_var(0, 'AddCounter', add_counter) vim.api.nvim_win_set_var(0, 'GetCounter', get_counter) vim.api.nvim_win_set_var(0, 'funcs', {add = add_counter, get = get_counter}) + vim.api.nvim_win_set_var(0, 'AddParens', function(s) return '(' .. s .. ')' end) ]] eq(0, eval('w:GetCounter()')) @@ -1265,6 +1285,7 @@ describe('lua stdlib', function() eq(5, exec_lua([[return vim.w.funcs.get()]])) exec_lua([[vim.api.nvim_win_get_var(0, 'funcs').add()]]) eq(6, exec_lua([[return vim.api.nvim_win_get_var(0, 'funcs').get()]])) + eq('((foo))', eval([['foo'->w:AddParens()->w:AddParens()]])) exec([[ function Test() @@ -1316,6 +1337,7 @@ describe('lua stdlib', function() vim.t.AddCounter = add_counter vim.t.GetCounter = get_counter vim.t.funcs = {add = add_counter, get = get_counter} + vim.t.AddParens = function(s) return '(' .. s .. ')' end ]] eq(0, eval('t:GetCounter()')) @@ -1331,6 +1353,7 @@ describe('lua stdlib', function() eq(5, exec_lua([[return vim.t.funcs.get()]])) exec_lua([[vim.api.nvim_tabpage_get_var(0, 'funcs').add()]]) eq(6, exec_lua([[return vim.api.nvim_tabpage_get_var(0, 'funcs').get()]])) + eq('((foo))', eval([['foo'->t:AddParens()->t:AddParens()]])) exec_lua [[ local counter = 0 @@ -1339,6 +1362,7 @@ describe('lua stdlib', function() vim.api.nvim_tabpage_set_var(0, 'AddCounter', add_counter) vim.api.nvim_tabpage_set_var(0, 'GetCounter', get_counter) vim.api.nvim_tabpage_set_var(0, 'funcs', {add = add_counter, get = get_counter}) + vim.api.nvim_tabpage_set_var(0, 'AddParens', function(s) return '(' .. s .. ')' end) ]] eq(0, eval('t:GetCounter()')) @@ -1354,6 +1378,7 @@ describe('lua stdlib', function() eq(5, exec_lua([[return vim.t.funcs.get()]])) exec_lua([[vim.api.nvim_tabpage_get_var(0, 'funcs').add()]]) eq(6, exec_lua([[return vim.api.nvim_tabpage_get_var(0, 'funcs').get()]])) + eq('((foo))', eval([['foo'->t:AddParens()->t:AddParens()]])) exec_lua [[ vim.cmd "tabnew" diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index 9da2c4aa61..e032f3bc2b 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -418,6 +418,43 @@ describe('LSP', function() } end) + it('should detach buffer on bufwipe', function() + clear() + local result = exec_lua([[ + local server = function(dispatchers) + local closing = false + return { + request = function(method, params, callback) + if method == 'initialize' then + callback(nil, { capabilities = {} }) + end + end, + notify = function(...) + end, + is_closing = function() return closing end, + terminate = function() closing = true end + } + end + local bufnr = vim.api.nvim_create_buf(false, true) + vim.api.nvim_set_current_buf(bufnr) + local client_id = vim.lsp.start({ name = 'detach-dummy', cmd = server }) + assert(client_id, "lsp.start must return client_id") + local client = vim.lsp.get_client_by_id(client_id) + local num_attached_before = vim.tbl_count(client.attached_buffers) + vim.api.nvim_buf_delete(bufnr, { force = true }) + local num_attached_after = vim.tbl_count(client.attached_buffers) + return { + bufnr = bufnr, + client_id = client_id, + num_attached_before = num_attached_before, + num_attached_after = num_attached_after, + } + ]]) + eq(true, result ~= nil, "exec_lua must return result") + eq(1, result.num_attached_before) + eq(0, result.num_attached_after) + end) + it('client should return settings via workspace/configuration handler', function() local expected_handlers = { {NIL, {}, {method="shutdown", client_id=1}}; @@ -1682,6 +1719,46 @@ describe('LSP', function() end) end) + describe('apply_text_edits regression tests for #20116', function() + before_each(function() + insert(dedent([[ + Test line one + Test line two 21 char]])) + end) + describe('with LSP end column out of bounds and start column at 0', function() + it('applies edits at the end of the buffer', function() + local edits = { + make_edit(0, 0, 1, 22, {'#include "whatever.h"\r\n#include <algorithm>\r'}); + } + exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-8") + eq({'#include "whatever.h"', '#include <algorithm>'}, buf_lines(1)) + end) + it('applies edits in the middle of the buffer', function() + local edits = { + make_edit(0, 0, 0, 22, {'#include "whatever.h"\r\n#include <algorithm>\r'}); + } + exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-8") + eq({'#include "whatever.h"', '#include <algorithm>', 'Test line two 21 char'}, buf_lines(1)) + end) + end) + describe('with LSP end column out of bounds and start column NOT at 0', function() + it('applies edits at the end of the buffer', function() + local edits = { + make_edit(0, 2, 1, 22, {'#include "whatever.h"\r\n#include <algorithm>\r'}); + } + exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-8") + eq({'Te#include "whatever.h"', '#include <algorithm>'}, buf_lines(1)) + end) + it('applies edits in the middle of the buffer', function() + local edits = { + make_edit(0, 2, 0, 22, {'#include "whatever.h"\r\n#include <algorithm>\r'}); + } + exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-8") + eq({'Te#include "whatever.h"', '#include <algorithm>', 'Test line two 21 char'}, buf_lines(1)) + end) + end) + end) + describe('apply_text_document_edit', function() local target_bufnr local text_document_edit = function(editVersion) @@ -3255,4 +3332,75 @@ describe('LSP', function() eq(result.method, "initialize") end) end) + + describe('handlers', function() + it('handler can return false as response', function() + local result = exec_lua [[ + local uv = vim.loop + local server = uv.new_tcp() + local messages = {} + local responses = {} + server:bind('127.0.0.1', 0) + server:listen(127, function(err) + assert(not err, err) + local socket = uv.new_tcp() + server:accept(socket) + socket:read_start(require('vim.lsp.rpc').create_read_loop(function(body) + local payload = vim.json.decode(body) + if payload.method then + table.insert(messages, payload.method) + if payload.method == 'initialize' then + local msg = vim.json.encode({ + id = payload.id, + jsonrpc = '2.0', + result = { + capabilities = {} + }, + }) + socket:write(table.concat({'Content-Length: ', tostring(#msg), '\r\n\r\n', msg})) + elseif payload.method == 'initialized' then + local msg = vim.json.encode({ + id = 10, + jsonrpc = '2.0', + method = 'dummy', + params = {}, + }) + socket:write(table.concat({'Content-Length: ', tostring(#msg), '\r\n\r\n', msg})) + end + else + table.insert(responses, payload) + socket:close() + end + end)) + end) + local port = server:getsockname().port + local handler_called = false + vim.lsp.handlers['dummy'] = function(err, result) + handler_called = true + return false + end + local client_id = vim.lsp.start({ name = 'dummy', cmd = vim.lsp.rpc.connect('127.0.0.1', port) }) + local client = vim.lsp.get_client_by_id(client_id) + vim.wait(1000, function() return #messages == 2 and handler_called and #responses == 1 end) + server:close() + server:shutdown() + return { + messages = messages, + handler_called = handler_called, + responses = responses } + ]] + local expected = { + messages = { 'initialize', 'initialized' }, + handler_called = true, + responses = { + { + id = 10, + jsonrpc = '2.0', + result = false + } + } + } + eq(expected, result) + end) + end) end) diff --git a/test/functional/shada/shada_spec.lua b/test/functional/shada/shada_spec.lua index d10a2facbb..f5a81eb2ef 100644 --- a/test/functional/shada/shada_spec.lua +++ b/test/functional/shada/shada_spec.lua @@ -238,6 +238,15 @@ describe('ShaDa support code', function() eq('', meths.get_option('shada')) end) + it('setting &shada gives proper error message on missing number', function() + eq([[Vim(set):E526: Missing number after <">: shada="]], + exc_exec([[set shada=\"]])) + for _, c in ipairs({"'", "/", ":", "<", "@", "s"}) do + eq(([[Vim(set):E526: Missing number after <%s>: shada=%s]]):format(c, c), + exc_exec(([[set shada=%s]]):format(c))) + end + end) + it('does not crash when ShaDa file directory is not writable', function() if helpers.pending_win32(pending) then return end diff --git a/test/functional/terminal/ex_terminal_spec.lua b/test/functional/terminal/ex_terminal_spec.lua index 23b69319f0..36f9f90143 100644 --- a/test/functional/terminal/ex_terminal_spec.lua +++ b/test/functional/terminal/ex_terminal_spec.lua @@ -10,6 +10,7 @@ local retry = helpers.retry local ok = helpers.ok local iswin = helpers.iswin local command = helpers.command +local uname = helpers.uname describe(':terminal', function() local screen @@ -45,6 +46,9 @@ describe(':terminal', function() end) it("reads output buffer on terminal reporting #4151", function() + if uname() == 'freebsd' then + pending('Failing FreeBSD test') + end if helpers.pending_win32(pending) then return end if iswin() then feed_command([[terminal powershell -NoProfile -NoLogo -Command Write-Host -NoNewline "\"$([char]27)[6n\""; Start-Sleep -Milliseconds 500 ]]) diff --git a/test/functional/treesitter/highlight_spec.lua b/test/functional/treesitter/highlight_spec.lua index d557b2c012..1684337c3c 100644 --- a/test/functional/treesitter/highlight_spec.lua +++ b/test/functional/treesitter/highlight_spec.lua @@ -605,8 +605,8 @@ describe('treesitter highlighting', function() }} eq({ - {capture='Error', priority='101'}; - {capture='type'}; + {capture='Error', metadata = { priority='101' }}; + {capture='type', metadata = { } }; }, exec_lua [[ return vim.treesitter.get_captures_at_position(0, 0, 2) ]]) end) diff --git a/test/functional/ui/cmdline_spec.lua b/test/functional/ui/cmdline_spec.lua index db13647cc6..92eb853686 100644 --- a/test/functional/ui/cmdline_spec.lua +++ b/test/functional/ui/cmdline_spec.lua @@ -934,6 +934,15 @@ describe('cmdheight=0', function() before_each(function() clear() screen = Screen.new(25, 5) + screen:set_default_attr_ids { + [1] = {bold = true, foreground = Screen.colors.Blue}; + [2] = {bold = true, reverse = true}; + [3] = {bold = true}; + [4] = {foreground = Screen.colors.White, background = Screen.colors.Red}; + [5] = {foreground = Screen.colors.SeaGreen4, bold = true}; + [6] = {reverse = true}; + [7] = {background = Screen.colors.Yellow}; + } screen:attach() end) @@ -941,9 +950,9 @@ describe('cmdheight=0', function() command("set cmdheight=1 noruler laststatus=2") screen:expect{grid=[[ ^ | - ~ | - ~ | - [No Name] | + {1:~ }| + {1:~ }| + {2:[No Name] }| | ]]} end) @@ -952,10 +961,10 @@ describe('cmdheight=0', function() command("set cmdheight=0 noruler laststatus=2") screen:expect{grid=[[ ^ | - ~ | - ~ | - ~ | - [No Name] | + {1:~ }| + {1:~ }| + {1:~ }| + {2:[No Name] }| ]]} end) @@ -963,10 +972,10 @@ describe('cmdheight=0', function() command("set cmdheight=0 ruler laststatus=0") screen:expect{grid=[[ ^ | - ~ | - ~ | - ~ | - ~ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| ]]} end) @@ -975,10 +984,10 @@ describe('cmdheight=0', function() feed('i') screen:expect{grid=[[ ^ | - ~ | - ~ | - ~ | - ~ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| ]], showmode={}} feed('<Esc>') eq(0, eval('&cmdheight')) @@ -989,10 +998,10 @@ describe('cmdheight=0', function() feed('i') screen:expect{grid=[[ ^ | - ~ | - ~ | - ~ | - ~ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| ]], showmode={}} feed('<Esc>') eq(0, eval('&cmdheight')) @@ -1003,10 +1012,10 @@ describe('cmdheight=0', function() feed('i') screen:expect{grid=[[ ^ | - ~ | - ~ | - ~ | - -- INSERT -- | + {1:~ }| + {1:~ }| + {1:~ }| + {3:-- INSERT --} | ]]} feed('<Esc>') eq(1, eval('&cmdheight')) @@ -1017,19 +1026,19 @@ describe('cmdheight=0', function() feed(':') screen:expect{grid=[[ | - ~ | - ~ | - ~ | + {1:~ }| + {1:~ }| + {1:~ }| :^ | ]]} - eq(1, eval('&cmdheight')) + eq(0, eval('&cmdheight')) feed('<cr>') screen:expect{grid=[[ ^ | - ~ | - ~ | - ~ | - ~ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| ]], showmode={}} eq(0, eval('&cmdheight')) end) @@ -1039,19 +1048,19 @@ describe('cmdheight=0', function() feed(':call input("foo >")<cr>') screen:expect{grid=[[ | - ~ | - ~ | - ~ | + {1:~ }| + {2: }| + :call input("foo >") | foo >^ | ]]} - eq(1, eval('&cmdheight')) + eq(0, eval('&cmdheight')) feed('<cr>') screen:expect{grid=[[ ^ | - ~ | - ~ | - ~ | - ~ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| ]], showmode={}} eq(0, eval('&cmdheight')) end) @@ -1060,35 +1069,35 @@ describe('cmdheight=0', function() command("set cmdheight=0 noruler laststatus=3 winbar=foo") feed(':split<CR>') screen:expect{grid=[[ - foo | - | - E36: Not enough room | - Press ENTER or type comma| - nd to continue^ | + {2: }| + :split | + {4:E36: Not enough room} | + {5:Press ENTER or type comma}| + {5:nd to continue}^ | ]]} feed('<CR>') screen:expect{grid=[[ - foo | + {3:foo }| ^ | - ~ | - ~ | - [No Name] | + {1:~ }| + {1:~ }| + {2:[No Name] }| ]]} feed(':') screen:expect{grid=[[ - foo | + {3:foo }| | - ~ | - [No Name] | + {1:~ }| + {1:~ }| :^ | ]]} feed('<Esc>') screen:expect{grid=[[ - foo | + {3:foo }| ^ | - ~ | - ~ | - [No Name] | + {1:~ }| + {1:~ }| + {2:[No Name] }| ]], showmode={}} eq(0, eval('&cmdheight')) @@ -1100,19 +1109,19 @@ describe('cmdheight=0', function() feed('qq') screen:expect{grid=[[ ^ | - ~ | - ~ | - ~ | - recording @q | - ]], showmode={}} + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ]]} feed('q') screen:expect{grid=[[ ^ | - ~ | - ~ | - ~ | - ~ | - ]], showmode={}} + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ]], unchanged=true} end) it("when substitute text", function() @@ -1120,28 +1129,28 @@ describe('cmdheight=0', function() feed('ifoo<ESC>') screen:expect{grid=[[ fo^o | - ~ | - ~ | - ~ | - [No Name] [+] | + {1:~ }| + {1:~ }| + {1:~ }| + {2:[No Name] [+] }| ]]} feed(':%s/foo/bar/gc<CR>') screen:expect{grid=[[ - foo | - ~ | - ~ | - [No Name] [+] | - replace wi...q/l/^E/^Y)?^ | + {6:foo} | + {1:~ }| + {1:~ }| + {1:~ }| + {5:replace wi...q/l/^E/^Y)?}^ | ]]} feed('y') screen:expect{grid=[[ ^bar | - ~ | - ~ | - ~ | - [No Name] [+] | + {1:~ }| + {1:~ }| + {1:~ }| + {2:[No Name] [+] }| ]]} assert_alive() @@ -1152,4 +1161,26 @@ describe('cmdheight=0', function() feed('<C-w>+') eq(0, eval('&cmdheight')) end) + + it("with non-silent mappings with cmdline", function() + command("set cmdheight=0") + command("map <f3> :nohlsearch<cr>") + feed('iaabbaa<esc>/aa<cr>') + screen:expect{grid=[[ + {7:^aa}bb{7:aa} | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ]]} + + feed('<f3>') + screen:expect{grid=[[ + ^aabbaa | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ]]} + end) end) diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua index db5a775632..eff6fe6d23 100644 --- a/test/functional/ui/decorations_spec.lua +++ b/test/functional/ui/decorations_spec.lua @@ -686,15 +686,15 @@ end]] screen:expect{grid=[[ {5:^for} _,item {5:in} {6:ipairs}(items) {5:do} | - {5:local} text, hl_id_cell, count = unpack(item) | - {5:if} hl_id_cell ~= {13:nil} {5:then} | - hl_id = hl_id_cell | + {5:local} text, hl_id_cell, count {5:=} unpack(item) | + {5:if} hl_id_cell {5:~=} {13:nil} {5:then} | + hl_id {5:=} hl_id_cell | {5:end} | - {5:for} _ = {13:1}, (count {5:or} {13:1}) {5:do} | - {5:local} cell = line[colpos] | - cell.text = text | - cell.hl_id = hl_id | - colpos = colpos+{13:1} | + {5:for} _ {5:=} {13:1}, (count {5:or} {13:1}) {5:do} | + {5:local} cell {5:=} line[colpos] | + cell.text {5:=} text | + cell.hl_id {5:=} hl_id | + colpos {5:=} colpos{5:+}{13:1} | {5:end} | {5:end} | {1:~ }| @@ -713,15 +713,15 @@ end]] screen:expect{grid=[[ {5:^for} _,item {5:in} {6:ipairs}(items) {5:do} | - {5:l}{8:blen}{7:dy}{10:e}{7:text}{10:h}{7:-}{10:_}{7:here}ell, count = unpack(item) | - {5:i}{12:c}{11:ombining color} {13:nil} {5:then} | + {5:l}{8:blen}{7:dy}{10:e}{7:text}{10:h}{7:-}{10:_}{7:here}ell, count {5:=} unpack(item) | + {5:i}{12:c}{11:ombining col}{12:or} {13:nil} {5:then} | {11:replacing color}d_cell | {5:e}{8:bl}{7:endy}{10: }{7:text}{10: }{7:-}{10: }{7:here} | - {5:f}{12:co}{11:mbini}{16:n}{11:g color}t {5:or} {13:1}) {5:do} | + {5:f}{12:co}{11:mbi}{12:n}{11:i}{16:n}{11:g color}t {5:or} {13:1}) {5:do} | {11:replacing color} line[colpos] | - cell.text = text | - cell.hl_id = hl_id | - colpos = colpos+{13:1} | + cell.text {5:=} text | + cell.hl_id {5:=} hl_id | + colpos {5:=} colpos{5:+}{13:1} | {5:end} | {5:end} | {1:~ }| @@ -732,15 +732,15 @@ end]] feed 'V5G' screen:expect{grid=[[ {17:for}{18: _,item }{17:in}{18: }{19:ipairs}{18:(items) }{17:do} | - {18: }{17:l}{20:blen}{21:dy}{22:e}{21:text}{22:h}{21:-}{22:_}{21:here}{18:ell, count = unpack(item)} | - {18: }{17:i}{12:c}{11:ombining color}{18: }{23:nil}{18: }{17:then} | + {18: }{17:l}{20:blen}{21:dy}{22:e}{21:text}{22:h}{21:-}{22:_}{21:here}{18:ell, count }{17:=}{18: unpack(item)} | + {18: }{17:i}{12:c}{11:ombining col}{12:or}{18: }{23:nil}{18: }{17:then} | {18: }{11:replacing color}{18:d_cell} | {18: }{5:^e}{17:nd} | - {5:f}{12:co}{11:mbini}{16:n}{11:g color}t {5:or} {13:1}) {5:do} | + {5:f}{12:co}{11:mbi}{12:n}{11:i}{16:n}{11:g color}t {5:or} {13:1}) {5:do} | {11:replacing color} line[colpos] | - cell.text = text | - cell.hl_id = hl_id | - colpos = colpos+{13:1} | + cell.text {5:=} text | + cell.hl_id {5:=} hl_id | + colpos {5:=} colpos{5:+}{13:1} | {5:end} | {5:end} | {1:~ }| @@ -751,15 +751,15 @@ end]] feed 'jj' screen:expect{grid=[[ {17:for}{18: _,item }{17:in}{18: }{19:ipairs}{18:(items) }{17:do} | - {18: }{17:l}{20:blen}{21:dy}{22:e}{21:text}{22:h}{21:-}{22:_}{21:here}{18:ell, count = unpack(item)} | - {18: }{17:i}{12:c}{11:ombining color}{18: }{23:nil}{18: }{17:then} | + {18: }{17:l}{20:blen}{21:dy}{22:e}{21:text}{22:h}{21:-}{22:_}{21:here}{18:ell, count }{17:=}{18: unpack(item)} | + {18: }{17:i}{12:c}{11:ombining col}{12:or}{18: }{23:nil}{18: }{17:then} | {18: }{11:replacing color}{18:d_cell} | {18: }{17:end} | - {18: }{17:for}{18: _ = }{23:1}{18:, (count }{17:or}{18: }{23:1}{18:) }{17:do} | - {18: }^ {18: }{17:local}{18: cell = line[colpos]} | - cell.text = text | - cell.hl_id = hl_id | - colpos = colpos+{13:1} | + {18: }{17:for}{18: _ }{17:=}{18: }{23:1}{18:, (count }{17:or}{18: }{23:1}{18:) }{17:do} | + {18: }^ {18: }{17:local}{18: cell }{17:=}{18: line[colpos]} | + cell.text {5:=} text | + cell.hl_id {5:=} hl_id | + colpos {5:=} colpos{5:+}{13:1} | {5:end} | {5:end} | {1:~ }| diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index 5967b630f6..5e819f14a3 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -596,6 +596,11 @@ describe('float window', function() meths.buf_delete(old_buf, {force = true}) eq(old_win, curwin().id) end) + it('if called from non-floating window in another tabpage', function() + command('tab split') + eq(3, #meths.list_tabpages()) + meths.buf_delete(old_buf, {force = true}) + end) it('if called from floating window with the same buffer', function() meths.set_current_win(same_buf_float) command('autocmd WinLeave * let g:win_leave = nvim_get_current_win()') @@ -8147,6 +8152,366 @@ describe('float window', function() ]]} end end) + + it('it can be resized with messages and cmdheight=0 #20106', function() + screen:try_resize(40,9) + command 'set cmdheight=0' + local buf = meths.create_buf(false,true) + local win = meths.open_win(buf, false, {relative='editor', width=40, height=4, anchor='SW', row=9, col=0, style='minimal', border="single", noautocmd=true}) + + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + ## grid 2 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + ## grid 5 + {5:┌────────────────────────────────────────┐}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:└────────────────────────────────────────┘}| + ]], float_pos={ + [5] = {{id = 1002}, "SW", 1, 9, 0, true, 50}; + }, win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + }} + else + screen:expect{grid=[[ + ^ | + {0:~ }| + {0:~ }| + {5:┌──────────────────────────────────────┐}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:└──────────────────────────────────────┘}| + ]]} + end + + exec_lua([[ + local win = ... + vim.api.nvim_win_set_height(win, 2) + vim.api.nvim_echo({ { "" } }, false, {}) + ]], win) + + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + ## grid 2 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + ## grid 5 + {5:┌────────────────────────────────────────┐}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:└────────────────────────────────────────┘}| + ]], float_pos={ + [5] = {{id = 1002}, "SW", 1, 9, 0, true, 50}; + }, win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + }} + else + screen:expect{grid=[[ + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {5:┌──────────────────────────────────────┐}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:└──────────────────────────────────────┘}| + ]]} + + end + + meths.win_close(win, true) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + ## grid 2 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + }} + else + screen:expect{grid=[[ + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ]]} + end + end) + + it('it can be resized with messages and cmdheight=1', function() + screen:try_resize(40,9) + local buf = meths.create_buf(false,true) + local win = meths.open_win(buf, false, {relative='editor', width=40, height=4, anchor='SW', row=8, col=0, style='minimal', border="single", noautocmd=true}) + + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ## grid 5 + {5:┌────────────────────────────────────────┐}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:└────────────────────────────────────────┘}| + ]], float_pos={ + [5] = {{id = 1002}, "SW", 1, 8, 0, true, 50}; + }, win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + }} + else + screen:expect{grid=[[ + ^ | + {0:~ }| + {5:┌──────────────────────────────────────┐}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:└──────────────────────────────────────┘}| + | + ]]} + end + + exec_lua([[ + -- echo prompt is blocking, so schedule + local win = ... + vim.schedule(function() + vim.api.nvim_win_set_height(win, 2) + vim.api.nvim_echo({ { "\n" } }, false, {}) + end) + ]], win) + + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + {8:Press ENTER or type command to continue}^ | + ## grid 5 + {5:┌────────────────────────────────────────┐}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:└────────────────────────────────────────┘}| + ]], float_pos={ + [5] = {{id = 1002}, "SW", 1, 8, 0, true, 50}; + }, win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + }} + else + screen:expect{grid=[[ + | + {0:~ }| + {5:┌──────────────────────────────────────┐}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {4: }| + | + {8:Press ENTER or type command to continue}^ | + ]]} + end + + feed('<cr>') + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ## grid 5 + {5:┌────────────────────────────────────────┐}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:└────────────────────────────────────────┘}| + ]], float_pos={ + [5] = {{id = 1002}, "SW", 1, 8, 0, true, 50}; + }, win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + }} + else + screen:expect{grid=[[ + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {5:┌──────────────────────────────────────┐}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:└──────────────────────────────────────┘}| + | + ]]} + end + + meths.win_close(win, true) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + }} + + else + screen:expect{grid=[[ + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + | + ]]} + end + end) end describe('with ext_multigrid', function() diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua index 9ca4673efe..49b3c7a655 100644 --- a/test/functional/ui/inccommand_spec.lua +++ b/test/functional/ui/inccommand_spec.lua @@ -1190,6 +1190,8 @@ describe(":substitute, inccommand=split", function() end) it("deactivates if 'redrawtime' is exceeded #5602", function() + -- prevent redraws from 'incsearch' + meths.set_option('incsearch', false) -- Assert that 'inccommand' is ENABLED initially. eq("split", eval("&inccommand")) -- Set 'redrawtime' to minimal value, to ensure timeout is triggered. @@ -2972,6 +2974,59 @@ it(':substitute with inccommand, does not crash if range contains invalid marks' ]]) end) +it(':substitute with inccommand, no unnecessary redraw if preview is not shown', function() + local screen = Screen.new(60, 6) + clear() + common_setup(screen, 'split', 'test') + feed(':ls<CR>') + screen:expect([[ + test | + {15:~ }| + {11: }| + :ls | + 1 %a + "[No Name]" line 1 | + {13:Press ENTER or type command to continue}^ | + ]]) + feed(':s') + -- no unnecessary redraw, so messages are still shown + screen:expect([[ + test | + {15:~ }| + {11: }| + :ls | + 1 %a + "[No Name]" line 1 | + :s^ | + ]]) + feed('o') + screen:expect([[ + test | + {15:~ }| + {11: }| + :ls | + 1 %a + "[No Name]" line 1 | + :so^ | + ]]) + feed('<BS>') + screen:expect([[ + test | + {15:~ }| + {11: }| + :ls | + 1 %a + "[No Name]" line 1 | + :s^ | + ]]) + feed('/test') + -- now inccommand is shown, so screen is redrawn + screen:expect([[ + {12:test} | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + :s/test^ | + ]]) +end) + it(":substitute doesn't crash with inccommand, if undo is empty #12932", function() local screen = Screen.new(10,5) clear() diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua index 522c9ccba2..6b8fa99b38 100644 --- a/test/functional/ui/messages_spec.lua +++ b/test/functional/ui/messages_spec.lua @@ -2020,4 +2020,55 @@ aliquip ex ea commodo consequat.]]) | ]]} end) + + it('with cmdheight=0 does not crash with g<', function() + command('set cmdheight=0') + feed(':ls<cr>') + screen:expect{grid=[[ + | + {1:~ }| + {12: }| + :ls | + 1 %a "[No Name]" | + line 1 | + {4:Press ENTER or type command to cont}| + {4:inue}^ | + ]]} + + feed('<cr>') + screen:expect{grid=[[ + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ]]} + + feed('g<lt>') + screen:expect{grid=[[ + | + {1:~ }| + {12: }| + :ls | + 1 %a "[No Name]" | + line 1 | + {4:Press ENTER or type command to cont}| + {4:inue}^ | + ]]} + + feed('<cr>') + screen:expect{grid=[[ + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ]]} + end) end) diff --git a/test/functional/ui/syntax_conceal_spec.lua b/test/functional/ui/syntax_conceal_spec.lua index f790597140..e8798ddd93 100644 --- a/test/functional/ui/syntax_conceal_spec.lua +++ b/test/functional/ui/syntax_conceal_spec.lua @@ -947,7 +947,7 @@ describe('Screen', function() {0:~ }| | ]]} - eq({{2, 0, {{'c', 0, 3}}}}, grid_lines) + eq({{2, 0, {{'c', 0, 3}, {' ', 0, 50}}}, {3, 0, {{' ', 0, 53}}}}, grid_lines) end) it('K_EVENT should not cause extra redraws with concealcursor #13196', function() @@ -994,10 +994,11 @@ describe('Screen', function() {0:~ }| | ]]} - eq({{2, 0, {{'c', 0, 3}}}}, grid_lines) + eq({{2, 0, {{'c', 0, 3}, {' ', 0, 50}}}}, grid_lines) + grid_lines = {} poke_eventloop() -- causes K_EVENT key screen:expect_unchanged() - eq({{2, 0, {{'c', 0, 3}}}}, grid_lines) + eq({}, grid_lines) -- no redraw was done end) -- Copy of Test_cursor_column_in_concealed_line_after_window_scroll in diff --git a/test/functional/vimscript/executable_spec.lua b/test/functional/vimscript/executable_spec.lua index b4162b2336..b49eb09512 100644 --- a/test/functional/vimscript/executable_spec.lua +++ b/test/functional/vimscript/executable_spec.lua @@ -34,11 +34,13 @@ describe('executable()', function() it('fails for invalid values', function() for _, input in ipairs({'v:null', 'v:true', 'v:false', '{}', '[]'}) do - eq('Vim(call):E928: String required', exc_exec('call executable('..input..')')) + eq('Vim(call):E1174: String required for argument 1', + exc_exec('call executable('..input..')')) end command('let $PATH = fnamemodify("./test/functional/fixtures/bin", ":p")') for _, input in ipairs({'v:null', 'v:true', 'v:false'}) do - eq('Vim(call):E928: String required', exc_exec('call executable('..input..')')) + eq('Vim(call):E1174: String required for argument 1', + exc_exec('call executable('..input..')')) end end) diff --git a/test/functional/vimscript/exepath_spec.lua b/test/functional/vimscript/exepath_spec.lua index bbca954511..439dd96fcd 100644 --- a/test/functional/vimscript/exepath_spec.lua +++ b/test/functional/vimscript/exepath_spec.lua @@ -21,12 +21,12 @@ describe('exepath()', function() it('fails for invalid values', function() for _, input in ipairs({'v:null', 'v:true', 'v:false', '{}', '[]'}) do - eq('Vim(call):E928: String required', exc_exec('call exepath('..input..')')) + eq('Vim(call):E1174: String required for argument 1', exc_exec('call exepath('..input..')')) end - eq('Vim(call):E1142: Non-empty string required', exc_exec('call exepath("")')) + eq('Vim(call):E1142: Non-empty string required for argument 1', exc_exec('call exepath("")')) command('let $PATH = fnamemodify("./test/functional/fixtures/bin", ":p")') for _, input in ipairs({'v:null', 'v:true', 'v:false'}) do - eq('Vim(call):E928: String required', exc_exec('call exepath('..input..')')) + eq('Vim(call):E1174: String required for argument 1', exc_exec('call exepath('..input..')')) end end) diff --git a/test/functional/vimscript/timer_spec.lua b/test/functional/vimscript/timer_spec.lua index 5463cfb234..1818a71ea2 100644 --- a/test/functional/vimscript/timer_spec.lua +++ b/test/functional/vimscript/timer_spec.lua @@ -131,34 +131,34 @@ describe('timers', function() nvim_async("command", "call timer_start("..load_adjust(100)..", 'AddItem', {'repeat': -1})") screen:expect([[ - ITEM 1 | + ^ITEM 1 | ITEM 2 | {1:~ }| {1:~ }| {1:~ }| - ^ | + | ]]) nvim_async("command", "let g:cont = 1") screen:expect([[ - ITEM 1 | + ^ITEM 1 | ITEM 2 | ITEM 3 | {1:~ }| {1:~ }| - ^ | + | ]]) feed("3") eq(51, eval("g:c2")) - screen:expect([[ + screen:expect{grid=[[ ^ITEM 1 | ITEM 2 | ITEM 3 | {1:~ }| {1:~ }| | - ]]) + ]], unchanged=true} end) it('can be stopped', function() diff --git a/test/helpers.lua b/test/helpers.lua index 7ec9beea92..a7eda60f87 100644 --- a/test/helpers.lua +++ b/test/helpers.lua @@ -1,4 +1,4 @@ -require('vim.compat') +require('test.compat') local shared = require('vim.shared') local assert = require('luassert') local luv = require('luv') @@ -790,10 +790,9 @@ end function module.isCI(name) local any = (name == nil) - assert(any or name == 'sourcehut' or name == 'github') - local sh = ((any or name == 'sourcehut') and nil ~= os.getenv('SOURCEHUT')) + assert(any or name == 'github') local gh = ((any or name == 'github') and nil ~= os.getenv('GITHUB_ACTIONS')) - return sh or gh + return gh end |