aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--config/config.h.in1
-rw-r--r--contrib/flake.lock43
-rw-r--r--contrib/flake.nix11
-rw-r--r--runtime/autoload/netrw.vim282
-rw-r--r--runtime/autoload/netrwSettings.vim2
-rw-r--r--runtime/autoload/netrw_gitignore.vim58
-rw-r--r--runtime/autoload/tar.vim277
-rw-r--r--runtime/doc/api.txt44
-rw-r--r--runtime/doc/eval.txt74
-rw-r--r--runtime/doc/insert.txt6
-rw-r--r--runtime/doc/lsp.txt28
-rw-r--r--runtime/doc/options.txt6
-rw-r--r--runtime/doc/pi_netrw.txt50
-rw-r--r--runtime/doc/pi_tar.txt109
-rw-r--r--runtime/doc/usr_41.txt1
-rw-r--r--runtime/doc/vim_diff.txt8
-rw-r--r--runtime/filetype.vim6
-rw-r--r--runtime/lua/vim/lsp.lua51
-rw-r--r--runtime/lua/vim/lsp/buf.lua12
-rw-r--r--runtime/lua/vim/lsp/callbacks.lua4
-rw-r--r--runtime/lua/vim/lsp/diagnostic.lua18
-rw-r--r--runtime/lua/vim/lsp/handlers.lua4
-rw-r--r--runtime/lua/vim/lsp/protocol.lua2
-rw-r--r--runtime/lua/vim/lsp/rpc.lua5
-rw-r--r--runtime/lua/vim/lsp/util.lua82
-rw-r--r--runtime/lua/vim/treesitter/languagetree.lua16
-rw-r--r--runtime/plugin/netrwPlugin.vim8
-rw-r--r--runtime/plugin/tarPlugin.vim6
-rw-r--r--runtime/syntax/netrw.vim4
-rw-r--r--src/nvim/api/buffer.c77
-rw-r--r--src/nvim/charset.c2
-rw-r--r--src/nvim/decoration.c91
-rw-r--r--src/nvim/decoration.h8
-rw-r--r--src/nvim/edit.c15
-rw-r--r--src/nvim/eval.c13
-rw-r--r--src/nvim/eval.h13
-rw-r--r--src/nvim/eval.lua1
-rw-r--r--src/nvim/eval/funcs.c48
-rw-r--r--src/nvim/eval/typval.h1
-rw-r--r--src/nvim/eval/userfunc.c91
-rw-r--r--src/nvim/ex_cmds.c4
-rw-r--r--src/nvim/ex_cmds.lua4
-rw-r--r--src/nvim/ex_cmds2.c69
-rw-r--r--src/nvim/ex_getln.c2
-rw-r--r--src/nvim/globals.h16
-rw-r--r--src/nvim/memline.c2
-rw-r--r--src/nvim/misc1.c2
-rw-r--r--src/nvim/normal.c43
-rw-r--r--src/nvim/ops.c9
-rw-r--r--src/nvim/path.c2
-rw-r--r--src/nvim/pos.h7
-rw-r--r--src/nvim/screen.c65
-rw-r--r--src/nvim/search.c10
-rw-r--r--src/nvim/tag.c2
-rw-r--r--src/nvim/testdir/test_alot.vim1
-rw-r--r--src/nvim/testdir/test_exit.vim29
-rw-r--r--src/nvim/testdir/test_filetype.vim2
-rw-r--r--src/nvim/testdir/test_functions.vim25
-rw-r--r--src/nvim/testdir/test_options.vim42
-rw-r--r--src/nvim/testdir/test_statusline.vim16
-rw-r--r--src/nvim/testdir/test_user_func.vim53
-rw-r--r--src/nvim/tui/input.c4
-rw-r--r--src/nvim/window.c12
-rw-r--r--test/functional/ex_cmds/source_spec.lua47
-rw-r--r--test/functional/fixtures/fake-lsp-server.lua4
-rw-r--r--test/functional/legacy/options_spec.lua47
-rw-r--r--test/functional/lua/buffer_updates_spec.lua8
-rw-r--r--test/functional/plugin/lsp/diagnostic_spec.lua63
-rw-r--r--test/functional/plugin/lsp_spec.lua39
-rw-r--r--test/functional/ui/decorations_spec.lua95
71 files changed, 1654 insertions, 650 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e3c67c55cd..4e427eea26 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -83,6 +83,8 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
endif()
if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ # Ignore case when comparing filenames on Windows and Mac.
+ set(CASE_INSENSITIVE_FILENAME TRUE)
# Enable fixing case-insensitive filenames for Windows and Mac.
set(USE_FNAME_CASE TRUE)
endif()
diff --git a/config/config.h.in b/config/config.h.in
index 95e2c872a3..275bff79a0 100644
--- a/config/config.h.in
+++ b/config/config.h.in
@@ -40,6 +40,7 @@
#cmakedefine HAVE_WORKING_LIBINTL
#cmakedefine HAVE_WSL
#cmakedefine UNIX
+#cmakedefine CASE_INSENSITIVE_FILENAME
#cmakedefine USE_FNAME_CASE
#cmakedefine HAVE_SYS_UIO_H
#ifdef HAVE_SYS_UIO_H
diff --git a/contrib/flake.lock b/contrib/flake.lock
new file mode 100644
index 0000000000..521b7629d9
--- /dev/null
+++ b/contrib/flake.lock
@@ -0,0 +1,43 @@
+{
+ "nodes": {
+ "flake-utils": {
+ "locked": {
+ "lastModified": 1610051610,
+ "narHash": "sha256-U9rPz/usA1/Aohhk7Cmc2gBrEEKRzcW4nwPWMPwja4Y=",
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "rev": "3982c9903e93927c2164caa727cd3f6a0e6d14cc",
+ "type": "github"
+ },
+ "original": {
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "type": "github"
+ }
+ },
+ "nixpkgs": {
+ "locked": {
+ "lastModified": 1613226215,
+ "narHash": "sha256-3rA5cGIrBHD6yeKhNhsF7/t461ww25oJY8KyBb0IhjU=",
+ "owner": "nixos",
+ "repo": "nixpkgs",
+ "rev": "ff96a0fa5635770390b184ae74debea75c3fd534",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nixos",
+ "ref": "nixos-unstable",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "root": {
+ "inputs": {
+ "flake-utils": "flake-utils",
+ "nixpkgs": "nixpkgs"
+ }
+ }
+ },
+ "root": "root",
+ "version": 7
+}
diff --git a/contrib/flake.nix b/contrib/flake.nix
index d18534215c..08126a48e9 100644
--- a/contrib/flake.nix
+++ b/contrib/flake.nix
@@ -27,15 +27,20 @@
});
# a development binary to help debug issues
- neovim-debug = (neovim.override {
- stdenv = if pkgs.stdenv.isLinux then pkgs.llvmPackages_latest.stdenv else pkgs.stdenv;
+ neovim-debug = let
+ stdenv = pkgs.stdenvAdapters.keepDebugInfo (if pkgs.stdenv.isLinux then pkgs.llvmPackages_latest.stdenv else pkgs.stdenv);
+ in
+ pkgs.enableDebugging ((neovim.override {
lua = pkgs.enableDebugging pkgs.luajit;
+ inherit stdenv;
}).overrideAttrs (oa: {
cmakeBuildType = "Debug";
cmakeFlags = oa.cmakeFlags ++ [
"-DMIN_LOG_LEVEL=0"
];
- });
+
+ disallowedReferences = [];
+ }));
# for neovim developers, very slow
# brings development tools as well
diff --git a/runtime/autoload/netrw.vim b/runtime/autoload/netrw.vim
index b69ad7187a..7a799abb13 100644
--- a/runtime/autoload/netrw.vim
+++ b/runtime/autoload/netrw.vim
@@ -1,8 +1,8 @@
" netrw.vim: Handles file transfer and remote directory listing across
" AUTOLOAD SECTION
-" Date: Jul 16, 2019
-" Version: 165
-" Maintainer: Charles E Campbell <NdrOchip@ScampbellPfamily.AbizM-NOSPAM>
+" Date: Jan 07, 2020
+" Version: 168
+" Maintainer: Charles E Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
" GetLatestVimScripts: 1075 1 :AutoInstall: netrw.vim
" Copyright: Copyright (C) 2016 Charles E. Campbell {{{1
" Permission is hereby granted to use and distribute this code,
@@ -13,6 +13,10 @@
" expressed or implied. By using this plugin, you agree that
" in no event will the copyright holder be liable for any damages
" resulting from the use of this software.
+"
+" Note: the code here was started in 1999 under a much earlier version of vim. The directory browsing
+" code was written using vim v6, which did not have Lists (Lists were first offered with vim-v7).
+"
"redraw!|call DechoSep()|call inputsave()|call input("Press <cr> to continue")|call inputrestore()
"
" But be doers of the Word, and not only hearers, deluding your own selves {{{1
@@ -39,7 +43,7 @@ if exists("s:needspatches")
endfor
endif
-let g:loaded_netrw = "v165"
+let g:loaded_netrw = "v168"
if !exists("s:NOTE")
let s:NOTE = 0
let s:WARNING = 1
@@ -64,7 +68,7 @@ setl cpo&vim
" Usage: netrw#ErrorMsg(s:NOTE | s:WARNING | s:ERROR,"some message",error-number)
" netrw#ErrorMsg(s:NOTE | s:WARNING | s:ERROR,["message1","message2",...],error-number)
" (this function can optionally take a list of messages)
-" Mar 21, 2017 : max errnum currently is 105
+" Dec 2, 2019 : max errnum currently is 106
fun! netrw#ErrorMsg(level,msg,errnum)
" call Dfunc("netrw#ErrorMsg(level=".a:level." msg<".a:msg."> errnum=".a:errnum.") g:netrw_use_errorwindow=".g:netrw_use_errorwindow)
@@ -232,12 +236,12 @@ if !exists("g:netrw_ftp_options")
let g:netrw_ftp_options= "-i -n"
endif
if !exists("g:netrw_http_cmd")
- if executable("curl")
- let g:netrw_http_cmd = "curl"
- call s:NetrwInit("g:netrw_http_xcmd","-L -o")
- elseif executable("wget")
+ if executable("wget")
let g:netrw_http_cmd = "wget"
call s:NetrwInit("g:netrw_http_xcmd","-q -O")
+ elseif executable("curl")
+ let g:netrw_http_cmd = "curl"
+ call s:NetrwInit("g:netrw_http_xcmd","-L -o")
elseif executable("elinks")
let g:netrw_http_cmd = "elinks"
call s:NetrwInit("g:netrw_http_xcmd","-source >")
@@ -443,23 +447,9 @@ if !exists("g:netrw_localmovecmd")
let g:netrw_localmovecmd= ""
endif
endif
-if v:version < 704 || (v:version == 704 && !has("patch1107"))
- " 1109 provides for delete(tmpdir,"d") which is what will be used
- if exists("g:netrw_local_rmdir")
- let g:netrw_localrmdir= g:netrw_local_rmdir
- call netrw#ErrorMsg(s:NOTE,"g:netrw_local_rmdir is deprecated in favor of g:netrw_localrmdir",86)
- endif
- if has("win32") || has("win95") || has("win64") || has("win16")
- if g:netrw_cygwin
- call s:NetrwInit("g:netrw_localrmdir","rmdir")
- else
- let g:netrw_localrmdir = expand("$COMSPEC")
- let g:netrw_localrmdiropt= " /c rmdir"
- endif
- else
- call s:NetrwInit("g:netrw_localrmdir","rmdir")
- endif
-endif
+" following serves as an example for how to insert a version&patch specific test
+"if v:version < 704 || (v:version == 704 && !has("patch1107"))
+"endif
call s:NetrwInit("g:netrw_liststyle" , s:THINLIST)
" sanity checks
if g:netrw_liststyle < 0 || g:netrw_liststyle >= s:MAXLIST
@@ -1500,7 +1490,8 @@ fun! netrw#Obtain(islocal,fname,...)
" -i : turns off interactive prompting from ftp
" -n unix : DON'T use <.netrc>, even though it exists
" -n win32: quit being obnoxious about password
- NetrwKeepj norm! 1Gdd
+ " Note: using "_dd to delete to the black hole register; avoids messing up @@
+ NetrwKeepj norm! 1G"_dd
call s:NetrwExe(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." ".g:netrw_ftp_options)
" If the result of the ftp operation isn't blank, show an error message (tnx to Doug Claar)
if getline(1) !~ "^$"
@@ -1614,7 +1605,6 @@ fun! s:NetrwOptionsSave(vt)
let {a:vt}netrw_cpokeep = &l:cpo
let {a:vt}netrw_diffkeep = &l:diff
let {a:vt}netrw_fenkeep = &l:fen
-" call Decho("saving current settings: got here#1",'~'.expand("<slnum>"))
if !exists("g:netrw_ffkeep") || g:netrw_ffkeep
let {a:vt}netrw_ffkeep = &l:ff
endif
@@ -1633,7 +1623,6 @@ fun! s:NetrwOptionsSave(vt)
let {a:vt}netrw_rokeep = &l:ro
let {a:vt}netrw_selkeep = &l:sel
let {a:vt}netrw_spellkeep = &l:spell
-" call Decho("saving current settings: got here#2",'~'.expand("<slnum>"))
if !g:netrw_use_noswf
let {a:vt}netrw_swfkeep = &l:swf
endif
@@ -1647,6 +1636,7 @@ fun! s:NetrwOptionsSave(vt)
" call Decho("saving a few selected netrw-related variables",'~'.expand("<slnum>"))
if g:netrw_keepdir
let {a:vt}netrw_dirkeep = getcwd()
+" call Decho("saving to ".a:vt."netrw_dirkeep<".{a:vt}netrw_dirkeep.">",'~'.expand("<slnum>"))
endif
sil! let {a:vt}netrw_slashkeep= @/
@@ -1713,6 +1703,7 @@ fun! s:NetrwOptionsRestore(vt)
" call Dfunc("s:NetrwOptionsRestore(vt<".a:vt.">) win#".winnr()." buf#".bufnr("%")."<".bufname("%")."> winnr($)=".winnr("$"))
" call Decho("settings buf#".bufnr("%")."<".bufname("%").">: ".((&l:ma == 0)? "no" : "")."ma ".((&l:mod == 0)? "no" : "")."mod ".((&l:bl == 0)? "no" : "")."bl ".((&l:ro == 0)? "no" : "")."ro fo=".&l:fo." a:vt=".a:vt,'~'.expand("<slnum>"))
if !exists("{a:vt}netrw_optionsave")
+" call Decho("case ".a:vt."netrw_optionsave : doesn't exist",'~'.expand("<slnum>"))
" call Decho("settings buf#".bufnr("%")."<".bufname("%").">: ".((&l:ma == 0)? "no" : "")."ma ".((&l:mod == 0)? "no" : "")."mod ".((&l:bl == 0)? "no" : "")."bl ".((&l:ro == 0)? "no" : "")."ro fo=".&l:fo." a:vt=".a:vt,'~'.expand("<slnum>"))
" call Decho("ro=".&l:ro." ma=".&l:ma." mod=".&l:mod." wrap=".&l:wrap." (filename<".expand("%")."> win#".winnr()." ft<".&ft.">)",'~'.expand("<slnum>"))
" call Dret("s:NetrwOptionsRestore : ".a:vt."netrw_optionsave doesn't exist")
@@ -1854,7 +1845,7 @@ endfun
" Used by s:NetrwOptionsRestore() to restore each netrw-senstive setting
" keepvars are set up by s:NetrwOptionsSave
fun! s:NetrwRestoreSetting(keepvar,setting)
-"" call Dfunc("s:NetrwRestoreSetting(a:keepvar<".a:keepvar."> a:setting<".a:setting.">)")
+""" call Dfunc("s:NetrwRestoreSetting(a:keepvar<".a:keepvar."> a:setting<".a:setting.">)")
" typically called from s:NetrwOptionsRestore
" call s:NetrwRestoreSettings(keep-option-variable-name,'associated-option')
@@ -1869,7 +1860,7 @@ fun! s:NetrwRestoreSetting(keepvar,setting)
"" call Decho("fyi: a:setting<".a:setting."> setting<".setting.">")
if setting != keepvarval
-"" call Decho("restore setting<".a:setting."=".setting."> to keepvarval<".keepvarval.">")
+"" call Decho("restore setting<".a:setting."> (currently=".setting.") to keepvarval<".keepvarval.">")
if type(a:setting) == 0
exe "let ".a:setting."= ".keepvarval
elseif type(a:setting) == 1
@@ -2159,7 +2150,7 @@ fun! netrw#NetRead(mode,...)
" -i : turns off interactive prompting from ftp
" -n unix : DON'T use <.netrc>, even though it exists
" -n win32: quit being obnoxious about password
- NetrwKeepj norm! 1Gdd
+ NetrwKeepj norm! 1G"_dd
call s:NetrwExe(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." ".g:netrw_ftp_options)
" If the result of the ftp operation isn't blank, show an error message (tnx to Doug Claar)
if getline(1) !~ "^$"
@@ -2259,7 +2250,7 @@ fun! netrw#NetRead(mode,...)
NetrwKeepj put ='quit'
" perform cadaver operation:
- NetrwKeepj norm! 1Gdd
+ NetrwKeepj norm! 1G"_dd
call s:NetrwExe(s:netrw_silentxfer."%!".g:netrw_dav_cmd)
keepj bd!
endif
@@ -2575,7 +2566,7 @@ fun! netrw#NetWrite(...) range
" -i : turns off interactive prompting from ftp
" -n unix : DON'T use <.netrc>, even though it exists
" -n win32: quit being obnoxious about password
- NetrwKeepj norm! 1Gdd
+ NetrwKeepj norm! 1G"_dd
call s:NetrwExe(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." ".g:netrw_ftp_options)
" If the result of the ftp operation isn't blank, show an error message (tnx to Doug Claar)
if getline(1) !~ "^$"
@@ -2641,7 +2632,7 @@ fun! netrw#NetWrite(...) range
NetrwKeepj put ='put '.tmpfile.' '.netrw_fname
" perform cadaver operation:
- NetrwKeepj norm! 1Gdd
+ NetrwKeepj norm! 1G"_dd
call s:NetrwExe(s:netrw_silentxfer."%!".g:netrw_dav_cmd)
" remove enew buffer (quietly)
@@ -2827,7 +2818,7 @@ fun! s:NetrwGetFile(readcmd, tfile, method)
" readcmd=='t': simply do nothing
if a:readcmd == 't'
" call Decho(" ro=".&l:ro." ma=".&l:ma." mod=".&l:mod." wrap=".&l:wrap." (filename<".expand("%")."> win#".winnr()." ft<".&ft.">)",'~'.expand("<slnum>"))
-" call Dret("NetrwGetFile : skip read of <".a:tfile.">")
+" call Dret("NetrwGetFile : skip read of tfile<".a:tfile.">")
return
endif
@@ -4323,7 +4314,7 @@ fun! s:NetrwGetWord()
let curline= getline('.')
if curline =~# '"\s*Sorted by\s'
- NetrwKeepj norm! s
+ NetrwKeepj norm! "_s
let s:netrw_skipbrowse= 1
echo 'Pressing "s" also works'
@@ -5158,17 +5149,31 @@ fun! s:NetrwBrowseUpDir(islocal)
endfun
" ---------------------------------------------------------------------
-" netrw#BrowseX: (implements "x") executes a special "viewer" script or program for the {{{2
+" netrw#BrowseX: (implements "x" and "gx") executes a special "viewer" script or program for the {{{2
" given filename; typically this means given their extension.
" 0=local, 1=remote
fun! netrw#BrowseX(fname,remote)
-" call Dfunc("netrw#BrowseX(fname<".a:fname."> remote=".a:remote.")")
-
- " if its really just a local directory, then do a "gf" instead
- if (a:remote == 0 && isdirectory(a:fname)) || (a:remote == 1 && a:fname =~ '/$' && a:fname !~ '^https\=:')
+ let use_ctrlo= 1
+" call Dfunc("netrw#BrowseX(fname<".a:fname."> remote=".a:remote.") implements x and gx maps")
+
+ if a:remote == 0 && isdirectory(a:fname)
+ " if its really just a local directory, then do a "gf" instead
+" call Decho("remote≡0 and a:fname<".a:fname."> ".(isdirectory(a:fname)? "is a directory" : "is not a directory"),'~'.expand("<slnum>"))
+" call Decho("..appears to be a local directory; using e ".a:fname." instead",'~'.expand("<slnum>"))
+ exe "e ".a:fname
+" call Dret("netrw#BrowseX")
+ return
+ elseif a:remote == 1 && a:fname !~ '^https\=:' && a:fname =~ '/$'
+ " remote directory, not a webpage access, looks like an attempt to do a directory listing
+" call Decho("remote≡1 and a:fname<".a:fname.">",'~'.expand("<slnum>"))
+" call Decho("..and fname ".((a:fname =~ '^https\=:')? 'matches' : 'does not match').'^https\=:','~'.expand("<slnum>"))
+" call Decho("..and fname ".((a:fname =~ '/$')? 'matches' : 'does not match').' /$','~'.expand("<slnum>"))
+" call Decho("..appears to be a remote directory listing request; using gf instead",'~'.expand("<slnum>"))
norm! gf
-" call Dret("(netrw#BrowseX) did gf instead")
+" call Dret("netrw#BrowseX")
+ return
endif
+" call Decho("not a local file nor a webpage request",'~'.expand("<slnum>"))
let ykeep = @@
let screenposn = winsaveview()
@@ -5266,10 +5271,9 @@ fun! netrw#BrowseX(fname,remote)
endif
" call Decho("set up redirection: redir{".redir."} srr{".&srr."}",'~'.expand("<slnum>"))
- " extract any viewing options. Assumes that they're set apart by quotes.
-" call Decho("extract any viewing options",'~'.expand("<slnum>"))
+ " extract any viewing options. Assumes that they're set apart by spaces.
if exists("g:netrw_browsex_viewer")
-" call Decho("g:netrw_browsex_viewer<".g:netrw_browsex_viewer.">",'~'.expand("<slnum>"))
+" call Decho("extract any viewing options from g:netrw_browsex_viewer<".g:netrw_browsex_viewer.">",'~'.expand("<slnum>"))
if g:netrw_browsex_viewer =~ '\s'
let viewer = substitute(g:netrw_browsex_viewer,'\s.*$','','')
let viewopt = substitute(g:netrw_browsex_viewer,'^\S\+\s*','','')." "
@@ -5292,16 +5296,16 @@ fun! netrw#BrowseX(fname,remote)
" execute the file handler
" call Decho("execute the file handler (if any)",'~'.expand("<slnum>"))
if exists("g:netrw_browsex_viewer") && g:netrw_browsex_viewer == '-'
-" call Decho("g:netrw_browsex_viewer<".g:netrw_browsex_viewer.">",'~'.expand("<slnum>"))
+" call Decho("(netrw#BrowseX) g:netrw_browsex_viewer<".g:netrw_browsex_viewer.">",'~'.expand("<slnum>"))
let ret= netrwFileHandlers#Invoke(exten,fname)
elseif exists("g:netrw_browsex_viewer") && executable(viewer)
-" call Decho("g:netrw_browsex_viewer<".g:netrw_browsex_viewer.">",'~'.expand("<slnum>"))
+" call Decho("(netrw#BrowseX) g:netrw_browsex_viewer<".g:netrw_browsex_viewer.">",'~'.expand("<slnum>"))
call s:NetrwExe("sil !".viewer." ".viewopt.s:ShellEscape(fname,1).redir)
let ret= v:shell_error
elseif has("win32") || has("win64")
-" call Decho("win".(has("win32")? "32" : "64")",'~'.expand("<slnum>"))
+" call Decho("(netrw#BrowseX) win".(has("win32")? "32" : "64"),'~'.expand("<slnum>"))
if executable("start")
call s:NetrwExe('sil! !start rundll32 url.dll,FileProtocolHandler '.s:ShellEscape(fname,1))
elseif executable("rundll32")
@@ -5309,56 +5313,68 @@ fun! netrw#BrowseX(fname,remote)
else
call netrw#ErrorMsg(s:WARNING,"rundll32 not on path",74)
endif
- " call inputsave()|call input("Press <cr> to continue")|call inputrestore()
let ret= v:shell_error
elseif has("win32unix")
let winfname= 'c:\cygwin'.substitute(fname,'/','\\','g')
-" call Decho("cygwin: winfname<".s:ShellEscape(winfname,1).">",'~'.expand("<slnum>"))
+" call Decho("(netrw#BrowseX) cygwin: winfname<".s:ShellEscape(winfname,1).">",'~'.expand("<slnum>"))
if executable("start")
+" call Decho("(netrw#BrowseX) win32unix+start",'~'.expand("<slnum>"))
call s:NetrwExe('sil !start rundll32 url.dll,FileProtocolHandler '.s:ShellEscape(winfname,1))
elseif executable("rundll32")
+" call Decho("(netrw#BrowseX) win32unix+rundll32",'~'.expand("<slnum>"))
call s:NetrwExe('sil !rundll32 url.dll,FileProtocolHandler '.s:ShellEscape(winfname,1))
elseif executable("cygstart")
+" call Decho("(netrw#BrowseX) win32unix+cygstart",'~'.expand("<slnum>"))
call s:NetrwExe('sil !cygstart '.s:ShellEscape(fname,1))
else
call netrw#ErrorMsg(s:WARNING,"rundll32 not on path",74)
endif
- " call inputsave()|call input("Press <cr> to continue")|call inputrestore()
let ret= v:shell_error
elseif has("unix") && executable("kfmclient") && s:CheckIfKde()
-" call Decho("unix and kfmclient",'~'.expand("<slnum>"))
+" call Decho("(netrw#BrowseX) unix and kfmclient",'~'.expand("<slnum>"))
call s:NetrwExe("sil !kfmclient exec ".s:ShellEscape(fname,1)." ".redir)
let ret= v:shell_error
elseif has("unix") && executable("exo-open") && executable("xdg-open") && executable("setsid")
-" call Decho("unix, exo-open, xdg-open",'~'.expand("<slnum>"))
+" call Decho("(netrw#BrowseX) unix, exo-open, xdg-open",'~'.expand("<slnum>"))
call s:NetrwExe("sil !setsid xdg-open ".s:ShellEscape(fname,1).redir)
let ret= v:shell_error
elseif has("unix") && $DESKTOP_SESSION == "mate" && executable("atril")
-" call Decho("unix and atril",'~'.expand("<slnum>"))
- call s:NetrwExe("sil !atril ".s:ShellEscape(fname,1).redir)
+" call Decho("(netrw#BrowseX) unix and atril",'~'.expand("<slnum>"))
+ if a:fname =~ '^https\=://'
+ " atril does not appear to understand how to handle html -- so use gvim to edit the document
+ let use_ctrlo= 0
+" call Decho("(COMBAK) fname<".fname.">")
+" call Decho("(COMBAK) a:fname<".a:fname.">")
+ call s:NetrwExe("sil! !gvim ".fname.' -c "keepj keepalt file '.fnameescape(a:fname).'"')
+
+ else
+ call s:NetrwExe("sil !atril ".s:ShellEscape(fname,1).redir)
+ endif
let ret= v:shell_error
elseif has("unix") && executable("xdg-open")
-" call Decho("unix and xdg-open",'~'.expand("<slnum>"))
+" call Decho("(netrw#BrowseX) unix and xdg-open",'~'.expand("<slnum>"))
call s:NetrwExe("sil !xdg-open ".s:ShellEscape(fname,1).redir)
let ret= v:shell_error
elseif has("macunix") && executable("open")
-" call Decho("macunix and open",'~'.expand("<slnum>"))
+" call Decho("(netrw#BrowseX) macunix and open",'~'.expand("<slnum>"))
call s:NetrwExe("sil !open ".s:ShellEscape(fname,1)." ".redir)
let ret= v:shell_error
else
" netrwFileHandlers#Invoke() always returns 0
+" call Decho("(netrw#BrowseX) use netrwFileHandlers",'~'.expand("<slnum>"))
let ret= netrwFileHandlers#Invoke(exten,fname)
endif
" if unsuccessful, attempt netrwFileHandlers#Invoke()
if ret
+" call Decho("(netrw#BrowseX) ret=".ret," indicates unsuccessful thus far",'~'.expand("<slnum>"))
let ret= netrwFileHandlers#Invoke(exten,fname)
endif
@@ -5380,8 +5396,9 @@ fun! netrw#BrowseX(fname,remote)
if g:netrw_use_noswf
setl noswf
endif
- exe "sil! NetrwKeepj norm! \<c-o>"
-" redraw!
+ if use_ctrlo
+ exe "sil! NetrwKeepj norm! \<c-o>"
+ endif
endif
" call Decho("restoring posn to screenposn<".string(screenposn).">",'~'.expand("<slnum>"))
call winrestview(screenposn)
@@ -5410,11 +5427,11 @@ endfun
" netrw#BrowseXVis: used by gx in visual mode to select a file for browsing {{{2
fun! netrw#BrowseXVis()
" call Dfunc("netrw#BrowseXVis()")
- let atkeep = @@
- norm! gvy
-" call Decho("@@<".@@.">",'~'.expand("<slnum>"))
- call netrw#BrowseX(@@,netrw#CheckIfRemote(@@))
- let @@ = atkeep
+ let akeep = @a
+ norm! gv"ay
+ let gxfile= @a
+ let @a = akeep
+ call netrw#BrowseX(gxfile,netrw#CheckIfRemote(gxfile))
" call Dret("netrw#BrowseXVis")
endfun
@@ -5764,22 +5781,7 @@ fun! s:NetrwHome()
if exists("g:netrw_home")
let home= expand(g:netrw_home)
else
- " go to vim plugin home
- for home in split(&rtp,',') + ['']
- if isdirectory(s:NetrwFile(home)) && filewritable(s:NetrwFile(home)) | break | endif
- let basehome= substitute(home,'[/\\]\.vim$','','')
- if isdirectory(s:NetrwFile(basehome)) && filewritable(s:NetrwFile(basehome))
- let home= basehome."/.vim"
- break
- endif
- endfor
- if home == ""
- " just pick the first directory
- let home= substitute(&rtp,',.*$','','')
- endif
- if (has("win32") || has("win95") || has("win64") || has("win16"))
- let home= substitute(home,'/','\\','g')
- endif
+ let home = stdpath('data')
endif
" insure that the home directory exists
if g:netrw_dirhistmax > 0 && !isdirectory(s:NetrwFile(home))
@@ -6039,13 +6041,12 @@ fun! s:NetrwSLeftrelease(islocal)
endfun
" ---------------------------------------------------------------------
-" s:NetrwListHide: uses [range]g~...~d to delete files that match comma {{{2
-" separated patterns given in g:netrw_list_hide
+" s:NetrwListHide: uses [range]g~...~d to delete files that match {{{2
+" comma-separated patterns given in g:netrw_list_hide
fun! s:NetrwListHide()
" call Dfunc("s:NetrwListHide() g:netrw_hide=".g:netrw_hide." g:netrw_list_hide<".g:netrw_list_hide.">")
" call Decho("initial: ".string(getline(w:netrw_bannercnt,'$')))
let ykeep= @@
-" call DechoBuf(bufnr("%"),"COMBAK#3")
" find a character not in the "hide" string to use as a separator for :g and :v commands
" How-it-works: take the hiding command, convert it into a range.
@@ -6054,8 +6055,8 @@ fun! s:NetrwListHide()
" Use the first character left as a separator character.
" call Decho("find a character not in the hide string to use as a separator")
let listhide= g:netrw_list_hide
- let sep = strpart(substitute('/~@#$%^&*{};:,<.>?|1234567890','['.escape(listhide,'-]^\').']','','ge'),1,1)
-" call Decho("sep=".sep,'~'.expand("<slnum>"))
+ let sep = strpart(substitute('~@#$%^&*{};:,<.>?|1234567890','['.escape(listhide,'-]^\').']','','ge'),1,1)
+" call Decho("sep=".sep," (sep not in hide string)'~'.expand("<slnum>"))
while listhide != ""
if listhide =~ ','
@@ -6065,10 +6066,19 @@ fun! s:NetrwListHide()
let hide = listhide
let listhide = ""
endif
-" call Decho("hide<".hide."> listhide<".listhide.'>','~'.expand("<slnum>"))
+" call Decho("..extracted from listhide: hide<".hide."> g:netrw_sort_by<".g:netrw_sort_by.'>','~'.expand("<slnum>"))
+ if g:netrw_sort_by =~ '^[ts]'
+ if hide =~ '^\^'
+" call Decho("..modify hide to handle a \"^...\" pattern",'~'.expand("<slnum>"))
+ let hide= substitute(hide,'^\^','^\(\\d\\+/\)','')
+ elseif hide =~ '^\\(\^'
+ let hide= substitute(hide,'^\\(\^','\\(^\\(\\d\\+/\\)','')
+ endif
+" call Decho("..hide<".hide."> listhide<".listhide.'>','~'.expand("<slnum>"))
+ endif
" Prune the list by hiding any files which match
-" call Decho("prune the list by hiding any files which ",((g:netrw_hide == 1)? "" : "don't")." match hide<".hide.">")
+" call Decho("..prune the list by hiding any files which ",((g:netrw_hide == 1)? "" : "don't")." match hide<".hide.">")
if g:netrw_hide == 1
" call Decho("..hiding<".hide.">",'~'.expand("<slnum>"))
exe 'sil! NetrwKeepj '.w:netrw_bannercnt.',$g'.sep.hide.sep.'d'
@@ -6089,7 +6099,6 @@ fun! s:NetrwListHide()
" remove any blank lines that have somehow remained.
" This seems to happen under Windows.
exe 'sil! NetrwKeepj 1,$g@^\s*$@d'
-" call DechoBuf(bufnr("%"),"COMBAK#4")
let @@= ykeep
" call Dret("s:NetrwListHide")
@@ -6297,7 +6306,7 @@ fun! s:NetrwMaps(islocal)
" generate default <Plug> maps {{{3
if !hasmapto('<Plug>NetrwHide') |nmap <buffer> <silent> <nowait> a <Plug>NetrwHide_a|endif
- if !hasmapto('<Plug>NetrwBrowseUpDir') |nmap <buffer> <silent> <nowait> - <Plug>NetrwBrowseUpDir |endif
+ if !hasmapto('<Plug>NetrwBrowseUpDir') |nmap <buffer> <silent> <nowait> - <Plug>NetrwBrowseUpDir|endif
if !hasmapto('<Plug>NetrwOpenFile') |nmap <buffer> <silent> <nowait> % <Plug>NetrwOpenFile|endif
if !hasmapto('<Plug>NetrwBadd_cb') |nmap <buffer> <silent> <nowait> cb <Plug>NetrwBadd_cb|endif
if !hasmapto('<Plug>NetrwBadd_cB') |nmap <buffer> <silent> <nowait> cB <Plug>NetrwBadd_cB|endif
@@ -6614,9 +6623,9 @@ fun! s:NetrwMarkFiles(islocal,...)
while i <= a:0
if a:islocal
if v:version > 704 || (v:version == 704 && has("patch656"))
- let mffiles= glob(fnameescape(a:{i}),0,1,1)
+ let mffiles= glob(a:{i},0,1,1)
else
- let mffiles= glob(fnameescape(a:{i}),0,1)
+ let mffiles= glob(a:{i},0,1)
endif
else
let mffiles= [a:{i}]
@@ -6757,13 +6766,15 @@ fun! s:NetrwMarkFile(islocal,fname)
if index(s:netrwmarkfilelist,dname) == -1
" append new filename to global markfilelist
call add(s:netrwmarkfilelist,s:ComposePath(b:netrw_curdir,a:fname))
-" call Decho("append filename<".a:fname."> to global markfilelist<".string(s:netrwmarkfilelist).">",'~'.expand("<slnum>"))
+" call Decho("append filename<".a:fname."> to global s:markfilelist<".string(s:netrwmarkfilelist).">",'~'.expand("<slnum>"))
else
" remove new filename from global markfilelist
-" call Decho("filter(".string(s:netrwmarkfilelist).",'v:val != '.".dname.")",'~'.expand("<slnum>"))
+" call Decho("remove new filename from global s:markfilelist",'~'.expand("<slnum>"))
+" call Decho("..filter(".string(s:netrwmarkfilelist).",'v:val != '.".dname.")",'~'.expand("<slnum>"))
call filter(s:netrwmarkfilelist,'v:val != "'.dname.'"')
-" call Decho("ending s:netrwmarkfilelist <".string(s:netrwmarkfilelist).">",'~'.expand("<slnum>"))
+" call Decho("..ending s:netrwmarkfilelist <".string(s:netrwmarkfilelist).">",'~'.expand("<slnum>"))
if s:netrwmarkfilelist == []
+" call Decho("s:netrwmarkfilelist is empty; unlet it",'~'.expand("<slnum>"))
unlet s:netrwmarkfilelist
endif
endif
@@ -6787,7 +6798,8 @@ fun! s:NetrwMarkFile(islocal,fname)
endif
endif
let @@= ykeep
-" call Dret("s:NetrwMarkFile : s:netrwmarkfilelist_".curbufnr."<".(exists("s:netrwmarkfilelist_{curbufnr}")? string(s:netrwmarkfilelist_{curbufnr}) : " doesn't exist").">")
+" call Decho("s:netrwmarkfilelist[".(exists("s:netrwmarkfilelist")? string(s:netrwmarkfilelist) : "")."] (avail in all buffers)",'~'.expand("<slnum>"))
+" call Dret("s:NetrwMarkFile : s:netrwmarkfilelist_".curbufnr."<".(exists("s:netrwmarkfilelist_{curbufnr}")? string(s:netrwmarkfilelist_{curbufnr}) : " doesn't exist")."> (buf#".curbufnr."list)")
endfun
" ---------------------------------------------------------------------
@@ -7078,17 +7090,8 @@ fun! s:NetrwMarkFileCopy(islocal,...)
" call Dret("s:NetrwMarkFileCopy : lcd failure")
return
endif
- if v:version < 704 || (v:version == 704 && !has("patch1107"))
- call s:NetrwExe("sil !".g:netrw_localrmdir.g:netrw_localrmdiropt." ".s:ShellEscape(tmpdir,1))
- if v:shell_error != 0
- call netrw#ErrorMsg(s:WARNING,"consider setting g:netrw_localrmdir<".g:netrw_localrmdir."> to something that works",80)
-" " call Dret("s:NetrwMarkFileCopy : failed: sil !".g:netrw_localrmdir." ".s:ShellEscape(tmpdir,1) )
- return
- endif
- else
- if delete(tmpdir,"d")
- call netrw#ErrorMsg(s:ERROR,"unable to delete directory <".tmpdir.">!",103)
- endif
+ if delete(tmpdir,"d")
+ call netrw#ErrorMsg(s:ERROR,"unable to delete directory <".tmpdir.">!",103)
endif
else
if s:NetrwLcd(curdir)
@@ -7542,8 +7545,9 @@ fun! s:NetrwMarkFileGrep(islocal)
let curdir = s:NetrwGetCurdir(a:islocal)
if exists("s:netrwmarkfilelist")
-" call Decho("s:netrwmarkfilelist".string(s:netrwmarkfilelist).">",'~'.expand("<slnum>"))
+" call Decho("using s:netrwmarkfilelist".string(s:netrwmarkfilelist).">",'~'.expand("<slnum>"))
let netrwmarkfilelist= join(map(deepcopy(s:netrwmarkfilelist), "fnameescape(v:val)"))
+" call Decho("keeping copy of s:netrwmarkfilelist in function-local variable,'~'.expand("<slnum>"))"
call s:NetrwUnmarkAll()
else
" call Decho('no marked files, using "*"','~'.expand("<slnum>"))
@@ -7551,6 +7555,7 @@ fun! s:NetrwMarkFileGrep(islocal)
endif
" ask user for pattern
+" call Decho("ask user for search pattern",'~'.expand("<slnum>"))
call inputsave()
let pat= input("Enter pattern: ","")
call inputrestore()
@@ -8663,7 +8668,7 @@ fun! s:NetrwUpload(fname,tgt,...)
" -i : turns off interactive prompting from ftp
" -n unix : DON'T use <.netrc>, even though it exists
" -n win32: quit being obnoxious about password
- NetrwKeepj norm! 1Gdd
+ NetrwKeepj norm! 1G"_dd
call s:NetrwExe(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." ".g:netrw_ftp_options)
" If the result of the ftp operation isn't blank, show an error message (tnx to Doug Claar)
sil NetrwKeepj g/Local directory now/d
@@ -9501,15 +9506,19 @@ fun! s:NetrwWideListing()
" fpl: filenames per line
" fpc: filenames per column
setl ma noro
+ let keepa= @a
" call Decho("setl ma noro",'~'.expand("<slnum>"))
let b:netrw_cpf= 0
if line("$") >= w:netrw_bannercnt
+ " determine the maximum filename size; use that to set cpf
exe 'sil NetrwKeepj '.w:netrw_bannercnt.',$g/^./if virtcol("$") > b:netrw_cpf|let b:netrw_cpf= virtcol("$")|endif'
NetrwKeepj call histdel("/",-1)
else
+ let @a= keepa
" call Dret("NetrwWideListing")
return
endif
+ " allow for two spaces to separate columns
let b:netrw_cpf= b:netrw_cpf + 2
" call Decho("b:netrw_cpf=max_filename_length+2=".b:netrw_cpf,'~'.expand("<slnum>"))
@@ -9532,10 +9541,11 @@ fun! s:NetrwWideListing()
if newcolend > line("$") | let newcolend= line("$") | endif
let newcolqty= newcolend - newcolstart
exe newcolstart
+ " COMBAK: both of the visual-mode using lines below are problematic vis-a-vis @*
if newcolqty == 0
- exe "sil! NetrwKeepj norm! 0\<c-v>$hx".w:netrw_bannercnt."G$p"
+ exe "sil! NetrwKeepj norm! 0\<c-v>$h\"ax".w:netrw_bannercnt."G$\"ap"
else
- exe "sil! NetrwKeepj norm! 0\<c-v>".newcolqty.'j$hx'.w:netrw_bannercnt.'G$p'
+ exe "sil! NetrwKeepj norm! 0\<c-v>".newcolqty.'j$h"ax'.w:netrw_bannercnt.'G$"ap'
endif
exe "sil! NetrwKeepj ".newcolstart.','.newcolend.'d _'
exe 'sil! NetrwKeepj '.w:netrw_bannercnt
@@ -9546,6 +9556,7 @@ fun! s:NetrwWideListing()
exe 'nno <buffer> <silent> b :call search(''^.\\|\s\s\zs\S'',''bW'')'."\<cr>"
" call Decho("NetrwWideListing) setl noma nomod ro",'~'.expand("<slnum>"))
exe "setl ".g:netrw_bufsettings
+ let @a= keepa
" call Decho("ro=".&l:ro." ma=".&l:ma." mod=".&l:mod." wrap=".&l:wrap." (filename<".expand("%")."> win#".winnr()." ft<".&ft.">)",'~'.expand("<slnum>"))
" call Dret("NetrwWideListing")
return
@@ -9743,6 +9754,7 @@ fun! s:PerformListing(islocal)
exe 'sil NetrwKeepj '.w:netrw_bannercnt.',$sort!'.' '.g:netrw_sort_options
endif
endif
+
" remove priority pattern prefix
" call Decho("remove priority pattern prefix",'~'.expand("<slnum>"))
exe 'sil! NetrwKeepj '.w:netrw_bannercnt.',$s/^\d\{3}'.g:netrw_sepchr.'//e'
@@ -9781,6 +9793,7 @@ fun! s:PerformListing(islocal)
" call Decho('exe sil NetrwKeepj '.w:netrw_bannercnt.',$sort!','~'.expand("<slnum>"))
exe 'sil! NetrwKeepj '.w:netrw_bannercnt.',$sort!'.' '.g:netrw_sort_options
endif
+" call Decho("remove leading digits/ (sorting) information from listing",'~'.expand("<slnum>"))
exe 'sil! NetrwKeepj '.w:netrw_bannercnt.',$s/^\d\{-}\///e'
NetrwKeepj call histdel("/",-1)
endif
@@ -9843,6 +9856,7 @@ fun! s:PerformListing(islocal)
" call Decho("exe setl ts=".(g:netrw_maxfilenamelen+1),'~'.expand("<slnum>"))
exe "setl ts=".(g:netrw_maxfilenamelen+1)
endif
+" call Decho("PerformListing buffer:",'~'.expand("<slnum>"))
" call DechoBuf(bufnr("%"))
if exists("s:treecurpos")
@@ -10810,7 +10824,6 @@ fun! s:LocalListing()
for filename in filelist
" call Decho(" ",'~'.expand("<slnum>"))
" call Decho("for filename in filelist: filename<".filename.">",'~'.expand("<slnum>"))
-" call DechoBuf(bufnr("%"),"COMBAK#1")
if getftype(filename) == "link"
" indicate a symbolic link
@@ -10868,10 +10881,10 @@ fun! s:LocalListing()
if w:netrw_liststyle == s:LONGLIST
let sz = getfsize(filename)
+ let fsz = strpart(" ",1,15-strlen(sz)).sz
if g:netrw_sizestyle =~# "[hH]"
let sz= s:NetrwHumanReadable(sz)
endif
- let fsz = strpart(" ",1,15-strlen(sz)).sz
let longfile= printf("%-".(g:netrw_maxfilenamelen+1)."s",pfile)
let pfile = longfile.fsz." ".strftime(g:netrw_timefmt,getftime(filename))
" call Decho("longlist support: sz=".sz." fsz=".fsz,'~'.expand("<slnum>"))
@@ -10879,10 +10892,11 @@ fun! s:LocalListing()
if g:netrw_sort_by =~# "^t"
" sort by time (handles time up to 1 quintillion seconds, US)
+ " Decorate listing by prepending a timestamp/ . Sorting will then be done based on time.
" call Decho("getftime(".filename.")=".getftime(filename),'~'.expand("<slnum>"))
let t = getftime(filename)
let ft = strpart("000000000000000000",1,18-strlen(t)).t
-" call Decho("exe NetrwKeepj put ='".ft.'/'.filename."'",'~'.expand("<slnum>"))
+" call Decho("exe NetrwKeepj put ='".ft.'/'.pfile."'",'~'.expand("<slnum>"))
let ftpfile= ft.'/'.pfile
sil! NetrwKeepj put=ftpfile
@@ -10903,7 +10917,7 @@ fun! s:LocalListing()
" call Decho("exe NetrwKeepj put ='".pfile."'",'~'.expand("<slnum>"))
sil! NetrwKeepj put=pfile
endif
-" call DechoBuf(bufnr("%"),"COMBAK#2")
+" call DechoBuf(bufnr("%"),"bufnr(%)")
endfor
" cleanup any windows mess at end-of-line
@@ -10950,9 +10964,10 @@ fun! s:NetrwLocalRename(path) range
" call Dfunc("NetrwLocalRename(path<".a:path.">)")
" preparation for removing multiple files/directories
- let ykeep = @@
- let ctr = a:firstline
- let svpos = winsaveview()
+ let ykeep = @@
+ let ctr = a:firstline
+ let svpos = winsaveview()
+ let all = 0
" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>"))
" rename files given by the markfilelist
@@ -10980,6 +10995,23 @@ fun! s:NetrwLocalRename(path) range
let newname = substitute(oldname,subfrom,subto,'')
endif
endif
+ if !all && filereadable(newname)
+ call inputsave()
+ let response= input("File<".newname."> already exists; do you want to overwrite it? (y/all/n) ")
+ call inputrestore()
+ if response == "all"
+ let all= 1
+ elseif response != "y" && response != "yes"
+ " refresh the directory
+" call Decho("refresh the directory listing",'~'.expand("<slnum>"))
+ NetrwKeepj call s:NetrwRefresh(1,s:NetrwBrowseChgDir(1,'./'))
+" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>"))
+ NetrwKeepj call winrestview(svpos)
+ let @@= ykeep
+" call Dret("NetrwLocalRename")
+ return
+ endif
+ endif
call rename(oldname,newname)
endfor
call s:NetrwUnmarkList(bufnr("%"),b:netrw_curdir)
@@ -11003,14 +11035,14 @@ fun! s:NetrwLocalRename(path) range
NetrwKeepj norm! 0
let oldname= s:ComposePath(a:path,curword)
-" call Decho("oldname<".oldname.">",'~'.expand("<slnum>"))
+" call Decho("oldname<".oldname.">",'~'.expand("<slnum>"))
call inputsave()
let newname= input("Moving ".oldname." to : ",substitute(oldname,'/*$','','e'))
call inputrestore()
call rename(oldname,newname)
-" call Decho("renaming <".oldname."> to <".newname.">",'~'.expand("<slnum>"))
+" call Decho("renaming <".oldname."> to <".newname.">",'~'.expand("<slnum>"))
let ctr= ctr + 1
endwhile
@@ -11220,7 +11252,9 @@ fun! netrw#Expose(varname)
" call Dfunc("netrw#Expose(varname<".a:varname.">)")
if exists("s:".a:varname)
exe "let retval= s:".a:varname
+" call Decho("retval=".retval,'~'.expand("<slnum>"))
if exists("g:netrw_pchk")
+" call Decho("type(g:netrw_pchk=".g:netrw_pchk.")=".type(retval),'~'.expand("<slnum>"))
if type(retval) == 3
let retval = copy(retval)
let i = 0
@@ -11229,10 +11263,13 @@ fun! netrw#Expose(varname)
let i = i + 1
endwhile
endif
-" call Dret("netrw#Expose ".string(retval))
+" call Dret("netrw#Expose ".string(retval)),'~'.expand("<slnum>"))
return string(retval)
+ else
+" call Decho("g:netrw_pchk doesn't exist",'~'.expand("<slnum>"))
endif
else
+" call Decho("s:".a:varname." doesn't exist",'~'.expand("<slnum>"))
let retval= "n/a"
endif
@@ -11793,6 +11830,9 @@ fun! s:NetrwExe(cmd)
" call Decho("exe ".a:cmd,'~'.expand("<slnum>"))
exe a:cmd
endif
+ if v:shell_error
+ call netrw#ErrorMsg(s:WARNING,"shell signalled an error",106)
+ endif
" call Dret("s:NetrwExe : v:shell_error=".v:shell_error)
endfun
diff --git a/runtime/autoload/netrwSettings.vim b/runtime/autoload/netrwSettings.vim
index 327db6a540..bed5cfc455 100644
--- a/runtime/autoload/netrwSettings.vim
+++ b/runtime/autoload/netrwSettings.vim
@@ -1,6 +1,6 @@
" netrwSettings.vim: makes netrw settings simpler
" Date: Nov 09, 2016
-" Maintainer: Charles E Campbell <drchipNOSPAM at campbellfamily dot biz>
+" Maintainer: Charles E Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
" Version: 16
" Copyright: Copyright (C) 1999-2007 Charles E. Campbell {{{1
" Permission is hereby granted to use and distribute this code,
diff --git a/runtime/autoload/netrw_gitignore.vim b/runtime/autoload/netrw_gitignore.vim
index da3f50bca0..1b55e2488a 100644
--- a/runtime/autoload/netrw_gitignore.vim
+++ b/runtime/autoload/netrw_gitignore.vim
@@ -18,61 +18,5 @@
" holder be liable for any damages resulting from the use
" of this software.
function! netrw_gitignore#Hide(...)
- let additional_files = a:000
-
- let default_files = ['.gitignore', '.git/info/exclude']
-
- " get existing global/system gitignore files
- let global_gitignore = expand(substitute(system("git config --global core.excludesfile"), '\n', '', 'g'))
- if global_gitignore !=# ''
- let default_files = add(default_files, global_gitignore)
- endif
- let system_gitignore = expand(substitute(system("git config --system core.excludesfile"), '\n', '', 'g'))
- if system_gitignore !=# ''
- let default_files = add(default_files, system_gitignore)
- endif
-
- " append additional files if given as function arguments
- if additional_files !=# []
- let files = extend(default_files, additional_files)
- else
- let files = default_files
- endif
-
- " keep only existing/readable files
- let gitignore_files = []
- for file in files
- if filereadable(file)
- let gitignore_files = add(gitignore_files, file)
- endif
- endfor
-
- " get contents of gitignore patterns from those files
- let gitignore_lines = []
- for file in gitignore_files
- for line in readfile(file)
- " filter empty lines and comments
- if line !~# '^#' && line !~# '^$'
- let gitignore_lines = add(gitignore_lines, line)
- endif
- endfor
- endfor
-
- " convert gitignore patterns to Netrw/Vim regex patterns
- let escaped_lines = []
- for line in gitignore_lines
- let escaped = line
- let escaped = substitute(escaped, '\*\*', '*', 'g')
- let escaped = substitute(escaped, '\.', '\\.', 'g')
- let escaped = substitute(escaped, '\$', '\\$', 'g')
- let escaped = substitute(escaped, '*', '.*', 'g')
- " correction: dot, dollar and asterisks chars shouldn't be escaped when
- " within regex matching groups.
- let escaped = substitute(escaped, '\(\[[^]]*\)\zs\\\.', '\.', 'g')
- let escaped = substitute(escaped, '\(\[[^]]*\)\zs\\\$', '\$', 'g')
- let escaped = substitute(escaped, '\(\[[^]]*\)\zs\.\*', '*', 'g')
- let escaped_lines = add(escaped_lines, escaped)
- endfor
-
- return join(escaped_lines, ',')
+ return substitute(substitute(system('git ls-files --other --ignored --exclude-standard --directory'), '\n', ',', 'g'), ',$', '', '')
endfunction
diff --git a/runtime/autoload/tar.vim b/runtime/autoload/tar.vim
index dc670dbd14..b6c4c660b8 100644
--- a/runtime/autoload/tar.vim
+++ b/runtime/autoload/tar.vim
@@ -1,13 +1,13 @@
" tar.vim: Handles browsing tarfiles
" AUTOLOAD PORTION
-" Date: Apr 17, 2013
-" Version: 29
-" Maintainer: Charles E Campbell <NdrOchip@ScampbellPfamily.AbizM-NOSPAM>
-" License: Vim License (see vim's :help license)
+" Date: Jan 07, 2020
+" Version: 32
+" Maintainer: Charles E Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
+" License: Vim License (see vim's :help license)
"
" Contains many ideas from Michael Toren's <tar.vim>
"
-" Copyright: Copyright (C) 2005-2011 Charles E. Campbell {{{1
+" Copyright: Copyright (C) 2005-2017 Charles E. Campbell {{{1
" Permission is hereby granted to use and distribute this code,
" with or without modifications, provided that this copyright
" notice is copied with it. Like anything else that's free,
@@ -22,7 +22,7 @@
if &cp || exists("g:loaded_tar")
finish
endif
-let g:loaded_tar= "v29"
+let g:loaded_tar= "v32"
if v:version < 702
echohl WarningMsg
echo "***warning*** this version of tar needs vim 7.2"
@@ -48,6 +48,9 @@ endif
if !exists("g:tar_writeoptions")
let g:tar_writeoptions= "uf"
endif
+if !exists("g:tar_delfile")
+ let g:tar_delfile="--delete -f"
+endif
if !exists("g:netrw_cygwin")
if has("win32") || has("win95") || has("win64") || has("win16")
if &shell =~ '\%(\<bash\>\|\<zsh\>\)\%(\.exe\)\=$'
@@ -109,6 +112,7 @@ fun! tar#Browse(tarfile)
" sanity checks
if !executable(g:tar_cmd)
redraw!
+" call Decho('***error*** (tar#Browse) "'.g:tar_cmd.'" not available on your system')
echohl Error | echo '***error*** (tar#Browse) "'.g:tar_cmd.'" not available on your system'
let &report= repkeep
" call Dret("tar#Browse")
@@ -119,6 +123,7 @@ fun! tar#Browse(tarfile)
if a:tarfile !~# '^\a\+://'
" if it's an url, don't complain, let url-handlers such as vim do its thing
redraw!
+" call Decho("***error*** (tar#Browse) File not readable<".a:tarfile.">")
echohl Error | echo "***error*** (tar#Browse) File not readable<".a:tarfile.">" | echohl None
endif
let &report= repkeep
@@ -152,12 +157,29 @@ fun! tar#Browse(tarfile)
" assuming cygwin
let tarfile=substitute(system("cygpath -u ".shellescape(tarfile,0)),'\n$','','e')
endif
-
let curlast= line("$")
- if tarfile =~# '\.\(gz\|tgz\)$'
- let gzip_command = s:get_gzip_command(tarfile)
+
+ if tarfile =~# '\.\(gz\)$'
" call Decho("1: exe silent r! gzip -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - ")
- exe "sil! r! " . gzip_command . " -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
+ exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
+
+ elseif tarfile =~# '\.\(tgz\)$' || tarfile =~# '\.\(tbz\)$' || tarfile =~# '\.\(txz\)$' || tarfile =~# '\.\(tzs\)$'
+ if has("unix") && executable("file")
+ let filekind= system("file ".shellescape(tarfile,1)) =~ "bzip2"
+ else
+ let filekind= ""
+ endif
+
+ if filekind =~ "bzip2"
+ exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
+ elseif filekind =~ "XZ"
+ exe "sil! r! xz -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
+ elseif filekind =~ "Zstandard"
+ exe "sil! r! zstd --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
+ else
+ exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
+ endif
+
elseif tarfile =~# '\.lrp'
" call Decho("2: exe silent r! cat -- ".shellescape(tarfile,1)."|gzip -d -c -|".g:tar_cmd." -".g:tar_browseoptions." - ")
exe "sil! r! cat -- ".shellescape(tarfile,1)."|gzip -d -c -|".g:tar_cmd." -".g:tar_browseoptions." - "
@@ -170,6 +192,8 @@ fun! tar#Browse(tarfile)
elseif tarfile =~# '\.\(xz\|txz\)$'
" call Decho("3: exe silent r! xz --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - ")
exe "sil! r! xz --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
+ elseif tarfile =~# '\.\(zst\|tzs\)$'
+ exe "sil! r! zstd --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
else
if tarfile =~ '^\s*-'
" A file name starting with a dash is taken as an option. Prepend ./ to avoid that.
@@ -184,7 +208,7 @@ fun! tar#Browse(tarfile)
" call Dret("tar#Browse : a:tarfile<".a:tarfile.">")
return
endif
- if line("$") == curlast || ( line("$") == (curlast + 1) && getline("$") =~ '\c\%(warning\|error\|inappropriate\|unrecognized\)')
+ if line("$") == curlast || ( line("$") == (curlast + 1) && getline("$") =~# '\c\%(warning\|error\|inappropriate\|unrecognized\)')
redraw!
echohl WarningMsg | echo "***warning*** (tar#Browse) ".a:tarfile." doesn't appear to be a tar file" | echohl None
keepj sil! %d
@@ -197,8 +221,13 @@ fun! tar#Browse(tarfile)
return
endif
+ " set up maps supported for tar
setlocal noma nomod ro
- noremap <silent> <buffer> <cr> :call <SID>TarBrowseSelect()<cr>
+ noremap <silent> <buffer> <cr> :call <SID>TarBrowseSelect()<cr>
+ noremap <silent> <buffer> x :call tar#Extract()<cr>
+ if &mouse != ""
+ noremap <silent> <buffer> <leftmouse> <leftmouse>:call <SID>TarBrowseSelect()<cr>
+ endif
let &report= repkeep
" call Dret("tar#Browse : b:tarfile<".b:tarfile.">")
@@ -235,7 +264,8 @@ fun! s:TarBrowseSelect()
let tarfile=substitute(system("cygpath -u ".shellescape(tarfile,0)),'\n$','','e')
endif
- new
+ " open a new window (tar#Read will read a file into it)
+ noswapfile new
if !exists("g:tar_nomax") || g:tar_nomax == 0
wincmd _
endif
@@ -267,7 +297,7 @@ fun! tar#Read(fname,mode)
if fname =~ '\.bz2$' && executable("bzcat")
let decmp= "|bzcat"
let doro = 1
- elseif fname =~ '\.gz$' && executable("zcat")
+ elseif fname =~ '\.t\=gz$' && executable("zcat")
let decmp= "|zcat"
let doro = 1
elseif fname =~ '\.lzma$' && executable("lzcat")
@@ -276,6 +306,9 @@ fun! tar#Read(fname,mode)
elseif fname =~ '\.xz$' && executable("xzcat")
let decmp= "|xzcat"
let doro = 1
+ elseif fname =~ '\.zst$' && executable("zstdcat")
+ let decmp= "|zstdcat"
+ let doro = 1
else
let decmp=""
let doro = 0
@@ -291,20 +324,31 @@ fun! tar#Read(fname,mode)
endif
if tarfile =~# '\.bz2$'
-" call Decho("7: exe silent r! bzip2 -d -c ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp)
exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
- elseif tarfile =~# '\.\(gz\|tgz\)$'
- let gzip_command = s:get_gzip_command(tarfile)
-" call Decho("5: exe silent r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd.' -'.g:tar_readoptions.' - '.tar_secure.shellescape(fname,1))
- exe "sil! r! " . gzip_command . " -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
+ elseif tarfile =~# '\.\(gz\)$'
+ exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
+
+ elseif tarfile =~# '\(\.tgz\|\.tbz\|\.txz\)'
+ if has("unix") && executable("file")
+ let filekind= system("file ".shellescape(tarfile,1))
+ else
+ let filekind= ""
+ endif
+ if filekind =~ "bzip2"
+ exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
+ elseif filekind =~ "XZ"
+ exe "sil! r! xz -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
+ elseif filekind =~ "Zstandard"
+ exe "sil! r! zstd --decompress --stdout -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
+ else
+ exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
+ endif
+
elseif tarfile =~# '\.lrp$'
-" call Decho("6: exe silent r! cat ".shellescape(tarfile,1)." | gzip -d -c - | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp)
exe "sil! r! cat -- ".shellescape(tarfile,1)." | gzip -d -c - | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
elseif tarfile =~# '\.lzma$'
-" call Decho("7: exe silent r! lzma -d -c ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp)
exe "sil! r! lzma -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
elseif tarfile =~# '\.\(xz\|txz\)$'
-" call Decho("3: exe silent r! xz --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp)
exe "sil! r! xz --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
else
if tarfile =~ '^\s*-'
@@ -348,13 +392,14 @@ fun! tar#Write(fname)
" sanity checks
if !executable(g:tar_cmd)
redraw!
- echohl Error | echo '***error*** (tar#Browse) "'.g:tar_cmd.'" not available on your system'
+" call Decho('***error*** (tar#Browse) "'.g:tar_cmd.'" not available on your system')
let &report= repkeep
" call Dret("tar#Write")
return
endif
if !exists("*mkdir")
redraw!
+" call Decho("***error*** (tar#Write) sorry, mkdir() doesn't work on your system")
echohl Error | echo "***error*** (tar#Write) sorry, mkdir() doesn't work on your system" | echohl None
let &report= repkeep
" call Dret("tar#Write")
@@ -375,6 +420,7 @@ fun! tar#Write(fname)
exe "cd ".fnameescape(tmpdir)
catch /^Vim\%((\a\+)\)\=:E344/
redraw!
+" call Decho("***error*** (tar#Write) cannot cd to temporary directory")
echohl Error | echo "***error*** (tar#Write) cannot cd to temporary directory" | Echohl None
let &report= repkeep
" call Dret("tar#Write")
@@ -393,8 +439,6 @@ fun! tar#Write(fname)
let tarfile = substitute(b:tarfile,'tarfile:\(.\{-}\)::.*$','\1','')
let fname = substitute(b:tarfile,'tarfile:.\{-}::\(.*\)$','\1','')
- let gzip_command = s:get_gzip_command(tarfile)
-
" handle compressed archives
if tarfile =~# '\.bz2'
call system("bzip2 -d -- ".shellescape(tarfile,0))
@@ -402,12 +446,12 @@ fun! tar#Write(fname)
let compress= "bzip2 -- ".shellescape(tarfile,0)
" call Decho("compress<".compress.">")
elseif tarfile =~# '\.gz'
- call system(gzip_command . " -d -- ".shellescape(tarfile,0))
+ call system("gzip -d -- ".shellescape(tarfile,0))
let tarfile = substitute(tarfile,'\.gz','','e')
let compress= "gzip -- ".shellescape(tarfile,0)
" call Decho("compress<".compress.">")
elseif tarfile =~# '\.tgz'
- call system(gzip_command . " -d -- ".shellescape(tarfile,0))
+ call system("gzip -d -- ".shellescape(tarfile,0))
let tarfile = substitute(tarfile,'\.tgz','.tar','e')
let compress= "gzip -- ".shellescape(tarfile,0)
let tgz = 1
@@ -417,6 +461,10 @@ fun! tar#Write(fname)
let tarfile = substitute(tarfile,'\.xz','','e')
let compress= "xz -- ".shellescape(tarfile,0)
" call Decho("compress<".compress.">")
+ elseif tarfile =~# '\.zst'
+ call system("zstd --decompress -- ".shellescape(tarfile,0))
+ let tarfile = substitute(tarfile,'\.zst','','e')
+ let compress= "zstd -- ".shellescape(tarfile,0)
elseif tarfile =~# '\.lzma'
call system("lzma -d -- ".shellescape(tarfile,0))
let tarfile = substitute(tarfile,'\.lzma','','e')
@@ -427,6 +475,7 @@ fun! tar#Write(fname)
if v:shell_error != 0
redraw!
+" call Decho("***error*** (tar#Write) sorry, unable to update ".tarfile." with ".fname)
echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".tarfile." with ".fname | echohl None
else
@@ -459,10 +508,11 @@ fun! tar#Write(fname)
endif
" delete old file from tarfile
-" call Decho("system(".g:tar_cmd." --delete -f ".shellescape(tarfile,0)." -- ".shellescape(fname,0).")")
- call system(g:tar_cmd." --delete -f ".shellescape(tarfile,0).tar_secure.shellescape(fname,0))
+" call Decho("system(".g:tar_cmd." ".g:tar_delfile." ".shellescape(tarfile,0)." -- ".shellescape(fname,0).")")
+ call system(g:tar_cmd." ".g:tar_delfile." ".shellescape(tarfile,0).tar_secure.shellescape(fname,0))
if v:shell_error != 0
redraw!
+" call Decho("***error*** (tar#Write) sorry, unable to update ".fnameescape(tarfile)." with ".fnameescape(fname))
echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".fnameescape(tarfile)." with ".fnameescape(fname) | echohl None
else
@@ -471,6 +521,7 @@ fun! tar#Write(fname)
call system(g:tar_cmd." -".g:tar_writeoptions." ".shellescape(tarfile,0).tar_secure.shellescape(fname,0))
if v:shell_error != 0
redraw!
+" call Decho("***error*** (tar#Write) sorry, unable to update ".fnameescape(tarfile)." with ".fnameescape(fname))
echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".fnameescape(tarfile)." with ".fnameescape(fname) | echohl None
elseif exists("compress")
" call Decho("call system(".compress.")")
@@ -486,11 +537,11 @@ fun! tar#Write(fname)
if s:tblfile_{winnr()} =~ '^\a\+://'
" call Decho("handle writing <".tarfile."> across network to <".s:tblfile_{winnr()}.">")
let tblfile= s:tblfile_{winnr()}
- 1split|enew
+ 1split|noswapfile enew
let binkeep= &l:binary
let eikeep = &ei
set binary ei=all
- exe "e! ".fnameescape(tarfile)
+ exe "noswapfile e! ".fnameescape(tarfile)
call netrw#NetWrite(tblfile)
let &ei = eikeep
let &l:binary = binkeep
@@ -524,7 +575,7 @@ fun! tar#Diff(userfname,fname)
" sets up b:tardiff_otherbuf variables so each buffer knows about the other (for closing purposes)
diffthis
wincmd v
- exe "e ".fnameescape(fname)
+ exe "noswapfile e ".fnameescape(fname)
diffthis
else
redraw!
@@ -534,6 +585,141 @@ fun! tar#Diff(userfname,fname)
endfun
" ---------------------------------------------------------------------
+" tar#Extract: extract a file from a (possibly compressed) tar archive {{{2
+fun! tar#Extract()
+" call Dfunc("tar#Extract()")
+
+ let repkeep= &report
+ set report=10
+ let fname= getline(".")
+" call Decho("fname<".fname.">")
+
+ if !exists("g:tar_secure") && fname =~ '^\s*-\|\s\+-'
+ redraw!
+ echohl WarningMsg | echo '***warning*** (tar#BrowseSelect) rejecting tarfile member<'.fname.'> because of embedded "-"'
+" call Dret('tar#BrowseSelect : rejecting tarfile member<'.fname.'> because of embedded "-"')
+ return
+ endif
+
+ " sanity check
+ if fname =~ '^"'
+ let &report= repkeep
+" call Dret("TarBrowseSelect")
+ return
+ endif
+
+ let tarball = expand("%")
+" call Decho("tarball<".tarball.">")
+ let tarbase = substitute(tarball,'\..*$','','')
+" call Decho("tarbase<".tarbase.">")
+
+ let extractcmd= netrw#WinPath(g:tar_extractcmd)
+ if filereadable(tarbase.".tar")
+" call Decho("system(".extractcmd." ".shellescape(tarbase).".tar ".shellescape(fname).")")
+ call system(extractcmd." ".shellescape(tarbase).".tar ".shellescape(fname))
+ if v:shell_error != 0
+ echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar ".fname.": failed!" | echohl NONE
+" call Decho("***error*** ".extractcmd." ".tarbase.".tar ".fname.": failed!")
+ else
+ echo "***note*** successfully extracted ".fname
+ endif
+
+ elseif filereadable(tarbase.".tgz")
+ let extractcmd= substitute(extractcmd,"-","-z","")
+" call Decho("system(".extractcmd." ".shellescape(tarbase).".tgz ".shellescape(fname).")")
+ call system(extractcmd." ".shellescape(tarbase).".tgz ".shellescape(fname))
+ if v:shell_error != 0
+ echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tgz ".fname.": failed!" | echohl NONE
+" call Decho("***error*** ".extractcmd."t ".tarbase.".tgz ".fname.": failed!")
+ else
+ echo "***note*** successfully extracted ".fname
+ endif
+
+ elseif filereadable(tarbase.".tar.gz")
+ let extractcmd= substitute(extractcmd,"-","-z","")
+" call Decho("system(".extractcmd." ".shellescape(tarbase).".tar.gz ".shellescape(fname).")")
+ call system(extractcmd." ".shellescape(tarbase).".tar.gz ".shellescape(fname))
+ if v:shell_error != 0
+ echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar.gz ".fname.": failed!" | echohl NONE
+" call Decho("***error*** ".extractcmd." ".tarbase.".tar.gz ".fname.": failed!")
+ else
+ echo "***note*** successfully extracted ".fname
+ endif
+
+ elseif filereadable(tarbase.".tbz")
+ let extractcmd= substitute(extractcmd,"-","-j","")
+" call Decho("system(".extractcmd." ".shellescape(tarbase).".tbz ".shellescape(fname).")")
+ call system(extractcmd." ".shellescape(tarbase).".tbz ".shellescape(fname))
+ if v:shell_error != 0
+ echohl Error | echo "***error*** ".extractcmd."j ".tarbase.".tbz ".fname.": failed!" | echohl NONE
+" call Decho("***error*** ".extractcmd."j ".tarbase.".tbz ".fname.": failed!")
+ else
+ echo "***note*** successfully extracted ".fname
+ endif
+
+ elseif filereadable(tarbase.".tar.bz2")
+ let extractcmd= substitute(extractcmd,"-","-j","")
+" call Decho("system(".extractcmd." ".shellescape(tarbase).".tar.bz2 ".shellescape(fname).")")
+ call system(extractcmd." ".shellescape(tarbase).".tar.bz2 ".shellescape(fname))
+ if v:shell_error != 0
+ echohl Error | echo "***error*** ".extractcmd."j ".tarbase.".tar.bz2 ".fname.": failed!" | echohl NONE
+" call Decho("***error*** ".extractcmd."j ".tarbase.".tar.bz2 ".fname.": failed!")
+ else
+ echo "***note*** successfully extracted ".fname
+ endif
+
+ elseif filereadable(tarbase.".txz")
+ let extractcmd= substitute(extractcmd,"-","-J","")
+" call Decho("system(".extractcmd." ".shellescape(tarbase).".txz ".shellescape(fname).")")
+ call system(extractcmd." ".shellescape(tarbase).".txz ".shellescape(fname))
+ if v:shell_error != 0
+ echohl Error | echo "***error*** ".extractcmd." ".tarbase.".txz ".fname.": failed!" | echohl NONE
+" call Decho("***error*** ".extractcmd." ".tarbase.".txz ".fname.": failed!")
+ else
+ echo "***note*** successfully extracted ".fname
+ endif
+
+ elseif filereadable(tarbase.".tar.xz")
+ let extractcmd= substitute(extractcmd,"-","-J","")
+" call Decho("system(".extractcmd." ".shellescape(tarbase).".tar.xz ".shellescape(fname).")")
+ call system(extractcmd." ".shellescape(tarbase).".tar.xz ".shellescape(fname))
+ if v:shell_error != 0
+ echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar.xz ".fname.": failed!" | echohl NONE
+" call Decho("***error*** ".extractcmd." ".tarbase.".tar.xz ".fname.": failed!")
+ else
+ echo "***note*** successfully extracted ".fname
+ endif
+
+ elseif filereadable(tarbase.".tzs")
+ let extractcmd= substitute(extractcmd,"-","--zstd","")
+" call Decho("system(".extractcmd." ".shellescape(tarbase).".tzs ".shellescape(fname).")")
+ call system(extractcmd." ".shellescape(tarbase).".txz ".shellescape(fname))
+ if v:shell_error != 0
+ echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tzs ".fname.": failed!" | echohl NONE
+" call Decho("***error*** ".extractcmd." ".tarbase.".tzs ".fname.": failed!")
+ else
+ echo "***note*** successfully extracted ".fname
+ endif
+
+ elseif filereadable(tarbase.".tar.zst")
+ let extractcmd= substitute(extractcmd,"-","--zstd","")
+" call Decho("system(".extractcmd." ".shellescape(tarbase).".tar.zst ".shellescape(fname).")")
+ call system(extractcmd." ".shellescape(tarbase).".tar.xz ".shellescape(fname))
+ if v:shell_error != 0
+ echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar.zst ".fname.": failed!" | echohl NONE
+" call Decho("***error*** ".extractcmd." ".tarbase.".tar.zst ".fname.": failed!")
+ else
+ echo "***note*** successfully extracted ".fname
+ endif
+ endif
+
+ " restore option
+ let &report= repkeep
+
+" call Dret("tar#Extract")
+endfun
+
+" ---------------------------------------------------------------------
" s:Rmdir: {{{2
fun! s:Rmdir(fname)
" call Dfunc("Rmdir(fname<".a:fname.">)")
@@ -587,10 +773,7 @@ fun! tar#Vimuntar(...)
" if necessary, decompress the tarball; then, extract it
if tartail =~ '\.tgz'
- let gzip_command = s:get_gzip_command(tarfile)
- if executable(gzip_command)
- silent exe "!" . gzip_command . " -d ".shellescape(tartail)
- elseif executable("gunzip")
+ if executable("gunzip")
silent exe "!gunzip ".shellescape(tartail)
elseif executable("gzip")
silent exe "!gzip -d ".shellescape(tartail)
@@ -628,28 +811,6 @@ fun! tar#Vimuntar(...)
" call Dret("tar#Vimuntar")
endfun
-func s:get_gzip_command(file)
- " Try using the "file" command to get the actual compression type, since
- " there is no standard way for the naming: ".tgz", ".tbz", ".txz", etc.
- " If the "file" command doesn't work fall back to just using the file name.
- if a:file =~# 'z$'
- let filetype = system('file ' . a:file)
- if filetype =~ 'bzip2 compressed' && executable('bzip2')
- return 'bzip2'
- endif
- if filetype =~ 'XZ compressed' && executable('xz')
- return 'xz'
- endif
- endif
- if a:file =~# 'bz2$'
- return 'bzip2'
- endif
- if a:file =~# 'xz$'
- return 'xz'
- endif
- return 'gzip'
-endfunc
-
" =====================================================================
" Modelines And Restoration: {{{1
let &cpo= s:keepcpo
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index dd3469372e..fdc41af1d5 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -1148,6 +1148,18 @@ nvim_load_context({dict}) *nvim_load_context()*
Parameters: ~
{dict} |Context| map.
+nvim_notify({msg}, {log_level}, {opts}) *nvim_notify()*
+ Notify the user with a message
+
+ Relays the call to vim.notify . By default forwards your
+ message in the echo area but can be overriden to trigger
+ desktop notifications.
+
+ Parameters: ~
+ {msg} Message to display to the user
+ {log_level} The log level
+ {opts} Reserved for future use.
+
nvim_open_win({buffer}, {enter}, {config}) *nvim_open_win()*
Open a new window.
@@ -1800,6 +1812,25 @@ nvim_buf_attach({buffer}, {send_buffer}, {opts}) *nvim_buf_attach()*
• deleted_codeunits (if `utf_sizes` is
true)
+ • on_bytes: lua callback invoked on change.
+ This callback receives more granular
+ information about the change compared to
+ on_lines. Return`true`to detach. Args:
+ • the string "bytes"
+ • buffer handle
+ • b:changedtick
+ • start row of the changed text
+ (zero-indexed)
+ • start column of the changed text
+ • byte offset of the changed text (from
+ the start of the buffer)
+ • old end row of the changed text
+ • old end column of the changed text
+ • old end byte length of the changed text
+ • new end row of the changed text
+ • new end column of the changed text
+ • new end byte length of the changed text
+
• on_changedtick: Lua callback invoked on
changedtick increment without text
change. Args:
@@ -1812,6 +1843,12 @@ nvim_buf_attach({buffer}, {send_buffer}, {opts}) *nvim_buf_attach()*
• the string "detach"
• buffer handle
+ • on_reload: Lua callback invoked on
+ reload. The entire buffer content should
+ be considered changed. Args:
+ • the string "detach"
+ • buffer handle
+
• utf_sizes: include UTF-32 and UTF-16 size
of the replaced region, as args to
`on_lines` .
@@ -2158,6 +2195,13 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {opts})
• hl_group : name of the highlight group used to
highlight this mark.
• virt_text : virtual text to link to this mark.
+ • virt_text_pos : positioning of virtual text.
+ Possible values:
+ • "eol": right after eol character (default)
+ • "overlay": display over the specified
+ column, without shifting the underlying
+ text.
+
• ephemeral : for use with
|nvim_set_decoration_provider| callbacks. The
mark will only be used for the current redraw
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index b96fc4ac01..be7c026f5a 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1541,7 +1541,10 @@ v:dying Normally zero. When a deadly signal is caught it's set to
VimLeave autocommands will not be executed.
*v:exiting* *exiting-variable*
-v:exiting Exit code, or |v:null| if not exiting. |VimLeave|
+v:exiting Exit code, or |v:null| before invoking the |VimLeavePre|
+ and |VimLeave| autocmds. See |:q|, |:x| and |:cquit|.
+ Example: >
+ :au VimLeave * echo "Exit value is " .. v:exiting
*v:echospace* *echospace-variable*
v:echospace Number of screen cells that can be used for an `:echo` message
@@ -2074,6 +2077,8 @@ changenr() Number current change number
chanclose({id}[, {stream}]) Number Closes a channel or one of its streams
chansend({id}, {data}) Number Writes {data} to channel
char2nr({expr}[, {utf8}]) Number ASCII/UTF8 value of first char in {expr}
+charidx({string}, {idx} [, {countcc}])
+ Number char index of byte {idx} in {string}
cindent({lnum}) Number C indent for line {lnum}
clearmatches([{win}]) none clear all matches
col({expr}) Number column nr of cursor or mark
@@ -3024,6 +3029,29 @@ char2nr({expr} [, {utf8}]) *char2nr()*
A combining character is a separate character.
|nr2char()| does the opposite.
+ *charidx()*
+charidx({string}, {idx} [, {countcc}])
+ Return the character index of the byte at {idx} in {string}.
+ The index of the first character is zero.
+ If there are no multibyte characters the returned value is
+ equal to {idx}.
+ When {countcc} is omitted or zero, then composing characters
+ are not counted separately, their byte length is added to the
+ preceding base character.
+ When {countcc} is set to 1, then composing characters are
+ counted as separate characters.
+ Returns -1 if the arguments are invalid or if {idx} is greater
+ than the index of the last byte in {string}. An error is
+ given if the first argument is not a string, the second
+ argument is not a number or when the third argument is present
+ and is not zero or one.
+ See |byteidx()| and |byteidxcomp()| for getting the byte index
+ from the character index.
+ Examples: >
+ echo charidx('áb́ć', 3) returns 1
+ echo charidx('áb́ć', 6, 1) returns 4
+ echo charidx('áb́ć', 16) returns -1
+
cindent({lnum}) *cindent()*
Get the amount of indent for line {lnum} according the C
indenting rules, as with 'cindent'.
@@ -5097,6 +5125,8 @@ has({feature}) Returns 1 if {feature} is supported, 0 otherwise. The
iconv Can use |iconv()| for conversion.
+shellslash Can use backslashes in filenames (Windows)
clipboard |clipboard| provider is available.
+ fname_case Case in file names matters (for Darwin and MS-Windows
+ this is not present).
mac MacOS system.
nvim This is Nvim.
python2 Legacy Vim |python2| interface. |has-python|
@@ -9776,15 +9806,49 @@ change their contents. Thus you can pass a |List| to a function and have the
function add an item to it. If you want to make sure the function cannot
change a |List| or |Dictionary| use |:lockvar|.
-When not using "...", the number of arguments in a function call must be equal
-to the number of named arguments. When using "...", the number of arguments
-may be larger.
-
It is also possible to define a function without any arguments. You must
still supply the () then.
It is allowed to define another function inside a function body.
+ *optional-function-argument*
+You can provide default values for positional named arguments. This makes
+them optional for function calls. When a positional argument is not
+specified at a call, the default expression is used to initialize it.
+This only works for functions declared with |function|, not for lambda
+expressions |expr-lambda|.
+
+Example: >
+ function Something(key, value = 10)
+ echo a:key .. ": " .. a:value
+ endfunction
+ call Something('empty') "empty: 10"
+ call Something('key', 20) "key: 20"
+
+The argument default expressions are evaluated at the time of the function
+call, not definition. Thus it is possible to use an expression which is
+invalid the moment the function is defined. The expressions are also only
+evaluated when arguments are not specified during a call.
+
+ *E989*
+Optional arguments with default expressions must occur after any mandatory
+arguments. You can use "..." after all optional named arguments.
+
+It is possible for later argument defaults to refer to prior arguments,
+but not the other way around. They must be prefixed with "a:", as with all
+arguments.
+
+Example that works: >
+ :function Okay(mandatory, optional = a:mandatory)
+ :endfunction
+Example that does NOT work: >
+ :function NoGood(first = a:second, second = 10)
+ :endfunction
+<
+When not using "...", the number of arguments in a function call must be equal
+to the number of mandatory named arguments. When using "...", the number of
+arguments may be larger.
+
*local-variables*
Inside a function local variables can be used. These will disappear when the
function returns. Global variables need to be accessed with "g:".
diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt
index c4b93a2a27..6902ed5fd4 100644
--- a/runtime/doc/insert.txt
+++ b/runtime/doc/insert.txt
@@ -287,8 +287,7 @@ character is written at the end of each line. Thus if you want to insert a
*i_CTRL-X* *insert_expand*
CTRL-X enters a sub-mode where several commands can be used. Most of these
-commands do keyword completion; see |ins-completion|. These are not available
-when Vim was compiled without the |+insert_expand| feature.
+commands do keyword completion; see |ins-completion|.
Two commands can be used to scroll the window up or down, without exiting
insert mode:
@@ -592,9 +591,6 @@ In Insert and Replace mode, there are several commands to complete part of a
keyword or line that has been typed. This is useful if you are using
complicated keywords (e.g., function names with capitals and underscores).
-These commands are not available when the |+insert_expand| feature was
-disabled at compile time.
-
Completion can be done for:
1. Whole lines |i_CTRL-X_CTRL-L|
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt
index 06666c3a27..d2d88fb9ba 100644
--- a/runtime/doc/lsp.txt
+++ b/runtime/doc/lsp.txt
@@ -397,6 +397,11 @@ LSP HIGHLIGHT *lsp-highlight*
Reference Highlights:
+Highlight groups that are meant to be used by |vim.lsp.buf.document_highlight()|.
+
+You can see more about the differences in types here:
+https://microsoft.github.io/language-server-protocol/specification#textDocument_documentHighlight
+
*hl-LspReferenceText*
LspReferenceText used for highlighting "text" references
*hl-LspReferenceRead*
@@ -932,15 +937,21 @@ definition() *vim.lsp.buf.definition()*
Jumps to the definition of the symbol under the cursor.
document_highlight() *vim.lsp.buf.document_highlight()*
- Send request to server to resolve document highlights for the
- current text document position. This request can be associated
- to key mapping or to events such as `CursorHold` , eg:
+ Send request to the server to resolve document highlights for
+ the current text document position. This request can be
+ triggered by a key mapping or by events such as `CursorHold` ,
+ eg:
>
vim.api.nvim_command [[autocmd CursorHold <buffer> lua vim.lsp.buf.document_highlight()]]
vim.api.nvim_command [[autocmd CursorHoldI <buffer> lua vim.lsp.buf.document_highlight()]]
vim.api.nvim_command [[autocmd CursorMoved <buffer> lua vim.lsp.buf.clear_references()]]
<
+ Note: Usage of |vim.lsp.buf.document_highlight()| requires the
+ following highlight groups to be defined or you won't be able
+ to see the actual highlights. |LspReferenceText|
+ |LspReferenceRead| |LspReferenceWrite|
+
document_symbol() *vim.lsp.buf.document_symbol()*
Lists all symbols in the current buffer in the quickfix
window.
@@ -1307,6 +1318,17 @@ on_publish_diagnostics({_}, {_}, {params}, {client_id}, {_}, {config})
• Update diagnostics in InsertMode or wait
until InsertLeave
+reset({client_id}, {buffer_client_map}) *vim.lsp.diagnostic.reset()*
+ Clear diagnotics and diagnostic cache
+
+ Handles saving diagnostics from multiple clients in the same
+ buffer.
+
+ Parameters: ~
+ {client_id} number
+ {buffer_client_map} table map of buffers to active
+ clients
+
save({diagnostics}, {bufnr}, {client_id}) *vim.lsp.diagnostic.save()*
Save diagnostics to the current buffer.
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index ce3788e0fc..c4d5df84cf 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -4090,8 +4090,6 @@ A jump table for the options with a short description can be found at |Q_op|.
In the "popup" model the right mouse button produces a pop-up menu.
You need to define this first, see |popup-menu|.
- In a terminal the popup menu works if Vim is compiled with the
- |+insert_expand| option.
Note that you can further refine the meaning of buttons with mappings.
See |mouse-overview|. But mappings are NOT used for modeless selection.
@@ -4858,7 +4856,9 @@ A jump table for the options with a short description can be found at |Q_op|.
local to window
Number of lines to scroll with CTRL-U and CTRL-D commands. Will be
set to half the number of lines in the window when the window size
- changes. If you give a count to the CTRL-U or CTRL-D command it will
+ changes. This may happen when enabling the |status-line| or
+ 'tabline' option after setting the 'scroll' option.
+ If you give a count to the CTRL-U or CTRL-D command it will
be used as the new value for 'scroll'. Reset to half the window
height with ":set scroll=0".
diff --git a/runtime/doc/pi_netrw.txt b/runtime/doc/pi_netrw.txt
index 9a75a95f23..7312ab721b 100644
--- a/runtime/doc/pi_netrw.txt
+++ b/runtime/doc/pi_netrw.txt
@@ -1,9 +1,9 @@
-*pi_netrw.txt* For Vim version 8.1. Last change: 2019 Jul 17
+*pi_netrw.txt* For Vim version 8.2. Last change: 2020 Aug 15
------------------------------------------------
NETRW REFERENCE MANUAL by Charles E. Campbell
------------------------------------------------
-Author: Charles E. Campbell <NdrOchip@ScampbellPfamily.AbizM>
+Author: Charles E. Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
(remove NOSPAM from Campbell's email first)
Copyright: Copyright (C) 2017 Charles E Campbell *netrw-copyright*
@@ -1565,8 +1565,8 @@ So, for example: >
file.rcs,v -> NFH_rcsCOMMAv()
<
If more such translations are necessary, please send me email: >
- NdrOchip at ScampbellPfamily.AbizM - NOSPAM
-with a request.
+ NcampObell@SdrPchip.AorgM-NOSPAM
+with a request. (remove the embedded NOSPAM first)
Associated setting variable: |g:netrw_browsex_viewer|
@@ -2744,9 +2744,8 @@ your browsing preferences. (see also: |netrw-settings|)
*g:netrw_home* The home directory for where bookmarks and
history are saved (as .netrwbook and
.netrwhist).
- Netrw uses |expand()|on the string.
- default: the first directory on the
- |'runtimepath'|
+ Netrw uses |expand()| on the string.
+ default: stdpath('data') (see |stdpath()|)
*g:netrw_keepdir* =1 (default) keep current directory immune from
the browsing directory.
@@ -3054,7 +3053,7 @@ your browsing preferences. (see also: |netrw-settings|)
(see |netrw-c-tab|).
*g:netrw_xstrlen* Controls how netrw computes string lengths,
- including multi-byte characters' string
+ including multibyte characters' string
length. (thanks to N Weibull, T Mechelynck)
=0: uses Vim's built-in strlen()
=1: number of codepoints (Latin a + combining
@@ -3229,7 +3228,8 @@ If there are marked files: (see |netrw-mf|)
R [query: reply with s/^\(.*\)\.c$/\1.cpp/]
<
This example will mark all *.c files and then rename them to *.cpp
- files.
+ files. Netrw will protect you from overwriting local files without
+ confirmation, but not remote ones.
The ctrl-X character has special meaning for renaming files: >
@@ -3512,7 +3512,7 @@ Example: Clear netrw's marked file list via a mapping on gu >
- Click "Add..."
- Set External Editor (adjust path as needed, include
the quotes and !.! at the end):
- "c:\Program Files\Vim\vim70\gvim.exe" !.!
+ "c:\Program Files\Vim\vim82\gvim.exe" !.!
- Check that the filetype in the box below is
{asterisk}.{asterisk} (all files), or whatever types
you want (cec: change {asterisk} to * ; I had to
@@ -3762,8 +3762,8 @@ by obtaining a copy of the latest (often developmental) netrw at:
The <netrw.vim> script is typically installed on systems as something like:
>
- /usr/local/share/vim/vim7x/plugin/netrwPlugin.vim
- /usr/local/share/vim/vim7x/autoload/netrw.vim
+ /usr/local/share/vim/vim8x/plugin/netrwPlugin.vim
+ /usr/local/share/vim/vim8x/autoload/netrw.vim
(see output of :echo &rtp)
<
which is loaded automatically at startup (assuming :set nocp). If you
@@ -3836,12 +3836,30 @@ netrw:
Please send that information to <netrw.vim>'s maintainer along
with the o/s you're using and the vim version that you're using
- (see |:version|) >
- NdrOchip at ScampbellPfamily.AbizM - NOSPAM
+ (see |:version|) (remove the embedded NOSPAM first) >
+ NcampObell@SdrPchip.AorgM-NOSPAM
<
==============================================================================
12. History *netrw-history* {{{1
+ v169: Dec 20, 2019 * (reported by amkarthik) that netrw's x
+ (|netrw-x|) would throw an error when
+ attempting to open a local directory.
+ v168: Dec 12, 2019 * scp timeout error message not reported,
+ hopefully now fixed (Shane Xb Qian)
+
+ v167: Nov 29, 2019 * netrw does a save&restore on @* and @+.
+ That causes problems with the clipboard.
+ Now restores occurs only if @* or @+ have
+ been changed.
+ * netrw will change @* or @+ less often.
+ Never if I happen to have caught all the
+ operations that modify the unnamed
+ register (which also writes @*).
+ * Modified hiding behavior so that "s"
+ will not ignore hiding.
+ v166: Nov 06, 2019 * Removed a space from a nmap for "-"
+ * Numerous debugging statement changes
v163: Dec 05, 2017 * (Cristi Balan) reported that a setting ('sel')
was left changed
* (Holger Mitschke) reported a problem with
@@ -3852,6 +3870,8 @@ netrw:
* (Holger Mitschke) amended this help file
with additional |g:netrw_special_syntax|
items
+ * Prioritized wget over curl for
+ g:netrw_http_cmd
v162: Sep 19, 2016 * (haya14busa) pointed out two syntax errors
with a patch; these are now fixed.
Oct 26, 2016 * I started using mate-terminal and found that
@@ -4265,7 +4285,7 @@ netrw:
Vim editor by Bram Moolenaar (Thanks, Bram!)
dav support by C Campbell
fetch support by Bram Moolenaar and C Campbell
- ftp support by C Campbell <NdrOchip@ScampbellPfamily.AbizM>
+ ftp support by C Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
http support by Bram Moolenaar <bram@moolenaar.net>
rcp
rsync support by C Campbell (suggested by Erik Warendorph)
diff --git a/runtime/doc/pi_tar.txt b/runtime/doc/pi_tar.txt
index 59b318b7fd..c6c0596ea0 100644
--- a/runtime/doc/pi_tar.txt
+++ b/runtime/doc/pi_tar.txt
@@ -1,12 +1,12 @@
-*pi_tar.txt* Nvim
+*pi_tar.txt* For Vim version 8.2. Last change: 2020 Jan 07
+====================+
| Tar File Interface |
+====================+
-Author: Charles E. Campbell <NdrOchip@ScampbellPfamily.AbizM>
+Author: Charles E. Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
(remove NOSPAM from Campbell's email first)
-Copyright 2005-2012: *tar-copyright*
+Copyright 2005-2017: *tar-copyright*
The VIM LICENSE (see |copyright|) applies to the files in this
package, including tarPlugin.vim, tar.vim, and pi_tar.txt. Like
anything else that's except use "tar.vim" instead of "VIM". Like
@@ -104,48 +104,67 @@ Copyright 2005-2012: *tar-copyright*
==============================================================================
4. History *tar-history*
-
- v28 Jun 23, 2011 * a few more decompression options (tbz tb2 txz)
- v27 May 31, 2011 * moved cygwin detection before g:tar_copycmd handling
- * inserted additional |:keepj| modifiers
- * changed silent to sil! (|:silent|)
- v26 Aug 09, 2010 * uses buffer-local instead of window variables to hold
- tarfile name
- * inserted keepj before 0d to protect jump list
- v25 Jun 19, 2010 * (Jan Steffens) added support for xz compression
- v24 Apr 07, 2009 * :Untarvim command implemented
- Sep 28, 2009 * Added lzma support
- v22 Aug 08, 2008 * security fixes
- v16 Jun 06, 2008 * tarfile:: used instead of tarfile: when editing files
- inside tarballs. Fixes a problem with tarballs called
- things like c:\abc.tar. (tnx to Bill McCarthy)
- v14 May 09, 2008 * arno caught a security bug
- May 28, 2008 * various security improvements. Now requires patch 299
- which provides the fnameescape() function
- May 30, 2008 * allows one to view *.gz and *.bz2 files that are in
- *.tar files.
- v12 Sep 07, 2007 * &shq now used if not the empty string for g:tar_shq
- v10 May 02, 2006 * now using "redraw then echo" to show messages, instead
- of "echo and prompt user"
- v9 May 02, 2006 * improved detection of masquerading as tar file
- v8 May 02, 2006 * allows editing of files that merely masquerade as tar
- files
- v7 Mar 22, 2006 * work on making tar plugin work across network
- Mar 27, 2006 * g:tar_cmd now available for users to change the name
- of the tar program to be used. By default, of course,
- it's "tar".
- v6 Dec 21, 2005 * writing to files not in directories caused problems -
- fixed (pointed out by Christian Robinson)
- v5 Nov 22, 2005 * report option workaround installed
- v3 Sep 16, 2005 * handles writing files in an archive back to the
- archive
- Oct 18, 2005 * <amatch> used instead of <afile> in autocmds
- Oct 18, 2005 * handles writing to compressed archives
- Nov 03, 2005 * handles writing tarfiles across a network using
- netrw#NetWrite()
- v2 * converted to use Vim7's new autoload feature by
- Bram Moolenaar
- v1 (original) * Michael Toren (see http://michael.toren.net/code/)
+ v31 Apr 02, 2017 * (klartext) reported that browsing encrypted
+ files in a zip archive created unencrypted
+ swap files. I am applying a similar fix
+ used on zip.vim to tar.vim: new buffers
+ are opened with |:noswapfile|.
+ May 16, 2017 * When the mouse option isn't empty, the
+ leftmouse can be used to select a file
+ in the tar-file listing.
+ v30 Apr 22, 2014 * .tgz files are ambiguous: they may have been
+ compressed with either gzip or bzip2. Tar.vim
+ disambiguates by using unix's "file" command.
+ Feb 18, 2016 * Changed =~ to =~# where appropriate
+ Feb 18, 2017 * Now also permits xz decompression
+ v28 Jun 23, 2011 * a few more decompression options (tbz tb2 txz)
+ v27 May 31, 2011 * moved cygwin detection before g:tar_copycmd
+ handling
+ * inserted additional |:keepj| modifiers
+ * changed silent to sil! (|:silent|)
+ v26 Aug 09, 2010 * uses buffer-local instead of window variables
+ to hold tarfile name
+ * inserted keepj before 0d to protect jump list
+ v25 Jun 19, 2010 * (Jan Steffens) added support for xz
+ compression
+ v24 Apr 07, 2009 * :Untarvim command implemented
+ Sep 28, 2009 * Added lzma support
+ v22 Aug 08, 2008 * security fixes
+ v16 Jun 06, 2008 * tarfile:: used instead of tarfile: when
+ editing files inside tarballs. Fixes a
+ problem with tarballs called things like
+ c:\abc.tar. (tnx to Bill McCarthy)
+ v14 May 09, 2008 * arno caught a security bug
+ May 28, 2008 * various security improvements. Now requires
+ patch 299 which provides the fnameescape()
+ function
+ May 30, 2008 * allows one to view *.gz and *.bz2 files that
+ are in *.tar files.
+ v12 Sep 07, 2007 * &shq now used if not the empty string for
+ g:tar_shq
+ v10 May 02, 2006 * now using "redraw then echo" to show messages,
+ instead of "echo and prompt user"
+ v9 May 02, 2006 * improved detection of masquerading as tar file
+ v8 May 02, 2006 * allows editing of files that merely masquerade
+ as tar files
+ v7 Mar 22, 2006 * work on making tar plugin work across network
+ Mar 27, 2006 * g:tar_cmd now available for users to change
+ the name of the tar program to be used. By
+ default, of course, it's "tar".
+ v6 Dec 21, 2005 * writing to files not in directories caused
+ problems - fixed (pointed out by
+ Christian Robinson)
+ v5 Nov 22, 2005 * report option workaround installed
+ v3 Sep 16, 2005 * handles writing files in an archive back to
+ the archive
+ Oct 18, 2005 * <amatch> used instead of <afile> in autocmds
+ Oct 18, 2005 * handles writing to compressed archives
+ Nov 03, 2005 * handles writing tarfiles across a network
+ using netrw#NetWrite()
+ v2 * converted to use Vim7's new autoload feature
+ by Bram Moolenaar
+ v1 (original) * Michael Toren
+ (see http://michael.toren.net/code/)
==============================================================================
vim:tw=78:ts=8:noet:ft=help
diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt
index e92e464c6a..63c899da0c 100644
--- a/runtime/doc/usr_41.txt
+++ b/runtime/doc/usr_41.txt
@@ -613,6 +613,7 @@ String manipulation: *string-functions*
iconv() convert text from one encoding to another
byteidx() byte index of a character in a string
byteidxcomp() like byteidx() but count composing characters
+ charidx() character index of a byte in a string
repeat() repeat a string multiple times
eval() evaluate a string expression
execute() execute an Ex command and get the output
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index 808af5f544..0c1e216164 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -144,7 +144,6 @@ Command-line highlighting:
removed in the future).
Commands:
- |:autocmd| accepts the `++once` flag
|:checkhealth|
|:drop| is always available
|:Man| is available by default, with many improvements such as completion
@@ -157,8 +156,6 @@ Events:
|TermOpen|
|UIEnter|
|UILeave|
- |VimResume|
- |VimSuspend|
|WinClosed|
Functions:
@@ -195,11 +192,10 @@ Options:
'cpoptions' flags: |cpo-_|
'display' flags: "msgsep" minimizes scrolling when showing messages
'guicursor' works in the terminal
- 'fillchars' flags: "msgsep" (see 'display'), "eob" for |hl-EndOfBuffer|
- marker, "foldopen", "foldsep", "foldclose"
+ 'fillchars' flags: "msgsep" (see 'display'), "foldopen", "foldsep",
+ "foldclose"
'foldcolumn' supports up to 9 dynamic/fixed columns
'inccommand' shows interactive results for |:substitute|-like commands
- 'listchars' local to window
'pumblend' pseudo-transparent popupmenu
'scrollback'
'signcolumn' supports up to 9 dynamic/fixed columns
diff --git a/runtime/filetype.vim b/runtime/filetype.vim
index 53fd66c4df..6a13e67ac5 100644
--- a/runtime/filetype.vim
+++ b/runtime/filetype.vim
@@ -212,6 +212,9 @@ au BufNewFile,BufRead *.bc setf bc
" BDF font
au BufNewFile,BufRead *.bdf setf bdf
+" Beancount
+au BufNewFile,BufRead *.beancount setf beancount
+
" BibTeX bibliography database file
au BufNewFile,BufRead *.bib setf bib
@@ -1491,6 +1494,9 @@ au BufNewFile,BufRead *.sdl,*.pr setf sdl
" sed
au BufNewFile,BufRead *.sed setf sed
+" svelte
+au BufNewFile,BufRead *.svelte setf svelte
+
" Sieve (RFC 3028, 5228)
au BufNewFile,BufRead *.siv,*.sieve setf sieve
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
index a6f118abde..143909fe41 100644
--- a/runtime/lua/vim/lsp.lua
+++ b/runtime/lua/vim/lsp.lua
@@ -16,10 +16,7 @@ local validate = vim.validate
local lsp = {
protocol = protocol;
- -- TODO(tjdevries): Add in the warning that `callbacks` is no longer supported.
- -- util.warn_once("vim.lsp.callbacks is deprecated. Use vim.lsp.handlers instead.")
handlers = default_handlers;
- callbacks = default_handlers;
buf = require'vim.lsp.buf';
diagnostic = require'vim.lsp.diagnostic';
@@ -219,8 +216,6 @@ local function validate_client_config(config)
}
validate {
root_dir = { config.root_dir, is_dir, "directory" };
- -- TODO(remove-callbacks)
- callbacks = { config.callbacks, "t", true };
handlers = { config.handlers, "t", true };
capabilities = { config.capabilities, "t", true };
cmd_cwd = { config.cmd_cwd, optional_validator(is_dir), "directory" };
@@ -235,13 +230,6 @@ local function validate_client_config(config)
flags = { config.flags, "t", true };
}
- -- TODO(remove-callbacks)
- if config.handlers and config.callbacks then
- error(debug.traceback(
- "Unable to configure LSP with both 'config.handlers' and 'config.callbacks'. Use 'config.handlers' exclusively."
- ))
- end
-
local cmd, cmd_args = lsp._cmd_parts(config.cmd)
local offset_encoding = valid_encodings.UTF16
if config.offset_encoding then
@@ -473,8 +461,7 @@ function lsp.start_client(config)
local client_id = next_client_id()
- -- TODO(remove-callbacks)
- local handlers = config.handlers or config.callbacks or {}
+ local handlers = config.handlers or {}
local name = config.name or tostring(client_id)
local log_prefix = string.format("LSP[%s]", name)
@@ -548,19 +535,13 @@ function lsp.start_client(config)
function dispatch.on_exit(code, signal)
active_clients[client_id] = nil
uninitialized_clients[client_id] = nil
- local active_buffers = {}
- for bufnr, client_ids in pairs(all_buffer_active_clients) do
- if client_ids[client_id] then
- table.insert(active_buffers, bufnr)
- end
+
+ lsp.diagnostic.reset(client_id, all_buffer_active_clients)
+ all_client_active_buffers[client_id] = nil
+ for _, client_ids in pairs(all_buffer_active_clients) do
client_ids[client_id] = nil
end
- -- Buffer level cleanup
- vim.schedule(function()
- for _, bufnr in ipairs(active_buffers) do
- lsp.diagnostic.clear(bufnr)
- end
- end)
+
if config.on_exit then
pcall(config.on_exit, code, signal, client_id)
end
@@ -579,8 +560,6 @@ function lsp.start_client(config)
offset_encoding = offset_encoding;
config = config;
- -- TODO(remove-callbacks)
- callbacks = handlers;
handlers = handlers;
-- for $/progress report
messages = { name = name, messages = {}, progress = {}, status = {} }
@@ -751,6 +730,13 @@ function lsp.start_client(config)
---
--@param force (bool, optional)
function client.stop(force)
+
+ lsp.diagnostic.reset(client_id, all_buffer_active_clients)
+ all_client_active_buffers[client_id] = nil
+ for _, client_ids in pairs(all_buffer_active_clients) do
+ client_ids[client_id] = nil
+ end
+
local handle = rpc.handle
if handle:is_closing() then
return
@@ -1016,23 +1002,12 @@ end
function lsp.stop_client(client_id, force)
local ids = type(client_id) == 'table' and client_id or {client_id}
for _, id in ipairs(ids) do
- local resolved_client_id
if type(id) == 'table' and id.stop ~= nil then
id.stop(force)
- resolved_client_id = id.id
elseif active_clients[id] then
active_clients[id].stop(force)
- resolved_client_id = id
elseif uninitialized_clients[id] then
uninitialized_clients[id].stop(true)
- resolved_client_id = id
- end
- if resolved_client_id then
- local client_buffers = lsp.get_buffers_by_client_id(resolved_client_id)
- for idx = 1, #client_buffers do
- lsp.diagnostic.clear(client_buffers[idx], resolved_client_id)
- end
- all_client_active_buffers[resolved_client_id] = nil
end
end
end
diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua
index 00219b6d98..31116985e2 100644
--- a/runtime/lua/vim/lsp/buf.lua
+++ b/runtime/lua/vim/lsp/buf.lua
@@ -310,15 +310,21 @@ function M.workspace_symbol(query)
request('workspace/symbol', params)
end
---- Send request to server to resolve document highlights for the
---- current text document position. This request can be associated
---- to key mapping or to events such as `CursorHold`, eg:
+--- Send request to the server to resolve document highlights for the current
+--- text document position. This request can be triggered by a key mapping or
+--- by events such as `CursorHold`, eg:
---
--- <pre>
--- vim.api.nvim_command [[autocmd CursorHold <buffer> lua vim.lsp.buf.document_highlight()]]
--- vim.api.nvim_command [[autocmd CursorHoldI <buffer> lua vim.lsp.buf.document_highlight()]]
--- vim.api.nvim_command [[autocmd CursorMoved <buffer> lua vim.lsp.buf.clear_references()]]
--- </pre>
+---
+--- Note: Usage of |vim.lsp.buf.document_highlight()| requires the following highlight groups
+--- to be defined or you won't be able to see the actual highlights.
+--- |LspReferenceText|
+--- |LspReferenceRead|
+--- |LspReferenceWrite|
function M.document_highlight()
local params = util.make_position_params()
request('textDocument/documentHighlight', params)
diff --git a/runtime/lua/vim/lsp/callbacks.lua b/runtime/lua/vim/lsp/callbacks.lua
deleted file mode 100644
index 1da92b900d..0000000000
--- a/runtime/lua/vim/lsp/callbacks.lua
+++ /dev/null
@@ -1,4 +0,0 @@
-local util = require 'vim.lsp.util'
-
-util._warn_once("require('vim.lsp.callbacks') is deprecated. Use vim.lsp.handlers instead.")
-return require('vim.lsp.handlers')
diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua
index a625098bab..df25943ecd 100644
--- a/runtime/lua/vim/lsp/diagnostic.lua
+++ b/runtime/lua/vim/lsp/diagnostic.lua
@@ -1158,6 +1158,24 @@ local loclist_type_map = {
[DiagnosticSeverity.Hint] = 'I',
}
+
+--- Clear diagnotics and diagnostic cache
+---
+--- Handles saving diagnostics from multiple clients in the same buffer.
+---@param client_id number
+---@param buffer_client_map table map of buffers to active clients
+function M.reset(client_id, buffer_client_map)
+ buffer_client_map = vim.deepcopy(buffer_client_map)
+ vim.schedule(function()
+ for bufnr, client_ids in pairs(buffer_client_map) do
+ if client_ids[client_id] then
+ clear_diagnostic_cache(bufnr, client_id)
+ M.clear(bufnr, client_id)
+ end
+ end
+ end)
+end
+
--- Sets the location list
---@param opts table|nil Configuration table. Keys:
--- - {open_loclist}: (boolean, default true)
diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua
index 7eac3febd9..7819bddcb9 100644
--- a/runtime/lua/vim/lsp/handlers.lua
+++ b/runtime/lua/vim/lsp/handlers.lua
@@ -13,7 +13,7 @@ local M = {}
--- Writes to error buffer.
--@param ... (table of strings) Will be concatenated before being written
local function err_message(...)
- api.nvim_err_writeln(table.concat(vim.tbl_flatten{...}))
+ vim.notify(table.concat(vim.tbl_flatten{...}), vim.log.levels.ERROR)
api.nvim_command("redraw")
end
@@ -409,7 +409,7 @@ for k, fn in pairs(M) do
})
if err then
- error(tostring(err))
+ return err_message(tostring(err))
end
return fn(err, method, params, client_id, bufnr, config)
diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua
index 3e111c154a..388f65c180 100644
--- a/runtime/lua/vim/lsp/protocol.lua
+++ b/runtime/lua/vim/lsp/protocol.lua
@@ -938,7 +938,7 @@ function protocol.resolve_capabilities(server_capabilities)
text_document_did_change = textDocumentSync;
text_document_will_save = false;
text_document_will_save_wait_until = false;
- text_document_save = false;
+ text_document_save = true;
text_document_save_include_text = false;
}
elseif type(textDocumentSync) == 'table' then
diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua
index 90f51dfc5a..4e2dd7c8e8 100644
--- a/runtime/lua/vim/lsp/rpc.lua
+++ b/runtime/lua/vim/lsp/rpc.lua
@@ -376,6 +376,9 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
spawn_params.env = env_merge(extra_spawn_params.env)
end
handle, pid = uv.spawn(cmd, spawn_params, onexit)
+ if handle == nil then
+ error(string.format("start `%s` failed: %s", cmd, pid))
+ end
end
--@private
@@ -386,7 +389,7 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
--@returns true if the payload could be scheduled, false if the main event-loop is in the process of closing.
local function encode_and_send(payload)
local _ = log.debug() and log.debug("rpc.send.payload", payload)
- if handle:is_closing() then return false end
+ if handle == nil or handle:is_closing() then return false end
-- TODO(ashkan) remove this once we have a Lua json_encode
schedule(function()
local encoded = assert(json_encode(payload))
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index 00bdeecef3..6fb9f09c99 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -18,14 +18,6 @@ end
local M = {}
--- TODO(remove-callbacks)
-M.diagnostics_by_buf = setmetatable({}, {
- __index = function(_, bufnr)
- warn_once("diagnostics_by_buf is deprecated. Use 'vim.lsp.diagnostic.get'")
- return vim.lsp.diagnostic.get(bufnr)
- end
-})
-
--@private
local function split_lines(value)
return split(value, '\n', true)
@@ -211,7 +203,7 @@ function M.apply_text_edits(text_edits, bufnr)
local lines = api.nvim_buf_get_lines(bufnr, start_line, finish_line + 1, false)
local fix_eol = api.nvim_buf_get_option(bufnr, 'fixeol')
local set_eol = fix_eol and api.nvim_buf_line_count(bufnr) <= finish_line + 1
- if set_eol and #lines[#lines] ~= 0 then
+ if set_eol and (#lines == 0 or #lines[#lines] ~= 0) then
table.insert(lines, '')
end
@@ -1027,78 +1019,6 @@ function M.open_floating_preview(contents, filetype, opts)
return floating_bufnr, floating_winnr
end
--- TODO(remove-callbacks)
-do
- --@deprecated
- function M.get_severity_highlight_name(severity)
- warn_once("vim.lsp.util.get_severity_highlight_name is deprecated.")
- return vim.lsp.diagnostic._get_severity_highlight_name(severity)
- end
-
- --@deprecated
- function M.buf_clear_diagnostics(bufnr, client_id)
- warn_once("buf_clear_diagnostics is deprecated. Use vim.lsp.diagnostic.clear")
- return vim.lsp.diagnostic.clear(bufnr, client_id)
- end
-
- --@deprecated
- function M.get_line_diagnostics()
- warn_once("get_line_diagnostics is deprecated. Use vim.lsp.diagnostic.get_line_diagnostics")
-
- local bufnr = api.nvim_get_current_buf()
- local line_nr = api.nvim_win_get_cursor(0)[1] - 1
-
- return vim.lsp.diagnostic.get_line_diagnostics(bufnr, line_nr)
- end
-
- --@deprecated
- function M.show_line_diagnostics()
- warn_once("show_line_diagnostics is deprecated. Use vim.lsp.diagnostic.show_line_diagnostics")
-
- local bufnr = api.nvim_get_current_buf()
- local line_nr = api.nvim_win_get_cursor(0)[1] - 1
-
- return vim.lsp.diagnostic.show_line_diagnostics(bufnr, line_nr)
- end
-
- --@deprecated
- function M.buf_diagnostics_save_positions(bufnr, diagnostics, client_id)
- warn_once("buf_diagnostics_save_positions is deprecated. Use vim.lsp.diagnostic.save")
- return vim.lsp.diagnostic.save(diagnostics, bufnr, client_id)
- end
-
- --@deprecated
- function M.buf_diagnostics_get_positions(bufnr, client_id)
- warn_once("buf_diagnostics_get_positions is deprecated. Use vim.lsp.diagnostic.get")
- return vim.lsp.diagnostic.get(bufnr, client_id)
- end
-
- --@deprecated
- function M.buf_diagnostics_underline(bufnr, diagnostics, client_id)
- warn_once("buf_diagnostics_underline is deprecated. Use 'vim.lsp.diagnostic.set_underline'")
- return vim.lsp.diagnostic.set_underline(diagnostics, bufnr, client_id)
- end
-
- --@deprecated
- function M.buf_diagnostics_virtual_text(bufnr, diagnostics, client_id)
- warn_once("buf_diagnostics_virtual_text is deprecated. Use 'vim.lsp.diagnostic.set_virtual_text'")
- return vim.lsp.diagnostic.set_virtual_text(diagnostics, bufnr, client_id)
- end
-
- --@deprecated
- function M.buf_diagnostics_signs(bufnr, diagnostics, client_id)
- warn_once("buf_diagnostics_signs is deprecated. Use 'vim.lsp.diagnostic.set_signs'")
- return vim.lsp.diagnostic.set_signs(diagnostics, bufnr, client_id)
- end
-
- --@deprecated
- function M.buf_diagnostics_count(kind, client_id)
- warn_once("buf_diagnostics_count is deprecated. Use 'vim.lsp.diagnostic.get_count'")
- return vim.lsp.diagnostic.get_count(vim.api.nvim_get_current_buf(), client_id, kind)
- end
-
-end
-
do --[[ References ]]
local reference_ns = api.nvim_create_namespace("vim_lsp_references")
diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua
index 28a87f26c7..4168c1e365 100644
--- a/runtime/lua/vim/treesitter/languagetree.lua
+++ b/runtime/lua/vim/treesitter/languagetree.lua
@@ -249,17 +249,17 @@ end
--
-- @param regions A list of regions this tree should manage and parse.
function LanguageTree:set_included_regions(regions)
- -- Transform the tables from 4 element long to 6 element long (with byte offset)
- for _, region in ipairs(regions) do
- for i, range in ipairs(region) do
- if type(range) == "table" and #range == 4 then
- -- TODO(vigoux): I don't think string parsers are useful for now
- if type(self._source) == "number" then
+ -- TODO(vigoux): I don't think string parsers are useful for now
+ if type(self._source) == "number" then
+ -- Transform the tables from 4 element long to 6 element long (with byte offset)
+ for _, region in ipairs(regions) do
+ for i, range in ipairs(region) do
+ if type(range) == "table" and #range == 4 then
local start_row, start_col, end_row, end_col = unpack(range)
-- Easy case, this is a buffer parser
-- TODO(vigoux): proper byte computation here, and account for EOL ?
- local start_byte = a.nvim_buf_get_offset(self.bufnr, start_row) + start_col
- local end_byte = a.nvim_buf_get_offset(self.bufnr, end_row) + end_col
+ local start_byte = a.nvim_buf_get_offset(self._source, start_row) + start_col
+ local end_byte = a.nvim_buf_get_offset(self._source, end_row) + end_col
region[i] = { start_row, start_col, start_byte, end_row, end_col, end_byte }
end
diff --git a/runtime/plugin/netrwPlugin.vim b/runtime/plugin/netrwPlugin.vim
index 2d67f6a4e4..87302cf23b 100644
--- a/runtime/plugin/netrwPlugin.vim
+++ b/runtime/plugin/netrwPlugin.vim
@@ -1,7 +1,7 @@
" netrwPlugin.vim: Handles file transfer and remote directory listing across a network
" PLUGIN SECTION
-" Date: Feb 08, 2016
-" Maintainer: Charles E Campbell <NdrOchip@ScampbellPfamily.AbizM-NOSPAM>
+" Date: Feb 08, 2016 - Jan 07, 2020
+" Maintainer: Charles E Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
" GetLatestVimScripts: 1075 1 :AutoInstall: netrw.vim
" Copyright: Copyright (C) 1999-2013 Charles E. Campbell {{{1
" Permission is hereby granted to use and distribute this code,
@@ -20,7 +20,7 @@
if &cp || exists("g:loaded_netrwPlugin")
finish
endif
-let g:loaded_netrwPlugin = "v165"
+let g:loaded_netrwPlugin = "v168"
let s:keepcpo = &cpo
set cpo&vim
"DechoRemOn
@@ -81,7 +81,7 @@ if !exists("g:netrw_nogx")
if !hasmapto('<Plug>NetrwBrowseX')
nmap <unique> gx <Plug>NetrwBrowseX
endif
- nno <silent> <Plug>NetrwBrowseX :call netrw#BrowseX(expand((exists("g:netrw_gx")? g:netrw_gx : '<cfile>')),netrw#CheckIfRemote())<cr>
+ nno <silent> <Plug>NetrwBrowseX :call netrw#BrowseX(netrw#GX(),netrw#CheckIfRemote(netrw#GX()))<cr>
endif
if maparg('gx','v') == ""
if !hasmapto('<Plug>NetrwBrowseXVis')
diff --git a/runtime/plugin/tarPlugin.vim b/runtime/plugin/tarPlugin.vim
index 6d9e6bd540..d55492a93e 100644
--- a/runtime/plugin/tarPlugin.vim
+++ b/runtime/plugin/tarPlugin.vim
@@ -14,7 +14,7 @@
if &cp || exists("g:loaded_tarPlugin")
finish
endif
-let g:loaded_tarPlugin = "v29"
+let g:loaded_tarPlugin = "v32"
let s:keepcpo = &cpo
set cpo&vim
@@ -39,11 +39,13 @@ augroup tar
au BufReadCmd *.lrp call tar#Browse(expand("<amatch>"))
au BufReadCmd *.tar.bz2 call tar#Browse(expand("<amatch>"))
au BufReadCmd *.tar.Z call tar#Browse(expand("<amatch>"))
- au BufReadCmd *.tgz call tar#Browse(expand("<amatch>"))
au BufReadCmd *.tbz call tar#Browse(expand("<amatch>"))
+ au BufReadCmd *.tgz call tar#Browse(expand("<amatch>"))
au BufReadCmd *.tar.lzma call tar#Browse(expand("<amatch>"))
au BufReadCmd *.tar.xz call tar#Browse(expand("<amatch>"))
au BufReadCmd *.txz call tar#Browse(expand("<amatch>"))
+ au BufReadCmd *.tar.zst call tar#Browse(expand("<amatch>"))
+ au BufReadCmd *.tzs call tar#Browse(expand("<amatch>"))
augroup END
com! -nargs=? -complete=file Vimuntar call tar#Vimuntar(<q-args>)
diff --git a/runtime/syntax/netrw.vim b/runtime/syntax/netrw.vim
index c4d3cf5fda..83ae17445d 100644
--- a/runtime/syntax/netrw.vim
+++ b/runtime/syntax/netrw.vim
@@ -1,7 +1,7 @@
" Language : Netrw Listing Syntax
" Maintainer : Charles E. Campbell
-" Last change: Oct 31, 2016
-" Version : 20 NOT RELEASED
+" Last change: Nov 07, 2019
+" Version : 20
" ---------------------------------------------------------------------
if exists("b:current_syntax")
finish
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index bd336a2b3d..c1f2842b52 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -111,6 +111,24 @@ Integer nvim_buf_line_count(Buffer buffer, Error *err)
/// - byte count of previous contents
/// - deleted_codepoints (if `utf_sizes` is true)
/// - deleted_codeunits (if `utf_sizes` is true)
+/// - on_bytes: lua callback invoked on change.
+/// This callback receives more granular information about the
+/// change compared to on_lines.
+/// Return `true` to detach.
+/// Args:
+/// - the string "bytes"
+/// - buffer handle
+/// - b:changedtick
+/// - start row of the changed text (zero-indexed)
+/// - start column of the changed text
+/// - byte offset of the changed text (from the start of
+/// the buffer)
+/// - old end row of the changed text
+/// - old end column of the changed text
+/// - old end byte length of the changed text
+/// - new end row of the changed text
+/// - new end column of the changed text
+/// - new end byte length of the changed text
/// - on_changedtick: Lua callback invoked on changedtick
/// increment without text change. Args:
/// - the string "changedtick"
@@ -1407,6 +1425,11 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id,
/// - hl_group : name of the highlight group used to highlight
/// this mark.
/// - virt_text : virtual text to link to this mark.
+/// - virt_text_pos : positioning of virtual text. Possible
+/// values:
+/// - "eol": right after eol character (default)
+/// - "overlay": display over the specified column, without
+/// shifting the underlying text.
/// - ephemeral : for use with |nvim_set_decoration_provider|
/// callbacks. The mark will only be used for the current
/// redraw cycle, and not be permantently stored in the
@@ -1456,8 +1479,9 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
uint64_t id = 0;
int line2 = -1, hl_id = 0;
DecorPriority priority = DECOR_PRIORITY_BASE;
- colnr_T col2 = 0;
+ colnr_T col2 = -1;
VirtText virt_text = KV_INITIAL_VALUE;
+ VirtTextPos virt_text_pos = kVTEndOfLine;
bool right_gravity = true;
bool end_right_gravity = false;
bool end_gravity_set = false;
@@ -1526,6 +1550,22 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
if (ERROR_SET(err)) {
goto error;
}
+ } else if (strequal("virt_text_pos", k.data)) {
+ if (v->type != kObjectTypeString) {
+ api_set_error(err, kErrorTypeValidation,
+ "virt_text_pos is not a String");
+ goto error;
+ }
+ String str = v->data.string;
+ if (strequal("eol", str.data)) {
+ virt_text_pos = kVTEndOfLine;
+ } else if (strequal("overlay", str.data)) {
+ virt_text_pos = kVTOverlay;
+ } else {
+ api_set_error(err, kErrorTypeValidation,
+ "virt_text_pos: invalid value");
+ goto error;
+ }
} else if (strequal("ephemeral", k.data)) {
ephemeral = api_object_to_bool(*v, "ephemeral", false, err);
if (ERROR_SET(err)) {
@@ -1567,7 +1607,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
// Only error out if they try to set end_right_gravity without
// setting end_col or end_line
- if (line2 == -1 && col2 == 0 && end_gravity_set) {
+ if (line2 == -1 && col2 == -1 && end_gravity_set) {
api_set_error(err, kErrorTypeValidation,
"cannot set end_right_gravity "
"without setting end_line or end_col");
@@ -1591,30 +1631,28 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
col2 = 0;
}
+ Decoration *decor = NULL, tmp = { 0 };
+
+ if (kv_size(virt_text) || priority != DECOR_PRIORITY_BASE) {
+ // TODO(bfredl): this is a bit sketchy. eventually we should
+ // have predefined decorations for both marks/ephemerals
+ decor = ephemeral ? &tmp : xcalloc(1, sizeof(*decor));
+ decor->hl_id = hl_id;
+ decor->virt_text = virt_text;
+ decor->priority = priority;
+ decor->virt_text_pos = virt_text_pos;
+ } else if (hl_id) {
+ decor = decor_hl(hl_id);
+ }
+
// TODO(bfredl): synergize these two branches even more
if (ephemeral && decor_state.buf == buf) {
- int attr_id = hl_id > 0 ? syn_id2attr(hl_id) : 0;
- VirtText *vt_allocated = NULL;
- if (kv_size(virt_text)) {
- vt_allocated = xmalloc(sizeof *vt_allocated);
- *vt_allocated = virt_text;
- }
- decor_add_ephemeral(attr_id, (int)line, (colnr_T)col,
- (int)line2, (colnr_T)col2, priority, vt_allocated);
+ decor_add_ephemeral((int)line, (int)col, line2, col2, decor, 0);
} else {
if (ephemeral) {
api_set_error(err, kErrorTypeException, "not yet implemented");
goto error;
}
- Decoration *decor = NULL;
- if (kv_size(virt_text)) {
- decor = xcalloc(1, sizeof(*decor));
- decor->hl_id = hl_id;
- decor->virt_text = virt_text;
- } else if (hl_id) {
- decor = decor_hl(hl_id);
- decor->priority = priority;
- }
id = extmark_set(buf, (uint64_t)ns_id, id, (int)line, (colnr_T)col,
line2, col2, decor, right_gravity,
@@ -1930,7 +1968,6 @@ static void fix_cursor(linenr_T lo, linenr_T hi, linenr_T extra)
curwin->w_cursor.lnum += extra;
check_cursor_col();
} else if (extra < 0) {
- curwin->w_cursor.lnum = lo;
check_cursor();
} else {
check_cursor_col();
diff --git a/src/nvim/charset.c b/src/nvim/charset.c
index be265e3f27..5ad1fe0dfd 100644
--- a/src/nvim/charset.c
+++ b/src/nvim/charset.c
@@ -708,7 +708,7 @@ int ptr2cells(const char_u *p)
/// @return number of character cells.
int vim_strsize(char_u *s)
{
- return vim_strnsize(s, (int)MAXCOL);
+ return vim_strnsize(s, MAXCOL);
}
/// Return the number of character cells string "s[len]" will take on the
diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c
index f3ee42fab1..a1289f202a 100644
--- a/src/nvim/decoration.c
+++ b/src/nvim/decoration.c
@@ -188,20 +188,21 @@ bool decor_redraw_start(buf_T *buf, int top_row, DecorState *state)
goto next_mark;
}
- int attr_id = decor->hl_id > 0 ? syn_id2attr(decor->hl_id) : 0;
- VirtText *vt = kv_size(decor->virt_text) ? &decor->virt_text : NULL;
- HlRange range;
if (mark.id&MARKTREE_END_FLAG) {
- range = (HlRange){ altpos.row, altpos.col, mark.row, mark.col,
- attr_id, decor->priority, vt, false };
+ decor_add(state, altpos.row, altpos.col, mark.row, mark.col,
+ decor, false, 0);
} else {
- range = (HlRange){ mark.row, mark.col, altpos.row,
- altpos.col, attr_id, decor->priority, vt, false };
+ if (altpos.row == -1) {
+ altpos.row = mark.row;
+ altpos.col = mark.col;
+ }
+ decor_add(state, mark.row, mark.col, altpos.row, altpos.col,
+ decor, false, 0);
}
- hlrange_activate(range, state);
next_mark:
if (marktree_itr_node_done(state->itr)) {
+ marktree_itr_next(buf->b_marktree, state->itr);
break;
}
marktree_itr_next(buf->b_marktree, state->itr);
@@ -220,41 +221,39 @@ bool decor_redraw_line(buf_T *buf, int row, DecorState *state)
return true; // TODO(bfredl): be more precise
}
-static void hlrange_activate(HlRange range, DecorState *state)
+static void decor_add(DecorState *state, int start_row, int start_col,
+ int end_row, int end_col, Decoration *decor, bool owned,
+ DecorPriority priority)
{
- // Get size before preparing the push, to have the number of elements
- size_t s = kv_size(state->active);
-
- kv_pushp(state->active);
+ int attr_id = decor->hl_id > 0 ? syn_id2attr(decor->hl_id) : 0;
- size_t dest_index = 0;
+ HlRange range = { start_row, start_col, end_row, end_col,
+ attr_id, MAX(priority, decor->priority),
+ kv_size(decor->virt_text) ? &decor->virt_text : NULL,
+ decor->virt_text_pos,
+ kv_size(decor->virt_text) && owned, -1 };
- // Determine insertion dest_index
- while (dest_index < s) {
- HlRange item = kv_A(state->active, dest_index);
- if (item.priority > range.priority) {
+ kv_pushp(state->active);
+ size_t index;
+ for (index = kv_size(state->active)-1; index > 0; index--) {
+ HlRange item = kv_A(state->active, index-1);
+ if (item.priority <= range.priority) {
break;
}
-
- dest_index++;
- }
-
- // Splice
- for (size_t index = s; index > dest_index; index--) {
kv_A(state->active, index) = kv_A(state->active, index-1);
}
-
- // Insert
- kv_A(state->active, dest_index) = range;
+ kv_A(state->active, index) = range;
}
-int decor_redraw_col(buf_T *buf, int col, DecorState *state)
+int decor_redraw_col(buf_T *buf, int col, int virt_col, DecorState *state)
{
if (col <= state->col_until) {
return state->current;
}
state->col_until = MAXCOL;
while (true) {
+ // TODO(bfredl): check duplicate entry in "intersection"
+ // branch
mtmark_t mark = marktree_itr_current(state->itr);
if (mark.row < 0 || mark.row > state->row) {
break;
@@ -278,6 +277,11 @@ int decor_redraw_col(buf_T *buf, int col, DecorState *state)
}
Decoration *decor = item->decor;
+ if (endpos.row == -1) {
+ endpos.row = mark.row;
+ endpos.col = mark.col;
+ }
+
if (endpos.row < mark.row
|| (endpos.row == mark.row && endpos.col <= mark.col)) {
if (!kv_size(decor->virt_text)) {
@@ -285,12 +289,8 @@ int decor_redraw_col(buf_T *buf, int col, DecorState *state)
}
}
- int attr_id = decor->hl_id > 0 ? syn_id2attr(decor->hl_id) : 0;
- VirtText *vt = kv_size(decor->virt_text) ? &decor->virt_text : NULL;
- hlrange_activate((HlRange){ mark.row, mark.col,
- endpos.row, endpos.col,
- attr_id, decor->priority,
- vt, false }, state);
+ decor_add(state, mark.row, mark.col, endpos.row, endpos.col,
+ decor, false, 0);
next_mark:
marktree_itr_next(buf->b_marktree, state->itr);
@@ -310,7 +310,7 @@ next_mark:
if (item.start_row < state->row
|| (item.start_row == state->row && item.start_col <= col)) {
active = true;
- if (item.end_row == state->row) {
+ if (item.end_row == state->row && item.end_col > col) {
state->col_until = MIN(state->col_until, item.end_col-1);
}
} else {
@@ -322,8 +322,12 @@ next_mark:
if (active && item.attr_id > 0) {
attr = hl_combine_attr(attr, item.attr_id);
}
+ if ((item.start_row == state->row && item.start_col <= col)
+ && item.virt_text && item.virt_col == -1) {
+ item.virt_col = virt_col;
+ }
if (keep) {
- kv_A(state->active, j++) = kv_A(state->active, i);
+ kv_A(state->active, j++) = item;
} else if (item.virt_text_owned) {
clear_virttext(item.virt_text);
xfree(item.virt_text);
@@ -341,21 +345,20 @@ void decor_redraw_end(DecorState *state)
VirtText *decor_redraw_virt_text(buf_T *buf, DecorState *state)
{
- decor_redraw_col(buf, MAXCOL, state);
+ decor_redraw_col(buf, MAXCOL, MAXCOL, state);
for (size_t i = 0; i < kv_size(state->active); i++) {
HlRange item = kv_A(state->active, i);
- if (item.start_row == state->row && item.virt_text) {
+ if (item.start_row == state->row && item.virt_text
+ && item.virt_text_pos == kVTEndOfLine) {
return item.virt_text;
}
}
return NULL;
}
-void decor_add_ephemeral(int attr_id, int start_row, int start_col,
- int end_row, int end_col, DecorPriority priority,
- VirtText *virt_text)
+void decor_add_ephemeral(int start_row, int start_col, int end_row, int end_col,
+ Decoration *decor, DecorPriority priority)
{
-hlrange_activate(((HlRange){ start_row, start_col, end_row, end_col, attr_id,
- priority, virt_text, virt_text != NULL }),
- &decor_state);
+ decor_add(&decor_state, start_row, start_col, end_row, end_col, decor, true,
+ priority);
}
diff --git a/src/nvim/decoration.h b/src/nvim/decoration.h
index 2533a641dd..47bd9abbc3 100644
--- a/src/nvim/decoration.h
+++ b/src/nvim/decoration.h
@@ -18,10 +18,16 @@ typedef kvec_t(VirtTextChunk) VirtText;
typedef uint16_t DecorPriority;
#define DECOR_PRIORITY_BASE 0x1000
+typedef enum {
+ kVTEndOfLine,
+ kVTOverlay,
+} VirtTextPos;
+
struct Decoration
{
int hl_id; // highlight group
VirtText virt_text;
+ VirtTextPos virt_text_pos;
// TODO(bfredl): style, signs, etc
DecorPriority priority;
bool shared; // shared decoration, don't free
@@ -35,7 +41,9 @@ typedef struct {
int attr_id;
DecorPriority priority;
VirtText *virt_text;
+ VirtTextPos virt_text_pos;
bool virt_text_owned;
+ int virt_col;
} HlRange;
typedef struct {
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 100e88e261..53717229f6 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -1627,11 +1627,11 @@ static void init_prompt(int cmdchar_todo)
ml_append(curbuf->b_ml.ml_line_count, prompt, 0, false);
}
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
- coladvance((colnr_T)MAXCOL);
+ coladvance(MAXCOL);
changed_bytes(curbuf->b_ml.ml_line_count, 0);
}
if (cmdchar_todo == 'A') {
- coladvance((colnr_T)MAXCOL);
+ coladvance(MAXCOL);
}
if (cmdchar_todo == 'I' || curwin->w_cursor.col <= (int)STRLEN(prompt)) {
curwin->w_cursor.col = STRLEN(prompt);
@@ -6246,9 +6246,10 @@ void auto_format(
if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) {
// "cannot happen"
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
- coladvance((colnr_T)MAXCOL);
- } else
+ coladvance(MAXCOL);
+ } else {
check_cursor_col();
+ }
// Insert mode: If the cursor is now after the end of the line while it
// previously wasn't, the line was broken. Because of the rule above we
@@ -8432,8 +8433,8 @@ static void ins_left(void)
// if 'whichwrap' set for cursor in insert mode may go to previous line.
// always break undo when moving upwards/downwards, else undo may break
start_arrow(&tpos);
- --(curwin->w_cursor.lnum);
- coladvance((colnr_T)MAXCOL);
+ curwin->w_cursor.lnum--;
+ coladvance(MAXCOL);
curwin->w_set_curswant = true; // so we stay at the end
} else {
vim_beep(BO_CRSR);
@@ -8467,7 +8468,7 @@ static void ins_end(int c)
tpos = curwin->w_cursor;
if (c == K_C_END)
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
- coladvance((colnr_T)MAXCOL);
+ coladvance(MAXCOL);
curwin->w_curswant = MAXCOL;
start_arrow(&tpos);
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index d07618d2c0..6d97310c1c 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -176,7 +176,6 @@ static struct vimvar {
VV(VV_DYING, "dying", VAR_NUMBER, VV_RO),
VV(VV_EXCEPTION, "exception", VAR_STRING, VV_RO),
VV(VV_THROWPOINT, "throwpoint", VAR_STRING, VV_RO),
- VV(VV_STDERR, "stderr", VAR_NUMBER, VV_RO),
VV(VV_REG, "register", VAR_STRING, VV_RO),
VV(VV_CMDBANG, "cmdbang", VAR_NUMBER, VV_RO),
VV(VV_INSERTMODE, "insertmode", VAR_STRING, VV_RO),
@@ -211,13 +210,9 @@ static struct vimvar {
VV(VV_OPTION_OLD, "option_old", VAR_STRING, VV_RO),
VV(VV_OPTION_TYPE, "option_type", VAR_STRING, VV_RO),
VV(VV_ERRORS, "errors", VAR_LIST, 0),
- VV(VV_MSGPACK_TYPES, "msgpack_types", VAR_DICT, VV_RO),
- VV(VV_EVENT, "event", VAR_DICT, VV_RO),
VV(VV_FALSE, "false", VAR_BOOL, VV_RO),
VV(VV_TRUE, "true", VAR_BOOL, VV_RO),
VV(VV_NULL, "null", VAR_SPECIAL, VV_RO),
- VV(VV__NULL_LIST, "_null_list", VAR_LIST, VV_RO),
- VV(VV__NULL_DICT, "_null_dict", VAR_DICT, VV_RO),
VV(VV_VIM_DID_ENTER, "vim_did_enter", VAR_NUMBER, VV_RO),
VV(VV_TESTING, "testing", VAR_NUMBER, 0),
VV(VV_TYPE_NUMBER, "t_number", VAR_NUMBER, VV_RO),
@@ -227,10 +222,16 @@ static struct vimvar {
VV(VV_TYPE_DICT, "t_dict", VAR_NUMBER, VV_RO),
VV(VV_TYPE_FLOAT, "t_float", VAR_NUMBER, VV_RO),
VV(VV_TYPE_BOOL, "t_bool", VAR_NUMBER, VV_RO),
+ VV(VV_EVENT, "event", VAR_DICT, VV_RO),
VV(VV_ECHOSPACE, "echospace", VAR_NUMBER, VV_RO),
+ VV(VV_ARGV, "argv", VAR_LIST, VV_RO),
VV(VV_EXITING, "exiting", VAR_NUMBER, VV_RO),
+ // Neovim
+ VV(VV_STDERR, "stderr", VAR_NUMBER, VV_RO),
+ VV(VV_MSGPACK_TYPES, "msgpack_types", VAR_DICT, VV_RO),
+ VV(VV__NULL_LIST, "_null_list", VAR_LIST, VV_RO),
+ VV(VV__NULL_DICT, "_null_dict", VAR_DICT, VV_RO),
VV(VV_LUA, "lua", VAR_PARTIAL, VV_RO),
- VV(VV_ARGV, "argv", VAR_LIST, VV_RO),
};
#undef VV
diff --git a/src/nvim/eval.h b/src/nvim/eval.h
index c1891758ea..4f03d5d259 100644
--- a/src/nvim/eval.h
+++ b/src/nvim/eval.h
@@ -105,7 +105,6 @@ typedef enum {
VV_DYING,
VV_EXCEPTION,
VV_THROWPOINT,
- VV_STDERR,
VV_REG,
VV_CMDBANG,
VV_INSERTMODE,
@@ -140,13 +139,9 @@ typedef enum {
VV_OPTION_OLD,
VV_OPTION_TYPE,
VV_ERRORS,
- VV_MSGPACK_TYPES,
- VV_EVENT,
VV_FALSE,
VV_TRUE,
VV_NULL,
- VV__NULL_LIST, // List with NULL value. For test purposes only.
- VV__NULL_DICT, // Dictionary with NULL value. For test purposes only.
VV_VIM_DID_ENTER,
VV_TESTING,
VV_TYPE_NUMBER,
@@ -156,10 +151,16 @@ typedef enum {
VV_TYPE_DICT,
VV_TYPE_FLOAT,
VV_TYPE_BOOL,
+ VV_EVENT,
VV_ECHOSPACE,
+ VV_ARGV,
VV_EXITING,
+ // Neovim
+ VV_STDERR,
+ VV_MSGPACK_TYPES,
+ VV__NULL_LIST, // List with NULL value. For test purposes only.
+ VV__NULL_DICT, // Dictionary with NULL value. For test purposes only.
VV_LUA,
- VV_ARGV,
} VimVarIndex;
/// All recognized msgpack types
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index 952fa35b83..eac0feafcf 100644
--- a/src/nvim/eval.lua
+++ b/src/nvim/eval.lua
@@ -63,6 +63,7 @@ return {
chanclose={args={1, 2}},
chansend={args=2},
char2nr={args={1, 2}},
+ charidx={args={2, 3}},
cindent={args=1},
clearmatches={args={0, 1}},
col={args=1},
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index d54e49bbd4..8c8e0d568b 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -940,6 +940,52 @@ static void f_char2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
(const char_u *)tv_get_string(&argvars[0]));
}
+// "charidx()" function
+static void f_charidx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+{
+ rettv->vval.v_number = -1;
+
+ if (argvars[0].v_type != VAR_STRING
+ || argvars[1].v_type != VAR_NUMBER
+ || (argvars[2].v_type != VAR_UNKNOWN
+ && argvars[2].v_type != VAR_NUMBER)) {
+ EMSG(_(e_invarg));
+ return;
+ }
+
+ const char *str = tv_get_string_chk(&argvars[0]);
+ varnumber_T idx = tv_get_number_chk(&argvars[1], NULL);
+ if (str == NULL || idx < 0) {
+ return;
+ }
+ int countcc = 0;
+ if (argvars[2].v_type != VAR_UNKNOWN) {
+ countcc = (int)tv_get_number(&argvars[2]);
+ }
+ if (countcc < 0 || countcc > 1) {
+ EMSG(_(e_invarg));
+ return;
+ }
+
+ int (*ptr2len)(const char_u *);
+ if (countcc) {
+ ptr2len = utf_ptr2len;
+ } else {
+ ptr2len = utfc_ptr2len;
+ }
+
+ const char *p;
+ int len;
+ for (p = str, len = 0; p <= str + idx; len++) {
+ if (*p == NUL) {
+ return;
+ }
+ p += ptr2len((const char_u *)p);
+ }
+
+ rettv->vval.v_number = len > 0 ? len - 1 : 0;
+}
+
/*
* "cindent(lnum)" function
*/
@@ -4085,7 +4131,9 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr)
#ifdef _WIN64
"win64",
#endif
+#ifndef CASE_INSENSITIVE_FILENAME
"fname_case",
+#endif
#ifdef HAVE_ACL
"acl",
#endif
diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h
index d8ede1e3ba..6fcb01aace 100644
--- a/src/nvim/eval/typval.h
+++ b/src/nvim/eval/typval.h
@@ -315,6 +315,7 @@ struct ufunc {
int uf_calls; ///< nr of active calls
bool uf_cleared; ///< func_clear() was already called
garray_T uf_args; ///< arguments
+ garray_T uf_def_args; ///< default argument expressions
garray_T uf_lines; ///< function lines
int uf_profiling; ///< true when func is being profiled
int uf_prof_initialized;
diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c
index 70c998ef39..689d05e079 100644
--- a/src/nvim/eval/userfunc.c
+++ b/src/nvim/eval/userfunc.c
@@ -67,7 +67,7 @@ void func_init(void)
/// Get function arguments.
static int get_function_args(char_u **argp, char_u endchar, garray_T *newargs,
- int *varargs, bool skip)
+ int *varargs, garray_T *default_args, bool skip)
{
bool mustend = false;
char_u *arg = *argp;
@@ -78,12 +78,16 @@ static int get_function_args(char_u **argp, char_u endchar, garray_T *newargs,
if (newargs != NULL) {
ga_init(newargs, (int)sizeof(char_u *), 3);
}
+ if (default_args != NULL) {
+ ga_init(default_args, (int)sizeof(char_u *), 3);
+ }
if (varargs != NULL) {
*varargs = false;
}
// Isolate the arguments: "arg1, arg2, ...)"
+ bool any_default = false;
while (*p != endchar) {
if (p[0] == '.' && p[1] == '.' && p[2] == '.') {
if (varargs != NULL) {
@@ -123,6 +127,38 @@ static int get_function_args(char_u **argp, char_u endchar, garray_T *newargs,
*p = c;
}
+ if (*skipwhite(p) == '=' && default_args != NULL) {
+ typval_T rettv;
+
+ any_default = true;
+ p = skipwhite(p) + 1;
+ p = skipwhite(p);
+ char_u *expr = p;
+ if (eval1(&p, &rettv, false) != FAIL) {
+ ga_grow(default_args, 1);
+
+ // trim trailing whitespace
+ while (p > expr && ascii_iswhite(p[-1])) {
+ p--;
+ }
+ c = *p;
+ *p = NUL;
+ expr = vim_strsave(expr);
+ if (expr == NULL) {
+ *p = c;
+ goto err_ret;
+ }
+ ((char_u **)(default_args->ga_data))
+ [default_args->ga_len] = expr;
+ default_args->ga_len++;
+ *p = c;
+ } else {
+ mustend = true;
+ }
+ } else if (any_default) {
+ EMSG(_("E989: Non-default argument follows default argument"));
+ mustend = true;
+ }
if (*p == ',') {
p++;
} else {
@@ -149,6 +185,9 @@ err_ret:
if (newargs != NULL) {
ga_clear_strings(newargs);
}
+ if (default_args != NULL) {
+ ga_clear_strings(default_args);
+ }
return FAIL;
}
@@ -195,7 +234,7 @@ int get_lambda_tv(char_u **arg, typval_T *rettv, bool evaluate)
bool eval_lavars = false;
// First, check if this is a lambda expression. "->" must exists.
- ret = get_function_args(&start, '-', NULL, NULL, true);
+ ret = get_function_args(&start, '-', NULL, NULL, NULL, true);
if (ret == FAIL || *start != '>') {
return NOTDONE;
}
@@ -207,7 +246,7 @@ int get_lambda_tv(char_u **arg, typval_T *rettv, bool evaluate)
pnewargs = NULL;
}
*arg = skipwhite(*arg + 1);
- ret = get_function_args(arg, '-', pnewargs, &varargs, false);
+ ret = get_function_args(arg, '-', pnewargs, &varargs, NULL, false);
if (ret == FAIL || **arg != '>') {
goto errret;
}
@@ -259,6 +298,7 @@ int get_lambda_tv(char_u **arg, typval_T *rettv, bool evaluate)
STRCPY(fp->uf_name, name);
hash_add(&func_hashtab, UF2HIKEY(fp));
fp->uf_args = newargs;
+ ga_init(&fp->uf_def_args, (int)sizeof(char_u *), 1);
fp->uf_lines = newlines;
if (current_funccal != NULL && eval_lavars) {
flags |= FC_CLOSURE;
@@ -715,6 +755,7 @@ static bool func_remove(ufunc_T *fp)
static void func_clear_items(ufunc_T *fp)
{
ga_clear_strings(&(fp->uf_args));
+ ga_clear_strings(&(fp->uf_def_args));
ga_clear_strings(&(fp->uf_lines));
if (fp->uf_cb_free != NULL) {
@@ -857,12 +898,13 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars,
}
// Init a: variables, unless none found (in lambda).
- // Set a:0 to "argcount".
+ // Set a:0 to "argcount" less number of named arguments, if >= 0.
// Set a:000 to a list with room for the "..." arguments.
init_var_dict(&fc->l_avars, &fc->l_avars_var, VAR_SCOPE);
if ((fp->uf_flags & FC_NOARGS) == 0) {
add_nr_var(&fc->l_avars, (dictitem_T *)&fc->fixvar[fixvar_idx++], "0",
- (varnumber_T)(argcount - fp->uf_args.ga_len));
+ (varnumber_T)(argcount >= fp->uf_args.ga_len
+ ? argcount - fp->uf_args.ga_len : 0));
}
fc->l_avars.dv_lock = VAR_FIXED;
if ((fp->uf_flags & FC_NOARGS) == 0) {
@@ -892,8 +934,11 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars,
add_nr_var(&fc->l_avars, (dictitem_T *)&fc->fixvar[fixvar_idx++],
"lastline", (varnumber_T)lastline);
}
- for (int i = 0; i < argcount; i++) {
+ bool default_arg_err = false;
+ for (int i = 0; i < argcount || i < fp->uf_args.ga_len; i++) {
bool addlocal = false;
+ bool isdefault = false;
+ typval_T def_rettv;
ai = i - fp->uf_args.ga_len;
if (ai < 0) {
@@ -902,6 +947,21 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars,
if (islambda) {
addlocal = true;
}
+
+ // evaluate named argument default expression
+ isdefault = ai + fp->uf_def_args.ga_len >= 0 && i >= argcount;
+ if (isdefault) {
+ char_u *default_expr = NULL;
+ def_rettv.v_type = VAR_NUMBER;
+ def_rettv.vval.v_number = -1;
+
+ default_expr = ((char_u **)(fp->uf_def_args.ga_data))
+ [ai + fp->uf_def_args.ga_len];
+ if (eval1(&default_expr, &def_rettv, true) == FAIL) {
+ default_arg_err = true;
+ break;
+ }
+ }
} else {
if ((fp->uf_flags & FC_NOARGS) != 0) {
// Bail out if no a: arguments used (in lambda).
@@ -922,7 +982,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars,
// Note: the values are copied directly to avoid alloc/free.
// "argvars" must have VAR_FIXED for v_lock.
- v->di_tv = argvars[i];
+ v->di_tv = isdefault ? def_rettv : argvars[i];
v->di_tv.v_lock = VAR_FIXED;
if (addlocal) {
@@ -1046,7 +1106,9 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars,
save_did_emsg = did_emsg;
did_emsg = FALSE;
- if (islambda) {
+ if (default_arg_err && (fp->uf_flags & FC_ABORT)) {
+ did_emsg = true;
+ } else if (islambda) {
char_u *p = *(char_u **)fp->uf_lines.ga_data + 7;
// A Lambda always has the command "return {expr}". It is much faster
@@ -1490,7 +1552,7 @@ call_func(
if (fp->uf_flags & FC_RANGE) {
*doesrange = true;
}
- if (argcount < fp->uf_args.ga_len) {
+ if (argcount < fp->uf_args.ga_len - fp->uf_def_args.ga_len) {
error = ERROR_TOOFEW;
} else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len) {
error = ERROR_TOOMANY;
@@ -1573,6 +1635,11 @@ static void list_func_head(ufunc_T *fp, int indent, bool force)
msg_puts(", ");
}
msg_puts((const char *)FUNCARG(fp, j));
+ if (j >= fp->uf_args.ga_len - fp->uf_def_args.ga_len) {
+ msg_puts(" = ");
+ msg_puts(((char **)(fp->uf_def_args.ga_data))
+ [j - fp->uf_args.ga_len + fp->uf_def_args.ga_len]);
+ }
}
if (fp->uf_varargs) {
if (j) {
@@ -1836,6 +1903,7 @@ void ex_function(exarg_T *eap)
char_u *arg;
char_u *line_arg = NULL;
garray_T newargs;
+ garray_T default_args;
garray_T newlines;
int varargs = false;
int flags = 0;
@@ -2039,7 +2107,8 @@ void ex_function(exarg_T *eap)
}
}
- if (get_function_args(&p, ')', &newargs, &varargs, eap->skip) == FAIL) {
+ if (get_function_args(&p, ')', &newargs, &varargs,
+ &default_args, eap->skip) == FAIL) {
goto errret_2;
}
@@ -2458,6 +2527,7 @@ void ex_function(exarg_T *eap)
fp->uf_refcount = 1;
}
fp->uf_args = newargs;
+ fp->uf_def_args = default_args;
fp->uf_lines = newlines;
if ((flags & FC_CLOSURE) != 0) {
register_closure(fp);
@@ -2480,6 +2550,7 @@ void ex_function(exarg_T *eap)
erret:
ga_clear_strings(&newargs);
+ ga_clear_strings(&default_args);
errret_2:
ga_clear_strings(&newlines);
ret_free:
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index b220b034dd..103c081143 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -4198,7 +4198,7 @@ skip:
// when interactive leave cursor on the match
if (!subflags.do_ask) {
if (endcolumn) {
- coladvance((colnr_T)MAXCOL);
+ coladvance(MAXCOL);
} else {
beginline(BL_WHITE | BL_FIX);
}
@@ -5020,7 +5020,7 @@ int find_help_tags(const char_u *arg, int *num_matches, char_u ***matches,
if (keep_lang) {
flags |= TAG_KEEP_LANG;
}
- if (find_tags(IObuff, num_matches, matches, flags, (int)MAXCOL, NULL) == OK
+ if (find_tags(IObuff, num_matches, matches, flags, MAXCOL, NULL) == OK
&& *num_matches > 0) {
/* Sort the matches found on the heuristic number that is after the
* tag name. */
diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua
index 10dd7d68ca..2965ea7496 100644
--- a/src/nvim/ex_cmds.lua
+++ b/src/nvim/ex_cmds.lua
@@ -2521,8 +2521,8 @@ module.cmds = {
},
{
command='source',
- flags=bit.bor(BANG, FILE1, TRLBAR, SBOXOK, CMDWIN),
- addr_type='ADDR_NONE',
+ flags=bit.bor(RANGE, DFLALL, WHOLEFOLD, BANG, FILE1, TRLBAR, SBOXOK, CMDWIN),
+ addr_type='ADDR_LINES',
func='ex_source',
},
{
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index bb53f4d373..c4c18c4324 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -29,6 +29,7 @@
#include "nvim/getchar.h"
#include "nvim/mark.h"
#include "nvim/mbyte.h"
+#include "nvim/memline.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
#include "nvim/garray.h"
@@ -2526,7 +2527,7 @@ void ex_pyxdo(exarg_T *eap)
}
}
-/// ":source {fname}"
+/// ":source [{fname}]"
void ex_source(exarg_T *eap)
{
cmd_source(eap->arg, eap);
@@ -2535,7 +2536,7 @@ void ex_source(exarg_T *eap)
static void cmd_source(char_u *fname, exarg_T *eap)
{
if (*fname == NUL) {
- EMSG(_(e_argreq));
+ cmd_source_buffer(eap);
} else if (eap != NULL && eap->forceit) {
// ":source!": read Normal mode commands
// Need to execute the commands directly. This is required at least
@@ -2553,6 +2554,37 @@ static void cmd_source(char_u *fname, exarg_T *eap)
}
}
+typedef struct {
+ linenr_T curr_lnum;
+ const linenr_T final_lnum;
+} GetBufferLineCookie;
+
+/// Get one line from the current selection in the buffer.
+/// Called by do_cmdline() when it's called from cmd_source_buffer().
+///
+/// @return pointer to allocated line, or NULL for end-of-file or
+/// some error.
+static char_u *get_buffer_line(int c, void *cookie, int indent, bool do_concat)
+{
+ GetBufferLineCookie *p = cookie;
+ if (p->curr_lnum > p->final_lnum) {
+ return NULL;
+ }
+ char_u *curr_line = ml_get(p->curr_lnum);
+ p->curr_lnum++;
+ return (char_u *)xstrdup((const char *)curr_line);
+}
+
+static void cmd_source_buffer(exarg_T *eap)
+{
+ GetBufferLineCookie cookie = {
+ .curr_lnum = eap->line1,
+ .final_lnum = eap->line2,
+ };
+ source_using_linegetter((void *)&cookie, get_buffer_line,
+ ":source (no file)");
+}
+
/// ":source" and associated commands.
///
/// @return address holding the next breakpoint line for a source cookie
@@ -2624,10 +2656,9 @@ static char_u *get_str_line(int c, void *cookie, int indent, bool do_concat)
return (char_u *)xstrdup(buf);
}
-/// Executes lines in `src` as Ex commands.
-///
-/// @see do_source()
-int do_source_str(const char *cmd, const char *traceback_name)
+static int source_using_linegetter(void *cookie,
+ LineGetter fgetline,
+ const char *traceback_name)
{
char_u *save_sourcing_name = sourcing_name;
linenr_T save_sourcing_lnum = sourcing_lnum;
@@ -2642,22 +2673,33 @@ int do_source_str(const char *cmd, const char *traceback_name)
}
sourcing_lnum = 0;
- GetStrLineCookie cookie = {
- .buf = (char_u *)cmd,
- .offset = 0,
- };
const sctx_T save_current_sctx = current_sctx;
current_sctx.sc_sid = SID_STR;
current_sctx.sc_seq = 0;
current_sctx.sc_lnum = save_sourcing_lnum;
- int retval = do_cmdline(NULL, get_str_line, (void *)&cookie,
+ funccal_entry_T entry;
+ save_funccal(&entry);
+ int retval = do_cmdline(NULL, fgetline, cookie,
DOCMD_VERBOSE | DOCMD_NOWAIT | DOCMD_REPEAT);
- current_sctx = save_current_sctx;
sourcing_lnum = save_sourcing_lnum;
sourcing_name = save_sourcing_name;
+ current_sctx = save_current_sctx;
+ restore_funccal();
return retval;
}
+/// Executes lines in `src` as Ex commands.
+///
+/// @see do_source()
+int do_source_str(const char *cmd, const char *traceback_name)
+{
+ GetStrLineCookie cookie = {
+ .buf = (char_u *)cmd,
+ .offset = 0,
+ };
+ return source_using_linegetter((void *)&cookie, get_str_line, traceback_name);
+}
+
/// Reads the file `fname` and executes its lines as Ex commands.
///
/// This function may be called recursively!
@@ -2982,6 +3024,7 @@ void scriptnames_slash_adjust(void)
# endif
/// Get a pointer to a script name. Used for ":verbose set".
+/// Message appended to "Last set from "
char_u *get_scriptname(LastSet last_set, bool *should_free)
{
*should_free = false;
@@ -2997,6 +3040,8 @@ char_u *get_scriptname(LastSet last_set, bool *should_free)
return (char_u *)_("environment variable");
case SID_ERROR:
return (char_u *)_("error handler");
+ case SID_WINLAYOUT:
+ return (char_u *)_("changed window size");
case SID_LUA:
return (char_u *)_("Lua");
case SID_API_CLIENT:
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index c66ae13f53..d470bfb418 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -6774,6 +6774,6 @@ static void set_search_match(pos_T *t)
t->col = search_match_endcol;
if (t->lnum > curbuf->b_ml.ml_line_count) {
t->lnum = curbuf->b_ml.ml_line_count;
- coladvance((colnr_T)MAXCOL);
+ coladvance(MAXCOL);
}
}
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 22f06941aa..7b8e809de7 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -180,6 +180,11 @@ EXTERN int compl_cont_status INIT(= 0);
# define CONT_LOCAL 32 // for ctrl_x_mode 0, ^X^P/^X^N do a local
// expansion, (eg use complete=.)
+EXTERN char_u *edit_submode INIT(= NULL); // msg for CTRL-X submode
+EXTERN char_u *edit_submode_pre INIT(= NULL); // prepended to edit_submode
+EXTERN char_u *edit_submode_extra INIT(= NULL); // appended to edit_submode
+EXTERN hlf_T edit_submode_highl; // highl. method for extra info
+
// state for putting characters in the message area
EXTERN int cmdmsg_rl INIT(= false); // cmdline is drawn right to left
EXTERN int msg_col;
@@ -328,9 +333,10 @@ EXTERN int garbage_collect_at_exit INIT(= false);
#define SID_ENV -4 // for sourcing environment variable
#define SID_ERROR -5 // option was reset because of an error
#define SID_NONE -6 // don't set scriptID
-#define SID_LUA -7 // for Lua scripts/chunks
-#define SID_API_CLIENT -8 // for API clients
-#define SID_STR -9 // for sourcing a string
+#define SID_WINLAYOUT -7 // changing window size
+#define SID_LUA -8 // for Lua scripts/chunks
+#define SID_API_CLIENT -9 // for API clients
+#define SID_STR -10 // for sourcing a string
// Script CTX being sourced or was sourced to define the current function.
EXTERN sctx_T current_sctx INIT(= { 0 COMMA 0 COMMA 0 });
@@ -639,10 +645,6 @@ EXTERN int arrow_used; // Normally false, set to true after
// to call u_sync()
EXTERN bool ins_at_eol INIT(= false); // put cursor after eol when
// restarting edit after CTRL-O
-EXTERN char_u *edit_submode INIT(= NULL); // msg for CTRL-X submode
-EXTERN char_u *edit_submode_pre INIT(= NULL); // prepended to edit_submode
-EXTERN char_u *edit_submode_extra INIT(= NULL); // appended to edit_submode
-EXTERN hlf_T edit_submode_highl; // highl. method for extra info
EXTERN int no_abbr INIT(= true); // true when no abbreviations loaded
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index 31dc6b3649..293a4d01db 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -4142,7 +4142,7 @@ void goto_byte(long cnt)
if (lnum < 1) { // past the end
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
curwin->w_curswant = MAXCOL;
- coladvance((colnr_T)MAXCOL);
+ coladvance(MAXCOL);
} else {
curwin->w_cursor.lnum = lnum;
curwin->w_cursor.col = (colnr_T)boff;
diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c
index fcffe64595..34c43da0f7 100644
--- a/src/nvim/misc1.c
+++ b/src/nvim/misc1.c
@@ -412,7 +412,7 @@ int plines_win_nofold(win_T *wp, linenr_T lnum)
s = ml_get_buf(wp->w_buffer, lnum, FALSE);
if (*s == NUL) /* empty line */
return 1;
- col = win_linetabsize(wp, s, (colnr_T)MAXCOL);
+ col = win_linetabsize(wp, s, MAXCOL);
// If list mode is on, then the '$' at the end of the line may take up one
// extra column.
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 8f22243348..d5c92bc3e6 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -5225,16 +5225,13 @@ static void nv_left(cmdarg_T *cap)
* 'h' wraps to previous line if 'whichwrap' has 'h'.
* CURS_LEFT wraps to previous line if 'whichwrap' has '<'.
*/
- if ( (((cap->cmdchar == K_BS
- || cap->cmdchar == Ctrl_H)
- && vim_strchr(p_ww, 'b') != NULL)
- || (cap->cmdchar == 'h'
- && vim_strchr(p_ww, 'h') != NULL)
- || (cap->cmdchar == K_LEFT
- && vim_strchr(p_ww, '<') != NULL))
- && curwin->w_cursor.lnum > 1) {
- --(curwin->w_cursor.lnum);
- coladvance((colnr_T)MAXCOL);
+ if ((((cap->cmdchar == K_BS || cap->cmdchar == Ctrl_H)
+ && vim_strchr(p_ww, 'b') != NULL)
+ || (cap->cmdchar == 'h' && vim_strchr(p_ww, 'h') != NULL)
+ || (cap->cmdchar == K_LEFT && vim_strchr(p_ww, '<') != NULL))
+ && curwin->w_cursor.lnum > 1) {
+ curwin->w_cursor.lnum--;
+ coladvance(MAXCOL);
curwin->w_set_curswant = true;
// When the NL before the first char has to be deleted we
@@ -5792,16 +5789,20 @@ static void nv_percent(cmdarg_T *cap)
} else {
cap->oap->motion_type = kMTLineWise;
setpcmark();
- /* Round up, so CTRL-G will give same value. Watch out for a
- * large line count, the line number must not go negative! */
- if (curbuf->b_ml.ml_line_count > 1000000)
+ // Round up, so 'normal 100%' always jumps at the line line.
+ // Beyond 21474836 lines, (ml_line_count * 100 + 99) would
+ // overflow on 32-bits, so use a formula with less accuracy
+ // to avoid overflows.
+ if (curbuf->b_ml.ml_line_count >= 21474836) {
curwin->w_cursor.lnum = (curbuf->b_ml.ml_line_count + 99L)
/ 100L * cap->count0;
- else
+ } else {
curwin->w_cursor.lnum = (curbuf->b_ml.ml_line_count *
cap->count0 + 99L) / 100L;
- if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
+ }
+ if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) {
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
+ }
beginline(BL_SOL | BL_FIX);
}
} else { // "%" : go to matching paren
@@ -6467,7 +6468,7 @@ static void nv_visual(cmdarg_T *cap)
}
if (resel_VIsual_vcol == MAXCOL) {
curwin->w_curswant = MAXCOL;
- coladvance((colnr_T)MAXCOL);
+ coladvance(MAXCOL);
} else if (VIsual_mode == Ctrl_V) {
validate_virtcol();
assert(cap->count0 >= INT_MIN && cap->count0 <= INT_MAX);
@@ -7570,6 +7571,12 @@ static void nv_esc(cmdarg_T *cap)
got_int = false; /* don't stop executing autocommands et al. */
return;
}
+ } else if (cmdwin_type != 0 && ex_normal_busy) {
+ // When :normal runs out of characters while in the command line window
+ // vgetorpeek() will return ESC. Exit the cmdline window to break the
+ // loop.
+ cmdwin_result = K_IGNORE;
+ return;
}
if (VIsual_active) {
@@ -7600,7 +7607,7 @@ void set_cursor_for_append_to_line(void)
// Pretend Insert mode here to allow the cursor on the
// character past the end of the line
State = INSERT;
- coladvance((colnr_T)MAXCOL);
+ coladvance(MAXCOL);
State = save_State;
} else {
curwin->w_cursor.col += (colnr_T)STRLEN(get_cursor_pos_ptr());
@@ -7988,7 +7995,7 @@ static void nv_put_opt(cmdarg_T *cap, bool fix_indent)
* line. */
if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) {
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
- coladvance((colnr_T)MAXCOL);
+ coladvance(MAXCOL);
}
}
auto_format(false, true);
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index ea52d6a3d3..3038fad894 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -4305,11 +4305,12 @@ format_lines(
* tabs and spaces, according to current options */
(void)set_indent(get_indent(), SIN_CHANGED);
- /* put cursor on last non-space */
- State = NORMAL; /* don't go past end-of-line */
- coladvance((colnr_T)MAXCOL);
- while (curwin->w_cursor.col && ascii_isspace(gchar_cursor()))
+ // put cursor on last non-space
+ State = NORMAL; // don't go past end-of-line
+ coladvance(MAXCOL);
+ while (curwin->w_cursor.col && ascii_isspace(gchar_cursor())) {
dec_cursor();
+ }
/* do the formatting, without 'showmode' */
State = INSERT; /* for open_line() */
diff --git a/src/nvim/path.c b/src/nvim/path.c
index 2de7e00ddb..3e1713fbdd 100644
--- a/src/nvim/path.c
+++ b/src/nvim/path.c
@@ -342,7 +342,7 @@ int path_fnamencmp(const char *const fname1, const char *const fname2,
p1 += utfc_ptr2len((const char_u *)p1);
p2 += utfc_ptr2len((const char_u *)p2);
}
- return c1 - c2;
+ return p_fic ? CH_FOLD(c1) - CH_FOLD(c2) : c1 - c2;
#else
if (p_fic) {
return mb_strnicmp((const char_u *)fname1, (const char_u *)fname2, len);
diff --git a/src/nvim/pos.h b/src/nvim/pos.h
index 8e86ea08c5..b7c4b6ef92 100644
--- a/src/nvim/pos.h
+++ b/src/nvim/pos.h
@@ -1,6 +1,9 @@
#ifndef NVIM_POS_H
#define NVIM_POS_H
+// for INT_MAX, LONG_MAX et al.
+#include <limits.h>
+
typedef long linenr_T; // line number type
/// Format used to print values which have linenr_T type
#define PRIdLINENR "ld"
@@ -12,8 +15,8 @@ typedef int colnr_T;
/// Maximal (invalid) line number
enum { MAXLNUM = 0x7fffffff };
-/// Maximal column number, 31 bits
-enum { MAXCOL = 0x7fffffff };
+/// Maximal column number
+enum { MAXCOL = INT_MAX };
// Minimum line number
enum { MINLNUM = 1 };
// minimum column number
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index c16fe46955..20e3cc0a2e 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -143,7 +143,7 @@ long tab_page_click_defs_size = 0;
// for line_putchar. Contains the state that needs to be remembered from
// putting one character to the next.
typedef struct {
- const char_u *p;
+ const char *p;
int prev_c; // previous Arabic character
int prev_c1; // first composing char for prev_c
} LineState;
@@ -1857,7 +1857,7 @@ static int compute_foldcolumn(win_T *wp, int col)
/// Handles composing chars and arabic shaping state.
static int line_putchar(LineState *s, schar_T *dest, int maxcells, bool rl)
{
- const char_u *p = s->p;
+ const char_u *p = (char_u *)s->p;
int cells = utf_ptr2cells(p);
int c_len = utfc_ptr2len(p);
int u8c, u8cc[MAX_MCO];
@@ -2870,6 +2870,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
&& vcol >= (long)wp->w_virtcol)
|| (number_only && draw_state > WL_NR))
&& filler_todo <= 0) {
+ draw_virt_text(buf, &col, grid->Columns);
grid_put_linebuf(grid, row, 0, col, -grid->Columns, wp->w_p_rl, wp,
wp->w_hl_attr_normal, false);
// Pretend we have finished updating the window. Except when
@@ -3397,7 +3398,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
}
if (has_decor && v > 0) {
- int extmark_attr = decor_redraw_col(wp->w_buffer, (colnr_T)v-1,
+ int extmark_attr = decor_redraw_col(wp->w_buffer, (colnr_T)v-1, off,
&decor_state);
if (extmark_attr != 0) {
if (!attr_pri) {
@@ -3919,7 +3920,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
int i;
size_t virt_pos = 0;
- LineState s = LINE_STATE((char_u *)"");
+ LineState s = LINE_STATE("");
int virt_attr = 0;
// Make sure alignment is the same regardless
@@ -3963,7 +3964,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
if (do_virttext && !delay_virttext) {
if (*s.p == NUL) {
if (virt_pos < virt_text.size) {
- s.p = (char_u *)kv_A(virt_text, virt_pos).text;
+ s.p = kv_A(virt_text, virt_pos).text;
int hl_id = kv_A(virt_text, virt_pos).hl_id;
virt_attr = hl_id > 0 ? syn_id2attr(hl_id) : 0;
virt_pos++;
@@ -4029,6 +4030,8 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
col += n;
}
}
+
+ draw_virt_text(buf, &col, grid->Columns);
grid_put_linebuf(grid, row, 0, col, grid->Columns, wp->w_p_rl, wp,
wp->w_hl_attr_normal, false);
row++;
@@ -4247,7 +4250,10 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
&& (grid->Columns == Columns // Window spans the width of the screen,
|| ui_has(kUIMultigrid)) // or has dedicated grid.
&& !wp->w_p_rl; // Not right-to-left.
- grid_put_linebuf(grid, row, 0, col - boguscols, grid->Columns, wp->w_p_rl,
+
+ int draw_col = col - boguscols;
+ draw_virt_text(buf, &draw_col, grid->Columns);
+ grid_put_linebuf(grid, row, 0, draw_col, grid->Columns, wp->w_p_rl,
wp, wp->w_hl_attr_normal, wrap);
if (wrap) {
ScreenGrid *current_grid = grid;
@@ -4323,6 +4329,43 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
return row;
}
+void draw_virt_text(buf_T *buf, int *end_col, int max_col)
+{
+ DecorState *state = &decor_state;
+ for (size_t i = 0; i < kv_size(state->active); i++) {
+ HlRange *item = &kv_A(state->active, i);
+ if (item->start_row == state->row && item->virt_text
+ && item->virt_text_pos == kVTOverlay
+ && item->virt_col >= 0) {
+ VirtText vt = *item->virt_text;
+ LineState s = LINE_STATE("");
+ int virt_attr = 0;
+ int col = item->virt_col;
+ size_t virt_pos = 0;
+ item->virt_col = -2; // deactivate
+
+ while (col < max_col) {
+ if (!*s.p) {
+ if (virt_pos == kv_size(vt)) {
+ break;
+ }
+ s.p = kv_A(vt, virt_pos).text;
+ int hl_id = kv_A(vt, virt_pos).hl_id;
+ virt_attr = hl_id > 0 ? syn_id2attr(hl_id) : 0;
+ virt_pos++;
+ continue;
+ }
+ int cells = line_putchar(&s, &linebuf_char[col], 2, false);
+ linebuf_attr[col++] = virt_attr;
+ if (cells > 1) {
+ linebuf_attr[col++] = virt_attr;
+ }
+ }
+ *end_col = MAX(*end_col, col);
+ }
+ }
+}
+
/// Determine if dedicated window grid should be used or the default_grid
///
/// If UI did not request multigrid support, draw all windows on the
@@ -7109,11 +7152,13 @@ static void win_redr_ruler(win_T *wp, int always)
if (wp->w_cursor.lnum > wp->w_buffer->b_ml.ml_line_count)
return;
- /* Don't draw the ruler while doing insert-completion, it might overwrite
- * the (long) mode message. */
- if (wp == lastwin && lastwin->w_status_height == 0)
- if (edit_submode != NULL)
+ // Don't draw the ruler while doing insert-completion, it might overwrite
+ // the (long) mode message.
+ if (wp == lastwin && lastwin->w_status_height == 0) {
+ if (edit_submode != NULL) {
return;
+ }
+ }
if (*p_ruf) {
int save_called_emsg = called_emsg;
diff --git a/src/nvim/search.c b/src/nvim/search.c
index 2802da6f7f..84b71d56a0 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -2685,8 +2685,9 @@ fwd_word(
while (--count >= 0) {
/* When inside a range of folded lines, move to the last char of the
* last line. */
- if (hasFolding(curwin->w_cursor.lnum, NULL, &curwin->w_cursor.lnum))
- coladvance((colnr_T)MAXCOL);
+ if (hasFolding(curwin->w_cursor.lnum, NULL, &curwin->w_cursor.lnum)) {
+ coladvance(MAXCOL);
+ }
sclass = cls();
/*
@@ -2803,8 +2804,9 @@ int end_word(long count, int bigword, int stop, int empty)
while (--count >= 0) {
/* When inside a range of folded lines, move to the last char of the
* last line. */
- if (hasFolding(curwin->w_cursor.lnum, NULL, &curwin->w_cursor.lnum))
- coladvance((colnr_T)MAXCOL);
+ if (hasFolding(curwin->w_cursor.lnum, NULL, &curwin->w_cursor.lnum)) {
+ coladvance(MAXCOL);
+ }
sclass = cls();
if (inc_cursor() == -1)
return FAIL;
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index 84ca240734..4ea298fba9 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -3152,7 +3152,7 @@ int get_tags(list_T *list, char_u *pat, char_u *buf_fname)
bool is_static;
ret = find_tags(pat, &num_matches, &matches,
- TAG_REGEXP | TAG_NOIC, (int)MAXCOL, buf_fname);
+ TAG_REGEXP | TAG_NOIC, MAXCOL, buf_fname);
if (ret == OK && num_matches > 0) {
for (i = 0; i < num_matches; ++i) {
int parse_result = parse_match(matches[i], &tp);
diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim
index 4f056abdc0..daf3c9c110 100644
--- a/src/nvim/testdir/test_alot.vim
+++ b/src/nvim/testdir/test_alot.vim
@@ -37,7 +37,6 @@ source test_recover.vim
source test_scroll_opt.vim
source test_sort.vim
source test_sha256.vim
-source test_statusline.vim
source test_suspend.vim
source test_syn_attr.vim
source test_tabline.vim
diff --git a/src/nvim/testdir/test_exit.vim b/src/nvim/testdir/test_exit.vim
index 99a401d4a4..bd3e9eb4d4 100644
--- a/src/nvim/testdir/test_exit.vim
+++ b/src/nvim/testdir/test_exit.vim
@@ -81,3 +81,32 @@ func Test_exiting()
endif
call delete('Xtestout')
endfunc
+
+" Test for getting the Vim exit code from v:exiting
+func Test_exit_code()
+ call assert_equal(v:null, v:exiting)
+
+ let before =<< trim [CODE]
+ au QuitPre * call writefile(['qp = ' .. v:exiting], 'Xtestout', 'a')
+ au ExitPre * call writefile(['ep = ' .. v:exiting], 'Xtestout', 'a')
+ au VimLeavePre * call writefile(['lp = ' .. v:exiting], 'Xtestout', 'a')
+ au VimLeave * call writefile(['l = ' .. v:exiting], 'Xtestout', 'a')
+ [CODE]
+
+ if RunVim(before, ['quit'], '')
+ call assert_equal(['qp = null', 'ep = null', 'lp = 0', 'l = 0'], readfile('Xtestout'))
+ endif
+ call delete('Xtestout')
+
+ if RunVim(before, ['cquit'], '')
+ call assert_equal(['lp = 1', 'l = 1'], readfile('Xtestout'))
+ endif
+ call delete('Xtestout')
+
+ if RunVim(before, ['cquit 4'], '')
+ call assert_equal(['lp = 4', 'l = 4'], readfile('Xtestout'))
+ endif
+ call delete('Xtestout')
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim
index f9f0ade1f6..6bc5fba5db 100644
--- a/src/nvim/testdir/test_filetype.vim
+++ b/src/nvim/testdir/test_filetype.vim
@@ -79,6 +79,7 @@ let s:filename_checks = {
\ 'bc': ['file.bc'],
\ 'bdf': ['file.bdf'],
\ 'bib': ['file.bib'],
+ \ 'beancount': ['file.beancount'],
\ 'bindzone': ['named.root'],
\ 'blank': ['file.bl'],
\ 'bsdl': ['file.bsd', 'file.bsdl'],
@@ -427,6 +428,7 @@ let s:filename_checks = {
\ 'slrnrc': ['.slrnrc'],
\ 'slrnsc': ['file.score'],
\ 'sm': ['sendmail.cf'],
+ \ 'svelte': ['file.svelte'],
\ 'smarty': ['file.tpl'],
\ 'smcl': ['file.hlp', 'file.ihlp', 'file.smcl'],
\ 'smith': ['file.smt', 'file.smith'],
diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim
index f0c1a1c7f9..5dae8d681a 100644
--- a/src/nvim/testdir/test_functions.vim
+++ b/src/nvim/testdir/test_functions.vim
@@ -833,6 +833,31 @@ func Test_byte2line_line2byte()
bw!
endfunc
+" Test for charidx()
+func Test_charidx()
+ let a = 'xáb́y'
+ call assert_equal(0, charidx(a, 0))
+ call assert_equal(1, charidx(a, 3))
+ call assert_equal(2, charidx(a, 4))
+ call assert_equal(3, charidx(a, 7))
+ call assert_equal(-1, charidx(a, 8))
+ call assert_equal(-1, charidx('', 0))
+
+ " count composing characters
+ call assert_equal(0, charidx(a, 0, 1))
+ call assert_equal(2, charidx(a, 2, 1))
+ call assert_equal(3, charidx(a, 4, 1))
+ call assert_equal(5, charidx(a, 7, 1))
+ call assert_equal(-1, charidx(a, 8, 1))
+ call assert_equal(-1, charidx('', 0, 1))
+
+ call assert_fails('let x = charidx([], 1)', 'E474:')
+ call assert_fails('let x = charidx("abc", [])', 'E474:')
+ call assert_fails('let x = charidx("abc", 1, [])', 'E474:')
+ call assert_fails('let x = charidx("abc", 1, -1)', 'E474:')
+ call assert_fails('let x = charidx("abc", 1, 2)', 'E474:')
+endfunc
+
func Test_count()
let l = ['a', 'a', 'A', 'b']
call assert_equal(2, count(l, 'a'))
diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim
index 5a10c9baa6..1202b842fd 100644
--- a/src/nvim/testdir/test_options.vim
+++ b/src/nvim/testdir/test_options.vim
@@ -1,5 +1,7 @@
" Test for options
+source check.vim
+
func Test_whichwrap()
set whichwrap=b,s
call assert_equal('b,s', &whichwrap)
@@ -604,6 +606,27 @@ func Test_opt_boolean()
set number&
endfunc
+func Test_opt_winminheight_term()
+ " See test/functional/legacy/options_spec.lua
+ CheckRunVimInTerminal
+
+ " The tabline should be taken into account.
+ let lines =<< trim END
+ set wmh=0 stal=2
+ below sp | wincmd _
+ below sp | wincmd _
+ below sp | wincmd _
+ below sp
+ END
+ call writefile(lines, 'Xwinminheight')
+ let buf = RunVimInTerminal('-S Xwinminheight', #{rows: 11})
+ call term_sendkeys(buf, ":set wmh=1\n")
+ call WaitForAssert({-> assert_match('E36: Not enough room', term_getline(buf, 11))})
+
+ call StopVimInTerminal(buf)
+ call delete('Xwinminheight')
+endfunc
+
" Test for setting option value containing spaces with isfname+=32
func Test_isfname_with_options()
set isfname+=32
@@ -613,4 +636,23 @@ func Test_isfname_with_options()
setlocal keywordprg&
endfunc
+" Test that resetting laststatus does change scroll option
+func Test_opt_reset_scroll()
+ " See test/functional/legacy/options_spec.lua
+ CheckRunVimInTerminal
+ let vimrc =<< trim [CODE]
+ set scroll=2
+ set laststatus=2
+ [CODE]
+ call writefile(vimrc, 'Xscroll')
+ let buf = RunVimInTerminal('-S Xscroll', {'rows': 16, 'cols': 45})
+ call term_sendkeys(buf, ":verbose set scroll?\n")
+ call WaitForAssert({-> assert_match('Last set.*window size', term_getline(buf, 15))})
+ call assert_match('^\s*scroll=7$', term_getline(buf, 14))
+ call StopVimInTerminal(buf)
+
+ " clean up
+ call delete('Xscroll')
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_statusline.vim b/src/nvim/testdir/test_statusline.vim
index 4e38f7ebd8..ce2ef4dcd8 100644
--- a/src/nvim/testdir/test_statusline.vim
+++ b/src/nvim/testdir/test_statusline.vim
@@ -1,12 +1,12 @@
" Test 'statusline'
"
" Not tested yet:
-" %a
" %N
" %T
" %X
source view_util.vim
+source check.vim
source term_util.vim
func s:get_statusline()
@@ -61,7 +61,19 @@ func Test_statusline_will_be_disabled_with_error()
endfunc
func Test_statusline()
- new Xstatusline
+ CheckFeature quickfix
+
+ " %a: Argument list ({current} of {max})
+ set statusline=%a
+ call assert_match('^\s*$', s:get_statusline())
+ arglocal a1 a2
+ rewind
+ call assert_match('^ (1 of 2)\s*$', s:get_statusline())
+ next
+ call assert_match('^ (2 of 2)\s*$', s:get_statusline())
+ e Xstatusline
+ call assert_match('^ ((2) of 2)\s*$', s:get_statusline())
+
only
set laststatus=2
set splitbelow
diff --git a/src/nvim/testdir/test_user_func.vim b/src/nvim/testdir/test_user_func.vim
index 67701ee3ca..e9e181ce3d 100644
--- a/src/nvim/testdir/test_user_func.vim
+++ b/src/nvim/testdir/test_user_func.vim
@@ -95,6 +95,59 @@ func Test_user_func()
enew!
endfunc
+func Log(val, base = 10)
+ return log(a:val) / log(a:base)
+endfunc
+
+func Args(mandatory, optional = v:null, ...)
+ return deepcopy(a:)
+endfunc
+
+func Args2(a = 1, b = 2, c = 3)
+ return deepcopy(a:)
+endfunc
+
+func MakeBadFunc()
+ func s:fcn(a, b=1, c)
+ endfunc
+endfunc
+
+func Test_default_arg()
+ call assert_equal(1.0, Log(10))
+ call assert_equal(log(10), Log(10, exp(1)))
+ call assert_fails("call Log(1,2,3)", 'E118')
+
+ let res = Args(1)
+ call assert_equal(res.mandatory, 1)
+ call assert_equal(res.optional, v:null)
+ call assert_equal(res['0'], 0)
+
+ let res = Args(1,2)
+ call assert_equal(res.mandatory, 1)
+ call assert_equal(res.optional, 2)
+ call assert_equal(res['0'], 0)
+
+ let res = Args(1,2,3)
+ call assert_equal(res.mandatory, 1)
+ call assert_equal(res.optional, 2)
+ call assert_equal(res['0'], 1)
+
+ call assert_fails("call MakeBadFunc()", 'E989')
+ call assert_fails("fu F(a=1 ,) | endf", 'E475')
+
+ " Since neovim does not have v:none, the ability to use the default
+ " argument with the intermediate argument set to v:none has been omitted.
+ " Therefore, this test is not performed.
+ " let d = Args2(7, v:none, 9)
+ " call assert_equal([7, 2, 9], [d.a, d.b, d.c])
+
+ call assert_equal("\n"
+ \ .. " function Args2(a = 1, b = 2, c = 3)\n"
+ \ .. "1 return deepcopy(a:)\n"
+ \ .. " endfunction",
+ \ execute('func Args2'))
+endfunc
+
func Test_failed_call_in_try()
try | call UnknownFunc() | catch | endtry
endfunc
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c
index 3e683a4926..6705ab98c2 100644
--- a/src/nvim/tui/input.c
+++ b/src/nvim/tui/input.c
@@ -557,8 +557,8 @@ HandleState ut_handle_background_color(TermInput *input)
static void handle_raw_buffer(TermInput *input, bool force)
{
- HandleState is_paste;
- HandleState is_bc;
+ HandleState is_paste = kNotApplicable;
+ HandleState is_bc = kNotApplicable;
do {
if (!force
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 00f49724b6..0f717a2f90 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -5501,7 +5501,7 @@ void win_setminheight(void)
// loop until there is a 'winminheight' that is possible
while (p_wmh > 0) {
- const int room = Rows - p_ch;
+ const int room = Rows - p_ch - tabline_height();
const int needed = frame_minheight(topframe, NULL);
if (room >= needed) {
break;
@@ -5960,9 +5960,17 @@ void win_new_width(win_T *wp, int width)
void win_comp_scroll(win_T *wp)
{
+ const long old_w_p_scr = wp->w_p_scr;
+
wp->w_p_scr = wp->w_height / 2;
- if (wp->w_p_scr == 0)
+ if (wp->w_p_scr == 0) {
wp->w_p_scr = 1;
+ }
+ if (wp->w_p_scr != old_w_p_scr) {
+ // Used by "verbose set scroll".
+ wp->w_p_script_ctx[WV_SCROLL].script_ctx.sc_sid = SID_WINLAYOUT;
+ wp->w_p_script_ctx[WV_SCROLL].script_ctx.sc_lnum = 0;
+ }
}
/*
diff --git a/test/functional/ex_cmds/source_spec.lua b/test/functional/ex_cmds/source_spec.lua
new file mode 100644
index 0000000000..16d0dfb6a1
--- /dev/null
+++ b/test/functional/ex_cmds/source_spec.lua
@@ -0,0 +1,47 @@
+local helpers = require('test.functional.helpers')(after_each)
+local command = helpers.command
+local insert = helpers.insert
+local eq = helpers.eq
+local clear = helpers.clear
+local meths = helpers.meths
+local feed = helpers.feed
+local feed_command = helpers.feed_command
+
+describe(':source', function()
+ before_each(function()
+ clear()
+ end)
+
+ it('current buffer', function()
+ insert('let a = 2')
+ command('source')
+ eq('2', meths.exec('echo a', true))
+ end)
+
+ it('selection in current buffer', function()
+ insert(
+ 'let a = 2\n'..
+ 'let a = 3\n'..
+ 'let a = 4\n')
+
+ -- Source the 2nd line only
+ feed('ggjV')
+ feed_command(':source')
+ eq('3', meths.exec('echo a', true))
+
+ -- Source from 2nd line to end of file
+ feed('ggjVG')
+ feed_command(':source')
+ eq('4', meths.exec('echo a', true))
+ end)
+
+ it('multiline heredoc command', function()
+ insert(
+ 'lua << EOF\n'..
+ 'y = 4\n'..
+ 'EOF\n')
+
+ command('source')
+ eq('4', meths.exec('echo luaeval("y")', true))
+ end)
+end)
diff --git a/test/functional/fixtures/fake-lsp-server.lua b/test/functional/fixtures/fake-lsp-server.lua
index 252db88b6b..3bbb4c4517 100644
--- a/test/functional/fixtures/fake-lsp-server.lua
+++ b/test/functional/fixtures/fake-lsp-server.lua
@@ -70,11 +70,11 @@ local function expect_notification(method, params, ...)
..., "expect_notification", "message")
end
-local function expect_request(method, callback, ...)
+local function expect_request(method, handler, ...)
local req = read_message()
assert_eq(method, req.method,
..., "expect_request", "method")
- local err, result = callback(req.params)
+ local err, result = handler(req.params)
respond(req.id, err, result)
end
diff --git a/test/functional/legacy/options_spec.lua b/test/functional/legacy/options_spec.lua
index 1db7afc7a7..d7f5df3a1e 100644
--- a/test/functional/legacy/options_spec.lua
+++ b/test/functional/legacy/options_spec.lua
@@ -1,6 +1,10 @@
+-- See also: src/nvim/testdir/test_options.vim
local helpers = require('test.functional.helpers')(after_each)
local command, clear = helpers.command, helpers.clear
local source, expect = helpers.source, helpers.expect
+local exc_exec = helpers.exc_exec;
+local matches = helpers.matches;
+local Screen = require('test.functional.ui.screen')
describe('options', function()
setup(clear)
@@ -11,7 +15,7 @@ describe('options', function()
end)
describe('set', function()
- setup(clear)
+ before_each(clear)
it("should keep two comma when 'path' is changed", function()
source([[
@@ -24,4 +28,45 @@ describe('set', function()
foo,,bar]])
end)
+
+ it('winminheight works', function()
+ local screen = Screen.new(20, 11)
+ screen:attach()
+ source([[
+ set wmh=0 stal=2
+ below sp | wincmd _
+ below sp | wincmd _
+ below sp | wincmd _
+ below sp
+ ]])
+ matches('E36: Not enough room', exc_exec('set wmh=1'))
+ end)
+
+ it('scroll works', function()
+ local screen = Screen.new(42, 16)
+ screen:attach()
+ source([[
+ set scroll=2
+ set laststatus=2
+ ]])
+ command('verbose set scroll?')
+ screen:expect([[
+ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ scroll=7 |
+ Last set from changed window size |
+ Press ENTER or type command to continue^ |
+ ]])
+ end)
end)
diff --git a/test/functional/lua/buffer_updates_spec.lua b/test/functional/lua/buffer_updates_spec.lua
index db268ea707..7a6b5be8bc 100644
--- a/test/functional/lua/buffer_updates_spec.lua
+++ b/test/functional/lua/buffer_updates_spec.lua
@@ -244,6 +244,14 @@ describe('lua buffer event callbacks: on_lines', function()
eq(1, meths.get_var('listener_cursor_line'))
end)
+ it('has valid cursor position while deleting lines', function()
+ meths.buf_set_lines(0, 0, -1, true, { "line_1", "line_2", "line_3", "line_4"})
+ meths.win_set_cursor(0, {2, 0})
+ eq(2, meths.win_get_cursor(0)[1])
+ meths.buf_set_lines(0, 0, -1, true, { "line_1", "line_2", "line_3"})
+ eq(2, meths.win_get_cursor(0)[1])
+ end)
+
it('does not SEGFAULT when calling win_findbuf in on_detach', function()
exec_lua[[
diff --git a/test/functional/plugin/lsp/diagnostic_spec.lua b/test/functional/plugin/lsp/diagnostic_spec.lua
index 4705a76465..8c91c4ab2c 100644
--- a/test/functional/plugin/lsp/diagnostic_spec.lua
+++ b/test/functional/plugin/lsp/diagnostic_spec.lua
@@ -208,6 +208,69 @@ describe('vim.lsp.diagnostic', function()
]]))
end)
+ describe('reset', function()
+ it('diagnostic count is 0 and displayed diagnostics are 0 after call', function()
+ -- 1 Error (1)
+ -- 1 Warning (2)
+ -- 1 Warning (2) + 1 Warning (1)
+ -- 2 highlights and 2 underlines (since error)
+ -- 1 highlight + 1 underline
+ local all_highlights = {1, 1, 2, 4, 2}
+ eq(all_highlights, exec_lua [[
+ local server_1_diags = {
+ make_error("Error 1", 1, 1, 1, 5),
+ make_warning("Warning on Server 1", 2, 1, 2, 5),
+ }
+ local server_2_diags = {
+ make_warning("Warning 1", 2, 1, 2, 5),
+ }
+
+ vim.lsp.diagnostic.on_publish_diagnostics(nil, nil, { uri = fake_uri, diagnostics = server_1_diags }, 1)
+ vim.lsp.diagnostic.on_publish_diagnostics(nil, nil, { uri = fake_uri, diagnostics = server_2_diags }, 2)
+ return {
+ vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1),
+ vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", 2),
+ vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", nil),
+ count_of_extmarks_for_client(diagnostic_bufnr, 1),
+ count_of_extmarks_for_client(diagnostic_bufnr, 2),
+ }
+ ]])
+
+ -- Reset diagnostics from server 1
+ exec_lua([[ vim.lsp.diagnostic.reset(1, { [ diagnostic_bufnr ] = { [ 1 ] = true ; [ 2 ] = true } } )]])
+
+ -- Make sure we have the right diagnostic count
+ eq({0, 1, 1, 0, 2} , exec_lua [[
+ local diagnostic_count = {}
+ vim.wait(100, function () diagnostic_count = {
+ vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1),
+ vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", 2),
+ vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", nil),
+ count_of_extmarks_for_client(diagnostic_bufnr, 1),
+ count_of_extmarks_for_client(diagnostic_bufnr, 2),
+ } end )
+ return diagnostic_count
+ ]])
+
+ -- Reset diagnostics from server 2
+ exec_lua([[ vim.lsp.diagnostic.reset(2, { [ diagnostic_bufnr ] = { [ 1 ] = true ; [ 2 ] = true } } )]])
+
+ -- Make sure we have the right diagnostic count
+ eq({0, 0, 0, 0, 0}, exec_lua [[
+ local diagnostic_count = {}
+ vim.wait(100, function () diagnostic_count = {
+ vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1),
+ vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", 2),
+ vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", nil),
+ count_of_extmarks_for_client(diagnostic_bufnr, 1),
+ count_of_extmarks_for_client(diagnostic_bufnr, 2),
+ } end )
+ return diagnostic_count
+ ]])
+
+ end)
+ end)
+
describe('get_next_diagnostic_pos', function()
it('can find the next pos with only one client', function()
eq({1, 1}, exec_lua [[
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index 981e2a96a8..8ac81daeef 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -41,10 +41,10 @@ local function fake_lsp_server_setup(test_name, timeout_ms)
"-c", string.format("lua TIMEOUT = %d", timeout),
"-c", "luafile "..fixture_filename,
};
- callbacks = setmetatable({}, {
+ handlers = setmetatable({}, {
__index = function(t, method)
return function(...)
- return vim.rpcrequest(1, 'callback', ...)
+ return vim.rpcrequest(1, 'handler', ...)
end
end;
});
@@ -89,7 +89,7 @@ local function test_rpc_server(config)
end
return NIL
end
- if method == 'callback' then
+ if method == 'handler' then
if config.on_callback then
config.on_callback(unpack(args))
end
@@ -205,7 +205,7 @@ describe('LSP', function()
}
test_rpc_server {
test_name = "basic_init";
- on_init = function(client, _init_result)
+ on_init = function(client, _)
-- client is a dummy object which will queue up commands to be run
-- once the server initializes. It can't accept lua callbacks or
-- other types that may be unserializable for now.
@@ -333,6 +333,7 @@ describe('LSP', function()
client.stop()
local full_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full")
eq(full_kind, client.resolved_capabilities().text_document_did_change)
+ eq(true, client.resolved_capabilities().text_document_save)
end;
on_exit = function(code, signal)
eq(0, code, "exit code", fake_lsp_logfile)
@@ -386,7 +387,7 @@ describe('LSP', function()
exec_lua([=[
BUFFER = vim.api.nvim_get_current_buf()
lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)
- vim.lsp.callbacks['textDocument/typeDefinition'] = function(err, method)
+ vim.lsp.handlers['textDocument/typeDefinition'] = function(err, method)
vim.lsp._last_lsp_callback = { err = err; method = method }
end
vim.lsp._unsupported_method = function(method)
@@ -425,7 +426,7 @@ describe('LSP', function()
test_name = "capabilities_for_client_supports_method";
on_setup = function()
exec_lua([=[
- vim.lsp.callbacks['textDocument/typeDefinition'] = function(err, method)
+ vim.lsp.handlers['textDocument/typeDefinition'] = function(err, method)
vim.lsp._last_lsp_callback = { err = err; method = method }
end
vim.lsp._unsupported_method = function(method)
@@ -897,8 +898,8 @@ describe('LSP', function()
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")
+ on_handler = function(err, method, params, client_id)
+ eq(table.remove(expected_callbacks), {err, method, params, client_id}, "expected handler")
end;
}
end)
@@ -1032,6 +1033,20 @@ describe('LSP', function()
'å ä ɧ 汉语 ↥ 🤦 🦄';
}, buf_lines(1))
end)
+ it('applies text edits at the end of the document', function()
+ local edits = {
+ make_edit(5, 0, 5, 0, "foobar");
+ }
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1)
+ eq({
+ 'First line of text';
+ 'Second line of text';
+ 'Third line of text';
+ 'Fourth line of text';
+ 'å å ɧ 汉语 ↥ 🤦 🦄';
+ 'foobar';
+ }, buf_lines(1))
+ end)
describe('with LSP end line after what Vim considers to be the end line', function()
it('applies edits when the last linebreak is considered a new line', function()
@@ -1765,8 +1780,8 @@ describe('LSP', function()
uri = "file:///src/main.rs"
}
} }
- local callback = require'vim.lsp.handlers'['callHierarchy/outgoingCalls']
- callback(nil, nil, rust_analyzer_response)
+ local handler = require'vim.lsp.handlers'['callHierarchy/outgoingCalls']
+ handler(nil, nil, rust_analyzer_response)
return vim.fn.getqflist()
]=])
@@ -1837,8 +1852,8 @@ describe('LSP', function()
} }
} }
- local callback = require'vim.lsp.handlers'['callHierarchy/incomingCalls']
- callback(nil, nil, rust_analyzer_response)
+ local handler = require'vim.lsp.handlers'['callHierarchy/incomingCalls']
+ handler(nil, nil, rust_analyzer_response)
return vim.fn.getqflist()
]=])
diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua
index 781fdf7203..7a87521a6b 100644
--- a/test/functional/ui/decorations_spec.lua
+++ b/test/functional/ui/decorations_spec.lua
@@ -302,3 +302,98 @@ describe('decorations providers', function()
]]}
end)
end)
+
+describe('extmark decorations', function()
+ local screen
+ before_each( function()
+ clear()
+ screen = Screen.new(50, 15)
+ screen:attach()
+ screen:set_default_attr_ids {
+ [1] = {bold=true, foreground=Screen.colors.Blue};
+ [2] = {foreground = Screen.colors.Brown};
+ [3] = {bold = true, foreground = Screen.colors.SeaGreen};
+ [4] = {background = Screen.colors.Red1, foreground = Screen.colors.Gray100};
+ }
+ end)
+
+ it('can have virtual text of overlay style', function()
+ insert [[
+for _,item in ipairs(items) do
+ local text, hl_id_cell, count = unpack(item)
+ if hl_id_cell ~= nil then
+ hl_id = hl_id_cell
+ end
+ for _ = 1, (count or 1) do
+ local cell = line[colpos]
+ cell.text = text
+ cell.hl_id = hl_id
+ colpos = colpos+1
+ end
+end]]
+ feed 'gg'
+
+ local ns = meths.create_namespace 'test'
+ for i = 1,9 do
+ meths.buf_set_extmark(0, ns, i, 0, { virt_text={{'|', 'LineNr'}}, virt_text_pos='overlay'})
+ if i == 3 or (i >= 6 and i <= 9) then
+ meths.buf_set_extmark(0, ns, i, 4, { virt_text={{'|', 'NonText'}}, virt_text_pos='overlay'})
+ end
+ end
+ meths.buf_set_extmark(0, ns, 9, 10, { virt_text={{'foo'}, {'bar', 'MoreMsg'}, {'!!', 'ErrorMsg'}}, virt_text_pos='overlay'})
+
+ -- can "float" beyond end of line
+ meths.buf_set_extmark(0, ns, 5, 28, { virt_text={{'loopy', 'ErrorMsg'}}, virt_text_pos='overlay'})
+ -- bound check: right edge of window
+ meths.buf_set_extmark(0, ns, 2, 26, { virt_text={{'bork bork bork ' }, {'bork bork bork', 'ErrorMsg'}}, virt_text_pos='overlay'})
+
+ screen:expect{grid=[[
+ ^for _,item in ipairs(items) do |
+ {2:|} local text, hl_id_cell, count = unpack(item) |
+ {2:|} if hl_id_cell ~= nil tbork bork bork {4:bork bork}|
+ {2:|} {1:|} hl_id = hl_id_cell |
+ {2:|} end |
+ {2:|} for _ = 1, (count or 1) {4:loopy} |
+ {2:|} {1:|} local cell = line[colpos] |
+ {2:|} {1:|} cell.text = text |
+ {2:|} {1:|} cell.hl_id = hl_id |
+ {2:|} {1:|} cofoo{3:bar}{4:!!}olpos+1 |
+ end |
+ end |
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+
+ -- handles broken lines
+ screen:try_resize(22, 25)
+ screen:expect{grid=[[
+ ^for _,item in ipairs(i|
+ tems) do |
+ {2:|} local text, hl_id_|
+ cell, count = unpack(i|
+ tem) |
+ {2:|} if hl_id_cell ~= n|
+ il tbork bork bork {4:bor}|
+ {2:|} {1:|} hl_id = hl_id_|
+ cell |
+ {2:|} end |
+ {2:|} for _ = 1, (count |
+ or 1) {4:loopy} |
+ {2:|} {1:|} local cell = l|
+ ine[colpos] |
+ {2:|} {1:|} cell.text = te|
+ xt |
+ {2:|} {1:|} cell.hl_id = h|
+ l_id |
+ {2:|} {1:|} cofoo{3:bar}{4:!!}olpo|
+ s+1 |
+ end |
+ end |
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ end)
+end)