aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml4
-rw-r--r--.github/workflows/release.yml6
-rw-r--r--README.md3
-rw-r--r--contrib/flake.nix169
-rw-r--r--man/nvim.12
-rw-r--r--runtime/autoload/dist/ft.vim23
-rw-r--r--runtime/autoload/man.vim2
-rw-r--r--runtime/doc/api.txt11
-rw-r--r--runtime/doc/eval.txt49
-rw-r--r--runtime/doc/index.txt10
-rw-r--r--runtime/doc/lsp.txt110
-rw-r--r--runtime/doc/lua.txt17
-rw-r--r--runtime/doc/options.txt9
-rw-r--r--runtime/doc/quickfix.txt59
-rw-r--r--runtime/doc/repeat.txt4
-rw-r--r--runtime/doc/starting.txt9
-rw-r--r--runtime/doc/tagsrch.txt2
-rw-r--r--runtime/doc/treesitter.txt3
-rw-r--r--runtime/doc/ui.txt4
-rw-r--r--runtime/doc/usr_41.txt1
-rw-r--r--runtime/doc/various.txt18
-rw-r--r--runtime/doc/windows.txt2
-rw-r--r--runtime/filetype.vim20
-rw-r--r--runtime/ftplugin/elm.vim18
-rw-r--r--runtime/ftplugin/man.vim13
-rw-r--r--runtime/indent/elm.vim114
-rw-r--r--runtime/lua/vim/lsp.lua21
-rw-r--r--runtime/lua/vim/lsp/diagnostic.lua73
-rw-r--r--runtime/lua/vim/lsp/handlers.lua58
-rw-r--r--runtime/lua/vim/lsp/log.lua4
-rw-r--r--runtime/lua/vim/lsp/protocol.lua26
-rw-r--r--runtime/lua/vim/lsp/util.lua39
-rw-r--r--runtime/lua/vim/treesitter.lua2
-rw-r--r--runtime/lua/vim/treesitter/languagetree.lua18
-rw-r--r--runtime/lua/vim/treesitter/query.lua65
-rw-r--r--runtime/nvim.appdata.xml1
-rw-r--r--runtime/scripts.vim4
-rw-r--r--runtime/syntax/elm.vim105
-rw-r--r--scripts/genvimvim.lua2
-rw-r--r--src/nvim/README.md2
-rw-r--r--src/nvim/api/private/helpers.c41
-rw-r--r--src/nvim/api/vim.c41
-rw-r--r--src/nvim/buffer.c7
-rw-r--r--src/nvim/edit.c5
-rw-r--r--src/nvim/eval.c24
-rw-r--r--src/nvim/eval.lua1
-rw-r--r--src/nvim/eval/funcs.c23
-rw-r--r--src/nvim/ex_cmds.c63
-rw-r--r--src/nvim/ex_cmds.lua1456
-rw-r--r--src/nvim/ex_cmds2.c2
-rw-r--r--src/nvim/ex_cmds_defs.h63
-rw-r--r--src/nvim/ex_docmd.c458
-rw-r--r--src/nvim/ex_getln.c4
-rw-r--r--src/nvim/generators/gen_ex_cmds.lua16
-rw-r--r--src/nvim/globals.h1
-rw-r--r--src/nvim/log.c18
-rw-r--r--src/nvim/lua/executor.c15
-rw-r--r--src/nvim/main.c1
-rw-r--r--src/nvim/mark.c85
-rw-r--r--src/nvim/message.c34
-rw-r--r--src/nvim/message.h9
-rw-r--r--src/nvim/option.c14
-rw-r--r--src/nvim/option_defs.h7
-rw-r--r--src/nvim/os/env.c53
-rw-r--r--src/nvim/os/input.c2
-rw-r--r--src/nvim/os/stdpaths.c11
-rw-r--r--src/nvim/po/af.po7
-rw-r--r--src/nvim/po/ca.po4
-rw-r--r--src/nvim/po/cs.cp1250.po4
-rw-r--r--src/nvim/po/cs.po4
-rw-r--r--src/nvim/po/da.po3
-rw-r--r--src/nvim/po/de.po4
-rw-r--r--src/nvim/po/en_GB.po4
-rw-r--r--src/nvim/po/eo.po3
-rw-r--r--src/nvim/po/es.po4
-rw-r--r--src/nvim/po/fi.po7
-rw-r--r--src/nvim/po/fr.po3
-rw-r--r--src/nvim/po/ga.po3
-rw-r--r--src/nvim/po/it.po4
-rw-r--r--src/nvim/po/ja.euc-jp.po3
-rw-r--r--src/nvim/po/ja.po3
-rw-r--r--src/nvim/po/ko.UTF-8.po4
-rw-r--r--src/nvim/po/nb.po4
-rw-r--r--src/nvim/po/nl.po4
-rw-r--r--src/nvim/po/no.po4
-rw-r--r--src/nvim/po/pl.UTF-8.po4
-rw-r--r--src/nvim/po/pt_BR.po4
-rw-r--r--src/nvim/po/ru.po4
-rw-r--r--src/nvim/po/sk.cp1250.po4
-rw-r--r--src/nvim/po/sk.po4
-rw-r--r--src/nvim/po/sr.po3
-rw-r--r--src/nvim/po/sv.po4
-rw-r--r--src/nvim/po/uk.po253
-rw-r--r--src/nvim/po/vi.po4
-rw-r--r--src/nvim/po/zh_CN.UTF-8.po4
-rw-r--r--src/nvim/po/zh_TW.UTF-8.po4
-rw-r--r--src/nvim/quickfix.c302
-rw-r--r--src/nvim/screen.c32
-rw-r--r--src/nvim/search.c87
-rw-r--r--src/nvim/syntax.c2
-rw-r--r--src/nvim/testdir/test_autocmd.vim6
-rw-r--r--src/nvim/testdir/test_backspace_opt.vim151
-rw-r--r--src/nvim/testdir/test_excmd.vim91
-rw-r--r--src/nvim/testdir/test_filetype.vim38
-rw-r--r--src/nvim/testdir/test_find_complete.vim8
-rw-r--r--src/nvim/testdir/test_findfile.vim43
-rw-r--r--src/nvim/testdir/test_hardcopy.vim80
-rw-r--r--src/nvim/testdir/test_marks.vim30
-rw-r--r--src/nvim/testdir/test_options.vim21
-rw-r--r--src/nvim/testdir/test_quickfix.vim248
-rw-r--r--src/nvim/testdir/test_sleep.vim26
-rw-r--r--src/nvim/testdir/test_startup.vim78
-rw-r--r--src/nvim/testdir/test_usercommands.vim10
-rw-r--r--src/nvim/testdir/test_window_cmd.vim2
-rw-r--r--test/functional/api/keymap_spec.lua5
-rw-r--r--test/functional/api/vim_spec.lua65
-rw-r--r--test/functional/eval/environ_spec.lua61
-rw-r--r--test/functional/fixtures/fake-lsp-server.lua17
-rw-r--r--test/functional/helpers.lua13
-rw-r--r--test/functional/legacy/assert_spec.lua12
-rw-r--r--test/functional/legacy/backspace_opt_spec.lua67
-rw-r--r--test/functional/legacy/memory_usage_spec.lua46
-rw-r--r--test/functional/lua/treesitter_spec.lua1015
-rw-r--r--test/functional/options/defaults_spec.lua26
-rw-r--r--test/functional/plugin/lsp/diagnostic_spec.lua100
-rw-r--r--test/functional/plugin/lsp_spec.lua162
-rw-r--r--test/functional/provider/define_spec.lua8
-rw-r--r--test/functional/treesitter/highlight_spec.lua475
-rw-r--r--test/functional/treesitter/language_spec.lua71
-rw-r--r--test/functional/treesitter/parser_spec.lua599
130 files changed, 5061 insertions, 2860 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 3653f04d5d..44a911b21b 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -56,10 +56,12 @@ jobs:
- name: Install brew packages
if: matrix.os == 'osx'
run: |
+ # Workaround brew issues
rm -f /usr/local/bin/2to3
+ brew unlink gcc@8 gcc@9
brew update >/dev/null
- brew install automake ccache cpanminus ninja
brew upgrade
+ brew install automake ccache perl cpanminus ninja
- name: Setup interpreter packages
run: |
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 7587f62e59..753142e555 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -30,7 +30,7 @@ jobs:
- name: Build release
id: build
run: |
- make CMAKE_BUILD_TYPE=RelWithDebinfo CMAKE_EXTRA_FLAGS="-DCMAKE_INSTALL_PREFIX:PATH="
+ 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
@@ -76,7 +76,9 @@ jobs:
- name: Install brew packages
run: |
rm -f /usr/local/bin/2to3
+ brew unlink gcc@8 gcc@9
brew update >/dev/null
+ brew upgrade
brew install automake ninja
- name: Build release
run: |
@@ -154,7 +156,7 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
- delete_release: false
+ delete_release: ''
tag_name: nightly
- uses: meeDamian/github-release@2.0
with:
diff --git a/README.md b/README.md
index 180fc1df14..f4d92b77a1 100644
--- a/README.md
+++ b/README.md
@@ -46,7 +46,7 @@ Install from package
Pre-built packages for Windows, macOS, and Linux are found on the
[Releases](https://github.com/neovim/neovim/releases/) page.
-[Managed packages] are in Homebrew, [Debian], [Ubuntu], [Fedora], [Arch Linux],
+[Managed packages] are in [Homebrew], [Debian], [Ubuntu], [Fedora], [Arch Linux],
[Gentoo], and more!
Install from source
@@ -137,5 +137,6 @@ Apache 2.0 license, except for contributions copied from Vim (identified by the
[Fedora]: https://apps.fedoraproject.org/packages/neovim
[Arch Linux]: https://www.archlinux.org/packages/?q=neovim
[Gentoo]: https://packages.gentoo.org/packages/app-editors/neovim
+[Homebrew]: https://formulae.brew.sh/formula/neovim
<!-- vim: set tw=80: -->
diff --git a/contrib/flake.nix b/contrib/flake.nix
index 86e4b37cfa..d18534215c 100644
--- a/contrib/flake.nix
+++ b/contrib/flake.nix
@@ -3,93 +3,100 @@
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
+ flake-utils.url = "github:numtide/flake-utils";
};
- 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;
+ outputs = { self, nixpkgs, flake-utils }:
+ {
+ overlay = final: prev:
+ let
+ pkgs = nixpkgs.legacyPackages.${prev.system};
+ in
+ rec {
+ neovim = pkgs.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 = if pkgs.stdenv.isLinux then pkgs.llvmPackages_latest.stdenv else pkgs.stdenv;
+ lua = pkgs.enableDebugging pkgs.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 = pkgs.python3;
+ luacheck = pkgs.luaPackages.luacheck;
+ in
+ (neovim-debug.override ({ doCheck = pkgs.stdenv.isLinux; })).overrideAttrs (oa: {
+ cmakeFlags = oa.cmakeFlags ++ [
+ "-DLUACHECK_PRG=${luacheck}/bin/luacheck"
+ "-DMIN_LOG_LEVEL=0"
+ "-DENABLE_LTO=OFF"
+ "-DUSE_BUNDLED=OFF"
+ ] ++ pkgs.stdenv.lib.optionals pkgs.stdenv.isLinux [
+ # 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
+ '';
+ });
+ };
+ } //
+ flake-utils.lib.eachDefaultSystem (system:
+ let
+ pkgs = import nixpkgs {
+ overlays = [ self.overlay ];
+ inherit system;
+ };
in
- (neovim-debug.override({doCheck = true;})).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
+ rec {
- export ASAN_OPTIONS="log_path=./test.log:abort_on_error=1"
- export UBSAN_OPTIONS=print_stacktrace=1
- '';
- });
- };
+ packages = with pkgs; {
+ inherit neovim neovim-debug neovim-developer;
+ };
- defaultPackage."${system}" = self.packages."${system}".neovim;
+ defaultPackage = pkgs.neovim;
- overlay = final: prev: {
- inherit (self.packages."${system}") neovim neovim-debug;
- };
+ apps = {
+ nvim = flake-utils.lib.mkApp { drv = pkgs.neovim; name = "nvim"; };
+ nvim-debug = flake-utils.lib.mkApp { drv = pkgs.neovim-debug; name = "nvim"; };
+ };
- 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 = apps.nvim;
- defaultApp."${system}" = self.apps."${system}".nvim;
-
- devShell."${system}" = self.packages."${system}".neovim-developer;
- };
+ devShell = pkgs.neovim-developer;
+ }
+ );
}
diff --git a/man/nvim.1 b/man/nvim.1
index 305551c7d4..ca0f41d489 100644
--- a/man/nvim.1
+++ b/man/nvim.1
@@ -327,7 +327,7 @@ Print version information and exit.
.Sh ENVIRONMENT
.Bl -tag -width Fl
.It Ev NVIM_LOG_FILE
-Low-level log file, usually found at ~/.local/share/nvim/log.
+Low-level log file, usually found at ~/.cache/nvim/log.
:help $NVIM_LOG_FILE
.It Ev VIM
Used to locate user files, such as init.vim.
diff --git a/runtime/autoload/dist/ft.vim b/runtime/autoload/dist/ft.vim
index b6297472c3..cf26bc3172 100644
--- a/runtime/autoload/dist/ft.vim
+++ b/runtime/autoload/dist/ft.vim
@@ -362,6 +362,10 @@ func dist#ft#FTinc()
setf aspvbs
elseif lines =~ "<?"
setf php
+ " Pascal supports // comments but they're vary rarely used for file
+ " headers so assume POV-Ray
+ elseif lines =~ '^\s*\%({\|(\*\)' || lines =~? s:ft_pascal_keywords
+ setf pascal
else
call dist#ft#FTasmsyntax()
if exists("b:asmsyntax")
@@ -408,6 +412,9 @@ func dist#ft#FTprogress_asm()
setf progress
endfunc
+let s:ft_pascal_comments = '^\s*\%({\|(\*\|//\)'
+let s:ft_pascal_keywords = '^\s*\%(program\|unit\|library\|uses\|begin\|procedure\|function\|const\|type\|var\)\>'
+
func dist#ft#FTprogress_pascal()
if exists("g:filetype_p")
exe "setf " . g:filetype_p
@@ -419,8 +426,7 @@ func dist#ft#FTprogress_pascal()
let lnum = 1
while lnum <= 10 && lnum < line('$')
let line = getline(lnum)
- if line =~ '^\s*\(program\|unit\|procedure\|function\|const\|type\|var\)\>'
- \ || line =~ '^\s*{' || line =~ '^\s*(\*'
+ if line =~ s:ft_pascal_comments || line =~? s:ft_pascal_keywords
setf pascal
return
elseif line !~ '^\s*$' || line =~ '^/\*'
@@ -433,6 +439,19 @@ func dist#ft#FTprogress_pascal()
setf progress
endfunc
+func dist#ft#FTpp()
+ if exists("g:filetype_pp")
+ exe "setf " . g:filetype_pp
+ else
+ let line = getline(nextnonblank(1))
+ if line =~ s:ft_pascal_comments || line =~? s:ft_pascal_keywords
+ setf pascal
+ else
+ setf puppet
+ endif
+ endif
+endfunc
+
func dist#ft#FTr()
let max = line("$") > 50 ? 50 : line("$")
diff --git a/runtime/autoload/man.vim b/runtime/autoload/man.vim
index 99d8c41dba..78a86315a3 100644
--- a/runtime/autoload/man.vim
+++ b/runtime/autoload/man.vim
@@ -137,8 +137,6 @@ function! s:put_page(page) abort
setlocal modifiable
setlocal noreadonly
setlocal noswapfile
- " git-ls-files(1) is all one keyword/tag-target
- setlocal iskeyword+=(,)
silent keepjumps %delete _
silent put =a:page
while getline(1) =~# '^\s*$'
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index 485c93b0dd..a810bef8f6 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -663,6 +663,17 @@ nvim_del_var({name}) *nvim_del_var()*
Parameters: ~
{name} Variable name
+nvim_echo({chunks}, {history}, {opts}) *nvim_echo()*
+ Echo a message.
+
+ Parameters: ~
+ {chunks} A list of [text, hl_group] arrays, each
+ representing a text chunk with specified
+ highlight. `hl_group` element can be omitted
+ for no highlight.
+ {history} if true, add to |message-history|.
+ {opts} Optional parameters. Reserved for future use.
+
nvim_err_write({str}) *nvim_err_write()*
Writes a message to the Vim error buffer. Does not append
"\n", the message is buffered (won't display) until a linefeed
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index d04f52de0b..384bdd63a4 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1600,7 +1600,7 @@ v:event Dictionary of event data for the current |autocommand|. Valid
regtype Type of register as returned by
|getregtype()|.
visual Selection is visual (as opposed to,
- e.g., via motion).
+ e.g., via motion).
completed_item Current selected complete item on
|CompleteChanged|, Is `{}` when no complete
item selected.
@@ -1783,7 +1783,7 @@ v:msgpack_types Dictionary containing msgpack types used by |msgpackparse()|
of msgpack types, use |is| operator.
*v:null* *null-variable*
-v:null Special value used to put "null" in JSON and NIL in msgpack.
+v:null Special value used to put "null" in JSON and NIL in msgpack.
See |json_encode()|. This value is converted to "v:null" when
used as a String (e.g. in |expr5| with string concatenation
operator) and to zero when used as a Number (e.g. in |expr5|
@@ -2184,6 +2184,7 @@ getjumplist([{winnr} [, {tabnr}]])
getline({lnum}) String line {lnum} of current buffer
getline({lnum}, {end}) List lines {lnum} to {end} of current buffer
getloclist({nr} [, {what}]) List list of location list items
+getmarklist([{expr}]) List list of global/local marks
getmatches([{win}]) List list of current matches
getpid() Number process ID of Vim
getpos({expr}) List position of cursor, mark, etc.
@@ -4149,7 +4150,7 @@ function({name} [, {arglist}] [, {dict}])
garbagecollect([{atexit}]) *garbagecollect()*
Cleanup unused |Lists| and |Dictionaries| that have circular
references.
-
+
There is hardly ever a need to invoke this function, as it is
automatically done when Vim runs out of memory or is waiting
for the user to press a key after 'updatetime'. Items without
@@ -4649,6 +4650,24 @@ getloclist({nr},[, {what}]) *getloclist()*
field is applicable only when called from a location list
window. See |location-list-file-window| for more details.
+getmarklist([{expr}] *getmarklist()*
+ Without the {expr} argument returns a |List| with information
+ about all the global marks. |mark|
+
+ If the optional {expr} argument is specified, returns the
+ local marks defined in buffer {expr}. For the use of {expr},
+ see |bufname()|.
+
+ Each item in the retuned List is a |Dict| with the following:
+ name - name of the mark prefixed by "'"
+ pos - a |List| with the position of the mark:
+ [bufnum, lnum, col, off]
+ Refer to |getpos()| for more information.
+ file - file name
+
+ Refer to |getpos()| for getting information about a specific
+ mark.
+
getmatches([{win}]) *getmatches()*
Returns a |List| with all matches previously defined for the
current window by |matchadd()| and the |:match| commands.
@@ -4915,7 +4934,7 @@ getwininfo([{winid}]) *getwininfo()*
quickfix 1 if quickfix or location list window
terminal 1 if a terminal window
tabnr tab page number
- topline first displayed buffer line
+ topline first displayed buffer line
variables a reference to the dictionary with
window-local variables
width window width
@@ -5055,7 +5074,7 @@ has({feature}) Returns 1 if {feature} is supported, 0 otherwise. The
Vim's compile-time feature-names (prefixed with "+") are not
recognized because Nvim is always compiled with all possible
- features. |feature-compile|
+ features. |feature-compile|
Feature names can be:
1. Nvim version. For example the "nvim-0.2.1" feature means
@@ -5080,7 +5099,7 @@ has({feature}) Returns 1 if {feature} is supported, 0 otherwise. The
ttyin input is a terminal (tty)
ttyout output is a terminal (tty)
unix Unix system.
- *vim_starting* True during |startup|.
+ *vim_starting* True during |startup|.
win32 Windows system (32 or 64 bit).
win64 Windows system (64 bit).
wsl WSL (Windows Subsystem for Linux) system
@@ -5665,7 +5684,7 @@ json_encode({expr}) *json_encode()*
|msgpack-special-dict|), values with self-referencing
containers, strings which contain non-UTF-8 characters,
pseudo-UTF-8 strings which contain codepoints reserved for
- surrogate pairs (such strings are not valid UTF-8 strings).
+ surrogate pairs (such strings are not valid UTF-8 strings).
Non-printable characters are converted into "\u1234" escapes
or special escapes like "\t", other are dumped as-is.
@@ -5828,7 +5847,7 @@ map({expr1}, {expr2}) *map()*
{expr1} must be a |List| or a |Dictionary|.
Replace each item in {expr1} with the result of evaluating
{expr2}. {expr2} must be a |string| or |Funcref|.
-
+
If {expr2} is a |string|, inside {expr2} |v:val| has the value
of the current item. For a |Dictionary| |v:key| has the key
of the current item and for a |List| |v:key| has the index of
@@ -6095,8 +6114,8 @@ matchaddpos({group}, {pos} [, {priority} [, {id} [, {dict}]]])
- A list with three numbers, e.g., [23, 11, 3]. As above, but
the third number gives the length of the highlight in bytes.
- Entries with zero and negative line numbers are silently
- ignored, as well as entries with negative column numbers and
+ Entries with zero and negative line numbers are silently
+ ignored, as well as entries with negative column numbers and
lengths.
The maximum number of positions is 8.
@@ -7589,7 +7608,7 @@ setpos({expr}, {list})
setqflist({list} [, {action}[, {what}]]) *setqflist()*
Create or replace or add to the quickfix list.
-
+
When {what} is not present, use the items in {list}. Each
item must be a dictionary. Non-dictionary items in {list} are
ignored. Each dictionary item can contain the following
@@ -7630,12 +7649,12 @@ setqflist({list} [, {action}[, {what}]]) *setqflist()*
'a' The items from {list} are added to the existing
quickfix list. If there is no existing list, then a
new list is created.
-
+
'r' The items from the current quickfix list are replaced
with the items from {list}. This can also be used to
clear the list: >
:call setqflist([], 'r')
-<
+<
'f' All the quickfix lists in the quickfix stack are
freed.
@@ -8004,7 +8023,7 @@ sign_place({id}, {group}, {name}, {expr} [, {dict}])
empty string. {group} functions as a namespace for {id}, thus
two groups can use the same IDs. Refer to |sign-identifier|
for more information.
-
+
{name} refers to a defined sign.
{expr} refers to a buffer name or number. For the accepted
values, see |bufname()|.
@@ -8784,7 +8803,7 @@ system({cmd} [, {input}]) *system()* *E677*
Note: Use |shellescape()| or |::S| with |expand()| or
|fnamemodify()| to escape special characters in a command
- argument. Newlines in {cmd} may cause the command to fail.
+ argument. Newlines in {cmd} may cause the command to fail.
The characters in 'shellquote' and 'shellxquote' may also
cause trouble.
diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt
index afcacad460..172821ac28 100644
--- a/runtime/doc/index.txt
+++ b/runtime/doc/index.txt
@@ -1173,9 +1173,11 @@ tag command action ~
|:caddbuffer| :cad[dbuffer] add errors from buffer
|:caddexpr| :cadde[xpr] add errors from expr
|:caddfile| :caddf[ile] add error message to current quickfix list
+|:cafter| :caf[ter] go to error after current cursor
|:call| :cal[l] call a function
|:catch| :cat[ch] part of a :try command
-|:cbelow| :cbe[low] go to error below current line
+|:cbefore| :cbef[ore] go to error before current cursor
+|:cbelow| :cbel[ow] go to error below current line
|:cbottom| :cbo[ttom] scroll to the bottom of the quickfix window
|:cbuffer| :cb[uffer] parse error messages and jump to first error
|:cc| :cc go to specific error
@@ -1336,10 +1338,12 @@ tag command action ~
|:laddexpr| :lad[dexpr] add locations from expr
|:laddbuffer| :laddb[uffer] add locations from buffer
|:laddfile| :laddf[ile] add locations to current location list
+|:lafter| :laf[ter] go to location after current cursor
|:last| :la[st] go to the last file in the argument list
|:language| :lan[guage] set the language (locale)
|:later| :lat[er] go to newer change, redo
-|:lbelow| :lbe[low] go to location below current line
+|:lbefore| :lbef[ore] go to location before current cursor
+|:lbelow| :lbel[ow] go to location below current line
|:lbottom| :lbo[ttom] scroll to the bottom of the location window
|:lbuffer| :lb[uffer] parse locations and jump to first location
|:lcd| :lc[d] change directory locally
@@ -1539,6 +1543,8 @@ tag command action ~
|:sign| :sig[n] manipulate signs
|:silent| :sil[ent] run a command silently
|:sleep| :sl[eep] do nothing for a few seconds
+|:sleep!| :sl[eep]! do nothing for a few seconds, without the
+ cursor visible
|:slast| :sla[st] split window and go to last file in the
argument list
|:smagic| :sm[agic] :substitute with 'magic'
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt
index 8e93b188e9..772afdcc1a 100644
--- a/runtime/doc/lsp.txt
+++ b/runtime/doc/lsp.txt
@@ -27,9 +27,9 @@ Follow these steps to get LSP features:
1. Install the nvim-lspconfig plugin. It provides common configuration for
various servers so you can get started quickly.
https://github.com/neovim/nvim-lspconfig
- 2. Install a language server. Try ":LspInstall <tab>" or use your system
- package manager to install the relevant language server:
+ 2. Install a language server. A list of language servers can be found here:
https://microsoft.github.io/language-server-protocol/implementors/servers/
+ See individual server documentation for installation instructions.
3. Add `lua require('lspconfig').xx.setup{…}` to your init.vim, where "xx" is
the name of the relevant config. See the nvim-lspconfig README for details.
NOTE: Make sure to restart nvim after installing and configuring.
@@ -62,20 +62,39 @@ Example config (in init.vim): >
vim.api.nvim_buf_set_option(0, 'omnifunc', 'v:lua.vim.lsp.omnifunc')
-- For plugins with an `on_attach` callback, call them here. For example:
- -- require('completion').on_attach(client)
+ -- require('completion').on_attach()
end
-- An example of configuring for `sumneko_lua`,
-- a language server for Lua.
- -- First, you must run `:LspInstall sumneko_lua` for this to work.
+
+ -- set the path to the sumneko installation
+ local system_name = "Linux" -- (Linux, macOS, or Windows)
+ local sumneko_root_path = '/path/to/lua-language-server'
+ local sumneko_binary = sumneko_root_path.."/bin/"..system_name.."/lua-language-server"
+
require('lspconfig').sumneko_lua.setup({
+ cmd = {sumneko_binary, "-E", sumneko_root_path .. "/main.lua"};
-- An example of settings for an LSP server.
-- For more options, see nvim-lspconfig
settings = {
Lua = {
+ runtime = {
+ -- Tell the language server which version of Lua you're using (most likely LuaJIT in the case of Neovim)
+ version = 'LuaJIT',
+ -- Setup your lua path
+ path = vim.split(package.path, ';'),
+ },
diagnostics = {
- enable = true,
- globals = { "vim" },
+ -- Get the language server to recognize the `vim` global
+ globals = {'vim'},
+ },
+ workspace = {
+ -- Make the server aware of Neovim runtime files
+ library = {
+ [vim.fn.expand('$VIMRUNTIME/lua')] = true,
+ [vim.fn.expand('$VIMRUNTIME/lua/vim/lsp')] = true,
+ },
},
}
},
@@ -176,6 +195,7 @@ specification. These LSP requests/notifications are defined by default:
textDocument/typeDefinition*
window/logMessage
window/showMessage
+ window/showMessageRequest
workspace/applyEdit
workspace/symbol
@@ -619,8 +639,9 @@ client() *vim.lsp.client*
automatically escalate and force shutdown.
• is_stopped() Checks whether a client is stopped. Returns:
true if the client is fully stopped.
- • on_attach(bufnr) Runs the on_attach function from the
- client's config if it was defined.
+ • on_attach(client, bufnr) Runs the on_attach function from
+ the client's config if it was defined. Useful for
+ buffer-local setup.
• Members
• {id} (number): The id allocated to the client.
@@ -755,6 +776,11 @@ start_client({config}) *vim.lsp.start_client()*
array.
{handlers} Map of language server method names to
|lsp-handler|
+ {settings} Map with language server specific
+ settings. These are returned to the
+ language server if requested via
+ `workspace/configuration` . Keys are
+ case-sensitive.
{init_options} Values to pass in the initialization
request as `initializationOptions` .
See `initialize` in the LSP spec.
@@ -791,7 +817,14 @@ start_client({config}) *vim.lsp.start_client()*
`capabilities.offsetEncoding` was sent
to it. You can only modify the
`client.offset_encoding` here before
- any notifications are sent.
+ any notifications are sent. Most
+ language servers expect to be sent
+ client specified settings after
+ initialization. Neovim does not make
+ this assumption. A
+ `workspace/didChangeConfiguration`
+ notification should be sent to the
+ server during on_init.
{on_exit} Callback (code, signal, client_id)
invoked on client exit.
• code: exit code of the process
@@ -1318,6 +1351,10 @@ set_signs({diagnostics}, {bufnr}, {client_id}, {sign_ns}, {opts})
{sign_ns} number|nil
{opts} table Configuration for signs. Keys:
• priority: Set the priority of the signs.
+ • severity_limit (DiagnosticSeverity):
+ • Limit severity of diagnostics found.
+ E.g. "Warning" means { "Error",
+ "Warning" } will be valid.
*vim.lsp.diagnostic.set_underline()*
set_underline({diagnostics}, {bufnr}, {client_id}, {diagnostic_ns}, {opts})
@@ -1335,10 +1372,14 @@ set_underline({diagnostics}, {bufnr}, {client_id}, {diagnostic_ns}, {opts})
Parameters: ~
{diagnostics} Diagnostic []
- {bufnr} number The buffer number
- {client_id} number the client id
- {diagnostic_ns} number|nil
- {opts} table Currently unused.
+ {bufnr} number: The buffer number
+ {client_id} number: The client id
+ {diagnostic_ns} number|nil: The namespace
+ {opts} table: Configuration table:
+ • severity_limit (DiagnosticSeverity):
+ • Limit severity of diagnostics found.
+ E.g. "Warning" means { "Error",
+ "Warning" } will be valid.
*vim.lsp.diagnostic.set_virtual_text()*
set_virtual_text({diagnostics}, {bufnr}, {client_id}, {diagnostic_ns}, {opts})
@@ -1365,6 +1406,10 @@ set_virtual_text({diagnostics}, {bufnr}, {client_id}, {diagnostic_ns}, {opts})
before virtual text on line
• spacing (number): Number of spaces to
insert before virtual text
+ • severity_limit (DiagnosticSeverity):
+ • Limit severity of diagnostics found.
+ E.g. "Warning" means { "Error",
+ "Warning" } will be valid.
*vim.lsp.diagnostic.show_line_diagnostics()*
show_line_diagnostics({opts}, {bufnr}, {line_nr}, {client_id})
@@ -1388,16 +1433,31 @@ show_line_diagnostics({opts}, {bufnr}, {line_nr}, {client_id})
{client_id} number|nil the client id
Return: ~
- {popup_bufnr, win_id}
+ table {popup_bufnr, win_id}
+
+
+==============================================================================
+Lua module: vim.lsp.handlers *lsp-handlers*
+
+ *vim.lsp.handlers.progress_callback()*
+progress_callback({_}, {_}, {params}, {client_id})
+ See also: ~
+ https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand
==============================================================================
Lua module: vim.lsp.util *lsp-util*
*vim.lsp.util.apply_text_document_edit()*
-apply_text_document_edit({text_document_edit})
+apply_text_document_edit({text_document_edit}, {index})
+ Applies a `TextDocumentEdit` , which is a list of changes to a
+ single document.
+
Parameters: ~
- {text_document_edit} (table) a `TextDocumentEdit` object
+ {text_document_edit} table: a `TextDocumentEdit` object
+ {index} number: Optional index of the edit,
+ if from a list of edits (or nil, if
+ not from a list)
See also: ~
https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentEdit
@@ -1577,6 +1637,9 @@ get_effective_tabstop({bufnr}) *vim.lsp.util.get_effective_tabstop()*
See also: ~
|softtabstop|
+get_progress_messages() *vim.lsp.util.get_progress_messages()*
+ TODO: Documentation
+
jump_to_location({location}) *vim.lsp.util.jump_to_location()*
Jumps to a location.
@@ -1598,6 +1661,19 @@ locations_to_items({locations}) *vim.lsp.util.locations_to_items()*
Return: ~
(table) list of items
+lookup_section({settings}, {section}) *vim.lsp.util.lookup_section()*
+ Helper function to return nested values in language server
+ settings
+
+ Parameters: ~
+ {settings} a table of language server settings
+ {section} a string indicating the field of the settings
+ table
+
+ Return: ~
+ (table or string) The value of settings accessed via
+ section
+
*vim.lsp.util.make_floating_popup_options()*
make_floating_popup_options({width}, {height}, {opts})
Creates a table with sensible default options for a floating
@@ -1678,7 +1754,7 @@ make_workspace_params({added}, {removed})
Create the workspace params
Parameters: ~
- {added}
+ {added}
{removed}
*vim.lsp.util.open_floating_preview()*
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index a03de10a17..0bbed56662 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -622,6 +622,9 @@ vim.api.{func}({...}) *vim.api*
Example: call the "nvim_get_current_line()" API function: >
print(tostring(vim.api.nvim_get_current_line()))
+vim.version() *vim.version*
+ Returns the version of the current neovim build.
+
vim.in_fast_event() *vim.in_fast_event()*
Returns true if the code is executing as part of a "fast" event
handler, where most of the API is disabled. These are low-level events
@@ -1262,14 +1265,12 @@ validate({opt}) *vim.validate()*
vim.validate{arg1={{'foo'}, 'table'}, arg2={'foo', 'string'}}
=> NOP (success)
-<
->
- vim.validate{arg1={1, 'table'}}
- => error('arg1: expected table, got number')
-<
->
- vim.validate{arg1={3, function(a) return (a % 2) == 0 end, 'even number'}}
- => error('arg1: expected even number, got 3')
+
+ vim.validate{arg1={1, 'table'}}
+ => error('arg1: expected table, got number')
+
+ vim.validate{arg1={3, function(a) return (a % 2) == 0 end, 'even number'}}
+ => error('arg1: expected even number, got 3')
<
Parameters: ~
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index e740a45bec..2a757bbed9 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -734,6 +734,8 @@ A jump table for the options with a short description can be found at |Q_op|.
eol allow backspacing over line breaks (join lines)
start allow backspacing over the start of insert; CTRL-W and CTRL-U
stop once at the start of insert.
+ nostop like start, except CTRL-W and CTRL-U do not stop at the start of
+ insert.
When the value is empty, Vi compatible backspacing is used.
@@ -742,6 +744,7 @@ A jump table for the options with a short description can be found at |Q_op|.
0 same as ":set backspace=" (Vi compatible)
1 same as ":set backspace=indent,eol"
2 same as ":set backspace=indent,eol,start"
+ 3 same as ":set backspace=indent,eol,nostop"
*'backup'* *'bk'* *'nobackup'* *'nobk'*
'backup' 'bk' boolean (default off)
@@ -2609,7 +2612,7 @@ A jump table for the options with a short description can be found at |Q_op|.
when internal formatting is used. Make sure the cursor is kept in the
same spot relative to the text then! The |mode()| function will
return "i" or "R" in this situation.
-
+
When the expression evaluates to non-zero Vim will fall back to using
the internal format mechanism.
@@ -3184,7 +3187,7 @@ A jump table for the options with a short description can be found at |Q_op|.
*'inccommand'* *'icm'*
'inccommand' 'icm' string (default "")
global
-
+
"nosplit": Shows the effects of a command incrementally, as you type.
"split" : Also shows partial off-screen results in a preview window.
@@ -6838,7 +6841,7 @@ A jump table for the options with a short description can be found at |Q_op|.
a built-in |highlight-groups| item to be overridden by {hl} group in
the window. Only built-in |highlight-groups| are supported, not
syntax highlighting (use |:ownsyntax| for that).
-
+
Highlights of vertical separators are determined by the window to the
left of the separator. The 'tabline' highlight of a tabpage is
decided by the last-focused window of the tabpage. Highlights of
diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt
index d6ff3ea9ea..fab3b11430 100644
--- a/runtime/doc/quickfix.txt
+++ b/runtime/doc/quickfix.txt
@@ -74,7 +74,7 @@ processing a quickfix or location list command, it will be aborted.
*:cc*
:cc[!] [nr] Display error [nr]. If [nr] is omitted, the same
- error is displayed again. Without [!] this doesn't
+:[nr]cc[!] error is displayed again. Without [!] this doesn't
work when jumping to another buffer, the current buffer
has been changed, there is the only window for the
buffer and both 'hidden' and 'autowrite' are off.
@@ -83,10 +83,13 @@ processing a quickfix or location list command, it will be aborted.
there is another window for this buffer.
The 'switchbuf' settings are respected when jumping
to a buffer.
+ When used in the quickfix window the line number can
+ be used, including "." for the current line and "$"
+ for the last line.
*:ll*
:ll[!] [nr] Same as ":cc", except the location list for the
- current window is used instead of the quickfix list.
+:[nr]ll[!] current window is used instead of the quickfix list.
*:cn* *:cne* *:cnext* *E553*
:[count]cn[ext][!] Display the [count] next error in the list that
@@ -125,8 +128,8 @@ processing a quickfix or location list command, it will be aborted.
:[count]lab[ove] Same as ":cabove", except the location list for the
current window is used instead of the quickfix list.
- *:cbe* *:cbelow*
-:[count]cbe[low] Go to the [count] error below the current line in the
+ *:cbel* *:cbelow*
+:[count]cbel[ow] Go to the [count] error below the current line in the
current buffer. If [count] is omitted, then 1 is
used. If there are no errors, then an error message
is displayed. Assumes that the entries in a quickfix
@@ -136,8 +139,36 @@ processing a quickfix or location list command, it will be aborted.
exceeds the number of entries below the current line,
then the last error in the file is selected.
- *:lbe* *:lbelow*
-:[count]lbe[low] Same as ":cbelow", except the location list for the
+ *:lbel* *:lbelow*
+:[count]lbel[ow] Same as ":cbelow", except the location list for the
+ current window is used instead of the quickfix list.
+
+ *:cbe* *:cbefore*
+:[count]cbe[fore] Go to the [count] error before the current cursor
+ position in the current buffer. If [count] is
+ omitted, then 1 is used. If there are no errors, then
+ an error message is displayed. Assumes that the
+ entries in a quickfix list are sorted by their buffer,
+ line and column numbers. If [count] exceeds the
+ number of entries before the current position, then
+ the first error in the file is selected.
+
+ *:lbe* *:lbefore*
+:[count]lbe[fore] Same as ":cbefore", except the location list for the
+ current window is used instead of the quickfix list.
+
+ *:caf* *:cafter*
+:[count]caf[ter] Go to the [count] error after the current cursor
+ position in the current buffer. If [count] is
+ omitted, then 1 is used. If there are no errors, then
+ an error message is displayed. Assumes that the
+ entries in a quickfix list are sorted by their buffer,
+ line and column numbers. If [count] exceeds the
+ number of entries after the current position, then
+ the last error in the file is selected.
+
+ *:laf* *:lafter*
+:[count]laf[ter] Same as ":cafter", except the location list for the
current window is used instead of the quickfix list.
*:cnf* *:cnfile*
@@ -805,14 +836,19 @@ lists. They set one of the existing error lists as the current one.
the current window instead of the quickfix list.
*:chistory* *:chi*
-:chi[story] Show the list of error lists. The current list is
+:[count]chi[story] Show the list of error lists. The current list is
marked with ">". The output looks like:
error list 1 of 3; 43 errors ~
> error list 2 of 3; 0 errors ~
error list 3 of 3; 15 errors ~
+ When [count] is given, then the count'th quickfix
+ list is made the current list. Example: >
+ " Make the 4th quickfix list current
+ :4chistory
+<
*:lhistory* *:lhi*
-:lhi[story] Show the list of location lists, otherwise like
+:[count]lhi[story] Show the list of location lists, otherwise like
`:chistory`.
When adding a new error list, it becomes the current list.
@@ -1294,7 +1330,11 @@ Basic items
%v virtual column number (finds a number representing
screen column of the error (1 <tab> == 8 screen
columns))
- %t error type (finds a single character)
+ %t error type (finds a single character):
+ e - error message
+ w - warning message
+ i - info message
+ n - note message
%n error number (finds a number)
%m error message (finds a string)
%r matches the "rest" of a single-line file message %O/P/Q
@@ -1365,6 +1405,7 @@ prefixes are:
%E start of a multi-line error message
%W start of a multi-line warning message
%I start of a multi-line informational message
+ %N start of a multi-line note message
%A start of a multi-line message (unspecified type)
%> for next line start with current pattern again |efm-%>|
%C continuation of a multi-line message
diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt
index d4b6324bc3..604c969c64 100644
--- a/runtime/doc/repeat.txt
+++ b/runtime/doc/repeat.txt
@@ -180,7 +180,7 @@ For writing a Vim script, see chapter 41 of the user manual |usr_41.txt|.
Read Ex commands from {file} in each directory given
by 'runtimepath' and/or 'packpath'. There is no error
for non-existing files.
-
+
Example: >
:runtime syntax/c.vim
@@ -254,7 +254,7 @@ For writing a Vim script, see chapter 41 of the user manual |usr_41.txt|.
*:packl* *:packloadall*
:packl[oadall][!] Load all packages in the "start" directory under each
entry in 'packpath'.
-
+
First all the directories found are added to
'runtimepath', then the plugins found in the
directories are sourced. This allows for a plugin to
diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt
index 160995b440..4a99aa47bf 100644
--- a/runtime/doc/starting.txt
+++ b/runtime/doc/starting.txt
@@ -1316,8 +1316,9 @@ file when reading and include:
==============================================================================
Standard Paths *standard-path*
-Nvim stores configuration and data in standard locations. Plugins are strongly
-encouraged to follow this pattern also. Use |stdpath()| to get the paths.
+Nvim stores configuration, data, and logs in standard locations. Plugins are
+strongly encouraged to follow this pattern also. Use |stdpath()| to get the
+paths.
*base-directories* *xdg*
The "base" (root) directories conform to the XDG Base Directory Specification.
@@ -1342,8 +1343,8 @@ LOG FILE *$NVIM_LOG_FILE*
Besides 'debug' and 'verbose', Nvim keeps a general log file for internal
debugging, plugins and RPC clients. >
:echo $NVIM_LOG_FILE
-Usually the file is ~/.local/share/nvim/log unless that path is inaccessible
-or if $NVIM_LOG_FILE was set before |startup|.
+By default, the file is located at stdpath('cache')/log unless that path
+is inaccessible or if $NVIM_LOG_FILE was set before |startup|.
vim:noet:tw=78:ts=8:ft=help:norl:
diff --git a/runtime/doc/tagsrch.txt b/runtime/doc/tagsrch.txt
index b011db3dd3..23db809543 100644
--- a/runtime/doc/tagsrch.txt
+++ b/runtime/doc/tagsrch.txt
@@ -544,7 +544,7 @@ only supported by new versions of ctags (such as Exuberant ctags).
the bar) and ;" is used to have Vi ignore the rest of the
line. Example:
APP file.c call cursor(3, 4)|;" v
-
+
{field} .. A list of optional fields. Each field has the form:
<Tab>{fieldname}:{value}
diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt
index 911e7b8b47..1696d3b9ba 100644
--- a/runtime/doc/treesitter.txt
+++ b/runtime/doc/treesitter.txt
@@ -195,7 +195,8 @@ query:iter_captures({node}, {bufnr}, {start_row}, {end_row})
text of the buffer. {start_row} and {end_row} can be used to limit
matches inside a row range (this is typically used with root node
as the node, i e to get syntax highlight matches in the current
- viewport)
+ viewport). When omitted the start and end row values are used from
+ the given node.
The iterator returns three values, a numeric id identifying the capture,
the captured node, and metadata from any directives processing the match.
diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt
index 0a8584927e..82406898c8 100644
--- a/runtime/doc/ui.txt
+++ b/runtime/doc/ui.txt
@@ -170,7 +170,7 @@ the editor.
`mouse_shape`: (To be implemented.)
Some keys are missing in some modes.
-
+
The following keys are deprecated:
`hl_id`: Use `attr_id` instead.
@@ -460,7 +460,7 @@ is not active. New UIs should implement |ui-linegrid| instead.
["set_scroll_region", top, bot, left, right]
Define the scroll region used by `scroll` below.
-
+
Note: ranges are end-inclusive, which is inconsistent with API
conventions.
diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt
index 31da51bfbe..e92e464c6a 100644
--- a/runtime/doc/usr_41.txt
+++ b/runtime/doc/usr_41.txt
@@ -723,6 +723,7 @@ Cursor and mark position: *cursor-functions* *mark-functions*
getcurpos() get position of the cursor
getpos() get position of cursor, mark, etc.
setpos() set position of cursor, mark, etc.
+ getmarklist() list of global/local marks
byte2line() get line number at a specific byte count
line2byte() byte count at a specific line
diff_filler() get the number of filler lines above a line
diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt
index 32551815b0..5fb7c4ce50 100644
--- a/runtime/doc/various.txt
+++ b/runtime/doc/various.txt
@@ -46,26 +46,26 @@ CTRL-L Clears and redraws the screen. The redraw may happen
ga Print the ascii value of the character under the
cursor in decimal, hexadecimal and octal.
Mnemonic: Get Ascii value.
-
+
For example, when the cursor is on a 'R':
<R> 82, Hex 52, Octal 122 ~
When the character is a non-standard ASCII character,
but printable according to the 'isprint' option, the
non-printable version is also given.
-
+
When the character is larger than 127, the <M-x> form
is also printed. For example:
<~A> <M-^A> 129, Hex 81, Octal 201 ~
<p> <|~> <M-~> 254, Hex fe, Octal 376 ~
(where <p> is a special character)
-
+
The <Nul> character in a file is stored internally as
<NL>, but it will be shown as:
<^@> 0, Hex 00, Octal 000 ~
-
+
If the character has composing characters these are
also shown. The value of 'maxcombine' doesn't matter.
-
+
If the character can be inserted as a digraph, also
output the two characters that can be used to create
the character:
@@ -317,11 +317,11 @@ g8 Print the hex values of the bytes used in the
optional.
:redi[r] @{a-z}>> Append messages to register {a-z}.
-:redi[r] @*>
+:redi[r] @*>
:redi[r] @+> Redirect messages to the selection or clipboard. For
backward compatibility, the ">" after the register
name can be omitted. See |quotestar| and |quoteplus|.
-:redi[r] @*>>
+:redi[r] @*>>
:redi[r] @+>> Append messages to the selection or clipboard.
:redi[r] @"> Redirect messages to the unnamed register. For
@@ -489,12 +489,12 @@ gO Show a filetype-specific, navigable "outline" of the
Currently works in |help| and |:Man| buffers.
[N]gs *gs* *:sl* *:sleep*
-:[N]sl[eep] [N] [m] Do nothing for [N] seconds, or [N] milliseconds if [m]
+:[N]sl[eep] [N][m] Do nothing for [N] seconds, or [N] milliseconds if [m]
was given. "gs" always uses seconds.
Default is one second. >
:sleep "sleep for one second
:5sleep "sleep for five seconds
- :sleep 100m "sleep for a hundred milliseconds
+ :sleep 100m "sleep for 100 milliseconds
10gs "sleep for ten seconds
< Can be interrupted with CTRL-C.
"gs" stands for "goto sleep".
diff --git a/runtime/doc/windows.txt b/runtime/doc/windows.txt
index b5623f4ea4..2c3ffcbe9a 100644
--- a/runtime/doc/windows.txt
+++ b/runtime/doc/windows.txt
@@ -124,7 +124,7 @@ CTRL-W CTRL-S *CTRL-W_CTRL-S*
:[N]sp[lit] [++opt] [+cmd] [file] *:sp* *:split*
Split current window in two. The result is two viewports on
the same file.
-
+
Make the new window N high (default is to use half the height
of the current window). Reduces the current window height to
create room (and others, if the 'equalalways' option is set,
diff --git a/runtime/filetype.vim b/runtime/filetype.vim
index d2083b23d3..9104519451 100644
--- a/runtime/filetype.vim
+++ b/runtime/filetype.vim
@@ -495,6 +495,9 @@ au BufNewFile,BufRead *.com call dist#ft#BindzoneCheck('dcl')
" DOT
au BufNewFile,BufRead *.dot,*.gv setf dot
+" Dune
+au BufNewFile,BufRead jbuild,dune,dune-project,dune-workspace setf dune
+
" Dylan - lid files
au BufNewFile,BufRead *.lid setf dylanlid
@@ -1121,8 +1124,8 @@ au BufNewFile,BufRead *.nse setf lua
" NSIS
au BufNewFile,BufRead *.nsi,*.nsh setf nsis
-" OCAML
-au BufNewFile,BufRead *.ml,*.mli,*.mll,*.mly,.ocamlinit setf ocaml
+" OCaml
+au BufNewFile,BufRead *.ml,*.mli,*.mll,*.mly,.ocamlinit,*.mlt,*.mlp,*.mlip,*.mli.cppo,*.ml.cppo setf ocaml
" Occam
au BufNewFile,BufRead *.occ setf occam
@@ -1130,6 +1133,9 @@ au BufNewFile,BufRead *.occ setf occam
" Omnimark
au BufNewFile,BufRead *.xom,*.xin setf omnimark
+" OPAM
+au BufNewFile,BufRead opam,*.opam,*.opam.template setf opam
+
" OpenROAD
au BufNewFile,BufRead *.or setf openroad
@@ -1164,7 +1170,9 @@ au BufNewFile,BufRead *.papp,*.pxml,*.pxsl setf papp
au BufNewFile,BufRead */etc/passwd,*/etc/passwd-,*/etc/passwd.edit,*/etc/shadow,*/etc/shadow-,*/etc/shadow.edit,*/var/backups/passwd.bak,*/var/backups/shadow.bak setf passwd
" Pascal (also *.p)
-au BufNewFile,BufRead *.pas,*.pp setf pascal
+au BufNewFile,BufRead *.pas setf pascal
+
+au BufNewFile,BufRead *.pp call dist#ft#FTpp()
" Delphi or Lazarus program file
au BufNewFile,BufRead *.dpr,*.lpr setf pascal
@@ -1549,6 +1557,9 @@ au BufNewFile,BufRead *.scm,*.ss,*.rkt setf scheme
" Screen RC
au BufNewFile,BufRead .screenrc,screenrc setf screen
+" Sexplib
+au BufNewFile,BufRead *.sexp setf sexplib
+
" Simula
au BufNewFile,BufRead *.sim setf simula
@@ -1609,6 +1620,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()
+" SPARQL queries
+au BufNewFile,BufRead *.rq,*.sparql setf sparql
+
" Spec (Linux RPM)
au BufNewFile,BufRead *.spec setf spec
diff --git a/runtime/ftplugin/elm.vim b/runtime/ftplugin/elm.vim
new file mode 100644
index 0000000000..1e10346186
--- /dev/null
+++ b/runtime/ftplugin/elm.vim
@@ -0,0 +1,18 @@
+" Elm filetype plugin file
+" Language: Elm
+" Maintainer: Andreas Scharf <as@99n.de>
+" Latest Revision: 2020-05-29
+
+if exists("b:did_ftplugin")
+ finish
+endif
+let b:did_ftplugin = 1
+
+let s:cpo_save = &cpo
+set cpo&vim
+
+setlocal comments=s1fl:{-,mb:\ ,ex:-},:--
+setlocal commentstring=--\ %s
+
+let &cpo = s:cpo_save
+unlet s:cpo_save
diff --git a/runtime/ftplugin/man.vim b/runtime/ftplugin/man.vim
index 74225a558c..5d3e00d033 100644
--- a/runtime/ftplugin/man.vim
+++ b/runtime/ftplugin/man.vim
@@ -16,7 +16,11 @@ setlocal noswapfile buftype=nofile bufhidden=hide
setlocal nomodified readonly nomodifiable
setlocal noexpandtab tabstop=8 softtabstop=8 shiftwidth=8
setlocal wrap breakindent linebreak
-setlocal iskeyword+=-
+
+" Parentheses and '-' for references like `git-ls-files(1)`; '@' for systemd
+" pages; ':' for Perl and C++ pages. Here, I intentionally omit the locale
+" specific characters matched by `@`.
+setlocal iskeyword=@-@,:,a-z,A-Z,48-57,_,.,-,(,)
setlocal nonumber norelativenumber
setlocal foldcolumn=0 colorcolumn=0 nolist nofoldenable
@@ -24,9 +28,10 @@ setlocal foldcolumn=0 colorcolumn=0 nolist nofoldenable
setlocal tagfunc=man#goto_tag
if !exists('g:no_plugin_maps') && !exists('g:no_man_maps')
- nnoremap <silent> <buffer> j gj
- nnoremap <silent> <buffer> k gk
- nnoremap <silent> <buffer> gO :call man#show_toc()<CR>
+ nnoremap <silent> <buffer> j gj
+ nnoremap <silent> <buffer> k gk
+ nnoremap <silent> <buffer> gO :call man#show_toc()<CR>
+ nnoremap <silent> <buffer> <2-LeftMouse> :Man<CR>
if s:pager
nnoremap <silent> <buffer> <nowait> q :lclose<CR>:q<CR>
else
diff --git a/runtime/indent/elm.vim b/runtime/indent/elm.vim
new file mode 100644
index 0000000000..232c347c66
--- /dev/null
+++ b/runtime/indent/elm.vim
@@ -0,0 +1,114 @@
+" Elm indent plugin file
+" Language: Elm
+" Maintainer: Andreas Scharf <as@99n.de>
+" Original Author: Joseph Hager <ajhager@gmail.com>
+" Copyright: Joseph Hager <ajhager@gmail.com>
+" License: BSD3
+" Latest Revision: 2020-05-29
+
+" Only load this indent file when no other was loaded.
+if exists('b:did_indent')
+ finish
+endif
+let b:did_indent = 1
+
+" Local defaults
+setlocal expandtab
+setlocal indentexpr=GetElmIndent()
+setlocal indentkeys+=0=else,0=if,0=of,0=import,0=then,0=type,0\|,0},0\],0),=-},0=in
+setlocal nolisp
+setlocal nosmartindent
+
+" Only define the function once.
+if exists('*GetElmIndent')
+ finish
+endif
+
+" Indent pairs
+function! s:FindPair(pstart, pmid, pend)
+ "call search(a:pend, 'bW')
+ return indent(searchpair(a:pstart, a:pmid, a:pend, 'bWn', 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string\\|comment"'))
+endfunction
+
+function! GetElmIndent()
+ let l:lnum = v:lnum - 1
+
+ " Ident 0 if the first line of the file:
+ if l:lnum == 0
+ return 0
+ endif
+
+ let l:ind = indent(l:lnum)
+ let l:lline = getline(l:lnum)
+ let l:line = getline(v:lnum)
+
+ " Indent if current line begins with '}':
+ if l:line =~? '^\s*}'
+ return s:FindPair('{', '', '}')
+
+ " Indent if current line begins with 'else':
+ elseif l:line =~# '^\s*else\>'
+ if l:lline !~# '^\s*\(if\|then\)\>'
+ return s:FindPair('\<if\>', '', '\<else\>')
+ endif
+
+ " Indent if current line begins with 'then':
+ elseif l:line =~# '^\s*then\>'
+ if l:lline !~# '^\s*\(if\|else\)\>'
+ return s:FindPair('\<if\>', '', '\<then\>')
+ endif
+
+ " HACK: Indent lines in case with nearest case clause:
+ elseif l:line =~# '->' && l:line !~# ':' && l:line !~# '\\'
+ return indent(search('^\s*case', 'bWn')) + &shiftwidth
+
+ " HACK: Don't change the indentation if the last line is a comment.
+ elseif l:lline =~# '^\s*--'
+ return l:ind
+
+ " Align the end of block comments with the start
+ elseif l:line =~# '^\s*-}'
+ return indent(search('{-', 'bWn'))
+
+ " Indent double shift after let with an empty rhs
+ elseif l:lline =~# '\<let\>.*\s=$'
+ return l:ind + 4 + &shiftwidth
+
+ " Align 'in' with the parent let.
+ elseif l:line =~# '^\s*in\>'
+ return indent(search('^\s*let', 'bWn'))
+
+ " Align bindings with the parent let.
+ elseif l:lline =~# '\<let\>'
+ return l:ind + 4
+
+ " Align bindings with the parent in.
+ elseif l:lline =~# '^\s*in\>'
+ return l:ind
+
+ endif
+
+ " Add a 'shiftwidth' after lines ending with:
+ if l:lline =~# '\(|\|=\|->\|<-\|(\|\[\|{\|\<\(of\|else\|if\|then\)\)\s*$'
+ let l:ind = l:ind + &shiftwidth
+
+ " Add a 'shiftwidth' after lines starting with type ending with '=':
+ elseif l:lline =~# '^\s*type' && l:line =~# '^\s*='
+ let l:ind = l:ind + &shiftwidth
+
+ " Back to normal indent after comments:
+ elseif l:lline =~# '-}\s*$'
+ call search('-}', 'bW')
+ let l:ind = indent(searchpair('{-', '', '-}', 'bWn', 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string"'))
+
+ " Ident some operators if there aren't any starting the last line.
+ elseif l:line =~# '^\s*\(!\|&\|(\|`\|+\||\|{\|[\|,\)=' && l:lline !~# '^\s*\(!\|&\|(\|`\|+\||\|{\|[\|,\)=' && l:lline !~# '^\s*$'
+ let l:ind = l:ind + &shiftwidth
+
+ elseif l:lline ==# '' && getline(l:lnum - 1) !=# ''
+ let l:ind = indent(search('^\s*\S+', 'bWn'))
+
+ endif
+
+ return l:ind
+endfunc
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
index 0326550245..64d08e9733 100644
--- a/runtime/lua/vim/lsp.lua
+++ b/runtime/lua/vim/lsp.lua
@@ -226,6 +226,7 @@ local function validate_client_config(config)
on_error = { config.on_error, "f", true };
on_exit = { config.on_exit, "f", true };
on_init = { config.on_init, "f", true };
+ settings = { config.settings, "t", true };
before_init = { config.before_init, "f", true };
offset_encoding = { config.offset_encoding, "s", true };
flags = { config.flags, "t", true };
@@ -327,8 +328,9 @@ end
--- Checks whether a client is stopped.
--- Returns: true if the client is fully stopped.
---
---- - on_attach(bufnr)
+--- - on_attach(client, bufnr)
--- Runs the on_attach function from the client's config if it was defined.
+--- Useful for buffer-local setup.
---
--- - Members
--- - {id} (number): The id allocated to the client.
@@ -398,6 +400,10 @@ end
---
--@param handlers Map of language server method names to |lsp-handler|
---
+--@param settings Map with language server specific settings. These are
+--- returned to the language server if requested via `workspace/configuration`.
+--- Keys are case-sensitive.
+---
--@param init_options Values to pass in the initialization request
--- as `initializationOptions`. See `initialize` in the LSP spec.
---
@@ -424,7 +430,10 @@ end
--- the server may send. For example, clangd sends
--- `initialize_result.offsetEncoding` if `capabilities.offsetEncoding` was
--- sent to it. You can only modify the `client.offset_encoding` here before
---- any notifications are sent.
+--- any notifications are sent. Most language servers expect to be sent client specified settings after
+--- initialization. Neovim does not make this assumption. A
+--- `workspace/didChangeConfiguration` notification should be sent
+--- to the server during on_init.
---
--@param on_exit Callback (code, signal, client_id) invoked on client
--- exit.
@@ -457,6 +466,7 @@ function lsp.start_client(config)
local cmd, cmd_args, offset_encoding = cleaned_config.cmd, cleaned_config.cmd_args, cleaned_config.offset_encoding
config.flags = config.flags or {}
+ config.settings = config.settings or {}
local client_id = next_client_id()
@@ -581,12 +591,19 @@ function lsp.start_client(config)
local valid_traces = {
off = 'off'; messages = 'messages'; verbose = 'verbose';
}
+ local version = vim.version()
local initialize_params = {
-- The process Id of the parent process that started the server. Is null if
-- the process has not been started by another process. If the parent
-- process is not alive then the server should exit (see exit notification)
-- its process.
processId = uv.getpid();
+ -- Information about the client
+ -- since 3.15.0
+ clientInfo = {
+ name = "Neovim",
+ version = string.format("%s.%s.%s", version.major, version.minor, version.patch)
+ };
-- The rootPath of the workspace. Is null if no folder is open.
--
-- @deprecated in favour of rootUri.
diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua
index 072349b226..a625098bab 100644
--- a/runtime/lua/vim/lsp/diagnostic.lua
+++ b/runtime/lua/vim/lsp/diagnostic.lua
@@ -16,6 +16,24 @@ local to_severity = function(severity)
return type(severity) == 'string' and DiagnosticSeverity[severity] or severity
end
+local filter_to_severity_limit = function(severity, diagnostics)
+ local filter_level = to_severity(severity)
+ if not filter_level then
+ return diagnostics
+ end
+
+ return vim.tbl_filter(function(t) return t.severity == filter_level end, diagnostics)
+end
+
+local filter_by_severity_limit = function(severity_limit, diagnostics)
+ local filter_level = to_severity(severity_limit)
+ if not filter_level then
+ return diagnostics
+ end
+
+ return vim.tbl_filter(function(t) return t.severity <= filter_level end, diagnostics)
+end
+
local to_position = function(position, bufnr)
vim.validate { position = {position, 't'} }
@@ -377,11 +395,9 @@ function M.get_line_diagnostics(bufnr, line_nr, opts, client_id)
end
if opts.severity then
- local filter_level = to_severity(opts.severity)
- line_diagnostics = vim.tbl_filter(function(t) return t.severity == filter_level end, line_diagnostics)
+ line_diagnostics = filter_to_severity_limit(opts.severity, line_diagnostics)
elseif opts.severity_limit then
- local filter_level = to_severity(opts.severity_limit)
- line_diagnostics = vim.tbl_filter(function(t) return t.severity <= filter_level end, line_diagnostics)
+ line_diagnostics = filter_by_severity_limit(opts.severity_limit, line_diagnostics)
end
if opts.severity_sort then
@@ -542,7 +558,7 @@ function M.goto_prev(opts)
)
end
---- Get the previous diagnostic closest to the cursor_position
+--- Get the next diagnostic closest to the cursor_position
---@param opts table See |vim.lsp.diagnostic.goto_next()|
---@return table Next diagnostic
function M.get_next(opts)
@@ -609,6 +625,8 @@ end
---@param sign_ns number|nil
---@param opts table Configuration for signs. Keys:
--- - priority: Set the priority of the signs.
+--- - severity_limit (DiagnosticSeverity):
+--- - Limit severity of diagnostics found. E.g. "Warning" means { "Error", "Warning" } will be valid.
function M.set_signs(diagnostics, bufnr, client_id, sign_ns, opts)
opts = opts or {}
sign_ns = sign_ns or M._get_sign_namespace(client_id)
@@ -622,9 +640,11 @@ function M.set_signs(diagnostics, bufnr, client_id, sign_ns, opts)
end
bufnr = get_bufnr(bufnr)
+ diagnostics = filter_by_severity_limit(opts.severity_limit, diagnostics)
local ok = true
for _, diagnostic in ipairs(diagnostics) do
+
ok = ok and pcall(vim.fn.sign_place,
0,
sign_ns,
@@ -654,15 +674,17 @@ end
--- </pre>
---
---@param diagnostics Diagnostic[]
----@param bufnr number The buffer number
----@param client_id number the client id
----@param diagnostic_ns number|nil
----@param opts table Currently unused.
+---@param bufnr number: The buffer number
+---@param client_id number: The client id
+---@param diagnostic_ns number|nil: The namespace
+---@param opts table: Configuration table:
+--- - severity_limit (DiagnosticSeverity):
+--- - Limit severity of diagnostics found. E.g. "Warning" means { "Error", "Warning" } will be valid.
function M.set_underline(diagnostics, bufnr, client_id, diagnostic_ns, opts)
opts = opts or {}
- assert(opts) -- lint
diagnostic_ns = diagnostic_ns or M._get_diagnostic_namespace(client_id)
+ diagnostics = filter_by_severity_limit(opts.severity_limit, diagnostics)
for _, diagnostic in ipairs(diagnostics) do
local start = diagnostic.range["start"]
@@ -703,6 +725,8 @@ end
---@param opts table Options on how to display virtual text. Keys:
--- - prefix (string): Prefix to display before virtual text on line
--- - spacing (number): Number of spaces to insert before virtual text
+--- - severity_limit (DiagnosticSeverity):
+--- - Limit severity of diagnostics found. E.g. "Warning" means { "Error", "Warning" } will be valid.
function M.set_virtual_text(diagnostics, bufnr, client_id, diagnostic_ns, opts)
opts = opts or {}
@@ -721,6 +745,7 @@ function M.set_virtual_text(diagnostics, bufnr, client_id, diagnostic_ns, opts)
end
for line, line_diagnostics in pairs(buffer_line_diagnostics) do
+ line_diagnostics = filter_by_severity_limit(opts.severity_limit, line_diagnostics)
local virt_texts = M.get_virtual_text_chunks_for_line(bufnr, line, line_diagnostics, opts)
if virt_texts then
@@ -1082,7 +1107,7 @@ end
---@param bufnr number The buffer number
---@param line_nr number The line number
---@param client_id number|nil the client id
----@return {popup_bufnr, win_id}
+---@return table {popup_bufnr, win_id}
function M.show_line_diagnostics(opts, bufnr, line_nr, client_id)
opts = opts or {}
opts.severity_sort = if_nil(opts.severity_sort, true)
@@ -1151,30 +1176,14 @@ function M.set_loclist(opts)
local bufnr = vim.api.nvim_get_current_buf()
local buffer_diags = M.get(bufnr, opts.client_id)
- local severity = to_severity(opts.severity)
- local severity_limit = to_severity(opts.severity_limit)
+ if opts.severity then
+ buffer_diags = filter_to_severity_limit(opts.severity, buffer_diags)
+ elseif opts.severity_limit then
+ buffer_diags = filter_by_severity_limit(opts.severity_limit, buffer_diags)
+ end
local items = {}
local insert_diag = function(diag)
- if severity then
- -- Handle missing severities
- if not diag.severity then
- return
- end
-
- if severity ~= diag.severity then
- return
- end
- elseif severity_limit then
- if not diag.severity then
- return
- end
-
- if severity_limit < diag.severity then
- return
- end
- end
-
local pos = diag.range.start
local row = pos.line
local col = util.character_offset(bufnr, row, pos.character)
diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua
index fd23a6a547..7eac3febd9 100644
--- a/runtime/lua/vim/lsp/handlers.lua
+++ b/runtime/lua/vim/lsp/handlers.lua
@@ -28,8 +28,9 @@ end
-- Basically a token of type number/string
local function progress_callback(_, _, params, client_id)
local client = vim.lsp.get_client_by_id(client_id)
+ local client_name = client and client.name or string.format("id=%d", client_id)
if not client then
- err_message("LSP[", client_id, "] client has shut down after sending the message")
+ err_message("LSP[", client_name, "] client has shut down after sending the message")
end
local val = params.value -- unspecified yet
local token = params.token -- string or number
@@ -43,14 +44,11 @@ local function progress_callback(_, _, params, client_id)
percentage = val.percentage,
}
elseif val.kind == 'report' then
- client.messages.progress[token] = {
- message = val.message,
- percentage = val.percentage,
- }
+ client.messages.progress[token].message = val.message;
+ client.messages.progress[token].percentage = val.percentage;
elseif val.kind == 'end' then
if client.messages.progress[token] == nil then
- err_message(
- 'echom "[lsp-status] Received `end` message with no corresponding `begin` from "')
+ err_message("LSP[", client_name, "] received `end` message with no corresponding `begin`")
else
client.messages.progress[token].message = val.message
client.messages.progress[token].done = true
@@ -70,8 +68,9 @@ M['$/progress'] = progress_callback
M['window/workDoneProgress/create'] = function(_, _, params, client_id)
local client = vim.lsp.get_client_by_id(client_id)
local token = params.token -- string or number
+ local client_name = client and client.name or string.format("id=%d", client_id)
if not client then
- err_message("LSP[", client_id, "] client has shut down after sending the message")
+ err_message("LSP[", client_name, "] client has shut down after sending the message")
end
client.messages.progress[token] = {}
return vim.NIL
@@ -94,13 +93,22 @@ M['window/showMessageRequest'] = function(_, _, params)
if choice < 1 or choice > #actions then
return vim.NIL
else
- local action_chosen = actions[choice]
- return {
- title = action_chosen;
- }
+ return actions[choice]
end
end
+--@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#client_registerCapability
+M['client/registerCapability'] = function(_, _, _, client_id)
+ local warning_tpl = "The language server %s triggers a registerCapability "..
+ "handler despite dynamicRegistration set to false. "..
+ "Report upstream, this warning is harmless"
+ local client = vim.lsp.get_client_by_id(client_id)
+ local client_name = client and client.name or string.format("id=%d", client_id)
+ local warning = string.format(warning_tpl, client_name)
+ log.warn(warning)
+ return vim.NIL
+end
+
--@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction
M['textDocument/codeAction'] = function(_, _, actions)
if actions == nil or vim.tbl_isempty(actions) then
@@ -149,6 +157,32 @@ M['workspace/applyEdit'] = function(_, _, workspace_edit)
}
end
+--@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_configuration
+M['workspace/configuration'] = function(err, _, params, client_id)
+ local client = vim.lsp.get_client_by_id(client_id)
+ if not client then
+ err_message("LSP[id=", client_id, "] client has shut down after sending the message")
+ return
+ end
+ if err then error(vim.inspect(err)) end
+ if not params.items then
+ return {}
+ end
+
+ local result = {}
+ for _, item in ipairs(params.items) do
+ if item.section then
+ local value = util.lookup_section(client.config.settings, item.section) or vim.NIL
+ -- For empty sections with no explicit '' key, return settings as is
+ if value == vim.NIL and item.section == '' then
+ value = client.config.settings or vim.NIL
+ end
+ table.insert(result, value)
+ end
+ end
+ return result
+end
+
M['textDocument/publishDiagnostics'] = function(...)
return require('vim.lsp.diagnostic').on_publish_diagnostics(...)
end
diff --git a/runtime/lua/vim/lsp/log.lua b/runtime/lua/vim/lsp/log.lua
index 587a65cd96..b6e91e37b9 100644
--- a/runtime/lua/vim/lsp/log.lua
+++ b/runtime/lua/vim/lsp/log.lua
@@ -28,7 +28,7 @@ do
local function path_join(...)
return table.concat(vim.tbl_flatten{...}, path_sep)
end
- local logfilename = path_join(vim.fn.stdpath('data'), 'lsp.log')
+ local logfilename = path_join(vim.fn.stdpath('cache'), 'lsp.log')
--- Returns the log filename.
--@returns (string) log filename
@@ -36,7 +36,7 @@ do
return logfilename
end
- vim.fn.mkdir(vim.fn.stdpath('data'), "p")
+ vim.fn.mkdir(vim.fn.stdpath('cache'), "p")
local logfile = assert(io.open(logfilename, "a+"))
for level, levelnr in pairs(log.levels) do
-- Also export the log level on the root object.
diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua
index b2d3d0641c..3e111c154a 100644
--- a/runtime/lua/vim/lsp/protocol.lua
+++ b/runtime/lua/vim/lsp/protocol.lua
@@ -34,6 +34,13 @@ local constants = {
Hint = 4;
};
+ DiagnosticTag = {
+ -- Unused or unnecessary code
+ Unnecessary = 1;
+ -- Deprecated or obsolete code
+ Deprecated = 2;
+ };
+
MessageType = {
-- An error message.
Error = 1;
@@ -521,6 +528,13 @@ export interface TextDocumentClientCapabilities {
publishDiagnostics?: {
--Whether the clients accepts diagnostics with related information.
relatedInformation?: boolean;
+ --Client supports the tag property to provide meta data about a diagnostic.
+ --Clients supporting tags have to handle unknown tags gracefully.
+ --Since 3.15.0
+ tagSupport?: {
+ --The tags supported by this client
+ valueSet: DiagnosticTag[];
+ };
};
--Capabilities specific to `textDocument/foldingRange` requests.
--
@@ -706,6 +720,18 @@ function protocol.make_client_capabilities()
dynamicRegistration = false;
prepareSupport = true;
};
+ publishDiagnostics = {
+ relatedInformation = true;
+ tagSupport = {
+ valueSet = (function()
+ local res = {}
+ for k in ipairs(protocol.DiagnosticTag) do
+ if type(k) == 'number' then table.insert(res, k) end
+ end
+ return res
+ end)();
+ };
+ };
};
workspace = {
symbol = {
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index 0972ea83c4..e33e0109b6 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -254,19 +254,27 @@ function M.extract_completion_items(result)
end
--- Applies a `TextDocumentEdit`, which is a list of changes to a single
--- document.
+--- document.
---
---@param text_document_edit (table) a `TextDocumentEdit` object
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentEdit
-function M.apply_text_document_edit(text_document_edit)
+---@param text_document_edit table: a `TextDocumentEdit` object
+---@param index number: Optional index of the edit, if from a list of edits (or nil, if not from a list)
+---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentEdit
+function M.apply_text_document_edit(text_document_edit, index)
local text_document = text_document_edit.textDocument
local bufnr = vim.uri_to_bufnr(text_document.uri)
+ -- For lists of text document edits,
+ -- do not check the version after the first edit.
+ local should_check_version = true
+ if index and index > 1 then
+ should_check_version = false
+ end
+
-- `VersionedTextDocumentIdentifier`s version may be null
-- https://microsoft.github.io/language-server-protocol/specification#versionedTextDocumentIdentifier
- if text_document.version
+ if should_check_version and (text_document.version
and M.buf_versions[bufnr]
- and M.buf_versions[bufnr] > text_document.version then
+ and M.buf_versions[bufnr] > text_document.version) then
print("Buffer ", text_document.uri, " newer than edits.")
return
end
@@ -459,12 +467,12 @@ end
-- @see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit
function M.apply_workspace_edit(workspace_edit)
if workspace_edit.documentChanges then
- for _, change in ipairs(workspace_edit.documentChanges) do
+ for idx, change in ipairs(workspace_edit.documentChanges) do
if change.kind then
-- TODO(ashkan) handle CreateFile/RenameFile/DeleteFile
error(string.format("Unsupported change: %q", vim.inspect(change)))
else
- M.apply_text_document_edit(change)
+ M.apply_text_document_edit(change, idx)
end
end
return
@@ -1422,6 +1430,21 @@ function M.character_offset(buf, row, col)
return str_utfindex(line, col)
end
+--- Helper function to return nested values in language server settings
+---
+--@param settings a table of language server settings
+--@param section a string indicating the field of the settings table
+--@returns (table or string) The value of settings accessed via section
+function M.lookup_section(settings, section)
+ for part in vim.gsplit(section, '.', true) do
+ settings = settings[part]
+ if not settings then
+ return
+ end
+ end
+ return settings
+end
+
M._get_line_byte_from_position = get_line_byte_from_position
M._warn_once = warn_once
diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index 79dcf77f9e..38ac182e32 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -50,7 +50,7 @@ function M._create_parser(bufnr, lang, opts)
end
end
- a.nvim_buf_attach(self.bufnr, false, {on_bytes=bytes_cb, on_detach=detach_cb, preview=true})
+ a.nvim_buf_attach(self:source(), false, {on_bytes=bytes_cb, on_detach=detach_cb, preview=true})
self:parse()
diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua
index 9c620c422c..c864fe5878 100644
--- a/runtime/lua/vim/treesitter/languagetree.lua
+++ b/runtime/lua/vim/treesitter/languagetree.lua
@@ -425,23 +425,21 @@ function LanguageTree:register_cbs(cbs)
end
end
-local function region_contains(region, range)
- for _, node in ipairs(region) do
- local start_row, start_col, end_row, end_col = node:range()
- local start_fits = start_row < range[1] or (start_row == range[1] and start_col <= range[2])
- local end_fits = end_row > range[3] or (end_row == range[3] and end_col >= range[4])
+local function tree_contains(tree, range)
+ local start_row, start_col, end_row, end_col = tree:root():range()
+ local start_fits = start_row < range[1] or (start_row == range[1] and start_col <= range[2])
+ local end_fits = end_row > range[3] or (end_row == range[3] and end_col >= range[4])
- if start_fits and end_fits then
- return true
- end
+ if start_fits and end_fits then
+ return true
end
return false
end
function LanguageTree:contains(range)
- for _, region in pairs(self._regions) do
- if region_contains(region, range) then
+ for _, tree in pairs(self._trees) do
+ if tree_contains(tree, range) then
return true
end
end
diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua
index 682f981fbc..e49f54681d 100644
--- a/runtime/lua/vim/treesitter/query.lua
+++ b/runtime/lua/vim/treesitter/query.lua
@@ -8,36 +8,10 @@ Query.__index = Query
local M = {}
--- Filter the runtime query files, the spec is like regular runtime files but in the new `queries`
--- directory. They resemble ftplugins, that is that you can override queries by adding things in the
--- `queries` directory, and extend using the `after/queries` directory.
-local function filter_files(file_list)
- local main = nil
- local after = {}
-
- for _, fname in ipairs(file_list) do
- -- Only get the name of the directory containing the queries directory
- if vim.fn.fnamemodify(fname, ":p:h:h:h:t") == "after" then
- table.insert(after, fname)
- -- The first one is the one with most priority
- elseif not main then
- main = fname
- end
- end
- return main and { main, unpack(after) } or after
-end
-
-local function runtime_query_path(lang, query_name)
- return string.format('queries/%s/%s.scm', lang, query_name)
-end
-
-local function filtered_runtime_queries(lang, query_name)
- return filter_files(a.nvim_get_runtime_file(runtime_query_path(lang, query_name), true) or {})
-end
-
-local function get_query_files(lang, query_name, is_included)
- local lang_files = filtered_runtime_queries(lang, query_name)
+function M.get_query_files(lang, query_name, is_included)
+ local query_path = string.format('queries/%s/%s.scm', lang, query_name)
+ local lang_files = a.nvim_get_runtime_file(query_path, true)
if #lang_files == 0 then return {} end
@@ -51,10 +25,10 @@ local function get_query_files(lang, query_name, is_included)
local MODELINE_FORMAT = "^;+%s*inherits%s*:?%s*([a-z_,()]+)%s*$"
for _, file in ipairs(lang_files) do
- local modeline = vim.fn.readfile(file, "", 1)
+ local modeline = io.open(file, 'r'):read('*l')
- if #modeline == 1 then
- local langlist = modeline[1]:match(MODELINE_FORMAT)
+ if modeline then
+ local langlist = modeline:match(MODELINE_FORMAT)
if langlist then
for _, incllang in ipairs(vim.split(langlist, ',', true)) do
@@ -74,7 +48,7 @@ local function get_query_files(lang, query_name, is_included)
local query_files = {}
for _, base_lang in ipairs(base_langs) do
- local base_files = get_query_files(base_lang, query_name, true)
+ local base_files = M.get_query_files(base_lang, query_name, true)
vim.list_extend(query_files, base_files)
end
vim.list_extend(query_files, lang_files)
@@ -86,10 +60,10 @@ local function read_query_files(filenames)
local contents = {}
for _,filename in ipairs(filenames) do
- vim.list_extend(contents, vim.fn.readfile(filename))
+ table.insert(contents, io.open(filename, 'r'):read('*a'))
end
- return table.concat(contents, '\n')
+ return table.concat(contents, '')
end
local match_metatable = {
@@ -110,7 +84,7 @@ end
--
-- @return The corresponding query, parsed.
function M.get_query(lang, query_name)
- local query_files = get_query_files(lang, query_name)
+ local query_files = M.get_query_files(lang, query_name)
local query_string = read_query_files(query_files)
if #query_string > 0 then
@@ -366,6 +340,19 @@ function Query:apply_directives(match, pattern, source, metadata)
end
end
+
+--- Returns the start and stop value if set else the node's range.
+-- When the node's range is used, the stop is incremented by 1
+-- to make the search inclusive.
+local function value_or_node_range(start, stop, node)
+ if start == nil and stop == nil then
+ local node_start, _, node_stop, _ = node:range()
+ return node_start, node_stop + 1 -- Make stop inclusive
+ end
+
+ return start, stop
+end
+
--- Iterates of the captures of self on a given range.
--
-- @param node The node under witch the search will occur
@@ -379,6 +366,9 @@ function Query:iter_captures(node, source, start, stop)
if type(source) == "number" and source == 0 then
source = vim.api.nvim_get_current_buf()
end
+
+ start, stop = value_or_node_range(start, stop, node)
+
local raw_iter = node:_rawquery(self.query, true, start, stop)
local function iter()
local capture, captured_node, match = raw_iter()
@@ -411,6 +401,9 @@ function Query:iter_matches(node, source, start, stop)
if type(source) == "number" and source == 0 then
source = vim.api.nvim_get_current_buf()
end
+
+ start, stop = value_or_node_range(start, stop, node)
+
local raw_iter = node:_rawquery(self.query, false, start, stop)
local function iter()
local pattern, match = raw_iter()
diff --git a/runtime/nvim.appdata.xml b/runtime/nvim.appdata.xml
index 025de1b5a9..e99c76a930 100644
--- a/runtime/nvim.appdata.xml
+++ b/runtime/nvim.appdata.xml
@@ -26,6 +26,7 @@
</screenshots>
<releases>
+ <release date="2020-08-04" version="0.4.4"/>
<release date="2019-11-06" version="0.4.3"/>
<release date="2019-09-15" version="0.4.2"/>
<release date="2019-09-15" version="0.4.1"/>
diff --git a/runtime/scripts.vim b/runtime/scripts.vim
index 6aae2b1ec3..536993d485 100644
--- a/runtime/scripts.vim
+++ b/runtime/scripts.vim
@@ -182,6 +182,10 @@ if s:line1 =~# "^#!"
elseif s:name =~# 'clojure'
set ft=clojure
+ " Free Pascal
+ elseif s:name =~# 'instantfpc\>'
+ set ft=pascal
+
endif
unlet s:name
diff --git a/runtime/syntax/elm.vim b/runtime/syntax/elm.vim
new file mode 100644
index 0000000000..1277827f57
--- /dev/null
+++ b/runtime/syntax/elm.vim
@@ -0,0 +1,105 @@
+" Vim syntax file
+" Language: Elm
+" Maintainer: Andreas Scharf <as@99n.de>
+" Original Author: Joseph Hager <ajhager@gmail.com>
+" Copyright: Joseph Hager <ajhager@gmail.com>
+" License: BSD3
+" Latest Revision: 2020-05-29
+
+if exists('b:current_syntax')
+ finish
+endif
+
+" Keywords
+syn keyword elmConditional else if of then case
+syn keyword elmAlias alias
+syn keyword elmTypedef contained type port
+syn keyword elmImport exposing as import module where
+
+" Operators
+" elm/core
+syn match elmOperator contained "\(<|\||>\|||\|&&\|==\|/=\|<=\|>=\|++\|::\|+\|-\|*\|/\|//\|^\|<>\|>>\|<<\|<\|>\|%\)"
+" elm/parser
+syn match elmOperator contained "\(|.\||=\)"
+" elm/url
+syn match elmOperator contained "\(</>\|<?>\)"
+
+" Types
+syn match elmType "\<[A-Z][0-9A-Za-z_-]*"
+syn keyword elmNumberType number
+
+" Modules
+syn match elmModule "\<\([A-Z][0-9A-Za-z_'-\.]*\)\+\.[A-Za-z]"me=e-2
+syn match elmModule "^\(module\|import\)\s\+[A-Z][0-9A-Za-z_'-\.]*\(\s\+as\s\+[A-Z][0-9A-Za-z_'-\.]*\)\?\(\s\+exposing\)\?" contains=elmImport
+
+" Delimiters
+syn match elmDelimiter "[,;]"
+syn match elmBraces "[()[\]{}]"
+
+" Functions
+syn match elmTupleFunction "\((,\+)\)"
+
+" Comments
+syn keyword elmTodo TODO FIXME XXX contained
+syn match elmLineComment "--.*" contains=elmTodo,@spell
+syn region elmComment matchgroup=elmComment start="{-|\=" end="-}" contains=elmTodo,elmComment,@spell fold
+
+" Strings
+syn match elmStringEscape "\\u[0-9a-fA-F]\{4}" contained
+syn match elmStringEscape "\\[nrfvbt\\\"]" contained
+syn region elmString start="\"" skip="\\\"" end="\"" contains=elmStringEscape,@spell
+syn region elmTripleString start="\"\"\"" skip="\\\"" end="\"\"\"" contains=elmStringEscape,@spell
+syn match elmChar "'[^'\\]'\|'\\.'\|'\\u[0-9a-fA-F]\{4}'"
+
+" Lambda
+syn region elmLambdaFunc start="\\"hs=s+1 end="->"he=e-2
+
+" Debug
+syn match elmDebug "Debug.\(log\|todo\|toString\)"
+
+" Numbers
+syn match elmInt "-\?\<\d\+\>"
+syn match elmFloat "-\?\(\<\d\+\.\d\+\>\)"
+
+" Identifiers
+syn match elmTopLevelDecl "^\s*[a-zA-Z][a-zA-z0-9_]*\('\)*\s\+:\(\r\n\|\r\|\n\|\s\)\+" contains=elmOperator
+syn match elmFuncName /^\l\w*/
+
+" Folding
+syn region elmTopLevelTypedef start="type" end="\n\(\n\n\)\@=" contains=ALL fold
+syn region elmTopLevelFunction start="^[a-zA-Z].\+\n[a-zA-Z].\+=" end="^\(\n\+\)\@=" contains=ALL fold
+syn region elmCaseBlock matchgroup=elmCaseBlockDefinition start="^\z\(\s\+\)\<case\>" end="^\z1\@!\W\@=" end="\(\n\n\z1\@!\)\@=" end="\n\z1\@!\(\n\n\)\@=" contains=ALL fold
+syn region elmCaseItemBlock start="^\z\(\s\+\).\+->$" end="^\z1\@!\W\@=" end="\(\n\n\z1\@!\)\@=" end="\(\n\z1\S\)\@=" contains=ALL fold
+syn region elmLetBlock matchgroup=elmLetBlockDefinition start="\<let\>" end="\<in\>" contains=ALL fold
+
+hi def link elmFuncName Function
+hi def link elmCaseBlockDefinition Conditional
+hi def link elmCaseBlockItemDefinition Conditional
+hi def link elmLetBlockDefinition TypeDef
+hi def link elmTopLevelDecl Function
+hi def link elmTupleFunction Normal
+hi def link elmTodo Todo
+hi def link elmComment Comment
+hi def link elmLineComment Comment
+hi def link elmString String
+hi def link elmTripleString String
+hi def link elmChar String
+hi def link elmStringEscape Special
+hi def link elmInt Number
+hi def link elmFloat Float
+hi def link elmDelimiter Delimiter
+hi def link elmBraces Delimiter
+hi def link elmTypedef TypeDef
+hi def link elmImport Include
+hi def link elmConditional Conditional
+hi def link elmAlias Delimiter
+hi def link elmOperator Operator
+hi def link elmType Type
+hi def link elmNumberType Identifier
+hi def link elmLambdaFunc Function
+hi def link elmDebug Debug
+hi def link elmModule Type
+
+syn sync minlines=500
+
+let b:current_syntax = 'elm'
diff --git a/scripts/genvimvim.lua b/scripts/genvimvim.lua
index 806533f2ff..ccd5489fdc 100644
--- a/scripts/genvimvim.lua
+++ b/scripts/genvimvim.lua
@@ -55,7 +55,7 @@ end
vimcmd_start = 'syn keyword vimCommand contained '
w(vimcmd_start)
local prev_cmd = nil
-for _, cmd_desc in ipairs(ex_cmds) do
+for _, cmd_desc in ipairs(ex_cmds.cmds) do
if lld.line_length > 850 then
w('\n' .. vimcmd_start)
end
diff --git a/src/nvim/README.md b/src/nvim/README.md
index d14ba85546..affc5c79cc 100644
--- a/src/nvim/README.md
+++ b/src/nvim/README.md
@@ -38,7 +38,7 @@ alternate file (e.g. stderr) use `LOG_CALLSTACK_TO_FILE(FILE*)`. Requires
Many log messages have a shared prefix, such as "UI" or "RPC". Use the shell to
filter the log, e.g. at DEBUG level you might want to exclude UI messages:
- tail -F ~/.local/share/nvim/log | cat -v | stdbuf -o0 grep -v UI | stdbuf -o0 tee -a log
+ tail -F ~/.cache/nvim/log | cat -v | stdbuf -o0 grep -v UI | stdbuf -o0 tee -a log
Build with ASAN
---------------
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index 2c99d3426c..7cee569989 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -820,6 +820,10 @@ void modify_keymap(Buffer buffer, bool is_unmap, String mode, String lhs,
}
buf_T *target_buf = find_buffer_by_handle(buffer, err);
+ if (!target_buf) {
+ return;
+ }
+
MapArguments parsed_args;
memset(&parsed_args, 0, sizeof(parsed_args));
if (parse_keymap_opts(opts, &parsed_args, err)) {
@@ -1641,6 +1645,43 @@ bool api_object_to_bool(Object obj, const char *what,
}
}
+HlMessage parse_hl_msg(Array chunks, Error *err)
+{
+ HlMessage hl_msg = KV_INITIAL_VALUE;
+ for (size_t i = 0; i < chunks.size; i++) {
+ if (chunks.items[i].type != kObjectTypeArray) {
+ api_set_error(err, kErrorTypeValidation, "Chunk is not an array");
+ goto free_exit;
+ }
+ Array chunk = chunks.items[i].data.array;
+ if (chunk.size == 0 || chunk.size > 2
+ || chunk.items[0].type != kObjectTypeString
+ || (chunk.size == 2 && chunk.items[1].type != kObjectTypeString)) {
+ api_set_error(err, kErrorTypeValidation,
+ "Chunk is not an array with one or two strings");
+ goto free_exit;
+ }
+
+ String str = copy_string(chunk.items[0].data.string);
+
+ int attr = 0;
+ if (chunk.size == 2) {
+ String hl = chunk.items[1].data.string;
+ if (hl.size > 0) {
+ int hl_id = syn_check_group((char_u *)hl.data, (int)hl.size);
+ attr = hl_id > 0 ? syn_id2attr(hl_id) : 0;
+ }
+ }
+ kv_push(hl_msg, ((HlMessageChunk){ .text = str, .attr = attr }));
+ }
+
+ return hl_msg;
+
+free_exit:
+ clear_hl_msg(&hl_msg);
+ return hl_msg;
+}
+
const char *describe_ns(NS ns_id)
{
String name;
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 1e972e01be..9e2fb6da6f 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -990,6 +990,47 @@ void nvim_set_option(uint64_t channel_id, String name, Object value, Error *err)
set_option_to(channel_id, NULL, SREQ_GLOBAL, name, value, err);
}
+/// Echo a message.
+///
+/// @param chunks A list of [text, hl_group] arrays, each representing a
+/// text chunk with specified highlight. `hl_group` element
+/// can be omitted for no highlight.
+/// @param history if true, add to |message-history|.
+/// @param opts Optional parameters. Reserved for future use.
+void nvim_echo(Array chunks, Boolean history, Dictionary opts, Error *err)
+ FUNC_API_SINCE(7)
+{
+ HlMessage hl_msg = parse_hl_msg(chunks, err);
+ if (ERROR_SET(err)) {
+ goto error;
+ }
+
+ if (opts.size > 0) {
+ api_set_error(err, kErrorTypeValidation, "opts dict isn't empty");
+ goto error;
+ }
+
+ no_wait_return++;
+ bool need_clear = true;
+ msg_start();
+ for (uint32_t i = 0; i < kv_size(hl_msg); i++) {
+ HlMessageChunk chunk = kv_A(hl_msg, i);
+ msg_multiline_attr((const char *)chunk.text.data, chunk.attr,
+ false, &need_clear);
+ }
+ if (history) {
+ msg_ext_set_kind("echomsg");
+ add_hl_msg_hist(hl_msg);
+ } else {
+ msg_ext_set_kind("echo");
+ }
+ no_wait_return--;
+ msg_end();
+
+error:
+ clear_hl_msg(&hl_msg);
+}
+
/// Writes a message to the Vim output buffer. Does not append "\n", the
/// message is buffered (won't display) until a linefeed is written.
///
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 93a03986e5..0134ee838d 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -2159,10 +2159,11 @@ static buf_T *buflist_findname_file_id(char_u *ffname, FileID *file_id,
int buflist_findpat(
const char_u *pattern,
const char_u *pattern_end, // pointer to first char after pattern
- int unlisted, // find unlisted buffers
- int diffmode, // find diff-mode buffers only
- int curtab_only // find buffers in current tab only
+ bool unlisted, // find unlisted buffers
+ bool diffmode, // find diff-mode buffers only
+ bool curtab_only // find buffers in current tab only
)
+ FUNC_ATTR_NONNULL_ARG(1)
{
int match = -1;
int find_listed;
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 876e53e3cd..b2abb06075 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -8282,8 +8282,9 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
}
} while (revins_on
|| (curwin->w_cursor.col > mincol
- && (curwin->w_cursor.lnum != Insstart_orig.lnum
- || curwin->w_cursor.col != Insstart_orig.col)));
+ && (can_bs(BS_NOSTOP)
+ || (curwin->w_cursor.lnum != Insstart_orig.lnum
+ || curwin->w_cursor.col != Insstart_orig.col))));
}
did_backspace = true;
}
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index f60504de5e..8a1556320c 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -5948,6 +5948,19 @@ int assert_exception(typval_T *argvars)
return 0;
}
+static void assert_append_cmd_or_arg(garray_T *gap, typval_T *argvars,
+ const char *cmd)
+ FUNC_ATTR_NONNULL_ALL
+{
+ if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN) {
+ char *const tofree = encode_tv2echo(&argvars[2], NULL);
+ ga_concat(gap, (char_u *)tofree);
+ xfree(tofree);
+ } else {
+ ga_concat(gap, (char_u *)cmd);
+ }
+}
+
int assert_fails(typval_T *argvars)
FUNC_ATTR_NONNULL_ALL
{
@@ -5966,14 +5979,7 @@ int assert_fails(typval_T *argvars)
if (!called_emsg) {
prepare_assert_error(&ga);
ga_concat(&ga, (const char_u *)"command did not fail: ");
- if (argvars[1].v_type != VAR_UNKNOWN
- && argvars[2].v_type != VAR_UNKNOWN) {
- char *const tofree = encode_tv2echo(&argvars[2], NULL);
- ga_concat(&ga, (char_u *)tofree);
- xfree(tofree);
- } else {
- ga_concat(&ga, (const char_u *)cmd);
- }
+ assert_append_cmd_or_arg(&ga, argvars, cmd);
assert_error(&ga);
ga_clear(&ga);
ret = 1;
@@ -5986,6 +5992,8 @@ int assert_fails(typval_T *argvars)
prepare_assert_error(&ga);
fill_assert_error(&ga, &argvars[2], NULL, &argvars[1],
&vimvars[VV_ERRMSG].vv_tv, ASSERT_OTHER);
+ ga_concat(&ga, (char_u *)": ");
+ assert_append_cmd_or_arg(&ga, argvars, cmd);
assert_error(&ga);
ga_clear(&ga);
ret = 1;
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index 466f1800c7..952fa35b83 100644
--- a/src/nvim/eval.lua
+++ b/src/nvim/eval.lua
@@ -150,6 +150,7 @@ return {
getjumplist={args={0, 2}},
getline={args={1, 2}},
getloclist={args={1, 2}},
+ getmarklist={args={0, 1}},
getmatches={args={0, 1}},
getpid={},
getpos={args=1},
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 16eb6f8898..8235d74cbb 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -726,7 +726,7 @@ buf_T *tv_get_buf(typval_T *tv, int curtab_only)
p_cpo = (char_u *)"";
buf = buflist_findnr(buflist_findpat(name, name + STRLEN(name),
- TRUE, FALSE, curtab_only));
+ true, false, curtab_only));
p_magic = save_magic;
p_cpo = save_cpo;
@@ -2165,7 +2165,7 @@ static void f_expandcmd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
.nextcmd = NULL,
.cmdidx = CMD_USER,
};
- eap.argt |= NOSPC;
+ eap.argt |= EX_NOSPC;
expand_filename(&eap, &cmdstr, &errormsg);
if (errormsg != NULL && *errormsg != NUL) {
@@ -3483,6 +3483,25 @@ static void f_getloclist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
get_qf_loc_list(false, wp, &argvars[1], rettv);
}
+
+/// "getmarklist()" function
+static void f_getmarklist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+{
+ tv_list_alloc_ret(rettv, kListLenMayKnow);
+
+ if (argvars[0].v_type == VAR_UNKNOWN) {
+ get_global_marks(rettv->vval.v_list);
+ return;
+ }
+
+ buf_T *buf = tv_get_buf(&argvars[0], false);
+ if (buf == NULL) {
+ return;
+ }
+
+ get_buf_local_marks(buf, rettv->vval.v_list);
+}
+
/*
* "getmatches()" function
*/
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index ae389a6727..a2487336f1 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -629,6 +629,8 @@ void ex_sort(exarg_T *eap)
if (sort_abort)
goto sortend;
+ bcount_t old_count = 0, new_count = 0;
+
// Insert the lines in the sorted order below the last one.
lnum = eap->line2;
for (i = 0; i < count; i++) {
@@ -641,6 +643,8 @@ void ex_sort(exarg_T *eap)
}
s = ml_get(get_lnum);
+ size_t bytelen = STRLEN(s) + 1; // include EOL in bytelen
+ old_count += bytelen;
if (!unique || i == 0
|| (sort_ic ? STRICMP(s, sortbuf1) : STRCMP(s, sortbuf1)) != 0) {
// Copy the line into a buffer, it may become invalid in
@@ -649,6 +653,7 @@ void ex_sort(exarg_T *eap)
if (ml_append(lnum++, sortbuf1, (colnr_T)0, false) == FAIL) {
break;
}
+ new_count += bytelen;
}
fast_breakcheck();
if (got_int)
@@ -668,11 +673,16 @@ void ex_sort(exarg_T *eap)
deleted = (long)(count - (lnum - eap->line2));
if (deleted > 0) {
mark_adjust(eap->line2 - deleted, eap->line2, (long)MAXLNUM, -deleted,
- kExtmarkUndo);
+ kExtmarkNOOP);
msgmore(-deleted);
} else if (deleted < 0) {
- mark_adjust(eap->line2, MAXLNUM, -deleted, 0L, kExtmarkUndo);
+ mark_adjust(eap->line2, MAXLNUM, -deleted, 0L, kExtmarkNOOP);
}
+
+ extmark_splice(curbuf, eap->line1-1, 0,
+ count, 0, old_count,
+ lnum - eap->line2, 0, new_count, kExtmarkUndo);
+
if (change_occurred || deleted != 0) {
changed_lines(eap->line1, 0, eap->line2 + 1, -deleted, true);
}
@@ -1032,14 +1042,15 @@ void free_prev_shellcmd(void)
* Bangs in the argument are replaced with the previously entered command.
* Remember the argument.
*/
-void do_bang(int addr_count, exarg_T *eap, int forceit, int do_in, int do_out)
+void do_bang(int addr_count, exarg_T *eap, bool forceit,
+ bool do_in, bool do_out)
+ FUNC_ATTR_NONNULL_ALL
{
- char_u *arg = eap->arg; /* command */
- linenr_T line1 = eap->line1; /* start of range */
- linenr_T line2 = eap->line2; /* end of range */
- char_u *newcmd = NULL; /* the new command */
- int free_newcmd = FALSE; /* need to free() newcmd */
- int ins_prevcmd;
+ char_u *arg = eap->arg; // command
+ linenr_T line1 = eap->line1; // start of range
+ linenr_T line2 = eap->line2; // end of range
+ char_u *newcmd = NULL; // the new command
+ bool free_newcmd = false; // need to free() newcmd
char_u *t;
char_u *p;
char_u *trailarg;
@@ -1064,7 +1075,7 @@ void do_bang(int addr_count, exarg_T *eap, int forceit, int do_in, int do_out)
* Try to find an embedded bang, like in :!<cmd> ! [args]
* (:!! is indicated by the 'forceit' variable)
*/
- ins_prevcmd = forceit;
+ bool ins_prevcmd = forceit;
trailarg = arg;
do {
len = (int)STRLEN(trailarg) + 1;
@@ -1101,7 +1112,7 @@ void do_bang(int addr_count, exarg_T *eap, int forceit, int do_in, int do_out)
else {
trailarg = p;
*trailarg++ = NUL;
- ins_prevcmd = TRUE;
+ ins_prevcmd = true;
break;
}
}
@@ -1131,7 +1142,7 @@ void do_bang(int addr_count, exarg_T *eap, int forceit, int do_in, int do_out)
STRCPY(newcmd, p_shq);
STRCAT(newcmd, prevcmd);
STRCAT(newcmd, p_shq);
- free_newcmd = TRUE;
+ free_newcmd = true;
}
if (addr_count == 0) { /* :! */
/* echo the command */
@@ -1164,15 +1175,15 @@ void do_bang(int addr_count, exarg_T *eap, int forceit, int do_in, int do_out)
// do this.
// Alternatively, if on Unix and redirecting input or output, but not both,
// and the 'shelltemp' option isn't set, use pipes.
-// We use input redirection if do_in is TRUE.
-// We use output redirection if do_out is TRUE.
+// We use input redirection if do_in is true.
+// We use output redirection if do_out is true.
static void do_filter(
linenr_T line1,
linenr_T line2,
exarg_T *eap, /* for forced 'ff' and 'fenc' */
char_u *cmd,
- int do_in,
- int do_out)
+ bool do_in,
+ bool do_out)
{
char_u *itmp = NULL;
char_u *otmp = NULL;
@@ -1669,10 +1680,17 @@ void ex_update(exarg_T *eap)
*/
void ex_write(exarg_T *eap)
{
- if (eap->usefilter) /* input lines to shell command */
- do_bang(1, eap, FALSE, TRUE, FALSE);
- else
+ if (eap->cmdidx == CMD_saveas) {
+ // :saveas does not take a range, uses all lines.
+ eap->line1 = 1;
+ eap->line2 = curbuf->b_ml.ml_line_count;
+ }
+
+ if (eap->usefilter) { // input lines to shell command
+ do_bang(1, eap, false, true, false);
+ } else {
(void)do_write(eap);
+ }
}
/*
@@ -3675,6 +3693,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout,
} else {
char_u *orig_line = NULL;
int len_change = 0;
+ const bool save_p_lz = p_lz;
int save_p_fen = curwin->w_p_fen;
curwin->w_p_fen = FALSE;
@@ -3683,6 +3702,9 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout,
int temp = RedrawingDisabled;
RedrawingDisabled = 0;
+ // avoid calling update_screen() in vgetorpeek()
+ p_lz = false;
+
if (new_start != NULL) {
/* There already was a substitution, we would
* like to show this to the user. We cannot
@@ -3736,7 +3758,8 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout,
/* clear the question */
msg_didout = FALSE; /* don't scroll up */
msg_col = 0;
- gotocmdline(TRUE);
+ gotocmdline(true);
+ p_lz = save_p_lz;
// restore the line
if (orig_line != NULL) {
diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua
index 380237c822..e9046da800 100644
--- a/src/nvim/ex_cmds.lua
+++ b/src/nvim/ex_cmds.lua
@@ -1,6 +1,9 @@
local bit = require 'bit'
+local module = {}
+
-- Description of the values below is contained in ex_cmds_defs.h file.
+-- "EX_" prefix is omitted.
local RANGE = 0x001
local BANG = 0x002
local EXTRA = 0x004
@@ -14,23 +17,26 @@ local REGSTR = 0x200
local COUNT = 0x400
local NOTRLCOM = 0x800
local ZEROR = 0x1000
-local USECTRLV = 0x2000
-local NOTADR = 0x4000
-local EDITCMD = 0x8000
-local BUFNAME = 0x10000
-local BUFUNL = 0x20000
-local ARGOPT = 0x40000
-local SBOXOK = 0x80000
-local CMDWIN = 0x100000
-local MODIFY = 0x200000
-local EXFLAGS = 0x400000
-local RESTRICT = 0x800000
+local CTRLV = 0x2000
+local CMDARG = 0x4000
+local BUFNAME = 0x8000
+local BUFUNL = 0x10000
+local ARGOPT = 0x20000
+local SBOXOK = 0x40000
+local CMDWIN = 0x80000
+local MODIFY = 0x100000
+local FLAGS = 0x200000
local FILES = bit.bor(XFILE, EXTRA)
local WORD1 = bit.bor(EXTRA, NOSPC)
local FILE1 = bit.bor(FILES, NOSPC)
+module.flags = {
+ RANGE = RANGE,
+ DFLALL = DFLALL,
+}
+
-- The following table is described in ex_cmds_defs.h file.
-return {
+module.cmds = {
{
command='append',
flags=bit.bor(BANG, RANGE, ZEROR, TRLBAR, CMDWIN, MODIFY),
@@ -39,247 +45,247 @@ return {
},
{
command='abbreviate',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_abbreviate',
},
{
command='abclear',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_abclear',
},
{
command='aboveleft',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='all',
- flags=bit.bor(BANG, RANGE, NOTADR, COUNT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_all',
},
{
command='amenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='anoremenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='args',
- flags=bit.bor(BANG, FILES, EDITCMD, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, FILES, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_args',
},
{
command='argadd',
- flags=bit.bor(BANG, RANGE, NOTADR, ZEROR, FILES, TRLBAR),
+ flags=bit.bor(BANG, RANGE, ZEROR, FILES, TRLBAR),
addr_type='ADDR_ARGUMENTS',
func='ex_argadd',
},
{
command='argdelete',
- flags=bit.bor(BANG, RANGE, NOTADR, FILES, TRLBAR),
+ flags=bit.bor(BANG, RANGE, FILES, TRLBAR),
addr_type='ADDR_ARGUMENTS',
func='ex_argdelete',
},
{
command='argdo',
- flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, NOTADR, DFLALL),
+ flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
addr_type='ADDR_ARGUMENTS',
func='ex_listdo',
},
{
command='argedit',
- flags=bit.bor(BANG, NEEDARG, RANGE, NOTADR, ZEROR, FILES, EDITCMD, ARGOPT, TRLBAR),
+ flags=bit.bor(BANG, NEEDARG, RANGE, ZEROR, FILES, CMDARG, ARGOPT, TRLBAR),
addr_type='ADDR_ARGUMENTS',
func='ex_argedit',
},
{
command='argglobal',
- flags=bit.bor(BANG, FILES, EDITCMD, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, FILES, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_args',
},
{
command='arglocal',
- flags=bit.bor(BANG, FILES, EDITCMD, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, FILES, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_args',
},
{
command='argument',
- flags=bit.bor(BANG, RANGE, NOTADR, COUNT, EXTRA, EDITCMD, ARGOPT, TRLBAR),
+ flags=bit.bor(BANG, RANGE, COUNT, EXTRA, CMDARG, ARGOPT, TRLBAR),
addr_type='ADDR_ARGUMENTS',
func='ex_argument',
},
{
command='ascii',
flags=bit.bor(TRLBAR, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='do_ascii',
},
{
command='autocmd',
- flags=bit.bor(BANG, EXTRA, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, EXTRA, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_autocmd',
},
{
command='augroup',
flags=bit.bor(BANG, WORD1, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_autocmd',
},
{
command='aunmenu',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_menu',
},
{
command='buffer',
- flags=bit.bor(BANG, RANGE, NOTADR, BUFNAME, BUFUNL, COUNT, EXTRA, EDITCMD, TRLBAR),
+ flags=bit.bor(BANG, RANGE, BUFNAME, BUFUNL, COUNT, EXTRA, CMDARG, TRLBAR),
addr_type='ADDR_BUFFERS',
func='ex_buffer',
},
{
command='bNext',
- flags=bit.bor(BANG, RANGE, NOTADR, COUNT, EDITCMD, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, RANGE, COUNT, CMDARG, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_bprevious',
},
{
command='ball',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_buffer_all',
},
{
command='badd',
- flags=bit.bor(NEEDARG, FILE1, EDITCMD, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(NEEDARG, FILE1, CMDARG, TRLBAR, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_edit',
},
{
command='bdelete',
- flags=bit.bor(BANG, RANGE, NOTADR, BUFNAME, COUNT, EXTRA, TRLBAR),
+ flags=bit.bor(BANG, RANGE, BUFNAME, COUNT, EXTRA, TRLBAR),
addr_type='ADDR_BUFFERS',
func='ex_bunload',
},
{
command='behave',
flags=bit.bor(NEEDARG, WORD1, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_behave',
},
{
command='belowright',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='bfirst',
- flags=bit.bor(BANG, RANGE, NOTADR, EDITCMD, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, RANGE, CMDARG, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_brewind',
},
{
command='blast',
- flags=bit.bor(BANG, RANGE, NOTADR, EDITCMD, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, RANGE, CMDARG, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_blast',
},
{
command='bmodified',
- flags=bit.bor(BANG, RANGE, NOTADR, COUNT, EDITCMD, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, RANGE, COUNT, CMDARG, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_bmodified',
},
{
command='bnext',
- flags=bit.bor(BANG, RANGE, NOTADR, COUNT, EDITCMD, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, RANGE, COUNT, CMDARG, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_bnext',
},
{
command='botright',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='bprevious',
- flags=bit.bor(BANG, RANGE, NOTADR, COUNT, EDITCMD, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, RANGE, COUNT, CMDARG, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_bprevious',
},
{
command='brewind',
- flags=bit.bor(BANG, RANGE, NOTADR, EDITCMD, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, RANGE, CMDARG, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_brewind',
},
{
command='break',
flags=bit.bor(TRLBAR, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_break',
},
{
command='breakadd',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_breakadd',
},
{
command='breakdel',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_breakdel',
},
{
command='breaklist',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_breaklist',
},
{
command='browse',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='buffers',
flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='buflist_list',
},
{
command='bufdo',
- flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, NOTADR, DFLALL),
+ flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
addr_type='ADDR_BUFFERS',
func='ex_listdo',
},
{
command='bunload',
- flags=bit.bor(BANG, RANGE, NOTADR, BUFNAME, COUNT, EXTRA, TRLBAR),
+ flags=bit.bor(BANG, RANGE, BUFNAME, COUNT, EXTRA, TRLBAR),
addr_type='ADDR_LOADED_BUFFERS',
func='ex_bunload',
},
{
command='bwipeout',
- flags=bit.bor(BANG, RANGE, NOTADR, BUFNAME, BUFUNL, COUNT, EXTRA, TRLBAR),
+ flags=bit.bor(BANG, RANGE, BUFNAME, BUFUNL, COUNT, EXTRA, TRLBAR),
addr_type='ADDR_BUFFERS',
func='ex_bunload',
},
@@ -291,53 +297,59 @@ return {
},
{
command='cNext',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cnext',
},
{
command='cNfile',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cnext',
},
{
command='cabbrev',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_abbreviate',
},
{
command='cabclear',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_abclear',
},
{
command='cabove',
- flags=bit.bor(RANGE, TRLBAR),
- addr_type='ADDR_OTHER ',
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_UNSIGNED',
func='ex_cbelow',
},
{
command='caddbuffer',
- flags=bit.bor(RANGE, NOTADR, WORD1, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, WORD1, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_cbuffer',
},
{
command='caddexpr',
flags=bit.bor(NEEDARG, WORD1, NOTRLCOM),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_cexpr',
},
{
command='caddfile',
flags=bit.bor(TRLBAR, FILE1),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_cfile',
},
{
+ command='cafter',
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_UNSIGNED',
+ func='ex_cbelow',
+ },
+ {
command='call',
flags=bit.bor(RANGE, NEEDARG, EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
addr_type='ADDR_LINES',
@@ -346,49 +358,55 @@ return {
{
command='catch',
flags=bit.bor(EXTRA, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_catch',
},
{
command='cbuffer',
- flags=bit.bor(BANG, RANGE, NOTADR, WORD1, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, RANGE, WORD1, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_cbuffer',
},
{
+ command='cbefore',
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_UNSIGNED',
+ func='ex_cbelow',
+ },
+ {
command='cbelow',
- flags=bit.bor(RANGE, TRLBAR),
- addr_type='ADDR_OTHER ',
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_UNSIGNED',
func='ex_cbelow',
},
{
command='cbottom',
flags=bit.bor(TRLBAR),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_cbottom',
},
{
command='cc',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_QUICKFIX',
func='ex_cc',
},
{
command='cclose',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_cclose',
},
{
command='cd',
flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_cd',
},
{
command='cdo',
- flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, NOTADR, DFLALL),
- addr_type='ADDR_QUICKFIX',
+ flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
+ addr_type='ADDR_QUICKFIX_VALID',
func='ex_listdo',
},
{
@@ -400,159 +418,159 @@ return {
{
command='cexpr',
flags=bit.bor(NEEDARG, WORD1, NOTRLCOM, BANG),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_cexpr',
},
{
command='cfile',
flags=bit.bor(TRLBAR, FILE1, BANG),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_cfile',
},
-- Even though 'cfdo' is alphabetically lower than 'cfile', it is after
-- 'cfile' in this cmd list to support the existing ":cf" abbreviation.
{
command='cfdo',
- flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, NOTADR, DFLALL),
- addr_type='ADDR_QUICKFIX',
+ flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
+ addr_type='ADDR_QUICKFIX_VALID',
func='ex_listdo',
},
{
command='cfirst',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cc',
},
{
command='cgetfile',
flags=bit.bor(TRLBAR, FILE1),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_cfile',
},
{
command='cgetbuffer',
- flags=bit.bor(RANGE, NOTADR, WORD1, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, WORD1, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_cbuffer',
},
{
command='cgetexpr',
flags=bit.bor(NEEDARG, WORD1, NOTRLCOM),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_cexpr',
},
{
command='chdir',
flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_cd',
},
{
command='changes',
flags=bit.bor(TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_changes',
},
{
command='checkhealth',
flags=bit.bor(EXTRA, TRLBAR),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_checkhealth',
},
{
command='checkpath',
flags=bit.bor(TRLBAR, BANG, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_checkpath',
},
{
command='checktime',
- flags=bit.bor(RANGE, NOTADR, BUFNAME, COUNT, EXTRA, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BUFNAME, COUNT, EXTRA, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_checktime',
},
{
command='chistory',
- flags=bit.bor(TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_UNSIGNED',
func='qf_history',
},
{
command='clist',
flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='qf_list',
},
{
command='clast',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cc',
},
{
command='close',
- flags=bit.bor(BANG, RANGE, NOTADR, COUNT, TRLBAR, CMDWIN),
+ flags=bit.bor(BANG, RANGE, COUNT, TRLBAR, CMDWIN),
addr_type='ADDR_WINDOWS',
func='ex_close',
},
{
command='clearjumps',
flags=bit.bor(TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_clearjumps',
},
{
command='cmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='cmapclear',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_mapclear',
},
{
command='cmenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='cnext',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cnext',
},
{
command='cnewer',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_UNSIGNED',
func='qf_age',
},
{
command='cnfile',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cnext',
},
{
command='cnoremap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='cnoreabbrev',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_abbreviate',
},
{
command='cnoremenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
@@ -563,116 +581,116 @@ return {
},
{
command='colder',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_UNSIGNED',
func='qf_age',
},
{
command='colorscheme',
flags=bit.bor(WORD1, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_colorscheme',
},
{
command='command',
- flags=bit.bor(EXTRA, BANG, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, BANG, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_command',
},
{
command='comclear',
flags=bit.bor(TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_comclear',
},
{
command='compiler',
flags=bit.bor(BANG, TRLBAR, WORD1, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_compiler',
},
{
command='continue',
flags=bit.bor(TRLBAR, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_continue',
},
{
command='confirm',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='const',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_const',
},
{
command='copen',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_copen',
},
{
command='cprevious',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cnext',
},
{
command='cpfile',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_OTHER',
func='ex_cnext',
},
{
command='cquit',
- flags=bit.bor(RANGE, NOTADR, COUNT, ZEROR, TRLBAR, BANG),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, ZEROR, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cquit',
},
{
command='crewind',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cc',
},
{
command='cscope',
flags=bit.bor(EXTRA, NOTRLCOM, XFILE),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_cscope',
},
{
command='cstag',
flags=bit.bor(BANG, TRLBAR, WORD1),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_cstag',
},
{
command='cunmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_unmap',
},
{
command='cunabbrev',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_abbreviate',
},
{
command='cunmenu',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_menu',
},
{
command='cwindow',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_cwindow',
},
{
@@ -684,43 +702,43 @@ return {
{
command='delmarks',
flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_delmarks',
},
{
command='debug',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_debug',
},
{
command='debuggreedy',
- flags=bit.bor(RANGE, NOTADR, ZEROR, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, ZEROR, TRLBAR, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_debuggreedy',
},
{
command='delcommand',
flags=bit.bor(BANG, NEEDARG, WORD1, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_delcommand',
},
{
command='delfunction',
flags=bit.bor(BANG, NEEDARG, WORD1, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_delfunction',
},
{
command='display',
flags=bit.bor(EXTRA, NOTRLCOM, TRLBAR, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_display',
},
{
command='diffupdate',
flags=bit.bor(BANG, TRLBAR),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_diffupdate',
},
{
@@ -732,13 +750,13 @@ return {
{
command='diffoff',
flags=bit.bor(BANG, TRLBAR),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_diffoff',
},
{
command='diffpatch',
flags=bit.bor(EXTRA, FILE1, TRLBAR, MODIFY),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_diffpatch',
},
{
@@ -750,19 +768,19 @@ return {
{
command='diffsplit',
flags=bit.bor(EXTRA, FILE1, TRLBAR),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_diffsplit',
},
{
command='diffthis',
flags=bit.bor(TRLBAR),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_diffthis',
},
{
command='digraphs',
flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_digraphs',
},
{
@@ -780,19 +798,19 @@ return {
{
command='doautocmd',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_doautocmd',
},
{
command='doautoall',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_doautoall',
},
{
command='drop',
- flags=bit.bor(FILES, EDITCMD, NEEDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(FILES, CMDARG, NEEDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_drop',
},
{
@@ -809,110 +827,110 @@ return {
},
{
command='edit',
- flags=bit.bor(BANG, FILE1, EDITCMD, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, FILE1, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_edit',
},
{
command='earlier',
flags=bit.bor(TRLBAR, EXTRA, NOSPC, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_later',
},
{
command='echo',
flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_echo',
},
{
command='echoerr',
flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_execute',
},
{
command='echohl',
flags=bit.bor(EXTRA, TRLBAR, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_echohl',
},
{
command='echomsg',
flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_execute',
},
{
command='echon',
flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_echo',
},
{
command='else',
flags=bit.bor(TRLBAR, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_else',
},
{
command='elseif',
flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_else',
},
{
command='emenu',
- flags=bit.bor(NEEDARG, EXTRA, TRLBAR, NOTRLCOM, RANGE, NOTADR, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(NEEDARG, EXTRA, TRLBAR, NOTRLCOM, RANGE, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_emenu',
},
{
command='endif',
flags=bit.bor(TRLBAR, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_endif',
},
{
command='endfunction',
flags=bit.bor(TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_endfunction',
},
{
command='endfor',
flags=bit.bor(TRLBAR, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_endwhile',
},
{
command='endtry',
flags=bit.bor(TRLBAR, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_endtry',
},
{
command='endwhile',
flags=bit.bor(TRLBAR, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_endwhile',
},
{
command='enew',
flags=bit.bor(BANG, TRLBAR),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_edit',
},
{
command='ex',
- flags=bit.bor(BANG, FILE1, EDITCMD, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, FILE1, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_edit',
},
{
command='execute',
flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_execute',
},
{
@@ -924,55 +942,55 @@ return {
{
command='exusage',
flags=bit.bor(TRLBAR),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_exusage',
},
{
command='file',
- flags=bit.bor(RANGE, NOTADR, ZEROR, BANG, FILE1, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, ZEROR, BANG, FILE1, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_file',
},
{
command='files',
flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='buflist_list',
},
{
command='filetype',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_filetype',
},
{
command='filter',
flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='find',
- flags=bit.bor(RANGE, NOTADR, BANG, FILE1, EDITCMD, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BANG, FILE1, CMDARG, ARGOPT, TRLBAR, NEEDARG),
+ addr_type='ADDR_OTHER',
func='ex_find',
},
{
command='finally',
flags=bit.bor(TRLBAR, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_finally',
},
{
command='finish',
flags=bit.bor(TRLBAR, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_finish',
},
{
command='first',
- flags=bit.bor(EXTRA, BANG, EDITCMD, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_rewind',
},
{
@@ -1008,13 +1026,13 @@ return {
{
command='for',
flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_while',
},
{
command='function',
flags=bit.bor(EXTRA, BANG, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_function',
},
{
@@ -1025,56 +1043,56 @@ return {
},
{
command='goto',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR, SBOXOK, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_goto',
},
{
command='grep',
- flags=bit.bor(RANGE, NOTADR, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
+ addr_type='ADDR_OTHER',
func='ex_make',
},
{
command='grepadd',
- flags=bit.bor(RANGE, NOTADR, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
+ addr_type='ADDR_OTHER',
func='ex_make',
},
{
command='gui',
- flags=bit.bor(BANG, FILES, EDITCMD, ARGOPT, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, FILES, CMDARG, ARGOPT, TRLBAR, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_nogui',
},
{
command='gvim',
- flags=bit.bor(BANG, FILES, EDITCMD, ARGOPT, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, FILES, CMDARG, ARGOPT, TRLBAR, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_nogui',
},
{
command='help',
flags=bit.bor(BANG, EXTRA, NOTRLCOM),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_help',
},
{
command='helpclose',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_helpclose',
},
{
command='helpgrep',
flags=bit.bor(EXTRA, NOTRLCOM, NEEDARG),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_helpgrep',
},
{
command='helptags',
flags=bit.bor(NEEDARG, FILES, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_helptags',
},
{
@@ -1086,19 +1104,19 @@ return {
{
command='highlight',
flags=bit.bor(BANG, EXTRA, TRLBAR, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_highlight',
},
{
command='hide',
- flags=bit.bor(BANG, RANGE, NOTADR, COUNT, EXTRA, TRLBAR),
+ flags=bit.bor(BANG, RANGE, COUNT, EXTRA, TRLBAR),
addr_type='ADDR_WINDOWS',
func='ex_hide',
},
{
command='history',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_history',
},
{
@@ -1109,20 +1127,20 @@ return {
},
{
command='iabbrev',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_abbreviate',
},
{
command='iabclear',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_abclear',
},
{
command='if',
flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_if',
},
{
@@ -1139,44 +1157,44 @@ return {
},
{
command='imap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='imapclear',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_mapclear',
},
{
command='imenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='inoremap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='inoreabbrev',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_abbreviate',
},
{
command='inoremenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='intro',
flags=bit.bor(TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_intro',
},
{
@@ -1193,32 +1211,32 @@ return {
},
{
command='iunmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_unmap',
},
{
command='iunabbrev',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_abbreviate',
},
{
command='iunmenu',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_menu',
},
{
command='join',
- flags=bit.bor(BANG, RANGE, WHOLEFOLD, COUNT, EXFLAGS, TRLBAR, CMDWIN, MODIFY),
+ flags=bit.bor(BANG, RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, MODIFY),
addr_type='ADDR_LINES',
func='ex_join',
},
{
command='jumps',
flags=bit.bor(TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_jumps',
},
{
@@ -1230,133 +1248,145 @@ return {
{
command='keepmarks',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='keepjumps',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='keeppatterns',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='keepalt',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='list',
- flags=bit.bor(RANGE, WHOLEFOLD, COUNT, EXFLAGS, TRLBAR, CMDWIN),
+ flags=bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN),
addr_type='ADDR_LINES',
func='ex_print',
},
{
command='lNext',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cnext',
},
{
command='lNfile',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cnext',
},
{
command='last',
- flags=bit.bor(EXTRA, BANG, EDITCMD, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_last',
},
{
command='labove',
- flags=bit.bor(RANGE, TRLBAR),
- addr_type='ADDR_OTHER ',
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_UNSIGNED',
func='ex_cbelow',
},
{
command='language',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_language',
},
{
command='laddexpr',
flags=bit.bor(NEEDARG, WORD1, NOTRLCOM),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_cexpr',
},
{
command='laddbuffer',
- flags=bit.bor(RANGE, NOTADR, WORD1, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, WORD1, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_cbuffer',
},
{
command='laddfile',
flags=bit.bor(TRLBAR, FILE1),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_cfile',
},
{
+ command='lafter',
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_UNSIGNED',
+ func='ex_cbelow',
+ },
+ {
command='later',
flags=bit.bor(TRLBAR, EXTRA, NOSPC, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_later',
},
{
command='lbuffer',
- flags=bit.bor(BANG, RANGE, NOTADR, WORD1, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, RANGE, WORD1, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_cbuffer',
},
{
+ command='lbefore',
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_UNSIGNED',
+ func='ex_cbelow',
+ },
+ {
command='lbelow',
- flags=bit.bor(RANGE, TRLBAR),
- addr_type='ADDR_OTHER ',
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_UNSIGNED',
func='ex_cbelow',
},
{
command='lbottom',
flags=bit.bor(TRLBAR),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_cbottom',
},
{
command='lcd',
flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_cd',
},
{
command='lchdir',
flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_cd',
},
{
command='lclose',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_cclose',
},
{
command='lcscope',
flags=bit.bor(EXTRA, NOTRLCOM, XFILE),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_cscope',
},
{
command='ldo',
- flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, NOTADR, DFLALL),
- addr_type='ADDR_QUICKFIX',
+ flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
+ addr_type='ADDR_QUICKFIX_VALID',
func='ex_listdo',
},
{
@@ -1368,249 +1398,249 @@ return {
{
command='leftabove',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='let',
flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_let',
},
{
command='lexpr',
flags=bit.bor(NEEDARG, WORD1, NOTRLCOM, BANG),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_cexpr',
},
{
command='lfile',
flags=bit.bor(TRLBAR, FILE1, BANG),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_cfile',
},
-- Even though 'lfdo' is alphabetically lower than 'lfile', it is after
-- 'lfile' in this cmd list to support the existing ":lf" abbreviation.
{
command='lfdo',
- flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, NOTADR, DFLALL),
- addr_type='ADDR_QUICKFIX',
+ flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
+ addr_type='ADDR_QUICKFIX_VALID',
func='ex_listdo',
},
{
command='lfirst',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cc',
},
{
command='lgetfile',
flags=bit.bor(TRLBAR, FILE1),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_cfile',
},
{
command='lgetbuffer',
- flags=bit.bor(RANGE, NOTADR, WORD1, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, WORD1, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_cbuffer',
},
{
command='lgetexpr',
flags=bit.bor(NEEDARG, WORD1, NOTRLCOM),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_cexpr',
},
{
command='lgrep',
- flags=bit.bor(RANGE, NOTADR, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
+ addr_type='ADDR_OTHER',
func='ex_make',
},
{
command='lgrepadd',
- flags=bit.bor(RANGE, NOTADR, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
+ addr_type='ADDR_OTHER',
func='ex_make',
},
{
command='lhelpgrep',
flags=bit.bor(EXTRA, NOTRLCOM, NEEDARG),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_helpgrep',
},
{
command='lhistory',
- flags=bit.bor(TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_UNSIGNED',
func='qf_history',
},
{
command='ll',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_QUICKFIX',
func='ex_cc',
},
{
command='llast',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cc',
},
{
command='llist',
flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='qf_list',
},
{
command='lmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='lmapclear',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_mapclear',
},
{
command='lmake',
flags=bit.bor(BANG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_make',
},
{
command='lnoremap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='lnext',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cnext',
},
{
command='lnewer',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_UNSIGNED',
func='qf_age',
},
{
command='lnfile',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cnext',
},
{
command='loadview',
flags=bit.bor(FILE1, TRLBAR),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_loadview',
},
{
command='loadkeymap',
flags=bit.bor(CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_loadkeymap',
},
{
command='lockmarks',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='lockvar',
flags=bit.bor(BANG, EXTRA, NEEDARG, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_lockvar',
},
{
command='lolder',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_UNSIGNED',
func='qf_age',
},
{
command='lopen',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_copen',
},
{
command='lprevious',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cnext',
},
{
command='lpfile',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_OTHER',
func='ex_cnext',
},
{
command='lrewind',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cc',
},
{
command='ltag',
- flags=bit.bor(NOTADR, TRLBAR, BANG, WORD1),
- addr_type='ADDR_LINES',
+ flags=bit.bor(TRLBAR, BANG, WORD1),
+ addr_type='ADDR_NONE',
func='ex_tag',
},
{
command='lunmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_unmap',
},
{
command='lua',
- flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, RESTRICT),
+ flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN),
addr_type='ADDR_LINES',
func='ex_lua',
},
{
command='luado',
- flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, RESTRICT),
+ flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN),
addr_type='ADDR_LINES',
func='ex_luado',
},
{
command='luafile',
- flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, RESTRICT),
+ flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN),
addr_type='ADDR_LINES',
func='ex_luafile',
},
{
command='lvimgrep',
- flags=bit.bor(RANGE, NOTADR, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
+ addr_type='ADDR_OTHER',
func='ex_vimgrep',
},
{
command='lvimgrepadd',
- flags=bit.bor(RANGE, NOTADR, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
+ addr_type='ADDR_OTHER',
func='ex_vimgrep',
},
{
command='lwindow',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_cwindow',
},
{
command='ls',
flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='buflist_list',
},
{
@@ -1628,43 +1658,43 @@ return {
{
command='make',
flags=bit.bor(BANG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_make',
},
{
command='map',
- flags=bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='mapclear',
flags=bit.bor(EXTRA, BANG, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_mapclear',
},
{
command='marks',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_marks',
},
{
command='match',
- flags=bit.bor(RANGE, NOTADR, EXTRA, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, EXTRA, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_match',
},
{
command='menu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, BANG, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, ZEROR, BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='menutranslate',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_menutranslate',
},
{
@@ -1676,37 +1706,37 @@ return {
{
command='mkexrc',
flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_mkrc',
},
{
command='mksession',
flags=bit.bor(BANG, FILE1, TRLBAR),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_mkrc',
},
{
command='mkspell',
flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_mkspell',
},
{
command='mkvimrc',
flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_mkrc',
},
{
command='mkview',
flags=bit.bor(BANG, FILE1, TRLBAR),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_mkrc',
},
{
command='mode',
flags=bit.bor(WORD1, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_mode',
},
{
@@ -1723,260 +1753,260 @@ return {
},
{
command='next',
- flags=bit.bor(RANGE, NOTADR, BANG, FILES, EDITCMD, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BANG, FILES, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_next',
},
{
command='new',
- flags=bit.bor(BANG, FILE1, RANGE, NOTADR, EDITCMD, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, FILE1, RANGE, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_splitview',
},
{
command='nmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='nmapclear',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_mapclear',
},
{
command='nmenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='nnoremap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='nnoremenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='noremap',
- flags=bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='noautocmd',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='nohlsearch',
flags=bit.bor(TRLBAR, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_nohlsearch',
},
{
command='noreabbrev',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_abbreviate',
},
{
command='noremenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, BANG, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, ZEROR, BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='noswapfile',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='normal',
- flags=bit.bor(RANGE, BANG, EXTRA, NEEDARG, NOTRLCOM, USECTRLV, SBOXOK, CMDWIN),
+ flags=bit.bor(RANGE, BANG, EXTRA, NEEDARG, NOTRLCOM, CTRLV, SBOXOK, CMDWIN),
addr_type='ADDR_LINES',
func='ex_normal',
},
{
command='number',
- flags=bit.bor(RANGE, WHOLEFOLD, COUNT, EXFLAGS, TRLBAR, CMDWIN),
+ flags=bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN),
addr_type='ADDR_LINES',
func='ex_print',
},
{
command='nunmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_unmap',
},
{
command='nunmenu',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_menu',
},
{
command='oldfiles',
flags=bit.bor(BANG, TRLBAR, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_oldfiles',
},
{
command='omap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='omapclear',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_mapclear',
},
{
command='omenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='only',
- flags=bit.bor(BANG, NOTADR, RANGE, COUNT, TRLBAR),
+ flags=bit.bor(BANG, RANGE, COUNT, TRLBAR),
addr_type='ADDR_WINDOWS',
func='ex_only',
},
{
command='onoremap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='onoremenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='options',
flags=bit.bor(TRLBAR),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_options',
},
{
command='ounmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_unmap',
},
{
command='ounmenu',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_menu',
},
{
command='ownsyntax',
flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_ownsyntax',
},
{
command='print',
- flags=bit.bor(RANGE, WHOLEFOLD, COUNT, EXFLAGS, TRLBAR, CMDWIN, SBOXOK),
+ flags=bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, SBOXOK),
addr_type='ADDR_LINES',
func='ex_print',
},
{
command='packadd',
flags=bit.bor(BANG, FILE1, NEEDARG, TRLBAR, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_packadd',
},
{
command='packloadall',
flags=bit.bor(BANG, TRLBAR, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_packloadall',
},
{
command='pclose',
flags=bit.bor(BANG, TRLBAR),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_pclose',
},
{
command='perl',
- flags=bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, SBOXOK, CMDWIN, RESTRICT),
+ flags=bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, SBOXOK, CMDWIN),
addr_type='ADDR_LINES',
func='ex_perl',
},
{
command='perldo',
- flags=bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, CMDWIN, RESTRICT),
+ flags=bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, CMDWIN),
addr_type='ADDR_LINES',
func='ex_perldo',
},
{
command='perlfile',
- flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, RESTRICT),
+ flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN),
addr_type='ADDR_LINES',
func='ex_perlfile',
},
{
command='pedit',
- flags=bit.bor(BANG, FILE1, EDITCMD, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, FILE1, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_pedit',
},
{
command='pop',
- flags=bit.bor(RANGE, NOTADR, BANG, COUNT, TRLBAR, ZEROR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BANG, COUNT, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_tag',
},
{
command='popup',
flags=bit.bor(NEEDARG, EXTRA, BANG, TRLBAR, NOTRLCOM, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_ni',
},
{
command='ppop',
- flags=bit.bor(RANGE, NOTADR, BANG, COUNT, TRLBAR, ZEROR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BANG, COUNT, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_ptag',
},
{
command='preserve',
flags=bit.bor(TRLBAR),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_preserve',
},
{
command='previous',
- flags=bit.bor(EXTRA, RANGE, NOTADR, COUNT, BANG, EDITCMD, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, RANGE, COUNT, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_previous',
},
{
command='profile',
flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_profile',
},
{
command='profdel',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_breakdel',
},
{
@@ -1987,56 +2017,56 @@ return {
},
{
command='ptag',
- flags=bit.bor(RANGE, NOTADR, BANG, WORD1, TRLBAR, ZEROR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BANG, WORD1, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_ptag',
},
{
command='ptNext',
- flags=bit.bor(RANGE, NOTADR, BANG, TRLBAR, ZEROR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_ptag',
},
{
command='ptfirst',
- flags=bit.bor(RANGE, NOTADR, BANG, TRLBAR, ZEROR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_ptag',
},
{
command='ptjump',
flags=bit.bor(BANG, TRLBAR, WORD1),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_ptag',
},
{
command='ptlast',
flags=bit.bor(BANG, TRLBAR),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_ptag',
},
{
command='ptnext',
- flags=bit.bor(RANGE, NOTADR, BANG, TRLBAR, ZEROR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_ptag',
},
{
command='ptprevious',
- flags=bit.bor(RANGE, NOTADR, BANG, TRLBAR, ZEROR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_ptag',
},
{
command='ptrewind',
- flags=bit.bor(RANGE, NOTADR, BANG, TRLBAR, ZEROR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_ptag',
},
{
command='ptselect',
flags=bit.bor(BANG, TRLBAR, WORD1),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_ptag',
},
{
@@ -2048,91 +2078,91 @@ return {
{
command='pwd',
flags=bit.bor(TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_pwd',
},
{
command='python',
- flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, RESTRICT),
+ flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN),
addr_type='ADDR_LINES',
func='ex_python',
},
{
command='pydo',
- flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, RESTRICT),
+ flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN),
addr_type='ADDR_LINES',
func='ex_pydo',
},
{
command='pyfile',
- flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, RESTRICT),
+ flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN),
addr_type='ADDR_LINES',
func='ex_pyfile',
},
{
command='py3',
- flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, RESTRICT),
+ flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN),
addr_type='ADDR_LINES',
func='ex_python3',
},
{
command='py3do',
- flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, RESTRICT),
+ flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN),
addr_type='ADDR_LINES',
func='ex_pydo3',
},
{
command='python3',
- flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, RESTRICT),
+ flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN),
addr_type='ADDR_LINES',
func='ex_python3',
},
{
command='py3file',
- flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, RESTRICT),
+ flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN),
addr_type='ADDR_LINES',
func='ex_py3file',
},
{
command='pyx',
- flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, RESTRICT),
+ flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN),
addr_type='ADDR_LINES',
func='ex_pyx',
},
{
command='pyxdo',
- flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, RESTRICT),
+ flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN),
addr_type='ADDR_LINES',
func='ex_pyxdo',
},
{
command='pythonx',
- flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, RESTRICT),
+ flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN),
addr_type='ADDR_LINES',
func='ex_pyx',
},
{
command='pyxfile',
- flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, RESTRICT),
+ flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN),
addr_type='ADDR_LINES',
func='ex_pyxfile',
},
{
command='quit',
- flags=bit.bor(BANG, RANGE, COUNT, NOTADR, TRLBAR, CMDWIN),
+ flags=bit.bor(BANG, RANGE, COUNT, TRLBAR, CMDWIN),
addr_type='ADDR_WINDOWS',
func='ex_quit',
},
{
command='quitall',
flags=bit.bor(BANG, TRLBAR),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_quit_all',
},
{
command='qall',
flags=bit.bor(BANG, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_quit_all',
},
{
@@ -2144,49 +2174,49 @@ return {
{
command='recover',
flags=bit.bor(BANG, FILE1, TRLBAR),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_recover',
},
{
command='redo',
flags=bit.bor(TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_redo',
},
{
command='redir',
flags=bit.bor(BANG, FILES, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_redir',
},
{
command='redraw',
flags=bit.bor(BANG, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_redraw',
},
{
command='redrawstatus',
flags=bit.bor(BANG, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_redrawstatus',
},
{
command='redrawtabline',
flags=bit.bor(TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_redrawtabline',
},
{
command='registers',
flags=bit.bor(EXTRA, NOTRLCOM, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_display',
},
{
command='resize',
- flags=bit.bor(RANGE, NOTADR, TRLBAR, WORD1, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, TRLBAR, WORD1, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_resize',
},
{
@@ -2198,13 +2228,13 @@ return {
{
command='return',
flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_return',
},
{
command='rewind',
- flags=bit.bor(EXTRA, BANG, EDITCMD, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_rewind',
},
{
@@ -2216,49 +2246,49 @@ return {
{
command='rightbelow',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='rshada',
flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_shada',
},
{
command='runtime',
flags=bit.bor(BANG, NEEDARG, FILES, TRLBAR, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_runtime',
},
{
command='rundo',
flags=bit.bor(NEEDARG, FILE1),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_rundo',
},
{
command='ruby',
- flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, RESTRICT),
+ flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN),
addr_type='ADDR_LINES',
func='ex_ruby',
},
{
command='rubydo',
- flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, RESTRICT),
+ flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN),
addr_type='ADDR_LINES',
func='ex_rubydo',
},
{
command='rubyfile',
- flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, RESTRICT),
+ flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN),
addr_type='ADDR_LINES',
func='ex_rubyfile',
},
{
command='rviminfo',
flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_shada',
},
{
@@ -2269,170 +2299,170 @@ return {
},
{
command='sNext',
- flags=bit.bor(EXTRA, RANGE, NOTADR, COUNT, BANG, EDITCMD, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, RANGE, COUNT, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_previous',
},
{
command='sargument',
- flags=bit.bor(BANG, RANGE, NOTADR, COUNT, EXTRA, EDITCMD, ARGOPT, TRLBAR),
+ flags=bit.bor(BANG, RANGE, COUNT, EXTRA, CMDARG, ARGOPT, TRLBAR),
addr_type='ADDR_ARGUMENTS',
func='ex_argument',
},
{
command='sall',
- flags=bit.bor(BANG, RANGE, NOTADR, COUNT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_all',
},
{
command='sandbox',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='saveas',
- flags=bit.bor(BANG, DFLALL, FILE1, ARGOPT, CMDWIN, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, FILE1, ARGOPT, CMDWIN, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_write',
},
{
command='sbuffer',
- flags=bit.bor(BANG, RANGE, NOTADR, BUFNAME, BUFUNL, COUNT, EXTRA, EDITCMD, TRLBAR),
+ flags=bit.bor(BANG, RANGE, BUFNAME, BUFUNL, COUNT, EXTRA, CMDARG, TRLBAR),
addr_type='ADDR_BUFFERS',
func='ex_buffer',
},
{
command='sbNext',
- flags=bit.bor(RANGE, NOTADR, COUNT, EDITCMD, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, CMDARG, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_bprevious',
},
{
command='sball',
- flags=bit.bor(RANGE, NOTADR, COUNT, EDITCMD, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, CMDARG, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_buffer_all',
},
{
command='sbfirst',
- flags=bit.bor(EDITCMD, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(CMDARG, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_brewind',
},
{
command='sblast',
- flags=bit.bor(EDITCMD, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(CMDARG, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_blast',
},
{
command='sbmodified',
- flags=bit.bor(RANGE, NOTADR, COUNT, EDITCMD, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, CMDARG, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_bmodified',
},
{
command='sbnext',
- flags=bit.bor(RANGE, NOTADR, COUNT, EDITCMD, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, CMDARG, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_bnext',
},
{
command='sbprevious',
- flags=bit.bor(RANGE, NOTADR, COUNT, EDITCMD, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, CMDARG, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_bprevious',
},
{
command='sbrewind',
- flags=bit.bor(EDITCMD, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(CMDARG, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_brewind',
},
{
command='scriptnames',
- flags=bit.bor(BANG, RANGE, NOTADR, COUNT, TRLBAR, CMDWIN),
+ flags=bit.bor(BANG, RANGE, COUNT, TRLBAR, CMDWIN),
addr_type='ADDR_OTHER',
func='ex_scriptnames',
},
{
command='scriptencoding',
flags=bit.bor(WORD1, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_scriptencoding',
},
{
command='scscope',
flags=bit.bor(EXTRA, NOTRLCOM),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_scscope',
},
{
command='set',
flags=bit.bor(TRLBAR, EXTRA, CMDWIN, SBOXOK),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_set',
},
{
command='setfiletype',
flags=bit.bor(TRLBAR, EXTRA, NEEDARG, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_setfiletype',
},
{
command='setglobal',
flags=bit.bor(TRLBAR, EXTRA, CMDWIN, SBOXOK),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_set',
},
{
command='setlocal',
flags=bit.bor(TRLBAR, EXTRA, CMDWIN, SBOXOK),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_set',
},
{
command='sfind',
- flags=bit.bor(BANG, FILE1, RANGE, NOTADR, EDITCMD, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, FILE1, RANGE, CMDARG, ARGOPT, TRLBAR, NEEDARG),
+ addr_type='ADDR_OTHER',
func='ex_splitview',
},
{
command='sfirst',
- flags=bit.bor(EXTRA, BANG, EDITCMD, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_rewind',
},
{
command='simalt',
flags=bit.bor(NEEDARG, WORD1, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_ni',
},
{
command='sign',
- flags=bit.bor(NEEDARG, RANGE, NOTADR, EXTRA, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(NEEDARG, RANGE, EXTRA, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_sign',
},
{
command='silent',
flags=bit.bor(NEEDARG, EXTRA, BANG, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='sleep',
- flags=bit.bor(RANGE, NOTADR, COUNT, EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, RANGE, COUNT, EXTRA, TRLBAR, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_sleep',
},
{
command='slast',
- flags=bit.bor(EXTRA, BANG, EDITCMD, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_last',
},
{
@@ -2443,26 +2473,26 @@ return {
},
{
command='smap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='smapclear',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_mapclear',
},
{
command='smenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='snext',
- flags=bit.bor(RANGE, NOTADR, BANG, FILES, EDITCMD, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BANG, FILES, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_next',
},
{
@@ -2473,20 +2503,20 @@ return {
},
{
command='snoremap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='snoremenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='source',
flags=bit.bor(BANG, FILE1, TRLBAR, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_source',
},
{
@@ -2497,158 +2527,158 @@ return {
},
{
command='split',
- flags=bit.bor(BANG, FILE1, RANGE, NOTADR, EDITCMD, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, FILE1, RANGE, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_splitview',
},
{
command='spellgood',
- flags=bit.bor(BANG, RANGE, NOTADR, NEEDARG, EXTRA, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, RANGE, NEEDARG, EXTRA, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_spell',
},
{
command='spelldump',
flags=bit.bor(BANG, TRLBAR),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_spelldump',
},
{
command='spellinfo',
flags=bit.bor(TRLBAR),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_spellinfo',
},
{
command='spellrepall',
flags=bit.bor(TRLBAR),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_spellrepall',
},
{
command='spellundo',
- flags=bit.bor(BANG, RANGE, NOTADR, NEEDARG, EXTRA, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, RANGE, NEEDARG, EXTRA, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_spell',
},
{
command='spellwrong',
- flags=bit.bor(BANG, RANGE, NOTADR, NEEDARG, EXTRA, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, RANGE, NEEDARG, EXTRA, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_spell',
},
{
command='sprevious',
- flags=bit.bor(EXTRA, RANGE, NOTADR, COUNT, BANG, EDITCMD, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, RANGE, COUNT, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_previous',
},
{
command='srewind',
- flags=bit.bor(EXTRA, BANG, EDITCMD, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_rewind',
},
{
command='stop',
flags=bit.bor(TRLBAR, BANG, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_stop',
},
{
command='stag',
- flags=bit.bor(RANGE, NOTADR, BANG, WORD1, TRLBAR, ZEROR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BANG, WORD1, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_stag',
},
{
command='startinsert',
flags=bit.bor(BANG, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_startinsert',
},
{
command='startgreplace',
flags=bit.bor(BANG, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_startinsert',
},
{
command='startreplace',
flags=bit.bor(BANG, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_startinsert',
},
{
command='stopinsert',
flags=bit.bor(BANG, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_stopinsert',
},
{
command='stjump',
flags=bit.bor(BANG, TRLBAR, WORD1),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_stag',
},
{
command='stselect',
flags=bit.bor(BANG, TRLBAR, WORD1),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_stag',
},
{
command='sunhide',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_buffer_all',
},
{
command='sunmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_unmap',
},
{
command='sunmenu',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_menu',
},
{
command='suspend',
flags=bit.bor(TRLBAR, BANG, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_stop',
},
{
command='sview',
- flags=bit.bor(BANG, FILE1, RANGE, NOTADR, EDITCMD, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, FILE1, RANGE, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_splitview',
},
{
command='swapname',
flags=bit.bor(TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_swapname',
},
{
command='syntax',
flags=bit.bor(EXTRA, NOTRLCOM, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_syntax',
},
{
command='syntime',
flags=bit.bor(NEEDARG, WORD1, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_syntime',
},
{
command='syncbind',
flags=bit.bor(TRLBAR),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_syncbind',
},
{
@@ -2660,121 +2690,121 @@ return {
{
command='tcd',
flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_cd',
},
{
command='tchdir',
flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_cd',
},
{
command='tNext',
- flags=bit.bor(RANGE, NOTADR, BANG, TRLBAR, ZEROR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_tag',
},
{
command='tag',
- flags=bit.bor(RANGE, NOTADR, BANG, WORD1, TRLBAR, ZEROR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BANG, WORD1, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_tag',
},
{
command='tags',
flags=bit.bor(TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='do_tags',
},
{
command='tab',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_TABS',
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='tabclose',
- flags=bit.bor(BANG, RANGE, NOTADR, ZEROR, EXTRA, NOSPC, TRLBAR, CMDWIN),
+ flags=bit.bor(BANG, RANGE, ZEROR, EXTRA, NOSPC, TRLBAR, CMDWIN),
addr_type='ADDR_TABS',
func='ex_tabclose',
},
{
command='tabdo',
- flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM, RANGE, NOTADR, DFLALL),
+ flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
addr_type='ADDR_TABS',
func='ex_listdo',
},
{
command='tabedit',
- flags=bit.bor(BANG, FILE1, RANGE, NOTADR, ZEROR, EDITCMD, ARGOPT, TRLBAR),
+ flags=bit.bor(BANG, FILE1, RANGE, ZEROR, CMDARG, ARGOPT, TRLBAR),
addr_type='ADDR_TABS',
func='ex_splitview',
},
{
command='tabfind',
- flags=bit.bor(BANG, FILE1, RANGE, NOTADR, ZEROR, EDITCMD, ARGOPT, NEEDARG, TRLBAR),
+ flags=bit.bor(BANG, FILE1, RANGE, ZEROR, CMDARG, ARGOPT, NEEDARG, TRLBAR),
addr_type='ADDR_TABS',
func='ex_splitview',
},
{
command='tabfirst',
flags=bit.bor(TRLBAR),
- addr_type='ADDR_TABS',
+ addr_type='ADDR_NONE',
func='ex_tabnext',
},
{
command='tabmove',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, NOSPC, TRLBAR),
+ flags=bit.bor(RANGE, ZEROR, EXTRA, NOSPC, TRLBAR),
addr_type='ADDR_TABS',
func='ex_tabmove',
},
{
command='tablast',
flags=bit.bor(TRLBAR),
- addr_type='ADDR_TABS',
+ addr_type='ADDR_NONE',
func='ex_tabnext',
},
{
command='tabnext',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, NOSPC, TRLBAR),
+ flags=bit.bor(RANGE, ZEROR, EXTRA, NOSPC, TRLBAR),
addr_type='ADDR_TABS',
func='ex_tabnext',
},
{
command='tabnew',
- flags=bit.bor(BANG, FILE1, RANGE, NOTADR, ZEROR, EDITCMD, ARGOPT, TRLBAR),
+ flags=bit.bor(BANG, FILE1, RANGE, ZEROR, CMDARG, ARGOPT, TRLBAR),
addr_type='ADDR_TABS',
func='ex_splitview',
},
{
command='tabonly',
- flags=bit.bor(BANG, RANGE, NOTADR, ZEROR, EXTRA, NOSPC, TRLBAR, CMDWIN),
+ flags=bit.bor(BANG, RANGE, ZEROR, EXTRA, NOSPC, TRLBAR, CMDWIN),
addr_type='ADDR_TABS',
func='ex_tabonly',
},
{
command='tabprevious',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, NOSPC, TRLBAR),
+ flags=bit.bor(RANGE, ZEROR, EXTRA, NOSPC, TRLBAR),
addr_type='ADDR_TABS_RELATIVE',
func='ex_tabnext',
},
{
command='tabNext',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, NOSPC, TRLBAR),
+ flags=bit.bor(RANGE, ZEROR, EXTRA, NOSPC, TRLBAR),
addr_type='ADDR_TABS_RELATIVE',
func='ex_tabnext',
},
{
command='tabrewind',
flags=bit.bor(TRLBAR),
- addr_type='ADDR_TABS',
+ addr_type='ADDR_NONE',
func='ex_tabnext',
},
{
command='tabs',
flags=bit.bor(TRLBAR, CMDWIN),
- addr_type='ADDR_TABS',
+ addr_type='ADDR_NONE',
func='ex_tabs',
},
{
@@ -2798,163 +2828,163 @@ return {
{
command='terminal',
flags=bit.bor(BANG, FILES, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_terminal',
},
{
command='tfirst',
- flags=bit.bor(RANGE, NOTADR, BANG, TRLBAR, ZEROR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_tag',
},
{
command='throw',
flags=bit.bor(EXTRA, NEEDARG, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_throw',
},
{
command='tjump',
flags=bit.bor(BANG, TRLBAR, WORD1),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_tag',
},
{
command='tlast',
flags=bit.bor(BANG, TRLBAR),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_tag',
},
{
command='tmenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='tmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='tmapclear',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_mapclear',
},
{
command='tnext',
- flags=bit.bor(RANGE, NOTADR, BANG, TRLBAR, ZEROR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_tag',
},
{
command='tnoremap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='topleft',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='tprevious',
- flags=bit.bor(RANGE, NOTADR, BANG, TRLBAR, ZEROR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_tag',
},
{
command='trewind',
- flags=bit.bor(RANGE, NOTADR, BANG, TRLBAR, ZEROR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_tag',
},
{
command='try',
flags=bit.bor(TRLBAR, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_try',
},
{
command='tselect',
flags=bit.bor(BANG, TRLBAR, WORD1),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_tag',
},
{
command='tunmenu',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_menu',
},
{
command='tunmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_unmap',
},
{
command='undo',
- flags=bit.bor(RANGE, NOTADR, COUNT, ZEROR, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, ZEROR, TRLBAR, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_undo',
},
{
command='undojoin',
flags=bit.bor(TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_undojoin',
},
{
command='undolist',
flags=bit.bor(TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_undolist',
},
{
command='unabbreviate',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_abbreviate',
},
{
command='unhide',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_buffer_all',
},
{
command='unlet',
flags=bit.bor(BANG, EXTRA, NEEDARG, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_unlet',
},
{
command='unlockvar',
flags=bit.bor(BANG, EXTRA, NEEDARG, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_lockvar',
},
{
command='unmap',
- flags=bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_unmap',
},
{
command='unmenu',
- flags=bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_menu',
},
{
command='unsilent',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
@@ -2972,103 +3002,103 @@ return {
{
command='version',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_version',
},
{
command='verbose',
- flags=bit.bor(NEEDARG, RANGE, NOTADR, EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(NEEDARG, RANGE, EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_wrongmodifier',
},
{
command='vertical',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='visual',
- flags=bit.bor(BANG, FILE1, EDITCMD, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, FILE1, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_edit',
},
{
command='view',
- flags=bit.bor(BANG, FILE1, EDITCMD, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, FILE1, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_edit',
},
{
command='vimgrep',
- flags=bit.bor(RANGE, NOTADR, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
+ addr_type='ADDR_OTHER',
func='ex_vimgrep',
},
{
command='vimgrepadd',
- flags=bit.bor(RANGE, NOTADR, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
+ addr_type='ADDR_OTHER',
func='ex_vimgrep',
},
{
command='viusage',
flags=bit.bor(TRLBAR),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_viusage',
},
{
command='vmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='vmapclear',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_mapclear',
},
{
command='vmenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='vnoremap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='vnew',
- flags=bit.bor(BANG, FILE1, RANGE, NOTADR, EDITCMD, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, FILE1, RANGE, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_splitview',
},
{
command='vnoremenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='vsplit',
- flags=bit.bor(BANG, FILE1, RANGE, NOTADR, EDITCMD, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, FILE1, RANGE, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_splitview',
},
{
command='vunmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_unmap',
},
{
command='vunmenu',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_menu',
},
{
@@ -3079,56 +3109,56 @@ return {
},
{
command='wNext',
- flags=bit.bor(RANGE, WHOLEFOLD, NOTADR, BANG, FILE1, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, WHOLEFOLD, BANG, FILE1, ARGOPT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_wnext',
},
{
command='wall',
flags=bit.bor(BANG, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='do_wqall',
},
{
command='while',
flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_while',
},
{
command='winsize',
flags=bit.bor(EXTRA, NEEDARG, TRLBAR),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_winsize',
},
{
command='wincmd',
- flags=bit.bor(NEEDARG, WORD1, RANGE, NOTADR, CMDWIN),
- addr_type='ADDR_WINDOWS',
+ flags=bit.bor(NEEDARG, WORD1, RANGE, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_wincmd',
},
{
command='windo',
- flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM, RANGE, NOTADR, DFLALL),
+ flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
addr_type='ADDR_WINDOWS',
func='ex_listdo',
},
{
command='winpos',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_ni',
},
{
command='wnext',
- flags=bit.bor(RANGE, NOTADR, BANG, FILE1, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BANG, FILE1, ARGOPT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_wnext',
},
{
command='wprevious',
- flags=bit.bor(RANGE, NOTADR, BANG, FILE1, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, BANG, FILE1, ARGOPT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_wnext',
},
{
@@ -3139,26 +3169,26 @@ return {
},
{
command='wqall',
- flags=bit.bor(BANG, FILE1, ARGOPT, DFLALL, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(BANG, FILE1, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='do_wqall',
},
{
command='wshada',
flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_shada',
},
{
command='wundo',
flags=bit.bor(BANG, NEEDARG, FILE1),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_wundo',
},
{
command='wviminfo',
flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_shada',
},
{
@@ -3170,49 +3200,49 @@ return {
{
command='xall',
flags=bit.bor(BANG, TRLBAR),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='do_wqall',
},
{
command='xmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='xmapclear',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type='ADDR_LINES',
+ addr_type='ADDR_NONE',
func='ex_mapclear',
},
{
command='xmenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='xnoremap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='xnoremenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='xunmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_unmap',
},
{
command='xunmenu',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_menu',
},
{
@@ -3223,7 +3253,7 @@ return {
},
{
command='z',
- flags=bit.bor(RANGE, WHOLEFOLD, EXTRA, EXFLAGS, TRLBAR, CMDWIN),
+ flags=bit.bor(RANGE, WHOLEFOLD, EXTRA, FLAGS, TRLBAR, CMDWIN),
addr_type='ADDR_LINES',
func='ex_z',
},
@@ -3237,7 +3267,7 @@ return {
{
command='#',
enum='CMD_pound',
- flags=bit.bor(RANGE, WHOLEFOLD, COUNT, EXFLAGS, TRLBAR, CMDWIN),
+ flags=bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN),
addr_type='ADDR_LINES',
func='ex_print',
},
@@ -3251,21 +3281,21 @@ return {
{
command='<',
enum='CMD_lshift',
- flags=bit.bor(RANGE, WHOLEFOLD, COUNT, EXFLAGS, TRLBAR, CMDWIN, MODIFY),
+ flags=bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, MODIFY),
addr_type='ADDR_LINES',
func='ex_operators',
},
{
command='=',
enum='CMD_equal',
- flags=bit.bor(RANGE, TRLBAR, DFLALL, EXFLAGS, CMDWIN),
+ flags=bit.bor(RANGE, TRLBAR, DFLALL, FLAGS, CMDWIN),
addr_type='ADDR_LINES',
func='ex_equal',
},
{
command='>',
enum='CMD_rshift',
- flags=bit.bor(RANGE, WHOLEFOLD, COUNT, EXFLAGS, TRLBAR, CMDWIN, MODIFY),
+ flags=bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, MODIFY),
addr_type='ADDR_LINES',
func='ex_operators',
},
@@ -3278,8 +3308,8 @@ return {
},
{
command='Next',
- flags=bit.bor(EXTRA, RANGE, NOTADR, COUNT, BANG, EDITCMD, ARGOPT, TRLBAR),
- addr_type='ADDR_LINES',
+ flags=bit.bor(EXTRA, RANGE, COUNT, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_previous',
},
{
@@ -3290,3 +3320,5 @@ return {
func='ex_substitute',
},
}
+
+return module
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index bde584d27e..c400975108 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -2113,7 +2113,7 @@ void ex_listdo(exarg_T *eap)
}
} else if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo
|| eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) {
- qf_size = qf_get_size(eap);
+ qf_size = qf_get_valid_size(eap);
assert(eap->line1 >= 0);
if (qf_size == 0 || (size_t)eap->line1 > qf_size) {
buf = NULL;
diff --git a/src/nvim/ex_cmds_defs.h b/src/nvim/ex_cmds_defs.h
index 5613ae4b8c..ca84d375ce 100644
--- a/src/nvim/ex_cmds_defs.h
+++ b/src/nvim/ex_cmds_defs.h
@@ -36,35 +36,34 @@
// 4. Add documentation in ../doc/xxx.txt. Add a tag for both the short and
// long name of the command.
-#define RANGE 0x001 // allow a linespecs
-#define BANG 0x002 // allow a ! after the command name
-#define EXTRA 0x004 // allow extra args after command name
-#define XFILE 0x008 // expand wildcards in extra part
-#define NOSPC 0x010 // no spaces allowed in the extra part
-#define DFLALL 0x020 // default file range is 1,$
-#define WHOLEFOLD 0x040 // extend range to include whole fold also
- // when less than two numbers given
-#define NEEDARG 0x080 // argument required
-#define TRLBAR 0x100 // check for trailing vertical bar
-#define REGSTR 0x200 // allow "x for register designation
-#define COUNT 0x400 // allow count in argument, after command
-#define NOTRLCOM 0x800 // no trailing comment allowed
-#define ZEROR 0x1000 // zero line number allowed
-#define USECTRLV 0x2000 // do not remove CTRL-V from argument
-#define NOTADR 0x4000 // number before command is not an address
-#define EDITCMD 0x8000 // allow "+command" argument
-#define BUFNAME 0x10000 // accepts buffer name
-#define BUFUNL 0x20000 // accepts unlisted buffer too
-#define ARGOPT 0x40000 // allow "++opt=val" argument
-#define SBOXOK 0x80000 // allowed in the sandbox
-#define CMDWIN 0x100000 // allowed in cmdline window; when missing
- // disallows editing another buffer when
- // curbuf_lock is set
-#define MODIFY 0x200000 // forbidden in non-'modifiable' buffer
-#define EXFLAGS 0x400000 // allow flags after count in argument
-#define FILES (XFILE | EXTRA) // multiple extra files allowed
-#define WORD1 (EXTRA | NOSPC) // one extra word allowed
-#define FILE1 (FILES | NOSPC) // 1 file allowed, defaults to current file
+#define EX_RANGE 0x001 // allow a linespecs
+#define EX_BANG 0x002 // allow a ! after the command name
+#define EX_EXTRA 0x004 // allow extra args after command name
+#define EX_XFILE 0x008 // expand wildcards in extra part
+#define EX_NOSPC 0x010 // no spaces allowed in the extra part
+#define EX_DFLALL 0x020 // default file range is 1,$
+#define EX_WHOLEFOLD 0x040 // extend range to include whole fold also
+ // when less than two numbers given
+#define EX_NEEDARG 0x080 // argument required
+#define EX_TRLBAR 0x100 // check for trailing vertical bar
+#define EX_REGSTR 0x200 // allow "x for register designation
+#define EX_COUNT 0x400 // allow count in argument, after command
+#define EX_NOTRLCOM 0x800 // no trailing comment allowed
+#define EX_ZEROR 0x1000 // zero line number allowed
+#define EX_CTRLV 0x2000 // do not remove CTRL-V from argument
+#define EX_CMDARG 0x4000 // allow "+command" argument
+#define EX_BUFNAME 0x8000 // accepts buffer name
+#define EX_BUFUNL 0x10000 // accepts unlisted buffer too
+#define EX_ARGOPT 0x20000 // allow "++opt=val" argument
+#define EX_SBOXOK 0x40000 // allowed in the sandbox
+#define EX_CMDWIN 0x80000 // allowed in cmdline window; when missing
+ // disallows editing another buffer when
+ // curbuf_lock is set
+#define EX_MODIFY 0x100000 // forbidden in non-'modifiable' buffer
+#define EX_FLAGS 0x200000 // allow flags after count in argument
+#define EX_FILES (EX_XFILE | EX_EXTRA) // multiple extra files allowed
+#define EX_FILE1 (EX_FILES | EX_NOSPC) // 1 file, defaults to current file
+#define EX_WORD1 (EX_EXTRA | EX_NOSPC) // one extra word allowed
// values for cmd_addr_type
typedef enum {
@@ -75,8 +74,10 @@ typedef enum {
ADDR_BUFFERS, // buffer number
ADDR_TABS, // tab page number
ADDR_TABS_RELATIVE, // Tab page that only relative
+ ADDR_QUICKFIX_VALID, // quickfix list valid entry number
ADDR_QUICKFIX, // quickfix list entry number
- ADDR_OTHER, // something else
+ ADDR_UNSIGNED, // positive count or zero, defaults to 1
+ ADDR_OTHER, // something else, use line number for '$', '%', etc.
ADDR_NONE // no range used
} cmd_addr_T;
@@ -153,7 +154,7 @@ struct exarg {
int addr_count; ///< the number of addresses given
linenr_T line1; ///< the first line number
linenr_T line2; ///< the second line number or count
- int addr_type; ///< type of the count/range
+ cmd_addr_T addr_type; ///< type of the count/range
int flags; ///< extra flags after count: EXFLAG_
char_u *do_ecmd_cmd; ///< +command arg to be used in edited file
linenr_T do_ecmd_lnum; ///< the line number in an edited file
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 003c78b241..ccf7dd0f68 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -1086,7 +1086,10 @@ static int compute_buffer_local_count(int addr_type, int lnum, int offset)
return buf->b_fnum;
}
-static int current_win_nr(win_T *win)
+// Return the window number of "win".
+// When "win" is NULL return the number of windows.
+static int current_win_nr(const win_T *win)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
int nr = 0;
@@ -1163,7 +1166,7 @@ static void get_wincmd_addr_type(char_u *arg, exarg_T *eap)
case 'd':
case Ctrl_D:
// window size or any count
- eap->addr_type = ADDR_LINES; // -V1037
+ eap->addr_type = ADDR_OTHER; // -V1037
break;
case Ctrl_HAT:
@@ -1199,7 +1202,7 @@ static void get_wincmd_addr_type(char_u *arg, exarg_T *eap)
case '=':
case CAR:
// no count
- eap->addr_type = 0;
+ eap->addr_type = ADDR_NONE;
break;
}
}
@@ -1380,6 +1383,10 @@ static char_u * do_one_cmd(char_u **cmdlinep,
if (ea.cmdidx == CMD_wincmd && p != NULL) {
get_wincmd_addr_type(skipwhite(p), &ea);
}
+ // :.cc in quickfix window uses line number
+ if ((ea.cmdidx == CMD_cc || ea.cmdidx == CMD_ll) && bt_quickfix(curbuf)) {
+ ea.addr_type = ADDR_OTHER;
+ }
}
ea.cmd = cmd;
@@ -1411,7 +1418,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
}
if (*ea.cmd == '|' || (exmode_active && ea.line1 != ea.line2)) {
ea.cmdidx = CMD_print;
- ea.argt = RANGE | COUNT | TRLBAR;
+ ea.argt = EX_RANGE | EX_COUNT | EX_TRLBAR;
if ((errormsg = invalid_range(&ea)) == NULL) {
correct_range(&ea);
ex_print(&ea);
@@ -1490,20 +1497,18 @@ static char_u * do_one_cmd(char_u **cmdlinep,
ea.forceit = false;
}
- /*
- * 6. Parse arguments.
- */
+ // 6. Parse arguments. Then check for errors.
if (!IS_USER_CMDIDX(ea.cmdidx)) {
ea.argt = cmdnames[(int)ea.cmdidx].cmd_argt;
}
if (!ea.skip) {
- if (sandbox != 0 && !(ea.argt & SBOXOK)) {
+ if (sandbox != 0 && !(ea.argt & EX_SBOXOK)) {
// Command not allowed in sandbox.
errormsg = (char_u *)_(e_sandbox);
goto doend;
}
- if (!MODIFIABLE(curbuf) && (ea.argt & MODIFY)
+ if (!MODIFIABLE(curbuf) && (ea.argt & EX_MODIFY)
// allow :put in terminals
&& (!curbuf->terminal || ea.cmdidx != CMD_put)) {
/* Command not allowed in non-'modifiable' buffer */
@@ -1511,7 +1516,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
goto doend;
}
- if (text_locked() && !(ea.argt & CMDWIN)
+ if (text_locked() && !(ea.argt & EX_CMDWIN)
&& !IS_USER_CMDIDX(ea.cmdidx)) {
// Command not allowed when editing the command line.
errormsg = (char_u *)_(get_text_locked_msg());
@@ -1522,7 +1527,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
// Do allow ":checktime" (it is postponed).
// Do allow ":edit" (check for an argument later).
// Do allow ":file" with no arguments (check for an argument later).
- if (!(ea.argt & CMDWIN)
+ if (!(ea.argt & EX_CMDWIN)
&& ea.cmdidx != CMD_checktime
&& ea.cmdidx != CMD_edit
&& ea.cmdidx != CMD_file
@@ -1531,14 +1536,14 @@ static char_u * do_one_cmd(char_u **cmdlinep,
goto doend;
}
- if (!ni && !(ea.argt & RANGE) && ea.addr_count > 0) {
- /* no range allowed */
+ if (!ni && !(ea.argt & EX_RANGE) && ea.addr_count > 0) {
+ // no range allowed
errormsg = (char_u *)_(e_norange);
goto doend;
}
}
- if (!ni && !(ea.argt & BANG) && ea.forceit) { /* no <!> allowed */
+ if (!ni && !(ea.argt & EX_BANG) && ea.forceit) { // no <!> allowed
errormsg = (char_u *)_(e_nobang);
goto doend;
}
@@ -1547,12 +1552,10 @@ static char_u * do_one_cmd(char_u **cmdlinep,
* Don't complain about the range if it is not used
* (could happen if line_count is accidentally set to 0).
*/
- if (!ea.skip && !ni) {
- /*
- * If the range is backwards, ask for confirmation and, if given, swap
- * ea.line1 & ea.line2 so it's forwards again.
- * When global command is busy, don't ask, will fail below.
- */
+ if (!ea.skip && !ni && (ea.argt & EX_RANGE)) {
+ // If the range is backwards, ask for confirmation and, if given, swap
+ // ea.line1 & ea.line2 so it's forwards again.
+ // When global command is busy, don't ask, will fail below.
if (!global_busy && ea.line1 > ea.line2) {
if (msg_silent == 0) {
if ((flags & DOCMD_VERBOSE) || exmode_active) {
@@ -1571,12 +1574,14 @@ static char_u * do_one_cmd(char_u **cmdlinep,
goto doend;
}
- if ((ea.argt & NOTADR) && ea.addr_count == 0) /* default is 1, not cursor */
+ if ((ea.addr_type == ADDR_OTHER) && ea.addr_count == 0) {
+ // default is 1, not cursor
ea.line2 = 1;
+ }
correct_range(&ea);
- if (((ea.argt & WHOLEFOLD) || ea.addr_count >= 2) && !global_busy
+ if (((ea.argt & EX_WHOLEFOLD) || ea.addr_count >= 2) && !global_busy
&& ea.addr_type == ADDR_LINES) {
// Put the first line at the start of a closed fold, put the last line
// at the end of a closed fold.
@@ -1610,12 +1615,14 @@ static char_u * do_one_cmd(char_u **cmdlinep,
* Check for "++opt=val" argument.
* Must be first, allow ":w ++enc=utf8 !cmd"
*/
- if (ea.argt & ARGOPT)
- while (ea.arg[0] == '+' && ea.arg[1] == '+')
+ if (ea.argt & EX_ARGOPT) {
+ while (ea.arg[0] == '+' && ea.arg[1] == '+') {
if (getargopt(&ea) == FAIL && !ni) {
errormsg = (char_u *)_(e_invarg);
goto doend;
}
+ }
+ }
if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update) {
if (*ea.arg == '>') { /* append */
@@ -1654,14 +1661,15 @@ static char_u * do_one_cmd(char_u **cmdlinep,
* Check for "+command" argument, before checking for next command.
* Don't do this for ":read !cmd" and ":write !cmd".
*/
- if ((ea.argt & EDITCMD) && !ea.usefilter)
+ if ((ea.argt & EX_CMDARG) && !ea.usefilter) {
ea.do_ecmd_cmd = getargcmd(&ea.arg);
+ }
/*
* Check for '|' to separate commands and '"' to start comments.
* Don't do this for ":read !cmd" and ":write !cmd".
*/
- if ((ea.argt & TRLBAR) && !ea.usefilter) {
+ if ((ea.argt & EX_TRLBAR) && !ea.usefilter) {
separate_nextcmd(&ea);
} else if (ea.cmdidx == CMD_bang
|| ea.cmdidx == CMD_terminal
@@ -1688,12 +1696,13 @@ static char_u * do_one_cmd(char_u **cmdlinep,
}
}
- if ((ea.argt & DFLALL) && ea.addr_count == 0) {
+ if ((ea.argt & EX_DFLALL) && ea.addr_count == 0) {
buf_T *buf;
ea.line1 = 1;
switch (ea.addr_type) {
case ADDR_LINES:
+ case ADDR_OTHER:
ea.line2 = curbuf->b_ml.ml_line_count;
break;
case ADDR_LOADED_BUFFERS:
@@ -1728,24 +1737,27 @@ static char_u * do_one_cmd(char_u **cmdlinep,
ea.line2 = ARGCOUNT;
}
break;
- case ADDR_QUICKFIX:
- ea.line2 = qf_get_size(&ea);
+ case ADDR_QUICKFIX_VALID:
+ ea.line2 = qf_get_valid_size(&ea);
if (ea.line2 == 0) {
ea.line2 = 1;
}
break;
case ADDR_NONE:
- IEMSG(_("INTERNAL: Cannot use DFLALL with ADDR_NONE"));
+ case ADDR_UNSIGNED:
+ case ADDR_QUICKFIX:
+ IEMSG(_("INTERNAL: Cannot use EX_DFLALL "
+ "with ADDR_NONE, ADDR_UNSIGNED or ADDR_QUICKFIX"));
break;
}
}
- /* accept numbered register only when no count allowed (:put) */
- if ((ea.argt & REGSTR)
+ // accept numbered register only when no count allowed (:put)
+ if ((ea.argt & EX_REGSTR)
&& *ea.arg != NUL
/* Do not allow register = for user commands */
&& (!IS_USER_CMDIDX(ea.cmdidx) || *ea.arg != '=')
- && !((ea.argt & COUNT) && ascii_isdigit(*ea.arg))) {
+ && !((ea.argt & EX_COUNT) && ascii_isdigit(*ea.arg))) {
if (valid_yank_reg(*ea.arg, (ea.cmdidx != CMD_put
&& !IS_USER_CMDIDX(ea.cmdidx)))) {
ea.regname = *ea.arg++;
@@ -1759,19 +1771,19 @@ static char_u * do_one_cmd(char_u **cmdlinep,
}
//
- // Check for a count. When accepting a BUFNAME, don't use "123foo" as a
+ // Check for a count. When accepting a EX_BUFNAME, don't use "123foo" as a
// count, it's a buffer name.
///
- if ((ea.argt & COUNT) && ascii_isdigit(*ea.arg)
- && (!(ea.argt & BUFNAME) || *(p = skipdigits(ea.arg)) == NUL
+ if ((ea.argt & EX_COUNT) && ascii_isdigit(*ea.arg)
+ && (!(ea.argt & EX_BUFNAME) || *(p = skipdigits(ea.arg)) == NUL
|| ascii_iswhite(*p))) {
n = getdigits_long(&ea.arg, false, -1);
ea.arg = skipwhite(ea.arg);
- if (n <= 0 && !ni && (ea.argt & ZEROR) == 0) {
+ if (n <= 0 && !ni && (ea.argt & EX_ZEROR) == 0) {
errormsg = (char_u *)_(e_zerocount);
goto doend;
}
- if (ea.argt & NOTADR) { /* e.g. :buffer 2, :sleep 3 */
+ if (ea.addr_type != ADDR_LINES) { // e.g. :buffer 2, :sleep 3
ea.line2 = n;
if (ea.addr_count == 0)
ea.addr_count = 1;
@@ -1780,8 +1792,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
ea.line2 += n - 1;
++ea.addr_count;
// Be vi compatible: no error message for out of range.
- if (ea.addr_type == ADDR_LINES
- && ea.line2 > curbuf->b_ml.ml_line_count) {
+ if (ea.line2 > curbuf->b_ml.ml_line_count) {
ea.line2 = curbuf->b_ml.ml_line_count;
}
}
@@ -1790,16 +1801,17 @@ static char_u * do_one_cmd(char_u **cmdlinep,
/*
* Check for flags: 'l', 'p' and '#'.
*/
- if (ea.argt & EXFLAGS)
+ if (ea.argt & EX_FLAGS) {
get_flags(&ea);
- /* no arguments allowed */
- if (!ni && !(ea.argt & EXTRA) && *ea.arg != NUL
- && *ea.arg != '"' && (*ea.arg != '|' || (ea.argt & TRLBAR) == 0)) {
+ }
+ if (!ni && !(ea.argt & EX_EXTRA) && *ea.arg != NUL
+ && *ea.arg != '"' && (*ea.arg != '|' || (ea.argt & EX_TRLBAR) == 0)) {
+ // no arguments allowed but there is something
errormsg = (char_u *)_(e_trailing);
goto doend;
}
- if (!ni && (ea.argt & NEEDARG) && *ea.arg == NUL) {
+ if (!ni && (ea.argt & EX_NEEDARG) && *ea.arg == NUL) {
errormsg = (char_u *)_(e_argreq);
goto doend;
}
@@ -1828,9 +1840,9 @@ static char_u * do_one_cmd(char_u **cmdlinep,
case CMD_function:
break;
- /* Commands that handle '|' themselves. Check: A command should
- * either have the TRLBAR flag, appear in this list or appear in
- * the list at ":help :bar". */
+ // Commands that handle '|' themselves. Check: A command should
+ // either have the EX_TRLBAR flag, appear in this list or appear in
+ // the list at ":help :bar".
case CMD_aboveleft:
case CMD_and:
case CMD_belowright:
@@ -1901,16 +1913,17 @@ static char_u * do_one_cmd(char_u **cmdlinep,
}
}
- if (ea.argt & XFILE) {
- if (expand_filename(&ea, cmdlinep, &errormsg) == FAIL)
+ if (ea.argt & EX_XFILE) {
+ if (expand_filename(&ea, cmdlinep, &errormsg) == FAIL) {
goto doend;
+ }
}
/*
* Accept buffer name. Cannot be used at the same time with a buffer
* number. Don't do this for a user command.
*/
- if ((ea.argt & BUFNAME) && *ea.arg != NUL && ea.addr_count == 0
+ if ((ea.argt & EX_BUFNAME) && *ea.arg != NUL && ea.addr_count == 0
&& !IS_USER_CMDIDX(ea.cmdidx)
) {
/*
@@ -1926,10 +1939,11 @@ static char_u * do_one_cmd(char_u **cmdlinep,
while (p > ea.arg && ascii_iswhite(p[-1]))
--p;
}
- ea.line2 = buflist_findpat(ea.arg, p, (ea.argt & BUFUNL) != 0,
- FALSE, FALSE);
- if (ea.line2 < 0) /* failed */
+ ea.line2 = buflist_findpat(ea.arg, p, (ea.argt & EX_BUFUNL) != 0,
+ false, false);
+ if (ea.line2 < 0) { // failed
goto doend;
+ }
ea.addr_count = 1;
ea.arg = skipwhite(p);
}
@@ -2325,6 +2339,7 @@ int parse_cmd_address(exarg_T *eap, char_u **errormsg, bool silent)
eap->line1 = eap->line2;
switch (eap->addr_type) {
case ADDR_LINES:
+ case ADDR_OTHER:
// default is current line number
eap->line2 = curwin->w_cursor.lnum;
break;
@@ -2345,9 +2360,13 @@ int parse_cmd_address(exarg_T *eap, char_u **errormsg, bool silent)
eap->line2 = CURRENT_TAB_NR;
break;
case ADDR_TABS_RELATIVE:
+ case ADDR_UNSIGNED:
eap->line2 = 1;
break;
case ADDR_QUICKFIX:
+ eap->line2 = qf_get_cur_idx(eap);
+ break;
+ case ADDR_QUICKFIX_VALID:
eap->line2 = qf_get_cur_valid_idx(eap);
break;
case ADDR_NONE:
@@ -2365,6 +2384,7 @@ int parse_cmd_address(exarg_T *eap, char_u **errormsg, bool silent)
eap->cmd++;
switch (eap->addr_type) {
case ADDR_LINES:
+ case ADDR_OTHER:
eap->line1 = 1;
eap->line2 = curbuf->b_ml.ml_line_count;
break;
@@ -2400,7 +2420,8 @@ int parse_cmd_address(exarg_T *eap, char_u **errormsg, bool silent)
}
break;
case ADDR_TABS_RELATIVE:
- case ADDR_OTHER:
+ case ADDR_UNSIGNED:
+ case ADDR_QUICKFIX:
*errormsg = (char_u *)_(e_invrange);
return FAIL;
case ADDR_ARGUMENTS:
@@ -2411,9 +2432,9 @@ int parse_cmd_address(exarg_T *eap, char_u **errormsg, bool silent)
eap->line2 = ARGCOUNT;
}
break;
- case ADDR_QUICKFIX:
+ case ADDR_QUICKFIX_VALID:
eap->line1 = 1;
- eap->line2 = qf_get_size(eap);
+ eap->line2 = qf_get_valid_size(eap);
if (eap->line2 == 0) {
eap->line2 = 1;
}
@@ -2522,14 +2543,13 @@ static void append_command(char_u *cmd)
*d = NUL;
}
-/*
- * Find an Ex command by its name, either built-in or user.
- * Start of the name can be found at eap->cmd.
- * Returns pointer to char after the command name.
- * "full" is set to TRUE if the whole command name matched.
- * Returns NULL for an ambiguous user command.
- */
+// Find an Ex command by its name, either built-in or user.
+// Start of the name can be found at eap->cmd.
+// Sets eap->cmdidx and returns a pointer to char after the command name.
+// "full" is set to TRUE if the whole command name matched.
+// Returns NULL for an ambiguous user command.
static char_u *find_command(exarg_T *eap, int *full)
+ FUNC_ATTR_NONNULL_ARG(1)
{
int len;
char_u *p;
@@ -2980,7 +3000,7 @@ const char * set_one_cmd_context(
const char *arg = (const char *)skipwhite((const char_u *)p);
// Skip over ++argopt argument
- if ((ea.argt & ARGOPT) && *arg != NUL && strncmp(arg, "++", 2) == 0) {
+ if ((ea.argt & EX_ARGOPT) && *arg != NUL && strncmp(arg, "++", 2) == 0) {
p = arg;
while (*p && !ascii_isspace(*p)) {
MB_PTR_ADV(p);
@@ -3015,9 +3035,9 @@ const char * set_one_cmd_context(
arg = (const char *)skipwhite((const char_u *)arg);
}
- /* Does command allow "+command"? */
- if ((ea.argt & EDITCMD) && !usefilter && *arg == '+') {
- /* Check if we're in the +command */
+ // Does command allow "+command"?
+ if ((ea.argt & EX_CMDARG) && !usefilter && *arg == '+') {
+ // Check if we're in the +command
p = arg + 1;
arg = (const char *)skip_cmd_arg((char_u *)arg, false);
@@ -3033,17 +3053,19 @@ const char * set_one_cmd_context(
* Check for '|' to separate commands and '"' to start comments.
* Don't do this for ":read !cmd" and ":write !cmd".
*/
- if ((ea.argt & TRLBAR) && !usefilter) {
+ if ((ea.argt & EX_TRLBAR) && !usefilter) {
p = arg;
/* ":redir @" is not the start of a comment */
if (ea.cmdidx == CMD_redir && p[0] == '@' && p[1] == '"')
p += 2;
while (*p) {
if (*p == Ctrl_V) {
- if (p[1] != NUL)
- ++p;
- } else if ( (*p == '"' && !(ea.argt & NOTRLCOM))
- || *p == '|' || *p == '\n') {
+ if (p[1] != NUL) {
+ p++;
+ }
+ } else if ((*p == '"' && !(ea.argt & EX_NOTRLCOM))
+ || *p == '|'
+ || *p == '\n') {
if (*(p - 1) != '\\') {
if (*p == '|' || *p == '\n')
return p + 1;
@@ -3054,8 +3076,8 @@ const char * set_one_cmd_context(
}
}
- // no arguments allowed
- if (!(ea.argt & EXTRA) && *arg != NUL && strchr("|\"", *arg) == NULL) {
+ if (!(ea.argt & EX_EXTRA) && *arg != NUL && strchr("|\"", *arg) == NULL) {
+ // no arguments allowed but there is something
return NULL;
}
@@ -3075,7 +3097,7 @@ const char * set_one_cmd_context(
}
}
- if (ea.argt & XFILE) {
+ if (ea.argt & EX_XFILE) {
int c;
int in_quote = false;
const char *bow = NULL; // Beginning of word.
@@ -3496,8 +3518,8 @@ const char * set_one_cmd_context(
case CMD_USER:
case CMD_USER_BUF:
if (context != EXPAND_NOTHING) {
- // XFILE: file names are handled above.
- if (!(ea.argt & XFILE)) {
+ // EX_XFILE: file names are handled above.
+ if (!(ea.argt & EX_XFILE)) {
if (context == EXPAND_MENUS) {
return (const char *)set_context_in_menu_cmd(xp, (char_u *)cmd,
(char_u *)arg, forceit);
@@ -3707,6 +3729,15 @@ char_u *skip_range(
return (char_u *)cmd;
}
+static void addr_error(cmd_addr_T addr_type)
+{
+ if (addr_type == ADDR_NONE) {
+ EMSG(_(e_norange));
+ } else {
+ EMSG(_(e_invrange));
+ }
+}
+
// Get a single EX address
//
// Set ptr to the next character after the part that was interpreted.
@@ -3716,14 +3747,13 @@ char_u *skip_range(
// Return MAXLNUM when no Ex address was found.
static linenr_T get_address(exarg_T *eap,
char_u **ptr,
- cmd_addr_T addr_type_arg,
+ cmd_addr_T addr_type,
int skip, // only skip the address, don't use it
bool silent, // no errors or side effects
int to_other_file, // flag: may jump to other file
int address_count) // 1 for first, >1 after comma
FUNC_ATTR_NONNULL_ALL
{
- const int addr_type = addr_type_arg;
int c;
int i;
long n;
@@ -3741,6 +3771,7 @@ static linenr_T get_address(exarg_T *eap,
++cmd;
switch (addr_type) {
case ADDR_LINES:
+ case ADDR_OTHER:
lnum = curwin->w_cursor.lnum;
break;
case ADDR_WINDOWS:
@@ -3756,13 +3787,17 @@ static linenr_T get_address(exarg_T *eap,
case ADDR_TABS:
lnum = CURRENT_TAB_NR;
break;
- case ADDR_TABS_RELATIVE:
case ADDR_NONE:
- EMSG(_(e_invrange));
+ case ADDR_TABS_RELATIVE:
+ case ADDR_UNSIGNED:
+ addr_error(addr_type);
cmd = NULL;
goto error;
break;
case ADDR_QUICKFIX:
+ lnum = qf_get_cur_idx(eap);
+ break;
+ case ADDR_QUICKFIX_VALID:
lnum = qf_get_cur_valid_idx(eap);
break;
}
@@ -3772,6 +3807,7 @@ static linenr_T get_address(exarg_T *eap,
++cmd;
switch (addr_type) {
case ADDR_LINES:
+ case ADDR_OTHER:
lnum = curbuf->b_ml.ml_line_count;
break;
case ADDR_WINDOWS:
@@ -3796,9 +3832,10 @@ static linenr_T get_address(exarg_T *eap,
case ADDR_TABS:
lnum = LAST_TAB_NR;
break;
- case ADDR_TABS_RELATIVE:
case ADDR_NONE:
- EMSG(_(e_invrange));
+ case ADDR_TABS_RELATIVE:
+ case ADDR_UNSIGNED:
+ addr_error(addr_type);
cmd = NULL;
goto error;
break;
@@ -3808,6 +3845,12 @@ static linenr_T get_address(exarg_T *eap,
lnum = 1;
}
break;
+ case ADDR_QUICKFIX_VALID:
+ lnum = qf_get_valid_size(eap);
+ if (lnum == 0) {
+ lnum = 1;
+ }
+ break;
}
break;
@@ -3817,7 +3860,7 @@ static linenr_T get_address(exarg_T *eap,
goto error;
}
if (addr_type != ADDR_LINES) {
- EMSG(_(e_invaddr));
+ addr_error(addr_type);
cmd = NULL;
goto error;
}
@@ -3845,7 +3888,7 @@ static linenr_T get_address(exarg_T *eap,
case '?': /* '/' or '?' - search */
c = *cmd++;
if (addr_type != ADDR_LINES) {
- EMSG(_(e_invaddr));
+ addr_error(addr_type);
cmd = NULL;
goto error;
}
@@ -3892,7 +3935,7 @@ static linenr_T get_address(exarg_T *eap,
case '\\': /* "\?", "\/" or "\&", repeat search */
++cmd;
if (addr_type != ADDR_LINES) {
- EMSG(_(e_invaddr));
+ addr_error(addr_type);
cmd = NULL;
goto error;
}
@@ -3939,7 +3982,9 @@ static linenr_T get_address(exarg_T *eap,
if (lnum == MAXLNUM) {
switch (addr_type) {
case ADDR_LINES:
- lnum = curwin->w_cursor.lnum; /* "+1" is same as ".+1" */
+ case ADDR_OTHER:
+ // "+1" is same as ".+1"
+ lnum = curwin->w_cursor.lnum;
break;
case ADDR_WINDOWS:
lnum = CURRENT_WIN_NR;
@@ -3958,9 +4003,14 @@ static linenr_T get_address(exarg_T *eap,
lnum = 1;
break;
case ADDR_QUICKFIX:
+ lnum = qf_get_cur_idx(eap);
+ break;
+ case ADDR_QUICKFIX_VALID:
lnum = qf_get_cur_valid_idx(eap);
break;
case ADDR_NONE:
+ case ADDR_UNSIGNED:
+ lnum = 0;
break;
}
}
@@ -4051,12 +4101,11 @@ static char_u *invalid_range(exarg_T *eap)
return (char_u *)_(e_invrange);
}
- if (eap->argt & RANGE) {
- switch(eap->addr_type) {
+ if (eap->argt & EX_RANGE) {
+ switch (eap->addr_type) {
case ADDR_LINES:
- if (!(eap->argt & NOTADR)
- && eap->line2 > curbuf->b_ml.ml_line_count
- + (eap->cmdidx == CMD_diffget)) {
+ if (eap->line2 > (curbuf->b_ml.ml_line_count
+ + (eap->cmdidx == CMD_diffget))) {
return (char_u *)_(e_invrange);
}
break;
@@ -4105,11 +4154,24 @@ static char_u *invalid_range(exarg_T *eap)
}
break;
case ADDR_TABS_RELATIVE:
- // Do nothing
+ case ADDR_OTHER:
+ // Any range is OK.
break;
case ADDR_QUICKFIX:
assert(eap->line2 >= 0);
- if (eap->line2 != 1 && (size_t)eap->line2 > qf_get_size(eap)) {
+ // No error for value that is too big, will use the last entry.
+ if (eap->line2 <= 0) {
+ return (char_u *)_(e_invrange);
+ }
+ break;
+ case ADDR_QUICKFIX_VALID:
+ if ((eap->line2 != 1 && (size_t)eap->line2 > qf_get_valid_size(eap))
+ || eap->line2 < 0) {
+ return (char_u *)_(e_invrange);
+ }
+ break;
+ case ADDR_UNSIGNED:
+ if (eap->line2 < 0) {
return (char_u *)_(e_invrange);
}
break;
@@ -4126,11 +4188,13 @@ static char_u *invalid_range(exarg_T *eap)
*/
static void correct_range(exarg_T *eap)
{
- if (!(eap->argt & ZEROR)) { /* zero in range not allowed */
- if (eap->line1 == 0)
+ if (!(eap->argt & EX_ZEROR)) { // zero in range not allowed
+ if (eap->line1 == 0) {
eap->line1 = 1;
- if (eap->line2 == 0)
+ }
+ if (eap->line2 == 0) {
eap->line2 = 1;
+ }
}
}
@@ -4297,7 +4361,7 @@ int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp)
&& eap->cmdidx != CMD_lmake
&& eap->cmdidx != CMD_make
&& eap->cmdidx != CMD_terminal
- && !(eap->argt & NOSPC)
+ && !(eap->argt & EX_NOSPC)
) {
char_u *l;
#ifdef BACKSLASH_IN_FILENAME
@@ -4338,7 +4402,7 @@ int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp)
* One file argument: Expand wildcards.
* Don't do this with ":r !command" or ":w !command".
*/
- if ((eap->argt & NOSPC) && !eap->usefilter) {
+ if ((eap->argt & EX_NOSPC) && !eap->usefilter) {
// Replace environment variables.
if (has_wildcards) {
/*
@@ -4451,38 +4515,39 @@ void separate_nextcmd(exarg_T *eap)
for (; *p; MB_PTR_ADV(p)) {
if (*p == Ctrl_V) {
- if (eap->argt & (USECTRLV | XFILE))
- ++p; /* skip CTRL-V and next char */
- else
- /* remove CTRL-V and skip next char */
+ if (eap->argt & (EX_CTRLV | EX_XFILE)) {
+ p++; // skip CTRL-V and next char
+ } else {
+ // remove CTRL-V and skip next char
STRMOVE(p, p + 1);
- if (*p == NUL) /* stop at NUL after CTRL-V */
+ }
+ if (*p == NUL) { // stop at NUL after CTRL-V
break;
- }
- /* Skip over `=expr` when wildcards are expanded. */
- else if (p[0] == '`' && p[1] == '=' && (eap->argt & XFILE)) {
+ }
+ } else if (p[0] == '`' && p[1] == '=' && (eap->argt & EX_XFILE)) {
+ // Skip over `=expr` when wildcards are expanded.
p += 2;
(void)skip_expr(&p);
if (*p == NUL) { // stop at NUL after CTRL-V
break;
}
- }
- /* Check for '"': start of comment or '|': next command */
- /* :@" does not start a comment!
- * :redir @" doesn't either. */
- else if ((*p == '"' && !(eap->argt & NOTRLCOM)
- && (eap->cmdidx != CMD_at || p != eap->arg)
- && (eap->cmdidx != CMD_redir
- || p != eap->arg + 1 || p[-1] != '@'))
- || *p == '|' || *p == '\n') {
- /*
- * We remove the '\' before the '|', unless USECTRLV is used
- * AND 'b' is present in 'cpoptions'.
- */
+ } else if (
+ // Check for '"': start of comment or '|': next command */
+ // :@" does not start a comment!
+ // :redir @" doesn't either.
+ (*p == '"'
+ && !(eap->argt & EX_NOTRLCOM)
+ && (eap->cmdidx != CMD_at || p != eap->arg)
+ && (eap->cmdidx != CMD_redir
+ || p != eap->arg + 1 || p[-1] != '@'))
+ || *p == '|'
+ || *p == '\n') {
+ // We remove the '\' before the '|', unless EX_CTRLV is used
+ // AND 'b' is present in 'cpoptions'.
if ((vim_strchr(p_cpo, CPO_BAR) == NULL
- || !(eap->argt & USECTRLV)) && *(p - 1) == '\\') {
- STRMOVE(p - 1, p); /* remove the '\' */
- --p;
+ || !(eap->argt & EX_CTRLV)) && *(p - 1) == '\\') {
+ STRMOVE(p - 1, p); // remove the '\'
+ p--;
} else {
eap->nextcmd = check_nextcmd(p);
*p = NUL;
@@ -4491,8 +4556,9 @@ void separate_nextcmd(exarg_T *eap)
}
}
- if (!(eap->argt & NOTRLCOM)) /* remove trailing spaces */
+ if (!(eap->argt & EX_NOTRLCOM)) { // remove trailing spaces
del_trailing_spaces(eap->arg);
+ }
}
/*
@@ -5181,11 +5247,11 @@ static void uc_list(char_u *name, size_t name_len)
// Special cases
int len = 4;
- if (a & BANG) {
+ if (a & EX_BANG) {
msg_putchar('!');
len--;
}
- if (a & REGSTR) {
+ if (a & EX_REGSTR) {
msg_putchar('"');
len--;
}
@@ -5193,7 +5259,7 @@ static void uc_list(char_u *name, size_t name_len)
msg_putchar('b');
len--;
}
- if (a & TRLBAR) {
+ if (a & EX_TRLBAR) {
msg_putchar('|');
len--;
}
@@ -5215,20 +5281,20 @@ static void uc_list(char_u *name, size_t name_len)
len = 0;
// Arguments
- switch (a & (EXTRA|NOSPC|NEEDARG)) {
+ switch (a & (EX_EXTRA | EX_NOSPC | EX_NEEDARG)) {
case 0:
IObuff[len++] = '0';
break;
- case (EXTRA):
+ case (EX_EXTRA):
IObuff[len++] = '*';
break;
- case (EXTRA|NOSPC):
+ case (EX_EXTRA | EX_NOSPC):
IObuff[len++] = '?';
break;
- case (EXTRA|NEEDARG):
+ case (EX_EXTRA | EX_NEEDARG):
IObuff[len++] = '+';
break;
- case (EXTRA|NOSPC|NEEDARG):
+ case (EX_EXTRA | EX_NOSPC | EX_NEEDARG):
IObuff[len++] = '1';
break;
}
@@ -5238,13 +5304,13 @@ static void uc_list(char_u *name, size_t name_len)
} while (len < 5 - over);
// Address / Range
- if (a & (RANGE|COUNT)) {
- if (a & COUNT) {
+ if (a & (EX_RANGE | EX_COUNT)) {
+ if (a & EX_COUNT) {
// -count=N
snprintf((char *)IObuff + len, IOSIZE, "%" PRId64 "c",
(int64_t)cmd->uc_def);
len += (int)STRLEN(IObuff + len);
- } else if (a & DFLALL) {
+ } else if (a & EX_DFLALL) {
IObuff[len++] = '%';
} else if (cmd->uc_def >= 0) {
// -range=N
@@ -5319,16 +5385,16 @@ static int uc_scan_attr(char_u *attr, size_t len, uint32_t *argt, long *def,
return FAIL;
}
- /* First, try the simple attributes (no arguments) */
- if (STRNICMP(attr, "bang", len) == 0)
- *argt |= BANG;
- else if (STRNICMP(attr, "buffer", len) == 0)
+ // First, try the simple attributes (no arguments)
+ if (STRNICMP(attr, "bang", len) == 0) {
+ *argt |= EX_BANG;
+ } else if (STRNICMP(attr, "buffer", len) == 0) {
*flags |= UC_BUFFER;
- else if (STRNICMP(attr, "register", len) == 0)
- *argt |= REGSTR;
- else if (STRNICMP(attr, "bar", len) == 0)
- *argt |= TRLBAR;
- else {
+ } else if (STRNICMP(attr, "register", len) == 0) {
+ *argt |= EX_REGSTR;
+ } else if (STRNICMP(attr, "bar", len) == 0) {
+ *argt |= EX_TRLBAR;
+ } else {
int i;
char_u *val = NULL;
size_t vallen = 0;
@@ -5346,28 +5412,29 @@ static int uc_scan_attr(char_u *attr, size_t len, uint32_t *argt, long *def,
if (STRNICMP(attr, "nargs", attrlen) == 0) {
if (vallen == 1) {
- if (*val == '0')
- /* Do nothing - this is the default */;
- else if (*val == '1')
- *argt |= (EXTRA | NOSPC | NEEDARG);
- else if (*val == '*')
- *argt |= EXTRA;
- else if (*val == '?')
- *argt |= (EXTRA | NOSPC);
- else if (*val == '+')
- *argt |= (EXTRA | NEEDARG);
- else
+ if (*val == '0') {
+ // Do nothing - this is the default;
+ } else if (*val == '1') {
+ *argt |= (EX_EXTRA | EX_NOSPC | EX_NEEDARG);
+ } else if (*val == '*') {
+ *argt |= EX_EXTRA;
+ } else if (*val == '?') {
+ *argt |= (EX_EXTRA | EX_NOSPC);
+ } else if (*val == '+') {
+ *argt |= (EX_EXTRA | EX_NEEDARG);
+ } else {
goto wrong_nargs;
+ }
} else {
wrong_nargs:
EMSG(_("E176: Invalid number of arguments"));
return FAIL;
}
} else if (STRNICMP(attr, "range", attrlen) == 0) {
- *argt |= RANGE;
- if (vallen == 1 && *val == '%')
- *argt |= DFLALL;
- else if (val != NULL) {
+ *argt |= EX_RANGE;
+ if (vallen == 1 && *val == '%') {
+ *argt |= EX_DFLALL;
+ } else if (val != NULL) {
p = val;
if (*def >= 0) {
two_count:
@@ -5376,7 +5443,7 @@ two_count:
}
*def = getdigits_long(&p, true, 0);
- *argt |= (ZEROR | NOTADR);
+ *argt |= EX_ZEROR;
if (p != val + vallen || vallen == 0) {
invalid_count:
@@ -5384,8 +5451,16 @@ invalid_count:
return FAIL;
}
}
+ // default for -range is using buffer lines
+ if (*addr_type_arg == ADDR_NONE) {
+ *addr_type_arg = ADDR_LINES;
+ }
} else if (STRNICMP(attr, "count", attrlen) == 0) {
- *argt |= (COUNT | ZEROR | RANGE | NOTADR);
+ *argt |= (EX_COUNT | EX_ZEROR | EX_RANGE);
+ // default for -count is using any number
+ if (*addr_type_arg == ADDR_NONE) {
+ *addr_type_arg = ADDR_OTHER;
+ }
if (val != NULL) {
p = val;
@@ -5411,16 +5486,16 @@ invalid_count:
return FAIL;
}
} else if (STRNICMP(attr, "addr", attrlen) == 0) {
- *argt |= RANGE;
+ *argt |= EX_RANGE;
if (val == NULL) {
EMSG(_("E179: argument required for -addr"));
return FAIL;
}
- if (parse_addr_type_arg(val, (int)vallen, argt, addr_type_arg) == FAIL) {
+ if (parse_addr_type_arg(val, (int)vallen, addr_type_arg) == FAIL) {
return FAIL;
}
if (*addr_type_arg != ADDR_LINES) {
- *argt |= (ZEROR | NOTADR);
+ *argt |= EX_ZEROR;
}
} else {
char_u ch = attr[len];
@@ -5447,7 +5522,7 @@ static void ex_command(exarg_T *eap)
int flags = 0;
int compl = EXPAND_NOTHING;
char_u *compl_arg = NULL;
- cmd_addr_T addr_type_arg = ADDR_LINES;
+ cmd_addr_T addr_type_arg = ADDR_NONE;
int has_attr = (eap->arg[0] == '-');
int name_len;
@@ -5724,8 +5799,9 @@ uc_check_code(
/* When specified there is a single argument don't split it.
* Works for ":Cmd %" when % is "a b c". */
- if ((eap->argt & NOSPC) && quote == 2)
+ if ((eap->argt & EX_NOSPC) && quote == 2) {
quote = 1;
+ }
switch (quote) {
case 0: /* No quoting, no splitting */
@@ -6105,8 +6181,7 @@ char_u *get_user_cmd_complete(expand_T *xp, int idx)
/*
* Parse address type argument
*/
-int parse_addr_type_arg(char_u *value, int vallen, uint32_t *argt,
- cmd_addr_T *addr_type_arg)
+int parse_addr_type_arg(char_u *value, int vallen, cmd_addr_T *addr_type_arg)
FUNC_ATTR_NONNULL_ALL
{
int i, a, b;
@@ -6129,9 +6204,6 @@ int parse_addr_type_arg(char_u *value, int vallen, uint32_t *argt,
return FAIL;
}
- if (*addr_type_arg != ADDR_LINES)
- *argt |= NOTADR;
-
return OK;
}
@@ -6169,9 +6241,9 @@ int parse_compl_arg(const char_u *value, int vallen, int *complp,
&& STRNCMP(value, command_complete[i], valend) == 0) {
*complp = i;
if (i == EXPAND_BUFFERS) {
- *argt |= BUFNAME;
+ *argt |= EX_BUFNAME;
} else if (i == EXPAND_DIRECTORIES || i == EXPAND_FILES) {
- *argt |= XFILE;
+ *argt |= EX_XFILE;
}
break;
}
@@ -7423,11 +7495,12 @@ static void ex_read(exarg_T *eap)
int empty = (curbuf->b_ml.ml_flags & ML_EMPTY);
linenr_T lnum;
- if (eap->usefilter) /* :r!cmd */
- do_bang(1, eap, FALSE, FALSE, TRUE);
- else {
- if (u_save(eap->line2, (linenr_T)(eap->line2 + 1)) == FAIL)
+ if (eap->usefilter) { // :r!cmd
+ do_bang(1, eap, false, false, true);
+ } else {
+ if (u_save(eap->line2, (linenr_T)(eap->line2 + 1)) == FAIL) {
return;
+ }
if (*eap->arg == NUL) {
if (check_fname() == FAIL) /* check for no file name */
@@ -7799,7 +7872,7 @@ static void ex_copymove(exarg_T *eap)
* move or copy lines from 'eap->line1'-'eap->line2' to below line 'n'
*/
if (n == MAXLNUM || n < 0 || n > curbuf->b_ml.ml_line_count) {
- EMSG(_(e_invaddr));
+ EMSG(_(e_invrange));
return;
}
@@ -7897,7 +7970,7 @@ static void ex_at(exarg_T *eap)
*/
static void ex_bang(exarg_T *eap)
{
- do_bang(eap->addr_count, eap, eap->forceit, TRUE, TRUE);
+ do_bang(eap->addr_count, eap, eap->forceit, true, true);
}
/*
@@ -8647,6 +8720,7 @@ ssize_t find_cmdline_var(const char_u *src, size_t *usedlen)
* '#' to curwin->w_altfile
* '<cword>' to word under the cursor
* '<cWORD>' to WORD under the cursor
+ * '<cexpr>' to C-expression under the cursor
* '<cfile>' to path name under the cursor
* '<sfile>' to sourced file name
* '<slnum>' to sourced file line number
@@ -9475,16 +9549,16 @@ Dictionary commands_array(buf_T *buf)
PUT(d, "name", STRING_OBJ(cstr_to_string((char *)cmd->uc_name)));
PUT(d, "definition", STRING_OBJ(cstr_to_string((char *)cmd->uc_rep)));
PUT(d, "script_id", INTEGER_OBJ(cmd->uc_script_ctx.sc_sid));
- PUT(d, "bang", BOOLEAN_OBJ(!!(cmd->uc_argt & BANG)));
- PUT(d, "bar", BOOLEAN_OBJ(!!(cmd->uc_argt & TRLBAR)));
- PUT(d, "register", BOOLEAN_OBJ(!!(cmd->uc_argt & REGSTR)));
+ PUT(d, "bang", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_BANG)));
+ PUT(d, "bar", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_TRLBAR)));
+ PUT(d, "register", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_REGSTR)));
- switch (cmd->uc_argt & (EXTRA|NOSPC|NEEDARG)) {
- case 0: arg[0] = '0'; break;
- case(EXTRA): arg[0] = '*'; break;
- case(EXTRA|NOSPC): arg[0] = '?'; break;
- case(EXTRA|NEEDARG): arg[0] = '+'; break;
- case(EXTRA|NOSPC|NEEDARG): arg[0] = '1'; break;
+ switch (cmd->uc_argt & (EX_EXTRA | EX_NOSPC | EX_NEEDARG)) {
+ case 0: arg[0] = '0'; break;
+ case(EX_EXTRA): arg[0] = '*'; break;
+ case(EX_EXTRA | EX_NOSPC): arg[0] = '?'; break;
+ case(EX_EXTRA | EX_NEEDARG): arg[0] = '+'; break;
+ case(EX_EXTRA | EX_NOSPC | EX_NEEDARG): arg[0] = '1'; break;
}
PUT(d, "nargs", STRING_OBJ(cstr_to_string(arg)));
@@ -9495,7 +9569,7 @@ Dictionary commands_array(buf_T *buf)
? NIL : STRING_OBJ(cstr_to_string((char *)cmd->uc_compl_arg)));
Object obj = NIL;
- if (cmd->uc_argt & COUNT) {
+ if (cmd->uc_argt & EX_COUNT) {
if (cmd->uc_def >= 0) {
snprintf(str, sizeof(str), "%" PRId64, (int64_t)cmd->uc_def);
obj = STRING_OBJ(cstr_to_string(str)); // -count=N
@@ -9506,8 +9580,8 @@ Dictionary commands_array(buf_T *buf)
PUT(d, "count", obj);
obj = NIL;
- if (cmd->uc_argt & RANGE) {
- if (cmd->uc_argt & DFLALL) {
+ if (cmd->uc_argt & EX_RANGE) {
+ if (cmd->uc_argt & EX_DFLALL) {
obj = STRING_OBJ(cstr_to_string("%")); // -range=%
} else if (cmd->uc_def >= 0) {
snprintf(str, sizeof(str), "%" PRId64, (int64_t)cmd->uc_def);
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 0f50d5153d..2aa66f6a8c 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -3828,7 +3828,7 @@ static void cmd_cursor_goto(int row, int col)
ui_grid_cursor_goto(grid->handle, row, col);
}
-void gotocmdline(int clr)
+void gotocmdline(bool clr)
{
if (ui_has(kUICmdline)) {
return;
@@ -4780,7 +4780,7 @@ char_u *addstar(char_u *fname, size_t len, int context)
* EXPAND_COMMANDS Cursor is still touching the command, so complete
* it.
* EXPAND_BUFFERS Complete file names for :buf and :sbuf commands.
- * EXPAND_FILES After command with XFILE set, or after setting
+ * EXPAND_FILES After command with EX_XFILE set, or after setting
* with P_EXPAND set. eg :e ^I, :w>>^I
* EXPAND_DIRECTORIES In some cases this is used instead of the latter
* when we know only directories are of interest. eg
diff --git a/src/nvim/generators/gen_ex_cmds.lua b/src/nvim/generators/gen_ex_cmds.lua
index 2574af6218..844661adc3 100644
--- a/src/nvim/generators/gen_ex_cmds.lua
+++ b/src/nvim/generators/gen_ex_cmds.lua
@@ -22,7 +22,10 @@ local defsfname = autodir .. '/ex_cmds_defs.generated.h'
local enumfile = io.open(enumfname, 'w')
local defsfile = io.open(defsfname, 'w')
-local defs = require('ex_cmds')
+local bit = require 'bit'
+local ex_cmds = require('ex_cmds')
+local defs = ex_cmds.cmds
+local flags = ex_cmds.flags
local byte_a = string.byte('a')
local byte_z = string.byte('z')
@@ -51,6 +54,17 @@ static CommandDefinition cmdnames[%u] = {
]], #defs, #defs))
local cmds, cmdidxs1, cmdidxs2 = {}, {}, {}
for _, cmd in ipairs(defs) do
+ if bit.band(cmd.flags, flags.RANGE) == flags.RANGE then
+ assert(cmd.addr_type ~= 'ADDR_NONE',
+ string.format('ex_cmds.lua:%s: Using RANGE with ADDR_NONE\n', cmd.command))
+ else
+ assert(cmd.addr_type == 'ADDR_NONE',
+ string.format('ex_cmds.lua:%s: Missing ADDR_NONE\n', cmd.command))
+ end
+ if bit.band(cmd.flags, flags.DFLALL) == flags.DFLALL then
+ assert(cmd.addr_type ~= 'ADDR_OTHER' and cmd.addr_type ~= 'ADDR_NONE',
+ string.format('ex_cmds.lua:%s: Missing misplaced DFLALL\n', cmd.command))
+ end
local enumname = cmd.enum or ('CMD_' .. cmd.command)
local byte_cmd = cmd.command:sub(1, 1):byte()
if byte_a <= byte_cmd and byte_cmd <= byte_z then
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 31b905e858..3b8f4116b7 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -866,7 +866,6 @@ EXTERN char_u e_failed[] INIT(= N_("E472: Command failed"));
EXTERN char_u e_internal[] INIT(= N_("E473: Internal error"));
EXTERN char_u e_intern2[] INIT(= N_("E685: Internal error: %s"));
EXTERN char_u e_interr[] INIT(= N_("Interrupted"));
-EXTERN char_u e_invaddr[] INIT(= N_("E14: Invalid address"));
EXTERN char_u e_invarg[] INIT(= N_("E474: Invalid argument"));
EXTERN char_u e_invarg2[] INIT(= N_("E475: Invalid argument: %s"));
EXTERN char_u e_invargval[] INIT(= N_("E475: Invalid value for argument %s"));
diff --git a/src/nvim/log.c b/src/nvim/log.c
index 19203a3c2a..324382a0f7 100644
--- a/src/nvim/log.c
+++ b/src/nvim/log.c
@@ -51,7 +51,7 @@ static bool log_try_create(char *fname)
/// Initializes path to log file. Sets $NVIM_LOG_FILE if empty.
///
-/// Tries $NVIM_LOG_FILE, or falls back to $XDG_DATA_HOME/nvim/log. Path to log
+/// Tries $NVIM_LOG_FILE, or falls back to $XDG_CACHE_HOME/nvim/log. Path to log
/// file is cached, so only the first call has effect, unless first call was not
/// successful. Failed initialization indicates either a bug in expand_env()
/// or both $NVIM_LOG_FILE and $HOME environment variables are undefined.
@@ -69,8 +69,16 @@ static bool log_path_init(void)
|| log_file_path[0] == '\0'
|| os_isdir((char_u *)log_file_path)
|| !log_try_create(log_file_path)) {
+ // Make kXDGCacheHome if it does not exist.
+ char *cachehome = get_xdg_home(kXDGCacheHome);
+ char *failed_dir = NULL;
+ bool log_dir_failure = false;
+ if (!os_isdir((char_u *)cachehome)) {
+ log_dir_failure = (os_mkdir_recurse(cachehome, 0700, &failed_dir) != 0);
+ }
+ XFREE_CLEAR(cachehome);
// Invalid $NVIM_LOG_FILE or failed to expand; fall back to default.
- char *defaultpath = stdpaths_user_data_subpath("log", 0, true);
+ char *defaultpath = stdpaths_user_cache_subpath("log");
size_t len = xstrlcpy(log_file_path, defaultpath, size);
xfree(defaultpath);
// Fall back to .nvimlog
@@ -83,6 +91,11 @@ static bool log_path_init(void)
return false;
}
os_setenv(LOG_FILE_ENV, log_file_path, true);
+ if (log_dir_failure) {
+ WLOG("Failed to create directory %s for writing logs: %s",
+ failed_dir, os_strerror(log_dir_failure));
+ }
+ XFREE_CLEAR(failed_dir);
}
return true;
}
@@ -323,4 +336,3 @@ static bool v_do_log_to_file(FILE *log_file, int log_level,
return true;
}
-
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index 344a2387d6..3219c02068 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -5,6 +5,7 @@
#include <lualib.h>
#include <lauxlib.h>
+#include "nvim/version.h"
#include "nvim/misc1.h"
#include "nvim/getchar.h"
#include "nvim/garray.h"
@@ -78,6 +79,17 @@ static void nlua_error(lua_State *const lstate, const char *const msg)
lua_pop(lstate, 1);
}
+/// Return version of current neovim build
+///
+/// @param lstate Lua interpreter state.
+static int nlua_nvim_version(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
+{
+ Dictionary version = version_dict();
+ nlua_push_Dictionary(lstate, version, true);
+ api_free_dictionary(version);
+ return 1;
+}
+
/// Compare two strings, ignoring case
///
/// Expects two values on the stack: compared strings. Returns one of the
@@ -420,6 +432,9 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
// str_byteindex
lua_pushcfunction(lstate, &nlua_str_byteindex);
lua_setfield(lstate, -2, "str_byteindex");
+ // neovim version
+ lua_pushcfunction(lstate, &nlua_nvim_version);
+ lua_setfield(lstate, -2, "version");
// schedule
lua_pushcfunction(lstate, &nlua_schedule);
lua_setfield(lstate, -2, "schedule");
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 8bf745966e..9f71df3a46 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -2044,7 +2044,6 @@ static void usage(void)
mch_msg(_(" -u <config> Use this config file\n"));
mch_msg(_(" -v, --version Print version information\n"));
mch_msg(_(" -V[N][file] Verbose [level][file]\n"));
- mch_msg(_(" -Z Restricted mode\n"));
mch_msg("\n");
mch_msg(_(" --api-info Write msgpack-encoded API metadata to stdout\n"));
mch_msg(_(" --embed Use stdin/stdout as a msgpack-rpc channel\n"));
diff --git a/src/nvim/mark.c b/src/nvim/mark.c
index 1ecfae57ed..73a9c1d1d7 100644
--- a/src/nvim/mark.c
+++ b/src/nvim/mark.c
@@ -777,6 +777,7 @@ void ex_delmarks(exarg_T *eap)
n = i - 'A';
}
namedfm[n].fmark.mark.lnum = 0;
+ namedfm[n].fmark.fnum = 0;
XFREE_CLEAR(namedfm[n].fname);
}
}
@@ -1552,3 +1553,87 @@ void mark_mb_adjustpos(buf_T *buf, pos_T *lp)
}
}
}
+
+
+// Add information about mark 'mname' to list 'l'
+static int add_mark(list_T *l, const char *mname, const pos_T *pos, int bufnr,
+ const char *fname)
+ FUNC_ATTR_NONNULL_ARG(1, 2, 3)
+{
+ if (pos->lnum <= 0) {
+ return OK;
+ }
+
+ dict_T *d = tv_dict_alloc();
+ tv_list_append_dict(l, d);
+
+ list_T *lpos = tv_list_alloc(kListLenMayKnow);
+
+ tv_list_append_number(lpos, bufnr);
+ tv_list_append_number(lpos, pos->lnum);
+ tv_list_append_number(lpos, pos->col + 1);
+ tv_list_append_number(lpos, pos->coladd);
+
+ if (tv_dict_add_str(d, S_LEN("mark"), mname) == FAIL
+ || tv_dict_add_list(d, S_LEN("pos"), lpos) == FAIL
+ || (fname != NULL && tv_dict_add_str(d, S_LEN("file"), fname) == FAIL)) {
+ return FAIL;
+ }
+
+ return OK;
+}
+
+
+/// Get information about marks local to a buffer.
+///
+/// @param[in] buf Buffer to get the marks from
+/// @param[out] l List to store marks
+void get_buf_local_marks(const buf_T *buf, list_T *l)
+ FUNC_ATTR_NONNULL_ALL
+{
+ char mname[3] = "' ";
+
+ // Marks 'a' to 'z'
+ for (int i = 0; i < NMARKS; i++) {
+ mname[1] = (char)('a' + i);
+ add_mark(l, mname, &buf->b_namedm[i].mark, buf->b_fnum, NULL);
+ }
+
+ // Mark '' is a window local mark and not a buffer local mark
+ add_mark(l, "''", &curwin->w_pcmark, curbuf->b_fnum, NULL);
+
+ add_mark(l, "'\"", &buf->b_last_cursor.mark, buf->b_fnum, NULL);
+ add_mark(l, "'[", &buf->b_op_start, buf->b_fnum, NULL);
+ add_mark(l, "']", &buf->b_op_end, buf->b_fnum, NULL);
+ add_mark(l, "'^", &buf->b_last_insert.mark, buf->b_fnum, NULL);
+ add_mark(l, "'.", &buf->b_last_change.mark, buf->b_fnum, NULL);
+ add_mark(l, "'<", &buf->b_visual.vi_start, buf->b_fnum, NULL);
+ add_mark(l, "'>", &buf->b_visual.vi_end, buf->b_fnum, NULL);
+}
+
+/// Get information about global marks ('A' to 'Z' and '0' to '9')
+///
+/// @param[out] l List to store global marks
+void get_global_marks(list_T *l)
+ FUNC_ATTR_NONNULL_ALL
+{
+ char mname[3] = "' ";
+ char *name;
+
+ // Marks 'A' to 'Z' and '0' to '9'
+ for (int i = 0; i < NMARKS + EXTRA_MARKS; i++) {
+ if (namedfm[i].fmark.fnum != 0) {
+ name = (char *)buflist_nr2name(namedfm[i].fmark.fnum, true, true);
+ } else {
+ name = (char *)namedfm[i].fname;
+ }
+ if (name != NULL) {
+ mname[1] = i >= NMARKS ? (char)(i - NMARKS + '0') : (char)(i + 'A');
+
+ add_mark(l, mname, &namedfm[i].fmark.mark, namedfm[i].fmark.fnum, name);
+ if (namedfm[i].fmark.fnum != 0) {
+ xfree(name);
+ }
+ }
+ }
+}
diff --git a/src/nvim/message.c b/src/nvim/message.c
index f94529c687..ba7a667a60 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -890,6 +890,40 @@ char_u *msg_may_trunc(int force, char_u *s)
return s;
}
+void clear_hl_msg(HlMessage *hl_msg)
+{
+ for (size_t i = 0; i < kv_size(*hl_msg); i++) {
+ xfree(kv_A(*hl_msg, i).text.data);
+ }
+ kv_destroy(*hl_msg);
+ *hl_msg = (HlMessage)KV_INITIAL_VALUE;
+}
+
+#define LINE_BUFFER_SIZE 4096
+
+void add_hl_msg_hist(HlMessage hl_msg)
+{
+ // TODO(notomo): support multi highlighted message history
+ size_t pos = 0;
+ char buf[LINE_BUFFER_SIZE];
+ for (uint32_t i = 0; i < kv_size(hl_msg); i++) {
+ HlMessageChunk chunk = kv_A(hl_msg, i);
+ for (uint32_t j = 0; j < chunk.text.size; j++) {
+ if (pos == LINE_BUFFER_SIZE - 1) {
+ buf[pos] = NUL;
+ add_msg_hist((const char *)buf, -1, MSG_HIST, true);
+ pos = 0;
+ continue;
+ }
+ buf[pos++] = chunk.text.data[j];
+ }
+ }
+ if (pos != 0) {
+ buf[pos] = NUL;
+ add_msg_hist((const char *)buf, -1, MSG_HIST, true);
+ }
+}
+
/// @param[in] len Length of s or -1.
static void add_msg_hist(const char *s, int len, int attr, bool multiline)
{
diff --git a/src/nvim/message.h b/src/nvim/message.h
index fdb9bc96ca..377c725fa1 100644
--- a/src/nvim/message.h
+++ b/src/nvim/message.h
@@ -8,6 +8,8 @@
#include "nvim/macros.h"
#include "nvim/types.h"
#include "nvim/grid_defs.h"
+#include "nvim/api/private/defs.h"
+#include "nvim/lib/kvec.h"
/*
* Types of dialogs passed to do_dialog().
@@ -75,6 +77,13 @@
/// Like #MSG_PUTS_ATTR, but if middle part of long messages will be replaced
#define MSG_PUTS_LONG_ATTR(s, a) msg_puts_long_attr((char_u *)(s), (a))
+typedef struct {
+ String text;
+ int attr;
+} HlMessageChunk;
+
+typedef kvec_t(HlMessageChunk) HlMessage;
+
/// Message history for `:messages`
typedef struct msg_hist {
struct msg_hist *next; ///< Next message.
diff --git a/src/nvim/option.c b/src/nvim/option.c
index d43dd9ba15..47b9e9bb07 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -306,7 +306,7 @@ static char *(p_buftype_values[]) = { "nofile", "nowrite", "quickfix",
static char *(p_bufhidden_values[]) = { "hide", "unload", "delete",
"wipe", NULL };
-static char *(p_bs_values[]) = { "indent", "eol", "start", NULL };
+static char *(p_bs_values[]) = { "indent", "eol", "start", "nostop", NULL };
static char *(p_fdm_values[]) = { "manual", "expr", "marker", "indent",
"syntax", "diff", NULL };
static char *(p_fcl_values[]) = { "all", NULL };
@@ -1366,6 +1366,10 @@ int do_set(
*(char_u **)varp = vim_strsave(
(char_u *)"indent,eol,start");
break;
+ case 3:
+ *(char_u **)varp = vim_strsave(
+ (char_u *)"indent,eol,nostop");
+ break;
}
xfree(oldval);
if (origval == oldval) {
@@ -2939,7 +2943,7 @@ ambw_end:
}
} else if (varp == &p_bs) { // 'backspace'
if (ascii_isdigit(*p_bs)) {
- if (*p_bs >'2' || p_bs[1] != NUL) {
+ if (*p_bs > '3' || p_bs[1] != NUL) {
errmsg = e_invarg;
}
} else if (check_opt_strings(p_bs, p_bs_values, true) != OK) {
@@ -6801,15 +6805,15 @@ static int check_opt_wim(void)
}
/// Check if backspacing over something is allowed.
-/// The parameter what is one of the following: whatBS_INDENT, BS_EOL
-/// or BS_START
+/// @param what BS_INDENT, BS_EOL, BS_START, or BS_NOSTOP
bool can_bs(int what)
{
if (what == BS_START && bt_prompt(curbuf)) {
return false;
}
switch (*p_bs) {
- case '2': return true;
+ case '3': return true;
+ case '2': return what != BS_NOSTOP;
case '1': return what != BS_START;
case '0': return false;
}
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index ec2160d365..683afc670e 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -282,9 +282,14 @@ enum {
#define WIM_BUFLASTUSED 8
// arguments for can_bs()
+// each defined char should be unique over all values
+// except for BS_START, that intentionally also matches BS_NOSTOP
+// because BS_NOSTOP behaves exactly the same except it
+// does not stop at the start of the insert point
#define BS_INDENT 'i' // "Indent"
-#define BS_EOL 'o' // "eOl"
+#define BS_EOL 'l' // "eoL"
#define BS_START 's' // "Start"
+#define BS_NOSTOP 'p' // "nostoP
#define LISPWORD_VALUE \
"defun,define,defmacro,set!,lambda,if,case,let,flet,let*,letrec,do,do*,define-syntax,let-syntax,letrec-syntax,destructuring-bind,defpackage,defparameter,defstruct,deftype,defvar,do-all-symbols,do-external-symbols,do-symbols,dolist,dotimes,ecase,etypecase,eval-when,labels,macrolet,multiple-value-bind,multiple-value-call,multiple-value-prog1,multiple-value-setq,prog1,progv,typecase,unless,unwind-protect,when,with-input-from-string,with-open-file,with-open-stream,with-output-to-string,with-package-iterator,define-condition,handler-bind,handler-case,restart-bind,restart-case,with-simple-restart,store-value,use-value,muffle-warning,abort,continue,with-slots,with-slots*,with-accessors,with-accessors*,defclass,defmethod,print-unreadable-object"
diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c
index 879266e3d4..008f5ef63b 100644
--- a/src/nvim/os/env.c
+++ b/src/nvim/os/env.c
@@ -394,13 +394,21 @@ void os_get_hostname(char *hostname, size_t size)
}
/// To get the "real" home directory:
-/// - get value of $HOME
+/// 1. get value of $HOME
+/// 2. if $HOME is not set, try the following
+/// For Windows:
+/// 1. assemble homedir using HOMEDRIVE and HOMEPATH
+/// 2. try os_homedir()
+/// 3. resolve a direct reference to another system variable
+/// 4. guess C drive
/// For Unix:
-/// - go to that directory
-/// - do os_dirname() to get the real name of that directory.
-/// This also works with mounts and links.
-/// Don't do this for Windows, it will change the "current dir" for a drive.
+/// 1. try os_homedir()
+/// 2. go to that directory
+/// This also works with mounts and links.
+/// Don't do this for Windows, it will change the "current dir" for a drive.
+/// 3. fall back to current working directory as a last resort
static char *homedir = NULL;
+static char *os_homedir(void);
void init_homedir(void)
{
@@ -430,7 +438,7 @@ void init_homedir(void)
}
}
if (var == NULL) {
- var = os_getenv("USERPROFILE");
+ var = os_homedir();
}
// Weird but true: $HOME may contain an indirect reference to another
@@ -440,6 +448,7 @@ void init_homedir(void)
const char *p = strchr(var + 1, '%');
if (p != NULL) {
vim_snprintf(os_buf, (size_t)(p - var), "%s", var + 1);
+ var = NULL;
const char *exp = os_getenv(os_buf);
if (exp != NULL && *exp != NUL
&& STRLEN(exp) + STRLEN(p) < MAXPATHL) {
@@ -458,8 +467,12 @@ void init_homedir(void)
}
#endif
- if (var != NULL) {
#ifdef UNIX
+ if (var == NULL) {
+ var = os_homedir();
+ }
+
+ if (var != NULL) {
// Change to the directory and get the actual path. This resolves
// links. Don't do it when we can't return.
if (os_dirname((char_u *)os_buf, MAXPATHL) == OK && os_chdir(os_buf) == 0) {
@@ -470,11 +483,37 @@ void init_homedir(void)
EMSG(_(e_prev_dir));
}
}
+ }
+
+ // Fall back to current working directory if home is not found
+ if ((var == NULL || *var == NUL)
+ && os_dirname((char_u *)os_buf, sizeof(os_buf)) == OK) {
+ var = os_buf;
+ }
#endif
+ if (var != NULL) {
homedir = xstrdup(var);
}
}
+static char homedir_buf[MAXPATHL];
+
+static char *os_homedir(void)
+{
+ homedir_buf[0] = NUL;
+ size_t homedir_size = MAXPATHL;
+ uv_mutex_lock(&mutex);
+ // http://docs.libuv.org/en/v1.x/misc.html#c.uv_os_homedir
+ int ret_value = uv_os_homedir(homedir_buf, &homedir_size);
+ uv_mutex_unlock(&mutex);
+ if (ret_value == 0 && homedir_size < MAXPATHL) {
+ return homedir_buf;
+ }
+ ELOG("uv_os_homedir() failed %d: %s", ret_value, os_strerror(ret_value));
+ homedir_buf[0] = NUL;
+ return NULL;
+}
+
#if defined(EXITFREE)
void free_homedir(void)
diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c
index b7878d9da8..9d6518841a 100644
--- a/src/nvim/os/input.c
+++ b/src/nvim/os/input.c
@@ -393,7 +393,7 @@ static InbufPollResult inbuf_poll(int ms, MultiQueue *events)
prof_inchar_enter();
}
- if ((ms == - 1 || ms > 0) && events == NULL && !input_eof) {
+ if ((ms == - 1 || ms > 0) && events != main_loop.events && !input_eof) {
// The pending input provoked a blocking wait. Do special events now. #6247
blocking = true;
multiqueue_process_events(ch_before_blocking_events);
diff --git a/src/nvim/os/stdpaths.c b/src/nvim/os/stdpaths.c
index 66bc990402..93b8d5ca12 100644
--- a/src/nvim/os/stdpaths.c
+++ b/src/nvim/os/stdpaths.c
@@ -108,6 +108,17 @@ char *get_xdg_home(const XDGVarType idx)
return dir;
}
+/// Return subpath of $XDG_CACHE_HOME
+///
+/// @param[in] fname New component of the path.
+///
+/// @return [allocated] `$XDG_CACHE_HOME/nvim/{fname}`
+char *stdpaths_user_cache_subpath(const char *fname)
+ FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
+{
+ return concat_fnames_realloc(get_xdg_home(kXDGCacheHome), fname, true);
+}
+
/// Return subpath of $XDG_CONFIG_HOME
///
/// @param[in] fname New component of the path.
diff --git a/src/nvim/po/af.po b/src/nvim/po/af.po
index fa6674469c..db44f50a46 100644
--- a/src/nvim/po/af.po
+++ b/src/nvim/po/af.po
@@ -3290,10 +3290,6 @@ msgstr "-o[N]\t\tMaak N vensters oop (verstek: een vir elke lêer)"
#~ msgid " -V[N][file] Verbose [level][file]\n"
#~ msgstr ""
-#, fuzzy
-#~ msgid " -Z Restricted mode\n"
-#~ msgstr " vir twee modusse "
-
#~ msgid " --api-info Write msgpack-encoded API metadata to stdout\n"
#~ msgstr ""
@@ -7473,9 +7469,6 @@ msgstr "E446: Geen lêernaam onder loper"
#~ msgid "-b\t\t\tBinary mode"
#~ msgstr "-b\t\t\tBinêre modus"
-#~ msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-#~ msgstr "-Z\t\t\tBeperkte modus (soos \"rvim\")"
-
#~ msgid "-R\t\t\tReadonly mode (like \"view\")"
#~ msgstr "-R\t\t\tLeesalleen modus (soos \"view\")"
diff --git a/src/nvim/po/ca.po b/src/nvim/po/ca.po
index be4206f36e..6c4d6ddd22 100644
--- a/src/nvim/po/ca.po
+++ b/src/nvim/po/ca.po
@@ -3469,10 +3469,6 @@ msgstr "-y\t\t\tMode senzill (com \"evim\", sense modes)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tMode només lectura (com \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tMode restringit (com \"rvim)"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tNo permet modificar (escriure) fitxers"
diff --git a/src/nvim/po/cs.cp1250.po b/src/nvim/po/cs.cp1250.po
index 5b9f3d3a58..859039eb87 100644
--- a/src/nvim/po/cs.cp1250.po
+++ b/src/nvim/po/cs.cp1250.po
@@ -3547,10 +3547,6 @@ msgstr "-v\t\t\tSnadný režim (stejné jako \"evim\", žádné módy )"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tRežim pouze_pro_ètení (jako \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tOmezený režim (stejné jako \"rvim\")"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tZmìny (ukládání souborù) zakázány"
diff --git a/src/nvim/po/cs.po b/src/nvim/po/cs.po
index 31a90dc514..4d9ad58836 100644
--- a/src/nvim/po/cs.po
+++ b/src/nvim/po/cs.po
@@ -3547,10 +3547,6 @@ msgstr "-v\t\t\tSnadný re¾im (stejné jako \"evim\", ¾ádné módy )"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tRe¾im pouze_pro_ètení (jako \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tOmezený re¾im (stejné jako \"rvim\")"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tZmìny (ukládání souborù) zakázány"
diff --git a/src/nvim/po/da.po b/src/nvim/po/da.po
index f35272810b..7a75425019 100644
--- a/src/nvim/po/da.po
+++ b/src/nvim/po/da.po
@@ -3015,9 +3015,6 @@ msgstr "-y\t\t\tEasy-tilstand (ligesom \"evim\", tilstandsløs)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tSkrivebeskyttet tilstand (ligesom \"view\")"
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tRestriktiv tilstand (ligesom \"rvim\")"
-
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tÆndringer (skrivning af filer) ikke tilladt"
diff --git a/src/nvim/po/de.po b/src/nvim/po/de.po
index a2e04965e5..740e9e5f6a 100644
--- a/src/nvim/po/de.po
+++ b/src/nvim/po/de.po
@@ -2895,10 +2895,6 @@ msgstr "-y\t\t\tLeichter Modus (wie \"evim\", ohne Modi)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tModus ohne Schreibrechte (wie \"view\")"
-#: ../main.c:2186
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tEingeschränkter Modus (wie \"rvim\")"
-
#: ../main.c:2187
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tÄnderungen (beim Schreiben von Dateien) sind nicht erlaubt"
diff --git a/src/nvim/po/en_GB.po b/src/nvim/po/en_GB.po
index 7919fc8946..66cdba6f92 100644
--- a/src/nvim/po/en_GB.po
+++ b/src/nvim/po/en_GB.po
@@ -3368,10 +3368,6 @@ msgstr ""
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr ""
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr ""
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr ""
diff --git a/src/nvim/po/eo.po b/src/nvim/po/eo.po
index 99c46c7275..5480e6a4d8 100644
--- a/src/nvim/po/eo.po
+++ b/src/nvim/po/eo.po
@@ -2989,9 +2989,6 @@ msgstr "-y\t\t\tFacila reÄimo (kiel \"evim\", senreÄima)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tNurlegebla reÄimo (kiel \"view\")"
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tLimigita reÄimo (kiel \"rvim\")"
-
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tÅœanÄoj (skribo al dosieroj) nepermeseblaj"
diff --git a/src/nvim/po/es.po b/src/nvim/po/es.po
index eeea27610d..064484d1a4 100644
--- a/src/nvim/po/es.po
+++ b/src/nvim/po/es.po
@@ -3524,10 +3524,6 @@ msgstr "-y\t\t\tModo fácil (como \"evim\", sin modo)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tModo de solo lectura (como \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tModo restringido (como \"rvim\")"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tModificación de archivos desactivada"
diff --git a/src/nvim/po/fi.po b/src/nvim/po/fi.po
index 4489139cfb..5986a57488 100644
--- a/src/nvim/po/fi.po
+++ b/src/nvim/po/fi.po
@@ -3249,10 +3249,6 @@ msgstr ""
#~ msgstr " kahta tilaa varten "
#, fuzzy
-#~ msgid " -Z Restricted mode\n"
-#~ msgstr " kahta tilaa varten "
-
-#, fuzzy
#~ msgid " -m Modifications (writing files) not allowed\n"
#~ msgstr "-m\t\t\tMuokkaukset (kirjoittaminen tiedostoon) pois käytöstä"
@@ -6961,9 +6957,6 @@ msgstr "Lista tai luku tarvitaan"
#~ msgid "-b\t\t\tBinary mode"
#~ msgstr "-b\t\t\tBinääritila"
-#~ msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-#~ msgstr "-Z\t\t\tRajoitettu tila (kuten rvimillä)"
-
#~ msgid "-R\t\t\tReadonly mode (like \"view\")"
#~ msgstr "-R\t\t\tKirjoitussuojattu tila (kuten view'lla)"
diff --git a/src/nvim/po/fr.po b/src/nvim/po/fr.po
index bb60649c91..5f1ca2fec5 100644
--- a/src/nvim/po/fr.po
+++ b/src/nvim/po/fr.po
@@ -3231,9 +3231,6 @@ msgstr "-y\t\tMode facile (comme \"evim\", vim sans modes)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\tMode lecture seule (comme \"view\")"
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\tMode restreint (comme \"rvim\")"
-
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\tInterdire l'enregistrement des fichiers"
diff --git a/src/nvim/po/ga.po b/src/nvim/po/ga.po
index 1104b31c32..bad01d592a 100644
--- a/src/nvim/po/ga.po
+++ b/src/nvim/po/ga.po
@@ -3022,9 +3022,6 @@ msgstr "-y\t\t\tMód éasca (mar \"evim\", gan mhóid)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tMód inléite amháin (mar \"view\")"
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tMód srianta (mar \"rvim\")"
-
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tNí cheadaítear athruithe (.i. scríobh na gcomhad)"
diff --git a/src/nvim/po/it.po b/src/nvim/po/it.po
index 511f910b71..dfabc4bee0 100644
--- a/src/nvim/po/it.po
+++ b/src/nvim/po/it.po
@@ -3510,10 +3510,6 @@ msgstr "-y\t\t\tModalità Facile (come \"evim\", senza modalità)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tModalità Sola Lettura (come \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tModalità Ristretta (come \"rvim\")"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tRiscritture del file non permesse"
diff --git a/src/nvim/po/ja.euc-jp.po b/src/nvim/po/ja.euc-jp.po
index 523e9ca4e3..e2cf68f016 100644
--- a/src/nvim/po/ja.euc-jp.po
+++ b/src/nvim/po/ja.euc-jp.po
@@ -3024,9 +3024,6 @@ msgstr "-y\t\t\t¥¤¡¼¥¸¡¼¥â¡¼¥É (\"evim\" ¤ÈƱ¤¸¡¢¥â¡¼¥É̵)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tÆÉ¹þÀìÍѥ⡼¥É (\"view\" ¤ÈƱ¤¸)"
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tÀ©¸Â¥â¡¼¥É (\"rvim\" ¤ÈƱ¤¸)"
-
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tÊѹ¹ (¥Õ¥¡¥¤¥ëÊݸ»þ) ¤ò¤Ç¤­¤Ê¤¤¤è¤¦¤Ë¤¹¤ë"
diff --git a/src/nvim/po/ja.po b/src/nvim/po/ja.po
index 5a69d0c5bf..85a45cd171 100644
--- a/src/nvim/po/ja.po
+++ b/src/nvim/po/ja.po
@@ -3024,9 +3024,6 @@ msgstr "-y\t\t\tイージーモード (\"evim\" ã¨åŒã˜ã€ãƒ¢ãƒ¼ãƒ‰ç„¡)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\t読込専用モード (\"view\" ã¨åŒã˜)"
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\t制é™ãƒ¢ãƒ¼ãƒ‰ (\"rvim\" ã¨åŒã˜)"
-
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\t変更 (ファイルä¿å­˜æ™‚) ã‚’ã§ããªã„よã†ã«ã™ã‚‹"
diff --git a/src/nvim/po/ko.UTF-8.po b/src/nvim/po/ko.UTF-8.po
index 128b238f8b..b99c22caeb 100644
--- a/src/nvim/po/ko.UTF-8.po
+++ b/src/nvim/po/ko.UTF-8.po
@@ -3438,10 +3438,6 @@ msgstr "-y\t\t\t쉬운 ìƒíƒœ (\"evim\"ê³¼ ê°™ìŒ, modeless)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tì½ê¸° ì „ìš© ìƒíƒœ (\"view\"와 ê°™ìŒ)"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tì œí•œëœ ìƒíƒœ (\"rvim\"ê³¼ ê°™ìŒ)"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\t수정(íŒŒì¼ ì“°ê¸°)ì´ í—ˆìš©ë˜ì§€ 않ìŒ"
diff --git a/src/nvim/po/nb.po b/src/nvim/po/nb.po
index 34617ccf18..2285d755cf 100644
--- a/src/nvim/po/nb.po
+++ b/src/nvim/po/nb.po
@@ -3452,10 +3452,6 @@ msgstr "-y\t\t\tLett modus (som \"evim\", uten modus)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tSkrivebeskyttet modus (som \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tBegrenset modus (som \"rvim\")"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tModifisering (lagring av filer) ikke tillatt"
diff --git a/src/nvim/po/nl.po b/src/nvim/po/nl.po
index 30f34508f5..00d113c83c 100644
--- a/src/nvim/po/nl.po
+++ b/src/nvim/po/nl.po
@@ -3449,10 +3449,6 @@ msgstr "-y\t\t\tEenvoudige modus (zoals \"evim\", zonder modus)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tAlleen-lezen modus (zoals \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tBeperkte modus (zoals \"rvim\")"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tAanpassingen (bestanden opslaan) niet toegestaan"
diff --git a/src/nvim/po/no.po b/src/nvim/po/no.po
index 34617ccf18..2285d755cf 100644
--- a/src/nvim/po/no.po
+++ b/src/nvim/po/no.po
@@ -3452,10 +3452,6 @@ msgstr "-y\t\t\tLett modus (som \"evim\", uten modus)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tSkrivebeskyttet modus (som \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tBegrenset modus (som \"rvim\")"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tModifisering (lagring av filer) ikke tillatt"
diff --git a/src/nvim/po/pl.UTF-8.po b/src/nvim/po/pl.UTF-8.po
index f5c452e924..5f1779d1bd 100644
--- a/src/nvim/po/pl.UTF-8.po
+++ b/src/nvim/po/pl.UTF-8.po
@@ -3417,10 +3417,6 @@ msgstr "-y\t\t\tTryb łatwy (jak \"evim\", bez trybów)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tTryb wyłącznie do odczytu (jak \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tTryb ograniczenia (jak \"rvim\")"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tModyfikacje (zapisywanie plików) niedozwolone"
diff --git a/src/nvim/po/pt_BR.po b/src/nvim/po/pt_BR.po
index 4f39cb5bdb..533d916de1 100644
--- a/src/nvim/po/pt_BR.po
+++ b/src/nvim/po/pt_BR.po
@@ -6229,10 +6229,6 @@ msgstr "-y\t\t\tModo fácil (como \"evim\", o Vim não modal)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tmodo somente-leitura (como \"view\")"
-#: ../main.c:2186
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tmodo restrito (como \"rvim\")"
-
#: ../main.c:2187
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tNão permitir alterações (gravação de arquivos)"
diff --git a/src/nvim/po/ru.po b/src/nvim/po/ru.po
index 62f892d257..3a96ece2fb 100644
--- a/src/nvim/po/ru.po
+++ b/src/nvim/po/ru.po
@@ -3442,10 +3442,6 @@ msgstr "-y\t\t\tПроÑтой режим (как \"evim\", безрежимны
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tТолько Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ (как \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tОграниченный режим (как \"rvim\")"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tБез возможноÑти ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ð¹ (запиÑи файлов)"
diff --git a/src/nvim/po/sk.cp1250.po b/src/nvim/po/sk.cp1250.po
index ced343bf6b..ff95c68a12 100644
--- a/src/nvim/po/sk.cp1250.po
+++ b/src/nvim/po/sk.cp1250.po
@@ -3450,10 +3450,6 @@ msgstr "-y\t\t\tJednoduchý mód (rovnaké ako \"evim\", bezmódový)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tMód iba pre èítanie (ako \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tObmedzený mód (rovnaké ako \"rvim\")"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tZmeny (ukladanie súborov) zakázané"
diff --git a/src/nvim/po/sk.po b/src/nvim/po/sk.po
index 66b3d5abb1..d35622726f 100644
--- a/src/nvim/po/sk.po
+++ b/src/nvim/po/sk.po
@@ -3450,10 +3450,6 @@ msgstr "-y\t\t\tJednoduchý mód (rovnaké ako \"evim\", bezmódový)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tMód iba pre èítanie (ako \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tObmedzený mód (rovnaké ako \"rvim\")"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tZmeny (ukladanie súborov) zakázané"
diff --git a/src/nvim/po/sr.po b/src/nvim/po/sr.po
index 4c157658e5..a93a2ec584 100644
--- a/src/nvim/po/sr.po
+++ b/src/nvim/po/sr.po
@@ -3028,9 +3028,6 @@ msgstr "-y\t\t\tEasy режим (као \"evim\", безрежимни)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tReadonly режим (као \"view\")"
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tRestricted режим (као \"rvim\")"
-
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tИзмене (упиÑивање датотека) ниÑу дозвољене"
diff --git a/src/nvim/po/sv.po b/src/nvim/po/sv.po
index db7bada888..d50c9d695d 100644
--- a/src/nvim/po/sv.po
+++ b/src/nvim/po/sv.po
@@ -5735,10 +5735,6 @@ msgstr "-y\t\t\tLätt läge (som \"evim\", lägeslös)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tSkrivskyddat läge (som \"view\")"
-#: ../main.c:2186
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tBegränsat läge (som \"rvim\")"
-
#: ../main.c:2187
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tModifieringar (skriva filer) inte tillåtet"
diff --git a/src/nvim/po/uk.po b/src/nvim/po/uk.po
index 604e425bd0..f0ae154648 100644
--- a/src/nvim/po/uk.po
+++ b/src/nvim/po/uk.po
@@ -14,7 +14,7 @@ msgid ""
msgstr ""
"Project-Id-Version: vim 7.4\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-08-23 18:45+0300\n"
+"POT-Creation-Date: 2021-01-18 17:46+0200\n"
"PO-Revision-Date: 2020-08-23 20:19+0300\n"
"Last-Translator: Ðнатолій Сахнік <sakhnik@gmail.com>\n"
"Language-Team: Ukrainian\n"
@@ -23,6 +23,67 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
+msgid "--Deleted--"
+msgstr "--Знищено--"
+
+#, c-format
+msgid "auto-removing autocommand: %s <buffer=%d>"
+msgstr "Ðвтоматичне Ð·Ð½Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð°Ð²Ñ‚Ð¾ÐºÐ¾Ð¼Ð°Ð½Ð´Ð¸: %s <буфер=%d>"
+
+#, c-format
+msgid "E367: No such group: \"%s\""
+msgstr "E367: Ðемає такої групи: «%s»"
+
+msgid "E936: Cannot delete the current group"
+msgstr "E936: Ðе вдалоÑÑ Ð·Ð½Ð¸Ñ‰Ð¸Ñ‚Ð¸ цю групу"
+
+msgid "W19: Deleting augroup that is still in use"
+msgstr "W19: Ð—Ð½Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð°Ð²Ñ‚Ð¾Ð³Ñ€ÑƒÐ¿Ð¸, Ñка вÑе ще викориÑтовуєтьÑÑ"
+
+#, c-format
+msgid "E215: Illegal character after *: %s"
+msgstr "E215: Ðедозволений Ñимвол піÑÐ»Ñ *: %s"
+
+#, c-format
+msgid "E216: No such event: %s"
+msgstr "E216: Ðемає такої події: %s"
+
+#, c-format
+msgid "E216: No such group or event: %s"
+msgstr "E216: Ðемає такої групи чи події: %s"
+
+msgid ""
+"\n"
+"--- Autocommands ---"
+msgstr ""
+"\n"
+"--- Ðвтокоманди ---"
+
+#, c-format
+msgid "E680: <buffer=%d>: invalid buffer number "
+msgstr "E680: <буфер=%d>: некоректний номер буфера "
+
+msgid "E217: Can't execute autocommands for ALL events"
+msgstr "E217: Ðе можу виконувати автокоманди Ð´Ð»Ñ Ð£Ð¡Ð†Ð¥ подій"
+
+msgid "No matching autocommands"
+msgstr "Ðемає відповідних автокоманд"
+
+msgid "E218: autocommand nesting too deep"
+msgstr "E218: Забагато вкладених автокоманд"
+
+#, c-format
+msgid "%s Autocommands for \"%s\""
+msgstr "%s Ðвтокоманди Ð´Ð»Ñ Â«%s»"
+
+#, c-format
+msgid "Executing %s"
+msgstr "ВиконуєтьÑÑ %s"
+
+#, c-format
+msgid "autocommand %s"
+msgstr "автокоманда %s"
+
msgid "[Location List]"
msgstr "[СпиÑок міÑць]"
@@ -95,9 +156,15 @@ msgid ""
"E89: No write since last change for buffer %<PRId64> (add ! to override)"
msgstr "E89: Буфер %<PRId64> має зміни (! щоб не зважати)"
+msgid "E948: Job still running (add ! to end the job)"
+msgstr "E948: Задача вÑе ще виконуєтьÑÑ (! щоб закінчити)"
+
msgid "E37: No write since last change (add ! to override)"
msgstr "E37: Зміни не було запиÑано (! щоб не зважати)"
+msgid "E948: Job still running"
+msgstr "E948: Задача вÑе ще виконуєтьÑÑ"
+
msgid "E37: No write since last change"
msgstr "E37: Ðе запиÑано піÑÐ»Ñ Ð¾Ñтанніх змін"
@@ -465,6 +532,10 @@ msgid "E957: Invalid window number"
msgstr "E957: Ðекоректний номер вікна"
#, c-format
+msgid "E940: Cannot lock or unlock variable %s"
+msgstr "E940: Ðеможливо заблокувати чи розблокувати змінну %s"
+
+#, c-format
msgid "E734: Wrong variable type for %s="
msgstr "E734: Ðеправильний тип змінної Ð´Ð»Ñ %s="
@@ -544,10 +615,6 @@ msgstr "E690: Пропущено «in» піÑÐ»Ñ :for"
msgid "E108: No such variable: \"%s\""
msgstr "E108: Змінної немає: «%s»"
-#, c-format
-msgid "E940: Cannot lock or unlock variable %s"
-msgstr "E940: Ðеможливо заблокувати чи розблокувати змінну %s"
-
msgid "E109: Missing ':' after '?'"
msgstr "E109: Бракує ':' піÑÐ»Ñ '?'"
@@ -950,9 +1017,6 @@ msgstr "E684: Ð†Ð½Ð´ÐµÐºÑ ÑпиÑку поза межами: %<PRId64>"
msgid "E686: Argument of %s must be a List"
msgstr "E686: Ðргумент у %s має бути ÑпиÑком"
-msgid "E928: String required"
-msgstr "E928: Потрібен String"
-
#, c-format
msgid "Error converting the call result: %s"
msgstr "Ðе вдалоÑÑ Ð¿ÐµÑ€ÐµÑ‚Ð²Ð¾Ñ€Ð¸Ñ‚Ð¸ результат виклику: %s"
@@ -1591,6 +1655,10 @@ msgid "Close \"%s\"?"
msgstr "Закрити «%s»?"
#, c-format
+msgid "E947: Job still running in buffer \"%s\""
+msgstr "E947: Задача вÑе ще запущена у буфері «%s»"
+
+#, c-format
msgid "E162: No write since last change for buffer \"%s\""
msgstr "E162: Буфер «%s» має незбережені зміни"
@@ -1615,18 +1683,6 @@ msgid "E666: compiler not supported: %s"
msgstr "E666: КомпілÑтор не підтримуєтьÑÑ: %s"
#, c-format
-msgid "Searching for \"%s\" in \"%s\""
-msgstr "Пошук «%s» в «%s»"
-
-#, c-format
-msgid "Searching for \"%s\""
-msgstr "Пошук «%s»"
-
-#, c-format
-msgid "not found in '%s': \"%s\""
-msgstr "не знайдено в '%s': «%s»"
-
-#, c-format
msgid ":source error parsing command %s"
msgstr ":source помилка розбору команди %s"
@@ -1702,12 +1758,16 @@ msgstr "Режим Ex. Ð”Ð»Ñ Ð¿Ð¾Ð²ÐµÑ€Ð½ÐµÐ½Ð½Ñ Ð´Ð¾ нормального Ñ
msgid "E501: At end-of-file"
msgstr "E501: Кінець файлу"
-msgid "E169: Command too recursive"
-msgstr "E169: Команда занадто рекурÑивна"
+#, c-format
+msgid "Executing: %s"
+msgstr "ВиконуєтьÑÑ: %s"
msgid "line %"
msgstr "Ñ€Ñдок %"
+msgid "E169: Command too recursive"
+msgstr "E169: Команда занадто рекурÑивна"
+
#, c-format
msgid "E605: Exception not caught: %s"
msgstr "E605: ВинÑткова ÑÐ¸Ñ‚ÑƒÐ°Ñ†Ñ–Ñ Ð½Ðµ оброблена: %s"
@@ -1724,9 +1784,6 @@ msgstr "E464: Ðеоднозначний вжиток команди кориÑÑ
msgid "E492: Not an editor command"
msgstr "E492: Це не команда редактора"
-msgid "E981: Command not allowed in restricted mode"
-msgstr "E981: Команду не дозволено у обмеженому режимі"
-
msgid "E493: Backwards range given"
msgstr "E493: Інтервал задано навиворіт"
@@ -1736,6 +1793,11 @@ msgstr "Інтервал задано навиворіт, щоб помінÑÑ‚Ð
msgid "E494: Use w or w>>"
msgstr "E494: Спробуйте w або w>>"
+msgid ""
+"INTERNAL: Cannot use EX_DFLALL with ADDR_NONE, ADDR_UNSIGNED or ADDR_QUICKFIX"
+msgstr ""
+"Ð’ÐУТРІШÐЄ: Ðе можна вживати EX_DFLALL з ADDR_NONE, ADDR_UNSIGNED чи ADDR_QUICKFIX"
+
msgid "E943: Command table needs to be updated, run 'make'"
msgstr "E943: Потрібно поновити таблицю команд, запуÑтіть 'make'"
@@ -1762,10 +1824,10 @@ msgstr "E174: Команда вже Ñ–Ñнує, ! щоб замінити Ñ—Ñ—:
msgid ""
"\n"
-" Name Args Address Complete Definition"
+" Name Args Address Complete Definition"
msgstr ""
"\n"
-" Ðазва Ðрг. ÐдреÑа Ð”Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð’Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ"
+" Ðазва Ðрг. ÐдреÑа Ð”Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð’Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ"
msgid "No user-defined commands found"
msgstr "Ðе знайдено команд кориÑтувача"
@@ -2077,12 +2139,12 @@ msgstr "E347: У шлÑху пошуку більше немає файлів «
msgid "E812: Autocommands changed buffer or buffer name"
msgstr "E812: Ðвтокоманди змінили буфер чи його назву"
-msgid "Illegal file name"
-msgstr "Ðедозволена назва файлу"
-
msgid "is a directory"
msgstr "каталог"
+msgid "Illegal file name"
+msgstr "Ðедозволена назва файлу"
+
msgid "is not a file"
msgstr "не файл"
@@ -2104,9 +2166,6 @@ msgstr "E201: Ðвтокоманди *ReadPre не повинні змінюва
msgid "E202: Conversion made file unreadable!"
msgstr "E202: ÐšÐ¾Ð½Ð²ÐµÑ€Ñ‚Ð°Ñ†Ñ–Ñ ÑƒÐ½ÐµÐ¼Ð¾Ð¶Ð»Ð¸Ð²Ð¸Ð»Ð° Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñƒ!"
-msgid "[fifo/socket]"
-msgstr "[канал/Ñокет]"
-
msgid "[fifo]"
msgstr "[канал]"
@@ -2353,67 +2412,6 @@ msgstr "E462: Ðе вдалоÑÑ Ð¿Ñ–Ð´Ð³Ð¾Ñ‚ÑƒÐ²Ð°Ñ‚Ð¸ «%s», щоб пере
msgid "E321: Could not reload \"%s\""
msgstr "E321: Ðе вдалоÑÑ Ð¿ÐµÑ€ÐµÑ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ «%s»"
-msgid "--Deleted--"
-msgstr "--Знищено--"
-
-#, c-format
-msgid "auto-removing autocommand: %s <buffer=%d>"
-msgstr "Ðвтоматичне Ð·Ð½Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð°Ð²Ñ‚Ð¾ÐºÐ¾Ð¼Ð°Ð½Ð´Ð¸: %s <буфер=%d>"
-
-#, c-format
-msgid "E367: No such group: \"%s\""
-msgstr "E367: Ðемає такої групи: «%s»"
-
-msgid "E936: Cannot delete the current group"
-msgstr "E936: Ðе вдалоÑÑ Ð·Ð½Ð¸Ñ‰Ð¸Ñ‚Ð¸ цю групу"
-
-msgid "W19: Deleting augroup that is still in use"
-msgstr "W19: Ð—Ð½Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð°Ð²Ñ‚Ð¾Ð³Ñ€ÑƒÐ¿Ð¸, Ñка вÑе ще викориÑтовуєтьÑÑ"
-
-#, c-format
-msgid "E215: Illegal character after *: %s"
-msgstr "E215: Ðедозволений Ñимвол піÑÐ»Ñ *: %s"
-
-#, c-format
-msgid "E216: No such event: %s"
-msgstr "E216: Ðемає такої події: %s"
-
-#, c-format
-msgid "E216: No such group or event: %s"
-msgstr "E216: Ðемає такої групи чи події: %s"
-
-msgid ""
-"\n"
-"--- Autocommands ---"
-msgstr ""
-"\n"
-"--- Ðвтокоманди ---"
-
-#, c-format
-msgid "E680: <buffer=%d>: invalid buffer number "
-msgstr "E680: <буфер=%d>: некоректний номер буфера "
-
-msgid "E217: Can't execute autocommands for ALL events"
-msgstr "E217: Ðе можу виконувати автокоманди Ð´Ð»Ñ Ð£Ð¡Ð†Ð¥ подій"
-
-msgid "No matching autocommands"
-msgstr "Ðемає відповідних автокоманд"
-
-msgid "E218: autocommand nesting too deep"
-msgstr "E218: Забагато вкладених автокоманд"
-
-#, c-format
-msgid "%s Autocommands for \"%s\""
-msgstr "%s Ðвтокоманди Ð´Ð»Ñ Â«%s»"
-
-#, c-format
-msgid "Executing %s"
-msgstr "ВиконуєтьÑÑ %s"
-
-#, c-format
-msgid "autocommand %s"
-msgstr "автокоманда %s"
-
msgid "E219: Missing {."
msgstr "E219: Бракує {."
@@ -2519,9 +2517,6 @@ msgstr "E685: Ð’Ð½ÑƒÑ‚Ñ€Ñ–ÑˆÐ½Ñ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°: %s"
msgid "Interrupted"
msgstr "Перервано"
-msgid "E14: Invalid address"
-msgstr "E14: Ðеправильна адреÑа"
-
msgid "E474: Invalid argument"
msgstr "E474: Ðекоректний аргумент"
@@ -2719,6 +2714,9 @@ msgstr "E45: Ð’Ñтановлено опцію 'readonly' (! щоб не зваÐ
msgid "E46: Cannot change read-only variable \"%.*s\""
msgstr "E46: Змінна тільки Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ: «%.*s»"
+msgid "E928: String required"
+msgstr "E928: Потрібен String"
+
msgid "E715: Dictionary required"
msgstr "E715: Потрібен Ñловник"
@@ -2727,8 +2725,8 @@ msgid "E118: Too many arguments for function: %s"
msgstr "E118: Забагато аргументів Ð´Ð»Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ–Ñ—: %s"
#, c-format
-msgid "E716: Key not present in Dictionary: %s"
-msgstr "E716: Ðемає такого ключа у Ñловнику: %s"
+msgid "E716: Key not present in Dictionary: \"%s\""
+msgstr "E716: Ðемає такого ключа у Ñловнику: «%s»"
msgid "E714: List required"
msgstr "E714: Потрібен ÑпиÑок"
@@ -3158,6 +3156,10 @@ msgid "E5106: Error while creating shared module: %.*s"
msgstr "E5106: Помилка ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ€Ð¾Ð·Ð´Ñ–Ð»ÑŽÐ²Ð°Ð½Ð¾Ð³Ð¾ модулÑ: %.*s"
#, c-format
+msgid "E5106: Error while creating inspect module: %.*s"
+msgstr "E5106: Помилка ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¼Ð¾Ð´ÑƒÐ»Ñ inspect: %.*s"
+
+#, c-format
msgid "E5106: Error while creating vim module: %.*s"
msgstr "E5106: Помилка ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¼Ð¾Ð´ÑƒÐ»Ñ vim: %.*s"
@@ -3165,10 +3167,6 @@ msgid "E970: Failed to initialize lua interpreter"
msgstr "E970: Ðе вдалоÑÑ Ñ–Ð½Ñ–Ñ†Ñ–Ð°Ð»Ñ–Ð·ÑƒÐ²Ð°Ñ‚Ð¸ інтерпретатор lua"
#, c-format
-msgid "E5117: Error while updating package paths: %.*s"
-msgstr "E5117: Помилка Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ÑˆÐ»Ñхів пакунку: %.*s"
-
-#, c-format
msgid "E5114: Error while converting print argument #%i: %.*s"
msgstr "E5114: Ðе вдалоÑÑ Ð¿ÐµÑ€ÐµÑ‚Ð²Ð¾Ñ€Ð¸Ñ‚Ð¸ аргумент #%i друку: %.*s"
@@ -3256,6 +3254,10 @@ msgid "pre-vimrc command line"
msgstr "команди перед vimrc"
#, c-format
+msgid "Conflicting configs: \"%s\" \"%s\""
+msgstr "Суперечливі конфігурації: «%s» «%s»"
+
+#, c-format
msgid "E282: Cannot read from \"%s\""
msgstr "E282: Ðе вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ з «%s»"
@@ -3367,9 +3369,6 @@ msgstr " -v, --version Ðадрукувати інформацію пр
msgid " -V[N][file] Verbose [level][file]\n"
msgstr " -V[N][файл] Більше повідомлень [рівень][файл]\n"
-msgid " -Z Restricted mode\n"
-msgstr " -Z Обмежений режим\n"
-
msgid " --api-info Write msgpack-encoded API metadata to stdout\n"
msgstr ""
" --api-info ЗапиÑати метадані API, Ñеріалізовані у msgpack, у "
@@ -4005,8 +4004,7 @@ msgstr ""
"Введіть :qa! Ñ– натиÑніÑть <Enter> щоб відкинути вÑÑ– зміни Ñ– вийти Nvim"
msgid "Type :qa and press <Enter> to exit Nvim"
-msgstr ""
-"Введіть :qa Ñ– натиÑніÑть <Enter> щоб вийти з Nvim"
+msgstr "Введіть :qa Ñ– натиÑніÑть <Enter> щоб вийти з Nvim"
#, c-format
msgid "1 line %sed 1 time"
@@ -4071,10 +4069,10 @@ msgstr "E353: У регіÑтрі %s нічого немає"
msgid ""
"\n"
-"--- Registers ---"
+"Type Name Content"
msgstr ""
"\n"
-"--- РегіÑтри ---"
+"Тип Ðаз. ВміÑÑ‚ "
msgid ""
"E883: search pattern and expression register may not contain two or more "
@@ -4187,9 +4185,6 @@ msgstr "E537: 'commentstring' має бути порожньою чи міÑти
msgid "E540: Unclosed expression sequence"
msgstr "E540: ПоÑлідовніÑть виразів не завершено"
-msgid "E541: too many items"
-msgstr "E541: Забагато елементів"
-
msgid "E542: unbalanced groups"
msgstr "E542: Групи не збаланÑовано"
@@ -4277,6 +4272,9 @@ msgstr ""
msgid "E5677: Error writing input to shell-command: %s"
msgstr "E5677: Ðе вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати на вхід команди оболонки: %s"
+msgid "%a %b %d %H:%M:%S %Y"
+msgstr "%H:%M:%S %a, %d %B %Y р."
+
#, c-format
msgid "E447: Can't find file \"%s\" in path"
msgstr "E447: Файл «%s» не знайдено у шлÑху пошуку"
@@ -4284,8 +4282,11 @@ msgstr "E447: Файл «%s» не знайдено у шлÑху пошуку"
msgid "E553: No more items"
msgstr "E553: Ðемає більше елементів"
+msgid "E925: Current quickfix list was changed"
+msgstr "E925: Поточний ÑпиÑок quickfix змінивÑÑ"
+
msgid "E926: Current location list was changed"
-msgstr "E926: Цей ÑпиÑок міÑць було змінено"
+msgstr "E926: Поточний ÑпиÑок міÑць змінивÑÑ"
#, c-format
msgid "E372: Too many %%%c in format string"
@@ -4319,9 +4320,6 @@ msgstr "E379: Пропущена чи Ð¿Ð¾Ñ€Ð¾Ð¶Ð½Ñ Ð½Ð°Ð·Ð²Ð° каталогу
msgid "E924: Current window was closed"
msgstr "E924: Ðктивне вікно було закрито"
-msgid "E925: Current quickfix was changed"
-msgstr "E925: Цей quickfix було змінено"
-
#, c-format
msgid "(%d of %d)%s%s: "
msgstr "(%d з %d)%s%s: "
@@ -4349,6 +4347,9 @@ msgstr "E683: Пропущено назву файлу чи некоректни
msgid "Cannot open file \"%s\""
msgstr "Ðе вдалоÑÑ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸ файл «%s»"
+msgid "cannot have both a list and a \"what\" argument"
+msgstr "не можна задавати одночаÑно ÑпиÑок Ñ– аргумент «що»"
+
msgid "E681: Buffer is not loaded"
msgstr "E681: Буфер не завантажено"
@@ -4469,6 +4470,18 @@ msgstr ""
msgid "Switching to backtracking RE engine for pattern: "
msgstr "ÐŸÐµÑ€ÐµÐ¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð´Ð¾ проÑтого Ñ€ÑƒÑˆÑ–Ñ Ñ€ÐµÐ³ÑƒÐ»Ñрних виразів: "
+#, c-format
+msgid "Searching for \"%s\" in \"%s\""
+msgstr "Пошук «%s» в «%s»"
+
+#, c-format
+msgid "Searching for \"%s\""
+msgstr "Пошук «%s»"
+
+#, c-format
+msgid "not found in '%s': \"%s\""
+msgstr "не знайдено в '%s': «%s»"
+
msgid " TERMINAL"
msgstr " ТЕРМІÐÐЛ"
@@ -5252,6 +5265,9 @@ msgstr "ÑинхронізуєтьÑÑ Ð¿Ð¾ коментарÑÑ… Ñтилю С"
msgid "no syncing"
msgstr "без Ñинхронізації"
+msgid "syncing starts at the first line"
+msgstr "ÑÐ¸Ð½Ñ…Ñ€Ð¾Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ Ð¿Ð¾Ñ‡Ð¸Ð½Ð°Ñ”Ñ‚ÑŒÑÑ Ð· першого Ñ€Ñдка"
+
msgid "syncing starts "
msgstr "починаєтьÑÑ ÑÐ¸Ð½Ñ…Ñ€Ð¾Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ Ð·Ð° "
@@ -5283,6 +5299,9 @@ msgstr ""
msgid "E392: No such syntax cluster: %s"
msgstr "E392: Ðемає такого ÑинтакÑичного клаÑтера: %s"
+msgid "from the first line"
+msgstr "з першого Ñ€Ñдка"
+
msgid "minimal "
msgstr "мінімальний "
diff --git a/src/nvim/po/vi.po b/src/nvim/po/vi.po
index a954ea6e34..c693f910d8 100644
--- a/src/nvim/po/vi.po
+++ b/src/nvim/po/vi.po
@@ -3479,10 +3479,6 @@ msgstr "-y\t\t\tChế độ đơn giản (giống \"evim\", không có chế Ä‘á
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tChế độ chỉ Ä‘á»c (giống \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tChế độ hạn chế (giống \"rvim\")"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tKhông có khả năng ghi nhớ thay đổi (ghi nhớ tập tin)"
diff --git a/src/nvim/po/zh_CN.UTF-8.po b/src/nvim/po/zh_CN.UTF-8.po
index 542157002a..1e329443ce 100644
--- a/src/nvim/po/zh_CN.UTF-8.po
+++ b/src/nvim/po/zh_CN.UTF-8.po
@@ -3427,10 +3427,6 @@ msgstr "-y\t\t\tå®¹æ˜“æ¨¡å¼ (åŒ \"evim\",无模å¼)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tåªè¯»æ¨¡å¼ (åŒ \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\té™åˆ¶æ¨¡å¼ (åŒ \"rvim\")"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tä¸å¯ä¿®æ”¹(写入文件)"
diff --git a/src/nvim/po/zh_TW.UTF-8.po b/src/nvim/po/zh_TW.UTF-8.po
index 6a11b5e669..c97f31ddcf 100644
--- a/src/nvim/po/zh_TW.UTF-8.po
+++ b/src/nvim/po/zh_TW.UTF-8.po
@@ -3482,10 +3482,6 @@ msgstr "-y\t\t\tç°¡æ˜“æ¨¡å¼ (åŒ \"evim\", modeless)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tå”¯è®€æ¨¡å¼ (åŒ \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\té™åˆ¶æ¨¡å¼ (åŒ \"rvim\")"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tä¸å¯ä¿®æ”¹ (寫入檔案)"
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index aeac6e4905..a625c09f78 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -143,6 +143,7 @@ struct efm_S {
// 'E' error message
// 'W' warning message
// 'I' informational message
+ // 'N' note message
// 'C' continuation line
// 'Z' end of multi-line message
// 'G' general, unspecific message
@@ -457,7 +458,7 @@ static const char_u *efm_analyze_prefix(const char_u *efmp, efm_T *efminfo,
if (vim_strchr((char_u *)"+-", *efmp) != NULL) {
efminfo->flags = *efmp++;
}
- if (vim_strchr((char_u *)"DXAEWICZGOPQ", *efmp) != NULL) {
+ if (vim_strchr((char_u *)"DXAEWINCZGOPQ", *efmp) != NULL) {
efminfo->prefix = *efmp;
} else {
snprintf((char *)errmsg, errmsglen,
@@ -967,7 +968,7 @@ restofline:
fmt_start = fmt_ptr;
}
- if (vim_strchr((char_u *)"AEWI", idx) != NULL) {
+ if (vim_strchr((char_u *)"AEWIN", idx) != NULL) {
qfl->qf_multiline = true; // start of a multi-line message
qfl->qf_multiignore = false; // reset continuation
} else if (vim_strchr((char_u *)"CZ", idx) != NULL) {
@@ -1499,7 +1500,7 @@ static int qf_parse_match(char_u *linebuf, size_t linelen, efm_T *fmt_ptr,
if ((idx == 'C' || idx == 'Z') && !qf_multiline) {
return QF_FAIL;
}
- if (vim_strchr((char_u *)"EWI", idx) != NULL) {
+ if (vim_strchr((char_u *)"EWIN", idx) != NULL) {
fields->type = idx;
} else {
fields->type = 0;
@@ -3300,6 +3301,24 @@ void qf_history(exarg_T *eap)
qf_info_T *qi = qf_cmd_get_stack(eap, false);
int i;
+ if (eap->addr_count > 0) {
+ if (qi == NULL) {
+ EMSG(_(e_loclist));
+ return;
+ }
+
+ // Jump to the specified quickfix list
+ if (eap->line2 > 0 && eap->line2 <= qi->qf_listcount) {
+ qi->qf_curlist = (int)(eap->line2 - 1);
+ qf_msg(qi, qi->qf_curlist, "");
+ qf_update_buffer(qi, NULL);
+ } else {
+ EMSG(_(e_invrange));
+ }
+
+ return;
+ }
+
if (qf_stack_empty(qi)) {
MSG(_("No entries"));
} else {
@@ -3414,11 +3433,13 @@ bool qf_mark_adjust(win_T *wp, linenr_T line1, linenr_T line2, long amount,
// e or E 0 " error"
// w or W 0 " warning"
// i or I 0 " info"
+// n or N 0 " note"
// 0 0 ""
// other 0 " c"
// e or E n " error n"
// w or W n " warning n"
// i or I n " info n"
+// n or N n " note n"
// 0 n " error n"
// other n " c n"
// 1 x "" :helpgrep
@@ -3428,15 +3449,17 @@ static char_u *qf_types(int c, int nr)
static char_u cc[3];
char_u *p;
- if (c == 'W' || c == 'w')
+ if (c == 'W' || c == 'w') {
p = (char_u *)" warning";
- else if (c == 'I' || c == 'i')
+ } else if (c == 'I' || c == 'i') {
p = (char_u *)" info";
- else if (c == 'E' || c == 'e' || (c == 0 && nr > 0))
+ } else if (c == 'N' || c == 'n') {
+ p = (char_u *)" note";
+ } else if (c == 'E' || c == 'e' || (c == 0 && nr > 0)) {
p = (char_u *)" error";
- else if (c == 0 || c == 1)
+ } else if (c == 0 || c == 1) {
p = (char_u *)"";
- else {
+ } else {
cc[0] = ' ';
cc[1] = (char_u)c;
cc[2] = NUL;
@@ -3622,7 +3645,7 @@ static int qf_open_new_cwindow(qf_info_T *qi, int height)
// Set the options for the quickfix buffer/window (if not already done)
// Do this even if the quickfix buffer was already present, as an autocmd
// might have previously deleted (:bdelete) the quickfix buffer.
- if (curbuf->b_p_bt[0] != 'q') {
+ if (!bt_quickfix(curbuf)) {
qf_set_cwindow_options();
}
@@ -4269,11 +4292,22 @@ static char_u *get_mef_name(void)
return name;
}
-/// Returns the number of valid entries in the current quickfix/location list.
+/// Returns the number of entries in the current quickfix/location list.
size_t qf_get_size(exarg_T *eap)
FUNC_ATTR_NONNULL_ALL
{
qf_info_T *qi;
+
+ if ((qi = qf_cmd_get_stack(eap, false)) == NULL) {
+ return 0;
+ }
+ return (size_t)qf_get_curlist(qi)->qf_count;
+}
+
+/// Returns the number of valid entries in the current quickfix/location list.
+size_t qf_get_valid_size(exarg_T *eap)
+{
+ qf_info_T *qi;
qf_list_T *qfl;
if ((qi = qf_cmd_get_stack(eap, false)) == NULL) {
@@ -4562,74 +4596,150 @@ static qfline_T * qf_find_last_entry_on_line(qfline_T *entry, int *errornr)
return entry;
}
-/// Find the first quickfix entry below line 'lnum' in buffer 'bnr'.
+// Returns true if the specified quickfix entry is
+// after the given line (linewise is true)
+// or after the line and column.
+static bool qf_entry_after_pos(const qfline_T *qfp, const pos_T *pos,
+ bool linewise)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ if (linewise) {
+ return qfp->qf_lnum > pos->lnum;
+ }
+ return qfp->qf_lnum > pos->lnum
+ || (qfp->qf_lnum == pos->lnum && qfp->qf_col > pos->col);
+}
+
+// Returns true if the specified quickfix entry is
+// before the given line (linewise is true)
+// or before the line and column.
+static bool qf_entry_before_pos(const qfline_T *qfp, const pos_T *pos,
+ bool linewise)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ if (linewise) {
+ return qfp->qf_lnum < pos->lnum;
+ }
+ return qfp->qf_lnum < pos->lnum
+ || (qfp->qf_lnum == pos->lnum && qfp->qf_col < pos->col);
+}
+
+// Returns true if the specified quickfix entry is
+// on or after the given line (linewise is true)
+// or on or after the line and column.
+static bool qf_entry_on_or_after_pos(const qfline_T *qfp, const pos_T *pos,
+ bool linewise)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ if (linewise) {
+ return qfp->qf_lnum >= pos->lnum;
+ }
+ return qfp->qf_lnum > pos->lnum
+ || (qfp->qf_lnum == pos->lnum && qfp->qf_col >= pos->col);
+}
+
+// Returns true if the specified quickfix entry is
+// on or before the given line (linewise is true)
+// or on or before the line and column.
+static bool qf_entry_on_or_before_pos(const qfline_T *qfp, const pos_T *pos,
+ bool linewise)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ if (linewise) {
+ return qfp->qf_lnum <= pos->lnum;
+ }
+ return qfp->qf_lnum < pos->lnum
+ || (qfp->qf_lnum == pos->lnum && qfp->qf_col <= pos->col);
+}
+
+/// Find the first quickfix entry after position 'pos' in buffer 'bnr'.
+/// If 'linewise' is true, returns the entry after the specified line and treats
+/// multiple entries on a single line as one. Otherwise returns the entry after
+/// the specified line and column.
/// 'qfp' points to the very first entry in the buffer and 'errornr' is the
/// index of the very first entry in the quickfix list.
-/// Returns NULL if an entry is not found after 'lnum'.
-static qfline_T *qf_find_entry_on_next_line(int bnr,
- linenr_T lnum,
- qfline_T *qfp,
- int *errornr)
+/// Returns NULL if an entry is not found after 'pos'.
+static qfline_T *qf_find_entry_after_pos(
+ int bnr,
+ const pos_T *pos,
+ bool linewise,
+ qfline_T *qfp,
+ int *errornr
+)
+ FUNC_ATTR_NONNULL_ALL
{
- if (qfp->qf_lnum > lnum) {
- // First entry is after line 'lnum'
+ if (qf_entry_after_pos(qfp, pos, linewise)) {
+ // First entry is after postion 'pos'
return qfp;
}
- // Find the entry just before or at the line 'lnum'
+ // Find the entry just before or at the position 'pos'
while (qfp->qf_next != NULL
&& qfp->qf_next->qf_fnum == bnr
- && qfp->qf_next->qf_lnum <= lnum) {
+ && qf_entry_on_or_before_pos(qfp->qf_next, pos, linewise)) {
qfp = qfp->qf_next;
(*errornr)++;
}
if (qfp->qf_next == NULL || qfp->qf_next->qf_fnum != bnr) {
- // No entries found after 'lnum'
+ // No entries found after position 'pos'
return NULL;
}
- // Use the entry just after line 'lnum'
+ // Use the entry just after position 'pos'
qfp = qfp->qf_next;
(*errornr)++;
return qfp;
}
-/// Find the first quickfix entry before line 'lnum' in buffer 'bnr'.
+/// Find the first quickfix entry before position 'pos' in buffer 'bnr'.
+/// If 'linewise' is true, returns the entry before the specified line and
+/// treats multiple entries on a single line as one. Otherwise returns the entry
+/// before the specified line and column.
/// 'qfp' points to the very first entry in the buffer and 'errornr' is the
/// index of the very first entry in the quickfix list.
-/// Returns NULL if an entry is not found before 'lnum'.
-static qfline_T *qf_find_entry_on_prev_line(int bnr,
- linenr_T lnum,
- qfline_T *qfp,
- int *errornr)
+/// Returns NULL if an entry is not found before 'pos'.
+static qfline_T *qf_find_entry_before_pos(
+ int bnr,
+ const pos_T *pos,
+ bool linewise,
+ qfline_T *qfp,
+ int *errornr
+)
+ FUNC_ATTR_NONNULL_ALL
{
- // Find the entry just before the line 'lnum'
+ // Find the entry just before the position 'pos'
while (qfp->qf_next != NULL
&& qfp->qf_next->qf_fnum == bnr
- && qfp->qf_next->qf_lnum < lnum) {
+ && qf_entry_before_pos(qfp->qf_next, pos, linewise)) {
qfp = qfp->qf_next;
(*errornr)++;
}
- if (qfp->qf_lnum >= lnum) { // entry is after 'lnum'
+ if (qf_entry_on_or_after_pos(qfp, pos, linewise)) {
return NULL;
}
- // If multiple entries are on the same line, then use the first entry
- qfp = qf_find_first_entry_on_line(qfp, errornr);
+ if (linewise) {
+ // If multiple entries are on the same line, then use the first entry
+ qfp = qf_find_first_entry_on_line(qfp, errornr);
+ }
return qfp;
}
-/// Find a quickfix entry in 'qfl' closest to line 'lnum' in buffer 'bnr' in
+/// Find a quickfix entry in 'qfl' closest to position 'pos' in buffer 'bnr' in
/// the direction 'dir'.
-static qfline_T *qf_find_closest_entry(qf_list_T *qfl,
- int bnr,
- linenr_T lnum,
- int dir,
- int *errornr)
+static qfline_T *qf_find_closest_entry(
+ qf_list_T *qfl,
+ int bnr,
+ const pos_T *pos,
+ Direction dir,
+ bool linewise,
+ int *errornr
+)
+ FUNC_ATTR_NONNULL_ALL
{
qfline_T *qfp;
@@ -4642,33 +4752,38 @@ static qfline_T *qf_find_closest_entry(qf_list_T *qfl,
}
if (dir == FORWARD) {
- qfp = qf_find_entry_on_next_line(bnr, lnum, qfp, errornr);
+ qfp = qf_find_entry_after_pos(bnr, pos, linewise, qfp, errornr);
} else {
- qfp = qf_find_entry_on_prev_line(bnr, lnum, qfp, errornr);
+ qfp = qf_find_entry_before_pos(bnr, pos, linewise, qfp, errornr);
}
return qfp;
}
-/// Get the nth quickfix entry below the specified entry treating multiple
-/// entries on a single line as one. Searches forward in the list.
-static void qf_get_nth_below_entry(qfline_T *entry,
- int *errornr,
- linenr_T n)
+/// Get the nth quickfix entry below the specified entry. Searches forward in
+/// the list. If linewise is true, then treat multiple entries on a single line
+/// as one.
+static void qf_get_nth_below_entry(qfline_T *entry, linenr_T n,
+ bool linewise, int *errornr)
+ FUNC_ATTR_NONNULL_ALL
{
while (n-- > 0 && !got_int) {
// qfline_T *first_entry = entry;
int first_errornr = *errornr;
- // Treat all the entries on the same line in this file as one
- entry = qf_find_last_entry_on_line(entry, errornr);
+ if (linewise) {
+ // Treat all the entries on the same line in this file as one
+ entry = qf_find_last_entry_on_line(entry, errornr);
+ }
if (entry->qf_next == NULL
|| entry->qf_next->qf_fnum != entry->qf_fnum) {
- // If multiple entries are on the same line, then use the first
- // entry
- // entry = first_entry;
- *errornr = first_errornr;
+ if (linewise) {
+ // If multiple entries are on the same line, then use the first
+ // entry
+ // entry = first_entry;
+ *errornr = first_errornr;
+ }
break;
}
@@ -4677,11 +4792,12 @@ static void qf_get_nth_below_entry(qfline_T *entry,
}
}
-/// Get the nth quickfix entry above the specified entry treating multiple
-/// entries on a single line as one. Searches backwards in the list.
-static void qf_get_nth_above_entry(qfline_T *entry,
- int *errornr,
- linenr_T n)
+/// Get the nth quickfix entry above the specified entry. Searches backwards in
+/// the list. If linewise is TRUE, then treat multiple entries on a single line
+/// as one.
+static void qf_get_nth_above_entry(qfline_T *entry, linenr_T n,
+ bool linewise, int *errornr)
+ FUNC_ATTR_NONNULL_ALL
{
while (n-- > 0 && !got_int) {
if (entry->qf_prev == NULL
@@ -4692,25 +4808,30 @@ static void qf_get_nth_above_entry(qfline_T *entry,
entry = entry->qf_prev;
(*errornr)--;
- // If multiple entries are on the same line, then use the first entry
- entry = qf_find_first_entry_on_line(entry, errornr);
+ if (linewise) {
+ entry = qf_find_first_entry_on_line(entry, errornr);
+ }
}
}
-/// Find the n'th quickfix entry adjacent to line 'lnum' in buffer 'bnr' in the
-/// specified direction.
-/// Returns the error number in the quickfix list or 0 if an entry is not found.
-static int qf_find_nth_adj_entry(qf_list_T *qfl,
- int bnr,
- linenr_T lnum,
- linenr_T n,
- int dir)
+/// Find the n'th quickfix entry adjacent to position 'pos' in buffer 'bnr' in
+/// the specified direction. Returns the error number in the quickfix list or 0
+/// if an entry is not found.
+static int qf_find_nth_adj_entry(
+ qf_list_T *qfl,
+ int bnr,
+ pos_T *pos,
+ linenr_T n,
+ Direction dir,
+ bool linewise
+)
+ FUNC_ATTR_NONNULL_ALL
{
- qfline_T *adj_entry;
int errornr;
- // Find an entry closest to the specified line
- adj_entry = qf_find_closest_entry(qfl, bnr, lnum, dir, &errornr);
+ // Find an entry closest to the specified position
+ qfline_T *const adj_entry = qf_find_closest_entry(qfl, bnr, pos, dir,
+ linewise, &errornr);
if (adj_entry == NULL) {
return 0;
}
@@ -4718,24 +4839,25 @@ static int qf_find_nth_adj_entry(qf_list_T *qfl,
if (--n > 0) {
// Go to the n'th entry in the current buffer
if (dir == FORWARD) {
- qf_get_nth_below_entry(adj_entry, &errornr, n);
+ qf_get_nth_below_entry(adj_entry, n, linewise, &errornr);
} else {
- qf_get_nth_above_entry(adj_entry, &errornr, n);
+ qf_get_nth_above_entry(adj_entry, n, linewise, &errornr);
}
}
return errornr;
}
-/// Jump to a quickfix entry in the current file nearest to the current line.
-/// ":cabove", ":cbelow", ":labove" and ":lbelow" commands
+/// Jump to a quickfix entry in the current file nearest to the current line or
+/// current line/col.
+/// ":cabove", ":cbelow", ":labove", ":lbelow", ":cafter", ":cbefore",
+/// ":lafter" and ":lbefore" commands
void ex_cbelow(exarg_T *eap)
{
qf_info_T *qi;
qf_list_T *qfl;
int dir;
int buf_has_flag;
- int errornr = 0;
if (eap->addr_count > 0 && eap->line2 <= 0) {
EMSG(_(e_invrange));
@@ -4743,7 +4865,8 @@ void ex_cbelow(exarg_T *eap)
}
// Check whether the current buffer has any quickfix entries
- if (eap->cmdidx == CMD_cabove || eap->cmdidx == CMD_cbelow) {
+ if (eap->cmdidx == CMD_cabove || eap->cmdidx == CMD_cbelow
+ || eap->cmdidx == CMD_cbefore || eap->cmdidx == CMD_cafter) {
buf_has_flag = BUF_HAS_QF_ENTRY;
} else {
buf_has_flag = BUF_HAS_LL_ENTRY;
@@ -4764,14 +4887,30 @@ void ex_cbelow(exarg_T *eap)
return;
}
- if (eap->cmdidx == CMD_cbelow || eap->cmdidx == CMD_lbelow) {
+ if (eap->cmdidx == CMD_cbelow
+ || eap->cmdidx == CMD_lbelow
+ || eap->cmdidx == CMD_cafter
+ || eap->cmdidx == CMD_lafter) {
+ // Forward motion commands
dir = FORWARD;
} else {
dir = BACKWARD;
}
- errornr = qf_find_nth_adj_entry(qfl, curbuf->b_fnum, curwin->w_cursor.lnum,
- eap->addr_count > 0 ? eap->line2 : 0, dir);
+ pos_T pos = curwin->w_cursor;
+ // A quickfix entry column number is 1 based whereas cursor column
+ // number is 0 based. Adjust the column number.
+ pos.col++;
+ const int errornr = qf_find_nth_adj_entry(
+ qfl,
+ curbuf->b_fnum,
+ &pos,
+ eap->addr_count > 0 ? eap->line2 : 0,
+ dir,
+ eap->cmdidx == CMD_cbelow
+ || eap->cmdidx == CMD_lbelow
+ || eap->cmdidx == CMD_cabove
+ || eap->cmdidx == CMD_labove);
if (errornr > 0) {
qf_jump(qi, 0, errornr, false);
@@ -6818,8 +6957,9 @@ void ex_helpgrep(exarg_T *eap)
if (au_name != NULL) {
apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name,
curbuf->b_fname, true, curbuf);
- if (!new_qi && IS_LL_STACK(qi) && qf_find_buf(qi) == NULL) {
- // autocommands made "qi" invalid
+ // When adding a location list to an existing location list stack,
+ // if the autocmd made the stack invalid, then just return.
+ if (!new_qi && IS_LL_STACK(qi) && qf_find_win_with_loclist(qi) == NULL) {
decr_quickfix_busy();
return;
}
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index a7fd2bfcc6..a78f905a70 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -2417,8 +2417,8 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
}
}
- if (wp->w_p_list) {
- if (curwin->w_p_lcs_chars.space
+ if (wp->w_p_list && !has_fold) {
+ if (wp->w_p_lcs_chars.space
|| wp->w_p_lcs_chars.trail
|| wp->w_p_lcs_chars.nbsp) {
extra_check = true;
@@ -2665,7 +2665,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
}
}
- //sign column
+ // sign column, this is hit until sign_idx reaches count
if (draw_state == WL_SIGN - 1 && n_extra == 0) {
draw_state = WL_SIGN;
/* Show the sign column when there are any signs in this
@@ -2883,8 +2883,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
}
if (draw_state == WL_LINE
- && foldinfo.fi_level != 0
- && foldinfo.fi_lines > 0
+ && has_fold
&& vcol == 0
&& n_extra == 0
&& row == startrow) {
@@ -2905,8 +2904,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
}
if (draw_state == WL_LINE
- && foldinfo.fi_level != 0
- && foldinfo.fi_lines > 0
+ && has_fold
&& col < grid->Columns
&& n_extra == 0
&& row == startrow) {
@@ -2918,8 +2916,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
}
if (draw_state == WL_LINE
- && foldinfo.fi_level != 0
- && foldinfo.fi_lines > 0
+ && has_fold
&& col >= grid->Columns
&& n_extra != 0
&& row == startrow) {
@@ -3087,7 +3084,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
|| vcol < fromcol || vcol_prev < fromcol_prev
|| vcol >= tocol)) {
char_attr = line_attr;
- } else {
+ } else {
attr_pri = false;
if (has_syntax) {
char_attr = syntax_attr;
@@ -3742,7 +3739,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
}
wp->w_wrow = row;
did_wcol = true;
- curwin->w_valid |= VALID_WCOL|VALID_WROW|VALID_VIRTCOL;
+ wp->w_valid |= VALID_WCOL|VALID_WROW|VALID_VIRTCOL;
}
// Don't override visual selection highlighting.
@@ -3835,9 +3832,9 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
// Add a blank character to highlight.
schar_from_ascii(linebuf_char[off], ' ');
}
- if (area_attr == 0) {
- /* Use attributes from match with highest priority among
- * 'search_hl' and the match list. */
+ if (area_attr == 0 && !has_fold) {
+ // Use attributes from match with highest priority among
+ // 'search_hl' and the match list.
char_attr = search_hl.attr;
cur = wp->w_match_head;
shl_flag = FALSE;
@@ -4053,6 +4050,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
&& !wp->w_p_wrap
&& filler_todo <= 0
&& (wp->w_p_rl ? col == 0 : col == grid->Columns - 1)
+ && !has_fold
&& (*ptr != NUL
|| lcs_eol_one > 0
|| (n_extra && (c_extra != NUL || *p_extra != NUL)))) {
@@ -4347,6 +4345,10 @@ void screen_adjust_grid(ScreenGrid **grid, int *row_off, int *col_off)
// Get information needed to display the sign in line 'lnum' in window 'wp'.
// If 'nrcol' is TRUE, the sign is going to be displayed in the number column.
// Otherwise the sign is going to be displayed in the sign column.
+//
+// @param count max number of signs
+// @param[out] n_extrap number of characters from pp_extra to display
+// @param[in, out] sign_idxp Index of the displayed sign
static void get_sign_display_info(
bool nrcol,
win_T *wp,
@@ -4423,6 +4425,8 @@ static void get_sign_display_info(
(*sign_idxp)++;
if (*sign_idxp < count) {
*draw_statep = WL_SIGN - 1;
+ } else {
+ *sign_idxp = 0;
}
}
diff --git a/src/nvim/search.c b/src/nvim/search.c
index 787a464070..2802da6f7f 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -4497,9 +4497,9 @@ find_pattern_in_path(
regmatch_T regmatch;
regmatch_T incl_regmatch;
regmatch_T def_regmatch;
- int matched = FALSE;
- int did_show = FALSE;
- int found = FALSE;
+ bool matched = false;
+ bool did_show = false;
+ bool found = false;
int i;
char_u *already = NULL;
char_u *startp = NULL;
@@ -4611,7 +4611,7 @@ find_pattern_in_path(
}
MSG_PUTS_TITLE(_("in path ---\n"));
}
- did_show = TRUE;
+ did_show = true;
while (depth_displayed < depth && !got_int) {
++depth_displayed;
for (i = 0; i < depth_displayed; i++)
@@ -4761,10 +4761,10 @@ search_line:
matched = !STRNCMP(startp, ptr, len);
if (matched && define_matched && whole
&& vim_iswordc(startp[len]))
- matched = FALSE;
+ matched = false;
} else if (regmatch.regprog != NULL
&& vim_regexec(&regmatch, line, (colnr_T)(p - line))) {
- matched = TRUE;
+ matched = true;
startp = regmatch.startp[0];
// Check if the line is not a comment line (unless we are
// looking for a define). A line starting with "# define"
@@ -4789,15 +4789,16 @@ search_line:
if (matched
&& p[0] == '/'
&& (p[1] == '*' || p[1] == '/')) {
- matched = FALSE;
- /* After "//" all text is comment */
- if (p[1] == '/')
+ matched = false;
+ // After "//" all text is comment
+ if (p[1] == '/') {
break;
- ++p;
+ }
+ p++;
} else if (!matched && p[0] == '*' && p[1] == '/') {
- /* Can find match after "* /". */
- matched = TRUE;
- ++p;
+ // Can find match after "* /".
+ matched = true;
+ p++;
}
}
}
@@ -4811,7 +4812,7 @@ search_line:
if (depth == -1 && lnum == curwin->w_cursor.lnum)
break;
- found = TRUE;
+ found = true;
aux = p = startp;
if (compl_cont_status & CONT_ADDING) {
p += compl_length;
@@ -4879,9 +4880,10 @@ search_line:
break;
}
} else if (action == ACTION_SHOW_ALL) {
- found = TRUE;
- if (!did_show)
- gotocmdline(TRUE); /* cursor at status line */
+ found = true;
+ if (!did_show) {
+ gotocmdline(true); // cursor at status line
+ }
if (curr_fname != prev_fname) {
if (did_show)
msg_putchar('\n'); /* cursor below last one */
@@ -4890,28 +4892,28 @@ search_line:
msg_home_replace_hl(curr_fname);
prev_fname = curr_fname;
}
- did_show = TRUE;
- if (!got_int)
- show_pat_in_path(line, type, TRUE, action,
- (depth == -1) ? NULL : files[depth].fp,
- (depth == -1) ? &lnum : &files[depth].lnum,
- match_count++);
+ did_show = true;
+ if (!got_int) {
+ show_pat_in_path(line, type, true, action,
+ (depth == -1) ? NULL : files[depth].fp,
+ (depth == -1) ? &lnum : &files[depth].lnum,
+ match_count++);
+ }
/* Set matched flag for this file and all the ones that
* include it */
for (i = 0; i <= depth; ++i)
files[i].matched = TRUE;
} else if (--count <= 0) {
- found = TRUE;
+ found = true;
if (depth == -1 && lnum == curwin->w_cursor.lnum
- && l_g_do_tagpreview == 0
- )
+ && l_g_do_tagpreview == 0) {
EMSG(_("E387: Match is on current line"));
- else if (action == ACTION_SHOW) {
+ } else if (action == ACTION_SHOW) {
show_pat_in_path(line, type, did_show, action,
- (depth == -1) ? NULL : files[depth].fp,
- (depth == -1) ? &lnum : &files[depth].lnum, 1L);
- did_show = TRUE;
+ (depth == -1) ? NULL : files[depth].fp,
+ (depth == -1) ? &lnum : &files[depth].lnum, 1L);
+ did_show = true;
} else {
/* ":psearch" uses the preview window */
if (l_g_do_tagpreview != 0) {
@@ -4960,15 +4962,16 @@ search_line:
break;
}
exit_matched:
- matched = FALSE;
- /* look for other matches in the rest of the line if we
- * are not at the end of it already */
+ matched = false;
+ // look for other matches in the rest of the line if we
+ // are not at the end of it already
if (def_regmatch.regprog == NULL
&& action == ACTION_EXPAND
&& !(compl_cont_status & CONT_SOL)
&& *startp != NUL
- && *(p = startp + utfc_ptr2len(startp)) != NUL)
+ && *(p = startp + utfc_ptr2len(startp)) != NUL) {
goto search_line;
+ }
}
line_breakcheck();
if (action == ACTION_EXPAND)
@@ -5046,16 +5049,20 @@ fpip_end:
vim_regfree(def_regmatch.regprog);
}
-static void show_pat_in_path(char_u *line, int type, int did_show, int action, FILE *fp, linenr_T *lnum, long count)
+static void show_pat_in_path(char_u *line, int type, bool did_show, int action,
+ FILE *fp, linenr_T *lnum, long count)
+ FUNC_ATTR_NONNULL_ARG(1, 6)
{
char_u *p;
- if (did_show)
- msg_putchar('\n'); /* cursor below last one */
- else if (!msg_silent)
- gotocmdline(TRUE); /* cursor at status line */
- if (got_int) /* 'q' typed at "--more--" message */
+ if (did_show) {
+ msg_putchar('\n'); // cursor below last one
+ } else if (!msg_silent) {
+ gotocmdline(true); // cursor at status line
+ }
+ if (got_int) { // 'q' typed at "--more--" message
return;
+ }
for (;; ) {
p = line + STRLEN(line) - 1;
if (fp != NULL) {
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index 4d88df5a3a..f99eca7953 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -4275,7 +4275,7 @@ static void syn_cmd_include(exarg_T *eap, int syncing)
* Everything that's left, up to the next command, should be the
* filename to include.
*/
- eap->argt |= (XFILE | NOSPC);
+ eap->argt |= (EX_XFILE | EX_NOSPC);
separate_nextcmd(eap);
if (*eap->arg == '<' || *eap->arg == '$' || path_is_absolute(eap->arg)) {
// For an absolute path, "$VIM/..." or "<sfile>.." we ":source" the
diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim
index 641e98ab30..c571e37ac3 100644
--- a/src/nvim/testdir/test_autocmd.vim
+++ b/src/nvim/testdir/test_autocmd.vim
@@ -1110,14 +1110,14 @@ func Test_BufReadCmd()
endfunc
func SetChangeMarks(start, end)
- exe a:start. 'mark ['
- exe a:end. 'mark ]'
+ exe a:start .. 'mark ['
+ exe a:end .. 'mark ]'
endfunc
" Verify the effects of autocmds on '[ and ']
func Test_change_mark_in_autocmds()
edit! Xtest
- call feedkeys("ia\<CR>b\<CR>c\<CR>d\<C-g>u", 'xtn')
+ call feedkeys("ia\<CR>b\<CR>c\<CR>d\<C-g>u\<Esc>", 'xtn')
call SetChangeMarks(2, 3)
write
diff --git a/src/nvim/testdir/test_backspace_opt.vim b/src/nvim/testdir/test_backspace_opt.vim
new file mode 100644
index 0000000000..d680b442db
--- /dev/null
+++ b/src/nvim/testdir/test_backspace_opt.vim
@@ -0,0 +1,151 @@
+" Tests for 'backspace' settings
+
+func Exec(expr)
+ let str=''
+ try
+ exec a:expr
+ catch /.*/
+ let str=v:exception
+ endtry
+ return str
+endfunc
+
+func Test_backspace_option()
+ set backspace=
+ call assert_equal('', &backspace)
+ set backspace=indent
+ call assert_equal('indent', &backspace)
+ set backspace=eol
+ call assert_equal('eol', &backspace)
+ set backspace=start
+ call assert_equal('start', &backspace)
+ set backspace=nostop
+ call assert_equal('nostop', &backspace)
+ " Add the value
+ set backspace=
+ set backspace=indent
+ call assert_equal('indent', &backspace)
+ set backspace+=eol
+ call assert_equal('indent,eol', &backspace)
+ set backspace+=start
+ call assert_equal('indent,eol,start', &backspace)
+ set backspace+=nostop
+ call assert_equal('indent,eol,start,nostop', &backspace)
+ " Delete the value
+ set backspace-=nostop
+ call assert_equal('indent,eol,start', &backspace)
+ set backspace-=indent
+ call assert_equal('eol,start', &backspace)
+ set backspace-=start
+ call assert_equal('eol', &backspace)
+ set backspace-=eol
+ call assert_equal('', &backspace)
+ " Check the error
+ call assert_equal(0, match(Exec('set backspace=ABC'), '.*E474'))
+ call assert_equal(0, match(Exec('set backspace+=def'), '.*E474'))
+ " NOTE: Vim doesn't check following error...
+ "call assert_equal(0, match(Exec('set backspace-=ghi'), '.*E474'))
+
+ " Check backwards compatibility with version 5.4 and earlier
+ set backspace=0
+ call assert_equal('0', &backspace)
+ set backspace=1
+ call assert_equal('1', &backspace)
+ set backspace=2
+ call assert_equal('2', &backspace)
+ set backspace=3
+ call assert_equal('3', &backspace)
+ call assert_false(match(Exec('set backspace=4'), '.*E474'))
+ call assert_false(match(Exec('set backspace=10'), '.*E474'))
+
+ " Cleared when 'compatible' is set
+ " set compatible
+ " call assert_equal('', &backspace)
+ set nocompatible viminfo+=nviminfo
+endfunc
+
+" Test with backspace set to the non-compatible setting
+func Test_backspace_ctrl_u()
+ new
+ call append(0, [
+ \ "1 this shouldn't be deleted",
+ \ "2 this shouldn't be deleted",
+ \ "3 this shouldn't be deleted",
+ \ "4 this should be deleted",
+ \ "5 this shouldn't be deleted",
+ \ "6 this shouldn't be deleted",
+ \ "7 this shouldn't be deleted",
+ \ "8 this shouldn't be deleted (not touched yet)"])
+ call cursor(2, 1)
+
+ " set compatible
+ set backspace=2
+
+ exe "normal Avim1\<C-U>\<Esc>\<CR>"
+ exe "normal Avim2\<C-G>u\<C-U>\<Esc>\<CR>"
+
+ set cpo-=<
+ inoremap <c-u> <left><c-u>
+ exe "normal Avim3\<C-U>\<Esc>\<CR>"
+ iunmap <c-u>
+ exe "normal Avim4\<C-U>\<C-U>\<Esc>\<CR>"
+
+ " Test with backspace set to the compatible setting
+ set backspace= visualbell
+ exe "normal A vim5\<Esc>A\<C-U>\<C-U>\<Esc>\<CR>"
+ exe "normal A vim6\<Esc>Azwei\<C-G>u\<C-U>\<Esc>\<CR>"
+
+ inoremap <c-u> <left><c-u>
+ exe "normal A vim7\<C-U>\<C-U>\<Esc>\<CR>"
+
+ call assert_equal([
+ \ "1 this shouldn't be deleted",
+ \ "2 this shouldn't be deleted",
+ \ "3 this shouldn't be deleted",
+ \ "4 this should be deleted3",
+ \ "",
+ \ "6 this shouldn't be deleted vim5",
+ \ "7 this shouldn't be deleted vim6",
+ \ "8 this shouldn't be deleted (not touched yet) vim7",
+ \ ""], getline(1, '$'))
+
+ " Reset values
+ set compatible&vim
+ set visualbell&vim
+ set backspace&vim
+
+ " Test new nostop option
+ %d_
+ let expected = "foo bar foobar"
+ call setline(1, expected)
+ call cursor(1, 8)
+ exe ":norm! ianotherone\<c-u>"
+ call assert_equal(expected, getline(1))
+ call cursor(1, 8)
+ exe ":norm! ianothertwo\<c-w>"
+ call assert_equal(expected, getline(1))
+
+ let content = getline(1)
+ for value in ['indent,nostop', 'eol,nostop', 'indent,eol,nostop', 'indent,eol,start,nostop']
+ exe ":set bs=".. value
+ %d _
+ call setline(1, content)
+ let expected = " foobar"
+ call cursor(1, 8)
+ exe ":norm! ianotherone\<c-u>"
+ call assert_equal(expected, getline(1), 'CTRL-U backspace value: '.. &bs)
+ let expected = "foo foobar"
+ call setline(1, content)
+ call cursor(1, 8)
+ exe ":norm! ianothertwo\<c-w>"
+ call assert_equal(expected, getline(1), 'CTRL-W backspace value: '.. &bs)
+ endfor
+
+ " Reset options
+ set compatible&vim
+ set visualbell&vim
+ set backspace&vim
+ close!
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_excmd.vim b/src/nvim/testdir/test_excmd.vim
index 4a027c3864..20508b12d3 100644
--- a/src/nvim/testdir/test_excmd.vim
+++ b/src/nvim/testdir/test_excmd.vim
@@ -1,5 +1,7 @@
" Tests for various Ex commands.
+source check.vim
+
func Test_ex_delete()
new
call setline(1, ['a', 'b', 'c'])
@@ -9,6 +11,17 @@ func Test_ex_delete()
call assert_equal(['a', 'c'], getline(1, 2))
endfunc
+func Test_range_error()
+ call assert_fails(':.echo 1', 'E481:')
+ call assert_fails(':$echo 1', 'E481:')
+ call assert_fails(':1,2echo 1', 'E481:')
+ call assert_fails(':+1echo 1', 'E481:')
+ call assert_fails(':/1/echo 1', 'E481:')
+ call assert_fails(':\/echo 1', 'E481:')
+ normal vv
+ call assert_fails(":'<,'>echo 1", 'E481:')
+endfunc
+
func Test_buffers_lastused()
edit bufc " oldest
@@ -40,3 +53,81 @@ func Test_buffers_lastused()
bwipeout bufb
bwipeout bufc
endfunc
+
+" Test for the :confirm command dialog
+func Test_confirm_cmd()
+ CheckNotGui
+ CheckRunVimInTerminal
+ call writefile(['foo1'], 'foo')
+ call writefile(['bar1'], 'bar')
+ " Test for saving all the modified buffers
+ let buf = RunVimInTerminal('', {'rows': 20})
+ call term_sendkeys(buf, ":set nomore\n")
+ call term_sendkeys(buf, ":new foo\n")
+ call term_sendkeys(buf, ":call setline(1, 'foo2')\n")
+ call term_sendkeys(buf, ":new bar\n")
+ call term_sendkeys(buf, ":call setline(1, 'bar2')\n")
+ call term_sendkeys(buf, ":wincmd b\n")
+ call term_sendkeys(buf, ":confirm qall\n")
+ call WaitForAssert({-> assert_match('\[Y\]es, (N)o, Save (A)ll, (D)iscard All, (C)ancel: ', term_getline(buf, 20))}, 1000)
+ call term_sendkeys(buf, "A")
+ call StopVimInTerminal(buf)
+ call assert_equal(['foo2'], readfile('foo'))
+ call assert_equal(['bar2'], readfile('bar'))
+ " Test for discarding all the changes to modified buffers
+ let buf = RunVimInTerminal('', {'rows': 20})
+ call term_sendkeys(buf, ":set nomore\n")
+ call term_sendkeys(buf, ":new foo\n")
+ call term_sendkeys(buf, ":call setline(1, 'foo3')\n")
+ call term_sendkeys(buf, ":new bar\n")
+ call term_sendkeys(buf, ":call setline(1, 'bar3')\n")
+ call term_sendkeys(buf, ":wincmd b\n")
+ call term_sendkeys(buf, ":confirm qall\n")
+ call WaitForAssert({-> assert_match('\[Y\]es, (N)o, Save (A)ll, (D)iscard All, (C)ancel: ', term_getline(buf, 20))}, 1000)
+ call term_sendkeys(buf, "D")
+ call StopVimInTerminal(buf)
+ call assert_equal(['foo2'], readfile('foo'))
+ call assert_equal(['bar2'], readfile('bar'))
+ " Test for saving and discarding changes to some buffers
+ let buf = RunVimInTerminal('', {'rows': 20})
+ call term_sendkeys(buf, ":set nomore\n")
+ call term_sendkeys(buf, ":new foo\n")
+ call term_sendkeys(buf, ":call setline(1, 'foo4')\n")
+ call term_sendkeys(buf, ":new bar\n")
+ call term_sendkeys(buf, ":call setline(1, 'bar4')\n")
+ call term_sendkeys(buf, ":wincmd b\n")
+ call term_sendkeys(buf, ":confirm qall\n")
+ call WaitForAssert({-> assert_match('\[Y\]es, (N)o, Save (A)ll, (D)iscard All, (C)ancel: ', term_getline(buf, 20))}, 1000)
+ call term_sendkeys(buf, "N")
+ call WaitForAssert({-> assert_match('\[Y\]es, (N)o, (C)ancel: ', term_getline(buf, 20))}, 1000)
+ call term_sendkeys(buf, "Y")
+ call StopVimInTerminal(buf)
+ call assert_equal(['foo4'], readfile('foo'))
+ call assert_equal(['bar2'], readfile('bar'))
+
+ call delete('foo')
+ call delete('bar')
+endfunc
+
+func Test_confirm_cmd_cancel()
+ CheckNotGui
+ CheckRunVimInTerminal
+
+ " Test for closing a window with a modified buffer
+ let buf = RunVimInTerminal('', {'rows': 20})
+ call term_sendkeys(buf, ":set nomore\n")
+ call term_sendkeys(buf, ":new\n")
+ call term_sendkeys(buf, ":call setline(1, 'abc')\n")
+ call term_sendkeys(buf, ":confirm close\n")
+ call WaitForAssert({-> assert_match('^\[Y\]es, (N)o, (C)ancel: *$',
+ \ term_getline(buf, 20))}, 1000)
+ call term_sendkeys(buf, "C")
+ call WaitForAssert({-> assert_equal('', term_getline(buf, 20))}, 1000)
+ call term_sendkeys(buf, ":confirm close\n")
+ call WaitForAssert({-> assert_match('^\[Y\]es, (N)o, (C)ancel: *$',
+ \ term_getline(buf, 20))}, 1000)
+ call term_sendkeys(buf, "N")
+ call WaitForAssert({-> assert_match('^ *0,0-1 All$',
+ \ term_getline(buf, 20))}, 1000)
+ call StopVimInTerminal(buf)
+endfunc
diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim
index 2123780f11..180170fe9a 100644
--- a/src/nvim/testdir/test_filetype.vim
+++ b/src/nvim/testdir/test_filetype.vim
@@ -150,6 +150,7 @@ let s:filename_checks = {
\ 'dsl': ['file.dsl'],
\ 'dtd': ['file.dtd'],
\ 'dts': ['file.dts', 'file.dtsi'],
+ \ 'dune': ['jbuild', 'dune', 'dune-project', 'dune-workspace'],
\ 'dylan': ['file.dylan'],
\ 'dylanintr': ['file.intr'],
\ 'dylanlid': ['file.lid'],
@@ -322,15 +323,16 @@ let s:filename_checks = {
\ 'nroff': ['file.tr', 'file.nr', 'file.roff', 'file.tmac', 'file.mom'],
\ 'nsis': ['file.nsi', 'file.nsh'],
\ 'obj': ['file.obj'],
- \ 'ocaml': ['file.ml', 'file.mli', 'file.mll', 'file.mly', '.ocamlinit'],
+ \ 'ocaml': ['file.ml', 'file.mli', 'file.mll', 'file.mly', '.ocamlinit', 'file.mlt', 'file.mlp', 'file.mlip', 'file.mli.cppo', 'file.ml.cppo'],
\ 'occam': ['file.occ'],
\ 'omnimark': ['file.xom', 'file.xin'],
+ \ 'opam': ['opam', 'file.opam', 'file.opam.template'],
\ 'openroad': ['file.or'],
\ 'ora': ['file.ora'],
\ 'pamconf': ['/etc/pam.conf'],
\ 'pamenv': ['/etc/security/pam_env.conf', '/home/user/.pam_environment'],
\ 'papp': ['file.papp', 'file.pxml', 'file.pxsl'],
- \ 'pascal': ['file.pas', 'file.pp', 'file.dpr', 'file.lpr'],
+ \ 'pascal': ['file.pas', 'file.dpr', 'file.lpr'],
\ 'passwd': ['any/etc/passwd', 'any/etc/passwd-', 'any/etc/passwd.edit', 'any/etc/shadow', 'any/etc/shadow-', 'any/etc/shadow.edit', 'any/var/backups/passwd.bak', 'any/var/backups/shadow.bak'],
\ 'pbtxt': ['file.pbtxt'],
\ 'pccts': ['file.g'],
@@ -366,6 +368,7 @@ let s:filename_checks = {
\ 'proto': ['file.proto'],
\ 'protocols': ['/etc/protocols'],
\ 'psf': ['file.psf'],
+ \ 'puppet': ['file.pp'],
\ 'pyrex': ['file.pyx', 'file.pxd'],
\ 'python': ['file.py', 'file.pyw', '.pythonstartup', '.pythonrc', 'file.ptl', 'file.pyi', 'SConstruct'],
\ 'quake': ['anybaseq2/file.cfg', 'anyid1/file.cfg', 'quake3/file.cfg'],
@@ -398,6 +401,7 @@ let s:filename_checks = {
\ 'scheme': ['file.scm', 'file.ss', 'file.rkt'],
\ 'scilab': ['file.sci', 'file.sce'],
\ 'screen': ['.screenrc', 'screenrc'],
+ \ 'sexplib': ['file.sexp'],
\ 'scss': ['file.scss'],
\ 'sd': ['file.sd'],
\ 'sdc': ['file.sdc'],
@@ -425,6 +429,7 @@ let s:filename_checks = {
\ 'smith': ['file.smt', 'file.smith'],
\ 'sml': ['file.sml'],
\ 'snobol4': ['file.sno', 'file.spt'],
+ \ 'sparql': ['file.rq', 'file.sparql'],
\ 'spec': ['file.spec'],
\ 'spice': ['file.sp', 'file.spice'],
\ 'spup': ['file.speedup', 'file.spdata', 'file.spd'],
@@ -616,6 +621,7 @@ let s:script_checks = {
\ 'cpp': [['// Standard iostream objects -*- C++ -*-'],
\ ['// -*- C++ -*-']],
\ 'yaml': [['%YAML 1.2']],
+ \ 'pascal': [['#!/path/instantfpc']],
\ }
" Various forms of "env" optional arguments.
@@ -686,5 +692,33 @@ func Test_ts_file()
filetype off
endfunc
+func Test_pp_file()
+ filetype on
+
+ call writefile(['looks like puppet'], 'Xfile.pp')
+ split Xfile.pp
+ call assert_equal('puppet', &filetype)
+ bwipe!
+
+ let g:filetype_pp = 'pascal'
+ split Xfile.pp
+ call assert_equal('pascal', &filetype)
+ bwipe!
+
+ " Test dist#ft#FTpp()
+ call writefile(['{ pascal comment'], 'Xfile.pp')
+ split Xfile.pp
+ call assert_equal('pascal', &filetype)
+ bwipe!
+
+ call writefile(['procedure pascal'], 'Xfile.pp')
+ split Xfile.pp
+ call assert_equal('pascal', &filetype)
+ bwipe!
+
+ call delete('Xfile.pp')
+ filetype off
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_find_complete.vim b/src/nvim/testdir/test_find_complete.vim
index a7bc135d47..0a00d9432f 100644
--- a/src/nvim/testdir/test_find_complete.vim
+++ b/src/nvim/testdir/test_find_complete.vim
@@ -15,22 +15,22 @@ func Test_find_complete()
new
set path=
- call assert_fails('call feedkeys(":find\t\n", "xt")', 'E345:')
+ call assert_fails('call feedkeys(":find \t\n", "xt")', 'E471:')
close
new
set path=.
- call assert_fails('call feedkeys(":find\t\n", "xt")', 'E32:')
+ call assert_fails('call feedkeys(":find \t\n", "xt")', 'E471:')
close
new
set path=.,,
- call assert_fails('call feedkeys(":find\t\n", "xt")', 'E32:')
+ call assert_fails('call feedkeys(":find \t\n", "xt")', 'E471:')
close
new
set path=./**
- call assert_fails('call feedkeys(":find\t\n", "xt")', 'E32:')
+ call assert_fails('call feedkeys(":find \t\n", "xt")', 'E471:')
close
" We shouldn't find any file till this point
diff --git a/src/nvim/testdir/test_findfile.vim b/src/nvim/testdir/test_findfile.vim
index f5488a6a27..2195bf527e 100644
--- a/src/nvim/testdir/test_findfile.vim
+++ b/src/nvim/testdir/test_findfile.vim
@@ -184,3 +184,46 @@ func Test_finddir_error()
call assert_fails('call finddir("x", "**x")', 'E343:')
call assert_fails('call finddir("x", repeat("x", 5000))', 'E854:')
endfunc
+
+" Test for the :find, :sfind and :tabfind commands
+func Test_find_cmd()
+ new
+ let save_path = &path
+ let save_dir = getcwd()
+ set path=.,./**/*
+ call CreateFiles()
+ cd Xdir1
+ " Test for :find
+ find foo
+ call assert_equal('foo', expand('%:.'))
+ 2find foo
+ call assert_equal('Xdir2/foo', expand('%:.'))
+ call assert_fails('3find foo', 'E347:')
+ " Test for :sfind
+ enew
+ sfind barfoo
+ call assert_equal('Xdir2/Xdir3/barfoo', expand('%:.'))
+ call assert_equal(3, winnr('$'))
+ close
+ call assert_fails('sfind baz', 'E345:')
+ call assert_equal(2, winnr('$'))
+ " Test for :tabfind
+ enew
+ tabfind foobar
+ call assert_equal('Xdir2/foobar', expand('%:.'))
+ call assert_equal(2, tabpagenr('$'))
+ tabclose
+ call assert_fails('tabfind baz', 'E345:')
+ call assert_equal(1, tabpagenr('$'))
+ " call chdir(save_dir)
+ exe 'cd ' . save_dir
+ call CleanFiles()
+ let &path = save_path
+ close
+
+ call assert_fails('find', 'E471:')
+ call assert_fails('sfind', 'E471:')
+ call assert_fails('tabfind', 'E471:')
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_hardcopy.vim b/src/nvim/testdir/test_hardcopy.vim
index 6125f9b993..e390bd5cc8 100644
--- a/src/nvim/testdir/test_hardcopy.vim
+++ b/src/nvim/testdir/test_hardcopy.vim
@@ -1,5 +1,7 @@
" Test :hardcopy
+source check.vim
+
func Test_printoptions()
edit test_hardcopy.vim
syn on
@@ -8,8 +10,10 @@ func Test_printoptions()
\ 'left:2in,top:30pt,right:16mm,bottom:3pc',
\ 'header:3,syntax:y,number:y,wrap:n',
\ 'header:3,syntax:n,number:y,wrap:y',
+ \ 'header:0,syntax:a,number:y,wrap:y',
\ 'duplex:short,collate:n,jobsplit:y,portrait:n',
\ 'duplex:long,collate:y,jobsplit:n,portrait:y',
+ \ 'duplex:off,collate:y,jobsplit:y,portrait:y',
\ 'paper:10x14',
\ 'paper:A3',
\ 'paper:A4',
@@ -28,7 +32,7 @@ func Test_printoptions()
\ '']
exe 'set printoptions=' .. opt
if has('postscript')
- hardcopy > Xhardcopy_printoptions
+ 1,50hardcopy > Xhardcopy_printoptions
let lines = readfile('Xhardcopy_printoptions')
call assert_true(len(lines) > 20, opt)
call assert_true(lines[0] =~ 'PS-Adobe', opt)
@@ -44,8 +48,8 @@ func Test_printoptions()
endfunc
func Test_printmbfont()
- " Print a small help page which contains tabs to cover code that expands tabs to spaces.
- help help
+ " Print a help page which contains tabs, underlines (etc) to recover more code.
+ help syntax.txt
syn on
for opt in [':WadaMin-Regular,b:WadaMin-Bold,i:WadaMin-Italic,o:WadaMin-Bold-Italic,c:yes,a:no',
@@ -63,10 +67,39 @@ func Test_printmbfont()
bwipe
endfunc
+func Test_printmbcharset()
+ CheckFeature postscript
+
+ " digraph.txt has plenty of non-latin1 characters.
+ help digraph.txt
+ set printmbcharset=ISO10646 printencoding=utf-8
+ for courier in ['yes', 'no']
+ for ascii in ['yes', 'no']
+ exe 'set printmbfont=r:WadaMin-Regular,b:WadaMin-Bold,i:WadaMin-Italic,o:WadaMin-BoldItalic'
+ \ .. ',c:' .. courier .. ',a:' .. ascii
+ hardcopy > Xhardcopy_printmbcharset
+ let lines = readfile('Xhardcopy_printmbcharset')
+ call assert_true(len(lines) > 20)
+ call assert_true(lines[0] =~ 'PS-Adobe')
+ endfor
+ endfor
+
+ set printmbcharset=does-not-exist printencoding=utf-8 printmbfont=r:WadaMin-Regular
+ call assert_fails('hardcopy > Xhardcopy_printmbcharset', 'E456:')
+
+ set printmbcharset=GB_2312-80 printencoding=utf-8 printmbfont=r:WadaMin-Regular
+ call assert_fails('hardcopy > Xhardcopy_printmbcharset', 'E673:')
+
+ set printmbcharset=ISO10646 printencoding=utf-8 printmbfont=
+ call assert_fails('hardcopy > Xhardcopy_printmbcharset', 'E675:')
+
+ call delete('Xhardcopy_printmbcharset')
+ set printmbcharset& printencoding& printmbfont&
+ bwipe
+endfunc
+
func Test_printexpr()
- if !has('unix')
- return
- endif
+ CheckFeature postscript
" Not a very useful printexpr value, but enough to test
" hardcopy with 'printexpr'.
@@ -84,7 +117,7 @@ func Test_printexpr()
\ readfile('Xhardcopy_printexpr'))
call delete('Xhardcopy_printexpr')
- " Function return 1 to test print failure.
+ " Function returns 1 to test print failure.
function PrintFails(fname)
call delete(a:fname)
return 1
@@ -97,12 +130,11 @@ func Test_printexpr()
endfunc
func Test_errors()
- " FIXME: Windows fails differently than Unix.
- if has('unix')
- edit test_hardcopy.vim
- call assert_fails('hardcopy >', 'E324:')
- bwipe
- endif
+ CheckFeature postscript
+
+ edit test_hardcopy.vim
+ call assert_fails('hardcopy >', 'E324:')
+ bwipe
endfunc
func Test_dark_background()
@@ -126,12 +158,11 @@ func Test_dark_background()
endfun
func Test_empty_buffer()
- " FIXME: Unclear why this fails on Windows.
- if has('unix')
- new
- call assert_equal("\nNo text to be printed", execute('hardcopy'))
- bwipe
- endif
+ CheckFeature postscript
+
+ new
+ call assert_equal("\nNo text to be printed", execute('hardcopy'))
+ bwipe
endfunc
func Test_printheader_parsing()
@@ -145,9 +176,8 @@ func Test_printheader_parsing()
endfunc
func Test_fname_with_spaces()
- if !has('postscript')
- return
- endif
+ CheckFeature postscript
+
split t\ e\ s\ t.txt
call setline(1, ['just', 'some', 'text'])
hardcopy > %.ps
@@ -157,9 +187,11 @@ func Test_fname_with_spaces()
endfunc
func Test_illegal_byte()
- if !has('postscript') || &enc != 'utf-8'
+ CheckFeature postscript
+ if &enc != 'utf-8'
return
endif
+
new
" conversion of 0xff will fail, this used to cause a crash
call setline(1, "\xff")
@@ -168,3 +200,5 @@ func Test_illegal_byte()
bwipe!
call delete('Xpstest')
endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_marks.vim b/src/nvim/testdir/test_marks.vim
index 66df57ea39..2fd82a4b6d 100644
--- a/src/nvim/testdir/test_marks.vim
+++ b/src/nvim/testdir/test_marks.vim
@@ -171,6 +171,11 @@ func Test_delmarks()
" Deleting an already deleted mark should not fail.
delmarks x
+ " getpos() should return all zeros after deleting a filemark.
+ norm mA
+ delmarks A
+ call assert_equal([0, 0, 0, 0], getpos("'A"))
+
" Test deleting a range of marks.
norm ma
norm mb
@@ -201,3 +206,28 @@ func Test_mark_error()
call assert_fails('mark xx', 'E488:')
call assert_fails('mark _', 'E191:')
endfunc
+
+" Test for the getmarklist() function
+func Test_getmarklist()
+ new
+ " global marks
+ delmarks A-Z 0-9 \" ^.[]
+ call assert_equal([], getmarklist())
+ call setline(1, ['one', 'two', 'three'])
+ mark A
+ call cursor(3, 5)
+ normal mN
+ call assert_equal([{'file' : '', 'mark' : "'A", 'pos' : [bufnr(), 1, 1, 0]},
+ \ {'file' : '', 'mark' : "'N", 'pos' : [bufnr(), 3, 5, 0]}],
+ \ getmarklist())
+ " buffer local marks
+ delmarks!
+ call assert_equal([{'mark' : "''", 'pos' : [bufnr(), 1, 1, 0]},
+ \ {'mark' : "'\"", 'pos' : [bufnr(), 1, 1, 0]}], getmarklist(bufnr()))
+ call cursor(2, 2)
+ normal mr
+ call assert_equal({'mark' : "'r", 'pos' : [bufnr(), 2, 2, 0]},
+ \ getmarklist(bufnr())[0])
+ call assert_equal([], getmarklist({}))
+ close!
+endfunc
diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim
index ccc5e6ffc9..84d99ebb74 100644
--- a/src/nvim/testdir/test_options.vim
+++ b/src/nvim/testdir/test_options.vim
@@ -266,8 +266,14 @@ func Test_set_errors()
call assert_fails('set foldmarker=x', 'E536:')
call assert_fails('set commentstring=x', 'E537:')
call assert_fails('set complete=x', 'E539:')
+ call assert_fails('set rulerformat=%-', 'E539:')
+ call assert_fails('set rulerformat=%(', 'E542:')
+ call assert_fails('set rulerformat=%15(%%', 'E542:')
+ call assert_fails('set statusline=%$', 'E539:')
call assert_fails('set statusline=%{', 'E540:')
call assert_fails('set statusline=%(', 'E542:')
+ call assert_fails('set statusline=%)', 'E542:')
+
if has('cursorshape')
" This invalid value for 'guicursor' used to cause Vim to crash.
call assert_fails('set guicursor=i-ci,r-cr:h', 'E545:')
@@ -281,6 +287,21 @@ func Test_set_errors()
call assert_fails('set winminwidth=10 winwidth=9', 'E592:')
call assert_fails("set showbreak=\x01", 'E595:')
call assert_fails('set t_foo=', 'E846:')
+ if has('python') || has('python3')
+ call assert_fails('set pyxversion=6', 'E474:')
+ endif
+ call assert_fails("let &tabstop='ab'", 'E521:')
+ call assert_fails('set sessionoptions=curdir,sesdir', 'E474:')
+ call assert_fails('set foldmarker={{{,', 'E474:')
+ call assert_fails('set sessionoptions=sesdir,curdir', 'E474:')
+ call assert_fails('set listchars=trail:· ambiwidth=double', 'E834:')
+ set listchars&
+ call assert_fails('set fillchars=stl:· ambiwidth=double', 'E835:')
+ set fillchars&
+ call assert_fails('set fileencoding=latin1,utf-8', 'E474:')
+ set nomodifiable
+ call assert_fails('set fileencoding=latin1', 'E21:')
+ set modifiable&
endfunc
" Must be executed before other tests that set 'term'.
diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim
index 563dbd90d9..48c0a83053 100644
--- a/src/nvim/testdir/test_quickfix.vim
+++ b/src/nvim/testdir/test_quickfix.vim
@@ -29,7 +29,7 @@ func s:setup_commands(cchar)
command! -count -nargs=* -bang Xprev <mods><count>cprev<bang> <args>
command! -nargs=* -bang Xfirst <mods>cfirst<bang> <args>
command! -nargs=* -bang Xlast <mods>clast<bang> <args>
- command! -nargs=* -bang -range Xnfile <mods><count>cnfile<bang> <args>
+ command! -count -nargs=* -bang Xnfile <mods><count>cnfile<bang> <args>
command! -nargs=* -bang Xpfile <mods>cpfile<bang> <args>
command! -nargs=* Xexpr <mods>cexpr <args>
command! -range -nargs=* Xvimgrep <mods><count>vimgrep <args>
@@ -40,6 +40,8 @@ func s:setup_commands(cchar)
command! -nargs=0 -count Xcc <count>cc
command! -count=1 -nargs=0 Xbelow <mods><count>cbelow
command! -count=1 -nargs=0 Xabove <mods><count>cabove
+ command! -count=1 -nargs=0 Xbefore <mods><count>cbefore
+ command! -count=1 -nargs=0 Xafter <mods><count>cafter
let g:Xgetlist = function('getqflist')
let g:Xsetlist = function('setqflist')
call setqflist([], 'f')
@@ -64,7 +66,7 @@ func s:setup_commands(cchar)
command! -count -nargs=* -bang Xprev <mods><count>lprev<bang> <args>
command! -nargs=* -bang Xfirst <mods>lfirst<bang> <args>
command! -nargs=* -bang Xlast <mods>llast<bang> <args>
- command! -nargs=* -bang -range Xnfile <mods><count>lnfile<bang> <args>
+ command! -count -nargs=* -bang Xnfile <mods><count>lnfile<bang> <args>
command! -nargs=* -bang Xpfile <mods>lpfile<bang> <args>
command! -nargs=* Xexpr <mods>lexpr <args>
command! -range -nargs=* Xvimgrep <mods><count>lvimgrep <args>
@@ -75,6 +77,8 @@ func s:setup_commands(cchar)
command! -nargs=0 -count Xcc <count>ll
command! -count=1 -nargs=0 Xbelow <mods><count>lbelow
command! -count=1 -nargs=0 Xabove <mods><count>labove
+ command! -count=1 -nargs=0 Xbefore <mods><count>lbefore
+ command! -count=1 -nargs=0 Xafter <mods><count>lafter
let g:Xgetlist = function('getloclist', [0])
let g:Xsetlist = function('setloclist', [0])
call setloclist(0, [], 'f')
@@ -260,6 +264,9 @@ func XwindowTests(cchar)
\ winheight('.') == 7 &&
\ getline('.') ==# '|| non-error 1')
+ " :cnext in quickfix window should move to the next entry
+ Xnext
+ call assert_equal(2, g:Xgetlist({'idx' : 0}).idx)
" Calling cwindow should close the quickfix window with no valid errors
Xwindow
@@ -431,13 +438,19 @@ func Xtest_browse(cchar)
" result in failure
if a:cchar == 'c'
let err = 'E42:'
+ let cmd = '$cc'
else
let err = 'E776:'
+ let cmd = '$ll'
endif
call assert_fails('Xnext', err)
call assert_fails('Xprev', err)
call assert_fails('Xnfile', err)
call assert_fails('Xpfile', err)
+ call assert_fails(cmd, err)
+
+ Xexpr ''
+ call assert_fails(cmd, 'E42:')
call s:create_test_file('Xqftestfile1')
call s:create_test_file('Xqftestfile2')
@@ -1247,6 +1260,36 @@ func Test_efm2()
let &efm = save_efm
endfunc
+" Test for '%t' (error type) field in 'efm'
+func Test_efm_error_type()
+ let save_efm = &efm
+
+ " error type
+ set efm=%f:%l:%t:%m
+ cexpr ["Xfile1:10:E:msg1", "Xfile1:20:W:msg2", "Xfile1:30:I:msg3",
+ \ "Xfile1:40:N:msg4", "Xfile1:50:R:msg5"]
+ let output = split(execute('clist'), "\n")
+ call assert_equal([
+ \ ' 1 Xfile1:10 error: msg1',
+ \ ' 2 Xfile1:20 warning: msg2',
+ \ ' 3 Xfile1:30 info: msg3',
+ \ ' 4 Xfile1:40 note: msg4',
+ \ ' 5 Xfile1:50 R: msg5'], output)
+
+ " error type and a error number
+ set efm=%f:%l:%t:%n:%m
+ cexpr ["Xfile1:10:E:2:msg1", "Xfile1:20:W:4:msg2", "Xfile1:30:I:6:msg3",
+ \ "Xfile1:40:N:8:msg4", "Xfile1:50:R:3:msg5"]
+ let output = split(execute('clist'), "\n")
+ call assert_equal([
+ \ ' 1 Xfile1:10 error 2: msg1',
+ \ ' 2 Xfile1:20 warning 4: msg2',
+ \ ' 3 Xfile1:30 info 6: msg3',
+ \ ' 4 Xfile1:40 note 8: msg4',
+ \ ' 5 Xfile1:50 R 3: msg5'], output)
+ let &efm = save_efm
+endfunc
+
func XquickfixChangedByAutocmd(cchar)
call s:setup_commands(a:cchar)
if a:cchar == 'c'
@@ -1810,14 +1853,27 @@ func s:test_xgrep(cchar)
enew! | only
set makeef&vim
silent Xgrep Grep_Test_Text: test_quickfix.vim
- call assert_true(len(g:Xgetlist()) == 3)
+ call assert_true(len(g:Xgetlist()) == 5)
Xopen
call assert_true(w:quickfix_title =~ '^:grep')
Xclose
enew
set makeef=Temp_File_##
silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim
- call assert_true(len(g:Xgetlist()) == 6)
+
+ " Try with 'grepprg' set to 'internal'
+ set grepprg=internal
+ silent Xgrep Grep_Test_Text: test_quickfix.vim
+ silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim
+ call assert_true(len(g:Xgetlist()) == 9)
+ set grepprg&vim
+
+ call writefile(['Vim'], 'XtestTempFile')
+ set makeef=XtestTempFile
+ silent Xgrep Grep_Test_Text: test_quickfix.vim
+ call assert_equal(5, len(g:Xgetlist()))
+ call assert_false(filereadable('XtestTempFile'))
+ set makeef&vim
endfunc
func Test_grep()
@@ -1914,9 +1970,23 @@ func HistoryTest(cchar)
call assert_equal(' error list 2 of 3; 2 ' . common, res[1])
call assert_equal('> error list 3 of 3; 3 ' . common, res[2])
+ " Test for changing the quickfix lists
+ call assert_equal(3, g:Xgetlist({'nr' : 0}).nr)
+ exe '1' . a:cchar . 'hist'
+ call assert_equal(1, g:Xgetlist({'nr' : 0}).nr)
+ exe '3' . a:cchar . 'hist'
+ call assert_equal(3, g:Xgetlist({'nr' : 0}).nr)
+ call assert_fails('-2' . a:cchar . 'hist', 'E16:')
+ call assert_fails('4' . a:cchar . 'hist', 'E16:')
+
call g:Xsetlist([], 'f')
let l = split(execute(a:cchar . 'hist'), "\n")
call assert_equal('No entries', l[0])
+ if a:cchar == 'c'
+ call assert_fails('4chist', 'E16:')
+ else
+ call assert_fails('4lhist', 'E776:')
+ endif
" An empty list should still show the stack history
call g:Xsetlist([])
@@ -2365,14 +2435,28 @@ func Test_Autocmd()
silent grepadd GrepAdd_Autocmd_Text test_quickfix.vim
silent grep abc123def Xtest
silent grepadd abc123def Xtest
+ set grepprg=internal
+ silent grep Grep_Autocmd_Text test_quickfix.vim
+ silent grepadd GrepAdd_Autocmd_Text test_quickfix.vim
+ silent lgrep Grep_Autocmd_Text test_quickfix.vim
+ silent lgrepadd GrepAdd_Autocmd_Text test_quickfix.vim
+ set grepprg&vim
let l = ['pregrep',
- \ 'postgrep',
- \ 'pregrepadd',
- \ 'postgrepadd',
- \ 'pregrep',
- \ 'postgrep',
- \ 'pregrepadd',
- \ 'postgrepadd']
+ \ 'postgrep',
+ \ 'pregrepadd',
+ \ 'postgrepadd',
+ \ 'pregrep',
+ \ 'postgrep',
+ \ 'pregrepadd',
+ \ 'postgrepadd',
+ \ 'pregrep',
+ \ 'postgrep',
+ \ 'pregrepadd',
+ \ 'postgrepadd',
+ \ 'prelgrep',
+ \ 'postlgrep',
+ \ 'prelgrepadd',
+ \ 'postlgrepadd']
call assert_equal(l, g:acmds)
endif
@@ -2491,6 +2575,19 @@ 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
+ " window by wrapping around the window list.
+ enew | only
+ call setloclist(0, [], 'f')
+ new | new
+ lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
+ lopen
+ 1close
+ call assert_equal(0, getloclist(3, {'id' : 0}).id)
+ lnext
+ call assert_equal(3, winnr())
+ call assert_equal(getloclist(1, {'id' : 0}).id, getloclist(3, {'id' : 0}).id)
+
enew | only
set efm&vim
endfunc
@@ -4201,17 +4298,22 @@ func Test_empty_qfbuf()
endfunc
" Test for the :cbelow, :cabove, :lbelow and :labove commands.
+" And for the :cafter, :cbefore, :lafter and :lbefore commands.
func Xtest_below(cchar)
call s:setup_commands(a:cchar)
" No quickfix/location list
call assert_fails('Xbelow', 'E42:')
call assert_fails('Xabove', 'E42:')
+ call assert_fails('Xbefore', 'E42:')
+ call assert_fails('Xafter', 'E42:')
" Empty quickfix/location list
call g:Xsetlist([])
call assert_fails('Xbelow', 'E42:')
call assert_fails('Xabove', 'E42:')
+ call assert_fails('Xbefore', 'E42:')
+ call assert_fails('Xafter', 'E42:')
call s:create_test_file('X1')
call s:create_test_file('X2')
@@ -4225,39 +4327,74 @@ func Xtest_below(cchar)
call assert_fails('Xabove', 'E42:')
call assert_fails('3Xbelow', 'E42:')
call assert_fails('4Xabove', 'E42:')
+ call assert_fails('Xbefore', 'E42:')
+ call assert_fails('Xafter', 'E42:')
+ call assert_fails('3Xbefore', 'E42:')
+ call assert_fails('4Xafter', 'E42:')
" Test the commands with various arguments
- Xexpr ["X1:5:L5", "X2:5:L5", "X2:10:L10", "X2:15:L15", "X3:3:L3"]
+ Xexpr ["X1:5:3:L5", "X2:5:2:L5", "X2:10:3:L10", "X2:15:4:L15", "X3:3:5:L3"]
edit +7 X2
Xabove
call assert_equal(['X2', 5], [bufname(''), line('.')])
call assert_fails('Xabove', 'E553:')
+ normal 7G
+ Xbefore
+ call assert_equal(['X2', 5, 2], [bufname(''), line('.'), col('.')])
+ call assert_fails('Xbefore', 'E553:')
+
normal 2j
Xbelow
call assert_equal(['X2', 10], [bufname(''), line('.')])
+ normal 7G
+ Xafter
+ call assert_equal(['X2', 10, 3], [bufname(''), line('.'), col('.')])
+
" Last error in this file
Xbelow 99
call assert_equal(['X2', 15], [bufname(''), line('.')])
call assert_fails('Xbelow', 'E553:')
+ normal gg
+ Xafter 99
+ call assert_equal(['X2', 15, 4], [bufname(''), line('.'), col('.')])
+ call assert_fails('Xafter', 'E553:')
+
" First error in this file
Xabove 99
call assert_equal(['X2', 5], [bufname(''), line('.')])
call assert_fails('Xabove', 'E553:')
+ normal G
+ Xbefore 99
+ call assert_equal(['X2', 5, 2], [bufname(''), line('.'), col('.')])
+ call assert_fails('Xbefore', 'E553:')
+
normal gg
Xbelow 2
call assert_equal(['X2', 10], [bufname(''), line('.')])
+ normal gg
+ Xafter 2
+ call assert_equal(['X2', 10, 3], [bufname(''), line('.'), col('.')])
+
normal G
Xabove 2
call assert_equal(['X2', 10], [bufname(''), line('.')])
+ normal G
+ Xbefore 2
+ call assert_equal(['X2', 10, 3], [bufname(''), line('.'), col('.')])
+
edit X4
call assert_fails('Xabove', 'E42:')
call assert_fails('Xbelow', 'E42:')
+ call assert_fails('Xbefore', 'E42:')
+ call assert_fails('Xafter', 'E42:')
if a:cchar == 'l'
" If a buffer has location list entries from some other window but not
" from the current window, then the commands should fail.
edit X1 | split | call setloclist(0, [], 'f')
call assert_fails('Xabove', 'E776:')
call assert_fails('Xbelow', 'E776:')
+ call assert_fails('Xbefore', 'E776:')
+ call assert_fails('Xafter', 'E776:')
close
endif
@@ -4268,31 +4405,52 @@ func Xtest_below(cchar)
edit +1 X2
Xbelow 2
call assert_equal(['X2', 10, 1], [bufname(''), line('.'), col('.')])
+ normal 1G
+ Xafter 2
+ call assert_equal(['X2', 5, 2], [bufname(''), line('.'), col('.')])
+
normal gg
Xbelow 99
call assert_equal(['X2', 15, 1], [bufname(''), line('.'), col('.')])
+ normal gg
+ Xafter 99
+ call assert_equal(['X2', 15, 3], [bufname(''), line('.'), col('.')])
+
normal G
Xabove 2
call assert_equal(['X2', 10, 1], [bufname(''), line('.'), col('.')])
normal G
+ Xbefore 2
+ call assert_equal(['X2', 15, 2], [bufname(''), line('.'), col('.')])
+
+ normal G
Xabove 99
call assert_equal(['X2', 5, 1], [bufname(''), line('.'), col('.')])
+ normal G
+ Xbefore 99
+ call assert_equal(['X2', 5, 1], [bufname(''), line('.'), col('.')])
+
normal 10G
Xabove
call assert_equal(['X2', 5, 1], [bufname(''), line('.'), col('.')])
+ normal 10G$
+ 2Xbefore
+ call assert_equal(['X2', 10, 2], [bufname(''), line('.'), col('.')])
+
normal 10G
Xbelow
call assert_equal(['X2', 15, 1], [bufname(''), line('.'), col('.')])
+ normal 9G
+ 5Xafter
+ call assert_equal(['X2', 15, 2], [bufname(''), line('.'), col('.')])
" Invalid range
if a:cchar == 'c'
- call assert_fails('-2cbelow', 'E553:')
- " TODO: should go to first error in the current line?
- 0cabove
+ call assert_fails('-2cbelow', 'E16:')
+ call assert_fails('-2cafter', 'E16:')
else
- call assert_fails('-2lbelow', 'E553:')
- " TODO: should go to first error in the current line?
- 0labove
+ call assert_fails('-2lbelow', 'E16:')
+ call assert_fails('-2lafter', 'E16:')
endif
call delete('X1')
@@ -4306,6 +4464,42 @@ func Test_cbelow()
call Xtest_below('l')
endfunc
+func Test_quickfix_count()
+ let commands = [
+ \ 'cNext',
+ \ 'cNfile',
+ \ 'cabove',
+ \ 'cbelow',
+ \ 'cfirst',
+ \ 'clast',
+ \ 'cnewer',
+ \ 'cnext',
+ \ 'cnfile',
+ \ 'colder',
+ \ 'cprevious',
+ \ 'crewind',
+ \
+ \ 'lNext',
+ \ 'lNfile',
+ \ 'labove',
+ \ 'lbelow',
+ \ 'lfirst',
+ \ 'llast',
+ \ 'lnewer',
+ \ 'lnext',
+ \ 'lnfile',
+ \ 'lolder',
+ \ 'lprevious',
+ \ 'lrewind',
+ \ ]
+ for cmd in commands
+ call assert_fails('-1' .. cmd, 'E16:')
+ call assert_fails('.' .. cmd, 'E16:')
+ call assert_fails('%' .. cmd, 'E16:')
+ call assert_fails('$' .. cmd, 'E16:')
+ endfor
+endfunc
+
" Test for aborting quickfix commands using QuickFixCmdPre
func Xtest_qfcmd_abort(cchar)
call s:setup_commands(a:cchar)
@@ -4461,6 +4655,24 @@ func Test_cquit()
call assert_fails('-3cquit', 'E16:')
endfunc
+" Running :lhelpgrep command more than once in a help window, doesn't jump to
+" the help topic
+func Test_lhelpgrep_from_help_window()
+ call mkdir('Xtestdir/doc', 'p')
+ call writefile(['window'], 'Xtestdir/doc/a.txt')
+ call writefile(['buffer'], 'Xtestdir/doc/b.txt')
+ let save_rtp = &rtp
+ let &rtp = 'Xtestdir'
+ lhelpgrep window
+ lhelpgrep buffer
+ call assert_equal('b.txt', fnamemodify(@%, ":p:t"))
+ lhelpgrep window
+ call assert_equal('a.txt', fnamemodify(@%, ":p:t"))
+ let &rtp = save_rtp
+ call delete('Xtestdir', 'rf')
+ new | only!
+endfunc
+
" Test for adding an invalid entry with the quickfix window open and making
" sure that the window contents are not changed
func Test_add_invalid_entry_with_qf_window()
diff --git a/src/nvim/testdir/test_sleep.vim b/src/nvim/testdir/test_sleep.vim
new file mode 100644
index 0000000000..f71855fd4b
--- /dev/null
+++ b/src/nvim/testdir/test_sleep.vim
@@ -0,0 +1,26 @@
+" Test for sleep and sleep! commands
+
+func! s:get_time_ms()
+ let timestr = reltimestr(reltime())
+ let dotidx = stridx(timestr, '.')
+ let sec = str2nr(timestr[:dotidx])
+ let msec = str2nr(timestr[dotidx + 1:])
+ return (sec * 1000) + (msec / 1000)
+endfunc
+
+func! s:assert_takes_longer(cmd, time_ms)
+ let start = s:get_time_ms()
+ execute a:cmd
+ let end = s:get_time_ms()
+ call assert_true(end - start >=# a:time_ms)
+endfun
+
+func! Test_sleep_bang()
+ call s:assert_takes_longer('sleep 50m', 50)
+ call s:assert_takes_longer('sleep! 50m', 50)
+ call s:assert_takes_longer('sl 50m', 50)
+ call s:assert_takes_longer('sl! 50m', 50)
+ call s:assert_takes_longer('1sleep', 1000)
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_startup.vim b/src/nvim/testdir/test_startup.vim
index e7f332bc4c..e6ad92f483 100644
--- a/src/nvim/testdir/test_startup.vim
+++ b/src/nvim/testdir/test_startup.vim
@@ -735,4 +735,82 @@ func Test_x_arg()
call delete('Xtest_x_arg')
endfunc
+" Test starting vim with various names: vim, ex, view, evim, etc.
+func Test_progname()
+ CheckUnix
+
+ call mkdir('Xprogname', 'p')
+ call writefile(['silent !date',
+ \ 'call writefile([mode(1), '
+ \ .. '&insertmode, &diff, &readonly, &updatecount, '
+ \ .. 'join(split(execute("message"), "\n")[1:])], "Xprogname_out")',
+ \ 'qall'], 'Xprogname_after')
+
+ " +---------------------------------------------- progname
+ " | +--------------------------------- mode(1)
+ " | | +--------------------------- &insertmode
+ " | | | +---------------------- &diff
+ " | | | | +----------------- &readonly
+ " | | | | | +-------- &updatecount
+ " | | | | | | +--- :messages
+ " | | | | | | |
+ " let expectations = {
+ " \ 'vim': ['n', '0', '0', '0', '200', ''],
+ " \ 'gvim': ['n', '0', '0', '0', '200', ''],
+ " \ 'ex': ['ce', '0', '0', '0', '200', ''],
+ " \ 'exim': ['cv', '0', '0', '0', '200', ''],
+ " \ 'view': ['n', '0', '0', '1', '10000', ''],
+ " \ 'gview': ['n', '0', '0', '1', '10000', ''],
+ " \ 'evim': ['n', '1', '0', '0', '200', ''],
+ " \ 'eview': ['n', '1', '0', '1', '10000', ''],
+ " \ 'rvim': ['n', '0', '0', '0', '200', 'line 1: E145: Shell commands and some functionality not allowed in rvim'],
+ " \ 'rgvim': ['n', '0', '0', '0', '200', 'line 1: E145: Shell commands and some functionality not allowed in rvim'],
+ " \ 'rview': ['n', '0', '0', '1', '10000', 'line 1: E145: Shell commands and some functionality not allowed in rvim'],
+ " \ 'rgview': ['n', '0', '0', '1', '10000', 'line 1: E145: Shell commands and some functionality not allowed in rvim'],
+ " \ 'vimdiff': ['n', '0', '1', '0', '200', ''],
+ " \ 'gvimdiff': ['n', '0', '1', '0', '200', '']}
+ let expectations = {'nvim': ['n', '0', '0', '0', '200', '']}
+
+ " let prognames = ['vim', 'gvim', 'ex', 'exim', 'view', 'gview',
+ " \ 'evim', 'eview', 'rvim', 'rgvim', 'rview', 'rgview',
+ " \ 'vimdiff', 'gvimdiff']
+ let prognames = ['nvim']
+
+ for progname in prognames
+ if empty($DISPLAY)
+ if progname =~# 'g'
+ " Can't run gvim, gview (etc.) if $DISPLAY is not setup.
+ continue
+ endif
+ if has('gui') && (progname ==# 'evim' || progname ==# 'eview')
+ " evim or eview will start the GUI if there is gui support.
+ " So don't try to start them either if $DISPLAY is not setup.
+ continue
+ endif
+ endif
+
+ exe 'silent !ln -s -f ' ..exepath(GetVimProg()) .. ' Xprogname/' .. progname
+
+ let stdout_stderr = ''
+ if progname =~# 'g'
+ let stdout_stderr = system('Xprogname/'..progname..' -f --clean --not-a-term -S Xprogname_after')
+ else
+ exe 'sil !Xprogname/'..progname..' -f --clean -S Xprogname_after'
+ endif
+
+ if progname =~# 'g' && !has('gui')
+ call assert_equal("E25: GUI cannot be used: Not enabled at compile time\n", stdout_stderr, progname)
+ else
+ call assert_equal('', stdout_stderr, progname)
+ call assert_equal(expectations[progname], readfile('Xprogname_out'), progname)
+ endif
+
+ call delete('Xprogname/' .. progname)
+ call delete('Xprogname_out')
+ endfor
+
+ call delete('Xprogname_after')
+ call delete('Xprogname', 'd')
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_usercommands.vim b/src/nvim/testdir/test_usercommands.vim
index 0a89066a2b..4621207d19 100644
--- a/src/nvim/testdir/test_usercommands.vim
+++ b/src/nvim/testdir/test_usercommands.vim
@@ -393,9 +393,13 @@ func Test_addr_all()
call assert_equal(len(gettabinfo()), g:a2)
bwipe
- command! -addr=other DoSomething echo 'nothing'
+ command! -addr=other DoSomething let g:a1 = <line1> | let g:a2 = <line2>
DoSomething
- call assert_fails('%DoSomething')
+ call assert_equal(line('.'), g:a1)
+ call assert_equal(line('.'), g:a2)
+ %DoSomething
+ call assert_equal(1, g:a1)
+ call assert_equal(line('$'), g:a2)
delcommand DoSomething
endfunc
@@ -421,7 +425,7 @@ func Test_command_list()
\ execute('command DoCmd'))
command! -count=2 DoCmd :
call assert_equal("\n Name Args Address Complete Definition"
- \ .. "\n DoCmd 0 2c :",
+ \ .. "\n DoCmd 0 2c ? :",
\ execute('command DoCmd'))
" Test with various -addr= argument values.
diff --git a/src/nvim/testdir/test_window_cmd.vim b/src/nvim/testdir/test_window_cmd.vim
index bed39d0741..687b1cb989 100644
--- a/src/nvim/testdir/test_window_cmd.vim
+++ b/src/nvim/testdir/test_window_cmd.vim
@@ -856,7 +856,7 @@ func Test_window_resize()
wincmd l
let other_winnr = winnr('h')
call assert_notequal(winnr(), other_winnr)
- exe 'vert ' .. other_winnr .. 'resize -100'
+ exe 'vert ' .. other_winnr .. 'resize -' .. &columns
call assert_equal(0, winwidth(other_winnr))
%bwipe!
diff --git a/test/functional/api/keymap_spec.lua b/test/functional/api/keymap_spec.lua
index d8a9c3b411..4194945645 100644
--- a/test/functional/api/keymap_spec.lua
+++ b/test/functional/api/keymap_spec.lua
@@ -809,4 +809,9 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
command('normal lhs')
eq({'rhs'}, bufmeths.get_lines(0, 0, 1, 1))
end)
+
+ it("does not crash when setting keymap in a non-existing buffer #13541", function()
+ pcall_err(bufmeths.set_keymap, 100, '', 'lsh', 'irhs<Esc>', {})
+ helpers.assert_alive()
+ end)
end)
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index c42d5c34cc..1d8ffc2087 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -972,6 +972,12 @@ describe('API', function()
nvim("input", "gu")
eq({mode='no', blocking=false}, nvim("get_mode"))
end)
+
+ it("at '-- More --' prompt returns blocking=true #11899", function()
+ command('set more')
+ feed(':digraphs<cr>')
+ eq({mode='rm', blocking=true}, nvim("get_mode"))
+ end)
end)
describe('RPC (K_EVENT) #6166', function()
@@ -1996,4 +2002,63 @@ describe('API', function()
}, meths.get_option_info'showcmd')
end)
end)
+
+ describe('nvim_echo', function()
+ local screen
+
+ before_each(function()
+ clear()
+ screen = Screen.new(40, 8)
+ screen:attach()
+ screen:set_default_attr_ids({
+ [0] = {bold=true, foreground=Screen.colors.Blue},
+ [1] = {bold = true, foreground = Screen.colors.SeaGreen},
+ [2] = {bold = true, reverse = true},
+ [3] = {foreground = Screen.colors.Brown, bold = true}, -- Statement
+ [4] = {foreground = Screen.colors.SlateBlue}, -- Special
+ })
+ command('highlight Statement gui=bold guifg=Brown')
+ command('highlight Special guifg=SlateBlue')
+ end)
+
+ it('can show highlighted line', function()
+ nvim_async("echo", {{"msg_a"}, {"msg_b", "Statement"}, {"msg_c", "Special"}}, true, {})
+ screen:expect{grid=[[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ msg_a{3:msg_b}{4:msg_c} |
+ ]]}
+ end)
+
+ it('can show highlighted multiline', function()
+ nvim_async("echo", {{"msg_a\nmsg_a", "Statement"}, {"msg_b", "Special"}}, true, {})
+ screen:expect{grid=[[
+ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {2: }|
+ {3:msg_a} |
+ {3:msg_a}{4:msg_b} |
+ {1:Press ENTER or type command to continue}^ |
+ ]]}
+ end)
+
+ it('can save message history', function()
+ nvim('command', 'set cmdheight=2') -- suppress Press ENTER
+ nvim("echo", {{"msg\nmsg"}, {"msg"}}, true, {})
+ eq("msg\nmsgmsg", meths.exec('messages', true))
+ end)
+
+ it('can disable saving message history', function()
+ nvim('command', 'set cmdheight=2') -- suppress Press ENTER
+ nvim_async("echo", {{"msg\nmsg"}, {"msg"}}, false, {})
+ eq("", meths.exec("messages", true))
+ end)
+ end)
end)
diff --git a/test/functional/eval/environ_spec.lua b/test/functional/eval/environ_spec.lua
index 54d2dc960b..9e19568249 100644
--- a/test/functional/eval/environ_spec.lua
+++ b/test/functional/eval/environ_spec.lua
@@ -3,6 +3,11 @@ local clear = helpers.clear
local eq = helpers.eq
local environ = helpers.funcs.environ
local exists = helpers.funcs.exists
+local system = helpers.funcs.system
+local nvim_prog = helpers.nvim_prog
+local command = helpers.command
+local eval = helpers.eval
+local setenv = helpers.funcs.setenv
describe('environment variables', function()
it('environ() handles empty env variable', function()
@@ -17,3 +22,59 @@ describe('environment variables', function()
eq(0, exists('$DOES_NOT_EXIST'))
end)
end)
+
+describe('empty $HOME', function()
+ local original_home = os.getenv('HOME')
+
+ -- recover $HOME after each test
+ after_each(function()
+ if original_home ~= nil then
+ setenv('HOME', original_home)
+ end
+ os.remove('test_empty_home')
+ os.remove('./~')
+ end)
+
+ local function tilde_in_cwd()
+ -- get files in cwd
+ command("let test_empty_home_cwd_files = split(globpath('.', '*'), '\n')")
+ -- get the index of the file named '~'
+ command('let test_empty_home_tilde_index = index(test_empty_home_cwd_files, "./~")')
+ return eval('test_empty_home_tilde_index') ~= -1
+ end
+
+ local function write_and_test_tilde()
+ system({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--headless',
+ '-c', 'write test_empty_home', '+q'})
+ eq(false, tilde_in_cwd())
+ end
+
+ it("'~' folder not created in cwd if $HOME and related env not defined", function()
+ command("unlet $HOME")
+ write_and_test_tilde()
+
+ command("let $HOMEDRIVE='C:'")
+ command("let $USERPROFILE='C:\\'")
+ write_and_test_tilde()
+
+ command("unlet $HOMEDRIVE")
+ write_and_test_tilde()
+
+ command("unlet $USERPROFILE")
+ write_and_test_tilde()
+
+ command("let $HOME='%USERPROFILE%'")
+ command("let $USERPROFILE='C:\\'")
+ write_and_test_tilde()
+ end)
+
+ it("'~' folder not created in cwd if writing a file with invalid $HOME", function()
+ setenv('HOME', '/path/does/not/exist')
+ write_and_test_tilde()
+ end)
+
+ it("'~' folder not created in cwd if writing a file with $HOME=''", function()
+ command("let $HOME=''")
+ write_and_test_tilde()
+ end)
+end)
diff --git a/test/functional/fixtures/fake-lsp-server.lua b/test/functional/fixtures/fake-lsp-server.lua
index a30eb748d0..252db88b6b 100644
--- a/test/functional/fixtures/fake-lsp-server.lua
+++ b/test/functional/fixtures/fake-lsp-server.lua
@@ -109,6 +109,23 @@ function tests.basic_init()
}
end
+function tests.check_workspace_configuration()
+ skeleton {
+ on_init = function(_params)
+ return { capabilities = {} }
+ end;
+ body = function()
+ notify('start')
+ notify('workspace/configuration', { items = {
+ { section = "testSetting1" };
+ { section = "testSetting2" };
+ } })
+ expect_notification('workspace/configuration', { true; vim.NIL})
+ notify('shutdown')
+ end;
+ }
+end
+
function tests.basic_check_capabilities()
skeleton {
on_init = function(params)
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index 0829560b9c..4acb1a7d8d 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -725,6 +725,19 @@ function module.pending_win32(pending_fn)
end
end
+function module.pending_c_parser(pending_fn)
+ local status, msg = unpack(module.exec_lua([[ return {pcall(vim.treesitter.require_language, 'c')} ]]))
+ if not status then
+ if module.isCI() then
+ error("treesitter C parser not found, required on CI: " .. msg)
+ else
+ pending_fn 'no C parser, skipping'
+ return true
+ end
+ end
+ return false
+end
+
-- Calls pending() and returns `true` if the system is too slow to
-- run fragile or expensive tests. Else returns `false`.
function module.skip_fragile(pending_fn, cond)
diff --git a/test/functional/legacy/assert_spec.lua b/test/functional/legacy/assert_spec.lua
index d48b8882af..515d6d91b8 100644
--- a/test/functional/legacy/assert_spec.lua
+++ b/test/functional/legacy/assert_spec.lua
@@ -242,9 +242,9 @@ describe('assert function:', function()
-- assert_fails({cmd}, [, {error}])
describe('assert_fails', function()
it('should change v:errors when error does not match v:errmsg', function()
- eq(1, eval([[assert_fails('xxx', {})]]))
- command([[call assert_match("Expected {} but got 'E731:", v:errors[0])]])
- expected_errors({"Expected {} but got 'E731: using Dictionary as a String'"})
+ eq(1, eval([[assert_fails('xxx', 'E12345')]]))
+ command([[call assert_match("Expected 'E12345' but got 'E492:", v:errors[0])]])
+ expected_errors({"Expected 'E12345' but got 'E492: Not an editor command: xxx': xxx"})
end)
it('should not change v:errors when cmd errors', function()
@@ -258,9 +258,9 @@ describe('assert function:', function()
end)
it('can specify and get a message about what failed', function()
- eq(1, eval([[assert_fails('xxx', {}, 'stupid')]]))
- command([[call assert_match("stupid: Expected {} but got 'E731:", v:errors[0])]])
- expected_errors({"stupid: Expected {} but got 'E731: using Dictionary as a String'"})
+ eq(1, eval([[assert_fails('xxx', 'E9876', 'stupid')]]))
+ command([[call assert_match("stupid: Expected 'E9876' but got 'E492:", v:errors[0])]])
+ expected_errors({"stupid: Expected 'E9876' but got 'E492: Not an editor command: xxx': stupid"})
end)
it('can specify and get a message even when cmd succeeds', function()
diff --git a/test/functional/legacy/backspace_opt_spec.lua b/test/functional/legacy/backspace_opt_spec.lua
deleted file mode 100644
index 90bc6f74f0..0000000000
--- a/test/functional/legacy/backspace_opt_spec.lua
+++ /dev/null
@@ -1,67 +0,0 @@
-local helpers = require('test.functional.helpers')(after_each)
-local call, clear = helpers.call, helpers.clear
-local source, eq, nvim = helpers.source, helpers.eq, helpers.meths
-
-describe("test 'backspace' settings", function()
- before_each(function()
- clear()
-
- source([[
- func Exec(expr)
- let str=''
- try
- exec a:expr
- catch /.*/
- let str=v:exception
- endtry
- return str
- endfunc
-
- func Test_backspace_option()
- set backspace=
- call assert_equal('', &backspace)
- set backspace=indent
- call assert_equal('indent', &backspace)
- set backspace=eol
- call assert_equal('eol', &backspace)
- set backspace=start
- call assert_equal('start', &backspace)
- " Add the value
- set backspace=
- set backspace=indent
- call assert_equal('indent', &backspace)
- set backspace+=eol
- call assert_equal('indent,eol', &backspace)
- set backspace+=start
- call assert_equal('indent,eol,start', &backspace)
- " Delete the value
- set backspace-=indent
- call assert_equal('eol,start', &backspace)
- set backspace-=start
- call assert_equal('eol', &backspace)
- set backspace-=eol
- call assert_equal('', &backspace)
- " Check the error
- call assert_equal(0, match(Exec('set backspace=ABC'), '.*E474'))
- call assert_equal(0, match(Exec('set backspace+=def'), '.*E474'))
- " NOTE: Vim doesn't check following error...
- "call assert_equal(0, match(Exec('set backspace-=ghi'), '.*E474'))
-
- " Check backwards compatibility with version 5.4 and earlier
- set backspace=0
- call assert_equal('0', &backspace)
- set backspace=1
- call assert_equal('1', &backspace)
- set backspace=2
- call assert_equal('2', &backspace)
- call assert_false(match(Exec('set backspace=3'), '.*E474'))
- call assert_false(match(Exec('set backspace=10'), '.*E474'))
- endfunc
- ]])
- end)
-
- it('works', function()
- call('Test_backspace_option')
- eq({}, nvim.get_vvar('errors'))
- end)
-end)
diff --git a/test/functional/legacy/memory_usage_spec.lua b/test/functional/legacy/memory_usage_spec.lua
index fb0bacc2d2..5f7bbd887f 100644
--- a/test/functional/legacy/memory_usage_spec.lua
+++ b/test/functional/legacy/memory_usage_spec.lua
@@ -10,6 +10,29 @@ local source = helpers.source
local poke_eventloop = helpers.poke_eventloop
local uname = helpers.uname
local load_adjust = helpers.load_adjust
+local isCI = helpers.isCI
+
+local function isasan()
+ local version = eval('execute("version")')
+ return version:match('-fsanitize=[a-z,]*address')
+end
+
+clear()
+if isasan() then
+ pending('ASAN build is difficult to estimate memory usage', function() end)
+ return
+elseif iswin() then
+ if isCI('github') then
+ pending('Windows runners in Github Actions do not have a stable environment to estimate memory usage', function() end)
+ return
+ elseif eval("executable('wmic')") == 0 then
+ pending('missing "wmic" command', function() end)
+ return
+ end
+elseif eval("executable('ps')") == 0 then
+ pending('missing "ps" command', function() end)
+ return
+end
local monitor_memory_usage = {
memory_usage = function(self)
@@ -71,11 +94,6 @@ describe('memory usage', function()
end
end
- local function isasan()
- local version = eval('execute("version")')
- return version:match('-fsanitize=[a-z,]*address')
- end
-
before_each(clear)
--[[
@@ -83,15 +101,6 @@ describe('memory usage', function()
just after it finishes.
]]--
it('function capture vargs', function()
- if isasan() then
- pending('ASAN build is difficult to estimate memory usage')
- end
- if iswin() and eval("executable('wmic')") == 0 then
- pending('missing "wmic" command')
- elseif eval("executable('ps')") == 0 then
- pending('missing "ps" command')
- end
-
local pid = eval('getpid()')
local before = monitor_memory_usage(pid)
source([[
@@ -125,15 +134,6 @@ describe('memory usage', function()
increase so much even when rerun Xtest.vim since system memory caches.
]]--
it('function capture lvars', function()
- if isasan() then
- pending('ASAN build is difficult to estimate memory usage')
- end
- if iswin() and eval("executable('wmic')") == 0 then
- pending('missing "wmic" command')
- elseif eval("executable('ps')") == 0 then
- pending('missing "ps" command')
- end
-
local pid = eval('getpid()')
local before = monitor_memory_usage(pid)
local fname = source([[
diff --git a/test/functional/lua/treesitter_spec.lua b/test/functional/lua/treesitter_spec.lua
deleted file mode 100644
index e522c339a9..0000000000
--- a/test/functional/lua/treesitter_spec.lua
+++ /dev/null
@@ -1,1015 +0,0 @@
--- Test suite for testing interactions with API bindings
-local helpers = require('test.functional.helpers')(after_each)
-local Screen = require('test.functional.ui.screen')
-
-local clear = helpers.clear
-local eq = helpers.eq
-local insert = helpers.insert
-local exec_lua = helpers.exec_lua
-local feed = helpers.feed
-local pcall_err = helpers.pcall_err
-local matches = helpers.matches
-
-before_each(clear)
-
-describe('treesitter API', function()
- -- error tests not requiring a parser library
- it('handles missing language', function()
- eq("Error executing lua: .../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers",
- pcall_err(exec_lua, "parser = vim.treesitter.get_parser(0, 'borklang')"))
-
- -- actual message depends on platform
- matches("Error executing lua: Failed to load parser: uv_dlopen: .+",
- pcall_err(exec_lua, "parser = vim.treesitter.require_language('borklang', 'borkbork.so')"))
-
- -- Should not throw an error when silent
- eq(false, exec_lua("return vim.treesitter.require_language('borklang', nil, true)"))
- eq(false, exec_lua("return vim.treesitter.require_language('borklang', 'borkbork.so', true)"))
-
- eq("Error executing lua: .../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers",
- pcall_err(exec_lua, "parser = vim.treesitter.inspect_language('borklang')"))
- end)
-end)
-
-describe('treesitter API with C parser', function()
- local function check_parser()
- local status, msg = unpack(exec_lua([[ return {pcall(vim.treesitter.require_language, 'c')} ]]))
- if not status then
- if helpers.isCI() then
- error("treesitter C parser not found, required on CI: " .. msg)
- else
- pending('no C parser, skipping')
- end
- end
- return status
- end
-
- it('parses buffer', function()
- if helpers.pending_win32(pending) or not check_parser() then return end
-
- insert([[
- int main() {
- int x = 3;
- }]])
-
- exec_lua([[
- parser = vim.treesitter.get_parser(0, "c")
- tree = parser:parse()[1]
- root = tree:root()
- lang = vim.treesitter.inspect_language('c')
- ]])
-
- eq("<tree>", exec_lua("return tostring(tree)"))
- eq("<node translation_unit>", exec_lua("return tostring(root)"))
- eq({0,0,3,0}, exec_lua("return {root:range()}"))
-
- eq(1, exec_lua("return root:child_count()"))
- exec_lua("child = root:child(0)")
- eq("<node function_definition>", exec_lua("return tostring(child)"))
- eq({0,0,2,1}, exec_lua("return {child:range()}"))
-
- eq("function_definition", exec_lua("return child:type()"))
- eq(true, exec_lua("return child:named()"))
- eq("number", type(exec_lua("return child:symbol()")))
- eq({'function_definition', true}, exec_lua("return lang.symbols[child:symbol()]"))
-
- exec_lua("anon = root:descendant_for_range(0,8,0,9)")
- eq("(", exec_lua("return anon:type()"))
- eq(false, exec_lua("return anon:named()"))
- eq("number", type(exec_lua("return anon:symbol()")))
- eq({'(', false}, exec_lua("return lang.symbols[anon:symbol()]"))
-
- exec_lua("descendant = root:descendant_for_range(1,2,1,12)")
- eq("<node declaration>", exec_lua("return tostring(descendant)"))
- eq({1,2,1,12}, exec_lua("return {descendant:range()}"))
- eq("(declaration type: (primitive_type) declarator: (init_declarator declarator: (identifier) value: (number_literal)))", exec_lua("return descendant:sexpr()"))
-
- feed("2G7|ay")
- exec_lua([[
- tree2 = parser:parse()[1]
- root2 = tree2:root()
- descendant2 = root2:descendant_for_range(1,2,1,13)
- ]])
- eq(false, exec_lua("return tree2 == tree1"))
- eq(false, exec_lua("return root2 == root"))
- eq("<node declaration>", exec_lua("return tostring(descendant2)"))
- eq({1,2,1,13}, exec_lua("return {descendant2:range()}"))
-
- eq(true, exec_lua("return child == child"))
- -- separate lua object, but represents same node
- eq(true, exec_lua("return child == root:child(0)"))
- eq(false, exec_lua("return child == descendant2"))
- eq(false, exec_lua("return child == nil"))
- eq(false, exec_lua("return child == tree"))
-
- eq("string", exec_lua("return type(child:id())"))
- eq(true, exec_lua("return child:id() == child:id()"))
- -- separate lua object, but represents same node
- eq(true, exec_lua("return child:id() == root:child(0):id()"))
- eq(false, exec_lua("return child:id() == descendant2:id()"))
- eq(false, exec_lua("return child:id() == nil"))
- eq(false, exec_lua("return child:id() == tree"))
-
- -- unchanged buffer: return the same tree
- eq(true, exec_lua("return parser:parse()[1] == tree2"))
- end)
-
- local test_text = [[
-void ui_refresh(void)
-{
- int width = INT_MAX, height = INT_MAX;
- bool ext_widgets[kUIExtCount];
- for (UIExtension i = 0; (int)i < kUIExtCount; i++) {
- ext_widgets[i] = true;
- }
-
- bool inclusive = ui_override();
- for (size_t i = 0; i < ui_count; i++) {
- UI *ui = uis[i];
- width = MIN(ui->width, width);
- height = MIN(ui->height, height);
- foo = BAR(ui->bazaar, bazaar);
- for (UIExtension j = 0; (int)j < kUIExtCount; j++) {
- ext_widgets[j] &= (ui->ui_ext[j] || inclusive);
- }
- }
-}]]
-
- it('allows to iterate over nodes children', function()
- if not check_parser() then return end
-
- insert(test_text);
-
- local res = exec_lua([[
- parser = vim.treesitter.get_parser(0, "c")
-
- func_node = parser:parse()[1]:root():child(0)
-
- res = {}
- for node, field in func_node:iter_children() do
- table.insert(res, {node:type(), field})
- end
- return res
- ]])
-
- eq({
- {"primitive_type", "type"},
- {"function_declarator", "declarator"},
- {"compound_statement", "body"}
- }, res)
- end)
-
- it('allows to get a child by field', function()
- if not check_parser() then return end
-
- insert(test_text);
-
- local res = exec_lua([[
- parser = vim.treesitter.get_parser(0, "c")
-
- func_node = parser:parse()[1]:root():child(0)
-
- local res = {}
- for _, node in ipairs(func_node:field("type")) do
- table.insert(res, {node:type(), node:range()})
- end
- return res
- ]])
-
- eq({{ "primitive_type", 0, 0, 0, 4 }}, res)
-
- local res_fail = exec_lua([[
- parser = vim.treesitter.get_parser(0, "c")
-
- return #func_node:field("foo") == 0
- ]])
-
- assert(res_fail)
- end)
-
- local query = [[
- ((call_expression function: (identifier) @minfunc (argument_list (identifier) @min_id)) (eq? @minfunc "MIN"))
- "for" @keyword
- (primitive_type) @type
- (field_expression argument: (identifier) @fieldarg)
- ]]
-
- it("supports runtime queries", function()
- if not check_parser() then return end
-
- local ret = exec_lua [[
- return require"vim.treesitter.query".get_query("c", "highlights").captures[1]
- ]]
-
- eq('variable', ret)
- end)
-
- it('support query and iter by capture', function()
- if not check_parser() then return end
-
- insert(test_text)
-
- local res = exec_lua([[
- cquery = vim.treesitter.parse_query("c", ...)
- parser = vim.treesitter.get_parser(0, "c")
- tree = parser:parse()[1]
- res = {}
- for cid, node in cquery:iter_captures(tree:root(), 0, 7, 14) do
- -- can't transmit node over RPC. just check the name and range
- table.insert(res, {cquery.captures[cid], node:type(), node:range()})
- end
- return res
- ]], query)
-
- eq({
- { "type", "primitive_type", 8, 2, 8, 6 },
- { "keyword", "for", 9, 2, 9, 5 },
- { "type", "primitive_type", 9, 7, 9, 13 },
- { "minfunc", "identifier", 11, 12, 11, 15 },
- { "fieldarg", "identifier", 11, 16, 11, 18 },
- { "min_id", "identifier", 11, 27, 11, 32 },
- { "minfunc", "identifier", 12, 13, 12, 16 },
- { "fieldarg", "identifier", 12, 17, 12, 19 },
- { "min_id", "identifier", 12, 29, 12, 35 },
- { "fieldarg", "identifier", 13, 14, 13, 16 }
- }, res)
- end)
-
- it('support query and iter by match', function()
- if not check_parser() then return end
-
- insert(test_text)
-
- local res = exec_lua([[
- cquery = vim.treesitter.parse_query("c", ...)
- parser = vim.treesitter.get_parser(0, "c")
- tree = parser:parse()[1]
- res = {}
- for pattern, match in cquery:iter_matches(tree:root(), 0, 7, 14) do
- -- can't transmit node over RPC. just check the name and range
- local mrepr = {}
- for cid,node in pairs(match) do
- table.insert(mrepr, {cquery.captures[cid], node:type(), node:range()})
- end
- table.insert(res, {pattern, mrepr})
- end
- return res
- ]], query)
-
- eq({
- { 3, { { "type", "primitive_type", 8, 2, 8, 6 } } },
- { 2, { { "keyword", "for", 9, 2, 9, 5 } } },
- { 3, { { "type", "primitive_type", 9, 7, 9, 13 } } },
- { 4, { { "fieldarg", "identifier", 11, 16, 11, 18 } } },
- { 1, { { "minfunc", "identifier", 11, 12, 11, 15 }, { "min_id", "identifier", 11, 27, 11, 32 } } },
- { 4, { { "fieldarg", "identifier", 12, 17, 12, 19 } } },
- { 1, { { "minfunc", "identifier", 12, 13, 12, 16 }, { "min_id", "identifier", 12, 29, 12, 35 } } },
- { 4, { { "fieldarg", "identifier", 13, 14, 13, 16 } } }
- }, res)
- end)
-
- it('allow loading query with escaped quotes and capture them with `lua-match?` and `vim-match?`', function()
- if not check_parser() then return end
-
- insert('char* astring = "Hello World!";')
-
- local res = exec_lua([[
- cquery = vim.treesitter.parse_query("c", '((_) @quote (vim-match? @quote "^\\"$")) ((_) @quote (lua-match? @quote "^\\"$"))')
- parser = vim.treesitter.get_parser(0, "c")
- tree = parser:parse()[1]
- res = {}
- for pattern, match in cquery:iter_matches(tree:root(), 0, 0, 1) do
- -- can't transmit node over RPC. just check the name and range
- local mrepr = {}
- for cid,node in pairs(match) do
- table.insert(mrepr, {cquery.captures[cid], node:type(), node:range()})
- end
- table.insert(res, {pattern, mrepr})
- end
- return res
- ]])
-
- eq({
- { 1, { { "quote", '"', 0, 16, 0, 17 } } },
- { 2, { { "quote", '"', 0, 16, 0, 17 } } },
- { 1, { { "quote", '"', 0, 29, 0, 30 } } },
- { 2, { { "quote", '"', 0, 29, 0, 30 } } },
- }, res)
- end)
-
- it('allows to add predicates', function()
- insert([[
- int main(void) {
- return 0;
- }
- ]])
-
- local custom_query = "((identifier) @main (#is-main? @main))"
-
- local res = exec_lua([[
- local query = require"vim.treesitter.query"
-
- local function is_main(match, pattern, bufnr, predicate)
- local node = match[ predicate[2] ]
-
- return query.get_node_text(node, bufnr)
- end
-
- local parser = vim.treesitter.get_parser(0, "c")
-
- query.add_predicate("is-main?", is_main)
-
- local query = query.parse_query("c", ...)
-
- local nodes = {}
- for _, node in query:iter_captures(parser:parse()[1]:root(), 0, 0, 19) do
- table.insert(nodes, {node:range()})
- end
-
- return nodes
- ]], custom_query)
-
- eq({{0, 4, 0, 8}}, res)
-
- local res_list = exec_lua[[
- local query = require'vim.treesitter.query'
-
- local list = query.list_predicates()
-
- table.sort(list)
-
- return list
- ]]
-
- eq({ 'contains?', 'eq?', 'is-main?', 'lua-match?', 'match?', 'vim-match?' }, res_list)
- end)
-
- local hl_text = [[
-/// Schedule Lua callback on main loop's event queue
-static int nlua_schedule(lua_State *const lstate)
-{
- if (lua_type(lstate, 1) != LUA_TFUNCTION
- || lstate != lstate) {
- lua_pushliteral(lstate, "vim.schedule: expected function");
- return lua_error(lstate);
- }
-
- LuaRef cb = nlua_ref(lstate, 1);
-
- multiqueue_put(main_loop.events, nlua_schedule_event,
- 1, (void *)(ptrdiff_t)cb);
- return 0;
-}]]
-
-local hl_query = [[
-(ERROR) @ErrorMsg
-
-"if" @keyword
-"else" @keyword
-"for" @keyword
-"return" @keyword
-
-"const" @type
-"static" @type
-"struct" @type
-"enum" @type
-"extern" @type
-
-(string_literal) @string
-
-(number_literal) @number
-(char_literal) @string
-
-(type_identifier) @type
-((type_identifier) @Special (#eq? @Special "LuaRef"))
-
-(primitive_type) @type
-(sized_type_specifier) @type
-
-; Use lua regexes
-((identifier) @Identifier (#contains? @Identifier "lua_"))
-((identifier) @Constant (#lua-match? @Constant "^[A-Z_]+$"))
-((identifier) @Normal (#vim-match? @Constant "^lstate$"))
-
-((binary_expression left: (identifier) @WarningMsg.left right: (identifier) @WarningMsg.right) (#eq? @WarningMsg.left @WarningMsg.right))
-
-(comment) @comment
-]]
-
- describe('when highlighting', function()
- local screen
-
- before_each(function()
- screen = Screen.new(65, 18)
- screen:attach()
- screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {foreground = Screen.colors.Blue1},
- [3] = {bold = true, foreground = Screen.colors.SeaGreen4},
- [4] = {bold = true, foreground = Screen.colors.Brown},
- [5] = {foreground = Screen.colors.Magenta},
- [6] = {foreground = Screen.colors.Red},
- [7] = {bold = true, foreground = Screen.colors.SlateBlue},
- [8] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [9] = {foreground = Screen.colors.Magenta, background = Screen.colors.Red},
- [10] = {foreground = Screen.colors.Red, background = Screen.colors.Red},
- [11] = {foreground = Screen.colors.Cyan4},
- })
- end)
-
- it('supports highlighting', function()
- if not check_parser() then return end
-
- insert(hl_text)
- screen:expect{grid=[[
- /// Schedule Lua callback on main loop's event queue |
- static int nlua_schedule(lua_State *const lstate) |
- { |
- if (lua_type(lstate, 1) != LUA_TFUNCTION |
- || lstate != lstate) { |
- lua_pushliteral(lstate, "vim.schedule: expected function"); |
- return lua_error(lstate); |
- } |
- |
- LuaRef cb = nlua_ref(lstate, 1); |
- |
- multiqueue_put(main_loop.events, nlua_schedule_event, |
- 1, (void *)(ptrdiff_t)cb); |
- return 0; |
- ^} |
- {1:~ }|
- {1:~ }|
- |
- ]]}
-
- exec_lua([[
- local parser = vim.treesitter.get_parser(0, "c")
- local highlighter = vim.treesitter.highlighter
- local query = ...
- test_hl = highlighter.new(parser, {queries = {c = query}})
- ]], hl_query)
- screen:expect{grid=[[
- {2:/// Schedule Lua callback on main loop's event queue} |
- {3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
- { |
- {4:if} ({11:lua_type}(lstate, {5:1}) != {5:LUA_TFUNCTION} |
- || {6:lstate} != {6:lstate}) { |
- {11:lua_pushliteral}(lstate, {5:"vim.schedule: expected function"}); |
- {4:return} {11:lua_error}(lstate); |
- } |
- |
- {7:LuaRef} cb = {11:nlua_ref}(lstate, {5:1}); |
- |
- multiqueue_put(main_loop.events, {11:nlua_schedule_event}, |
- {5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
- {4:return} {5:0}; |
- ^} |
- {1:~ }|
- {1:~ }|
- |
- ]]}
-
- feed("5Goc<esc>dd")
-
- screen:expect{grid=[[
- {2:/// Schedule Lua callback on main loop's event queue} |
- {3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
- { |
- {4:if} ({11:lua_type}(lstate, {5:1}) != {5:LUA_TFUNCTION} |
- || {6:lstate} != {6:lstate}) { |
- {11:^lua_pushliteral}(lstate, {5:"vim.schedule: expected function"}); |
- {4:return} {11:lua_error}(lstate); |
- } |
- |
- {7:LuaRef} cb = {11:nlua_ref}(lstate, {5:1}); |
- |
- multiqueue_put(main_loop.events, {11:nlua_schedule_event}, |
- {5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
- {4:return} {5:0}; |
- } |
- {1:~ }|
- {1:~ }|
- |
- ]]}
-
- feed('7Go*/<esc>')
- screen:expect{grid=[[
- {2:/// Schedule Lua callback on main loop's event queue} |
- {3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
- { |
- {4:if} ({11:lua_type}(lstate, {5:1}) != {5:LUA_TFUNCTION} |
- || {6:lstate} != {6:lstate}) { |
- {11:lua_pushliteral}(lstate, {5:"vim.schedule: expected function"}); |
- {4:return} {11:lua_error}(lstate); |
- {8:*^/} |
- } |
- |
- {7:LuaRef} cb = {11:nlua_ref}(lstate, {5:1}); |
- |
- multiqueue_put(main_loop.events, {11:nlua_schedule_event}, |
- {5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
- {4:return} {5:0}; |
- } |
- {1:~ }|
- |
- ]]}
-
- feed('3Go/*<esc>')
- screen:expect{grid=[[
- {2:/// Schedule Lua callback on main loop's event queue} |
- {3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
- { |
- {2:/^*} |
- {2: if (lua_type(lstate, 1) != LUA_TFUNCTION} |
- {2: || lstate != lstate) {} |
- {2: lua_pushliteral(lstate, "vim.schedule: expected function");} |
- {2: return lua_error(lstate);} |
- {2:*/} |
- } |
- |
- {7:LuaRef} cb = {11:nlua_ref}(lstate, {5:1}); |
- |
- multiqueue_put(main_loop.events, {11:nlua_schedule_event}, |
- {5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
- {4:return} {5:0}; |
- {8:}} |
- |
- ]]}
-
- feed("gg$")
- feed("~")
- screen:expect{grid=[[
- {2:/// Schedule Lua callback on main loop's event queu^E} |
- {3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
- { |
- {2:/*} |
- {2: if (lua_type(lstate, 1) != LUA_TFUNCTION} |
- {2: || lstate != lstate) {} |
- {2: lua_pushliteral(lstate, "vim.schedule: expected function");} |
- {2: return lua_error(lstate);} |
- {2:*/} |
- } |
- |
- {7:LuaRef} cb = {11:nlua_ref}(lstate, {5:1}); |
- |
- multiqueue_put(main_loop.events, {11:nlua_schedule_event}, |
- {5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
- {4:return} {5:0}; |
- {8:}} |
- |
- ]]}
-
-
- feed("re")
- screen:expect{grid=[[
- {2:/// Schedule Lua callback on main loop's event queu^e} |
- {3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
- { |
- {2:/*} |
- {2: if (lua_type(lstate, 1) != LUA_TFUNCTION} |
- {2: || lstate != lstate) {} |
- {2: lua_pushliteral(lstate, "vim.schedule: expected function");} |
- {2: return lua_error(lstate);} |
- {2:*/} |
- } |
- |
- {7:LuaRef} cb = {11:nlua_ref}(lstate, {5:1}); |
- |
- multiqueue_put(main_loop.events, {11:nlua_schedule_event}, |
- {5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
- {4:return} {5:0}; |
- {8:}} |
- |
- ]]}
- end)
-
- it("supports highlighting with custom parser", function()
- if not check_parser() then return end
-
- screen:set_default_attr_ids({ {bold = true, foreground = Screen.colors.SeaGreen4} })
-
- insert(test_text)
-
- screen:expect{ grid= [[
- int width = INT_MAX, height = INT_MAX; |
- bool ext_widgets[kUIExtCount]; |
- for (UIExtension i = 0; (int)i < kUIExtCount; i++) { |
- ext_widgets[i] = true; |
- } |
- |
- bool inclusive = ui_override(); |
- for (size_t i = 0; i < ui_count; i++) { |
- UI *ui = uis[i]; |
- width = MIN(ui->width, width); |
- height = MIN(ui->height, height); |
- foo = BAR(ui->bazaar, bazaar); |
- for (UIExtension j = 0; (int)j < kUIExtCount; j++) { |
- ext_widgets[j] &= (ui->ui_ext[j] || inclusive); |
- } |
- } |
- ^} |
- |
- ]] }
-
- exec_lua([[
- parser = vim.treesitter.get_parser(0, "c")
- query = vim.treesitter.parse_query("c", "(declaration) @decl")
-
- local nodes = {}
- for _, node in query:iter_captures(parser:parse()[1]:root(), 0, 0, 19) do
- table.insert(nodes, node)
- end
-
- parser:set_included_regions({nodes})
-
- local hl = vim.treesitter.highlighter.new(parser, {queries = {c = "(identifier) @type"}})
- ]])
-
- screen:expect{ grid = [[
- int {1:width} = {1:INT_MAX}, {1:height} = {1:INT_MAX}; |
- bool {1:ext_widgets}[{1:kUIExtCount}]; |
- for (UIExtension {1:i} = 0; (int)i < kUIExtCount; i++) { |
- ext_widgets[i] = true; |
- } |
- |
- bool {1:inclusive} = {1:ui_override}(); |
- for (size_t {1:i} = 0; i < ui_count; i++) { |
- UI *{1:ui} = {1:uis}[{1:i}]; |
- width = MIN(ui->width, width); |
- height = MIN(ui->height, height); |
- foo = BAR(ui->bazaar, bazaar); |
- for (UIExtension {1:j} = 0; (int)j < kUIExtCount; j++) { |
- ext_widgets[j] &= (ui->ui_ext[j] || inclusive); |
- } |
- } |
- ^} |
- |
- ]] }
- end)
-
- it("supports highlighting injected languages", function()
- if not check_parser() then return end
-
- insert([[
- int x = INT_MAX;
- #define READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y))
- #define foo void main() { \
- return 42; \
- }
- ]])
-
- screen:expect{grid=[[
- int x = INT_MAX; |
- #define READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y))|
- #define foo void main() { \ |
- return 42; \ |
- } |
- ^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- |
- ]]}
-
- exec_lua([[
- local parser = vim.treesitter.get_parser(0, "c", {
- queries = {c = "(preproc_def (preproc_arg) @c) (preproc_function_def value: (preproc_arg) @c)"}
- })
- local highlighter = vim.treesitter.highlighter
- local query = ...
- test_hl = highlighter.new(parser, {queries = {c = query}})
- ]], hl_query)
-
- screen:expect{grid=[[
- {3:int} x = {5:INT_MAX}; |
- #define {5:READ_STRING}(x, y) ({3:char_u} *)read_string((x), ({3:size_t})(y))|
- #define foo {3:void} main() { \ |
- {4:return} {5:42}; \ |
- } |
- ^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- |
- ]]}
- end)
- end)
-
- it('inspects language', function()
- if not check_parser() then return end
-
- local keys, fields, symbols = unpack(exec_lua([[
- local lang = vim.treesitter.inspect_language('c')
- local keys, symbols = {}, {}
- for k,_ in pairs(lang) do
- keys[k] = true
- end
-
- -- symbols array can have "holes" and is thus not a valid msgpack array
- -- but we don't care about the numbers here (checked in the parser test)
- for _, v in pairs(lang.symbols) do
- table.insert(symbols, v)
- end
- return {keys, lang.fields, symbols}
- ]]))
-
- eq({fields=true, symbols=true}, keys)
-
- local fset = {}
- for _,f in pairs(fields) do
- eq("string", type(f))
- fset[f] = true
- end
- eq(true, fset["directive"])
- eq(true, fset["initializer"])
-
- local has_named, has_anonymous
- for _,s in pairs(symbols) do
- eq("string", type(s[1]))
- eq("boolean", type(s[2]))
- if s[1] == "for_statement" and s[2] == true then
- has_named = true
- elseif s[1] == "|=" and s[2] == false then
- has_anonymous = true
- end
- end
- eq({true,true}, {has_named,has_anonymous})
- end)
- it('allows to set simple ranges', function()
- if not check_parser() then return end
-
- insert(test_text)
-
- local res = exec_lua [[
- parser = vim.treesitter.get_parser(0, "c")
- return { parser:parse()[1]:root():range() }
- ]]
-
- eq({0, 0, 19, 0}, res)
-
- -- The following sets the included ranges for the current parser
- -- As stated here, this only includes the function (thus the whole buffer, without the last line)
- local res2 = exec_lua [[
- local root = parser:parse()[1]:root()
- parser:set_included_regions({{root:child(0)}})
- parser:invalidate()
- return { parser:parse()[1]:root():range() }
- ]]
-
- eq({0, 0, 18, 1}, res2)
-
- local range = exec_lua [[
- local res = {}
- for _, region in ipairs(parser:included_regions()) do
- for _, node in ipairs(region) do
- table.insert(res, {node:range()})
- end
- end
- return res
- ]]
-
- eq(range, { { 0, 0, 18, 1 } })
-
- local range_tbl = exec_lua [[
- parser:set_included_regions { { { 0, 0, 17, 1 } } }
- parser:parse()
- return parser:included_regions()
- ]]
-
- eq(range_tbl, { { { 0, 0, 0, 17, 1, 508 } } })
- end)
- it("allows to set complex ranges", function()
- if not check_parser() then return end
-
- insert(test_text)
-
- local res = exec_lua [[
- parser = vim.treesitter.get_parser(0, "c")
- query = vim.treesitter.parse_query("c", "(declaration) @decl")
-
- local nodes = {}
- for _, node in query:iter_captures(parser:parse()[1]:root(), 0, 0, 19) do
- table.insert(nodes, node)
- end
-
- parser:set_included_regions({nodes})
-
- local root = parser:parse()[1]:root()
-
- local res = {}
- for i=0,(root:named_child_count() - 1) do
- table.insert(res, { root:named_child(i):range() })
- end
- return res
- ]]
-
- eq({
- { 2, 2, 2, 40 },
- { 3, 2, 3, 32 },
- { 4, 7, 4, 25 },
- { 8, 2, 8, 33 },
- { 9, 7, 9, 20 },
- { 10, 4, 10, 20 },
- { 14, 9, 14, 27 } }, res)
- end)
-
- it("allows to create string parsers", function()
- local ret = exec_lua [[
- local parser = vim.treesitter.get_string_parser("int foo = 42;", "c")
- return { parser:parse()[1]:root():range() }
- ]]
-
- eq({ 0, 0, 0, 13 }, ret)
- end)
-
- it("allows to run queries with string parsers", function()
- local txt = [[
- int foo = 42;
- int bar = 13;
- ]]
-
- local ret = exec_lua([[
- local str = ...
- local parser = vim.treesitter.get_string_parser(str, "c")
-
- local nodes = {}
- local query = vim.treesitter.parse_query("c", '((identifier) @id (eq? @id "foo"))')
-
- for _, node in query:iter_captures(parser:parse()[1]:root(), str, 0, 2) do
- table.insert(nodes, { node:range() })
- end
-
- return nodes]], txt)
-
- eq({ {0, 10, 0, 13} }, ret)
- end)
-
- describe("when creating a language tree", function()
- local function get_ranges()
- return exec_lua([[
- local result = {}
- parser:for_each_tree(function(tree) table.insert(result, {tree:root():range()}) end)
- return result
- ]])
- end
-
- before_each(function()
- insert([[
-int x = INT_MAX;
-#define READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y))
-#define READ_STRING_OK(x, y) (char_u *)read_string((x), (size_t)(y))
-#define VALUE 123
-#define VALUE1 123
-#define VALUE2 123
- ]])
- end)
-
- describe("when parsing regions independently", function()
- it("should inject a language", function()
- exec_lua([[
- parser = vim.treesitter.get_parser(0, "c", {
- queries = {
- c = "(preproc_def (preproc_arg) @c) (preproc_function_def value: (preproc_arg) @c)"}})
- ]])
-
- eq("table", exec_lua("return type(parser:children().c)"))
- eq(5, exec_lua("return #parser:children().c:trees()"))
- eq({
- {0, 0, 7, 0}, -- root tree
- {3, 14, 3, 17}, -- VALUE 123
- {4, 15, 4, 18}, -- VALUE1 123
- {5, 15, 5, 18}, -- VALUE2 123
- {1, 26, 1, 65}, -- READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y))
- {2, 29, 2, 68} -- READ_STRING_OK(x, y) (char_u *)read_string((x), (size_t)(y))
- }, get_ranges())
- end)
- end)
-
- describe("when parsing regions combined", function()
- it("should inject a language", function()
- exec_lua([[
- parser = vim.treesitter.get_parser(0, "c", {
- queries = {
- c = "(preproc_def (preproc_arg) @c @combined) (preproc_function_def value: (preproc_arg) @c @combined)"}})
- ]])
-
- eq("table", exec_lua("return type(parser:children().c)"))
- eq(2, exec_lua("return #parser:children().c:trees()"))
- eq({
- {0, 0, 7, 0}, -- root tree
- {3, 14, 5, 18}, -- VALUE 123
- -- VALUE1 123
- -- VALUE2 123
- {1, 26, 2, 68} -- READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y))
- -- READ_STRING_OK(x, y) (char_u *)read_string((x), (size_t)(y))
- }, get_ranges())
- end)
- end)
-
- describe("when using the offset directive", function()
- it("should shift the range by the directive amount", function()
- exec_lua([[
- parser = vim.treesitter.get_parser(0, "c", {
- queries = {
- c = "(preproc_def ((preproc_arg) @c (#offset! @c 0 2 0 -1))) (preproc_function_def value: (preproc_arg) @c)"}})
- ]])
-
- eq("table", exec_lua("return type(parser:children().c)"))
- eq({
- {0, 0, 7, 0}, -- root tree
- {3, 15, 3, 16}, -- VALUE 123
- {4, 16, 4, 17}, -- VALUE1 123
- {5, 16, 5, 17}, -- VALUE2 123
- {1, 26, 1, 65}, -- READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y))
- {2, 29, 2, 68} -- READ_STRING_OK(x, y) (char_u *)read_string((x), (size_t)(y))
- }, get_ranges())
- end)
- 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)
-
- describe("when getting/setting match data", function()
- describe("when setting for the whole match", function()
- it("should set/get the data correctly", function()
- insert([[
- int x = 3;
- ]])
-
- local result = exec_lua([[
- local result
-
- query = vim.treesitter.parse_query("c", '((number_literal) @number (#set! "key" "value"))')
- parser = vim.treesitter.get_parser(0, "c")
-
- for pattern, match, metadata in query:iter_matches(parser:parse()[1]:root(), 0, 0, 1) do
- result = metadata.key
- end
-
- return result
- ]])
-
- eq(result, "value")
- end)
- end)
-
- describe("when setting for a capture match", function()
- it("should set/get the data correctly", function()
- insert([[
- int x = 3;
- ]])
-
- local result = exec_lua([[
- local result
-
- query = vim.treesitter.parse_query("c", '((number_literal) @number (#set! @number "key" "value"))')
- parser = vim.treesitter.get_parser(0, "c")
-
- for pattern, match, metadata in query:iter_matches(parser:parse()[1]:root(), 0, 0, 1) do
- result = metadata[pattern].key
- end
-
- return result
- ]])
-
- eq(result, "value")
- end)
- end)
- end)
-end)
diff --git a/test/functional/options/defaults_spec.lua b/test/functional/options/defaults_spec.lua
index 92d077ed14..eb5e284385 100644
--- a/test/functional/options/defaults_spec.lua
+++ b/test/functional/options/defaults_spec.lua
@@ -204,9 +204,8 @@ describe('startup defaults', function()
end)
describe('$NVIM_LOG_FILE', function()
- local datasubdir = iswin() and 'nvim-data' or 'nvim'
local xdgdir = 'Xtest-startup-xdg-logpath'
- local xdgdatadir = xdgdir..'/'..datasubdir
+ local xdgcachedir = xdgdir..'/nvim'
after_each(function()
os.remove('Xtest-logpath')
rmdir(xdgdir)
@@ -218,28 +217,21 @@ describe('startup defaults', function()
}})
eq('Xtest-logpath', eval('$NVIM_LOG_FILE'))
end)
- it('defaults to stdpath("data")/log if empty', function()
- eq(true, mkdir(xdgdir) and mkdir(xdgdatadir))
+ it('defaults to stdpath("cache")/log if empty', function()
+ eq(true, mkdir(xdgdir) and mkdir(xdgcachedir))
clear({env={
- XDG_DATA_HOME=xdgdir,
+ XDG_CACHE_HOME=xdgdir,
NVIM_LOG_FILE='', -- Empty is invalid.
}})
- eq(xdgdir..'/'..datasubdir..'/log', string.gsub(eval('$NVIM_LOG_FILE'), '\\', '/'))
+ eq(xdgcachedir..'/log', string.gsub(eval('$NVIM_LOG_FILE'), '\\', '/'))
end)
- it('defaults to stdpath("data")/log if invalid', function()
- eq(true, mkdir(xdgdir) and mkdir(xdgdatadir))
+ it('defaults to stdpath("cache")/log if invalid', function()
+ eq(true, mkdir(xdgdir) and mkdir(xdgcachedir))
clear({env={
- XDG_DATA_HOME=xdgdir,
+ XDG_CACHE_HOME=xdgdir,
NVIM_LOG_FILE='.', -- Any directory is invalid.
}})
- eq(xdgdir..'/'..datasubdir..'/log', string.gsub(eval('$NVIM_LOG_FILE'), '\\', '/'))
- end)
- it('defaults to .nvimlog if stdpath("data") is invalid', function()
- clear({env={
- XDG_DATA_HOME='Xtest-missing-xdg-dir',
- NVIM_LOG_FILE='.', -- Any directory is invalid.
- }})
- eq('.nvimlog', eval('$NVIM_LOG_FILE'))
+ eq(xdgcachedir..'/log', string.gsub(eval('$NVIM_LOG_FILE'), '\\', '/'))
end)
end)
end)
diff --git a/test/functional/plugin/lsp/diagnostic_spec.lua b/test/functional/plugin/lsp/diagnostic_spec.lua
index 3a676359ab..4705a76465 100644
--- a/test/functional/plugin/lsp/diagnostic_spec.lua
+++ b/test/functional/plugin/lsp/diagnostic_spec.lua
@@ -12,41 +12,41 @@ describe('vim.lsp.diagnostic', function()
clear()
exec_lua [[
- require('vim.lsp')
-
- make_range = function(x1, y1, x2, y2)
- return { start = { line = x1, character = y1 }, ['end'] = { line = x2, character = y2 } }
- end
-
- make_error = function(msg, x1, y1, x2, y2)
- return {
- range = make_range(x1, y1, x2, y2),
- message = msg,
- severity = 1,
- }
- end
-
- make_warning = function(msg, x1, y1, x2, y2)
- return {
- range = make_range(x1, y1, x2, y2),
- message = msg,
- severity = 2,
- }
- end
-
- make_information = function(msg, x1, y1, x2, y2)
- return {
- range = make_range(x1, y1, x2, y2),
- message = msg,
- severity = 3,
- }
- end
-
- count_of_extmarks_for_client = function(bufnr, client_id)
- return #vim.api.nvim_buf_get_extmarks(
- bufnr, vim.lsp.diagnostic._get_diagnostic_namespace(client_id), 0, -1, {}
- )
- end
+ require('vim.lsp')
+
+ make_range = function(x1, y1, x2, y2)
+ return { start = { line = x1, character = y1 }, ['end'] = { line = x2, character = y2 } }
+ end
+
+ make_error = function(msg, x1, y1, x2, y2)
+ return {
+ range = make_range(x1, y1, x2, y2),
+ message = msg,
+ severity = 1,
+ }
+ end
+
+ make_warning = function(msg, x1, y1, x2, y2)
+ return {
+ range = make_range(x1, y1, x2, y2),
+ message = msg,
+ severity = 2,
+ }
+ end
+
+ make_information = function(msg, x1, y1, x2, y2)
+ return {
+ range = make_range(x1, y1, x2, y2),
+ message = msg,
+ severity = 3,
+ }
+ end
+
+ count_of_extmarks_for_client = function(bufnr, client_id)
+ return #vim.api.nvim_buf_get_extmarks(
+ bufnr, vim.lsp.diagnostic._get_diagnostic_namespace(client_id), 0, -1, {}
+ )
+ end
]]
fake_uri = "file://fake/uri"
@@ -640,6 +640,36 @@ describe('vim.lsp.diagnostic', function()
eq(expected_spacing, #spacing)
end)
+
+ it('allows filtering via severity limit', function()
+ local get_extmark_count_with_severity = function(severity_limit)
+ return exec_lua([[
+ PublishDiagnostics = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
+ underline = false,
+ virtual_text = {
+ severity_limit = ...
+ },
+ })
+
+ PublishDiagnostics(nil, nil, {
+ uri = fake_uri,
+ diagnostics = {
+ make_warning('Delayed Diagnostic', 4, 4, 4, 4),
+ }
+ }, 1
+ )
+
+ return count_of_extmarks_for_client(diagnostic_bufnr, 1)
+ ]], severity_limit)
+ end
+
+ -- No messages with Error or higher
+ eq(0, get_extmark_count_with_severity("Error"))
+
+ -- But now we don't filter it
+ eq(1, get_extmark_count_with_severity("Warning"))
+ eq(1, get_extmark_count_with_severity("Hint"))
+ end)
end)
describe('lsp.util.show_line_diagnostics', function()
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index f01d90bbeb..41fdf845df 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -262,6 +262,63 @@ describe('LSP', function()
}
end)
+ it('client should return settings via workspace/configuration handler', function()
+ local expected_callbacks = {
+ {NIL, "shutdown", {}, 1};
+ {NIL, "workspace/configuration", { items = {
+ { section = "testSetting1" };
+ { section = "testSetting2" };
+ }}, 1};
+ {NIL, "start", {}, 1};
+ }
+ local client
+ test_rpc_server {
+ test_name = "check_workspace_configuration";
+ on_init = function(_client)
+ client = _client
+ end;
+ on_exit = function(code, signal)
+ eq(0, code, "exit code", fake_lsp_logfile)
+ eq(0, signal, "exit signal", fake_lsp_logfile)
+ end;
+ on_callback = function(err, method, params, client_id)
+ eq(table.remove(expected_callbacks), {err, method, params, client_id}, "expected callback")
+ if method == 'start' then
+ exec_lua([=[
+ local client = vim.lsp.get_client_by_id(TEST_RPC_CLIENT_ID)
+ client.config.settings = {
+ testSetting1 = true;
+ testSetting2 = false;
+ }]=])
+ end
+ if method == 'workspace/configuration' then
+ local result = exec_lua([=[
+ local method, params = ...
+ return require'vim.lsp.handlers'['workspace/configuration'](err, method, params, TEST_RPC_CLIENT_ID)]=], method, params)
+ client.notify('workspace/configuration', result)
+ end
+ if method == 'shutdown' then
+ client.stop()
+ end
+ end;
+ }
+ end)
+ it('workspace/configuration returns NIL per section if client was started without config.settings', function()
+ fake_lsp_server_setup('workspace/configuration no settings')
+ eq({
+ NIL,
+ NIL,
+ }, exec_lua [[
+ local params = {
+ items = {
+ {section = 'foo'},
+ {section = 'bar'},
+ }
+ }
+ return vim.lsp.handlers['workspace/configuration'](nil, nil, params, TEST_RPC_CLIENT_ID)
+ ]])
+ end)
+
it('should verify capabilities sent', function()
local expected_callbacks = {
{NIL, "shutdown", {}, 1};
@@ -1003,7 +1060,7 @@ describe('LSP', function()
return {
edits = {
make_edit(0, 0, 0, 3, "First ↥ 🤦 🦄")
- },
+ },
textDocument = {
uri = "file://fake/uri";
version = editVersion
@@ -1044,7 +1101,7 @@ describe('LSP', function()
local args = {...}
local versionedBuf = args[2]
vim.lsp.util.buf_versions[versionedBuf.bufnr] = versionedBuf.currentVersion
- vim.lsp.util.apply_text_document_edit(...)
+ vim.lsp.util.apply_text_document_edit(args[1])
]], edit, versionedBuf)
end
@@ -1067,6 +1124,7 @@ describe('LSP', function()
}, buf_lines(target_bufnr))
end)
end)
+
describe('workspace_apply_edit', function()
it('workspace/applyEdit returns ApplyWorkspaceEditResponse', function()
local expected = {
@@ -1082,6 +1140,106 @@ describe('LSP', function()
]])
end)
end)
+
+ describe('apply_workspace_edit', function()
+ local replace_line_edit = function(row, new_line, editVersion)
+ return {
+ edits = {
+ -- NOTE: This is a hack if you have a line longer than 1000 it won't replace it
+ make_edit(row, 0, row, 1000, new_line)
+ },
+ textDocument = {
+ uri = "file://fake/uri";
+ version = editVersion
+ }
+ }
+ end
+
+ -- Some servers send all the edits separately, but with the same version.
+ -- We should not stop applying the edits
+ local make_workspace_edit = function(changes)
+ return {
+ documentChanges = changes
+ }
+ end
+
+ local target_bufnr, changedtick = nil, nil
+
+ before_each(function()
+ local ret = exec_lua [[
+ local bufnr = vim.uri_to_bufnr("file://fake/uri")
+ local lines = {
+ "Original Line #1",
+ "Original Line #2"
+ }
+
+ vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines)
+
+ local update_changed_tick = function()
+ vim.lsp.util.buf_versions[bufnr] = vim.api.nvim_buf_get_var(bufnr, 'changedtick')
+ end
+
+ update_changed_tick()
+ vim.api.nvim_buf_attach(bufnr, false, {
+ on_changedtick = function()
+ update_changed_tick()
+ end
+ })
+
+ return {bufnr, vim.api.nvim_buf_get_var(bufnr, 'changedtick')}
+ ]]
+
+ target_bufnr = ret[1]
+ changedtick = ret[2]
+ end)
+
+ it('apply_workspace_edit applies a single edit', function()
+ local new_lines = {
+ "First Line",
+ }
+
+ local edits = {}
+ for row, line in ipairs(new_lines) do
+ table.insert(edits, replace_line_edit(row - 1, line, changedtick))
+ end
+
+ eq({
+ "First Line",
+ "Original Line #2",
+ }, exec_lua([[
+ local args = {...}
+ local workspace_edits = args[1]
+ local target_bufnr = args[2]
+
+ vim.lsp.util.apply_workspace_edit(workspace_edits)
+
+ return vim.api.nvim_buf_get_lines(target_bufnr, 0, -1, false)
+ ]], make_workspace_edit(edits), target_bufnr))
+ end)
+
+ it('apply_workspace_edit applies multiple edits', function()
+ local new_lines = {
+ "First Line",
+ "Second Line",
+ }
+
+ local edits = {}
+ for row, line in ipairs(new_lines) do
+ table.insert(edits, replace_line_edit(row - 1, line, changedtick))
+ end
+
+ eq(new_lines, exec_lua([[
+ local args = {...}
+ local workspace_edits = args[1]
+ local target_bufnr = args[2]
+
+ vim.lsp.util.apply_workspace_edit(workspace_edits)
+
+ return vim.api.nvim_buf_get_lines(target_bufnr, 0, -1, false)
+ ]], make_workspace_edit(edits), target_bufnr))
+ end)
+ end)
+
describe('completion_list_to_complete_items', function()
-- Completion option precedence:
-- textEdit.newText > insertText > label
diff --git a/test/functional/provider/define_spec.lua b/test/functional/provider/define_spec.lua
index 1d50ce0a56..12efbec326 100644
--- a/test/functional/provider/define_spec.lua
+++ b/test/functional/provider/define_spec.lua
@@ -136,7 +136,7 @@ local function command_specs_for(fn, sync, first_arg_factory, init)
end)
it('with nargs/count', function()
- call(fn, args..', {"nargs": "1", "range": "5"}')
+ call(fn, args..', {"nargs": "1", "count": "5"}')
local function on_setup()
command('5RpcCommand arg')
end
@@ -152,7 +152,7 @@ local function command_specs_for(fn, sync, first_arg_factory, init)
end)
it('with nargs/count/bang', function()
- call(fn, args..', {"nargs": "1", "range": "5", "bang": ""}')
+ call(fn, args..', {"nargs": "1", "count": "5", "bang": ""}')
local function on_setup()
command('5RpcCommand! arg')
end
@@ -169,7 +169,7 @@ local function command_specs_for(fn, sync, first_arg_factory, init)
end)
it('with nargs/count/bang/register', function()
- call(fn, args..', {"nargs": "1", "range": "5", "bang": "",'..
+ call(fn, args..', {"nargs": "1", "count": "5", "bang": "",'..
' "register": ""}')
local function on_setup()
command('5RpcCommand! b arg')
@@ -188,7 +188,7 @@ local function command_specs_for(fn, sync, first_arg_factory, init)
end)
it('with nargs/count/bang/register/eval', function()
- call(fn, args..', {"nargs": "1", "range": "5", "bang": "",'..
+ call(fn, args..', {"nargs": "1", "count": "5", "bang": "",'..
' "register": "", "eval": "@<reg>"}')
local function on_setup()
command('let @b = "regb"')
diff --git a/test/functional/treesitter/highlight_spec.lua b/test/functional/treesitter/highlight_spec.lua
new file mode 100644
index 0000000000..cb73bfbbe1
--- /dev/null
+++ b/test/functional/treesitter/highlight_spec.lua
@@ -0,0 +1,475 @@
+local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
+
+local clear = helpers.clear
+local insert = helpers.insert
+local exec_lua = helpers.exec_lua
+local feed = helpers.feed
+local pending_c_parser = helpers.pending_c_parser
+
+before_each(clear)
+
+local hl_query = [[
+ (ERROR) @ErrorMsg
+
+ "if" @keyword
+ "else" @keyword
+ "for" @keyword
+ "return" @keyword
+
+ "const" @type
+ "static" @type
+ "struct" @type
+ "enum" @type
+ "extern" @type
+
+ (string_literal) @string
+
+ (number_literal) @number
+ (char_literal) @string
+
+ (type_identifier) @type
+ ((type_identifier) @Special (#eq? @Special "LuaRef"))
+
+ (primitive_type) @type
+ (sized_type_specifier) @type
+
+ ; Use lua regexes
+ ((identifier) @Identifier (#contains? @Identifier "lua_"))
+ ((identifier) @Constant (#lua-match? @Constant "^[A-Z_]+$"))
+ ((identifier) @Normal (#vim-match? @Constant "^lstate$"))
+
+ ((binary_expression left: (identifier) @WarningMsg.left right: (identifier) @WarningMsg.right) (#eq? @WarningMsg.left @WarningMsg.right))
+
+ (comment) @comment
+]]
+
+local hl_text = [[
+/// Schedule Lua callback on main loop's event queue
+static int nlua_schedule(lua_State *const lstate)
+{
+ if (lua_type(lstate, 1) != LUA_TFUNCTION
+ || lstate != lstate) {
+ lua_pushliteral(lstate, "vim.schedule: expected function");
+ return lua_error(lstate);
+ }
+
+ LuaRef cb = nlua_ref(lstate, 1);
+
+ multiqueue_put(main_loop.events, nlua_schedule_event,
+ 1, (void *)(ptrdiff_t)cb);
+ return 0;
+}]]
+
+local test_text = [[
+void ui_refresh(void)
+{
+ int width = INT_MAX, height = INT_MAX;
+ bool ext_widgets[kUIExtCount];
+ for (UIExtension i = 0; (int)i < kUIExtCount; i++) {
+ ext_widgets[i] = true;
+ }
+
+ bool inclusive = ui_override();
+ for (size_t i = 0; i < ui_count; i++) {
+ UI *ui = uis[i];
+ width = MIN(ui->width, width);
+ height = MIN(ui->height, height);
+ foo = BAR(ui->bazaar, bazaar);
+ for (UIExtension j = 0; (int)j < kUIExtCount; j++) {
+ ext_widgets[j] &= (ui->ui_ext[j] || inclusive);
+ }
+ }
+}]]
+
+describe('treesitter highlighting', function()
+ local screen
+
+ before_each(function()
+ screen = Screen.new(65, 18)
+ screen:attach()
+ screen:set_default_attr_ids {
+ [1] = {bold = true, foreground = Screen.colors.Blue1};
+ [2] = {foreground = Screen.colors.Blue1};
+ [3] = {bold = true, foreground = Screen.colors.SeaGreen4};
+ [4] = {bold = true, foreground = Screen.colors.Brown};
+ [5] = {foreground = Screen.colors.Magenta};
+ [6] = {foreground = Screen.colors.Red};
+ [7] = {bold = true, foreground = Screen.colors.SlateBlue};
+ [8] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red};
+ [9] = {foreground = Screen.colors.Magenta, background = Screen.colors.Red};
+ [10] = {foreground = Screen.colors.Red, background = Screen.colors.Red};
+ [11] = {foreground = Screen.colors.Cyan4};
+ }
+
+ exec_lua([[ hl_query = ... ]], hl_query)
+ end)
+
+ it('is updated with edits', function()
+ if pending_c_parser(pending) then return end
+
+ insert(hl_text)
+ screen:expect{grid=[[
+ /// Schedule Lua callback on main loop's event queue |
+ static int nlua_schedule(lua_State *const lstate) |
+ { |
+ if (lua_type(lstate, 1) != LUA_TFUNCTION |
+ || lstate != lstate) { |
+ lua_pushliteral(lstate, "vim.schedule: expected function"); |
+ return lua_error(lstate); |
+ } |
+ |
+ LuaRef cb = nlua_ref(lstate, 1); |
+ |
+ multiqueue_put(main_loop.events, nlua_schedule_event, |
+ 1, (void *)(ptrdiff_t)cb); |
+ return 0; |
+ ^} |
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ exec_lua [[
+ local parser = vim.treesitter.get_parser(0, "c")
+ local highlighter = vim.treesitter.highlighter
+ test_hl = highlighter.new(parser, {queries = {c = hl_query}})
+ ]]
+ screen:expect{grid=[[
+ {2:/// Schedule Lua callback on main loop's event queue} |
+ {3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
+ { |
+ {4:if} ({11:lua_type}(lstate, {5:1}) != {5:LUA_TFUNCTION} |
+ || {6:lstate} != {6:lstate}) { |
+ {11:lua_pushliteral}(lstate, {5:"vim.schedule: expected function"}); |
+ {4:return} {11:lua_error}(lstate); |
+ } |
+ |
+ {7:LuaRef} cb = {11:nlua_ref}(lstate, {5:1}); |
+ |
+ multiqueue_put(main_loop.events, {11:nlua_schedule_event}, |
+ {5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
+ {4:return} {5:0}; |
+ ^} |
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ feed("5Goc<esc>dd")
+
+ screen:expect{grid=[[
+ {2:/// Schedule Lua callback on main loop's event queue} |
+ {3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
+ { |
+ {4:if} ({11:lua_type}(lstate, {5:1}) != {5:LUA_TFUNCTION} |
+ || {6:lstate} != {6:lstate}) { |
+ {11:^lua_pushliteral}(lstate, {5:"vim.schedule: expected function"}); |
+ {4:return} {11:lua_error}(lstate); |
+ } |
+ |
+ {7:LuaRef} cb = {11:nlua_ref}(lstate, {5:1}); |
+ |
+ multiqueue_put(main_loop.events, {11:nlua_schedule_event}, |
+ {5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
+ {4:return} {5:0}; |
+ } |
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ feed('7Go*/<esc>')
+ screen:expect{grid=[[
+ {2:/// Schedule Lua callback on main loop's event queue} |
+ {3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
+ { |
+ {4:if} ({11:lua_type}(lstate, {5:1}) != {5:LUA_TFUNCTION} |
+ || {6:lstate} != {6:lstate}) { |
+ {11:lua_pushliteral}(lstate, {5:"vim.schedule: expected function"}); |
+ {4:return} {11:lua_error}(lstate); |
+ {8:*^/} |
+ } |
+ |
+ {7:LuaRef} cb = {11:nlua_ref}(lstate, {5:1}); |
+ |
+ multiqueue_put(main_loop.events, {11:nlua_schedule_event}, |
+ {5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
+ {4:return} {5:0}; |
+ } |
+ {1:~ }|
+ |
+ ]]}
+
+ feed('3Go/*<esc>')
+ screen:expect{grid=[[
+ {2:/// Schedule Lua callback on main loop's event queue} |
+ {3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
+ { |
+ {2:/^*} |
+ {2: if (lua_type(lstate, 1) != LUA_TFUNCTION} |
+ {2: || lstate != lstate) {} |
+ {2: lua_pushliteral(lstate, "vim.schedule: expected function");} |
+ {2: return lua_error(lstate);} |
+ {2:*/} |
+ } |
+ |
+ {7:LuaRef} cb = {11:nlua_ref}(lstate, {5:1}); |
+ |
+ multiqueue_put(main_loop.events, {11:nlua_schedule_event}, |
+ {5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
+ {4:return} {5:0}; |
+ {8:}} |
+ |
+ ]]}
+
+ feed("gg$")
+ feed("~")
+ screen:expect{grid=[[
+ {2:/// Schedule Lua callback on main loop's event queu^E} |
+ {3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
+ { |
+ {2:/*} |
+ {2: if (lua_type(lstate, 1) != LUA_TFUNCTION} |
+ {2: || lstate != lstate) {} |
+ {2: lua_pushliteral(lstate, "vim.schedule: expected function");} |
+ {2: return lua_error(lstate);} |
+ {2:*/} |
+ } |
+ |
+ {7:LuaRef} cb = {11:nlua_ref}(lstate, {5:1}); |
+ |
+ multiqueue_put(main_loop.events, {11:nlua_schedule_event}, |
+ {5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
+ {4:return} {5:0}; |
+ {8:}} |
+ |
+ ]]}
+
+
+ feed("re")
+ screen:expect{grid=[[
+ {2:/// Schedule Lua callback on main loop's event queu^e} |
+ {3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
+ { |
+ {2:/*} |
+ {2: if (lua_type(lstate, 1) != LUA_TFUNCTION} |
+ {2: || lstate != lstate) {} |
+ {2: lua_pushliteral(lstate, "vim.schedule: expected function");} |
+ {2: return lua_error(lstate);} |
+ {2:*/} |
+ } |
+ |
+ {7:LuaRef} cb = {11:nlua_ref}(lstate, {5:1}); |
+ |
+ multiqueue_put(main_loop.events, {11:nlua_schedule_event}, |
+ {5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
+ {4:return} {5:0}; |
+ {8:}} |
+ |
+ ]]}
+ end)
+
+ it('is updated with :sort', function()
+ if pending_c_parser(pending) then return end
+
+ insert(test_text)
+ exec_lua [[
+ local parser = vim.treesitter.get_parser(0, "c")
+ test_hl = vim.treesitter.highlighter.new(parser, {queries = {c = hl_query}})
+ ]]
+ screen:expect{grid=[[
+ {3:int} width = {5:INT_MAX}, height = {5:INT_MAX}; |
+ {3:bool} ext_widgets[kUIExtCount]; |
+ {4:for} ({3:UIExtension} i = {5:0}; ({3:int})i < kUIExtCount; i++) { |
+ ext_widgets[i] = true; |
+ } |
+ |
+ {3:bool} inclusive = ui_override(); |
+ {4:for} ({3:size_t} i = {5:0}; i < ui_count; i++) { |
+ {3:UI} *ui = uis[i]; |
+ width = {5:MIN}(ui->width, width); |
+ height = {5:MIN}(ui->height, height); |
+ foo = {5:BAR}(ui->bazaar, bazaar); |
+ {4:for} ({3:UIExtension} j = {5:0}; ({3:int})j < kUIExtCount; j++) { |
+ ext_widgets[j] &= (ui->ui_ext[j] || inclusive); |
+ } |
+ } |
+ ^} |
+ |
+ ]]}
+
+ feed ":sort<cr>"
+ screen:expect{grid=[[
+ ^ |
+ ext_widgets[j] &= (ui->ui_ext[j] || inclusive); |
+ {3:UI} *ui = uis[i]; |
+ ext_widgets[i] = true; |
+ foo = {5:BAR}(ui->bazaar, bazaar); |
+ {4:for} ({3:UIExtension} j = {5:0}; ({3:int})j < kUIExtCount; j++) { |
+ height = {5:MIN}(ui->height, height); |
+ width = {5:MIN}(ui->width, width); |
+ } |
+ {3:bool} ext_widgets[kUIExtCount]; |
+ {3:bool} inclusive = ui_override(); |
+ {4:for} ({3:UIExtension} i = {5:0}; ({3:int})i < kUIExtCount; i++) { |
+ {4:for} ({3:size_t} i = {5:0}; i < ui_count; i++) { |
+ {3:int} width = {5:INT_MAX}, height = {5:INT_MAX}; |
+ } |
+ } |
+ {3:void} ui_refresh({3:void}) |
+ :sort |
+ ]]}
+
+ feed "u"
+
+ screen:expect{grid=[[
+ {3:int} width = {5:INT_MAX}, height = {5:INT_MAX}; |
+ {3:bool} ext_widgets[kUIExtCount]; |
+ {4:for} ({3:UIExtension} i = {5:0}; ({3:int})i < kUIExtCount; i++) { |
+ ext_widgets[i] = true; |
+ } |
+ |
+ {3:bool} inclusive = ui_override(); |
+ {4:for} ({3:size_t} i = {5:0}; i < ui_count; i++) { |
+ {3:UI} *ui = uis[i]; |
+ width = {5:MIN}(ui->width, width); |
+ height = {5:MIN}(ui->height, height); |
+ foo = {5:BAR}(ui->bazaar, bazaar); |
+ {4:for} ({3:UIExtension} j = {5:0}; ({3:int})j < kUIExtCount; j++) { |
+ ext_widgets[j] &= (ui->ui_ext[j] || inclusive); |
+ } |
+ } |
+ ^} |
+ 19 changes; before #2 {MATCH:.*}|
+ ]]}
+ end)
+
+ it("supports with custom parser", function()
+ if pending_c_parser(pending) then return end
+
+ screen:set_default_attr_ids {
+ [1] = {bold = true, foreground = Screen.colors.SeaGreen4};
+ }
+
+ insert(test_text)
+
+ screen:expect{ grid= [[
+ int width = INT_MAX, height = INT_MAX; |
+ bool ext_widgets[kUIExtCount]; |
+ for (UIExtension i = 0; (int)i < kUIExtCount; i++) { |
+ ext_widgets[i] = true; |
+ } |
+ |
+ bool inclusive = ui_override(); |
+ for (size_t i = 0; i < ui_count; i++) { |
+ UI *ui = uis[i]; |
+ width = MIN(ui->width, width); |
+ height = MIN(ui->height, height); |
+ foo = BAR(ui->bazaar, bazaar); |
+ for (UIExtension j = 0; (int)j < kUIExtCount; j++) { |
+ ext_widgets[j] &= (ui->ui_ext[j] || inclusive); |
+ } |
+ } |
+ ^} |
+ |
+ ]] }
+
+ exec_lua [[
+ parser = vim.treesitter.get_parser(0, "c")
+ query = vim.treesitter.parse_query("c", "(declaration) @decl")
+
+ local nodes = {}
+ for _, node in query:iter_captures(parser:parse()[1]:root(), 0, 0, 19) do
+ table.insert(nodes, node)
+ end
+
+ parser:set_included_regions({nodes})
+
+ local hl = vim.treesitter.highlighter.new(parser, {queries = {c = "(identifier) @type"}})
+ ]]
+
+ screen:expect{ grid = [[
+ int {1:width} = {1:INT_MAX}, {1:height} = {1:INT_MAX}; |
+ bool {1:ext_widgets}[{1:kUIExtCount}]; |
+ for (UIExtension {1:i} = 0; (int)i < kUIExtCount; i++) { |
+ ext_widgets[i] = true; |
+ } |
+ |
+ bool {1:inclusive} = {1:ui_override}(); |
+ for (size_t {1:i} = 0; i < ui_count; i++) { |
+ UI *{1:ui} = {1:uis}[{1:i}]; |
+ width = MIN(ui->width, width); |
+ height = MIN(ui->height, height); |
+ foo = BAR(ui->bazaar, bazaar); |
+ for (UIExtension {1:j} = 0; (int)j < kUIExtCount; j++) { |
+ ext_widgets[j] &= (ui->ui_ext[j] || inclusive); |
+ } |
+ } |
+ ^} |
+ |
+ ]] }
+ end)
+
+ it("supports injected languages", function()
+ if pending_c_parser(pending) then return end
+
+ insert([[
+ int x = INT_MAX;
+ #define READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y))
+ #define foo void main() { \
+ return 42; \
+ }
+ ]])
+
+ screen:expect{grid=[[
+ int x = INT_MAX; |
+ #define READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y))|
+ #define foo void main() { \ |
+ return 42; \ |
+ } |
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ exec_lua [[
+ local parser = vim.treesitter.get_parser(0, "c", {
+ queries = {c = "(preproc_def (preproc_arg) @c) (preproc_function_def value: (preproc_arg) @c)"}
+ })
+ local highlighter = vim.treesitter.highlighter
+ test_hl = highlighter.new(parser, {queries = {c = hl_query}})
+ ]]
+
+ screen:expect{grid=[[
+ {3:int} x = {5:INT_MAX}; |
+ #define {5:READ_STRING}(x, y) ({3:char_u} *)read_string((x), ({3:size_t})(y))|
+ #define foo {3:void} main() { \ |
+ {4:return} {5:42}; \ |
+ } |
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ end)
+end)
diff --git a/test/functional/treesitter/language_spec.lua b/test/functional/treesitter/language_spec.lua
new file mode 100644
index 0000000000..a5801271cb
--- /dev/null
+++ b/test/functional/treesitter/language_spec.lua
@@ -0,0 +1,71 @@
+local helpers = require('test.functional.helpers')(after_each)
+
+local clear = helpers.clear
+local eq = helpers.eq
+local exec_lua = helpers.exec_lua
+local pcall_err = helpers.pcall_err
+local matches = helpers.matches
+local pending_c_parser = helpers.pending_c_parser
+
+before_each(clear)
+
+describe('treesitter API', function()
+ -- error tests not requiring a parser library
+ it('handles missing language', function()
+ eq("Error executing lua: .../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers",
+ pcall_err(exec_lua, "parser = vim.treesitter.get_parser(0, 'borklang')"))
+
+ -- actual message depends on platform
+ matches("Error executing lua: Failed to load parser: uv_dlopen: .+",
+ pcall_err(exec_lua, "parser = vim.treesitter.require_language('borklang', 'borkbork.so')"))
+
+ -- Should not throw an error when silent
+ eq(false, exec_lua("return vim.treesitter.require_language('borklang', nil, true)"))
+ eq(false, exec_lua("return vim.treesitter.require_language('borklang', 'borkbork.so', true)"))
+
+ eq("Error executing lua: .../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers",
+ pcall_err(exec_lua, "parser = vim.treesitter.inspect_language('borklang')"))
+ end)
+
+ it('inspects language', function()
+ if pending_c_parser(pending) then return end
+
+ local keys, fields, symbols = unpack(exec_lua([[
+ local lang = vim.treesitter.inspect_language('c')
+ local keys, symbols = {}, {}
+ for k,_ in pairs(lang) do
+ keys[k] = true
+ end
+
+ -- symbols array can have "holes" and is thus not a valid msgpack array
+ -- but we don't care about the numbers here (checked in the parser test)
+ for _, v in pairs(lang.symbols) do
+ table.insert(symbols, v)
+ end
+ return {keys, lang.fields, symbols}
+ ]]))
+
+ eq({fields=true, symbols=true}, keys)
+
+ local fset = {}
+ for _,f in pairs(fields) do
+ eq("string", type(f))
+ fset[f] = true
+ end
+ eq(true, fset["directive"])
+ eq(true, fset["initializer"])
+
+ local has_named, has_anonymous
+ for _,s in pairs(symbols) do
+ eq("string", type(s[1]))
+ eq("boolean", type(s[2]))
+ if s[1] == "for_statement" and s[2] == true then
+ has_named = true
+ elseif s[1] == "|=" and s[2] == false then
+ has_anonymous = true
+ end
+ end
+ eq({true,true}, {has_named,has_anonymous})
+ end)
+end)
+
diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua
new file mode 100644
index 0000000000..f99362fbdf
--- /dev/null
+++ b/test/functional/treesitter/parser_spec.lua
@@ -0,0 +1,599 @@
+local helpers = require('test.functional.helpers')(after_each)
+
+local clear = helpers.clear
+local eq = helpers.eq
+local insert = helpers.insert
+local exec_lua = helpers.exec_lua
+local feed = helpers.feed
+local pending_c_parser = helpers.pending_c_parser
+
+before_each(clear)
+
+describe('treesitter parser API', function()
+
+ it('parses buffer', function()
+ if helpers.pending_win32(pending) or pending_c_parser(pending) then return end
+
+ insert([[
+ int main() {
+ int x = 3;
+ }]])
+
+ exec_lua([[
+ parser = vim.treesitter.get_parser(0, "c")
+ tree = parser:parse()[1]
+ root = tree:root()
+ lang = vim.treesitter.inspect_language('c')
+ ]])
+
+ eq("<tree>", exec_lua("return tostring(tree)"))
+ eq("<node translation_unit>", exec_lua("return tostring(root)"))
+ eq({0,0,3,0}, exec_lua("return {root:range()}"))
+
+ eq(1, exec_lua("return root:child_count()"))
+ exec_lua("child = root:child(0)")
+ eq("<node function_definition>", exec_lua("return tostring(child)"))
+ eq({0,0,2,1}, exec_lua("return {child:range()}"))
+
+ eq("function_definition", exec_lua("return child:type()"))
+ eq(true, exec_lua("return child:named()"))
+ eq("number", type(exec_lua("return child:symbol()")))
+ eq({'function_definition', true}, exec_lua("return lang.symbols[child:symbol()]"))
+
+ exec_lua("anon = root:descendant_for_range(0,8,0,9)")
+ eq("(", exec_lua("return anon:type()"))
+ eq(false, exec_lua("return anon:named()"))
+ eq("number", type(exec_lua("return anon:symbol()")))
+ eq({'(', false}, exec_lua("return lang.symbols[anon:symbol()]"))
+
+ exec_lua("descendant = root:descendant_for_range(1,2,1,12)")
+ eq("<node declaration>", exec_lua("return tostring(descendant)"))
+ eq({1,2,1,12}, exec_lua("return {descendant:range()}"))
+ eq("(declaration type: (primitive_type) declarator: (init_declarator declarator: (identifier) value: (number_literal)))", exec_lua("return descendant:sexpr()"))
+
+ feed("2G7|ay")
+ exec_lua([[
+ tree2 = parser:parse()[1]
+ root2 = tree2:root()
+ descendant2 = root2:descendant_for_range(1,2,1,13)
+ ]])
+ eq(false, exec_lua("return tree2 == tree1"))
+ eq(false, exec_lua("return root2 == root"))
+ eq("<node declaration>", exec_lua("return tostring(descendant2)"))
+ eq({1,2,1,13}, exec_lua("return {descendant2:range()}"))
+
+ eq(true, exec_lua("return child == child"))
+ -- separate lua object, but represents same node
+ eq(true, exec_lua("return child == root:child(0)"))
+ eq(false, exec_lua("return child == descendant2"))
+ eq(false, exec_lua("return child == nil"))
+ eq(false, exec_lua("return child == tree"))
+
+ eq("string", exec_lua("return type(child:id())"))
+ eq(true, exec_lua("return child:id() == child:id()"))
+ -- separate lua object, but represents same node
+ eq(true, exec_lua("return child:id() == root:child(0):id()"))
+ eq(false, exec_lua("return child:id() == descendant2:id()"))
+ eq(false, exec_lua("return child:id() == nil"))
+ eq(false, exec_lua("return child:id() == tree"))
+
+ -- unchanged buffer: return the same tree
+ eq(true, exec_lua("return parser:parse()[1] == tree2"))
+ end)
+
+ local test_text = [[
+void ui_refresh(void)
+{
+ int width = INT_MAX, height = INT_MAX;
+ bool ext_widgets[kUIExtCount];
+ for (UIExtension i = 0; (int)i < kUIExtCount; i++) {
+ ext_widgets[i] = true;
+ }
+
+ bool inclusive = ui_override();
+ for (size_t i = 0; i < ui_count; i++) {
+ UI *ui = uis[i];
+ width = MIN(ui->width, width);
+ height = MIN(ui->height, height);
+ foo = BAR(ui->bazaar, bazaar);
+ for (UIExtension j = 0; (int)j < kUIExtCount; j++) {
+ ext_widgets[j] &= (ui->ui_ext[j] || inclusive);
+ }
+ }
+}]]
+
+ it('allows to iterate over nodes children', function()
+ if pending_c_parser(pending) then return end
+
+ insert(test_text);
+
+ local res = exec_lua([[
+ parser = vim.treesitter.get_parser(0, "c")
+
+ func_node = parser:parse()[1]:root():child(0)
+
+ res = {}
+ for node, field in func_node:iter_children() do
+ table.insert(res, {node:type(), field})
+ end
+ return res
+ ]])
+
+ eq({
+ {"primitive_type", "type"},
+ {"function_declarator", "declarator"},
+ {"compound_statement", "body"}
+ }, res)
+ end)
+
+ it('allows to get a child by field', function()
+ if pending_c_parser(pending) then return end
+
+ insert(test_text);
+
+ local res = exec_lua([[
+ parser = vim.treesitter.get_parser(0, "c")
+
+ func_node = parser:parse()[1]:root():child(0)
+
+ local res = {}
+ for _, node in ipairs(func_node:field("type")) do
+ table.insert(res, {node:type(), node:range()})
+ end
+ return res
+ ]])
+
+ eq({{ "primitive_type", 0, 0, 0, 4 }}, res)
+
+ local res_fail = exec_lua([[
+ parser = vim.treesitter.get_parser(0, "c")
+
+ return #func_node:field("foo") == 0
+ ]])
+
+ assert(res_fail)
+ end)
+
+ local query = [[
+ ((call_expression function: (identifier) @minfunc (argument_list (identifier) @min_id)) (eq? @minfunc "MIN"))
+ "for" @keyword
+ (primitive_type) @type
+ (field_expression argument: (identifier) @fieldarg)
+ ]]
+
+ it("supports runtime queries", function()
+ if pending_c_parser(pending) then return end
+
+ local ret = exec_lua [[
+ return require"vim.treesitter.query".get_query("c", "highlights").captures[1]
+ ]]
+
+ eq('variable', ret)
+ end)
+
+ it('support query and iter by capture', function()
+ if pending_c_parser(pending) then return end
+
+ insert(test_text)
+
+ local res = exec_lua([[
+ cquery = vim.treesitter.parse_query("c", ...)
+ parser = vim.treesitter.get_parser(0, "c")
+ tree = parser:parse()[1]
+ res = {}
+ for cid, node in cquery:iter_captures(tree:root(), 0, 7, 14) do
+ -- can't transmit node over RPC. just check the name and range
+ table.insert(res, {cquery.captures[cid], node:type(), node:range()})
+ end
+ return res
+ ]], query)
+
+ eq({
+ { "type", "primitive_type", 8, 2, 8, 6 },
+ { "keyword", "for", 9, 2, 9, 5 },
+ { "type", "primitive_type", 9, 7, 9, 13 },
+ { "minfunc", "identifier", 11, 12, 11, 15 },
+ { "fieldarg", "identifier", 11, 16, 11, 18 },
+ { "min_id", "identifier", 11, 27, 11, 32 },
+ { "minfunc", "identifier", 12, 13, 12, 16 },
+ { "fieldarg", "identifier", 12, 17, 12, 19 },
+ { "min_id", "identifier", 12, 29, 12, 35 },
+ { "fieldarg", "identifier", 13, 14, 13, 16 }
+ }, res)
+ end)
+
+ it('support query and iter by match', function()
+ if pending_c_parser(pending) then return end
+
+ insert(test_text)
+
+ local res = exec_lua([[
+ cquery = vim.treesitter.parse_query("c", ...)
+ parser = vim.treesitter.get_parser(0, "c")
+ tree = parser:parse()[1]
+ res = {}
+ for pattern, match in cquery:iter_matches(tree:root(), 0, 7, 14) do
+ -- can't transmit node over RPC. just check the name and range
+ local mrepr = {}
+ for cid,node in pairs(match) do
+ table.insert(mrepr, {cquery.captures[cid], node:type(), node:range()})
+ end
+ table.insert(res, {pattern, mrepr})
+ end
+ return res
+ ]], query)
+
+ eq({
+ { 3, { { "type", "primitive_type", 8, 2, 8, 6 } } },
+ { 2, { { "keyword", "for", 9, 2, 9, 5 } } },
+ { 3, { { "type", "primitive_type", 9, 7, 9, 13 } } },
+ { 4, { { "fieldarg", "identifier", 11, 16, 11, 18 } } },
+ { 1, { { "minfunc", "identifier", 11, 12, 11, 15 }, { "min_id", "identifier", 11, 27, 11, 32 } } },
+ { 4, { { "fieldarg", "identifier", 12, 17, 12, 19 } } },
+ { 1, { { "minfunc", "identifier", 12, 13, 12, 16 }, { "min_id", "identifier", 12, 29, 12, 35 } } },
+ { 4, { { "fieldarg", "identifier", 13, 14, 13, 16 } } }
+ }, res)
+ end)
+
+ it('allow loading query with escaped quotes and capture them with `lua-match?` and `vim-match?`', function()
+ if pending_c_parser(pending) then return end
+
+ insert('char* astring = "Hello World!";')
+
+ local res = exec_lua([[
+ cquery = vim.treesitter.parse_query("c", '((_) @quote (vim-match? @quote "^\\"$")) ((_) @quote (lua-match? @quote "^\\"$"))')
+ parser = vim.treesitter.get_parser(0, "c")
+ tree = parser:parse()[1]
+ res = {}
+ for pattern, match in cquery:iter_matches(tree:root(), 0) do
+ -- can't transmit node over RPC. just check the name and range
+ local mrepr = {}
+ for cid,node in pairs(match) do
+ table.insert(mrepr, {cquery.captures[cid], node:type(), node:range()})
+ end
+ table.insert(res, {pattern, mrepr})
+ end
+ return res
+ ]])
+
+ eq({
+ { 1, { { "quote", '"', 0, 16, 0, 17 } } },
+ { 2, { { "quote", '"', 0, 16, 0, 17 } } },
+ { 1, { { "quote", '"', 0, 29, 0, 30 } } },
+ { 2, { { "quote", '"', 0, 29, 0, 30 } } },
+ }, res)
+ end)
+
+ it('allows to add predicates', function()
+ insert([[
+ int main(void) {
+ return 0;
+ }
+ ]])
+
+ local custom_query = "((identifier) @main (#is-main? @main))"
+
+ local res = exec_lua([[
+ local query = require"vim.treesitter.query"
+
+ local function is_main(match, pattern, bufnr, predicate)
+ local node = match[ predicate[2] ]
+
+ return query.get_node_text(node, bufnr)
+ end
+
+ local parser = vim.treesitter.get_parser(0, "c")
+
+ query.add_predicate("is-main?", is_main)
+
+ local query = query.parse_query("c", ...)
+
+ local nodes = {}
+ for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do
+ table.insert(nodes, {node:range()})
+ end
+
+ return nodes
+ ]], custom_query)
+
+ eq({{0, 4, 0, 8}}, res)
+
+ local res_list = exec_lua[[
+ local query = require'vim.treesitter.query'
+
+ local list = query.list_predicates()
+
+ table.sort(list)
+
+ return list
+ ]]
+
+ eq({ 'contains?', 'eq?', 'is-main?', 'lua-match?', 'match?', 'vim-match?' }, res_list)
+ end)
+
+
+ it('allows to set simple ranges', function()
+ if pending_c_parser(pending) then return end
+
+ insert(test_text)
+
+ local res = exec_lua [[
+ parser = vim.treesitter.get_parser(0, "c")
+ return { parser:parse()[1]:root():range() }
+ ]]
+
+ eq({0, 0, 19, 0}, res)
+
+ -- The following sets the included ranges for the current parser
+ -- As stated here, this only includes the function (thus the whole buffer, without the last line)
+ local res2 = exec_lua [[
+ local root = parser:parse()[1]:root()
+ parser:set_included_regions({{root:child(0)}})
+ parser:invalidate()
+ return { parser:parse()[1]:root():range() }
+ ]]
+
+ eq({0, 0, 18, 1}, res2)
+
+ local range = exec_lua [[
+ local res = {}
+ for _, region in ipairs(parser:included_regions()) do
+ for _, node in ipairs(region) do
+ table.insert(res, {node:range()})
+ end
+ end
+ return res
+ ]]
+
+ eq(range, { { 0, 0, 18, 1 } })
+
+ local range_tbl = exec_lua [[
+ parser:set_included_regions { { { 0, 0, 17, 1 } } }
+ parser:parse()
+ return parser:included_regions()
+ ]]
+
+ eq(range_tbl, { { { 0, 0, 0, 17, 1, 508 } } })
+ end)
+ it("allows to set complex ranges", function()
+ if pending_c_parser() then return end
+
+ insert(test_text)
+
+ local res = exec_lua [[
+ parser = vim.treesitter.get_parser(0, "c")
+ query = vim.treesitter.parse_query("c", "(declaration) @decl")
+
+ local nodes = {}
+ for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do
+ table.insert(nodes, node)
+ end
+
+ parser:set_included_regions({nodes})
+
+ local root = parser:parse()[1]:root()
+
+ local res = {}
+ for i=0,(root:named_child_count() - 1) do
+ table.insert(res, { root:named_child(i):range() })
+ end
+ return res
+ ]]
+
+ eq({
+ { 2, 2, 2, 40 },
+ { 3, 2, 3, 32 },
+ { 4, 7, 4, 25 },
+ { 8, 2, 8, 33 },
+ { 9, 7, 9, 20 },
+ { 10, 4, 10, 20 },
+ { 14, 9, 14, 27 } }, res)
+ end)
+
+ it("allows to create string parsers", function()
+ local ret = exec_lua [[
+ local parser = vim.treesitter.get_string_parser("int foo = 42;", "c")
+ return { parser:parse()[1]:root():range() }
+ ]]
+
+ eq({ 0, 0, 0, 13 }, ret)
+ end)
+
+ it("allows to run queries with string parsers", function()
+ local txt = [[
+ int foo = 42;
+ int bar = 13;
+ ]]
+
+ local ret = exec_lua([[
+ local str = ...
+ local parser = vim.treesitter.get_string_parser(str, "c")
+
+ local nodes = {}
+ local query = vim.treesitter.parse_query("c", '((identifier) @id (eq? @id "foo"))')
+
+ for _, node in query:iter_captures(parser:parse()[1]:root(), str) do
+ table.insert(nodes, { node:range() })
+ end
+
+ return nodes]], txt)
+
+ eq({ {0, 10, 0, 13} }, ret)
+ end)
+
+ it("should use node range when omitted", function()
+ local txt = [[
+ int foo = 42;
+ int bar = 13;
+ ]]
+
+ local ret = exec_lua([[
+ local str = ...
+ local parser = vim.treesitter.get_string_parser(str, "c")
+
+ local nodes = {}
+ local query = vim.treesitter.parse_query("c", '((identifier) @foo)')
+ local first_child = parser:parse()[1]:root():child(1)
+
+ for _, node in query:iter_captures(first_child, str) do
+ table.insert(nodes, { node:range() })
+ end
+
+ return nodes]], txt)
+
+ eq({ {1, 10, 1, 13} }, ret)
+ end)
+
+ describe("when creating a language tree", function()
+ local function get_ranges()
+ return exec_lua([[
+ local result = {}
+ parser:for_each_tree(function(tree) table.insert(result, {tree:root():range()}) end)
+ return result
+ ]])
+ end
+
+ before_each(function()
+ insert([[
+int x = INT_MAX;
+#define READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y))
+#define READ_STRING_OK(x, y) (char_u *)read_string((x), (size_t)(y))
+#define VALUE 123
+#define VALUE1 123
+#define VALUE2 123
+ ]])
+ end)
+
+ describe("when parsing regions independently", function()
+ it("should inject a language", function()
+ exec_lua([[
+ parser = vim.treesitter.get_parser(0, "c", {
+ queries = {
+ c = "(preproc_def (preproc_arg) @c) (preproc_function_def value: (preproc_arg) @c)"}})
+ ]])
+
+ eq("table", exec_lua("return type(parser:children().c)"))
+ eq(5, exec_lua("return #parser:children().c:trees()"))
+ eq({
+ {0, 0, 7, 0}, -- root tree
+ {3, 14, 3, 17}, -- VALUE 123
+ {4, 15, 4, 18}, -- VALUE1 123
+ {5, 15, 5, 18}, -- VALUE2 123
+ {1, 26, 1, 65}, -- READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y))
+ {2, 29, 2, 68} -- READ_STRING_OK(x, y) (char_u *)read_string((x), (size_t)(y))
+ }, get_ranges())
+ end)
+ end)
+
+ describe("when parsing regions combined", function()
+ it("should inject a language", function()
+ exec_lua([[
+ parser = vim.treesitter.get_parser(0, "c", {
+ queries = {
+ c = "(preproc_def (preproc_arg) @c @combined) (preproc_function_def value: (preproc_arg) @c @combined)"}})
+ ]])
+
+ eq("table", exec_lua("return type(parser:children().c)"))
+ eq(2, exec_lua("return #parser:children().c:trees()"))
+ eq({
+ {0, 0, 7, 0}, -- root tree
+ {3, 14, 5, 18}, -- VALUE 123
+ -- VALUE1 123
+ -- VALUE2 123
+ {1, 26, 2, 68} -- READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y))
+ -- READ_STRING_OK(x, y) (char_u *)read_string((x), (size_t)(y))
+ }, get_ranges())
+ end)
+ end)
+
+ describe("when using the offset directive", function()
+ it("should shift the range by the directive amount", function()
+ exec_lua([[
+ parser = vim.treesitter.get_parser(0, "c", {
+ queries = {
+ c = "(preproc_def ((preproc_arg) @c (#offset! @c 0 2 0 -1))) (preproc_function_def value: (preproc_arg) @c)"}})
+ ]])
+
+ eq("table", exec_lua("return type(parser:children().c)"))
+ eq({
+ {0, 0, 7, 0}, -- root tree
+ {3, 15, 3, 16}, -- VALUE 123
+ {4, 16, 4, 17}, -- VALUE1 123
+ {5, 16, 5, 17}, -- VALUE2 123
+ {1, 26, 1, 65}, -- READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y))
+ {2, 29, 2, 68} -- READ_STRING_OK(x, y) (char_u *)read_string((x), (size_t)(y))
+ }, get_ranges())
+ end)
+ 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)
+
+ describe("when getting/setting match data", function()
+ describe("when setting for the whole match", function()
+ it("should set/get the data correctly", function()
+ insert([[
+ int x = 3;
+ ]])
+
+ local result = exec_lua([[
+ local result
+
+ query = vim.treesitter.parse_query("c", '((number_literal) @number (#set! "key" "value"))')
+ parser = vim.treesitter.get_parser(0, "c")
+
+ for pattern, match, metadata in query:iter_matches(parser:parse()[1]:root(), 0) do
+ result = metadata.key
+ end
+
+ return result
+ ]])
+
+ eq(result, "value")
+ end)
+ end)
+
+ describe("when setting for a capture match", function()
+ it("should set/get the data correctly", function()
+ insert([[
+ int x = 3;
+ ]])
+
+ local result = exec_lua([[
+ local result
+
+ query = vim.treesitter.parse_query("c", '((number_literal) @number (#set! @number "key" "value"))')
+ parser = vim.treesitter.get_parser(0, "c")
+
+ for pattern, match, metadata in query:iter_matches(parser:parse()[1]:root(), 0) do
+ result = metadata[pattern].key
+ end
+
+ return result
+ ]])
+
+ eq(result, "value")
+ end)
+ end)
+ end)
+end)