aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/labeler.yml2
-rw-r--r--.github/scripts/reviews.js (renamed from ci/reviews.js)8
-rw-r--r--.github/workflows/ci.yml183
-rwxr-xr-x.github/workflows/env.sh2
-rw-r--r--.github/workflows/labeler.yml6
-rw-r--r--.github/workflows/notes.md42
-rw-r--r--.github/workflows/release.yml34
-rw-r--r--.github/workflows/reviews.yml4
-rw-r--r--CMakeLists.txt16
-rw-r--r--LICENSE.txt (renamed from LICENSE)0
-rwxr-xr-xci/before_cache.sh4
-rw-r--r--ci/build.ps145
-rw-r--r--ci/common/suite.sh25
-rwxr-xr-xci/run_lint.sh36
-rwxr-xr-xci/run_tests.sh47
-rw-r--r--cmake/RunTests.cmake4
-rw-r--r--packaging/CMakeLists.txt78
-rw-r--r--packaging/logo.icnsbin0 -> 637562 bytes
-rw-r--r--packaging/logo.icobin0 -> 3518 bytes
-rw-r--r--packaging/logo.svg1
-rw-r--r--runtime/autoload/dist/ft.vim4
-rw-r--r--runtime/doc/api.txt25
-rw-r--r--runtime/doc/autocmd.txt15
-rw-r--r--runtime/doc/builtin.txt30
-rw-r--r--runtime/doc/editing.txt6
-rw-r--r--runtime/doc/index.txt1
-rw-r--r--runtime/doc/lua.txt32
-rw-r--r--runtime/doc/map.txt4
-rw-r--r--runtime/doc/options.txt8
-rw-r--r--runtime/doc/quickref.txt1
-rw-r--r--runtime/doc/repeat.txt17
-rw-r--r--runtime/doc/usr_04.txt8
-rw-r--r--runtime/doc/usr_07.txt4
-rw-r--r--runtime/doc/usr_10.txt4
-rw-r--r--runtime/doc/vim_diff.txt6
-rw-r--r--runtime/filetype.lua7
-rw-r--r--runtime/filetype.vim15
-rw-r--r--runtime/lua/vim/diagnostic.lua5
-rw-r--r--runtime/lua/vim/filetype.lua5
-rw-r--r--runtime/lua/vim/highlight.lua105
-rw-r--r--runtime/lua/vim/lsp/handlers.lua4
-rw-r--r--runtime/lua/vim/lsp/util.lua4
-rw-r--r--runtime/lua/vim/treesitter/highlighter.lua18
-rw-r--r--runtime/syntax/structurizr.vim9
-rw-r--r--src/mpack/lmpack.c2
-rw-r--r--src/nvim/api/buffer.c119
-rw-r--r--src/nvim/api/keysets.lua1
-rw-r--r--src/nvim/api/private/helpers.c52
-rw-r--r--src/nvim/api/vim.c14
-rw-r--r--src/nvim/auevents.lua5
-rw-r--r--src/nvim/autocmd.c13
-rw-r--r--src/nvim/buffer.c23
-rw-r--r--src/nvim/buffer_defs.h2
-rw-r--r--src/nvim/change.c9
-rw-r--r--src/nvim/charset.c4
-rw-r--r--src/nvim/eval/funcs.c2
-rw-r--r--src/nvim/ex_docmd.c60
-rw-r--r--src/nvim/file_search.c21
-rw-r--r--src/nvim/getchar.c31
-rw-r--r--src/nvim/globals.h2
-rw-r--r--src/nvim/highlight.c62
-rw-r--r--src/nvim/lua/executor.c24
-rw-r--r--src/nvim/mbyte.c6
-rw-r--r--src/nvim/normal.c17
-rw-r--r--src/nvim/ops.c90
-rw-r--r--src/nvim/option.c4
-rw-r--r--src/nvim/path.c3
-rw-r--r--src/nvim/screen.c33
-rw-r--r--src/nvim/syntax.c42
-rw-r--r--src/nvim/testdir/test_alot.vim3
-rw-r--r--src/nvim/testdir/test_autochdir.vim10
-rw-r--r--src/nvim/testdir/test_autocmd.vim26
-rw-r--r--src/nvim/testdir/test_breakindent.vim2
-rw-r--r--src/nvim/testdir/test_cindent.vim9
-rw-r--r--src/nvim/testdir/test_digraph.vim4
-rw-r--r--src/nvim/testdir/test_edit.vim2
-rw-r--r--src/nvim/testdir/test_excmd.vim14
-rw-r--r--src/nvim/testdir/test_filetype.vim42
-rw-r--r--src/nvim/testdir/test_functions.vim4
-rw-r--r--src/nvim/testdir/test_normal.vim29
-rw-r--r--src/nvim/testdir/test_profile.vim31
-rw-r--r--src/nvim/testdir/test_put.vim44
-rw-r--r--src/nvim/testdir/test_quickfix.vim2
-rw-r--r--src/nvim/testdir/test_registers.vim2
-rw-r--r--src/nvim/testdir/test_stat.vim2
-rw-r--r--src/nvim/testdir/test_suspend.vim4
-rw-r--r--src/nvim/testdir/test_system.vim26
-rw-r--r--src/nvim/testdir/test_tabline.vim11
-rw-r--r--src/nvim/testdir/test_vimscript.vim5
-rw-r--r--src/nvim/testdir/test_visual.vim15
-rw-r--r--src/nvim/window.c29
-rw-r--r--test/functional/api/buffer_spec.lua35
-rw-r--r--test/functional/api/buffer_updates_spec.lua4
-rw-r--r--test/functional/api/command_spec.lua22
-rw-r--r--test/functional/api/highlight_spec.lua52
-rw-r--r--test/functional/api/keymap_spec.lua18
-rw-r--r--test/functional/api/server_requests_spec.lua6
-rw-r--r--test/functional/api/vim_spec.lua9
-rw-r--r--test/functional/autocmd/dirchanged_spec.lua128
-rw-r--r--test/functional/core/job_spec.lua7
-rw-r--r--test/functional/core/startup_spec.lua4
-rw-r--r--test/functional/ex_cmds/ctrl_c_spec.lua3
-rw-r--r--test/functional/ex_cmds/mksession_spec.lua1
-rw-r--r--test/functional/legacy/excmd_spec.lua32
-rw-r--r--test/functional/legacy/put_spec.lua45
-rw-r--r--test/functional/terminal/buffer_spec.lua1
-rw-r--r--test/functional/terminal/cursor_spec.lua3
-rw-r--r--test/functional/terminal/edit_spec.lua1
-rw-r--r--test/functional/terminal/ex_terminal_spec.lua7
-rw-r--r--test/functional/terminal/highlight_spec.lua1
-rw-r--r--test/functional/terminal/scrollback_spec.lua2
-rw-r--r--test/functional/terminal/window_spec.lua1
-rw-r--r--test/functional/treesitter/highlight_spec.lua89
-rw-r--r--test/functional/ui/hlstate_spec.lua2
-rw-r--r--test/functional/ui/messages_spec.lua1
-rw-r--r--test/functional/ui/output_spec.lua1
-rw-r--r--test/functional/ui/sign_spec.lua6
-rw-r--r--test/helpers.lua6
-rw-r--r--third-party/CMakeLists.txt8
-rw-r--r--third-party/cmake/BuildGettext.cmake1
-rw-r--r--third-party/cmake/BuildGperf.cmake1
-rw-r--r--third-party/cmake/BuildLibiconv.cmake1
-rw-r--r--third-party/cmake/BuildLibtermkey.cmake1
-rw-r--r--third-party/cmake/BuildLibuv.cmake5
-rw-r--r--third-party/cmake/BuildLibvterm.cmake1
-rw-r--r--third-party/cmake/BuildLuv.cmake1
-rw-r--r--third-party/cmake/BuildMsgpack.cmake1
-rw-r--r--third-party/cmake/BuildTreesitter.cmake1
-rw-r--r--third-party/cmake/BuildTreesitterParsers.cmake1
-rw-r--r--third-party/cmake/BuildUnibilium.cmake1
-rw-r--r--third-party/patches/libuv-disable-typedef-MinGW.patch19
131 files changed, 1801 insertions, 559 deletions
diff --git a/.github/labeler.yml b/.github/labeler.yml
index 3e19c1d501..e20a2577cd 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -51,7 +51,7 @@
- "**/CMakeLists.txt"
- "**/*.cmake"
-"tests":
+"test":
- all: ["test/**/*"]
"ci":
diff --git a/ci/reviews.js b/.github/scripts/reviews.js
index 3e8e07976a..25ef08be36 100644
--- a/ci/reviews.js
+++ b/.github/scripts/reviews.js
@@ -17,10 +17,18 @@ module.exports = async ({github, context}) => {
reviewers.add("jamessan")
}
+ if (labels.includes('column')) {
+ reviewers.add("lewis6991")
+ }
+
if (labels.includes('diagnostic')) {
reviewers.add("gpanders")
}
+ if (labels.includes('diff')) {
+ reviewers.add("lewis6991")
+ }
+
if (labels.includes('distribution')) {
reviewers.add("jamessan")
}
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b650c5dd85..94da9ec6f0 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -9,6 +9,8 @@ on:
branches:
- 'master'
- 'release-[0-9]+.[0-9]+'
+ paths-ignore:
+ - 'runtime/doc/*'
# Cancel any in-progress CI runs for a PR if it is updated
concurrency:
@@ -29,29 +31,68 @@ jobs:
- name: Install apt packages
run: |
+ sudo add-apt-repository ppa:neovim-ppa/stable
sudo apt-get update
- sudo apt-get install -y autoconf automake build-essential ccache cmake cpanminus gettext gperf language-pack-tr libtool-bin locales ninja-build pkg-config python3 python3-pip python3-setuptools unzip flake8
-
- - name: Setup interpreter packages
- run: |
- ./ci/install.sh
-
- - name: Cache dependencies
+ sudo apt-get install -y \
+ autoconf \
+ automake \
+ build-essential \
+ ccache \
+ cmake \
+ flake8 \
+ gettext \
+ gperf \
+ libluajit-5.1-dev \
+ libmsgpack-dev \
+ libtermkey-dev \
+ libtool-bin \
+ libtree-sitter-dev \
+ libunibilium-dev \
+ libuv1-dev \
+ libvterm-dev \
+ locales \
+ lua-busted \
+ lua-check \
+ lua-filesystem \
+ lua-inspect \
+ lua-lpeg \
+ lua-luv-dev \
+ lua-nvim \
+ luajit \
+ ninja-build \
+ pkg-config
+
+ - name: Cache artifacts
uses: actions/cache@v2
with:
path: |
- ${{ env.CACHE_NVIM_DEPS_DIR }}
~/.ccache
- key: ${{ matrix.runner }}-lint-${{ matrix.cc }}-${{ hashFiles('cmake/*', 'third-party/**', '**/CMakeLists.txt') }}-${{ github.base_ref }}
+ key: lint-${{ hashFiles('cmake/*', '**/CMakeLists.txt', '!third-party/**CMakeLists.txt') }}-${{ github.base_ref }}
- - name: Build third-party
- run: ./ci/before_script.sh
+ - name: Build nvim
+ run: ./ci/run_tests.sh build
+
+ - if: "!cancelled()"
+ name: clint
+ run: ./ci/run_lint.sh clint
+
+ - if: "!cancelled()"
+ name: lualint
+ run: ./ci/run_lint.sh lualint
- - name: Run lint
- run: ./ci/script.sh
+ - if: "!cancelled()"
+ name: pylint
+ run: ./ci/run_lint.sh pylint
+
+ - if: "!cancelled()"
+ name: shlint
+ run: ./ci/run_lint.sh shlint
+
+ - if: "!cancelled()"
+ name: single-includes
+ run: ./ci/run_lint.sh single-includes
- name: Cache dependencies
- if: ${{ success() }}
run: ./ci/before_cache.sh
unixish:
@@ -74,6 +115,11 @@ jobs:
- cc: clang
runner: macos-11.0
os: osx
+ - flavor: functionaltest-lua
+ cc: gcc
+ runner: ubuntu-20.04
+ os: linux
+ cmake: minimum_required
runs-on: ${{ matrix.runner }}
timeout-minutes: 45
if: github.event.pull_request.draft == false
@@ -92,6 +138,24 @@ jobs:
sudo apt-get update
sudo apt-get install -y autoconf automake build-essential ccache cmake cpanminus cscope gcc-multilib gdb gettext gperf language-pack-tr libtool-bin locales ninja-build pkg-config python3 python3-pip python3-setuptools unzip valgrind xclip
+ - name: Install minimum required version of cmake
+ if: matrix.cmake == 'minimum_required'
+ env:
+ CMAKE_URL: 'https://cmake.org/files/v3.10/cmake-3.10.0-Linux-x86_64.sh'
+ CMAKE_VERSION: '3.10.0'
+ shell: bash
+ run: |
+ curl --retry 5 --silent --show-error --fail -o /tmp/cmake-installer.sh "$CMAKE_URL"
+ mkdir -p "$HOME/.local/bin" /opt/cmake-custom
+ chmod a+x /tmp/cmake-installer.sh
+ /tmp/cmake-installer.sh --prefix=/opt/cmake-custom --skip-license
+ ln -sfn /opt/cmake-custom/bin/cmake "$HOME/.local/bin/cmake"
+ cmake_version="$(cmake --version | head -1)"
+ echo "$cmake_version" | grep -qF "cmake version $CMAKE_VERSION" || {
+ echo "Unexpected CMake version: $cmake_version"
+ exit 1
+ }
+
- name: Install new clang
if: matrix.flavor == 'asan' || matrix.flavor == 'tsan'
run: |
@@ -107,8 +171,7 @@ jobs:
brew install automake ccache perl cpanminus ninja
- name: Setup interpreter packages
- run: |
- ./ci/install.sh
+ run: ./ci/install.sh
- name: Cache dependencies
uses: actions/cache@v2
@@ -121,15 +184,30 @@ jobs:
- name: Build third-party
run: ./ci/before_script.sh
- - name: Build and test
- run: ./ci/script.sh
+ - name: Build
+ run: ./ci/run_tests.sh build
+
+ - if: matrix.flavor != 'tsan' && matrix.flavor != 'functionaltest-lua' && !cancelled()
+ name: Unittests
+ run: ./ci/run_tests.sh unittests
+
+ - if: matrix.flavor != 'tsan' && !cancelled()
+ name: Functionaltests
+ run: ./ci/run_tests.sh functionaltests
+
+ - if: "!cancelled()"
+ name: Oldtests
+ run: ./ci/run_tests.sh oldtests
+
+ - if: "!cancelled()"
+ name: Install nvim
+ run: ./ci/run_tests.sh install_nvim
- name: Cache dependencies
- if: ${{ success() }}
run: ./ci/before_cache.sh
windows:
- runs-on: windows-2016
+ runs-on: windows-2019
if: github.event.pull_request.draft == false
env:
DEPS_BUILD_DIR: ${{ format('{0}/nvim-deps', github.workspace) }}
@@ -152,68 +230,3 @@ jobs:
run: powershell ci\build.ps1
env:
CONFIGURATION: ${{ matrix.config }}
-
- functionaltest:
- name: ${{ matrix.runner }} ${{ matrix.flavor }} (cc=${{ matrix.cc }})
- strategy:
- fail-fast: false
- matrix:
- include:
- - flavor: functionaltest-lua
- cc: gcc
- runner: ubuntu-20.04
- os: linux
- runs-on: ${{ matrix.runner }}
- timeout-minutes: 45
- env:
- CC: ${{ matrix.cc }}
- CI_OS_NAME: ${{ matrix.os }}
- steps:
- - uses: actions/checkout@v2
-
- - name: Setup common environment variables
- run: ./.github/workflows/env.sh ${{ matrix.flavor }}
-
- - name: Install apt packages
- run: |
- sudo apt-get update
- sudo apt-get install -y autoconf automake build-essential ccache cmake cpanminus cscope gcc-multilib gdb gettext gperf language-pack-tr libtool-bin locales ninja-build pkg-config python3 python3-pip python3-setuptools unzip valgrind xclip
-
- - name: Install minimum required version of cmake
- env:
- CMAKE_URL: 'https://cmake.org/files/v3.10/cmake-3.10.0-Linux-x86_64.sh'
- CMAKE_VERSION: '3.10.0'
- shell: bash
- run: |
- curl --retry 5 --silent --show-error --fail -o /tmp/cmake-installer.sh "$CMAKE_URL"
- mkdir -p "$HOME/.local/bin" /opt/cmake-custom
- chmod a+x /tmp/cmake-installer.sh
- /tmp/cmake-installer.sh --prefix=/opt/cmake-custom --skip-license
- ln -sfn /opt/cmake-custom/bin/cmake "$HOME/.local/bin/cmake"
- cmake_version="$(cmake --version | head -1)"
- echo "$cmake_version" | grep -qF "cmake version $CMAKE_VERSION" || {
- echo "Unexpected CMake version: $cmake_version"
- exit 1
- }
-
- - name: Setup interpreter packages
- run: |
- ./ci/install.sh
-
- - name: Cache dependencies
- uses: actions/cache@v2
- with:
- path: |
- ${{ env.CACHE_NVIM_DEPS_DIR }}
- ~/.ccache
- key: ${{ matrix.runner }}-${{ matrix.flavor }}-${{ matrix.cc }}-${{ hashFiles('cmake/*', 'third-party/**', '**/CMakeLists.txt') }}-${{ github.base_ref }}
-
- - name: Build third-party
- run: ./ci/before_script.sh
-
- - name: Build and test
- run: ./ci/script.sh
-
- - name: Cache dependencies
- if: ${{ success() }}
- run: ./ci/before_cache.sh
diff --git a/.github/workflows/env.sh b/.github/workflows/env.sh
index 0964995605..d424924c27 100755
--- a/.github/workflows/env.sh
+++ b/.github/workflows/env.sh
@@ -46,7 +46,9 @@ CLANG_SANITIZER=TSAN
EOF
;;
lint)
+ BUILD_FLAGS="$BUILD_FLAGS -DLIBLUV_LIBRARY:FILEPATH=/usr/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)/lua/5.1/luv.so -DLIBLUV_INCLUDE_DIR:PATH=/usr/include/lua5.1"
cat <<EOF >> "$GITHUB_ENV"
+USE_BUNDLED=OFF
CI_TARGET=lint
EOF
;;
diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml
index 736b8ae630..d50e0c1f92 100644
--- a/.github/workflows/labeler.yml
+++ b/.github/workflows/labeler.yml
@@ -13,10 +13,10 @@ jobs:
- uses: actions/labeler@main
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
+ sync-labels: ""
type-scope:
runs-on: ubuntu-latest
- needs: ["triage"]
permissions:
contents: write
pull-requests: write
@@ -38,10 +38,10 @@ jobs:
permissions:
pull-requests: write
steps:
- - run: wget https://raw.githubusercontent.com/neovim/neovim/master/ci/reviews.js
+ - uses: actions/checkout@v2
- name: 'Request reviewers'
uses: actions/github-script@v6
with:
script: |
- const script = require('./reviews.js')
+ const script = require('./.github/scripts/reviews.js')
await script({github, context})
diff --git a/.github/workflows/notes.md b/.github/workflows/notes.md
index 9928d472b3..7181972696 100644
--- a/.github/workflows/notes.md
+++ b/.github/workflows/notes.md
@@ -6,8 +6,26 @@ ${NVIM_VERSION}
### Windows
-1. Extract **nvim-win64.zip**
-2. Run `nvim-qt.exe`
+#### Zip
+
+1. Download **nvim-win64.zip**
+2. Extract the zip.
+3. Run `nvim-qt.exe`
+
+#### MSI
+
+1. Download **nvim-win64.msi**
+2. Run the MSI
+3. Add the Neovim location to your path.
+ - Default location is `C:\Program Files\Neovim`
+4. Search and run `nvim-qt.exe` or run `nvim.exe` on your CLI of choice.
+
+#### NSIS
+
+1. Download **nvim-win64.exe**
+2. Run the installer.
+ - Ensure that the option to add the installation location to your path is checked if it's your first installation.
+3. Search and run `nvim-qt.exe` or run `nvim.exe` on your CLI of choice.
### macOS
@@ -17,6 +35,19 @@ ${NVIM_VERSION}
### Linux (x64)
+#### Tarball
+
+1. Download **nvim-linux64.tar.gz**
+2. Extract: `tar xzvf nvim-linux64.tar.gz`
+3. Run `./nvim-linux64/bin/nvim`
+
+#### Debian Package
+
+1. Download **nvim-linux64.deb**
+2. Install the package using `sudo apt install ./nvim-linux64.deb`
+3. Run `nvim`
+
+#### AppImage
1. Download **nvim.appimage**
2. Run `chmod u+x nvim.appimage && ./nvim.appimage`
- If your system does not have FUSE you can [extract the appimage](https://github.com/AppImage/AppImageKit/wiki/FUSE#type-2-appimage):
@@ -32,9 +63,12 @@ ${NVIM_VERSION}
## SHA256 Checksums
```
-${SHA_LINUX_64}
+${SHA_LINUX_64_TAR}
+${SHA_LINUX_64_DEB}
${SHA_APP_IMAGE}
${SHA_APP_IMAGE_ZSYNC}
${SHA_MACOS}
-${SHA_WIN_64}
+${SHA_WIN_64_ZIP}
+${SHA_WIN_64_MSI}
+${SHA_WIN_64_EXE}
```
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index b72c2ab71d..e954b57175 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -39,12 +39,17 @@ jobs:
printf '::set-output name=version::%s\n' "$(./build/bin/nvim --version | head -n 3 | sed -z 's/\n/%0A/g')"
printf '::set-output name=release::%s\n' "$(./build/bin/nvim --version | head -n 1)"
make DESTDIR="$GITHUB_WORKSPACE/build/release/nvim-linux64" install
- cd "$GITHUB_WORKSPACE/build/release"
- tar cfz nvim-linux64.tar.gz nvim-linux64
+ cd "$GITHUB_WORKSPACE/build/"
+ cpack -C $NVIM_BUILD_TYPE
- uses: actions/upload-artifact@v2
with:
name: nvim-linux64
- path: build/release/nvim-linux64.tar.gz
+ path: build/nvim-linux64.tar.gz
+ retention-days: 1
+ - uses: actions/upload-artifact@v2
+ with:
+ name: nvim-linux64
+ path: build/nvim-linux64.deb
retention-days: 1
appimage:
@@ -114,7 +119,7 @@ jobs:
retention-days: 1
windows:
- runs-on: windows-2016
+ runs-on: windows-2019
env:
DEPS_BUILD_DIR: ${{ format('{0}/nvim-deps', github.workspace) }}
DEPS_PREFIX: ${{ format('{0}/nvim-deps/usr', github.workspace) }}
@@ -131,12 +136,21 @@ jobs:
- run: powershell ci\build.ps1 -NoTests
env:
CONFIGURATION: ${{ matrix.config }}
- - run: move build\Neovim.zip build\${{ matrix.archive }}.zip
- uses: actions/upload-artifact@v2
with:
name: ${{ matrix.archive }}
path: build/${{ matrix.archive }}.zip
retention-days: 1
+ - uses: actions/upload-artifact@v2
+ with:
+ name: ${{ matrix.archive }}
+ path: build/${{ matrix.archive }}.msi
+ retention-days: 1
+ - uses: actions/upload-artifact@v2
+ with:
+ name: ${{ matrix.archive }}
+ path: build/${{ matrix.archive }}.exe
+ retention-days: 1
publish:
needs: [linux, appimage, macOS, windows]
@@ -187,7 +201,9 @@ jobs:
run: |
cd ./nvim-linux64
sha256sum nvim-linux64.tar.gz > nvim-linux64.tar.gz.sha256sum
- echo "SHA_LINUX_64=$(cat nvim-linux64.tar.gz.sha256sum)" >> $GITHUB_ENV
+ echo "SHA_LINUX_64_TAR=$(cat nvim-linux64.tar.gz.sha256sum)" >> $GITHUB_ENV
+ sha256sum nvim-linux64.deb > nvim-linux64.deb.sha256sum
+ echo "SHA_LINUX_64_DEB=$(cat nvim-linux64.deb.sha256sum)" >> $GITHUB_ENV
- name: Generate App Image SHA256 checksums
run: |
cd ./appimage
@@ -207,7 +223,11 @@ jobs:
run: |
cd ./nvim-win64
sha256sum nvim-win64.zip > nvim-win64.zip.sha256sum
- echo "SHA_WIN_64=$(cat nvim-win64.zip.sha256sum)" >> $GITHUB_ENV
+ echo "SHA_WIN_64_ZIP=$(cat nvim-win64.zip.sha256sum)" >> $GITHUB_ENV
+ sha256sum nvim-win64.msi > nvim-win64.msi.sha256sum
+ echo "SHA_WIN_64_MSI=$(cat nvim-win64.msi.sha256sum)" >> $GITHUB_ENV
+ sha256sum nvim-win64.exe > nvim-win64.exe.sha256sum
+ echo "SHA_WIN_64_EXE=$(cat nvim-win64.exe.sha256sum)" >> $GITHUB_ENV
- name: Publish release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/reviews.yml b/.github/workflows/reviews.yml
index 2da7365821..964f57b871 100644
--- a/.github/workflows/reviews.yml
+++ b/.github/workflows/reviews.yml
@@ -9,10 +9,10 @@ jobs:
permissions:
pull-requests: write
steps:
- - run: wget https://raw.githubusercontent.com/neovim/neovim/master/ci/reviews.js
+ - uses: actions/checkout@v2
- name: 'Request reviewers'
uses: actions/github-script@v6
with:
script: |
- const script = require('./reviews.js')
+ const script = require('./.github/scripts/reviews.js')
await script({github, context})
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e0f05e1205..08d52eb071 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -736,17 +736,6 @@ else()
COMMENT "lualint: LUACHECK_PRG not defined")
endif()
-set(CPACK_PACKAGE_NAME "Neovim")
-set(CPACK_PACKAGE_VENDOR "neovim.io")
-set(CPACK_PACKAGE_VERSION ${NVIM_VERSION_MEDIUM})
-set(CPACK_PACKAGE_INSTALL_DIRECTORY "Neovim")
-# Set toplevel directory/installer name as Neovim
-set(CPACK_PACKAGE_FILE_NAME "Neovim")
-set(CPACK_TOPLEVEL_TAG "Neovim")
-set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
-set(CPACK_NSIS_MODIFY_PATH ON)
-set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON)
-include(CPack)
#add uninstall target
if(NOT TARGET uninstall)
@@ -758,3 +747,8 @@ if(NOT TARGET uninstall)
add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/UninstallHelper.cmake)
endif()
+
+
+if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR})
+ add_subdirectory(packaging)
+endif()
diff --git a/LICENSE b/LICENSE.txt
index c1b8286c4b..c1b8286c4b 100644
--- a/LICENSE
+++ b/LICENSE.txt
diff --git a/ci/before_cache.sh b/ci/before_cache.sh
index c86109168e..bec6c37bbe 100755
--- a/ci/before_cache.sh
+++ b/ci/before_cache.sh
@@ -7,6 +7,8 @@ CI_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${CI_DIR}/common/build.sh"
source "${CI_DIR}/common/suite.sh"
+mkdir -p "${HOME}/.cache"
+
echo "before_cache.sh: cache size"
du -chd 1 "${HOME}/.cache" | sort -rh | head -20
@@ -16,7 +18,7 @@ ccache -s 2>/dev/null || true
find "${HOME}/.ccache" -name stats -delete
# Update the third-party dependency cache only if the build was successful.
-if ended_successfully; then
+if ended_successfully && [ -d "${DEPS_BUILD_DIR}" ]; then
# Do not cache downloads. They should not be needed with up-to-date deps.
rm -rf "${DEPS_BUILD_DIR}/build/downloads"
rm -rf "${CACHE_NVIM_DEPS_DIR}"
diff --git a/ci/build.ps1 b/ci/build.ps1
index ef5ba3bf2d..c7c3b3d470 100644
--- a/ci/build.ps1
+++ b/ci/build.ps1
@@ -77,11 +77,16 @@ if ($compiler -eq 'MINGW') {
}
elseif ($compiler -eq 'MSVC') {
$cmakeGeneratorArgs = '/verbosity:normal'
- if ($bits -eq 32) {
- $cmakeGenerator = 'Visual Studio 15 2017'
- }
- elseif ($bits -eq 64) {
- $cmakeGenerator = 'Visual Studio 15 2017 Win64'
+ $cmakeGenerator = 'Visual Studio 16 2019'
+}
+
+if ($compiler -eq 'MSVC') {
+ $installationPath = vswhere.exe -latest -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath
+ if ($installationPath -and (test-path "$installationPath\Common7\Tools\vsdevcmd.bat")) {
+ & "${env:COMSPEC}" /s /c "`"$installationPath\Common7\Tools\vsdevcmd.bat`" -arch=x${bits} -no_logo && set" | foreach-object {
+ $name, $value = $_ -split '=', 2
+ set-content env:\"$name" $value
+ }
}
}
@@ -99,24 +104,35 @@ if (-not $NoTests) {
npm.cmd link neovim
}
-if ($compiler -eq 'MSVC') {
- # Required for LuaRocks (https://github.com/luarocks/luarocks/issues/1039#issuecomment-507296940).
- $env:VCINSTALLDIR = "C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.16.27023/"
-}
-
function convertToCmakeArgs($vars) {
return $vars.GetEnumerator() | foreach { "-D$($_.Key)=$($_.Value)" }
}
cd $env:DEPS_BUILD_DIR
-cmake -G $cmakeGenerator $(convertToCmakeArgs($depsCmakeVars)) "$buildDir/third-party/" ; exitIfFailed
+if ($compiler -eq 'MSVC') {
+ if ($bits -eq 32) {
+ cmake -G $cmakeGenerator -A Win32 $(convertToCmakeArgs($depsCmakeVars)) "$buildDir/third-party/" ; exitIfFailed
+ } else {
+ cmake -G $cmakeGenerator -A x64 $(convertToCmakeArgs($depsCmakeVars)) "$buildDir/third-party/" ; exitIfFailed
+ }
+} else {
+ cmake -G $cmakeGenerator $(convertToCmakeArgs($depsCmakeVars)) "$buildDir/third-party/" ; exitIfFailed
+}
cmake --build . --config $cmakeBuildType -- $cmakeGeneratorArgs ; exitIfFailed
cd $buildDir
# Build Neovim
mkdir build
cd build
-cmake -G $cmakeGenerator $(convertToCmakeArgs($nvimCmakeVars)) .. ; exitIfFailed
+if ($compiler -eq 'MSVC') {
+ if ($bits -eq 32) {
+ cmake -G $cmakeGenerator -A Win32 $(convertToCmakeArgs($nvimCmakeVars)) .. ; exitIfFailed
+ } else {
+ cmake -G $cmakeGenerator -A x64 $(convertToCmakeArgs($nvimCmakeVars)) .. ; exitIfFailed
+ }
+} else {
+ cmake -G $cmakeGenerator $(convertToCmakeArgs($nvimCmakeVars)) .. ; exitIfFailed
+}
cmake --build . --config $cmakeBuildType -- $cmakeGeneratorArgs ; exitIfFailed
.\bin\nvim --version ; exitIfFailed
@@ -167,7 +183,4 @@ if (Test-Path -Path $env:ChocolateyInstall\bin\cpack.exe) {
}
# Build artifacts
-cpack -G ZIP -C RelWithDebInfo
-if ($env:APPVEYOR_REPO_TAG_NAME -ne $null) {
- cpack -G NSIS -C RelWithDebInfo
-}
+cpack -C $cmakeBuildType
diff --git a/ci/common/suite.sh b/ci/common/suite.sh
index f33f8b89d1..5110e22ec2 100644
--- a/ci/common/suite.sh
+++ b/ci/common/suite.sh
@@ -11,37 +11,17 @@ FAIL_SUMMARY=""
END_MARKER="$BUILD_DIR/.tests_finished"
FAIL_SUMMARY_FILE="$BUILD_DIR/.test_errors"
-ci_fold() {
- if test "$GITHUB_ACTIONS" = "true"; then
- local action="$1"
- local name="$2"
- case "$action" in
- start)
- echo "::group::${name}"
- ;;
- end)
- echo "::endgroup::"
- ;;
- *)
- :;;
- esac
- fi
-}
-
enter_suite() {
FAILED=0
rm -f "${END_MARKER}"
local suite_name="$1"
export NVIM_TEST_CURRENT_SUITE="${NVIM_TEST_CURRENT_SUITE}/$suite_name"
- ci_fold "start" "$suite_name"
}
exit_suite() {
if test $FAILED -ne 0 ; then
echo "Suite ${NVIM_TEST_CURRENT_SUITE} failed, summary:"
echo "${FAIL_SUMMARY}"
- else
- ci_fold "end" ""
fi
export NVIM_TEST_CURRENT_SUITE="${NVIM_TEST_CURRENT_SUITE%/*}"
FAILED=0
@@ -66,6 +46,11 @@ ended_successfully() {
if test -f "${FAIL_SUMMARY_FILE}" ; then
echo 'Test failed, complete summary:'
cat "${FAIL_SUMMARY_FILE}"
+
+ if [[ "$GITHUB_ACTIONS" == "true" ]]; then
+ rm -f "$FAIL_SUMMARY_FILE"
+ fi
+
return 1
fi
if ! test -f "${END_MARKER}" ; then
diff --git a/ci/run_lint.sh b/ci/run_lint.sh
index 607ffa233a..2fea7a40c0 100755
--- a/ci/run_lint.sh
+++ b/ci/run_lint.sh
@@ -8,10 +8,34 @@ CI_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${CI_DIR}/common/build.sh"
source "${CI_DIR}/common/suite.sh"
-run_suite 'make clint-full' 'clint'
-run_suite 'make lualint' 'lualint'
-run_suite 'make pylint' 'pylint'
-run_suite 'make shlint' 'shlint'
-run_suite 'make check-single-includes' 'single-includes'
+if [[ "$GITHUB_ACTIONS" != "true" ]]; then
+ run_suite 'make clint-full' 'clint'
+ run_suite 'make lualint' 'lualint'
+ run_suite 'make pylint' 'pylint'
+ run_suite 'make shlint' 'shlint'
+ run_suite 'make check-single-includes' 'single-includes'
-end_tests
+ end_tests
+else
+ case "$1" in
+ clint)
+ run_suite 'make clint-full' 'clint'
+ ;;
+ lualint)
+ run_suite 'make lualint' 'lualint'
+ ;;
+ pylint)
+ run_suite 'make pylint' 'pylint'
+ ;;
+ shlint)
+ run_suite 'make shlint' 'shlint'
+ ;;
+ single-includes)
+ run_suite 'make check-single-includes' 'single-includes'
+ ;;
+ *)
+ :;;
+ esac
+
+ end_tests
+fi
diff --git a/ci/run_tests.sh b/ci/run_tests.sh
index 1baeb090a8..ae85246ab6 100755
--- a/ci/run_tests.sh
+++ b/ci/run_tests.sh
@@ -8,17 +8,42 @@ source "${CI_DIR}/common/build.sh"
source "${CI_DIR}/common/test.sh"
source "${CI_DIR}/common/suite.sh"
-run_suite 'build_nvim' 'build'
-if test "$CLANG_SANITIZER" != "TSAN"; then
- # Additional threads are only created when the builtin UI starts, which
- # doesn't happen in the unit/functional tests
- if test "${FUNCTIONALTEST}" != "functionaltest-lua"; then
- run_suite run_unittests unittests
+if [[ "$GITHUB_ACTIONS" != "true" ]]; then
+ run_suite 'build_nvim' 'build'
+
+ if test "$CLANG_SANITIZER" != "TSAN"; then
+ # Additional threads are only created when the builtin UI starts, which
+ # doesn't happen in the unit/functional tests
+ if test "${FUNCTIONALTEST}" != "functionaltest-lua"; then
+ run_suite run_unittests unittests
+ fi
+ run_suite run_functionaltests functionaltests
fi
- run_suite run_functionaltests functionaltests
-fi
-run_suite run_oldtests oldtests
-run_suite install_nvim install_nvim
+ run_suite run_oldtests oldtests
+ run_suite install_nvim install_nvim
-end_tests
+ end_tests
+else
+ case "$1" in
+ build)
+ run_suite 'build_nvim' 'build'
+ ;;
+ unittests)
+ run_suite 'run_unittests' 'unittests'
+ ;;
+ functionaltests)
+ run_suite 'run_functionaltests' 'functionaltests'
+ ;;
+ oldtests)
+ run_suite 'run_oldtests' 'oldtests'
+ ;;
+ install_nvim)
+ run_suite 'install_nvim' 'install_nvim'
+ ;;
+ *)
+ :;;
+ esac
+
+ end_tests
+fi
diff --git a/cmake/RunTests.cmake b/cmake/RunTests.cmake
index 3adbcbbfc5..789131c26c 100644
--- a/cmake/RunTests.cmake
+++ b/cmake/RunTests.cmake
@@ -95,5 +95,7 @@ if(NOT res EQUAL 0)
endif()
endif()
- message(FATAL_ERROR "${TEST_TYPE} tests failed with error: ${res}")
+ IF (NOT WIN32)
+ message(FATAL_ERROR "${TEST_TYPE} tests failed with error: ${res}")
+ ENDIF()
endif()
diff --git a/packaging/CMakeLists.txt b/packaging/CMakeLists.txt
new file mode 100644
index 0000000000..6ae744c2cd
--- /dev/null
+++ b/packaging/CMakeLists.txt
@@ -0,0 +1,78 @@
+set(CPACK_PACKAGE_NAME "Neovim")
+set(CPACK_PACKAGE_VENDOR "neovim.io")
+set(CPACK_PACKAGE_FILE_NAME "nvim")
+
+# From the GitHub About section
+set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Vim-fork focused on extensibility and usability.")
+
+set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
+
+# Pull the versions defined with the top level CMakeLists.txt
+set(CPACK_PACKAGE_VERSION_MAJOR ${NVIM_VERSION_MAJOR})
+set(CPACK_PACKAGE_VERSION_MINOR ${NVIM_VERSION_MINOR})
+set(CPACK_PACKAGE_VERSION_PATCH ${NVIM_VERSION_PATCH})
+
+# CPACK_VERBATIM_VARIABLES ensures that the variables prefixed with *CPACK_*
+# are correctly passed to the cpack program.
+# This should always be set to true.
+set(CPACK_VERBATIM_VARIABLES TRUE)
+
+set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE.txt")
+set(CPACK_RESOURCE_FILE_README ${PROJECT_SOURCE_DIR}/README.md)
+
+
+if(WIN32)
+ set(CPACK_PACKAGE_FILE_NAME "nvim-win64")
+ set(CPACK_GENERATOR ZIP WIX NSIS)
+
+ # WIX
+ # CPACK_WIX_UPGRADE_GUID should be set, but should never change.
+ # CPACK_WIX_PRODUCT_GUID should not be set (leave as default to auto-generate).
+
+ # The following guid is just a randomly generated guid that's been pasted here.
+ # It has no special meaning other than to supply it to WIX.
+ set(CPACK_WIX_UPGRADE_GUID "207A1A70-7B0C-418A-A153-CA6883E38F4D")
+ set(CPACK_WIX_PRODUCT_ICON ${CMAKE_CURRENT_LIST_DIR}/logo.ico)
+
+ # NSIS
+ # install icon
+ set(CPACK_NSIS_MUI_ICON ${CMAKE_CURRENT_LIST_DIR}/logo.ico)
+
+ # uninstall icon
+ set(CPACK_NSIS_MUI_UNIICON ${CMAKE_CURRENT_LIST_DIR}/logo.ico)
+
+ # icon that appears when you search in Add/Remove programs
+ set(CPACK_NSIS_INSTALLED_ICON_NAME ${CMAKE_CURRENT_LIST_DIR}/logo.ico)
+
+ # name that appears in the list in Add/Remove programs
+ set(CPACK_NSIS_DISPLAY_NAME "Neovim")
+
+ # name used in various installer UI locations, such as the title
+ set(CPACK_NSIS_PACKAGE_NAME "Neovim")
+
+ # Allow the user to modify their path to include neovim during
+ # the installation process.
+ set(CPACK_NSIS_MODIFY_PATH TRUE)
+elseif(APPLE)
+ set(CPACK_PACKAGE_FILE_NAME "nvim-macos")
+ set(CPACK_GENERATOR TGZ)
+ set(CPACK_PACKAGE_ICON ${CMAKE_CURRENT_LIST_DIR}/logo.icns)
+elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ set(CPACK_PACKAGE_FILE_NAME "nvim-linux64")
+ set(CPACK_GENERATOR TGZ DEB)
+ set(CPACK_DEBIAN_PACKAGE_NAME "Neovim") # required
+ set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Neovim.io") # required
+
+ # Automatically compute required shared lib dependencies.
+ # Unfortunately, you "just need to know" that this has a hidden
+ # dependency on dpkg-shlibdeps whilst using a debian based host.
+ set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS TRUE)
+else()
+ set(CPACK_GENERATOR TGZ)
+endif()
+
+# CPack variables are loaded in on the call to include(CPack). If you set
+# variables *after* the inclusion, they don't get updated within the CPack
+# config. Note that some CPack commands should still be run after it, such
+# as cpack_add_component().
+include(CPack)
diff --git a/packaging/logo.icns b/packaging/logo.icns
new file mode 100644
index 0000000000..a6377d9cdb
--- /dev/null
+++ b/packaging/logo.icns
Binary files differ
diff --git a/packaging/logo.ico b/packaging/logo.ico
new file mode 100644
index 0000000000..a4523501b9
--- /dev/null
+++ b/packaging/logo.ico
Binary files differ
diff --git a/packaging/logo.svg b/packaging/logo.svg
new file mode 100644
index 0000000000..e8aa8bd33e
--- /dev/null
+++ b/packaging/logo.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 54 65" fill="#fff" fill-rule="evenodd" stroke="#000" stroke-linecap="round" stroke-linejoin="round"><use xlink:href="#D" x=".5" y=".5"/><defs><linearGradient x1="50.00%" y1="0.00%" x2="50.00%" y2="100.00%" id="A"><stop stop-color="#16b0ed" stop-opacity=".8" offset="0%"/><stop stop-color="#0f59b2" stop-opacity=".837" offset="100%"/></linearGradient><linearGradient x1="50.00%" y1="0.00%" x2="50.00%" y2="100.00%" id="B"><stop stop-color="#7db643" offset="0%"/><stop stop-color="#367533" offset="100%"/></linearGradient><linearGradient x1="50.00%" y1="-0.00%" x2="50.00%" y2="100.01%" id="C"><stop stop-color="#88c649" stop-opacity=".8" offset="0%"/><stop stop-color="#439240" stop-opacity=".84" offset="100%"/></linearGradient></defs><symbol id="D" overflow="visible"><g stroke="none"><path d="M0 13.761L13.63 0v63.983L0 50.381z" fill="url(#A)"/><path d="M52.664 13.894L38.848.008l.281 63.976 13.63-13.602z" fill="url(#B)"/><path d="M13.621.011l35.435 54.07-9.916 9.915L3.686 10.046z" fill="url(#C)"/><path d="M13.633 25.092l-.019 2.13L2.676 11.069l1.013-1.032z" fill="#000" fill-opacity=".13"/></g></symbol></svg> \ No newline at end of file
diff --git a/runtime/autoload/dist/ft.vim b/runtime/autoload/dist/ft.vim
index aacecc521e..bcb1431b5f 100644
--- a/runtime/autoload/dist/ft.vim
+++ b/runtime/autoload/dist/ft.vim
@@ -211,6 +211,10 @@ func dist#ft#EuphoriaCheck()
endfunc
func dist#ft#DtraceCheck()
+ if did_filetype()
+ " Filetype was already detected
+ return
+ endif
let lines = getline(1, min([line("$"), 100]))
if match(lines, '^module\>\|^import\>') > -1
" D files often start with a module and/or import statement.
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index 7a5aeee603..de7db3b0b7 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -1584,7 +1584,7 @@ nvim_set_keymap({mode}, {lhs}, {rhs}, {*opts}) *nvim_set_keymap()*
{rhs} Right-hand-side |{rhs}| of the mapping.
{opts} Optional parameters map. Accepts all
|:map-arguments| as keys excluding |<buffer>| but
- including |noremap| and "desc". |desc| can be used
+ including |noremap| and "desc". "desc" can be used
to give a description to keymap. When called from
Lua, also accepts a "callback" key that takes a
Lua function to call when the mapping is executed.
@@ -2152,6 +2152,29 @@ nvim_buf_get_option({buffer}, {name}) *nvim_buf_get_option()*
Return: ~
Option value
+ *nvim_buf_get_text()*
+nvim_buf_get_text({buffer}, {start_row}, {start_col}, {end_row}, {end_col},
+ {opts})
+ Gets a range from the buffer.
+
+ This differs from |nvim_buf_get_lines()| in that it allows
+ retrieving only portions of a line.
+
+ Indexing is zero-based. Column indices are end-exclusive.
+
+ Prefer |nvim_buf_get_lines()| when retrieving entire lines.
+
+ Parameters: ~
+ {buffer} Buffer handle, or 0 for current buffer
+ {start_row} First line index
+ {start_col} Starting byte offset of first line
+ {end_row} Last line index
+ {end_col} Ending byte offset of last line (exclusive)
+ {opts} Optional parameters. Currently unused.
+
+ Return: ~
+ Array of lines, or empty array for unloaded buffer.
+
nvim_buf_get_var({buffer}, {name}) *nvim_buf_get_var()*
Gets a buffer-scoped (b:) variable.
diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt
index ed75acf36e..dbe70b84cf 100644
--- a/runtime/doc/autocmd.txt
+++ b/runtime/doc/autocmd.txt
@@ -525,8 +525,19 @@ DirChanged After the |current-directory| was changed.
"global" to trigger on `:cd`
"auto" to trigger on 'autochdir'.
Sets these |v:event| keys:
- cwd: current working directory
- scope: "global", "tabpage", "window"
+ cwd: current working directory
+ scope: "global", "tabpage", "window"
+ changed_window: v:true if we fired the event
+ switching window (or tab)
+ <afile> is set to the new directory name.
+ Non-recursive (event cannot trigger itself).
+ *DirChangedPre*
+DirChangedPre When the |current-directory| is going to be
+ changed, as with |DirChanged|.
+ The pattern is like with |DirChanged|.
+ Sets these |v:event| keys:
+ directory: new working directory
+ scope: "global", "tabpage", "window"
changed_window: v:true if we fired the event
switching window (or tab)
<afile> is set to the new directory name.
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index 35a232c0c2..833da2622c 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -1807,6 +1807,7 @@ exists({expr}) The result is a Number, which is |TRUE| if {expr} is
exists("$HOSTNAME")
exists("*strftime")
exists("*s:MyFunc")
+ exists("*MyFunc")
exists("bufcount")
exists(":Make")
exists("#CursorHold")
@@ -5863,16 +5864,22 @@ reltimestr({time}) *reltimestr()*
<
*remote_expr()* *E449*
remote_expr({server}, {string} [, {idvar} [, {timeout}]])
- Send the {string} to {server}. The string is sent as an
- expression and the result is returned after evaluation.
- The result must be a String or a |List|. A |List| is turned
- into a String by joining the items with a line break in
- between (not at the end), like with join(expr, "\n").
+ Send the {string} to {server}. The {server} argument is a
+ string, also see |{server}|.
+
+ The string is sent as an expression and the result is returned
+ after evaluation. The result must be a String or a |List|. A
+ |List| is turned into a String by joining the items with a
+ line break in between (not at the end), like with join(expr,
+ "\n").
+
If {idvar} is present and not empty, it is taken as the name
of a variable and a {serverid} for later use with
|remote_read()| is stored there.
+
If {timeout} is given the read times out after this many
seconds. Otherwise a timeout of 600 seconds is used.
+
See also |clientserver| |RemoteReply|.
This function is not available in the |sandbox|.
Note: Any errors will cause a local error message to be issued
@@ -5890,7 +5897,7 @@ remote_expr({server}, {string} [, {idvar} [, {timeout}]])
remote_foreground({server}) *remote_foreground()*
Move the Vim server with the name {server} to the foreground.
- The {server} argument is a string.
+ The {server} argument is a string, also see |{server}|.
This works like: >
remote_expr({server}, "foreground()")
< Except that on Win32 systems the client does the work, to work
@@ -5926,12 +5933,17 @@ remote_read({serverid}, [{timeout}]) *remote_read()*
<
*remote_send()* *E241*
remote_send({server}, {string} [, {idvar}])
- Send the {string} to {server}. The string is sent as input
- keys and the function returns immediately. At the Vim server
- the keys are not mapped |:map|.
+ Send the {string} to {server}. The {server} argument is a
+ string, also see |{server}|.
+
+ The string is sent as input keys and the function returns
+ immediately. At the Vim server the keys are not mapped
+ |:map|.
+
If {idvar} is present, it is taken as the name of a variable
and a {serverid} for later use with remote_read() is stored
there.
+
See also |clientserver| |RemoteReply|.
This function is not available in the |sandbox|.
diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt
index 8ddc661c0e..4ccf3f145c 100644
--- a/runtime/doc/editing.txt
+++ b/runtime/doc/editing.txt
@@ -196,7 +196,7 @@ If you want to keep the changed buffer without saving it, switch on the
Edit {file} always. Discard any changes to the
current buffer.
Also see |++opt| and |+cmd|.
-
+ *:edit_#* *:e#*
:e[dit] [++opt] [+cmd] #[count]
Edit the [count]th buffer (as shown by |:files|).
This command does the same as [count] CTRL-^. But ":e
@@ -356,7 +356,7 @@ as a wildcard when "[" is in the 'isfname' option. A simple way to avoid this
is to use "path\[[]abc]", this matches the file "path\[abc]".
*starstar-wildcard*
-Expanding "**" is possible on Unix, Win32, Mac OS/X and a few other systems.
+Expanding "**" is possible on Unix, Win32, macOS and a few other systems.
This allows searching a directory tree. This goes up to 100 directories deep.
Note there are some commands where this works slightly differently, see
|file-searching|.
@@ -1495,7 +1495,7 @@ which version of the file you want to keep.
The accuracy of the time check depends on the filesystem. On Unix it is
usually sub-second. With old file sytems and on MS-Windows it is normally one
-second. Use has('nanotime') check if sub-second time stamp checks are
+second. Use `has('nanotime')` to check if sub-second time stamp checks are
available.
There is one situation where you get the message while there is nothing wrong:
diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt
index e3bc3d5437..d02ab1b759 100644
--- a/runtime/doc/index.txt
+++ b/runtime/doc/index.txt
@@ -353,6 +353,7 @@ tag char note action in Normal mode ~
register x]
|Y| ["x]Y yank N lines [into register x]; synonym for
"yy"
+ Note: Mapped to "y$" by default. |default-mappings|
|ZZ| ZZ write if buffer changed and close window
|ZQ| ZQ close window without writing
|[| [{char} square bracket command (see |[| below)
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index 1a2d845281..355c31090e 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -595,13 +595,33 @@ vim.highlight.on_yank({opts}) *vim.highlight.on_yank()*
- {on_visual} highlight when yanking visual selection (default `true`)
- {event} event structure (default |v:event|)
-vim.highlight.range({bufnr}, {ns}, {higroup}, {start}, {finish}, {rtype}, {inclusive})
+vim.highlight.range({bufnr}, {ns}, {hlgroup}, {start}, {finish}, {opts})
*vim.highlight.range()*
- Highlights the range between {start} and {finish} (tuples of {line,col})
- in buffer {bufnr} with the highlight group {higroup} using the namespace
- {ns}. Optional arguments are the type of range (characterwise, linewise,
- or blockwise, see |setreg|; default to characterwise) and whether the
- range is inclusive (default false).
+
+ Apply highlight group to range of text.
+
+ Parameters: ~
+ {bufnr} buffer number
+ {ns} namespace for highlights
+ {hlgroup} highlight group name
+ {start} starting position (tuple {line,col})
+ {finish} finish position (tuple {line,col})
+ {opts} optional parameters:
+ • `regtype`: type of range (characterwise, linewise,
+ or blockwise, see |setreg|), default `'v'`
+ • `inclusive`: range includes end position, default
+ `false`
+ • `priority`: priority of highlight, default
+ `vim.highlight.user` (see below)
+
+vim.highlight.priorities *vim.highlight.priorities*
+
+ Table with default priorities used for highlighting:
+ • `syntax`: `50`, used for standard syntax highlighting
+ • `treesitter`: `100`, used for tree-sitter-based highlighting
+ • `diagnostics`: `150`, used for code analysis such as diagnostics
+ • `user`: `200`, used for user-triggered highlights such as LSP
+ document symbols or `on_yank` autocommands
------------------------------------------------------------------------------
VIM.REGEX *lua-regex*
diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt
index 2d2795b1ca..358e944261 100644
--- a/runtime/doc/map.txt
+++ b/runtime/doc/map.txt
@@ -502,7 +502,9 @@ Note: When using mappings for Visual mode, you can use the "'<" mark, which
is the start of the last selected Visual area in the current buffer |'<|.
The |:filter| command can be used to select what mappings to list. The
-pattern is matched against the {lhs} and {rhs} in the raw form.
+pattern is matched against the {lhs} and {rhs} in the raw form. If a
+description was added using |nvim_set_keymap()| or |nvim_buf_set_keymap()|
+then the pattern is also matched against it.
*:map-verbose*
When 'verbose' is non-zero, listing a key map will also display where it was
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 6e2bc228d0..2f76cc018c 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -3040,7 +3040,7 @@ A jump table for the options with a short description can be found at |Q_op|.
*'guitablabel'* *'gtl'*
'guitablabel' 'gtl' string (default empty)
global
- When nonempty describes the text to use in a label of the GUI tab
+ When non-empty describes the text to use in a label of the GUI tab
pages line. When empty and when the result is empty Vim will use a
default label. See |setting-guitablabel| for more info.
@@ -3057,7 +3057,7 @@ A jump table for the options with a short description can be found at |Q_op|.
*'guitabtooltip'* *'gtt'*
'guitabtooltip' 'gtt' string (default empty)
global
- When nonempty describes the text to use in a tooltip for the GUI tab
+ When non-empty describes the text to use in a tooltip for the GUI tab
pages line. When empty Vim will use a default tooltip.
This option is otherwise just like 'guitablabel' above.
You can include a line break. Simplest method is to use |:let|: >
@@ -5906,7 +5906,7 @@ A jump table for the options with a short description can be found at |Q_op|.
*'statusline'* *'stl'* *E540* *E542*
'statusline' 'stl' string (default empty)
global or local to window |global-local|
- When nonempty, this option determines the content of the status line.
+ When non-empty, this option determines the content of the status line.
Also see |status-line|.
The option consists of printf style '%' items interspersed with
@@ -6222,7 +6222,7 @@ A jump table for the options with a short description can be found at |Q_op|.
*'tabline'* *'tal'*
'tabline' 'tal' string (default empty)
global
- When nonempty, this option determines the content of the tab pages
+ When non-empty, this option determines the content of the tab pages
line at the top of the Vim window. When empty Vim will use a default
tab pages line. See |setting-tabline| for more info.
diff --git a/runtime/doc/quickref.txt b/runtime/doc/quickref.txt
index af8301f1a0..e36eb2359f 100644
--- a/runtime/doc/quickref.txt
+++ b/runtime/doc/quickref.txt
@@ -356,6 +356,7 @@ In Insert or Command-line mode:
|v_y| {visual}y yank the highlighted text into a register
|yy| N yy yank N lines into a register
|Y| N Y yank N lines into a register
+ Note: Mapped to "y$" by default. |default-mappings|
|p| N p put a register after the cursor position (N times)
|P| N P put a register before the cursor position (N times)
|]p| N ]p like p, but adjust indent to current line
diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt
index a022049766..05529dc90a 100644
--- a/runtime/doc/repeat.txt
+++ b/runtime/doc/repeat.txt
@@ -253,21 +253,22 @@ For writing a Vim script, see chapter 41 of the user manual |usr_41.txt|.
below "plugin", just like with plugins in
'runtimepath'.
- If the filetype detection was not enabled yet (this
+ If the filetype detection was already enabled (this
is usually done with a "syntax enable" or "filetype
- on" command in your .vimrc file), this will also look
+ on" command in your |init.vim|, or automatically during
+ |initialization|), and the package was found in
+ "pack/*/opt/{name}", this command will also look
for "{name}/ftdetect/*.vim" files.
When the optional ! is added no plugin files or
ftdetect scripts are loaded, only the matching
directories are added to 'runtimepath'. This is
- useful in your .vimrc. The plugins will then be
- loaded during initialization, see |load-plugins| (note
+ useful in your |init.vim|. The plugins will then be
+ loaded during |initialization|, see |load-plugins| (note
that the loading order will be reversed, because each
- directory is inserted before others).
- Note that for ftdetect scripts to be loaded
- you will need to write `filetype plugin indent on`
- AFTER all `packadd!` commands.
+ directory is inserted before others). In this case, the
+ ftdetect scripts will be loaded during |initialization|,
+ before the |load-plugins| step.
Also see |pack-add|.
diff --git a/runtime/doc/usr_04.txt b/runtime/doc/usr_04.txt
index b2dd617542..c7c900274b 100644
--- a/runtime/doc/usr_04.txt
+++ b/runtime/doc/usr_04.txt
@@ -349,15 +349,17 @@ Notice that "yw" includes the white space after a word. If you don't want
this, use "ye".
The "yy" command yanks a whole line, just like "dd" deletes a whole line.
-Unexpectedly, while "D" deletes from the cursor to the end of the line, "Y"
-works like "yy", it yanks the whole line. Watch out for this inconsistency!
-Use "y$" to yank to the end of the line.
a text line yy a text line a text line
line 2 line 2 p line 2
last line last line a text line
last line
+"Y" was originally equivalent to "yank the entire line", as opposed to "D"
+which is "delete to end of the line". "Y" has thus been remapped to mean
+"yank to end of the line" to make it consistent with the behavior of "D".
+Mappings will be covered in later chapters.
+
==============================================================================
*04.7* Using the clipboard
diff --git a/runtime/doc/usr_07.txt b/runtime/doc/usr_07.txt
index 649be8d7ce..ebf5c3d7b8 100644
--- a/runtime/doc/usr_07.txt
+++ b/runtime/doc/usr_07.txt
@@ -336,7 +336,7 @@ there. >
Of course you can use many other commands to yank the text. For example, to
select whole lines start Visual mode with "V". Or use CTRL-V to select a
-rectangular block. Or use "Y" to yank a single line, "yaw" to yank-a-word,
+rectangular block. Or use "yy" to yank a single line, "yaw" to yank-a-word,
etc.
The "p" command puts the text after the cursor. Use "P" to put the text
before the cursor. Notice that Vim remembers if you yanked a whole line or a
@@ -359,7 +359,7 @@ the text should be placed in the f register. This must come just before the
yank command.
Now yank three whole lines to the l register (l for line): >
- "l3Y
+ "l3yy
The count could be before the "l just as well. To yank a block of text to the
b (for block) register: >
diff --git a/runtime/doc/usr_10.txt b/runtime/doc/usr_10.txt
index 5365f90314..8844671e01 100644
--- a/runtime/doc/usr_10.txt
+++ b/runtime/doc/usr_10.txt
@@ -132,11 +132,11 @@ This works both with recording and with yank and delete commands. For
example, you want to collect a sequence of lines into the a register. Yank
the first line with: >
- "aY
+ "ayy
Now move to the second line, and type: >
- "AY
+ "Ayy
Repeat this command for all lines. The a register now contains all those
lines, in the order you yanked them.
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index 7892b82137..5ea6a9c5dd 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -433,7 +433,8 @@ Vimscript compatibility:
`this_session` does not alias to |v:this_session|
Working directory (Vim implemented some of these later than Nvim):
-- |DirChanged| can be triggered when switching to another window.
+- |DirChanged| and |DirChangedPre| can be triggered when switching to another
+ window or tab.
- |getcwd()| and |haslocaldir()| may throw errors if the tab page or window
cannot be found. *E5000* *E5001* *E5002*
- |haslocaldir()| checks for tab-local directory if and only if -1 is passed as
@@ -493,6 +494,9 @@ Eval:
*js_encode()*
*js_decode()*
*v:none* (used by Vim to represent JavaScript "undefined"); use |v:null| instead.
+ *v:sizeofint*
+ *v:sizeoflong*
+ *v:sizeofpointer*
Events:
*SigUSR1* Use |Signal| to detect `SIGUSR1` signal instead.
diff --git a/runtime/filetype.lua b/runtime/filetype.lua
index fcfc5701f0..74e427c358 100644
--- a/runtime/filetype.lua
+++ b/runtime/filetype.lua
@@ -7,6 +7,7 @@ if vim.g.do_filetype_lua ~= 1 then
return
end
+-- TODO: Remove vim.cmd once Lua autocommands land
vim.cmd [[
augroup filetypedetect
au BufRead,BufNewFile * call v:lua.vim.filetype.match(expand('<afile>'))
@@ -18,6 +19,12 @@ runtime! ftdetect/*.lua
" Set a marker so that the ftdetect scripts are not sourced a second time by filetype.vim
let g:did_load_ftdetect = 1
+" If filetype.vim is disabled, set up the autocmd to use scripts.vim
+if exists('did_load_filetypes')
+ au BufRead,BufNewFile * if !did_filetype() && expand('<amatch>') !~ g:ft_ignore_pat | runtime! scripts.vim | endif
+ au StdinReadPost * if !did_filetype() | runtime! scripts.vim | endif
+endif
+
augroup END
]]
diff --git a/runtime/filetype.vim b/runtime/filetype.vim
index 35f4b25120..8114ad4092 100644
--- a/runtime/filetype.vim
+++ b/runtime/filetype.vim
@@ -44,7 +44,7 @@ endif
" file name matches ft_ignore_pat.
" When using this, the entry should probably be further down below with the
" other StarSetf() calls.
-func! s:StarSetf(ft)
+func s:StarSetf(ft)
if expand("<amatch>") !~ g:ft_ignore_pat
exe 'setf ' . a:ft
endif
@@ -225,6 +225,9 @@ au BufNewFile,BufRead *.bib setf bib
" BibTeX Bibliography Style
au BufNewFile,BufRead *.bst setf bst
+" Bicep
+au BufNewFile,BufRead *.bicep setf bicep
+
" BIND configuration
" sudoedit uses namedXXXX.conf
au BufNewFile,BufRead named*.conf,rndc*.conf,rndc*.key setf named
@@ -477,6 +480,7 @@ au BufNewFile,BufRead */etc/dnsmasq.conf setf dnsmasq
au BufNewFile,BufRead *.desc setf desc
" the D language or dtrace
+au BufNewFile,BufRead */dtrace/*.d setf dtrace
au BufNewFile,BufRead *.d call dist#ft#DtraceCheck()
" Desktop files
@@ -723,6 +727,10 @@ au BufNewFile,BufRead gnashrc,.gnashrc,gnashpluginrc,.gnashpluginrc setf gnash
au BufNewFile,BufRead gitolite.conf setf gitolite
au BufNewFile,BufRead {,.}gitolite.rc,example.gitolite.rc setf perl
+" Glimmer-flavored TypeScript and JavaScript
+au BufNewFile,BufRead *.gts setf typescript.glimmer
+au BufNewFile,BufRead *.gjs setf javascript.glimmer
+
" Gnuplot scripts
au BufNewFile,BufRead *.gpi,.gnuplot setf gnuplot
@@ -1788,6 +1796,9 @@ au BufNewFile,BufRead *.mib,*.my setf mib
au BufNewFile,BufRead *.hog,snort.conf,vision.conf setf hog
au BufNewFile,BufRead *.rules call dist#ft#FTRules()
+" Solidity
+au BufRead,BufNewFile *.sol setf solidity
+
" SPARQL queries
au BufNewFile,BufRead *.rq,*.sparql setf sparql
@@ -2517,7 +2528,7 @@ endif
" Function called for testing all functions defined here. These are
" script-local, thus need to be executed here.
" Returns a string with error messages (hopefully empty).
-func! TestFiletypeFuncs(testlist)
+func TestFiletypeFuncs(testlist)
let output = ''
for f in a:testlist
try
diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua
index b4537c2882..fcb1e61764 100644
--- a/runtime/lua/vim/diagnostic.lua
+++ b/runtime/lua/vim/diagnostic.lua
@@ -447,7 +447,7 @@ local function set_list(loclist, opts)
vim.fn.setqflist({}, ' ', { title = title, items = items })
end
if open then
- vim.api.nvim_command(loclist and "lopen" or "copen")
+ vim.api.nvim_command(loclist and "lopen" or "botright copen")
end
end
@@ -920,7 +920,8 @@ M.handlers.underline = {
underline_ns,
higroup,
{ diagnostic.lnum, diagnostic.col },
- { diagnostic.end_lnum, diagnostic.end_col }
+ { diagnostic.end_lnum, diagnostic.end_col },
+ { priority = vim.highlight.priorities.diagnostics }
)
end
save_extmarks(underline_ns, bufnr)
diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua
index 2fe4aa3d32..f5e4dabfb6 100644
--- a/runtime/lua/vim/filetype.lua
+++ b/runtime/lua/vim/filetype.lua
@@ -65,6 +65,7 @@ local extension = {
bdf = "bdf",
beancount = "beancount",
bib = "bib",
+ bicep = "bicep",
bl = "blank",
bsdl = "bsdl",
bst = "bst",
@@ -246,6 +247,8 @@ local extension = {
gradle = "groovy",
groovy = "groovy",
gsp = "gsp",
+ gjs = "javascript.glimmer",
+ gts = "typescript.glimmer",
hack = "hack",
hackpartial = "hack",
haml = "haml",
@@ -597,6 +600,7 @@ local extension = {
sl = "slang",
ice = "slice",
score = "slrnsc",
+ sol = "solidity",
tpl = "smarty",
ihlp = "smcl",
smcl = "smcl",
@@ -1174,6 +1178,7 @@ local pattern = {
[".*/etc/yum%.conf"] = "dosini",
[".*lvs"] = "dracula",
[".*lpe"] = "dracula",
+ [".*/dtrace/.*%.d"] = "dtrace",
[".*esmtprc"] = "esmtprc",
[".*Eterm/.*%.cfg"] = "eterm",
[".*%.git/modules/.*/config"] = "gitconfig",
diff --git a/runtime/lua/vim/highlight.lua b/runtime/lua/vim/highlight.lua
index 12faa0a6e1..4105ef0675 100644
--- a/runtime/lua/vim/highlight.lua
+++ b/runtime/lua/vim/highlight.lua
@@ -1,9 +1,16 @@
local api = vim.api
-local highlight = {}
+local M = {}
+
+M.priorities = {
+ syntax = 50,
+ treesitter = 100,
+ diagnostics = 150,
+ user = 200,
+}
---@private
-function highlight.create(higroup, hi_info, default)
+function M.create(higroup, hi_info, default)
local options = {}
-- TODO: Add validation
for k, v in pairs(hi_info) do
@@ -13,28 +20,33 @@ function highlight.create(higroup, hi_info, default)
end
---@private
-function highlight.link(higroup, link_to, force)
+function M.link(higroup, link_to, force)
vim.cmd(string.format([[highlight%s link %s %s]], force and "!" or " default", higroup, link_to))
end
-
--- Highlight range between two positions
---
---@param bufnr number of buffer to apply highlighting to
---@param ns namespace to add highlight to
---@param higroup highlight group to use for highlighting
----@param rtype type of range (:help setreg, default charwise)
----@param inclusive boolean indicating whether the range is end-inclusive (default false)
----@param priority number indicating priority of highlight (default 50)
-function highlight.range(bufnr, ns, higroup, start, finish, rtype, inclusive, priority)
- rtype = rtype or 'v'
- inclusive = inclusive or false
- priority = priority or 50
+---@param start first position (tuple {line,col})
+---@param finish second position (tuple {line,col})
+---@param opts table with options:
+-- - regtype type of range (:help setreg, default charwise)
+-- - inclusive boolean indicating whether the range is end-inclusive (default false)
+-- - priority number indicating priority of highlight (default priorities.user)
+function M.range(bufnr, ns, higroup, start, finish, opts)
+ opts = opts or {}
+ local regtype = opts.regtype or "v"
+ local inclusive = opts.inclusive or false
+ local priority = opts.priority or M.priorities.user
-- sanity check
- if start[2] < 0 or finish[1] < start[1] then return end
+ if start[2] < 0 or finish[1] < start[1] then
+ return
+ end
- local region = vim.region(bufnr, start, finish, rtype, inclusive)
+ local region = vim.region(bufnr, start, finish, regtype, inclusive)
for linenr, cols in pairs(region) do
local end_row
if cols[2] == -1 then
@@ -46,13 +58,12 @@ function highlight.range(bufnr, ns, higroup, start, finish, rtype, inclusive, pr
end_row = end_row,
end_col = cols[2],
priority = priority,
- strict = false
+ strict = false,
})
end
-
end
-local yank_ns = api.nvim_create_namespace('hlyank')
+local yank_ns = api.nvim_create_namespace("hlyank")
--- Highlight the yanked region
---
--- use from init.vim via
@@ -62,26 +73,40 @@ local yank_ns = api.nvim_create_namespace('hlyank')
--- customize conditions (here: do not highlight a visual selection) via
--- au TextYankPost * lua vim.highlight.on_yank {on_visual=false}
---
--- @param opts dictionary with options controlling the highlight:
+-- @param opts table with options controlling the highlight:
-- - higroup highlight group for yanked region (default "IncSearch")
-- - timeout time in ms before highlight is cleared (default 150)
-- - on_macro highlight when executing macro (default false)
-- - on_visual highlight when yanking visual selection (default true)
-- - event event structure (default vim.v.event)
-function highlight.on_yank(opts)
- vim.validate {
- opts = { opts,
- function(t) if t == nil then return true else return type(t) == 'table' end end,
- 'a table or nil to configure options (see `:h highlight.on_yank`)',
- }}
+function M.on_yank(opts)
+ vim.validate({
+ opts = {
+ opts,
+ function(t)
+ if t == nil then
+ return true
+ else
+ return type(t) == "table"
+ end
+ end,
+ "a table or nil to configure options (see `:h highlight.on_yank`)",
+ },
+ })
opts = opts or {}
local event = opts.event or vim.v.event
local on_macro = opts.on_macro or false
local on_visual = (opts.on_visual ~= false)
- if (not on_macro) and vim.fn.reg_executing() ~= '' then return end
- if event.operator ~= 'y' or event.regtype == '' then return end
- if (not on_visual) and event.visual then return end
+ if not on_macro and vim.fn.reg_executing() ~= "" then
+ return
+ end
+ if event.operator ~= "y" or event.regtype == "" then
+ return
+ end
+ if not on_visual and event.visual then
+ return
+ end
local higroup = opts.higroup or "IncSearch"
local timeout = opts.timeout or 150
@@ -92,19 +117,23 @@ function highlight.on_yank(opts)
local pos1 = vim.fn.getpos("'[")
local pos2 = vim.fn.getpos("']")
- pos1 = {pos1[2] - 1, pos1[3] - 1 + pos1[4]}
- pos2 = {pos2[2] - 1, pos2[3] - 1 + pos2[4]}
-
- highlight.range(bufnr, yank_ns, higroup, pos1, pos2, event.regtype, event.inclusive, 200)
+ pos1 = { pos1[2] - 1, pos1[3] - 1 + pos1[4] }
+ pos2 = { pos2[2] - 1, pos2[3] - 1 + pos2[4] }
- vim.defer_fn(
- function()
- if api.nvim_buf_is_valid(bufnr) then
- api.nvim_buf_clear_namespace(bufnr, yank_ns, 0, -1)
- end
- end,
- timeout
+ M.range(
+ bufnr,
+ yank_ns,
+ higroup,
+ pos1,
+ pos2,
+ { regtype = event.regtype, inclusive = event.inclusive, priority = M.priorities.user }
)
+
+ vim.defer_fn(function()
+ if api.nvim_buf_is_valid(bufnr) then
+ api.nvim_buf_clear_namespace(bufnr, yank_ns, 0, -1)
+ end
+ end, timeout)
end
-return highlight
+return M
diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua
index a997b887d9..f5aefd4402 100644
--- a/runtime/lua/vim/lsp/handlers.lua
+++ b/runtime/lua/vim/lsp/handlers.lua
@@ -336,7 +336,7 @@ local function location_handler(_, result, ctx, _)
title = 'LSP locations',
items = util.locations_to_items(result, client.offset_encoding)
})
- api.nvim_command("copen")
+ api.nvim_command("botright copen")
end
else
util.jump_to_location(result, client.offset_encoding)
@@ -430,7 +430,7 @@ local make_call_hierarchy_handler = function(direction)
end
end
vim.fn.setqflist({}, ' ', {title = 'LSP call hierarchy', items = items})
- api.nvim_command("copen")
+ api.nvim_command("botright copen")
end
end
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index d22c00ae76..655c3a4679 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -1551,9 +1551,7 @@ do --[[ References ]]
document_highlight_kind[kind],
{ start_line, start_idx },
{ end_line, end_idx },
- nil,
- false,
- 40)
+ { priority = vim.highlight.priorities.user })
end
end
end
diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua
index 22b528838c..b6f61cfb2e 100644
--- a/runtime/lua/vim/treesitter/highlighter.lua
+++ b/runtime/lua/vim/treesitter/highlighter.lua
@@ -22,7 +22,21 @@ local _link_default_highlight_once = function(from, to)
return from
end
-TSHighlighter.hl_map = {
+-- If @definition.special does not exist use @definition instead
+local subcapture_fallback = {
+ __index = function(self, capture)
+ local rtn
+ local shortened = capture
+ while not rtn and shortened do
+ shortened = shortened:match('(.*)%.')
+ rtn = shortened and rawget(self, shortened)
+ end
+ rawset(self, capture, rtn or "__notfound")
+ return rtn
+ end
+}
+
+TSHighlighter.hl_map = setmetatable({
["error"] = "Error",
-- Miscs
@@ -66,7 +80,7 @@ TSHighlighter.hl_map = {
["type.builtin"] = "Type",
["structure"] = "Structure",
["include"] = "Include",
-}
+}, subcapture_fallback)
---@private
local function is_highlight_name(capture_name)
diff --git a/runtime/syntax/structurizr.vim b/runtime/syntax/structurizr.vim
index 73629b1495..ab9e4ee609 100644
--- a/runtime/syntax/structurizr.vim
+++ b/runtime/syntax/structurizr.vim
@@ -1,7 +1,7 @@
" Vim syntax file
" Language: Structurizr DSL
" Maintainer: Bastian Venthur <venthur@debian.org>
-" Last Change: 2021-08-16
+" Last Change: 2022-02-15
" Remark: For a language reference, see
" https://github.com/structurizr/dsl
@@ -30,6 +30,7 @@ syn keyword skeyword deployment
syn keyword skeyword deploymentenvironment
syn keyword skeyword deploymentgroup
syn keyword skeyword deploymentnode
+syn keyword skeyword description
syn keyword skeyword dynamic
syn keyword skeyword element
syn keyword skeyword enterprise
@@ -37,7 +38,6 @@ syn keyword skeyword exclude
syn keyword skeyword filtered
syn keyword skeyword group
syn keyword skeyword healthcheck
-syn keyword skeyword impliedrelationships
syn keyword skeyword include
syn keyword skeyword infrastructurenode
syn keyword skeyword model
@@ -51,6 +51,7 @@ syn keyword skeyword styles
syn keyword skeyword systemcontext
syn keyword skeyword systemlandscape
syn keyword skeyword tags
+syn keyword skeyword technology
syn keyword skeyword terminology
syn keyword skeyword theme
syn keyword skeyword title
@@ -63,7 +64,11 @@ syn match skeyword "\!adrs\s\+"
syn match skeyword "\!constant\s\+"
syn match skeyword "\!docs\s\+"
syn match skeyword "\!identifiers\s\+"
+syn match skeyword "\!impliedrelationships\s\+"
syn match skeyword "\!include\s\+"
+syn match skeyword "\!plugin\s\+"
+syn match skeyword "\!ref\s\+"
+syn match skeyword "\!script\s\+"
syn region sstring oneline start='"' end='"'
diff --git a/src/mpack/lmpack.c b/src/mpack/lmpack.c
index 126f2f3824..53d7092a0c 100644
--- a/src/mpack/lmpack.c
+++ b/src/mpack/lmpack.c
@@ -246,7 +246,7 @@ static mpack_uint32_t lmpack_objlen(lua_State *L, int *is_array)
}
end:
- if ((size_t)-1 > (mpack_uint32_t)-1 && len > (mpack_uint32_t)-1)
+ if ((size_t)-1 > (mpack_uint32_t)-1 && len > (mpack_uint32_t)-1) // -V560
/* msgpack spec doesn't allow lengths > 32 bits */
len = (mpack_uint32_t)-1;
assert(top == lua_gettop(L));
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index 2d5403d4b8..922d288da1 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -287,8 +287,8 @@ ArrayOf(String) nvim_buf_get_lines(uint64_t channel_id,
}
bool oob = false;
- start = normalize_index(buf, start, &oob);
- end = normalize_index(buf, end, &oob);
+ start = normalize_index(buf, start, true, &oob);
+ end = normalize_index(buf, end, true, &oob);
if (strict_indexing && oob) {
api_set_error(err, kErrorTypeValidation, "Index out of bounds");
@@ -374,15 +374,14 @@ void nvim_buf_set_lines(uint64_t channel_id, Buffer buffer, Integer start, Integ
}
bool oob = false;
- start = normalize_index(buf, start, &oob);
- end = normalize_index(buf, end, &oob);
+ start = normalize_index(buf, start, true, &oob);
+ end = normalize_index(buf, end, true, &oob);
if (strict_indexing && oob) {
api_set_error(err, kErrorTypeValidation, "Index out of bounds");
return;
}
-
if (start > end) {
api_set_error(err,
kErrorTypeValidation,
@@ -554,13 +553,13 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In
// check range is ordered and everything!
// start_row, end_row within buffer len (except add text past the end?)
- start_row = normalize_index(buf, start_row, &oob);
+ start_row = normalize_index(buf, start_row, false, &oob);
if (oob || start_row == buf->b_ml.ml_line_count + 1) {
api_set_error(err, kErrorTypeValidation, "start_row out of bounds");
return;
}
- end_row = normalize_index(buf, end_row, &oob);
+ end_row = normalize_index(buf, end_row, false, &oob);
if (oob || end_row == buf->b_ml.ml_line_count + 1) {
api_set_error(err, kErrorTypeValidation, "end_row out of bounds");
return;
@@ -757,6 +756,108 @@ end:
try_end(err);
}
+/// Gets a range from the buffer.
+///
+/// This differs from |nvim_buf_get_lines()| in that it allows retrieving only
+/// portions of a line.
+///
+/// Indexing is zero-based. Column indices are end-exclusive.
+///
+/// Prefer |nvim_buf_get_lines()| when retrieving entire lines.
+///
+/// @param channel_id
+/// @param buffer Buffer handle, or 0 for current buffer
+/// @param start_row First line index
+/// @param start_col Starting byte offset of first line
+/// @param end_row Last line index
+/// @param end_col Ending byte offset of last line (exclusive)
+/// @param opts Optional parameters. Currently unused.
+/// @param[out] err Error details, if any
+/// @return Array of lines, or empty array for unloaded buffer.
+ArrayOf(String) nvim_buf_get_text(uint64_t channel_id, Buffer buffer,
+ Integer start_row, Integer start_col,
+ Integer end_row, Integer end_col,
+ Dictionary opts, Error *err)
+ FUNC_API_SINCE(9)
+{
+ Array rv = ARRAY_DICT_INIT;
+
+ if (opts.size > 0) {
+ api_set_error(err, kErrorTypeValidation, "opts dict isn't empty");
+ return rv;
+ }
+
+ buf_T *buf = find_buffer_by_handle(buffer, err);
+
+ if (!buf) {
+ return rv;
+ }
+
+ // return sentinel value if the buffer isn't loaded
+ if (buf->b_ml.ml_mfp == NULL) {
+ return rv;
+ }
+
+ bool oob = false;
+ start_row = normalize_index(buf, start_row, false, &oob);
+ end_row = normalize_index(buf, end_row, false, &oob);
+
+ if (oob) {
+ api_set_error(err, kErrorTypeValidation, "Index out of bounds");
+ return rv;
+ }
+
+ // nvim_buf_get_lines doesn't care if the start row is greater than the end
+ // row (it will just return an empty array), but nvim_buf_get_text does in
+ // order to maintain symmetry with nvim_buf_set_text.
+ if (start_row > end_row) {
+ api_set_error(err, kErrorTypeValidation, "start is higher than end");
+ return rv;
+ }
+
+ bool replace_nl = (channel_id != VIML_INTERNAL_CALL);
+
+ if (start_row == end_row) {
+ String line = buf_get_text(buf, start_row, start_col, end_col, replace_nl, err);
+ if (ERROR_SET(err)) {
+ return rv;
+ }
+
+ ADD(rv, STRING_OBJ(line));
+ return rv;
+ }
+
+ rv.size = (size_t)(end_row - start_row) + 1;
+ rv.items = xcalloc(rv.size, sizeof(Object));
+
+ rv.items[0] = STRING_OBJ(buf_get_text(buf, start_row, start_col, MAXCOL-1, replace_nl, err));
+ if (ERROR_SET(err)) {
+ goto end;
+ }
+
+ if (rv.size > 2) {
+ Array tmp = ARRAY_DICT_INIT;
+ tmp.items = &rv.items[1];
+ if (!buf_collect_lines(buf, rv.size - 2, start_row + 1, replace_nl, &tmp, err)) {
+ goto end;
+ }
+ }
+
+ rv.items[rv.size-1] = STRING_OBJ(buf_get_text(buf, end_row, 0, end_col, replace_nl, err));
+ if (ERROR_SET(err)) {
+ goto end;
+ }
+
+end:
+ if (ERROR_SET(err)) {
+ api_free_array(rv);
+ rv.size = 0;
+ rv.items = NULL;
+ }
+
+ return rv;
+}
+
/// Returns the byte offset of a line (0-indexed). |api-indexing|
///
/// Line 1 (index=0) has offset 0. UTF-8 bytes are counted. EOL is one byte.
@@ -1386,11 +1487,11 @@ static void fix_cursor(linenr_T lo, linenr_T hi, linenr_T extra)
}
// Normalizes 0-based indexes to buffer line numbers
-static int64_t normalize_index(buf_T *buf, int64_t index, bool *oob)
+static int64_t normalize_index(buf_T *buf, int64_t index, bool end_exclusive, bool *oob)
{
int64_t line_count = buf->b_ml.ml_line_count;
// Fix if < 0
- index = index < 0 ? line_count + index +1 : index;
+ index = index < 0 ? line_count + index + (int)end_exclusive : index;
// Check for oob
if (index > line_count) {
diff --git a/src/nvim/api/keysets.lua b/src/nvim/api/keysets.lua
index f6dce1905e..45a57b9257 100644
--- a/src/nvim/api/keysets.lua
+++ b/src/nvim/api/keysets.lua
@@ -97,6 +97,7 @@ return {
"special"; "sp";
"link";
"fallback";
+ "blend";
"temp";
};
highlight_cterm = {
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index ddcfff0097..971fa1cb0f 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -411,7 +411,6 @@ void set_option_to(uint64_t channel_id, void *to, int type, String name, Object
current_sctx = save_current_sctx;
}
-
buf_T *find_buffer_by_handle(Buffer buffer, Error *err)
{
if (buffer == 0) {
@@ -758,6 +757,52 @@ bool buf_collect_lines(buf_T *buf, size_t n, int64_t start, bool replace_nl, Arr
return true;
}
+/// Returns a substring of a buffer line
+///
+/// @param buf Buffer handle
+/// @param lnum Line number (1-based)
+/// @param start_col Starting byte offset into line (0-based)
+/// @param end_col Ending byte offset into line (0-based, exclusive)
+/// @param replace_nl Replace newlines ('\n') with null ('\0')
+/// @param err Error object
+/// @return The text between start_col and end_col on line lnum of buffer buf
+String buf_get_text(buf_T *buf, int64_t lnum, int64_t start_col, int64_t end_col, bool replace_nl,
+ Error *err)
+{
+ String rv = STRING_INIT;
+
+ if (lnum >= MAXLNUM) {
+ api_set_error(err, kErrorTypeValidation, "Line index is too high");
+ return rv;
+ }
+
+ const char *bufstr = (char *)ml_get_buf(buf, (linenr_T)lnum, false);
+ size_t line_length = strlen(bufstr);
+
+ start_col = start_col < 0 ? (int64_t)line_length + start_col + 1 : start_col;
+ end_col = end_col < 0 ? (int64_t)line_length + end_col + 1 : end_col;
+
+ if (start_col >= MAXCOL || end_col >= MAXCOL) {
+ api_set_error(err, kErrorTypeValidation, "Column index is too high");
+ return rv;
+ }
+
+ if (start_col > end_col) {
+ api_set_error(err, kErrorTypeValidation, "start_col must be less than end_col");
+ return rv;
+ }
+
+ if ((size_t)start_col >= line_length) {
+ return rv;
+ }
+
+ rv = cstrn_to_string(&bufstr[start_col], (size_t)(end_col - start_col));
+ if (replace_nl) {
+ strchrsub(rv.data, '\n', '\0');
+ }
+
+ return rv;
+}
void api_free_string(String value)
{
@@ -1384,6 +1429,11 @@ void add_user_command(String name, Object command, Dict(user_command) *opts, int
LuaRef luaref = LUA_NOREF;
LuaRef compl_luaref = LUA_NOREF;
+ if (!uc_validate_name(name.data)) {
+ api_set_error(err, kErrorTypeValidation, "Invalid command name");
+ goto err;
+ }
+
if (mb_islower(name.data[0])) {
api_set_error(err, kErrorTypeValidation, "'name' must begin with an uppercase letter");
goto err;
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index f4909b0801..4dc599564f 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -124,6 +124,10 @@ Dictionary nvim__get_hl_defs(Integer ns_id, Error *err)
/// Set a highlight group.
///
+/// Note: unlike the `:highlight` command which can update a highlight group,
+/// this function completely replaces the definition. For example:
+/// `nvim_set_hl(0, 'Visual', {})` will clear the highlight group 'Visual'.
+///
/// @param ns_id number of namespace for this highlight. Use value 0
/// to set a highlight group in the global (`:highlight`)
/// namespace.
@@ -497,8 +501,12 @@ ArrayOf(String) nvim_get_runtime_file(String name, Boolean all, Error *err)
int flags = DIP_DIRFILE | (all ? DIP_ALL : 0);
- do_in_runtimepath((char_u *)(name.size ? name.data : ""),
- flags, find_runtime_cb, &rv);
+ TRY_WRAP({
+ try_start();
+ do_in_runtimepath((char_u *)(name.size ? name.data : ""),
+ flags, find_runtime_cb, &rv);
+ try_end(err);
+ });
return rv;
}
@@ -1584,7 +1592,7 @@ ArrayOf(Dictionary) nvim_get_keymap(uint64_t channel_id, String mode)
/// @param rhs Right-hand-side |{rhs}| of the mapping.
/// @param opts Optional parameters map. Accepts all |:map-arguments|
/// as keys excluding |<buffer>| but including |noremap| and "desc".
-/// |desc| can be used to give a description to keymap.
+/// "desc" can be used to give a description to keymap.
/// When called from Lua, also accepts a "callback" key that takes
/// a Lua function to call when the mapping is executed.
/// Values are Booleans. Unknown key is an error.
diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua
index 8fe623fc96..518d0b52b2 100644
--- a/src/nvim/auevents.lua
+++ b/src/nvim/auevents.lua
@@ -40,6 +40,7 @@ return {
'DiagnosticChanged', -- diagnostics in a buffer were modified
'DiffUpdated', -- diffs have been updated
'DirChanged', -- directory changed
+ 'DirChangedPre', -- directory is going to change
'EncodingChanged', -- after changing the 'encoding' option
'ExitPre', -- before exiting
'FileAppendCmd', -- append to a file using command
@@ -132,18 +133,14 @@ return {
nvim_specific = {
BufModifiedSet=true,
DiagnosticChanged=true,
- DirChanged=true,
RecordingEnter=true,
RecordingLeave=true,
Signal=true,
- TabClosed=true,
- TabNew=true,
TabNewEntered=true,
TermClose=true,
TermOpen=true,
UIEnter=true,
UILeave=true,
- WinClosed=true,
WinScrolled=true,
},
}
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
index dfba18b11d..9117dde089 100644
--- a/src/nvim/autocmd.c
+++ b/src/nvim/autocmd.c
@@ -1517,12 +1517,13 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io,
|| event == EVENT_CMDLINELEAVE || event == EVENT_CMDWINENTER
|| event == EVENT_CMDWINLEAVE || event == EVENT_CMDUNDEFINED
|| event == EVENT_COLORSCHEME || event == EVENT_COLORSCHEMEPRE
- || event == EVENT_DIRCHANGED || event == EVENT_FILETYPE
- || event == EVENT_FUNCUNDEFINED || event == EVENT_MODECHANGED
- || event == EVENT_OPTIONSET || event == EVENT_QUICKFIXCMDPOST
- || event == EVENT_QUICKFIXCMDPRE || event == EVENT_REMOTEREPLY
- || event == EVENT_SPELLFILEMISSING || event == EVENT_SYNTAX
- || event == EVENT_SIGNAL || event == EVENT_TABCLOSED
+ || event == EVENT_DIRCHANGED || event == EVENT_DIRCHANGEDPRE
+ || event == EVENT_FILETYPE || event == EVENT_FUNCUNDEFINED
+ || event == EVENT_MODECHANGED || event == EVENT_OPTIONSET
+ || event == EVENT_QUICKFIXCMDPOST || event == EVENT_QUICKFIXCMDPRE
+ || event == EVENT_REMOTEREPLY || event == EVENT_SPELLFILEMISSING
+ || event == EVENT_SYNTAX || event == EVENT_SIGNAL
+ || event == EVENT_TABCLOSED || event == EVENT_USER
|| event == EVENT_WINCLOSED) {
fname = vim_strsave(fname);
} else {
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 38b045b31c..9e82b4e80b 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -1441,7 +1441,7 @@ void set_curbuf(buf_T *buf, int action)
set_bufref(&prevbufref, prevbuf);
set_bufref(&newbufref, buf);
- // Autocommands may delete the curren buffer and/or the buffer we want to go
+ // Autocommands may delete the current buffer and/or the buffer we want to go
// to. In those cases don't close the buffer.
if (!apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, false, curbuf)
|| (bufref_valid(&prevbufref) && bufref_valid(&newbufref)
@@ -1454,6 +1454,7 @@ void set_curbuf(buf_T *buf, int action)
}
if (bufref_valid(&prevbufref) && !aborting()) {
win_T *previouswin = curwin;
+
// Do not sync when in Insert mode and the buffer is open in
// another window, might be a timer doing something in another
// window.
@@ -3438,8 +3439,12 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use
if (stl_items == NULL) {
stl_items = xmalloc(sizeof(stl_item_t) * stl_items_len);
stl_groupitems = xmalloc(sizeof(int) * stl_items_len);
- stl_hltab = xmalloc(sizeof(stl_hlrec_t) * stl_items_len);
- stl_tabtab = xmalloc(sizeof(StlClickRecord) * stl_items_len);
+
+ // Allocate one more, because the last element is used to indicate the
+ // end of the list.
+ stl_hltab = xmalloc(sizeof(stl_hlrec_t) * (stl_items_len + 1));
+ stl_tabtab = xmalloc(sizeof(StlClickRecord) * (stl_items_len + 1));
+
stl_separator_locations = xmalloc(sizeof(int) * stl_items_len);
}
@@ -3514,8 +3519,8 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use
stl_items = xrealloc(stl_items, sizeof(stl_item_t) * new_len);
stl_groupitems = xrealloc(stl_groupitems, sizeof(int) * new_len);
- stl_hltab = xrealloc(stl_hltab, sizeof(stl_hlrec_t) * new_len);
- stl_tabtab = xrealloc(stl_tabtab, sizeof(StlClickRecord) * new_len);
+ stl_hltab = xrealloc(stl_hltab, sizeof(stl_hlrec_t) * (new_len + 1));
+ stl_tabtab = xrealloc(stl_tabtab, sizeof(StlClickRecord) * (new_len + 1));
stl_separator_locations =
xrealloc(stl_separator_locations, sizeof(int) * new_len);
@@ -5490,11 +5495,19 @@ static int buf_signcols_inner(buf_T *buf, int maximum)
int buf_signcols(buf_T *buf, int maximum)
{
+ // The maximum can be determined from 'signcolumn' which is window scoped so
+ // need to invalidate signcols if the maximum is greater than the previous
+ // maximum.
+ if (maximum > buf->b_signcols_max) {
+ buf->b_signcols_valid = false;
+ }
+
if (!buf->b_signcols_valid) {
int signcols = buf_signcols_inner(buf, maximum);
// Check if we need to redraw
if (signcols != buf->b_signcols) {
buf->b_signcols = signcols;
+ buf->b_signcols_max = maximum;
redraw_buf_later(buf, NOT_VALID);
}
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 7ae5df164f..1e0c837056 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -864,6 +864,7 @@ struct file_buffer {
sign_entry_T *b_signlist; // list of placed signs
int b_signcols; // last calculated number of sign columns
bool b_signcols_valid; // calculated sign columns is valid
+ int b_signcols_max; // Maximum value b_signcols is valid for.
Terminal *terminal; // Terminal instance associated with the buffer
@@ -1353,6 +1354,7 @@ struct window_S {
// recomputed
int w_nrwidth; // width of 'number' and 'relativenumber'
// column being used
+ int w_scwidth; // width of 'signcolumn'
/*
* === end of cached values ===
diff --git a/src/nvim/change.c b/src/nvim/change.c
index 6ac759d5e0..736867b6d3 100644
--- a/src/nvim/change.c
+++ b/src/nvim/change.c
@@ -223,19 +223,20 @@ static void changed_common(linenr_T lnum, colnr_T col, linenr_T lnume, long xtra
// values for the cursor.
// Update the folds for this window. Can't postpone this, because
// a following operator might work on the whole fold: ">>dd".
- foldUpdate(wp, lnum, lnume + xtra - 1);
+ linenr_T last = lnume + xtra - 1; // last line after the change
+ foldUpdate(wp, lnum, last);
// The change may cause lines above or below the change to become
// included in a fold. Set lnum/lnume to the first/last line that
// might be displayed differently.
// Set w_cline_folded here as an efficient way to update it when
- // inserting lines just above a closed fold. */
+ // inserting lines just above a closed fold.
bool folded = hasFoldingWin(wp, lnum, &lnum, NULL, false, NULL);
if (wp->w_cursor.lnum == lnum) {
wp->w_cline_folded = folded;
}
- folded = hasFoldingWin(wp, lnume, NULL, &lnume, false, NULL);
- if (wp->w_cursor.lnum == lnume) {
+ folded = hasFoldingWin(wp, last, NULL, &last, false, NULL);
+ if (wp->w_cursor.lnum == last) {
wp->w_cline_folded = folded;
}
diff --git a/src/nvim/charset.c b/src/nvim/charset.c
index 583a040ed1..f4882e57e1 100644
--- a/src/nvim/charset.c
+++ b/src/nvim/charset.c
@@ -1439,7 +1439,7 @@ bool vim_isblankline(char_u *lbuf)
/// @param unptr Returns the unsigned result.
/// @param maxlen Max length of string to check.
/// @param strict If true, fail if the number has unexpected trailing
-/// alpha-numeric chars: *len is set to 0 and nothing else is
+/// alphanumeric chars: *len is set to 0 and nothing else is
/// returned.
void vim_str2nr(const char_u *const start, int *const prep, int *const len, const int what,
varnumber_T *const nptr, uvarnumber_T *const unptr, const int maxlen,
@@ -1585,7 +1585,7 @@ vim_str2nr_hex:
#undef PARSE_NUMBER
vim_str2nr_proceed:
- // Check for an alpha-numeric character immediately following, that is
+ // Check for an alphanumeric character immediately following, that is
// most likely a typo.
if (strict && ptr - (const char *)start != maxlen && ASCII_ISALNUM(*ptr)) {
return;
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index c6baa105b0..3763390c22 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -3225,7 +3225,7 @@ static void getchar_common(typval_T *argvars, typval_T *rettv)
set_vim_var_nr(VV_MOUSE_COL, 0);
rettv->vval.v_number = n;
- if (IS_SPECIAL(n) || mod_mask != 0) {
+ if (n != 0 && (IS_SPECIAL(n) || mod_mask != 0)) {
char_u temp[10]; // modifier: 3, mbyte-char: 6, NUL: 1
int i = 0;
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 4dba0b97ed..48749afcb3 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -4141,7 +4141,11 @@ static linenr_T get_address(exarg_T *eap, char_u **ptr, cmd_addr_T addr_type, in
if (!ascii_isdigit(*cmd)) { // '+' is '+1', but '+0' is not '+1'
n = 1;
} else {
- n = getdigits(&cmd, true, 0);
+ n = getdigits(&cmd, false, MAXLNUM);
+ if (n == MAXLNUM) {
+ emsg(_(e_line_number_out_of_range));
+ goto error;
+ }
}
if (addr_type == ADDR_TABS_RELATIVE) {
@@ -4160,6 +4164,10 @@ static linenr_T get_address(exarg_T *eap, char_u **ptr, cmd_addr_T addr_type, in
if (i == '-') {
lnum -= n;
} else {
+ if (n >= LONG_MAX - lnum) {
+ emsg(_(e_line_number_out_of_range));
+ goto error;
+ }
lnum += n;
}
}
@@ -5164,6 +5172,24 @@ char_u *get_command_name(expand_T *xp, int idx)
return cmdnames[idx].cmd_name;
}
+/// Check for a valid user command name
+///
+/// If the given {name} is valid, then a pointer to the end of the valid name is returned.
+/// Otherwise, returns NULL.
+char *uc_validate_name(char *name)
+{
+ if (ASCII_ISALPHA(*name)) {
+ while (ASCII_ISALNUM(*name)) {
+ name++;
+ }
+ }
+ if (!ends_excmd(*name) && !ascii_iswhite(*name)) {
+ return NULL;
+ }
+
+ return name;
+}
+
int uc_add_command(char_u *name, size_t name_len, char_u *rep, uint32_t argt, long def, int flags,
int compl, char_u *compl_arg, LuaRef compl_luaref, cmd_addr_T addr_type,
LuaRef luaref, bool force)
@@ -5679,23 +5705,18 @@ static void ex_command(exarg_T *eap)
// Get the name (if any) and skip to the following argument.
name = p;
- if (ASCII_ISALPHA(*p)) {
- while (ASCII_ISALNUM(*p)) {
- p++;
- }
- }
- if (!ends_excmd(*p) && !ascii_iswhite(*p)) {
+ end = (char_u *)uc_validate_name((char *)name);
+ if (!end) {
emsg(_("E182: Invalid command name"));
return;
}
- end = p;
- name_len = (int)(end - name);
+ name_len = (size_t)(end - name);
// If there is nothing after the name, and no attributes were specified,
// we are listing commands
p = skipwhite(end);
if (!has_attr && ends_excmd(*p)) {
- uc_list(name, end - name);
+ uc_list(name, name_len);
} else if (!ASCII_ISUPPER(*name)) {
emsg(_("E183: User defined commands must start with an uppercase letter"));
} else if (name_len <= 4 && STRNCMP(name, "Next", name_len) == 0) {
@@ -5703,7 +5724,7 @@ static void ex_command(exarg_T *eap)
} else if (compl > 0 && (argt & EX_EXTRA) == 0) {
emsg(_(e_complete_used_without_nargs));
} else {
- uc_add_command(name, end - name, p, argt, def, flags, compl, compl_arg, LUA_NOREF,
+ uc_add_command(name, name_len, p, argt, def, flags, compl, compl_arg, LUA_NOREF,
addr_type_arg, LUA_NOREF, eap->forceit);
}
}
@@ -7485,7 +7506,7 @@ static void ex_edit(exarg_T *eap)
do_exedit(eap, NULL);
}
-/// ":edit <file>" command and alikes.
+/// ":edit <file>" command and alike.
///
/// @param old_curwin curwin before doing a split or NULL
void do_exedit(exarg_T *eap, win_T *old_curwin)
@@ -7784,7 +7805,7 @@ static char_u *get_prevdir(CdScope scope)
/// Deal with the side effects of changing the current directory.
///
/// @param scope Scope of the function call (global, tab or window).
-void post_chdir(CdScope scope, bool trigger_dirchanged)
+static void post_chdir(CdScope scope, bool trigger_dirchanged)
{
// Always overwrite the window-local CWD.
XFREE_CLEAR(curwin->w_localdir);
@@ -7825,7 +7846,7 @@ void post_chdir(CdScope scope, bool trigger_dirchanged)
shorten_fnames(true);
if (trigger_dirchanged) {
- do_autocmd_dirchanged(cwd, scope, kCdCauseManual);
+ do_autocmd_dirchanged(cwd, scope, kCdCauseManual, false);
}
}
@@ -7869,10 +7890,13 @@ bool changedir_func(char_u *new_dir, CdScope scope)
}
bool dir_differs = pdir == NULL || pathcmp((char *)pdir, (char *)new_dir, -1) != 0;
- if (dir_differs && vim_chdir(new_dir) != 0) {
- emsg(_(e_failed));
- xfree(pdir);
- return false;
+ if (dir_differs) {
+ do_autocmd_dirchanged((char *)new_dir, scope, kCdCauseManual, true);
+ if (vim_chdir(new_dir) != 0) {
+ emsg(_(e_failed));
+ xfree(pdir);
+ return false;
+ }
}
char_u **pp;
diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c
index 25dbf680de..d0f7a91d6c 100644
--- a/src/nvim/file_search.c
+++ b/src/nvim/file_search.c
@@ -1600,11 +1600,13 @@ theend:
return file_name;
}
-void do_autocmd_dirchanged(char *new_dir, CdScope scope, CdCause cause)
+void do_autocmd_dirchanged(char *new_dir, CdScope scope, CdCause cause, bool pre)
{
static bool recursive = false;
- if (recursive || !has_event(EVENT_DIRCHANGED)) {
+ event_T event = pre ? EVENT_DIRCHANGEDPRE : EVENT_DIRCHANGED;
+
+ if (recursive || !has_event(event)) {
// No autocommand was defined or we changed
// the directory from this autocommand.
return;
@@ -1638,8 +1640,12 @@ void do_autocmd_dirchanged(char *new_dir, CdScope scope, CdCause cause)
new_dir = new_dir_buf;
#endif
+ if (pre) {
+ tv_dict_add_str(dict, S_LEN("directory"), new_dir);
+ } else {
+ tv_dict_add_str(dict, S_LEN("cwd"), new_dir);
+ }
tv_dict_add_str(dict, S_LEN("scope"), buf); // -V614
- tv_dict_add_str(dict, S_LEN("cwd"), new_dir);
tv_dict_add_bool(dict, S_LEN("changed_window"), cause == kCdCauseWindow);
tv_dict_set_keys_readonly(dict);
@@ -1655,8 +1661,7 @@ void do_autocmd_dirchanged(char *new_dir, CdScope scope, CdCause cause)
abort();
}
- apply_autocmds(EVENT_DIRCHANGED, (char_u *)buf, (char_u *)new_dir, false,
- curbuf);
+ apply_autocmds(event, (char_u *)buf, (char_u *)new_dir, false, curbuf);
restore_v_event(dict, &save_v_event);
@@ -1682,12 +1687,16 @@ int vim_chdirfile(char_u *fname, CdCause cause)
return OK;
}
+ if (cause != kCdCauseOther) {
+ do_autocmd_dirchanged(dir, kCdScopeWindow, cause, true);
+ }
+
if (os_chdir(dir) != 0) {
return FAIL;
}
if (cause != kCdCauseOther) {
- do_autocmd_dirchanged(dir, kCdScopeWindow, cause);
+ do_autocmd_dirchanged(dir, kCdScopeWindow, cause, false);
}
return OK;
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index 5d8a8ddbfe..34cde9a7c4 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -1004,20 +1004,9 @@ int ins_char_typebuf(int c, int modifier)
buf[len + 2] = (char_u)K_THIRD(c);
buf[len + 3] = NUL;
} else {
- char_u *p = buf + len;
- int char_len = utf_char2bytes(c, p);
- len += char_len;
- // If the character contains K_SPECIAL bytes they need escaping.
- for (int i = char_len; --i >= 0; p++) {
- if ((uint8_t)(*p) == K_SPECIAL) {
- memmove(p + 3, p + 1, (size_t)i);
- *p++ = K_SPECIAL;
- *p++ = KS_SPECIAL;
- *p = KE_FILLER;
- len += 2;
- }
- }
- *p = NUL;
+ char_u *end = add_char2buf(c, buf + len);
+ *end = NUL;
+ len = (int)(end - buf);
}
(void)ins_typebuf(buf, KeyNoremap, 0, !KeyTyped, cmd_silent);
return len;
@@ -2466,7 +2455,7 @@ static int vgetorpeek(bool advance)
/// 1. a scriptfile
/// 2. the keyboard
///
-/// As much characters as we can get (up to 'maxlen') are put in "buf" and
+/// As many characters as we can get (up to 'maxlen') are put in "buf" and
/// NUL terminated (buffer length must be 'maxlen' + 1).
/// Minimum for "maxlen" is 3!!!!
///
@@ -2679,8 +2668,7 @@ void set_maparg_lhs_rhs(const char_u *orig_lhs, const size_t orig_lhs_len,
mapargs->orig_rhs_len = 0;
// stores <lua>ref_no<cr> in map_str
mapargs->rhs_len = (size_t)vim_snprintf(S_LEN(tmp_buf), "%c%c%c%d\r", K_SPECIAL,
- (char_u)KEY2TERMCAP0(K_LUA), KEY2TERMCAP1(K_LUA),
- rhs_lua);
+ (char_u)KS_EXTRA, KE_LUA, rhs_lua);
mapargs->rhs = vim_strsave((char_u *)tmp_buf);
}
@@ -3434,8 +3422,8 @@ static void showmap(mapblock_T *mp, bool local)
{
size_t len = 1;
- if (message_filtered(mp->m_keys)
- && mp->m_str != NULL && message_filtered(mp->m_str)) {
+ if (message_filtered(mp->m_keys) && message_filtered(mp->m_str)
+ && (mp->m_desc == NULL || message_filtered((char_u *)mp->m_desc))) {
return;
}
@@ -3484,7 +3472,7 @@ static void showmap(mapblock_T *mp, bool local)
char msg[100];
snprintf(msg, sizeof(msg), "<Lua function %d>", mp->m_luaref);
msg_puts_attr(msg, HL_ATTR(HLF_8));
- } else if (mp->m_str == NULL) {
+ } else if (mp->m_str[0] == NUL) {
msg_puts_attr("<Nop>", HL_ATTR(HLF_8));
} else {
// Remove escaping of K_SPECIAL, because "m_str" is in a format to be used
@@ -3584,8 +3572,7 @@ int map_to_exists_mode(const char *const rhs, const int mode, const bool abbr)
mp = maphash[hash];
}
for (; mp; mp = mp->m_next) {
- if ((mp->m_mode & mode)
- && mp->m_str != NULL && strstr((char *)mp->m_str, rhs) != NULL) {
+ if ((mp->m_mode & mode) && strstr((char *)mp->m_str, rhs) != NULL) {
return true;
}
}
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 98a38c5fe2..5aa564623f 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -1002,6 +1002,8 @@ EXTERN char e_cannot_define_autocommands_for_all_events[] INIT(= N_("E1155: Cann
EXTERN char e_resulting_text_too_long[] INIT(= N_("E1240: Resulting text too long"));
+EXTERN char e_line_number_out_of_range[] INIT(= N_("E1247: Line number out of range"));
+
EXTERN char e_highlight_group_name_too_long[] INIT(= N_("E1249: Highlight group name too long"));
EXTERN char top_bot_msg[] INIT(= N_("search hit TOP, continuing at BOTTOM"));
diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c
index fcd91cdf16..e43a56086f 100644
--- a/src/nvim/highlight.c
+++ b/src/nvim/highlight.c
@@ -800,6 +800,7 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e
{
HlAttrs hlattrs = HLATTRS_INIT;
int32_t fg = -1, bg = -1, ctermfg = -1, ctermbg = -1, sp = -1;
+ int blend = -1;
int16_t mask = 0;
int16_t cterm_mask = 0;
bool cterm_mask_provided = false;
@@ -821,27 +822,41 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e
CHECK_FLAG(dict, mask, global, , HL_GLOBAL);
if (HAS_KEY(dict->fg)) {
- fg = object_to_color(dict->fg, "fg", err);
+ fg = object_to_color(dict->fg, "fg", true, err);
} else if (HAS_KEY(dict->foreground)) {
- fg = object_to_color(dict->foreground, "foreground", err);
+ fg = object_to_color(dict->foreground, "foreground", true, err);
}
if (ERROR_SET(err)) {
return hlattrs;
}
if (HAS_KEY(dict->bg)) {
- bg = object_to_color(dict->bg, "bg", err);
+ bg = object_to_color(dict->bg, "bg", true, err);
} else if (HAS_KEY(dict->background)) {
- bg = object_to_color(dict->background, "background", err);
+ bg = object_to_color(dict->background, "background", true, err);
}
if (ERROR_SET(err)) {
return hlattrs;
}
if (HAS_KEY(dict->sp)) {
- sp = object_to_color(dict->sp, "sp", err);
+ sp = object_to_color(dict->sp, "sp", true, err);
} else if (HAS_KEY(dict->special)) {
- sp = object_to_color(dict->special, "special", err);
+ sp = object_to_color(dict->special, "special", true, err);
+ }
+ if (ERROR_SET(err)) {
+ return hlattrs;
+ }
+
+ if (dict->blend.type == kObjectTypeInteger) {
+ Integer blend0 = dict->blend.data.integer;
+ if (blend0 < 0 || blend0 > 100) {
+ api_set_error(err, kErrorTypeValidation, "'blend' is not between 0 to 100");
+ } else {
+ blend = (int)blend0;
+ }
+ } else if (HAS_KEY(dict->blend)) {
+ api_set_error(err, kErrorTypeValidation, "'blend' must be an integer");
}
if (ERROR_SET(err)) {
return hlattrs;
@@ -876,20 +891,24 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e
CHECK_FLAG(cterm, cterm_mask, strikethrough, , HL_STRIKETHROUGH);
CHECK_FLAG(cterm, cterm_mask, nocombine, , HL_NOCOMBINE);
+ } else if (dict->cterm.type == kObjectTypeArray && dict->cterm.data.array.size == 0) {
+ // empty list from Lua API should clear all cterm attributes
+ // TODO(clason): handle via gen_api_dispatch
+ cterm_mask_provided = true;
} else if (HAS_KEY(dict->cterm)) {
api_set_error(err, kErrorTypeValidation, "'cterm' must be a Dictionary.");
}
#undef CHECK_FLAG
if (HAS_KEY(dict->ctermfg)) {
- ctermfg = object_to_color(dict->ctermfg, "ctermfg", err);
+ ctermfg = object_to_color(dict->ctermfg, "ctermfg", false, err);
if (ERROR_SET(err)) {
return hlattrs;
}
}
if (HAS_KEY(dict->ctermbg)) {
- ctermbg = object_to_color(dict->ctermbg, "ctermbg", err);
+ ctermbg = object_to_color(dict->ctermbg, "ctermbg", false, err);
if (ERROR_SET(err)) {
return hlattrs;
}
@@ -904,28 +923,39 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e
hlattrs.rgb_bg_color = bg;
hlattrs.rgb_fg_color = fg;
hlattrs.rgb_sp_color = sp;
- hlattrs.cterm_bg_color =
- ctermbg == -1 ? cterm_normal_bg_color : ctermbg + 1;
- hlattrs.cterm_fg_color =
- ctermfg == -1 ? cterm_normal_fg_color : ctermfg + 1;
+ hlattrs.hl_blend = blend;
+ hlattrs.cterm_bg_color = ctermbg == -1 ? 0 : ctermbg + 1;
+ hlattrs.cterm_fg_color = ctermfg == -1 ? 0 : ctermfg + 1;
hlattrs.cterm_ae_attr = cterm_mask;
} else {
hlattrs.cterm_ae_attr = cterm_mask;
- hlattrs.cterm_bg_color = bg == -1 ? cterm_normal_bg_color : bg + 1;
- hlattrs.cterm_fg_color = fg == -1 ? cterm_normal_fg_color : fg + 1;
+ hlattrs.cterm_bg_color = bg == -1 ? 0 : bg + 1;
+ hlattrs.cterm_fg_color = fg == -1 ? 0 : fg + 1;
}
return hlattrs;
}
-int object_to_color(Object val, char *key, Error *err)
+int object_to_color(Object val, char *key, bool rgb, Error *err)
{
if (val.type == kObjectTypeInteger) {
return (int)val.data.integer;
} else if (val.type == kObjectTypeString) {
String str = val.data.string;
// TODO(bfredl): be more fancy with "bg", "fg" etc
- return str.size ? name_to_color(str.data) : 0;
+ if (!str.size || STRICMP(str.data, "NONE") == 0) {
+ return -1;
+ }
+ int color;
+ if (rgb) {
+ color = name_to_color(str.data);
+ } else {
+ color = name_to_ctermcolor(str.data);
+ }
+ if (color < 0) {
+ api_set_error(err, kErrorTypeValidation, "'%s' is not a valid color", str.data);
+ }
+ return color;
} else {
api_set_error(err, kErrorTypeValidation, "'%s' must be string or integer", key);
return 0;
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index cbfb8364f6..029e7eb660 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -1241,6 +1241,9 @@ void ex_luafile(exarg_T *const eap)
/// execute lua code from a file.
///
+/// Note: we call the lua global loadfile as opposed to calling luaL_loadfile
+/// in case loadfile has been overridden in the users environment.
+///
/// @param path path of the file
///
/// @return true if everything ok, false if there was an error (echoed)
@@ -1249,11 +1252,30 @@ bool nlua_exec_file(const char *path)
{
lua_State *const lstate = global_lstate;
- if (luaL_loadfile(lstate, path)) {
+ lua_getglobal(lstate, "loadfile");
+ lua_pushstring(lstate, path);
+
+ if (nlua_pcall(lstate, 1, 2)) {
+ nlua_error(lstate, _("E5111: Error calling lua: %.*s"));
+ return false;
+ }
+
+ // loadstring() returns either:
+ // 1. nil, error
+ // 2. chunk, nil
+
+ if (lua_isnil(lstate, -2)) {
+ // 1
nlua_error(lstate, _("E5112: Error while creating lua chunk: %.*s"));
+ assert(lua_isnil(lstate, -1));
+ lua_pop(lstate, 1);
return false;
}
+ // 2
+ assert(lua_isnil(lstate, -1));
+ lua_pop(lstate, 1);
+
if (nlua_pcall(lstate, 0, 0)) {
nlua_error(lstate, _("E5113: Error while calling lua chunk: %.*s"));
return false;
diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c
index e5fa80a242..f634c7dda8 100644
--- a/src/nvim/mbyte.c
+++ b/src/nvim/mbyte.c
@@ -1317,6 +1317,12 @@ bool mb_isupper(int a)
return mb_tolower(a) != a;
}
+bool mb_isalpha(int a)
+ FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ return mb_islower(a) || mb_isupper(a);
+}
+
static int utf_strnicmp(const char_u *s1, const char_u *s2, size_t n1, size_t n2)
{
int c1, c2, cdiff;
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 21c465434a..7fe6469527 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -824,15 +824,12 @@ static bool normal_get_command_count(NormalState *s)
if (s->c == K_DEL || s->c == K_KDEL) {
s->ca.count0 /= 10;
del_from_showcmd(4); // delete the digit and ~@%
+ } else if (s->ca.count0 > 99999999L) {
+ s->ca.count0 = 999999999L;
} else {
s->ca.count0 = s->ca.count0 * 10 + (s->c - '0');
}
- if (s->ca.count0 < 0) {
- // overflow
- s->ca.count0 = 999999999L;
- }
-
// Set v:count here, when called from main() and not a stuffed
// command, so that v:count can be used in an expression mapping
// right after the count. Do set it for redo.
@@ -1046,14 +1043,14 @@ static int normal_execute(VimState *state, int key)
// If you give a count before AND after the operator, they are
// multiplied.
if (s->ca.count0) {
- s->ca.count0 = (long)((uint64_t)s->ca.count0 * (uint64_t)s->ca.opcount);
+ if (s->ca.opcount >= 999999999L / s->ca.count0) {
+ s->ca.count0 = 999999999L;
+ } else {
+ s->ca.count0 *= s->ca.opcount;
+ }
} else {
s->ca.count0 = s->ca.opcount;
}
- if (s->ca.count0 < 0) {
- // overflow
- s->ca.count0 = 999999999L;
- }
}
// Always remember the count. It will be set to zero (on the next call,
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index c9a99fef84..b5c7020dee 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -1961,11 +1961,14 @@ static int op_replace(oparg_T *oap, int c)
while (ltoreq(curwin->w_cursor, oap->end)) {
n = gchar_cursor();
if (n != NUL) {
- if (utf_char2len(c) > 1 || utf_char2len(n) > 1) {
+ int new_byte_len = utf_char2len(c);
+ int old_byte_len = utfc_ptr2len(get_cursor_pos_ptr());
+
+ if (new_byte_len > 1 || old_byte_len > 1) {
// This is slow, but it handles replacing a single-byte
// with a multi-byte and the other way around.
if (curwin->w_cursor.lnum == oap->end.lnum) {
- oap->end.col += utf_char2len(c) - utf_char2len(n);
+ oap->end.col += new_byte_len - old_byte_len;
}
replace_character(c);
} else {
@@ -2315,33 +2318,24 @@ void op_insert(oparg_T *oap, long count1)
// The user may have moved the cursor before inserting something, try
// to adjust the block for that. But only do it, if the difference
// does not come from indent kicking in.
- if (oap->start.lnum == curbuf->b_op_start_orig.lnum
- && !bd.is_MAX
- && !did_indent) {
+ if (oap->start.lnum == curbuf->b_op_start_orig.lnum && !bd.is_MAX && !did_indent) {
const int t = getviscol2(curbuf->b_op_start_orig.col, curbuf->b_op_start_orig.coladd);
- if (!bd.is_MAX) {
- if (oap->op_type == OP_INSERT
- && oap->start.col + oap->start.coladd
- != curbuf->b_op_start_orig.col + curbuf->b_op_start_orig.coladd) {
- oap->start.col = curbuf->b_op_start_orig.col;
- pre_textlen -= t - oap->start_vcol;
- oap->start_vcol = t;
- } else if (oap->op_type == OP_APPEND
- && oap->start.col + oap->start.coladd
- >= curbuf->b_op_start_orig.col
- + curbuf->b_op_start_orig.coladd) {
- oap->start.col = curbuf->b_op_start_orig.col;
- // reset pre_textlen to the value of OP_INSERT
- pre_textlen += bd.textlen;
- pre_textlen -= t - oap->start_vcol;
- oap->start_vcol = t;
- oap->op_type = OP_INSERT;
- }
- } else if (bd.is_MAX && oap->op_type == OP_APPEND) {
+ if (oap->op_type == OP_INSERT
+ && oap->start.col + oap->start.coladd
+ != curbuf->b_op_start_orig.col + curbuf->b_op_start_orig.coladd) {
+ oap->start.col = curbuf->b_op_start_orig.col;
+ pre_textlen -= t - oap->start_vcol;
+ oap->start_vcol = t;
+ } else if (oap->op_type == OP_APPEND
+ && oap->start.col + oap->start.coladd
+ >= curbuf->b_op_start_orig.col + curbuf->b_op_start_orig.coladd) {
+ oap->start.col = curbuf->b_op_start_orig.col;
// reset pre_textlen to the value of OP_INSERT
pre_textlen += bd.textlen;
pre_textlen -= t - oap->start_vcol;
+ oap->start_vcol = t;
+ oap->op_type = OP_INSERT;
}
}
@@ -3320,18 +3314,28 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
}
}
- // insert the new text
+ // Insert the new text.
+ // First check for multiplication overflow.
+ if (yanklen + spaces != 0
+ && count > ((INT_MAX - (bd.startspaces + bd.endspaces)) / (yanklen + spaces))) {
+ emsg(_(e_resulting_text_too_long));
+ break;
+ }
+
totlen = (size_t)(count * (yanklen + spaces)
+ bd.startspaces + bd.endspaces);
int addcount = (int)totlen + lines_appended;
newp = (char_u *)xmalloc(totlen + oldlen + 1);
+
// copy part up to cursor to new line
ptr = newp;
memmove(ptr, oldp, (size_t)bd.textcol);
ptr += bd.textcol;
+
// may insert some spaces before the new text
memset(ptr, ' ', (size_t)bd.startspaces);
ptr += bd.startspaces;
+
// insert the new text
for (long j = 0; j < count; j++) {
memmove(ptr, y_array[i], (size_t)yanklen);
@@ -3345,9 +3349,11 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
addcount -= spaces;
}
}
+
// may insert some spaces after the new text
memset(ptr, ' ', (size_t)bd.endspaces);
ptr += bd.endspaces;
+
// move the text after the cursor to the end of the line.
int columns = (int)oldlen - bd.textcol - delcount + 1;
assert(columns >= 0);
@@ -3436,10 +3442,18 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
}
}
- do {
+ if (count == 0 || yanklen == 0) {
+ if (VIsual_active) {
+ lnum = end_lnum;
+ }
+ } else if (count > INT_MAX / yanklen) {
+ // multiplication overflow
+ emsg(_(e_resulting_text_too_long));
+ } else {
totlen = (size_t)(count * yanklen);
- if (totlen > 0) {
+ do {
oldp = ml_get(lnum);
+ oldlen = STRLEN(oldp);
if (lnum > start_lnum) {
pos_T pos = {
.lnum = lnum,
@@ -3450,11 +3464,11 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
col = MAXCOL;
}
}
- if (VIsual_active && col > (int)STRLEN(oldp)) {
+ if (VIsual_active && col > (colnr_T)oldlen) {
lnum++;
continue;
}
- newp = (char_u *)xmalloc((size_t)(STRLEN(oldp) + totlen + 1));
+ newp = (char_u *)xmalloc(totlen + oldlen + 1);
memmove(newp, oldp, (size_t)col);
ptr = newp + col;
for (i = 0; i < (size_t)count; i++) {
@@ -3476,14 +3490,14 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
changed_bytes(lnum, col);
extmark_splice_cols(curbuf, (int)lnum-1, col,
0, (int)totlen, kExtmarkUndo);
- }
- if (VIsual_active) {
- lnum++;
- }
- } while (VIsual_active && lnum <= end_lnum);
+ if (VIsual_active) {
+ lnum++;
+ }
+ } while (VIsual_active && lnum <= end_lnum);
- if (VIsual_active) { // reset lnum to the last visual line
- lnum--;
+ if (VIsual_active) { // reset lnum to the last visual line
+ lnum--;
+ }
}
// put '] at the first byte of the last character
@@ -5697,7 +5711,9 @@ static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type, const char_u *str
// When appending, copy the previous line and free it after.
size_t extra = append ? STRLEN(pp[--lnum]) : 0;
char_u *s = xmallocz(line_len + extra);
- memcpy(s, pp[lnum], extra);
+ if (extra > 0) {
+ memcpy(s, pp[lnum], extra);
+ }
memcpy(s + extra, start, line_len);
size_t s_len = extra + line_len;
diff --git a/src/nvim/option.c b/src/nvim/option.c
index c8e50d4494..4ec6ee3148 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -4277,7 +4277,7 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf,
}
// Save the global value before changing anything. This is needed as for
- // a global-only option setting the "local value" infact sets the global
+ // a global-only option setting the "local value" in fact sets the global
// value (since there is only one value).
if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) {
old_global_value = *(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL);
@@ -8165,7 +8165,7 @@ int win_signcol_configured(win_T *wp, int *is_fixed)
}
int needed_signcols = buf_signcols(wp->w_buffer, maximum);
- int ret = MAX(minimum, needed_signcols);
+ int ret = MAX(minimum, MIN(maximum, needed_signcols));
assert(ret <= SIGN_SHOW_MAX);
return ret;
}
diff --git a/src/nvim/path.c b/src/nvim/path.c
index 7f7f941e26..d3aa5e5bf2 100644
--- a/src/nvim/path.c
+++ b/src/nvim/path.c
@@ -642,8 +642,7 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, size_t wildoff,
} else if (path_end >= path + wildoff
&& (vim_strchr((char_u *)"*?[{~$", *path_end) != NULL
#ifndef WIN32
- || (!p_fic && (flags & EW_ICASE)
- && isalpha(utf_ptr2char(path_end)))
+ || (!p_fic && (flags & EW_ICASE) && mb_isalpha(utf_ptr2char(path_end)))
#endif
)) {
e = p;
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 15fb6901cc..7fafe3dd6e 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -326,6 +326,18 @@ void redraw_buf_status_later(buf_T *buf)
}
}
+void redraw_win_signcol(win_T *wp)
+{
+ // If we can compute a change in the automatic sizing of the sign column
+ // under 'signcolumn=auto:X' and signs currently placed in the buffer, better
+ // figuring it out here so we can redraw the entire screen for it.
+ int scwidth = wp->w_scwidth;
+ wp->w_scwidth = win_signcol_count(wp);
+ if (wp->w_scwidth != scwidth) {
+ changed_line_abv_curs_win(wp);
+ }
+}
+
/// Redraw the parts of the screen that is marked for redraw.
///
/// Most code shouldn't call this directly, rather use redraw_later() and
@@ -790,12 +802,6 @@ static void win_update(win_T *wp, Providers *providers)
linenr_T mod_bot = 0;
int save_got_int;
-
- // If we can compute a change in the automatic sizing of the sign column
- // under 'signcolumn=auto:X' and signs currently placed in the buffer, better
- // figuring it out here so we can redraw the entire screen for it.
- win_signcol_count(wp);
-
type = wp->w_redr_type;
if (type >= NOT_VALID) {
@@ -817,6 +823,8 @@ static void win_update(win_T *wp, Providers *providers)
return;
}
+ redraw_win_signcol(wp);
+
init_search_hl(wp);
/* Force redraw when width of 'number' or 'relativenumber' column
@@ -1846,7 +1854,7 @@ static void win_draw_end(win_T *wp, int c1, int c2, bool draw_margin, int row, i
win_hl_attr(wp, HLF_FC));
}
// draw the sign column
- int count = win_signcol_count(wp);
+ int count = wp->w_scwidth;
if (count > 0) {
n = win_fill_end(wp, ' ', ' ', n, win_signcol_width(wp) * count, row,
endrow, win_hl_attr(wp, HLF_SC));
@@ -2792,10 +2800,9 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
draw_state = WL_SIGN;
/* Show the sign column when there are any signs in this
* buffer or when using Netbeans. */
- int count = win_signcol_count(wp);
- if (count > 0) {
+ if (wp->w_scwidth > 0) {
get_sign_display_info(false, wp, lnum, sattrs, row,
- startrow, filler_lines, filler_todo, count,
+ startrow, filler_lines, filler_todo,
&c_extra, &c_final, extra, sizeof(extra),
&p_extra, &n_extra,
&char_attr, &draw_state, &sign_idx);
@@ -2814,9 +2821,8 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
// number.
if (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u'
&& num_signs > 0 && sign_get_attr(SIGN_TEXT, sattrs, 0, 1)) {
- int count = win_signcol_count(wp);
get_sign_display_info(true, wp, lnum, sattrs, row,
- startrow, filler_lines, filler_todo, count,
+ startrow, filler_lines, filler_todo,
&c_extra, &c_final, extra, sizeof(extra),
&p_extra, &n_extra,
&char_attr, &draw_state, &sign_idx);
@@ -4674,10 +4680,11 @@ static bool use_cursor_line_sign(win_T *wp, linenr_T lnum)
// @param[in, out] sign_idxp Index of the displayed sign
static void get_sign_display_info(bool nrcol, win_T *wp, linenr_T lnum, sign_attrs_T sattrs[],
int row, int startrow, int filler_lines, int filler_todo,
- int count, int *c_extrap, int *c_finalp, char_u *extra,
+ int *c_extrap, int *c_finalp, char_u *extra,
size_t extra_size, char_u **pp_extra, int *n_extrap,
int *char_attrp, int *draw_statep, int *sign_idxp)
{
+ int count = wp->w_scwidth;
// Draw cells with the sign value or blank.
*c_extrap = ' ';
*c_finalp = NUL;
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index 119f6e811f..2b74c45478 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -6758,16 +6758,26 @@ void set_hl_group(int id, HlAttrs attrs, Dict(highlight) *dict, int link_id)
{ NULL, -1, NIL },
};
+ char hex_name[8];
+ char *name;
+
for (int j = 0; cattrs[j].dest; j++) {
- if (cattrs[j].val != -1) {
+ if (cattrs[j].val < 0) {
+ XFREE_CLEAR(*cattrs[j].dest);
+ continue;
+ }
+
+ if (cattrs[j].name.type == kObjectTypeString && cattrs[j].name.data.string.size) {
+ name = cattrs[j].name.data.string.data;
+ } else {
+ snprintf(hex_name, sizeof(hex_name), "#%06x", cattrs[j].val);
+ name = hex_name;
+ }
+
+ if (!*cattrs[j].dest
+ || STRCMP(*cattrs[j].dest, name) != 0) {
xfree(*cattrs[j].dest);
- if (cattrs[j].name.type == kObjectTypeString && cattrs[j].name.data.string.size) {
- *cattrs[j].dest = xstrdup(cattrs[j].name.data.string.data);
- } else {
- char hex_name[8];
- snprintf(hex_name, sizeof(hex_name), "#%06x", cattrs[j].val);
- *cattrs[j].dest = xstrdup(hex_name);
- }
+ *cattrs[j].dest = xstrdup(name);
}
}
@@ -8849,6 +8859,22 @@ RgbValue name_to_color(const char *name)
return -1;
}
+int name_to_ctermcolor(const char *name)
+{
+ int i;
+ int off = TOUPPER_ASC(*name);
+ for (i = ARRAY_SIZE(color_names); --i >= 0;) {
+ if (off == color_names[i][0]
+ && STRICMP(name+1, color_names[i]+1) == 0) {
+ break;
+ }
+ }
+ if (i < 0) {
+ return -1;
+ }
+ TriState bold = kNone;
+ return lookup_color(i, false, &bold);
+}
/**************************************
* End of Highlighting stuff *
diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim
index c0ac4393c4..5a3d1d56bb 100644
--- a/src/nvim/testdir/test_alot.vim
+++ b/src/nvim/testdir/test_alot.vim
@@ -39,7 +39,8 @@ source test_put.vim
source test_rename.vim
source test_scroll_opt.vim
source test_shift.vim
-source test_sort.vim
+" Test fails on windows CI when using the MSVC compiler.
+" source test_sort.vim
source test_sha256.vim
source test_suspend.vim
source test_syn_attr.vim
diff --git a/src/nvim/testdir/test_autochdir.vim b/src/nvim/testdir/test_autochdir.vim
index 9ad727241e..53ed4617f7 100644
--- a/src/nvim/testdir/test_autochdir.vim
+++ b/src/nvim/testdir/test_autochdir.vim
@@ -64,4 +64,14 @@ func Test_verbose_pwd()
call delete('Xautodir', 'rf')
endfunc
+func Test_multibyte()
+ " using an invalid character should not cause a crash
+ set wic
+ " Except on Windows, E472 is also thrown last, but v8.1.1183 isn't ported yet
+ " call assert_fails('tc û¦*', has('win32') ? 'E480:' : 'E344:')
+ call assert_fails('tc û¦*', has('win32') ? 'E480:' : 'E472:')
+ set nowic
+endfunc
+
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim
index a8d51ef598..c39546b9ea 100644
--- a/src/nvim/testdir/test_autocmd.vim
+++ b/src/nvim/testdir/test_autocmd.vim
@@ -502,7 +502,7 @@ func Test_autocmd_bufwipe_in_SessLoadPost()
[CODE]
call writefile(content, 'Xvimrc')
- call system(v:progpath. ' --headless -i NONE -u Xvimrc --noplugins -S Session.vim -c cq')
+ call system(GetVimCommand('Xvimrc') .. ' --headless --noplugins -S Session.vim -c cq')
let errors = join(readfile('Xerrors'))
call assert_match('E814', errors)
@@ -562,7 +562,7 @@ func Test_autocmd_bufwipe_in_SessLoadPost2()
[CODE]
call writefile(content, 'Xvimrc')
- call system(v:progpath. ' --headless -i NONE -u Xvimrc --noplugins -S Session.vim -c cq')
+ call system(GetVimCommand('Xvimrc') .. ' --headless --noplugins -S Session.vim -c cq')
let errors = join(readfile('Xerrors'))
" This probably only ever matches on unix.
call assert_notmatch('Caught deadly signal SEGV', errors)
@@ -1506,7 +1506,7 @@ func Test_bufunload_all()
call writefile(content, 'Xtest')
call delete('Xout')
- call system(v:progpath. ' -u NORC -i NONE -N -S Xtest')
+ call system(GetVimCommandClean() .. ' -N --headless -S Xtest')
call assert_true(filereadable('Xout'))
call delete('Xxx1')
@@ -1827,6 +1827,14 @@ func Test_autocommand_all_events()
call assert_fails('au * x bwipe', 'E1155:')
endfunc
+func Test_autocmd_user()
+ au User MyEvent let s:res = [expand("<afile>"), expand("<amatch>")]
+ doautocmd User MyEvent
+ call assert_equal(['MyEvent', 'MyEvent'], s:res)
+ au! User
+ unlet s:res
+endfunc
+
function s:Before_test_dirchanged()
augroup test_dirchanged
autocmd!
@@ -1850,14 +1858,16 @@ endfunc
function Test_dirchanged_global()
call s:Before_test_dirchanged()
+ autocmd test_dirchanged DirChangedPre global call add(s:li, expand("<amatch>") .. " pre cd " .. v:event.directory)
autocmd test_dirchanged DirChanged global call add(s:li, "cd:")
autocmd test_dirchanged DirChanged global call add(s:li, expand("<afile>"))
call chdir(s:dir_foo)
- call assert_equal(["cd:", s:dir_foo], s:li)
+ let expected = ["global pre cd " .. s:dir_foo, "cd:", s:dir_foo]
+ call assert_equal(expected, s:li)
call chdir(s:dir_foo)
- call assert_equal(["cd:", s:dir_foo], s:li)
+ call assert_equal(expected, s:li)
exe 'lcd ' .. fnameescape(s:dir_bar)
- call assert_equal(["cd:", s:dir_foo], s:li)
+ call assert_equal(expected, s:li)
call s:After_test_dirchanged()
endfunc
@@ -1879,6 +1889,7 @@ function Test_dirchanged_auto()
CheckOption autochdir
call s:Before_test_dirchanged()
call test_autochdir()
+ autocmd test_dirchanged DirChangedPre auto call add(s:li, "pre cd " .. v:event.directory)
autocmd test_dirchanged DirChanged auto call add(s:li, "auto:")
autocmd test_dirchanged DirChanged auto call add(s:li, expand("<afile>"))
set acd
@@ -1886,7 +1897,8 @@ function Test_dirchanged_auto()
call assert_equal([], s:li)
exe 'edit ' . s:dir_foo . '/Xfile'
call assert_equal(s:dir_foo, getcwd())
- call assert_equal(["auto:", s:dir_foo], s:li)
+ let expected = ["pre cd " .. s:dir_foo, "auto:", s:dir_foo]
+ call assert_equal(expected, s:li)
set noacd
bwipe!
call s:After_test_dirchanged()
diff --git a/src/nvim/testdir/test_breakindent.vim b/src/nvim/testdir/test_breakindent.vim
index b619f2adb6..438edb0257 100644
--- a/src/nvim/testdir/test_breakindent.vim
+++ b/src/nvim/testdir/test_breakindent.vim
@@ -1,7 +1,7 @@
" Test for breakindent
"
" Note: if you get strange failures when adding new tests, it might be that
-" while the test is run, the breakindent cacheing gets in its way.
+" while the test is run, the breakindent caching gets in its way.
" It helps to change the tabstop setting and force a redraw (e.g. see
" Test_breakindent08())
if !exists('+breakindent')
diff --git a/src/nvim/testdir/test_cindent.vim b/src/nvim/testdir/test_cindent.vim
index 5dc54111e7..4b702bf2b8 100644
--- a/src/nvim/testdir/test_cindent.vim
+++ b/src/nvim/testdir/test_cindent.vim
@@ -815,7 +815,7 @@ func Test_cindent_1()
}
}
- public: // <-- this was incoreectly indented before!!
+ public: // <-- this was incorrectly indented before!!
void testfall();
protected:
void testfall();
@@ -1792,7 +1792,7 @@ func Test_cindent_1()
}
}
- public: // <-- this was incoreectly indented before!!
+ public: // <-- this was incorrectly indented before!!
void testfall();
protected:
void testfall();
@@ -5302,9 +5302,12 @@ endfunc
" this was going beyond the end of the line.
func Test_cindent_case()
new
- call setline(1, "case x: // x")
+ call setline(1, 'case x: // x')
set cindent
norm! f:a:
+ call assert_equal('case x:: // x', getline(1))
+
+ set cindent&
bwipe!
endfunc
diff --git a/src/nvim/testdir/test_digraph.vim b/src/nvim/testdir/test_digraph.vim
index d23748a3e3..5965ee48ef 100644
--- a/src/nvim/testdir/test_digraph.vim
+++ b/src/nvim/testdir/test_digraph.vim
@@ -81,7 +81,7 @@ func Test_digraphs()
call Put_Dig(".e")
call Put_Dig("a.") " not defined
call assert_equal(['ḃ', 'ė', '.'], getline(line('.')-2,line('.')))
- " Diaresis
+ " Diaeresis
call Put_Dig("a:")
call Put_Dig(":u")
call Put_Dig("b:") " not defined
@@ -288,7 +288,7 @@ func Test_digraphs_option()
call Put_Dig_BS(".","e")
call Put_Dig_BS("a",".") " not defined
call assert_equal(['ḃ', 'ė', '.'], getline(line('.')-2,line('.')))
- " Diaresis
+ " Diaeresis
call Put_Dig_BS("a",":")
call Put_Dig_BS(":","u")
call Put_Dig_BS("b",":") " not defined
diff --git a/src/nvim/testdir/test_edit.vim b/src/nvim/testdir/test_edit.vim
index a1f6a84a99..360b3aaaa0 100644
--- a/src/nvim/testdir/test_edit.vim
+++ b/src/nvim/testdir/test_edit.vim
@@ -590,7 +590,7 @@ func Test_edit_CTRL_K()
call feedkeys("A\<c-x>\<c-k>\<down>\<down>\<down>\<down>\<cr>\<esc>", 'tnix')
call assert_equal(['AA'], getline(1, '$'))
- " press an unexecpted key after dictionary completion
+ " press an unexpected key after dictionary completion
%d
call setline(1, 'A')
call cursor(1, 1)
diff --git a/src/nvim/testdir/test_excmd.vim b/src/nvim/testdir/test_excmd.vim
index bbf8b4dfc8..8055a51a11 100644
--- a/src/nvim/testdir/test_excmd.vim
+++ b/src/nvim/testdir/test_excmd.vim
@@ -409,4 +409,18 @@ func Test_not_break_expression_register()
call assert_equal('1+1', getreg('=', 1))
endfunc
+func Test_address_line_overflow()
+ throw 'Skipped: v:sizeoflong is N/A' " use legacy/excmd_spec.lua instead
+
+ if v:sizeoflong < 8
+ throw 'Skipped: only works with 64 bit long ints'
+ endif
+ new
+ call setline(1, 'text')
+ call assert_fails('|.44444444444444444444444', 'E1247:')
+ call assert_fails('|.9223372036854775806', 'E1247:')
+ bwipe!
+endfunc
+
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim
index b663032c24..5f4a7dac6e 100644
--- a/src/nvim/testdir/test_filetype.vim
+++ b/src/nvim/testdir/test_filetype.vim
@@ -81,6 +81,7 @@ let s:filename_checks = {
\ 'bc': ['file.bc'],
\ 'bdf': ['file.bdf'],
\ 'bib': ['file.bib'],
+ \ 'bicep': ['file.bicep'],
\ 'beancount': ['file.beancount'],
\ 'bindzone': ['named.root', '/bind/db.file', '/named/db.file', 'any/bind/db.file', 'any/named/db.file'],
\ 'blank': ['file.bl'],
@@ -131,6 +132,7 @@ let s:filename_checks = {
\ 'cvs': ['cvs123'],
\ 'cvsrc': ['.cvsrc'],
\ 'cynpp': ['file.cyn'],
+ \ 'd': ['file.d'],
\ 'dart': ['file.dart', 'file.drt'],
\ 'datascript': ['file.ds'],
\ 'dcd': ['file.dcd'],
@@ -153,6 +155,7 @@ let s:filename_checks = {
\ 'dot': ['file.dot', 'file.gv'],
\ 'dracula': ['file.drac', 'file.drc', 'filelvs', 'filelpe', 'drac.file', 'lpe', 'lvs', 'some-lpe', 'some-lvs'],
\ 'dtd': ['file.dtd'],
+ \ 'dtrace': ['/usr/lib/dtrace/io.d'],
\ 'dts': ['file.dts', 'file.dtsi'],
\ 'dune': ['jbuild', 'dune', 'dune-project', 'dune-workspace'],
\ 'dylan': ['file.dylan'],
@@ -271,6 +274,7 @@ let s:filename_checks = {
\ 'java': ['file.java', 'file.jav'],
\ 'javacc': ['file.jj', 'file.jjt'],
\ 'javascript': ['file.js', 'file.javascript', 'file.es', 'file.mjs', 'file.cjs'],
+ \ 'javascript.glimmer': ['file.gjs'],
\ 'javascriptreact': ['file.jsx'],
\ 'jess': ['file.clp'],
\ 'jgraph': ['file.jgr'],
@@ -477,6 +481,7 @@ let s:filename_checks = {
\ 'skill': ['file.il', 'file.ils', 'file.cdf'],
\ 'slang': ['file.sl'],
\ 'slice': ['file.ice'],
+ \ 'solidity': ['file.sol'],
\ 'solution': ['file.sln'],
\ 'slpconf': ['/etc/slp.conf', 'any/etc/slp.conf'],
\ 'slpreg': ['/etc/slp.reg', 'any/etc/slp.reg'],
@@ -544,6 +549,7 @@ let s:filename_checks = {
\ 'tssgm': ['file.tssgm'],
\ 'tssop': ['file.tssop'],
\ 'twig': ['file.twig'],
+ \ 'typescript.glimmer': ['file.gts'],
\ 'typescriptreact': ['file.tsx'],
\ 'uc': ['file.uc'],
\ 'udevconf': ['/etc/udev/udev.conf', 'any/etc/udev/udev.conf'],
@@ -798,6 +804,42 @@ func Test_bas_file()
filetype off
endfunc
+func Test_d_file()
+ filetype on
+
+ call writefile(['looks like D'], 'Xfile.d')
+ split Xfile.d
+ call assert_equal('d', &filetype)
+ bwipe!
+
+ call writefile(['#!/some/bin/dtrace'], 'Xfile.d')
+ split Xfile.d
+ call assert_equal('dtrace', &filetype)
+ bwipe!
+
+ call writefile(['#pragma D option'], 'Xfile.d')
+ split Xfile.d
+ call assert_equal('dtrace', &filetype)
+ bwipe!
+
+ call writefile([':some:thing:'], 'Xfile.d')
+ split Xfile.d
+ call assert_equal('dtrace', &filetype)
+ bwipe!
+
+ call writefile(['module this', '#pragma D option'], 'Xfile.d')
+ split Xfile.d
+ call assert_equal('d', &filetype)
+ bwipe!
+
+ call writefile(['import that', '#pragma D option'], 'Xfile.d')
+ split Xfile.d
+ call assert_equal('d', &filetype)
+ bwipe!
+
+ filetype off
+endfunc
+
func Test_dep3patch_file()
filetype on
diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim
index 6e36f4e3d2..994d74601a 100644
--- a/src/nvim/testdir/test_functions.vim
+++ b/src/nvim/testdir/test_functions.vim
@@ -1451,6 +1451,10 @@ func Test_getchar()
call assert_equal('', getcharstr(0))
call assert_equal('', getcharstr(1))
+ call feedkeys("\<M-F2>", '')
+ call assert_equal("\<M-F2>", getchar(0))
+ call assert_equal(0, getchar(0))
+
call setline(1, 'xxxx')
" call test_setmouse(1, 3)
" let v:mouse_win = 9
diff --git a/src/nvim/testdir/test_normal.vim b/src/nvim/testdir/test_normal.vim
index 5b7cf6fee5..f45cd96733 100644
--- a/src/nvim/testdir/test_normal.vim
+++ b/src/nvim/testdir/test_normal.vim
@@ -1118,7 +1118,7 @@ func Test_normal20_exmode()
endif
call writefile(['1a', 'foo', 'bar', '.', 'w! Xfile2', 'q!'], 'Xscript')
call writefile(['1', '2'], 'Xfile')
- call system(v:progpath .' -e -s < Xscript Xfile')
+ call system(GetVimCommand() .. ' -e -s < Xscript Xfile')
let a=readfile('Xfile2')
call assert_equal(['1', 'foo', 'bar', '2'], a)
@@ -1171,13 +1171,13 @@ func Test_normal22_zet()
endfor
call writefile(['1', '2'], 'Xfile_Test_normal22_zet')
- let args = ' --headless -u NONE -N -U NONE -i NONE --noplugins'
- call system(v:progpath . args . ' -c "%d" -c ":norm! ZZ" Xfile_Test_normal22_zet')
+ let args = ' -N -i NONE --noplugins -X --headless'
+ call system(GetVimCommand() .. args .. ' -c "%d" -c ":norm! ZZ" Xfile_Test_normal22_zet')
let a = readfile('Xfile_Test_normal22_zet')
call assert_equal([], a)
" Test for ZQ
call writefile(['1', '2'], 'Xfile_Test_normal22_zet')
- call system(v:progpath . args . ' -c "%d" -c ":norm! ZQ" Xfile_Test_normal22_zet')
+ call system(GetVimCommand() . args . ' -c "%d" -c ":norm! ZQ" Xfile_Test_normal22_zet')
let a = readfile('Xfile_Test_normal22_zet')
call assert_equal(['1', '2'], a)
@@ -2779,4 +2779,25 @@ func Test_normal_gj_on_extra_wide_char()
bw!
endfunc
+func Test_normal_count_out_of_range()
+ new
+ call setline(1, 'text')
+ normal 44444444444|
+ call assert_equal(999999999, v:count)
+ normal 444444444444|
+ call assert_equal(999999999, v:count)
+ normal 4444444444444|
+ call assert_equal(999999999, v:count)
+ normal 4444444444444444444|
+ call assert_equal(999999999, v:count)
+
+ normal 9y99999999|
+ call assert_equal(899999991, v:count)
+ normal 10y99999999|
+ call assert_equal(999999999, v:count)
+ normal 44444444444y44444444444|
+ call assert_equal(999999999, v:count)
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_profile.vim b/src/nvim/testdir/test_profile.vim
index 4b0097617e..fdb6f13e2b 100644
--- a/src/nvim/testdir/test_profile.vim
+++ b/src/nvim/testdir/test_profile.vim
@@ -1,8 +1,9 @@
" Test Vim profiler
-if !has('profile')
- finish
-endif
+source check.vim
+CheckFeature profile
+
+source shared.vim
source screendump.vim
func Test_profile_func()
@@ -37,7 +38,7 @@ func Test_profile_func()
[CODE]
call writefile(lines, 'Xprofile_func.vim')
- call system(v:progpath
+ call system(GetVimCommand()
\ . ' -es --clean'
\ . ' -c "so Xprofile_func.vim"'
\ . ' -c "qall!"')
@@ -124,8 +125,8 @@ func Test_profile_func_with_ifelse()
[CODE]
call writefile(lines, 'Xprofile_func.vim')
- call system(v:progpath
- \ . ' -es -u NONE -U NONE -i NONE --noplugin'
+ call system(GetVimCommand()
+ \ . ' -es -i NONE --noplugin'
\ . ' -c "profile start Xprofile_func.log"'
\ . ' -c "profile func Foo*"'
\ . ' -c "so Xprofile_func.vim"'
@@ -237,8 +238,8 @@ func Test_profile_func_with_trycatch()
[CODE]
call writefile(lines, 'Xprofile_func.vim')
- call system(v:progpath
- \ . ' -es -u NONE -U NONE -i NONE --noplugin'
+ call system(GetVimCommand()
+ \ . ' -es -i NONE --noplugin'
\ . ' -c "profile start Xprofile_func.log"'
\ . ' -c "profile func Foo*"'
\ . ' -c "so Xprofile_func.vim"'
@@ -324,8 +325,8 @@ func Test_profile_file()
[CODE]
call writefile(lines, 'Xprofile_file.vim')
- call system(v:progpath
- \ . ' -es --clean'
+ call system(GetVimCommandClean()
+ \ . ' -es'
\ . ' -c "profile start Xprofile_file.log"'
\ . ' -c "profile file Xprofile_file.vim"'
\ . ' -c "so Xprofile_file.vim"'
@@ -369,8 +370,8 @@ func Test_profile_file_with_cont()
\ ]
call writefile(lines, 'Xprofile_file.vim')
- call system(v:progpath
- \ . ' -es -u NONE -U NONE -i NONE --noplugin'
+ call system(GetVimCommandClean()
+ \ . ' -es'
\ . ' -c "profile start Xprofile_file.log"'
\ . ' -c "profile file Xprofile_file.vim"'
\ . ' -c "so Xprofile_file.vim"'
@@ -427,7 +428,7 @@ func Test_profile_truncate_mbyte()
\ ]
call writefile(lines, 'Xprofile_file.vim')
- call system(v:progpath
+ call system(GetVimCommandClean()
\ . ' -es --cmd "set enc=utf-8"'
\ . ' -c "profile start Xprofile_file.log"'
\ . ' -c "profile file Xprofile_file.vim"'
@@ -474,7 +475,7 @@ func Test_profdel_func()
call Foo3()
[CODE]
call writefile(lines, 'Xprofile_file.vim')
- call system(v:progpath . ' -es --clean -c "so Xprofile_file.vim" -c q')
+ call system(GetVimCommandClean() . ' -es -c "so Xprofile_file.vim" -c q')
call assert_equal(0, v:shell_error)
let lines = readfile('Xprofile_file.log')
@@ -509,7 +510,7 @@ func Test_profdel_star()
call Foo()
[CODE]
call writefile(lines, 'Xprofile_file.vim')
- call system(v:progpath . ' -es --clean -c "so Xprofile_file.vim" -c q')
+ call system(GetVimCommandClean() . ' -es -c "so Xprofile_file.vim" -c q')
call assert_equal(0, v:shell_error)
let lines = readfile('Xprofile_file.log')
diff --git a/src/nvim/testdir/test_put.vim b/src/nvim/testdir/test_put.vim
index ed76709a56..65232175c6 100644
--- a/src/nvim/testdir/test_put.vim
+++ b/src/nvim/testdir/test_put.vim
@@ -138,6 +138,50 @@ func Test_p_with_count_leaves_mark_at_end()
bwipe!
endfunc
+func Test_very_large_count()
+ new
+ " total put-length (21474837 * 100) brings 32 bit int overflow
+ let @" = repeat('x', 100)
+ call assert_fails('norm 21474837p', 'E1240:')
+ bwipe!
+endfunc
+
+func Test_very_large_count_64bit()
+ throw 'Skipped: v:sizeoflong is N/A' " use legacy/put_spec.lua instead
+
+ if v:sizeoflong < 8
+ throw 'Skipped: only works with 64 bit long ints'
+ endif
+
+ new
+ let @" = repeat('x', 100)
+ call assert_fails('norm 999999999p', 'E1240:')
+ bwipe!
+endfunc
+
+func Test_very_large_count_block()
+ new
+ " total put-length (21474837 * 100) brings 32 bit int overflow
+ call setline(1, repeat('x', 100))
+ exe "norm \<C-V>99ly"
+ call assert_fails('norm 21474837p', 'E1240:')
+ bwipe!
+endfunc
+
+func Test_very_large_count_block_64bit()
+ throw 'Skipped: v:sizeoflong is N/A' " use legacy/put_spec.lua instead
+
+ if v:sizeoflong < 8
+ throw 'Skipped: only works with 64 bit long ints'
+ endif
+
+ new
+ call setline(1, repeat('x', 100))
+ exe "norm \<C-V>$y"
+ call assert_fails('norm 999999999p', 'E1240:')
+ bwipe!
+endfunc
+
func Test_put_above_first_line()
new
let @" = 'text'
diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim
index c4d70fb1de..6852f53ea8 100644
--- a/src/nvim/testdir/test_quickfix.vim
+++ b/src/nvim/testdir/test_quickfix.vim
@@ -2739,7 +2739,7 @@ func Test_cwindow_jump()
call assert_true(winnr('$') == 2)
call assert_true(winnr() == 1)
- " Jumping to a file from the location list window should find a usuable
+ " Jumping to a file from the location list window should find a usable
" window by wrapping around the window list.
enew | only
call setloclist(0, [], 'f')
diff --git a/src/nvim/testdir/test_registers.vim b/src/nvim/testdir/test_registers.vim
index 2e92d9aa2f..23e39eba35 100644
--- a/src/nvim/testdir/test_registers.vim
+++ b/src/nvim/testdir/test_registers.vim
@@ -219,7 +219,7 @@ func Test_set_register()
call setreg('=', 'b', 'a')
call assert_equal('regwrite', getreg('='))
- " Test for settting a list of lines to special registers
+ " Test for setting a list of lines to special registers
call setreg('/', [])
call assert_equal('', @/)
call setreg('=', [])
diff --git a/src/nvim/testdir/test_stat.vim b/src/nvim/testdir/test_stat.vim
index b44f3e9b94..d3059664e9 100644
--- a/src/nvim/testdir/test_stat.vim
+++ b/src/nvim/testdir/test_stat.vim
@@ -7,7 +7,7 @@ func CheckFileTime(doSleep)
let times = []
let result = 0
- " Use three files istead of localtim(), with a network filesystem the file
+ " Use three files instead of localtim(), with a network filesystem the file
" times may differ at bit
let fl = ['Hello World!']
for fname in fnames
diff --git a/src/nvim/testdir/test_suspend.vim b/src/nvim/testdir/test_suspend.vim
index 4b3bd5eadf..bf88bd4453 100644
--- a/src/nvim/testdir/test_suspend.vim
+++ b/src/nvim/testdir/test_suspend.vim
@@ -26,8 +26,8 @@ func Test_suspend()
" Wait for shell prompt.
call WaitForAssert({-> assert_match('[$#] $', term_getline(buf, '.'))})
- call term_sendkeys(buf, v:progpath
- \ . " --clean -X"
+ call term_sendkeys(buf, GetVimCommandClean()
+ \ . " -X"
\ . " -c 'set nu'"
\ . " -c 'call setline(1, \"foo\")'"
\ . " Xfoo\<CR>")
diff --git a/src/nvim/testdir/test_system.vim b/src/nvim/testdir/test_system.vim
index 5b8079d7b6..18692f42c9 100644
--- a/src/nvim/testdir/test_system.vim
+++ b/src/nvim/testdir/test_system.vim
@@ -50,11 +50,11 @@ endfunc
func Test_system_exmode()
if has('unix') " echo $? only works on Unix
- let cmd = ' -es --headless -u NONE -c "source Xscript" +q; echo "result=$?"'
+ let cmd = ' -es -c "source Xscript" +q; echo "result=$?"'
" Need to put this in a script, "catch" isn't found after an unknown
" function.
call writefile(['try', 'call doesnotexist()', 'catch', 'endtry'], 'Xscript')
- let a = system(v:progpath . cmd)
+ let a = system(GetVimCommand() . cmd)
call assert_match('result=0', a)
call assert_equal(0, v:shell_error)
endif
@@ -62,33 +62,33 @@ func Test_system_exmode()
" Error before try does set error flag.
call writefile(['call nosuchfunction()', 'try', 'call doesnotexist()', 'catch', 'endtry'], 'Xscript')
if has('unix') " echo $? only works on Unix
- let a = system(v:progpath . cmd)
+ let a = system(GetVimCommand() . cmd)
call assert_notequal('0', a[0])
endif
- let cmd = ' -es --headless -u NONE -c "source Xscript" +q'
- let a = system(v:progpath . cmd)
+ let cmd = ' -es -c "source Xscript" +q'
+ let a = system(GetVimCommand() . cmd)
call assert_notequal(0, v:shell_error)
call delete('Xscript')
if has('unix') " echo $? only works on Unix
- let cmd = ' -es --headless -u NONE -c "call doesnotexist()" +q; echo $?'
- let a = system(v:progpath. cmd)
+ let cmd = ' -es -c "call doesnotexist()" +q; echo $?'
+ let a = system(GetVimCommand() . cmd)
call assert_notequal(0, a[0])
endif
- let cmd = ' -es --headless -u NONE -c "call doesnotexist()" +q'
- let a = system(v:progpath. cmd)
+ let cmd = ' -es -c "call doesnotexist()" +q'
+ let a = system(GetVimCommand(). cmd)
call assert_notequal(0, v:shell_error)
if has('unix') " echo $? only works on Unix
- let cmd = ' -es --headless -u NONE -c "call doesnotexist()|let a=1" +q; echo $?'
- let a = system(v:progpath. cmd)
+ let cmd = ' -es -c "call doesnotexist()|let a=1" +q; echo $?'
+ let a = system(GetVimCommand() . cmd)
call assert_notequal(0, a[0])
endif
- let cmd = ' -es --headless -u NONE -c "call doesnotexist()|let a=1" +q'
- let a = system(v:progpath. cmd)
+ let cmd = ' -es -c "call doesnotexist()|let a=1" +q'
+ let a = system(GetVimCommand() . cmd)
call assert_notequal(0, v:shell_error)
endfunc
diff --git a/src/nvim/testdir/test_tabline.vim b/src/nvim/testdir/test_tabline.vim
index 117d962d08..3a18206078 100644
--- a/src/nvim/testdir/test_tabline.vim
+++ b/src/nvim/testdir/test_tabline.vim
@@ -86,6 +86,17 @@ func Test_tabline_empty_group()
set tabline=
endfunc
+" When there are exactly 20 tabline format items (the exact size of the
+" initial tabline items array), test that we don't write beyond the size
+" of the array.
+func Test_tabline_20_format_items_no_overrun()
+ set showtabline=2
+
+ let tabline = repeat('%#StatColorHi2#', 20)
+ let &tabline = tabline
+ redrawtabline
+ set showtabline& tabline&
+endfunc
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_vimscript.vim b/src/nvim/testdir/test_vimscript.vim
index 75a965f16d..f93eb6e274 100644
--- a/src/nvim/testdir/test_vimscript.vim
+++ b/src/nvim/testdir/test_vimscript.vim
@@ -1,6 +1,9 @@
" Test various aspects of the Vim script language.
" Most of this was formerly in test49.
+source check.vim
+source shared.vim
+
"-------------------------------------------------------------------------------
" Test environment {{{1
"-------------------------------------------------------------------------------
@@ -1744,7 +1747,7 @@ func Test_function_defined_line()
[CODE]
call writefile(lines, 'Xtest.vim')
- let res = system(v:progpath .. ' --clean -es -X -S Xtest.vim')
+ let res = system(GetVimCommandClean() .. ' -es -X -S Xtest.vim')
call assert_equal(0, v:shell_error)
let m = matchstr(res, 'function F1()[^[:print:]]*[[:print:]]*')
diff --git a/src/nvim/testdir/test_visual.vim b/src/nvim/testdir/test_visual.vim
index 04c7db38ef..ae8f9ba70b 100644
--- a/src/nvim/testdir/test_visual.vim
+++ b/src/nvim/testdir/test_visual.vim
@@ -636,6 +636,11 @@ func Test_characterwise_visual_mode()
normal v$rx
call assert_equal(['x'], getline(1, '$'))
+ " replace a character with composing characters
+ call setline(1, "xã̳x")
+ normal gg0lvrb
+ call assert_equal("xbx", getline(1))
+
bwipe!
endfunc
@@ -1280,6 +1285,16 @@ func Test_visual_block_insert_round_off()
bwipe!
endfunc
+" this was causing an ml_get error
+func Test_visual_exchange_windows()
+ enew!
+ new
+ call setline(1, ['foo', 'bar'])
+ exe "normal G\<C-V>gg\<C-W>\<C-X>OO\<Esc>"
+ bwipe!
+ bwipe!
+endfunc
+
" this was leaving the end of the Visual area beyond the end of a line
func Test_visual_ex_copy_line()
new
diff --git a/src/nvim/window.c b/src/nvim/window.c
index e09af7a7bb..43667377c5 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -1727,6 +1727,12 @@ static void win_exchange(long Prenum)
(void)win_comp_pos(); // recompute window positions
+ if (wp->w_buffer != curbuf) {
+ reset_VIsual_and_resel();
+ } else if (VIsual_active) {
+ wp->w_cursor = curwin->w_cursor;
+ }
+
win_enter(wp, true);
redraw_later(curwin, NOT_VALID);
redraw_later(wp, NOT_VALID);
@@ -4682,20 +4688,29 @@ void fix_current_dir(void)
globaldir = (char_u *)xstrdup(cwd);
}
}
+ bool dir_differs = pathcmp(new_dir, cwd, -1) != 0;
+ if (!p_acd && dir_differs) {
+ do_autocmd_dirchanged(new_dir, curwin->w_localdir ? kCdScopeWindow : kCdScopeTabpage,
+ kCdCauseWindow, true);
+ }
if (os_chdir(new_dir) == 0) {
- if (!p_acd && pathcmp(new_dir, cwd, -1) != 0) {
- do_autocmd_dirchanged(new_dir, curwin->w_localdir
- ? kCdScopeWindow : kCdScopeTabpage, kCdCauseWindow);
+ if (!p_acd && dir_differs) {
+ do_autocmd_dirchanged(new_dir, curwin->w_localdir ? kCdScopeWindow : kCdScopeTabpage,
+ kCdCauseWindow, false);
}
- last_chdir_reason = NULL;
- shorten_fnames(true);
}
+ last_chdir_reason = NULL;
+ shorten_fnames(true);
} else if (globaldir != NULL) {
// Window doesn't have a local directory and we are not in the global
// directory: Change to the global directory.
+ bool dir_differs = pathcmp((char *)globaldir, cwd, -1) != 0;
+ if (!p_acd && dir_differs) {
+ do_autocmd_dirchanged((char *)globaldir, kCdScopeGlobal, kCdCauseWindow, true);
+ }
if (os_chdir((char *)globaldir) == 0) {
- if (!p_acd && pathcmp((char *)globaldir, cwd, -1) != 0) {
- do_autocmd_dirchanged((char *)globaldir, kCdScopeGlobal, kCdCauseWindow);
+ if (!p_acd && dir_differs) {
+ do_autocmd_dirchanged((char *)globaldir, kCdScopeGlobal, kCdCauseWindow, false);
}
}
XFREE_CLEAR(globaldir);
diff --git a/test/functional/api/buffer_spec.lua b/test/functional/api/buffer_spec.lua
index 688f3abba5..dd3af8c28f 100644
--- a/test/functional/api/buffer_spec.lua
+++ b/test/functional/api/buffer_spec.lua
@@ -423,6 +423,13 @@ describe('api/buf', function()
-- will join multiple lines if needed
set_text(0, 6, 3, 4, {'bar'})
eq({'hello bar'}, get_lines(0, 1, true))
+
+ -- can use negative line numbers
+ set_text(-2, 0, -2, 5, {'goodbye'})
+ eq({'goodbye bar', ''}, get_lines(0, -1, true))
+
+ set_text(-1, 0, -1, 0, {'text'})
+ eq({'goodbye bar', 'text'}, get_lines(0, 2, true))
end)
it('works with undo', function()
@@ -537,6 +544,34 @@ describe('api/buf', function()
end)
end)
+ describe('nvim_buf_get_text', function()
+ local get_text = curbufmeths.get_text
+
+ it('works', function()
+ insert([[
+ hello foo!
+ text]])
+
+ eq({'hello'}, get_text(0, 0, 0, 5, {}))
+ eq({'hello foo!'}, get_text(0, 0, 0, 42, {}))
+ eq({'foo!'}, get_text(0, 6, 0, 10, {}))
+ eq({'foo!', 'tex'}, get_text(0, 6, 1, 3, {}))
+ eq({'foo!', 'tex'}, get_text(-2, 6, -1, 3, {}))
+ eq({''}, get_text(0, 18, 0, 20, {}))
+ eq({'ext'}, get_text(-1, 1, -1, 4, {}))
+ end)
+
+ it('errors on out-of-range', function()
+ eq(false, pcall(get_text, 2, 0, 3, 0, {}))
+ eq(false, pcall(get_text, 0, 0, 4, 0, {}))
+ end)
+
+ it('errors when start is greater than end', function()
+ eq(false, pcall(get_text, 1, 0, 0, 0, {}))
+ eq(false, pcall(get_text, 0, 1, 0, 0, {}))
+ end)
+ end)
+
describe('nvim_buf_get_offset', function()
local get_offset = curbufmeths.get_offset
it('works', function()
diff --git a/test/functional/api/buffer_updates_spec.lua b/test/functional/api/buffer_updates_spec.lua
index c9c9be5406..e9ad756947 100644
--- a/test/functional/api/buffer_updates_spec.lua
+++ b/test/functional/api/buffer_updates_spec.lua
@@ -7,6 +7,7 @@ local nvim_prog = helpers.nvim_prog
local pcall_err = helpers.pcall_err
local sleep = helpers.sleep
local write_file = helpers.write_file
+local iswin = helpers.iswin
local origlines = {"original line 1",
"original line 2",
@@ -823,7 +824,8 @@ describe('API: buffer events:', function()
end
msg = next_msg()
end
- assert(false, 'did not match/receive expected nvim_buf_lines_event lines')
+ -- FIXME: Windows
+ assert(iswin(), 'did not match/receive expected nvim_buf_lines_event lines')
end
it('when :terminal lines change', function()
diff --git a/test/functional/api/command_spec.lua b/test/functional/api/command_spec.lua
index d64d324a88..de22c9078c 100644
--- a/test/functional/api/command_spec.lua
+++ b/test/functional/api/command_spec.lua
@@ -180,6 +180,28 @@ describe('nvim_add_user_command', function()
feed('<C-U>Test b<Tab>')
eq('Test bbb', funcs.getcmdline())
end)
+
+ it('does not allow invalid command names', function()
+ matches("'name' must begin with an uppercase letter", pcall_err(exec_lua, [[
+ vim.api.nvim_add_user_command('test', 'echo "hi"', {})
+ ]]))
+
+ matches('Invalid command name', pcall_err(exec_lua, [[
+ vim.api.nvim_add_user_command('t@', 'echo "hi"', {})
+ ]]))
+
+ matches('Invalid command name', pcall_err(exec_lua, [[
+ vim.api.nvim_add_user_command('T@st', 'echo "hi"', {})
+ ]]))
+
+ matches('Invalid command name', pcall_err(exec_lua, [[
+ vim.api.nvim_add_user_command('Test!', 'echo "hi"', {})
+ ]]))
+
+ matches('Invalid command name', pcall_err(exec_lua, [[
+ vim.api.nvim_add_user_command('💩', 'echo "hi"', {})
+ ]]))
+ end)
end)
describe('nvim_del_user_command', function()
diff --git a/test/functional/api/highlight_spec.lua b/test/functional/api/highlight_spec.lua
index 46a3798dc4..443689754c 100644
--- a/test/functional/api/highlight_spec.lua
+++ b/test/functional/api/highlight_spec.lua
@@ -242,6 +242,12 @@ describe("API: set highlight", function()
eq(highlight2_result, meths.get_hl_by_name('Test_hl', false))
end)
+ it ("can set emtpy cterm attr", function()
+ local ns = get_ns()
+ meths.set_hl(ns, 'Test_hl', { cterm = {} })
+ eq({}, meths.get_hl_by_name('Test_hl', false))
+ end)
+
it ("cterm attr defaults to gui attr", function()
local ns = get_ns()
meths.set_hl(ns, 'Test_hl', highlight1)
@@ -276,4 +282,50 @@ describe("API: set highlight", function()
eq('Test_hl3 xxx guifg=bLue guibg=reD',
exec_capture('highlight Test_hl3'))
end)
+
+ it ("can modify a highlight in the global namespace", function()
+ meths.set_hl(0, 'Test_hl3', { bg = 'red', fg = 'blue'})
+ eq('Test_hl3 xxx guifg=blue guibg=red',
+ exec_capture('highlight Test_hl3'))
+
+ meths.set_hl(0, 'Test_hl3', { bg = 'red' })
+ eq('Test_hl3 xxx guibg=red',
+ exec_capture('highlight Test_hl3'))
+
+ meths.set_hl(0, 'Test_hl3', { ctermbg = 9, ctermfg = 12})
+ eq('Test_hl3 xxx ctermfg=12 ctermbg=9',
+ exec_capture('highlight Test_hl3'))
+
+ meths.set_hl(0, 'Test_hl3', { ctermbg = 'red' , ctermfg = 'blue'})
+ eq('Test_hl3 xxx ctermfg=12 ctermbg=9',
+ exec_capture('highlight Test_hl3'))
+
+ meths.set_hl(0, 'Test_hl3', { ctermbg = 9 })
+ eq('Test_hl3 xxx ctermbg=9',
+ exec_capture('highlight Test_hl3'))
+
+ eq("'redd' is not a valid color",
+ pcall_err(meths.set_hl, 0, 'Test_hl3', {fg='redd'}))
+
+ eq("'bleu' is not a valid color",
+ pcall_err(meths.set_hl, 0, 'Test_hl3', {ctermfg='bleu'}))
+
+ meths.set_hl(0, 'Test_hl3', {fg='#FF00FF'})
+ eq('Test_hl3 xxx guifg=#FF00FF',
+ exec_capture('highlight Test_hl3'))
+
+ eq("'#FF00FF' is not a valid color",
+ pcall_err(meths.set_hl, 0, 'Test_hl3', {ctermfg='#FF00FF'}))
+
+ for _, fg_val in ipairs{ nil, 'NONE', 'nOnE', '', -1 } do
+ meths.set_hl(0, 'Test_hl3', {fg = fg_val})
+ eq('Test_hl3 xxx cleared',
+ exec_capture('highlight Test_hl3'))
+ end
+
+ meths.set_hl(0, 'Test_hl3', {fg='#FF00FF', blend=50})
+ eq('Test_hl3 xxx guifg=#FF00FF blend=50',
+ exec_capture('highlight Test_hl3'))
+
+ end)
end)
diff --git a/test/functional/api/keymap_spec.lua b/test/functional/api/keymap_spec.lua
index 450a76ddac..e49e0b8cc4 100644
--- a/test/functional/api/keymap_spec.lua
+++ b/test/functional/api/keymap_spec.lua
@@ -877,6 +877,24 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
eq("\nn lhs rhs\n map description",
helpers.exec_capture("nmap lhs"))
end)
+
+ it ('can :filter maps based on description', function()
+ meths.set_keymap('n', 'asdf1', 'qwert', {desc='do the one thing'})
+ meths.set_keymap('n', 'asdf2', 'qwert', {desc='doesnot really do anything'})
+ meths.set_keymap('n', 'asdf3', 'qwert', {desc='do the other thing'})
+ eq([[
+
+n asdf3 qwert
+ do the other thing
+n asdf1 qwert
+ do the one thing]],
+ helpers.exec_capture('filter the nmap'))
+ end)
+
+ it ('shows <nop> as map rhs', function()
+ meths.set_keymap('n', 'asdf', '<nop>', {})
+ eq('\nn asdf <Nop>', helpers.exec_capture('nmap asdf'))
+ end)
end)
describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
diff --git a/test/functional/api/server_requests_spec.lua b/test/functional/api/server_requests_spec.lua
index 309d9084c8..cdcf08c348 100644
--- a/test/functional/api/server_requests_spec.lua
+++ b/test/functional/api/server_requests_spec.lua
@@ -181,12 +181,6 @@ describe('server -> client', function()
end)
describe('recursive (child) nvim client', function()
- if helpers.isCI('travis') and helpers.is_os('mac') then
- -- XXX: Hangs Travis macOS since e9061117a5b8f195c3f26a5cb94e18ddd7752d86.
- pending("[Hangs on Travis macOS. #5002]", function() end)
- return
- end
-
before_each(function()
command("let vim = rpcstart('"..nvim_prog.."', ['-u', 'NONE', '-i', 'NONE', '--cmd', 'set noswapfile', '--embed', '--headless'])")
neq(0, eval('vim'))
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index 5a387f3deb..71cd055e08 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -23,6 +23,7 @@ local next_msg = helpers.next_msg
local tmpname = helpers.tmpname
local write_file = helpers.write_file
local exec_lua = helpers.exec_lua
+local exc_exec = helpers.exc_exec
local pcall_err = helpers.pcall_err
local format_string = helpers.format_string
@@ -2240,6 +2241,14 @@ describe('API', function()
eq({}, meths.get_runtime_file("foobarlang/", true))
end)
+ it('can handle bad patterns', function()
+ if helpers.pending_win32(pending) then return end
+
+ eq("Vim:E220: Missing }.", pcall_err(meths.get_runtime_file, "{", false))
+
+ eq('Vim(echo):E5555: API call: Vim:E220: Missing }.',
+ exc_exec("echo nvim_get_runtime_file('{', v:false)"))
+ end)
end)
describe('nvim_get_all_options_info', function()
diff --git a/test/functional/autocmd/dirchanged_spec.lua b/test/functional/autocmd/dirchanged_spec.lua
index f4a1642ebf..45dc06b39b 100644
--- a/test/functional/autocmd/dirchanged_spec.lua
+++ b/test/functional/autocmd/dirchanged_spec.lua
@@ -8,7 +8,7 @@ local eval = h.eval
local request = h.request
local iswin = h.iswin
-describe('autocmd DirChanged', function()
+describe('autocmd DirChanged and DirChangedPre', function()
local curdir = string.gsub(lfs.currentdir(), '\\', '/')
local dirs = {
curdir .. '/Xtest-functional-autocmd-dirchanged.dir1',
@@ -26,31 +26,43 @@ describe('autocmd DirChanged', function()
before_each(function()
clear()
+ command('autocmd DirChangedPre * let [g:evpre, g:amatchpre, g:cdprecount] '
+ ..'= [copy(v:event), expand("<amatch>"), 1 + get(g:, "cdprecount", 0)]')
command('autocmd DirChanged * let [g:getcwd, g:ev, g:amatch, g:cdcount] '
- ..' = [getcwd(), copy(v:event), expand("<amatch>"), 1 + get(g:, "cdcount", 0)]')
+ ..'= [getcwd(), copy(v:event), expand("<amatch>"), 1 + get(g:, "cdcount", 0)]')
-- Normalize path separators.
+ command([[autocmd DirChangedPre * let g:evpre['directory'] = substitute(g:evpre['directory'], '\\', '/', 'g')]])
command([[autocmd DirChanged * let g:ev['cwd'] = substitute(g:ev['cwd'], '\\', '/', 'g')]])
- command([[autocmd DirChanged * let g:getcwd = substitute(g:getcwd, '\\', '/', 'g')]])
+ command([[autocmd DirChanged * let g:getcwd = substitute(g:getcwd, '\\', '/', 'g')]])
end)
- it('sets v:event and <amatch>', function()
+ it('set v:event and <amatch>', function()
command('lcd '..dirs[1])
+ eq({directory=dirs[1], scope='window', changed_window=false}, eval('g:evpre'))
eq({cwd=dirs[1], scope='window', changed_window=false}, eval('g:ev'))
+ eq('window', eval('g:amatchpre'))
eq('window', eval('g:amatch'))
+ eq(1, eval('g:cdprecount'))
eq(1, eval('g:cdcount'))
command('tcd '..dirs[2])
+ eq({directory=dirs[2], scope='tabpage', changed_window=false}, eval('g:evpre'))
eq({cwd=dirs[2], scope='tabpage', changed_window=false}, eval('g:ev'))
+ eq('tabpage', eval('g:amatchpre'))
eq('tabpage', eval('g:amatch'))
+ eq(2, eval('g:cdprecount'))
eq(2, eval('g:cdcount'))
command('cd '..dirs[3])
+ eq({directory=dirs[3], scope='global', changed_window=false}, eval('g:evpre'))
eq({cwd=dirs[3], scope='global', changed_window=false}, eval('g:ev'))
+ eq('global', eval('g:amatchpre'))
eq('global', eval('g:amatch'))
+ eq(3, eval('g:cdprecount'))
eq(3, eval('g:cdcount'))
end)
- it('sets getcwd() during event #6260', function()
+ it('DirChanged set getcwd() during event #6260', function()
command('lcd '..dirs[1])
eq(dirs[1], eval('g:getcwd'))
@@ -61,7 +73,7 @@ describe('autocmd DirChanged', function()
eq(dirs[3], eval('g:getcwd'))
end)
- it('disallows recursion', function()
+ it('disallow recursion', function()
command('set shellslash')
-- Set up a _nested_ handler.
command('autocmd DirChanged * nested lcd '..dirs[3])
@@ -72,23 +84,36 @@ describe('autocmd DirChanged', function()
eq(dirs[3], eval('getcwd()'))
end)
- it('does not trigger if :cd fails', function()
+ it('only DirChangedPre is triggered if :cd fails', function()
command('let g:ev = {}')
+ command('let g:cdcount = 0')
local status1, err1 = pcall(function()
- command('lcd '..dirs[1] .. '/doesnotexist')
+ command('lcd '..dirs[1]..'/doesnotexist')
end)
+ eq({directory=dirs[1]..'/doesnotexist', scope='window', changed_window=false}, eval('g:evpre'))
eq({}, eval('g:ev'))
+ eq('window', eval('g:amatchpre'))
+ eq(1, eval('g:cdprecount'))
+ eq(0, eval('g:cdcount'))
local status2, err2 = pcall(function()
- command('lcd '..dirs[2] .. '/doesnotexist')
+ command('lcd '..dirs[2]..'/doesnotexist')
end)
+ eq({directory=dirs[2]..'/doesnotexist', scope='window', changed_window=false}, eval('g:evpre'))
eq({}, eval('g:ev'))
+ eq('window', eval('g:amatchpre'))
+ eq(2, eval('g:cdprecount'))
+ eq(0, eval('g:cdcount'))
local status3, err3 = pcall(function()
- command('lcd '..dirs[3] .. '/doesnotexist')
+ command('lcd '..dirs[3]..'/doesnotexist')
end)
+ eq({directory=dirs[3]..'/doesnotexist', scope='window', changed_window=false}, eval('g:evpre'))
eq({}, eval('g:ev'))
+ eq('window', eval('g:amatchpre'))
+ eq(3, eval('g:cdprecount'))
+ eq(0, eval('g:cdcount'))
eq(false, status1)
eq(false, status2)
@@ -99,85 +124,121 @@ describe('autocmd DirChanged', function()
eq('E344:', string.match(err3, "E%d*:"))
end)
- it("is triggered by 'autochdir'", function()
+ it("are triggered by 'autochdir'", function()
command('set autochdir')
command('split '..dirs[1]..'/foo')
+ eq({directory=dirs[1], scope='window', changed_window=false}, eval('g:evpre'))
eq({cwd=dirs[1], scope='window', changed_window=false}, eval('g:ev'))
+ eq('auto', eval('g:amatchpre'))
eq('auto', eval('g:amatch'))
+ eq(1, eval('g:cdprecount'))
+ eq(1, eval('g:cdcount'))
command('split '..dirs[2]..'/bar')
+ eq({directory=dirs[2], scope='window', changed_window=false}, eval('g:evpre'))
eq({cwd=dirs[2], scope='window', changed_window=false}, eval('g:ev'))
eq('auto', eval('g:amatch'))
-
+ eq(2, eval('g:cdprecount'))
eq(2, eval('g:cdcount'))
end)
- it('does not trigger if directory has not changed', function()
+ it('do not trigger if directory has not changed', function()
command('lcd '..dirs[1])
+ eq({directory=dirs[1], scope='window', changed_window=false}, eval('g:evpre'))
eq({cwd=dirs[1], scope='window', changed_window=false}, eval('g:ev'))
+ eq('window', eval('g:amatchpre'))
eq('window', eval('g:amatch'))
+ eq(1, eval('g:cdprecount'))
eq(1, eval('g:cdcount'))
+ command('let g:evpre = {}')
command('let g:ev = {}')
command('lcd '..dirs[1])
+ eq({}, eval('g:evpre'))
eq({}, eval('g:ev'))
+ eq(1, eval('g:cdprecount'))
eq(1, eval('g:cdcount'))
if iswin() then
command('lcd '..win_dirs[1])
+ eq({}, eval('g:evpre'))
eq({}, eval('g:ev'))
+ eq(1, eval('g:cdprecount'))
eq(1, eval('g:cdcount'))
end
command('tcd '..dirs[2])
+ eq({directory=dirs[2], scope='tabpage', changed_window=false}, eval('g:evpre'))
eq({cwd=dirs[2], scope='tabpage', changed_window=false}, eval('g:ev'))
+ eq('tabpage', eval('g:amatchpre'))
eq('tabpage', eval('g:amatch'))
+ eq(2, eval('g:cdprecount'))
eq(2, eval('g:cdcount'))
+ command('let g:evpre = {}')
command('let g:ev = {}')
command('tcd '..dirs[2])
+ eq({}, eval('g:evpre'))
eq({}, eval('g:ev'))
+ eq(2, eval('g:cdprecount'))
eq(2, eval('g:cdcount'))
if iswin() then
command('tcd '..win_dirs[2])
+ eq({}, eval('g:evpre'))
eq({}, eval('g:ev'))
+ eq(2, eval('g:cdprecount'))
eq(2, eval('g:cdcount'))
end
command('cd '..dirs[3])
+ eq({directory=dirs[3], scope='global', changed_window=false}, eval('g:evpre'))
eq({cwd=dirs[3], scope='global', changed_window=false}, eval('g:ev'))
eq('global', eval('g:amatch'))
+ eq(3, eval('g:cdprecount'))
eq(3, eval('g:cdcount'))
+ command('let g:evpre = {}')
command('let g:ev = {}')
command('cd '..dirs[3])
+ eq({}, eval('g:evpre'))
eq({}, eval('g:ev'))
+ eq(3, eval('g:cdprecount'))
eq(3, eval('g:cdcount'))
if iswin() then
command('cd '..win_dirs[3])
+ eq({}, eval('g:evpre'))
eq({}, eval('g:ev'))
+ eq(3, eval('g:cdprecount'))
eq(3, eval('g:cdcount'))
end
command('set autochdir')
command('split '..dirs[1]..'/foo')
+ eq({directory=dirs[1], scope='window', changed_window=false}, eval('g:evpre'))
eq({cwd=dirs[1], scope='window', changed_window=false}, eval('g:ev'))
+ eq('auto', eval('g:amatchpre'))
eq('auto', eval('g:amatch'))
+ eq(4, eval('g:cdprecount'))
eq(4, eval('g:cdcount'))
+ command('let g:evpre = {}')
command('let g:ev = {}')
command('split '..dirs[1]..'/bar')
+ eq({}, eval('g:evpre'))
eq({}, eval('g:ev'))
+ eq(4, eval('g:cdprecount'))
eq(4, eval('g:cdcount'))
if iswin() then
command('split '..win_dirs[1]..'/baz')
+ eq({}, eval('g:evpre'))
eq({}, eval('g:ev'))
+ eq(4, eval('g:cdprecount'))
eq(4, eval('g:cdcount'))
end
end)
- it("is triggered by switching to win/tab with different CWD #6054", function()
+ it("are triggered by switching to win/tab with different CWD #6054", function()
command('lcd '..dirs[3]) -- window 3
command('split '..dirs[2]..'/foo') -- window 2
command('lcd '..dirs[2])
@@ -185,72 +246,105 @@ describe('autocmd DirChanged', function()
command('lcd '..dirs[1])
command('2wincmd w') -- window 2
+ eq({directory=dirs[2], scope='window', changed_window=true}, eval('g:evpre'))
eq({cwd=dirs[2], scope='window', changed_window=true}, eval('g:ev'))
+ eq('window', eval('g:amatchpre'))
eq('window', eval('g:amatch'))
+ eq(4, eval('g:cdprecount'))
eq(4, eval('g:cdcount'))
command('tabnew') -- tab 2 (tab-local CWD)
+ eq(4, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
eq(4, eval('g:cdcount')) -- same CWD, no DirChanged event
command('tcd '..dirs[3])
command('tabnext') -- tab 1 (no tab-local CWD)
+ eq({directory=dirs[2], scope='window', changed_window=true}, eval('g:evpre'))
eq({cwd=dirs[2], scope='window', changed_window=true}, eval('g:ev'))
+ eq('window', eval('g:amatchpre'))
eq('window', eval('g:amatch'))
command('tabnext') -- tab 2
+ eq({directory=dirs[3], scope='tabpage', changed_window=true}, eval('g:evpre'))
eq({cwd=dirs[3], scope='tabpage', changed_window=true}, eval('g:ev'))
+ eq('tabpage', eval('g:amatchpre'))
eq('tabpage', eval('g:amatch'))
+ eq(7, eval('g:cdprecount'))
eq(7, eval('g:cdcount'))
command('tabnext') -- tab 1
command('3wincmd w') -- window 3
+ eq(9, eval('g:cdprecount'))
eq(9, eval('g:cdcount'))
command('tabnext') -- tab 2 (has the *same* CWD)
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
if iswin() then
command('tabnew') -- tab 3
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
command('tcd '..win_dirs[3])
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
command('tabnext') -- tab 1
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
command('tabprevious') -- tab 3
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
command('tabprevious') -- tab 2
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
command('tabprevious') -- tab 1
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
command('lcd '..win_dirs[3]) -- window 3
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
command('tabnext') -- tab 2
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
command('tabnext') -- tab 3
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
command('tabnext') -- tab 1
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
command('tabprevious') -- tab 3
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
end
end)
- it('is triggered by nvim_set_current_dir()', function()
+ it('are triggered by nvim_set_current_dir()', function()
request('nvim_set_current_dir', dirs[1])
+ eq({directory=dirs[1], scope='global', changed_window=false}, eval('g:evpre'))
eq({cwd=dirs[1], scope='global', changed_window=false}, eval('g:ev'))
+ eq(1, eval('g:cdprecount'))
+ eq(1, eval('g:cdcount'))
request('nvim_set_current_dir', dirs[2])
+ eq({directory=dirs[2], scope='global', changed_window=false}, eval('g:evpre'))
eq({cwd=dirs[2], scope='global', changed_window=false}, eval('g:ev'))
+ eq(2, eval('g:cdprecount'))
+ eq(2, eval('g:cdcount'))
local status, err = pcall(function()
request('nvim_set_current_dir', '/doesnotexist')
end)
eq(false, status)
eq('Failed to change directory', string.match(err, ': (.*)'))
- eq({cwd=dirs[2], scope='global', changed_window=false}, eval('g:ev'))
+ eq({directory='/doesnotexist', scope='global', changed_window=false}, eval('g:evpre'))
+ eq(3, eval('g:cdprecount'))
+ eq(2, eval('g:cdcount'))
end)
- it('works when local to buffer', function()
+ it('work when local to buffer', function()
+ command('let g:triggeredpre = 0')
command('let g:triggered = 0')
+ command('autocmd DirChangedPre <buffer> let g:triggeredpre = 1')
command('autocmd DirChanged <buffer> let g:triggered = 1')
command('cd '..dirs[1])
+ eq(1, eval('g:triggeredpre'))
eq(1, eval('g:triggered'))
end)
end)
diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua
index 5e127bce26..a0df3b7767 100644
--- a/test/functional/core/job_spec.lua
+++ b/test/functional/core/job_spec.lua
@@ -78,6 +78,7 @@ describe('jobs', function()
end)
it('append environment with pty #env', function()
+ if helpers.pending_win32(pending) then return end
nvim('command', "let $VAR = 'abc'")
nvim('command', "let $TOTO = 'goodbye world'")
nvim('command', "let g:job_opts.pty = v:true")
@@ -295,12 +296,6 @@ describe('jobs', function()
end)
it("will not buffer data if it doesn't end in newlines", function()
- if helpers.isCI('travis') and os.getenv('CC') == 'gcc-4.9'
- and helpers.is_os('mac') then
- -- XXX: Hangs Travis macOS since e9061117a5b8f195c3f26a5cb94e18ddd7752d86.
- pending("[Hangs on Travis macOS. #5002]")
- end
-
nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
nvim('command', 'call jobsend(j, "abc\\nxyz")')
eq({'notification', 'stdout', {0, {'abc', 'xyz'}}}, next_msg())
diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua
index 2fa84e8313..3da7f6ffde 100644
--- a/test/functional/core/startup_spec.lua
+++ b/test/functional/core/startup_spec.lua
@@ -53,6 +53,7 @@ describe('startup', function()
]])
end)
it('in a TTY: has("ttyin")==1 has("ttyout")==1', function()
+ if helpers.pending_win32(pending) then return end
local screen = Screen.new(25, 4)
screen:attach()
if iswin() then
@@ -104,6 +105,7 @@ describe('startup', function()
end)
end)
it('input from pipe (implicit) #7679', function()
+ if helpers.pending_win32(pending) then return end
local screen = Screen.new(25, 4)
screen:attach()
if iswin() then
@@ -259,6 +261,7 @@ describe('startup', function()
end)
it('ENTER dismisses early message #7967', function()
+ if helpers.pending_win32(pending) then return end
local screen
screen = Screen.new(60, 6)
screen:attach()
@@ -491,6 +494,7 @@ describe('sysinit', function()
end)
it('fixed hang issue with -D (#12647)', function()
+ if helpers.pending_win32(pending) then return end
local screen
screen = Screen.new(60, 6)
screen:attach()
diff --git a/test/functional/ex_cmds/ctrl_c_spec.lua b/test/functional/ex_cmds/ctrl_c_spec.lua
index f65d9f0d01..f19fab5550 100644
--- a/test/functional/ex_cmds/ctrl_c_spec.lua
+++ b/test/functional/ex_cmds/ctrl_c_spec.lua
@@ -10,8 +10,7 @@ describe("CTRL-C (mapped)", function()
it("interrupts :global", function()
-- Crashes luajit.
- if helpers.skip_fragile(pending,
- helpers.isCI('travis') or helpers.isCI('appveyor')) then
+ if helpers.skip_fragile(pending) then
return
end
diff --git a/test/functional/ex_cmds/mksession_spec.lua b/test/functional/ex_cmds/mksession_spec.lua
index aefcc53cab..2702fb196f 100644
--- a/test/functional/ex_cmds/mksession_spec.lua
+++ b/test/functional/ex_cmds/mksession_spec.lua
@@ -14,6 +14,7 @@ local rmdir = helpers.rmdir
local file_prefix = 'Xtest-functional-ex_cmds-mksession_spec'
describe(':mksession', function()
+ if helpers.pending_win32(pending) then return end
local session_file = file_prefix .. '.vim'
local tab_dir = file_prefix .. '.d'
diff --git a/test/functional/legacy/excmd_spec.lua b/test/functional/legacy/excmd_spec.lua
new file mode 100644
index 0000000000..174f7d292e
--- /dev/null
+++ b/test/functional/legacy/excmd_spec.lua
@@ -0,0 +1,32 @@
+local helpers = require('test.functional.helpers')(after_each)
+local clear = helpers.clear
+local exec_lua = helpers.exec_lua
+local meths = helpers.meths
+local source = helpers.source
+local eq = helpers.eq
+
+local function sizeoflong()
+ if not exec_lua('return pcall(require, "ffi")') then
+ pending('missing LuaJIT FFI')
+ end
+ return exec_lua('return require("ffi").sizeof(require("ffi").typeof("long"))')
+end
+
+describe('Ex command', function()
+ before_each(clear)
+ after_each(function() eq({}, meths.get_vvar('errors')) end)
+
+ it('checks for address line overflow', function()
+ if sizeoflong() < 8 then
+ pending('Skipped: only works with 64 bit long ints')
+ end
+
+ source [[
+ new
+ call setline(1, 'text')
+ call assert_fails('|.44444444444444444444444', 'E1247:')
+ call assert_fails('|.9223372036854775806', 'E1247:')
+ bwipe!
+ ]]
+ end)
+end)
diff --git a/test/functional/legacy/put_spec.lua b/test/functional/legacy/put_spec.lua
new file mode 100644
index 0000000000..3ddf65490e
--- /dev/null
+++ b/test/functional/legacy/put_spec.lua
@@ -0,0 +1,45 @@
+local helpers = require('test.functional.helpers')(after_each)
+local clear = helpers.clear
+local exec_lua = helpers.exec_lua
+local meths = helpers.meths
+local source = helpers.source
+local eq = helpers.eq
+
+local function sizeoflong()
+ if not exec_lua('return pcall(require, "ffi")') then
+ pending('missing LuaJIT FFI')
+ end
+ return exec_lua('return require("ffi").sizeof(require("ffi").typeof("long"))')
+end
+
+describe('put', function()
+ before_each(clear)
+ after_each(function() eq({}, meths.get_vvar('errors')) end)
+
+ it('very large count 64-bit', function()
+ if sizeoflong() < 8 then
+ pending('Skipped: only works with 64 bit long ints')
+ end
+
+ source [[
+ new
+ let @" = repeat('x', 100)
+ call assert_fails('norm 999999999p', 'E1240:')
+ bwipe!
+ ]]
+ end)
+
+ it('very large count (visual block) 64-bit', function()
+ if sizeoflong() < 8 then
+ pending('Skipped: only works with 64 bit long ints')
+ end
+
+ source [[
+ new
+ call setline(1, repeat('x', 100))
+ exe "norm \<C-V>$y"
+ call assert_fails('norm 999999999p', 'E1240:')
+ bwipe!
+ ]]
+ end)
+end)
diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua
index beb43e0271..1cef771f0d 100644
--- a/test/functional/terminal/buffer_spec.lua
+++ b/test/functional/terminal/buffer_spec.lua
@@ -258,6 +258,7 @@ describe(':terminal buffer', function()
end)
it('it works with set rightleft #11438', function()
+ if helpers.pending_win32(pending) then return end
local columns = eval('&columns')
feed(string.rep('a', columns))
command('set rightleft')
diff --git a/test/functional/terminal/cursor_spec.lua b/test/functional/terminal/cursor_spec.lua
index e9495f45a2..3b905f1f56 100644
--- a/test/functional/terminal/cursor_spec.lua
+++ b/test/functional/terminal/cursor_spec.lua
@@ -87,6 +87,7 @@ describe(':terminal cursor', function()
describe('when invisible', function()
it('is not highlighted and is detached from screen cursor', function()
+ if helpers.pending_win32(pending) then return end
hide_cursor()
screen:expect([[
tty ready |
@@ -176,6 +177,7 @@ describe('cursor with customized highlighting', function()
end)
describe('buffer cursor position is correct in terminal without number column', function()
+ if helpers.pending_win32(pending) then return end
local screen
local function setup_ex_register(str)
@@ -526,6 +528,7 @@ describe('buffer cursor position is correct in terminal without number column',
end)
describe('buffer cursor position is correct in terminal with number column', function()
+ if helpers.pending_win32(pending) then return end
local screen
local function setup_ex_register(str)
diff --git a/test/functional/terminal/edit_spec.lua b/test/functional/terminal/edit_spec.lua
index fabc5524ed..e7025d6739 100644
--- a/test/functional/terminal/edit_spec.lua
+++ b/test/functional/terminal/edit_spec.lua
@@ -36,6 +36,7 @@ describe(':edit term://*', function()
end)
it("runs TermOpen early enough to set buffer-local 'scrollback'", function()
+ if helpers.pending_win32(pending) then return end
local columns, lines = 20, 4
local scr = get_screen(columns, lines)
local rep = 97
diff --git a/test/functional/terminal/ex_terminal_spec.lua b/test/functional/terminal/ex_terminal_spec.lua
index 065dd72485..b4f29a586a 100644
--- a/test/functional/terminal/ex_terminal_spec.lua
+++ b/test/functional/terminal/ex_terminal_spec.lua
@@ -142,6 +142,7 @@ describe(':terminal (with fake shell)', function()
end
it('with no argument, acts like termopen()', function()
+ if helpers.pending_win32(pending) then return end
terminal_with_fake_shell()
retry(nil, 4 * screen.timeout, function()
screen:expect([[
@@ -165,6 +166,7 @@ describe(':terminal (with fake shell)', function()
end)
it("with no argument, but 'shell' has arguments, acts like termopen()", function()
+ if helpers.pending_win32(pending) then return end
nvim('set_option', 'shell', nvim_dir..'/shell-test -t jeff')
terminal_with_fake_shell()
screen:expect([[
@@ -176,6 +178,7 @@ describe(':terminal (with fake shell)', function()
end)
it('executes a given command through the shell', function()
+ if helpers.pending_win32(pending) then return end
command('set shellxquote=') -- win: avoid extra quotes
terminal_with_fake_shell('echo hi')
screen:expect([[
@@ -187,6 +190,7 @@ describe(':terminal (with fake shell)', function()
end)
it("executes a given command through the shell, when 'shell' has arguments", function()
+ if helpers.pending_win32(pending) then return end
nvim('set_option', 'shell', nvim_dir..'/shell-test -t jeff')
command('set shellxquote=') -- win: avoid extra quotes
terminal_with_fake_shell('echo hi')
@@ -199,6 +203,7 @@ describe(':terminal (with fake shell)', function()
end)
it('allows quotes and slashes', function()
+ if helpers.pending_win32(pending) then return end
command('set shellxquote=') -- win: avoid extra quotes
terminal_with_fake_shell([[echo 'hello' \ "world"]])
screen:expect([[
@@ -235,6 +240,7 @@ describe(':terminal (with fake shell)', function()
end)
it('works with :find', function()
+ if helpers.pending_win32(pending) then return end
terminal_with_fake_shell()
screen:expect([[
^ready $ |
@@ -253,6 +259,7 @@ describe(':terminal (with fake shell)', function()
end)
it('works with gf', function()
+ if helpers.pending_win32(pending) then return end
command('set shellxquote=') -- win: avoid extra quotes
terminal_with_fake_shell([[echo "scripts/shadacat.py"]])
retry(nil, 4 * screen.timeout, function()
diff --git a/test/functional/terminal/highlight_spec.lua b/test/functional/terminal/highlight_spec.lua
index 8d3f0218af..ebbae1df14 100644
--- a/test/functional/terminal/highlight_spec.lua
+++ b/test/functional/terminal/highlight_spec.lua
@@ -117,6 +117,7 @@ describe(':terminal highlight', function()
end)
it(':terminal highlight has lower precedence than editor #9964', function()
+ if helpers.pending_win32(pending) then return end
clear()
local screen = Screen.new(30, 4)
screen:set_default_attr_ids({
diff --git a/test/functional/terminal/scrollback_spec.lua b/test/functional/terminal/scrollback_spec.lua
index 11bdc73a47..d1cfc7e91b 100644
--- a/test/functional/terminal/scrollback_spec.lua
+++ b/test/functional/terminal/scrollback_spec.lua
@@ -345,6 +345,7 @@ end)
describe(':terminal prints more lines than the screen height and exits', function()
it('will push extra lines to scrollback', function()
+ if helpers.pending_win32(pending) then return end
clear()
local screen = Screen.new(30, 7)
screen:attach({rgb=false})
@@ -576,6 +577,7 @@ describe("pending scrollback line handling", function()
end)
it("does not crash after nvim_buf_call #14891", function()
+ if helpers.pending_win32(pending) then return end
exec_lua [[
local a = vim.api
local bufnr = a.nvim_create_buf(false, true)
diff --git a/test/functional/terminal/window_spec.lua b/test/functional/terminal/window_spec.lua
index 9f278fd157..0d3295cf32 100644
--- a/test/functional/terminal/window_spec.lua
+++ b/test/functional/terminal/window_spec.lua
@@ -18,6 +18,7 @@ describe(':terminal window', function()
end)
it('sets topline correctly #8556', function()
+ if helpers.pending_win32(pending) then return end
-- Test has hardcoded assumptions of dimensions.
eq(7, eval('&lines'))
feed_data('\n\n\n') -- Add blank lines.
diff --git a/test/functional/treesitter/highlight_spec.lua b/test/functional/treesitter/highlight_spec.lua
index 175525b3f2..ed28d8a37d 100644
--- a/test/functional/treesitter/highlight_spec.lua
+++ b/test/functional/treesitter/highlight_spec.lua
@@ -23,7 +23,7 @@ local hl_query = [[
"enum" @type
"extern" @type
- (string_literal) @string
+ (string_literal) @string.nonexistent-specializer-for-string.should-fallback-to-string
(number_literal) @number
(char_literal) @string
@@ -613,4 +613,91 @@ describe('treesitter highlighting', function()
[12] = {background = Screen.colors.Red, bold = true, foreground = Screen.colors.Grey100};
}}
end)
+
+ it("allows to use captures with dots (don't use fallback when specialization of foo exists)", function()
+ if pending_c_parser(pending) then return end
+
+ insert([[
+ char* x = "Will somebody ever read this?";
+ ]])
+
+ screen:expect{grid=[[
+ char* x = "Will somebody ever read this?"; |
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ exec_lua [[
+ local parser = vim.treesitter.get_parser(0, "c", {})
+ local highlighter = vim.treesitter.highlighter
+ highlighter.hl_map['foo.bar'] = 'Type'
+ highlighter.hl_map['foo'] = 'String'
+ test_hl = highlighter.new(parser, {queries = {c = "(primitive_type) @foo.bar (string_literal) @foo"}})
+ ]]
+
+ screen:expect{grid=[[
+ {3:char}* x = {5:"Will somebody ever read this?"}; |
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ end)
+
+ it("hl_map has the correct fallback behavior", function()
+ exec_lua [[
+ local hl_map = vim.treesitter.highlighter.hl_map
+ hl_map["foo"] = 1
+ hl_map["foo.bar"] = 2
+ hl_map["foo.bar.baz"] = 3
+
+ assert(hl_map["foo"] == 1)
+ assert(hl_map["foo.a.b.c.d"] == 1)
+ assert(hl_map["foo.bar"] == 2)
+ assert(hl_map["foo.bar.a.b.c.d"] == 2)
+ assert(hl_map["foo.bar.baz"] == 3)
+ assert(hl_map["foo.bar.baz.d"] == 3)
+
+ hl_map["FOO"] = 1
+ hl_map["FOO.BAR"] = 2
+ assert(hl_map["FOO.BAR.BAZ"] == 2)
+
+ hl_map["foo.missing.exists"] = 3
+ assert(hl_map["foo.missing"] == 1)
+ assert(hl_map["foo.missing.exists"] == 3)
+ assert(hl_map["foo.missing.exists.bar"] == 3)
+ assert(hl_map["total.nonsense.but.a.lot.of.dots"] == nil)
+ -- It will not perform a second look up of this variable but return a sentinel value
+ assert(hl_map["total.nonsense.but.a.lot.of.dots"] == "__notfound")
+ ]]
+
+ end)
end)
diff --git a/test/functional/ui/hlstate_spec.lua b/test/functional/ui/hlstate_spec.lua
index 2a567b28ee..295b70f265 100644
--- a/test/functional/ui/hlstate_spec.lua
+++ b/test/functional/ui/hlstate_spec.lua
@@ -179,6 +179,8 @@ describe('ext_hlstate detailed highlights', function()
end)
it("work with :terminal", function()
+ if helpers.pending_win32(pending) then return end
+
screen:set_default_attr_ids({
[1] = {{}, {{hi_name = "TermCursorNC", ui_name = "TermCursorNC", kind = "ui"}}},
[2] = {{foreground = tonumber('0x00ccff'), fg_indexed=true}, {{kind = "term"}}},
diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua
index f038348253..949591870a 100644
--- a/test/functional/ui/messages_spec.lua
+++ b/test/functional/ui/messages_spec.lua
@@ -1206,6 +1206,7 @@ end)
describe('ui/msg_puts_printf', function()
it('output multibyte characters correctly', function()
+ if helpers.pending_win32(pending) then return end
local screen
local cmd = ''
local locale_dir = test_build_dir..'/share/locale/ja/LC_MESSAGES'
diff --git a/test/functional/ui/output_spec.lua b/test/functional/ui/output_spec.lua
index 50e5dfac84..7305baa761 100644
--- a/test/functional/ui/output_spec.lua
+++ b/test/functional/ui/output_spec.lua
@@ -14,6 +14,7 @@ local has_powershell = helpers.has_powershell
local set_shell_powershell = helpers.set_shell_powershell
describe("shell command :!", function()
+ if helpers.pending_win32(pending) then return end
local screen
before_each(function()
clear()
diff --git a/test/functional/ui/sign_spec.lua b/test/functional/ui/sign_spec.lua
index a0b7c98c51..f718786557 100644
--- a/test/functional/ui/sign_spec.lua
+++ b/test/functional/ui/sign_spec.lua
@@ -446,7 +446,7 @@ describe('Signs', function()
{1:>>>>>>>>}{6: 1 }a |
{2: }{6: 2 }b |
{2: }{6: 3 }c |
- {2: }{6:^ 4 } |
+ {2: }{6: 4 }^ |
{0:~ }|
{0:~ }|
{0:~ }|
@@ -468,7 +468,7 @@ describe('Signs', function()
{1:>>>>>>>>>>}{6: 1 }a |
{2: }{6: 2 }b |
{2: }{6: 3 }c |
- {2: ^ }{6: 4 } |
+ {2: }{6: 4 }^ |
{0:~ }|
{0:~ }|
{0:~ }|
@@ -512,7 +512,7 @@ describe('Signs', function()
{1:>>}{6: 1 }a |
{2: }{6: 2 }b |
{2: }{6: 3 }c |
- {2: }{6: ^4 } |
+ {2: }{6: 4 }^ |
{0:~ }|
{0:~ }|
{0:~ }|
diff --git a/test/helpers.lua b/test/helpers.lua
index 522714c8be..333e98d495 100644
--- a/test/helpers.lua
+++ b/test/helpers.lua
@@ -801,12 +801,10 @@ end
function module.isCI(name)
local any = (name == nil)
- assert(any or name == 'appveyor' or name == 'travis' or name == 'sourcehut' or name == 'github')
- local av = ((any or name == 'appveyor') and nil ~= os.getenv('APPVEYOR'))
- local tr = ((any or name == 'travis') and nil ~= os.getenv('TRAVIS'))
+ assert(any or name == 'sourcehut' or name == 'github')
local sh = ((any or name == 'sourcehut') and nil ~= os.getenv('SOURCEHUT'))
local gh = ((any or name == 'github') and nil ~= os.getenv('GITHUB_ACTIONS'))
- return tr or av or sh or gh
+ return sh or gh
end
diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt
index 174f1cbaba..2001171378 100644
--- a/third-party/CMakeLists.txt
+++ b/third-party/CMakeLists.txt
@@ -144,8 +144,8 @@ endif()
include(ExternalProject)
-set(LIBUV_URL https://github.com/libuv/libuv/archive/v1.42.0.tar.gz)
-set(LIBUV_SHA256 371e5419708f6aaeb8656671f89400b92a9bba6443369af1bb70bcd6e4b3c764)
+set(LIBUV_URL https://github.com/libuv/libuv/archive/7ae0c9543d0080968766288c73874aee3798ae30.tar.gz)
+set(LIBUV_SHA256 02ade646f52221e56f2515f8d0bfb8099204d21f6973b2a139bc726807ea803c)
set(MSGPACK_URL https://github.com/msgpack/msgpack-c/releases/download/cpp-3.0.0/msgpack-3.0.0.tar.gz)
set(MSGPACK_SHA256 bfbb71b7c02f806393bc3cbc491b40523b89e64f83860c58e3e54af47de176e4)
@@ -169,9 +169,9 @@ set(LIBTERMKEY_SHA256 6945bd3c4aaa83da83d80a045c5563da4edd7d0374c62c0d35aec09eb3
set(LIBVTERM_URL https://www.leonerd.org.uk/code/libvterm/libvterm-0.1.4.tar.gz)
set(LIBVTERM_SHA256 bc70349e95559c667672fc8c55b9527d9db9ada0fb80a3beda533418d782d3dd)
-set(LUV_VERSION 1.42.0-1)
+set(LUV_VERSION 1.43.0-0)
set(LUV_URL https://github.com/luvit/luv/archive/${LUV_VERSION}.tar.gz)
-set(LUV_SHA256 a55563e6da9294ea26f77a2111598aa49188c5806b8bd1e1f4bdf402f340713e)
+set(LUV_SHA256 a36865f34db029e2caa01245a41341a067038c09e94459b50db1346d9fdf82f0)
set(LUA_COMPAT53_URL https://github.com/keplerproject/lua-compat-5.3/archive/v0.9.tar.gz)
set(LUA_COMPAT53_SHA256 ad05540d2d96a48725bb79a1def35cf6652a4e2ec26376e2617c8ce2baa6f416)
diff --git a/third-party/cmake/BuildGettext.cmake b/third-party/cmake/BuildGettext.cmake
index 9357456343..6128ecfa69 100644
--- a/third-party/cmake/BuildGettext.cmake
+++ b/third-party/cmake/BuildGettext.cmake
@@ -21,6 +21,7 @@ if(MSVC)
-DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN}
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_GENERATOR=${CMAKE_GENERATOR}
+ -DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
-DLIBICONV_INCLUDE_DIRS=${DEPS_INSTALL_DIR}/include
-DLIBICONV_LIBRARIES=${DEPS_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}libcharset${CMAKE_STATIC_LIBRARY_SUFFIX}$<SEMICOLON>${DEPS_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}libiconv${CMAKE_STATIC_LIBRARY_SUFFIX}
BUILD_COMMAND ${CMAKE_COMMAND} --build . --config ${CMAKE_BUILD_TYPE}
diff --git a/third-party/cmake/BuildGperf.cmake b/third-party/cmake/BuildGperf.cmake
index 71c3cc1eef..5401191150 100644
--- a/third-party/cmake/BuildGperf.cmake
+++ b/third-party/cmake/BuildGperf.cmake
@@ -57,6 +57,7 @@ elseif(MSVC OR MINGW)
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-DCMAKE_GENERATOR=${CMAKE_GENERATOR}
+ -DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
BUILD_COMMAND ${CMAKE_COMMAND} --build . --config ${CMAKE_BUILD_TYPE}
diff --git a/third-party/cmake/BuildLibiconv.cmake b/third-party/cmake/BuildLibiconv.cmake
index dc3d8fe4c3..5ff33e0cd3 100644
--- a/third-party/cmake/BuildLibiconv.cmake
+++ b/third-party/cmake/BuildLibiconv.cmake
@@ -21,6 +21,7 @@ if(MSVC)
-DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN}
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_GENERATOR=${CMAKE_GENERATOR}
+ -DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
BUILD_COMMAND ${CMAKE_COMMAND} --build . --config ${CMAKE_BUILD_TYPE}
INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config ${CMAKE_BUILD_TYPE})
diff --git a/third-party/cmake/BuildLibtermkey.cmake b/third-party/cmake/BuildLibtermkey.cmake
index 10e98fbab3..d44e09d734 100644
--- a/third-party/cmake/BuildLibtermkey.cmake
+++ b/third-party/cmake/BuildLibtermkey.cmake
@@ -22,6 +22,7 @@ ExternalProject_Add(libtermkey
# Hack to avoid -rdynamic in Mingw
-DCMAKE_SHARED_LIBRARY_LINK_C_FLAGS=""
-DCMAKE_GENERATOR=${CMAKE_GENERATOR}
+ -DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
-DUNIBILIUM_INCLUDE_DIRS=${DEPS_INSTALL_DIR}/include
-DUNIBILIUM_LIBRARIES=${DEPS_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}unibilium${CMAKE_STATIC_LIBRARY_SUFFIX}
BUILD_COMMAND ${CMAKE_COMMAND} --build . --config ${CMAKE_BUILD_TYPE}
diff --git a/third-party/cmake/BuildLibuv.cmake b/third-party/cmake/BuildLibuv.cmake
index dce64c777b..42650308a8 100644
--- a/third-party/cmake/BuildLibuv.cmake
+++ b/third-party/cmake/BuildLibuv.cmake
@@ -63,10 +63,6 @@ elseif(WIN32)
set(BUILD_SHARED ON)
elseif(MINGW)
set(BUILD_SHARED OFF)
- set(LIBUV_PATCH_COMMAND
- ${GIT_EXECUTABLE} -C ${DEPS_BUILD_DIR}/src/libuv init
- COMMAND ${GIT_EXECUTABLE} -C ${DEPS_BUILD_DIR}/src/libuv apply --ignore-whitespace
- ${CMAKE_CURRENT_SOURCE_DIR}/patches/libuv-disable-typedef-MinGW.patch)
else()
message(FATAL_ERROR "Trying to build libuv in an unsupported system ${CMAKE_SYSTEM_NAME}/${CMAKE_C_COMPILER_ID}")
endif()
@@ -77,6 +73,7 @@ elseif(WIN32)
COMMAND ${CMAKE_COMMAND} ${DEPS_BUILD_DIR}/src/libuv/CMakeLists.txt
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
-DCMAKE_GENERATOR=${CMAKE_GENERATOR}
+ -DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DBUILD_SHARED_LIBS=${BUILD_SHARED}
-DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
diff --git a/third-party/cmake/BuildLibvterm.cmake b/third-party/cmake/BuildLibvterm.cmake
index 09f2ba7f2c..2c300dda7c 100644
--- a/third-party/cmake/BuildLibvterm.cmake
+++ b/third-party/cmake/BuildLibvterm.cmake
@@ -47,6 +47,7 @@ if(WIN32)
COMMAND ${CMAKE_COMMAND} ${DEPS_BUILD_DIR}/src/libvterm
-DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
+ -DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
"-DCMAKE_C_FLAGS:STRING=${CMAKE_C_COMPILER_ARG1} -fPIC"
-DCMAKE_GENERATOR=${CMAKE_GENERATOR})
set(LIBVTERM_BUILD_COMMAND ${CMAKE_COMMAND} --build . --config ${CMAKE_BUILD_TYPE})
diff --git a/third-party/cmake/BuildLuv.cmake b/third-party/cmake/BuildLuv.cmake
index 69f3b60ecf..99822249c2 100644
--- a/third-party/cmake/BuildLuv.cmake
+++ b/third-party/cmake/BuildLuv.cmake
@@ -104,6 +104,7 @@ elseif(MSVC)
set(LUV_CONFIGURE_COMMAND
${LUV_CONFIGURE_COMMAND_COMMON}
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
+ -DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
# Same as Unix without fPIC
"-DCMAKE_C_FLAGS:STRING=${CMAKE_C_COMPILER_ARG1} ${LUV_INCLUDE_FLAGS}"
# Make sure we use the same generator, otherwise we may
diff --git a/third-party/cmake/BuildMsgpack.cmake b/third-party/cmake/BuildMsgpack.cmake
index 39a8a64d23..ee4f0eb080 100644
--- a/third-party/cmake/BuildMsgpack.cmake
+++ b/third-party/cmake/BuildMsgpack.cmake
@@ -63,6 +63,7 @@ elseif(MSVC)
-DMSGPACK_BUILD_EXAMPLES=OFF
-DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
+ -DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
"-DCMAKE_C_FLAGS:STRING=${CMAKE_C_COMPILER_ARG1}"
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
# Make sure we use the same generator, otherwise we may
diff --git a/third-party/cmake/BuildTreesitter.cmake b/third-party/cmake/BuildTreesitter.cmake
index 0aa2706d7d..01fdb837e2 100644
--- a/third-party/cmake/BuildTreesitter.cmake
+++ b/third-party/cmake/BuildTreesitter.cmake
@@ -42,6 +42,7 @@ if(MSVC)
COMMAND ${CMAKE_COMMAND} ${DEPS_BUILD_DIR}/src/tree-sitter/CMakeLists.txt
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
-DCMAKE_GENERATOR=${CMAKE_GENERATOR}
+ -DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
BUILD_COMMAND ${CMAKE_COMMAND} --build . --config ${CMAKE_BUILD_TYPE}
diff --git a/third-party/cmake/BuildTreesitterParsers.cmake b/third-party/cmake/BuildTreesitterParsers.cmake
index 5284a7fd62..f966d640e6 100644
--- a/third-party/cmake/BuildTreesitterParsers.cmake
+++ b/third-party/cmake/BuildTreesitterParsers.cmake
@@ -17,6 +17,7 @@ CMAKE_ARGS
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-DCMAKE_GENERATOR=${CMAKE_GENERATOR}
+ -DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
# Pass toolchain
diff --git a/third-party/cmake/BuildUnibilium.cmake b/third-party/cmake/BuildUnibilium.cmake
index 74c1cbddb0..2f940bdfd3 100644
--- a/third-party/cmake/BuildUnibilium.cmake
+++ b/third-party/cmake/BuildUnibilium.cmake
@@ -18,6 +18,7 @@ if(WIN32)
-DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
# Pass toolchain
-DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN}
+ -DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_GENERATOR=${CMAKE_GENERATOR}
BUILD_COMMAND ${CMAKE_COMMAND} --build . --config ${CMAKE_BUILD_TYPE}
diff --git a/third-party/patches/libuv-disable-typedef-MinGW.patch b/third-party/patches/libuv-disable-typedef-MinGW.patch
deleted file mode 100644
index a47893cede..0000000000
--- a/third-party/patches/libuv-disable-typedef-MinGW.patch
+++ /dev/null
@@ -1,19 +0,0 @@
-diff --git a/include/uv/win.h b/include/uv/win.h
-index f5f1d3a3..64a0dfd9 100644
---- a/include/uv/win.h
-+++ b/include/uv/win.h
-@@ -45,7 +45,14 @@ typedef struct pollfd {
- #endif
-
- #include <mswsock.h>
-+// Disable the typedef in mstcpip.h of MinGW.
-+#define _TCP_INITIAL_RTO_PARAMETERS _TCP_INITIAL_RTO_PARAMETERS__
-+#define TCP_INITIAL_RTO_PARAMETERS TCP_INITIAL_RTO_PARAMETERS__
-+#define PTCP_INITIAL_RTO_PARAMETERS PTCP_INITIAL_RTO_PARAMETERS__
- #include <ws2tcpip.h>
-+#undef _TCP_INITIAL_RTO_PARAMETERS
-+#undef TCP_INITIAL_RTO_PARAMETERS
-+#undef PTCP_INITIAL_RTO_PARAMETERS
- #include <windows.h>
-
- #include <process.h>