diff options
39 files changed, 964 insertions, 554 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 70cdc3b4a2..dcc3c2c45f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,5 +1,9 @@ name: CI -on: [push, pull_request] +on: + push: + branches: '**' + pull_request: + branches: 'master' jobs: build: diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml deleted file mode 100644 index d4187d9dad..0000000000 --- a/.github/workflows/nightly.yml +++ /dev/null @@ -1,128 +0,0 @@ -name: Nightly release -on: - schedule: - - cron: '5 5 * * *' - -jobs: - linux: - runs-on: ubuntu-20.04 - outputs: - version: ${{ steps.build.outputs.version }} - release: ${{ steps.build.outputs.release }} - steps: - - uses: actions/checkout@v2 - - name: Install dependencies - 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: Build nightly - id: build - run: | - make CMAKE_BUILD_TYPE=RelWithDebinfo CMAKE_EXTRA_FLAGS="-DCMAKE_INSTALL_PREFIX:PATH=" - 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 | sed 's/-.*//')" - make DESTDIR="$GITHUB_WORKSPACE/build/nightly/nvim-linux64" install - cd "$GITHUB_WORKSPACE/build/nightly" - tar cfz nvim-linux64.tar.gz nvim-linux64 - - uses: actions/upload-artifact@v2 - with: - name: nvim-linux64.tar.gz - path: build/nightly/nvim-linux64.tar.gz - retention-days: 1 - - macOS: - runs-on: macos-10.15 - steps: - - uses: actions/checkout@v2 - - name: Install brew packages - run: | - brew update >/dev/null - brew install automake ninja - - name: Build nightly - run: | - make CMAKE_BUILD_TYPE=Release CMAKE_EXTRA_FLAGS="-DCMAKE_INSTALL_PREFIX:PATH= -DCMAKE_OSX_DEPLOYMENT_TARGET=10.11" - make DESTDIR="$GITHUB_WORKSPACE/build/nightly/nvim-osx64" install - - name: Create package - run: | - cd "$GITHUB_WORKSPACE/build/nightly" - mkdir -p bundle/nvim/libs - mkdir -p bundle/nvim/bin - cp nvim-osx64/bin/nvim bundle/nvim/bin/ - libs=($(otool -L nvim-osx64/bin/nvim | sed 1d | sed -E -e 's|^[[:space:]]*||' -e 's| .*||')) - echo "libs:" - for lib in "${libs[@]}"; do - if echo "$lib" | grep -q -E 'libSystem|CoreFoundation' 2>/dev/null; then - echo " [skipped] $lib" - else - echo " $lib" - relname="libs/${lib##*/}" - cp -L "$lib" "bundle/nvim/$relname" - install_name_tool -change "$lib" "@executable_path/../$relname" bundle/nvim/bin/nvim - fi - done - tar cjSf nvim-macos.tar.bz2 -C bundle nvim - - uses: actions/upload-artifact@v2 - with: - name: nvim-macos.tar.bz2 - path: build/nightly/nvim-macos.tar.bz2 - retention-days: 1 - - publish: - needs: [linux, macOS] - runs-on: ubuntu-20.04 - steps: - - uses: actions/download-artifact@v2 - - uses: actions/create-release@v1 - id: create_release - with: - tag_name: nightly - release_name: NVIM ${{ needs.linux.outputs.release }} - body: | - Nvim development (prerelease) build. - ``` - ${{ needs.linux.outputs.version }} - ``` - - ## Install - - ### Windows - - 1. Extract **nvim-win64.zip** (or **nvim-win32.zip**) - 2. Run `nvim-qt.exe` - - ### macOS - - 1. Download **nvim-macos.tar.gz** - 2. Extract: `tar xzvf nvim-macos.tar.gz` - 3. Run `./nvim-osx64/bin/nvim` - - ### Linux (x64) - - 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): - ``` - ./nvim.appimage --appimage-extract - ./squashfs-root/usr/bin/nvim - ``` - - ### Other - - - Install by [package manager](https://github.com/neovim/neovim/wiki/Installing-Neovim) - prerelease: true - - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./nvim-macos.tar.bz2 - asset_name: nvim-macos.tar.bz2 - asset_content_type: application/x-bzip2 - - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./nvim-linux64.tar.gz - asset_name: nvim-linux64.tar.gz - asset_content_type: application/gzip diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000000..d7f9556028 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,175 @@ +name: Release +on: + schedule: + - cron: '5 5 * * *' + workflow_dispatch: + inputs: + tag_name: + description: 'Tag name for release' + required: false + default: nightly + push: + tags: + - v[0-9]+.[0-9]+.[0-9]+ + +# Build on the oldest supported images, so we have broader compatibility +jobs: + linux: + runs-on: ubuntu-16.04 + outputs: + version: ${{ steps.build.outputs.version }} + release: ${{ steps.build.outputs.release }} + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y autoconf automake build-essential cmake gcc-multilib gettext gperf libtool-bin locales ninja-build pkg-config unzip + - name: Build release + id: build + run: | + make CMAKE_BUILD_TYPE=RelWithDebinfo CMAKE_EXTRA_FLAGS="-DCMAKE_INSTALL_PREFIX:PATH=" + 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 + - uses: actions/upload-artifact@v2 + with: + name: nvim-linux64 + path: build/release/nvim-linux64.tar.gz + retention-days: 1 + + appimage: + runs-on: ubuntu-16.04 + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y autoconf automake build-essential cmake gcc-multilib gettext gperf libtool-bin locales ninja-build pkg-config unzip + - if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.tag_name != 'nightly') + run: make appimage-latest + - if: github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && github.event.inputs.tag_name == 'nightly') + run: make appimage-nightly + - uses: actions/upload-artifact@v2 + with: + name: appimage + path: build/bin/nvim.appimage + retention-days: 1 + - uses: actions/upload-artifact@v2 + with: + name: appimage + path: build/bin/nvim.appimage.zsync + retention-days: 1 + + macOS: + runs-on: macos-10.15 + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Install brew packages + run: | + brew update >/dev/null + brew install automake ninja + - name: Build release + run: | + make CMAKE_BUILD_TYPE=Release CMAKE_EXTRA_FLAGS="-DCMAKE_INSTALL_PREFIX:PATH= -DCMAKE_OSX_DEPLOYMENT_TARGET=10.11" + make DESTDIR="$GITHUB_WORKSPACE/build/release/nvim-osx64" install + - name: Create package + run: | + cd "$GITHUB_WORKSPACE/build/release" + mkdir -p nvim-osx64/libs + libs=($(otool -L nvim-osx64/bin/nvim | sed 1d | sed -E -e 's|^[[:space:]]*||' -e 's| .*||')) + echo "libs:" + for lib in "${libs[@]}"; do + if echo "$lib" | grep -q -E 'libSystem|CoreFoundation' 2>/dev/null; then + echo " [skipped] $lib" + else + echo " $lib" + relname="libs/${lib##*/}" + cp -L "$lib" "nvim-osx64/$relname" + install_name_tool -change "$lib" "@executable_path/../$relname" nvim-osx64/bin/nvim + fi + done + tar cfz nvim-macos.tar.gz nvim-osx64 + - uses: actions/upload-artifact@v2 + with: + name: nvim-macos + path: build/release/nvim-macos.tar.gz + retention-days: 1 + + publish: + needs: [linux, appimage, macOS] + runs-on: ubuntu-20.04 + steps: + - uses: actions/download-artifact@v2 + - if: github.event_name == 'workflow_dispatch' + run: echo "TAG_NAME=${{ github.event.inputs.tag_name }}" >> $GITHUB_ENV + - if: github.event_name == 'schedule' + run: echo 'TAG_NAME=nightly' >> $GITHUB_ENV + - if: github.event_name == 'push' + run: | + TAG_NAME=${{ github.ref }} + echo "TAG_NAME=${TAG_NAME#refs/tags/}" >> $GITHUB_ENV + - if: env.TAG_NAME == 'nightly' + run: echo 'SUBJECT=Nvim development (prerelease) build' >> $GITHUB_ENV + - if: env.TAG_NAME != 'nightly' + run: echo 'SUBJECT=Nvim release build' >> $GITHUB_ENV + - if: env.TAG_NAME == 'nightly' + uses: dev-drprasad/delete-tag-and-release@v0.1.2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + delete_release: false + tag_name: nightly + - uses: meeDamian/github-release@2.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + tag: ${{ env.TAG_NAME }} + name: ${{ needs.linux.outputs.release }} + prerelease: ${{ env.TAG_NAME == 'nightly' }} + commitish: ${{ github.sha }} + gzip: false + allow_override: ${{ env.TAG_NAME == 'nightly' }} + files: | + nvim-macos.tar.gz:./nvim-macos/nvim-macos.tar.gz + nvim-linux64.tar.gz:./nvim-linux64/nvim-linux64.tar.gz + nvim.appimage:./appimage/nvim.appimage + nvim.appimage.zsync:./appimage/nvim.appimage.zsync + body: | + ${{ env.SUBJECT }} + ``` + ${{ needs.linux.outputs.version }}``` + + ## Install + + ### Windows + + 1. Extract **nvim-win64.zip** (or **nvim-win32.zip**) + 2. Run `nvim-qt.exe` + + ### macOS + + 1. Download **nvim-macos.tar.gz** + 2. Extract: `tar xzvf nvim-macos.tar.gz` + 3. Run `./nvim-osx64/bin/nvim` + + ### Linux (x64) + + 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): + ``` + ./nvim.appimage --appimage-extract + ./squashfs-root/usr/bin/nvim + ``` + + ### Other + + - Install by [package manager](https://github.com/neovim/neovim/wiki/Installing-Neovim) diff --git a/contrib/flake.nix b/contrib/flake.nix new file mode 100644 index 0000000000..a75e584075 --- /dev/null +++ b/contrib/flake.nix @@ -0,0 +1,95 @@ +{ + description = "Neovim flake"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + }; + + outputs = { self, nixpkgs }: let + system = "x86_64-linux"; + legacyPkgs = nixpkgs.legacyPackages."${system}".pkgs; + pkgs = legacyPkgs; + in { + + packages."${system}" = rec { + + neovim = legacyPkgs.neovim-unwrapped.overrideAttrs(oa: { + version = "master"; + src = ../.; + + buildInputs = oa.buildInputs ++ ([ + pkgs.tree-sitter + ]); + + cmakeFlags = oa.cmakeFlags ++ [ + "-DUSE_BUNDLED=OFF" + ]; + }); + + # a development binary to help debug issues + neovim-debug = (neovim.override { + stdenv = pkgs.llvmPackages_latest.stdenv; + lua = pkgs.enableDebugging legacyPkgs.luajit; + }).overrideAttrs(oa:{ + cmakeBuildType="Debug"; + cmakeFlags = oa.cmakeFlags ++ [ + "-DMIN_LOG_LEVEL=0" + ]; + }); + + # for neovim developers, very slow + # brings development tools as well + neovim-developer = let + lib = nixpkgs.lib; + pythonEnv = legacyPkgs.python3; + luacheck = legacyPkgs.luaPackages.luacheck; + in + neovim-debug.overrideAttrs(oa: { + cmakeFlags = oa.cmakeFlags ++ [ + "-DLUACHECK_PRG=${luacheck}/bin/luacheck" + "-DMIN_LOG_LEVEL=0" + "-DENABLE_LTO=OFF" + "-DUSE_BUNDLED=OFF" + # https://github.com/google/sanitizers/wiki/AddressSanitizerFlags + # https://clang.llvm.org/docs/AddressSanitizer.html#symbolizing-the-reports + "-DCLANG_ASAN_UBSAN=ON" + ]; + + nativeBuildInputs = oa.nativeBuildInputs ++ (with pkgs; [ + pythonEnv + include-what-you-use # for scripts/check-includes.py + jq # jq for scripts/vim-patch.sh -r + doxygen + ]); + + shellHook = oa.shellHook + '' + export NVIM_PYTHON_LOG_LEVEL=DEBUG + export NVIM_LOG_FILE=/tmp/nvim.log + + export ASAN_OPTIONS="log_path=./test.log:abort_on_error=1" + export UBSAN_OPTIONS=print_stacktrace=1 + ''; + }); + }; + + defaultPackage."${system}" = self.packages."${system}".neovim; + + overlay = final: prev: { + inherit (self.packages."${system}") neovim neovim-debug; + }; + + apps."${system}" = let + mkApp = pkg: { + type = "app"; + program = pkg + "/bin/nvim"; + }; + in { + nvim = mkApp self.packages."${system}".neovim; + nvim-debug = mkApp self.packages."${system}".neovim-debug; + }; + + defaultApp."${system}" = self.apps."${system}".nvim; + + devShell."${system}" = self.packages."${system}".neovim-developer; + }; +} diff --git a/runtime/autoload/man.vim b/runtime/autoload/man.vim index 486ed99e3f..99d8c41dba 100644 --- a/runtime/autoload/man.vim +++ b/runtime/autoload/man.vim @@ -18,7 +18,7 @@ function! man#init() abort endtry endfunction -function! man#open_page(count, count1, mods, ...) abort +function! man#open_page(count, mods, ...) abort if a:0 > 2 call s:error('too many arguments') return @@ -39,9 +39,7 @@ function! man#open_page(count, count1, mods, ...) abort endif try let [sect, name] = s:extract_sect_and_name_ref(ref) - if a:count ==# a:count1 - " v:count defaults to 0 which is a valid section, and v:count1 defaults to - " 1, also a valid section. If they are equal, count explicitly set. + if a:count >= 0 let sect = string(a:count) endif let path = s:verify_exists(sect, name) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 343e35bf66..f306806c96 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -8441,8 +8441,6 @@ strftime({format} [, {time}]) *strftime()* :echo strftime("%H:%M") 11:55 :echo strftime("%c", getftime("file.c")) Show mod time of file.c. -< Not available on all systems. To check use: > - :if exists("*strftime") strgetchar({str}, {index}) *strgetchar()* Get character {index} from {str}. This uses a character diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index c8a44dfb75..ea9072841c 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -247,7 +247,7 @@ For |lsp-notification|, each |lsp-handler| has this signature: > of a particular handler. For an example, see: - |vim.lsp.diagnostics.on_publish_diagnostics()| + |vim.lsp.diagnostic.on_publish_diagnostics()| To configure a particular |lsp-handler|, see: |lsp-handler-configuration| @@ -715,6 +715,15 @@ start_client({config}) *vim.lsp.start_client()* The following parameters describe fields in the {config} table. +> + + -- In attach function for the client, you can do: + local custom_attach = function(client) + if client.config.flags then + client.config.flags.allow_incremental_sync = true + end + end +< Parameters: ~ {root_dir} (required, string) Directory where the @@ -796,6 +805,11 @@ start_client({config}) *vim.lsp.start_client()* in the initialize request. Invalid/empty values will default to "off" + {flags} A table with flags for the client. The + current (experimental) flags are: + • allow_incremental_sync (bool, default + false): Allow using on_line callbacks + for lsp Return: ~ Client id. |vim.lsp.get_client_by_id()| Note: client may @@ -833,6 +847,12 @@ with({handler}, {override_config}) *vim.lsp.with()* ============================================================================== Lua module: vim.lsp.buf *lsp-buf* + *vim.lsp.buf.add_workspace_folder()* +add_workspace_folder({workspace_folder}) + Add the folder at path to the workspace folders. If {path} is + not provided, the user will be prompted for a path using + |input()|. + clear_references() *vim.lsp.buf.clear_references()* Removes document highlights from current buffer. @@ -935,6 +955,9 @@ incoming_calls() *vim.lsp.buf.incoming_calls()* |quickfix| window. If the symbol can resolve to multiple items, the user can pick one in the |inputlist|. +list_workspace_folders() *vim.lsp.buf.list_workspace_folders()* + List workspace folders. + outgoing_calls() *vim.lsp.buf.outgoing_calls()* Lists all the items that are called by the symbol under the cursor in the |quickfix| window. If the symbol can resolve to @@ -961,6 +984,9 @@ range_formatting({options}, {start_pos}, {end_pos}) Parameters: ~ {options} Table with valid `FormattingOptions` entries. {start_pos} ({number, number}, optional) mark-indexed + position. Defaults to the start of the last + visual selection. + {end_pos} ({number, number}, optional) mark-indexed position. Defaults to the end of the last visual selection. @@ -974,6 +1000,12 @@ references({context}) *vim.lsp.buf.references()* See also: ~ https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references + *vim.lsp.buf.remove_workspace_folder()* +remove_workspace_folder({workspace_folder}) + Remove the folder at path from the workspace folders. If + {path} is not provided, the user will be prompted for a path + using |input()|. + rename({new_name}) *vim.lsp.buf.rename()* Renames all references to the symbol under the cursor. @@ -996,19 +1028,6 @@ type_definition() *vim.lsp.buf.type_definition()* Jumps to the definition of the type of the symbol under the cursor. -add_workspace_folder({path}) *vim.lsp.buf.add_workspace_folder()* - Add the folder at path to the workspace folders. If {path} is - not provided, the user will be prompted for a path using - |input()|. - -remove_workspace_folder({path}) *vim.lsp.buf.remove_workspace_folder()* - Remove the folder at path from the workspace folders. If - {path} is not provided, the user will be prompted for - a path using |input()|. - -list_workspace_folders() *vim.lsp.buf.list_workspace_folders()* - List all folders in the workspace. - workspace_symbol({query}) *vim.lsp.buf.workspace_symbol()* Lists all symbols in the current workspace in the quickfix window. @@ -1062,9 +1081,9 @@ get_count({bufnr}, {severity}, {client_id}) let sl = '' if luaeval('not vim.tbl_isempty(vim.lsp.buf_get_clients(0))') let sl.='%#MyStatuslineLSP#E:' - let sl.='%#MyStatuslineLSPErrors#%{luaeval("vim.lsp.diagnostic.get_count(vim.fn.bufnr('%'), [[Error]])")}' + let sl.='%#MyStatuslineLSPErrors#%{luaeval("vim.lsp.diagnostic.get_count(0, [[Error]])")}' let sl.='%#MyStatuslineLSP# W:' - let sl.='%#MyStatuslineLSPWarnings#%{luaeval("vim.lsp.diagnostic.get_count(vim.fn.bufnr('%'), [[Warning]])")}' + let sl.='%#MyStatuslineLSPWarnings#%{luaeval("vim.lsp.diagnostic.get_count(0, [[Warning]])")}' else let sl.='%#MyStatuslineLSPErrors#off' endif @@ -1104,7 +1123,7 @@ get_next({opts}) *vim.lsp.diagnostic.get_next()* Get the previous diagnostic closest to the cursor_position Parameters: ~ - {opts} table See |vim.lsp.diagnostics.goto_next()| + {opts} table See |vim.lsp.diagnostic.goto_next()| Return: ~ table Next diagnostic @@ -1114,7 +1133,7 @@ get_next_pos({opts}) *vim.lsp.diagnostic.get_next_pos()* current buffer. Parameters: ~ - {opts} table See |vim.lsp.diagnostics.goto_next()| + {opts} table See |vim.lsp.diagnostic.goto_next()| Return: ~ table Next diagnostic position @@ -1123,7 +1142,7 @@ get_prev({opts}) *vim.lsp.diagnostic.get_prev()* Get the previous diagnostic closest to the cursor_position Parameters: ~ - {opts} table See |vim.lsp.diagnostics.goto_next()| + {opts} table See |vim.lsp.diagnostic.goto_next()| Return: ~ table Previous diagnostic @@ -1133,7 +1152,7 @@ get_prev_pos({opts}) *vim.lsp.diagnostic.get_prev_pos()* current buffer. Parameters: ~ - {opts} table See |vim.lsp.diagnostics.goto_next()| + {opts} table See |vim.lsp.diagnostic.goto_next()| Return: ~ table Previous diagnostic position @@ -1196,7 +1215,7 @@ goto_prev({opts}) *vim.lsp.diagnostic.goto_prev()* Move to the previous diagnostic Parameters: ~ - {opts} table See |vim.lsp.diagnostics.goto_next()| + {opts} table See |vim.lsp.diagnostic.goto_next()| *vim.lsp.diagnostic.on_publish_diagnostics()* on_publish_diagnostics({_}, {_}, {params}, {client_id}, {_}, {config}) @@ -1654,6 +1673,14 @@ make_text_document_params() *vim.lsp.util.make_text_document_params()* See also: ~ https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentIdentifier + *vim.lsp.util.make_workspace_params()* +make_workspace_params({added}, {removed}) + Create the workspace params + + Parameters: ~ + {added} + {removed} + *vim.lsp.util.open_floating_preview()* open_floating_preview({contents}, {filetype}, {opts}) Shows contents in a floating window. diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index ae77b0a35a..cd6186834d 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -280,7 +280,7 @@ This lists the currently available predicates to use in queries. Treesitter syntax highlighting (WIP) *lua-treesitter-highlight* NOTE: This is a partially implemented feature, and not usable as a default -solution yet. What is documented here is a temporary interface indented +solution yet. What is documented here is a temporary interface intended for those who want to experiment with this feature and contribute to its development. diff --git a/runtime/filetype.vim b/runtime/filetype.vim index ed19fa1a43..ed3204c537 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -1744,6 +1744,9 @@ au BufNewFile,BufRead *.tf,.tfrc,tfrc setf tf " tmux configuration au BufNewFile,BufRead {.,}tmux*.conf setf tmux +" TOML +au BufNewFile,BufRead *.toml setf toml + " TPP - Text Presentation Program au BufNewFile,BufReadPost *.tpp setf tpp diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index f082fe29f2..ed31572abb 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1,3 +1,5 @@ +local if_nil = vim.F.if_nil + local default_handlers = require 'vim.lsp.handlers' local log = require 'vim.lsp.log' local lsp_rpc = require 'vim.lsp.rpc' @@ -226,6 +228,7 @@ local function validate_client_config(config) on_init = { config.on_init, "f", true }; before_init = { config.before_init, "f", true }; offset_encoding = { config.offset_encoding, "s", true }; + flags = { config.flags, "t", true }; } -- TODO(remove-callbacks) @@ -434,6 +437,17 @@ end --- --@param trace: "off" | "messages" | "verbose" | nil passed directly to the language --- server in the initialize request. Invalid/empty values will default to "off" +--@param flags: A table with flags for the client. The current (experimental) flags are: +--- - allow_incremental_sync (bool, default false): Allow using on_line callbacks for lsp +--- +--- <pre> +--- -- In attach function for the client, you can do: +--- local custom_attach = function(client) +--- if client.config.flags then +--- client.config.flags.allow_incremental_sync = true +--- end +--- end +--- </pre> --- --@returns Client id. |vim.lsp.get_client_by_id()| Note: client may not be --- fully initialized. Use `on_init` to do any actions once @@ -442,6 +456,8 @@ function lsp.start_client(config) local cleaned_config = validate_client_config(config) local cmd, cmd_args, offset_encoding = cleaned_config.cmd, cleaned_config.cmd_args, cleaned_config.offset_encoding + config.flags = config.flags or {} + local client_id = next_client_id() -- TODO(remove-callbacks) @@ -799,6 +815,7 @@ do local size_index = encoding_index[client.offset_encoding] local length = select(size_index, old_byte_size, old_utf16_size, old_utf32_size) local lines = nvim_buf_get_lines(bufnr, firstline, new_lastline, true) + -- This is necessary because we are specifying the full line including the -- newline in range. Therefore, we must replace the newline as well. if #lines > 0 then @@ -820,6 +837,8 @@ do end) local uri = vim.uri_from_bufnr(bufnr) for_each_buffer_client(bufnr, function(client, _client_id) + local allow_incremental_sync = if_nil(client.config.flags.allow_incremental_sync, false) + local text_document_did_change = client.resolved_capabilities.text_document_did_change local changes if text_document_did_change == protocol.TextDocumentSyncKind.None then @@ -830,7 +849,7 @@ do -- is no way to specify the sync capability by the client. -- See https://github.com/palantir/python-language-server/commit/cfd6675bc10d5e8dbc50fc50f90e4a37b7178821#diff-f68667852a14e9f761f6ebf07ba02fc8 for an example of pyls handling both. --]=] - elseif true or text_document_did_change == protocol.TextDocumentSyncKind.Full then + elseif not allow_incremental_sync or text_document_did_change == protocol.TextDocumentSyncKind.Full then changes = full_changes(client) elseif text_document_did_change == protocol.TextDocumentSyncKind.Incremental then changes = incremental_changes(client) diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index a70581478b..00219b6d98 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -149,7 +149,7 @@ end --@param options Table with valid `FormattingOptions` entries. --@param start_pos ({number, number}, optional) mark-indexed position. ---Defaults to the start of the last visual selection. ---@param start_pos ({number, number}, optional) mark-indexed position. +--@param end_pos ({number, number}, optional) mark-indexed position. ---Defaults to the end of the last visual selection. function M.range_formatting(options, start_pos, end_pos) validate { options = {options, 't', true} } @@ -239,6 +239,7 @@ function M.outgoing_calls() end --- List workspace folders. +--- function M.list_workspace_folders() local workspace_folders = {} for _, client in ipairs(vim.lsp.buf_get_clients()) do @@ -249,7 +250,8 @@ function M.list_workspace_folders() return workspace_folders end ---- Add a workspace folder. +--- Add the folder at path to the workspace folders. If {path} is +--- not provided, the user will be prompted for a path using |input()|. function M.add_workspace_folder(workspace_folder) workspace_folder = workspace_folder or npcall(vfn.input, "Workspace Folder: ", vfn.expand('%:p:h')) vim.api.nvim_command("redraw") @@ -275,7 +277,9 @@ function M.add_workspace_folder(workspace_folder) end end ---- Remove a workspace folder. +--- Remove the folder at path from the workspace folders. If +--- {path} is not provided, the user will be prompted for +--- a path using |input()|. function M.remove_workspace_folder(workspace_folder) workspace_folder = workspace_folder or npcall(vfn.input, "Workspace Folder: ", vfn.expand('%:p:h')) vim.api.nvim_command("redraw") diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua index 27a1f53f89..efca5b53af 100644 --- a/runtime/lua/vim/lsp/diagnostic.lua +++ b/runtime/lua/vim/lsp/diagnostic.lua @@ -400,9 +400,9 @@ end --- let sl = '' --- if luaeval('not vim.tbl_isempty(vim.lsp.buf_get_clients(0))') --- let sl.='%#MyStatuslineLSP#E:' ---- let sl.='%#MyStatuslineLSPErrors#%{luaeval("vim.lsp.diagnostic.get_count([[Error]])")}' +--- let sl.='%#MyStatuslineLSPErrors#%{luaeval("vim.lsp.diagnostic.get_count(0, [[Error]])")}' --- let sl.='%#MyStatuslineLSP# W:' ---- let sl.='%#MyStatuslineLSPWarnings#%{luaeval("vim.lsp.diagnostic.get_count([[Warning]])")}' +--- let sl.='%#MyStatuslineLSPWarnings#%{luaeval("vim.lsp.diagnostic.get_count(0, [[Warning]])")}' --- else --- let sl.='%#MyStatuslineLSPErrors#off' --- endif @@ -510,7 +510,7 @@ end --- Get the previous diagnostic closest to the cursor_position --- ----@param opts table See |vim.lsp.diagnostics.goto_next()| +---@param opts table See |vim.lsp.diagnostic.goto_next()| ---@return table Previous diagnostic function M.get_prev(opts) opts = opts or {} @@ -523,7 +523,7 @@ function M.get_prev(opts) end --- Return the pos, {row, col}, for the prev diagnostic in the current buffer. ----@param opts table See |vim.lsp.diagnostics.goto_next()| +---@param opts table See |vim.lsp.diagnostic.goto_next()| ---@return table Previous diagnostic position function M.get_prev_pos(opts) return _iter_diagnostic_lines_pos( @@ -533,7 +533,7 @@ function M.get_prev_pos(opts) end --- Move to the previous diagnostic ----@param opts table See |vim.lsp.diagnostics.goto_next()| +---@param opts table See |vim.lsp.diagnostic.goto_next()| function M.goto_prev(opts) return _iter_diagnostic_move_pos( "DiagnosticPrevious", @@ -543,7 +543,7 @@ function M.goto_prev(opts) end --- Get the previous diagnostic closest to the cursor_position ----@param opts table See |vim.lsp.diagnostics.goto_next()| +---@param opts table See |vim.lsp.diagnostic.goto_next()| ---@return table Next diagnostic function M.get_next(opts) opts = opts or {} @@ -556,7 +556,7 @@ function M.get_next(opts) end --- Return the pos, {row, col}, for the next diagnostic in the current buffer. ----@param opts table See |vim.lsp.diagnostics.goto_next()| +---@param opts table See |vim.lsp.diagnostic.goto_next()| ---@return table Next diagnostic position function M.get_next_pos(opts) return _iter_diagnostic_lines_pos( diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 5804ac6656..3da4dd6219 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -1022,7 +1022,7 @@ do --@deprecated function M.buf_diagnostics_signs(bufnr, diagnostics, client_id) - warn_once("buf_diagnostics_signs is deprecated. Use 'vim.lsp.diagnostics.set_signs'") + warn_once("buf_diagnostics_signs is deprecated. Use 'vim.lsp.diagnostic.set_signs'") return vim.lsp.diagnostic.set_signs(diagnostics, bufnr, client_id) end @@ -1315,6 +1315,9 @@ function M.make_text_document_params() return { uri = vim.uri_from_bufnr(0) } end +--- Create the workspace params +--@param added +--@param removed function M.make_workspace_params(added, removed) return { event = { added = added; removed = removed; } } end diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index 0a28891814..04b5fee256 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -452,7 +452,7 @@ end function LanguageTree:language_for_range(range) for _, child in pairs(self._children) do if child:contains(range) then - return child:node_for_range(range) + return child:language_for_range(range) end end diff --git a/runtime/plugin/man.vim b/runtime/plugin/man.vim index e762eb3664..689aa32ef3 100644 --- a/runtime/plugin/man.vim +++ b/runtime/plugin/man.vim @@ -5,9 +5,9 @@ if exists('g:loaded_man') endif let g:loaded_man = 1 -command! -bang -bar -range=0 -complete=customlist,man#complete -nargs=* Man +command! -bang -bar -range=-1 -complete=customlist,man#complete -nargs=* Man \ if <bang>0 | set ft=man | - \ else | call man#open_page(v:count, v:count1, <q-mods>, <f-args>) | endif + \ else | call man#open_page(<count>, <q-mods>, <f-args>) | endif augroup man autocmd! diff --git a/scripts/update_version_stamp.lua b/scripts/update_version_stamp.lua index 11b521fab6..0342e08f31 100755 --- a/scripts/update_version_stamp.lua +++ b/scripts/update_version_stamp.lua @@ -35,11 +35,10 @@ if not described then end -- `git describe` annotates the most recent tagged release; for pre-release --- builds we must replace that with the unreleased version. -local with_prefix = described:gsub("^v%d+%.%d+%.%d+", prefix) -if described == with_prefix then - -- Prepend the prefix always, e.g. with "nightly-12208-g4041b62b9". - with_prefix = prefix .. "-" .. described +-- builds we append that to the dev version +local with_prefix = prefix +if prefix:match('-dev$') ~= nil then + with_prefix = prefix .. '+' .. described:gsub('^v%d+%.%d+%.%d+-', '') end -- Read existing include file. diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 8ec087c626..db77931c16 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -242,7 +242,7 @@ if(use_git_version) add_custom_target(update_version_stamp ALL COMMAND ${LUA_PRG} scripts/update_version_stamp.lua ${relbuild}/config/auto/versiondef_git.h - "v${NVIM_VERSION_MAJOR}.${NVIM_VERSION_MINOR}.${NVIM_VERSION_PATCH}" + "v${NVIM_VERSION_MAJOR}.${NVIM_VERSION_MINOR}.${NVIM_VERSION_PATCH}${NVIM_VERSION_PRERELEASE}" WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} BYPRODUCTS ${CMAKE_BINARY_DIR}/config/auto/versiondef_git.h) else() diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 1011f050fd..db37e2100d 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -1,7 +1,7 @@ // This is an open source non-commercial project. Dear PVS-Studio, please check // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -// Much of this code was adapted from 'if_py_both.h' from the original +// Some of this code was adapted from 'if_py_both.h' from the original // vim source #include <stdbool.h> #include <stdint.h> @@ -80,34 +80,6 @@ Integer nvim_buf_line_count(Buffer buffer, Error *err) return buf->b_ml.ml_line_count; } -/// Gets a buffer line -/// -/// @deprecated use nvim_buf_get_lines instead. -/// for positive indices (including 0) use -/// "nvim_buf_get_lines(buffer, index, index+1, true)" -/// for negative indices use -/// "nvim_buf_get_lines(buffer, index-1, index, true)" -/// -/// @param buffer Buffer handle -/// @param index Line index -/// @param[out] err Error details, if any -/// @return Line string -String buffer_get_line(Buffer buffer, Integer index, Error *err) -{ - String rv = { .size = 0 }; - - index = convert_index(index); - Array slice = nvim_buf_get_lines(0, buffer, index, index+1, true, err); - - if (!ERROR_SET(err) && slice.size) { - rv = slice.items[0].data.string; - } - - xfree(slice.items); - - return rv; -} - /// Activates buffer-update events on a channel, or as Lua callbacks. /// /// Example (Lua): capture buffer updates in a global `events` variable @@ -258,68 +230,6 @@ void nvim__buf_redraw_range(Buffer buffer, Integer first, Integer last, redraw_buf_range_later(buf, (linenr_T)first+1, (linenr_T)last); } -/// Sets a buffer line -/// -/// @deprecated use nvim_buf_set_lines instead. -/// for positive indices use -/// "nvim_buf_set_lines(buffer, index, index+1, true, [line])" -/// for negative indices use -/// "nvim_buf_set_lines(buffer, index-1, index, true, [line])" -/// -/// @param buffer Buffer handle -/// @param index Line index -/// @param line Contents of the new line -/// @param[out] err Error details, if any -void buffer_set_line(Buffer buffer, Integer index, String line, Error *err) -{ - Object l = STRING_OBJ(line); - Array array = { .items = &l, .size = 1 }; - index = convert_index(index); - nvim_buf_set_lines(0, buffer, index, index+1, true, array, err); -} - -/// Deletes a buffer line -/// -/// @deprecated use nvim_buf_set_lines instead. -/// for positive indices use -/// "nvim_buf_set_lines(buffer, index, index+1, true, [])" -/// for negative indices use -/// "nvim_buf_set_lines(buffer, index-1, index, true, [])" -/// @param buffer buffer handle -/// @param index line index -/// @param[out] err Error details, if any -void buffer_del_line(Buffer buffer, Integer index, Error *err) -{ - Array array = ARRAY_DICT_INIT; - index = convert_index(index); - nvim_buf_set_lines(0, buffer, index, index+1, true, array, err); -} - -/// Retrieves a line range from the buffer -/// -/// @deprecated use nvim_buf_get_lines(buffer, newstart, newend, false) -/// where newstart = start + int(not include_start) - int(start < 0) -/// newend = end + int(include_end) - int(end < 0) -/// int(bool) = 1 if bool is true else 0 -/// @param buffer Buffer handle -/// @param start First line index -/// @param end Last line index -/// @param include_start True if the slice includes the `start` parameter -/// @param include_end True if the slice includes the `end` parameter -/// @param[out] err Error details, if any -/// @return Array of lines -ArrayOf(String) buffer_get_line_slice(Buffer buffer, - Integer start, - Integer end, - Boolean include_start, - Boolean include_end, - Error *err) -{ - start = convert_index(start) + !include_start; - end = convert_index(end) + include_end; - return nvim_buf_get_lines(0, buffer, start , end, false, err); -} - /// Gets a line-range from the buffer. /// /// Indexing is zero-based, end-exclusive. Negative indices are interpreted @@ -392,35 +302,6 @@ end: } -/// Replaces a line range on the buffer -/// -/// @deprecated use nvim_buf_set_lines(buffer, newstart, newend, false, lines) -/// where newstart = start + int(not include_start) + int(start < 0) -/// newend = end + int(include_end) + int(end < 0) -/// int(bool) = 1 if bool is true else 0 -/// -/// @param buffer Buffer handle, or 0 for current buffer -/// @param start First line index -/// @param end Last line index -/// @param include_start True if the slice includes the `start` parameter -/// @param include_end True if the slice includes the `end` parameter -/// @param replacement Array of lines to use as replacement (0-length -// array will delete the line range) -/// @param[out] err Error details, if any -void buffer_set_line_slice(Buffer buffer, - Integer start, - Integer end, - Boolean include_start, - Boolean include_end, - ArrayOf(String) replacement, - Error *err) -{ - start = convert_index(start) + !include_start; - end = convert_index(end) + include_end; - nvim_buf_set_lines(0, buffer, start, end, false, replacement, err); -} - - /// Sets (replaces) a line-range in the buffer. /// /// Indexing is zero-based, end-exclusive. Negative indices are interpreted @@ -787,48 +668,6 @@ void nvim_buf_del_var(Buffer buffer, String name, Error *err) dict_set_var(buf->b_vars, name, NIL, true, false, err); } -/// Sets a buffer-scoped (b:) variable -/// -/// @deprecated -/// -/// @param buffer Buffer handle, or 0 for current buffer -/// @param name Variable name -/// @param value Variable value -/// @param[out] err Error details, if any -/// @return Old value or nil if there was no previous value. -/// -/// @warning It may return nil if there was no previous value -/// or if previous value was `v:null`. -Object buffer_set_var(Buffer buffer, String name, Object value, Error *err) -{ - buf_T *buf = find_buffer_by_handle(buffer, err); - - if (!buf) { - return (Object) OBJECT_INIT; - } - - return dict_set_var(buf->b_vars, name, value, false, true, err); -} - -/// Removes a buffer-scoped (b:) variable -/// -/// @deprecated -/// -/// @param buffer Buffer handle, or 0 for current buffer -/// @param name Variable name -/// @param[out] err Error details, if any -/// @return Old value -Object buffer_del_var(Buffer buffer, String name, Error *err) -{ - buf_T *buf = find_buffer_by_handle(buffer, err); - - if (!buf) { - return (Object) OBJECT_INIT; - } - - return dict_set_var(buf->b_vars, name, NIL, true, true, err); -} - /// Gets a buffer option value /// @@ -869,28 +708,6 @@ void nvim_buf_set_option(uint64_t channel_id, Buffer buffer, set_option_to(channel_id, buf, SREQ_BUF, name, value, err); } -/// Gets the buffer number -/// -/// @deprecated The buffer number now is equal to the object id, -/// so there is no need to use this function. -/// -/// @param buffer Buffer handle, or 0 for current buffer -/// @param[out] err Error details, if any -/// @return Buffer number -Integer nvim_buf_get_number(Buffer buffer, Error *err) - FUNC_API_SINCE(1) - FUNC_API_DEPRECATED_SINCE(2) -{ - Integer rv = 0; - buf_T *buf = find_buffer_by_handle(buffer, err); - - if (!buf) { - return rv; - } - - return buf->b_fnum; -} - /// Gets the full file name for the buffer /// /// @param buffer Buffer handle, or 0 for current buffer @@ -1017,25 +834,6 @@ Boolean nvim_buf_is_valid(Buffer buffer) return ret; } -/// Inserts a sequence of lines to a buffer at a certain index -/// -/// @deprecated use nvim_buf_set_lines(buffer, lnum, lnum, true, lines) -/// -/// @param buffer Buffer handle -/// @param lnum Insert the lines after `lnum`. If negative, appends to -/// the end of the buffer. -/// @param lines Array of lines -/// @param[out] err Error details, if any -void buffer_insert(Buffer buffer, - Integer lnum, - ArrayOf(String) lines, - Error *err) -{ - // "lnum" will be the index of the line after inserting, - // no matter if it is negative or not - nvim_buf_set_lines(0, buffer, lnum, lnum, true, lines, err); -} - /// Return a tuple (row,col) representing the position of the named mark. /// /// Marks are (1,0)-indexed. |api-indexing| @@ -1667,27 +1465,6 @@ void nvim_buf_clear_namespace(Buffer buffer, (int)line_end-1, MAXCOL); } -/// Clears highlights and virtual text from namespace and range of lines -/// -/// @deprecated use |nvim_buf_clear_namespace()|. -/// -/// @param buffer Buffer handle, or 0 for current buffer -/// @param ns_id Namespace to clear, or -1 to clear all. -/// @param line_start Start of range of lines to clear -/// @param line_end End of range of lines to clear (exclusive) or -1 to clear -/// to end of file. -/// @param[out] err Error details, if any -void nvim_buf_clear_highlight(Buffer buffer, - Integer ns_id, - Integer line_start, - Integer line_end, - Error *err) - FUNC_API_SINCE(1) -{ - nvim_buf_clear_namespace(buffer, ns_id, line_start, line_end, err); -} - - /// Set the virtual text (annotation) for a buffer line. /// /// By default (and currently the only option) the text will be placed after @@ -1873,8 +1650,3 @@ static int64_t normalize_index(buf_T *buf, int64_t index, bool *oob) index++; return index; } - -static int64_t convert_index(int64_t index) -{ - return index < 0 ? index - 1 : index; -} diff --git a/src/nvim/api/deprecated.c b/src/nvim/api/deprecated.c new file mode 100644 index 0000000000..3989386bb9 --- /dev/null +++ b/src/nvim/api/deprecated.c @@ -0,0 +1,367 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + +#include <stdbool.h> +#include <stdint.h> +#include <stdlib.h> +#include <limits.h> + +#include "nvim/api/deprecated.h" +#include "nvim/api/buffer.h" +#include "nvim/api/vim.h" +#include "nvim/api/private/helpers.h" +#include "nvim/api/private/defs.h" +#include "nvim/lua/executor.h" + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "api/deprecated.c.generated.h" +#endif + +/// @deprecated +/// @see nvim_exec +String nvim_command_output(String command, Error *err) + FUNC_API_SINCE(1) + FUNC_API_DEPRECATED_SINCE(7) +{ + return nvim_exec(command, true, err); +} + +/// @deprecated Use nvim_exec_lua() instead. +/// @see nvim_exec_lua +Object nvim_execute_lua(String code, Array args, Error *err) + FUNC_API_SINCE(3) + FUNC_API_DEPRECATED_SINCE(7) + FUNC_API_REMOTE_ONLY +{ + return nlua_exec(code, args, err); +} + +/// Gets the buffer number +/// +/// @deprecated The buffer number now is equal to the object id, +/// so there is no need to use this function. +/// +/// @param buffer Buffer handle, or 0 for current buffer +/// @param[out] err Error details, if any +/// @return Buffer number +Integer nvim_buf_get_number(Buffer buffer, Error *err) + FUNC_API_SINCE(1) + FUNC_API_DEPRECATED_SINCE(2) +{ + Integer rv = 0; + buf_T *buf = find_buffer_by_handle(buffer, err); + + if (!buf) { + return rv; + } + + return buf->b_fnum; +} + +/// Clears highlights and virtual text from namespace and range of lines +/// +/// @deprecated use |nvim_buf_clear_namespace()|. +/// +/// @param buffer Buffer handle, or 0 for current buffer +/// @param ns_id Namespace to clear, or -1 to clear all. +/// @param line_start Start of range of lines to clear +/// @param line_end End of range of lines to clear (exclusive) or -1 to clear +/// to end of file. +/// @param[out] err Error details, if any +void nvim_buf_clear_highlight(Buffer buffer, + Integer ns_id, + Integer line_start, + Integer line_end, + Error *err) + FUNC_API_SINCE(1) + FUNC_API_DEPRECATED_SINCE(7) +{ + nvim_buf_clear_namespace(buffer, ns_id, line_start, line_end, err); +} + + +/// Inserts a sequence of lines to a buffer at a certain index +/// +/// @deprecated use nvim_buf_set_lines(buffer, lnum, lnum, true, lines) +/// +/// @param buffer Buffer handle +/// @param lnum Insert the lines after `lnum`. If negative, appends to +/// the end of the buffer. +/// @param lines Array of lines +/// @param[out] err Error details, if any +void buffer_insert(Buffer buffer, + Integer lnum, + ArrayOf(String) lines, + Error *err) +{ + // "lnum" will be the index of the line after inserting, + // no matter if it is negative or not + nvim_buf_set_lines(0, buffer, lnum, lnum, true, lines, err); +} + +/// Gets a buffer line +/// +/// @deprecated use nvim_buf_get_lines instead. +/// for positive indices (including 0) use +/// "nvim_buf_get_lines(buffer, index, index+1, true)" +/// for negative indices use +/// "nvim_buf_get_lines(buffer, index-1, index, true)" +/// +/// @param buffer Buffer handle +/// @param index Line index +/// @param[out] err Error details, if any +/// @return Line string +String buffer_get_line(Buffer buffer, Integer index, Error *err) +{ + String rv = { .size = 0 }; + + index = convert_index(index); + Array slice = nvim_buf_get_lines(0, buffer, index, index+1, true, err); + + if (!ERROR_SET(err) && slice.size) { + rv = slice.items[0].data.string; + } + + xfree(slice.items); + + return rv; +} + +/// Sets a buffer line +/// +/// @deprecated use nvim_buf_set_lines instead. +/// for positive indices use +/// "nvim_buf_set_lines(buffer, index, index+1, true, [line])" +/// for negative indices use +/// "nvim_buf_set_lines(buffer, index-1, index, true, [line])" +/// +/// @param buffer Buffer handle +/// @param index Line index +/// @param line Contents of the new line +/// @param[out] err Error details, if any +void buffer_set_line(Buffer buffer, Integer index, String line, Error *err) +{ + Object l = STRING_OBJ(line); + Array array = { .items = &l, .size = 1 }; + index = convert_index(index); + nvim_buf_set_lines(0, buffer, index, index+1, true, array, err); +} + +/// Deletes a buffer line +/// +/// @deprecated use nvim_buf_set_lines instead. +/// for positive indices use +/// "nvim_buf_set_lines(buffer, index, index+1, true, [])" +/// for negative indices use +/// "nvim_buf_set_lines(buffer, index-1, index, true, [])" +/// @param buffer buffer handle +/// @param index line index +/// @param[out] err Error details, if any +void buffer_del_line(Buffer buffer, Integer index, Error *err) +{ + Array array = ARRAY_DICT_INIT; + index = convert_index(index); + nvim_buf_set_lines(0, buffer, index, index+1, true, array, err); +} + +/// Retrieves a line range from the buffer +/// +/// @deprecated use nvim_buf_get_lines(buffer, newstart, newend, false) +/// where newstart = start + int(not include_start) - int(start < 0) +/// newend = end + int(include_end) - int(end < 0) +/// int(bool) = 1 if bool is true else 0 +/// @param buffer Buffer handle +/// @param start First line index +/// @param end Last line index +/// @param include_start True if the slice includes the `start` parameter +/// @param include_end True if the slice includes the `end` parameter +/// @param[out] err Error details, if any +/// @return Array of lines +ArrayOf(String) buffer_get_line_slice(Buffer buffer, + Integer start, + Integer end, + Boolean include_start, + Boolean include_end, + Error *err) +{ + start = convert_index(start) + !include_start; + end = convert_index(end) + include_end; + return nvim_buf_get_lines(0, buffer, start , end, false, err); +} + +/// Replaces a line range on the buffer +/// +/// @deprecated use nvim_buf_set_lines(buffer, newstart, newend, false, lines) +/// where newstart = start + int(not include_start) + int(start < 0) +/// newend = end + int(include_end) + int(end < 0) +/// int(bool) = 1 if bool is true else 0 +/// +/// @param buffer Buffer handle, or 0 for current buffer +/// @param start First line index +/// @param end Last line index +/// @param include_start True if the slice includes the `start` parameter +/// @param include_end True if the slice includes the `end` parameter +/// @param replacement Array of lines to use as replacement (0-length +// array will delete the line range) +/// @param[out] err Error details, if any +void buffer_set_line_slice(Buffer buffer, + Integer start, + Integer end, + Boolean include_start, + Boolean include_end, + ArrayOf(String) replacement, + Error *err) +{ + start = convert_index(start) + !include_start; + end = convert_index(end) + include_end; + nvim_buf_set_lines(0, buffer, start, end, false, replacement, err); +} + + +/// Sets a buffer-scoped (b:) variable +/// +/// @deprecated +/// +/// @param buffer Buffer handle, or 0 for current buffer +/// @param name Variable name +/// @param value Variable value +/// @param[out] err Error details, if any +/// @return Old value or nil if there was no previous value. +/// +/// @warning It may return nil if there was no previous value +/// or if previous value was `v:null`. +Object buffer_set_var(Buffer buffer, String name, Object value, Error *err) +{ + buf_T *buf = find_buffer_by_handle(buffer, err); + + if (!buf) { + return NIL; + } + + return dict_set_var(buf->b_vars, name, value, false, true, err); +} + +/// Removes a buffer-scoped (b:) variable +/// +/// @deprecated +/// +/// @param buffer Buffer handle, or 0 for current buffer +/// @param name Variable name +/// @param[out] err Error details, if any +/// @return Old value +Object buffer_del_var(Buffer buffer, String name, Error *err) +{ + buf_T *buf = find_buffer_by_handle(buffer, err); + + if (!buf) { + return NIL; + } + + return dict_set_var(buf->b_vars, name, NIL, true, true, err); +} + +/// Sets a window-scoped (w:) variable +/// +/// @deprecated +/// +/// @param window Window handle, or 0 for current window +/// @param name Variable name +/// @param value Variable value +/// @param[out] err Error details, if any +/// @return Old value or nil if there was no previous value. +/// +/// @warning It may return nil if there was no previous value +/// or if previous value was `v:null`. +Object window_set_var(Window window, String name, Object value, Error *err) +{ + win_T *win = find_window_by_handle(window, err); + + if (!win) { + return NIL; + } + + return dict_set_var(win->w_vars, name, value, false, true, err); +} + +/// Removes a window-scoped (w:) variable +/// +/// @deprecated +/// +/// @param window Window handle, or 0 for current window +/// @param name variable name +/// @param[out] err Error details, if any +/// @return Old value +Object window_del_var(Window window, String name, Error *err) +{ + win_T *win = find_window_by_handle(window, err); + + if (!win) { + return NIL; + } + + return dict_set_var(win->w_vars, name, NIL, true, true, err); +} + +/// Sets a tab-scoped (t:) variable +/// +/// @deprecated +/// +/// @param tabpage Tabpage handle, or 0 for current tabpage +/// @param name Variable name +/// @param value Variable value +/// @param[out] err Error details, if any +/// @return Old value or nil if there was no previous value. +/// +/// @warning It may return nil if there was no previous value +/// or if previous value was `v:null`. +Object tabpage_set_var(Tabpage tabpage, String name, Object value, Error *err) +{ + tabpage_T *tab = find_tab_by_handle(tabpage, err); + + if (!tab) { + return NIL; + } + + return dict_set_var(tab->tp_vars, name, value, false, true, err); +} + +/// Removes a tab-scoped (t:) variable +/// +/// @deprecated +/// +/// @param tabpage Tabpage handle, or 0 for current tabpage +/// @param name Variable name +/// @param[out] err Error details, if any +/// @return Old value +Object tabpage_del_var(Tabpage tabpage, String name, Error *err) +{ + tabpage_T *tab = find_tab_by_handle(tabpage, err); + + if (!tab) { + return NIL; + } + + return dict_set_var(tab->tp_vars, name, NIL, true, true, err); +} + +/// @deprecated +/// @see nvim_set_var +/// @warning May return nil if there was no previous value +/// OR if previous value was `v:null`. +/// @return Old value or nil if there was no previous value. +Object vim_set_var(String name, Object value, Error *err) +{ + return dict_set_var(&globvardict, name, value, false, true, err); +} + +/// @deprecated +/// @see nvim_del_var +Object vim_del_var(String name, Error *err) +{ + return dict_set_var(&globvardict, name, NIL, true, true, err); +} + +static int64_t convert_index(int64_t index) +{ + return index < 0 ? index - 1 : index; +} diff --git a/src/nvim/api/deprecated.h b/src/nvim/api/deprecated.h new file mode 100644 index 0000000000..79095167e1 --- /dev/null +++ b/src/nvim/api/deprecated.h @@ -0,0 +1,11 @@ +#ifndef NVIM_API_DEPRECATED_H +#define NVIM_API_DEPRECATED_H + +#include <stdint.h> + +#include "nvim/api/private/defs.h" + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "api/deprecated.h.generated.h" +#endif +#endif // NVIM_API_DEPRECATED_H diff --git a/src/nvim/api/private/dispatch.c b/src/nvim/api/private/dispatch.c index 2975df3c68..eae4581f42 100644 --- a/src/nvim/api/private/dispatch.c +++ b/src/nvim/api/private/dispatch.c @@ -19,6 +19,7 @@ #include "nvim/api/ui.h" #include "nvim/api/vim.h" #include "nvim/api/window.h" +#include "nvim/api/deprecated.h" static Map(String, MsgpackRpcRequestHandler) *methods = NULL; diff --git a/src/nvim/api/tabpage.c b/src/nvim/api/tabpage.c index dd17bc03e5..5f727dbc38 100644 --- a/src/nvim/api/tabpage.c +++ b/src/nvim/api/tabpage.c @@ -97,48 +97,6 @@ void nvim_tabpage_del_var(Tabpage tabpage, String name, Error *err) dict_set_var(tab->tp_vars, name, NIL, true, false, err); } -/// Sets a tab-scoped (t:) variable -/// -/// @deprecated -/// -/// @param tabpage Tabpage handle, or 0 for current tabpage -/// @param name Variable name -/// @param value Variable value -/// @param[out] err Error details, if any -/// @return Old value or nil if there was no previous value. -/// -/// @warning It may return nil if there was no previous value -/// or if previous value was `v:null`. -Object tabpage_set_var(Tabpage tabpage, String name, Object value, Error *err) -{ - tabpage_T *tab = find_tab_by_handle(tabpage, err); - - if (!tab) { - return (Object) OBJECT_INIT; - } - - return dict_set_var(tab->tp_vars, name, value, false, true, err); -} - -/// Removes a tab-scoped (t:) variable -/// -/// @deprecated -/// -/// @param tabpage Tabpage handle, or 0 for current tabpage -/// @param name Variable name -/// @param[out] err Error details, if any -/// @return Old value -Object tabpage_del_var(Tabpage tabpage, String name, Error *err) -{ - tabpage_T *tab = find_tab_by_handle(tabpage, err); - - if (!tab) { - return (Object) OBJECT_INIT; - } - - return dict_set_var(tab->tp_vars, name, NIL, true, true, err); -} - /// Gets the current window in a tabpage /// /// @param tabpage Tabpage handle, or 0 for current tabpage diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 8ac820abd9..8b80d4aad9 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -15,6 +15,7 @@ #include "nvim/api/private/dispatch.h" #include "nvim/api/buffer.h" #include "nvim/api/window.h" +#include "nvim/api/deprecated.h" #include "nvim/msgpack_rpc/channel.h" #include "nvim/msgpack_rpc/helpers.h" #include "nvim/lua/executor.h" @@ -479,15 +480,6 @@ String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, return cstr_as_string(ptr); } -/// @deprecated -/// @see nvim_exec -String nvim_command_output(String command, Error *err) - FUNC_API_SINCE(1) - FUNC_API_DEPRECATED_SINCE(7) -{ - return nvim_exec(command, true, err); -} - /// Evaluates a VimL |expression|. /// Dictionaries and Lists are recursively expanded. /// @@ -534,16 +526,6 @@ Object nvim_eval(String expr, Error *err) return rv; } -/// @deprecated Use nvim_exec_lua() instead. -/// @see nvim_exec_lua -Object nvim_execute_lua(String code, Array args, Error *err) - FUNC_API_SINCE(3) - FUNC_API_DEPRECATED_SINCE(7) - FUNC_API_REMOTE_ONLY -{ - return nlua_exec(code, args, err); -} - /// Execute Lua code. Parameters (if any) are available as `...` inside the /// chunk. The chunk can return a value. /// @@ -920,23 +902,6 @@ void nvim_del_var(String name, Error *err) dict_set_var(&globvardict, name, NIL, true, false, err); } -/// @deprecated -/// @see nvim_set_var -/// @warning May return nil if there was no previous value -/// OR if previous value was `v:null`. -/// @return Old value or nil if there was no previous value. -Object vim_set_var(String name, Object value, Error *err) -{ - return dict_set_var(&globvardict, name, value, false, true, err); -} - -/// @deprecated -/// @see nvim_del_var -Object vim_del_var(String name, Error *err) -{ - return dict_set_var(&globvardict, name, NIL, true, true, err); -} - /// Gets a v: variable. /// /// @param name Variable name diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c index f09a03f592..a3ec1c8e53 100644 --- a/src/nvim/api/window.c +++ b/src/nvim/api/window.c @@ -288,48 +288,6 @@ void nvim_win_del_var(Window window, String name, Error *err) dict_set_var(win->w_vars, name, NIL, true, false, err); } -/// Sets a window-scoped (w:) variable -/// -/// @deprecated -/// -/// @param window Window handle, or 0 for current window -/// @param name Variable name -/// @param value Variable value -/// @param[out] err Error details, if any -/// @return Old value or nil if there was no previous value. -/// -/// @warning It may return nil if there was no previous value -/// or if previous value was `v:null`. -Object window_set_var(Window window, String name, Object value, Error *err) -{ - win_T *win = find_window_by_handle(window, err); - - if (!win) { - return (Object) OBJECT_INIT; - } - - return dict_set_var(win->w_vars, name, value, false, true, err); -} - -/// Removes a window-scoped (w:) variable -/// -/// @deprecated -/// -/// @param window Window handle, or 0 for current window -/// @param name variable name -/// @param[out] err Error details, if any -/// @return Old value -Object window_del_var(Window window, String name, Error *err) -{ - win_T *win = find_window_by_handle(window, err); - - if (!win) { - return (Object) OBJECT_INIT; - } - - return dict_set_var(win->w_vars, name, NIL, true, true, err); -} - /// Gets a window option value /// /// @param window Window handle, or 0 for current window diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index ed408c28e5..a0910f1394 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -4327,7 +4327,8 @@ void ExpandEscape(expand_T *xp, char_u *str, int numfiles, char_u **files, int o /// if true then it escapes for a shell command. /// /// @return [allocated] escaped file name. -char *vim_strsave_fnameescape(const char *const fname, const bool shell) +char *vim_strsave_fnameescape(const char *const fname, + const bool shell FUNC_ATTR_UNUSED) FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL { #ifdef BACKSLASH_IN_FILENAME diff --git a/src/nvim/log.c b/src/nvim/log.c index 225e40cdb4..19203a3c2a 100644 --- a/src/nvim/log.c +++ b/src/nvim/log.c @@ -13,9 +13,6 @@ #include <stdarg.h> #include <stdbool.h> #include <stdio.h> -#if !defined(WIN32) -# include <sys/time.h> // for gettimeofday() -#endif #include <uv.h> #include "auto/config.h" @@ -296,12 +293,10 @@ static bool v_do_log_to_file(FILE *log_file, int log_level, } int millis = 0; -#if !defined(WIN32) - struct timeval curtime; - if (gettimeofday(&curtime, NULL) == 0) { + uv_timeval64_t curtime; + if (uv_gettimeofday(&curtime) == 0) { millis = (int)curtime.tv_usec / 1000; } -#endif // Print the log message. int64_t pid = os_get_pid(); diff --git a/src/nvim/main.c b/src/nvim/main.c index 79c165419e..025312a6e1 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -1414,7 +1414,10 @@ static void read_stdin(void) no_wait_return = true; int save_msg_didany = msg_didany; set_buflisted(true); - (void)open_buffer(true, NULL, 0); // create memfile and read file + + // Create memfile and read from stdin. + (void)open_buffer(true, NULL, 0); + if (BUFEMPTY() && curbuf->b_next != NULL) { // stdin was empty, go to buffer 2 (e.g. "echo file1 | xargs nvim"). #8561 do_cmdline_cmd("silent! bnext"); diff --git a/src/nvim/message.c b/src/nvim/message.c index ad38e6d060..02a7732f5c 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -1712,7 +1712,7 @@ void msg_prt_line(char_u *s, int list) col += utf_ptr2cells(s); char buf[MB_MAXBYTES + 1]; if (l >= MB_MAXBYTES) { - xstrlcpy(buf, "¿", sizeof(buf)); + xstrlcpy(buf, "?", sizeof(buf)); } else if (curwin->w_p_lcs_chars.nbsp != NUL && list && (utf_ptr2char(s) == 160 || utf_ptr2char(s) == 0x202f)) { diff --git a/src/nvim/popupmnu.c b/src/nvim/popupmnu.c index f242b7d71a..551a650045 100644 --- a/src/nvim/popupmnu.c +++ b/src/nvim/popupmnu.c @@ -742,6 +742,7 @@ static int pum_set_selected(int n, int repeat) // Edit a new, empty buffer. Set options for a "wipeout" // buffer. set_option_value("swf", 0L, NULL, OPT_LOCAL); + set_option_value("bl", 0L, NULL, OPT_LOCAL); set_option_value("bt", 0L, "nofile", OPT_LOCAL); set_option_value("bh", 0L, "wipe", OPT_LOCAL); set_option_value("diff", 0L, NULL, OPT_LOCAL); diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index 1c88bd4ba4..2878e73573 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -3605,6 +3605,22 @@ theend: if (backpos.ga_maxlen > BACKPOS_INITIAL) ga_clear(&backpos); + // Make sure the end is never before the start. Can happen when \zs and + // \ze are used. + if (REG_MULTI) { + const lpos_T *const start = &rex.reg_mmatch->startpos[0]; + const lpos_T *const end = &rex.reg_mmatch->endpos[0]; + + if (end->lnum < start->lnum + || (end->lnum == start->lnum && end->col < start->col)) { + rex.reg_mmatch->endpos[0] = rex.reg_mmatch->startpos[0]; + } + } else { + if (rex.reg_match->endp[0] < rex.reg_match->startp[0]) { + rex.reg_match->endp[0] = rex.reg_match->startp[0]; + } + } + return retval; } diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c index 7dfd16fb4f..137b2304c0 100644 --- a/src/nvim/regexp_nfa.c +++ b/src/nvim/regexp_nfa.c @@ -6591,6 +6591,22 @@ static long nfa_regexec_both(char_u *line, colnr_T startcol, #endif theend: + // Make sure the end is never before the start. Can happen when \zs and + // \ze are used. + if (REG_MULTI) { + const lpos_T *const start = &rex.reg_mmatch->startpos[0]; + const lpos_T *const end = &rex.reg_mmatch->endpos[0]; + + if (end->lnum < start->lnum + || (end->lnum == start->lnum && end->col < start->col)) { + rex.reg_mmatch->endpos[0] = rex.reg_mmatch->startpos[0]; + } + } else { + if (rex.reg_match->endp[0] < rex.reg_match->startp[0]) { + rex.reg_match->endp[0] = rex.reg_match->startp[0]; + } + } + return retval; } diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index f3c3e085f6..356a7ce135 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -463,6 +463,7 @@ let s:filename_checks = { \ 'tilde': ['file.t.html'], \ 'tli': ['file.tli'], \ 'tmux': ['tmuxfile.conf', '.tmuxfile.conf'], + \ 'toml': ['file.toml'], \ 'tpp': ['file.tpp'], \ 'treetop': ['file.treetop'], \ 'trustees': ['trustees.conf'], diff --git a/src/nvim/testdir/test_regexp_latin.vim b/src/nvim/testdir/test_regexp_latin.vim index 2ee0ee1c0c..1bb2ee53de 100644 --- a/src/nvim/testdir/test_regexp_latin.vim +++ b/src/nvim/testdir/test_regexp_latin.vim @@ -755,6 +755,13 @@ func Test_start_end_of_buffer_match() bwipe! endfunc +func Test_ze_before_zs() + call assert_equal('', matchstr(' ', '\%#=1\ze \zs')) + call assert_equal('', matchstr(' ', '\%#=2\ze \zs')) + call assert_equal(repeat([''], 10), matchlist(' ', '\%#=1\ze \zs')) + call assert_equal(repeat([''], 10), matchlist(' ', '\%#=2\ze \zs')) +endfunc + " Check for detecting error func Test_regexp_error() set regexpengine=2 diff --git a/src/nvim/testdir/test_ruby.vim b/src/nvim/testdir/test_ruby.vim index 9c74c35049..1a274d1fec 100644 --- a/src/nvim/testdir/test_ruby.vim +++ b/src/nvim/testdir/test_ruby.vim @@ -27,6 +27,19 @@ func Test_rubydo() %bwipe! endfunc +func Test_rubydo_dollar_underscore() + throw 'skipped: TODO: ' + new + call setline(1, ['one', 'two', 'three', 'four']) + 2,3rubydo $_ = '[' + $_ + ']' + call assert_equal(['one', '[two]', '[three]', 'four'], getline(1, '$')) + bwipe! + + call assert_fails('rubydo $_ = 0', 'E265:') + call assert_fails('rubydo (') + bwipe! +endfunc + func Test_rubyfile() " Check :rubyfile does not SEGV with Ruby level exception but just fails let tempfile = tempname() . '.rb' @@ -391,3 +404,14 @@ func Test_ruby_p() let messages = GetMessages() call assert_equal(0, len(messages)) endfunc + +func Test_rubyeval_error() + " On Linux or Windows the error matches: + " "syntax error, unexpected end-of-input" + " whereas on macOS in CI, the error message makes less sense: + " "SyntaxError: array length must be 2" + " Unclear why. The test does not check the error message. + call assert_fails('call rubyeval("(")') +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_search.vim b/src/nvim/testdir/test_search.vim index 6824c50112..8d71ada551 100644 --- a/src/nvim/testdir/test_search.vim +++ b/src/nvim/testdir/test_search.vim @@ -508,7 +508,7 @@ endfunc func Test_search_cmdline7() throw 'skipped: Nvim does not support test_override()' - " Test that an pressing <c-g> in an empty command line + " Test that pressing <c-g> in an empty command line " does not move the cursor if !exists('+incsearch') return @@ -1172,3 +1172,24 @@ func Test_search_special() set t_PE= exe "norm /\x80PS" endfunc + +" Test 'smartcase' with utf-8. +func Test_search_smartcase_utf8() + new + let save_enc = &encoding + set encoding=utf8 ignorecase smartcase + + call setline(1, 'Café cafÉ') + 1s/café/x/g + call assert_equal('x x', getline(1)) + + call setline(1, 'Café cafÉ') + 1s/cafÉ/x/g + call assert_equal('Café x', getline(1)) + + set ignorecase& smartcase& + let &encoding = save_enc + close! +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/undo.c b/src/nvim/undo.c index a8b8f7aa50..636d00bbbf 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -1255,7 +1255,8 @@ theend: /// a bit more verbose. /// Otherwise use curbuf->b_ffname to generate the undo file name. /// "hash[UNDO_HASH_SIZE]" must be the hash value of the buffer text. -void u_read_undo(char *name, char_u *hash, char_u *orig_name) +void u_read_undo(char *name, const char_u *hash, + const char_u *orig_name FUNC_ATTR_UNUSED) FUNC_ATTR_NONNULL_ARG(2) { u_header_T **uhp_table = NULL; @@ -1273,7 +1274,7 @@ void u_read_undo(char *name, char_u *hash, char_u *orig_name) // owner of the text file or equal to the current user. FileInfo file_info_orig; FileInfo file_info_undo; - if (os_fileinfo((char *)orig_name, &file_info_orig) + if (os_fileinfo((const char *)orig_name, &file_info_orig) && os_fileinfo((char *)file_name, &file_info_undo) && file_info_orig.stat.st_uid != file_info_undo.stat.st_uid && file_info_undo.stat.st_uid != getuid()) { diff --git a/src/nvim/window.c b/src/nvim/window.c index 72ee400e40..9eb16e67ec 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -3787,32 +3787,35 @@ void free_tabpage(tabpage_T *tp) /// @return Was the new tabpage created successfully? FAIL or OK. int win_new_tabpage(int after, char_u *filename) { - tabpage_T *tp = curtab; + tabpage_T *old_curtab = curtab; tabpage_T *newtp; int n; newtp = alloc_tabpage(); - /* Remember the current windows in this Tab page. */ - if (leave_tabpage(curbuf, TRUE) == FAIL) { + // Remember the current windows in this Tab page. + if (leave_tabpage(curbuf, true) == FAIL) { xfree(newtp); return FAIL; } - newtp->tp_localdir = tp->tp_localdir ? vim_strsave(tp->tp_localdir) : NULL; + newtp->tp_localdir = old_curtab->tp_localdir + ? vim_strsave(old_curtab->tp_localdir) : NULL; curtab = newtp; - /* Create a new empty window. */ - if (win_alloc_firstwin(tp->tp_curwin) == OK) { - /* Make the new Tab page the new topframe. */ + // Create a new empty window. + if (win_alloc_firstwin(old_curtab->tp_curwin) == OK) { + // Make the new Tab page the new topframe. if (after == 1) { - /* New tab page becomes the first one. */ + // New tab page becomes the first one. newtp->tp_next = first_tabpage; first_tabpage = newtp; } else { + tabpage_T *tp = old_curtab; + if (after > 0) { - /* Put new tab page before tab page "after". */ + // Put new tab page before tab page "after". n = 2; for (tp = first_tabpage; tp->tp_next != NULL && n < after; tp = tp->tp_next) @@ -3826,13 +3829,13 @@ int win_new_tabpage(int after, char_u *filename) win_comp_scroll(curwin); newtp->tp_topframe = topframe; - last_status(FALSE); + last_status(false); redraw_all_later(NOT_VALID); - tabpage_check_windows(tp); + tabpage_check_windows(old_curtab); - lastused_tabpage = tp; + lastused_tabpage = old_curtab; apply_autocmds(EVENT_WINNEW, NULL, NULL, false, curbuf); apply_autocmds(EVENT_WINENTER, NULL, NULL, false, curbuf); @@ -3842,8 +3845,8 @@ int win_new_tabpage(int after, char_u *filename) return OK; } - /* Failed, get back the previous Tab page */ - enter_tabpage(curtab, curbuf, TRUE, TRUE); + // Failed, get back the previous Tab page + enter_tabpage(curtab, curbuf, true, true); return FAIL; } diff --git a/test/functional/lua/treesitter_spec.lua b/test/functional/lua/treesitter_spec.lua index fc4928eb71..f34cbbb65b 100644 --- a/test/functional/lua/treesitter_spec.lua +++ b/test/functional/lua/treesitter_spec.lua @@ -923,4 +923,25 @@ local hl_query = [[ end) end) + describe("when getting the language for a range", function() + before_each(function() + insert([[ +int x = INT_MAX; +#define VALUE 123456789 + ]]) + end) + + it("should return the correct language tree", function() + local result = exec_lua([[ + parser = vim.treesitter.get_parser(0, "c", { + queries = { c = "(preproc_def (preproc_arg) @c)"}}) + + local sub_tree = parser:language_for_range({1, 18, 1, 19}) + + return sub_tree == parser:children().c + ]]) + + eq(result, true) + end) + end) end) diff --git a/test/functional/ui/multigrid_spec.lua b/test/functional/ui/multigrid_spec.lua index 6601c2d68e..719e2ee82a 100644 --- a/test/functional/ui/multigrid_spec.lua +++ b/test/functional/ui/multigrid_spec.lua @@ -1562,6 +1562,77 @@ describe('ext_multigrid', function() {1:~ }| ]]} + command('tabnext') + command('$tabnew') + screen:expect{grid=[[ + ## grid 1 + {16: }{17:2}{16: [No Name] }{17:2}{16: [No Name] }{7: [No Name] }{12: }{16:X}| + [7:-----------------------------------------------------]| + [7:-----------------------------------------------------]| + [7:-----------------------------------------------------]| + [7:-----------------------------------------------------]| + [7:-----------------------------------------------------]| + [7:-----------------------------------------------------]| + [7:-----------------------------------------------------]| + [7:-----------------------------------------------------]| + [7:-----------------------------------------------------]| + [7:-----------------------------------------------------]| + [7:-----------------------------------------------------]| + {11:[No Name] }| + [3:-----------------------------------------------------]| + ## grid 2 (hidden) + | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 3 + | + ## grid 4 (hidden) + | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 5 (hidden) + | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 6 (hidden) + | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 7 + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ]]} + + command('tabclose') command('tabclose') screen:expect{grid=[[ ## grid 1 |