diff options
Diffstat (limited to 'runtime')
179 files changed, 7383 insertions, 6670 deletions
diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index c171fab9e9..9f108b4df4 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -118,4 +118,4 @@ foreach(D ${RUNTIME_DIRS}) endforeach() # only foo.sh script in runtime/ -install_helper(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/macros/less.sh DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/nvim/runtime/macros/) +install_helper(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/scripts/less.sh DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/nvim/runtime/scripts/) diff --git a/runtime/autoload/README.txt b/runtime/autoload/README.txt index 3b18d3dde5..bca86a2a4c 100644 --- a/runtime/autoload/README.txt +++ b/runtime/autoload/README.txt @@ -7,7 +7,7 @@ gzip.vim for editing compressed files netrw*.vim browsing (remote) directories and editing remote files tar.vim browsing tar files zip.vim browsing zip files -paste.vim common code for mswin.vim, menu.vim and macmap.vim +paste.vim common code for mswin.vim and menu.vim spellfile.vim downloading of a missing spell file Omni completion files: diff --git a/runtime/autoload/netrw.vim b/runtime/autoload/netrw.vim index a96364fb4b..1df545278f 100644 --- a/runtime/autoload/netrw.vim +++ b/runtime/autoload/netrw.vim @@ -4,8 +4,8 @@ " Date: May 03, 2023 " Version: 173a " Last Change: {{{1 -" 2023 Nov 21 by Vim Project: ignore wildignore when expanding $COMSPEC (v173a) -" 2023 Nov 22 by Vim Project: fix handling of very long filename on longlist style (v173a) +" 2023 Nov 21 by Vim Project: ignore wildignore when expanding $COMSPEC (v173a) +" 2023 Nov 22 by Vim Project: fix handling of very long filename on longlist style (v173a) " 2024 Feb 19 by Vim Project: (announce adoption) " 2024 Feb 29 by Vim Project: handle symlinks in tree mode correctly " 2024 Apr 03 by Vim Project: detect filetypes for remote edited files @@ -26,6 +26,16 @@ " 2024 Sep 15 by Vim Project: more strict confirmation dialog (#15680) " 2024 Sep 19 by Vim Project: mf-selection highlight uses wrong pattern (#15700) " 2024 Sep 21 by Vim Project: remove extraneous closing bracket (#15718) +" 2024 Oct 21 by Vim Project: remove netrwFileHandlers (#15895) +" 2024 Oct 27 by Vim Project: clean up gx mapping (#15721) +" 2024 Oct 30 by Vim Project: fix filetype detection for remote files (#15961) +" 2024 Oct 30 by Vim Project: fix x mapping on cygwin (#13687) +" 2024 Oct 31 by Vim Project: add netrw#Launch() and netrw#Open() (#15962) +" 2024 Oct 31 by Vim Project: fix E874 when browsing remote dir (#15964) +" 2024 Nov 07 by Vim Project: use keeppatterns to prevent polluting the search history +" 2024 Nov 07 by Vim Project: fix a few issues with netrw tree listing (#15996) +" 2024 Nov 10 by Vim Project: directory symlink not resolved in tree view (#16020) +" 2024 Nov 14 by Vim Project: small fixes to netrw#BrowseX (#16056) " }}} " Former Maintainer: Charles E Campbell " GetLatestVimScripts: 1075 1 :AutoInstall: netrw.vim @@ -532,7 +542,6 @@ if !exists("g:netrw_sort_sequence") endif call s:NetrwInit("g:netrw_special_syntax" , 0) call s:NetrwInit("g:netrw_ssh_browse_reject", '^total\s\+\d\+$') -call s:NetrwInit("g:netrw_suppress_gx_mesg", 1) call s:NetrwInit("g:netrw_use_noswf" , 1) call s:NetrwInit("g:netrw_sizestyle" ,"b") " Default values - t-w ---------- {{{3 @@ -672,11 +681,8 @@ endif " == 4: Vexplore style == 5: Vexplore! " == 6: Texplore fun! netrw#Explore(indx,dosplit,style,...) -" call Dfunc("netrw#Explore(indx=".a:indx." dosplit=".a:dosplit." style=".a:style.",a:1<".a:1.">) &modified=".&modified." modifiable=".&modifiable." a:0=".a:0." win#".winnr()." buf#".bufnr("%")." ft=".&ft) -" call Decho("tab#".tabpagenr()." win#".winnr()." buf#".bufnr("%")."<".bufname("%")."> line#".line(".")." col#".col(".")." winline#".winline()." wincol#".wincol(),'~'.expand("<slnum>")) if !exists("b:netrw_curdir") let b:netrw_curdir= getcwd() -" call Decho("set b:netrw_curdir<".b:netrw_curdir."> (used getcwd)",'~'.expand("<slnum>")) endif " record current file for Rexplore's benefit @@ -690,17 +696,11 @@ fun! netrw#Explore(indx,dosplit,style,...) if !exists("g:netrw_cygwin") && has("win32") let curdir= substitute(curdir,'\','/','g') endif -" call Decho("curdir<".curdir."> curfiledir<".curfiledir.">",'~'.expand("<slnum>")) " using completion, directories with spaces in their names (thanks, Bill Gates, for a truly dumb idea) " will end up with backslashes here. Solution: strip off backslashes that precede white space and " try Explore again. if a:0 > 0 -" call Decho('considering retry: a:1<'.a:1.'>: '. - \ ((a:1 =~ "\\\s")? 'has backslash whitespace' : 'does not have backslash whitespace').', '. - \ ((filereadable(s:NetrwFile(a:1)))? 'is readable' : 'is not readable').', '. - \ ((isdirectory(s:NetrwFile(a:1))))? 'is a directory' : 'is not a directory', - \ '~'.expand("<slnum>")) if a:1 =~ "\\\s" && !filereadable(s:NetrwFile(a:1)) && !isdirectory(s:NetrwFile(a:1)) let a1 = substitute(a:1, '\\\(\s\)', '\1', 'g') if a1 != a:1 @@ -711,6 +711,11 @@ fun! netrw#Explore(indx,dosplit,style,...) endif " save registers + if !has('nvim') && has("clipboard") && g:netrw_clipboard +" call Decho("(netrw#Explore) save @* and @+",'~'.expand("<slnum>")) + sil! let keepregstar = @* + sil! let keepregplus = @+ + endif sil! let keepregslash= @/ " if dosplit @@ -763,64 +768,45 @@ fun! netrw#Explore(indx,dosplit,style,...) NetrwKeepj norm! 0 if a:0 > 0 -" call Decho("case [a:0=".a:0."] > 0: a:1<".a:1.">",'~'.expand("<slnum>")) if a:1 =~ '^\~' && (has("unix") || (exists("g:netrw_cygwin") && g:netrw_cygwin)) -" call Decho("..case a:1<".a:1.">: starts with ~ and unix or cygwin",'~'.expand("<slnum>")) let dirname= simplify(substitute(a:1,'\~',expand("$HOME"),'')) -" call Decho("..using dirname<".dirname."> (case: ~ && unix||cygwin)",'~'.expand("<slnum>")) elseif a:1 == '.' -" call Decho("..case a:1<".a:1.">: matches .",'~'.expand("<slnum>")) let dirname= simplify(exists("b:netrw_curdir")? b:netrw_curdir : getcwd()) if dirname !~ '/$' let dirname= dirname."/" endif -" call Decho("..using dirname<".dirname."> (case: ".(exists("b:netrw_curdir")? "b:netrw_curdir" : "getcwd()").")",'~'.expand("<slnum>")) elseif a:1 =~ '\$' -" call Decho("..case a:1<".a:1.">: matches ending $",'~'.expand("<slnum>")) let dirname= simplify(expand(a:1)) -" call Decho("..using user-specified dirname<".dirname."> with $env-var",'~'.expand("<slnum>")) elseif a:1 !~ '^\*\{1,2}/' && a:1 !~ '^\a\{3,}://' -" call Decho("..case a:1<".a:1.">: other, not pattern or filepattern",'~'.expand("<slnum>")) let dirname= simplify(a:1) -" call Decho("..using user-specified dirname<".dirname.">",'~'.expand("<slnum>")) else -" call Decho("..case a:1: pattern or filepattern",'~'.expand("<slnum>")) let dirname= a:1 endif else " clear explore -" call Decho("case a:0=".a:0.": clearing Explore list",'~'.expand("<slnum>")) call s:NetrwClearExplore() -" call Dret("netrw#Explore : cleared list") return endif -" call Decho("dirname<".dirname.">",'~'.expand("<slnum>")) if dirname =~ '\.\./\=$' let dirname= simplify(fnamemodify(dirname,':p:h')) elseif dirname =~ '\.\.' || dirname == '.' let dirname= simplify(fnamemodify(dirname,':p')) endif -" call Decho("dirname<".dirname."> (after simplify)",'~'.expand("<slnum>")) if dirname =~ '^\*//' " starpat=1: Explore *//pattern (current directory only search for files containing pattern) -" call Decho("case starpat=1: Explore *//pattern",'~'.expand("<slnum>")) let pattern= substitute(dirname,'^\*//\(.*\)$','\1','') let starpat= 1 -" call Decho("..Explore *//pat: (starpat=".starpat.") dirname<".dirname."> -> pattern<".pattern.">",'~'.expand("<slnum>")) if &hls | let keepregslash= s:ExplorePatHls(pattern) | endif elseif dirname =~ '^\*\*//' " starpat=2: Explore **//pattern (recursive descent search for files containing pattern) -" call Decho("case starpat=2: Explore **//pattern",'~'.expand("<slnum>")) let pattern= substitute(dirname,'^\*\*//','','') let starpat= 2 -" call Decho("..Explore **//pat: (starpat=".starpat.") dirname<".dirname."> -> pattern<".pattern.">",'~'.expand("<slnum>")) elseif dirname =~ '/\*\*/' " handle .../**/.../filepat -" call Decho("case starpat=4: Explore .../**/.../filepat",'~'.expand("<slnum>")) let prefixdir= substitute(dirname,'^\(.\{-}\)\*\*.*$','\1','') if prefixdir =~ '^/' || (prefixdir =~ '^\a:/' && has("win32")) let b:netrw_curdir = prefixdir @@ -829,30 +815,23 @@ fun! netrw#Explore(indx,dosplit,style,...) endif let dirname= substitute(dirname,'^.\{-}\(\*\*/.*\)$','\1','') let starpat= 4 -" call Decho("..pwd<".getcwd()."> dirname<".dirname.">",'~'.expand("<slnum>")) -" call Decho("..case Explore ../**/../filepat (starpat=".starpat.")",'~'.expand("<slnum>")) elseif dirname =~ '^\*/' " case starpat=3: Explore */filepat (search in current directory for filenames matching filepat) let starpat= 3 -" call Decho("case starpat=3: Explore */filepat (starpat=".starpat.")",'~'.expand("<slnum>")) elseif dirname=~ '^\*\*/' " starpat=4: Explore **/filepat (recursive descent search for filenames matching filepat) let starpat= 4 -" call Decho("case starpat=4: Explore **/filepat (starpat=".starpat.")",'~'.expand("<slnum>")) else let starpat= 0 -" call Decho("case starpat=0: default",'~'.expand("<slnum>")) endif if starpat == 0 && a:indx >= 0 " [Explore Hexplore Vexplore Sexplore] [dirname] -" call Decho("case starpat==0 && a:indx=".a:indx.": dirname<".dirname.">, handles Explore Hexplore Vexplore Sexplore",'~'.expand("<slnum>")) if dirname == "" let dirname= curfiledir -" call Decho("..empty dirname, using current file's directory<".dirname.">",'~'.expand("<slnum>")) endif if dirname =~# '^scp://' || dirname =~ '^ftp://' call netrw#Nread(2,dirname) @@ -868,10 +847,7 @@ fun! netrw#Explore(indx,dosplit,style,...) elseif dirname !~ '^/' let dirname= b:netrw_curdir."/".dirname endif -" call Decho("..calling LocalBrowseCheck(dirname<".dirname.">)",'~'.expand("<slnum>")) call netrw#LocalBrowseCheck(dirname) -" call Decho(" modified=".&modified." modifiable=".&modifiable." readonly=".&readonly,'~'.expand("<slnum>")) -" call Decho("tab#".tabpagenr()." win#".winnr()." buf#".bufnr("%")."<".bufname("%")."> line#".line(".")." col#".col(".")." winline#".winline()." wincol#".wincol(),'~'.expand("<slnum>")) endif if exists("w:netrw_bannercnt") " done to handle P08-Ingelrest. :Explore will _Always_ go to the line just after the banner. @@ -879,15 +855,6 @@ fun! netrw#Explore(indx,dosplit,style,...) exe w:netrw_bannercnt endif -" call Decho("curdir<".curdir.">",'~'.expand("<slnum>")) - " --------------------------------------------------------------------- - " Jan 24, 2013: not sure why the following was present. See P08-Ingelrest -" if has("win32") || has("win95") || has("win64") || has("win16") -" NetrwKeepj call search('\<'.substitute(curdir,'^.*[/\\]','','e').'\>','cW') -" else -" NetrwKeepj call search('\<'.substitute(curdir,'^.*/','','e').'\>','cW') -" endif - " --------------------------------------------------------------------- " starpat=1: Explore *//pattern (current directory only search for files containing pattern) " starpat=2: Explore **//pattern (recursive descent search for files containing pattern) @@ -895,86 +862,75 @@ fun! netrw#Explore(indx,dosplit,style,...) " starpat=4: Explore **/filepat (recursive descent search for filenames matching filepat) elseif a:indx <= 0 " Nexplore, Pexplore, Explore: handle starpat -" call Decho("case a:indx<=0: Nexplore, Pexplore, <s-down>, <s-up> starpat=".starpat." a:indx=".a:indx,'~'.expand("<slnum>")) if !mapcheck("<s-up>","n") && !mapcheck("<s-down>","n") && exists("b:netrw_curdir") -" call Decho("..set up <s-up> and <s-down> maps",'~'.expand("<slnum>")) let s:didstarstar= 1 nnoremap <buffer> <silent> <s-up> :Pexplore<cr> nnoremap <buffer> <silent> <s-down> :Nexplore<cr> endif if has("path_extra") -" call Decho("..starpat=".starpat.": has +path_extra",'~'.expand("<slnum>")) if !exists("w:netrw_explore_indx") let w:netrw_explore_indx= 0 endif let indx = a:indx -" call Decho("..starpat=".starpat.": set indx= [a:indx=".indx."]",'~'.expand("<slnum>")) if indx == -1 " Nexplore -" call Decho("..case Nexplore with starpat=".starpat.": (indx=".indx.")",'~'.expand("<slnum>")) if !exists("w:netrw_explore_list") " sanity check NetrwKeepj call netrw#ErrorMsg(s:WARNING,"using Nexplore or <s-down> improperly; see help for netrw-starstar",40) + if !has('nvim') && has("clipboard") && g:netrw_clipboard + if @* != keepregstar | sil! let @* = keepregstar | endif + if @+ != keepregplus | sil! let @+ = keepregplus | endif + endif sil! let @/ = keepregslash -" call Dret("netrw#Explore") return endif let indx= w:netrw_explore_indx if indx < 0 | let indx= 0 | endif if indx >= w:netrw_explore_listlen | let indx= w:netrw_explore_listlen - 1 | endif let curfile= w:netrw_explore_list[indx] -" call Decho("....indx=".indx." curfile<".curfile.">",'~'.expand("<slnum>")) while indx < w:netrw_explore_listlen && curfile == w:netrw_explore_list[indx] let indx= indx + 1 -" call Decho("....indx=".indx." (Nexplore while loop)",'~'.expand("<slnum>")) endwhile if indx >= w:netrw_explore_listlen | let indx= w:netrw_explore_listlen - 1 | endif -" call Decho("....Nexplore: indx= [w:netrw_explore_indx=".w:netrw_explore_indx."]=".indx,'~'.expand("<slnum>")) elseif indx == -2 " Pexplore -" call Decho("case Pexplore with starpat=".starpat.": (indx=".indx.")",'~'.expand("<slnum>")) if !exists("w:netrw_explore_list") " sanity check NetrwKeepj call netrw#ErrorMsg(s:WARNING,"using Pexplore or <s-up> improperly; see help for netrw-starstar",41) + if !has('nvim') && has("clipboard") && g:netrw_clipboard + if @* != keepregstar | sil! let @* = keepregstar | endif + if @+ != keepregplus | sil! let @+ = keepregplus | endif + endif sil! let @/ = keepregslash -" call Dret("netrw#Explore") return endif let indx= w:netrw_explore_indx if indx < 0 | let indx= 0 | endif if indx >= w:netrw_explore_listlen | let indx= w:netrw_explore_listlen - 1 | endif let curfile= w:netrw_explore_list[indx] -" call Decho("....indx=".indx." curfile<".curfile.">",'~'.expand("<slnum>")) while indx >= 0 && curfile == w:netrw_explore_list[indx] let indx= indx - 1 -" call Decho("....indx=".indx." (Pexplore while loop)",'~'.expand("<slnum>")) endwhile if indx < 0 | let indx= 0 | endif -" call Decho("....Pexplore: indx= [w:netrw_explore_indx=".w:netrw_explore_indx."]=".indx,'~'.expand("<slnum>")) else " Explore -- initialize " build list of files to Explore with Nexplore/Pexplore -" call Decho("..starpat=".starpat.": case Explore: initialize (indx=".indx.")",'~'.expand("<slnum>")) NetrwKeepj keepalt call s:NetrwClearExplore() let w:netrw_explore_indx= 0 if !exists("b:netrw_curdir") let b:netrw_curdir= getcwd() endif -" call Decho("....starpat=".starpat.": b:netrw_curdir<".b:netrw_curdir.">",'~'.expand("<slnum>")) " switch on starpat to build the w:netrw_explore_list of files if starpat == 1 " starpat=1: Explore *//pattern (current directory only search for files containing pattern) -" call Decho("..case starpat=".starpat.": build *//pattern list (curdir-only srch for files containing pattern) &hls=".&hls,'~'.expand("<slnum>")) -" call Decho("....pattern<".pattern.">",'~'.expand("<slnum>")) try exe "NetrwKeepj noautocmd vimgrep /".pattern."/gj ".fnameescape(b:netrw_curdir)."/*" catch /^Vim\%((\a\+)\)\=:E480/ keepalt call netrw#ErrorMsg(s:WARNING,"no match with pattern<".pattern.">",76) -" call Dret("netrw#Explore : unable to find pattern<".pattern.">") return endtry let w:netrw_explore_list = s:NetrwExploreListUniq(map(getqflist(),'bufname(v:val.bufnr)')) @@ -982,15 +938,16 @@ fun! netrw#Explore(indx,dosplit,style,...) elseif starpat == 2 " starpat=2: Explore **//pattern (recursive descent search for files containing pattern) -" call Decho("..case starpat=".starpat.": build **//pattern list (recursive descent files containing pattern)",'~'.expand("<slnum>")) -" call Decho("....pattern<".pattern.">",'~'.expand("<slnum>")) try exe "sil NetrwKeepj noautocmd keepalt vimgrep /".pattern."/gj "."**/*" catch /^Vim\%((\a\+)\)\=:E480/ keepalt call netrw#ErrorMsg(s:WARNING,'no files matched pattern<'.pattern.'>',45) if &hls | let keepregslash= s:ExplorePatHls(pattern) | endif + if !has('nvim') && has("clipboard") && g:netrw_clipboard + if @* != keepregstar | sil! let @* = keepregstar | endif + if @+ != keepregplus | sil! let @+ = keepregplus | endif + endif sil! let @/ = keepregslash -" call Dret("netrw#Explore : no files matched pattern") return endtry let s:netrw_curdir = b:netrw_curdir @@ -1000,51 +957,43 @@ fun! netrw#Explore(indx,dosplit,style,...) elseif starpat == 3 " starpat=3: Explore */filepat (search in current directory for filenames matching filepat) -" call Decho("..case starpat=".starpat.": build */filepat list (curdir-only srch filenames matching filepat) &hls=".&hls,'~'.expand("<slnum>")) let filepat= substitute(dirname,'^\*/','','') let filepat= substitute(filepat,'^[%#<]','\\&','') -" call Decho("....b:netrw_curdir<".b:netrw_curdir.">",'~'.expand("<slnum>")) -" call Decho("....filepat<".filepat.">",'~'.expand("<slnum>")) let w:netrw_explore_list= s:NetrwExploreListUniq(split(expand(b:netrw_curdir."/".filepat),'\n')) if &hls | let keepregslash= s:ExplorePatHls(filepat) | endif elseif starpat == 4 " starpat=4: Explore **/filepat (recursive descent search for filenames matching filepat) -" call Decho("..case starpat=".starpat.": build **/filepat list (recursive descent srch filenames matching filepat) &hls=".&hls,'~'.expand("<slnum>")) let w:netrw_explore_list= s:NetrwExploreListUniq(split(expand(b:netrw_curdir."/".dirname),'\n')) if &hls | let keepregslash= s:ExplorePatHls(dirname) | endif endif " switch on starpat to build w:netrw_explore_list let w:netrw_explore_listlen = len(w:netrw_explore_list) -" call Decho("....w:netrw_explore_list<".string(w:netrw_explore_list).">",'~'.expand("<slnum>")) -" call Decho("....w:netrw_explore_listlen=".w:netrw_explore_listlen,'~'.expand("<slnum>")) if w:netrw_explore_listlen == 0 || (w:netrw_explore_listlen == 1 && w:netrw_explore_list[0] =~ '\*\*\/') keepalt NetrwKeepj call netrw#ErrorMsg(s:WARNING,"no files matched",42) + if !has('nvim') && has("clipboard") && g:netrw_clipboard + if @* != keepregstar | sil! let @* = keepregstar | endif + if @+ != keepregplus | sil! let @+ = keepregplus | endif + endif sil! let @/ = keepregslash -" call Dret("netrw#Explore : no files matched") return endif endif " if indx ... endif " NetrwStatusLine support - for exploring support let w:netrw_explore_indx= indx -" call Decho("....w:netrw_explore_list<".join(w:netrw_explore_list,',')."> len=".w:netrw_explore_listlen,'~'.expand("<slnum>")) " wrap the indx around, but issue a note if indx >= w:netrw_explore_listlen || indx < 0 -" call Decho("....wrap indx (indx=".indx." listlen=".w:netrw_explore_listlen.")",'~'.expand("<slnum>")) let indx = (indx < 0)? ( w:netrw_explore_listlen - 1 ) : 0 let w:netrw_explore_indx= indx keepalt NetrwKeepj call netrw#ErrorMsg(s:NOTE,"no more files match Explore pattern",43) endif exe "let dirfile= w:netrw_explore_list[".indx."]" -" call Decho("....dirfile=w:netrw_explore_list[indx=".indx."]= <".dirfile.">",'~'.expand("<slnum>")) let newdir= substitute(dirfile,'/[^/]*$','','e') -" call Decho("....newdir<".newdir.">",'~'.expand("<slnum>")) -" call Decho("....calling LocalBrowseCheck(newdir<".newdir.">)",'~'.expand("<slnum>")) call netrw#LocalBrowseCheck(newdir) if !exists("w:netrw_liststyle") let w:netrw_liststyle= g:netrw_liststyle @@ -1058,20 +1007,20 @@ fun! netrw#Explore(indx,dosplit,style,...) let w:netrw_explore_bufnr = bufnr("%") let w:netrw_explore_line = line(".") keepalt NetrwKeepj call s:SetupNetrwStatusLine('%f %h%m%r%=%9*%{NetrwStatusLine()}') -" call Decho("....explore: mtchcnt=".w:netrw_explore_mtchcnt." bufnr=".w:netrw_explore_bufnr." line#".w:netrw_explore_line,'~'.expand("<slnum>")) else -" call Decho("..your vim does not have +path_extra",'~'.expand("<slnum>")) if !exists("g:netrw_quiet") keepalt NetrwKeepj call netrw#ErrorMsg(s:WARNING,"your vim needs the +path_extra feature for Exploring with **!",44) endif + if !has('nvim') && has("clipboard") && g:netrw_clipboard + if @* != keepregstar | sil! let @* = keepregstar | endif + if @+ != keepregplus | sil! let @+ = keepregplus | endif + endif sil! let @/ = keepregslash -" call Dret("netrw#Explore : missing +path_extra") return endif else -" call Decho("..default case: Explore newdir<".dirname.">",'~'.expand("<slnum>")) if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST && dirname =~ '/' sil! unlet w:netrw_treedict sil! unlet w:netrw_treetop @@ -1080,18 +1029,14 @@ fun! netrw#Explore(indx,dosplit,style,...) if !exists("b:netrw_curdir") NetrwKeepj call netrw#LocalBrowseCheck(getcwd()) else - NetrwKeepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,newdir)) + NetrwKeepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,newdir,0)) endif endif " visual display of **/ **// */ Exploration files -" call Decho("w:netrw_explore_indx=".(exists("w:netrw_explore_indx")? w:netrw_explore_indx : "doesn't exist"),'~'.expand("<slnum>")) -" call Decho("b:netrw_curdir<".(exists("b:netrw_curdir")? b:netrw_curdir : "n/a").">",'~'.expand("<slnum>")) if exists("w:netrw_explore_indx") && exists("b:netrw_curdir") -" call Decho("s:explore_prvdir<".(exists("s:explore_prvdir")? s:explore_prvdir : "-doesn't exist-"),'~'.expand("<slnum>")) if !exists("s:explore_prvdir") || s:explore_prvdir != b:netrw_curdir " only update match list when current directory isn't the same as before -" call Decho("only update match list when current directory not the same as before",'~'.expand("<slnum>")) let s:explore_prvdir = b:netrw_curdir let s:explore_match = "" let dirlen = strlen(b:netrw_curdir) @@ -1100,7 +1045,6 @@ fun! netrw#Explore(indx,dosplit,style,...) endif let prvfname= "" for fname in w:netrw_explore_list -" call Decho("fname<".fname.">",'~'.expand("<slnum>")) if fname =~ '^'.b:netrw_curdir if s:explore_match == "" let s:explore_match= '\<'.escape(strpart(fname,dirlen),g:netrw_markfileesc).'\>' @@ -1116,7 +1060,6 @@ fun! netrw#Explore(indx,dosplit,style,...) endif let prvfname= fname endfor -" call Decho("explore_match<".s:explore_match.">",'~'.expand("<slnum>")) if has("syntax") && exists("g:syntax_on") && g:syntax_on exe "2match netrwMarkFile /".s:explore_match."/" endif @@ -1126,15 +1069,17 @@ fun! netrw#Explore(indx,dosplit,style,...) 2match none if exists("s:explore_match") | unlet s:explore_match | endif if exists("s:explore_prvdir") | unlet s:explore_prvdir | endif -" call Decho("cleared explore match list",'~'.expand("<slnum>")) endif " since Explore may be used to initialize netrw's browser, " there's no danger of a late FocusGained event on initialization. " Consequently, set s:netrw_events to 2. let s:netrw_events= 2 + if !has('nvim') && has("clipboard") && g:netrw_clipboard + if @* != keepregstar | sil! let @* = keepregstar | endif + if @+ != keepregplus | sil! let @+ = keepregplus | endif + endif sil! let @/ = keepregslash -" call Dret("netrw#Explore : @/<".@/.">") endfun " --------------------------------------------------------------------- @@ -1152,47 +1097,35 @@ fun! netrw#Lexplore(count,rightside,...) " if a netrw window is already on the left-side of the tab " and a directory has been specified, explore with that " directory. -" call Decho("case has input argument(s) (a:1<".a:1.">)") let a1 = expand(a:1) -" call Decho("a:1<".a:1."> curwin#".curwin,'~'.expand("<slnum>")) exe "1wincmd w" if &ft == "netrw" -" call Decho("exe Explore ".fnameescape(a:1),'~'.expand("<slnum>")) exe "Explore ".fnameescape(a1) exe curwin."wincmd w" let s:lexplore_win= curwin let w:lexplore_buf= bufnr("%") if exists("t:netrw_lexposn") -" call Decho("forgetting t:netrw_lexposn",'~'.expand("<slnum>")) unlet t:netrw_lexposn endif -" call Dret("netrw#Lexplore") return endif exe curwin."wincmd w" else let a1= "" -" call Decho("no input arguments") endif if exists("t:netrw_lexbufnr") " check if t:netrw_lexbufnr refers to a netrw window let lexwinnr = bufwinnr(t:netrw_lexbufnr) -" call Decho("lexwinnr= bufwinnr(t:netrw_lexbufnr#".t:netrw_lexbufnr.")=".lexwinnr) else let lexwinnr= 0 -" call Decho("t:netrw_lexbufnr doesn't exist") endif -" call Decho("lexwinnr=".lexwinnr,'~'.expand("<slnum>")) if lexwinnr > 0 " close down netrw explorer window -" call Decho("t:netrw_lexbufnr#".t:netrw_lexbufnr.": close down netrw window",'~'.expand("<slnum>")) exe lexwinnr."wincmd w" let g:netrw_winsize = -winwidth(0) let t:netrw_lexposn = winsaveview() -" call Decho("saving posn to t:netrw_lexposn<".string(t:netrw_lexposn).">",'~'.expand("<slnum>")) -" call Decho("saving t:netrw_lexposn",'~'.expand("<slnum>")) close if lexwinnr < curwin let curwin= curwin - 1 @@ -1201,11 +1134,9 @@ fun! netrw#Lexplore(count,rightside,...) exe curwin."wincmd w" endif unlet t:netrw_lexbufnr -" call Decho("unlet t:netrw_lexbufnr") else " open netrw explorer window -" call Decho("t:netrw_lexbufnr<n/a>: open netrw explorer window",'~'.expand("<slnum>")) exe "1wincmd w" let keep_altv = g:netrw_altv let g:netrw_altv = 0 @@ -1214,18 +1145,13 @@ fun! netrw#Lexplore(count,rightside,...) let g:netrw_winsize = a:count endif let curfile= expand("%") -" call Decho("curfile<".curfile.">",'~'.expand("<slnum>")) exe (a:rightside? "botright" : "topleft")." vertical ".((g:netrw_winsize > 0)? (g:netrw_winsize*winwidth(0))/100 : -g:netrw_winsize) . " new" -" call Decho("new buf#".bufnr("%")." win#".winnr()) if a:0 > 0 && a1 != "" -" call Decho("case 1: Explore ".a1,'~'.expand("<slnum>")) call netrw#Explore(0,0,0,a1) exe "Explore ".fnameescape(a1) elseif curfile =~ '^\a\{3,}://' -" call Decho("case 2: Explore ".substitute(curfile,'[^/\\]*$','',''),'~'.expand("<slnum>")) call netrw#Explore(0,0,0,substitute(curfile,'[^/\\]*$','','')) else -" call Decho("case 3: Explore .",'~'.expand("<slnum>")) call netrw#Explore(0,0,0,".") endif if a:count != 0 @@ -1238,11 +1164,7 @@ fun! netrw#Lexplore(count,rightside,...) " Since the intended use of :Lexplore is to have an always-present explorer window, the extra " effort to prevent mis-use of :Lex is warranted. set bh=wipe -" call Decho("let t:netrw_lexbufnr=".t:netrw_lexbufnr) -" call Decho("t:netrw_lexposn".(exists("t:netrw_lexposn")? string(t:netrw_lexposn) : " n/a")) if exists("t:netrw_lexposn") -" call Decho("restoring to t:netrw_lexposn",'~'.expand("<slnum>")) -" call Decho("restoring posn to t:netrw_lexposn<".string(t:netrw_lexposn).">",'~'.expand("<slnum>")) call winrestview(t:netrw_lexposn) unlet t:netrw_lexposn endif @@ -1255,10 +1177,8 @@ fun! netrw#Lexplore(count,rightside,...) else let g:netrw_chgwin= 2 endif -" call Decho("let g:netrw_chgwin=".g:netrw_chgwin) endif -" call Dret("netrw#Lexplore") endfun " --------------------------------------------------------------------- @@ -1670,8 +1590,13 @@ fun! s:NetrwOptionsSave(vt) let {a:vt}netrw_dirkeep = getcwd() " call Decho("saving to ".a:vt."netrw_dirkeep<".{a:vt}netrw_dirkeep.">",'~'.expand("<slnum>")) endif + if !has('nvim') && has("clipboard") && g:netrw_clipboard + sil! let {a:vt}netrw_starkeep = @* + sil! let {a:vt}netrw_pluskeep = @+ + endif sil! let {a:vt}netrw_slashkeep= @/ +" call Decho("(s:NetrwOptionsSave) lines=".&lines) " 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 Dret("s:NetrwOptionsSave : tab#".tabpagenr()." win#".winnr()) endfun @@ -1742,29 +1667,20 @@ endfun " --------------------------------------------------------------------- " s:NetrwOptionsRestore: restore options (based on prior s:NetrwOptionsSave) {{{2 fun! s:NetrwOptionsRestore(vt) -" call Dfunc("s:NetrwOptionsRestore(vt<".a:vt.">) win#".winnr()." buf#".bufnr("%")."<".bufname("%")."> winnr($)=".winnr("$")) -" call Decho("(s:NetrwOptionsRestore) lines=".&lines) -" 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>")) - - " filereadable() returns zero for remote files (e.g. scp://localhost//etc/fstab) - if filereadable(expand("%")) || expand("%") =~# '^\w\+://\f\+/' -" call Decho("..doing filetype detect anyway") + " filereadable() returns zero for remote files (e.g. scp://user@localhost//etc/fstab) + " Note: @ may not be in 'isfname', so '^\w\+://\f\+/' may not match + if filereadable(expand("%")) || expand("%") =~# '^\w\+://\f\+' filetype detect -" 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>")) else setl ft=netrw endif -" 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") return endif unlet {a:vt}netrw_optionsave if exists("+acd") if exists("{a:vt}netrw_acdkeep") -" call Decho("g:netrw_keepdir=".g:netrw_keepdir.": getcwd<".getcwd()."> acd=".&acd,'~'.expand("<slnum>")) let curdir = getcwd() let &l:acd = {a:vt}netrw_acdkeep unlet {a:vt}netrw_acdkeep @@ -1773,53 +1689,43 @@ fun! s:NetrwOptionsRestore(vt) endif endif endif -" call Decho("(s:NetrwOptionsRestore) #1 lines=".&lines) call s:NetrwRestoreSetting(a:vt."netrw_aikeep","&l:ai") call s:NetrwRestoreSetting(a:vt."netrw_awkeep","&l:aw") call s:NetrwRestoreSetting(a:vt."netrw_blkeep","&l:bl") call s:NetrwRestoreSetting(a:vt."netrw_btkeep","&l:bt") call s:NetrwRestoreSetting(a:vt."netrw_bombkeep","&l:bomb") -" call Decho("(s:NetrwOptionsRestore) #2 lines=".&lines) call s:NetrwRestoreSetting(a:vt."netrw_cedit","&cedit") call s:NetrwRestoreSetting(a:vt."netrw_cikeep","&l:ci") call s:NetrwRestoreSetting(a:vt."netrw_cinkeep","&l:cin") call s:NetrwRestoreSetting(a:vt."netrw_cinokeep","&l:cino") call s:NetrwRestoreSetting(a:vt."netrw_comkeep","&l:com") -" call Decho("(s:NetrwOptionsRestore) #3 lines=".&lines) call s:NetrwRestoreSetting(a:vt."netrw_cpokeep","&l:cpo") call s:NetrwRestoreSetting(a:vt."netrw_diffkeep","&l:diff") call s:NetrwRestoreSetting(a:vt."netrw_fenkeep","&l:fen") if exists("g:netrw_ffkeep") && g:netrw_ffkeep call s:NetrwRestoreSetting(a:vt."netrw_ffkeep")","&l:ff") endif -" call Decho("(s:NetrwOptionsRestore) #4 lines=".&lines) call s:NetrwRestoreSetting(a:vt."netrw_fokeep" ,"&l:fo") call s:NetrwRestoreSetting(a:vt."netrw_gdkeep" ,"&l:gd") call s:NetrwRestoreSetting(a:vt."netrw_gokeep" ,"&go") call s:NetrwRestoreSetting(a:vt."netrw_hidkeep" ,"&l:hidden") -" call Decho("(s:NetrwOptionsRestore) #5 lines=".&lines) call s:NetrwRestoreSetting(a:vt."netrw_imkeep" ,"&l:im") call s:NetrwRestoreSetting(a:vt."netrw_iskkeep" ,"&l:isk") -" call Decho("(s:NetrwOptionsRestore) #6 lines=".&lines) call s:NetrwRestoreSetting(a:vt."netrw_lines" ,"&lines") -" call Decho("(s:NetrwOptionsRestore) #7 lines=".&lines) call s:NetrwRestoreSetting(a:vt."netrw_lskeep" ,"&l:ls") call s:NetrwRestoreSetting(a:vt."netrw_makeep" ,"&l:ma") call s:NetrwRestoreSetting(a:vt."netrw_magickeep","&l:magic") call s:NetrwRestoreSetting(a:vt."netrw_modkeep" ,"&l:mod") call s:NetrwRestoreSetting(a:vt."netrw_nukeep" ,"&l:nu") -" call Decho("(s:NetrwOptionsRestore) #8 lines=".&lines) call s:NetrwRestoreSetting(a:vt."netrw_rnukeep" ,"&l:rnu") call s:NetrwRestoreSetting(a:vt."netrw_repkeep" ,"&l:report") call s:NetrwRestoreSetting(a:vt."netrw_rokeep" ,"&l:ro") call s:NetrwRestoreSetting(a:vt."netrw_selkeep" ,"&l:sel") -" call Decho("(s:NetrwOptionsRestore) #9 lines=".&lines) call s:NetrwRestoreSetting(a:vt."netrw_spellkeep","&l:spell") call s:NetrwRestoreSetting(a:vt."netrw_twkeep" ,"&l:tw") call s:NetrwRestoreSetting(a:vt."netrw_wigkeep" ,"&l:wig") call s:NetrwRestoreSetting(a:vt."netrw_wrapkeep" ,"&l:wrap") call s:NetrwRestoreSetting(a:vt."netrw_writekeep","&l:write") -" call Decho("(s:NetrwOptionsRestore) #10 lines=".&lines) call s:NetrwRestoreSetting("s:yykeep","@@") " former problem: start with liststyle=0; press <i> : result, following line resets l:ts. " Fixed; in s:PerformListing, when w:netrw_liststyle is s:LONGLIST, will use a printf to pad filename with spaces @@ -1850,24 +1756,18 @@ fun! s:NetrwOptionsRestore(vt) unlet {a:vt}netrw_dirkeep endif endif + if !has('nvim') && has("clipboard") && g:netrw_clipboard + call s:NetrwRestoreSetting(a:vt."netrw_starkeep","@*") + call s:NetrwRestoreSetting(a:vt."netrw_pluskeep","@+") + endif call s:NetrwRestoreSetting(a:vt."netrw_slashkeep","@/") -" call Decho("g:netrw_keepdir=".g:netrw_keepdir.": getcwd<".getcwd()."> acd=".&acd,'~'.expand("<slnum>")) -" call Decho("fo=".&fo.(exists("+acd")? " acd=".&acd : " acd doesn't exist"),'~'.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 Decho("diff=".&l:diff." win#".winnr()." w:netrw_diffkeep=".(exists("w:netrw_diffkeep")? w:netrw_diffkeep : "doesn't exist"),'~'.expand("<slnum>")) -" call Decho("ts=".&l:ts,'~'.expand("<slnum>")) " Moved the filetype detect here from NetrwGetFile() because remote files " were having their filetype detect-generated settings overwritten by " NetrwOptionRestore. if &ft != "netrw" -" call Decho("before: filetype detect (ft=".&ft.")",'~'.expand("<slnum>")) filetype detect -" call Decho("after : filetype detect (ft=".&ft.")",'~'.expand("<slnum>")) endif -" call Decho("(s:NetrwOptionsRestore) lines=".&lines) -" 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 Dret("s:NetrwOptionsRestore : tab#".tabpagenr()." win#".winnr()." buf#".bufnr("%")."<".bufname("%")."> modified=".&modified." modifiable=".&modifiable." readonly=".&readonly) endfun " --------------------------------------------------------------------- @@ -2818,36 +2718,27 @@ endfun " netrw#SetTreetop: resets the tree top to the current directory/specified directory {{{2 " (implements the :Ntree command) fun! netrw#SetTreetop(iscmd,...) -" call Dfunc("netrw#SetTreetop(iscmd=".a:iscmd." ".((a:0 > 0)? a:1 : "").") a:0=".a:0) -" call Decho("w:netrw_treetop<".w:netrw_treetop.">") " iscmd==0: netrw#SetTreetop called using gn mapping " iscmd==1: netrw#SetTreetop called using :Ntree from the command line -" call Decho("(iscmd=".a:iscmd.": called using :Ntree from command line",'~'.expand("<slnum>")) " clear out the current tree if exists("w:netrw_treetop") -" call Decho("clearing out current tree",'~'.expand("<slnum>")) let inittreetop= w:netrw_treetop unlet w:netrw_treetop endif if exists("w:netrw_treedict") -" call Decho("freeing w:netrw_treedict",'~'.expand("<slnum>")) unlet w:netrw_treedict endif -" call Decho("inittreetop<".(exists("inittreetop")? inittreetop : "n/a").">") if (a:iscmd == 0 || a:1 == "") && exists("inittreetop") let treedir = s:NetrwTreePath(inittreetop) -" call Decho("treedir<".treedir.">",'~'.expand("<slnum>")) else if isdirectory(s:NetrwFile(a:1)) -" call Decho("a:1<".a:1."> is a directory",'~'.expand("<slnum>")) let treedir = a:1 let s:netrw_treetop = treedir elseif exists("b:netrw_curdir") && (isdirectory(s:NetrwFile(b:netrw_curdir."/".a:1)) || a:1 =~ '^\a\{3,}://') let treedir = b:netrw_curdir."/".a:1 let s:netrw_treetop = treedir -" call Decho("a:1<".a:1."> is NOT a directory, using treedir<".treedir.">",'~'.expand("<slnum>")) else " normally the cursor is left in the message window. " However, here this results in the directory being listed in the message window, which is not wanted. @@ -2858,20 +2749,17 @@ fun! netrw#SetTreetop(iscmd,...) let s:netrw_treetop = getcwd() endif endif -" call Decho("treedir<".treedir.">",'~'.expand("<slnum>")) " determine if treedir is remote or local let islocal= expand("%") !~ '^\a\{3,}://' -" call Decho("islocal=".islocal,'~'.expand("<slnum>")) " browse the resulting directory if islocal - call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(islocal,treedir)) + call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(islocal,treedir,0)) else - call s:NetrwBrowse(islocal,s:NetrwBrowseChgDir(islocal,treedir)) + call s:NetrwBrowse(islocal,s:NetrwBrowseChgDir(islocal,treedir,0)) endif -" call Dret("netrw#SetTreetop") endfun " =========================================== @@ -3729,16 +3617,11 @@ endfun " Often called via: Explore/e dirname/etc -> netrw#LocalBrowseCheck() -> s:NetrwBrowse() fun! s:NetrwBrowse(islocal,dirname) if !exists("w:netrw_liststyle")|let w:netrw_liststyle= g:netrw_liststyle|endif -" call Dfunc("s:NetrwBrowse(islocal=".a:islocal." dirname<".a:dirname.">) liststyle=".w:netrw_liststyle." ".g:loaded_netrw." buf#".bufnr("%")."<".bufname("%")."> win#".winnr()) -" call Decho("fyi: modified=".&modified." modifiable=".&modifiable." readonly=".&readonly,'~'.expand("<slnum>")) -" call Decho("fyi: tab#".tabpagenr()." win#".winnr()." buf#".bufnr("%")."<".bufname("%")."> line#".line(".")." col#".col(".")." winline#".winline()." wincol#".wincol(),'~'.expand("<slnum>")) -" call Dredir("ls!","s:NetrwBrowse") " save alternate-file's filename if w:netrw_rexlocal doesn't exist " This is useful when one edits a local file, then :e ., then :Rex if a:islocal && !exists("w:netrw_rexfile") && bufname("#") != "" let w:netrw_rexfile= bufname("#") -" call Decho("setting w:netrw_rexfile<".w:netrw_rexfile."> win#".winnr(),'~'.expand("<slnum>")) endif " s:NetrwBrowse : initialize history {{{3 @@ -3749,32 +3632,26 @@ fun! s:NetrwBrowse(islocal,dirname) " s:NetrwBrowse : simplify the dirname (especially for ".."s in dirnames) {{{3 if a:dirname !~ '^\a\{3,}://' let dirname= simplify(a:dirname) -" call Decho("simplified dirname<".dirname.">") else let dirname= a:dirname endif " repoint t:netrw_lexbufnr if appropriate if exists("t:netrw_lexbufnr") && bufnr("%") == t:netrw_lexbufnr -" call Decho("set repointlexbufnr to true!") let repointlexbufnr= 1 endif " s:NetrwBrowse : sanity checks: {{{3 if exists("s:netrw_skipbrowse") unlet s:netrw_skipbrowse -" 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:NetrwBrowse : s:netrw_skipbrowse existed") return endif if !exists("*shellescape") NetrwKeepj call netrw#ErrorMsg(s:ERROR,"netrw can't run -- your vim is missing shellescape()",69) -" call Dret("s:NetrwBrowse : missing shellescape()") return endif if !exists("*fnameescape") NetrwKeepj call netrw#ErrorMsg(s:ERROR,"netrw can't run -- your vim is missing fnameescape()",70) -" call Dret("s:NetrwBrowse : missing fnameescape()") return endif @@ -3784,53 +3661,39 @@ fun! s:NetrwBrowse(islocal,dirname) " s:NetrwBrowse : re-instate any marked files {{{3 if has("syntax") && exists("g:syntax_on") && g:syntax_on if exists("s:netrwmarkfilelist_{bufnr('%')}") -" call Decho("clearing marked files",'~'.expand("<slnum>")) exe "2match netrwMarkFile /".s:netrwmarkfilemtch_{bufnr("%")}."/" endif endif if a:islocal && exists("w:netrw_acdkeep") && w:netrw_acdkeep " s:NetrwBrowse : set up "safe" options for local directory/file {{{3 -" call Decho("handle w:netrw_acdkeep:",'~'.expand("<slnum>")) -" call Decho("NetrwKeepj lcd ".fnameescape(dirname)." (due to w:netrw_acdkeep=".w:netrw_acdkeep." - acd=".&acd.")",'~'.expand("<slnum>")) if s:NetrwLcd(dirname) -" call Dret("s:NetrwBrowse : lcd failure") return endif - " call s:NetrwOptionsSafe() " tst952 failed with this enabled. -" call Decho("getcwd<".getcwd().">",'~'.expand("<slnum>")) elseif !a:islocal && dirname !~ '[\/]$' && dirname !~ '^"' " s:NetrwBrowse : remote regular file handler {{{3 -" call Decho("handle remote regular file: dirname<".dirname.">",'~'.expand("<slnum>")) if bufname(dirname) != "" -" call Decho("edit buf#".bufname(dirname)." in win#".winnr(),'~'.expand("<slnum>")) exe "NetrwKeepj b ".bufname(dirname) else " attempt transfer of remote regular file -" call Decho("attempt transfer as regular file<".dirname.">",'~'.expand("<slnum>")) " remove any filetype indicator from end of dirname, except for the " "this is a directory" indicator (/). " There shouldn't be one of those here, anyway. let path= substitute(dirname,'[*=@|]\r\=$','','e') -" call Decho("new path<".path.">",'~'.expand("<slnum>")) call s:RemotePathAnalysis(dirname) " s:NetrwBrowse : remote-read the requested file into current buffer {{{3 call s:NetrwEnew(dirname) call s:NetrwOptionsSafe(a:islocal) setl ma noro -" call Decho("setl ma noro",'~'.expand("<slnum>")) let b:netrw_curdir = dirname let url = s:method."://".((s:user == "")? "" : s:user."@").s:machine.(s:port ? ":".s:port : "")."/".s:path call s:NetrwBufRename(url) exe "sil! NetrwKeepj keepalt doau BufReadPre ".fnameescape(s:fname) sil call netrw#NetRead(2,url) " netrw.vim and tar.vim have already handled decompression of the tarball; avoiding gzip.vim error -" call Decho("url<".url.">",'~'.expand("<slnum>")) -" call Decho("s:path<".s:path.">",'~'.expand("<slnum>")) -" call Decho("s:fname<".s:fname.">",'~'.expand("<slnum>")) if s:path =~ '.bz2' exe "sil NetrwKeepj keepalt doau BufReadPost ".fnameescape(substitute(s:fname,'\.bz2$','','')) elseif s:path =~ '.gz' @@ -3845,11 +3708,7 @@ fun! s:NetrwBrowse(islocal,dirname) " s:NetrwBrowse : save certain window-oriented variables into buffer-oriented variables {{{3 call s:SetBufWinVars() call s:NetrwOptionsRestore("w:") -" call Decho("setl ma nomod",'~'.expand("<slnum>")) setl ma nomod noro -" 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:NetrwBrowse : file<".s:fname.">") return endif @@ -3865,33 +3724,31 @@ fun! s:NetrwBrowse(islocal,dirname) NetrwKeepj call s:NetrwMenu(1) " get/set-up buffer {{{3 -" call Decho("saving position across a buffer refresh",'~'.expand("<slnum>")) let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + + " NetrwGetBuffer might change buffers but s:rexposn_X was set for the + " previous buffer + let prevbufnr = bufnr('%') let reusing= s:NetrwGetBuffer(a:islocal,dirname) + if exists("s:rexposn_".prevbufnr) + let s:rexposn_{bufnr('%')} = s:rexposn_{prevbufnr} + endif " maintain markfile highlighting if has("syntax") && exists("g:syntax_on") && g:syntax_on if exists("s:netrwmarkfilemtch_{bufnr('%')}") && s:netrwmarkfilemtch_{bufnr("%")} != "" -" " call Decho("bufnr(%)=".bufnr('%'),'~'.expand("<slnum>")) -" " call Decho("exe 2match netrwMarkFile /".s:netrwmarkfilemtch_{bufnr("%")}."/",'~'.expand("<slnum>")) exe "2match netrwMarkFile /".s:netrwmarkfilemtch_{bufnr("%")}."/" else -" " call Decho("2match none",'~'.expand("<slnum>")) 2match none endif endif if reusing && line("$") > 1 call s:NetrwOptionsRestore("w:") -" call Decho("setl noma nomod nowrap",'~'.expand("<slnum>")) setl noma nomod nowrap -" call Decho("(set noma nomod nowrap) ro=".&l:ro." ma=".&l:ma." mod=".&l:mod." wrap=".&l:wrap." (filename<".expand("%")."> win#".winnr()." ft<".&ft.">)",'~'.expand("<slnum>")) -" call Dret("s:NetrwBrowse : re-using not-cleared buffer") return endif " set b:netrw_curdir to the new directory name {{{3 -" call Decho("set b:netrw_curdir to the new directory name<".dirname."> (buf#".bufnr("%").")",'~'.expand("<slnum>")) let b:netrw_curdir= dirname if b:netrw_curdir =~ '[/\\]$' let b:netrw_curdir= substitute(b:netrw_curdir,'[/\\]$','','e') @@ -3912,24 +3769,18 @@ fun! s:NetrwBrowse(islocal,dirname) if !a:islocal && b:netrw_curdir !~ '/$' let b:netrw_curdir= b:netrw_curdir.'/' endif -" call Decho("b:netrw_curdir<".b:netrw_curdir.">",'~'.expand("<slnum>")) " ------------ " (local only) {{{3 " ------------ if a:islocal -" call Decho("local only:",'~'.expand("<slnum>")) - " Set up ShellCmdPost handling. Append current buffer to browselist call s:LocalFastBrowser() " handle g:netrw_keepdir: set vim's current directory to netrw's notion of the current directory {{{3 if !g:netrw_keepdir -" call Decho("handle g:netrw_keepdir=".g:netrw_keepdir.": getcwd<".getcwd()."> acd=".&acd,'~'.expand("<slnum>")) -" call Decho("l:acd".(exists("&l:acd")? "=".&l:acd : " doesn't exist"),'~'.expand("<slnum>")) if !exists("&l:acd") || !&l:acd if s:NetrwLcd(b:netrw_curdir) -" call Dret("s:NetrwBrowse : lcd failure") return endif endif @@ -3939,23 +3790,18 @@ fun! s:NetrwBrowse(islocal,dirname) " remote handling: {{{3 " -------------------------------- else -" call Decho("remote only:",'~'.expand("<slnum>")) " analyze dirname and g:netrw_list_cmd {{{3 -" call Decho("b:netrw_curdir<".(exists("b:netrw_curdir")? b:netrw_curdir : "doesn't exist")."> dirname<".dirname.">",'~'.expand("<slnum>")) if dirname =~# "^NetrwTreeListing\>" let dirname= b:netrw_curdir -" call Decho("(dirname was <NetrwTreeListing>) dirname<".dirname.">",'~'.expand("<slnum>")) elseif exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST && exists("b:netrw_curdir") let dirname= substitute(b:netrw_curdir,'\\','/','g') if dirname !~ '/$' let dirname= dirname.'/' endif let b:netrw_curdir = dirname -" call Decho("(liststyle is TREELIST) dirname<".dirname.">",'~'.expand("<slnum>")) else let dirname = substitute(dirname,'\\','/','g') -" call Decho("(normal) dirname<".dirname.">",'~'.expand("<slnum>")) endif let dirpat = '^\(\w\{-}\)://\(\w\+@\)\=\([^/]\+\)/\(.*\)$' @@ -3964,14 +3810,10 @@ fun! s:NetrwBrowse(islocal,dirname) NetrwKeepj call netrw#ErrorMsg(s:ERROR,"netrw doesn't understand your dirname<".dirname.">",20) endif NetrwKeepj call s:NetrwOptionsRestore("w:") -" call Decho("setl noma nomod nowrap",'~'.expand("<slnum>")) setl noma nomod nowrap -" 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:NetrwBrowse : badly formatted dirname<".dirname.">") return endif let b:netrw_curdir= dirname -" call Decho("b:netrw_curdir<".b:netrw_curdir."> (remote)",'~'.expand("<slnum>")) endif " (additional remote handling) " ------------------------------- @@ -3983,12 +3825,10 @@ fun! s:NetrwBrowse(islocal,dirname) " restore option(s) call s:NetrwOptionsRestore("w:") -" call Decho("tab#".tabpagenr()." win#".winnr()." buf#".bufnr("%")."<".bufname("%")."> line#".line(".")." col#".col(".")." winline#".winline()." wincol#".wincol(),'~'.expand("<slnum>")) " If there is a rexposn: restore position with rexposn " Otherwise : set rexposn if exists("s:rexposn_".bufnr("%")) -" call Decho("restoring posn to s:rexposn_".bufnr('%')."<".string(s:rexposn_{bufnr('%')}).">",'~'.expand("<slnum>")) NetrwKeepj call winrestview(s:rexposn_{bufnr('%')}) if exists("w:netrw_bannercnt") && line(".") < w:netrw_bannercnt NetrwKeepj exe w:netrw_bannercnt @@ -3998,28 +3838,22 @@ fun! s:NetrwBrowse(islocal,dirname) endif if v:version >= 700 && has("balloon_eval") && &beval == 0 && &l:bexpr == "" && !exists("g:netrw_nobeval") let &l:bexpr= "netrw#BalloonHelp()" -" call Decho("set up balloon help: l:bexpr=".&l:bexpr,'~'.expand("<slnum>")) setl beval endif " repoint t:netrw_lexbufnr if appropriate if exists("repointlexbufnr") let t:netrw_lexbufnr= bufnr("%") -" call Decho("repoint t:netrw_lexbufnr to #".t:netrw_lexbufnr) endif " restore position if reusing -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) call winrestview(svpos) endif " The s:LocalBrowseRefresh() function is called by an autocmd " installed by s:LocalFastBrowser() when g:netrw_fastbrowse <= 1 (ie. slow or medium speed). " However, s:NetrwBrowse() causes the FocusGained event to fire the first time. -" call Decho("tab#".tabpagenr()." win#".winnr()." buf#".bufnr("%")."<".bufname("%")."> line#".line(".")." col#".col(".")." winline#".winline()." wincol#".wincol(),'~'.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:NetrwBrowse : did PerformListing ft<".&ft.">") return endfun @@ -4512,41 +4346,30 @@ endfun " islocal=0: remote browsing " =1: local browsing fun! s:NetrwListStyle(islocal) -" call Dfunc("NetrwListStyle(islocal=".a:islocal.") w:netrw_liststyle=".w:netrw_liststyle) - let ykeep = @@ let fname = s:NetrwGetWord() if !exists("w:netrw_liststyle")|let w:netrw_liststyle= g:netrw_liststyle|endif let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let w:netrw_liststyle = (w:netrw_liststyle + 1) % s:MAXLIST -" call Decho("fname<".fname.">",'~'.expand("<slnum>")) -" call Decho("chgd w:netrw_liststyle to ".w:netrw_liststyle,'~'.expand("<slnum>")) -" call Decho("b:netrw_curdir<".(exists("b:netrw_curdir")? b:netrw_curdir : "doesn't exist").">",'~'.expand("<slnum>")) " repoint t:netrw_lexbufnr if appropriate if exists("t:netrw_lexbufnr") && bufnr("%") == t:netrw_lexbufnr -" call Decho("set repointlexbufnr to true!") let repointlexbufnr= 1 endif if w:netrw_liststyle == s:THINLIST " use one column listing -" call Decho("use one column list",'~'.expand("<slnum>")) let g:netrw_list_cmd = substitute(g:netrw_list_cmd,' -l','','ge') elseif w:netrw_liststyle == s:LONGLIST " use long list -" call Decho("use long list",'~'.expand("<slnum>")) let g:netrw_list_cmd = g:netrw_list_cmd." -l" elseif w:netrw_liststyle == s:WIDELIST " give wide list -" call Decho("use wide list",'~'.expand("<slnum>")) let g:netrw_list_cmd = substitute(g:netrw_list_cmd,' -l','','ge') elseif exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST -" call Decho("use tree list",'~'.expand("<slnum>")) let g:netrw_list_cmd = substitute(g:netrw_list_cmd,' -l','','ge') else @@ -4556,25 +4379,19 @@ fun! s:NetrwListStyle(islocal) let g:netrw_list_cmd = substitute(g:netrw_list_cmd,' -l','','ge') endif setl ma noro -" call Decho("setl ma noro",'~'.expand("<slnum>")) " clear buffer - this will cause NetrwBrowse/LocalBrowseCheck to do a refresh -" call Decho("clear buffer<".expand("%")."> with :%d",'~'.expand("<slnum>")) sil! NetrwKeepj %d _ " following prevents tree listing buffer from being marked "modified" -" call Decho("setl nomod",'~'.expand("<slnum>")) setl nomod -" call Decho("ro=".&l:ro." ma=".&l:ma." mod=".&l:mod." wrap=".&l:wrap." (filename<".expand("%")."> win#".winnr()." ft<".&ft.">)",'~'.expand("<slnum>")) " refresh the listing -" call Decho("refresh the listing",'~'.expand("<slnum>")) - NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) NetrwKeepj call s:NetrwCursor(0) " repoint t:netrw_lexbufnr if appropriate if exists("repointlexbufnr") let t:netrw_lexbufnr= bufnr("%") -" call Decho("repoint t:netrw_lexbufnr to #".t:netrw_lexbufnr) endif " restore position; keep cursor on the filename @@ -4582,22 +4399,18 @@ fun! s:NetrwListStyle(islocal) NetrwKeepj call winrestview(svpos) let @@= ykeep -" call Dret("NetrwListStyle".(exists("w:netrw_liststyle")? ' : w:netrw_liststyle='.w:netrw_liststyle : "")) endfun " --------------------------------------------------------------------- " s:NetrwBannerCtrl: toggles the display of the banner {{{2 fun! s:NetrwBannerCtrl(islocal) -" call Dfunc("s:NetrwBannerCtrl(islocal=".a:islocal.") g:netrw_banner=".g:netrw_banner) - let ykeep= @@ " toggle the banner (enable/suppress) let g:netrw_banner= !g:netrw_banner " refresh the listing let svpos= winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) - call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) + call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) " keep cursor on the filename if g:netrw_banner && exists("w:netrw_bannercnt") && line(".") >= w:netrw_bannercnt @@ -4625,24 +4438,20 @@ endfun " " With bang: deletes files/directories from Netrw's bookmark system fun! s:NetrwBookmark(del,...) -" call Dfunc("s:NetrwBookmark(del=".a:del.",...) a:0=".a:0) if a:0 == 0 if &ft == "netrw" let curbufnr = bufnr("%") if exists("s:netrwmarkfilelist_{curbufnr}") " for every filename in the marked list -" call Decho("bookmark every filename in marked list",'~'.expand("<slnum>")) let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let islocal= expand("%") !~ '^\a\{3,}://' for fname in s:netrwmarkfilelist_{curbufnr} if a:del|call s:DeleteBookmark(fname)|else|call s:MakeBookmark(fname)|endif endfor let curdir = exists("b:netrw_curdir")? b:netrw_curdir : getcwd() call s:NetrwUnmarkList(curbufnr,curdir) - NetrwKeepj call s:NetrwRefresh(islocal,s:NetrwBrowseChgDir(islocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call s:NetrwRefresh(islocal,s:NetrwBrowseChgDir(islocal,'./',0)) NetrwKeepj call winrestview(svpos) else let fname= s:NetrwGetWord() @@ -4651,7 +4460,6 @@ fun! s:NetrwBookmark(del,...) else " bookmark currently open file -" call Decho("bookmark currently open file",'~'.expand("<slnum>")) let fname= expand("%") if a:del|call s:DeleteBookmark(fname)|else|call s:MakeBookmark(fname)|endif endif @@ -4662,7 +4470,6 @@ fun! s:NetrwBookmark(del,...) " by deciding if the current file begins with an url " Globbing cannot be done remotely. let islocal= expand("%") !~ '^\a\{3,}://' -" call Decho("bookmark specified file".((a:0>1)? "s" : ""),'~'.expand("<slnum>")) let i = 1 while i <= a:0 if islocal @@ -4674,9 +4481,7 @@ fun! s:NetrwBookmark(del,...) else let mbfiles= [a:{i}] endif -" call Decho("mbfiles".string(mbfiles),'~'.expand("<slnum>")) for mbfile in mbfiles -" call Decho("mbfile<".mbfile.">",'~'.expand("<slnum>")) if a:del|call s:DeleteBookmark(mbfile)|else|call s:MakeBookmark(mbfile)|endif endfor let i= i + 1 @@ -4685,8 +4490,6 @@ fun! s:NetrwBookmark(del,...) " update the menu call s:NetrwBookmarkMenu() - -" call Dret("s:NetrwBookmark") endfun " --------------------------------------------------------------------- @@ -4758,58 +4561,61 @@ endfun " directory and a new directory name. Also, if the " "new directory name" is actually a file, " NetrwBrowseChgDir() edits the file. -fun! s:NetrwBrowseChgDir(islocal,newdir,...) -" call Dfunc("s:NetrwBrowseChgDir(islocal=".a:islocal."> newdir<".a:newdir.">) a:0=".a:0." win#".winnr()." curpos<".string(getpos("."))."> b:netrw_curdir<".(exists("b:netrw_curdir")? b:netrw_curdir : "").">") -" call Decho("tab#".tabpagenr()." win#".winnr()." buf#".bufnr("%")."<".bufname("%")."> line#".line(".")." col#".col(".")." winline#".winline()." wincol#".wincol(),'~'.expand("<slnum>")) - +" cursor=0: newdir is relative to b:netrw_curdir +" =1: newdir is relative to the path to the word under the cursor in +" tree view +fun! s:NetrwBrowseChgDir(islocal,newdir,cursor,...) let ykeep= @@ if !exists("b:netrw_curdir") " Don't try to change-directory: this can happen, for example, when netrw#ErrorMsg has been called " and the current window is the NetrwMessage window. let @@= ykeep -" call Decho("b:netrw_curdir doesn't exist!",'~'.expand("<slnum>")) -" call Decho("getcwd<".getcwd().">",'~'.expand("<slnum>")) -" call Dredir("ls!","s:NetrwBrowseChgDir") -" call Dret("s:NetrwBrowseChgDir") return endif -" call Decho("b:netrw_curdir<".b:netrw_curdir.">") " NetrwBrowseChgDir; save options and initialize {{{3 -" call Decho("saving options",'~'.expand("<slnum>")) call s:SavePosn(s:netrw_posn) NetrwKeepj call s:NetrwOptionsSave("s:") NetrwKeepj call s:NetrwOptionsSafe(a:islocal) - if has("win32") - let dirname = substitute(b:netrw_curdir,'\\','/','ge') + + let newdir = a:newdir + if a:cursor && exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST && exists("w:netrw_treetop") + " dirname is the path to the word under the cursor + let dirname = s:NetrwTreePath(w:netrw_treetop) + " newdir resolves to a directory and points to a directory in dirname + " /tmp/test/folder_symlink/ -> /tmp/test/original_folder/ + if a:islocal && fnamemodify(dirname, ':t') == newdir && isdirectory(resolve(dirname)) && resolve(dirname) == resolve(newdir) + let dirname = fnamemodify(resolve(dirname), ':p:h:h') + let newdir = fnamemodify(resolve(newdir), ':t') + endif + " Remove trailing "/" + let dirname = substitute(dirname, "/$", "", "") + + " If the word under the cursor is a directory (except for ../), NetrwTreePath + " returns the full path, including the word under the cursor, remove it + if newdir =~ "/$" && newdir != "../" + let dirname = fnamemodify(dirname, ":h") + endif else let dirname = b:netrw_curdir endif - let newdir = a:newdir + if has("win32") + let dirname = substitute(dirname,'\\','/','ge') + endif let dolockout = 0 let dorestore = 1 -" call Decho("win#".winnr(),'~'.expand("<slnum>")) -" call Decho("dirname<".dirname.">",'~'.expand("<slnum>")) -" call Decho("newdir<".newdir.">",'~'.expand("<slnum>")) " ignore <cr>s when done in the banner -" call Decho('(s:NetrwBrowseChgDir) ignore [return]s when done in banner (g:netrw_banner='.g:netrw_banner.")",'~'.expand("<slnum>")) if g:netrw_banner -" call Decho("win#".winnr()." w:netrw_bannercnt=".(exists("w:netrw_bannercnt")? w:netrw_bannercnt : 'n/a')." line(.)#".line('.')." line($)#".line("#"),'~'.expand("<slnum>")) if exists("w:netrw_bannercnt") && line(".") < w:netrw_bannercnt && line("$") >= w:netrw_bannercnt if getline(".") =~# 'Quick Help' -" call Decho("#1: quickhelp=".g:netrw_quickhelp." ro=".&l:ro." ma=".&l:ma." mod=".&l:mod." wrap=".&l:wrap." (filename<".expand("%")."> win#".winnr()." ft<".&ft.">)",'~'.expand("<slnum>")) let g:netrw_quickhelp= (g:netrw_quickhelp + 1)%len(s:QuickHelp) -" call Decho("#2: quickhelp=".g:netrw_quickhelp." ro=".&l:ro." ma=".&l:ma." mod=".&l:mod." wrap=".&l:wrap." (filename<".expand("%")."> win#".winnr()." ft<".&ft.">)",'~'.expand("<slnum>")) setl ma noro nowrap NetrwKeepj call setline(line('.'),'" Quick Help: <F1>:help '.s:QuickHelp[g:netrw_quickhelp]) setl noma nomod nowrap NetrwKeepj call s:NetrwOptionsRestore("s:") -" call Decho("ro=".&l:ro." ma=".&l:ma." mod=".&l:mod." wrap=".&l:wrap." (filename<".expand("%")."> win#".winnr()." ft<".&ft.">)",'~'.expand("<slnum>")) endif endif -" else " Decho -" call Decho("g:netrw_banner=".g:netrw_banner." (no banner)",'~'.expand("<slnum>")) endif " set up o/s-dependent directory recognition pattern @@ -4818,69 +4624,45 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) else let dirpat= '[\/]$' endif -" call Decho("set up o/s-dependent directory recognition pattern: dirname<".dirname."> dirpat<".dirpat.">",'~'.expand("<slnum>")) if dirname !~ dirpat " apparently vim is "recognizing" that it is in a directory and " is removing the trailing "/". Bad idea, so let's put it back. let dirname= dirname.'/' -" call Decho("adjusting dirname<".dirname.'> (put trailing "/" back)','~'.expand("<slnum>")) endif -" call Decho("[newdir<".newdir."> ".((newdir =~ dirpat)? "=~" : "!~")." dirpat<".dirpat.">] && [islocal=".a:islocal."] && [newdir is ".(isdirectory(s:NetrwFile(newdir))? "" : "not ")."a directory]",'~'.expand("<slnum>")) if newdir !~ dirpat && !(a:islocal && isdirectory(s:NetrwFile(s:ComposePath(dirname,newdir)))) " ------------------------------ " NetrwBrowseChgDir: edit a file {{{3 " ------------------------------ -" call Decho('edit-a-file: case "handling a file": win#'.winnr().' newdir<'.newdir.'> !~ dirpat<'.dirpat.">",'~'.expand("<slnum>")) " save position for benefit of Rexplore let s:rexposn_{bufnr("%")}= winsaveview() -" call Decho("edit-a-file: saving posn to s:rexposn_".bufnr("%")."<".string(s:rexposn_{bufnr("%")}).">",'~'.expand("<slnum>")) -" call Decho("edit-a-file: win#".winnr()." buf#".bufnr("%")."<".bufname("%")."> ft=".&ft,'~'.expand("<slnum>")) -" call Decho("edit-a-file: w:netrw_liststyle=".(exists("w:netrw_liststyle")? w:netrw_liststyle : 'n/a')." w:netrw_treedict:".(exists("w:netrw_treedict")? "exists" : 'n/a')." newdir<".newdir.">",'~'.expand("<slnum>")) if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST && exists("w:netrw_treedict") && newdir !~ '^\(/\|\a:\)' -" call Decho("edit-a-file: handle tree listing: w:netrw_treedict<".(exists("w:netrw_treedict")? string(w:netrw_treedict) : 'n/a').">",'~'.expand("<slnum>")) -" call Decho("edit-a-file: newdir<".newdir.">",'~'.expand("<slnum>")) -" let newdir = s:NetrwTreePath(s:netrw_treetop) -" call Decho("edit-a-file: COMBAK why doesn't this recognize file1's directory???") - let dirname= s:NetrwTreeDir(a:islocal) - "COMBAK : not working for a symlink -- but what about a regular file? a directory? -" call Decho("COMBAK : not working for a symlink -- but what about a regular file? a directory?") - " Feb 17, 2019: following if-else-endif restored -- wasn't editing a file in tree mode if dirname =~ '/$' let dirname= dirname.newdir else let dirname= dirname."/".newdir endif -" call Decho("edit-a-file: dirname<".dirname.">",'~'.expand("<slnum>")) -" call Decho("edit-a-file: tree listing",'~'.expand("<slnum>")) elseif newdir =~ '^\(/\|\a:\)' -" call Decho("edit-a-file: handle an url or path starting with /: <".newdir.">",'~'.expand("<slnum>")) let dirname= newdir else let dirname= s:ComposePath(dirname,newdir) endif -" call Decho("edit-a-file: handling a file: dirname<".dirname."> (a:0=".a:0.")",'~'.expand("<slnum>")) " this lets netrw#BrowseX avoid the edit if a:0 < 1 -" call Decho("edit-a-file: (a:0=".a:0."<1) set up windows for editing<".fnameescape(dirname)."> didsplit=".(exists("s:didsplit")? s:didsplit : "doesn't exist"),'~'.expand("<slnum>")) NetrwKeepj call s:NetrwOptionsRestore("s:") let curdir= b:netrw_curdir if !exists("s:didsplit") -" " call Decho("edit-a-file: s:didsplit does not exist; g:netrw_browse_split=".string(g:netrw_browse_split)." win#".winnr()." g:netrw_chgwin=".g:netrw_chgwin",'~'.expand("<slnum>")) if type(g:netrw_browse_split) == 3 " open file in server " Note that g:netrw_browse_split is a List: [servername,tabnr,winnr] -" call Decho("edit-a-file: open file in server",'~'.expand("<slnum>")) call s:NetrwServerEdit(a:islocal,dirname) -" call Dret("s:NetrwBrowseChgDir") return elseif g:netrw_browse_split == 1 " horizontally splitting the window first -" call Decho("edit-a-file: horizontally splitting window prior to edit",'~'.expand("<slnum>")) let winsz= (g:netrw_winsize > 0)? (g:netrw_winsize*winheight(0))/100 : -g:netrw_winsize exe "keepalt ".(g:netrw_alto? "bel " : "abo ").winsz."wincmd s" if !&ea @@ -4890,7 +4672,6 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) elseif g:netrw_browse_split == 2 " vertically splitting the window first -" call Decho("edit-a-file: vertically splitting window prior to edit",'~'.expand("<slnum>")) let winsz= (g:netrw_winsize > 0)? (g:netrw_winsize*winwidth(0))/100 : -g:netrw_winsize exe "keepalt ".(g:netrw_alto? "top " : "bot ")."vert ".winsz."wincmd s" if !&ea @@ -4900,7 +4681,6 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) elseif g:netrw_browse_split == 3 " open file in new tab -" call Decho("edit-a-file: opening new tab prior to edit",'~'.expand("<slnum>")) keepalt tabnew if !exists("b:netrw_curdir") let b:netrw_curdir= getcwd() @@ -4909,21 +4689,17 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) elseif g:netrw_browse_split == 4 " act like "P" (ie. open previous window) -" call Decho("edit-a-file: use previous window for edit",'~'.expand("<slnum>")) if s:NetrwPrevWinOpen(2) == 3 let @@= ykeep -" call Dret("s:NetrwBrowseChgDir") return endif call s:SetRexDir(a:islocal,curdir) else " handling a file, didn't split, so remove menu -" call Decho("edit-a-file: handling a file+didn't split, so remove menu",'~'.expand("<slnum>")) call s:NetrwMenu(0) " optional change to window if g:netrw_chgwin >= 1 -" call Decho("edit-a-file: changing window to #".g:netrw_chgwin.": (due to g:netrw_chgwin)",'~'.expand("<slnum>")) if winnr("$")+1 == g:netrw_chgwin " if g:netrw_chgwin is set to one more than the last window, then " vertically split the last window to make that window available. @@ -4947,21 +4723,17 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) let dolockout= 1 endif if a:islocal -" call Decho("edit-a-file: edit local file: exe e! ".fnameescape(dirname),'~'.expand("<slnum>")) " some like c-^ to return to the last edited file " others like c-^ to return to the netrw buffer " Apr 30, 2020: used to have e! here. That can cause loss of a modified file, " so emit error E37 instead. call s:NetrwEditFile("e","",dirname) -" call Decho("edit-a-file: after e ".dirname.": hidden=".&hidden." bufhidden<".&bufhidden."> mod=".&mod,'~'.expand("<slnum>")) - " COMBAK -- cuc cul related call s:NetrwCursor(1) if &hidden || &bufhidden == "hide" " file came from vim's hidden storage. Don't "restore" options with it. let dorestore= 0 endif else -" call Decho("edit-a-file: remote file: NetrwBrowse will edit it",'~'.expand("<slnum>")) endif " handle g:Netrw_funcref -- call external-to-netrw functions @@ -4969,12 +4741,9 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) " or as a list of function references. It will ignore anything that's not " a function reference. See :help Funcref for information about function references. if exists("g:Netrw_funcref") -" call Decho("edit-a-file: handle optional Funcrefs",'~'.expand("<slnum>")) if type(g:Netrw_funcref) == 2 -" call Decho("edit-a-file: handling a g:Netrw_funcref",'~'.expand("<slnum>")) NetrwKeepj call g:Netrw_funcref() elseif type(g:Netrw_funcref) == 3 -" call Decho("edit-a-file: handling a list of g:Netrw_funcrefs",'~'.expand("<slnum>")) for Fncref in g:Netrw_funcref if type(Fncref) == 2 NetrwKeepj call Fncref() @@ -4988,7 +4757,6 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) " ---------------------------------------------------- " NetrwBrowseChgDir: just go to the new directory spec {{{3 " ---------------------------------------------------- -" call Decho('goto-newdir: case "just go to new directory spec": newdir<'.newdir.'>','~'.expand("<slnum>")) let dirname = newdir NetrwKeepj call s:SetRexDir(a:islocal,dirname) NetrwKeepj call s:NetrwOptionsRestore("s:") @@ -4998,7 +4766,6 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) " --------------------------------------------- " NetrwBrowseChgDir: refresh the directory list {{{3 " --------------------------------------------- -" call Decho('(s:NetrwBrowseChgDir)refresh-dirlist: case "refresh directory listing": newdir == "./"','~'.expand("<slnum>")) NetrwKeepj call s:SetRexDir(a:islocal,dirname) norm! m` @@ -5006,26 +4773,21 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) " -------------------------------------- " NetrwBrowseChgDir: go up one directory {{{3 " -------------------------------------- -" call Decho('(s:NetrwBrowseChgDir)go-up: case "go up one directory": newdir == "../"','~'.expand("<slnum>")) if w:netrw_liststyle == s:TREELIST && exists("w:netrw_treedict") " force a refresh -" call Decho("go-up: clear buffer<".expand("%")."> with :%d",'~'.expand("<slnum>")) -" call Decho("go-up: setl noro ma",'~'.expand("<slnum>")) setl noro ma NetrwKeepj %d _ endif if has("amiga") " amiga -" call Decho('go-up: case "go up one directory": newdir == "../" and amiga','~'.expand("<slnum>")) if a:islocal let dirname= substitute(dirname,'^\(.*[/:]\)\([^/]\+$\)','\1','') let dirname= substitute(dirname,'/$','','') else let dirname= substitute(dirname,'^\(.*[/:]\)\([^/]\+/$\)','\1','') endif -" call Decho("go-up: amiga: dirname<".dirname."> (go up one dir)",'~'.expand("<slnum>")) elseif !g:netrw_cygwin && has("win32") " windows @@ -5040,11 +4802,9 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) if dirname =~ '^\a:$' let dirname= dirname.'/' endif -" call Decho("go-up: windows: dirname<".dirname."> (go up one dir)",'~'.expand("<slnum>")) else " unix or cygwin -" call Decho('(s:NetrwBrowseChgDir)go-up: case "go up one directory": newdir == "../" and unix or cygwin','~'.expand("<slnum>")) if a:islocal let dirname= substitute(dirname,'^\(.*\)/\([^/]\+\)/$','\1','') if dirname == "" @@ -5053,7 +4813,6 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) else let dirname= substitute(dirname,'^\(\a\{3,}://.\{-}/\{1,2}\)\(.\{-}\)\([^/]\+\)/$','\1\2','') endif -" call Decho("go-up: unix: dirname<".dirname."> (go up one dir)",'~'.expand("<slnum>")) endif NetrwKeepj call s:SetRexDir(a:islocal,dirname) norm! m` @@ -5062,69 +4821,48 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) " -------------------------------------- " NetrwBrowseChgDir: Handle Tree Listing {{{3 " -------------------------------------- -" call Decho('(s:NetrwBrowseChgDir)tree-list: case liststyle is TREELIST and w:netrw_treedict exists','~'.expand("<slnum>")) " force a refresh (for TREELIST, NetrwTreeDir() will force the refresh) -" call Decho("tree-list: setl noro ma",'~'.expand("<slnum>")) setl noro ma if !(exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST && exists("b:netrw_curdir")) -" call Decho("tree-list: clear buffer<".expand("%")."> with :%d (force refresh)",'~'.expand("<slnum>")) NetrwKeepj %d _ endif let treedir = s:NetrwTreeDir(a:islocal) -" call Decho("tree-list: treedir<".treedir.">",'~'.expand("<slnum>")) let s:treecurpos = winsaveview() let haskey = 0 -" call Decho("tree-list: w:netrw_treedict<".string(w:netrw_treedict).">",'~'.expand("<slnum>")) " search treedict for tree dir as-is -" call Decho("tree-list: search treedict for tree dir as-is",'~'.expand("<slnum>")) if has_key(w:netrw_treedict,treedir) -" call Decho('(s:NetrwBrowseChgDir)tree-list: ....searched for treedir<'.treedir.'> : found it!','~'.expand("<slnum>")) let haskey= 1 else -" call Decho('(s:NetrwBrowseChgDir)tree-list: ....searched for treedir<'.treedir.'> : not found','~'.expand("<slnum>")) endif " search treedict for treedir with a [/@] appended -" call Decho("tree-list: search treedict for treedir with a [/@] appended",'~'.expand("<slnum>")) if !haskey && treedir !~ '[/@]$' if has_key(w:netrw_treedict,treedir."/") let treedir= treedir."/" -" call Decho('(s:NetrwBrowseChgDir)tree-list: ....searched.for treedir<'.treedir.'> found it!','~'.expand("<slnum>")) let haskey = 1 else -" call Decho('(s:NetrwBrowseChgDir)tree-list: ....searched for treedir<'.treedir.'/> : not found','~'.expand("<slnum>")) endif endif " search treedict for treedir with any trailing / elided -" call Decho("tree-list: search treedict for treedir with any trailing / elided",'~'.expand("<slnum>")) if !haskey && treedir =~ '/$' let treedir= substitute(treedir,'/$','','') if has_key(w:netrw_treedict,treedir) -" call Decho('(s:NetrwBrowseChgDir)tree-list: ....searched.for treedir<'.treedir.'> found it!','~'.expand("<slnum>")) let haskey = 1 else -" call Decho('(s:NetrwBrowseChgDir)tree-list: ....searched for treedir<'.treedir.'> : not found','~'.expand("<slnum>")) endif endif -" call Decho("haskey=".haskey,'~'.expand("<slnum>")) if haskey " close tree listing for selected subdirectory -" call Decho("tree-list: closing selected subdirectory<".dirname.">",'~'.expand("<slnum>")) call remove(w:netrw_treedict,treedir) -" call Decho("tree-list: removed entry<".treedir."> from treedict",'~'.expand("<slnum>")) -" call Decho("tree-list: yielding treedict<".string(w:netrw_treedict).">",'~'.expand("<slnum>")) let dirname= w:netrw_treetop else " go down one directory let dirname= substitute(treedir,'/*$','/','') -" call Decho("tree-list: go down one dir: treedir<".treedir.">",'~'.expand("<slnum>")) -" call Decho("tree-list: ... : dirname<".dirname.">",'~'.expand("<slnum>")) endif NetrwKeepj call s:SetRexDir(a:islocal,dirname) -" call Decho("setting s:treeforceredraw to true",'~'.expand("<slnum>")) let s:treeforceredraw = 1 else @@ -5132,7 +4870,6 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) " NetrwBrowseChgDir: Go down one directory {{{3 " ---------------------------------------- let dirname = s:ComposePath(dirname,newdir) -" call Decho("go down one dir: dirname<".dirname."> newdir<".newdir.">",'~'.expand("<slnum>")) NetrwKeepj call s:SetRexDir(a:islocal,dirname) norm! m` endif @@ -5143,29 +4880,18 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) if dorestore " dorestore is zero'd when a local file was hidden or bufhidden; " in such a case, we want to keep whatever settings it may have. -" call Decho("doing option restore (dorestore=".dorestore.")",'~'.expand("<slnum>")) NetrwKeepj call s:NetrwOptionsRestore("s:") -" else " Decho -" call Decho("skipping option restore (dorestore==0): hidden=".&hidden." bufhidden=".&bufhidden." mod=".&mod,'~'.expand("<slnum>")) endif if dolockout && dorestore -" call Decho("restore: filewritable(dirname<".dirname.">)=".filewritable(dirname),'~'.expand("<slnum>")) if filewritable(dirname) -" call Decho("restore: doing modification lockout settings: ma nomod noro",'~'.expand("<slnum>")) -" call Decho("restore: setl ma nomod noro",'~'.expand("<slnum>")) setl ma noro nomod -" call Decho("restore: ro=".&l:ro." ma=".&l:ma." mod=".&l:mod." wrap=".&l:wrap." (filename<".expand("%")."> win#".winnr()." ft<".&ft.">)",'~'.expand("<slnum>")) else -" call Decho("restore: doing modification lockout settings: ma nomod ro",'~'.expand("<slnum>")) -" call Decho("restore: setl ma nomod noro",'~'.expand("<slnum>")) setl ma ro nomod -" call Decho("restore: ro=".&l:ro." ma=".&l:ma." mod=".&l:mod." wrap=".&l:wrap." (filename<".expand("%")."> win#".winnr()." ft<".&ft.">)",'~'.expand("<slnum>")) endif endif call s:RestorePosn(s:netrw_posn) let @@= ykeep -" call Dret("s:NetrwBrowseChgDir <".dirname."> : curpos<".string(getpos(".")).">") return dirname endfun @@ -5174,19 +4900,16 @@ endfun " for thin, long, and wide: cursor placed just after banner " for tree, keeps cursor on current filename fun! s:NetrwBrowseUpDir(islocal) -" call Dfunc("s:NetrwBrowseUpDir(islocal=".a:islocal.")") if exists("w:netrw_bannercnt") && line(".") < w:netrw_bannercnt-1 " this test needed because occasionally this function seems to be incorrectly called " when multiple leftmouse clicks are taken when atop the one line help in the banner. " I'm allowing the very bottom line to permit a "-" exit so that one may escape empty " directories. -" call Dret("s:NetrwBrowseUpDir : cursor not in file area") return endif norm! 0 if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST && exists("w:netrw_treedict") -" call Decho("case: treestyle",'~'.expand("<slnum>")) let curline= getline(".") let swwline= winline() - 1 if exists("w:netrw_treetop") @@ -5200,22 +4923,18 @@ fun! s:NetrwBrowseUpDir(islocal) let curfile = getline(".") let curpath = s:NetrwTreePath(w:netrw_treetop) if a:islocal - call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,'../')) + call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,'../',0)) else - call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,'../')) + call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,'../',0)) endif -" call Decho("looking for curfile<^".s:treedepthstring.curfile.">",'~'.expand("<slnum>")) -" call Decho("having curpath<".curpath.">",'~'.expand("<slnum>")) if w:netrw_treetop == '/' keepj call search('^\M'.curfile,"w") elseif curfile == '../' keepj call search('^\M'.curfile,"wb") else -" call Decho("search(^\\M".s:treedepthstring.curfile.") backwards")) while 1 keepj call search('^\M'.s:treedepthstring.curfile,"wb") let treepath= s:NetrwTreePath(w:netrw_treetop) -" call Decho("..current treepath<".treepath.">",'~'.expand("<slnum>")) if treepath == curpath break endif @@ -5223,7 +4942,6 @@ fun! s:NetrwBrowseUpDir(islocal) endif else -" call Decho("case: not treestyle",'~'.expand("<slnum>")) call s:SavePosn(s:netrw_posn) if exists("b:netrw_curdir") let curdir= b:netrw_curdir @@ -5231,44 +4949,140 @@ fun! s:NetrwBrowseUpDir(islocal) let curdir= expand(getcwd()) endif if a:islocal - call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,'../')) + call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,'../',0)) else - call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,'../')) + call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,'../',0)) endif call s:RestorePosn(s:netrw_posn) let curdir= substitute(curdir,'^.*[\/]','','') let curdir= '\<'. escape(curdir, '~'). '/' call search(curdir,'wc') endif -" call Dret("s:NetrwBrowseUpDir") endfun +func s:redir() + " set up redirection (avoids browser messages) + " by default if not set, g:netrw_suppress_gx_mesg is true + if get(g:, 'netrw_suppress_gx_mesg', 1) + if &srr =~# "%s" + return printf(&srr, has("win32") ? "nul" : "/dev/null") + else + return &srr .. (has("win32") ? "nul" : "/dev/null") + endif + endif + return '' +endfunc + +if has('unix') + if has('win32unix') + " Cygwin provides cygstart + if executable('cygstart') + fun! netrw#Launch(args) + exe 'silent ! cygstart --hide' a:args s:redir() | redraw! + endfun + elseif !empty($MSYSTEM) && executable('start') + " MSYS2/Git Bash comes by default without cygstart; see + " https://www.msys2.org/wiki/How-does-MSYS2-differ-from-Cygwin + " Instead it provides /usr/bin/start script running `cmd.exe //c start` + " Adding "" //b` sets void title, hides cmd window and blocks path conversion + " of /b to \b\ " by MSYS2; see https://www.msys2.org/docs/filesystem-paths/ + fun! netrw#Launch(args) + exe 'silent !start "" //b' a:args s:redir() | redraw! + endfun + else + " imitate /usr/bin/start script for other environments and hope for the best + fun! netrw#Launch(args) + exe 'silent !cmd //c start "" //b' a:args s:redir() | redraw! + endfun + endif + elseif exists('$WSL_DISTRO_NAME') " use cmd.exe to start GUI apps in WSL + fun! netrw#Launch(args) + let args = a:args + exe 'silent !' .. + \ ((args =~? '\v<\f+\.(exe|com|bat|cmd)>') ? + \ 'cmd.exe /c start /b ' .. args : + \ 'nohup ' .. args .. ' ' .. s:redir() .. ' &') + \ | redraw! + endfun + else + fun! netrw#Launch(args) + exe ':silent ! nohup' a:args s:redir() '&' | redraw! + endfun + endif +elseif has('win32') + fun! netrw#Launch(args) + exe 'silent !' .. (&shell =~? '\<cmd\.exe\>' ? '' : 'cmd.exe /c') + \ 'start "" /b' a:args s:redir() | redraw! + endfun +else + fun! netrw#Launch(dummy) + echom 'No common launcher found' + endfun +endif + +" Git Bash +if has('win32unix') + " (cyg)start suffices + let s:os_viewer = '' +" Windows / WSL +elseif executable('explorer.exe') + let s:os_viewer = 'explorer.exe' +" Linux / BSD +elseif executable('xdg-open') + let s:os_viewer = 'xdg-open' +" MacOS +elseif executable('open') + let s:os_viewer = 'open' +endif + +fun! s:viewer() + if exists('g:netrw_browsex_viewer') && executable(g:netrw_browsex_viewer) + " extract any viewing options. Assumes that they're set apart by spaces. + " 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*','','')." " + let oviewer = '' + let cnt = 1 + while !executable(viewer) && viewer != oviewer + let viewer = substitute(g:netrw_browsex_viewer,'^\(\(^\S\+\s\+\)\{'.cnt.'}\S\+\)\(.*\)$','\1','') + let viewopt = substitute(g:netrw_browsex_viewer,'^\(\(^\S\+\s\+\)\{'.cnt.'}\S\+\)\(.*\)$','\3','')." " + let cnt = cnt + 1 + let oviewer = viewer + " call Decho("!exe: viewer<".viewer."> viewopt<".viewopt.">",'~'.expand("<slnum>")) + endwhile + else + let viewer = g:netrw_browsex_viewer + let viewopt = "" + endif + " call Decho("viewer<".viewer."> viewopt<".viewopt.">",'~'.expand("<slnum>")) + return viewer .. ' ' .. viewopt + else + if !exists('s:os_viewer') + call netrw#ErrorMsg(s:ERROR,"No program to open this path found. See :help Open for more information.",106) + else + return s:os_viewer + endif + endif +endfun + +fun! netrw#Open(file) abort + call netrw#Launch(s:viewer() .. ' ' .. shellescape(a:file, 1)) +endf + +if !exists('g:netrw_regex_url') + let g:netrw_regex_url = '\%(\%(http\|ftp\|irc\)s\?\|file\)://\S\{-}' +endif + " --------------------------------------------------------------------- " 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) - 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 =~ '/$' + if 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") - return endif -" call Decho("not a local file nor a webpage request",'~'.expand("<slnum>")) if exists("g:netrw_browsex_viewer") && exists("g:netrw_browsex_support_remote") && !g:netrw_browsex_support_remote let remote = a:remote @@ -5278,7 +5092,6 @@ fun! netrw#BrowseX(fname,remote) let ykeep = @@ let screenposn = winsaveview() -" call Decho("saving posn to screenposn<".string(screenposn).">",'~'.expand("<slnum>")) " need to save and restore aw setting as gx can invoke this function from non-netrw buffers let awkeep = &aw @@ -5289,22 +5102,18 @@ fun! netrw#BrowseX(fname,remote) if exists("g:Netrw_corehandler") if type(g:Netrw_corehandler) == 2 " g:Netrw_corehandler is a function reference (see :help Funcref) -" call Decho("g:Netrw_corehandler is a funcref",'~'.expand("<slnum>")) call g:Netrw_corehandler(s:NetrwFile(a:fname)) elseif type(g:Netrw_corehandler) == 3 " g:Netrw_corehandler is a List of function references (see :help Funcref) -" call Decho("g:Netrw_corehandler is a List",'~'.expand("<slnum>")) for Fncref in g:Netrw_corehandler if type(Fncref) == 2 call Fncref(a:fname) endif endfor endif -" call Decho("restoring posn: screenposn<".string(screenposn).">,'~'.expand("<slnum>"))" call winrestview(screenposn) let @@= ykeep let &aw= awkeep -" call Dret("netrw#BrowseX : coredump handler invoked") return endif endif @@ -5318,171 +5127,35 @@ fun! netrw#BrowseX(fname,remote) if exten =~ "[\\/]" let exten= "" endif -" call Decho("exten<".exten.">",'~'.expand("<slnum>")) if remote == 1 " create a local copy -" call Decho("remote: remote=".remote.": create a local copy of <".a:fname.">",'~'.expand("<slnum>")) setl bh=delete call netrw#NetRead(3,a:fname) " attempt to rename tempfile let basename= substitute(a:fname,'^\(.*\)/\(.*\)\.\([^.]*\)$','\2','') let newname = substitute(s:netrw_tmpfile,'^\(.*\)/\(.*\)\.\([^.]*\)$','\1/'.basename.'.\3','') -" call Decho("basename<".basename.">",'~'.expand("<slnum>")) -" call Decho("newname <".newname.">",'~'.expand("<slnum>")) if s:netrw_tmpfile != newname && newname != "" if rename(s:netrw_tmpfile,newname) == 0 " renaming succeeded -" call Decho("renaming succeeded (tmpfile<".s:netrw_tmpfile."> to <".newname.">)") let fname= newname else " renaming failed -" call Decho("renaming failed (tmpfile<".s:netrw_tmpfile."> to <".newname.">)") let fname= s:netrw_tmpfile endif else let fname= s:netrw_tmpfile endif else -" call Decho("local: remote=".remote.": handling local copy of <".a:fname.">",'~'.expand("<slnum>")) let fname= a:fname " special ~ handler for local if fname =~ '^\~' && expand("$HOME") != "" -" call Decho('invoking special ~ handler','~'.expand("<slnum>")) let fname= s:NetrwFile(substitute(fname,'^\~',expand("$HOME"),'')) endif endif -" call Decho("fname<".fname.">",'~'.expand("<slnum>")) -" call Decho("exten<".exten."> "."netrwFileHandlers#NFH_".exten."():exists=".exists("*netrwFileHandlers#NFH_".exten),'~'.expand("<slnum>")) - - " set up redirection (avoids browser messages) - " by default, g:netrw_suppress_gx_mesg is true - if g:netrw_suppress_gx_mesg - if &srr =~ "%s" - if has("win32") - let redir= substitute(&srr,"%s","nul","") - else - let redir= substitute(&srr,"%s","/dev/null","") - endif - elseif has("win32") - let redir= &srr . "nul" - else - let redir= &srr . "/dev/null" - endif - else - let redir= "" - endif -" call Decho("set up redirection: redir{".redir."} srr{".&srr."}",'~'.expand("<slnum>")) - - " extract any viewing options. Assumes that they're set apart by spaces. - if exists("g:netrw_browsex_viewer") -" 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*','','')." " - let oviewer = '' - let cnt = 1 - while !executable(viewer) && viewer != oviewer - let viewer = substitute(g:netrw_browsex_viewer,'^\(\(^\S\+\s\+\)\{'.cnt.'}\S\+\)\(.*\)$','\1','') - let viewopt = substitute(g:netrw_browsex_viewer,'^\(\(^\S\+\s\+\)\{'.cnt.'}\S\+\)\(.*\)$','\3','')." " - let cnt = cnt + 1 - let oviewer = viewer -" call Decho("!exe: viewer<".viewer."> viewopt<".viewopt.">",'~'.expand("<slnum>")) - endwhile - else - let viewer = g:netrw_browsex_viewer - let viewopt = "" - endif -" call Decho("viewer<".viewer."> viewopt<".viewopt.">",'~'.expand("<slnum>")) - endif - - " 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("(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("(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") -" 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") - call s:NetrwExe('sil! !rundll32 url.dll,FileProtocolHandler '.s:ShellEscape(fname,1)) - else - call netrw#ErrorMsg(s:WARNING,"rundll32 not on path",74) - endif - let ret= v:shell_error - - elseif has("win32unix") - let winfname= 'c:\cygwin'.substitute(fname,'/','\\','g') -" 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 - let ret= v:shell_error - - elseif has("unix") && $DESKTOP_SESSION == "mate" && executable("atril") -" 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("fname<".fname.">") -" call Decho("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("kfmclient") && s:CheckIfKde() -" 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("(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") && executable("xdg-open") -" 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("(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 - " restoring redraw! after external file handlers - redraw! + " although shellescape(..., 1) is used in netrw#Open(), it's insufficient + call netrw#Open(escape(fname, '#%')) " cleanup: remove temporary file, " delete current buffer if success with handler, @@ -5490,7 +5163,6 @@ fun! netrw#BrowseX(fname,remote) " Feb 12, 2008: had to de-activate removal of " temporary file because it wasn't getting seen. " if remote == 1 && fname != a:fname -"" call Decho("deleting temporary file<".fname.">",'~'.expand("<slnum>")) " call s:NetrwDelete(fname) " endif @@ -5499,16 +5171,11 @@ fun! netrw#BrowseX(fname,remote) if g:netrw_use_noswf setl noswf endif - if use_ctrlo - exe "sil! NetrwKeepj norm! \<c-o>" - endif + exe "sil! NetrwKeepj norm! \<c-o>" endif -" call Decho("restoring posn to screenposn<".string(screenposn).">",'~'.expand("<slnum>")) call winrestview(screenposn) let @@ = ykeep let &aw= awkeep - -" call Dret("netrw#BrowseX") endfun " --------------------------------------------------------------------- @@ -5520,12 +5187,37 @@ fun! netrw#GX() if &ft == "netrw" let fname= s:NetrwGetWord() else - let fname= expand((exists("g:netrw_gx")? g:netrw_gx : '<cfile>')) + let fname= exists("g:netrw_gx")? expand(g:netrw_gx) : s:GetURL() endif " call Dret("netrw#GX <".fname.">") return fname endfun +fun! s:GetURL() abort + let URL = '' + if exists('*Netrw_get_URL_' .. &filetype) + let URL = call('Netrw_get_URL_' .. &filetype, []) + endif + if !empty(URL) | return URL | endif + " URLs end in letter, digit or forward slash + let URL = matchstr(expand("<cWORD>"), '\<' .. g:netrw_regex_url .. '\ze[^A-Za-z0-9/]*$') + if !empty(URL) | return URL | endif + + " Is it a file in the current work dir ... + let file = expand("<cfile>") + if filereadable(file) | return file | endif + " ... or in that of the current buffer? + let path = fnamemodify(expand('%'), ':p') + if isdirectory(path) + let dir = path + elseif filereadable(path) + let dir = fnamemodify(path, ':h') + endif + if exists('dir') && filereadable(dir..'/'..file) | return dir..'/'..file | endif + + return '' +endf + " --------------------------------------------------------------------- " netrw#BrowseXVis: used by gx in visual mode to select a file for browsing {{{2 fun! netrw#BrowseXVis() @@ -5600,23 +5292,20 @@ endfun " --------------------------------------------------------------------- " s:NetrwChgPerm: (implements "gp") change file permission {{{2 fun! s:NetrwChgPerm(islocal,curdir) -" call Dfunc("s:NetrwChgPerm(islocal=".a:islocal." curdir<".a:curdir.">)") let ykeep = @@ call inputsave() let newperm= input("Enter new permission: ") call inputrestore() let chgperm= substitute(g:netrw_chgperm,'\<FILENAME\>',s:ShellEscape(expand("<cfile>")),'') let chgperm= substitute(chgperm,'\<PERM\>',s:ShellEscape(newperm),'') -" call Decho("chgperm<".chgperm.">",'~'.expand("<slnum>")) call system(chgperm) if v:shell_error != 0 NetrwKeepj call netrw#ErrorMsg(1,"changing permission on file<".expand("<cfile>")."> seems to have failed",75) endif if a:islocal - NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) endif let @@= ykeep -" call Dret("s:NetrwChgPerm") endfun " --------------------------------------------------------------------- @@ -5697,8 +5386,6 @@ endfun " --------------------------------------------------------------------- " s:NetrwExploreListUniq: {{{2 fun! s:NetrwExploreListUniq(explist) -" call Dfunc("s:NetrwExploreListUniq(explist<".string(a:explist).">)") - " this assumes that the list is already sorted let newexplist= [] for member in a:explist @@ -5707,15 +5394,12 @@ fun! s:NetrwExploreListUniq(explist) let newexplist = newexplist + [ member ] endif endfor - -" call Dret("s:NetrwExploreListUniq newexplist<".string(newexplist).">") return newexplist endfun " --------------------------------------------------------------------- " s:NetrwForceChgDir: (gd support) Force treatment as a directory {{{2 fun! s:NetrwForceChgDir(islocal,newdir) -" call Dfunc("s:NetrwForceChgDir(islocal=".a:islocal." newdir<".a:newdir.">)") let ykeep= @@ if a:newdir !~ '/$' " ok, looks like force is needed to get directory-style treatment @@ -5726,15 +5410,13 @@ fun! s:NetrwForceChgDir(islocal,newdir) else let newdir= a:newdir.'/' endif -" call Decho("adjusting newdir<".newdir."> due to gd",'~'.expand("<slnum>")) else " should already be getting treatment as a directory let newdir= a:newdir endif - let newdir= s:NetrwBrowseChgDir(a:islocal,newdir) + let newdir= s:NetrwBrowseChgDir(a:islocal,newdir,0) call s:NetrwBrowse(a:islocal,newdir) let @@= ykeep -" call Dret("s:NetrwForceChgDir") endfun " --------------------------------------------------------------------- @@ -5760,7 +5442,7 @@ fun! s:NetrwGlob(direntry,expr,pare) endif let w:netrw_liststyle= keep_liststyle else - let path= s:ComposePath(fnameescape(a:direntry),a:expr) + let path= s:ComposePath(fnameescape(a:direntry), a:expr) if has("win32") " escape [ so it is not detected as wildcard character, see :h wildcard let path= substitute(path, '[', '[[]', 'g') @@ -5774,25 +5456,22 @@ fun! s:NetrwGlob(direntry,expr,pare) let filelist= map(filelist,'substitute(v:val, "^.*/", "", "")') endif endif -" call Dret("s:NetrwGlob ".string(filelist)) return filelist endfun " --------------------------------------------------------------------- " s:NetrwForceFile: (gf support) Force treatment as a file {{{2 fun! s:NetrwForceFile(islocal,newfile) -" call Dfunc("s:NetrwForceFile(islocal=".a:islocal." newdir<".a:newfile.">)") if a:newfile =~ '[/@*=|\\]$' let newfile= substitute(a:newfile,'.$','','') else let newfile= a:newfile endif if a:islocal - call s:NetrwBrowseChgDir(a:islocal,newfile) + call s:NetrwBrowseChgDir(a:islocal,newfile,0) else - call s:NetrwBrowse(a:islocal,s:NetrwBrowseChgDir(a:islocal,newfile)) + call s:NetrwBrowse(a:islocal,s:NetrwBrowseChgDir(a:islocal,newfile,0)) endif -" call Dret("s:NetrwForceFile") endfun " --------------------------------------------------------------------- @@ -5803,24 +5482,18 @@ endfun " 1: show not-hidden files " 2: show hidden files only fun! s:NetrwHide(islocal) -" call Dfunc("NetrwHide(islocal=".a:islocal.") g:netrw_hide=".g:netrw_hide) let ykeep= @@ let svpos= winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) if exists("s:netrwmarkfilelist_{bufnr('%')}") -" call Decho("((g:netrw_hide == 1)? "unhide" : "hide")." files in markfilelist<".string(s:netrwmarkfilelist_{bufnr("%")}).">",'~'.expand("<slnum>")) -" call Decho("g:netrw_list_hide<".g:netrw_list_hide.">",'~'.expand("<slnum>")) " hide the files in the markfile list for fname in s:netrwmarkfilelist_{bufnr("%")} -" call Decho("match(g:netrw_list_hide<".g:netrw_list_hide.'> fname<\<'.fname.'\>>)='.match(g:netrw_list_hide,'\<'.fname.'\>')." l:isk=".&l:isk,'~'.expand("<slnum>")) if match(g:netrw_list_hide,'\<'.fname.'\>') != -1 " remove fname from hiding list let g:netrw_list_hide= substitute(g:netrw_list_hide,'..\<'.escape(fname,g:netrw_fname_escape).'\>..','','') let g:netrw_list_hide= substitute(g:netrw_list_hide,',,',',','g') let g:netrw_list_hide= substitute(g:netrw_list_hide,'^,\|,$','','') -" call Decho("unhide: g:netrw_list_hide<".g:netrw_list_hide.">",'~'.expand("<slnum>")) else " append fname to hiding list if exists("g:netrw_list_hide") && g:netrw_list_hide != "" @@ -5828,7 +5501,6 @@ fun! s:NetrwHide(islocal) else let g:netrw_list_hide= '\<'.escape(fname,g:netrw_fname_escape).'\>' endif -" call Decho("hide: g:netrw_list_hide<".g:netrw_list_hide.">",'~'.expand("<slnum>")) endif endfor NetrwKeepj call s:NetrwUnmarkList(bufnr("%"),b:netrw_curdir) @@ -5842,64 +5514,49 @@ fun! s:NetrwHide(islocal) if g:netrw_hide && g:netrw_list_hide == "" NetrwKeepj call netrw#ErrorMsg(s:WARNING,"your hiding list is empty!",49) let @@= ykeep -" call Dret("NetrwHide") return endif endif - NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) NetrwKeepj call winrestview(svpos) let @@= ykeep -" call Dret("NetrwHide") endfun " --------------------------------------------------------------------- " s:NetrwHideEdit: allows user to edit the file/directory hiding list {{{2 fun! s:NetrwHideEdit(islocal) -" call Dfunc("NetrwHideEdit(islocal=".a:islocal.")") - let ykeep= @@ " save current cursor position let svpos= winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) " get new hiding list from user call inputsave() let newhide= input("Edit Hiding List: ",g:netrw_list_hide) call inputrestore() let g:netrw_list_hide= newhide -" call Decho("new g:netrw_list_hide<".g:netrw_list_hide.">",'~'.expand("<slnum>")) " refresh the listing - sil NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,"./")) + sil NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,"./",0)) " restore cursor position -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) call winrestview(svpos) let @@= ykeep - -" call Dret("NetrwHideEdit") endfun " --------------------------------------------------------------------- " s:NetrwHidden: invoked by "gh" {{{2 fun! s:NetrwHidden(islocal) -" call Dfunc("s:NetrwHidden()") let ykeep= @@ " save current position let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) if g:netrw_list_hide =~ '\(^\|,\)\\(^\\|\\s\\s\\)\\zs\\.\\S\\+' " remove .file pattern from hiding list -" call Decho("remove .file pattern from hiding list",'~'.expand("<slnum>")) let g:netrw_list_hide= substitute(g:netrw_list_hide,'\(^\|,\)\\(^\\|\\s\\s\\)\\zs\\.\\S\\+','','') elseif s:Strlen(g:netrw_list_hide) >= 1 -" call Decho("add .file pattern from hiding list",'~'.expand("<slnum>")) let g:netrw_list_hide= g:netrw_list_hide . ',\(^\|\s\s\)\zs\.\S\+' else -" call Decho("set .file pattern as hiding list",'~'.expand("<slnum>")) let g:netrw_list_hide= '\(^\|\s\s\)\zs\.\S\+' endif if g:netrw_list_hide =~ '^,' @@ -5907,11 +5564,9 @@ fun! s:NetrwHidden(islocal) endif " refresh screen and return to saved position - NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) NetrwKeepj call winrestview(svpos) let @@= ykeep -" call Dret("s:NetrwHidden") endfun " --------------------------------------------------------------------- @@ -5946,7 +5601,6 @@ fun! s:NetrwLeftmouse(islocal) if &ft != "netrw" return endif -" call Dfunc("s:NetrwLeftmouse(islocal=".a:islocal.")") let ykeep= @@ " check if the status bar was clicked on instead of a file/directory name @@ -5958,36 +5612,30 @@ fun! s:NetrwLeftmouse(islocal) let mouse_lnum = v:mouse_lnum let wlastline = line('w$') let lastline = line('$') -" call Decho("v:mouse_lnum=".mouse_lnum." line(w$)=".wlastline." line($)=".lastline." v:mouse_win=".v:mouse_win." winnr#".winnr(),'~'.expand("<slnum>")) -" call Decho("v:mouse_col =".v:mouse_col." col=".col(".")." wincol =".wincol()." winwidth =".winwidth(0),'~'.expand("<slnum>")) if mouse_lnum >= wlastline + 1 || v:mouse_win != winnr() " appears to be a status bar leftmouse click let @@= ykeep -" call Dret("s:NetrwLeftmouse : detected a status bar leftmouse click") return endif " Dec 04, 2013: following test prevents leftmouse selection/deselection of directories and files in treelist mode " Windows are separated by vertical separator bars - but the mouse seems to be doing what it should when dragging that bar " without this test when its disabled. " May 26, 2014: edit file, :Lex, resize window -- causes refresh. Reinstated a modified test. See if problems develop. -" call Decho("v:mouse_col=".v:mouse_col." col#".col('.')." virtcol#".virtcol('.')." col($)#".col("$")." virtcol($)#".virtcol("$"),'~'.expand("<slnum>")) if v:mouse_col > virtcol('.') let @@= ykeep -" call Dret("s:NetrwLeftmouse : detected a vertical separator bar leftmouse click") return endif if a:islocal if exists("b:netrw_curdir") - NetrwKeepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,s:NetrwGetWord())) + NetrwKeepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,s:NetrwGetWord(),1)) endif else if exists("b:netrw_curdir") - NetrwKeepj call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,s:NetrwGetWord())) + NetrwKeepj call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,s:NetrwGetWord(),1)) endif endif let @@= ykeep -" call Dret("s:NetrwLeftmouse") endfun " --------------------------------------------------------------------- @@ -5996,9 +5644,7 @@ fun! s:NetrwCLeftmouse(islocal) if &ft != "netrw" return endif -" call Dfunc("s:NetrwCLeftmouse(islocal=".a:islocal.")") call s:NetrwMarkFileTgt(a:islocal) -" call Dret("s:NetrwCLeftmouse") endfun " --------------------------------------------------------------------- @@ -6011,39 +5657,30 @@ fun! s:NetrwServerEdit(islocal,fname) " call Dfunc("s:NetrwServerEdit(islocal=".a:islocal.",fname<".a:fname.">)") let islocal = a:islocal%2 " =0: remote =1: local let ctrlr = a:islocal >= 2 " =0: <c-r> not used =1: <c-r> used -" call Decho("islocal=".islocal." ctrlr=".ctrlr,'~'.expand("<slnum>")) if (islocal && isdirectory(s:NetrwFile(a:fname))) || (!islocal && a:fname =~ '/$') " handle directories in the local window -- not in the remote vim server " user must have closed the NETRWSERVER window. Treat as normal editing from netrw. -" call Decho("handling directory in client window",'~'.expand("<slnum>")) let g:netrw_browse_split= 0 if exists("s:netrw_browse_split") && exists("s:netrw_browse_split_".winnr()) let g:netrw_browse_split= s:netrw_browse_split_{winnr()} unlet s:netrw_browse_split_{winnr()} endif - call s:NetrwBrowse(islocal,s:NetrwBrowseChgDir(islocal,a:fname)) -" call Dret("s:NetrwServerEdit") + call s:NetrwBrowse(islocal,s:NetrwBrowseChgDir(islocal,a:fname,0)) return endif -" call Decho("handling file in server window",'~'.expand("<slnum>")) if has("clientserver") && executable("gvim") -" call Decho("has clientserver and gvim",'~'.expand("<slnum>")) if exists("g:netrw_browse_split") && type(g:netrw_browse_split) == 3 -" call Decho("g:netrw_browse_split=".string(g:netrw_browse_split),'~'.expand("<slnum>")) let srvrname = g:netrw_browse_split[0] let tabnum = g:netrw_browse_split[1] let winnum = g:netrw_browse_split[2] if serverlist() !~ '\<'.srvrname.'\>' -" call Decho("server not available; ctrlr=".ctrlr,'~'.expand("<slnum>")) - if !ctrlr " user must have closed the server window and the user did not use <c-r>, but " used something like <cr>. -" call Decho("user must have closed server AND did not use ctrl-r",'~'.expand("<slnum>")) if exists("g:netrw_browse_split") unlet g:netrw_browse_split endif @@ -6051,50 +5688,40 @@ fun! s:NetrwServerEdit(islocal,fname) if exists("s:netrw_browse_split_".winnr()) let g:netrw_browse_split= s:netrw_browse_split_{winnr()} endif - call s:NetrwBrowseChgDir(islocal,a:fname) -" call Dret("s:NetrwServerEdit") + call s:NetrwBrowseChgDir(islocal,a:fname,0) return elseif has("win32") && executable("start") " start up remote netrw server under windows -" call Decho("starting up gvim server<".srvrname."> for windows",'~'.expand("<slnum>")) call system("start gvim --servername ".srvrname) else " start up remote netrw server under linux -" call Decho("starting up gvim server<".srvrname.">",'~'.expand("<slnum>")) call system("gvim --servername ".srvrname) endif endif -" call Decho("srvrname<".srvrname."> tabnum=".tabnum." winnum=".winnum." server-editing<".a:fname.">",'~'.expand("<slnum>")) call remote_send(srvrname,":tabn ".tabnum."\<cr>") call remote_send(srvrname,":".winnum."wincmd w\<cr>") call remote_send(srvrname,":e ".fnameescape(s:NetrwFile(a:fname))."\<cr>") - else if serverlist() !~ '\<'.g:netrw_servername.'\>' if !ctrlr -" call Decho("server<".g:netrw_servername."> not available and ctrl-r not used",'~'.expand("<slnum>")) if exists("g:netrw_browse_split") unlet g:netrw_browse_split endif let g:netrw_browse_split= 0 - call s:NetrwBrowse(islocal,s:NetrwBrowseChgDir(islocal,a:fname)) -" call Dret("s:NetrwServerEdit") + call s:NetrwBrowse(islocal,s:NetrwBrowseChgDir(islocal,a:fname,0)) return else -" call Decho("server<".g:netrw_servername."> not available but ctrl-r used",'~'.expand("<slnum>")) if has("win32") && executable("start") " start up remote netrw server under windows -" call Decho("starting up gvim server<".g:netrw_servername."> for windows",'~'.expand("<slnum>")) call system("start gvim --servername ".g:netrw_servername) else " start up remote netrw server under linux -" call Decho("starting up gvim server<".g:netrw_servername.">",'~'.expand("<slnum>")) call system("gvim --servername ".g:netrw_servername) endif endif @@ -6102,7 +5729,6 @@ fun! s:NetrwServerEdit(islocal,fname) while 1 try -" call Decho("remote-send: e ".a:fname,'~'.expand("<slnum>")) call remote_send(g:netrw_servername,":e ".fnameescape(s:NetrwFile(a:fname))."\<cr>") break catch /^Vim\%((\a\+)\)\=:E241/ @@ -6123,7 +5749,6 @@ fun! s:NetrwServerEdit(islocal,fname) call netrw#ErrorMsg(s:ERROR,"you need a gui-capable vim and client-server to use <ctrl-r>",98) endif -" call Dret("s:NetrwServerEdit") endfun " --------------------------------------------------------------------- @@ -6247,7 +5872,6 @@ endfun " s:NetrwMakeDir: this function makes a directory (both local and remote) {{{2 " implements the "d" mapping. fun! s:NetrwMakeDir(usrhost) -" call Dfunc("s:NetrwMakeDir(usrhost<".a:usrhost.">)") let ykeep= @@ " get name of new directory from user. A bare <CR> will skip. @@ -6256,27 +5880,22 @@ fun! s:NetrwMakeDir(usrhost) call inputsave() let newdirname= input("Please give directory name: ") call inputrestore() -" call Decho("newdirname<".newdirname.">",'~'.expand("<slnum>")) if newdirname == "" let @@= ykeep -" call Dret("s:NetrwMakeDir : user aborted with bare <cr>") return endif if a:usrhost == "" -" call Decho("local mkdir",'~'.expand("<slnum>")) " Local mkdir: " sanity checks let fullnewdir= b:netrw_curdir.'/'.newdirname -" call Decho("fullnewdir<".fullnewdir.">",'~'.expand("<slnum>")) if isdirectory(s:NetrwFile(fullnewdir)) if !exists("g:netrw_quiet") NetrwKeepj call netrw#ErrorMsg(s:WARNING,"<".newdirname."> is already a directory!",24) endif let @@= ykeep -" call Dret("s:NetrwMakeDir : directory<".newdirname."> exists previously") return endif if s:FileReadable(fullnewdir) @@ -6284,7 +5903,6 @@ fun! s:NetrwMakeDir(usrhost) NetrwKeepj call netrw#ErrorMsg(s:WARNING,"<".newdirname."> is already a file!",25) endif let @@= ykeep -" call Dret("s:NetrwMakeDir : file<".newdirname."> exists previously") return endif @@ -6299,21 +5917,16 @@ fun! s:NetrwMakeDir(usrhost) else let netrw_origdir= s:NetrwGetcwd(1) if s:NetrwLcd(b:netrw_curdir) -" call Dret("s:NetrwMakeDir : lcd failure") return endif -" call Decho("netrw_origdir<".netrw_origdir.">: lcd b:netrw_curdir<".fnameescape(b:netrw_curdir).">",'~'.expand("<slnum>")) call s:NetrwExe("sil! !".g:netrw_localmkdir.g:netrw_localmkdiropt.' '.s:ShellEscape(newdirname,1)) if v:shell_error != 0 let @@= ykeep call netrw#ErrorMsg(s:ERROR,"consider setting g:netrw_localmkdir<".g:netrw_localmkdir."> to something that works",80) -" call Dret("s:NetrwMakeDir : failed: sil! !".g:netrw_localmkdir.' '.s:ShellEscape(newdirname,1)) return endif if !g:netrw_keepdir -" call Decho("restoring netrw_origdir since g:netrw_keepdir=".g:netrw_keepdir,'~'.expand("<slnum>")) if s:NetrwLcd(netrw_origdir) -" call Dret("s:NetrwBrowse : lcd failure") return endif endif @@ -6321,126 +5934,95 @@ fun! s:NetrwMakeDir(usrhost) if v:shell_error == 0 " refresh listing -" call Decho("refresh listing",'~'.expand("<slnum>")) let svpos= winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) - call s:NetrwRefresh(1,s:NetrwBrowseChgDir(1,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + call s:NetrwRefresh(1,s:NetrwBrowseChgDir(1,'./',0)) call winrestview(svpos) elseif !exists("g:netrw_quiet") call netrw#ErrorMsg(s:ERROR,"unable to make directory<".newdirname.">",26) endif -" redraw! elseif !exists("b:netrw_method") || b:netrw_method == 4 " Remote mkdir: using ssh -" call Decho("remote mkdir",'~'.expand("<slnum>")) let mkdircmd = s:MakeSshCmd(g:netrw_mkdir_cmd) let newdirname= substitute(b:netrw_curdir,'^\%(.\{-}/\)\{3}\(.*\)$','\1','').newdirname call s:NetrwExe("sil! !".mkdircmd." ".s:ShellEscape(newdirname,1)) if v:shell_error == 0 " refresh listing let svpos= winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) - NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./',0)) NetrwKeepj call winrestview(svpos) elseif !exists("g:netrw_quiet") NetrwKeepj call netrw#ErrorMsg(s:ERROR,"unable to make directory<".newdirname.">",27) endif -" redraw! elseif b:netrw_method == 2 " Remote mkdir: using ftp+.netrc let svpos= winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) -" call Decho("b:netrw_curdir<".b:netrw_curdir.">",'~'.expand("<slnum>")) if exists("b:netrw_fname") -" call Decho("b:netrw_fname<".b:netrw_fname.">",'~'.expand("<slnum>")) let remotepath= b:netrw_fname else let remotepath= "" endif call s:NetrwRemoteFtpCmd(remotepath,g:netrw_remote_mkdir.' "'.newdirname.'"') - NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./',0)) NetrwKeepj call winrestview(svpos) elseif b:netrw_method == 3 " Remote mkdir: using ftp + machine, id, passwd, and fname (ie. no .netrc) let svpos= winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) -" call Decho("b:netrw_curdir<".b:netrw_curdir.">",'~'.expand("<slnum>")) if exists("b:netrw_fname") -" call Decho("b:netrw_fname<".b:netrw_fname.">",'~'.expand("<slnum>")) let remotepath= b:netrw_fname else let remotepath= "" endif call s:NetrwRemoteFtpCmd(remotepath,g:netrw_remote_mkdir.' "'.newdirname.'"') - NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./',0)) NetrwKeepj call winrestview(svpos) endif let @@= ykeep -" call Dret("s:NetrwMakeDir") endfun " --------------------------------------------------------------------- " s:TreeSqueezeDir: allows a shift-cr (gvim only) to squeeze the current tree-listing directory {{{2 fun! s:TreeSqueezeDir(islocal) -" call Dfunc("s:TreeSqueezeDir(islocal=".a:islocal.")") if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST && exists("w:netrw_treedict") " its a tree-listing style let curdepth = substitute(getline('.'),'^\(\%('.s:treedepthstring.'\)*\)[^'.s:treedepthstring.'].\{-}$','\1','e') let stopline = (exists("w:netrw_bannercnt")? (w:netrw_bannercnt + 1) : 1) let depth = strchars(substitute(curdepth,' ','','g')) let srch = -1 -" call Decho("curdepth<".curdepth.'>','~'.expand("<slnum>")) -" call Decho("depth =".depth,'~'.expand("<slnum>")) -" call Decho("stopline#".stopline,'~'.expand("<slnum>")) -" call Decho("curline#".line(".")."<".getline('.').'>','~'.expand("<slnum>")) if depth >= 2 NetrwKeepj norm! 0 let curdepthm1= substitute(curdepth,'^'.s:treedepthstring,'','') let srch = search('^'.curdepthm1.'\%('.s:treedepthstring.'\)\@!','bW',stopline) -" call Decho("curdepthm1<".curdepthm1.'>','~'.expand("<slnum>")) -" call Decho("case depth>=2: srch<".srch.'>','~'.expand("<slnum>")) elseif depth == 1 NetrwKeepj norm! 0 let treedepthchr= substitute(s:treedepthstring,' ','','') let srch = search('^[^'.treedepthchr.']','bW',stopline) -" call Decho("case depth==1: srch<".srch.'>','~'.expand("<slnum>")) endif if srch > 0 -" call Decho("squeezing at line#".line(".").": ".getline('.'),'~'.expand("<slnum>")) - call s:NetrwBrowse(a:islocal,s:NetrwBrowseChgDir(a:islocal,s:NetrwGetWord())) + call s:NetrwBrowse(a:islocal,s:NetrwBrowseChgDir(a:islocal,s:NetrwGetWord(),1)) exe srch endif endif -" call Dret("s:TreeSqueezeDir") endfun " --------------------------------------------------------------------- " s:NetrwMaps: {{{2 fun! s:NetrwMaps(islocal) -" call Dfunc("s:NetrwMaps(islocal=".a:islocal.") b:netrw_curdir<".b:netrw_curdir.">") " mouse <Plug> maps: {{{3 if g:netrw_mousemaps && g:netrw_retmap " call Decho("set up Rexplore 2-leftmouse",'~'.expand("<slnum>")) if !hasmapto("<Plug>NetrwReturn") if maparg("<2-leftmouse>","n") == "" || maparg("<2-leftmouse>","n") =~ '^-$' -" call Decho("making map for 2-leftmouse",'~'.expand("<slnum>")) nmap <unique> <silent> <2-leftmouse> <Plug>NetrwReturn elseif maparg("<c-leftmouse>","n") == "" -" call Decho("making map for c-leftmouse",'~'.expand("<slnum>")) nmap <unique> <silent> <c-leftmouse> <Plug>NetrwReturn endif endif nno <silent> <Plug>NetrwReturn :Rexplore<cr> -" call Decho("made <Plug>NetrwReturn map",'~'.expand("<slnum>")) endif " generate default <Plug> maps {{{3 @@ -6456,56 +6038,8 @@ fun! s:NetrwMaps(islocal) if !hasmapto('<Plug>NetrwServerEdit') |nmap <buffer> <silent> <nowait> <c-r> <Plug>NetrwServerEdit|endif if !hasmapto('<Plug>NetrwMakeDir') |nmap <buffer> <silent> <nowait> d <Plug>NetrwMakeDir|endif if !hasmapto('<Plug>NetrwBookHistHandler_gb')|nmap <buffer> <silent> <nowait> gb <Plug>NetrwBookHistHandler_gb|endif -" --------------------------------------------------------------------- -" if !hasmapto('<Plug>NetrwForceChgDir') |nmap <buffer> <silent> <nowait> gd <Plug>NetrwForceChgDir|endif -" if !hasmapto('<Plug>NetrwForceFile') |nmap <buffer> <silent> <nowait> gf <Plug>NetrwForceFile|endif -" if !hasmapto('<Plug>NetrwHidden') |nmap <buffer> <silent> <nowait> gh <Plug>NetrwHidden|endif -" if !hasmapto('<Plug>NetrwSetTreetop') |nmap <buffer> <silent> <nowait> gn <Plug>NetrwSetTreetop|endif -" if !hasmapto('<Plug>NetrwChgPerm') |nmap <buffer> <silent> <nowait> gp <Plug>NetrwChgPerm|endif -" if !hasmapto('<Plug>NetrwBannerCtrl') |nmap <buffer> <silent> <nowait> I <Plug>NetrwBannerCtrl|endif -" if !hasmapto('<Plug>NetrwListStyle') |nmap <buffer> <silent> <nowait> i <Plug>NetrwListStyle|endif -" if !hasmapto('<Plug>NetrwMarkMoveMF2Arglist')|nmap <buffer> <silent> <nowait> ma <Plug>NetrwMarkMoveMF2Arglist|endif -" if !hasmapto('<Plug>NetrwMarkMoveArglist2MF')|nmap <buffer> <silent> <nowait> mA <Plug>NetrwMarkMoveArglist2MF|endif -" if !hasmapto('<Plug>NetrwBookHistHandler_mA')|nmap <buffer> <silent> <nowait> mb <Plug>NetrwBookHistHandler_mA|endif -" if !hasmapto('<Plug>NetrwBookHistHandler_mB')|nmap <buffer> <silent> <nowait> mB <Plug>NetrwBookHistHandler_mB|endif -" if !hasmapto('<Plug>NetrwMarkFileCopy') |nmap <buffer> <silent> <nowait> mc <Plug>NetrwMarkFileCopy|endif -" if !hasmapto('<Plug>NetrwMarkFileDiff') |nmap <buffer> <silent> <nowait> md <Plug>NetrwMarkFileDiff|endif -" if !hasmapto('<Plug>NetrwMarkFileEdit') |nmap <buffer> <silent> <nowait> me <Plug>NetrwMarkFileEdit|endif -" if !hasmapto('<Plug>NetrwMarkFile') |nmap <buffer> <silent> <nowait> mf <Plug>NetrwMarkFile|endif -" if !hasmapto('<Plug>NetrwUnmarkList') |nmap <buffer> <silent> <nowait> mF <Plug>NetrwUnmarkList|endif -" if !hasmapto('<Plug>NetrwMarkFileGrep') |nmap <buffer> <silent> <nowait> mg <Plug>NetrwMarkFileGrep|endif -" if !hasmapto('<Plug>NetrwMarkHideSfx') |nmap <buffer> <silent> <nowait> mh <Plug>NetrwMarkHideSfx|endif -" if !hasmapto('<Plug>NetrwMarkFileMove') |nmap <buffer> <silent> <nowait> mm <Plug>NetrwMarkFileMove|endif -" if !hasmapto('<Plug>NetrwMarkFileRegexp') |nmap <buffer> <silent> <nowait> mr <Plug>NetrwMarkFileRegexp|endif -" if !hasmapto('<Plug>NetrwMarkFileSource') |nmap <buffer> <silent> <nowait> ms <Plug>NetrwMarkFileSource|endif -" if !hasmapto('<Plug>NetrwMarkFileTag') |nmap <buffer> <silent> <nowait> mT <Plug>NetrwMarkFileTag|endif -" if !hasmapto('<Plug>NetrwMarkFileTgt') |nmap <buffer> <silent> <nowait> mt <Plug>NetrwMarkFileTgt|endif -" if !hasmapto('<Plug>NetrwUnMarkFile') |nmap <buffer> <silent> <nowait> mu <Plug>NetrwUnMarkFile|endif -" if !hasmapto('<Plug>NetrwMarkFileVimCmd') |nmap <buffer> <silent> <nowait> mv <Plug>NetrwMarkFileVimCmd|endif -" if !hasmapto('<Plug>NetrwMarkFileExe_mx') |nmap <buffer> <silent> <nowait> mx <Plug>NetrwMarkFileExe_mx|endif -" if !hasmapto('<Plug>NetrwMarkFileExe_mX') |nmap <buffer> <silent> <nowait> mX <Plug>NetrwMarkFileExe_mX|endif -" if !hasmapto('<Plug>NetrwMarkFileCompress') |nmap <buffer> <silent> <nowait> mz <Plug>NetrwMarkFileCompress|endif -" if !hasmapto('<Plug>NetrwObtain') |nmap <buffer> <silent> <nowait> O <Plug>NetrwObtain|endif -" if !hasmapto('<Plug>NetrwSplit_o') |nmap <buffer> <silent> <nowait> o <Plug>NetrwSplit_o|endif -" if !hasmapto('<Plug>NetrwPreview') |nmap <buffer> <silent> <nowait> p <Plug>NetrwPreview|endif -" if !hasmapto('<Plug>NetrwPrevWinOpen') |nmap <buffer> <silent> <nowait> P <Plug>NetrwPrevWinOpen|endif -" if !hasmapto('<Plug>NetrwBookHistHandler_qb')|nmap <buffer> <silent> <nowait> qb <Plug>NetrwBookHistHandler_qb|endif -" if !hasmapto('<Plug>NetrwFileInfo') |nmap <buffer> <silent> <nowait> qf <Plug>NetrwFileInfo|endif -" if !hasmapto('<Plug>NetrwMarkFileQFEL_qF') |nmap <buffer> <silent> <nowait> qF <Plug>NetrwMarkFileQFEL_qF|endif -" if !hasmapto('<Plug>NetrwMarkFileQFEL_qL') |nmap <buffer> <silent> <nowait> qL <Plug>NetrwMarkFileQFEL_qL|endif -" if !hasmapto('<Plug>NetrwSortStyle') |nmap <buffer> <silent> <nowait> s <Plug>NetrwSortStyle|endif -" if !hasmapto('<Plug>NetSortSequence') |nmap <buffer> <silent> <nowait> S <Plug>NetSortSequence|endif -" if !hasmapto('<Plug>NetrwSetTgt_Tb') |nmap <buffer> <silent> <nowait> Tb <Plug>NetrwSetTgt_Tb|endif -" if !hasmapto('<Plug>NetrwSetTgt_Th') |nmap <buffer> <silent> <nowait> Th <Plug>NetrwSetTgt_Th|endif -" if !hasmapto('<Plug>NetrwSplit_t') |nmap <buffer> <silent> <nowait> t <Plug>NetrwSplit_t|endif -" if !hasmapto('<Plug>NetrwBookHistHandler_u') |nmap <buffer> <silent> <nowait> u <Plug>NetrwBookHistHandler_u|endif -" if !hasmapto('<Plug>NetrwBookHistHandler_U') |nmap <buffer> <silent> <nowait> U <Plug>NetrwBookHistHandler_U|endif -" if !hasmapto('<Plug>NetrwSplit_v') |nmap <buffer> <silent> <nowait> v <Plug>NetrwSplit_v|endif -" if !hasmapto('<Plug>NetrwBrowseX') |nmap <buffer> <silent> <nowait> x <Plug>NetrwBrowseX|endif -" if !hasmapto('<Plug>NetrwLocalExecute') |nmap <buffer> <silent> <nowait> X <Plug>NetrwLocalExecute|endif if a:islocal -" call Decho("make local maps",'~'.expand("<slnum>")) " local normal-mode maps {{{3 nnoremap <buffer> <silent> <Plug>NetrwHide_a :<c-u>call <SID>NetrwHide(1)<cr> nnoremap <buffer> <silent> <Plug>NetrwBrowseUpDir :<c-u>call <SID>NetrwBrowseUpDir(1)<cr> @@ -6514,7 +6048,7 @@ fun! s:NetrwMaps(islocal) nnoremap <buffer> <silent> <Plug>NetrwBadd_cB :<c-u>call <SID>NetrwBadd(1,1)<cr> nnoremap <buffer> <silent> <Plug>NetrwLcd :<c-u>call <SID>NetrwLcd(b:netrw_curdir)<cr> nnoremap <buffer> <silent> <Plug>NetrwSetChgwin :<c-u>call <SID>NetrwSetChgwin()<cr> - nnoremap <buffer> <silent> <Plug>NetrwLocalBrowseCheck :<c-u>call netrw#LocalBrowseCheck(<SID>NetrwBrowseChgDir(1,<SID>NetrwGetWord()))<cr> + nnoremap <buffer> <silent> <Plug>NetrwLocalBrowseCheck :<c-u>call netrw#LocalBrowseCheck(<SID>NetrwBrowseChgDir(1,<SID>NetrwGetWord(),1))<cr> nnoremap <buffer> <silent> <Plug>NetrwServerEdit :<c-u>call <SID>NetrwServerEdit(3,<SID>NetrwGetWord())<cr> nnoremap <buffer> <silent> <Plug>NetrwMakeDir :<c-u>call <SID>NetrwMakeDir("")<cr> nnoremap <buffer> <silent> <Plug>NetrwBookHistHandler_gb :<c-u>call <SID>NetrwBookHistHandler(1,b:netrw_curdir)<cr> @@ -6538,6 +6072,7 @@ fun! s:NetrwMaps(islocal) nnoremap <buffer> <silent> <nowait> mg :<c-u>call <SID>NetrwMarkFileGrep(1)<cr> nnoremap <buffer> <silent> <nowait> mh :<c-u>call <SID>NetrwMarkHideSfx(1)<cr> nnoremap <buffer> <silent> <nowait> mm :<c-u>call <SID>NetrwMarkFileMove(1)<cr> + "nnoremap <buffer> <silent> <nowait> mp :<c-u>call <SID>NetrwMarkFilePrint(1)<cr> nnoremap <buffer> <silent> <nowait> mr :<c-u>call <SID>NetrwMarkFileRegexp(1)<cr> nnoremap <buffer> <silent> <nowait> ms :<c-u>call <SID>NetrwMarkFileSource(1)<cr> nnoremap <buffer> <silent> <nowait> mT :<c-u>call <SID>NetrwMarkFileTag(1)<cr> @@ -6549,7 +6084,7 @@ fun! s:NetrwMaps(islocal) nnoremap <buffer> <silent> <nowait> mz :<c-u>call <SID>NetrwMarkFileCompress(1)<cr> nnoremap <buffer> <silent> <nowait> O :<c-u>call <SID>NetrwObtain(1)<cr> nnoremap <buffer> <silent> <nowait> o :call <SID>NetrwSplit(3)<cr> - nnoremap <buffer> <silent> <nowait> p :<c-u>call <SID>NetrwPreview(<SID>NetrwBrowseChgDir(1,<SID>NetrwGetWord(),1))<cr> + nnoremap <buffer> <silent> <nowait> p :<c-u>call <SID>NetrwPreview(<SID>NetrwBrowseChgDir(1,<SID>NetrwGetWord(),1,1))<cr> nnoremap <buffer> <silent> <nowait> P :<c-u>call <SID>NetrwPrevWinOpen(1)<cr> nnoremap <buffer> <silent> <nowait> qb :<c-u>call <SID>NetrwBookHistHandler(2,b:netrw_curdir)<cr> nnoremap <buffer> <silent> <nowait> qf :<c-u>call <SID>NetrwFileInfo(1,<SID>NetrwGetWord())<cr> @@ -6563,10 +6098,10 @@ fun! s:NetrwMaps(islocal) nnoremap <buffer> <silent> <nowait> u :<c-u>call <SID>NetrwBookHistHandler(4,expand("%"))<cr> nnoremap <buffer> <silent> <nowait> U :<c-u>call <SID>NetrwBookHistHandler(5,expand("%"))<cr> nnoremap <buffer> <silent> <nowait> v :call <SID>NetrwSplit(5)<cr> - nnoremap <buffer> <silent> <nowait> x :<c-u>call netrw#BrowseX(<SID>NetrwBrowseChgDir(1,<SID>NetrwGetWord(),0),0)"<cr> + nnoremap <buffer> <silent> <nowait> x :<c-u>call netrw#BrowseX(<SID>NetrwBrowseChgDir(1,<SID>NetrwGetWord(),1,0),0)"<cr> nnoremap <buffer> <silent> <nowait> X :<c-u>call <SID>NetrwLocalExecute(expand("<cword>"))"<cr> - nnoremap <buffer> <silent> <nowait> r :<c-u>let g:netrw_sort_direction= (g:netrw_sort_direction =~# 'n')? 'r' : 'n'<bar>exe "norm! 0"<bar>call <SID>NetrwRefresh(1,<SID>NetrwBrowseChgDir(1,'./'))<cr> + nnoremap <buffer> <silent> <nowait> r :<c-u>let g:netrw_sort_direction= (g:netrw_sort_direction =~# 'n')? 'r' : 'n'<bar>exe "norm! 0"<bar>call <SID>NetrwRefresh(1,<SID>NetrwBrowseChgDir(1,'./',0))<cr> if !hasmapto('<Plug>NetrwHideEdit') nmap <buffer> <unique> <c-h> <Plug>NetrwHideEdit endif @@ -6574,7 +6109,7 @@ fun! s:NetrwMaps(islocal) if !hasmapto('<Plug>NetrwRefresh') nmap <buffer> <unique> <c-l> <Plug>NetrwRefresh endif - nnoremap <buffer> <silent> <Plug>NetrwRefresh <c-l>:call <SID>NetrwRefresh(1,<SID>NetrwBrowseChgDir(1,(exists("w:netrw_liststyle") && exists("w:netrw_treetop") && w:netrw_liststyle == 3)? w:netrw_treetop : './'))<cr> + nnoremap <buffer> <silent> <Plug>NetrwRefresh <c-l>:call <SID>NetrwRefresh(1,<SID>NetrwBrowseChgDir(1,(exists("w:netrw_liststyle") && exists("w:netrw_treetop") && w:netrw_liststyle == 3)? w:netrw_treetop : './',0))<cr> if s:didstarstar || !mapcheck("<s-down>","n") nnoremap <buffer> <silent> <s-down> :Nexplore<cr> endif @@ -6618,7 +6153,6 @@ fun! s:NetrwMaps(islocal) else " remote normal-mode maps {{{3 -" call Decho("make remote maps",'~'.expand("<slnum>")) call s:RemotePathAnalysis(b:netrw_curdir) nnoremap <buffer> <silent> <Plug>NetrwHide_a :<c-u>call <SID>NetrwHide(0)<cr> nnoremap <buffer> <silent> <Plug>NetrwBrowseUpDir :<c-u>call <SID>NetrwBrowseUpDir(0)<cr> @@ -6627,8 +6161,8 @@ fun! s:NetrwMaps(islocal) nnoremap <buffer> <silent> <Plug>NetrwBadd_cB :<c-u>call <SID>NetrwBadd(0,1)<cr> nnoremap <buffer> <silent> <Plug>NetrwLcd :<c-u>call <SID>NetrwLcd(b:netrw_curdir)<cr> nnoremap <buffer> <silent> <Plug>NetrwSetChgwin :<c-u>call <SID>NetrwSetChgwin()<cr> - nnoremap <buffer> <silent> <Plug>NetrwRefresh :<c-u>call <SID>NetrwRefresh(0,<SID>NetrwBrowseChgDir(0,'./'))<cr> - nnoremap <buffer> <silent> <Plug>NetrwLocalBrowseCheck :<c-u>call <SID>NetrwBrowse(0,<SID>NetrwBrowseChgDir(0,<SID>NetrwGetWord()))<cr> + nnoremap <buffer> <silent> <Plug>NetrwRefresh :<c-u>call <SID>NetrwRefresh(0,<SID>NetrwBrowseChgDir(0,'./',0))<cr> + nnoremap <buffer> <silent> <Plug>NetrwLocalBrowseCheck :<c-u>call <SID>NetrwBrowse(0,<SID>NetrwBrowseChgDir(0,<SID>NetrwGetWord(),1))<cr> nnoremap <buffer> <silent> <Plug>NetrwServerEdit :<c-u>call <SID>NetrwServerEdit(2,<SID>NetrwGetWord())<cr> nnoremap <buffer> <silent> <Plug>NetrwBookHistHandler_gb :<c-u>call <SID>NetrwBookHistHandler(1,b:netrw_curdir)<cr> " --------------------------------------------------------------------- @@ -6650,6 +6184,7 @@ fun! s:NetrwMaps(islocal) nnoremap <buffer> <silent> <nowait> mg :<c-u>call <SID>NetrwMarkFileGrep(0)<cr> nnoremap <buffer> <silent> <nowait> mh :<c-u>call <SID>NetrwMarkHideSfx(0)<cr> nnoremap <buffer> <silent> <nowait> mm :<c-u>call <SID>NetrwMarkFileMove(0)<cr> + "nnoremap <buffer> <silent> <nowait> mp :<c-u>call <SID>NetrwMarkFilePrint(0)<cr> nnoremap <buffer> <silent> <nowait> mr :<c-u>call <SID>NetrwMarkFileRegexp(0)<cr> nnoremap <buffer> <silent> <nowait> ms :<c-u>call <SID>NetrwMarkFileSource(0)<cr> nnoremap <buffer> <silent> <nowait> mT :<c-u>call <SID>NetrwMarkFileTag(0)<cr> @@ -6661,13 +6196,13 @@ fun! s:NetrwMaps(islocal) nnoremap <buffer> <silent> <nowait> mz :<c-u>call <SID>NetrwMarkFileCompress(0)<cr> nnoremap <buffer> <silent> <nowait> O :<c-u>call <SID>NetrwObtain(0)<cr> nnoremap <buffer> <silent> <nowait> o :call <SID>NetrwSplit(0)<cr> - nnoremap <buffer> <silent> <nowait> p :<c-u>call <SID>NetrwPreview(<SID>NetrwBrowseChgDir(1,<SID>NetrwGetWord(),1))<cr> + nnoremap <buffer> <silent> <nowait> p :<c-u>call <SID>NetrwPreview(<SID>NetrwBrowseChgDir(1,<SID>NetrwGetWord(),1,1))<cr> nnoremap <buffer> <silent> <nowait> P :<c-u>call <SID>NetrwPrevWinOpen(0)<cr> nnoremap <buffer> <silent> <nowait> qb :<c-u>call <SID>NetrwBookHistHandler(2,b:netrw_curdir)<cr> nnoremap <buffer> <silent> <nowait> qf :<c-u>call <SID>NetrwFileInfo(0,<SID>NetrwGetWord())<cr> nnoremap <buffer> <silent> <nowait> qF :<c-u>call <SID>NetrwMarkFileQFEL(0,getqflist())<cr> nnoremap <buffer> <silent> <nowait> qL :<c-u>call <SID>NetrwMarkFileQFEL(0,getloclist(v:count))<cr> - nnoremap <buffer> <silent> <nowait> r :<c-u>let g:netrw_sort_direction= (g:netrw_sort_direction =~# 'n')? 'r' : 'n'<bar>exe "norm! 0"<bar>call <SID>NetrwBrowse(0,<SID>NetrwBrowseChgDir(0,'./'))<cr> + nnoremap <buffer> <silent> <nowait> r :<c-u>let g:netrw_sort_direction= (g:netrw_sort_direction =~# 'n')? 'r' : 'n'<bar>exe "norm! 0"<bar>call <SID>NetrwBrowse(0,<SID>NetrwBrowseChgDir(0,'./',0))<cr> nnoremap <buffer> <silent> <nowait> s :call <SID>NetrwSortStyle(0)<cr> nnoremap <buffer> <silent> <nowait> S :<c-u>call <SID>NetSortSequence(0)<cr> nnoremap <buffer> <silent> <nowait> Tb :<c-u>call <SID>NetrwSetTgt(0,'b',v:count1)<cr> @@ -6676,7 +6211,8 @@ fun! s:NetrwMaps(islocal) nnoremap <buffer> <silent> <nowait> u :<c-u>call <SID>NetrwBookHistHandler(4,b:netrw_curdir)<cr> nnoremap <buffer> <silent> <nowait> U :<c-u>call <SID>NetrwBookHistHandler(5,b:netrw_curdir)<cr> nnoremap <buffer> <silent> <nowait> v :call <SID>NetrwSplit(2)<cr> - nnoremap <buffer> <silent> <nowait> x :<c-u>call netrw#BrowseX(<SID>NetrwBrowseChgDir(0,<SID>NetrwGetWord()),1)<cr> + nnoremap <buffer> <silent> <nowait> x :<c-u>call netrw#BrowseX(<SID>NetrwBrowseChgDir(0,<SID>NetrwGetWord(),1),1)<cr> + nmap <buffer> <nowait> gx x if !hasmapto('<Plug>NetrwHideEdit') nmap <buffer> <c-h> <Plug>NetrwHideEdit endif @@ -6692,7 +6228,7 @@ fun! s:NetrwMaps(islocal) let mapsafepath = escape(s:path, s:netrw_map_escape) let mapsafeusermach = escape(((s:user == "")? "" : s:user."@").s:machine, s:netrw_map_escape) - nnoremap <buffer> <silent> <Plug>NetrwRefresh :call <SID>NetrwRefresh(0,<SID>NetrwBrowseChgDir(0,'./'))<cr> + nnoremap <buffer> <silent> <Plug>NetrwRefresh :call <SID>NetrwRefresh(0,<SID>NetrwBrowseChgDir(0,'./',0))<cr> if g:netrw_mousemaps == 1 nmap <buffer> <leftmouse> <Plug>NetrwLeftmouse nno <buffer> <silent> <Plug>NetrwLeftmouse :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwLeftmouse(0)<cr> @@ -6724,8 +6260,6 @@ fun! s:NetrwMaps(islocal) " support user-specified maps call netrw#UserMaps(0) endif " }}}3 - -" call Dret("s:NetrwMaps") endfun " --------------------------------------------------------------------- @@ -6779,7 +6313,6 @@ endfun " --------------------------------------------------------------------- " s:NetrwMarkTarget: implements :MT (mark target) {{{2 fun! s:NetrwMarkTarget(...) -" call Dfunc("s:NetrwMarkTarget() a:0=".a:0) if a:0 == 0 || (a:0 == 1 && a:1 == "") let curdir = s:NetrwGetCurdir(1) let tgt = b:netrw_curdir @@ -6787,16 +6320,12 @@ fun! s:NetrwMarkTarget(...) let curdir = s:NetrwGetCurdir((a:1 =~ '^\a\{3,}://')? 0 : 1) let tgt = a:1 endif -" call Decho("tgt<".tgt.">",'~'.expand("<slnum>")) let s:netrwmftgt = tgt let s:netrwmftgt_islocal = tgt !~ '^\a\{3,}://' let curislocal = b:netrw_curdir !~ '^\a\{3,}://' let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) - call s:NetrwRefresh(curislocal,s:NetrwBrowseChgDir(curislocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + call s:NetrwRefresh(curislocal,s:NetrwBrowseChgDir(curislocal,'./',0)) call winrestview(svpos) -" call Dret("s:NetrwMarkTarget") endfun " --------------------------------------------------------------------- @@ -6939,10 +6468,7 @@ endfun " mA: move the argument list to marked file list (tomflist=1) " Uses the global marked file list fun! s:NetrwMarkFileArgList(islocal,tomflist) -" call Dfunc("s:NetrwMarkFileArgList(islocal=".a:islocal.",tomflist=".a:tomflist.")") - let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let curdir = s:NetrwGetCurdir(a:islocal) let curbufnr = bufnr("%") @@ -6950,7 +6476,6 @@ fun! s:NetrwMarkFileArgList(islocal,tomflist) " mA: move argument list to marked file list while argc() let fname= argv(0) -" call Decho("exe argdel ".fname,'~'.expand("<slnum>")) exe "argdel ".fnameescape(fname) call s:NetrwMarkFile(a:islocal,fname) endwhile @@ -6961,19 +6486,16 @@ fun! s:NetrwMarkFileArgList(islocal,tomflist) " for every filename in the marked list for fname in s:netrwmarkfilelist -" call Decho("exe argadd ".fname,'~'.expand("<slnum>")) exe "argadd ".fnameescape(fname) endfor " for every file in the marked list " unmark list and refresh call s:NetrwUnmarkList(curbufnr,curdir) - NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) NetrwKeepj call winrestview(svpos) endif endif -" call Dret("s:NetrwMarkFileArgList") endfun " --------------------------------------------------------------------- @@ -6985,30 +6507,24 @@ endfun " g:netrw_compress = "gzip" " g:netrw_decompress = { ".gz" : "gunzip" , ".bz2" : "bunzip2" , ".zip" : "unzip" , ".tar" : "tar -xf", ".xz" : "unxz"} fun! s:NetrwMarkFileCompress(islocal) -" call Dfunc("s:NetrwMarkFileCompress(islocal=".a:islocal.")") let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let curdir = s:NetrwGetCurdir(a:islocal) let curbufnr = bufnr("%") " sanity check if !exists("s:netrwmarkfilelist_{curbufnr}") || empty(s:netrwmarkfilelist_{curbufnr}) NetrwKeepj call netrw#ErrorMsg(2,"there are no marked files in this window (:help netrw-mf)",66) -" call Dret("s:NetrwMarkFileCompress") return endif -" call Decho("sanity chk passed: s:netrwmarkfilelist_".curbufnr."<".string(s:netrwmarkfilelist_{curbufnr}),'~'.expand("<slnum>")) if exists("s:netrwmarkfilelist_{curbufnr}") && exists("g:netrw_compress") && exists("g:netrw_decompress") " for every filename in the marked list for fname in s:netrwmarkfilelist_{curbufnr} let sfx= substitute(fname,'^.\{-}\(\.\a\+\)$','\1','') -" call Decho("extracted sfx<".sfx.">",'~'.expand("<slnum>")) if exists("g:netrw_decompress['".sfx."']") " fname has a suffix indicating that its compressed; apply associated decompression routine let exe= g:netrw_decompress[sfx] -" call Decho("fname<".fname."> is compressed so decompress with <".exe.">",'~'.expand("<slnum>")) let exe= netrw#WinPath(exe) if a:islocal if g:netrw_keepdir @@ -7041,11 +6557,9 @@ fun! s:NetrwMarkFileCompress(islocal) endfor " for every file in the marked list call s:NetrwUnmarkList(curbufnr,curdir) - NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) NetrwKeepj call winrestview(svpos) endif -" call Dret("s:NetrwMarkFileCompress") endfun " --------------------------------------------------------------------- @@ -7385,9 +6899,7 @@ endfun " mx enbloc=0: Uses the local marked-file list, applies command to each file individually " mX enbloc=1: Uses the global marked-file list, applies command to entire list fun! s:NetrwMarkFileExe(islocal,enbloc) -" call Dfunc("s:NetrwMarkFileExe(islocal=".a:islocal.",enbloc=".a:enbloc.")") let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let curdir = s:NetrwGetCurdir(a:islocal) let curbufnr = bufnr("%") @@ -7396,19 +6908,15 @@ fun! s:NetrwMarkFileExe(islocal,enbloc) " sanity check if !exists("s:netrwmarkfilelist_{curbufnr}") || empty(s:netrwmarkfilelist_{curbufnr}) NetrwKeepj call netrw#ErrorMsg(2,"there are no marked files in this window (:help netrw-mf)",66) -" call Dret("s:NetrwMarkFileExe") return endif -" call Decho("sanity chk passed: s:netrwmarkfilelist_".curbufnr."<".string(s:netrwmarkfilelist_{curbufnr}),'~'.expand("<slnum>")) if exists("s:netrwmarkfilelist_{curbufnr}") " get the command call inputsave() let cmd= input("Enter command: ","","file") call inputrestore() -" call Decho("cmd<".cmd.">",'~'.expand("<slnum>")) if cmd == "" -" call Dret("s:NetrwMarkFileExe : early exit, empty command") return endif @@ -7428,10 +6936,8 @@ fun! s:NetrwMarkFileExe(islocal,enbloc) let xcmd= cmd.' '.fname endif if a:islocal -" call Decho("local: xcmd<".xcmd.">",'~'.expand("<slnum>")) let ret= system(xcmd) else -" call Decho("remote: xcmd<".xcmd.">",'~'.expand("<slnum>")) let ret= s:RemoteSystem(xcmd) endif if v:shell_error < 0 @@ -7452,8 +6958,7 @@ fun! s:NetrwMarkFileExe(islocal,enbloc) call s:NetrwUnmarkList(curbufnr,curdir) " refresh the listing - NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) NetrwKeepj call winrestview(svpos) else NetrwKeepj call netrw#ErrorMsg(s:ERROR,"no files marked!",59) @@ -7464,9 +6969,7 @@ fun! s:NetrwMarkFileExe(islocal,enbloc) call inputsave() let cmd= input("Enter command: ","","file") call inputrestore() -" call Decho("cmd<".cmd.">",'~'.expand("<slnum>")) if cmd == "" -" call Dret("s:NetrwMarkFileExe : early exit, empty command") return endif if cmd =~ '%' @@ -7485,13 +6988,10 @@ fun! s:NetrwMarkFileExe(islocal,enbloc) call s:NetrwUnmarkAll() " refresh the listing - NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) NetrwKeepj call winrestview(svpos) endif - -" call Dret("s:NetrwMarkFileExe") endfun " --------------------------------------------------------------------- @@ -7499,16 +6999,13 @@ endfun " as the marked file(s) (toggles suffix presence) " Uses the local marked file list. fun! s:NetrwMarkHideSfx(islocal) -" call Dfunc("s:NetrwMarkHideSfx(islocal=".a:islocal.")") let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let curbufnr = bufnr("%") " s:netrwmarkfilelist_{curbufnr}: the List of marked files if exists("s:netrwmarkfilelist_{curbufnr}") for fname in s:netrwmarkfilelist_{curbufnr} -" call Decho("s:NetrwMarkFileCopy: fname<".fname.">",'~'.expand("<slnum>")) " construct suffix pattern if fname =~ '\.' let sfxpat= "^.*".substitute(fname,'^.*\(\.[^. ]\+\)$','\1','') @@ -7528,7 +7025,6 @@ fun! s:NetrwMarkHideSfx(islocal) let itemnum= itemnum + 1 endfor endif -" call Decho("fname<".fname."> inhidelist=".inhidelist." sfxpat<".sfxpat.">",'~'.expand("<slnum>")) if inhidelist " remove sfxpat from list call remove(hidelist,itemnum) @@ -7543,57 +7039,45 @@ fun! s:NetrwMarkHideSfx(islocal) endfor " refresh the listing - NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) NetrwKeepj call winrestview(svpos) else NetrwKeepj call netrw#ErrorMsg(s:ERROR,"no files marked!",59) endif - -" call Dret("s:NetrwMarkHideSfx") endfun " --------------------------------------------------------------------- " s:NetrwMarkFileVimCmd: (invoked by mv) execute arbitrary vim command on marked files, one at a time {{{2 " Uses the local marked-file list. fun! s:NetrwMarkFileVimCmd(islocal) -" call Dfunc("s:NetrwMarkFileVimCmd(islocal=".a:islocal.")") let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let curdir = s:NetrwGetCurdir(a:islocal) let curbufnr = bufnr("%") " sanity check if !exists("s:netrwmarkfilelist_{curbufnr}") || empty(s:netrwmarkfilelist_{curbufnr}) NetrwKeepj call netrw#ErrorMsg(2,"there are no marked files in this window (:help netrw-mf)",66) -" call Dret("s:NetrwMarkFileVimCmd") return endif -" call Decho("sanity chk passed: s:netrwmarkfilelist_".curbufnr."<".string(s:netrwmarkfilelist_{curbufnr}),'~'.expand("<slnum>")) if exists("s:netrwmarkfilelist_{curbufnr}") " get the command call inputsave() let cmd= input("Enter vim command: ","","file") call inputrestore() -" call Decho("cmd<".cmd.">",'~'.expand("<slnum>")) if cmd == "" -" " call Dret("s:NetrwMarkFileVimCmd : early exit, empty command") return endif " apply command to marked files. Substitute: filename -> % " If no %, then append a space and the filename to the command for fname in s:netrwmarkfilelist_{curbufnr} -" call Decho("fname<".fname.">",'~'.expand("<slnum>")) if a:islocal 1split exe "sil! NetrwKeepj keepalt e ".fnameescape(fname) -" call Decho("local<".fname.">: exe ".cmd,'~'.expand("<slnum>")) exe cmd exe "sil! keepalt wq!" else -" call Decho("remote<".fname.">: exe ".cmd." : NOT SUPPORTED YET",'~'.expand("<slnum>")) echo "sorry, \"mv\" not supported yet for remote files" endif endfor @@ -7602,14 +7086,11 @@ fun! s:NetrwMarkFileVimCmd(islocal) call s:NetrwUnmarkList(curbufnr,curdir) " refresh the listing - NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) NetrwKeepj call winrestview(svpos) else NetrwKeepj call netrw#ErrorMsg(s:ERROR,"no files marked!",59) endif - -" call Dret("s:NetrwMarkFileVimCmd") endfun " --------------------------------------------------------------------- @@ -7617,16 +7098,13 @@ endfun " as the marked file(s) (toggles suffix presence) " Uses the local marked file list. fun! s:NetrwMarkHideSfx(islocal) -" call Dfunc("s:NetrwMarkHideSfx(islocal=".a:islocal.")") let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let curbufnr = bufnr("%") " s:netrwmarkfilelist_{curbufnr}: the List of marked files if exists("s:netrwmarkfilelist_{curbufnr}") for fname in s:netrwmarkfilelist_{curbufnr} -" call Decho("s:NetrwMarkFileCopy: fname<".fname.">",'~'.expand("<slnum>")) " construct suffix pattern if fname =~ '\.' let sfxpat= "^.*".substitute(fname,'^.*\(\.[^. ]\+\)$','\1','') @@ -7646,7 +7124,6 @@ fun! s:NetrwMarkHideSfx(islocal) let itemnum= itemnum + 1 endfor endif -" call Decho("fname<".fname."> inhidelist=".inhidelist." sfxpat<".sfxpat.">",'~'.expand("<slnum>")) if inhidelist " remove sfxpat from list call remove(hidelist,itemnum) @@ -7661,14 +7138,11 @@ fun! s:NetrwMarkHideSfx(islocal) endfor " refresh the listing - NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) NetrwKeepj call winrestview(svpos) else NetrwKeepj call netrw#ErrorMsg(s:ERROR,"no files marked!",59) endif - -" call Dret("s:NetrwMarkHideSfx") endfun " --------------------------------------------------------------------- @@ -7872,6 +7346,46 @@ fun! s:NetrwMarkFileMove(islocal) endfun " --------------------------------------------------------------------- +" s:NetrwMarkFilePrint: (invoked by mp) This function prints marked files {{{2 +" using the hardcopy command. Local marked-file list only. +fun! s:NetrwMarkFilePrint(islocal) +" call Dfunc("s:NetrwMarkFilePrint(islocal=".a:islocal.")") + let curbufnr= bufnr("%") + + " sanity check + if !exists("s:netrwmarkfilelist_{curbufnr}") || empty(s:netrwmarkfilelist_{curbufnr}) + NetrwKeepj call netrw#ErrorMsg(2,"there are no marked files in this window (:help netrw-mf)",66) +" call Dret("s:NetrwMarkFilePrint") + return + endif +" call Decho("sanity chk passed: s:netrwmarkfilelist_".curbufnr."<".string(s:netrwmarkfilelist_{curbufnr}),'~'.expand("<slnum>")) + let curdir= s:NetrwGetCurdir(a:islocal) + + if exists("s:netrwmarkfilelist_{curbufnr}") + let netrwmarkfilelist = s:netrwmarkfilelist_{curbufnr} + call s:NetrwUnmarkList(curbufnr,curdir) + for fname in netrwmarkfilelist + if a:islocal + if g:netrw_keepdir + let fname= s:ComposePath(curdir,fname) + endif + else + let fname= curdir.fname + endif + 1split + " the autocmds will handle both local and remote files +" call Decho("exe sil e ".escape(fname,' '),'~'.expand("<slnum>")) + exe "sil NetrwKeepj e ".fnameescape(fname) +" call Decho("hardcopy",'~'.expand("<slnum>")) + hardcopy + q + endfor + 2match none + endif +" call Dret("s:NetrwMarkFilePrint") +endfun + +" --------------------------------------------------------------------- " s:NetrwMarkFileRegexp: (invoked by mr) This function is used to mark {{{2 " files when given a regexp (for which a prompt is " issued) (matches to name of files). @@ -7996,28 +7510,22 @@ endfun " s:NetrwMarkFileTag: (invoked by mT) This function applies g:netrw_ctags to marked files {{{2 " Uses the global markfilelist fun! s:NetrwMarkFileTag(islocal) -" call Dfunc("s:NetrwMarkFileTag(islocal=".a:islocal.")") let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let curdir = s:NetrwGetCurdir(a:islocal) let curbufnr = bufnr("%") " sanity check if !exists("s:netrwmarkfilelist_{curbufnr}") || empty(s:netrwmarkfilelist_{curbufnr}) NetrwKeepj call netrw#ErrorMsg(2,"there are no marked files in this window (:help netrw-mf)",66) -" call Dret("s:NetrwMarkFileTag") return endif -" call Decho("sanity chk passed: s:netrwmarkfilelist_".curbufnr."<".string(s:netrwmarkfilelist_{curbufnr}),'~'.expand("<slnum>")) if exists("s:netrwmarkfilelist") -" call Decho("s:netrwmarkfilelist".string(s:netrwmarkfilelist).">",'~'.expand("<slnum>")) let netrwmarkfilelist= join(map(deepcopy(s:netrwmarkfilelist), "s:ShellEscape(v:val,".!a:islocal.")")) call s:NetrwUnmarkAll() if a:islocal -" call Decho("call system(".g:netrw_ctags." ".netrwmarkfilelist.")",'~'.expand("<slnum>")) call system(g:netrw_ctags." ".netrwmarkfilelist) if v:shell_error call netrw#ErrorMsg(s:ERROR,"g:netrw_ctags<".g:netrw_ctags."> is not executable!",51) @@ -8030,18 +7538,14 @@ fun! s:NetrwMarkFileTag(islocal) 1split NetrwKeepj e tags let path= substitute(curdir,'^\(.*\)/[^/]*$','\1/','') -" call Decho("curdir<".curdir."> path<".path.">",'~'.expand("<slnum>")) exe 'NetrwKeepj %s/\t\(\S\+\)\t/\t'.escape(path,"/\n\r\\").'\1\t/e' call histdel("/",-1) wq! endif 2match none - call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) call winrestview(svpos) endif - -" call Dret("s:NetrwMarkFileTag") endfun " --------------------------------------------------------------------- @@ -8051,9 +7555,7 @@ endfun " s:netrwmftgt_islocal : 0=target directory is remote " 1=target directory is local fun! s:NetrwMarkFileTgt(islocal) -" call Dfunc("s:NetrwMarkFileTgt(islocal=".a:islocal.")") let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let curdir = s:NetrwGetCurdir(a:islocal) let hadtgt = exists("s:netrwmftgt") if !exists("w:netrw_bannercnt") @@ -8062,46 +7564,36 @@ fun! s:NetrwMarkFileTgt(islocal) " set up target if line(".") < w:netrw_bannercnt -" call Decho("set up target: line(.) < w:netrw_bannercnt=".w:netrw_bannercnt,'~'.expand("<slnum>")) " if cursor in banner region, use b:netrw_curdir for the target unless its already the target if exists("s:netrwmftgt") && exists("s:netrwmftgt_islocal") && s:netrwmftgt == b:netrw_curdir -" call Decho("cursor in banner region, and target already is <".b:netrw_curdir.">: removing target",'~'.expand("<slnum>")) unlet s:netrwmftgt s:netrwmftgt_islocal if g:netrw_fastbrowse <= 1 call s:LocalBrowseRefresh() endif - call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) call winrestview(svpos) -" call Dret("s:NetrwMarkFileTgt : removed target") return else let s:netrwmftgt= b:netrw_curdir -" call Decho("inbanner: s:netrwmftgt<".s:netrwmftgt.">",'~'.expand("<slnum>")) endif else " get word under cursor. " * If directory, use it for the target. " * If file, use b:netrw_curdir for the target -" call Decho("get word under cursor",'~'.expand("<slnum>")) let curword= s:NetrwGetWord() let tgtdir = s:ComposePath(curdir,curword) if a:islocal && isdirectory(s:NetrwFile(tgtdir)) let s:netrwmftgt = tgtdir -" call Decho("local isdir: s:netrwmftgt<".s:netrwmftgt.">",'~'.expand("<slnum>")) elseif !a:islocal && tgtdir =~ '/$' let s:netrwmftgt = tgtdir -" call Decho("remote isdir: s:netrwmftgt<".s:netrwmftgt.">",'~'.expand("<slnum>")) else let s:netrwmftgt = curdir -" call Decho("isfile: s:netrwmftgt<".s:netrwmftgt.">",'~'.expand("<slnum>")) endif endif if a:islocal " simplify the target (eg. /abc/def/../ghi -> /abc/ghi) let s:netrwmftgt= simplify(s:netrwmftgt) -" call Decho("simplify: s:netrwmftgt<".s:netrwmftgt.">",'~'.expand("<slnum>")) endif if g:netrw_cygwin let s:netrwmftgt= substitute(system("cygpath ".s:ShellEscape(s:netrwmftgt)),'\n$','','') @@ -8112,24 +7604,18 @@ fun! s:NetrwMarkFileTgt(islocal) " need to do refresh so that the banner will be updated " s:LocalBrowseRefresh handles all local-browsing buffers when not fast browsing if g:netrw_fastbrowse <= 1 -" call Decho("g:netrw_fastbrowse=".g:netrw_fastbrowse.", so refreshing all local netrw buffers",'~'.expand("<slnum>")) call s:LocalBrowseRefresh() endif -" call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) +" call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST - call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,w:netrw_treetop)) + call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,w:netrw_treetop,0)) else - call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) + call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) endif -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) call winrestview(svpos) if !hadtgt sil! NetrwKeepj norm! j endif - -" call Decho("getmatches=".string(getmatches()),'~'.expand("<slnum>")) -" call Decho("s:netrwmarkfilelist=".(exists("s:netrwmarkfilelist")? string(s:netrwmarkfilelist) : 'n/a'),'~'.expand("<slnum>")) -" call Dret("s:NetrwMarkFileTgt : netrwmftgt<".(exists("s:netrwmftgt")? s:netrwmftgt : "").">") endfun " --------------------------------------------------------------------- @@ -8248,7 +7734,7 @@ fun! netrw#Shrink() elseif winwidth(bufwinnr(t:netrw_lexbufnr)) >= 0 exe "vert resize ".t:netrw_winwidth " call Decho("vert resize ".t:netrw_winwidth,'~'.expand("<slnum>")) - else + else call netrw#Lexplore(0,0) endif @@ -8263,23 +7749,17 @@ endfun " --------------------------------------------------------------------- " s:NetSortSequence: allows user to edit the sorting sequence {{{2 fun! s:NetSortSequence(islocal) -" call Dfunc("NetSortSequence(islocal=".a:islocal.")") - let ykeep= @@ let svpos= winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) call inputsave() let newsortseq= input("Edit Sorting Sequence: ",g:netrw_sort_sequence) call inputrestore() " refresh the listing let g:netrw_sort_sequence= newsortseq - NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) NetrwKeepj call winrestview(svpos) let @@= ykeep - -" call Dret("NetSortSequence") endfun " --------------------------------------------------------------------- @@ -8350,9 +7830,7 @@ endfun " Marked files suitable for use with 2match are in: " s:netrwmarkfilemtch_# -- used with 2match to display marked files fun! s:NetrwUnMarkFile(islocal) -" call Dfunc("s:NetrwUnMarkFile(islocal=".a:islocal.")") let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let curbufnr = bufnr("%") " unmark marked file list @@ -8372,10 +7850,8 @@ fun! s:NetrwUnMarkFile(islocal) endwhile 2match none -" call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) -"call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) +" call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) call winrestview(svpos) -" call Dret("s:NetrwUnMarkFile") endfun " --------------------------------------------------------------------- @@ -8510,69 +7986,47 @@ endfun " choice = 2 : didn't save modified file, opened window " choice = 3 : cancel open fun! s:NetrwPrevWinOpen(islocal) -" call Dfunc("s:NetrwPrevWinOpen(islocal=".a:islocal.") win#".winnr()) - let ykeep= @@ " grab a copy of the b:netrw_curdir to pass it along to newly split windows let curdir = b:netrw_curdir -" call Decho("COMBAK#1: mod=".&mod." win#".winnr()) " get last window number and the word currently under the cursor let origwin = winnr() let lastwinnr = winnr("$") -" call Decho("origwin#".origwin." lastwinnr#".lastwinnr) -" call Decho("COMBAK#2: mod=".&mod." win#".winnr()) let curword = s:NetrwGetWord() let choice = 0 let s:prevwinopen= 1 " lets s:NetrwTreeDir() know that NetrwPrevWinOpen called it (s:NetrwTreeDir() will unlet s:prevwinopen) -" call Decho("COMBAK#3: mod=".&mod." win#".winnr()) let s:treedir = s:NetrwTreeDir(a:islocal) -" call Decho("COMBAK#4: mod=".&mod." win#".winnr()) let curdir = s:treedir -" call Decho("COMBAK#5: mod=".&mod." win#".winnr()) -" call Decho("winnr($)#".lastwinnr." curword<".curword.">",'~'.expand("<slnum>")) -" call Decho("COMBAK#6: mod=".&mod." win#".winnr()) let didsplit = 0 if lastwinnr == 1 " if only one window, open a new one first -" call Decho("only one window, so open a new one (g:netrw_alto=".g:netrw_alto.")",'~'.expand("<slnum>")) " g:netrw_preview=0: preview window shown in a horizontally split window " g:netrw_preview=1: preview window shown in a vertically split window if g:netrw_preview " vertically split preview window let winsz= (g:netrw_winsize > 0)? (g:netrw_winsize*winwidth(0))/100 : -g:netrw_winsize -" call Decho("exe ".(g:netrw_alto? "top " : "bot ")."vert ".winsz."wincmd s",'~'.expand("<slnum>")) exe (g:netrw_alto? "top " : "bot ")."vert ".winsz."wincmd s" else " horizontally split preview window let winsz= (g:netrw_winsize > 0)? (g:netrw_winsize*winheight(0))/100 : -g:netrw_winsize -" call Decho("exe ".(g:netrw_alto? "bel " : "abo ").winsz."wincmd s",'~'.expand("<slnum>")) exe (g:netrw_alto? "bel " : "abo ").winsz."wincmd s" endif let didsplit = 1 -" call Decho("did split",'~'.expand("<slnum>")) else -" call Decho("COMBAK#7: mod=".&mod." win#".winnr()) NetrwKeepj call s:SaveBufVars() -" call Decho("COMBAK#8: mod=".&mod." win#".winnr()) let eikeep= &ei -" call Decho("COMBAK#9: mod=".&mod." win#".winnr()) setl ei=all -" call Decho("COMBAK#10: mod=".&mod." win#".winnr()) wincmd p -" call Decho("COMBAK#11: mod=".&mod) -" call Decho("wincmd p (now in win#".winnr().") curdir<".curdir.">",'~'.expand("<slnum>")) -" call Decho("COMBAK#12: mod=".&mod) - + if exists("s:lexplore_win") && s:lexplore_win == winnr() " whoops -- user trying to open file in the Lexplore window. " Use Lexplore's opening-file window instead. -" call Decho("whoops -- user trying to open file in Lexplore Window. Use win#".g:netrw_chgwin." instead") " exe g:netrw_chgwin."wincmd w" wincmd p - call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,s:NetrwGetWord())) + call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,s:NetrwGetWord(),1)) endif " prevwinnr: the window number of the "prev" window @@ -8583,28 +8037,20 @@ fun! s:NetrwPrevWinOpen(islocal) let prevbufname = bufname("%") let prevmod = &mod let bnrcnt = 0 -" call Decho("COMBAK#13: mod=".&mod." win#".winnr()) NetrwKeepj call s:RestoreBufVars() -" call Decho("after wincmd p: win#".winnr()." win($)#".winnr("$")." origwin#".origwin." &mod=".&mod." bufname(%)<".bufname("%")."> prevbufnr=".prevbufnr,'~'.expand("<slnum>")) -" call Decho("COMBAK#14: mod=".&mod." win#".winnr()) " if the previous window's buffer has been changed (ie. its modified flag is set), " and it doesn't appear in any other extant window, then ask the " user if s/he wants to abandon modifications therein. if prevmod -" call Decho("detected that prev window's buffer has been modified: prevbufnr=".prevbufnr." winnr()#".winnr(),'~'.expand("<slnum>")) windo if winbufnr(0) == prevbufnr | let bnrcnt=bnrcnt+1 | endif -" call Decho("prevbufnr=".prevbufnr." bnrcnt=".bnrcnt." buftype=".&bt." winnr()=".winnr()." prevwinnr#".prevwinnr,'~'.expand("<slnum>")) exe prevwinnr."wincmd w" -" call Decho("COMBAK#15: mod=".&mod." win#".winnr()) if bnrcnt == 1 && &hidden == 0 " only one copy of the modified buffer in a window, and " hidden not set, so overwriting will lose the modified file. Ask first... let choice = confirm("Save modified buffer<".prevbufname."> first?","&Yes\n&No\n&Cancel") -" call Decho("prevbufname<".prevbufname."> choice=".choice." current-winnr#".winnr(),'~'.expand("<slnum>")) let &ei= eikeep -" call Decho("COMBAK#16: mod=".&mod." win#".winnr()) if choice == 1 " Yes -- write file & then browse @@ -8615,41 +8061,35 @@ fun! s:NetrwPrevWinOpen(islocal) exe origwin."wincmd w" let &ei = eikeep let @@ = ykeep -" call Dret("s:NetrwPrevWinOpen ".choice." : unable to write <".prevbufname.">") return choice endif elseif choice == 2 " No -- don't worry about changed file, just browse anyway -" call Decho("don't worry about chgd file, just browse anyway (winnr($)#".winnr("$").")",'~'.expand("<slnum>")) echomsg "**note** changes to ".prevbufname." abandoned" else " Cancel -- don't do this -" call Decho("cancel, don't browse, switch to win#".origwin,'~'.expand("<slnum>")) exe origwin."wincmd w" let &ei= eikeep let @@ = ykeep -" call Dret("s:NetrwPrevWinOpen ".choice." : cancelled") return choice endif endif endif let &ei= eikeep endif -" call Decho("COMBAK#17: mod=".&mod." win#".winnr()) " restore b:netrw_curdir (window split/enew may have lost it) let b:netrw_curdir= curdir if a:islocal < 2 if a:islocal - call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(a:islocal,curword)) + call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(a:islocal,curword,0)) else - call s:NetrwBrowse(a:islocal,s:NetrwBrowseChgDir(a:islocal,curword)) + call s:NetrwBrowse(a:islocal,s:NetrwBrowseChgDir(a:islocal,curword,0)) endif endif let @@= ykeep -" call Dret("s:NetrwPrevWinOpen ".choice) return choice endfun @@ -8956,32 +8396,25 @@ endfun " Called by NetrwMarkFileCopy() " Interfaces to s:NetrwRefresh() and s:LocalBrowseRefresh() fun! s:NetrwRefreshDir(islocal,dirname) -" call Dfunc("s:NetrwRefreshDir(islocal=".a:islocal." dirname<".a:dirname.">) g:netrw_fastbrowse=".g:netrw_fastbrowse) if g:netrw_fastbrowse == 0 " slowest mode (keep buffers refreshed, local or remote) -" call Decho("slowest mode: keep buffers refreshed, local or remote",'~'.expand("<slnum>")) let tgtwin= bufwinnr(a:dirname) -" call Decho("tgtwin= bufwinnr(".a:dirname.")=".tgtwin,'~'.expand("<slnum>")) if tgtwin > 0 " tgtwin is being displayed, so refresh it let curwin= winnr() -" call Decho("refresh tgtwin#".tgtwin." (curwin#".curwin.")",'~'.expand("<slnum>")) exe tgtwin."wincmd w" - NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) exe curwin."wincmd w" elseif bufnr(a:dirname) > 0 let bn= bufnr(a:dirname) -" call Decho("bd bufnr(".a:dirname.")=".bn,'~'.expand("<slnum>")) exe "sil keepj bd ".bn endif elseif g:netrw_fastbrowse <= 1 -" call Decho("medium-speed mode: refresh local buffers only",'~'.expand("<slnum>")) NetrwKeepj call s:LocalBrowseRefresh() endif -" call Dret("s:NetrwRefreshDir") endfun " --------------------------------------------------------------------- @@ -9121,18 +8554,13 @@ endfun " ===================================================================== " s:NetrwSortStyle: change sorting style (name - time - size - exten) and refresh display {{{2 fun! s:NetrwSortStyle(islocal) -" call Dfunc("s:NetrwSortStyle(islocal=".a:islocal.") netrw_sort_by<".g:netrw_sort_by.">") NetrwKeepj call s:NetrwSaveWordPosn() let svpos= winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let g:netrw_sort_by= (g:netrw_sort_by =~# '^n')? 'time' : (g:netrw_sort_by =~# '^t')? 'size' : (g:netrw_sort_by =~# '^siz')? 'exten' : 'name' NetrwKeepj norm! 0 - NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) NetrwKeepj call winrestview(svpos) - -" call Dret("s:NetrwSortStyle : netrw_sort_by<".g:netrw_sort_by.">") endfun " --------------------------------------------------------------------- @@ -9144,7 +8572,6 @@ endfun " =4 : local and t " =5 : local and v fun! s:NetrwSplit(mode) -" call Dfunc("s:NetrwSplit(mode=".a:mode.") alto=".g:netrw_alto." altv=".g:netrw_altv) let ykeep= @@ call s:SaveWinVars() @@ -9153,17 +8580,15 @@ fun! s:NetrwSplit(mode) " remote and o let winsz= (g:netrw_winsize > 0)? (g:netrw_winsize*winheight(0))/100 : -g:netrw_winsize if winsz == 0|let winsz= ""|endif -" call Decho("exe ".(g:netrw_alto? "bel " : "abo ").winsz."wincmd s",'~'.expand("<slnum>")) exe (g:netrw_alto? "bel " : "abo ").winsz."wincmd s" let s:didsplit= 1 NetrwKeepj call s:RestoreWinVars() - NetrwKeepj call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,s:NetrwGetWord())) + NetrwKeepj call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,s:NetrwGetWord(),1)) unlet s:didsplit elseif a:mode == 1 " remote and t - let newdir = s:NetrwBrowseChgDir(0,s:NetrwGetWord()) -" call Decho("tabnew",'~'.expand("<slnum>")) + let newdir = s:NetrwBrowseChgDir(0,s:NetrwGetWord(),1) tabnew let s:didsplit= 1 NetrwKeepj call s:RestoreWinVars() @@ -9174,22 +8599,20 @@ fun! s:NetrwSplit(mode) " remote and v let winsz= (g:netrw_winsize > 0)? (g:netrw_winsize*winwidth(0))/100 : -g:netrw_winsize if winsz == 0|let winsz= ""|endif -" call Decho("exe ".(g:netrw_altv? "rightb " : "lefta ").winsz."wincmd v",'~'.expand("<slnum>")) exe (g:netrw_altv? "rightb " : "lefta ").winsz."wincmd v" let s:didsplit= 1 NetrwKeepj call s:RestoreWinVars() - NetrwKeepj call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,s:NetrwGetWord())) + NetrwKeepj call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,s:NetrwGetWord(),1)) unlet s:didsplit elseif a:mode == 3 " local and o let winsz= (g:netrw_winsize > 0)? (g:netrw_winsize*winheight(0))/100 : -g:netrw_winsize if winsz == 0|let winsz= ""|endif -" call Decho("exe ".(g:netrw_alto? "bel " : "abo ").winsz."wincmd s",'~'.expand("<slnum>")) exe (g:netrw_alto? "bel " : "abo ").winsz."wincmd s" let s:didsplit= 1 NetrwKeepj call s:RestoreWinVars() - NetrwKeepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,s:NetrwGetWord())) + NetrwKeepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,s:NetrwGetWord(),1)) unlet s:didsplit elseif a:mode == 4 @@ -9206,12 +8629,11 @@ fun! s:NetrwSplit(mode) exe "NetrwKeepj norm! ".netrw_line."G0".netrw_col."\<bar>" let &ei = eikeep let netrw_curdir = s:NetrwTreeDir(0) -" call Decho("tabnew",'~'.expand("<slnum>")) tabnew let b:netrw_curdir = netrw_curdir let s:didsplit = 1 NetrwKeepj call s:RestoreWinVars() - NetrwKeepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,cursorword)) + NetrwKeepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,cursorword,0)) if &ft == "netrw" setl ei=all exe "NetrwKeepj norm! ".netrw_hline."G0z\<CR>" @@ -9224,11 +8646,10 @@ fun! s:NetrwSplit(mode) " local and v let winsz= (g:netrw_winsize > 0)? (g:netrw_winsize*winwidth(0))/100 : -g:netrw_winsize if winsz == 0|let winsz= ""|endif -" call Decho("exe ".(g:netrw_altv? "rightb " : "lefta ").winsz."wincmd v",'~'.expand("<slnum>")) exe (g:netrw_altv? "rightb " : "lefta ").winsz."wincmd v" let s:didsplit= 1 NetrwKeepj call s:RestoreWinVars() - NetrwKeepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,s:NetrwGetWord())) + NetrwKeepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,s:NetrwGetWord(),1)) unlet s:didsplit else @@ -9236,7 +8657,6 @@ fun! s:NetrwSplit(mode) endif let @@= ykeep -" call Dret("s:NetrwSplit") endfun " --------------------------------------------------------------------- @@ -9306,91 +8726,49 @@ endfun " s:NetrwTreeDir: determine tree directory given current cursor position {{{2 " (full path directory with trailing slash returned) fun! s:NetrwTreeDir(islocal) -" call Dfunc("s:NetrwTreeDir(islocal=".a:islocal.") getline(".line(".").")"."<".getline('.')."> b:netrw_curdir<".b:netrw_curdir."> tab#".tabpagenr()." win#".winnr()." buf#".bufnr("%")."<".bufname("%")."> ft=".&ft) -" call Decho("Determine tree directory given current cursor position") -" call Decho("g:netrw_keepdir =".(exists("g:netrw_keepdir")? g:netrw_keepdir : 'n/a'),'~'.expand("<slnum>")) -" call Decho("w:netrw_liststyle=".(exists("w:netrw_liststyle")? w:netrw_liststyle : 'n/a'),'~'.expand("<slnum>")) -" call Decho("w:netrw_treetop =".(exists("w:netrw_treetop")? w:netrw_treetop : 'n/a'),'~'.expand("<slnum>")) -" call Decho("current line<".getline(".").">") if exists("s:treedir") && exists("s:prevwinopen") " s:NetrwPrevWinOpen opens a "previous" window -- and thus needs to and does call s:NetrwTreeDir early -" call Decho('s:NetrwPrevWinOpen opens a "previous" window -- and thus needs to and does call s:NetrwTreeDir early') let treedir= s:treedir unlet s:treedir unlet s:prevwinopen -" call Dret("s:NetrwTreeDir ".treedir.": early return since s:treedir existed previously") return treedir endif if exists("s:prevwinopen") unlet s:prevwinopen endif -" call Decho("COMBAK#18 : mod=".&mod." win#".winnr()) if !exists("b:netrw_curdir") || b:netrw_curdir == "" let b:netrw_curdir= getcwd() endif let treedir = b:netrw_curdir -" call Decho("set initial treedir<".treedir.">",'~'.expand("<slnum>")) -" call Decho("COMBAK#19 : mod=".&mod." win#".winnr()) - let s:treecurpos= winsaveview() -" call Decho("saving posn to s:treecurpos<".string(s:treecurpos).">",'~'.expand("<slnum>")) -" call Decho("COMBAK#20 : mod=".&mod." win#".winnr()) if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST -" call Decho("w:netrw_liststyle is TREELIST:",'~'.expand("<slnum>")) -" call Decho("line#".line(".")." getline(.)<".getline('.')."> treecurpos<".string(s:treecurpos).">",'~'.expand("<slnum>")) -" call Decho("COMBAK#21 : mod=".&mod." win#".winnr()) " extract tree directory if on a line specifying a subdirectory (ie. ends with "/") let curline= substitute(getline('.'),"\t -->.*$",'','') if curline =~ '/$' -" call Decho("extract tree subdirectory from current line",'~'.expand("<slnum>")) let treedir= substitute(getline('.'),'^\%('.s:treedepthstring.'\)*\([^'.s:treedepthstring.'].\{-}\)$','\1','e') -" call Decho("treedir<".treedir.">",'~'.expand("<slnum>")) elseif curline =~ '@$' -" call Decho("handle symbolic link from current line",'~'.expand("<slnum>")) - let potentialdir= resolve(substitute(substitute(getline('.'),'@.*$','','e'),'^|*\s*','','e')) -" call Decho("treedir<".treedir.">",'~'.expand("<slnum>")) + let potentialdir= resolve(s:NetrwTreePath(w:netrw_treetop)) else -" call Decho("do not extract tree subdirectory from current line and set treedir to empty",'~'.expand("<slnum>")) let treedir= "" endif -" call Decho("COMBAK#22 : mod=".&mod." win#".winnr()) " detect user attempting to close treeroot -" call Decho("check if user is attempting to close treeroot",'~'.expand("<slnum>")) -" call Decho(".win#".winnr()." buf#".bufnr("%")."<".bufname("%").">",'~'.expand("<slnum>")) -" call Decho(".getline(".line(".").")<".getline('.').'> '.((getline('.') =~# '^'.s:treedepthstring)? '=~#' : '!~').' ^'.s:treedepthstring,'~'.expand("<slnum>")) if curline !~ '^'.s:treedepthstring && getline('.') != '..' -" call Decho(".user may have attempted to close treeroot",'~'.expand("<slnum>")) " now force a refresh -" call Decho(".force refresh: clear buffer<".expand("%")."> with :%d",'~'.expand("<slnum>")) sil! NetrwKeepj %d _ -" call Dret("s:NetrwTreeDir <".treedir."> : (side effect) s:treecurpos<".(exists("s:treecurpos")? string(s:treecurpos) : 'n/a').">") return b:netrw_curdir -" else " Decho -" call Decho(".user not attempting to close treeroot",'~'.expand("<slnum>")) endif -" call Decho("COMBAK#23 : mod=".&mod." win#".winnr()) - -" call Decho("islocal=".a:islocal." curline<".curline.">",'~'.expand("<slnum>")) -" call Decho("potentialdir<".potentialdir."> isdir=".isdirectory(potentialdir),'~'.expand("<slnum>")) -" call Decho("COMBAK#24 : mod=".&mod." win#".winnr()) " COMBAK: a symbolic link may point anywhere -- so it will be used to start a new treetop " if a:islocal && curline =~ '@$' && isdirectory(s:NetrwFile(potentialdir)) " let newdir = w:netrw_treetop.'/'.potentialdir -" " call Decho("apply NetrwTreePath to newdir<".newdir.">",'~'.expand("<slnum>")) -" let treedir = s:NetrwTreePath(newdir) -" let w:netrw_treetop = newdir -" " call Decho("newdir <".newdir.">",'~'.expand("<slnum>")) -" else -" call Decho("apply NetrwTreePath to treetop<".w:netrw_treetop.">",'~'.expand("<slnum>")) if a:islocal && curline =~ '@$' if isdirectory(s:NetrwFile(potentialdir)) - let treedir = w:netrw_treetop.'/'.potentialdir.'/' + let treedir = potentialdir let w:netrw_treetop = treedir endif else @@ -9398,29 +8776,21 @@ fun! s:NetrwTreeDir(islocal) let treedir = s:NetrwTreePath(w:netrw_treetop) endif endif -" call Decho("COMBAK#25 : mod=".&mod." win#".winnr()) " sanity maintenance: keep those //s away... let treedir= substitute(treedir,'//$','/','') -" call Decho("treedir<".treedir.">",'~'.expand("<slnum>")) -" call Decho("COMBAK#26 : mod=".&mod." win#".winnr()) - -" call Dret("s:NetrwTreeDir <".treedir."> : (side effect) s:treecurpos<".(exists("s:treecurpos")? string(s:treecurpos) : 'n/a').">") return treedir endfun " --------------------------------------------------------------------- " s:NetrwTreeDisplay: recursive tree display {{{2 fun! s:NetrwTreeDisplay(dir,depth) -" call Dfunc("NetrwTreeDisplay(dir<".a:dir."> depth<".a:depth.">)") - - " insure that there are no folds + " ensure that there are no folds setl nofen " install ../ and shortdir if a:depth == "" call setline(line("$")+1,'../') -" call Decho("setline#".line("$")." ../ (depth is zero)",'~'.expand("<slnum>")) endif if a:dir =~ '^\a\{3,}://' if a:dir == w:netrw_treetop @@ -9433,19 +8803,16 @@ fun! s:NetrwTreeDisplay(dir,depth) let shortdir= substitute(a:dir,'^.*/','','e') call setline(line("$")+1,a:depth.shortdir.'/') endif -" call Decho("setline#".line("$")." shortdir<".a:depth.shortdir.">",'~'.expand("<slnum>")) " append a / to dir if its missing one let dir= a:dir " display subtrees (if any) let depth= s:treedepthstring.a:depth -" call Decho("display subtrees with depth<".depth."> and current leaves",'~'.expand("<slnum>")) " implement g:netrw_hide for tree listings (uses g:netrw_list_hide) if g:netrw_hide == 1 " hide given patterns let listhide= split(g:netrw_list_hide,',') -" call Decho("listhide=".string(listhide)) for pat in listhide call filter(w:netrw_treedict[dir],'v:val !~ "'.escape(pat,'\\').'"') endfor @@ -9453,7 +8820,6 @@ fun! s:NetrwTreeDisplay(dir,depth) elseif g:netrw_hide == 2 " show given patterns (only) let listhide= split(g:netrw_list_hide,',') -" call Decho("listhide=".string(listhide)) let entries=[] for entry in w:netrw_treedict[dir] for pat in listhide @@ -9468,77 +8834,57 @@ fun! s:NetrwTreeDisplay(dir,depth) if depth != "" " always remove "." and ".." entries when there's depth call filter(w:netrw_treedict[dir],'v:val !~ "\\.\\.$"') + call filter(w:netrw_treedict[dir],'v:val !~ "\\.\\./$"') call filter(w:netrw_treedict[dir],'v:val !~ "\\.$"') + call filter(w:netrw_treedict[dir],'v:val !~ "\\./$"') endif -" call Decho("for every entry in w:netrw_treedict[".dir."]=".string(w:netrw_treedict[dir]),'~'.expand("<slnum>")) for entry in w:netrw_treedict[dir] if dir =~ '/$' let direntry= substitute(dir.entry,'[@/]$','','e') else let direntry= substitute(dir.'/'.entry,'[@/]$','','e') endif -" call Decho("dir<".dir."> entry<".entry."> direntry<".direntry.">",'~'.expand("<slnum>")) if entry =~ '/$' && has_key(w:netrw_treedict,direntry) -" call Decho("<".direntry."> is a key in treedict - display subtree for it",'~'.expand("<slnum>")) NetrwKeepj call s:NetrwTreeDisplay(direntry,depth) elseif entry =~ '/$' && has_key(w:netrw_treedict,direntry.'/') -" call Decho("<".direntry."/> is a key in treedict - display subtree for it",'~'.expand("<slnum>")) NetrwKeepj call s:NetrwTreeDisplay(direntry.'/',depth) elseif entry =~ '@$' && has_key(w:netrw_treedict,direntry.'@') -" call Decho("<".direntry."/> is a key in treedict - display subtree for it",'~'.expand("<slnum>")) - NetrwKeepj call s:NetrwTreeDisplay(direntry.'/',depth) + NetrwKeepj call s:NetrwTreeDisplay(direntry.'@',depth) else -" call Decho("<".entry."> is not a key in treedict (no subtree)",'~'.expand("<slnum>")) sil! NetrwKeepj call setline(line("$")+1,depth.entry) endif endfor -" call Decho("displaying: ".string(getline(w:netrw_bannercnt,'$'))) - -" call Dret("NetrwTreeDisplay") endfun " --------------------------------------------------------------------- " s:NetrwRefreshTreeDict: updates the contents information for a tree (w:netrw_treedict) {{{2 fun! s:NetrwRefreshTreeDict(dir) -" call Dfunc("s:NetrwRefreshTreeDict(dir<".a:dir.">)") if !exists("w:netrw_treedict") -" call Dret("s:NetrwRefreshTreeDict : w:netrw_treedict doesn't exist") return endif for entry in w:netrw_treedict[a:dir] let direntry= substitute(a:dir.'/'.entry,'[@/]$','','e') -" call Decho("a:dir<".a:dir."> entry<".entry."> direntry<".direntry.">",'~'.expand("<slnum>")) if entry =~ '/$' && has_key(w:netrw_treedict,direntry) -" call Decho("<".direntry."> is a key in treedict - display subtree for it",'~'.expand("<slnum>")) NetrwKeepj call s:NetrwRefreshTreeDict(direntry) - let liststar = s:NetrwGlob(direntry,'*',1) - let listdotstar = s:NetrwGlob(direntry,'.*',1) - let w:netrw_treedict[direntry] = liststar + listdotstar -" call Decho("updating w:netrw_treedict[".direntry.']='.string(w:netrw_treedict[direntry]),'~'.expand("<slnum>")) + let filelist = s:NetrwLocalListingList(direntry,0) + let w:netrw_treedict[direntry] = sort(filelist) elseif entry =~ '/$' && has_key(w:netrw_treedict,direntry.'/') -" call Decho("<".direntry."/> is a key in treedict - display subtree for it",'~'.expand("<slnum>")) NetrwKeepj call s:NetrwRefreshTreeDict(direntry.'/') - let liststar = s:NetrwGlob(direntry.'/','*',1) - let listdotstar= s:NetrwGlob(direntry.'/','.*',1) - let w:netrw_treedict[direntry]= liststar + listdotstar -" call Decho("updating w:netrw_treedict[".direntry.']='.string(w:netrw_treedict[direntry]),'~'.expand("<slnum>")) + let filelist = s:NetrwLocalListingList(direntry.'/',0) + let w:netrw_treedict[direntry] = sort(filelist) elseif entry =~ '@$' && has_key(w:netrw_treedict,direntry.'@') -" call Decho("<".direntry."/> is a key in treedict - display subtree for it",'~'.expand("<slnum>")) NetrwKeepj call s:NetrwRefreshTreeDict(direntry.'/') let liststar = s:NetrwGlob(direntry.'/','*',1) let listdotstar= s:NetrwGlob(direntry.'/','.*',1) -" call Decho("updating w:netrw_treedict[".direntry.']='.string(w:netrw_treedict[direntry]),'~'.expand("<slnum>")) else -" call Decho('not updating w:netrw_treedict['.string(direntry).'] with entry<'.string(entry).'> (no subtree)','~'.expand("<slnum>")) endif endfor -" call Dret("s:NetrwRefreshTreeDict") endfun " --------------------------------------------------------------------- @@ -9546,22 +8892,16 @@ endfun " Called by s:PerformListing() fun! s:NetrwTreeListing(dirname) if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST -" call Dfunc("s:NetrwTreeListing() bufname<".expand("%").">") -" call Decho("curdir<".a:dirname.">",'~'.expand("<slnum>")) -" call Decho("win#".winnr().": w:netrw_treetop ".(exists("w:netrw_treetop")? "exists" : "doesn't exist")." w:netrw_treedict ".(exists("w:netrw_treedict")? "exists" : "doesn't exit"),'~'.expand("<slnum>")) -" call Decho("g:netrw_banner=".g:netrw_banner.": banner ".(g:netrw_banner? "enabled" : "suppressed").": (line($)=".line("$")." byte2line(1)=".byte2line(1)." bannercnt=".w:netrw_bannercnt.")",'~'.expand("<slnum>")) " update the treetop if !exists("w:netrw_treetop") -" call Decho("update the treetop (w:netrw_treetop doesn't exist yet)",'~'.expand("<slnum>")) let w:netrw_treetop= a:dirname let s:netrw_treetop= w:netrw_treetop -" call Decho("w:netrw_treetop<".w:netrw_treetop."> (reusing)",'~'.expand("<slnum>")) - elseif (w:netrw_treetop =~ ('^'.a:dirname) && s:Strlen(a:dirname) < s:Strlen(w:netrw_treetop)) || a:dirname !~ ('^'.w:netrw_treetop) -" call Decho("update the treetop (override w:netrw_treetop with a:dirname<".a:dirname.">)",'~'.expand("<slnum>")) + " use \V in case the directory contains specials chars like '$' or '~' + elseif (w:netrw_treetop =~ ('^'.'\V'.a:dirname) && s:Strlen(a:dirname) < s:Strlen(w:netrw_treetop)) + \ || a:dirname !~ ('^'.'\V'.w:netrw_treetop) let w:netrw_treetop= a:dirname let s:netrw_treetop= w:netrw_treetop -" call Decho("w:netrw_treetop<".w:netrw_treetop."> (went up)",'~'.expand("<slnum>")) endif if exists("w:netrw_treetop") let s:netrw_treetop= w:netrw_treetop @@ -9572,16 +8912,12 @@ fun! s:NetrwTreeListing(dirname) if !exists("w:netrw_treedict") " insure that we have a treedict, albeit empty -" call Decho("initializing w:netrw_treedict to empty",'~'.expand("<slnum>")) let w:netrw_treedict= {} endif " update the dictionary for the current directory -" call Decho("updating: w:netrw_treedict[".a:dirname.'] -> [directory listing]','~'.expand("<slnum>")) -" call Decho("w:netrw_bannercnt=".w:netrw_bannercnt." line($)=".line("$"),'~'.expand("<slnum>")) - exe "sil! NetrwKeepj ".w:netrw_bannercnt.',$g@^\.\.\=/$@d _' + exe "sil! NetrwKeepj keepp ".w:netrw_bannercnt.',$g@^\.\.\=/$@d _' let w:netrw_treedict[a:dirname]= getline(w:netrw_bannercnt,line("$")) -" call Decho("w:treedict[".a:dirname."]= ".string(w:netrw_treedict[a:dirname]),'~'.expand("<slnum>")) exe "sil! NetrwKeepj ".w:netrw_bannercnt.",$d _" " if past banner, record word @@ -9590,23 +8926,17 @@ fun! s:NetrwTreeListing(dirname) else let fname= "" endif -" call Decho("fname<".fname.">",'~'.expand("<slnum>")) -" call Decho("g:netrw_banner=".g:netrw_banner.": banner ".(g:netrw_banner? "enabled" : "suppressed").": (line($)=".line("$")." byte2line(1)=".byte2line(1)." bannercnt=".w:netrw_bannercnt.")",'~'.expand("<slnum>")) " display from treetop on down -" call Decho("(s:NetrwTreeListing) w:netrw_treetop<".w:netrw_treetop.">") NetrwKeepj call s:NetrwTreeDisplay(w:netrw_treetop,"") -" call Decho("s:NetrwTreeDisplay) setl noma nomod ro",'~'.expand("<slnum>")) " remove any blank line remaining as line#1 (happens in treelisting mode with banner suppressed) while getline(1) =~ '^\s*$' && byte2line(1) > 0 -" call Decho("deleting blank line",'~'.expand("<slnum>")) 1d endwhile exe "setl ".g:netrw_bufsettings -" call Dret("s:NetrwTreeListing : bufname<".expand("%").">") return endif endfun @@ -9721,6 +9051,11 @@ fun! s:NetrwWideListing() let newcolstart = w:netrw_bannercnt + fpc let newcolend = newcolstart + fpc - 1 " call Decho("bannercnt=".w:netrw_bannercnt." fpl=".w:netrw_fpl." fpc=".fpc." newcol[".newcolstart.",".newcolend."]",'~'.expand("<slnum>")) + if !has('nvim') && has("clipboard") && g:netrw_clipboard +" call Decho("(s:NetrwWideListing) save @* and @+",'~'.expand("<slnum>")) + sil! let keepregstar = @* + sil! let keepregplus = @+ + endif while line("$") >= newcolstart if newcolend > line("$") | let newcolend= line("$") | endif let newcolqty= newcolend - newcolstart @@ -9734,6 +9069,11 @@ fun! s:NetrwWideListing() exe "sil! NetrwKeepj ".newcolstart.','.newcolend.'d _' exe 'sil! NetrwKeepj '.w:netrw_bannercnt endwhile + if !has('nvim') && has("clipboard") +" call Decho("(s:NetrwWideListing) restore @* and @+",'~'.expand("<slnum>")) + if @* != keepregstar | sil! let @* = keepregstar | endif + if @+ != keepregplus | sil! let @+ = keepregplus | endif + endif exe "sil! NetrwKeepj ".w:netrw_bannercnt.',$s/\s\+$//e' NetrwKeepj call histdel("/",-1) exe 'nno <buffer> <silent> w :call search(''^.\\|\s\s\zs\S'',''W'')'."\<cr>" @@ -10003,7 +9343,7 @@ fun! s:PerformListing(islocal) " resolve symbolic links if local and (thin or tree) if a:islocal && (w:netrw_liststyle == s:THINLIST || (exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST)) " call Decho("--resolve symbolic links if local and thin|tree",'~'.expand("<slnum>")) - sil! g/@$/call s:ShowLink() + sil! keepp g/@$/call s:ShowLink() endif if exists("w:netrw_bannercnt") && (line("$") >= w:netrw_bannercnt || !g:netrw_banner) @@ -10452,15 +9792,11 @@ endfun " --------------------------------------------------------------------- " s:NetrwRemoteRm: remove/delete a remote file or directory {{{2 fun! s:NetrwRemoteRm(usrhost,path) range -" call Dfunc("s:NetrwRemoteRm(usrhost<".a:usrhost."> path<".a:path.">) virtcol=".virtcol(".")) -" call Decho("firstline=".a:firstline." lastline=".a:lastline,'~'.expand("<slnum>")) let svpos= winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) let all= 0 if exists("s:netrwmarkfilelist_{bufnr('%')}") " remove all marked files -" call Decho("remove all marked files with bufnr#".bufnr("%"),'~'.expand("<slnum>")) for fname in s:netrwmarkfilelist_{bufnr("%")} let ok= s:NetrwRemoteRmFile(a:path,fname,all) if ok =~# 'q\%[uit]' @@ -10473,7 +9809,6 @@ fun! s:NetrwRemoteRm(usrhost,path) range else " remove files specified by range -" call Decho("remove files specified by range",'~'.expand("<slnum>")) " preparation for removing multiple files/directories let keepsol = &l:sol @@ -10495,12 +9830,8 @@ fun! s:NetrwRemoteRm(usrhost,path) range endif " refresh the (remote) directory listing -" call Decho("refresh remote directory listing",'~'.expand("<slnum>")) - NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./',0)) NetrwKeepj call winrestview(svpos) - -" call Dret("s:NetrwRemoteRm") endfun " --------------------------------------------------------------------- @@ -10626,7 +9957,6 @@ endfun " --------------------------------------------------------------------- " s:NetrwRemoteRename: rename a remote file or directory {{{2 fun! s:NetrwRemoteRename(usrhost,path) range -" call Dfunc("NetrwRemoteRename(usrhost<".a:usrhost."> path<".a:path.">)") " preparation for removing multiple files/directories let svpos = winsaveview() @@ -10637,10 +9967,8 @@ fun! s:NetrwRemoteRename(usrhost,path) range " rename files given by the markfilelist if exists("s:netrwmarkfilelist_{bufnr('%')}") for oldname in s:netrwmarkfilelist_{bufnr("%")} -" call Decho("oldname<".oldname.">",'~'.expand("<slnum>")) if exists("subfrom") let newname= substitute(oldname,subfrom,subto,'') -" call Decho("subfrom<".subfrom."> subto<".subto."> newname<".newname.">",'~'.expand("<slnum>")) else call inputsave() let newname= input("Moving ".oldname." to : ",oldname) @@ -10649,7 +9977,6 @@ fun! s:NetrwRemoteRename(usrhost,path) range let subfrom = substitute(newname,'^s/\([^/]*\)/.*/$','\1','') let subto = substitute(newname,'^s/[^/]*/\(.*\)/$','\1','') let newname = substitute(oldname,subfrom,subto,'') -" call Decho("subfrom<".subfrom."> subto<".subto."> newname<".newname.">",'~'.expand("<slnum>")) endif endif @@ -10658,7 +9985,6 @@ fun! s:NetrwRemoteRename(usrhost,path) range else let oldname= s:ShellEscape(a:path.oldname) let newname= s:ShellEscape(a:path.newname) -" call Decho("system(netrw#WinPath(".rename_cmd.") ".oldname.' '.newname.")",'~'.expand("<slnum>")) let ret = system(netrw#WinPath(rename_cmd).' '.oldname.' '.newname) endif @@ -10674,7 +10000,6 @@ fun! s:NetrwRemoteRename(usrhost,path) range exe "NetrwKeepj ".ctr let oldname= s:NetrwGetWord() -" call Decho("oldname<".oldname.">",'~'.expand("<slnum>")) call inputsave() let newname= input("Moving ".oldname." to : ",oldname) @@ -10685,7 +10010,6 @@ fun! s:NetrwRemoteRename(usrhost,path) range else let oldname= s:ShellEscape(a:path.oldname) let newname= s:ShellEscape(a:path.newname) -" call Decho("system(netrw#WinPath(".rename_cmd.") ".oldname.' '.newname.")",'~'.expand("<slnum>")) let ret = system(netrw#WinPath(rename_cmd).' '.oldname.' '.newname) endif @@ -10695,11 +10019,8 @@ fun! s:NetrwRemoteRename(usrhost,path) range endif " refresh the directory - NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call s:NetrwRefresh(0,s:NetrwBrowseChgDir(0,'./',0)) NetrwKeepj call winrestview(svpos) - -" call Dret("NetrwRemoteRename") endfun " ========================================== @@ -10826,17 +10147,11 @@ endfun " buffers to be refreshed after a user has executed some shell command, " on the chance that s/he removed/created a file/directory with it. fun! s:LocalBrowseRefresh() -" call Dfunc("s:LocalBrowseRefresh() tabpagenr($)=".tabpagenr("$")) -" call Decho("s:netrw_browselist =".(exists("s:netrw_browselist")? string(s:netrw_browselist) : '<n/a>'),'~'.expand("<slnum>")) -" call Decho("w:netrw_bannercnt =".(exists("w:netrw_bannercnt")? string(w:netrw_bannercnt) : '<n/a>'),'~'.expand("<slnum>")) - " determine which buffers currently reside in a tab if !exists("s:netrw_browselist") -" call Dret("s:LocalBrowseRefresh : browselist is empty") return endif if !exists("w:netrw_bannercnt") -" call Dret("s:LocalBrowseRefresh : don't refresh when focus not on netrw window") return endif if !empty(getcmdwintype()) @@ -10846,7 +10161,6 @@ fun! s:LocalBrowseRefresh() if exists("s:netrw_events") && s:netrw_events == 1 " s:LocalFastBrowser gets called (indirectly) from a let s:netrw_events= 2 -" call Dret("s:LocalBrowseRefresh : avoid initial double refresh") return endif let itab = 1 @@ -10857,47 +10171,36 @@ fun! s:LocalBrowseRefresh() let itab = itab + 1 sil! tabn endwhile -" call Decho("buftablist".string(buftablist),'~'.expand("<slnum>")) -" call Decho("s:netrw_browselist<".(exists("s:netrw_browselist")? string(s:netrw_browselist) : "").">",'~'.expand("<slnum>")) " GO through all buffers on netrw_browselist (ie. just local-netrw buffers): " | refresh any netrw window " | wipe out any non-displaying netrw buffer let curwinid = win_getid(winnr()) let ibl = 0 for ibuf in s:netrw_browselist -" call Decho("bufwinnr(".ibuf.") index(buftablist,".ibuf.")=".index(buftablist,ibuf),'~'.expand("<slnum>")) if bufwinnr(ibuf) == -1 && index(buftablist,ibuf) == -1 " wipe out any non-displaying netrw buffer " (ibuf not shown in a current window AND " ibuf not in any tab) -" call Decho("wiping buf#".ibuf,"<".bufname(ibuf).">",'~'.expand("<slnum>")) exe "sil! keepj bd ".fnameescape(ibuf) call remove(s:netrw_browselist,ibl) -" call Decho("browselist=".string(s:netrw_browselist),'~'.expand("<slnum>")) continue elseif index(tabpagebuflist(),ibuf) != -1 " refresh any netrw buffer -" call Decho("refresh buf#".ibuf.'-> win#'.bufwinnr(ibuf),'~'.expand("<slnum>")) exe bufwinnr(ibuf)."wincmd w" if getline(".") =~# 'Quick Help' " decrement g:netrw_quickhelp to prevent refresh from changing g:netrw_quickhelp " (counteracts s:NetrwBrowseChgDir()'s incrementing) let g:netrw_quickhelp= g:netrw_quickhelp - 1 endif -" call Decho("#3: quickhelp=".g:netrw_quickhelp,'~'.expand("<slnum>")) if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST NetrwKeepj call s:NetrwRefreshTreeDict(w:netrw_treetop) endif - NetrwKeepj call s:NetrwRefresh(1,s:NetrwBrowseChgDir(1,'./')) + NetrwKeepj call s:NetrwRefresh(1,s:NetrwBrowseChgDir(1,'./',0)) endif let ibl= ibl + 1 -" call Decho("bottom of s:netrw_browselist for loop: ibl=".ibl,'~'.expand("<slnum>")) endfor -" call Decho("restore window: win_gotoid(".curwinid.")") call win_gotoid(curwinid) let @@= ykeep - -" call Dret("s:LocalBrowseRefresh") endfun " --------------------------------------------------------------------- @@ -10919,22 +10222,15 @@ endfun " If :Explore used: it sets s:netrw_events to 2, so no FocusGained events are ignored. " =2: autocmds installed (doesn't ignore any FocusGained events) fun! s:LocalFastBrowser() -" call Dfunc("s:LocalFastBrowser() g:netrw_fastbrowse=".g:netrw_fastbrowse) -" call Decho("s:netrw_events ".(exists("s:netrw_events")? "exists" : 'n/a'),'~'.expand("<slnum>")) -" call Decho("autocmd: ShellCmdPost ".(exists("#ShellCmdPost")? "already installed" : "not installed"),'~'.expand("<slnum>")) -" call Decho("autocmd: FocusGained ".(exists("#FocusGained")? "already installed" : "not installed"),'~'.expand("<slnum>")) " initialize browselist, a list of buffer numbers that the local browser has used if !exists("s:netrw_browselist") -" call Decho("initialize s:netrw_browselist",'~'.expand("<slnum>")) let s:netrw_browselist= [] endif " append current buffer to fastbrowse list if empty(s:netrw_browselist) || bufnr("%") > s:netrw_browselist[-1] -" call Decho("appendng current buffer to browselist",'~'.expand("<slnum>")) call add(s:netrw_browselist,bufnr("%")) -" call Decho("browselist=".string(s:netrw_browselist),'~'.expand("<slnum>")) endif " enable autocmd events to handle refreshing/removing local browser buffers @@ -10948,10 +10244,8 @@ fun! s:LocalFastBrowser() augroup AuNetrwEvent au! if has("win32") -" call Decho("installing autocmd: ShellCmdPost",'~'.expand("<slnum>")) au ShellCmdPost * call s:LocalBrowseRefresh() else -" call Decho("installing autocmds: ShellCmdPost FocusGained",'~'.expand("<slnum>")) au ShellCmdPost,FocusGained * call s:LocalBrowseRefresh() endif augroup END @@ -10959,86 +10253,55 @@ fun! s:LocalFastBrowser() " user must have changed fastbrowse to its fast setting, so remove " the associated autocmd events elseif g:netrw_fastbrowse > 1 && exists("#ShellCmdPost") && exists("s:netrw_events") -" call Decho("remove AuNetrwEvent autcmd group",'~'.expand("<slnum>")) unlet s:netrw_events augroup AuNetrwEvent au! augroup END augroup! AuNetrwEvent endif - -" call Dret("s:LocalFastBrowser : browselist<".string(s:netrw_browselist).">") endfun -" --------------------------------------------------------------------- -" s:LocalListing: does the job of "ls" for local directories {{{2 -fun! s:LocalListing() -" call Dfunc("s:LocalListing()") -" call Decho("ro=".&l:ro." ma=".&l:ma." mod=".&l:mod." wrap=".&l:wrap." (filename<".expand("%")."> win#".winnr()." ft<".&ft.">)",'~'.expand("<slnum>")) -" call Decho("modified=".&modified." modifiable=".&modifiable." readonly=".&readonly,'~'.expand("<slnum>")) -" call Decho("tab#".tabpagenr()." win#".winnr()." buf#".bufnr("%")."<".bufname("%")."> line#".line(".")." col#".col(".")." winline#".winline()." wincol#".wincol(),'~'.expand("<slnum>")) - -" if exists("b:netrw_curdir") |call Decho('b:netrw_curdir<'.b:netrw_curdir.">") |else|call Decho("b:netrw_curdir doesn't exist",'~'.expand("<slnum>")) |endif -" if exists("g:netrw_sort_by")|call Decho('g:netrw_sort_by<'.g:netrw_sort_by.">")|else|call Decho("g:netrw_sort_by doesn't exist",'~'.expand("<slnum>"))|endif -" call Decho("g:netrw_banner=".g:netrw_banner.": banner ".(g:netrw_banner? "enabled" : "suppressed").": (line($)=".line("$")." byte2line(1)=".byte2line(1)." bannercnt=".w:netrw_bannercnt.")",'~'.expand("<slnum>")) - +fun! s:NetrwLocalListingList(dirname,setmaxfilenamelen) " get the list of files contained in the current directory - let dirname = b:netrw_curdir - let dirnamelen = strlen(b:netrw_curdir) + let dirname = a:dirname + let dirnamelen = strlen(dirname) let filelist = s:NetrwGlob(dirname,"*",0) let filelist = filelist + s:NetrwGlob(dirname,".*",0) -" call Decho("filelist=".string(filelist),'~'.expand("<slnum>")) if g:netrw_cygwin == 0 && has("win32") -" call Decho("filelist=".string(filelist),'~'.expand("<slnum>")) - elseif index(filelist,'..') == -1 && b:netrw_curdir !~ '/' + elseif index(filelist,'..') == -1 && dirname !~ '/' " include ../ in the glob() entry if its missing -" call Decho("forcibly including on \"..\"",'~'.expand("<slnum>")) - let filelist= filelist+[s:ComposePath(b:netrw_curdir,"../")] -" call Decho("filelist=".string(filelist),'~'.expand("<slnum>")) + let filelist= filelist+[s:ComposePath(dirname,"../")] endif -" call Decho("before while: dirname <".dirname.">",'~'.expand("<slnum>")) -" call Decho("before while: dirnamelen<".dirnamelen.">",'~'.expand("<slnum>")) -" call Decho("before while: filelist =".string(filelist),'~'.expand("<slnum>")) - - if get(g:, 'netrw_dynamic_maxfilenamelen', 0) + if a:setmaxfilenamelen && get(g:, 'netrw_dynamic_maxfilenamelen', 0) let filelistcopy = map(deepcopy(filelist),'fnamemodify(v:val, ":t")') let g:netrw_maxfilenamelen = max(map(filelistcopy,'len(v:val)')) + 1 -" call Decho("dynamic_maxfilenamelen: filenames =".string(filelistcopy),'~'.expand("<slnum>")) -" call Decho("dynamic_maxfilenamelen: g:netrw_maxfilenamelen=".g:netrw_maxfilenamelen,'~'.expand("<slnum>")) endif -" call Decho("g:netrw_banner=".g:netrw_banner.": banner ".(g:netrw_banner? "enabled" : "suppressed").": (line($)=".line("$")." byte2line(1)=".byte2line(1)." bannercnt=".w:netrw_bannercnt.")",'~'.expand("<slnum>")) + let resultfilelist = [] for filename in filelist -" call Decho(" ",'~'.expand("<slnum>")) -" call Decho("for filename in filelist: filename<".filename.">",'~'.expand("<slnum>")) if getftype(filename) == "link" " indicate a symbolic link -" call Decho("indicate <".filename."> is a symbolic link with trailing @",'~'.expand("<slnum>")) let pfile= filename."@" elseif getftype(filename) == "socket" " indicate a socket -" call Decho("indicate <".filename."> is a socket with trailing =",'~'.expand("<slnum>")) let pfile= filename."=" elseif getftype(filename) == "fifo" " indicate a fifo -" call Decho("indicate <".filename."> is a fifo with trailing |",'~'.expand("<slnum>")) let pfile= filename."|" elseif isdirectory(s:NetrwFile(filename)) " indicate a directory -" call Decho("indicate <".filename."> is a directory with trailing /",'~'.expand("<slnum>")) let pfile= filename."/" elseif exists("b:netrw_curdir") && b:netrw_curdir !~ '^.*://' && !isdirectory(s:NetrwFile(filename)) if has("win32") if filename =~ '\.[eE][xX][eE]$' || filename =~ '\.[cC][oO][mM]$' || filename =~ '\.[bB][aA][tT]$' " indicate an executable -" call Decho("indicate <".filename."> is executable with trailing *",'~'.expand("<slnum>")) let pfile= filename."*" else " normal file @@ -11046,7 +10309,6 @@ fun! s:LocalListing() endif elseif executable(filename) " indicate an executable -" call Decho("indicate <".filename."> is executable with trailing *",'~'.expand("<slnum>")) let pfile= filename."*" else " normal file @@ -11057,16 +10319,12 @@ fun! s:LocalListing() " normal file let pfile= filename endif -" call Decho("pfile<".pfile."> (after *@/ appending)",'~'.expand("<slnum>")) if pfile =~ '//$' let pfile= substitute(pfile,'//$','/','e') -" call Decho("change // to /: pfile<".pfile.">",'~'.expand("<slnum>")) endif let pfile= strpart(pfile,dirnamelen) let pfile= substitute(pfile,'^[/\\]','','e') -" call Decho("filename<".filename.">",'~'.expand("<slnum>")) -" call Decho("pfile <".pfile.">",'~'.expand("<slnum>")) if w:netrw_liststyle == s:LONGLIST let longfile = printf("%-".g:netrw_maxfilenamelen."S",pfile) @@ -11079,47 +10337,46 @@ fun! s:LocalListing() endif let fsz = printf("%".szlen."S",sz) let pfile= longfile." ".fsz." ".strftime(g:netrw_timefmt,getftime(filename)) -" call Decho("longlist support: sz=".sz." fsz=".fsz,'~'.expand("<slnum>")) endif 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("implementing g:netrw_sort_by=".g:netrw_sort_by." (time)") -" call Decho("getftime(".filename.")=".getftime(filename),'~'.expand("<slnum>")) let t = getftime(filename) let ft = printf("%018d",t) -" call Decho("exe NetrwKeepj put ='".ft.'/'.pfile."'",'~'.expand("<slnum>")) let ftpfile= ft.'/'.pfile - sil! NetrwKeepj put=ftpfile + let resultfilelist += [ftpfile] elseif g:netrw_sort_by =~ "^s" " sort by size (handles file sizes up to 1 quintillion bytes, US) -" call Decho("implementing g:netrw_sort_by=".g:netrw_sort_by." (size)") -" call Decho("getfsize(".filename.")=".getfsize(filename),'~'.expand("<slnum>")) let sz = getfsize(filename) let fsz = printf("%018d",sz) -" call Decho("exe NetrwKeepj put ='".fsz.'/'.filename."'",'~'.expand("<slnum>")) let fszpfile= fsz.'/'.pfile - sil! NetrwKeepj put =fszpfile + let resultfilelist += [fszpfile] else " sort by name -" call Decho("implementing g:netrw_sort_by=".g:netrw_sort_by." (name)") -" call Decho("exe NetrwKeepj put ='".pfile."'",'~'.expand("<slnum>")) - sil! NetrwKeepj put=pfile + let resultfilelist += [pfile] endif -" call DechoBuf(bufnr("%"),"bufnr(%)") + endfor + + return resultfilelist +endfun + +" --------------------------------------------------------------------- +" s:LocalListing: does the job of "ls" for local directories {{{2 +fun! s:LocalListing() + + let filelist = s:NetrwLocalListingList(b:netrw_curdir, 1) + for filename in filelist + sil! NetrwKeepj put =filename endfor " cleanup any windows mess at end-of-line sil! NetrwKeepj g/^$/d sil! NetrwKeepj %s/\r$//e call histdel("/",-1) -" call Decho("exe setl ts=".(g:netrw_maxfilenamelen+1),'~'.expand("<slnum>")) exe "setl ts=".(g:netrw_maxfilenamelen+1) - -" call Dret("s:LocalListing") endfun " --------------------------------------------------------------------- @@ -11153,7 +10410,6 @@ endfun " --------------------------------------------------------------------- " s:NetrwLocalRename: rename a local file or directory {{{2 fun! s:NetrwLocalRename(path) range -" call Dfunc("NetrwLocalRename(path<".a:path.">)") if !exists("w:netrw_bannercnt") let w:netrw_bannercnt= b:netrw_bannercnt @@ -11164,15 +10420,12 @@ fun! s:NetrwLocalRename(path) range 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 if exists("s:netrwmarkfilelist_{bufnr('%')}") for oldname in s:netrwmarkfilelist_{bufnr("%")} -" call Decho("oldname<".oldname.">",'~'.expand("<slnum>")) if exists("subfrom") let newname= substitute(oldname,subfrom,subto,'') -" call Decho("subfrom<".subfrom."> subto<".subto."> newname<".newname.">",'~'.expand("<slnum>")) else call inputsave() let newname= input("Moving ".oldname." to : ",oldname,"file") @@ -11187,7 +10440,6 @@ fun! s:NetrwLocalRename(path) range if newname =~ '^s/' let subfrom = substitute(newname,'^s/\([^/]*\)/.*/$','\1','') let subto = substitute(newname,'^s/[^/]*/\(.*\)/$','\1','') -" call Decho("subfrom<".subfrom."> subto<".subto."> newname<".newname.">",'~'.expand("<slnum>")) let newname = substitute(oldname,subfrom,subto,'') endif endif @@ -11199,12 +10451,9 @@ fun! s:NetrwLocalRename(path) range 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 s:NetrwRefresh(1,s:NetrwBrowseChgDir(1,'./',0)) NetrwKeepj call winrestview(svpos) let @@= ykeep -" call Dret("NetrwLocalRename") return endif endif @@ -11231,35 +10480,25 @@ fun! s:NetrwLocalRename(path) range NetrwKeepj norm! 0 let oldname= s:ComposePath(a:path,curword) -" 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>")) - let ctr= ctr + 1 endwhile endif " 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 s:NetrwRefresh(1,s:NetrwBrowseChgDir(1,'./',0)) NetrwKeepj call winrestview(svpos) let @@= ykeep - -" call Dret("NetrwLocalRename") endfun " --------------------------------------------------------------------- " s:NetrwLocalRm: {{{2 fun! s:NetrwLocalRm(path) range -" call Dfunc("s:NetrwLocalRm(path<".a:path.">)") -" call Decho("firstline=".a:firstline." lastline=".a:lastline,'~'.expand("<slnum>")) - if !exists("w:netrw_bannercnt") let w:netrw_bannercnt= b:netrw_bannercnt endif @@ -11269,11 +10508,9 @@ fun! s:NetrwLocalRm(path) range let ret = 0 let all = 0 let svpos = winsaveview() -" call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) if exists("s:netrwmarkfilelist_{bufnr('%')}") " remove all marked files -" call Decho("remove all marked files",'~'.expand("<slnum>")) for fname in s:netrwmarkfilelist_{bufnr("%")} let ok= s:NetrwLocalRmFile(a:path,fname,all) if ok =~# 'q\%[uit]' || ok == "no" @@ -11286,7 +10523,6 @@ fun! s:NetrwLocalRm(path) range else " remove (multiple) files and directories -" call Decho("remove files in range [".a:firstline.",".a:lastline."]",'~'.expand("<slnum>")) let keepsol= &l:sol setl nosol @@ -11316,15 +10552,11 @@ fun! s:NetrwLocalRm(path) range endif " refresh the directory -" call Decho("bufname<".bufname("%").">",'~'.expand("<slnum>")) if bufname("%") != "NetrwMessage" - NetrwKeepj call s:NetrwRefresh(1,s:NetrwBrowseChgDir(1,'./')) -" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("<slnum>")) + NetrwKeepj call s:NetrwRefresh(1,s:NetrwBrowseChgDir(1,'./',0)) NetrwKeepj call winrestview(svpos) endif let @@= ykeep - -" call Dret("s:NetrwLocalRm") endfun " --------------------------------------------------------------------- @@ -11970,7 +11202,7 @@ fun! s:NetrwEnew(...) " call Dfunc("s:NetrwEnew() a:0=".a:0." win#".winnr()." winnr($)=".winnr("$")." bufnr($)=".bufnr("$")." expand(%)<".expand("%").">") " call Decho("curdir<".((a:0>0)? a:1 : "")."> buf#".bufnr("%")."<".bufname("%").">",'~'.expand("<slnum>")) - " Clean out the last buffer: + " Clean out the last buffer: " Check if the last buffer has # > 1, is unlisted, is unnamed, and does not appear in a window " If so, delete it. call s:NetrwBufRemover(bufnr("$")) @@ -12050,13 +11282,16 @@ endfun " s:NetrwExe: executes a string using "!" {{{2 fun! s:NetrwExe(cmd) " call Dfunc("s:NetrwExe(a:cmd<".a:cmd.">)") - if has("win32") && &shell !~? 'cmd\|pwsh\|powershell' && !g:netrw_cygwin + if has("win32") " call Decho("using win32:",expand("<slnum>")) let savedShell=[&shell,&shellcmdflag,&shellxquote,&shellxescape,&shellquote,&shellpipe,&shellredir,&shellslash] set shell& shellcmdflag& shellxquote& shellxescape& set shellquote& shellpipe& shellredir& shellslash& - exe a:cmd - let [&shell,&shellcmdflag,&shellxquote,&shellxescape,&shellquote,&shellpipe,&shellredir,&shellslash] = savedShell + try + exe a:cmd + finally + let [&shell,&shellcmdflag,&shellxquote,&shellxescape,&shellquote,&shellpipe,&shellredir,&shellslash] = savedShell + endtry else " call Decho("exe ".a:cmd,'~'.expand("<slnum>")) exe a:cmd @@ -12159,7 +11394,7 @@ fun! s:NetrwHumanReadable(sz) " call Dfunc("s:NetrwHumanReadable(sz=".a:sz.") type=".type(a:sz)." style=".g:netrw_sizestyle ) if g:netrw_sizestyle == 'h' - if a:sz >= 1000000000 + if a:sz >= 1000000000 let sz = printf("%.1f",a:sz/1000000000.0)."g" elseif a:sz >= 10000000 let sz = printf("%d",a:sz/1000000)."m" @@ -12490,29 +11725,24 @@ endfun " --------------------------------------------------------------------- " s:ShowLink: used to modify thin and tree listings to show links {{{2 fun! s:ShowLink() -" " call Dfunc("s:ShowLink()") -" " call Decho("b:netrw_curdir<".(exists("b:netrw_curdir")? b:netrw_curdir : "doesn't exist").">",'~'.expand("<slnum>")) -" " call Decho(printf("line#%4d: %s",line("."),getline(".")),'~'.expand("<slnum>")) if exists("b:netrw_curdir") norm! $?\a - let fname = b:netrw_curdir.'/'.s:NetrwGetWord() + if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST && exists("w:netrw_treetop") + let basedir = s:NetrwTreePath(w:netrw_treetop) + else + let basedir = b:netrw_curdir.'/' + endif + let fname = basedir.s:NetrwGetWord() let resname = resolve(fname) -" " call Decho("fname <".fname.">",'~'.expand("<slnum>")) -" " call Decho("resname <".resname.">",'~'.expand("<slnum>")) -" " call Decho("b:netrw_curdir<".b:netrw_curdir.">",'~'.expand("<slnum>")) - if resname =~ '^\M'.b:netrw_curdir.'/' - let dirlen = strlen(b:netrw_curdir) - let resname = strpart(resname,dirlen+1) -" " call Decho("resname<".resname."> (b:netrw_curdir elided)",'~'.expand("<slnum>")) + if resname =~ '^\M'.basedir + let dirlen = strlen(basedir) + let resname = strpart(resname,dirlen) endif let modline = getline(".")."\t --> ".resname -" " call Decho("fname <".fname.">",'~'.expand("<slnum>")) -" " call Decho("modline<".modline.">",'~'.expand("<slnum>")) setl noro ma call setline(".",modline) setl ro noma nomod endif -" " call Dret("s:ShowLink".((exists("fname")? ' : '.fname : 'n/a'))) endfun " --------------------------------------------------------------------- @@ -12587,7 +11817,7 @@ endfun fun! s:ShellEscape(s, ...) if has('win32') && $SHELL == '' && &shellslash return printf('"%s"', substitute(a:s, '"', '""', 'g')) - endif + endif let f = a:0 > 0 ? a:1 : 0 return shellescape(a:s, f) endfun @@ -12673,8 +11903,6 @@ endfun " * interprets result " See netrw#UserMaps() fun! s:UserMaps(islocal,funcname) -" call Dfunc("s:UserMaps(islocal=".a:islocal.",funcname<".a:funcname.">)") - if !exists("b:netrw_curdir") let b:netrw_curdir= getcwd() endif @@ -12683,30 +11911,22 @@ fun! s:UserMaps(islocal,funcname) if type(result) == 1 " if result from user's funcref is a string... -" call Decho("result string from user funcref<".result.">",'~'.expand("<slnum>")) if result == "refresh" -" call Decho("refreshing display",'~'.expand("<slnum>")) - call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) + call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) elseif result != "" -" call Decho("executing result<".result.">",'~'.expand("<slnum>")) exe result endif elseif type(result) == 3 " if result from user's funcref is a List... -" call Decho("result List from user funcref<".string(result).">",'~'.expand("<slnum>")) for action in result if action == "refresh" -" call Decho("refreshing display",'~'.expand("<slnum>")) - call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./')) + call s:NetrwRefresh(a:islocal,s:NetrwBrowseChgDir(a:islocal,'./',0)) elseif action != "" -" call Decho("executing action<".action.">",'~'.expand("<slnum>")) exe action endif endfor endif - -" call Dret("s:UserMaps") endfun " ========================== diff --git a/runtime/autoload/netrwFileHandlers.vim b/runtime/autoload/netrwFileHandlers.vim index 2b6f8f7a0f..e69de29bb2 100644 --- a/runtime/autoload/netrwFileHandlers.vim +++ b/runtime/autoload/netrwFileHandlers.vim @@ -1,363 +0,0 @@ -" netrwFileHandlers: contains various extension-based file handlers for -" netrw's browsers' x command ("eXecute launcher") -" Maintainer: This runtime file is looking for a new maintainer. -" Original Author: Charles E. Campbell -" Date: Sep 18, 2020 -" Version: 11 -" Copyright: Copyright (C) 1999-2012 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, -" netrwFileHandlers.vim is provided *as is* and comes with no -" warranty of any kind, either expressed or implied. In no -" event will the copyright holder be liable for any damages -" resulting from the use of this software. -" -" Rom 6:23 (WEB) For the wages of sin is death, but the free gift of God {{{1 -" is eternal life in Christ Jesus our Lord. - -" --------------------------------------------------------------------- -" Load Once: {{{1 -if exists("g:loaded_netrwFileHandlers") || &cp - finish -endif -let g:loaded_netrwFileHandlers= "v11" -if v:version < 702 - echohl WarningMsg - echo "***warning*** this version of netrwFileHandlers needs vim 7.2" - echohl Normal - finish -endif -let s:keepcpo= &cpo -set cpo&vim - -" --------------------------------------------------------------------- -" netrwFileHandlers#Invoke: {{{1 -fun! netrwFileHandlers#Invoke(exten,fname) -" call Dfunc("netrwFileHandlers#Invoke(exten<".a:exten."> fname<".a:fname.">)") - let exten= a:exten - " list of supported special characters. Consider rcs,v --- that can be - " supported with a NFH_rcsCOMMAv() handler - if exten =~ '[@:,$!=\-+%?;~]' - let specials= { -\ '@' : 'AT', -\ ':' : 'COLON', -\ ',' : 'COMMA', -\ '$' : 'DOLLAR', -\ '!' : 'EXCLAMATION', -\ '=' : 'EQUAL', -\ '-' : 'MINUS', -\ '+' : 'PLUS', -\ '%' : 'PERCENT', -\ '?' : 'QUESTION', -\ ';' : 'SEMICOLON', -\ '~' : 'TILDE'} - let exten= substitute(a:exten,'[@:,$!=\-+%?;~]','\=specials[submatch(0)]','ge') -" call Decho('fname<'.fname.'> done with dictionary') - endif - - if a:exten != "" && exists("*NFH_".exten) - " support user NFH_*() functions -" call Decho("let ret= netrwFileHandlers#NFH_".a:exten.'("'.fname.'")') - exe "let ret= NFH_".exten.'("'.a:fname.'")' - elseif a:exten != "" && exists("*s:NFH_".exten) - " use builtin-NFH_*() functions -" call Decho("let ret= netrwFileHandlers#NFH_".a:exten.'("'.fname.'")') - exe "let ret= s:NFH_".a:exten.'("'.a:fname.'")' - endif - -" call Dret("netrwFileHandlers#Invoke 0 : ret=".ret) - return 0 -endfun - -" --------------------------------------------------------------------- -" s:NFH_html: handles html when the user hits "x" when the {{{1 -" cursor is atop a *.html file -fun! s:NFH_html(pagefile) -" call Dfunc("s:NFH_html(".a:pagefile.")") - - let page= substitute(a:pagefile,'^','file://','') - - if executable("mozilla") -" call Decho("executing !mozilla ".page) - exe "!mozilla ".shellescape(page,1) - elseif executable("netscape") -" call Decho("executing !netscape ".page) - exe "!netscape ".shellescape(page,1) - else -" call Dret("s:NFH_html 0") - return 0 - endif - -" call Dret("s:NFH_html 1") - return 1 -endfun - -" --------------------------------------------------------------------- -" s:NFH_htm: handles html when the user hits "x" when the {{{1 -" cursor is atop a *.htm file -fun! s:NFH_htm(pagefile) -" call Dfunc("s:NFH_htm(".a:pagefile.")") - - let page= substitute(a:pagefile,'^','file://','') - - if executable("mozilla") -" call Decho("executing !mozilla ".page) - exe "!mozilla ".shellescape(page,1) - elseif executable("netscape") -" call Decho("executing !netscape ".page) - exe "!netscape ".shellescape(page,1) - else -" call Dret("s:NFH_htm 0") - return 0 - endif - -" call Dret("s:NFH_htm 1") - return 1 -endfun - -" --------------------------------------------------------------------- -" s:NFH_jpg: {{{1 -fun! s:NFH_jpg(jpgfile) -" call Dfunc("s:NFH_jpg(jpgfile<".a:jpgfile.">)") - - if executable("gimp") - exe "silent! !gimp -s ".shellescape(a:jpgfile,1) - elseif executable(expand("$SystemRoot")."/SYSTEM32/MSPAINT.EXE") -" call Decho("silent! !".expand("$SystemRoot")."/SYSTEM32/MSPAINT ".escape(a:jpgfile," []|'")) - exe "!".expand("$SystemRoot")."/SYSTEM32/MSPAINT ".shellescape(a:jpgfile,1) - else -" call Dret("s:NFH_jpg 0") - return 0 - endif - -" call Dret("s:NFH_jpg 1") - return 1 -endfun - -" --------------------------------------------------------------------- -" s:NFH_gif: {{{1 -fun! s:NFH_gif(giffile) -" call Dfunc("s:NFH_gif(giffile<".a:giffile.">)") - - if executable("gimp") - exe "silent! !gimp -s ".shellescape(a:giffile,1) - elseif executable(expand("$SystemRoot")."/SYSTEM32/MSPAINT.EXE") - exe "silent! !".expand("$SystemRoot")."/SYSTEM32/MSPAINT ".shellescape(a:giffile,1) - else -" call Dret("s:NFH_gif 0") - return 0 - endif - -" call Dret("s:NFH_gif 1") - return 1 -endfun - -" --------------------------------------------------------------------- -" s:NFH_png: {{{1 -fun! s:NFH_png(pngfile) -" call Dfunc("s:NFH_png(pngfile<".a:pngfile.">)") - - if executable("gimp") - exe "silent! !gimp -s ".shellescape(a:pngfile,1) - elseif executable(expand("$SystemRoot")."/SYSTEM32/MSPAINT.EXE") - exe "silent! !".expand("$SystemRoot")."/SYSTEM32/MSPAINT ".shellescape(a:pngfile,1) - else -" call Dret("s:NFH_png 0") - return 0 - endif - -" call Dret("s:NFH_png 1") - return 1 -endfun - -" --------------------------------------------------------------------- -" s:NFH_pnm: {{{1 -fun! s:NFH_pnm(pnmfile) -" call Dfunc("s:NFH_pnm(pnmfile<".a:pnmfile.">)") - - if executable("gimp") - exe "silent! !gimp -s ".shellescape(a:pnmfile,1) - elseif executable(expand("$SystemRoot")."/SYSTEM32/MSPAINT.EXE") - exe "silent! !".expand("$SystemRoot")."/SYSTEM32/MSPAINT ".shellescape(a:pnmfile,1) - else -" call Dret("s:NFH_pnm 0") - return 0 - endif - -" call Dret("s:NFH_pnm 1") - return 1 -endfun - -" --------------------------------------------------------------------- -" s:NFH_bmp: visualize bmp files {{{1 -fun! s:NFH_bmp(bmpfile) -" call Dfunc("s:NFH_bmp(bmpfile<".a:bmpfile.">)") - - if executable("gimp") - exe "silent! !gimp -s ".a:bmpfile - elseif executable(expand("$SystemRoot")."/SYSTEM32/MSPAINT.EXE") - exe "silent! !".expand("$SystemRoot")."/SYSTEM32/MSPAINT ".shellescape(a:bmpfile,1) - else -" call Dret("s:NFH_bmp 0") - return 0 - endif - -" call Dret("s:NFH_bmp 1") - return 1 -endfun - -" --------------------------------------------------------------------- -" s:NFH_pdf: visualize pdf files {{{1 -fun! s:NFH_pdf(pdf) -" call Dfunc("s:NFH_pdf(pdf<".a:pdf.">)") - if executable("gs") - exe 'silent! !gs '.shellescape(a:pdf,1) - elseif executable("pdftotext") - exe 'silent! pdftotext -nopgbrk '.shellescape(a:pdf,1) - else -" call Dret("s:NFH_pdf 0") - return 0 - endif - -" call Dret("s:NFH_pdf 1") - return 1 -endfun - -" --------------------------------------------------------------------- -" s:NFH_doc: visualize doc files {{{1 -fun! s:NFH_doc(doc) -" call Dfunc("s:NFH_doc(doc<".a:doc.">)") - - if executable("oowriter") - exe 'silent! !oowriter '.shellescape(a:doc,1) - redraw! - else -" call Dret("s:NFH_doc 0") - return 0 - endif - -" call Dret("s:NFH_doc 1") - return 1 -endfun - -" --------------------------------------------------------------------- -" s:NFH_sxw: visualize sxw files {{{1 -fun! s:NFH_sxw(sxw) -" call Dfunc("s:NFH_sxw(sxw<".a:sxw.">)") - - if executable("oowriter") - exe 'silent! !oowriter '.shellescape(a:sxw,1) - redraw! - else -" call Dret("s:NFH_sxw 0") - return 0 - endif - -" call Dret("s:NFH_sxw 1") - return 1 -endfun - -" --------------------------------------------------------------------- -" s:NFH_xls: visualize xls files {{{1 -fun! s:NFH_xls(xls) -" call Dfunc("s:NFH_xls(xls<".a:xls.">)") - - if executable("oocalc") - exe 'silent! !oocalc '.shellescape(a:xls,1) - redraw! - else -" call Dret("s:NFH_xls 0") - return 0 - endif - -" call Dret("s:NFH_xls 1") - return 1 -endfun - -" --------------------------------------------------------------------- -" s:NFH_ps: handles PostScript files {{{1 -fun! s:NFH_ps(ps) -" call Dfunc("s:NFH_ps(ps<".a:ps.">)") - if executable("gs") -" call Decho("exe silent! !gs ".a:ps) - exe "silent! !gs ".shellescape(a:ps,1) - redraw! - elseif executable("ghostscript") -" call Decho("exe silent! !ghostscript ".a:ps) - exe "silent! !ghostscript ".shellescape(a:ps,1) - redraw! - elseif executable("gswin32") -" call Decho("exe silent! !gswin32 ".shellescape(a:ps,1)) - exe "silent! !gswin32 ".shellescape(a:ps,1) - redraw! - else -" call Dret("s:NFH_ps 0") - return 0 - endif - -" call Dret("s:NFH_ps 1") - return 1 -endfun - -" --------------------------------------------------------------------- -" s:NFH_eps: handles encapsulated PostScript files {{{1 -fun! s:NFH_eps(eps) -" call Dfunc("s:NFH_eps()") - if executable("gs") - exe "silent! !gs ".shellescape(a:eps,1) - redraw! - elseif executable("ghostscript") - exe "silent! !ghostscript ".shellescape(a:eps,1) - redraw! - elseif executable("ghostscript") - exe "silent! !ghostscript ".shellescape(a:eps,1) - redraw! - elseif executable("gswin32") - exe "silent! !gswin32 ".shellescape(a:eps,1) - redraw! - else -" call Dret("s:NFH_eps 0") - return 0 - endif -" call Dret("s:NFH_eps 0") - return 1 -endfun - -" --------------------------------------------------------------------- -" s:NFH_fig: handles xfig files {{{1 -fun! s:NFH_fig(fig) -" call Dfunc("s:NFH_fig()") - if executable("xfig") - exe "silent! !xfig ".a:fig - redraw! - else -" call Dret("s:NFH_fig 0") - return 0 - endif - -" call Dret("s:NFH_fig 1") - return 1 -endfun - -" --------------------------------------------------------------------- -" s:NFH_obj: handles tgif's obj files {{{1 -fun! s:NFH_obj(obj) -" call Dfunc("s:NFH_obj()") - if has("unix") && executable("tgif") - exe "silent! !tgif ".a:obj - redraw! - else -" call Dret("s:NFH_obj 0") - return 0 - endif - -" call Dret("s:NFH_obj 1") - return 1 -endfun - -let &cpo= s:keepcpo -unlet s:keepcpo -" --------------------------------------------------------------------- -" Modelines: {{{1 -" vim: fdm=marker diff --git a/runtime/autoload/paste.vim b/runtime/autoload/paste.vim index 1ba336c2b3..84d4d77401 100644 --- a/runtime/autoload/paste.vim +++ b/runtime/autoload/paste.vim @@ -4,7 +4,7 @@ " Former Maintainer: Bram Moolenaar <Bram@vim.org> " Define the string to use for items that are present both in Edit, Popup and -" Toolbar menu. Also used in mswin.vim and macmap.vim. +" Toolbar menu. Also used in mswin.vim. let paste#paste_cmd = {'n': ":call paste#Paste()<CR>"} let paste#paste_cmd['v'] = '"-c<Esc>' . paste#paste_cmd['n'] diff --git a/runtime/autoload/tar.vim b/runtime/autoload/tar.vim index f2a74db5ed..12409f8145 100644 --- a/runtime/autoload/tar.vim +++ b/runtime/autoload/tar.vim @@ -1,6 +1,6 @@ " tar.vim: Handles browsing tarfiles " AUTOLOAD PORTION -" Date: Nov 14, 2023 +" Date: Nov 11, 2024 " Version: 32b (with modifications from the Vim Project) " Maintainer: This runtime file is looking for a new maintainer. " Former Maintainer: Charles E Campbell @@ -23,7 +23,7 @@ if &cp || exists("g:loaded_tar") finish endif -let g:loaded_tar= "v32a" +let g:loaded_tar= "v32b" if v:version < 702 echohl WarningMsg echo "***warning*** this version of tar needs vim 7.2" @@ -41,7 +41,7 @@ if !exists("g:tar_browseoptions") let g:tar_browseoptions= "Ptf" endif if !exists("g:tar_readoptions") - let g:tar_readoptions= "OPxf" + let g:tar_readoptions= "pPxf" endif if !exists("g:tar_cmd") let g:tar_cmd= "tar" @@ -80,7 +80,7 @@ if !exists("g:tar_copycmd") let g:tar_copycmd= g:netrw_localcopycmd endif if !exists("g:tar_extractcmd") - let g:tar_extractcmd= "tar -xf" + let g:tar_extractcmd= "tar -pxf" endif " set up shell quoting character @@ -294,6 +294,41 @@ fun! tar#Read(fname,mode) set report=10 let tarfile = substitute(a:fname,'tarfile:\(.\{-}\)::.*$','\1','') let fname = substitute(a:fname,'tarfile:.\{-}::\(.*\)$','\1','') + +" changing the directory to the temporary earlier to allow tar to extract the file with permissions intact + if !exists("*mkdir") + redraw! + echohl Error | echo "***error*** (tar#Write) sorry, mkdir() doesn't work on your system" | echohl None + let &report= repkeep + return + endif + + let curdir= getcwd() + let tmpdir= tempname() + let b:curdir= tmpdir + let b:tmpdir= curdir + if tmpdir =~ '\.' + let tmpdir= substitute(tmpdir,'\.[^.]*$','','e') + endif + call mkdir(tmpdir,"p") + + " attempt to change to the indicated directory + try + exe "cd ".fnameescape(tmpdir) + catch /^Vim\%((\a\+)\)\=:E344/ + redraw! + echohl Error | echo "***error*** (tar#Write) cannot cd to temporary directory" | Echohl None + let &report= repkeep + return + endtry + + " place temporary files under .../_ZIPVIM_/ + if isdirectory("_ZIPVIM_") + call s:Rmdir("_ZIPVIM_") + endif + call mkdir("_ZIPVIM_") + cd _ZIPVIM_ + if has("win32unix") && executable("cygpath") " assuming cygwin let tarfile=substitute(system("cygpath -u ".shellescape(tarfile,0)),'\n$','','e') @@ -332,9 +367,10 @@ fun! tar#Read(fname,mode) if tarfile =~# '\.bz2$' exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp + exe "read ".fname elseif tarfile =~# '\.\(gz\)$' exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp - + exe "read ".fname elseif tarfile =~# '\(\.tgz\|\.tbz\|\.txz\)' if has("unix") && executable("file") let filekind= system("file ".shellescape(tarfile,1)) @@ -343,20 +379,27 @@ fun! tar#Read(fname,mode) 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 + exe "read ".fname elseif filekind =~ "XZ" exe "sil! r! xz -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp + exe "read ".fname elseif filekind =~ "Zstandard" exe "sil! r! zstd --decompress --stdout -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp + exe "read ".fname else exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp + exe "read ".fname endif elseif tarfile =~# '\.lrp$' exe "sil! r! cat -- ".shellescape(tarfile,1)." | gzip -d -c - | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp + exe "read ".fname elseif tarfile =~# '\.lzma$' exe "sil! r! lzma -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp + exe "read ".fname elseif tarfile =~# '\.\(xz\|txz\)$' exe "sil! r! xz --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp + exe "read ".fname else if tarfile =~ '^\s*-' " A file name starting with a dash is taken as an option. Prepend ./ to avoid that. @@ -364,6 +407,16 @@ fun! tar#Read(fname,mode) endif " call Decho("8: exe silent r! ".g:tar_cmd." -".g:tar_readoptions.tar_secure.shellescape(tarfile,1)." ".shellescape(fname,1).decmp) exe "silent r! ".g:tar_cmd." -".g:tar_readoptions.shellescape(tarfile,1)." ".tar_secure.shellescape(fname,1).decmp + exe "read ".fname + endif + + redraw! + +if v:shell_error != 0 + cd .. + call s:Rmdir("_ZIPVIM_") + exe "cd ".fnameescape(curdir) + echohl Error | echo "***error*** (tar#Read) sorry, unable to open or extract ".tarfile." with ".fname | echohl None endif if doro @@ -388,6 +441,10 @@ fun! tar#Write(fname) " call Dfunc("tar#Write(fname<".a:fname.">) b:tarfile<".b:tarfile."> tblfile_".winnr()."<".s:tblfile_{winnr()}.">") let repkeep= &report set report=10 + + " temporary buffer variable workaround because too fucking tired. but it works now + let curdir= b:curdir + let tmpdir= b:tmpdir if !exists("g:tar_secure") && a:fname =~ '^\s*-\|\s\+-' redraw! @@ -404,44 +461,6 @@ fun! tar#Write(fname) " 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") - return - endif - - let curdir= getcwd() - let tmpdir= tempname() -" call Decho("orig tempname<".tmpdir.">") - if tmpdir =~ '\.' - let tmpdir= substitute(tmpdir,'\.[^.]*$','','e') - endif -" call Decho("tmpdir<".tmpdir.">") - call mkdir(tmpdir,"p") - - " attempt to change to the indicated directory - try - 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") - return - endtry -" call Decho("current directory now: ".getcwd()) - - " place temporary files under .../_ZIPVIM_/ - if isdirectory("_ZIPVIM_") - call s:Rmdir("_ZIPVIM_") - endif - call mkdir("_ZIPVIM_") - cd _ZIPVIM_ -" call Decho("current directory now: ".getcwd()) let tarfile = substitute(b:tarfile,'tarfile:\(.\{-}\)::.*$','\1','') let fname = substitute(b:tarfile,'tarfile:.\{-}::\(.*\)$','\1','') diff --git a/runtime/autoload/typst.vim b/runtime/autoload/typst.vim index 55edd23928..6d097dd922 100644 --- a/runtime/autoload/typst.vim +++ b/runtime/autoload/typst.vim @@ -1,6 +1,6 @@ " Language: Typst " Maintainer: Gregory Anders -" Last Change: 2024-07-14 +" Last Change: 2024 Nov 02 " Based on: https://github.com/kaarmu/typst.vim function! typst#indentexpr() abort @@ -18,6 +18,9 @@ function! typst#indentexpr() abort " Use last indent for block comments if l:synname == 'typstCommentBlock' return l:ind + " do not change the indents of bullet lists + elseif l:synname == 'typstMarkupBulletList' + return indent(a:lnum) endif if l:pline =~ '\v[{[(]\s*$' @@ -31,6 +34,31 @@ function! typst#indentexpr() abort return l:ind endfunction +function typst#foldexpr() + let line = getline(v:lnum) + + " Whenever the user wants to fold nested headers under the parent + let nested = get(g:, "typst_foldnested", 1) + + " Regular headers + let depth = match(line, '\(^=\+\)\@<=\( .*$\)\@=') + + " Do not fold nested regular headers + if depth > 1 && !nested + let depth = 1 + endif + + if depth > 0 + " check syntax, it should be typstMarkupHeading + let syncode = synstack(v:lnum, 1) + if len(syncode) > 0 && synIDattr(syncode[0], 'name') ==# 'typstMarkupHeading' + return ">" . depth + endif + endif + + return "=" +endfunction + " Gets the previous non-blank line that is not a comment. function! s:get_prev_nonblank(lnum) abort let l:lnum = prevnonblank(a:lnum) diff --git a/runtime/autoload/zip.vim b/runtime/autoload/zip.vim index 172de98d36..a8ea6a3fab 100644 --- a/runtime/autoload/zip.vim +++ b/runtime/autoload/zip.vim @@ -408,7 +408,9 @@ fun! s:SetSaneOpts() let dict.shellslash = &shellslash let &report = 10 - let &shellslash = 0 + if exists('+shellslash') + let &shellslash = 0 + endif return dict endfun diff --git a/runtime/colors/README.txt b/runtime/colors/README.txt index bc6b8f0965..7a13312ed2 100644 --- a/runtime/colors/README.txt +++ b/runtime/colors/README.txt @@ -84,9 +84,6 @@ The default color settings can be found in the source file If you think you have a color scheme that is good enough to be used by others, please check the following items: -- Source the $VIMRUNTIME/colors/tools/check_colors.vim script to check for - common mistakes. - - Does it work in a color terminal as well as in the GUI? Is it consistent? - Is "g:colors_name" set to a meaningful value? In case of doubt you can do diff --git a/runtime/compiler/cppcheck.vim b/runtime/compiler/cppcheck.vim index ed7c46e90f..4df12d1714 100644 --- a/runtime/compiler/cppcheck.vim +++ b/runtime/compiler/cppcheck.vim @@ -1,15 +1,15 @@ " vim compiler file " Compiler: cppcheck (C++ static checker) " Maintainer: Vincent B. (twinside@free.fr) -" Last Change: 2024 Oct 4 by @Konfekt +" Last Change: 2024 Nov 08 by @Konfekt -if exists("cppcheck") - finish -endif +if exists("current_compiler") | finish | endif let current_compiler = "cppcheck" let s:cpo_save = &cpo -set cpo-=C +set cpo&vim + +let s:slash = has('win32')? '\' : '/' if !exists('g:c_cppcheck_params') let g:c_cppcheck_params = '--verbose --force --inline-suppr' @@ -20,12 +20,12 @@ endif let &l:makeprg = 'cppcheck --quiet' \ ..' --template="{file}:{line}:{column}: {severity}: [{id}] {message} {callstack}"' - \ ..' '..get(b:, 'c_cppcheck_params', - \ g:c_cppcheck_params..' '..(&filetype ==# 'cpp' ? ' --language=c++' : '')) + \ ..' '..get(b:, 'c_cppcheck_params', get(g:, 'c_cppcheck_params', (&filetype ==# 'cpp' ? ' --language=c++' : ''))) \ ..' '..get(b:, 'c_cppcheck_includes', get(g:, 'c_cppcheck_includes', \ (filereadable('compile_commands.json') ? '--project=compile_commands.json' : - \ (empty(&path) ? '' : '-I')..join(map(filter(split(&path, ','), 'isdirectory(v:val)'),'shellescape(v:val)'), ' -I')))) -silent CompilerSet makeprg + \ (!empty(glob('*'..s:slash..'compile_commands.json', 1, 1)) ? '--project='..glob('*'..s:slash..'compile_commands.json', 1, 1)[0] : + \ (empty(&path) ? '' : '-I')..join(map(filter(split(&path, ','), 'isdirectory(v:val)'),'shellescape(v:val)'), ' -I'))))) +exe 'CompilerSet makeprg='..escape(&l:makeprg, ' "') CompilerSet errorformat= \%f:%l:%c:\ %tarning:\ %m, diff --git a/runtime/compiler/maven.vim b/runtime/compiler/maven.vim new file mode 100644 index 0000000000..ef8d8a6fb2 --- /dev/null +++ b/runtime/compiler/maven.vim @@ -0,0 +1,40 @@ +" Vim compiler file +" Compiler: Maven +" Maintainer: D. Ben Knoble <ben.knoble+vim@gmail.com> +" Maintainer: Konfekt +" Original Source: https://github.com/JalaiAmitahl/maven-compiler.vim/blob/master/compiler/mvn.vim +" (Copyright Dan Taylor, distributed under the same terms as LICENSE) +" Original Source: https://github.com/mikelue/vim-maven-plugin/blob/master/compiler/maven.vim +" (distributed under same terms as LICENSE per +" https://github.com/mikelue/vim-maven-plugin/issues/13) +" Last Change: 2024 Nov 12 + +if exists("current_compiler") + finish +endif +let current_compiler = "maven" + +CompilerSet makeprg=mvn\ --batch-mode + +" Error message for POM +CompilerSet errorformat=[FATAL]\ Non-parseable\ POM\ %f:\ %m%\\s%\\+@%.%#line\ %l\\,\ column\ %c%.%#, +CompilerSet errorformat+=[%tRROR]\ Malformed\ POM\ %f:\ %m%\\s%\\+@%.%#line\ %l\\,\ column\ %c%.%# + +" Java related build messages +CompilerSet errorformat+=[%tARNING]\ %f:[%l\\,%c]\ %m +CompilerSet errorformat+=[%tRROR]\ %f:[%l\\,%c]\ %m +CompilerSet errorformat+=%A[%t%[A-Z]%#]\ %f:[%l\\,%c]\ %m,%Z +CompilerSet errorformat+=%A%f:[%l\\,%c]\ %m,%Z + +" jUnit related build messages +CompilerSet errorformat+=%+E\ \ %#test%m,%Z +CompilerSet errorformat+=%+E[ERROR]\ Please\ refer\ to\ %f\ for\ the\ individual\ test\ results. +" Message from JUnit 5(5.3.X), TestNG(6.14.X), JMockit(1.43), and AssertJ(3.11.X) +CompilerSet errorformat+=%+E%>[ERROR]\ %.%\\+Time\ elapsed:%.%\\+<<<\ FAILURE!, +CompilerSet errorformat+=%+E%>[ERROR]\ %.%\\+Time\ elapsed:%.%\\+<<<\ ERROR!, +CompilerSet errorformat+=%+Z%\\s%#at\ %f(%\\f%\\+:%l), +CompilerSet errorformat+=%+C%.%# + +" Misc message removal +CompilerSet errorformat+=%-G[INFO]\ %.%#, +CompilerSet errorformat+=%-G[debug]\ %.%# diff --git a/runtime/compiler/mypy.vim b/runtime/compiler/mypy.vim new file mode 100644 index 0000000000..891488626a --- /dev/null +++ b/runtime/compiler/mypy.vim @@ -0,0 +1,19 @@ +" Vim compiler file +" Compiler: Mypy (Python static checker) +" Maintainer: @Konfekt +" Last Change: 2024 Nov 07 + +if exists("current_compiler") | finish | endif +let current_compiler = "mypy" + +let s:cpo_save = &cpo +set cpo&vim + +" CompilerSet makeprg=mypy +let &l:makeprg = 'mypy --show-column-numbers ' + \ ..get(b:, 'mypy_makeprg_params', get(g:, 'mypy_makeprg_params', '--strict --ignore-missing-imports')) +exe 'CompilerSet makeprg='..escape(&l:makeprg, ' "') +CompilerSet errorformat=%f:%l:%c:\ %t%*[^:]:\ %m + +let &cpo = s:cpo_save +unlet s:cpo_save diff --git a/runtime/compiler/pylint.vim b/runtime/compiler/pylint.vim index 14e9696dbb..4c9c23e125 100644 --- a/runtime/compiler/pylint.vim +++ b/runtime/compiler/pylint.vim @@ -1,13 +1,20 @@ " Vim compiler file -" Compiler: Pylint for Python -" Maintainer: Daniel Moch <daniel@danielmoch.com> -" Last Change: 2016 May 20 -" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) - -if exists("current_compiler") - finish -endif +" Compiler: Pylint for Python +" Maintainer: Daniel Moch <daniel@danielmoch.com> +" Last Change: 2024 Nov 07 by The Vim Project (added params variable) + +if exists("current_compiler") | finish | endif let current_compiler = "pylint" -CompilerSet makeprg=pylint\ --output-format=text\ --msg-template=\"{path}:{line}:{column}:{C}:\ [{symbol}]\ {msg}\"\ --reports=no +let s:cpo_save = &cpo +set cpo&vim + +" CompilerSet makeprg=ruff +let &l:makeprg = 'pylint ' . + \ '--output-format=text --msg-template="{path}:{line}:{column}:{C}: [{symbol}] {msg}" --reports=no ' . + \ get(b:, "pylint_makeprg_params", get(g:, "pylint_makeprg_params", '--jobs=0')) +exe 'CompilerSet makeprg='..escape(&l:makeprg, ' "') CompilerSet errorformat=%A%f:%l:%c:%t:\ %m,%A%f:%l:\ %m,%A%f:(%l):\ %m,%-Z%p^%.%#,%-G%.%# + +let &cpo = s:cpo_save +unlet s:cpo_save diff --git a/runtime/compiler/ruff.vim b/runtime/compiler/ruff.vim new file mode 100644 index 0000000000..11a69740d8 --- /dev/null +++ b/runtime/compiler/ruff.vim @@ -0,0 +1,19 @@ +" Vim compiler file +" Compiler: Ruff (Python linter) +" Maintainer: @pbnj-dragon +" Last Change: 2024 Nov 07 + +if exists("current_compiler") | finish | endif +let current_compiler = "ruff" + +let s:cpo_save = &cpo +set cpo&vim + +" CompilerSet makeprg=ruff +let &l:makeprg= 'ruff check --output-format=concise ' + \ ..get(b:, 'ruff_makeprg_params', get(g:, 'ruff_makeprg_params', '--preview')) +exe 'CompilerSet makeprg='..escape(&l:makeprg, ' "') +CompilerSet errorformat=%f:%l:%c:\ %m,%f:%l:\ %m,%f:%l:%c\ -\ %m,%f: + +let &cpo = s:cpo_save +unlet s:cpo_save diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index dee0324a5b..c5dabeb551 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -658,12 +658,12 @@ nvim_echo({chunks}, {history}, {opts}) *nvim_echo()* Parameters: ~ • {chunks} A list of `[text, hl_group]` arrays, each representing a - text chunk with specified highlight. `hl_group` element can - be omitted for no highlight. + text chunk with specified highlight group name or ID. + `hl_group` element can be omitted for no highlight. • {history} if true, add to |message-history|. • {opts} Optional parameters. - • verbose: Message was printed as a result of 'verbose' - option if Nvim was invoked with -V3log_file, the message + • verbose: Message is printed as a result of 'verbose' + option. If Nvim was invoked with -V3log_file, the message will be redirected to the log_file and suppressed from direct output. @@ -2672,8 +2672,10 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {opts}) • id : id of the extmark to edit. • end_row : ending line of the mark, 0-based inclusive. • end_col : ending col of the mark, 0-based exclusive. - • hl_group : name of the highlight group used to highlight - this mark. + • hl_group : highlight group used for the text range. This + and below highlight groups can be supplied either as a + string or as an integer, the latter of which can be + obtained using |nvim_get_hl_id_by_name()|. • hl_eol : when true, for a multiline highlight covering the EOL of a line, continue the highlight for the rest of the screen line (just like for diff and cursorline highlight). @@ -2682,9 +2684,7 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {opts}) with specified highlight. `highlight` element can either be a single highlight group, or an array of multiple highlight groups that will be stacked (highest priority - last). A highlight group can be supplied either as a - string or as an integer, the latter which can be obtained - using |nvim_get_hl_id_by_name()|. + last). • virt_text_pos : position of virtual text. Possible values: • "eol": right after eol character (default). • "overlay": display over the specified column, without @@ -2750,15 +2750,14 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {opts}) buffer or end of the line respectively. Defaults to true. • sign_text: string of length 1-2 used to display in the sign column. - • sign_hl_group: name of the highlight group used to - highlight the sign column text. - • number_hl_group: name of the highlight group used to - highlight the number column. - • line_hl_group: name of the highlight group used to - highlight the whole line. - • cursorline_hl_group: name of the highlight group used to - highlight the sign column text when the cursor is on the - same line as the mark and 'cursorline' is enabled. + • sign_hl_group: highlight group used for the sign column + text. + • number_hl_group: highlight group used for the number + column. + • line_hl_group: highlight group used for the whole line. + • cursorline_hl_group: highlight group used for the sign + column text when the cursor is on the same line as the + mark and 'cursorline' is enabled. • conceal: string which should be either empty or a single character. Enable concealing similar to |:syn-conceal|. When a character is supplied it is used as |:syn-cchar|. @@ -3195,7 +3194,13 @@ nvim_open_win({buffer}, {enter}, {config}) *nvim_open_win()* be fractional. • focusable: Enable focus by user actions (wincmds, mouse events). Defaults to true. Non-focusable windows can be - entered by |nvim_set_current_win()|. + entered by |nvim_set_current_win()|, or, when the `mouse` + field is set to true, by mouse events. See |focusable|. + • mouse: Specify how this window interacts with mouse + events. Defaults to `focusable` value. + • If false, mouse events pass through this window. + • If true, mouse events interact with this window + normally. • external: GUI should display the window as an external top-level window. Currently accepts no other positioning configuration together with this. diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt index 8e5e2628de..998ef5e9f3 100644 --- a/runtime/doc/autocmd.txt +++ b/runtime/doc/autocmd.txt @@ -353,15 +353,11 @@ BufWritePost After writing the whole buffer to a file ChanInfo State of channel changed, for instance the client of a RPC channel described itself. Sets these |v:event| keys: - info - See |nvim_get_chan_info()| for the format of - the info Dictionary. + info as from |nvim_get_chan_info()| *ChanOpen* ChanOpen Just after a channel was opened. Sets these |v:event| keys: - info - See |nvim_get_chan_info()| for the format of - the info Dictionary. + info as from |nvim_get_chan_info()| *CmdUndefined* CmdUndefined When a user command is used but it isn't defined. Useful for defining a command only diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 4c726f86d2..ada3b7103c 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -269,16 +269,16 @@ assert_equal({expected}, {actual} [, {msg}]) *assert_equal()* Return: ~ (`0|1`) -assert_equalfile({fname-one}, {fname-two}) *assert_equalfile()* - When the files {fname-one} and {fname-two} do not contain +assert_equalfile({fname_one}, {fname_two}) *assert_equalfile()* + When the files {fname_one} and {fname_two} do not contain exactly the same text an error message is added to |v:errors|. Also see |assert-return|. - When {fname-one} or {fname-two} does not exist the error will + When {fname_one} or {fname_two} does not exist the error will mention that. Parameters: ~ - • {fname-one} (`string`) - • {fname-two} (`string`) + • {fname_one} (`string`) + • {fname_two} (`string`) Return: ~ (`0|1`) @@ -936,7 +936,7 @@ charclass({string}) *charclass()* The character class is one of: 0 blank 1 punctuation - 2 word character + 2 word character (depends on 'iskeyword') 3 emoji other specific Unicode class The class is used in patterns and word motions. @@ -959,7 +959,7 @@ charcol({expr} [, {winid}]) *charcol()* < Parameters: ~ - • {expr} (`string|integer[]`) + • {expr} (`string|any[]`) • {winid} (`integer?`) Return: ~ @@ -1100,7 +1100,7 @@ col({expr} [, {winid}]) *col()* < Parameters: ~ - • {expr} (`string|integer[]`) + • {expr} (`string|any[]`) • {winid} (`integer?`) Return: ~ @@ -3224,13 +3224,24 @@ getcharstr([{expr}]) *getcharstr()* Return: ~ (`string`) +getcmdcomplpat() *getcmdcomplpat()* + Return completion pattern of the current command-line. + Only works when the command line is being edited, thus + requires use of |c_CTRL-\_e| or |c_CTRL-R_=|. + Also see |getcmdtype()|, |setcmdpos()|, |getcmdline()|, + |getcmdprompt()|, |getcmdcompltype()| and |setcmdline()|. + Returns an empty string when completion is not defined. + + Return: ~ + (`string`) + getcmdcompltype() *getcmdcompltype()* Return the type of the current command-line completion. Only works when the command line is being edited, thus requires use of |c_CTRL-\_e| or |c_CTRL-R_=|. See |:command-completion| for the return string. Also see |getcmdtype()|, |setcmdpos()|, |getcmdline()|, - |getcmdprompt()| and |setcmdline()|. + |getcmdprompt()|, |getcmdcomplpat()| and |setcmdline()|. Returns an empty string when completion is not defined. Return: ~ @@ -3351,6 +3362,7 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()* runtime |:runtime| completion scriptnames sourced script names |:scriptnames| shellcmd Shell command + shellcmdline Shell command line with filename arguments sign |:sign| suboptions syntax syntax file names |'syntax'| syntime |:syntime| suboptions @@ -5746,7 +5758,7 @@ luaeval({expr} [, {expr}]) *luaeval()* map({expr1}, {expr2}) *map()* {expr1} must be a |List|, |String|, |Blob| or |Dictionary|. - When {expr1} is a |List|| or |Dictionary|, replace each + When {expr1} is a |List| or |Dictionary|, replace each item in {expr1} with the result of evaluating {expr2}. For a |Blob| each byte is replaced. For a |String|, each character, including composing @@ -8690,7 +8702,7 @@ setcellwidths({list}) *setcellwidths()* To clear the overrides pass an empty {list}: >vim call setcellwidths([]) -< You can use the script $VIMRUNTIME/tools/emoji_list.lua to see +< You can use the script $VIMRUNTIME/scripts/emoji_list.lua to see the effect for known emoji characters. Move the cursor through the text to check if the cell widths of your terminal match with what Vim knows about each emoji. If it doesn't @@ -9027,6 +9039,8 @@ setqflist({list} [, {action} [, {what}]]) *setqflist()* clear the list: >vim call setqflist([], 'r') < + 'u' Like 'r', but tries to preserve the current selection + in the quickfix list. 'f' All the quickfix lists in the quickfix stack are freed. @@ -9083,9 +9097,9 @@ setqflist({list} [, {action} [, {what}]]) *setqflist()* `:cc 1` to jump to the first position. Parameters: ~ - • {list} (`any[]`) + • {list} (`vim.quickfix.entry[]`) • {action} (`string?`) - • {what} (`table?`) + • {what} (`vim.fn.setqflist.what?`) Return: ~ (`any`) @@ -11597,7 +11611,7 @@ virtcol({expr} [, {list} [, {winid}]]) *virtcol()* < Parameters: ~ - • {expr} (`string|integer[]`) + • {expr} (`string|any[]`) • {list} (`boolean?`) • {winid} (`integer?`) @@ -11691,7 +11705,7 @@ wildmenumode() *wildmenumode()* For example to make <c-j> work like <down> in wildmode, use: >vim cnoremap <expr> <C-j> wildmenumode() ? "\<Down>\<Tab>" : "\<c-j>" < - (Note, this needs the 'wildcharm' option set appropriately). + (Note: this needs the 'wildcharm' option set appropriately). Return: ~ (`any`) diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt index 928b834600..768a449581 100644 --- a/runtime/doc/change.txt +++ b/runtime/doc/change.txt @@ -561,6 +561,8 @@ with ".". Vim does not recognize a comment (starting with '"') after the program {filter} (for {Visual} see |Visual-mode|). :{range}![!]{filter} [!][arg] *:range!* + For executing external commands see |:!| + Filter {range} lines through the external program {filter}. Vim replaces the optional bangs with the latest given command and appends the optional [arg]. diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt index 72d2faca02..5e809ad26c 100644 --- a/runtime/doc/deprecated.txt +++ b/runtime/doc/deprecated.txt @@ -21,6 +21,8 @@ API LUA - vim.region() Use |getregionpos()| instead. +- *vim.highlight* Renamed to |vim.hl|. +- vim.validate(opts: table) Use form 1. See |vim.validate()|. DIAGNOSTICS - *vim.diagnostic.goto_next()* Use |vim.diagnostic.jump()| with `{count=1, float=true}` instead. @@ -36,6 +38,25 @@ DIAGNOSTICS - The "cursor_position" parameter of |vim.diagnostic.JumpOpts| is renamed to "pos" +TREESITTER +• *TSNode:child_containing_descendant()* Use + |TSNode:child_with_descendant()| instead; it is identical except that it can + return the descendant itself. + +LSP +• *vim.lsp.util.jump_to_location* Use |vim.lsp.util.show_document()| with + `{focus=true}` instead. +• *vim.lsp.buf.execute_command* Use |Client:exec_cmd()| instead. +• *vim.lsp.buf.completion* Use |vim.lsp.completion.trigger()| instead. +• vim.lsp.buf_request_all The `error` key has been renamed to `err` inside + the result parameter of the handler. +• *vim.lsp.with()* Pass configuration to equivalent + functions in `vim.lsp.buf.*'. +• |vim.lsp.handlers| + No longer support client to server response handlers. Only server to + client requests/notification handlers are supported. +• *vim.lsp.handlers.signature_help()* Use |vim.lsp.buf.signature_help()| instead. + ------------------------------------------------------------------------------ DEPRECATED IN 0.10 *deprecated-0.10* diff --git a/runtime/doc/dev_style.txt b/runtime/doc/dev_style.txt index 32f7279704..97d5ebdb52 100644 --- a/runtime/doc/dev_style.txt +++ b/runtime/doc/dev_style.txt @@ -64,9 +64,8 @@ Symbols: - `extern` variables (including the `EXTERN` macro) Non-symbols: - - macros, i.e. `#define`. - - static inline functions, but only if its function declaration has a - `REAL_FATTR_ALWAYS_INLINE` attribute. + - macros, i.e. `#define` + - static inline functions with the `FUNC_ATTR_ALWAYS_INLINE` attribute - typedefs - structs - enums diff --git a/runtime/doc/diagnostic.txt b/runtime/doc/diagnostic.txt index 342947595e..9ccc3102b6 100644 --- a/runtime/doc/diagnostic.txt +++ b/runtime/doc/diagnostic.txt @@ -445,10 +445,10 @@ Lua module: vim.diagnostic *diagnostic-api* updated on |InsertLeave|) • {severity_sort}? (`boolean|{reverse?:boolean}`, default: `false`) Sort diagnostics by severity. This affects the - order in which signs and virtual text are - displayed. When true, higher severities are - displayed before lower severities (e.g. ERROR is - displayed before WARN). Options: + order in which signs, virtual text, and + highlights are displayed. When true, higher + severities are displayed before lower severities + (e.g. ERROR is displayed before WARN). Options: • {reverse}? (boolean) Reverse sort order • {jump}? (`vim.diagnostic.Opts.Jump`) Default values for |vim.diagnostic.jump()|. See diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt index 0008713025..4224709a39 100644 --- a/runtime/doc/editing.txt +++ b/runtime/doc/editing.txt @@ -1032,6 +1032,15 @@ explanation of when the copy is made and when the file is renamed. If the creation of a backup file fails, the write is not done. If you want to write anyway add a '!' to the command. + *file-watcher* +When you notice issues with programs, that act upon when a buffer is written +(like inotify, entr or fswatch) or when external applications execute Vim to +edit the file (like git) and those programs do not seem to notice that the +original file has been changed, you may want to consider switching the +'backupcopy' option value to "yes". This makes sure, Vim writes to the same +file, that those watcher programs expect, without creating a new file (which +prevents them from detecting that the file has changed). See also |crontab| + *write-permissions* When writing a new file the permissions are read-write. For unix the mask is 0o666 with additionally umask applied. When writing a file that was read Vim @@ -1287,7 +1296,7 @@ separated by ';'. For example, to have only Vim files in the dialog, you could use the following command: > - let g:browsefilter = "Vim Scripts\t*.vim\nVim Startup Files\t*vimrc\n" + let g:browsefilter = "Vim scripts\t*.vim\nVim Startup Files\t*vimrc\n" You can override the filter setting on a per-buffer basis by setting the b:browsefilter variable. You would most likely set b:browsefilter in a diff --git a/runtime/doc/faq.txt b/runtime/doc/faq.txt index 7d2774c191..a9a7b1768e 100644 --- a/runtime/doc/faq.txt +++ b/runtime/doc/faq.txt @@ -189,7 +189,7 @@ Other hints: - The python `neovim` module was renamed to `pynvim` (long ago). - If you're using pyenv or virtualenv for the `pynvim` module - https://pypi.python.org/pypi/pynvim/, you must set `g:python3_host_prog` to + https://pypi.org/project/pynvim/, you must set `g:python3_host_prog` to the virtualenv's interpreter path. - Read |provider-python|. - Be sure you have the latest version of the `pynvim` Python module: >bash diff --git a/runtime/doc/filetype.txt b/runtime/doc/filetype.txt index a577b0c5fb..19c018bc11 100644 --- a/runtime/doc/filetype.txt +++ b/runtime/doc/filetype.txt @@ -40,7 +40,7 @@ Detail: The ":filetype on" command will load these files: $VIMRUNTIME/scripts.vim is used to detect it from the contents of the file. When the GUI is running or will start soon, the |menu.vim| script is - also sourced. See |'go-M'| about avoiding that. + also sourced. To add your own file types, see |new-filetype| below. To search for help on a filetype prepend "ft-" and optionally append "-syntax", "-indent" or @@ -630,6 +630,19 @@ HARE *ft-hare* Since the text for this plugin is rather long it has been put in a separate file: |ft_hare.txt|. +IDRIS2 *ft-idris2-plugin* + +By default the following options are set: > + + setlocal shiftwidth=2 tabstop=2 expandtab + setlocal comments=s1:{-,mb:-,ex:-},:\|\|\|,:-- + setlocal commentstring=--\ %s + setlocal wildignore+=*.ibc + +To use tabs instead of spaces for indentation, set the following variable +in your vimrc: > + + let g:idris2#allow_tabchar = 1 JAVA *ft-java-plugin* @@ -774,6 +787,12 @@ To enable folding use this: > let g:markdown_recommended_style = 0 +ORG *ft-org-plugin* + +To enable folding use this: > + let g:org_folding = 1 +< + PDF *ft-pdf-plugin* Two maps, <C-]> and <C-T>, are provided to simulate a tag stack for navigating @@ -1039,6 +1058,19 @@ TYPST *ft-typst-plugin* *g:typst_conceal* When |TRUE| the Typst filetype plugin will set the 'conceallevel' option to 2. + *g:typst_folding* +When |TRUE| the Typst filetype plugin will fold headings. (default: |FALSE|) + +To enable: > + let g:typst_folding = 1 +< + *g:typst_foldnested* +When |TRUE| the Typst filetype plugin will fold nested heading under their +parents. (default: |TRUE|) + +To disable: > + let g:typst_foldnested = 0 +< VIM *ft-vim-plugin* The Vim filetype plugin defines mappings to move to the start and end of diff --git a/runtime/doc/gui.txt b/runtime/doc/gui.txt index 9ab5bf4e1e..21f1ba8241 100644 --- a/runtime/doc/gui.txt +++ b/runtime/doc/gui.txt @@ -164,7 +164,6 @@ menus and menu items. They are most useful for things that you can't remember what the key sequence was. For creating menus in a different language, see |:menutrans|. -If you don't want to use menus at all, see |'go-M'|. *menu.vim* The default menus are read from the file "$VIMRUNTIME/menu.vim". See diff --git a/runtime/doc/indent.txt b/runtime/doc/indent.txt index f97ae24068..49d770124a 100644 --- a/runtime/doc/indent.txt +++ b/runtime/doc/indent.txt @@ -809,6 +809,38 @@ Detail: : GetCSSIndent() else <!-- --> : -1 +IDRIS2 *ft-idris2-indent* + +Idris 2 indentation can be configured with several variables that control the +indentation level for different language constructs: + +The "g:idris2_indent_if" variable controls the indentation of `then` and `else` +blocks after `if` statements. Defaults to 3. + +The "g:idris2_indent_case" variable controls the indentation of patterns in +`case` expressions. Defaults to 5. + +The "g:idris2_indent_let" variable controls the indentation after `let` +bindings. Defaults to 4. + +The "g:idris2_indent_rewrite" variable controls the indentation after `rewrite` +expressions. Defaults to 8. + +The "g:idris2_indent_where" variable controls the indentation of `where` +blocks. Defaults to 6. + +The "g:idris2_indent_do" variable controls the indentation in `do` blocks. +Defaults to 3. + +Example configuration: > + + let g:idris2_indent_if = 2 + let g:idris2_indent_case = 4 + let g:idris2_indent_let = 4 + let g:idris2_indent_rewrite = 8 + let g:idris2_indent_where = 6 + let g:idris2_indent_do = 3 +< MATLAB *ft-matlab-indent* *matlab-indent* *matlab-indenting* diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt index d7cbb7c78e..48fd442b7e 100644 --- a/runtime/doc/insert.txt +++ b/runtime/doc/insert.txt @@ -1177,12 +1177,12 @@ items: user_data custom data which is associated with the item and available in |v:completed_item|; it can be any type; defaults to an empty string - hl_group an additional highlight group whose attributes are + abbr_hlgroup an additional highlight group whose attributes are combined with |hl-PmenuSel| and |hl-Pmenu| or |hl-PmenuMatchSel| and |hl-PmenuMatch| highlight attributes in the popup menu to apply cterm and gui properties (with higher priority) like strikethrough - to the completion items + to the completion items abbreviation kind_hlgroup an additional highlight group specifically for setting the highlight attributes of the completion kind. When this field is present, it will override the @@ -1907,6 +1907,16 @@ These commands are used to start inserting text. You can end insert mode with <Esc>. See |mode-ins-repl| for the other special characters in Insert mode. The effect of [count] takes place after Insert mode is exited. +The following commands insert text, but stay in normal mode: + + *]<Space>* +]<Space> Insert an empty line below the cursor without leaving + Normal mode, repeat [count] times. + + *[<Space>* +[<Space> Insert an empty line above the cursor without leaving + Normal mode, repeat [count] times. + When 'autoindent' is on, the indent for a new line is obtained from the previous line. When 'smartindent' or 'cindent' is on, the indent for a line is automatically adjusted for C programs. diff --git a/runtime/doc/intro.txt b/runtime/doc/intro.txt index 41846f8eed..d099c29bdb 100644 --- a/runtime/doc/intro.txt +++ b/runtime/doc/intro.txt @@ -536,7 +536,7 @@ CTRL-O in Insert mode you get a beep but you are still in Insert mode, type Select *5 ^O ^G *6 -- -- -- Insert <Esc> -- -- <Insert> -- -- Replace <Esc> -- -- <Insert> -- -- - Command-line `*3` -- -- :start -- -- + Command-line *3 -- -- :start -- -- Ex :vi -- -- -- -- -- -- not possible diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index 419f583c36..64bef849fc 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -71,11 +71,13 @@ options are not restored when the LSP client is stopped or detached. - |K| is mapped to |vim.lsp.buf.hover()| unless |'keywordprg'| is customized or a custom keymap for `K` exists. - *grr* *gra* *grn* *i_CTRL-S* + *grr* *gra* *grn* *gri* *i_CTRL-S* Some keymaps are created unconditionally when Nvim starts: - "grn" is mapped in Normal mode to |vim.lsp.buf.rename()| - "gra" is mapped in Normal and Visual mode to |vim.lsp.buf.code_action()| - "grr" is mapped in Normal mode to |vim.lsp.buf.references()| +- "gri" is mapped in Normal mode to |vim.lsp.buf.implementation()| +- "gO" is mapped in Normal mode to |vim.lsp.buf.document_symbol()| - CTRL-S is mapped in Insert mode to |vim.lsp.buf.signature_help()| If not wanted, these keymaps can be removed at any time using @@ -193,41 +195,41 @@ Requests and notifications defined by the LSP specification are referred to as They are also listed below. Note that handlers depend on server support: they won't run if your server doesn't support them. -- callHierarchy/incomingCalls -- callHierarchy/outgoingCalls -- textDocument/codeAction -- textDocument/completion -- textDocument/declaration* -- textDocument/definition -- textDocument/diagnostic -- textDocument/documentHighlight -- textDocument/documentSymbol -- textDocument/formatting -- textDocument/hover -- textDocument/implementation* -- textDocument/inlayHint -- textDocument/prepareTypeHierarchy -- textDocument/publishDiagnostics -- textDocument/rangeFormatting -- textDocument/rangesFormatting -- textDocument/references -- textDocument/rename -- textDocument/semanticTokens/full -- textDocument/semanticTokens/full/delta -- textDocument/signatureHelp -- textDocument/typeDefinition* -- typeHierarchy/subtypes -- typeHierarchy/supertypes -- window/logMessage -- window/showMessage -- window/showDocument -- window/showMessageRequest -- workspace/applyEdit -- workspace/configuration -- workspace/executeCommand -- workspace/inlayHint/refresh -- workspace/symbol -- workspace/workspaceFolders +- `'callHierarchy/incomingCalls'` +- `'callHierarchy/outgoingCalls'` +- `'textDocument/codeAction'` +- `'textDocument/completion'` +- `'textDocument/declaration'` +- `'textDocument/definition'` +- `'textDocument/diagnostic'` +- `'textDocument/documentHighlight'` +- `'textDocument/documentSymbol'` +- `'textDocument/formatting'` +- `'textDocument/hover'` +- `'textDocument/implementation'` +- `'textDocument/inlayHint'` +- `'textDocument/prepareTypeHierarchy'` +- `'textDocument/publishDiagnostics'` +- `'textDocument/rangeFormatting'` +- `'textDocument/rangesFormatting'` +- `'textDocument/references'` +- `'textDocument/rename'` +- `'textDocument/semanticTokens/full'` +- `'textDocument/semanticTokens/full/delta'` +- `'textDocument/signatureHelp'` +- `'textDocument/typeDefinition*'` +- `'typeHierarchy/subtypes'` +- `'typeHierarchy/supertypes'` +- `'window/logMessage'` +- `'window/showMessage'` +- `'window/showDocument'` +- `'window/showMessageRequest'` +- `'workspace/applyEdit'` +- `'workspace/configuration'` +- `'workspace/executeCommand'` +- `'workspace/inlayHint/refresh'` +- `'workspace/symbol'` +- `'workspace/workspaceFolders'` *lsp-handler* LSP handlers are functions that handle |lsp-response|s to requests made by Nvim @@ -236,7 +238,7 @@ there is no response, so they can't be handled. |lsp-notification|) Each response handler has this signature: > - function(err, result, ctx, config) + function(err, result, ctx) < Parameters: ~ • {err} (`table|nil`) Error info dict, or `nil` if the request @@ -253,121 +255,53 @@ Each response handler has this signature: > request. Handlers can compare this to the current document version to check if the response is "stale". See also |b:changedtick|. - • {config} (`table`) Handler-defined configuration table, which allows - users to customize handler behavior. - For an example, see: - |vim.lsp.diagnostic.on_publish_diagnostics()| - To configure a particular |lsp-handler|, see: - |lsp-handler-configuration| Returns: ~ Two values `result, err` where `err` is shaped like an RPC error: > { code, message, data? } < You can use |vim.lsp.rpc.rpc_response_error()| to create this object. - *lsp-handler-configuration* - -To configure the behavior of a builtin |lsp-handler|, the convenient method -|vim.lsp.with()| is provided for users. - - To configure the behavior of |vim.lsp.diagnostic.on_publish_diagnostics()|, - consider the following example, where a new |lsp-handler| is created using - |vim.lsp.with()| that no longer generates signs for the diagnostics: >lua - - vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with( - vim.lsp.diagnostic.on_publish_diagnostics, { - -- Disable signs - signs = false, - } - ) -< - To enable signs, use |vim.lsp.with()| again to create and assign a new - |lsp-handler| to |vim.lsp.handlers| for the associated method: >lua - - vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with( - vim.lsp.diagnostic.on_publish_diagnostics, { - -- Enable signs - signs = true, - } - ) -< - To configure a handler on a per-server basis, you can use the {handlers} key - for |vim.lsp.start_client()| >lua - - vim.lsp.start_client { - ..., -- Other configuration omitted. - handlers = { - ["textDocument/publishDiagnostics"] = vim.lsp.with( - vim.lsp.diagnostic.on_publish_diagnostics, { - -- Disable virtual_text - virtual_text = false, - } - ), - }, - } -< - or if using "nvim-lspconfig", you can use the {handlers} key of `setup()`: - >lua - - require('lspconfig').rust_analyzer.setup { - handlers = { - ["textDocument/publishDiagnostics"] = vim.lsp.with( - vim.lsp.diagnostic.on_publish_diagnostics, { - -- Disable virtual_text - virtual_text = false - } - ), - } - } -< - Some handlers do not have an explicitly named handler function (such as - |vim.lsp.diagnostic.on_publish_diagnostics()|). To override these, first - create a reference to the existing handler: >lua - - local on_references = vim.lsp.handlers["textDocument/references"] - vim.lsp.handlers["textDocument/references"] = vim.lsp.with( - on_references, { - -- Use location list instead of quickfix list - loclist = true, - } - ) -< *lsp-handler-resolution* -Handlers can be set by: +Handlers can be set by (in increasing priority): - Setting a field in vim.lsp.handlers. *vim.lsp.handlers* - vim.lsp.handlers is a global table that contains the default mapping of - |lsp-method| names to |lsp-handlers|. To override the handler for the - `"textDocument/definition"` method: >lua + `vim.lsp.handlers` is a global table that contains the default mapping of + |lsp-method| names to lsp-handlers. - vim.lsp.handlers["textDocument/definition"] = my_custom_default_definition + Example: >lua + + vim.lsp.handlers['textDocument/publishDiagnostics'] = my_custom_diagnostics_handler < + Note: this only applies for requests/notifications made by the + server to the client. + - The {handlers} parameter of |vim.lsp.start()|. This sets the default - |lsp-handler| for the server being started. Example: >lua + |lsp-handler| for a specific server. + + Example: >lua vim.lsp.start { ..., -- Other configuration omitted. handlers = { - ["textDocument/definition"] = my_custom_server_definition + ['textDocument/publishDiagnostics'] = my_custom_server_definition }, } +< + Note: this only applies for requests/notifications made by the + server to the client. - The {handler} parameter of |vim.lsp.buf_request_all()|. This sets - the |lsp-handler| ONLY for the given request(s). Example: >lua + the |lsp-handler| ONLY for the given request(s). + + Example: >lua vim.lsp.buf_request_all( 0, - "textDocument/definition", + 'textDocument/publishDiagnostics', my_request_params, my_handler ) < -In summary, the |lsp-handler| will be chosen based on the current |lsp-method| -in the following order: - -1. Handler passed to |vim.lsp.buf_request_all()|, if any. -2. Handler defined in |vim.lsp.start()|, if any. -3. Handler defined in |vim.lsp.handlers|, if any. *vim.lsp.log_levels* Log levels are defined in |vim.log.levels| @@ -404,13 +338,16 @@ 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* + *hl-LspReferenceText* LspReferenceText used for highlighting "text" references - *hl-LspReferenceRead* + *hl-LspReferenceRead* LspReferenceRead used for highlighting "read" references - *hl-LspReferenceWrite* + *hl-LspReferenceWrite* LspReferenceWrite used for highlighting "write" references - *hl-LspInlayHint* + *hl-LspReferenceTarget* +LspReferenceTarget used for highlighting reference targets (e.g. in a + hover range) + *hl-LspInlayHint* LspInlayHint used for highlighting inlay hints @@ -463,7 +400,7 @@ Use |:Inspect| to view the highlights for a specific token. Use |:hi| or hi @lsp.mod.deprecated gui=strikethrough " deprecated is crossed out hi @lsp.typemod.function.async guifg=Blue " async functions are blue < -The value |vim.highlight.priorities|`.semantic_tokens` is the priority of the +The value |vim.hl.priorities|`.semantic_tokens` is the priority of the `@lsp.type.*` highlights. The `@lsp.mod.*` and `@lsp.typemod.*` highlights have priorities one and two higher, respectively. @@ -541,10 +478,10 @@ LspDetach *LspDetach* -- Remove the autocommand to format the buffer on save, if it exists if client.supports_method('textDocument/formatting') then - vim.api.nvim_clear_autocmds({ - event = 'BufWritePre', - buffer = args.buf, - }) + vim.api.nvim_clear_autocmds({ + event = 'BufWritePre', + buffer = args.buf, + }) end end, }) @@ -701,7 +638,10 @@ buf_request_all({bufnr}, {method}, {params}, {handler}) Parameters: ~ • {bufnr} (`integer`) Buffer handle, or 0 for current. • {method} (`string`) LSP method name - • {params} (`table?`) Parameters to send to the server + • {params} (`table|(fun(client: vim.lsp.Client, bufnr: integer): table?)?`) + Parameters to send to the server. Can also be passed as a + function that returns the params table for cases where + parameters are specific to the client. • {handler} (`function`) Handler called after all requests are completed. Server results are passed as a `client_id:result` map. @@ -866,9 +806,9 @@ start({config}, {opts}) *vim.lsp.start()* |vim.lsp.start_client()|. • `root_dir` path to the project root. By default this is used to decide if an existing client should be re-used. The example above uses - |vim.fs.root()| and |vim.fs.dirname()| to detect the root by traversing - the file system upwards starting from the current directory until either - a `pyproject.toml` or `setup.py` file is found. + |vim.fs.root()| to detect the root by traversing the file system upwards + starting from the current directory until either a `pyproject.toml` or + `setup.py` file is found. • `workspace_folders` list of `{ uri:string, name: string }` tables specifying the project root folders used by the language server. If `nil` the property is derived from `root_dir` for convenience. @@ -950,14 +890,6 @@ tagfunc({pattern}, {flags}) *vim.lsp.tagfunc()* Return: ~ (`table[]`) tags A list of matching tags -with({handler}, {override_config}) *vim.lsp.with()* - Function to manage overriding defaults for LSP handlers. - - Parameters: ~ - • {handler} (`lsp.Handler`) See |lsp-handler| - • {override_config} (`table`) Table containing the keys to override - behavior of the {handler} - ============================================================================== Lua module: vim.lsp.client *lsp-client* @@ -1083,6 +1015,11 @@ Lua module: vim.lsp.client *lsp-client* • {is_stopped} (`fun(): boolean`) Checks whether a client is stopped. Returns: true if the client is fully stopped. + • {exec_cmd} (`fun(self: vim.lsp.Client, command: lsp.Command, context: {bufnr?: integer}?, handler: lsp.Handler?)`) + Execute a lsp command, either via client + command function (if available) or via + workspace/executeCommand (if supported by the + server) *vim.lsp.Client.Progress* Extends: |vim.Ringbuf| @@ -1153,7 +1090,8 @@ Lua module: vim.lsp.client *lsp-client* • {name}? (`string`, default: client-id) Name in log messages. • {get_language_id}? (`fun(bufnr: integer, filetype: string): string`) - Language ID as string. Defaults to the filetype. + Language ID as string. Defaults to the buffer + filetype. • {offset_encoding}? (`'utf-8'|'utf-16'|'utf-32'`) The encoding that the LSP server expects. Client does not verify this is correct. @@ -1212,6 +1150,15 @@ Lua module: vim.lsp.client *lsp-client* on initialization. +Client:exec_cmd({command}, {context}, {handler}) *Client:exec_cmd()* + Execute a lsp command, either via client command function (if available) + or via workspace/executeCommand (if supported by the server) + + Parameters: ~ + • {command} (`lsp.Command`) + • {context} (`{bufnr?: integer}?`) + • {handler} (`lsp.Handler?`) only called if a server command + ============================================================================== Lua module: vim.lsp.buf *lsp-buf* @@ -1253,6 +1200,20 @@ Lua module: vim.lsp.buf *lsp-buf* • {title}? (`string`) Title for the list. • {context}? (`table`) `ctx` from |lsp-handler| +*vim.lsp.buf.hover.Opts* + Extends: |vim.lsp.util.open_floating_preview.Opts| + + + Fields: ~ + • {silent}? (`boolean`) + +*vim.lsp.buf.signature_help.Opts* + Extends: |vim.lsp.util.open_floating_preview.Opts| + + + Fields: ~ + • {silent}? (`boolean`) + *vim.lsp.buf.add_workspace_folder()* add_workspace_folder({workspace_folder}) @@ -1294,19 +1255,6 @@ code_action({opts}) *vim.lsp.buf.code_action()* • https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction • vim.lsp.protocol.CodeActionTriggerKind -completion({context}) *vim.lsp.buf.completion()* - Retrieves the completion items at the current cursor position. Can only be - called in Insert mode. - - Parameters: ~ - • {context} (`table`) (context support not yet implemented) Additional - information about the context in which a completion was - triggered (how it was triggered, and by which trigger - character, if applicable) - - See also: ~ - • vim.lsp.protocol.CompletionTriggerKind - declaration({opts}) *vim.lsp.buf.declaration()* Jumps to the declaration of the symbol under the cursor. @@ -1343,15 +1291,6 @@ document_symbol({opts}) *vim.lsp.buf.document_symbol()* Parameters: ~ • {opts} (`vim.lsp.ListOpts?`) See |vim.lsp.ListOpts|. -execute_command({command_params}) *vim.lsp.buf.execute_command()* - Executes an LSP server command. - - Parameters: ~ - • {command_params} (`lsp.ExecuteCommandParams`) - - See also: ~ - • https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand - format({opts}) *vim.lsp.buf.format()* Formats a buffer using the attached (and optionally filtered) language server clients. @@ -1392,7 +1331,7 @@ format({opts}) *vim.lsp.buf.format()* contain `start` and `end` keys as described above, in which case `textDocument/rangesFormatting` support is required. -hover() *vim.lsp.buf.hover()* +hover({config}) *vim.lsp.buf.hover()* Displays hover information about the symbol under the cursor in a floating window. The window will be dismissed on cursor move. Calling the function twice will jump into the floating window (thus by default, "KK" will open @@ -1400,6 +1339,17 @@ hover() *vim.lsp.buf.hover()* mappings are available as usual, except that "q" dismisses the window. You can scroll the contents the same as you would any other buffer. + Note: to disable hover highlights, add the following to your config: >lua + vim.api.nvim_create_autocmd('ColorScheme', { + callback = function() + vim.api.nvim_set_hl(0, 'LspReferenceTarget', {}) + end, + }) +< + + Parameters: ~ + • {config} (`vim.lsp.buf.hover.Opts?`) See |vim.lsp.buf.hover.Opts|. + implementation({opts}) *vim.lsp.buf.implementation()* Lists all the implementations for the symbol under the cursor in the quickfix window. @@ -1454,10 +1404,14 @@ rename({new_name}, {opts}) *vim.lsp.buf.rename()* ones where client.name matches this field. • {bufnr}? (`integer`) (default: current buffer) -signature_help() *vim.lsp.buf.signature_help()* +signature_help({config}) *vim.lsp.buf.signature_help()* Displays signature information about the symbol under the cursor in a floating window. + Parameters: ~ + • {config} (`vim.lsp.buf.signature_help.Opts?`) See + |vim.lsp.buf.signature_help.Opts|. + type_definition({opts}) *vim.lsp.buf.type_definition()* Jumps to the definition of the type of the symbol under the cursor. @@ -1507,66 +1461,24 @@ get_namespace({client_id}, {is_pull}) client. Defaults to push *vim.lsp.diagnostic.on_diagnostic()* -on_diagnostic({_}, {result}, {ctx}, {config}) +on_diagnostic({_}, {result}, {ctx}) |lsp-handler| for the method "textDocument/diagnostic" - See |vim.diagnostic.config()| for configuration options. Handler-specific - configuration can be set using |vim.lsp.with()|: >lua - vim.lsp.handlers["textDocument/diagnostic"] = vim.lsp.with( - vim.lsp.diagnostic.on_diagnostic, { - -- Enable underline, use default values - underline = true, - -- Enable virtual text, override spacing to 4 - virtual_text = { - spacing = 4, - }, - -- Use a function to dynamically turn signs off - -- and on, using buffer local variables - signs = function(namespace, bufnr) - return vim.b[bufnr].show_signs == true - end, - -- Disable a feature - update_in_insert = false, - } - ) -< + See |vim.diagnostic.config()| for configuration options. Parameters: ~ • {result} (`lsp.DocumentDiagnosticReport`) • {ctx} (`lsp.HandlerContext`) - • {config} (`vim.diagnostic.Opts`) Configuration table (see - |vim.diagnostic.config()|). *vim.lsp.diagnostic.on_publish_diagnostics()* -on_publish_diagnostics({_}, {result}, {ctx}, {config}) +on_publish_diagnostics({_}, {result}, {ctx}) |lsp-handler| for the method "textDocument/publishDiagnostics" - See |vim.diagnostic.config()| for configuration options. Handler-specific - configuration can be set using |vim.lsp.with()|: >lua - vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with( - vim.lsp.diagnostic.on_publish_diagnostics, { - -- Enable underline, use default values - underline = true, - -- Enable virtual text, override spacing to 4 - virtual_text = { - spacing = 4, - }, - -- Use a function to dynamically turn signs off - -- and on, using buffer local variables - signs = function(namespace, bufnr) - return vim.b[bufnr].show_signs == true - end, - -- Disable a feature - update_in_insert = false, - } - ) -< + See |vim.diagnostic.config()| for configuration options. Parameters: ~ • {result} (`lsp.PublishDiagnosticsParams`) • {ctx} (`lsp.HandlerContext`) - • {config} (`vim.diagnostic.Opts?`) Configuration table (see - |vim.diagnostic.config()|). ============================================================================== @@ -1638,8 +1550,9 @@ Lua module: vim.lsp.completion *lsp-completion* *vim.lsp.completion.BufferOpts* Fields: ~ - • {autotrigger}? (`boolean`) Whether to trigger completion - automatically. Default: false + • {autotrigger}? (`boolean`) Default: false When true, completion + triggers automatically based on the server's + `triggerCharacters`. • {convert}? (`fun(item: lsp.CompletionItem): table`) Transforms an LSP CompletionItem to |complete-items|. @@ -1778,8 +1691,8 @@ highlight_token({token}, {bufnr}, {client_id}, {hl_group}, {opts}) • {hl_group} (`string`) Highlight group name • {opts} (`table?`) Optional parameters: • {priority}? (`integer`, default: - `vim.highlight.priorities.semantic_tokens + 3`) - Priority for the applied extmark. + `vim.hl.priorities.semantic_tokens + 3`) Priority for + the applied extmark. start({bufnr}, {client_id}, {opts}) *vim.lsp.semantic_tokens.start()* Start the semantic token highlighting engine for the given buffer with the @@ -1816,54 +1729,44 @@ stop({bufnr}, {client_id}) *vim.lsp.semantic_tokens.stop()* ============================================================================== -Lua module: vim.lsp.handlers *lsp-handlers* - -hover({_}, {result}, {ctx}, {config}) *vim.lsp.handlers.hover()* - |lsp-handler| for the method "textDocument/hover" >lua - vim.lsp.handlers["textDocument/hover"] = vim.lsp.with( - vim.lsp.handlers.hover, { - -- Use a sharp border with `FloatBorder` highlights - border = "single", - -- add the title in hover float window - title = "hover" - } - ) -< - - Parameters: ~ - • {result} (`lsp.Hover`) - • {ctx} (`lsp.HandlerContext`) - • {config} (`table`) Configuration table. - • border: (default=nil) - • Add borders to the floating window - • See |vim.lsp.util.open_floating_preview()| for more - options. - - *vim.lsp.handlers.signature_help()* -signature_help({_}, {result}, {ctx}, {config}) - |lsp-handler| for the method "textDocument/signatureHelp". - - The active parameter is highlighted with |hl-LspSignatureActiveParameter|. >lua - vim.lsp.handlers["textDocument/signatureHelp"] = vim.lsp.with( - vim.lsp.handlers.signature_help, { - -- Use a sharp border with `FloatBorder` highlights - border = "single" - } - ) -< +Lua module: vim.lsp.util *lsp-util* - Parameters: ~ - • {result} (`lsp.SignatureHelp`) Response from the language server - • {ctx} (`lsp.HandlerContext`) Client context - • {config} (`table`) Configuration table. - • border: (default=nil) - • Add borders to the floating window - • See |vim.lsp.util.open_floating_preview()| for more - options +*vim.lsp.util.open_floating_preview.Opts* + Fields: ~ + • {height}? (`integer`) Height of floating window + • {width}? (`integer`) Width of floating window + • {wrap}? (`boolean`, default: `true`) Wrap long lines + • {wrap_at}? (`integer`) Character to wrap at for computing height + when wrap is enabled + • {max_width}? (`integer`) Maximal width of floating window + • {max_height}? (`integer`) Maximal height of floating window + • {focus_id}? (`string`) If a popup with this id is opened, then + focus it + • {close_events}? (`table`) List of events that closes the floating + window + • {focusable}? (`boolean`, default: `true`) Make float focusable. + • {focus}? (`boolean`, default: `true`) If `true`, and if + {focusable} is also `true`, focus an existing + floating window with the same {focus_id} + • {offset_x}? (`integer`) offset to add to `col` + • {offset_y}? (`integer`) offset to add to `row` + • {border}? (`string|(string|[string,string])[]`) override + `border` + • {zindex}? (`integer`) override `zindex`, defaults to 50 + • {title}? (`string`) + • {title_pos}? (`'left'|'center'|'right'`) + • {relative}? (`'mouse'|'cursor'`) (default: `'cursor'`) + • {anchor_bias}? (`'auto'|'above'|'below'`, default: `'auto'`) - + "auto": place window based on which side of the + cursor has more lines + • "above": place the window above the cursor unless + there are not enough lines to display the full + window height. + • "below": place the window below the cursor unless + there are not enough lines to display the full + window height. -============================================================================== -Lua module: vim.lsp.util *lsp-util* *vim.lsp.util.apply_text_document_edit()* apply_text_document_edit({text_document_edit}, {index}, {offset_encoding}) @@ -1874,7 +1777,7 @@ apply_text_document_edit({text_document_edit}, {index}, {offset_encoding}) • {text_document_edit} (`lsp.TextDocumentEdit`) • {index} (`integer?`) Optional index of the edit, if from a list of edits (or nil, if not from a list) - • {offset_encoding} (`string?`) + • {offset_encoding} (`'utf-8'|'utf-16'|'utf-32'?`) See also: ~ • https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentEdit @@ -1886,7 +1789,7 @@ apply_text_edits({text_edits}, {bufnr}, {offset_encoding}) Parameters: ~ • {text_edits} (`lsp.TextEdit[]`) • {bufnr} (`integer`) Buffer id - • {offset_encoding} (`string`) utf-8|utf-16|utf-32 + • {offset_encoding} (`'utf-8'|'utf-16'|'utf-32'`) See also: ~ • https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textEdit @@ -1897,7 +1800,7 @@ apply_workspace_edit({workspace_edit}, {offset_encoding}) Parameters: ~ • {workspace_edit} (`lsp.WorkspaceEdit`) - • {offset_encoding} (`string`) utf-8|utf-16|utf-32 (required) + • {offset_encoding} (`'utf-8'|'utf-16'|'utf-32'`) (required) See also: ~ • https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit @@ -1915,7 +1818,7 @@ buf_highlight_references({bufnr}, {references}, {offset_encoding}) Parameters: ~ • {bufnr} (`integer`) Buffer id • {references} (`lsp.DocumentHighlight[]`) objects to highlight - • {offset_encoding} (`string`) One of "utf-8", "utf-16", "utf-32". + • {offset_encoding} (`'utf-8'|'utf-16'|'utf-32'`) See also: ~ • https://microsoft.github.io/language-server-protocol/specification/#textDocumentContentChangeEvent @@ -1928,7 +1831,7 @@ character_offset({buf}, {row}, {col}, {offset_encoding}) • {buf} (`integer`) buffer number (0 for current) • {row} (`integer`) 0-indexed line • {col} (`integer`) 0-indexed byte offset in line - • {offset_encoding} (`string`) utf-8|utf-16|utf-32 defaults to + • {offset_encoding} (`'utf-8'|'utf-16'|'utf-32'?`) defaults to `offset_encoding` of first client of `buf` Return: ~ @@ -1966,12 +1869,13 @@ convert_signature_help_to_markdown_lines({signature_help}, {ft}, {triggers}) `textDocument/SignatureHelp` • {ft} (`string?`) filetype that will be use as the `lang` for the label markdown code block - • {triggers} (`table?`) list of trigger characters from the lsp - server. used to better determine parameter offsets + • {triggers} (`string[]?`) list of trigger characters from the + lsp server. used to better determine parameter + offsets Return (multiple): ~ - (`string[]?`) table list of lines of converted markdown. - (`number[]?`) table of active hl + (`string[]?`) lines of converted markdown. + (`Range4?`) highlight range for the active parameter See also: ~ • https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_signatureHelp @@ -1988,19 +1892,6 @@ get_effective_tabstop({bufnr}) *vim.lsp.util.get_effective_tabstop()* See also: ~ • 'shiftwidth' - *vim.lsp.util.jump_to_location()* -jump_to_location({location}, {offset_encoding}, {reuse_win}) - Jumps to a location. - - Parameters: ~ - • {location} (`lsp.Location|lsp.LocationLink`) - • {offset_encoding} (`string?`) utf-8|utf-16|utf-32 - • {reuse_win} (`boolean?`) Jump to existing window if buffer is - already open. - - Return: ~ - (`boolean`) `true` if the jump succeeded - *vim.lsp.util.locations_to_items()* locations_to_items({locations}, {offset_encoding}) Returns the items with the byte position calculated correctly and in @@ -2014,19 +1905,11 @@ locations_to_items({locations}, {offset_encoding}) Parameters: ~ • {locations} (`lsp.Location[]|lsp.LocationLink[]`) - • {offset_encoding} (`string`) offset_encoding for locations - utf-8|utf-16|utf-32 default to first client of - buffer + • {offset_encoding} (`'utf-8'|'utf-16'|'utf-32'?`) default to first + client of buffer Return: ~ - (`table[]`) A list of objects with the following fields: - • {filename} (`string`) - • {lnum} (`integer`) 1-indexed line number - • {end_lnum} (`integer`) 1-indexed end line number - • {col} (`integer`) 1-indexed column - • {end_col} (`integer`) 1-indexed end column - • {text} (`string`) - • {user_data} (`lsp.Location|lsp.LocationLink`) + (`vim.quickfix.entry[]`) See |setqflist()| for the format *vim.lsp.util.make_floating_popup_options()* make_floating_popup_options({width}, {height}, {opts}) @@ -2036,23 +1919,11 @@ make_floating_popup_options({width}, {height}, {opts}) Parameters: ~ • {width} (`integer`) window width (in character cells) • {height} (`integer`) window height (in character cells) - • {opts} (`table`) optional - • offset_x (integer) offset to add to `col` - • offset_y (integer) offset to add to `row` - • border (string or table) override `border` - • focusable (string or table) override `focusable` - • zindex (string or table) override `zindex`, defaults to 50 - • relative ("mouse"|"cursor") defaults to "cursor" - • anchor_bias ("auto"|"above"|"below") defaults to "auto" - • "auto": place window based on which side of the cursor - has more lines - • "above": place the window above the cursor unless there - are not enough lines to display the full window height. - • "below": place the window below the cursor unless there - are not enough lines to display the full window height. + • {opts} (`vim.lsp.util.open_floating_preview.Opts?`) See + |vim.lsp.util.open_floating_preview.Opts|. Return: ~ - (`table`) Options + (`vim.api.keyset.win_config`) *vim.lsp.util.make_formatting_params()* make_formatting_params({options}) @@ -2075,13 +1946,15 @@ make_given_range_params({start_pos}, {end_pos}, {bufnr}, {offset_encoding}) similar to |vim.lsp.util.make_range_params()|. Parameters: ~ - • {start_pos} (`integer[]?`) {row,col} mark-indexed position. - Defaults to the start of the last visual selection. - • {end_pos} (`integer[]?`) {row,col} mark-indexed position. - Defaults to the end of the last visual selection. + • {start_pos} (`[integer,integer]?`) {row,col} mark-indexed + position. Defaults to the start of the last visual + selection. + • {end_pos} (`[integer,integer]?`) {row,col} mark-indexed + position. Defaults to the end of the last visual + selection. • {bufnr} (`integer?`) buffer handle or 0 for current, defaults to current - • {offset_encoding} (`"utf-8"|"utf-16"|"utf-32"?`) defaults to + • {offset_encoding} (`'utf-8'|'utf-16'|'utf-32'?`) defaults to `offset_encoding` of first client of `bufnr` Return: ~ @@ -2096,7 +1969,7 @@ make_position_params({window}, {offset_encoding}) Parameters: ~ • {window} (`integer?`) window handle or 0 for current, defaults to current - • {offset_encoding} (`string?`) utf-8|utf-16|utf-32|nil defaults to + • {offset_encoding} (`'utf-8'|'utf-16'|'utf-32'?`) defaults to `offset_encoding` of first client of buffer of `window` @@ -2155,27 +2028,11 @@ open_floating_preview({contents}, {syntax}, {opts}) Parameters: ~ • {contents} (`table`) of lines to show in window • {syntax} (`string`) of syntax to set for opened buffer - • {opts} (`table?`) with optional fields (additional keys are - filtered with |vim.lsp.util.make_floating_popup_options()| - before they are passed on to |nvim_open_win()|) - • {height}? (`integer`) Height of floating window - • {width}? (`integer`) Width of floating window - • {wrap}? (`boolean`, default: `true`) Wrap long lines - • {wrap_at}? (`integer`) Character to wrap at for - computing height when wrap is enabled - • {max_width}? (`integer`) Maximal width of floating - window - • {max_height}? (`integer`) Maximal height of floating - window - • {focus_id}? (`string`) If a popup with this id is - opened, then focus it - • {close_events}? (`table`) List of events that closes the - floating window - • {focusable}? (`boolean`, default: `true`) Make float - focusable. - • {focus}? (`boolean`, default: `true`) If `true`, and if - {focusable} is also `true`, focus an existing floating - window with the same {focus_id} + • {opts} (`vim.lsp.util.open_floating_preview.Opts?`) with optional + fields (additional keys are filtered with + |vim.lsp.util.make_floating_popup_options()| before they + are passed on to |nvim_open_win()|). See + |vim.lsp.util.open_floating_preview.Opts|. Return (multiple): ~ (`integer`) bufnr of newly created float window @@ -2191,7 +2048,8 @@ preview_location({location}, {opts}) *vim.lsp.util.preview_location()* Parameters: ~ • {location} (`lsp.Location|lsp.LocationLink`) - • {opts} (`table`) + • {opts} (`vim.lsp.util.open_floating_preview.Opts?`) See + |vim.lsp.util.open_floating_preview.Opts|. Return (multiple): ~ (`integer?`) buffer id of float window @@ -2221,12 +2079,12 @@ show_document({location}, {offset_encoding}, {opts}) Parameters: ~ • {location} (`lsp.Location|lsp.LocationLink`) - • {offset_encoding} (`string?`) utf-8|utf-16|utf-32 - • {opts} (`table?`) options - • reuse_win (boolean) Jump to existing window if - buffer is already open. - • focus (boolean) Whether to focus/jump to location - if possible. Defaults to true. + • {offset_encoding} (`'utf-8'|'utf-16'|'utf-32'?`) + • {opts} (`table?`) A table with the following fields: + • {reuse_win}? (`boolean`) Jump to existing window + if buffer is already open. + • {focus}? (`boolean`) Whether to focus/jump to + location if possible. (defaults: true) Return: ~ (`boolean`) `true` if succeeded @@ -2246,7 +2104,7 @@ stylize_markdown({bufnr}, {contents}, {opts}) Parameters: ~ • {bufnr} (`integer`) • {contents} (`string[]`) of lines to show in window - • {opts} (`table`) with optional fields + • {opts} (`table?`) with optional fields • height of floating window • width of floating window • wrap_at character to wrap at for computing height @@ -2261,9 +2119,12 @@ symbols_to_items({symbols}, {bufnr}) *vim.lsp.util.symbols_to_items()* Converts symbols to quickfix list items. Parameters: ~ - • {symbols} (`table`) DocumentSymbol[] or SymbolInformation[] + • {symbols} (`lsp.DocumentSymbol[]|lsp.SymbolInformation[]`) • {bufnr} (`integer?`) + Return: ~ + (`vim.quickfix.entry[]`) See |setqflist()| for the format + ============================================================================== Lua module: vim.lsp.log *lsp-log* @@ -2300,7 +2161,7 @@ should_log({level}) *vim.lsp.log.should_log()* • {level} (`integer`) log level Return: ~ - (`bool`) true if would log, false if not + (`boolean`) true if would log, false if not ============================================================================== diff --git a/runtime/doc/lua-guide.txt b/runtime/doc/lua-guide.txt index 5f06d51f42..b40d5a0791 100644 --- a/runtime/doc/lua-guide.txt +++ b/runtime/doc/lua-guide.txt @@ -552,7 +552,7 @@ This means that if your callback itself takes an (even optional) argument, you must wrap it in `function() end` to avoid an error: >lua vim.api.nvim_create_autocmd('TextYankPost', { - callback = function() vim.highlight.on_yank() end + callback = function() vim.hl.on_yank() end }) < (Since unused arguments can be omitted in Lua function definitions, this is @@ -576,7 +576,7 @@ Instead of using a pattern, you can create a buffer-local autocommand (see Similarly to mappings, you can (and should) add a description using `desc`: >lua vim.api.nvim_create_autocmd('TextYankPost', { - callback = function() vim.highlight.on_yank() end, + callback = function() vim.hl.on_yank() end, desc = "Briefly highlight yanked text" }) < diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index 396f24a1aa..243c907180 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -636,13 +636,13 @@ A subset of the `vim.*` API is available in threads. This includes: ============================================================================== -VIM.HIGHLIGHT *vim.highlight* +VIM.HL *vim.hl* -vim.highlight.on_yank({opts}) *vim.highlight.on_yank()* +vim.hl.on_yank({opts}) *vim.hl.on_yank()* Highlight the yanked text during a |TextYankPost| event. Add the following to your `init.vim`: >vim - autocmd TextYankPost * silent! lua vim.highlight.on_yank {higroup='Visual', timeout=300} + autocmd TextYankPost * silent! lua vim.hl.on_yank {higroup='Visual', timeout=300} < Parameters: ~ @@ -655,9 +655,9 @@ vim.highlight.on_yank({opts}) *vim.highlight.on_yank()* true) • event event structure (default vim.v.event) • priority integer priority (default - |vim.highlight.priorities|`.user`) + |vim.hl.priorities|`.user`) -vim.highlight.priorities *vim.highlight.priorities* +vim.hl.priorities *vim.hl.priorities* Table with default priorities used for highlighting: • `syntax`: `50`, used for standard syntax highlighting • `treesitter`: `100`, used for treesitter-based highlighting @@ -666,8 +666,8 @@ vim.highlight.priorities *vim.highlight.priorities* • `user`: `200`, used for user-triggered highlights such as LSP document symbols or `on_yank` autocommands - *vim.highlight.range()* -vim.highlight.range({bufnr}, {ns}, {higroup}, {start}, {finish}, {opts}) + *vim.hl.range()* +vim.hl.range({bufnr}, {ns}, {higroup}, {start}, {finish}, {opts}) Apply highlight group to range of text. Parameters: ~ @@ -684,8 +684,7 @@ vim.highlight.range({bufnr}, {ns}, {higroup}, {start}, {finish}, {opts}) • {inclusive}? (`boolean`, default: `false`) Indicates whether the range is end-inclusive • {priority}? (`integer`, default: - `vim.highlight.priorities.user`) Indicates priority of - highlight + `vim.hl.priorities.user`) Highlight priority ============================================================================== @@ -1001,22 +1000,6 @@ vim.schedule({fn}) *vim.schedule()* Parameters: ~ • {fn} (`fun()`) -vim.str_byteindex({str}, {index}, {use_utf16}) *vim.str_byteindex()* - Convert UTF-32 or UTF-16 {index} to byte index. If {use_utf16} is not - supplied, it defaults to false (use UTF-32). Returns the byte index. - - Invalid UTF-8 and NUL is treated like in |vim.str_utfindex()|. An {index} - in the middle of a UTF-16 sequence is rounded upwards to the end of that - sequence. - - Parameters: ~ - • {str} (`string`) - • {index} (`integer`) - • {use_utf16} (`boolean?`) - - Return: ~ - (`integer`) - vim.str_utf_end({str}, {index}) *vim.str_utf_end()* Gets the distance (in bytes) from the last byte of the codepoint (character) that {index} points to. @@ -1074,23 +1057,6 @@ vim.str_utf_start({str}, {index}) *vim.str_utf_start()* Return: ~ (`integer`) -vim.str_utfindex({str}, {index}) *vim.str_utfindex()* - Convert byte index to UTF-32 and UTF-16 indices. If {index} is not - supplied, the length of the string is used. All indices are zero-based. - - Embedded NUL bytes are treated as terminating the string. Invalid UTF-8 - bytes, and embedded surrogates are counted as one code point each. An - {index} in the middle of a UTF-8 sequence is rounded upwards to the end of - that sequence. - - Parameters: ~ - • {str} (`string`) - • {index} (`integer?`) - - Return (multiple): ~ - (`integer`) UTF-32 index - (`integer`) UTF-16 index - vim.stricmp({a}, {b}) *vim.stricmp()* Compares strings case-insensitively. @@ -1117,6 +1083,12 @@ vim.ui_attach({ns}, {options}, {callback}) *vim.ui_attach()* |ui-popupmenu| and the sections below for event format for respective events. + Callbacks for `msg_show` events are executed in |api-fast| context unless + Nvim will wait for input, in which case messages should be shown + immediately. + + Excessive errors inside the callback will result in forced detachment. + WARNING: This api is considered experimental. Usability will vary for different screen elements. In particular `ext_messages` behavior is subject to further changes and usability improvements. This is expected to @@ -1464,12 +1436,9 @@ Option:remove({value}) *vim.opt:remove()* • {value} (`string`) Value to remove vim.bo[{bufnr}] *vim.bo* - Get or set buffer-scoped |options| for the buffer with number {bufnr}. If - {bufnr} is omitted then the current buffer is used. Invalid {bufnr} or key - is an error. - - Note: this is equivalent to `:setlocal` for |global-local| options and - `:set` otherwise. + Get or set buffer-scoped |options| for the buffer with number {bufnr}. + Like `:setlocal`. If {bufnr} is omitted then the current buffer is used. + Invalid {bufnr} or key is an error. Example: >lua local bufnr = vim.api.nvim_get_current_buf() @@ -1672,7 +1641,7 @@ vim.notify_once({msg}, {level}, {opts}) *vim.notify_once()* Return: ~ (`boolean`) true if message was displayed, else false -vim.on_key({fn}, {ns_id}) *vim.on_key()* +vim.on_key({fn}, {ns_id}, {opts}) *vim.on_key()* Adds Lua function {fn} with namespace id {ns_id} as a listener to every, yes every, input key. @@ -1681,22 +1650,32 @@ vim.on_key({fn}, {ns_id}) *vim.on_key()* Note: ~ • {fn} will be removed on error. + • {fn} won't be invoked recursively, i.e. if {fn} itself consumes input, + it won't be invoked for those keys. • {fn} will not be cleared by |nvim_buf_clear_namespace()| Parameters: ~ - • {fn} (`fun(key: string, typed: string)?`) Function invoked on - every key press. |i_CTRL-V| {key} is the key after mappings - have been applied, and {typed} is the key(s) before mappings - are applied, which may be empty if {key} is produced by - non-typed keys. When {fn} is nil and {ns_id} is specified, - the callback associated with namespace {ns_id} is removed. + • {fn} (`fun(key: string, typed: string): string??`) Function + invoked for every input key, after mappings have been applied + but before further processing. Arguments {key} and {typed} + are raw keycodes, where {key} is the key after mappings are + applied, and {typed} is the key(s) before mappings are + applied. {typed} may be empty if {key} is produced by + non-typed key(s) or by the same typed key(s) that produced a + previous {key}. If {fn} returns an empty string, {key} is + discarded/ignored. When {fn} is `nil`, the callback + associated with namespace {ns_id} is removed. • {ns_id} (`integer?`) Namespace ID. If nil or 0, generates and returns a new |nvim_create_namespace()| id. + • {opts} (`table?`) Optional parameters Return: ~ (`integer`) Namespace id associated with {fn}. Or count of all callbacks if on_key() is called without arguments. + See also: ~ + • |keytrans()| + vim.paste({lines}, {phase}) *vim.paste()* Paste handler, invoked by |nvim_paste()|. @@ -1772,6 +1751,44 @@ vim.schedule_wrap({fn}) *vim.schedule_wrap()* • |vim.schedule()| • |vim.in_fast_event()| + *vim.str_byteindex()* +vim.str_byteindex({s}, {encoding}, {index}, {strict_indexing}) + Convert UTF-32, UTF-16 or UTF-8 {index} to byte index. If + {strict_indexing} is false then then an out of range index will return + byte length instead of throwing an error. + + Invalid UTF-8 and NUL is treated like in |vim.str_utfindex()|. An {index} + in the middle of a UTF-16 sequence is rounded upwards to the end of that + sequence. + + Parameters: ~ + • {s} (`string`) + • {encoding} (`"utf-8"|"utf-16"|"utf-32"`) + • {index} (`integer`) + • {strict_indexing} (`boolean?`) default: true + + Return: ~ + (`integer`) + + *vim.str_utfindex()* +vim.str_utfindex({s}, {encoding}, {index}, {strict_indexing}) + Convert byte index to UTF-32, UTF-16 or UTF-8 indices. If {index} is not + supplied, the length of the string is used. All indices are zero-based. + + If {strict_indexing} is false then an out of range index will return + string length instead of throwing an error. Invalid UTF-8 bytes, and + embedded surrogates are counted as one code point each. An {index} in the + middle of a UTF-8 sequence is rounded upwards to the end of that sequence. + + Parameters: ~ + • {s} (`string`) + • {encoding} (`"utf-8"|"utf-16"|"utf-32"`) + • {index} (`integer?`) + • {strict_indexing} (`boolean?`) default: true + + Return: ~ + (`integer`) + vim.system({cmd}, {opts}, {on_exit}) *vim.system()* Runs a system command or throws an error if {cmd} cannot be run. @@ -2394,31 +2411,29 @@ vim.trim({s}) *vim.trim()* • |lua-patterns| • https://www.lua.org/pil/20.2.html -vim.validate({opt}) *vim.validate()* + *vim.validate()* +vim.validate({name}, {value}, {validator}, {optional}, {message}) Validate function arguments. This function has two valid forms: - 1. vim.validate(name: str, value: any, type: string, optional?: bool) - 2. vim.validate(spec: table) - - Form 1 validates that argument {name} with value {value} has the type - {type}. {type} must be a value returned by |lua-type()|. If {optional} is - true, then {value} may be null. This form is significantly faster and - should be preferred for simple cases. - - Example: >lua - function vim.startswith(s, prefix) + 1. `vim.validate(name, value, validator[, optional][, message])` + Validates that argument {name} with value {value} satisfies + {validator}. If {optional} is given and is `true`, then {value} may be + `nil`. If {message} is given, then it is used as the expected type in + the error message. + Example: >lua + function vim.startswith(s, prefix) vim.validate('s', s, 'string') vim.validate('prefix', prefix, 'string') ... end < - - Form 2 validates a parameter specification (types and values). Specs are - evaluated in alphanumeric order, until the first failure. - - Usage example: >lua - function user.new(name, age, hobbies) + 2. `vim.validate(spec)` (deprecated) where `spec` is of type + `table<string,[value:any, validator: vim.validate.Validator, optional_or_msg? : boolean|string]>)` + Validates a argument specification. Specs are evaluated in alphanumeric + order, until the first failure. + Example: >lua + function user.new(name, age, hobbies) vim.validate{ name={name, 'string'}, age={age, 'number'}, @@ -2429,40 +2444,44 @@ vim.validate({opt}) *vim.validate()* < Examples with explicit argument values (can be run directly): >lua - vim.validate{arg1={{'foo'}, 'table'}, arg2={'foo', 'string'}} + vim.validate('arg1', {'foo'}, 'table') + --> NOP (success) + vim.validate('arg2', 'foo', 'string') --> NOP (success) - vim.validate{arg1={1, 'table'}} + vim.validate('arg1', 1, 'table') --> error('arg1: expected table, got number') - vim.validate{arg1={3, function(a) return (a % 2) == 0 end, 'even number'}} + vim.validate('arg1', 3, function(a) return (a % 2) == 0 end, 'even number') --> error('arg1: expected even number, got 3') < If multiple types are valid they can be given as a list. >lua - vim.validate{arg1={{'foo'}, {'table', 'string'}}, arg2={'foo', {'table', 'string'}}} + vim.validate('arg1', {'foo'}, {'table', 'string'}) + vim.validate('arg2', 'foo', {'table', 'string'}) -- NOP (success) - vim.validate{arg1={1, {'string', 'table'}}} + vim.validate('arg1', 1, {'string', 'table'}) -- error('arg1: expected string|table, got number') < + Note: ~ + • `validator` set to a value returned by |lua-type()| provides the best + performance. + Parameters: ~ - • {opt} (`table`) Names of parameters to validate. Each key is a - parameter name; each value is a tuple in one of these forms: - 1. (arg_value, type_name, optional) - • arg_value: argument value - • type_name: string|table type name, one of: ("table", "t", - "string", "s", "number", "n", "boolean", "b", "function", - "f", "nil", "thread", "userdata") or list of them. - • optional: (optional) boolean, if true, `nil` is valid - 2. (arg_value, fn, msg) - • arg_value: argument value - • fn: any function accepting one argument, returns true if - and only if the argument is valid. Can optionally return - an additional informative error message as the second - returned value. - • msg: (optional) error string if validation fails + • {name} (`string`) Argument name + • {value} (`string`) Argument value + • {validator} (`vim.validate.Validator`) + • (`string|string[]`): Any value that can be returned + from |lua-type()| in addition to `'callable'`: + `'boolean'`, `'callable'`, `'function'`, `'nil'`, + `'number'`, `'string'`, `'table'`, `'thread'`, + `'userdata'`. + • (`fun(val:any): boolean, string?`) A function that + returns a boolean and an optional string message. + • {optional} (`boolean?`) Argument is optional (may be omitted) + • {message} (`string?`) message when validation fails ============================================================================== @@ -2508,8 +2527,8 @@ vim.loader.find({modname}, {opts}) *vim.loader.find()* (`table[]`) A list of objects with the following fields: • {modpath} (`string`) Path of the module • {modname} (`string`) Name of the module - • {stat}? (`uv.uv_fs_t`) The fs_stat of the module path. Won't be - returned for `modname="*"` + • {stat}? (`uv.fs_stat.result`) The fs_stat of the module path. Won't + be returned for `modname="*"` vim.loader.reset({path}) *vim.loader.reset()* WARNING: This feature is experimental/unstable. @@ -2671,7 +2690,7 @@ vim.ui.select({items}, {opts}, {on_choice}) *vim.ui.select()* item shape. Plugins reimplementing `vim.ui.select` may wish to use this to infer the structure or semantics of `items`, or the context in which select() was called. - • {on_choice} (`fun(item: any?, idx: integer?)`) Called once the user + • {on_choice} (`fun(item: T?, idx: integer?)`) Called once the user made a choice. `idx` is the 1-based index of `item` within `items`. `nil` if the user aborted the dialog. diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index 7fd1f3bfbb..11048aee30 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -66,6 +66,8 @@ modes. where the map command applies. Disallow mapping of {rhs}, to avoid nested and recursive mappings. Often used to redefine a command. + Note: Keys in {rhs} also won't trigger abbreviation, + with the exception of |i_CTRL-]| and |c_CTRL-]|. Note: When <Plug> appears in the {rhs} this part is always applied even if remapping is disallowed. @@ -1411,6 +1413,8 @@ completion can be enabled: -complete=runtime file and directory names in |'runtimepath'| -complete=scriptnames sourced script names -complete=shellcmd Shell command + -complete=shellcmdline First is a shell command and subsequent ones + are filenames. The same behavior as |:!cmd| -complete=sign |:sign| suboptions -complete=syntax syntax file names |'syntax'| -complete=syntime |:syntime| suboptions diff --git a/runtime/doc/news-0.10.txt b/runtime/doc/news-0.10.txt index a5ded1ca22..35af570ec3 100644 --- a/runtime/doc/news-0.10.txt +++ b/runtime/doc/news-0.10.txt @@ -246,7 +246,7 @@ The following new features were added. indicator to see if a server supports a feature. Instead use `client.supports_method(<method>)`. It considers both the dynamic capabilities and static `server_capabilities`. - • `anchor_bias` option to |lsp-handlers| aids in positioning of floating + • `anchor_bias` option to lsp-handlers aids in positioning of floating windows. • |vim.lsp.util.locations_to_items()| sets the `user_data` of each item to the original LSP `Location` or `LocationLink`. diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index ed5bd973be..d19df84023 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -40,6 +40,8 @@ API This is not expected to break clients because there are no known clients that actually use the `return_type` field or the parameter type names reported by |--api-info| or |nvim_get_api_info()|. +• |nvim_open_win()| supports a `mouse` field that allows configuring mouse + interaction with the window separately from `focusable` field. • Renamed `nvim__id_dictionary` (unsupported/experimental API) to `nvim__id_dict`. @@ -53,6 +55,8 @@ DIAGNOSTICS • |vim.diagnostic.config()| accepts a "jump" table to specify defaults for |vim.diagnostic.jump()|. +• The "underline" diagnostics handler sorts diagnostics by severity when using + the "severity_sort" option. EDITOR @@ -63,10 +67,13 @@ EDITOR • Moving in the buffer list using |:bnext| and similar commands behaves as documented and skips help buffers if run from a non-help buffer, otherwise it moves to another help buffer. +• Bells from a |terminal| buffer are now silent by default, unless 'belloff' + option doesn't contain "term" or "all". EVENTS -• TODO +• |vim.ui_attach()| callbacks for |ui-messages| `msg_show` events are executed in + |api-fast| context. LSP @@ -75,6 +82,19 @@ LSP customizing the transformation of an LSP CompletionItem to |complete-items|. • |vim.lsp.diagnostic.from()| can be used to convert a list of |vim.Diagnostic| objects into their LSP diagnostic representation. +• |vim.lsp.buf.references()|, |vim.lsp.buf.declaration()|, |vim.lsp.buf.definition()|, + |vim.lsp.buf.type_definition()|, |vim.lsp.buf.implementation()| and + |vim.lsp.buf.hover()| now support merging the results of multiple clients + but no longer trigger the global handlers from `vim.lsp.handlers` +• |vim.lsp.buf.typehierarchy()| now passes the correct params for each + client request. +• |vim.lsp.handlers.signature_help()| is no longer used. +• |vim.lsp.diagnostic.on_publish_diagnostics()| and + |vim.lsp.diagnostic.on_diagnostic()| no longer accept a config parameter and + can no longer be configured with |vim.lsp.with()|. + Instead use: >lua + vim.diagnostic.config(config, vim.lsp.diagnostic.get_namespace(client_id)) +< LUA @@ -90,6 +110,12 @@ OPTIONS changes according to related options. It takes care of alignment, 'number', 'relativenumber' and 'signcolumn' set to "number". The now redundant `%r` item is no longer treated specially for 'statuscolumn'. +• `:set {option}<` removes the local value for all |global-local| options instead + of just string |global-local| options. +• `:setlocal {option}<` copies the global value to the local value for number + and boolean |global-local| options instead of removing the local value. +• Setting |hidden-options| now gives an error. In particular, setting + 'noshellslash' is now only allowed on Windows. PLUGINS @@ -108,6 +134,9 @@ TREESITTER if no languages are explicitly registered. • |vim.treesitter.language.add()| returns `true` if a parser was loaded successfully and `nil,errmsg` otherwise instead of throwing an error. +• New |TSNode:child_with_descendant()|, which is nearly identical to + |TSNode:child_containing_descendant()| except that it can return the + descendant itself. TUI @@ -136,8 +165,10 @@ DEFAULTS • Mappings: • |grn| in Normal mode maps to |vim.lsp.buf.rename()| • |grr| in Normal mode maps to |vim.lsp.buf.references()| + • |gri| in Normal mode maps to |vim.lsp.buf.implementation()| + • |gO| in Normal mode maps to |vim.lsp.buf.document_symbol()| • |gra| in Normal and Visual mode maps to |vim.lsp.buf.code_action()| - • CTRL-S in Insert mode maps to |vim.lsp.buf.signature_help()| + • CTRL-S in Insert and Select mode maps to |vim.lsp.buf.signature_help()| • Mouse |popup-menu| includes an "Open in web browser" item when you right-click on a URL. • Mouse |popup-menu| includes a "Go to definition" item when LSP is active @@ -148,6 +179,7 @@ DEFAULTS • |[t|, |]t|, |[T|, |]T|, |[CTRL-T|, |]CTRL-T| navigate through the |tag-matchlist| • |[a|, |]a|, |[A|, |]A| navigate through the |argument-list| • |[b|, |]b|, |[B|, |]B| navigate through the |buffer-list| + • |[<Space>|, |]<Space>| add an empty line above and below the cursor • Snippet: • `<Tab>` in Insert and Select mode maps to `vim.snippet.jump({ direction = 1 })` @@ -169,6 +201,7 @@ EVENTS • |CompleteDone| now sets the `reason` key in `v:event` which specifies the reason for completion being done. +• |vim.on_key()| callbacks can consume the key by returning an empty string. LSP @@ -178,14 +211,26 @@ LSP • |vim.lsp.buf.format()| now supports passing a list of ranges via the `range` parameter (this requires support for the `textDocument/rangesFormatting` request). +• |vim.lsp.buf.code_action()| actions show client name when there are multiple + clients. +• |vim.lsp.buf.signature_help()| can now cycle through different signatures + using `<C-s>` and also support multiple clients. +• The client now supports `'utf-8'` and `'utf-32'` position encodings. +• |vim.lsp.buf.hover()| now highlights hover ranges using the + |hl-LspReferenceTarget| highlight group. LUA • |vim.fs.rm()| can delete files and directories. +• |vim.validate()| now has a new signature which uses less tables, + is more peformant and easier to read. +• |vim.str_byteindex()| and |vim.str_utfindex()| gained overload signatures + supporting two new parameters, `encoding` and `strict_indexing`. OPTIONS • 'completeopt' flag "fuzzy" enables |fuzzy-matching| during |ins-completion|. +• 'msghistory' controls maximum number of messages to remember. • 'tabclose' controls which tab page to focus when closing a tab page. PERFORMANCE @@ -234,6 +279,16 @@ UI which controls the tool used to open the given path or URL. If you want to globally set this, you can override vim.ui.open using the same approach described at |vim.paste()|. +- `vim.ui.open()` now supports + [lemonade](https://github.com/lemonade-command/lemonade) as an option for + opening urls/files. This is handy if you are in an ssh connection and use + `lemonade`. +• The |ins-completion-menu| now supports cascading highlight styles. + |hl-PmenuSel| and |hl-PmenuMatch| both inherit from |hl-Pmenu|, and + |hl-PmenuMatchSel| inherits highlights from both |hl-PmenuSel| and + |hl-PmenuMatch|. + +• |ui-messages| content chunks now also contain the highlight group ID. ============================================================================== CHANGED FEATURES *news-changed* @@ -254,6 +309,17 @@ These existing features changed their behavior. more emoji characters than before, including those encoded with multiple emoji codepoints combined with ZWJ (zero width joiner) codepoints. +• Text in the 'statusline', 'tabline', and 'winbar' now inherits highlights + from the respective |hl-StatusLine|, |hl-TabLine|, and |hl-WinBar| highlight + groups. + +• |vim.on_key()| callbacks won't be invoked recursively when a callback itself + consumes input. + +• "q" in man pages now uses |CTRL-W_q| instead of |CTRL-W_c| to close the + current window, and it no longer throws |E444| when there is only one window + on the screen. Global variable `vim.g.pager` is removed. + ============================================================================== REMOVED FEATURES *news-removed* diff --git a/runtime/doc/nvim.txt b/runtime/doc/nvim.txt index f8eba3f7f8..86e344c654 100644 --- a/runtime/doc/nvim.txt +++ b/runtime/doc/nvim.txt @@ -4,7 +4,7 @@ NVIM REFERENCE MANUAL -Nvim *neovim* *nvim* *nvim-intro* +Nvim *nvim* *neovim* *nvim-intro* Nvim is based on Vim by Bram Moolenaar. diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 6dd062124b..97d5082e9e 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -306,19 +306,13 @@ created, thus they behave slightly differently: :se[t] {option}< Set the effective value of {option} to its global value. - For string |global-local| options, the local value is - removed, so that the global value will be used. + For |global-local| options, the local value is removed, + so that the global value will be used. For all other options, the global value is copied to the local value. :setl[ocal] {option}< Set the effective value of {option} to its global - value. - For number and boolean |global-local| options, the - local value is removed, so that the global value will - be used. - For all other options, including string |global-local| - options, the global value is copied to the local - value. + value by copying the global value to the local value. Note that the behaviour for |global-local| options is slightly different between string and number-based options. @@ -376,10 +370,11 @@ Note: In the future more global options can be made |global-local|. Using ":setlocal" on a global option might work differently then. *option-value-function* -Some options ('completefunc', 'omnifunc', 'operatorfunc', 'quickfixtextfunc', -'tagfunc' and 'thesaurusfunc') are set to a function name or a function -reference or a lambda function. When using a lambda it will be converted to -the name, e.g. "<lambda>123". Examples: +Some options ('completefunc', 'findfunc', 'omnifunc', 'operatorfunc', +'quickfixtextfunc', 'tagfunc' and 'thesaurusfunc') are set to a function name +or a function reference or a lambda function. When using a lambda it will be +converted to the name, e.g. "<lambda>123". +Examples: > set opfunc=MyOpFunc set opfunc=function('MyOpFunc') @@ -647,11 +642,12 @@ Hidden options *hidden-options* Not all options are supported in all versions. This depends on the supported features and sometimes on the system. A remark about this is in curly braces -below. When an option is not supported it may still be set without getting an -error, this is called a hidden option. You can't get the value of a hidden -option though, it is not stored. +below. When an option is not supported, it is called a hidden option. Trying +to get the value of a hidden option will not give an error, it will return the +default value for that option instead. You can't change the value of a hidden +option. -To test if option "foo" can be used with ":set" use something like this: > +To test if "foo" is a valid option name, use something like this: > if exists('&foo') This also returns true for a hidden option. To test if option "foo" is really supported use something like this: > @@ -897,12 +893,13 @@ A jump table for the options with a short description can be found at |Q_op|. useful for example in source trees where all the files are symbolic or hard links and any changes should stay in the local source tree, not be propagated back to the original source. - *crontab* + *crontab* One situation where "no" and "auto" will cause problems: A program that opens a file, invokes Vim to edit that file, and then tests if the open file was changed (through the file descriptor) will check the backup file instead of the newly created file. "crontab -e" is an - example. + example, as are several |file-watcher| daemons like inotify. In that + case you probably want to switch this option. When a copy is made, the original file is truncated and then filled with the new text. This means that protection bits, owner and @@ -1014,6 +1011,7 @@ A jump table for the options with a short description can be found at |Q_op|. separated list of items. For each item that is present, the bell will be silenced. This is most useful to specify specific events in insert mode to be silenced. + You can also make it flash by using 'visualbell'. item meaning when present ~ all All events. @@ -1037,6 +1035,7 @@ A jump table for the options with a short description can be found at |Q_op|. register Unknown register after <C-R> in |Insert-mode|. shell Bell from shell output |:!|. spell Error happened on spell suggest. + term Bell from |:terminal| output. wildmode More matches in |cmdline-completion| available (depends on the 'wildmode' setting). @@ -1138,16 +1137,6 @@ A jump table for the options with a short description can be found at |Q_op|. added for the 'showbreak' setting. (default: off) - *'browsedir'* *'bsdir'* -'browsedir' 'bsdir' string (default "last") - global - Which directory to use for the file browser: - last Use same directory as with last file browser, where a - file was opened or saved. - buffer Use the directory of the related buffer. - current Use the current directory. - {path} Use the specified directory - *'bufhidden'* *'bh'* 'bufhidden' 'bh' string (default "") local to buffer |local-noglobal| @@ -1414,7 +1403,7 @@ A jump table for the options with a short description can be found at |Q_op|. *'cmdheight'* *'ch'* 'cmdheight' 'ch' number (default 1) - global or local to tab page |global-local| + global or local to tab page Number of screen lines to use for the command-line. Helps avoiding |hit-enter| prompts. The value of this option is stored with the tab page, so that each tab @@ -1585,7 +1574,7 @@ A jump table for the options with a short description can be found at |Q_op|. *'completeslash'* *'csl'* 'completeslash' 'csl' string (default "") local to buffer - only for MS-Windows + only modifiable in MS-Windows When this option is set it overrules 'shellslash' for completion: - When this option is set to "slash", a forward slash is used for path completion in insert mode. This is useful when editing HTML tag, or @@ -2611,6 +2600,55 @@ A jump table for the options with a short description can be found at |Q_op|. eob EndOfBuffer |hl-EndOfBuffer| lastline NonText |hl-NonText| + *'findfunc'* *'ffu'* *E1514* +'findfunc' 'ffu' string (default "") + global or local to buffer |global-local| + Function that is called to obtain the filename(s) for the |:find| + command. When this option is empty, the internal |file-searching| + mechanism is used. + + The value can be the name of a function, a |lambda| or a |Funcref|. + See |option-value-function| for more information. + + The function is called with two arguments. The first argument is a + |String| and is the |:find| command argument. The second argument is + a |Boolean| and is set to |v:true| when the function is called to get + a List of command-line completion matches for the |:find| command. + The function should return a List of strings. + + The function is called only once per |:find| command invocation. + The function can process all the directories specified in 'path'. + + If a match is found, the function should return a |List| containing + one or more file names. If a match is not found, the function + should return an empty List. + + If any errors are encountered during the function invocation, an + empty List is used as the return value. + + It is not allowed to change text or jump to another window while + executing the 'findfunc' |textlock|. + + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + + Examples: + >vim + " Use glob() + func FindFuncGlob(cmdarg, cmdcomplete) + let pat = a:cmdcomplete ? $'{a:cmdarg}*' : a:cmdarg + return glob(pat, v:false, v:true) + endfunc + set findfunc=FindFuncGlob + + " Use the 'git ls-files' output + func FindGitFiles(cmdarg, cmdcomplete) + let fnames = systemlist('git ls-files') + return fnames->filter('v:val =~? a:cmdarg') + endfunc + set findfunc=FindGitFiles +< + *'fixendofline'* *'fixeol'* *'nofixendofline'* *'nofixeol'* 'fixendofline' 'fixeol' boolean (default on) local to buffer @@ -3097,136 +3135,6 @@ A jump table for the options with a short description can be found at |Q_op|. When 'guifont' has a valid font and 'guifontwide' is empty Vim will attempt to set 'guifontwide' to a matching double-width font. - *'guioptions'* *'go'* -'guioptions' 'go' string (default "egmrLT" (MS-Windows)) - global - This option only has an effect in the GUI version of Vim. It is a - sequence of letters which describes what components and options of the - GUI should be used. - To avoid problems with flags that are added in the future, use the - "+=" and "-=" feature of ":set" |add-option-flags|. - - Valid letters are as follows: - *guioptions_a* *'go-a'* - 'a' Autoselect: If present, then whenever VISUAL mode is started, - or the Visual area extended, Vim tries to become the owner of - the windowing system's global selection. This means that the - Visually highlighted text is available for pasting into other - applications as well as into Vim itself. When the Visual mode - ends, possibly due to an operation on the text, or when an - application wants to paste the selection, the highlighted text - is automatically yanked into the "* selection register. - Thus the selection is still available for pasting into other - applications after the VISUAL mode has ended. - If not present, then Vim won't become the owner of the - windowing system's global selection unless explicitly told to - by a yank or delete operation for the "* register. - The same applies to the modeless selection. - *'go-P'* - 'P' Like autoselect but using the "+ register instead of the "* - register. - *'go-A'* - 'A' Autoselect for the modeless selection. Like 'a', but only - applies to the modeless selection. - - 'guioptions' autoselect Visual autoselect modeless ~ - "" - - - "a" yes yes - "A" - yes - "aA" yes yes - - *'go-c'* - 'c' Use console dialogs instead of popup dialogs for simple - choices. - *'go-d'* - 'd' Use dark theme variant if available. - *'go-e'* - 'e' Add tab pages when indicated with 'showtabline'. - 'guitablabel' can be used to change the text in the labels. - When 'e' is missing a non-GUI tab pages line may be used. - The GUI tabs are only supported on some systems, currently - Mac OS/X and MS-Windows. - *'go-i'* - 'i' Use a Vim icon. - *'go-m'* - 'm' Menu bar is present. - *'go-M'* - 'M' The system menu "$VIMRUNTIME/menu.vim" is not sourced. Note - that this flag must be added in the vimrc file, before - switching on syntax or filetype recognition (when the |gvimrc| - file is sourced the system menu has already been loaded; the - `:syntax on` and `:filetype on` commands load the menu too). - *'go-g'* - 'g' Grey menu items: Make menu items that are not active grey. If - 'g' is not included inactive menu items are not shown at all. - *'go-T'* - 'T' Include Toolbar. Currently only in Win32 GUI. - *'go-r'* - 'r' Right-hand scrollbar is always present. - *'go-R'* - 'R' Right-hand scrollbar is present when there is a vertically - split window. - *'go-l'* - 'l' Left-hand scrollbar is always present. - *'go-L'* - 'L' Left-hand scrollbar is present when there is a vertically - split window. - *'go-b'* - 'b' Bottom (horizontal) scrollbar is present. Its size depends on - the longest visible line, or on the cursor line if the 'h' - flag is included. |gui-horiz-scroll| - *'go-h'* - 'h' Limit horizontal scrollbar size to the length of the cursor - line. Reduces computations. |gui-horiz-scroll| - - And yes, you may even have scrollbars on the left AND the right if - you really want to :-). See |gui-scrollbars| for more information. - - *'go-v'* - 'v' Use a vertical button layout for dialogs. When not included, - a horizontal layout is preferred, but when it doesn't fit a - vertical layout is used anyway. Not supported in GTK 3. - *'go-p'* - 'p' Use Pointer callbacks for X11 GUI. This is required for some - window managers. If the cursor is not blinking or hollow at - the right moment, try adding this flag. This must be done - before starting the GUI. Set it in your |gvimrc|. Adding or - removing it after the GUI has started has no effect. - *'go-k'* - 'k' Keep the GUI window size when adding/removing a scrollbar, or - toolbar, tabline, etc. Instead, the behavior is similar to - when the window is maximized and will adjust 'lines' and - 'columns' to fit to the window. Without the 'k' flag Vim will - try to keep 'lines' and 'columns' the same when adding and - removing GUI components. - - *'guitablabel'* *'gtl'* -'guitablabel' 'gtl' string (default "") - global - When non-empty describes the text to use in a label of the GUI tab - pages line. When empty and when the result is empty Vim will use a - default label. See |setting-guitablabel| for more info. - - The format of this option is like that of 'statusline'. - 'guitabtooltip' is used for the tooltip, see below. - The expression will be evaluated in the |sandbox| when set from a - modeline, see |sandbox-option|. - This option cannot be set in a modeline when 'modelineexpr' is off. - - Only used when the GUI tab pages line is displayed. 'e' must be - present in 'guioptions'. For the non-GUI tab pages line 'tabline' is - used. - - *'guitabtooltip'* *'gtt'* -'guitabtooltip' 'gtt' string (default "") - global - When non-empty describes the text to use in a tooltip for the GUI tab - pages line. When empty Vim will use a default tooltip. - This option is otherwise just like 'guitablabel' above. - You can include a line break. Simplest method is to use |:let|: >vim - let &guitabtooltip = "line one\nline two" -< - *'helpfile'* *'hf'* 'helpfile' 'hf' string (default (MS-Windows) "$VIMRUNTIME\doc\help.txt" (others) "$VIMRUNTIME/doc/help.txt") @@ -3289,7 +3197,8 @@ A jump table for the options with a short description can be found at |Q_op|. global A history of ":" commands, and a history of previous search patterns is remembered. This option decides how many entries may be stored in - each of these histories (see |cmdline-editing|). + each of these histories (see |cmdline-editing| and 'msghistory' for + the number of messages to remember). The maximum value is 10000. *'hlsearch'* *'hls'* *'nohlsearch'* *'nohls'* @@ -3344,23 +3253,6 @@ A jump table for the options with a short description can be found at |Q_op|. Can be overruled by using "\c" or "\C" in the pattern, see |/ignorecase|. - *'imcmdline'* *'imc'* *'noimcmdline'* *'noimc'* -'imcmdline' 'imc' boolean (default off) - global - When set the Input Method is always on when starting to edit a command - line, unless entering a search pattern (see 'imsearch' for that). - Setting this option is useful when your input method allows entering - English characters directly, e.g., when it's used to type accented - characters with dead keys. - - *'imdisable'* *'imd'* *'noimdisable'* *'noimd'* -'imdisable' 'imd' boolean (default off, on for some systems (SGI)) - global - When set the Input Method is never used. This is useful to disable - the IM when it doesn't work properly. - Currently this option is on by default for SGI/IRIX machines. This - may change in later releases. - *'iminsert'* *'imi'* 'iminsert' 'imi' number (default 0) local to buffer @@ -4392,75 +4284,18 @@ A jump table for the options with a short description can be found at |Q_op|. < Will make Nvim scroll 5 lines at a time when scrolling vertically, and scroll 2 columns at a time when scrolling horizontally. - *'mouseshape'* *'mouses'* *E547* -'mouseshape' 'mouses' string (default "i:beam,r:beam,s:updown,sd:cross, - m:no,ml:up-arrow,v:rightup-arrow") - global - This option tells Vim what the mouse pointer should look like in - different modes. The option is a comma-separated list of parts, much - like used for 'guicursor'. Each part consist of a mode/location-list - and an argument-list: - mode-list:shape,mode-list:shape,.. - The mode-list is a dash separated list of these modes/locations: - In a normal window: ~ - n Normal mode - v Visual mode - ve Visual mode with 'selection' "exclusive" (same as 'v', - if not specified) - o Operator-pending mode - i Insert mode - r Replace mode - - Others: ~ - c appending to the command-line - ci inserting in the command-line - cr replacing in the command-line - m at the 'Hit ENTER' or 'More' prompts - ml idem, but cursor in the last line - e any mode, pointer below last window - s any mode, pointer on a status line - sd any mode, while dragging a status line - vs any mode, pointer on a vertical separator line - vd any mode, while dragging a vertical separator line - a everywhere - - The shape is one of the following: - avail name looks like ~ - w x arrow Normal mouse pointer - w x blank no pointer at all (use with care!) - w x beam I-beam - w x updown up-down sizing arrows - w x leftright left-right sizing arrows - w x busy The system's usual busy pointer - w x no The system's usual "no input" pointer - x udsizing indicates up-down resizing - x lrsizing indicates left-right resizing - x crosshair like a big thin + - x hand1 black hand - x hand2 white hand - x pencil what you write with - x question big ? - x rightup-arrow arrow pointing right-up - w x up-arrow arrow pointing up - x <number> any X11 pointer number (see X11/cursorfont.h) - - The "avail" column contains a 'w' if the shape is available for Win32, - x for X11. - Any modes not specified or shapes not available use the normal mouse - pointer. - - Example: >vim - set mouseshape=s:udsizing,m:no -< will make the mouse turn to a sizing arrow over the status lines and - indicate no input when the hit-enter prompt is displayed (since - clicking the mouse has no effect in this state.) - *'mousetime'* *'mouset'* 'mousetime' 'mouset' number (default 500) global Defines the maximum time in msec between two mouse clicks for the second click to be recognized as a multi click. + *'msghistory'* *'mhi'* +'msghistory' 'mhi' number (default 500) + global + Determines how many entries are remembered in the |:messages| history. + The maximum value is 10000. + *'nrformats'* *'nf'* 'nrformats' 'nf' string (default "bin,hex") local to buffer @@ -4558,16 +4393,6 @@ A jump table for the options with a short description can be found at |Q_op|. This option cannot be set from a |modeline| or in the |sandbox|, for security reasons. - *'opendevice'* *'odev'* *'noopendevice'* *'noodev'* -'opendevice' 'odev' boolean (default off) - global - only for Windows - Enable reading and writing from devices. This may get Vim stuck on a - device that can be opened but doesn't actually do the I/O. Therefore - it is off by default. - Note that on Windows editing "aux.h", "lpt1.txt" and the like also - result in editing a device. - *'operatorfunc'* *'opfunc'* 'operatorfunc' 'opfunc' string (default "") global @@ -5363,7 +5188,7 @@ A jump table for the options with a short description can be found at |Q_op|. *shell-powershell* To use PowerShell: >vim let &shell = executable('pwsh') ? 'pwsh' : 'powershell' - let &shellcmdflag = '-NoLogo -ExecutionPolicy RemoteSigned -Command [Console]::InputEncoding=[Console]::OutputEncoding=[System.Text.UTF8Encoding]::new();$PSDefaultParameterValues[''Out-File:Encoding'']=''utf8'';Remove-Alias -Force -ErrorAction SilentlyContinue tee;' + let &shellcmdflag = '-NoLogo -NonInteractive -ExecutionPolicy RemoteSigned -Command [Console]::InputEncoding=[Console]::OutputEncoding=[System.Text.UTF8Encoding]::new();$PSDefaultParameterValues[''Out-File:Encoding'']=''utf8'';$PSStyle.OutputRendering=''plaintext'';Remove-Alias -Force -ErrorAction SilentlyContinue tee;' let &shellredir = '2>&1 | %%{ "$_" } | Out-File %s; exit $LastExitCode' let &shellpipe = '2>&1 | %%{ "$_" } | tee %s; exit $LastExitCode' set shellquote= shellxquote= @@ -5460,9 +5285,9 @@ A jump table for the options with a short description can be found at |Q_op|. security reasons. *'shellslash'* *'ssl'* *'noshellslash'* *'nossl'* -'shellslash' 'ssl' boolean (default off) +'shellslash' 'ssl' boolean (default on, Windows: off) global - only for MS-Windows + only modifiable in MS-Windows When set, a forward slash is used when expanding file names. This is useful when a Unix-like shell is used instead of cmd.exe. Backward slashes can still be typed, but they are changed to forward slashes by @@ -6275,7 +6100,7 @@ A jump table for the options with a short description can be found at |Q_op|. Examples: Emulate standard status line with 'ruler' set >vim - set statusline=%<%f\ %h%m%r%=%-14.(%l,%c%V%)\ %P + set statusline=%<%f\ %h%w%m%r%=%-14.(%l,%c%V%)\ %P < Similar, but add ASCII value of char under the cursor (like "ga") >vim set statusline=%<%f%h%m%r%=%b\ 0x%B\ \ %l,%c%V\ %P < Display byte count and byte value, modified flag in red. >vim @@ -6762,7 +6587,9 @@ A jump table for the options with a short description can be found at |Q_op|. window. This happens only when the 'title' option is on. When this option contains printf-style '%' items, they will be - expanded according to the rules used for 'statusline'. + expanded according to the rules used for 'statusline'. If it contains + an invalid '%' format, the value is used as-is and no error or warning + will be given when the value is set. This option cannot be set in a modeline when 'modelineexpr' is off. Example: >vim diff --git a/runtime/doc/pattern.txt b/runtime/doc/pattern.txt index 8ec02276cc..7f0938be05 100644 --- a/runtime/doc/pattern.txt +++ b/runtime/doc/pattern.txt @@ -154,7 +154,7 @@ or auto suspended with nohlsearch plugin. See |nohlsearch-install|. When 'shortmess' does not include the "S" flag, Vim will automatically show an -index, on which the cursor is. This can look like this: > +index, on which the cursor is. This can look like this: > [1/5] Cursor is on first of 5 matches. [1/>99] Cursor is on first of more than 99 matches. @@ -743,7 +743,7 @@ overview. \([a-z]\+\)\zs,\1 ",abc" in "abc,abc" \@123<= - Like "\@<=" but only look back 123 bytes. This avoids trying lots + Like "\@<=" but only look back 123 bytes. This avoids trying lots of matches that are known to fail and make executing the pattern very slow. Example, check if there is a "<" just before "span": /<\@1<=span @@ -769,7 +769,7 @@ overview. \(\/\/.*\)\@<!in "in" which is not after "//" \@123<! - Like "\@<!" but only look back 123 bytes. This avoids trying lots of + Like "\@<!" but only look back 123 bytes. This avoids trying lots of matches that are known to fail and make executing the pattern very slow. @@ -892,7 +892,7 @@ $ At end of pattern or in front of "\|", "\)" or "\n" ('magic' on): inside the Visual area put it at the start and just before the end of the pattern, e.g.: > /\%Vfoo.*ba\%Vr -< This also works if only "foo bar" was Visually selected. This: > +< This also works if only "foo bar" was Visually selected. This: > /\%Vfoo.*bar\%V < would match "foo bar" if the Visual selection continues after the "r". Only works for the current buffer. @@ -999,7 +999,7 @@ $ At end of pattern or in front of "\|", "\)" or "\n" ('magic' on): < To match all characters after the current virtual column (where the cursor is): > /\%>.v.* -< Column 17 is not included, because this is a |/zero-width| match. To +< Column 17 is not included, because this is a |/zero-width| match. To include the column use: > /^.*\%17v. < This command does the same thing, but also matches when there is no @@ -1123,11 +1123,11 @@ x A single character, with no special meaning, matches itself in the collection: "[^xyz]" matches anything but 'x', 'y' and 'z'. - If two characters in the sequence are separated by '-', this is shorthand for the full list of ASCII characters between them. E.g., - "[0-9]" matches any decimal digit. If the starting character exceeds - the ending character, e.g. [c-a], E944 occurs. Non-ASCII characters + "[0-9]" matches any decimal digit. If the starting character exceeds + the ending character, e.g. [c-a], E944 occurs. Non-ASCII characters can be used, but the character values must not be more than 256 apart - in the old regexp engine. For example, searching by [\u3000-\u4000] - after setting re=1 emits a E945 error. Prepending \%#=2 will fix it. + in the old regexp engine. For example, searching by [\u3000-\u4000] + after setting re=1 emits a E945 error. Prepending \%#=2 will fix it. - A character class expression is evaluated to the set of characters belonging to that character class. The following character classes are supported: @@ -1193,7 +1193,7 @@ x A single character, with no special meaning, matches itself any character that's not in "^]-\bdertnoUux". "[\xyz]" matches '\', 'x', 'y' and 'z'. It's better to use "\\" though, future expansions may use other characters after '\'. - - Omitting the trailing ] is not considered an error. "[]" works like + - Omitting the trailing ] is not considered an error. "[]" works like "[]]", it matches the ']' character. - The following translations are accepted when the 'l' flag is not included in 'cpoptions': @@ -1425,14 +1425,14 @@ Finally, these constructs are unique to Perl: display you may get unexpected results. That is because Vim looks for a match in the line where redrawing starts. - Also see |matcharg()| and |getmatches()|. The former returns + Also see |matcharg()| and |getmatches()|. The former returns the highlight group and pattern of a previous |:match| command. The latter returns a list with highlight groups and patterns defined by both |matchadd()| and |:match|. Highlighting matches using |:match| are limited to three matches (aside from |:match|, |:2match| and |:3match| are - available). |matchadd()| does not have this limitation and in + available). |matchadd()| does not have this limitation and in addition makes it possible to prioritize matches. Another example, which highlights all characters in virtual @@ -1461,7 +1461,7 @@ Finally, these constructs are unique to Perl: with the lowest number has priority if several match at the same position. It uses the match id 3. The ":3match" command is used by (older Vims) |matchparen| - plugin. You are suggested to use ":match" for manual matching + plugin. You are suggested to use ":match" for manual matching and ":2match" for another plugin or even better make use of the more flexible |matchadd()| (and similar) functions instead. @@ -1470,10 +1470,10 @@ Finally, these constructs are unique to Perl: Fuzzy matching refers to matching strings using a non-exact search string. Fuzzy matching will match a string, if all the characters in the search string -are present anywhere in the string in the same order. Case is ignored. In a +are present anywhere in the string in the same order. Case is ignored. In a matched string, other characters can be present between two consecutive -characters in the search string. If the search string has multiple words, then -each word is matched separately. So the words in the search string can be +characters in the search string. If the search string has multiple words, then +each word is matched separately. So the words in the search string can be present in any order in a string. Fuzzy matching assigns a score for each matched string based on the following @@ -1492,8 +1492,8 @@ will match the strings "GetPattern", "PatternGet", "getPattern", "patGetter", "getSomePattern", "MatchpatternGet" etc. The functions |matchfuzzy()| and |matchfuzzypos()| can be used to fuzzy search -a string in a List of strings. The matchfuzzy() function returns a List of -matching strings. The matchfuzzypos() functions returns the List of matches, +a string in a List of strings. The matchfuzzy() function returns a List of +matching strings. The matchfuzzypos() functions returns the List of matches, the matching positions and the fuzzy match scores. The "f" flag of `:vimgrep` enables fuzzy matching. diff --git a/runtime/doc/pi_netrw.txt b/runtime/doc/pi_netrw.txt index 0652fb27e7..09d1369d46 100644 --- a/runtime/doc/pi_netrw.txt +++ b/runtime/doc/pi_netrw.txt @@ -54,9 +54,10 @@ Copyright: Copyright (C) 2017 Charles E Campbell *netrw-copyright* Browsing With A Horizontally Split Window...........|netrw-o| Browsing With A New Tab.............................|netrw-t| Browsing With A Vertically Split Window.............|netrw-v| - Change File Permission..............................|netrw-gp| - Change Listing Style.(thin wide long tree)..........|netrw-i| + Change Listing Style (thin wide long tree)..........|netrw-i| Changing To A Bookmarked Directory..................|netrw-gb| + Quick hide/unhide of dot-files......................|netrw-gh| + Changing local-only File Permission.................|netrw-gp| Changing To A Predecessor Directory.................|netrw-u| Changing To A Successor Directory...................|netrw-U| Customizing Browsing With A Special Handler.........|netrw-x| @@ -1465,98 +1466,106 @@ With either form of the command, netrw will first ask for confirmation that the removal is in fact what you want to do. If netrw doesn't have permission to remove a file, it will issue an error message. - *netrw-gx* CUSTOMIZING BROWSING WITH A SPECIAL HANDLER *netrw-x* *netrw-handler* {{{2 - (also see |netrw_filehandler|) Certain files, such as html, gif, jpeg, (word/office) doc, etc, files, are best seen with a special handler (ie. a tool provided with your computer's -operating system). Netrw allows one to invoke such special handlers by: > +operating system). Netrw allows one to invoke such special handlers by: - * when Exploring, hit the "x" key - * when editing, hit gx with the cursor atop the special filename -< (latter not available if the |g:netrw_nogx| variable exists) + * hitting gx with the cursor atop the file path or alternatively x + in a netrw buffer; the former can be disabled by defining the + |g:netrw_nogx| variable + * when in command line, typing :Open <path>, see |:Open| below. -Netrw determines which special handler by the following method: - - * if |g:netrw_browsex_viewer| exists, then it will be used to attempt to - view files. Examples of useful settings (place into your <.vimrc>): > - - :let g:netrw_browsex_viewer= "kfmclient exec" -< or > - :let g:netrw_browsex_viewer= "xdg-open" -< - If g:netrw_browsex_viewer == '-', then netrwFileHandlers#Invoke() will be - used instead (see |netrw_filehandler|). - - If the viewer you wish to use does not support handling of a remote URL - directory, set |g:netrw_browsex_support_remote| to 0. - * for Windows 32 or 64, the URL and FileProtocolHandler dlls are used. - * for Gnome (with gnome-open): gnome-open is used. - * for KDE (with kfmclient) : kfmclient is used - * for Mac OS X : open is used. - * otherwise the netrwFileHandler plugin is used. - -The file's suffix is used by these various approaches to determine an -appropriate application to use to "handle" these files. Such things as -OpenOffice (*.sfx), visualization (*.jpg, *.gif, etc), and PostScript (*.ps, -*.eps) can be handled. - -The gx mapping extends to all buffers; apply "gx" while atop a word and netrw -will apply a special handler to it (like "x" works when in a netrw buffer). One may also use visual mode (see |visual-start|) to select the text that the -special handler will use. Normally gx uses expand("<cfile>") to pick up the -text under the cursor; one may change what |expand()| uses via the +special handler will use. Normally gx checks for a close-by URL or file name +to pick up the text under the cursor; one may change what |expand()| uses via the |g:netrw_gx| variable (options include "<cword>", "<cWORD>"). Note that expand("<cfile>") depends on the |'isfname'| setting. Alternatively, one may select the text to be used by gx by making a visual selection (see |visual-block|) and then pressing gx. +The selection function can be adapted for each filetype by adding a function +`Netrw_get_URL_<filetype>`, where <filetype> is given by the 'filetype'. +The function should return the URL or file name to be used by gx, and will +fall back to the default behavior if it returns an empty string. +For example, special handlers for links Markdown and HTML are + +" make gx work on concealed links regardless of exact cursor position: > + + function Netrw_get_URL_markdown() + " markdown URL such as [link text](http://ya.ru 'yandex search') + try + let save_view = winsaveview() + if searchpair('\[.\{-}\](', '', ')\zs', 'cbW', '', line('.')) > 0 + return matchstr(getline('.')[col('.')-1:], + \ '\[.\{-}\](\zs' .. g:netrw_regex_url .. '\ze\(\s\+.\{-}\)\?)') + endif + return '' + finally + call winrestview(save_view) + endtry + endfunction + + function Netrw_get_URL_html() + " HTML URL such as <a href='http://www.python.org'>Python is here</a> + " <a href="http://www.python.org"/> + try + let save_view = winsaveview() + if searchpair('<a\s\+href=', '', '\%(</a>\|/>\)\zs', 'cbW', '', line('.')) > 0 + return matchstr(getline('.')[col('.') - 1 : ], + \ 'href=["'.."'"..']\?\zs\S\{-}\ze["'.."'"..']\?/\?>') + endif + return '' + finally + call winrestview(save_view) + endtry + endfunction +< +Other than a file path, the text under the cursor may be a URL. Netrw uses +by default the following regular expression to determine if the text under the +cursor is a URL: +> + :let g:netrw_regex_url = '\%(\%(http\|ftp\|irc\)s\?\|file\)://\S\{-}' +< Associated setting variables: |g:netrw_gx| control how gx picks up the text under the cursor |g:netrw_nogx| prevent gx map while editing |g:netrw_suppress_gx_mesg| controls gx's suppression of browser messages - *netrw_filehandler* +OPENING FILES AND LAUNCHING APPS *netrw-gx* *:Open* *:Launch* {{{2 -When |g:netrw_browsex_viewer| exists and is "-", then netrw will attempt to -handle the special file with a vim function. The "x" map applies a function -to a file, based on its extension. Of course, the handler function must exist -for it to be called! -> - Ex. mypgm.html x -> NFH_html("scp://user@host/some/path/mypgm.html") +Netrw determines which special handler by the following method: -< Users may write their own netrw File Handler functions to - support more suffixes with special handling. See - <autoload/netrwFileHandlers.vim> for examples on how to make - file handler functions. As an example: > + * if |g:netrw_browsex_viewer| exists, then it will be used to attempt to + view files. + If the viewer you wish to use does not support handling of a remote URL + directory, set |g:netrw_browsex_support_remote| to 0. + * otherwise: - " NFH_suffix(filename) - fun! NFH_suffix(filename) - ..do something special with filename.. - endfun -< -These functions need to be defined in some file in your .vim/plugin -(vimfiles\plugin) directory. Vim's function names may not have punctuation -characters (except for the underscore) in them. To support suffices that -contain such characters, netrw will first convert the suffix using the -following table: > - - @ -> AT ! -> EXCLAMATION % -> PERCENT - : -> COLON = -> EQUAL ? -> QUESTION - , -> COMMA - -> MINUS ; -> SEMICOLON - $ -> DOLLAR + -> PLUS ~ -> TILDE -< -So, for example: > + * for Windows : explorer.exe is used + * for Mac OS X : open is used. + * for Linux : xdg-open is used. + +To open a path (or URL) <path> by the appropriate handler, type > - file.rcs,v -> NFH_rcsCOMMAv() + :Open <path> < -If more such translations are necessary, please send me email: > - NcampObell@SdrPchip.AorgM-NOSPAM -with a request. (remove the embedded NOSPAM first) +No escaping, neither for the shell nor for Vim's command-line, is needed. + +To launch a specific application <app> <args>, often <args> being <path> > + + :Launch <app> <args>. + +Since <args> can be arbitrarily complex, in particular contain many file +paths, the escaping is left to the user. -Associated setting variable: |g:netrw_browsex_viewer| +If you disabled the netrw plugin by setting g:loaded_netrwPlugin (see +|netrw-noload|), then you can use > + :call netrw#Launch('<app> <args>') + :call netrw#Open('<path>') +< *netrw-curdir* DELETING BOOKMARKS *netrw-mB* {{{2 @@ -2569,12 +2578,7 @@ your browsing preferences. (see also: |netrw-settings|) *g:netrw_browsex_viewer* specify user's preference for a viewer: > "kfmclient exec" "gnome-open" -< If > - "-" -< is used, then netrwFileHandler() will look for - a script/function to handle the given - extension. (see |netrw_filehandler|). - +< *g:netrw_browsex_support_remote* specify if the specified viewer supports a remote URL. (see |netrw-handler|). diff --git a/runtime/doc/pi_paren.txt b/runtime/doc/pi_paren.txt index 77083362da..caa88e8d56 100644 --- a/runtime/doc/pi_paren.txt +++ b/runtime/doc/pi_paren.txt @@ -10,6 +10,7 @@ The functionality mentioned here is a |standard-plugin|. This plugin is only available if 'compatible' is not set. You can avoid loading this plugin by setting the "loaded_matchparen" variable: > + :let loaded_matchparen = 1 The plugin installs CursorMoved, CursorMovedI and WinEnter autocommands to @@ -29,6 +30,16 @@ the ":highlight" command. Example: > :hi MatchParen ctermbg=blue guibg=lightblue +By default the plugin will highlight both the paren under the cursor and the +matching one using the |hl-MatchParen| highlighting group. This may result in +the cursor briefly disappearing from the screen as the MatchParen colors take +over the cursor highlight. To prevent this from happening and have the plugin +only highlight the matching paren and not the one under the cursor +(effectively leaving the cursor style unchanged), you can set the +"matchparen_disable_cursor_hl" variable: > + + :let matchparen_disable_cursor_hl = 1 + The characters to be matched come from the 'matchpairs' option. You can change the value to highlight different matches. Note that not everything is possible. For example, you can't highlight single or double quotes, because @@ -46,10 +57,10 @@ are: closed folds. - 'synmaxcol' times 2 bytes before or after the cursor to avoid a delay in a long line with syntax highlighting. -- A timeout of 300 msec (60 msec in Insert mode). This can be changed with the - g:matchparen_timeout and g:matchparen_insert_timeout variables and their - buffer-local equivalents b:matchparen_timeout and - b:matchparen_insert_timeout. +- A timeout of 300 msec (60 msec in Insert mode). This can be changed with + the "g:matchparen_timeout" and "g:matchparen_insert_timeout" variables and + their buffer-local equivalents "b:matchparen_timeout" and + "b:matchparen_insert_timeout". If you would like the |%| command to work better, the |matchit| plugin can be used. This plugin also helps to skip matches in comments. This is unrelated diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt index 63109bdaf3..b3399b2766 100644 --- a/runtime/doc/quickfix.txt +++ b/runtime/doc/quickfix.txt @@ -349,7 +349,7 @@ processing a quickfix or location list command, it will be aborted. Example: > :g/mypattern/caddexpr expand("%") .. ":" .. line(".") .. ":" .. getline(".") < - *:lad* *:addd* *:laddexpr* + *:lad* *:ladd* *:laddexpr* :lad[dexpr] {expr} Same as ":caddexpr", except the location list for the current window is used instead of the quickfix list. @@ -1366,6 +1366,32 @@ being checked. To disable this set g:perl_compiler_force_warnings to a zero value. For example: > let g:perl_compiler_force_warnings = 0 +MYPY TYPE CHECKER *compiler-mypy* + +Commonly used compiler options can be added to 'makeprg' by setting the +b/g:mypy_makeprg_params variable. For example: > + + let b:mypy_makeprg_params = "--warn-unused-ignores" + +The global default is "--strict --ignore-missing-imports". + +RUFF LINTER *compiler-ruff* + +Commonly used compiler options can be added to 'makeprg' by setting the +b/g:ruff_makeprg_params variable. For example: > + + let b:ruff_makeprg_params = "--max-line-length "..&textwidth + +The global default is "--preview". + +PYLINT LINTER *compiler-pylint* + +Commonly used compiler options can be added to 'makeprg' by setting the +b/g:pylint_makeprg_params variable. For example: > + + let b:pylint_makeprg_params = "--max-line-length "..&textwidth + +The global default is "--jobs=0" to use (almost) all cores. PYUNIT COMPILER *compiler-pyunit* diff --git a/runtime/doc/quickref.txt b/runtime/doc/quickref.txt index d77750b485..f43ddb57fb 100644 --- a/runtime/doc/quickref.txt +++ b/runtime/doc/quickref.txt @@ -705,6 +705,7 @@ Short explanation of each option: *option-list* 'fileignorecase' 'fic' ignore case when using file names 'filetype' 'ft' type of file, used for autocommands 'fillchars' 'fcs' characters to use for displaying special items +'findfunc' 'ffu' function to be called for the |:find| command 'fixendofline' 'fixeol' make sure last line in file has <EOL> 'foldclose' 'fcl' close a fold when the cursor leaves it 'foldcolumn' 'fdc' width of the column used to indicate folds diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt index 521d690d93..abeefb980e 100644 --- a/runtime/doc/repeat.txt +++ b/runtime/doc/repeat.txt @@ -967,21 +967,24 @@ For example, to profile the one_script.vim script file: > :prof[ile] start {fname} *:prof* *:profile* *E750* - Start profiling, write the output in {fname} upon exit. + Start profiling, write the output in {fname} upon exit or when + a `:profile stop` or `:profile dump` command is invoked. "~/" and environment variables in {fname} will be expanded. If {fname} already exists it will be silently overwritten. The variable |v:profiling| is set to one. :prof[ile] stop - Write the logfile and stop profiling. + Write the collected profiling information to the logfile and + stop profiling. You can use the `:profile start` command to + clear the profiling statistics and start profiling again. :prof[ile] pause - Don't profile until the following ":profile continue". Can be - used when doing something that should not be counted (e.g., an - external command). Does not nest. + Stop profiling until the next `:profile continue` command. + Can be used when doing something that should not be counted + (e.g., an external command). Does not nest. :prof[ile] continue - Continue profiling after ":profile pause". + Continue profiling after `:profile pause`. :prof[ile] func {pattern} Profile function that matches the pattern {pattern}. @@ -999,16 +1002,24 @@ For example, to profile the one_script.vim script file: > won't work. :prof[ile] dump - Don't wait until exiting Vim and write the current state of - profiling to the log immediately. + Write the current state of profiling to the logfile + immediately. After running this command, Vim continues to + collect the profiling statistics. :profd[el] ... *:profd* *:profdel* Stop profiling for the arguments specified. See |:breakdel| - for the arguments. - + for the arguments. Examples: > + profdel func MyFunc + profdel file MyScript.vim + profdel here You must always start with a ":profile start fname" command. The resulting -file is written when Vim exits. Here is an example of the output, with line +file is written when Vim exits. For example, to profile one specific +function: > + profile start /tmp/vimprofile + profile func MyFunc + +Here is an example of the output, with line numbers prepended for the explanation: 1 FUNCTION Test2() ~ diff --git a/runtime/doc/support.txt b/runtime/doc/support.txt index 0ddf037fba..a2776fca0d 100644 --- a/runtime/doc/support.txt +++ b/runtime/doc/support.txt @@ -13,10 +13,10 @@ Supported platforms *supported-platforms* `System` `Tier` `Versions` `Tested versions` Linux 1 >= 2.6.32, glibc >= 2.12 Ubuntu 24.04 -macOS (Intel) 1 >= 11 macOS 12 +macOS (Intel) 1 >= 11 macOS 13 macOS (M1) 1 >= 11 macOS 15 Windows 64-bit 1 >= Windows 10 Version 1809 Windows Server 2022 -FreeBSD 1 >= 10 FreeBSD 13 +FreeBSD 1 >= 10 FreeBSD 14 OpenBSD 2 >= 7 MinGW 2 MinGW-w64 Windows 64-bit 3 < Windows 10 Version 1809 diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index 219be92c58..75a855bbdd 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -45,7 +45,7 @@ directory where the Vim stuff is located. For example, if your syntax files are in the "/usr/vim/vim82/syntax" directory, set $VIMRUNTIME to "/usr/vim/vim82". You must do this in the shell, before starting Vim. This command also sources the |menu.vim| script when the GUI is running or -will start soon. See |'go-M'| about avoiding that. +will start soon. *:hi-normal* *:highlight-normal* If you are running in the GUI, you can get white text on a black background @@ -1209,20 +1209,20 @@ on" command in your .vimrc file. When you edit an existing Fortran file, the syntax script will assume free source form if the fortran_free_source variable has been set, and assumes fixed source form if the fortran_fixed_source variable has been set. Suppose -neither of these variables have been set. In that case, the syntax script attempts to -determine which source form has been used by examining the file extension -using conventions common to the ifort, gfortran, Cray, NAG, and PathScale -compilers (.f, .for, .f77 for fixed-source, .f90, .f95, .f03, .f08 for -free-source). No default is used for the .fpp and .ftn file extensions because -different compilers treat them differently. If none of this works, then the -script examines the first five columns of the first 500 lines of your file. If -no signs of free source form are detected, then the file is assumed to be in -fixed source form. The algorithm should work in the vast majority of cases. -In some cases, such as a file that begins with 500 or more full-line comments, -the script may incorrectly decide that the code is in fixed form. If that -happens, just add a non-comment statement beginning anywhere in the first five -columns of the first twenty-five lines, save (:w), and then reload (:e!) the -file. +neither of these variables have been set. In that case, the syntax script +attempts to determine which source form has been used by examining the file +extension using conventions common to the ifort, gfortran, Cray, NAG, and +PathScale compilers (.f, .for, .f77 for fixed-source, .f90, .f95, .f03, .f08 +for free-source). No default is used for the .fpp and .ftn file extensions +because different compilers treat them differently. If none of this works, +then the script examines the first five columns of the first 500 lines of your +file. If no signs of free source form are detected, then the file is assumed +to be in fixed source form. The algorithm should work in the vast majority of +cases. In some cases, such as a file that begins with 500 or more full-line +comments, the script may incorrectly decide that the code is in fixed form. +If that happens, just add a non-comment statement beginning anywhere in the +first five columns of the first twenty-five lines, save (:w), and then reload +(:e!) the file. Vendor extensions ~ Fixed-form Fortran requires a maximum line length of 72 characters but the @@ -1750,6 +1750,20 @@ define the vim variable 'lace_case_insensitive' in your startup file: > :let lace_case_insensitive=1 +LF (LFRC) *lf.vim* *ft-lf-syntax* *g:lf_shell_syntax* + *b:lf_shell_syntax* + +For the lf file manager configuration files (lfrc) the shell commands syntax +highlighting can be changed globally and per buffer by setting a different +'include' command search pattern using these variables: > + let g:lf_shell_syntax = "syntax/dosbatch.vim" + let b:lf_shell_syntax = "syntax/zsh.vim" + +These variables are unset by default. + +The default 'include' command search pattern is 'syntax/sh.vim'. + + LEX *lex.vim* *ft-lex-syntax* Lex uses brute-force synchronizing as the "^%%$" section delimiter @@ -2051,6 +2065,13 @@ set "msql_minlines" to the value you desire. Example: > :let msql_minlines = 200 +NEOMUTT *neomutt.vim* *ft-neomuttrc-syntax* + *ft-neomuttlog-syntax* + +To disable the default NeoMutt log colors: > + + :let g:neolog_disable_default_colors = 1 + N1QL *n1ql.vim* *ft-n1ql-syntax* N1QL is a SQL-like declarative language for manipulating JSON documents in @@ -2175,7 +2196,7 @@ To specify elements that should not be concealed, set the following variable: > :let g:pandoc#syntax#conceal#blacklist = [] -This is a list of the rules wich can be used here: +This is a list of the rules which can be used here: - titleblock - image @@ -2216,9 +2237,9 @@ specified. Default = 1 > :let g:pandoc#syntax#codeblocks#embeds#use = 1 -For specify what languages and using what syntax files to highlight embeds. This is a -list of language names. When the language pandoc and vim use don't match, you -can use the "PANDOC=VIM" syntax. For example: > +For specify what languages and using what syntax files to highlight embeds. +This is a list of language names. When the language pandoc and vim use don't +match, you can use the "PANDOC=VIM" syntax. For example: > :let g:pandoc#syntax#codeblocks#embeds#langs = ["ruby", "bash=sh"] @@ -3426,7 +3447,7 @@ set "tf_minlines" to the value you desire. Example: > :let tf_minlines = your choice < TYPESCRIPT *typescript.vim* *ft-typescript-syntax* - *typescriptreact.vim* *ft-typescriptreact-syntax* + *typescriptreact.vim* *ft-typescriptreact-syntax* There is one option to control the TypeScript syntax highlighting. @@ -3472,7 +3493,7 @@ This option is disabled by default. Some folding is now supported with when 'foldmethod' is set to "syntax": > g:vimsyn_folding == 0 or doesn't exist: no syntax-based folding - g:vimsyn_folding =~ 'a' : augroups + g:vimsyn_folding =~ 'a' : fold augroups g:vimsyn_folding =~ 'f' : fold functions g:vimsyn_folding =~ 'h' : fold heredocs g:vimsyn_folding =~ 'l' : fold Lua script @@ -5202,7 +5223,7 @@ NormalNC Normal text in non-current windows. *hl-Pmenu* Pmenu Popup menu: Normal item. *hl-PmenuSel* -PmenuSel Popup menu: Selected item. +PmenuSel Popup menu: Selected item. Combined with |hl-Pmenu|. *hl-PmenuKind* PmenuKind Popup menu: Normal item "kind". *hl-PmenuKindSel* @@ -5216,9 +5237,11 @@ PmenuSbar Popup menu: Scrollbar. *hl-PmenuThumb* PmenuThumb Popup menu: Thumb of the scrollbar. *hl-PmenuMatch* -PmenuMatch Popup menu: Matched text in normal item. +PmenuMatch Popup menu: Matched text in normal item. Combined with + |hl-Pmenu|. *hl-PmenuMatchSel* -PmenuMatchSel Popup menu: Matched text in selected item. +PmenuMatchSel Popup menu: Matched text in selected item. Combined with + |hl-PmenuMatch| and |hl-PmenuSel|. *hl-Question* Question |hit-enter| prompt and yes/no questions. *hl-QuickFixLine* @@ -5450,7 +5473,8 @@ This will set the "w:current_syntax" variable to "foo". The value of restoring "b:current_syntax", since the syntax files do set "b:current_syntax". The value set by the syntax file is assigned to "w:current_syntax". -Note: This resets the 'spell', 'spellcapcheck' and 'spellfile' options. +Note: This resets the 'spell', 'spellcapcheck', 'spellfile' and 'spelloptions' +options. Once a window has its own syntax, syntax commands executed from other windows on the same buffer (including :syntax clear) have no effect. Conversely, diff --git a/runtime/doc/terminal.txt b/runtime/doc/terminal.txt index 9c47e6de7d..ed9659d6e7 100644 --- a/runtime/doc/terminal.txt +++ b/runtime/doc/terminal.txt @@ -509,6 +509,7 @@ If the current window has enough horizontal space, it will be vertically split and the Var window will be shown side by side with the source code window (and the height options won't be used). + Communication ~ *termdebug-communication* There is another, hidden, buffer, which is used for Vim to communicate with @@ -601,15 +602,19 @@ If there is no g:termdebug_config you can use: >vim Change default signs ~ *termdebug_signs* Termdebug uses the hex number of the breakpoint ID in the signcolumn to -represent breakpoints. if it is greater than "0xFF", then it will be displayed +represent breakpoints. If it is greater than "0xFF", then it will be displayed as "F+", due to we really only have two screen cells for the sign. +You may also use decimal breakpoint signs instead, in which case IDs greater +than 99 will be displayed as "9+". -If you want to customize the breakpoint signs: >vim +If you want to customize the breakpoint signs to show `>>` in the signcolumn: >vim let g:termdebug_config['sign'] = '>>' -If there is no g:terminal_config yet you can use: >vim +If you would like to use decimal (base 10) breakpoint signs: >vim + let g:termdebug_config['sign_decimal'] = 1 +If the variable g:termdebug_config does not yet exist, you can use: >vim let g:termdebug_config = {'sign': '>>'} - -After this, breakpoints will be displayed as `>>` in the signcolumn. +Likewise, to enable decimal signs: >vim + let g:termdebug_config = {'sign_decimal': 1} Vim window width ~ diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index 35192cc43d..5fc6429f7a 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -622,9 +622,23 @@ TSNode:child({index}) *TSNode:child()* Return: ~ (`TSNode?`) - *TSNode:child_containing_descendant()* -TSNode:child_containing_descendant({descendant}) - Get the node's child that contains {descendant}. +TSNode:child_count() *TSNode:child_count()* + Get the node's number of children. + + Return: ~ + (`integer`) + + *TSNode:child_with_descendant()* +TSNode:child_with_descendant({descendant}) + Get the node's child that contains {descendant} (includes {descendant}). + + For example, with the following node hierarchy: > + a -> b -> c + + a:child_with_descendant(c) == b + a:child_with_descendant(b) == b + a:child_with_descendant(a) == nil +< Parameters: ~ • {descendant} (`TSNode`) @@ -632,12 +646,6 @@ TSNode:child_containing_descendant({descendant}) Return: ~ (`TSNode?`) -TSNode:child_count() *TSNode:child_count()* - Get the node's number of children. - - Return: ~ - (`integer`) - *TSNode:descendant_for_range()* TSNode:descendant_for_range({start_row}, {start_col}, {end_row}, {end_col}) Get the smallest node within this node that spans the given range of (row, @@ -778,9 +786,8 @@ TSNode:next_sibling() *TSNode:next_sibling()* (`TSNode?`) TSNode:parent() *TSNode:parent()* - Get the node's immediate parent. Prefer - |TSNode:child_containing_descendant()| for iterating over the node's - ancestors. + Get the node's immediate parent. Prefer |TSNode:child_with_descendant()| + for iterating over the node's ancestors. Return: ~ (`TSNode?`) @@ -1143,8 +1150,13 @@ get_lang({filetype}) *vim.treesitter.language.get_lang()* inspect({lang}) *vim.treesitter.language.inspect()* Inspects the provided language. - Inspecting provides some useful information on the language like node - names, ... + Inspecting provides some useful information on the language like node and + field names, ABI version, and whether the language came from a WASM + module. + + Node names are returned in a table mapping each node name to a `boolean` + indicating whether or not the node is named (i.e., not anonymous). + Anonymous nodes are surrounded with double quotes (`"`). Parameters: ~ • {lang} (`string`) Language @@ -1199,7 +1211,7 @@ add_predicate({name}, {handler}, {opts}) Parameters: ~ • {name} (`string`) Name of the predicate, without leading # - • {handler} (`fun(match: table<integer,TSNode[]>, pattern: integer, source: integer|string, predicate: any[], metadata: vim.treesitter.query.TSMetadata)`) + • {handler} (`fun(match: table<integer,TSNode[]>, pattern: integer, source: integer|string, predicate: any[], metadata: vim.treesitter.query.TSMetadata): boolean?`) • see |vim.treesitter.query.add_directive()| for argument meanings • {opts} (`table?`) A table with the following fields: @@ -1593,8 +1605,7 @@ LanguageTree:register_cbs({cbs}, {recursive}) • {cbs} (`table<TSCallbackNameOn,function>`) An |nvim_buf_attach()|-like table argument with the following handlers: - • `on_bytes` : see |nvim_buf_attach()|, but this will be - called after the parsers callback. + • `on_bytes` : see |nvim_buf_attach()|. • `on_changedtree` : a callback that will be called every time the tree has syntactical changes. It will be passed two arguments: a table of the ranges (as node diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt index d37cdfb9df..4e8253c47a 100644 --- a/runtime/doc/ui.txt +++ b/runtime/doc/ui.txt @@ -610,11 +610,12 @@ tabs. size). If the window was previously hidden, it should now be shown again. -["win_float_pos", grid, win, anchor, anchor_grid, anchor_row, anchor_col, focusable, zindex] ~ +["win_float_pos", grid, win, anchor, anchor_grid, anchor_row, anchor_col, mouse_enabled, zindex] ~ Display or reconfigure floating window `win`. The window should be displayed above another grid `anchor_grid` at the specified position - `anchor_row` and `anchor_col`. For the meaning of `anchor` and more - details of positioning, see |nvim_open_win()|. + `anchor_row` and `anchor_col`. For the meaning of `anchor` and more details + of positioning, see |nvim_open_win()|. `mouse_enabled` is true if the + window can receive mouse events. ["win_external_pos", grid, win] ~ Display or reconfigure external window `win`. The window should be @@ -795,6 +796,7 @@ must handle. "echomsg" |:echomsg| message "echoerr" |:echoerr| message "lua_error" Error in |:lua| code + "lua_print" |print()| from |:lua| code "rpc_error" Error response from |rpcrequest()| "return_prompt" |press-enter| prompt after a multiple messages "quickfix" Quickfix navigation message @@ -804,10 +806,11 @@ must handle. kinds as the empty kind. content - Array of `[attr_id, text_chunk]` tuples, building up the message - text of chunks of different highlights. No extra spacing should be - added between chunks, the `text_chunk` by itself contains any - necessary whitespace. Messages can contain line breaks "\n". + Array of `[attr_id, text_chunk, hl_id]` tuples, building up the + message text of chunks of different highlights. No extra spacing + should be added between chunks, the `text_chunk` by itself + contains any necessary whitespace. Messages can contain line + breaks "\n". replace_last Decides how multiple messages should be displayed: diff --git a/runtime/doc/undo.txt b/runtime/doc/undo.txt index b3a49dbb7e..7d8277d90e 100644 --- a/runtime/doc/undo.txt +++ b/runtime/doc/undo.txt @@ -184,7 +184,7 @@ g- Go to older text state. With a count repeat that many g+ Go to newer text state. With a count repeat that many times. *:lat* *:later* -:lat[er] {count} Go to newer text state {count} times. +:lat[er] {count} Go to newer text state {count} times. :lat[er] {N}s Go to newer text state about {N} seconds later. :lat[er] {N}m Go to newer text state about {N} minutes later. :lat[er] {N}h Go to newer text state about {N} hours later. diff --git a/runtime/doc/usr_10.txt b/runtime/doc/usr_10.txt index 3e45fda882..2f55aadef0 100644 --- a/runtime/doc/usr_10.txt +++ b/runtime/doc/usr_10.txt @@ -736,6 +736,11 @@ The "!!" command filters the current line through a filter. In Unix the "date" command prints the current time and date. "!!date<Enter>" replaces the current line with the output of "date". This is useful to add a timestamp to a file. +Note: There is a difference between "!cmd" (e.g. using it without any file +range) and "{range}!cmd". While the former will simply execute the external +command and Vim will show the output, the latter will filter {range}lines +through the filter and replace that range by the result of the filter command. +See |:!| and |:range!| for details. WHEN IT DOESN'T WORK diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index 8c7ed875cf..3202a70b76 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -906,6 +906,8 @@ Buffers, windows and the argument list: swapname() get the swap file path of a buffer Command line: *command-line-functions* + getcmdcomplpat() get completion pattern of the current command + line getcmdcompltype() get the type of the current command line completion getcmdline() get the current command line input diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt index 33da539c66..1ded5154a7 100644 --- a/runtime/doc/various.txt +++ b/runtime/doc/various.txt @@ -267,6 +267,7 @@ gx Opens the current filepath or URL (decided by < *:!cmd* *:!* :!{cmd} Execute {cmd} with 'shell'. See also |:terminal|. + For the filter command, see |:range!|. The command runs in a non-interactive shell connected to a pipe (not a terminal). Use |:terminal| to run an @@ -548,9 +549,9 @@ gO Show a filetype-specific, navigable "outline" of the If you use the less or more program to view a file, you don't get syntax highlighting. Thus you would like to use Vim instead. You can do this by -using the shell script "$VIMRUNTIME/macros/less.sh". +using the shell script "$VIMRUNTIME/scripts/less.sh". -This shell script uses the Vim script "$VIMRUNTIME/macros/less.vim". It sets +This shell script uses the Vim script "$VIMRUNTIME/scripts/less.vim". It sets up mappings to simulate the commands that less supports. Otherwise, you can still use the Vim commands. diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index e069678b30..8fa94a2601 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -150,6 +150,8 @@ of these in your config by simply removing the mapping, e.g. ":unmap Y". - |grn| - |grr| - |gra| + - |gri| + - |gO| - <C-S> |i_CTRL-S| - ]d |]d-default| - [d |[d-default| @@ -161,6 +163,7 @@ of these in your config by simply removing the mapping, e.g. ":unmap Y". - |[t|, |]t|, |[T|, |]T|, |[CTRL-T|, |]CTRL-T| - |[a|, |]a|, |[A|, |]A| - |[b|, |]b|, |[B|, |]B| +- |[<Space>|, |]<Space>| - Nvim LSP client defaults |lsp-defaults| - K |K-lsp-default| @@ -248,7 +251,7 @@ backwards-compatibility cost. Some examples: Some features are built in that otherwise required external plugins: -- Highlighting the yanked region, see |vim.highlight|. +- Highlighting the yanked region, see |vim.hl|. ARCHITECTURE @@ -338,10 +341,8 @@ Normal commands: Options: -Local values for global-local number/boolean options are unset when the option -is set without a scope (e.g. by using |:set|), similarly to how global-local -string options work. - +- `:set {option}<` removes local value for all |global-local| options. +- `:setlocal {option}<` copies global value to local value for all options. - 'autoread' works in the terminal (if it supports "focus" events) - 'cpoptions' flags: |cpo-_| - 'diffopt' "linematch" feature @@ -561,6 +562,9 @@ Highlight groups: the regexp `[a-zA-Z0-9_.@-]*` (see |group-name|). - |hl-StatusLineTerm| |hl-StatusLineTermNC| are implemented as 'winhighlight' window-local highlights which are set by the default |TermOpen| handler. +- The |ins-completion-menu| has cascading highlight styles. |hl-PmenuSel| and + |hl-PmenuMatch| both inherit from |hl-Pmenu|, and |hl-PmenuMatchSel| + inherits highlights from both |hl-PmenuSel| and |hl-PmenuMatch|. Macro (|recording|) behavior: - Replay of a macro recorded during :lmap produces the same actions as when it @@ -619,7 +623,12 @@ These legacy Vim features are not yet implemented: - *:gui* - *:gvim* +- *'browsedir'* *'bsdir'* - *'completepopup'* +- *'guioptions'* *'go'* +- *'guitablabel'* *'gtl'* +- *'guitabtooltip'* *'gtt'* +- *'mouseshape'* *'mouses'* - *'previewpopup'* ============================================================================== @@ -726,6 +735,8 @@ Options: CMD-v (macOS), middle-click, …). - *'imactivatefunc'* *'imaf'* - *'imactivatekey'* *'imak'* +- *'imcmdline'* *'imc'* *'noimcmdline'* *'noimc'* +- *'imdisable'* *'imd'* *'noimdisable'* *'noimd'* - *'imstatusfunc'* *'imsf'* - *'insertmode'* *'im'* Use the following script to emulate 'insertmode': >vim autocmd BufWinEnter * startinsert @@ -763,6 +774,7 @@ Options: 6 composing chars only. - *'maxmem'* Nvim delegates memory-management to the OS. - *'maxmemtot'* Nvim delegates memory-management to the OS. +- *'opendevice'* *'odev'* *'noopendevice'* *'noodev'* - printoptions - *'printdevice'* - *'printencoding'* @@ -797,6 +809,10 @@ Plugins: - logiPat - rrhelper - *vimball* +- macmap.vim +- tools/check_colors.vim +- macros/{justify,matchit,shellmenu,swapmous}.vim: use `packadd! justify` etc. + directly Providers: diff --git a/runtime/doc/vvars.txt b/runtime/doc/vvars.txt index 15d836a83d..0c349c4e57 100644 --- a/runtime/doc/vvars.txt +++ b/runtime/doc/vvars.txt @@ -152,13 +152,14 @@ v:event an aborting condition (e.g. |c_Esc| or |c_CTRL-C| for |CmdlineLeave|). chan |channel-id| + info Dict of arbitrary event data. cmdlevel Level of cmdline. cmdtype Type of cmdline, |cmdline-char|. cwd Current working directory. inclusive Motion is |inclusive|, else exclusive. scope Event-specific scope name. operator Current |operator|. Also set for Ex - commands (unlike |v:operator|). For + commands (unlike |v:operator|). For example if |TextYankPost| is triggered by the |:yank| Ex command then `v:event.operator` is "y". diff --git a/runtime/doc/windows.txt b/runtime/doc/windows.txt index 5729dd0874..24aa7b1b11 100644 --- a/runtime/doc/windows.txt +++ b/runtime/doc/windows.txt @@ -69,7 +69,8 @@ If a window is focusable, it is part of the "navigation stack", that is, editor commands such as :windo, |CTRL-W|, etc., will consider the window as one that can be made the "current window". A non-focusable window will be skipped by such commands (though it can be explicitly focused by -|nvim_set_current_win()|). +|nvim_set_current_win()|). Non-focusable windows are not listed by |:tabs|, and +are not counted by the default 'tabline'. Windows (especially floating windows) can have many other |api-win_config| properties such as "hide" and "fixed" which also affect behavior. diff --git a/runtime/ftplugin/ada.vim b/runtime/ftplugin/ada.vim index 688d912126..50e1388c80 100644 --- a/runtime/ftplugin/ada.vim +++ b/runtime/ftplugin/ada.vim @@ -103,7 +103,7 @@ endif if !exists ("b:match_words") && \ exists ("loaded_matchit") " - " The following lines enable the macros/matchit.vim plugin for + " The following lines enable the matchit.vim plugin for " Ada-specific extended matching with the % key. " let s:notend = '\%(\<end\s\+\)\@<!' diff --git a/runtime/ftplugin/checkhealth.vim b/runtime/ftplugin/checkhealth.vim index 62a1970b4a..00f24a2912 100644 --- a/runtime/ftplugin/checkhealth.vim +++ b/runtime/ftplugin/checkhealth.vim @@ -8,11 +8,11 @@ endif runtime! ftplugin/help.vim -setlocal wrap breakindent linebreak +setlocal wrap breakindent linebreak nolist let &l:iskeyword='!-~,^*,^|,^",192-255' if exists("b:undo_ftplugin") - let b:undo_ftplugin .= "|setl wrap< bri< lbr< kp< isk<" + let b:undo_ftplugin .= "|setl wrap< bri< lbr< kp< isk< list<" else - let b:undo_ftplugin = "setl wrap< bri< lbr< kp< isk<" + let b:undo_ftplugin = "setl wrap< bri< lbr< kp< isk< list<" endif diff --git a/runtime/ftplugin/cook.vim b/runtime/ftplugin/cook.vim new file mode 100644 index 0000000000..3697803e74 --- /dev/null +++ b/runtime/ftplugin/cook.vim @@ -0,0 +1,13 @@ +" Vim filetype plugin +" Language: Cooklang +" Maintainer: Riley Bruins <ribru17@gmail.com> +" Last Change: 2024 Nov 03 + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +setl comments=:-- commentstring=--\ %s + +let b:undo_ftplugin = 'setl com< cms<' diff --git a/runtime/ftplugin/dune.vim b/runtime/ftplugin/dune.vim index 6e20a8fabb..7608d53527 100644 --- a/runtime/ftplugin/dune.vim +++ b/runtime/ftplugin/dune.vim @@ -6,13 +6,14 @@ " 2023 Aug 28 - Added undo_ftplugin (Vim Project) " 2018 Nov 03 - Added commentstring (Markus Mottl) " 2017 Sep 06 - Initial version (Etienne Millon) +" 2024 Nov 09 - use setl instead of :set if exists("b:did_ftplugin") finish endif let b:did_ftplugin=1 -set lisp +setl lisp " Comment string setl commentstring=;\ %s diff --git a/runtime/ftplugin/erlang.vim b/runtime/ftplugin/erlang.vim index 5a3ab717d9..e82263d300 100644 --- a/runtime/ftplugin/erlang.vim +++ b/runtime/ftplugin/erlang.vim @@ -97,7 +97,7 @@ if !exists('*ErlangFoldText') endfunction endif -" The following lines enable the macros/matchit.vim plugin for extended +" The following lines enable the matchit.vim plugin for extended " matching with the % key. let b:match_ignorecase = 0 let b:match_words = diff --git a/runtime/ftplugin/gleam.vim b/runtime/ftplugin/gleam.vim new file mode 100644 index 0000000000..9ed607c4b3 --- /dev/null +++ b/runtime/ftplugin/gleam.vim @@ -0,0 +1,16 @@ +" Vim filetype plugin file +" Language: Gleam +" Maintainer: Trilowy (https://github.com/trilowy) +" Last Change: 2024 Oct 13 + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +setlocal comments=://,:///,://// +setlocal commentstring=//\ %s + +let b:undo_ftplugin = "setlocal comments< commentstring<" + +" vim: sw=2 sts=2 et diff --git a/runtime/ftplugin/idris2.vim b/runtime/ftplugin/idris2.vim new file mode 100644 index 0000000000..54e5acef90 --- /dev/null +++ b/runtime/ftplugin/idris2.vim @@ -0,0 +1,34 @@ +" Vim ftplugin file +" Language: Idris 2 +" Last Change: 2024 Nov 05 +" Maintainer: Idris Hackers (https://github.com/edwinb/idris2-vim), Serhii Khoma <srghma@gmail.com> +" License: Vim (see :h license) +" Repository: https://github.com/ShinKage/idris2-nvim +" +" Based on ftplugin/idris2.vim from https://github.com/edwinb/idris2-vim + +if exists("b:did_ftplugin") + finish +endif + +setlocal shiftwidth=2 +setlocal tabstop=2 + +" Set g:idris2#allow_tabchar = 1 to use tabs instead of spaces +if exists('g:idris2#allow_tabchar') && g:idris2#allow_tabchar != 0 + setlocal noexpandtab +else + setlocal expandtab +endif + +setlocal comments=s1:{-,mb:-,ex:-},:\|\|\|,:-- +setlocal commentstring=--\ %s + +" makes ? a part of a word, e.g. for named holes `vzipWith f [] [] = ?vzipWith_rhs_3`, uncomment if want to reenable +" setlocal iskeyword+=? + +setlocal wildignore+=*.ibc + +let b:undo_ftplugin = "setlocal shiftwidth< tabstop< expandtab< comments< commentstring< iskeyword< wildignore<" + +let b:did_ftplugin = 1 diff --git a/runtime/ftplugin/ipkg.vim b/runtime/ftplugin/ipkg.vim new file mode 100644 index 0000000000..70ae26ec17 --- /dev/null +++ b/runtime/ftplugin/ipkg.vim @@ -0,0 +1,19 @@ +" Vim ftplugin file +" Language: Ipkg +" Maintainer: Idris Hackers (https://github.com/edwinb/idris2-vim), Serhii Khoma <srghma@gmail.com> +" Last Change: 2024 Nov 05 +" Author: ShinKage +" License: Vim (see :h license) +" Repository: https://github.com/ShinKage/idris2-nvim + +if exists("b:did_ftplugin") + finish +endif + +setlocal comments=:-- +setlocal commentstring=--\ %s +setlocal wildignore+=*.ibc + +let b:undo_ftplugin = "setlocal shiftwidth< tabstop< expandtab< comments< commentstring< iskeyword< wildignore<" + +let b:did_ftplugin = 1 diff --git a/runtime/ftplugin/leo.vim b/runtime/ftplugin/leo.vim new file mode 100644 index 0000000000..a009c02df4 --- /dev/null +++ b/runtime/ftplugin/leo.vim @@ -0,0 +1,13 @@ +" Vim filetype plugin +" Language: Leo +" Maintainer: Riley Bruins <ribru17@gmail.com> +" Last Change: 2024 Nov 03 + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +setl comments=:// commentstring=//\ %s + +let b:undo_ftplugin = 'setl com< cms<' diff --git a/runtime/ftplugin/llvm.vim b/runtime/ftplugin/llvm.vim new file mode 100644 index 0000000000..148b12f102 --- /dev/null +++ b/runtime/ftplugin/llvm.vim @@ -0,0 +1,12 @@ +" Vim filetype plugin file +" Language: LLVM IR +" Last Change: 2024 Oct 22 +" Maintainer: Wu, Zhenyu <wuzhenyu@ustc.edu> + +if exists("b:did_ftplugin") | finish | endif +let b:did_ftplugin = 1 + +setl comments=:; +setl commentstring=;\ %s + +let b:undo_ftplugin = "setl commentstring< comments<" diff --git a/runtime/ftplugin/man.vim b/runtime/ftplugin/man.vim index 37667477f3..5ea36c32ce 100644 --- a/runtime/ftplugin/man.vim +++ b/runtime/ftplugin/man.vim @@ -26,11 +26,7 @@ if !exists('g:no_plugin_maps') && !exists('g:no_man_maps') nnoremap <silent> <buffer> k gk nnoremap <silent> <buffer> gO :lua require'man'.show_toc()<CR> nnoremap <silent> <buffer> <2-LeftMouse> :Man<CR> - if get(g:, 'pager') - nnoremap <silent> <buffer> <nowait> q :lclose<CR><C-W>q - else - nnoremap <silent> <buffer> <nowait> q :lclose<CR><C-W>c - endif + nnoremap <silent> <buffer> <nowait> q :lclose<CR><C-W>q endif if get(g:, 'ft_man_folding_enable', 0) diff --git a/runtime/ftplugin/mlir.vim b/runtime/ftplugin/mlir.vim new file mode 100644 index 0000000000..c6a9dc341f --- /dev/null +++ b/runtime/ftplugin/mlir.vim @@ -0,0 +1,10 @@ +" Vim filetype plugin file +" Language: MLIR + +if exists("b:did_ftplugin") | finish | endif +let b:did_ftplugin = 1 + +setl comments=:///,:// +setl commentstring=//\ %s + +let b:undo_ftplugin = "setl commentstring< comments<" diff --git a/runtime/ftplugin/mss.vim b/runtime/ftplugin/mss.vim new file mode 100644 index 0000000000..de2f8791ec --- /dev/null +++ b/runtime/ftplugin/mss.vim @@ -0,0 +1,16 @@ +" Vim filetype plugin file +" Language: Vivado mss file +" Last Change: 2024 Oct 22 +" Document: https://docs.amd.com/r/2020.2-English/ug1400-vitis-embedded/Microprocessor-Software-Specification-MSS +" Maintainer: Wu, Zhenyu <wuzhenyu@ustc.edu> + +if exists("b:did_ftplugin") + finish +endif +let b:did_ftplugin = 1 + +setlocal comments=b:#,fb:- +setlocal commentstring=#\ %s + +let b:match_words = '\<BEGIN\>:\<END\>' +let b:undo_ftplugin = "setl com< cms< | unlet b:match_words" diff --git a/runtime/ftplugin/org.vim b/runtime/ftplugin/org.vim new file mode 100644 index 0000000000..45a5e19d49 --- /dev/null +++ b/runtime/ftplugin/org.vim @@ -0,0 +1,37 @@ +" Vim filetype plugin file +" Language: Org +" Maintainer: Luca Saccarola <github.e41mv@aleeas.com> +" Last Change: 2024 Nov 14 + +if exists("b:did_ftplugin") + finish +endif +let b:did_ftplugin = 1 + +if exists('b:undo_ftplugin') + let b:undo_ftplugin .= "|setl cms< com< fo< flp<" +else + let b:undo_ftplugin = "setl cms< com< fo< flp<" +endif + +setl commentstring=#\ %s +setl comments=fb:*,fb:-,fb:+,b:#,b:\: + +setl formatoptions+=nql +setl formatlistpat=^\\s*\\(\\(\\d\\|\\a\\)\\+[.)]\\|[+-]\\)\\s\\+ + +function OrgFoldExpr() + let l:depth = match(getline(v:lnum), '\(^\*\+\)\@<=\( .*$\)\@=') + if l:depth > 0 && synIDattr(synID(v:lnum, 1, 1), 'name') =~# '\m^orgHeadline' + return ">" . l:depth + endif + return "=" +endfunction + +if has("folding") && get(g:, 'org_folding', 0) + setl foldexpr=OrgFoldExpr() + setl foldmethod=expr + let b:undo_ftplugin .= "|setl foldexpr< foldmethod<" +endif + +" vim: ts=8 sts=2 sw=2 et diff --git a/runtime/ftplugin/plaintex.vim b/runtime/ftplugin/plaintex.vim index 9e0e402680..17c1f5672f 100644 --- a/runtime/ftplugin/plaintex.vim +++ b/runtime/ftplugin/plaintex.vim @@ -22,7 +22,7 @@ let b:undo_ftplugin .= "| unlet! b:match_ignorecase b:match_skip b:match_words" let &l:define .= '\|\\new\(count\|dimen\|skip\|muskip\|box\|toks\|read\|write' \ . '\|fam\|insert\)' -" The following lines enable the macros/matchit.vim plugin for +" The following lines enable the matchit.vim plugin for " extended matching with the % key. " There is no default meaning for \(...\) etc., but many users define one. if exists("loaded_matchit") diff --git a/runtime/ftplugin/racket.vim b/runtime/ftplugin/racket.vim index 7bfd87ddc3..52768d67f5 100644 --- a/runtime/ftplugin/racket.vim +++ b/runtime/ftplugin/racket.vim @@ -3,7 +3,7 @@ " Maintainer: D. Ben Knoble <ben.knoble+github@gmail.com> " Previous Maintainer: Will Langstroth <will@langstroth.com> " URL: https://github.com/benknoble/vim-racket -" Last Change: 2024 May 28 +" Last Change: 2024 Jun 01 if exists("b:did_ftplugin") finish @@ -16,19 +16,20 @@ set cpo&vim " quick hack to allow adding values setlocal iskeyword=@,!,#-',*-:,<-Z,a-z,~,_,94 +setlocal shiftwidth=2 softtabstop=2 + " Enable auto begin new comment line when continuing from an old comment line setlocal comments=:;;;;,:;;;,:;;,:; setlocal formatoptions+=r -"setlocal commentstring=;;\ %s -setlocal commentstring=#\|\ %s\ \|# +setlocal commentstring=;;\ %s setlocal formatprg=raco\ fmt " Undo our settings when the filetype changes away from Racket " (this should be amended if settings/mappings are added above!) let b:undo_ftplugin = - \ "setlocal iskeyword< lispwords< lisp< comments< formatoptions< formatprg<" + \ "setlocal iskeyword< shiftwidth< softtabstop< comments< formatoptions< formatprg<" \. " | setlocal commentstring<" if !exists("no_plugin_maps") && !exists("no_racket_maps") diff --git a/runtime/ftplugin/spec.vim b/runtime/ftplugin/spec.vim index fa125be52c..4aaef26a2e 100644 --- a/runtime/ftplugin/spec.vim +++ b/runtime/ftplugin/spec.vim @@ -5,6 +5,7 @@ " Last Change: 2015 Jun 01 " Update by Zdenek Dohnal, 2022 May 17 " 2024 Sep 10 by Vim Project: add epoch support for spec changelog, #15537 +" 2024 Oct 07 by Vim Project: add comment support, #15817 if exists("b:did_ftplugin") finish @@ -14,6 +15,11 @@ let b:did_ftplugin = 1 let s:cpo_save = &cpo set cpo&vim +setlocal comments=b:# +setlocal commentstring=#\ %s + +let b:undo_ftplugin = "setlocal comments< commentstring<" + if !exists("no_plugin_maps") && !exists("no_spec_maps") if !hasmapto("<Plug>SpecChangelog") map <buffer> <LocalLeader>c <Plug>SpecChangelog @@ -204,7 +210,7 @@ if !exists("*s:ParseRpmVars") endfunction endif -" The following lines, along with the macros/matchit.vim plugin, +" The following lines, along with the matchit.vim plugin, " make it easy to navigate the different sections of a spec file " with the % key (thanks to Max Ischenko). @@ -216,4 +222,4 @@ let b:match_words = let &cpo = s:cpo_save unlet s:cpo_save -let b:undo_ftplugin = "unlet! b:match_ignorecase b:match_words" +let b:undo_ftplugin ..= " | unlet! b:match_ignorecase b:match_words" diff --git a/runtime/ftplugin/sway.vim b/runtime/ftplugin/sway.vim new file mode 100644 index 0000000000..35970b257c --- /dev/null +++ b/runtime/ftplugin/sway.vim @@ -0,0 +1,15 @@ +" Vim filetype plugin +" Language: Sway +" Maintainer: Riley Bruins <ribru17@gmail.com> +" Last Change: 2024 Nov 01 + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +setl commentstring=//\ %s +" From Rust comments +setl comments=s0:/*!,ex:*/,s1:/*,mb:*,ex:*/,:///,://!,:// + +let b:undo_ftplugin = 'setl com< cms<' diff --git a/runtime/ftplugin/tex.vim b/runtime/ftplugin/tex.vim index 0d68b51d46..7b58f67863 100644 --- a/runtime/ftplugin/tex.vim +++ b/runtime/ftplugin/tex.vim @@ -32,7 +32,7 @@ let &l:include .= '\|\\include{' " TeX file has \include{fname} (LaTeX only), strip everything except "fname". let &l:includeexpr = "substitute(v:fname, '^.\\{-}{\\|}.*', '', 'g')" -" The following lines enable the macros/matchit.vim plugin for +" The following lines enable the matchit.vim plugin for " extended matching with the % key. " ftplugin/plaintex.vim already defines b:match_skip and b:match_ignorecase " and matches \(, \), \[, \], \{, and \} . diff --git a/runtime/ftplugin/typst.vim b/runtime/ftplugin/typst.vim index 895fc688d9..3841e427f3 100644 --- a/runtime/ftplugin/typst.vim +++ b/runtime/ftplugin/typst.vim @@ -1,7 +1,7 @@ " Vim filetype plugin file " Language: Typst " Maintainer: Gregory Anders -" Last Change: 2024 Oct 04 +" Last Change: 2024 Oct 21 " Based on: https://github.com/kaarmu/typst.vim if exists('b:did_ftplugin') @@ -21,6 +21,12 @@ if get(g:, 'typst_conceal', 0) let b:undo_ftplugin .= ' cole<' endif +if has("folding") && get(g:, 'typst_folding', 0) + setlocal foldexpr=typst#foldexpr() + setlocal foldmethod=expr + let b:undo_ftplugin .= "|setl foldexpr< foldmethod<" +endif + if !exists('current_compiler') compiler typst let b:undo_ftplugin ..= "| compiler make" diff --git a/runtime/indent/idris2.vim b/runtime/indent/idris2.vim new file mode 100644 index 0000000000..d3c306e0a1 --- /dev/null +++ b/runtime/indent/idris2.vim @@ -0,0 +1,183 @@ +" Vim indent file +" Language: Idris 2 +" Maintainer: Idris Hackers (https://github.com/edwinb/idris2-vim), Serhii Khoma <srghma@gmail.com> +" Author: raichoo <raichoo@googlemail.com> +" Last Change: 2024 Nov 05 +" License: Vim (see :h license) +" Repository: https://github.com/ShinKage/idris2-nvim +" +" indentation for idris (idris-lang.org) +" +" Based on haskell indentation by motemen <motemen@gmail.com> +" +" Indentation configuration variables: +" +" g:idris2_indent_if (default: 3) +" Controls indentation after 'if' statements +" Example: +" if condition +" >>>then expr +" >>>else expr +" +" g:idris2_indent_case (default: 5) +" Controls indentation of case expressions +" Example: +" case x of +" >>>>>Left y => ... +" >>>>>Right z => ... +" +" g:idris2_indent_let (default: 4) +" Controls indentation after 'let' bindings +" Example: +" let x = expr in +" >>>>body +" +" g:idris2_indent_rewrite (default: 8) +" Controls indentation after 'rewrite' expressions +" Example: +" rewrite proof in +" >>>>>>>>expr +" +" g:idris2_indent_where (default: 6) +" Controls indentation of 'where' blocks +" Example: +" function args +" >>>>>>where helper = expr +" +" g:idris2_indent_do (default: 3) +" Controls indentation in 'do' blocks +" Example: +" do x <- action +" >>>y <- action +" +" Example configuration in .vimrc: +" let g:idris2_indent_if = 2 + +if exists('b:did_indent') + finish +endif + +setlocal indentexpr=GetIdrisIndent() +setlocal indentkeys=!^F,o,O,} + +let b:did_indent = 1 +let b:undo_indent = "setlocal indentexpr< indentkeys<" + +" we want to use line continuations (\) BEGINNING +let s:cpo_save = &cpo +set cpo&vim + +" Define defaults for indent configuration +let s:indent_defaults = { + \ 'idris2_indent_if': 3, + \ 'idris2_indent_case': 5, + \ 'idris2_indent_let': 4, + \ 'idris2_indent_rewrite': 8, + \ 'idris2_indent_where': 6, + \ 'idris2_indent_do': 3 + \ } + +" we want to use line continuations (\) END +let &cpo = s:cpo_save +unlet s:cpo_save + +" Set up indent settings with user overrides +for [key, default] in items(s:indent_defaults) + let varname = 'g:' . key + if !exists(varname) + execute 'let' varname '=' default + endif +endfor + +if exists("*GetIdrisIndent") + finish +endif + +function! GetIdrisIndent() + let prevline = getline(v:lnum - 1) + + if prevline =~ '\s\+(\s*.\+\s\+:\s\+.\+\s*)\s\+->\s*$' + return match(prevline, '(') + elseif prevline =~ '\s\+{\s*.\+\s\+:\s\+.\+\s*}\s\+->\s*$' + return match(prevline, '{') + endif + + if prevline =~ '[!#$%&*+./<>?@\\^|~-]\s*$' + let s = match(prevline, '[:=]') + if s > 0 + return s + 2 + else + return match(prevline, '\S') + endif + endif + + if prevline =~ '[{([][^})\]]\+$' + return match(prevline, '[{([]') + endif + + if prevline =~ '\<let\>\s\+.\+\<in\>\s*$' + return match(prevline, '\<let\>') + g:idris2_indent_let + endif + + if prevline =~ '\<rewrite\>\s\+.\+\<in\>\s*$' + return match(prevline, '\<rewrite\>') + g:idris2_indent_rewrite + endif + + if prevline !~ '\<else\>' + let s = match(prevline, '\<if\>.*\&.*\zs\<then\>') + if s > 0 + return s + endif + + let s = match(prevline, '\<if\>') + if s > 0 + return s + g:idris2_indent_if + endif + endif + + if prevline =~ '\(\<where\>\|\<do\>\|=\|[{([]\)\s*$' + return match(prevline, '\S') + &shiftwidth + endif + + if prevline =~ '\<where\>\s\+\S\+.*$' + return match(prevline, '\<where\>') + g:idris2_indent_where + endif + + if prevline =~ '\<do\>\s\+\S\+.*$' + return match(prevline, '\<do\>') + g:idris2_indent_do + endif + + if prevline =~ '^\s*\<\(co\)\?data\>\s\+[^=]\+\s\+=\s\+\S\+.*$' + return match(prevline, '=') + endif + + if prevline =~ '\<with\>\s\+([^)]*)\s*$' + return match(prevline, '\S') + &shiftwidth + endif + + if prevline =~ '\<case\>\s\+.\+\<of\>\s*$' + return match(prevline, '\<case\>') + g:idris2_indent_case + endif + + if prevline =~ '^\s*\(\<namespace\>\|\<\(co\)\?data\>\)\s\+\S\+\s*$' + return match(prevline, '\(\<namespace\>\|\<\(co\)\?data\>\)') + &shiftwidth + endif + + if prevline =~ '^\s*\(\<using\>\|\<parameters\>\)\s*([^(]*)\s*$' + return match(prevline, '\(\<using\>\|\<parameters\>\)') + &shiftwidth + endif + + if prevline =~ '^\s*\<mutual\>\s*$' + return match(prevline, '\<mutual\>') + &shiftwidth + endif + + let line = getline(v:lnum) + + if (line =~ '^\s*}\s*' && prevline !~ '^\s*;') + return match(prevline, '\S') - &shiftwidth + endif + + return match(prevline, '\S') +endfunction + +" vim:et:sw=2:sts=2 diff --git a/runtime/indent/racket.vim b/runtime/indent/racket.vim index d301cd64f9..2bab3f3bed 100644 --- a/runtime/indent/racket.vim +++ b/runtime/indent/racket.vim @@ -3,7 +3,7 @@ " Maintainer: D. Ben Knoble <ben.knoble+github@gmail.com> " Previous Maintainer: Will Langstroth <will@langstroth.com> " URL: https://github.com/benknoble/vim-racket -" Last Change: 2024 Jan 31 +" Last Change: 2024 Nov 12 if exists("b:did_indent") finish @@ -21,6 +21,7 @@ setlocal lispwords+=λ setlocal lispwords+=with-handlers setlocal lispwords+=define-values,opt-lambda,case-lambda,syntax-rules,with-syntax,syntax-case,syntax-parse setlocal lispwords+=define-for-syntax,define-syntax-parser,define-syntax-parse-rule,define-syntax-class,define-splicing-syntax-class +setlocal lispwords+=syntax/loc,quasisyntax/loc setlocal lispwords+=define-syntax-parameter,syntax-parameterize setlocal lispwords+=define-signature,unit,unit/sig,compund-unit/sig,define-values/invoke-unit/sig setlocal lispwords+=define-opt/c,define-syntax-rule @@ -30,6 +31,11 @@ setlocal lispwords+=with-input-from-file,with-output-to-file setlocal lispwords+=begin,begin0 setlocal lispwords+=place setlocal lispwords+=cond +" Racket style indents if like a function application: +" (if test +" then +" else) +setlocal lispwords-=if " Racket OOP " TODO missing a lot of define-like forms here (e.g., define/augment, etc.) @@ -50,6 +56,7 @@ setlocal lispwords+=for/set,for*/set setlocal lispwords+=for/first,for*/first setlocal lispwords+=for/last,for*/last setlocal lispwords+=for/stream,for*/stream +setlocal lispwords+=for/lists,for*/lists setlocal lispwords+=match,match*,match/values,define/match,match-lambda,match-lambda*,match-lambda** setlocal lispwords+=match-let,match-let*,match-let-values,match-let*-values @@ -66,4 +73,7 @@ setlocal lispwords+=if-view,case-view,cond-view,list-view,dyn-view setlocal lispwords+=case/dep setlocal lispwords+=define/obs +" rackunit +setlocal lispwords+=define-simple-check,define-binary-check,define-check,with-check-info + let b:undo_indent = "setlocal lisp< ai< si< lw<" .. (has('vim9script') ? ' indentexpr< lispoptions<' : '') diff --git a/runtime/indent/sh.vim b/runtime/indent/sh.vim index aa47c6d1bd..184e829873 100644 --- a/runtime/indent/sh.vim +++ b/runtime/indent/sh.vim @@ -7,6 +7,8 @@ " License: Vim (see :h license) " Repository: https://github.com/chrisbra/vim-sh-indent " Changelog: +" 20241411 - Detect dash character in function keyword for +" bash mode (issue #16049) " 20190726 - Correctly skip if keywords in syntax comments " (issue #17) " 20190603 - Do not indent in zsh filetypes with an `if` in comments @@ -195,7 +197,9 @@ endfunction function! s:is_function_definition(line) return a:line =~ '^\s*\<\k\+\>\s*()\s*{' || \ a:line =~ '^\s*{' || - \ a:line =~ '^\s*function\s*\k\+\s*\%(()\)\?\s*{' + \ a:line =~ '^\s*function\s*\k\+\s*\%(()\)\?\s*{' || + \ ((&ft is# 'zsh' || s:is_bash()) && + \ a:line =~ '^\s*function\s*\S\+\s*\%(()\)\?\s*{' ) endfunction function! s:is_array(line) diff --git a/runtime/indent/testdir/bash.in b/runtime/indent/testdir/bash.in new file mode 100644 index 0000000000..7ffcfc7a9d --- /dev/null +++ b/runtime/indent/testdir/bash.in @@ -0,0 +1,22 @@ +#!/bin/bash +# vim: set ft=bash sw=2 noet: + +# START_INDENT +a = 10 +b = 20 + +function add() { +c = $((a + b)) +} + +function print { +# do nothing +} + +if [[ $c -ge 15 ]]; +then +print("ok") +else +print("not ok") +fi +# END_INDENT diff --git a/runtime/indent/testdir/bash.ok b/runtime/indent/testdir/bash.ok new file mode 100644 index 0000000000..93d5b33c38 --- /dev/null +++ b/runtime/indent/testdir/bash.ok @@ -0,0 +1,22 @@ +#!/bin/bash +# vim: set ft=bash sw=2 noet: + +# START_INDENT +a = 10 +b = 20 + +function add() { + c = $((a + b)) +} + +function print { + # do nothing +} + +if [[ $c -ge 15 ]]; +then + print("ok") +else + print("not ok") +fi +# END_INDENT diff --git a/runtime/lua/man.lua b/runtime/lua/man.lua index fce8f89be8..114c94f9e5 100644 --- a/runtime/lua/man.lua +++ b/runtime/lua/man.lua @@ -305,7 +305,7 @@ local function matchstr(text, pat_or_re) return end - return text:sub(vim.str_utfindex(text, s) + 1, vim.str_utfindex(text, e)) + return text:sub(vim.str_utfindex(text, 'utf-32', s) + 1, vim.str_utfindex(text, 'utf-32', e)) end -- attempt to extract the name and sect out of 'name(sect)' @@ -675,7 +675,6 @@ function M.init_pager() vim.cmd.file({ 'man://' .. fn.fnameescape(ref):lower(), mods = { silent = true } }) end - vim.g.pager = true set_options() end diff --git a/runtime/lua/vim/_buf.lua b/runtime/lua/vim/_buf.lua new file mode 100644 index 0000000000..0631c96f77 --- /dev/null +++ b/runtime/lua/vim/_buf.lua @@ -0,0 +1,23 @@ +local M = {} + +--- Adds one or more blank lines above or below the cursor. +-- TODO: move to _defaults.lua once it is possible to assign a Lua function to options #25672 +--- @param above? boolean Place blank line(s) above the cursor +local function add_blank(above) + local offset = above and 1 or 0 + local repeated = vim.fn['repeat']({ '' }, vim.v.count1) + local linenr = vim.api.nvim_win_get_cursor(0)[1] + vim.api.nvim_buf_set_lines(0, linenr - offset, linenr - offset, true, repeated) +end + +-- TODO: move to _defaults.lua once it is possible to assign a Lua function to options #25672 +function M.space_above() + add_blank(true) +end + +-- TODO: move to _defaults.lua once it is possible to assign a Lua function to options #25672 +function M.space_below() + add_blank() +end + +return M diff --git a/runtime/lua/vim/_defaults.lua b/runtime/lua/vim/_defaults.lua index 6cad1dbca9..06f6ed6829 100644 --- a/runtime/lua/vim/_defaults.lua +++ b/runtime/lua/vim/_defaults.lua @@ -157,7 +157,7 @@ do --- client is attached. If no client is attached, or if a server does not support a capability, an --- error message is displayed rather than exhibiting different behavior. --- - --- See |grr|, |grn|, |gra|, |i_CTRL-S|. + --- See |grr|, |grn|, |gra|, |gri|, |gO|, |i_CTRL-S|. do vim.keymap.set('n', 'grn', function() vim.lsp.buf.rename() @@ -171,7 +171,15 @@ do vim.lsp.buf.references() end, { desc = 'vim.lsp.buf.references()' }) - vim.keymap.set('i', '<C-S>', function() + vim.keymap.set('n', 'gri', function() + vim.lsp.buf.implementation() + end, { desc = 'vim.lsp.buf.implementation()' }) + + vim.keymap.set('n', 'gO', function() + vim.lsp.buf.document_symbol() + end, { desc = 'vim.lsp.buf.document_symbol()' }) + + vim.keymap.set({ 'i', 's' }, '<C-S>', function() vim.lsp.buf.signature_help() end, { desc = 'vim.lsp.buf.signature_help()' }) end @@ -211,173 +219,163 @@ do --- vim-unimpaired style mappings. See: https://github.com/tpope/vim-unimpaired do + --- Execute a command and print errors without a stacktrace. + --- @param opts table Arguments to |nvim_cmd()| + local function cmd(opts) + local _, err = pcall(vim.api.nvim_cmd, opts, {}) + if err then + vim.api.nvim_err_writeln(err:sub(#'Vim:' + 1)) + end + end + -- Quickfix mappings vim.keymap.set('n', '[q', function() - vim.cmd.cprevious({ count = vim.v.count1 }) - end, { - desc = ':cprevious', - }) + cmd({ cmd = 'cprevious', count = vim.v.count1 }) + end, { desc = ':cprevious' }) vim.keymap.set('n', ']q', function() - vim.cmd.cnext({ count = vim.v.count1 }) - end, { - desc = ':cnext', - }) + cmd({ cmd = 'cnext', count = vim.v.count1 }) + end, { desc = ':cnext' }) vim.keymap.set('n', '[Q', function() - vim.cmd.crewind({ count = vim.v.count ~= 0 and vim.v.count or nil }) - end, { - desc = ':crewind', - }) + cmd({ cmd = 'crewind', count = vim.v.count ~= 0 and vim.v.count or nil }) + end, { desc = ':crewind' }) vim.keymap.set('n', ']Q', function() - vim.cmd.clast({ count = vim.v.count ~= 0 and vim.v.count or nil }) - end, { - desc = ':clast', - }) + cmd({ cmd = 'clast', count = vim.v.count ~= 0 and vim.v.count or nil }) + end, { desc = ':clast' }) vim.keymap.set('n', '[<C-Q>', function() - vim.cmd.cpfile({ count = vim.v.count1 }) - end, { - desc = ':cpfile', - }) + cmd({ cmd = 'cpfile', count = vim.v.count1 }) + end, { desc = ':cpfile' }) vim.keymap.set('n', ']<C-Q>', function() - vim.cmd.cnfile({ count = vim.v.count1 }) - end, { - desc = ':cnfile', - }) + cmd({ cmd = 'cnfile', count = vim.v.count1 }) + end, { desc = ':cnfile' }) -- Location list mappings vim.keymap.set('n', '[l', function() - vim.cmd.lprevious({ count = vim.v.count1 }) - end, { - desc = ':lprevious', - }) + cmd({ cmd = 'lprevious', count = vim.v.count1 }) + end, { desc = ':lprevious' }) vim.keymap.set('n', ']l', function() - vim.cmd.lnext({ count = vim.v.count1 }) - end, { - desc = ':lnext', - }) + cmd({ cmd = 'lnext', count = vim.v.count1 }) + end, { desc = ':lnext' }) vim.keymap.set('n', '[L', function() - vim.cmd.lrewind({ count = vim.v.count ~= 0 and vim.v.count or nil }) - end, { - desc = ':lrewind', - }) + cmd({ cmd = 'lrewind', count = vim.v.count ~= 0 and vim.v.count or nil }) + end, { desc = ':lrewind' }) vim.keymap.set('n', ']L', function() - vim.cmd.llast({ count = vim.v.count ~= 0 and vim.v.count or nil }) - end, { - desc = ':llast', - }) + cmd({ cmd = 'llast', count = vim.v.count ~= 0 and vim.v.count or nil }) + end, { desc = ':llast' }) vim.keymap.set('n', '[<C-L>', function() - vim.cmd.lpfile({ count = vim.v.count1 }) - end, { - desc = ':lpfile', - }) + cmd({ cmd = 'lpfile', count = vim.v.count1 }) + end, { desc = ':lpfile' }) vim.keymap.set('n', ']<C-L>', function() - vim.cmd.lnfile({ count = vim.v.count1 }) - end, { - desc = ':lnfile', - }) + cmd({ cmd = 'lnfile', count = vim.v.count1 }) + end, { desc = ':lnfile' }) -- Argument list vim.keymap.set('n', '[a', function() - vim.cmd.previous({ count = vim.v.count1 }) - end, { - desc = ':previous', - }) + cmd({ cmd = 'previous', count = vim.v.count1 }) + end, { desc = ':previous' }) vim.keymap.set('n', ']a', function() -- count doesn't work with :next, must use range. See #30641. - vim.cmd.next({ range = { vim.v.count1 } }) - end, { - desc = ':next', - }) + cmd({ cmd = 'next', range = { vim.v.count1 } }) + end, { desc = ':next' }) vim.keymap.set('n', '[A', function() if vim.v.count ~= 0 then - vim.cmd.argument({ count = vim.v.count }) + cmd({ cmd = 'argument', count = vim.v.count }) else - vim.cmd.rewind() + cmd({ cmd = 'rewind' }) end - end, { - desc = ':rewind', - }) + end, { desc = ':rewind' }) vim.keymap.set('n', ']A', function() if vim.v.count ~= 0 then - vim.cmd.argument({ count = vim.v.count }) + cmd({ cmd = 'argument', count = vim.v.count }) else - vim.cmd.last() + cmd({ cmd = 'last' }) end - end, { - desc = ':last', - }) + end, { desc = ':last' }) -- Tags vim.keymap.set('n', '[t', function() -- count doesn't work with :tprevious, must use range. See #30641. - vim.cmd.tprevious({ range = { vim.v.count1 } }) + cmd({ cmd = 'tprevious', range = { vim.v.count1 } }) end, { desc = ':tprevious' }) vim.keymap.set('n', ']t', function() -- count doesn't work with :tnext, must use range. See #30641. - vim.cmd.tnext({ range = { vim.v.count1 } }) + cmd({ cmd = 'tnext', range = { vim.v.count1 } }) end, { desc = ':tnext' }) vim.keymap.set('n', '[T', function() -- count doesn't work with :trewind, must use range. See #30641. - vim.cmd.trewind({ range = vim.v.count ~= 0 and { vim.v.count } or nil }) + cmd({ cmd = 'trewind', range = vim.v.count ~= 0 and { vim.v.count } or nil }) end, { desc = ':trewind' }) vim.keymap.set('n', ']T', function() -- :tlast does not accept a count, so use :trewind if count given if vim.v.count ~= 0 then - vim.cmd.trewind({ range = { vim.v.count } }) + cmd({ cmd = 'trewind', range = { vim.v.count } }) else - vim.cmd.tlast() + cmd({ cmd = 'tlast' }) end end, { desc = ':tlast' }) vim.keymap.set('n', '[<C-T>', function() -- count doesn't work with :ptprevious, must use range. See #30641. - vim.cmd.ptprevious({ range = { vim.v.count1 } }) + cmd({ cmd = 'ptprevious', range = { vim.v.count1 } }) end, { desc = ' :ptprevious' }) vim.keymap.set('n', ']<C-T>', function() -- count doesn't work with :ptnext, must use range. See #30641. - vim.cmd.ptnext({ range = { vim.v.count1 } }) + cmd({ cmd = 'ptnext', range = { vim.v.count1 } }) end, { desc = ':ptnext' }) -- Buffers vim.keymap.set('n', '[b', function() - vim.cmd.bprevious({ count = vim.v.count1 }) + cmd({ cmd = 'bprevious', count = vim.v.count1 }) end, { desc = ':bprevious' }) vim.keymap.set('n', ']b', function() - vim.cmd.bnext({ count = vim.v.count1 }) + cmd({ cmd = 'bnext', count = vim.v.count1 }) end, { desc = ':bnext' }) vim.keymap.set('n', '[B', function() if vim.v.count ~= 0 then - vim.cmd.buffer({ count = vim.v.count }) + cmd({ cmd = 'buffer', count = vim.v.count }) else - vim.cmd.brewind() + cmd({ cmd = 'brewind' }) end end, { desc = ':brewind' }) vim.keymap.set('n', ']B', function() if vim.v.count ~= 0 then - vim.cmd.buffer({ count = vim.v.count }) + cmd({ cmd = 'buffer', count = vim.v.count }) else - vim.cmd.blast() + cmd({ cmd = 'blast' }) end end, { desc = ':blast' }) + + -- Add empty lines + vim.keymap.set('n', '[<Space>', function() + -- TODO: update once it is possible to assign a Lua function to options #25672 + vim.go.operatorfunc = "v:lua.require'vim._buf'.space_above" + return 'g@l' + end, { expr = true, desc = 'Add empty line above cursor' }) + + vim.keymap.set('n', ']<Space>', function() + -- TODO: update once it is possible to assign a Lua function to options #25672 + vim.go.operatorfunc = "v:lua.require'vim._buf'.space_below" + return 'g@l' + end, { expr = true, desc = 'Add empty line below cursor' }) end end diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 2e829578a7..44f17b3f85 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -32,7 +32,7 @@ for k, v in pairs({ func = true, F = true, lsp = true, - highlight = true, + hl = true, diagnostic = true, keymap = true, ui = true, @@ -68,6 +68,12 @@ vim.log = { }, } +local utfs = { + ['utf-8'] = true, + ['utf-16'] = true, + ['utf-32'] = true, +} + -- TODO(lewis6991): document that the signature is system({cmd}, [{opts},] {on_exit}) --- Runs a system command or throws an error if {cmd} cannot be run. --- @@ -467,15 +473,11 @@ vim.cmd = setmetatable({}, { -- These are the vim.env/v/g/o/bo/wo variable magic accessors. do - local validate = vim.validate - --- @param scope string --- @param handle? false|integer --- @return vim.var_accessor local function make_dict_accessor(scope, handle) - validate({ - scope = { scope, 's' }, - }) + vim.validate('scope', scope, 'string') local mt = {} function mt:__newindex(k, v) return vim._setvar(scope, handle or 0, k, v) @@ -543,7 +545,7 @@ function vim.region(bufnr, pos1, pos2, regtype, inclusive) -- TODO: handle double-width characters if regtype:byte() == 22 then local bufline = vim.api.nvim_buf_get_lines(bufnr, pos1[1], pos1[1] + 1, true)[1] - pos1[2] = vim.str_utfindex(bufline, pos1[2]) + pos1[2] = vim.str_utfindex(bufline, 'utf-32', pos1[2]) end local region = {} @@ -555,14 +557,14 @@ function vim.region(bufnr, pos1, pos2, regtype, inclusive) c2 = c1 + tonumber(regtype:sub(2)) -- and adjust for non-ASCII characters local bufline = vim.api.nvim_buf_get_lines(bufnr, l, l + 1, true)[1] - local utflen = vim.str_utfindex(bufline, #bufline) + local utflen = vim.str_utfindex(bufline, 'utf-32', #bufline) if c1 <= utflen then - c1 = assert(tonumber(vim.str_byteindex(bufline, c1))) + c1 = assert(tonumber(vim.str_byteindex(bufline, 'utf-32', c1))) else c1 = #bufline + 1 end if c2 <= utflen then - c2 = assert(tonumber(vim.str_byteindex(bufline, c2))) + c2 = assert(tonumber(vim.str_byteindex(bufline, 'utf-32', c2))) else c2 = #bufline + 1 end @@ -591,7 +593,7 @@ end ---@param timeout integer Number of milliseconds to wait before calling `fn` ---@return table timer luv timer object function vim.defer_fn(fn, timeout) - vim.validate({ fn = { fn, 'c', true } }) + vim.validate('fn', fn, 'callable', true) local timer = assert(vim.uv.new_timer()) timer:start( timeout, @@ -649,7 +651,7 @@ do end end -local on_key_cbs = {} --- @type table<integer,function> +local on_key_cbs = {} --- @type table<integer,[function, table]> --- Adds Lua function {fn} with namespace id {ns_id} as a listener to every, --- yes every, input key. @@ -658,64 +660,225 @@ local on_key_cbs = {} --- @type table<integer,function> --- and cannot be toggled dynamically. --- ---@note {fn} will be removed on error. +---@note {fn} won't be invoked recursively, i.e. if {fn} itself consumes input, +--- it won't be invoked for those keys. ---@note {fn} will not be cleared by |nvim_buf_clear_namespace()| --- ----@param fn fun(key: string, typed: string)? ---- Function invoked on every key press. |i_CTRL-V| ---- {key} is the key after mappings have been applied, and ---- {typed} is the key(s) before mappings are applied, which ---- may be empty if {key} is produced by non-typed keys. ---- When {fn} is nil and {ns_id} is specified, the callback ---- associated with namespace {ns_id} is removed. +---@param fn nil|fun(key: string, typed: string): string? Function invoked for every input key, +--- after mappings have been applied but before further processing. Arguments +--- {key} and {typed} are raw keycodes, where {key} is the key after mappings +--- are applied, and {typed} is the key(s) before mappings are applied. +--- {typed} may be empty if {key} is produced by non-typed key(s) or by the +--- same typed key(s) that produced a previous {key}. +--- If {fn} returns an empty string, {key} is discarded/ignored. +--- When {fn} is `nil`, the callback associated with namespace {ns_id} is removed. ---@param ns_id integer? Namespace ID. If nil or 0, generates and returns a ---- new |nvim_create_namespace()| id. +--- new |nvim_create_namespace()| id. +---@param opts table? Optional parameters +--- +---@see |keytrans()| --- ---@return integer Namespace id associated with {fn}. Or count of all callbacks ---if on_key() is called without arguments. -function vim.on_key(fn, ns_id) +function vim.on_key(fn, ns_id, opts) if fn == nil and ns_id == nil then return vim.tbl_count(on_key_cbs) end - vim.validate({ - fn = { fn, 'c', true }, - ns_id = { ns_id, 'n', true }, - }) + vim.validate('fn', fn, 'callable', true) + vim.validate('ns_id', ns_id, 'number', true) + vim.validate('opts', opts, 'table', true) + opts = opts or {} if ns_id == nil or ns_id == 0 then ns_id = vim.api.nvim_create_namespace('') end - on_key_cbs[ns_id] = fn + on_key_cbs[ns_id] = fn and { fn, opts } return ns_id end --- Executes the on_key callbacks. ---@private function vim._on_key(buf, typed_buf) - local failed_ns_ids = {} - local failed_messages = {} + local failed = {} ---@type [integer, string][] + local discard = false for k, v in pairs(on_key_cbs) do - local ok, err_msg = pcall(v, buf, typed_buf) + local fn = v[1] + local ok, rv = xpcall(function() + return fn(buf, typed_buf) + end, debug.traceback) + if ok and rv ~= nil then + if type(rv) == 'string' and #rv == 0 then + discard = true + -- break -- Without break deliver to all callbacks even when it eventually discards. + -- "break" does not make sense unless callbacks are sorted by ???. + else + ok = false + rv = 'return string must be empty' + end + end if not ok then vim.on_key(nil, k) - table.insert(failed_ns_ids, k) - table.insert(failed_messages, err_msg) + table.insert(failed, { k, rv }) + end + end + + if #failed > 0 then + local errmsg = '' + for _, v in ipairs(failed) do + errmsg = errmsg .. string.format('\nWith ns_id %d: %s', v[1], v[2]) + end + error(errmsg) + end + return discard +end + +--- Convert UTF-32, UTF-16 or UTF-8 {index} to byte index. +--- If {strict_indexing} is false +--- then then an out of range index will return byte length +--- instead of throwing an error. +--- +--- Invalid UTF-8 and NUL is treated like in |vim.str_utfindex()|. +--- An {index} in the middle of a UTF-16 sequence is rounded upwards to +--- the end of that sequence. +---@param s string +---@param encoding "utf-8"|"utf-16"|"utf-32" +---@param index integer +---@param strict_indexing? boolean # default: true +---@return integer +function vim.str_byteindex(s, encoding, index, strict_indexing) + if type(encoding) == 'number' then + -- Legacy support for old API + -- Parameters: ~ + -- • {str} (`string`) + -- • {index} (`integer`) + -- • {use_utf16} (`boolean?`) + vim.deprecate( + 'vim.str_byteindex', + 'vim.str_byteindex(s, encoding, index, strict_indexing)', + '1.0' + ) + local old_index = encoding + local use_utf16 = index or false + return vim._str_byteindex(s, old_index, use_utf16) or error('index out of range') + end + + -- Avoid vim.validate for performance. + if type(s) ~= 'string' or type(index) ~= 'number' then + vim.validate('s', s, 'string') + vim.validate('index', index, 'number') + end + + local len = #s + + if index == 0 or len == 0 then + return 0 + end + + if not utfs[encoding] then + vim.validate('encoding', encoding, function(v) + return utfs[v], 'invalid encoding' + end) + end + + if strict_indexing ~= nil and type(strict_indexing) ~= 'boolean' then + vim.validate('strict_indexing', strict_indexing, 'boolean', true) + end + if strict_indexing == nil then + strict_indexing = true + end + + if encoding == 'utf-8' then + if index > len then + return strict_indexing and error('index out of range') or len end + return index end + return vim._str_byteindex(s, index, encoding == 'utf-16') + or strict_indexing and error('index out of range') + or len +end - if failed_ns_ids[1] then - error( - string.format( - "Error executing 'on_key' with ns_ids '%s'\n Messages: %s", - table.concat(failed_ns_ids, ', '), - table.concat(failed_messages, '\n') - ) +--- Convert byte index to UTF-32, UTF-16 or UTF-8 indices. If {index} is not +--- supplied, the length of the string is used. All indices are zero-based. +--- +--- If {strict_indexing} is false then an out of range index will return string +--- length instead of throwing an error. +--- Invalid UTF-8 bytes, and embedded surrogates are counted as one code point +--- each. An {index} in the middle of a UTF-8 sequence is rounded upwards to the end of +--- that sequence. +---@param s string +---@param encoding "utf-8"|"utf-16"|"utf-32" +---@param index? integer +---@param strict_indexing? boolean # default: true +---@return integer +function vim.str_utfindex(s, encoding, index, strict_indexing) + if encoding == nil or type(encoding) == 'number' then + -- Legacy support for old API + -- Parameters: ~ + -- • {str} (`string`) + -- • {index} (`integer?`) + vim.deprecate( + 'vim.str_utfindex', + 'vim.str_utfindex(s, encoding, index, strict_indexing)', + '1.0' ) + local old_index = encoding + local col32, col16 = vim._str_utfindex(s, old_index) --[[@as integer,integer]] + if not col32 or not col16 then + error('index out of range') + end + -- Return (multiple): ~ + -- (`integer`) UTF-32 index + -- (`integer`) UTF-16 index + return col32, col16 + end + + if type(s) ~= 'string' or (index ~= nil and type(index) ~= 'number') then + vim.validate('s', s, 'string') + vim.validate('index', index, 'number', true) + end + + if not index then + index = math.huge + strict_indexing = false + end + + if index == 0 then + return 0 + end + + if not utfs[encoding] then + vim.validate('encoding', encoding, function(v) + return utfs[v], 'invalid encoding' + end) end + + if strict_indexing ~= nil and type(strict_indexing) ~= 'boolean' then + vim.validate('strict_indexing', strict_indexing, 'boolean', true) + end + if strict_indexing == nil then + strict_indexing = true + end + + if encoding == 'utf-8' then + local len = #s + return index <= len and index or (strict_indexing and error('index out of range') or len) + end + local col32, col16 = vim._str_utfindex(s, index) --[[@as integer?,integer?]] + local col = encoding == 'utf-16' and col16 or col32 + if col then + return col + end + if strict_indexing then + error('index out of range') + end + local max32, max16 = vim._str_utfindex(s)--[[@as integer integer]] + return encoding == 'utf-16' and max16 or max32 end ---- Generates a list of possible completions for the string. +--- Generates a list of possible completions for the str --- String has the pattern. --- --- 1. Can we get it to just return things in the global namespace with that name prefix @@ -988,21 +1151,16 @@ end --- @param ... any --- @return any # given arguments. function vim.print(...) - if vim.in_fast_event() then - print(...) - return ... - end - + local msg = {} for i = 1, select('#', ...) do local o = select(i, ...) if type(o) == 'string' then - vim.api.nvim_out_write(o) + table.insert(msg, o) else - vim.api.nvim_out_write(vim.inspect(o, { newline = '\n', indent = ' ' })) + table.insert(msg, vim.inspect(o, { newline = '\n', indent = ' ' })) end - vim.api.nvim_out_write('\n') end - + print(table.concat(msg, '\n')) return ... end @@ -1146,16 +1304,22 @@ function vim.deprecate(name, alternative, version, plugin, backtrace) if plugin == 'Nvim' then require('vim.deprecated.health').add(name, version, traceback(), alternative) - -- Only issue warning if feature is hard-deprecated as specified by MAINTAIN.md. - -- Example: if removal_version is 0.12 (soft-deprecated since 0.10-dev), show warnings starting at - -- 0.11, including 0.11-dev + -- Show a warning only if feature is hard-deprecated (see MAINTAIN.md). + -- Example: if removal `version` is 0.12 (soft-deprecated since 0.10-dev), show warnings + -- starting at 0.11, including 0.11-dev. local major, minor = version:match('(%d+)%.(%d+)') major, minor = tonumber(major), tonumber(minor) + local nvim_major = 0 --- Current Nvim major version. + + -- We can't "subtract" from a major version, so: + -- * Always treat `major > nvim_major` as soft-deprecation. + -- * Compare `minor - 1` if `major == nvim_major`. + if major > nvim_major then + return -- Always soft-deprecation (see MAINTAIN.md). + end local hard_deprecated_since = string.format('nvim-%d.%d', major, minor - 1) - -- Assume there will be no next minor version before bumping up the major version - local is_hard_deprecated = minor == 0 or vim.fn.has(hard_deprecated_since) == 1 - if not is_hard_deprecated then + if major == nvim_major and vim.fn.has(hard_deprecated_since) == 0 then return end @@ -1166,12 +1330,10 @@ function vim.deprecate(name, alternative, version, plugin, backtrace) local displayed = vim._truncated_echo_once(msg) return displayed and msg or nil else - vim.validate { - name = { name, 'string' }, - alternative = { alternative, 'string', true }, - version = { version, 'string', true }, - plugin = { plugin, 'string', true }, - } + vim.validate('name', name, 'string') + vim.validate('alternative', alternative, 'string', true) + vim.validate('version', version, 'string', true) + vim.validate('plugin', plugin, 'string', true) local msg = ('%s is deprecated'):format(name) msg = alternative and ('%s, use %s instead.'):format(msg, alternative) or (msg .. '.') @@ -1190,4 +1352,7 @@ require('vim._options') ---@deprecated vim.loop = vim.uv +-- Deprecated. Remove at Nvim 2.0 +vim.highlight = vim._defer_deprecated_module('vim.highlight', 'vim.hl') + return vim diff --git a/runtime/lua/vim/_meta.lua b/runtime/lua/vim/_meta.lua index c9f207cb20..f8672d1f1f 100644 --- a/runtime/lua/vim/_meta.lua +++ b/runtime/lua/vim/_meta.lua @@ -15,7 +15,7 @@ vim.fs = require('vim.fs') vim.func = require('vim.func') vim.glob = require('vim.glob') vim.health = require('vim.health') -vim.highlight = require('vim.highlight') +vim.hl = require('vim.hl') vim.iter = require('vim.iter') vim.keymap = require('vim.keymap') vim.loader = require('vim.loader') diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index c66b295d3a..3c9b9d4f44 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -592,8 +592,9 @@ function vim.api.nvim_buf_line_count(buffer) end --- - id : id of the extmark to edit. --- - end_row : ending line of the mark, 0-based inclusive. --- - end_col : ending col of the mark, 0-based exclusive. ---- - hl_group : name of the highlight group used to highlight ---- this mark. +--- - hl_group : highlight group used for the text range. This and below +--- highlight groups can be supplied either as a string or as an integer, +--- the latter of which can be obtained using `nvim_get_hl_id_by_name()`. --- - hl_eol : when true, for a multiline highlight covering the --- EOL of a line, continue the highlight for the rest --- of the screen line (just like for diff and @@ -603,9 +604,7 @@ function vim.api.nvim_buf_line_count(buffer) end --- text chunk with specified highlight. `highlight` element --- can either be a single highlight group, or an array of --- multiple highlight groups that will be stacked ---- (highest priority last). A highlight group can be supplied ---- either as a string or as an integer, the latter which ---- can be obtained using `nvim_get_hl_id_by_name()`. +--- (highest priority last). --- - virt_text_pos : position of virtual text. Possible values: --- - "eol": right after eol character (default). --- - "overlay": display over the specified column, without @@ -676,15 +675,12 @@ function vim.api.nvim_buf_line_count(buffer) end --- buffer or end of the line respectively. Defaults to true. --- - sign_text: string of length 1-2 used to display in the --- sign column. ---- - sign_hl_group: name of the highlight group used to ---- highlight the sign column text. ---- - number_hl_group: name of the highlight group used to ---- highlight the number column. ---- - line_hl_group: name of the highlight group used to ---- highlight the whole line. ---- - cursorline_hl_group: name of the highlight group used to ---- highlight the sign column text when the cursor is on ---- the same line as the mark and 'cursorline' is enabled. +--- - sign_hl_group: highlight group used for the sign column text. +--- - number_hl_group: highlight group used for the number column. +--- - line_hl_group: highlight group used for the whole line. +--- - cursorline_hl_group: highlight group used for the sign +--- column text when the cursor is on the same line as the +--- mark and 'cursorline' is enabled. --- - conceal: string which should be either empty or a single --- character. Enable concealing similar to `:syn-conceal`. --- When a character is supplied it is used as `:syn-cchar`. @@ -1106,12 +1102,12 @@ function vim.api.nvim_del_var(name) end --- Echo a message. --- --- @param chunks any[] A list of `[text, hl_group]` arrays, each representing a ---- text chunk with specified highlight. `hl_group` element ---- can be omitted for no highlight. +--- text chunk with specified highlight group name or ID. +--- `hl_group` element can be omitted for no highlight. --- @param history boolean if true, add to `message-history`. --- @param opts vim.api.keyset.echo_opts Optional parameters. ---- - verbose: Message was printed as a result of 'verbose' option ---- if Nvim was invoked with -V3log_file, the message will be +--- - verbose: Message is printed as a result of 'verbose' option. +--- If Nvim was invoked with -V3log_file, the message will be --- redirected to the log_file and suppressed from direct output. function vim.api.nvim_echo(chunks, history, opts) end @@ -1767,7 +1763,12 @@ function vim.api.nvim_open_term(buffer, opts) end --- fractional. --- - focusable: Enable focus by user actions (wincmds, mouse events). --- Defaults to true. Non-focusable windows can be entered by ---- `nvim_set_current_win()`. +--- `nvim_set_current_win()`, or, when the `mouse` field is set to true, +--- by mouse events. See `focusable`. +--- - mouse: Specify how this window interacts with mouse events. +--- Defaults to `focusable` value. +--- - If false, mouse events pass through this window. +--- - If true, mouse events interact with this window normally. --- - external: GUI should display the window as an external --- top-level window. Currently accepts no other positioning --- configuration together with this. diff --git a/runtime/lua/vim/_meta/api_keysets.lua b/runtime/lua/vim/_meta/api_keysets.lua index 2fe5c32faf..bf184dee2d 100644 --- a/runtime/lua/vim/_meta/api_keysets.lua +++ b/runtime/lua/vim/_meta/api_keysets.lua @@ -295,6 +295,7 @@ error('Cannot require a meta file') --- @field bufpos? any[] --- @field external? boolean --- @field focusable? boolean +--- @field mouse? boolean --- @field vertical? boolean --- @field zindex? integer --- @field border? any diff --git a/runtime/lua/vim/_meta/builtin.lua b/runtime/lua/vim/_meta/builtin.lua index 13bd1c1294..b8779b66fe 100644 --- a/runtime/lua/vim/_meta/builtin.lua +++ b/runtime/lua/vim/_meta/builtin.lua @@ -112,18 +112,6 @@ function vim.rpcrequest(channel, method, ...) end --- equal, {a} is greater than {b} or {a} is lesser than {b}, respectively. function vim.stricmp(a, b) end ---- Convert UTF-32 or UTF-16 {index} to byte index. If {use_utf16} is not ---- supplied, it defaults to false (use UTF-32). Returns the byte index. ---- ---- Invalid UTF-8 and NUL is treated like in |vim.str_utfindex()|. ---- An {index} in the middle of a UTF-16 sequence is rounded upwards to ---- the end of that sequence. ---- @param str string ---- @param index integer ---- @param use_utf16? boolean ---- @return integer -function vim.str_byteindex(str, index, use_utf16) end - --- Gets a list of the starting byte positions of each UTF-8 codepoint in the given string. --- --- Embedded NUL bytes are treated as terminating the string. @@ -173,19 +161,6 @@ function vim.str_utf_start(str, index) end --- @return integer function vim.str_utf_end(str, index) end ---- Convert byte index to UTF-32 and UTF-16 indices. If {index} is not ---- supplied, the length of the string is used. All indices are zero-based. ---- ---- Embedded NUL bytes are treated as terminating the string. Invalid UTF-8 ---- bytes, and embedded surrogates are counted as one code point each. An ---- {index} in the middle of a UTF-8 sequence is rounded upwards to the end of ---- that sequence. ---- @param str string ---- @param index? integer ---- @return integer # UTF-32 index ---- @return integer # UTF-16 index -function vim.str_utfindex(str, index) end - --- The result is a String, which is the text {str} converted from --- encoding {from} to encoding {to}. When the conversion fails `nil` is --- returned. When some characters could not be converted they @@ -258,6 +233,12 @@ function vim.wait(time, callback, interval, fast_only) end --- {callback} receives event name plus additional parameters. See |ui-popupmenu| --- and the sections below for event format for respective events. --- +--- Callbacks for `msg_show` events are executed in |api-fast| context unless +--- Nvim will wait for input, in which case messages should be shown +--- immediately. +--- +--- Excessive errors inside the callback will result in forced detachment. +--- --- WARNING: This api is considered experimental. Usability will vary for --- different screen elements. In particular `ext_messages` behavior is subject --- to further changes and usability improvements. This is expected to be diff --git a/runtime/lua/vim/_meta/builtin_types.lua b/runtime/lua/vim/_meta/builtin_types.lua index aca6649957..eae76d80d7 100644 --- a/runtime/lua/vim/_meta/builtin_types.lua +++ b/runtime/lua/vim/_meta/builtin_types.lua @@ -66,6 +66,97 @@ --- @field winnr integer --- @field winrow integer +--- @class vim.quickfix.entry +--- buffer number; must be the number of a valid buffer +--- @field bufnr? integer +--- +--- name of a file; only used when "bufnr" is not +--- present or it is invalid. +--- @field filename? string +--- +--- name of a module; if given it will be used in +--- quickfix error window instead of the filename. +--- @field module? string +--- +--- line number in the file +--- @field lnum? integer +--- +--- end of lines, if the item spans multiple lines +--- @field end_lnum? integer +--- +--- search pattern used to locate the error +--- @field pattern? string +--- +--- column number +--- @field col? integer +--- +--- when non-zero: "col" is visual column +--- when zero: "col" is byte index +--- @field vcol? integer +--- +--- end column, if the item spans multiple columns +--- @field end_col? integer +--- +--- error number +--- @field nr? integer +--- +--- description of the error +--- @field text? string +--- +--- single-character error type, 'E', 'W', etc. +--- @field type? string +--- +--- recognized error message +--- @field valid? boolean +--- +--- custom data associated with the item, can be +--- any type. +--- @field user_data? any + +--- @class vim.fn.setqflist.what +--- +--- quickfix list context. See |quickfix-context| +--- @field context? table +--- +--- errorformat to use when parsing text from +--- "lines". If this is not present, then the +--- 'errorformat' option value is used. +--- See |quickfix-parse| +--- @field efm? string +--- +--- quickfix list identifier |quickfix-ID| +--- @field id? integer +--- index of the current entry in the quickfix +--- list specified by "id" or "nr". If set to '$', +--- then the last entry in the list is set as the +--- current entry. See |quickfix-index| +--- @field idx? integer +--- +--- list of quickfix entries. Same as the {list} +--- argument. +--- @field items? vim.quickfix.entry[] +--- +--- use 'errorformat' to parse a list of lines and +--- add the resulting entries to the quickfix list +--- {nr} or {id}. Only a |List| value is supported. +--- See |quickfix-parse| +--- @field lines? string[] +--- +--- list number in the quickfix stack; zero +--- means the current quickfix list and "$" means +--- the last quickfix list. +--- @field nr? integer +--- +--- function to get the text to display in the +--- quickfix window. The value can be the name of +--- a function or a funcref or a lambda. Refer +--- to |quickfix-window-function| for an explanation +--- of how to write the function and an example. +--- @field quickfixtextfunc? function +--- +--- quickfix list title text. See |quickfix-title| +--- @field title? string + --- @class vim.fn.sign_define.dict --- @field text string --- @field icon? string diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua index ce3ff4f861..cb783720ac 100644 --- a/runtime/lua/vim/_meta/options.lua +++ b/runtime/lua/vim/_meta/options.lua @@ -289,12 +289,13 @@ vim.go.bk = vim.go.backup --- useful for example in source trees where all the files are symbolic or --- hard links and any changes should stay in the local source tree, not --- be propagated back to the original source. ---- *crontab* +--- *crontab* --- One situation where "no" and "auto" will cause problems: A program --- that opens a file, invokes Vim to edit that file, and then tests if --- the open file was changed (through the file descriptor) will check the --- backup file instead of the newly created file. "crontab -e" is an ---- example. +--- example, as are several `file-watcher` daemons like inotify. In that +--- case you probably want to switch this option. --- --- When a copy is made, the original file is truncated and then filled --- with the new text. This means that protection bits, owner and @@ -429,6 +430,7 @@ vim.go.bsk = vim.go.backupskip --- separated list of items. For each item that is present, the bell --- will be silenced. This is most useful to specify specific events in --- insert mode to be silenced. +--- You can also make it flash by using 'visualbell'. --- --- item meaning when present ~ --- all All events. @@ -452,6 +454,7 @@ vim.go.bsk = vim.go.backupskip --- register Unknown register after <C-R> in `Insert-mode`. --- shell Bell from shell output `:!`. --- spell Error happened on spell suggest. +--- term Bell from `:terminal` output. --- wildmode More matches in `cmdline-completion` available --- (depends on the 'wildmode' setting). --- @@ -572,19 +575,6 @@ vim.o.briopt = vim.o.breakindentopt vim.wo.breakindentopt = vim.o.breakindentopt vim.wo.briopt = vim.wo.breakindentopt ---- Which directory to use for the file browser: ---- last Use same directory as with last file browser, where a ---- file was opened or saved. ---- buffer Use the directory of the related buffer. ---- current Use the current directory. ---- {path} Use the specified directory ---- ---- @type string -vim.o.browsedir = "" -vim.o.bsdir = vim.o.browsedir -vim.go.browsedir = vim.o.browsedir -vim.go.bsdir = vim.go.browsedir - --- This option specifies what happens when a buffer is no longer --- displayed in a window: --- <empty> follow the global 'hidden' option @@ -1116,7 +1106,7 @@ vim.bo.cot = vim.bo.completeopt vim.go.completeopt = vim.o.completeopt vim.go.cot = vim.go.completeopt ---- only for MS-Windows +--- only modifiable in MS-Windows --- When this option is set it overrules 'shellslash' for completion: --- - When this option is set to "slash", a forward slash is used for path --- completion in insert mode. This is useful when editing HTML tag, or @@ -2304,6 +2294,62 @@ vim.wo.fcs = vim.wo.fillchars vim.go.fillchars = vim.o.fillchars vim.go.fcs = vim.go.fillchars +--- Function that is called to obtain the filename(s) for the `:find` +--- command. When this option is empty, the internal `file-searching` +--- mechanism is used. +--- +--- The value can be the name of a function, a `lambda` or a `Funcref`. +--- See `option-value-function` for more information. +--- +--- The function is called with two arguments. The first argument is a +--- `String` and is the `:find` command argument. The second argument is +--- a `Boolean` and is set to `v:true` when the function is called to get +--- a List of command-line completion matches for the `:find` command. +--- The function should return a List of strings. +--- +--- The function is called only once per `:find` command invocation. +--- The function can process all the directories specified in 'path'. +--- +--- If a match is found, the function should return a `List` containing +--- one or more file names. If a match is not found, the function +--- should return an empty List. +--- +--- If any errors are encountered during the function invocation, an +--- empty List is used as the return value. +--- +--- It is not allowed to change text or jump to another window while +--- executing the 'findfunc' `textlock`. +--- +--- This option cannot be set from a `modeline` or in the `sandbox`, for +--- security reasons. +--- +--- Examples: +--- +--- ```vim +--- " Use glob() +--- func FindFuncGlob(cmdarg, cmdcomplete) +--- let pat = a:cmdcomplete ? $'{a:cmdarg}*' : a:cmdarg +--- return glob(pat, v:false, v:true) +--- endfunc +--- set findfunc=FindFuncGlob +--- +--- " Use the 'git ls-files' output +--- func FindGitFiles(cmdarg, cmdcomplete) +--- let fnames = systemlist('git ls-files') +--- return fnames->filter('v:val =~? a:cmdarg') +--- endfunc +--- set findfunc=FindGitFiles +--- ``` +--- +--- +--- @type string +vim.o.findfunc = "" +vim.o.ffu = vim.o.findfunc +vim.bo.findfunc = vim.o.findfunc +vim.bo.ffu = vim.bo.findfunc +vim.go.findfunc = vim.o.findfunc +vim.go.ffu = vim.go.findfunc + --- When writing a file and this option is on, <EOL> at the end of file --- will be restored if missing. Turn this option off if you want to --- preserve the situation from the original file. @@ -2897,148 +2943,6 @@ vim.o.gfw = vim.o.guifontwide vim.go.guifontwide = vim.o.guifontwide vim.go.gfw = vim.go.guifontwide ---- This option only has an effect in the GUI version of Vim. It is a ---- sequence of letters which describes what components and options of the ---- GUI should be used. ---- To avoid problems with flags that are added in the future, use the ---- "+=" and "-=" feature of ":set" `add-option-flags`. ---- ---- Valid letters are as follows: ---- *guioptions_a* *'go-a'* ---- 'a' Autoselect: If present, then whenever VISUAL mode is started, ---- or the Visual area extended, Vim tries to become the owner of ---- the windowing system's global selection. This means that the ---- Visually highlighted text is available for pasting into other ---- applications as well as into Vim itself. When the Visual mode ---- ends, possibly due to an operation on the text, or when an ---- application wants to paste the selection, the highlighted text ---- is automatically yanked into the "* selection register. ---- Thus the selection is still available for pasting into other ---- applications after the VISUAL mode has ended. ---- If not present, then Vim won't become the owner of the ---- windowing system's global selection unless explicitly told to ---- by a yank or delete operation for the "* register. ---- The same applies to the modeless selection. ---- *'go-P'* ---- 'P' Like autoselect but using the "+ register instead of the "* ---- register. ---- *'go-A'* ---- 'A' Autoselect for the modeless selection. Like 'a', but only ---- applies to the modeless selection. ---- ---- 'guioptions' autoselect Visual autoselect modeless ~ ---- "" - - ---- "a" yes yes ---- "A" - yes ---- "aA" yes yes ---- ---- *'go-c'* ---- 'c' Use console dialogs instead of popup dialogs for simple ---- choices. ---- *'go-d'* ---- 'd' Use dark theme variant if available. ---- *'go-e'* ---- 'e' Add tab pages when indicated with 'showtabline'. ---- 'guitablabel' can be used to change the text in the labels. ---- When 'e' is missing a non-GUI tab pages line may be used. ---- The GUI tabs are only supported on some systems, currently ---- Mac OS/X and MS-Windows. ---- *'go-i'* ---- 'i' Use a Vim icon. ---- *'go-m'* ---- 'm' Menu bar is present. ---- *'go-M'* ---- 'M' The system menu "$VIMRUNTIME/menu.vim" is not sourced. Note ---- that this flag must be added in the vimrc file, before ---- switching on syntax or filetype recognition (when the `gvimrc` ---- file is sourced the system menu has already been loaded; the ---- `:syntax on` and `:filetype on` commands load the menu too). ---- *'go-g'* ---- 'g' Grey menu items: Make menu items that are not active grey. If ---- 'g' is not included inactive menu items are not shown at all. ---- *'go-T'* ---- 'T' Include Toolbar. Currently only in Win32 GUI. ---- *'go-r'* ---- 'r' Right-hand scrollbar is always present. ---- *'go-R'* ---- 'R' Right-hand scrollbar is present when there is a vertically ---- split window. ---- *'go-l'* ---- 'l' Left-hand scrollbar is always present. ---- *'go-L'* ---- 'L' Left-hand scrollbar is present when there is a vertically ---- split window. ---- *'go-b'* ---- 'b' Bottom (horizontal) scrollbar is present. Its size depends on ---- the longest visible line, or on the cursor line if the 'h' ---- flag is included. `gui-horiz-scroll` ---- *'go-h'* ---- 'h' Limit horizontal scrollbar size to the length of the cursor ---- line. Reduces computations. `gui-horiz-scroll` ---- ---- And yes, you may even have scrollbars on the left AND the right if ---- you really want to :-). See `gui-scrollbars` for more information. ---- ---- *'go-v'* ---- 'v' Use a vertical button layout for dialogs. When not included, ---- a horizontal layout is preferred, but when it doesn't fit a ---- vertical layout is used anyway. Not supported in GTK 3. ---- *'go-p'* ---- 'p' Use Pointer callbacks for X11 GUI. This is required for some ---- window managers. If the cursor is not blinking or hollow at ---- the right moment, try adding this flag. This must be done ---- before starting the GUI. Set it in your `gvimrc`. Adding or ---- removing it after the GUI has started has no effect. ---- *'go-k'* ---- 'k' Keep the GUI window size when adding/removing a scrollbar, or ---- toolbar, tabline, etc. Instead, the behavior is similar to ---- when the window is maximized and will adjust 'lines' and ---- 'columns' to fit to the window. Without the 'k' flag Vim will ---- try to keep 'lines' and 'columns' the same when adding and ---- removing GUI components. ---- ---- @type string -vim.o.guioptions = "" -vim.o.go = vim.o.guioptions -vim.go.guioptions = vim.o.guioptions -vim.go.go = vim.go.guioptions - ---- When non-empty describes the text to use in a label of the GUI tab ---- pages line. When empty and when the result is empty Vim will use a ---- default label. See `setting-guitablabel` for more info. ---- ---- The format of this option is like that of 'statusline'. ---- 'guitabtooltip' is used for the tooltip, see below. ---- The expression will be evaluated in the `sandbox` when set from a ---- modeline, see `sandbox-option`. ---- This option cannot be set in a modeline when 'modelineexpr' is off. ---- ---- Only used when the GUI tab pages line is displayed. 'e' must be ---- present in 'guioptions'. For the non-GUI tab pages line 'tabline' is ---- used. ---- ---- @type string -vim.o.guitablabel = "" -vim.o.gtl = vim.o.guitablabel -vim.go.guitablabel = vim.o.guitablabel -vim.go.gtl = vim.go.guitablabel - ---- When non-empty describes the text to use in a tooltip for the GUI tab ---- pages line. When empty Vim will use a default tooltip. ---- This option is otherwise just like 'guitablabel' above. ---- You can include a line break. Simplest method is to use `:let`: ---- ---- ```vim ---- let &guitabtooltip = "line one\nline two" ---- ``` ---- ---- ---- @type string -vim.o.guitabtooltip = "" -vim.o.gtt = vim.o.guitabtooltip -vim.go.guitabtooltip = vim.o.guitabtooltip -vim.go.gtt = vim.go.guitabtooltip - --- Name of the main help file. All distributed help files should be --- placed together in one directory. Additionally, all "doc" directories --- in 'runtimepath' will be used. @@ -3112,7 +3016,8 @@ vim.go.hid = vim.go.hidden --- A history of ":" commands, and a history of previous search patterns --- is remembered. This option decides how many entries may be stored in ---- each of these histories (see `cmdline-editing`). +--- each of these histories (see `cmdline-editing` and 'msghistory' for +--- the number of messages to remember). --- The maximum value is 10000. --- --- @type integer @@ -3181,29 +3086,6 @@ vim.o.ic = vim.o.ignorecase vim.go.ignorecase = vim.o.ignorecase vim.go.ic = vim.go.ignorecase ---- When set the Input Method is always on when starting to edit a command ---- line, unless entering a search pattern (see 'imsearch' for that). ---- Setting this option is useful when your input method allows entering ---- English characters directly, e.g., when it's used to type accented ---- characters with dead keys. ---- ---- @type boolean -vim.o.imcmdline = false -vim.o.imc = vim.o.imcmdline -vim.go.imcmdline = vim.o.imcmdline -vim.go.imc = vim.go.imcmdline - ---- When set the Input Method is never used. This is useful to disable ---- the IM when it doesn't work properly. ---- Currently this option is on by default for SGI/IRIX machines. This ---- may change in later releases. ---- ---- @type boolean -vim.o.imdisable = false -vim.o.imd = vim.o.imdisable -vim.go.imdisable = vim.o.imdisable -vim.go.imd = vim.go.imdisable - --- Specifies whether :lmap or an Input Method (IM) is to be used in --- Insert mode. Valid values: --- 0 :lmap is off and IM is off @@ -4488,74 +4370,6 @@ vim.go.mousemev = vim.go.mousemoveevent vim.o.mousescroll = "ver:3,hor:6" vim.go.mousescroll = vim.o.mousescroll ---- This option tells Vim what the mouse pointer should look like in ---- different modes. The option is a comma-separated list of parts, much ---- like used for 'guicursor'. Each part consist of a mode/location-list ---- and an argument-list: ---- mode-list:shape,mode-list:shape,.. ---- The mode-list is a dash separated list of these modes/locations: ---- In a normal window: ~ ---- n Normal mode ---- v Visual mode ---- ve Visual mode with 'selection' "exclusive" (same as 'v', ---- if not specified) ---- o Operator-pending mode ---- i Insert mode ---- r Replace mode ---- ---- Others: ~ ---- c appending to the command-line ---- ci inserting in the command-line ---- cr replacing in the command-line ---- m at the 'Hit ENTER' or 'More' prompts ---- ml idem, but cursor in the last line ---- e any mode, pointer below last window ---- s any mode, pointer on a status line ---- sd any mode, while dragging a status line ---- vs any mode, pointer on a vertical separator line ---- vd any mode, while dragging a vertical separator line ---- a everywhere ---- ---- The shape is one of the following: ---- avail name looks like ~ ---- w x arrow Normal mouse pointer ---- w x blank no pointer at all (use with care!) ---- w x beam I-beam ---- w x updown up-down sizing arrows ---- w x leftright left-right sizing arrows ---- w x busy The system's usual busy pointer ---- w x no The system's usual "no input" pointer ---- x udsizing indicates up-down resizing ---- x lrsizing indicates left-right resizing ---- x crosshair like a big thin + ---- x hand1 black hand ---- x hand2 white hand ---- x pencil what you write with ---- x question big ? ---- x rightup-arrow arrow pointing right-up ---- w x up-arrow arrow pointing up ---- x <number> any X11 pointer number (see X11/cursorfont.h) ---- ---- The "avail" column contains a 'w' if the shape is available for Win32, ---- x for X11. ---- Any modes not specified or shapes not available use the normal mouse ---- pointer. ---- ---- Example: ---- ---- ```vim ---- set mouseshape=s:udsizing,m:no ---- ``` ---- will make the mouse turn to a sizing arrow over the status lines and ---- indicate no input when the hit-enter prompt is displayed (since ---- clicking the mouse has no effect in this state.) ---- ---- @type string -vim.o.mouseshape = "" -vim.o.mouses = vim.o.mouseshape -vim.go.mouseshape = vim.o.mouseshape -vim.go.mouses = vim.go.mouseshape - --- Defines the maximum time in msec between two mouse clicks for the --- second click to be recognized as a multi click. --- @@ -4565,6 +4379,15 @@ vim.o.mouset = vim.o.mousetime vim.go.mousetime = vim.o.mousetime vim.go.mouset = vim.go.mousetime +--- Determines how many entries are remembered in the `:messages` history. +--- The maximum value is 10000. +--- +--- @type integer +vim.o.msghistory = 500 +vim.o.mhi = vim.o.msghistory +vim.go.msghistory = vim.o.msghistory +vim.go.mhi = vim.go.msghistory + --- This defines what bases Vim will consider for numbers when using the --- CTRL-A and CTRL-X commands for adding to and subtracting from a number --- respectively; see `CTRL-A` for more info on these commands. @@ -4675,19 +4498,6 @@ vim.o.ofu = vim.o.omnifunc vim.bo.omnifunc = vim.o.omnifunc vim.bo.ofu = vim.bo.omnifunc ---- only for Windows ---- Enable reading and writing from devices. This may get Vim stuck on a ---- device that can be opened but doesn't actually do the I/O. Therefore ---- it is off by default. ---- Note that on Windows editing "aux.h", "lpt1.txt" and the like also ---- result in editing a device. ---- ---- @type boolean -vim.o.opendevice = false -vim.o.odev = vim.o.opendevice -vim.go.opendevice = vim.o.opendevice -vim.go.odev = vim.go.opendevice - --- This option specifies a function to be called by the `g@` operator. --- See `:map-operator` for more info and an example. The value can be --- the name of a function, a `lambda` or a `Funcref`. See @@ -5634,7 +5444,7 @@ vim.go.sdf = vim.go.shadafile --- --- ```vim --- let &shell = executable('pwsh') ? 'pwsh' : 'powershell' ---- let &shellcmdflag = '-NoLogo -ExecutionPolicy RemoteSigned -Command [Console]::InputEncoding=[Console]::OutputEncoding=[System.Text.UTF8Encoding]::new();$PSDefaultParameterValues[''Out-File:Encoding'']=''utf8'';Remove-Alias -Force -ErrorAction SilentlyContinue tee;' +--- let &shellcmdflag = '-NoLogo -NonInteractive -ExecutionPolicy RemoteSigned -Command [Console]::InputEncoding=[Console]::OutputEncoding=[System.Text.UTF8Encoding]::new();$PSDefaultParameterValues[''Out-File:Encoding'']=''utf8'';$PSStyle.OutputRendering=''plaintext'';Remove-Alias -Force -ErrorAction SilentlyContinue tee;' --- let &shellredir = '2>&1 | %%{ "$_" } | Out-File %s; exit $LastExitCode' --- let &shellpipe = '2>&1 | %%{ "$_" } | tee %s; exit $LastExitCode' --- set shellquote= shellxquote= @@ -5747,7 +5557,7 @@ vim.o.srr = vim.o.shellredir vim.go.shellredir = vim.o.shellredir vim.go.srr = vim.go.shellredir ---- only for MS-Windows +--- only modifiable in MS-Windows --- When set, a forward slash is used when expanding file names. This is --- useful when a Unix-like shell is used instead of cmd.exe. Backward --- slashes can still be typed, but they are changed to forward slashes by @@ -5764,7 +5574,7 @@ vim.go.srr = vim.go.shellredir --- Also see 'completeslash'. --- --- @type boolean -vim.o.shellslash = false +vim.o.shellslash = true vim.o.ssl = vim.o.shellslash vim.go.shellslash = vim.o.shellslash vim.go.ssl = vim.go.shellslash @@ -6695,7 +6505,7 @@ vim.wo.stc = vim.wo.statuscolumn --- Emulate standard status line with 'ruler' set --- --- ```vim ---- set statusline=%<%f\ %h%m%r%=%-14.(%l,%c%V%)\ %P +--- set statusline=%<%f\ %h%w%m%r%=%-14.(%l,%c%V%)\ %P --- ``` --- Similar, but add ASCII value of char under the cursor (like "ga") --- @@ -7309,7 +7119,9 @@ vim.go.titleold = vim.o.titleold --- window. This happens only when the 'title' option is on. --- --- When this option contains printf-style '%' items, they will be ---- expanded according to the rules used for 'statusline'. +--- expanded according to the rules used for 'statusline'. If it contains +--- an invalid '%' format, the value is used as-is and no error or warning +--- will be given when the value is set. --- This option cannot be set in a modeline when 'modelineexpr' is off. --- --- Example: diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index 3f6deba092..5eb15e1eee 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -221,16 +221,16 @@ function vim.fn.assert_beeps(cmd) end --- @return 0|1 function vim.fn.assert_equal(expected, actual, msg) end ---- When the files {fname-one} and {fname-two} do not contain +--- When the files {fname_one} and {fname_two} do not contain --- exactly the same text an error message is added to |v:errors|. --- Also see |assert-return|. ---- When {fname-one} or {fname-two} does not exist the error will +--- When {fname_one} or {fname_two} does not exist the error will --- mention that. --- ---- @param fname-one string ---- @param fname-two string +--- @param fname_one string +--- @param fname_two string --- @return 0|1 -function vim.fn.assert_equalfile(fname-one, fname-two) end +function vim.fn.assert_equalfile(fname_one, fname_two) end --- When v:exception does not contain the string {error} an error --- message is added to |v:errors|. Also see |assert-return|. @@ -809,7 +809,7 @@ function vim.fn.char2nr(string, utf8) end --- The character class is one of: --- 0 blank --- 1 punctuation ---- 2 word character +--- 2 word character (depends on 'iskeyword') --- 3 emoji --- other specific Unicode class --- The class is used in patterns and word motions. @@ -828,7 +828,7 @@ function vim.fn.charclass(string) end --- echo col('.') " returns 7 --- < --- ---- @param expr string|integer[] +--- @param expr string|any[] --- @param winid? integer --- @return integer function vim.fn.charcol(expr, winid) end @@ -956,7 +956,7 @@ function vim.fn.clearmatches(win) end --- imap <F2> <Cmd>echo col(".").."\n"<CR> --- < --- ---- @param expr string|integer[] +--- @param expr string|any[] --- @param winid? integer --- @return integer function vim.fn.col(expr, winid) end @@ -2879,12 +2879,22 @@ function vim.fn.getcharsearch() end --- @return string function vim.fn.getcharstr(expr) end +--- Return completion pattern of the current command-line. +--- Only works when the command line is being edited, thus +--- requires use of |c_CTRL-\_e| or |c_CTRL-R_=|. +--- Also see |getcmdtype()|, |setcmdpos()|, |getcmdline()|, +--- |getcmdprompt()|, |getcmdcompltype()| and |setcmdline()|. +--- Returns an empty string when completion is not defined. +--- +--- @return string +function vim.fn.getcmdcomplpat() end + --- Return the type of the current command-line completion. --- Only works when the command line is being edited, thus --- requires use of |c_CTRL-\_e| or |c_CTRL-R_=|. --- See |:command-completion| for the return string. --- Also see |getcmdtype()|, |setcmdpos()|, |getcmdline()|, ---- |getcmdprompt()| and |setcmdline()|. +--- |getcmdprompt()|, |getcmdcomplpat()| and |setcmdline()|. --- Returns an empty string when completion is not defined. --- --- @return string @@ -2998,6 +3008,7 @@ function vim.fn.getcmdwintype() end --- runtime |:runtime| completion --- scriptnames sourced script names |:scriptnames| --- shellcmd Shell command +--- shellcmdline Shell command line with filename arguments --- sign |:sign| suboptions --- syntax syntax file names |'syntax'| --- syntime |:syntime| suboptions @@ -5181,7 +5192,7 @@ function vim.fn.log(expr) end function vim.fn.log10(expr) end --- {expr1} must be a |List|, |String|, |Blob| or |Dictionary|. ---- When {expr1} is a |List|| or |Dictionary|, replace each +--- When {expr1} is a |List| or |Dictionary|, replace each --- item in {expr1} with the result of evaluating {expr2}. --- For a |Blob| each byte is replaced. --- For a |String|, each character, including composing @@ -7912,7 +7923,7 @@ function vim.fn.setbufvar(buf, varname, val) end --- To clear the overrides pass an empty {list}: >vim --- call setcellwidths([]) --- ---- <You can use the script $VIMRUNTIME/tools/emoji_list.lua to see +--- <You can use the script $VIMRUNTIME/scripts/emoji_list.lua to see --- the effect for known emoji characters. Move the cursor --- through the text to check if the cell widths of your terminal --- match with what Vim knows about each emoji. If it doesn't @@ -8218,6 +8229,8 @@ function vim.fn.setpos(expr, list) end --- clear the list: >vim --- call setqflist([], 'r') --- < +--- 'u' Like 'r', but tries to preserve the current selection +--- in the quickfix list. --- 'f' All the quickfix lists in the quickfix stack are --- freed. --- @@ -8273,9 +8286,9 @@ function vim.fn.setpos(expr, list) end --- independent of the 'errorformat' setting. Use a command like --- `:cc 1` to jump to the first position. --- ---- @param list any[] +--- @param list vim.quickfix.entry[] --- @param action? string ---- @param what? table +--- @param what? vim.fn.setqflist.what --- @return any function vim.fn.setqflist(list, action, what) end @@ -10533,7 +10546,7 @@ function vim.fn.values(dict) end --- echo max(map(range(1, line('$')), "virtcol([v:val, '$'])")) --- < --- ---- @param expr string|integer[] +--- @param expr string|any[] --- @param list? boolean --- @param winid? integer --- @return any @@ -10616,7 +10629,7 @@ function vim.fn.wait(timeout, condition, interval) end --- For example to make <c-j> work like <down> in wildmode, use: >vim --- cnoremap <expr> <C-j> wildmenumode() ? "\<Down>\<Tab>" : "\<c-j>" --- < ---- (Note, this needs the 'wildcharm' option set appropriately). +--- (Note: this needs the 'wildcharm' option set appropriately). --- --- @return any function vim.fn.wildmenumode() end diff --git a/runtime/lua/vim/_meta/vvars.lua b/runtime/lua/vim/_meta/vvars.lua index e00402ab3f..8784fdbac9 100644 --- a/runtime/lua/vim/_meta/vvars.lua +++ b/runtime/lua/vim/_meta/vvars.lua @@ -160,13 +160,14 @@ vim.v.errors = ... --- an aborting condition (e.g. `c_Esc` or --- `c_CTRL-C` for `CmdlineLeave`). --- chan `channel-id` +--- info Dict of arbitrary event data. --- cmdlevel Level of cmdline. --- cmdtype Type of cmdline, `cmdline-char`. --- cwd Current working directory. --- inclusive Motion is `inclusive`, else exclusive. --- scope Event-specific scope name. --- operator Current `operator`. Also set for Ex ---- commands (unlike `v:operator`). For +--- commands (unlike `v:operator`). For --- example if `TextYankPost` is triggered --- by the `:yank` Ex command then --- `v:event.operator` is "y". diff --git a/runtime/lua/vim/_options.lua b/runtime/lua/vim/_options.lua index a61fa61256..77d7054626 100644 --- a/runtime/lua/vim/_options.lua +++ b/runtime/lua/vim/_options.lua @@ -274,11 +274,9 @@ vim.go = setmetatable({}, { }) --- Get or set buffer-scoped |options| for the buffer with number {bufnr}. ---- If {bufnr} is omitted then the current buffer is used. +--- Like `:setlocal`. If {bufnr} is omitted then the current buffer is used. --- Invalid {bufnr} or key is an error. --- ---- Note: this is equivalent to `:setlocal` for |global-local| options and `:set` otherwise. ---- --- Example: --- --- ```lua diff --git a/runtime/lua/vim/_system.lua b/runtime/lua/vim/_system.lua index d603971495..ce5dbffeaa 100644 --- a/runtime/lua/vim/_system.lua +++ b/runtime/lua/vim/_system.lua @@ -230,6 +230,8 @@ local function default_handler(stream, text, bucket) end end +local is_win = vim.fn.has('win32') == 1 + local M = {} --- @param cmd string @@ -238,6 +240,13 @@ local M = {} --- @param on_error fun() --- @return uv.uv_process_t, integer local function spawn(cmd, opts, on_exit, on_error) + if is_win then + local cmd1 = vim.fn.exepath(cmd) + if cmd1 ~= '' then + cmd = cmd1 + end + end + local handle, pid_or_err = uv.spawn(cmd, opts, on_exit) if not handle then on_error() @@ -309,11 +318,9 @@ end --- @param on_exit? fun(out: vim.SystemCompleted) --- @return vim.SystemObj function M.run(cmd, opts, on_exit) - vim.validate({ - cmd = { cmd, 'table' }, - opts = { opts, 'table', true }, - on_exit = { on_exit, 'function', true }, - }) + vim.validate('cmd', cmd, 'table') + vim.validate('opts', opts, 'table', true) + vim.validate('on_exit', on_exit, 'function', true) opts = opts or {} diff --git a/runtime/lua/vim/_watch.lua b/runtime/lua/vim/_watch.lua index 11f6742941..13894c6147 100644 --- a/runtime/lua/vim/_watch.lua +++ b/runtime/lua/vim/_watch.lua @@ -59,11 +59,9 @@ end --- @param callback vim._watch.Callback Callback for new events --- @return fun() cancel Stops the watcher function M.watch(path, opts, callback) - vim.validate({ - path = { path, 'string', false }, - opts = { opts, 'table', true }, - callback = { callback, 'function', false }, - }) + vim.validate('path', path, 'string') + vim.validate('opts', opts, 'table', true) + vim.validate('callback', callback, 'function') opts = opts or {} @@ -127,11 +125,9 @@ end --- @param callback vim._watch.Callback Callback for new events --- @return fun() cancel Stops the watcher function M.watchdirs(path, opts, callback) - vim.validate({ - path = { path, 'string', false }, - opts = { opts, 'table', true }, - callback = { callback, 'function', false }, - }) + vim.validate('path', path, 'string') + vim.validate('opts', opts, 'table', true) + vim.validate('callback', callback, 'function') opts = opts or {} local debounce = opts.debounce or 500 diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index ef00a1fa51..4fb8c6a686 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -71,9 +71,9 @@ local M = {} --- (default: `false`) --- @field update_in_insert? boolean --- ---- Sort diagnostics by severity. This affects the order in which signs and ---- virtual text are displayed. When true, higher severities are displayed ---- before lower severities (e.g. ERROR is displayed before WARN). +--- Sort diagnostics by severity. This affects the order in which signs, +--- virtual text, and highlights are displayed. When true, higher severities are +--- displayed before lower severities (e.g. ERROR is displayed before WARN). --- Options: --- - {reverse}? (boolean) Reverse sort order --- (default: `false`) @@ -282,6 +282,11 @@ M.severity = { [2] = 'WARN', [3] = 'INFO', [4] = 'HINT', + --- Mappings from qflist/loclist error types to severities + E = 1, + W = 2, + I = 3, + N = 4, } --- @alias vim.diagnostic.SeverityInt 1|2|3|4 @@ -289,12 +294,6 @@ M.severity = { --- See |diagnostic-severity| and |vim.diagnostic.get()| --- @alias vim.diagnostic.SeverityFilter vim.diagnostic.Severity|vim.diagnostic.Severity[]|{min:vim.diagnostic.Severity,max:vim.diagnostic.Severity} --- Mappings from qflist/loclist error types to severities -M.severity.E = M.severity.ERROR -M.severity.W = M.severity.WARN -M.severity.I = M.severity.INFO -M.severity.N = M.severity.HINT - --- @type vim.diagnostic.Opts local global_diagnostic_options = { signs = true, @@ -320,7 +319,7 @@ local global_diagnostic_options = { --- @type table<string,vim.diagnostic.Handler> M.handlers = setmetatable({}, { __newindex = function(t, name, handler) - vim.validate({ handler = { handler, 't' } }) + vim.validate('handler', handler, 'table') rawset(t, name, handler) if global_diagnostic_options[name] == nil then global_diagnostic_options[name] = true @@ -477,10 +476,8 @@ end --- @param diagnostics vim.Diagnostic[] --- @return vim.Diagnostic[] local function reformat_diagnostics(format, diagnostics) - vim.validate({ - format = { format, 'f' }, - diagnostics = { diagnostics, 't' }, - }) + vim.validate('format', format, 'function') + vim.validate('diagnostics', diagnostics, vim.islist, 'a list of diagnostics') local formatted = vim.deepcopy(diagnostics, true) for _, diagnostic in ipairs(formatted) do @@ -659,6 +656,28 @@ local function save_extmarks(namespace, bufnr) api.nvim_buf_get_extmarks(bufnr, namespace, 0, -1, { details = true }) end +--- Create a function that converts a diagnostic severity to an extmark priority. +--- @param priority integer Base priority +--- @param opts vim.diagnostic.OptsResolved +--- @return fun(severity: vim.diagnostic.Severity): integer +local function severity_to_extmark_priority(priority, opts) + if opts.severity_sort then + if type(opts.severity_sort) == 'table' and opts.severity_sort.reverse then + return function(severity) + return priority + (severity - vim.diagnostic.severity.ERROR) + end + end + + return function(severity) + return priority + (vim.diagnostic.severity.HINT - severity) + end + end + + return function() + return priority + end +end + --- @type table<string,true> local registered_autocmds = {} @@ -871,14 +890,14 @@ local function next_diagnostic(search_forward, opts) if opts.win_id then vim.deprecate('opts.win_id', 'opts.winid', '0.13') opts.winid = opts.win_id - opts.win_id = nil + opts.win_id = nil --- @diagnostic disable-line end -- Support deprecated cursor_position alias if opts.cursor_position then vim.deprecate('opts.cursor_position', 'opts.pos', '0.13') opts.pos = opts.cursor_position - opts.cursor_position = nil + opts.cursor_position = nil --- @diagnostic disable-line end local winid = opts.winid or api.nvim_get_current_win() @@ -959,7 +978,7 @@ local function goto_diagnostic(diagnostic, opts) if opts.win_id then vim.deprecate('opts.win_id', 'opts.winid', '0.13') opts.winid = opts.win_id - opts.win_id = nil + opts.win_id = nil --- @diagnostic disable-line end local winid = opts.winid or api.nvim_get_current_win() @@ -972,8 +991,9 @@ local function goto_diagnostic(diagnostic, opts) vim.cmd('normal! zv') end) - if opts.float then - local float_opts = type(opts.float) == 'table' and opts.float or {} + local float_opts = opts.float + if float_opts then + float_opts = type(float_opts) == 'table' and float_opts or {} vim.schedule(function() M.open_float(vim.tbl_extend('keep', float_opts, { bufnr = api.nvim_win_get_buf(winid), @@ -1012,10 +1032,8 @@ end --- When omitted, update the global diagnostic options. ---@return vim.diagnostic.Opts? : Current diagnostic config if {opts} is omitted. function M.config(opts, namespace) - vim.validate({ - opts = { opts, 't', true }, - namespace = { namespace, 'n', true }, - }) + vim.validate('opts', opts, 'table', true) + vim.validate('namespace', namespace, 'number', true) local t --- @type vim.diagnostic.Opts if namespace then @@ -1058,16 +1076,10 @@ end ---@param diagnostics vim.Diagnostic[] ---@param opts? vim.diagnostic.Opts Display options to pass to |vim.diagnostic.show()| function M.set(namespace, bufnr, diagnostics, opts) - vim.validate({ - namespace = { namespace, 'n' }, - bufnr = { bufnr, 'n' }, - diagnostics = { - diagnostics, - vim.islist, - 'a list of diagnostics', - }, - opts = { opts, 't', true }, - }) + vim.validate('namespace', namespace, 'number') + vim.validate('bufnr', bufnr, 'number') + vim.validate('diagnostics', diagnostics, vim.islist, 'a list of diagnostics') + vim.validate('opts', opts, 'table', true) bufnr = get_bufnr(bufnr) @@ -1092,7 +1104,7 @@ end ---@param namespace integer Diagnostic namespace ---@return vim.diagnostic.NS : Namespace metadata function M.get_namespace(namespace) - vim.validate({ namespace = { namespace, 'n' } }) + vim.validate('namespace', namespace, 'number') if not all_namespaces[namespace] then local name --- @type string? for k, v in pairs(api.nvim_get_namespaces()) do @@ -1131,10 +1143,8 @@ end ---@return vim.Diagnostic[] : Fields `bufnr`, `end_lnum`, `end_col`, and `severity` --- are guaranteed to be present. function M.get(bufnr, opts) - vim.validate({ - bufnr = { bufnr, 'n', true }, - opts = { opts, 't', true }, - }) + vim.validate('bufnr', bufnr, 'number', true) + vim.validate('opts', opts, 'table', true) return vim.deepcopy(get_diagnostics(bufnr, opts, false), true) end @@ -1147,10 +1157,8 @@ end ---@return table : Table with actually present severity values as keys --- (see |diagnostic-severity|) and integer counts as values. function M.count(bufnr, opts) - vim.validate({ - bufnr = { bufnr, 'n', true }, - opts = { opts, 't', true }, - }) + vim.validate('bufnr', bufnr, 'number', true) + vim.validate('opts', opts, 'table', true) local diagnostics = get_diagnostics(bufnr, opts, false) local count = {} --- @type table<integer,integer> @@ -1309,7 +1317,7 @@ function M.jump(opts) if opts.cursor_position then vim.deprecate('opts.cursor_position', 'opts.pos', '0.13') opts.pos = opts.cursor_position - opts.cursor_position = nil + opts.cursor_position = nil --- @diagnostic disable-line end local diag = nil @@ -1348,16 +1356,10 @@ end M.handlers.signs = { show = function(namespace, bufnr, diagnostics, opts) - vim.validate({ - namespace = { namespace, 'n' }, - bufnr = { bufnr, 'n' }, - diagnostics = { - diagnostics, - vim.islist, - 'a list of diagnostics', - }, - opts = { opts, 't', true }, - }) + vim.validate('namespace', namespace, 'number') + vim.validate('bufnr', bufnr, 'number') + vim.validate('diagnostics', diagnostics, vim.islist, 'a list of diagnostics') + vim.validate('opts', opts, 'table', true) bufnr = get_bufnr(bufnr) opts = opts or {} @@ -1372,22 +1374,7 @@ M.handlers.signs = { -- 10 is the default sign priority when none is explicitly specified local priority = opts.signs and opts.signs.priority or 10 - local get_priority --- @type function - if opts.severity_sort then - if type(opts.severity_sort) == 'table' and opts.severity_sort.reverse then - get_priority = function(severity) - return priority + (severity - vim.diagnostic.severity.ERROR) - end - else - get_priority = function(severity) - return priority + (vim.diagnostic.severity.HINT - severity) - end - end - else - get_priority = function() - return priority - end - end + local get_priority = severity_to_extmark_priority(priority, opts) local ns = M.get_namespace(namespace) if not ns.user_data.sign_ns then @@ -1475,16 +1462,10 @@ M.handlers.signs = { M.handlers.underline = { show = function(namespace, bufnr, diagnostics, opts) - vim.validate({ - namespace = { namespace, 'n' }, - bufnr = { bufnr, 'n' }, - diagnostics = { - diagnostics, - vim.islist, - 'a list of diagnostics', - }, - opts = { opts, 't', true }, - }) + vim.validate('namespace', namespace, 'number') + vim.validate('bufnr', bufnr, 'number') + vim.validate('diagnostics', diagnostics, vim.islist, 'a list of diagnostics') + vim.validate('opts', opts, 'table', true) bufnr = get_bufnr(bufnr) opts = opts or {} @@ -1504,15 +1485,12 @@ M.handlers.underline = { end local underline_ns = ns.user_data.underline_ns + local get_priority = severity_to_extmark_priority(vim.hl.priorities.diagnostics, opts) + for _, diagnostic in ipairs(diagnostics) do - --- @type string? + -- Default to error if we don't have a highlight associated local higroup = underline_highlight_map[assert(diagnostic.severity)] - - if higroup == nil then - -- Default to error if we don't have a highlight associated - -- TODO(lewis6991): this is always nil since underline_highlight_map only has integer keys - higroup = underline_highlight_map.Error - end + or underline_highlight_map[vim.diagnostic.severity.ERROR] if diagnostic._tags then -- TODO(lewis6991): we should be able to stack these. @@ -1524,13 +1502,13 @@ M.handlers.underline = { end end - vim.highlight.range( + vim.hl.range( bufnr, underline_ns, higroup, { diagnostic.lnum, diagnostic.col }, { diagnostic.end_lnum, diagnostic.end_col }, - { priority = vim.highlight.priorities.diagnostics } + { priority = get_priority(diagnostic.severity) } ) end save_extmarks(underline_ns, bufnr) @@ -1548,16 +1526,10 @@ M.handlers.underline = { M.handlers.virtual_text = { show = function(namespace, bufnr, diagnostics, opts) - vim.validate({ - namespace = { namespace, 'n' }, - bufnr = { bufnr, 'n' }, - diagnostics = { - diagnostics, - vim.islist, - 'a list of diagnostics', - }, - opts = { opts, 't', true }, - }) + vim.validate('namespace', namespace, 'number') + vim.validate('bufnr', bufnr, 'number') + vim.validate('diagnostics', diagnostics, vim.islist, 'a list of diagnostics') + vim.validate('opts', opts, 'table', true) bufnr = get_bufnr(bufnr) opts = opts or {} @@ -1681,10 +1653,8 @@ end ---@param bufnr integer? Buffer number, or 0 for current buffer. When --- omitted, hide diagnostics in all buffers. function M.hide(namespace, bufnr) - vim.validate({ - namespace = { namespace, 'n', true }, - bufnr = { bufnr, 'n', true }, - }) + vim.validate('namespace', namespace, 'number', true) + vim.validate('bufnr', bufnr, 'number', true) local buffers = bufnr and { get_bufnr(bufnr) } or vim.tbl_keys(diagnostic_cache) for _, iter_bufnr in ipairs(buffers) do @@ -1741,18 +1711,10 @@ end --- or {bufnr} is nil. ---@param opts? vim.diagnostic.Opts Display options. function M.show(namespace, bufnr, diagnostics, opts) - vim.validate({ - namespace = { namespace, 'n', true }, - bufnr = { bufnr, 'n', true }, - diagnostics = { - diagnostics, - function(v) - return v == nil or vim.islist(v) - end, - 'a list of diagnostics', - }, - opts = { opts, 't', true }, - }) + vim.validate('namespace', namespace, 'number', true) + vim.validate('bufnr', bufnr, 'number', true) + vim.validate('diagnostics', diagnostics, vim.islist, true, 'a list of diagnostics') + vim.validate('opts', opts, 'table', true) if not bufnr or not namespace then assert(not diagnostics, 'Cannot show diagnostics without a buffer and namespace') @@ -1825,9 +1787,7 @@ function M.open_float(opts, ...) bufnr = opts opts = ... --- @type vim.diagnostic.Opts.Float else - vim.validate({ - opts = { opts, 't', true }, - }) + vim.validate('opts', opts, 'table', true) end opts = opts or {} @@ -1905,13 +1865,7 @@ function M.open_float(opts, ...) local highlights = {} --- @type table[] local header = if_nil(opts.header, 'Diagnostics:') if header then - vim.validate({ - header = { - header, - { 'string', 'table' }, - "'string' or 'table'", - }, - }) + vim.validate('header', header, { 'string', 'table' }, "'string' or 'table'") if type(header) == 'table' then -- Don't insert any lines for an empty string if string.len(if_nil(header[1], '')) > 0 then @@ -1939,13 +1893,12 @@ function M.open_float(opts, ...) local prefix, prefix_hl_group --- @type string?, string? if prefix_opt then - vim.validate({ - prefix = { - prefix_opt, - { 'string', 'table', 'function' }, - "'string' or 'table' or 'function'", - }, - }) + vim.validate( + 'prefix', + prefix_opt, + { 'string', 'table', 'function' }, + "'string' or 'table' or 'function'" + ) if type(prefix_opt) == 'string' then prefix, prefix_hl_group = prefix_opt, 'NormalFloat' elseif type(prefix_opt) == 'table' then @@ -1959,13 +1912,12 @@ function M.open_float(opts, ...) local suffix, suffix_hl_group --- @type string?, string? if suffix_opt then - vim.validate({ - suffix = { - suffix_opt, - { 'string', 'table', 'function' }, - "'string' or 'table' or 'function'", - }, - }) + vim.validate( + 'suffix', + suffix_opt, + { 'string', 'table', 'function' }, + "'string' or 'table' or 'function'" + ) if type(suffix_opt) == 'string' then suffix, suffix_hl_group = suffix_opt, 'NormalFloat' elseif type(suffix_opt) == 'table' then @@ -2038,10 +1990,8 @@ end ---@param bufnr integer? Remove diagnostics for the given buffer. When omitted, --- diagnostics are removed for all buffers. function M.reset(namespace, bufnr) - vim.validate({ - namespace = { namespace, 'n', true }, - bufnr = { bufnr, 'n', true }, - }) + vim.validate('namespace', namespace, 'number', true) + vim.validate('bufnr', bufnr, 'number', true) local buffers = bufnr and { get_bufnr(bufnr) } or vim.tbl_keys(diagnostic_cache) for _, iter_bufnr in ipairs(buffers) do @@ -2144,10 +2094,8 @@ function M.enable(enable, filter) '0.12' ) - vim.validate({ - enable = { enable, 'n', true }, -- Legacy `bufnr` arg. - filter = { filter, 'n', true }, -- Legacy `namespace` arg. - }) + vim.validate('enable', enable, 'number', true) -- Legacy `bufnr` arg. + vim.validate('filter', filter, 'number', true) -- Legacy `namespace` arg. local ns_id = type(filter) == 'number' and filter or nil filter = {} @@ -2156,17 +2104,16 @@ function M.enable(enable, filter) enable = true else filter = filter or {} - vim.validate({ - enable = { enable, 'b', true }, - filter = { filter, 't', true }, - }) + vim.validate('enable', enable, 'boolean', true) + vim.validate('filter', filter, 'table', true) end enable = enable == nil and true or enable local bufnr = filter.bufnr + local ns_id = filter.ns_id - if bufnr == nil then - if filter.ns_id == nil then + if not bufnr then + if not ns_id then diagnostic_disabled = ( enable -- Enable everything by setting diagnostic_disabled to an empty table. @@ -2180,12 +2127,12 @@ function M.enable(enable, filter) }) ) else - local ns = M.get_namespace(filter.ns_id) + local ns = M.get_namespace(ns_id) ns.disabled = not enable end else bufnr = get_bufnr(bufnr) - if filter.ns_id == nil then + if not ns_id then diagnostic_disabled[bufnr] = (not enable) and true or nil else if type(diagnostic_disabled[bufnr]) ~= 'table' then @@ -2195,14 +2142,14 @@ function M.enable(enable, filter) diagnostic_disabled[bufnr] = {} end end - diagnostic_disabled[bufnr][filter.ns_id] = (not enable) and true or nil + diagnostic_disabled[bufnr][ns_id] = (not enable) and true or nil end end if enable then - M.show(filter.ns_id, bufnr) + M.show(ns_id, bufnr) else - M.hide(filter.ns_id, bufnr) + M.hide(ns_id, bufnr) end end @@ -2234,13 +2181,11 @@ end --- ERROR. ---@return vim.Diagnostic?: |vim.Diagnostic| structure or `nil` if {pat} fails to match {str}. function M.match(str, pat, groups, severity_map, defaults) - vim.validate({ - str = { str, 's' }, - pat = { pat, 's' }, - groups = { groups, 't' }, - severity_map = { severity_map, 't', true }, - defaults = { defaults, 't', true }, - }) + vim.validate('str', str, 'string') + vim.validate('pat', pat, 'string') + vim.validate('groups', groups, 'table') + vim.validate('severity_map', severity_map, 'table', true) + vim.validate('defaults', defaults, 'table', true) --- @type table<string,vim.diagnostic.Severity> severity_map = severity_map or M.severity @@ -2283,13 +2228,7 @@ local errlist_type_map = { ---@param diagnostics vim.Diagnostic[] ---@return table[] : Quickfix list items |setqflist-what| function M.toqflist(diagnostics) - vim.validate({ - diagnostics = { - diagnostics, - vim.islist, - 'a list of diagnostics', - }, - }) + vim.validate('diagnostics', diagnostics, vim.islist, 'a list of diagnostics') local list = {} --- @type table[] for _, v in ipairs(diagnostics) do @@ -2323,13 +2262,7 @@ end ---@param list table[] List of quickfix items from |getqflist()| or |getloclist()|. ---@return vim.Diagnostic[] function M.fromqflist(list) - vim.validate({ - list = { - list, - vim.islist, - 'a list of quickfix items', - }, - }) + vim.validate('list', list, 'table') local diagnostics = {} --- @type vim.Diagnostic[] for _, item in ipairs(list) do diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index d3910e26eb..e1e73d63fe 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -4,15 +4,22 @@ local fn = vim.fn local M = {} --- @alias vim.filetype.mapfn fun(path:string,bufnr:integer, ...):string?, fun(b:integer)? ---- @alias vim.filetype.mapopts { parent: string, priority: number } +--- @alias vim.filetype.mapopts { priority: number } --- @alias vim.filetype.maptbl [string|vim.filetype.mapfn, vim.filetype.mapopts] --- @alias vim.filetype.mapping.value string|vim.filetype.mapfn|vim.filetype.maptbl --- @alias vim.filetype.mapping table<string,vim.filetype.mapping.value> +--- @class vim.filetype.mapping.sorted +--- @nodoc +--- @field [1] string parent pattern +--- @field [2] string pattern +--- @field [3] string|vim.filetype.mapfn +--- @field [4] integer priority + --- @param ft string|vim.filetype.mapfn ---- @param opts? vim.filetype.mapopts +--- @param priority? integer --- @return vim.filetype.maptbl -local function starsetf(ft, opts) +local function starsetf(ft, priority) return { function(path, bufnr) -- Note: when `ft` is a function its return value may be nil. @@ -27,11 +34,8 @@ local function starsetf(ft, opts) end end, { - -- Allow setting "parent" to be reused in closures, but don't have default as it will be - -- assigned later from grouping - parent = opts and opts.parent, -- Starset matches should have lowest priority by default - priority = (opts and opts.priority) or -math.huge, + priority = priority or -math.huge, }, } end @@ -402,6 +406,7 @@ local extension = { dtso = 'dts', its = 'dts', keymap = 'dts', + overlay = 'dts', dylan = 'dylan', intr = 'dylanintr', lid = 'dylanlid', @@ -587,6 +592,7 @@ local extension = { ibi = 'ibasic', icn = 'icon', idl = detect.idl, + idr = 'idris2', inc = detect.inc, inf = 'inform', INF = 'inform', @@ -594,6 +600,7 @@ local extension = { inko = 'inko', inp = detect.inp, ms = detect_seq(detect.nroff, 'xmath'), + ipkg = 'ipkg', iss = 'iss', mst = 'ist', ist = 'ist', @@ -667,13 +674,14 @@ local extension = { journal = 'ledger', ldg = 'ledger', ledger = 'ledger', + leo = 'leo', less = 'less', lex = 'lex', lxx = 'lex', ['l++'] = 'lex', l = 'lex', lhs = 'lhaskell', - ll = 'lifelines', + lidr = 'lidris2', ly = 'lilypond', ily = 'lilypond', liquid = 'liquid', @@ -688,6 +696,7 @@ local extension = { lt = 'lite', lite = 'lite', livemd = 'livebook', + ll = detect.ll, log = detect.log, Log = detect.log, LOG = detect.log, @@ -752,6 +761,7 @@ local extension = { mib = 'mib', mix = 'mix', mixal = 'mix', + mlir = 'mlir', mm = detect.mm, nb = 'mma', wl = 'mma', @@ -782,6 +792,7 @@ local extension = { mof = 'msidl', odl = 'msidl', msql = 'msql', + mss = 'mss', mu = 'mupad', mush = 'mush', mustache = 'mustache', @@ -1067,6 +1078,9 @@ local extension = { envrc = detect.sh, ksh = detect.ksh, sh = detect.sh, + lo = 'sh', + la = 'sh', + lai = 'sh', mdd = 'sh', sieve = 'sieve', siv = 'sieve', @@ -1146,6 +1160,7 @@ local extension = { sface = 'surface', svelte = 'svelte', svg = 'svg', + sw = 'sway', swift = 'swift', swiftinterface = 'swift', swig = 'swig', @@ -1303,6 +1318,7 @@ local extension = { xpfm = 'xml', spfm = 'xml', bxml = 'xml', + mmi = 'xml', xcu = 'xml', xlb = 'xml', xlc = 'xml', @@ -1610,6 +1626,7 @@ local filename = { ['ldaprc'] = 'ldapconf', ['.ldaprc'] = 'ldapconf', ['ldap.conf'] = 'ldapconf', + ['lfrc'] = 'lf', ['lftp.conf'] = 'lftp', ['.lftprc'] = 'lftp', ['/.libao'] = 'libao', @@ -1862,11 +1879,10 @@ local filename = { } -- Re-use closures as much as possible -local detect_apache_diretc = starsetf('apache', { parent = '/etc/' }) -local detect_apache_dotconf = starsetf('apache', { parent = '%.conf' }) -local detect_muttrc = starsetf('muttrc', { parent = 'utt' }) -local detect_neomuttrc = starsetf('neomuttrc', { parent = 'utt' }) -local detect_xkb = starsetf('xkb', { parent = '/usr/' }) +local detect_apache = starsetf('apache') +local detect_muttrc = starsetf('muttrc') +local detect_neomuttrc = starsetf('neomuttrc') +local detect_xkb = starsetf('xkb') ---@type table<string,vim.filetype.mapping> local pattern = { @@ -1883,14 +1899,14 @@ local pattern = { ['/etc/asound%.conf$'] = 'alsaconf', ['/etc/apache2/sites%-.*/.*%.com$'] = 'apache', ['/etc/httpd/.*%.conf$'] = 'apache', - ['/etc/apache2/.*%.conf'] = detect_apache_diretc, - ['/etc/apache2/conf%..*/'] = detect_apache_diretc, - ['/etc/apache2/mods%-.*/'] = detect_apache_diretc, - ['/etc/apache2/sites%-.*/'] = detect_apache_diretc, - ['/etc/httpd/conf%..*/'] = detect_apache_diretc, - ['/etc/httpd/conf%.d/.*%.conf'] = detect_apache_diretc, - ['/etc/httpd/mods%-.*/'] = detect_apache_diretc, - ['/etc/httpd/sites%-.*/'] = detect_apache_diretc, + ['/etc/apache2/.*%.conf'] = detect_apache, + ['/etc/apache2/conf%..*/'] = detect_apache, + ['/etc/apache2/mods%-.*/'] = detect_apache, + ['/etc/apache2/sites%-.*/'] = detect_apache, + ['/etc/httpd/conf%..*/'] = detect_apache, + ['/etc/httpd/conf%.d/.*%.conf'] = detect_apache, + ['/etc/httpd/mods%-.*/'] = detect_apache, + ['/etc/httpd/sites%-.*/'] = detect_apache, ['/etc/proftpd/.*%.conf'] = starsetf('apachestyle'), ['/etc/proftpd/conf%..*/'] = starsetf('apachestyle'), ['/etc/cdrdao%.conf$'] = 'cdrdaoconf', @@ -2106,6 +2122,7 @@ local pattern = { ['/build/conf/.*%.conf$'] = 'bitbake', ['/meta%-.*/conf/.*%.conf$'] = 'bitbake', ['/meta/conf/.*%.conf$'] = 'bitbake', + ['/project%-spec/configs/.*%.conf$'] = 'bitbake', ['/%.cabal/config$'] = 'cabalconfig', ['/cabal/config$'] = 'cabalconfig', ['/%.aws/config$'] = 'confini', @@ -2132,6 +2149,7 @@ local pattern = { ['/sway/config$'] = 'swayconfig', ['/%.cargo/config$'] = 'toml', ['/%.bundle/config$'] = 'yaml', + ['/%.kube/config$'] = 'yaml', }, ['/%.'] = { ['/%.aws/credentials$'] = 'confini', @@ -2180,11 +2198,13 @@ local pattern = { }, ['%.conf'] = { ['^proftpd%.conf'] = starsetf('apachestyle'), - ['^access%.conf'] = detect_apache_dotconf, - ['^apache%.conf'] = detect_apache_dotconf, - ['^apache2%.conf'] = detect_apache_dotconf, - ['^httpd%.conf'] = detect_apache_dotconf, - ['^srm%.conf'] = detect_apache_dotconf, + ['^access%.conf'] = detect_apache, + ['^apache%.conf'] = detect_apache, + ['^apache2%.conf'] = detect_apache, + ['^httpd%.conf'] = detect_apache, + ['^httpd%-.*%.conf'] = detect_apache, + ['^proxy%-html%.conf'] = detect_apache, + ['^srm%.conf'] = detect_apache, ['asterisk/.*%.conf'] = starsetf('asterisk'), ['asterisk.*/.*voicemail%.conf'] = starsetf('asteriskvm'), ['^dictd.*%.conf$'] = 'dictdconf', @@ -2260,6 +2280,7 @@ local pattern = { ['^%.?neomuttrc'] = detect_neomuttrc, ['/%.neomutt/neomuttrc'] = detect_neomuttrc, ['^Neomuttrc'] = detect_neomuttrc, + ['%.neomuttdebug'] = 'neomuttlog', }, ['^%.'] = { ['^%.cshrc'] = detect.csh, @@ -2293,6 +2314,8 @@ local pattern = { ['^crontab%.'] = starsetf('crontab'), ['^cvs%d+$'] = 'cvs', ['^php%.ini%-'] = 'dosini', + ['^php%-fpm%.conf'] = 'dosini', + ['^www%.conf'] = 'dosini', ['^drac%.'] = starsetf('dracula'), ['/dtrace/.*%.d$'] = 'dtrace', ['esmtprc$'] = 'esmtprc', @@ -2354,7 +2377,7 @@ local pattern = { ['/app%-defaults/'] = starsetf('xdefaults'), ['^Xresources'] = starsetf('xdefaults'), -- Increase priority to run before the pattern below - ['^XF86Config%-4'] = starsetf(detect.xfree86_v4, { priority = -math.huge + 1 }), + ['^XF86Config%-4'] = starsetf(detect.xfree86_v4, -math.huge + 1), ['^XF86Config'] = starsetf(detect.xfree86_v3), ['Xmodmap$'] = 'xmodmap', ['xmodmap'] = starsetf('xmodmap'), @@ -2380,8 +2403,10 @@ local pattern = { --- @type table<string,vim.filetype.pattern_cache> local pattern_lookup = {} +--- @param a vim.filetype.mapping.sorted +--- @param b vim.filetype.mapping.sorted local function compare_by_priority(a, b) - return a[next(a)][2].priority > b[next(b)][2].priority + return a[4] > b[4] end --- @param pat string @@ -2391,30 +2416,30 @@ local function parse_pattern(pat) end --- @param t table<string,vim.filetype.mapping> ---- @return vim.filetype.mapping[] ---- @return vim.filetype.mapping[] +--- @return vim.filetype.mapping.sorted[] +--- @return vim.filetype.mapping.sorted[] local function sort_by_priority(t) -- Separate patterns with non-negative and negative priority because they -- will be processed separately - local pos = {} --- @type vim.filetype.mapping[] - local neg = {} --- @type vim.filetype.mapping[] + local pos = {} --- @type vim.filetype.mapping.sorted[] + local neg = {} --- @type vim.filetype.mapping.sorted[] for parent, ft_map in pairs(t) do pattern_lookup[parent] = pattern_lookup[parent] or parse_pattern(parent) for pat, maptbl in pairs(ft_map) do - local ft = type(maptbl) == 'table' and maptbl[1] or maptbl + local ft_or_fun = type(maptbl) == 'table' and maptbl[1] or maptbl assert( - type(ft) == 'string' or type(ft) == 'function', + type(ft_or_fun) == 'string' or type(ft_or_fun) == 'function', 'Expected string or function for filetype' ) -- Parse pattern for common data and cache it once pattern_lookup[pat] = pattern_lookup[pat] or parse_pattern(pat) - local opts = (type(maptbl) == 'table' and type(maptbl[2]) == 'table') and maptbl[2] or {} - opts.parent = opts.parent or parent - opts.priority = opts.priority or 0 + --- @type vim.filetype.mapopts? + local opts = (type(maptbl) == 'table' and type(maptbl[2]) == 'table') and maptbl[2] or nil + local priority = opts and opts.priority or 0 - table.insert(opts.priority >= 0 and pos or neg, { [pat] = { ft, opts } }) + table.insert(priority >= 0 and pos or neg, { parent, pat, ft_or_fun, priority }) end end @@ -2625,7 +2650,8 @@ local function match_pattern(name, path, tail, pat, try_all_candidates) if some_env_missing then return nil end - pat, has_slash = expanded, expanded:find('/') ~= nil + pat = expanded + has_slash = has_slash or expanded:find('/') ~= nil end -- Try all possible candidates to make parent patterns not depend on slash presence @@ -2647,14 +2673,13 @@ end --- @param name string --- @param path string --- @param tail string ---- @param pattern_sorted vim.filetype.mapping[] +--- @param pattern_sorted vim.filetype.mapping.sorted[] --- @param parent_matches table<string,boolean> --- @param bufnr integer? local function match_pattern_sorted(name, path, tail, pattern_sorted, parent_matches, bufnr) - for i = 1, #pattern_sorted do - local pat, ft_data = next(pattern_sorted[i]) + for _, p in ipairs(pattern_sorted) do + local parent, pat, ft_or_fn = p[1], p[2], p[3] - local parent = ft_data[2].parent local parent_is_matched = parent_matches[parent] if parent_is_matched == nil then parent_matches[parent] = match_pattern(name, path, tail, parent, true) ~= nil @@ -2664,7 +2689,7 @@ local function match_pattern_sorted(name, path, tail, pattern_sorted, parent_mat if parent_is_matched then local matches = match_pattern(name, path, tail, pat, false) if matches then - local ft, on_detect = dispatch(ft_data[1], path, bufnr, matches) + local ft, on_detect = dispatch(ft_or_fn, path, bufnr, matches) if ft then return ft, on_detect end @@ -2729,9 +2754,7 @@ end --- filetype specific buffer variables). The function accepts a buffer number as --- its only argument. function M.match(args) - vim.validate({ - arg = { args, 't' }, - }) + vim.validate('arg', args, 'table') if not (args.buf or args.filename or args.contents) then error('At least one of "buf", "filename", or "contents" must be given') diff --git a/runtime/lua/vim/filetype/detect.lua b/runtime/lua/vim/filetype/detect.lua index 1cc81b177f..98b001bd51 100644 --- a/runtime/lua/vim/filetype/detect.lua +++ b/runtime/lua/vim/filetype/detect.lua @@ -869,6 +869,16 @@ function M.log(path, _) end --- @type vim.filetype.mapfn +function M.ll(_, bufnr) + local first_line = getline(bufnr, 1) + if matchregex(first_line, [[;\|\<source_filename\>\|\<target\>]]) then + return 'llvm' + else + return 'lifelines' + end +end + +--- @type vim.filetype.mapfn function M.lpc(_, bufnr) if vim.g.lpc_syntax_for_c then for _, line in ipairs(getlines(bufnr, 1, 12)) do @@ -1908,7 +1918,7 @@ local function match_from_hashbang(contents, path, dispatch_extension) end for k, v in pairs(patterns_hashbang) do - local ft = type(v) == 'table' and v[1] or v + local ft = type(v) == 'table' and v[1] or v --[[@as string]] local opts = type(v) == 'table' and v[2] or {} if opts.vim_regex and matchregex(name, k) or name:find(k) then return ft @@ -2080,6 +2090,7 @@ local function match_from_text(contents, path) return ft end else + --- @cast k string local opts = type(v) == 'table' and v[2] or {} if opts.start_lnum and opts.end_lnum then assert( diff --git a/runtime/lua/vim/fs.lua b/runtime/lua/vim/fs.lua index ccddf826f7..d91eeaf02f 100644 --- a/runtime/lua/vim/fs.lua +++ b/runtime/lua/vim/fs.lua @@ -53,7 +53,7 @@ function M.dirname(file) if file == nil then return nil end - vim.validate({ file = { file, 's' } }) + vim.validate('file', file, 'string') if iswin then file = file:gsub(os_sep, '/') --[[@as string]] if file:match('^%w:/?$') then @@ -83,7 +83,7 @@ function M.basename(file) if file == nil then return nil end - vim.validate({ file = { file, 's' } }) + vim.validate('file', file, 'string') if iswin then file = file:gsub(os_sep, '/') --[[@as string]] if file:match('^%w:/?$') then @@ -123,11 +123,9 @@ end function M.dir(path, opts) opts = opts or {} - vim.validate({ - path = { path, { 'string' } }, - depth = { opts.depth, { 'number' }, true }, - skip = { opts.skip, { 'function' }, true }, - }) + vim.validate('path', path, 'string') + vim.validate('depth', opts.depth, 'number', true) + vim.validate('skip', opts.skip, 'function', true) path = M.normalize(path) if not opts.depth or opts.depth == 1 then @@ -231,14 +229,12 @@ end ---@return (string[]) # Normalized paths |vim.fs.normalize()| of all matching items function M.find(names, opts) opts = opts or {} - vim.validate({ - names = { names, { 's', 't', 'f' } }, - path = { opts.path, 's', true }, - upward = { opts.upward, 'b', true }, - stop = { opts.stop, 's', true }, - type = { opts.type, 's', true }, - limit = { opts.limit, 'n', true }, - }) + vim.validate('names', names, { 'string', 'table', 'function' }) + vim.validate('path', opts.path, 'string', true) + vim.validate('upward', opts.upward, 'boolean', true) + vim.validate('stop', opts.stop, 'string', true) + vim.validate('type', opts.type, 'string', true) + vim.validate('limit', opts.limit, 'number', true) if type(names) == 'string' then names = { names } @@ -547,11 +543,9 @@ function M.normalize(path, opts) opts = opts or {} if not opts._fast then - vim.validate({ - path = { path, { 'string' } }, - expand_env = { opts.expand_env, { 'boolean' }, true }, - win = { opts.win, { 'boolean' }, true }, - }) + vim.validate('path', path, 'string') + vim.validate('expand_env', opts.expand_env, 'boolean', true) + vim.validate('win', opts.win, 'boolean', true) end local win = opts.win == nil and iswin or not not opts.win diff --git a/runtime/lua/vim/func/_memoize.lua b/runtime/lua/vim/func/_memoize.lua index 65210351bf..6e557905a7 100644 --- a/runtime/lua/vim/func/_memoize.lua +++ b/runtime/lua/vim/func/_memoize.lua @@ -39,10 +39,8 @@ end --- @param strong? boolean --- @return F return function(hash, fn, strong) - vim.validate({ - hash = { hash, { 'number', 'string', 'function' } }, - fn = { fn, 'function' }, - }) + vim.validate('hash', hash, { 'number', 'string', 'function' }) + vim.validate('fn', fn, 'function') ---@type table<any,table<any,any>> local cache = {} diff --git a/runtime/lua/vim/glob.lua b/runtime/lua/vim/glob.lua index 22073b15c8..4f86d5e1ca 100644 --- a/runtime/lua/vim/glob.lua +++ b/runtime/lua/vim/glob.lua @@ -48,7 +48,7 @@ function M.to_lpeg(pattern) end -- luacheck: push ignore s - local function cut(s, idx, match) + local function cut(_s, idx, match) return idx, match end -- luacheck: pop diff --git a/runtime/lua/vim/highlight.lua b/runtime/lua/vim/hl.lua index a8d88db372..099efa3c61 100644 --- a/runtime/lua/vim/highlight.lua +++ b/runtime/lua/vim/hl.lua @@ -17,7 +17,7 @@ M.priorities = { user = 200, } ---- @class vim.highlight.range.Opts +--- @class vim.hl.range.Opts --- @inlinedoc --- --- Type of range. See [getregtype()] @@ -28,8 +28,8 @@ M.priorities = { --- (default: `false`) --- @field inclusive? boolean --- ---- Indicates priority of highlight ---- (default: `vim.highlight.priorities.user`) +--- Highlight priority +--- (default: `vim.hl.priorities.user`) --- @field priority? integer --- Apply highlight group to range of text. @@ -39,7 +39,7 @@ M.priorities = { ---@param higroup string Highlight group to use for highlighting ---@param start integer[]|string Start of region as a (line, column) tuple or string accepted by |getpos()| ---@param finish integer[]|string End of region as a (line, column) tuple or string accepted by |getpos()| ----@param opts? vim.highlight.range.Opts +---@param opts? vim.hl.range.Opts function M.range(bufnr, ns, higroup, start, finish, opts) opts = opts or {} local regtype = opts.regtype or 'v' @@ -124,7 +124,7 @@ local yank_cancel --- @type fun()? --- Add the following to your `init.vim`: --- --- ```vim ---- autocmd TextYankPost * silent! lua vim.highlight.on_yank {higroup='Visual', timeout=300} +--- autocmd TextYankPost * silent! lua vim.hl.on_yank {higroup='Visual', timeout=300} --- ``` --- --- @param opts table|nil Optional parameters @@ -133,21 +133,9 @@ local yank_cancel --- @type fun()? --- - on_macro highlight when executing macro (default false) --- - on_visual highlight when yanking visual selection (default true) --- - event event structure (default vim.v.event) ---- - priority integer priority (default |vim.highlight.priorities|`.user`) +--- - priority integer priority (default |vim.hl.priorities|`.user`) function M.on_yank(opts) - vim.validate({ - opts = { - opts, - function(t) - if t == nil then - return true - else - return type(t) == 'table' - end - end, - 'a table or nil to configure options (see `:h highlight.on_yank`)', - }, - }) + vim.validate('opts', opts, 'table', true) opts = opts or {} local event = opts.event or vim.v.event local on_macro = opts.on_macro or false diff --git a/runtime/lua/vim/keymap.lua b/runtime/lua/vim/keymap.lua index 50ca0d2d0e..4c19435ef8 100644 --- a/runtime/lua/vim/keymap.lua +++ b/runtime/lua/vim/keymap.lua @@ -42,12 +42,10 @@ local keymap = {} ---@see |mapcheck()| ---@see |mapset()| function keymap.set(mode, lhs, rhs, opts) - vim.validate({ - mode = { mode, { 's', 't' } }, - lhs = { lhs, 's' }, - rhs = { rhs, { 's', 'f' } }, - opts = { opts, 't', true }, - }) + vim.validate('mode', mode, { 'string', 'table' }) + vim.validate('lhs', lhs, 'string') + vim.validate('rhs', rhs, { 'string', 'function' }) + vim.validate('opts', opts, 'table', true) opts = vim.deepcopy(opts or {}, true) @@ -107,11 +105,9 @@ end ---@param opts? vim.keymap.del.Opts ---@see |vim.keymap.set()| function keymap.del(modes, lhs, opts) - vim.validate({ - mode = { modes, { 's', 't' } }, - lhs = { lhs, 's' }, - opts = { opts, 't', true }, - }) + vim.validate('mode', modes, { 'string', 'table' }) + vim.validate('lhs', lhs, 'string') + vim.validate('opts', opts, 'table', true) opts = opts or {} modes = type(modes) == 'string' and { modes } or modes diff --git a/runtime/lua/vim/loader.lua b/runtime/lua/vim/loader.lua index e86d33bf53..0cce0ab21d 100644 --- a/runtime/lua/vim/loader.lua +++ b/runtime/lua/vim/loader.lua @@ -4,11 +4,14 @@ local uri_encode = vim.uri_encode --- @type function --- @type (fun(modename: string): fun()|string)[] local loaders = package.loaders +local _loadfile = loadfile + +local VERSION = 4 local M = {} ----@alias CacheHash {mtime: {nsec: integer, sec: integer}, size: integer, type?: string} ----@alias CacheEntry {hash:CacheHash, chunk:string} +--- @alias vim.loader.CacheHash {mtime: {nsec: integer, sec: integer}, size: integer, type?: string} +--- @alias vim.loader.CacheEntry {hash:vim.loader.CacheHash, chunk:string} --- @class vim.loader.find.Opts --- @inlinedoc @@ -40,107 +43,97 @@ local M = {} --- @field modname string --- --- The fs_stat of the module path. Won't be returned for `modname="*"` ---- @field stat? uv.uv_fs_t +--- @field stat? uv.fs_stat.result ----@alias LoaderStats table<string, {total:number, time:number, [string]:number?}?> +--- @alias vim.loader.Stats table<string, {total:number, time:number, [string]:number?}?> ----@nodoc +--- @private M.path = vim.fn.stdpath('cache') .. '/luac' ----@nodoc +--- @private M.enabled = false ----@class (private) Loader ----@field private _rtp string[] ----@field private _rtp_pure string[] ----@field private _rtp_key string ----@field private _hashes? table<string, CacheHash> -local Loader = { - VERSION = 4, - ---@type table<string, table<string,vim.loader.ModuleInfo>> - _indexed = {}, - ---@type table<string, string[]> - _topmods = {}, - _loadfile = loadfile, - ---@type LoaderStats - _stats = { - find = { total = 0, time = 0, not_found = 0 }, - }, -} +--- @type vim.loader.Stats +local stats = { find = { total = 0, time = 0, not_found = 0 } } + +--- @type table<string, uv.fs_stat.result>? +local fs_stat_cache + +--- @type table<string, table<string,vim.loader.ModuleInfo>> +local indexed = {} --- @param path string ---- @return CacheHash ---- @private -function Loader.get_hash(path) - if not Loader._hashes then - return uv.fs_stat(path) --[[@as CacheHash]] +--- @return uv.fs_stat.result? +local function fs_stat_cached(path) + if not fs_stat_cache then + return uv.fs_stat(path) end - if not Loader._hashes[path] then + if not fs_stat_cache[path] then -- Note we must never save a stat for a non-existent path. -- For non-existent paths fs_stat() will return nil. - Loader._hashes[path] = uv.fs_stat(path) + fs_stat_cache[path] = uv.fs_stat(path) end - return Loader._hashes[path] + return fs_stat_cache[path] end local function normalize(path) return fs.normalize(path, { expand_env = false, _fast = true }) end +local rtp_cached = {} --- @type string[] +local rtp_cache_key --- @type string? + --- Gets the rtp excluding after directories. --- The result is cached, and will be updated if the runtime path changes. --- When called from a fast event, the cached value will be returned. --- @return string[] rtp, boolean updated ----@private -function Loader.get_rtp() +local function get_rtp() if vim.in_fast_event() then - return (Loader._rtp or {}), false + return (rtp_cached or {}), false end local updated = false local key = vim.go.rtp - if key ~= Loader._rtp_key then - Loader._rtp = {} + if key ~= rtp_cache_key then + rtp_cached = {} for _, path in ipairs(vim.api.nvim_get_runtime_file('', true)) do path = normalize(path) -- skip after directories if path:sub(-6, -1) ~= '/after' - and not (Loader._indexed[path] and vim.tbl_isempty(Loader._indexed[path])) + and not (indexed[path] and vim.tbl_isempty(indexed[path])) then - Loader._rtp[#Loader._rtp + 1] = path + rtp_cached[#rtp_cached + 1] = path end end updated = true - Loader._rtp_key = key + rtp_cache_key = key end - return Loader._rtp, updated + return rtp_cached, updated end --- Returns the cache file name ----@param name string can be a module name, or a file name ----@return string file_name ----@private -function Loader.cache_file(name) +--- @param name string can be a module name, or a file name +--- @return string file_name +local function cache_filename(name) local ret = ('%s/%s'):format(M.path, uri_encode(name, 'rfc2396')) return ret:sub(-4) == '.lua' and (ret .. 'c') or (ret .. '.luac') end --- Saves the cache entry for a given module or file ----@param name string module name or filename ----@param entry CacheEntry ----@private -function Loader.write(name, entry) - local cname = Loader.cache_file(name) +--- @param cname string cache filename +--- @param hash vim.loader.CacheHash +--- @param chunk function +local function write_cachefile(cname, hash, chunk) local f = assert(uv.fs_open(cname, 'w', 438)) local header = { - Loader.VERSION, - entry.hash.size, - entry.hash.mtime.sec, - entry.hash.mtime.nsec, + VERSION, + hash.size, + hash.mtime.sec, + hash.mtime.nsec, } uv.fs_write(f, table.concat(header, ',') .. '\0') - uv.fs_write(f, entry.chunk) + uv.fs_write(f, string.dump(chunk)) uv.fs_close(f) end @@ -150,151 +143,159 @@ end local function readfile(path, mode) local f = uv.fs_open(path, 'r', mode) if f then - local hash = assert(uv.fs_fstat(f)) - local data = uv.fs_read(f, hash.size, 0) --[[@as string?]] + local size = assert(uv.fs_fstat(f)).size + local data = uv.fs_read(f, size, 0) uv.fs_close(f) return data end end --- Loads the cache entry for a given module or file ----@param name string module name or filename ----@return CacheEntry? ----@private -function Loader.read(name) - local cname = Loader.cache_file(name) +--- @param cname string cache filename +--- @return vim.loader.CacheHash? hash +--- @return string? chunk +local function read_cachefile(cname) local data = readfile(cname, 438) - if data then - local zero = data:find('\0', 1, true) - if not zero then - return - end + if not data then + return + end - ---@type integer[]|{[0]:integer} - local header = vim.split(data:sub(1, zero - 1), ',') - if tonumber(header[1]) ~= Loader.VERSION then - return - end - return { - hash = { - size = tonumber(header[2]), - mtime = { sec = tonumber(header[3]), nsec = tonumber(header[4]) }, - }, - chunk = data:sub(zero + 1), - } + local zero = data:find('\0', 1, true) + if not zero then + return + end + + --- @type integer[]|{[0]:integer} + local header = vim.split(data:sub(1, zero - 1), ',') + if tonumber(header[1]) ~= VERSION then + return end + + local hash = { + size = tonumber(header[2]), + mtime = { sec = tonumber(header[3]), nsec = tonumber(header[4]) }, + } + + local chunk = data:sub(zero + 1) + + return hash, chunk end --- The `package.loaders` loader for Lua files using the cache. ----@param modname string module name ----@return string|function ----@private -function Loader.loader(modname) - Loader._hashes = {} +--- @param modname string module name +--- @return string|function +local function loader_cached(modname) + fs_stat_cache = {} local ret = M.find(modname)[1] if ret then -- Make sure to call the global loadfile so we respect any augmentations done elsewhere. -- E.g. profiling local chunk, err = loadfile(ret.modpath) - Loader._hashes = nil + fs_stat_cache = nil return chunk or error(err) end - Loader._hashes = nil + fs_stat_cache = nil return ("\n\tcache_loader: module '%s' not found"):format(modname) end +local is_win = vim.fn.has('win32') == 1 + --- The `package.loaders` loader for libs ----@param modname string module name ----@return string|function ----@private -function Loader.loader_lib(modname) - local is_win = vim.fn.has('win32') == 1 - local ret = M.find(modname, { patterns = is_win and { '.dll' } or { '.so' } })[1] - if ret then - -- Making function name in Lua 5.1 (see src/loadlib.c:mkfuncname) is - -- a) strip prefix up to and including the first dash, if any - -- b) replace all dots by underscores - -- c) prepend "luaopen_" - -- So "foo-bar.baz" should result in "luaopen_bar_baz" - local dash = modname:find('-', 1, true) - local funcname = dash and modname:sub(dash + 1) or modname - local chunk, err = package.loadlib(ret.modpath, 'luaopen_' .. funcname:gsub('%.', '_')) - return chunk or error(err) +--- @param modname string module name +--- @return string|function +local function loader_lib_cached(modname) + local ret = M.find(modname, { patterns = { is_win and '.dll' or '.so' } })[1] + if not ret then + return ("\n\tcache_loader_lib: module '%s' not found"):format(modname) end - return ("\n\tcache_loader_lib: module '%s' not found"):format(modname) -end ---- `loadfile` using the cache ---- Note this has the mode and env arguments which is supported by LuaJIT and is 5.1 compatible. ----@param filename? string ----@param _mode? "b"|"t"|"bt" ----@param env? table ----@return function?, string? error_message ----@private -function Loader.loadfile(filename, _mode, env) - -- ignore mode, since we byte-compile the Lua source files - return Loader.load(normalize(filename), { env = env }) + -- Making function name in Lua 5.1 (see src/loadlib.c:mkfuncname) is + -- a) strip prefix up to and including the first dash, if any + -- b) replace all dots by underscores + -- c) prepend "luaopen_" + -- So "foo-bar.baz" should result in "luaopen_bar_baz" + local dash = modname:find('-', 1, true) + local funcname = dash and modname:sub(dash + 1) or modname + local chunk, err = package.loadlib(ret.modpath, 'luaopen_' .. funcname:gsub('%.', '_')) + return chunk or error(err) end --- Checks whether two cache hashes are the same based on: --- * file size --- * mtime in seconds --- * mtime in nanoseconds ----@param h1 CacheHash ----@param h2 CacheHash ----@private -function Loader.eq(h1, h2) - return h1 - and h2 - and h1.size == h2.size - and h1.mtime.sec == h2.mtime.sec - and h1.mtime.nsec == h2.mtime.nsec +--- @param a? vim.loader.CacheHash +--- @param b? vim.loader.CacheHash +local function hash_eq(a, b) + return a + and b + and a.size == b.size + and a.mtime.sec == b.mtime.sec + and a.mtime.nsec == b.mtime.nsec end ---- Loads the given module path using the cache ----@param modpath string ----@param opts? {mode?: "b"|"t"|"bt", env?:table} (table|nil) Options for loading the module: ---- - mode: (string) the mode to load the module with. "b"|"t"|"bt" (defaults to `nil`) ---- - env: (table) the environment to load the module in. (defaults to `nil`) ----@see |luaL_loadfile()| ----@return function?, string? error_message ----@private -function Loader.load(modpath, opts) - opts = opts or {} - local hash = Loader.get_hash(modpath) - ---@type function?, string? - local chunk, err - - if not hash then - -- trigger correct error - return Loader._loadfile(modpath, opts.mode, opts.env) - end - - local entry = Loader.read(modpath) - if entry and Loader.eq(entry.hash, hash) then - -- found in cache and up to date - chunk, err = load(entry.chunk --[[@as string]], '@' .. modpath, opts.mode, opts.env) - if not (err and err:find('cannot load incompatible bytecode', 1, true)) then - return chunk, err +--- `loadfile` using the cache +--- Note this has the mode and env arguments which is supported by LuaJIT and is 5.1 compatible. +--- @param filename? string +--- @param mode? "b"|"t"|"bt" +--- @param env? table +--- @return function?, string? error_message +local function loadfile_cached(filename, mode, env) + local modpath = normalize(filename) + local stat = fs_stat_cached(modpath) + local cname = cache_filename(modpath) + if stat then + local e_hash, e_chunk = read_cachefile(cname) + if hash_eq(e_hash, stat) and e_chunk then + -- found in cache and up to date + local chunk, err = load(e_chunk, '@' .. modpath, mode, env) + if not (err and err:find('cannot load incompatible bytecode', 1, true)) then + return chunk, err + end end end - entry = { hash = hash, modpath = modpath } - chunk, err = Loader._loadfile(modpath, opts.mode, opts.env) - if chunk then - entry.chunk = string.dump(chunk) - Loader.write(modpath, entry) + local chunk, err = _loadfile(modpath, mode, env) + if chunk and stat then + write_cachefile(cname, stat, chunk) end return chunk, err end +--- Return the top-level \`/lua/*` modules for this path +--- @param path string path to check for top-level Lua modules +local function lsmod(path) + if not indexed[path] then + indexed[path] = {} + for name, t in fs.dir(path .. '/lua') do + local modpath = path .. '/lua/' .. name + -- HACK: type is not always returned due to a bug in luv + t = t or fs_stat_cached(modpath).type + --- @type string + local topname + local ext = name:sub(-4) + if ext == '.lua' or ext == '.dll' then + topname = name:sub(1, -5) + elseif name:sub(-3) == '.so' then + topname = name:sub(1, -4) + elseif t == 'link' or t == 'directory' then + topname = name + end + if topname then + indexed[path][topname] = { modpath = modpath, modname = topname } + end + end + end + return indexed[path] +end + --- Finds Lua modules for the given module name. --- --- @since 0 --- ----@param modname string Module name, or `"*"` to find the top-level modules instead ----@param opts? vim.loader.find.Opts Options for finding a module: ----@return vim.loader.ModuleInfo[] +--- @param modname string Module name, or `"*"` to find the top-level modules instead +--- @param opts? vim.loader.find.Opts Options for finding a module: +--- @return vim.loader.ModuleInfo[] function M.find(modname, opts) opts = opts or {} @@ -320,7 +321,7 @@ function M.find(modname, opts) patterns[p] = '/lua/' .. basename .. pattern end - ---@type vim.loader.ModuleInfo[] + --- @type vim.loader.ModuleInfo[] local results = {} -- Only continue if we haven't found anything yet or we want to find all @@ -330,23 +331,23 @@ function M.find(modname, opts) -- Checks if the given paths contain the top-level module. -- If so, it tries to find the module path for the given module name. - ---@param paths string[] + --- @param paths string[] local function _find(paths) for _, path in ipairs(paths) do if topmod == '*' then - for _, r in pairs(Loader.lsmod(path)) do + for _, r in pairs(lsmod(path)) do results[#results + 1] = r if not continue() then return end end - elseif Loader.lsmod(path)[topmod] then + elseif lsmod(path)[topmod] then for _, pattern in ipairs(patterns) do local modpath = path .. pattern - Loader._stats.find.stat = (Loader._stats.find.stat or 0) + 1 - local hash = Loader.get_hash(modpath) - if hash then - results[#results + 1] = { modpath = modpath, stat = hash, modname = modname } + stats.find.stat = (stats.find.stat or 0) + 1 + local stat = fs_stat_cached(modpath) + if stat then + results[#results + 1] = { modpath = modpath, stat = stat, modname = modname } if not continue() then return end @@ -358,9 +359,9 @@ function M.find(modname, opts) -- always check the rtp first if opts.rtp ~= false then - _find(Loader._rtp or {}) + _find(rtp_cached or {}) if continue() then - local rtp, updated = Loader.get_rtp() + local rtp, updated = get_rtp() if updated then _find(rtp) end @@ -374,7 +375,7 @@ function M.find(modname, opts) if #results == 0 then -- module not found - Loader._stats.find.not_found = Loader._stats.find.not_found + 1 + stats.find.not_found = stats.find.not_found + 1 end return results @@ -384,17 +385,17 @@ end --- --- @since 0 --- ----@param path string? path to reset +--- @param path string? path to reset function M.reset(path) if path then - Loader._indexed[normalize(path)] = nil + indexed[normalize(path)] = nil else - Loader._indexed = {} + indexed = {} end -- Path could be a directory so just clear all the hashes. - if Loader._hashes then - Loader._hashes = {} + if fs_stat_cache then + fs_stat_cache = {} end end @@ -411,11 +412,11 @@ function M.enable() end M.enabled = true vim.fn.mkdir(vim.fn.fnamemodify(M.path, ':p'), 'p') - _G.loadfile = Loader.loadfile + _G.loadfile = loadfile_cached -- add Lua loader - table.insert(loaders, 2, Loader.loader) + table.insert(loaders, 2, loader_cached) -- add libs loader - table.insert(loaders, 3, Loader.loader_lib) + table.insert(loaders, 3, loader_lib_cached) -- remove Nvim loader for l, loader in ipairs(loaders) do if loader == vim._load_package then @@ -435,111 +436,75 @@ function M.disable() return end M.enabled = false - _G.loadfile = Loader._loadfile + _G.loadfile = _loadfile for l, loader in ipairs(loaders) do - if loader == Loader.loader or loader == Loader.loader_lib then + if loader == loader_cached or loader == loader_lib_cached then table.remove(loaders, l) end end table.insert(loaders, 2, vim._load_package) end ---- Return the top-level \`/lua/*` modules for this path ----@param path string path to check for top-level Lua modules ----@private -function Loader.lsmod(path) - if not Loader._indexed[path] then - Loader._indexed[path] = {} - for name, t in fs.dir(path .. '/lua') do - local modpath = path .. '/lua/' .. name - -- HACK: type is not always returned due to a bug in luv - t = t or Loader.get_hash(modpath).type - ---@type string - local topname - local ext = name:sub(-4) - if ext == '.lua' or ext == '.dll' then - topname = name:sub(1, -5) - elseif name:sub(-3) == '.so' then - topname = name:sub(1, -4) - elseif t == 'link' or t == 'directory' then - topname = name - end - if topname then - Loader._indexed[path][topname] = { modpath = modpath, modname = topname } - Loader._topmods[topname] = Loader._topmods[topname] or {} - if not vim.list_contains(Loader._topmods[topname], path) then - table.insert(Loader._topmods[topname], path) - end - end - end - end - return Loader._indexed[path] -end - --- Tracks the time spent in a function --- @generic F: function --- @param f F --- @return F ---- @private -function Loader.track(stat, f) +local function track(stat, f) return function(...) local start = vim.uv.hrtime() local r = { f(...) } - Loader._stats[stat] = Loader._stats[stat] or { total = 0, time = 0 } - Loader._stats[stat].total = Loader._stats[stat].total + 1 - Loader._stats[stat].time = Loader._stats[stat].time + uv.hrtime() - start + stats[stat] = stats[stat] or { total = 0, time = 0 } + stats[stat].total = stats[stat].total + 1 + stats[stat].time = stats[stat].time + uv.hrtime() - start return unpack(r, 1, table.maxn(r)) end end ----@class (private) vim.loader._profile.Opts ----@field loaders? boolean Add profiling to the loaders +--- @class (private) vim.loader._profile.Opts +--- @field loaders? boolean Add profiling to the loaders --- Debug function that wraps all loaders and tracks stats ----@private ----@param opts vim.loader._profile.Opts? +--- Must be called before vim.loader.enable() +--- @private +--- @param opts vim.loader._profile.Opts? function M._profile(opts) - Loader.get_rtp = Loader.track('get_rtp', Loader.get_rtp) - Loader.read = Loader.track('read', Loader.read) - Loader.loader = Loader.track('loader', Loader.loader) - Loader.loader_lib = Loader.track('loader_lib', Loader.loader_lib) - Loader.loadfile = Loader.track('loadfile', Loader.loadfile) - Loader.load = Loader.track('load', Loader.load) - M.find = Loader.track('find', M.find) - Loader.lsmod = Loader.track('lsmod', Loader.lsmod) + get_rtp = track('get_rtp', get_rtp) + read_cachefile = track('read', read_cachefile) + loader_cached = track('loader', loader_cached) + loader_lib_cached = track('loader_lib', loader_lib_cached) + loadfile_cached = track('loadfile', loadfile_cached) + M.find = track('find', M.find) + lsmod = track('lsmod', lsmod) if opts and opts.loaders then for l, loader in pairs(loaders) do local loc = debug.getinfo(loader, 'Sn').source:sub(2) - loaders[l] = Loader.track('loader ' .. l .. ': ' .. loc, loader) + loaders[l] = track('loader ' .. l .. ': ' .. loc, loader) end end end --- Prints all cache stats ----@param opts? {print?:boolean} ----@return LoaderStats ----@private +--- @param opts? {print?:boolean} +--- @return vim.loader.Stats +--- @private function M._inspect(opts) if opts and opts.print then local function ms(nsec) return math.floor(nsec / 1e6 * 1000 + 0.5) / 1000 .. 'ms' end - local chunks = {} ---@type string[][] - ---@type string[] - local stats = vim.tbl_keys(Loader._stats) - table.sort(stats) - for _, stat in ipairs(stats) do + local chunks = {} --- @type string[][] + for _, stat in vim.spairs(stats) do vim.list_extend(chunks, { { '\n' .. stat .. '\n', 'Title' }, { '* total: ' }, - { tostring(Loader._stats[stat].total) .. '\n', 'Number' }, + { tostring(stat.total) .. '\n', 'Number' }, { '* time: ' }, - { ms(Loader._stats[stat].time) .. '\n', 'Bold' }, + { ms(stat.time) .. '\n', 'Bold' }, { '* avg time: ' }, - { ms(Loader._stats[stat].time / Loader._stats[stat].total) .. '\n', 'Bold' }, + { ms(stat.time / stat.total) .. '\n', 'Bold' }, }) - for k, v in pairs(Loader._stats[stat]) do + for k, v in pairs(stat) do if not vim.list_contains({ 'time', 'total' }, k) then chunks[#chunks + 1] = { '* ' .. k .. ':' .. string.rep(' ', 9 - #k) } chunks[#chunks + 1] = { tostring(v) .. '\n', 'Number' } @@ -548,7 +513,7 @@ function M._inspect(opts) end vim.api.nvim_echo(chunks, true, {}) end - return Loader._stats + return stats end return M diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 60677554ce..0de3b4ee4d 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -3,7 +3,6 @@ local validate = vim.validate local lsp = vim._defer_require('vim.lsp', { _changetracking = ..., --- @module 'vim.lsp._changetracking' - _dynamic = ..., --- @module 'vim.lsp._dynamic' _snippet_grammar = ..., --- @module 'vim.lsp._snippet_grammar' _tagfunc = ..., --- @module 'vim.lsp._tagfunc' _watchfiles = ..., --- @module 'vim.lsp._watchfiles' @@ -31,6 +30,13 @@ local changetracking = lsp._changetracking ---@nodoc lsp.rpc_response_error = lsp.rpc.rpc_response_error +lsp._resolve_to_request = { + [ms.codeAction_resolve] = ms.textDocument_codeAction, + [ms.codeLens_resolve] = ms.textDocument_codeLens, + [ms.documentLink_resolve] = ms.textDocument_documentLink, + [ms.inlayHint_resolve] = ms.textDocument_inlayHint, +} + -- maps request name to the required server_capability in the client. lsp._request_name_to_capability = { [ms.callHierarchy_incomingCalls] = { 'callHierarchyProvider' }, @@ -86,7 +92,7 @@ lsp._request_name_to_capability = { ---@param bufnr (integer|nil) Buffer number to resolve. Defaults to current buffer ---@return integer bufnr local function resolve_bufnr(bufnr) - validate({ bufnr = { bufnr, 'n', true } }) + validate('bufnr', bufnr, 'number', true) if bufnr == nil or bufnr == 0 then return api.nvim_get_current_buf() end @@ -189,9 +195,10 @@ local function reuse_client_default(client, config) end if config.root_dir then + local root = vim.uri_from_fname(config.root_dir) for _, dir in ipairs(client.workspace_folders or {}) do -- note: do not need to check client.root_dir since that should be client.workspace_folders[1] - if config.root_dir == dir.name then + if root == dir.uri then return true end end @@ -235,9 +242,9 @@ end --- - `name` arbitrary name for the LSP client. Should be unique per language server. --- - `cmd` command string[] or function, described at |vim.lsp.start_client()|. --- - `root_dir` path to the project root. By default this is used to decide if an existing client ---- should be re-used. The example above uses |vim.fs.root()| and |vim.fs.dirname()| to detect ---- the root by traversing the file system upwards starting from the current directory until ---- either a `pyproject.toml` or `setup.py` file is found. +--- should be re-used. The example above uses |vim.fs.root()| to detect the root by traversing +--- the file system upwards starting from the current directory until either a `pyproject.toml` +--- or `setup.py` file is found. --- - `workspace_folders` list of `{ uri:string, name: string }` tables specifying the project root --- folders used by the language server. If `nil` the property is derived from `root_dir` for --- convenience. @@ -630,10 +637,8 @@ end ---@param client_id (integer) Client id ---@return boolean success `true` if client was attached successfully; `false` otherwise function lsp.buf_attach_client(bufnr, client_id) - validate({ - bufnr = { bufnr, 'n', true }, - client_id = { client_id, 'n' }, - }) + validate('bufnr', bufnr, 'number', true) + validate('client_id', client_id, 'number') bufnr = resolve_bufnr(bufnr) if not api.nvim_buf_is_loaded(bufnr) then log.warn(string.format('buf_attach_client called on unloaded buffer (id: %d): ', bufnr)) @@ -669,10 +674,8 @@ end ---@param bufnr integer Buffer handle, or 0 for current ---@param client_id integer Client id function lsp.buf_detach_client(bufnr, client_id) - validate({ - bufnr = { bufnr, 'n', true }, - client_id = { client_id, 'n' }, - }) + validate('bufnr', bufnr, 'number', true) + validate('client_id', client_id, 'number') bufnr = resolve_bufnr(bufnr) local client = all_clients[client_id] @@ -773,7 +776,7 @@ end ---@param filter? vim.lsp.get_clients.Filter ---@return vim.lsp.Client[]: List of |vim.lsp.Client| objects function lsp.get_clients(filter) - validate({ filter = { filter, 't', true } }) + validate('filter', filter, 'table', true) filter = filter or {} @@ -858,7 +861,7 @@ api.nvim_create_autocmd('VimLeavePre', { --- ---@param bufnr (integer) Buffer handle, or 0 for current. ---@param method (string) LSP method name ----@param params table|nil Parameters to send to the server +---@param params? table|(fun(client: vim.lsp.Client, bufnr: integer): table?) Parameters to send to the server ---@param handler? lsp.Handler See |lsp-handler| --- If nil, follows resolution strategy defined in |lsp-handler-configuration| ---@param on_unsupported? fun() @@ -870,12 +873,10 @@ api.nvim_create_autocmd('VimLeavePre', { ---cancel all the requests. You could instead ---iterate all clients and call their `cancel_request()` methods. function lsp.buf_request(bufnr, method, params, handler, on_unsupported) - validate({ - bufnr = { bufnr, 'n', true }, - method = { method, 's' }, - handler = { handler, 'f', true }, - on_unsupported = { on_unsupported, 'f', true }, - }) + validate('bufnr', bufnr, 'number', true) + validate('method', method, 'string') + validate('handler', handler, 'function', true) + validate('on_unsupported', on_unsupported, 'function', true) bufnr = resolve_bufnr(bufnr) local method_supported = false @@ -885,7 +886,8 @@ function lsp.buf_request(bufnr, method, params, handler, on_unsupported) if client.supports_method(method, { bufnr = bufnr }) then method_supported = true - local request_success, request_id = client.request(method, params, handler, bufnr) + local cparams = type(params) == 'function' and params(client, bufnr) or params --[[@as table?]] + local request_success, request_id = client.request(method, cparams, handler, bufnr) -- This could only fail if the client shut down in the time since we looked -- it up and we did the request, which should be rare. if request_success then @@ -920,35 +922,31 @@ end --- ---@param bufnr (integer) Buffer handle, or 0 for current. ---@param method (string) LSP method name ----@param params (table|nil) Parameters to send to the server ----@param handler fun(results: table<integer, {error: lsp.ResponseError?, result: any}>) (function) +---@param params? table|(fun(client: vim.lsp.Client, bufnr: integer): table?) Parameters to send to the server. +--- Can also be passed as a function that returns the params table for cases where +--- parameters are specific to the client. +---@param handler lsp.MultiHandler (function) --- Handler called after all requests are completed. Server results are passed as --- a `client_id:result` map. ---@return function cancel Function that cancels all requests. function lsp.buf_request_all(bufnr, method, params, handler) - local results = {} --- @type table<integer,{error: lsp.ResponseError?, result: any}> - local result_count = 0 - local expected_result_count = 0 - - local set_expected_result_count = once(function() - for _, client in ipairs(lsp.get_clients({ bufnr = bufnr })) do - if client.supports_method(method, { bufnr = bufnr }) then - expected_result_count = expected_result_count + 1 - end + local results = {} --- @type table<integer,{err: lsp.ResponseError?, result: any}> + local remaining --- @type integer? + + local _, cancel = lsp.buf_request(bufnr, method, params, function(err, result, ctx, config) + if not remaining then + -- Calculate as late as possible in case a client is removed during the request + remaining = #lsp.get_clients({ bufnr = bufnr, method = method }) end - end) - local function _sync_handler(err, result, ctx) - results[ctx.client_id] = { error = err, result = result } - result_count = result_count + 1 - set_expected_result_count() + -- The error key is deprecated and will be removed in 0.13 + results[ctx.client_id] = { err = err, error = err, result = result } + remaining = remaining - 1 - if result_count >= expected_result_count then - handler(results) + if remaining == 0 then + handler(results, ctx, config) end - end - - local _, cancel = lsp.buf_request(bufnr, method, params, _sync_handler) + end) return cancel end @@ -992,10 +990,8 @@ end --- ---@return boolean success true if any client returns true; false otherwise function lsp.buf_notify(bufnr, method, params) - validate({ - bufnr = { bufnr, 'n', true }, - method = { method, 's' }, - }) + validate('bufnr', bufnr, 'number', true) + validate('method', method, 'string') local resp = false for _, client in ipairs(lsp.get_clients({ bufnr = bufnr })) do if client.rpc.notify(method, params) then @@ -1056,7 +1052,7 @@ function lsp.formatexpr(opts) if client.supports_method(ms.textDocument_rangeFormatting) then local params = util.make_formatting_params() local end_line = vim.fn.getline(end_lnum) --[[@as string]] - local end_col = util._str_utfindex_enc(end_line, nil, client.offset_encoding) + local end_col = vim.str_utfindex(end_line, client.offset_encoding) --- @cast params +lsp.DocumentRangeFormattingParams params.range = { start = { @@ -1175,6 +1171,7 @@ function lsp.for_each_buffer_client(bufnr, fn) end end +--- @deprecated --- Function to manage overriding defaults for LSP handlers. ---@param handler (lsp.Handler) See |lsp-handler| ---@param override_config (table) Table containing the keys to override behavior of the {handler} diff --git a/runtime/lua/vim/lsp/_dynamic.lua b/runtime/lua/vim/lsp/_dynamic.lua deleted file mode 100644 index 27113c0e74..0000000000 --- a/runtime/lua/vim/lsp/_dynamic.lua +++ /dev/null @@ -1,110 +0,0 @@ -local glob = vim.glob - ---- @class lsp.DynamicCapabilities ---- @field capabilities table<string, lsp.Registration[]> ---- @field client_id number -local M = {} - ---- @param client_id number ---- @return lsp.DynamicCapabilities -function M.new(client_id) - return setmetatable({ - capabilities = {}, - client_id = client_id, - }, { __index = M }) -end - -function M:supports_registration(method) - local client = vim.lsp.get_client_by_id(self.client_id) - if not client then - return false - end - local capability = vim.tbl_get(client.capabilities, unpack(vim.split(method, '/'))) - return type(capability) == 'table' and capability.dynamicRegistration -end - ---- @param registrations lsp.Registration[] -function M:register(registrations) - -- remove duplicates - self:unregister(registrations) - for _, reg in ipairs(registrations) do - local method = reg.method - if not self.capabilities[method] then - self.capabilities[method] = {} - end - table.insert(self.capabilities[method], reg) - end -end - ---- @param unregisterations lsp.Unregistration[] -function M:unregister(unregisterations) - for _, unreg in ipairs(unregisterations) do - local method = unreg.method - if not self.capabilities[method] then - return - end - local id = unreg.id - for i, reg in ipairs(self.capabilities[method]) do - if reg.id == id then - table.remove(self.capabilities[method], i) - break - end - end - end -end - ---- @param method string ---- @param opts? {bufnr: integer?} ---- @return lsp.Registration? (table|nil) the registration if found -function M:get(method, opts) - opts = opts or {} - opts.bufnr = opts.bufnr or vim.api.nvim_get_current_buf() - for _, reg in ipairs(self.capabilities[method] or {}) do - if not reg.registerOptions then - return reg - end - local documentSelector = reg.registerOptions.documentSelector - if not documentSelector then - return reg - end - if self:match(opts.bufnr, documentSelector) then - return reg - end - end -end - ---- @param method string ---- @param opts? {bufnr: integer?} -function M:supports(method, opts) - return self:get(method, opts) ~= nil -end - ---- @param bufnr number ---- @param documentSelector lsp.DocumentSelector ---- @private -function M:match(bufnr, documentSelector) - local client = vim.lsp.get_client_by_id(self.client_id) - if not client then - return false - end - local language = client.get_language_id(bufnr, vim.bo[bufnr].filetype) - local uri = vim.uri_from_bufnr(bufnr) - local fname = vim.uri_to_fname(uri) - for _, filter in ipairs(documentSelector) do - local matches = true - if filter.language and language ~= filter.language then - matches = false - end - if matches and filter.scheme and not vim.startswith(uri, filter.scheme .. ':') then - matches = false - end - if matches and filter.pattern and not glob.to_lpeg(filter.pattern):match(fname) then - matches = false - end - if matches then - return true - end - end -end - -return M diff --git a/runtime/lua/vim/lsp/_meta.lua b/runtime/lua/vim/lsp/_meta.lua index be3222828d..bf693ccc57 100644 --- a/runtime/lua/vim/lsp/_meta.lua +++ b/runtime/lua/vim/lsp/_meta.lua @@ -1,7 +1,8 @@ ---@meta error('Cannot require a meta file') ----@alias lsp.Handler fun(err: lsp.ResponseError?, result: any, context: lsp.HandlerContext, config?: table): ...any +---@alias lsp.Handler fun(err: lsp.ResponseError?, result: any, context: lsp.HandlerContext): ...any +---@alias lsp.MultiHandler fun(results: table<integer,{err: lsp.ResponseError?, result: any}>, context: lsp.HandlerContext): ...any ---@class lsp.HandlerContext ---@field method string diff --git a/runtime/lua/vim/lsp/_tagfunc.lua b/runtime/lua/vim/lsp/_tagfunc.lua index 4ad50e4a58..f75d43f373 100644 --- a/runtime/lua/vim/lsp/_tagfunc.lua +++ b/runtime/lua/vim/lsp/_tagfunc.lua @@ -1,4 +1,5 @@ local lsp = vim.lsp +local api = vim.api local util = lsp.util local ms = lsp.protocol.Methods @@ -21,32 +22,48 @@ end ---@param pattern string ---@return table[] local function query_definition(pattern) - local params = util.make_position_params() - local results_by_client, err = lsp.buf_request_sync(0, ms.textDocument_definition, params, 1000) - if err then + local bufnr = api.nvim_get_current_buf() + local clients = vim.lsp.get_clients({ bufnr = bufnr, method = ms.textDocument_definition }) + if not next(clients) then return {} end + local win = api.nvim_get_current_win() local results = {} + + --- @param range lsp.Range + --- @param uri string + --- @param offset_encoding string local add = function(range, uri, offset_encoding) table.insert(results, mk_tag_item(pattern, range, uri, offset_encoding)) end - for client_id, lsp_results in pairs(assert(results_by_client)) do - local client = lsp.get_client_by_id(client_id) - local offset_encoding = client and client.offset_encoding or 'utf-16' - local result = lsp_results.result or {} - if result.range then -- Location - add(result.range, result.uri) - else - result = result --[[@as (lsp.Location[]|lsp.LocationLink[])]] - for _, item in pairs(result) do - if item.range then -- Location - add(item.range, item.uri, offset_encoding) - else -- LocationLink - add(item.targetSelectionRange, item.targetUri, offset_encoding) + + local remaining = #clients + for _, client in ipairs(clients) do + ---@param result nil|lsp.Location|lsp.Location[]|lsp.LocationLink[] + local function on_response(_, result) + if result then + local encoding = client.offset_encoding + -- single Location + if result.range then + add(result.range, result.uri, encoding) + else + for _, location in ipairs(result) do + if location.range then -- Location + add(location.range, location.uri, encoding) + else -- LocationLink + add(location.targetSelectionRange, location.targetUri, encoding) + end + end end end + remaining = remaining - 1 end + local params = util.make_position_params(win, client.offset_encoding) + client.request(ms.textDocument_definition, params, on_response, bufnr) end + vim.wait(1000, function() + return remaining == 0 + end) return results end diff --git a/runtime/lua/vim/lsp/_watchfiles.lua b/runtime/lua/vim/lsp/_watchfiles.lua index 98e9818bcd..c4cdb5aea8 100644 --- a/runtime/lua/vim/lsp/_watchfiles.lua +++ b/runtime/lua/vim/lsp/_watchfiles.lua @@ -44,9 +44,8 @@ M._poll_exclude_pattern = glob.to_lpeg('**/.git/{objects,subtree-cache}/**') --- Registers the workspace/didChangeWatchedFiles capability dynamically. --- ---@param reg lsp.Registration LSP Registration object. ----@param ctx lsp.HandlerContext Context from the |lsp-handler|. -function M.register(reg, ctx) - local client_id = ctx.client_id +---@param client_id integer Client ID. +function M.register(reg, client_id) local client = assert(vim.lsp.get_client_by_id(client_id), 'Client must be running') -- Ill-behaved servers may not honor the client capability and try to register -- anyway, so ignore requests when the user has opted out of the feature. @@ -155,9 +154,8 @@ end --- Unregisters the workspace/didChangeWatchedFiles capability dynamically. --- ---@param unreg lsp.Unregistration LSP Unregistration object. ----@param ctx lsp.HandlerContext Context from the |lsp-handler|. -function M.unregister(unreg, ctx) - local client_id = ctx.client_id +---@param client_id integer Client ID. +function M.unregister(unreg, client_id) local client_cancels = cancels[client_id] local reg_cancels = client_cancels[unreg.id] while #reg_cancels > 0 do diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index 301c1f0cb6..6383855a30 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -1,4 +1,5 @@ local api = vim.api +local lsp = vim.lsp local validate = vim.validate local util = require('vim.lsp.util') local npcall = vim.F.npcall @@ -6,28 +7,24 @@ local ms = require('vim.lsp.protocol').Methods local M = {} ---- Sends an async request to all active clients attached to the current ---- buffer. ---- ----@param method (string) LSP method name ----@param params (table|nil) Parameters to send to the server ----@param handler lsp.Handler? See |lsp-handler|. Follows |lsp-handler-resolution| ---- ----@return table<integer, integer> client_request_ids Map of client-id:request-id pairs ----for all successful requests. ----@return function _cancel_all_requests Function which can be used to ----cancel all the requests. You could instead ----iterate all clients and call their `cancel_request()` methods. ---- ----@see |vim.lsp.buf_request()| -local function request(method, params, handler) - validate({ - method = { method, 's' }, - handler = { handler, 'f', true }, - }) - return vim.lsp.buf_request(0, method, params, handler) +--- @param params? table +--- @return fun(client: vim.lsp.Client): lsp.TextDocumentPositionParams +local function client_positional_params(params) + local win = api.nvim_get_current_win() + return function(client) + local ret = util.make_position_params(win, client.offset_encoding) + if params then + ret = vim.tbl_extend('force', ret, params) + end + return ret + end end +local hover_ns = api.nvim_create_namespace('vim_lsp_hover_range') + +--- @class vim.lsp.buf.hover.Opts : vim.lsp.util.open_floating_preview.Opts +--- @field silent? boolean + --- Displays hover information about the symbol under the cursor in a floating --- window. The window will be dismissed on cursor move. --- Calling the function twice will jump into the floating window @@ -35,21 +32,210 @@ end --- In the floating window, all commands and mappings are available as usual, --- except that "q" dismisses the window. --- You can scroll the contents the same as you would any other buffer. -function M.hover() - local params = util.make_position_params() - request(ms.textDocument_hover, params) +--- +--- Note: to disable hover highlights, add the following to your config: +--- +--- ```lua +--- vim.api.nvim_create_autocmd('ColorScheme', { +--- callback = function() +--- vim.api.nvim_set_hl(0, 'LspReferenceTarget', {}) +--- end, +--- }) +--- ``` +--- @param config? vim.lsp.buf.hover.Opts +function M.hover(config) + config = config or {} + config.focus_id = ms.textDocument_hover + + lsp.buf_request_all(0, ms.textDocument_hover, client_positional_params(), function(results, ctx) + local bufnr = assert(ctx.bufnr) + if api.nvim_get_current_buf() ~= bufnr then + -- Ignore result since buffer changed. This happens for slow language servers. + return + end + + -- Filter errors from results + local results1 = {} --- @type table<integer,lsp.Hover> + + for client_id, resp in pairs(results) do + local err, result = resp.err, resp.result + if err then + lsp.log.error(err.code, err.message) + elseif result then + results1[client_id] = result + end + end + + if vim.tbl_isempty(results1) then + if config.silent ~= true then + vim.notify('No information available') + end + return + end + + local contents = {} --- @type string[] + + local nresults = #vim.tbl_keys(results1) + + local format = 'markdown' + + for client_id, result in pairs(results1) do + local client = assert(lsp.get_client_by_id(client_id)) + if nresults > 1 then + -- Show client name if there are multiple clients + contents[#contents + 1] = string.format('# %s', client.name) + end + if type(result.contents) == 'table' and result.contents.kind == 'plaintext' then + if #results1 == 1 then + format = 'plaintext' + contents = vim.split(result.contents.value or '', '\n', { trimempty = true }) + else + -- Surround plaintext with ``` to get correct formatting + contents[#contents + 1] = '```' + vim.list_extend( + contents, + vim.split(result.contents.value or '', '\n', { trimempty = true }) + ) + contents[#contents + 1] = '```' + end + else + vim.list_extend(contents, util.convert_input_to_markdown_lines(result.contents)) + end + local range = result.range + if range then + local start = range.start + local end_ = range['end'] + local start_idx = util._get_line_byte_from_position(bufnr, start, client.offset_encoding) + local end_idx = util._get_line_byte_from_position(bufnr, end_, client.offset_encoding) + + vim.hl.range( + bufnr, + hover_ns, + 'LspReferenceTarget', + { start.line, start_idx }, + { end_.line, end_idx }, + { priority = vim.hl.priorities.user } + ) + end + contents[#contents + 1] = '---' + end + + -- Remove last linebreak ('---') + contents[#contents] = nil + + if vim.tbl_isempty(contents) then + if config.silent ~= true then + vim.notify('No information available') + end + return + end + + local _, winid = lsp.util.open_floating_preview(contents, format, config) + + api.nvim_create_autocmd('WinClosed', { + pattern = tostring(winid), + once = true, + callback = function() + api.nvim_buf_clear_namespace(bufnr, hover_ns, 0, -1) + return true + end, + }) + end) end local function request_with_opts(name, params, opts) local req_handler --- @type function? if opts then req_handler = function(err, result, ctx, config) - local client = assert(vim.lsp.get_client_by_id(ctx.client_id)) - local handler = client.handlers[name] or vim.lsp.handlers[name] + local client = assert(lsp.get_client_by_id(ctx.client_id)) + local handler = client.handlers[name] or lsp.handlers[name] handler(err, result, ctx, vim.tbl_extend('force', config or {}, opts)) end end - request(name, params, req_handler) + lsp.buf_request(0, name, params, req_handler) +end + +---@param method string +---@param opts? vim.lsp.LocationOpts +local function get_locations(method, opts) + opts = opts or {} + local bufnr = api.nvim_get_current_buf() + local clients = lsp.get_clients({ method = method, bufnr = bufnr }) + if not next(clients) then + vim.notify(lsp._unsupported_method(method), vim.log.levels.WARN) + return + end + local win = api.nvim_get_current_win() + local from = vim.fn.getpos('.') + from[1] = bufnr + local tagname = vim.fn.expand('<cword>') + local remaining = #clients + + ---@type vim.quickfix.entry[] + local all_items = {} + + ---@param result nil|lsp.Location|lsp.Location[] + ---@param client vim.lsp.Client + local function on_response(_, result, client) + local locations = {} + if result then + locations = vim.islist(result) and result or { result } + end + local items = util.locations_to_items(locations, client.offset_encoding) + vim.list_extend(all_items, items) + remaining = remaining - 1 + if remaining == 0 then + if vim.tbl_isempty(all_items) then + vim.notify('No locations found', vim.log.levels.INFO) + return + end + + local title = 'LSP locations' + if opts.on_list then + assert(vim.is_callable(opts.on_list), 'on_list is not a function') + opts.on_list({ + title = title, + items = all_items, + context = { bufnr = bufnr, method = method }, + }) + return + end + + if #all_items == 1 then + local item = all_items[1] + local b = item.bufnr or vim.fn.bufadd(item.filename) + + -- Save position in jumplist + vim.cmd("normal! m'") + -- Push a new item into tagstack + local tagstack = { { tagname = tagname, from = from } } + vim.fn.settagstack(vim.fn.win_getid(win), { items = tagstack }, 't') + + vim.bo[b].buflisted = true + local w = opts.reuse_win and vim.fn.win_findbuf(b)[1] or win + api.nvim_win_set_buf(w, b) + api.nvim_win_set_cursor(w, { item.lnum, item.col - 1 }) + vim._with({ win = w }, function() + -- Open folds under the cursor + vim.cmd('normal! zv') + end) + return + end + if opts.loclist then + vim.fn.setloclist(0, {}, ' ', { title = title, items = all_items }) + vim.cmd.lopen() + else + vim.fn.setqflist({}, ' ', { title = title, items = all_items }) + vim.cmd('botright copen') + end + end + end + for _, client in ipairs(clients) do + local params = util.make_position_params(win, client.offset_encoding) + client.request(method, params, function(_, result) + on_response(_, result, client) + end) + end end --- @class vim.lsp.ListOpts @@ -89,39 +275,145 @@ end --- @note Many servers do not implement this method. Generally, see |vim.lsp.buf.definition()| instead. --- @param opts? vim.lsp.LocationOpts function M.declaration(opts) - local params = util.make_position_params() - request_with_opts(ms.textDocument_declaration, params, opts) + get_locations(ms.textDocument_declaration, opts) end --- Jumps to the definition of the symbol under the cursor. --- @param opts? vim.lsp.LocationOpts function M.definition(opts) - local params = util.make_position_params() - request_with_opts(ms.textDocument_definition, params, opts) + get_locations(ms.textDocument_definition, opts) end --- Jumps to the definition of the type of the symbol under the cursor. --- @param opts? vim.lsp.LocationOpts function M.type_definition(opts) - local params = util.make_position_params() - request_with_opts(ms.textDocument_typeDefinition, params, opts) + get_locations(ms.textDocument_typeDefinition, opts) end --- Lists all the implementations for the symbol under the cursor in the --- quickfix window. --- @param opts? vim.lsp.LocationOpts function M.implementation(opts) - local params = util.make_position_params() - request_with_opts(ms.textDocument_implementation, params, opts) + get_locations(ms.textDocument_implementation, opts) end +--- @param results table<integer,{err: lsp.ResponseError?, result: lsp.SignatureHelp?}> +local function process_signature_help_results(results) + local signatures = {} --- @type [vim.lsp.Client,lsp.SignatureInformation][] + + -- Pre-process results + for client_id, r in pairs(results) do + local err = r.err + local client = assert(lsp.get_client_by_id(client_id)) + if err then + vim.notify( + client.name .. ': ' .. tostring(err.code) .. ': ' .. err.message, + vim.log.levels.ERROR + ) + api.nvim_command('redraw') + else + local result = r.result --- @type lsp.SignatureHelp + if result and result.signatures and result.signatures[1] then + for _, sig in ipairs(result.signatures) do + signatures[#signatures + 1] = { client, sig } + end + end + end + end + + return signatures +end + +local sig_help_ns = api.nvim_create_namespace('vim_lsp_signature_help') + +--- @class vim.lsp.buf.signature_help.Opts : vim.lsp.util.open_floating_preview.Opts +--- @field silent? boolean + +-- TODO(lewis6991): support multiple clients --- Displays signature information about the symbol under the cursor in a --- floating window. -function M.signature_help() - local params = util.make_position_params() - request(ms.textDocument_signatureHelp, params) +--- @param config? vim.lsp.buf.signature_help.Opts +function M.signature_help(config) + local method = ms.textDocument_signatureHelp + + config = config and vim.deepcopy(config) or {} + config.focus_id = method + + lsp.buf_request_all(0, method, client_positional_params(), function(results, ctx) + if api.nvim_get_current_buf() ~= ctx.bufnr then + -- Ignore result since buffer changed. This happens for slow language servers. + return + end + + local signatures = process_signature_help_results(results) + + if not next(signatures) then + if config.silent ~= true then + print('No signature help available') + end + return + end + + local ft = vim.bo[ctx.bufnr].filetype + local total = #signatures + local idx = 0 + + --- @param update_win? integer + local function show_signature(update_win) + idx = (idx % total) + 1 + local client, result = signatures[idx][1], signatures[idx][2] + --- @type string[]? + local triggers = + vim.tbl_get(client.server_capabilities, 'signatureHelpProvider', 'triggerCharacters') + local lines, hl = + util.convert_signature_help_to_markdown_lines({ signatures = { result } }, ft, triggers) + if not lines then + return + end + + local sfx = total > 1 and string.format(' (%d/%d) (<C-s> to cycle)', idx, total) or '' + local title = string.format('Signature Help: %s%s', client.name, sfx) + if config.border then + config.title = title + else + table.insert(lines, 1, '# ' .. title) + if hl then + hl[1] = hl[1] + 1 + hl[3] = hl[3] + 1 + end + end + + config._update_win = update_win + + local buf, win = util.open_floating_preview(lines, 'markdown', config) + + if hl then + vim.api.nvim_buf_clear_namespace(buf, sig_help_ns, 0, -1) + vim.hl.range( + buf, + sig_help_ns, + 'LspSignatureActiveParameter', + { hl[1], hl[2] }, + { hl[3], hl[4] } + ) + end + return buf, win + end + + local fbuf, fwin = show_signature() + + if total > 1 then + vim.keymap.set('n', '<C-s>', function() + show_signature(fwin) + end, { + buffer = fbuf, + desc = 'Cycle next signature', + }) + end + end) end +--- @deprecated --- Retrieves the completion items at the current cursor position. Can only be --- called in Insert mode. --- @@ -131,9 +423,14 @@ end --- ---@see vim.lsp.protocol.CompletionTriggerKind function M.completion(context) - local params = util.make_position_params() - params.context = context - return request(ms.textDocument_completion, params) + vim.depends('vim.lsp.buf.completion', 'vim.lsp.commpletion.trigger', '0.12') + return lsp.buf_request( + 0, + ms.textDocument_completion, + client_positional_params({ + context = context, + }) + ) end ---@param bufnr integer @@ -240,7 +537,7 @@ function M.format(opts) method = ms.textDocument_formatting end - local clients = vim.lsp.get_clients({ + local clients = lsp.get_clients({ id = opts.id, bufnr = bufnr, name = opts.name, @@ -277,7 +574,7 @@ function M.format(opts) end local params = set_range(client, util.make_formatting_params(opts.formatting_options)) client.request(method, params, function(...) - local handler = client.handlers[method] or vim.lsp.handlers[method] + local handler = client.handlers[method] or lsp.handlers[method] handler(...) do_format(next(clients, idx)) end, bufnr) @@ -319,7 +616,7 @@ end function M.rename(new_name, opts) opts = opts or {} local bufnr = opts.bufnr or api.nvim_get_current_buf() - local clients = vim.lsp.get_clients({ + local clients = lsp.get_clients({ bufnr = bufnr, name = opts.name, -- Clients must at least support rename, prepareRename is optional @@ -338,6 +635,8 @@ function M.rename(new_name, opts) -- Compute early to account for cursor movements after going async local cword = vim.fn.expand('<cword>') + --- @param range lsp.Range + --- @param offset_encoding string local function get_text_at_range(range, offset_encoding) return api.nvim_buf_get_text( bufnr, @@ -359,7 +658,7 @@ function M.rename(new_name, opts) local params = util.make_position_params(win, client.offset_encoding) params.newName = name local handler = client.handlers[ms.textDocument_rename] - or vim.lsp.handlers[ms.textDocument_rename] + or lsp.handlers[ms.textDocument_rename] client.request(ms.textDocument_rename, params, function(...) handler(...) try_use_client(next(clients, idx)) @@ -437,12 +736,60 @@ end ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references ---@param opts? vim.lsp.ListOpts function M.references(context, opts) - validate({ context = { context, 't', true } }) - local params = util.make_position_params() - params.context = context or { - includeDeclaration = true, - } - request_with_opts(ms.textDocument_references, params, opts) + validate('context', context, 'table', true) + local bufnr = api.nvim_get_current_buf() + local clients = lsp.get_clients({ method = ms.textDocument_references, bufnr = bufnr }) + if not next(clients) then + return + end + local win = api.nvim_get_current_win() + opts = opts or {} + + local all_items = {} + local title = 'References' + + local function on_done() + if not next(all_items) then + vim.notify('No references found') + else + local list = { + title = title, + items = all_items, + context = { + method = ms.textDocument_references, + bufnr = bufnr, + }, + } + if opts.loclist then + vim.fn.setloclist(0, {}, ' ', list) + vim.cmd.lopen() + elseif opts.on_list then + assert(vim.is_callable(opts.on_list), 'on_list is not a function') + opts.on_list(list) + else + vim.fn.setqflist({}, ' ', list) + vim.cmd('botright copen') + end + end + end + + local remaining = #clients + for _, client in ipairs(clients) do + local params = util.make_position_params(win, client.offset_encoding) + + ---@diagnostic disable-next-line: inject-field + params.context = context or { + includeDeclaration = true, + } + client.request(ms.textDocument_references, params, function(_, result) + local items = util.locations_to_items(result or {}, client.offset_encoding) + vim.list_extend(all_items, items) + remaining = remaining - 1 + if remaining == 0 then + on_done() + end + end) + end end --- Lists all symbols in the current buffer in the quickfix window. @@ -452,65 +799,116 @@ function M.document_symbol(opts) request_with_opts(ms.textDocument_documentSymbol, params, opts) end ---- @param call_hierarchy_items lsp.CallHierarchyItem[] ---- @return lsp.CallHierarchyItem? -local function pick_call_hierarchy_item(call_hierarchy_items) - if #call_hierarchy_items == 1 then - return call_hierarchy_items[1] - end - local items = {} - for i, item in pairs(call_hierarchy_items) do - local entry = item.detail or item.name - table.insert(items, string.format('%d. %s', i, entry)) - end - local choice = vim.fn.inputlist(items) - if choice < 1 or choice > #items then +--- @param client_id integer +--- @param method string +--- @param params table +--- @param handler? lsp.Handler +--- @param bufnr? integer +local function request_with_id(client_id, method, params, handler, bufnr) + local client = lsp.get_client_by_id(client_id) + if not client then + vim.notify( + string.format('Client with id=%d disappeared during hierarchy request', client_id), + vim.log.levels.WARN + ) return end - return call_hierarchy_items[choice] + client.request(method, params, handler, bufnr) +end + +--- @param item lsp.TypeHierarchyItem|lsp.CallHierarchyItem +local function format_hierarchy_item(item) + if not item.detail or #item.detail == 0 then + return item.name + end + return string.format('%s %s', item.name, item.detail) end +local hierarchy_methods = { + [ms.typeHierarchy_subtypes] = 'type', + [ms.typeHierarchy_supertypes] = 'type', + [ms.callHierarchy_incomingCalls] = 'call', + [ms.callHierarchy_outgoingCalls] = 'call', +} + --- @param method string -local function call_hierarchy(method) - local params = util.make_position_params() - --- @param result lsp.CallHierarchyItem[]? - request(ms.textDocument_prepareCallHierarchy, params, function(err, result, ctx) - if err then - vim.notify(err.message, vim.log.levels.WARN) - return - end - if not result or vim.tbl_isempty(result) then +local function hierarchy(method) + local kind = hierarchy_methods[method] + if not kind then + error('unsupported method ' .. method) + end + + local prepare_method = kind == 'type' and ms.textDocument_prepareTypeHierarchy + or ms.textDocument_prepareCallHierarchy + + local bufnr = api.nvim_get_current_buf() + local clients = lsp.get_clients({ bufnr = bufnr, method = prepare_method }) + if not next(clients) then + vim.notify(lsp._unsupported_method(method), vim.log.levels.WARN) + return + end + + local win = api.nvim_get_current_win() + + --- @param results [integer, lsp.TypeHierarchyItem|lsp.CallHierarchyItem][] + local function on_response(results) + if #results == 0 then vim.notify('No item resolved', vim.log.levels.WARN) - return - end - local call_hierarchy_item = pick_call_hierarchy_item(result) - if not call_hierarchy_item then - return - end - local client = vim.lsp.get_client_by_id(ctx.client_id) - if client then - client.request(method, { item = call_hierarchy_item }, nil, ctx.bufnr) + elseif #results == 1 then + local client_id, item = results[1][1], results[1][2] + request_with_id(client_id, method, { item = item }, nil, bufnr) else - vim.notify( - string.format('Client with id=%d disappeared during call hierarchy request', ctx.client_id), - vim.log.levels.WARN - ) + vim.ui.select(results, { + prompt = string.format('Select a %s hierarchy item:', kind), + kind = kind .. 'hierarchy', + format_item = function(x) + return format_hierarchy_item(x[2]) + end, + }, function(x) + if x then + local client_id, item = x[1], x[2] + request_with_id(client_id, method, { item = item }, nil, bufnr) + end + end) end - end) + end + + local results = {} --- @type [integer, lsp.TypeHierarchyItem|lsp.CallHierarchyItem][] + + local remaining = #clients + + for _, client in ipairs(clients) do + local params = util.make_position_params(win, client.offset_encoding) + --- @param result lsp.CallHierarchyItem[]|lsp.TypeHierarchyItem[]? + client.request(prepare_method, params, function(err, result, ctx) + if err then + vim.notify(err.message, vim.log.levels.WARN) + elseif result then + for _, item in ipairs(result) do + results[#results + 1] = { ctx.client_id, item } + end + end + + remaining = remaining - 1 + if remaining == 0 then + on_response(results) + end + end, bufnr) + end end --- Lists all the call sites of the symbol under the cursor in the --- |quickfix| window. If the symbol can resolve to multiple --- items, the user can pick one in the |inputlist()|. function M.incoming_calls() - call_hierarchy(ms.callHierarchy_incomingCalls) + hierarchy(ms.callHierarchy_incomingCalls) end --- Lists all the items that are called by the symbol under the --- cursor in the |quickfix| window. If the symbol can resolve to --- multiple items, the user can pick one in the |inputlist()|. function M.outgoing_calls() - call_hierarchy(ms.callHierarchy_outgoingCalls) + hierarchy(ms.callHierarchy_outgoingCalls) end --- Lists all the subtypes or supertypes of the symbol under the @@ -519,79 +917,14 @@ end ---@param kind "subtypes"|"supertypes" function M.typehierarchy(kind) local method = kind == 'subtypes' and ms.typeHierarchy_subtypes or ms.typeHierarchy_supertypes - - --- Merge results from multiple clients into a single table. Client-ID is preserved. - --- - --- @param results table<integer, {error: lsp.ResponseError?, result: lsp.TypeHierarchyItem[]?}> - --- @return [integer, lsp.TypeHierarchyItem][] - local function merge_results(results) - local merged_results = {} - for client_id, client_result in pairs(results) do - if client_result.error then - vim.notify(client_result.error.message, vim.log.levels.WARN) - elseif client_result.result then - for _, item in pairs(client_result.result) do - table.insert(merged_results, { client_id, item }) - end - end - end - return merged_results - end - - local bufnr = api.nvim_get_current_buf() - local params = util.make_position_params() - --- @param results table<integer, {error: lsp.ResponseError?, result: lsp.TypeHierarchyItem[]?}> - vim.lsp.buf_request_all(bufnr, ms.textDocument_prepareTypeHierarchy, params, function(results) - local merged_results = merge_results(results) - if #merged_results == 0 then - vim.notify('No items resolved', vim.log.levels.INFO) - return - end - - if #merged_results == 1 then - local item = merged_results[1] - local client = vim.lsp.get_client_by_id(item[1]) - if client then - client.request(method, { item = item[2] }, nil, bufnr) - else - vim.notify( - string.format('Client with id=%d disappeared during call hierarchy request', item[1]), - vim.log.levels.WARN - ) - end - else - local select_opts = { - prompt = 'Select a type hierarchy item:', - kind = 'typehierarchy', - format_item = function(item) - if not item[2].detail or #item[2].detail == 0 then - return item[2].name - end - return string.format('%s %s', item[2].name, item[2].detail) - end, - } - - vim.ui.select(merged_results, select_opts, function(item) - local client = vim.lsp.get_client_by_id(item[1]) - if client then - --- @type lsp.TypeHierarchyItem - client.request(method, { item = item[2] }, nil, bufnr) - else - vim.notify( - string.format('Client with id=%d disappeared during call hierarchy request', item[1]), - vim.log.levels.WARN - ) - end - end) - end - end) + hierarchy(method) end --- List workspace folders. --- function M.list_workspace_folders() local workspace_folders = {} - for _, client in pairs(vim.lsp.get_clients({ bufnr = 0 })) do + for _, client in pairs(lsp.get_clients({ bufnr = 0 })) do for _, folder in pairs(client.workspace_folders or {}) do table.insert(workspace_folders, folder.name) end @@ -614,7 +947,7 @@ function M.add_workspace_folder(workspace_folder) return end local bufnr = api.nvim_get_current_buf() - for _, client in pairs(vim.lsp.get_clients({ bufnr = bufnr })) do + for _, client in pairs(lsp.get_clients({ bufnr = bufnr })) do client:_add_workspace_folder(workspace_folder) end end @@ -631,7 +964,7 @@ function M.remove_workspace_folder(workspace_folder) return end local bufnr = api.nvim_get_current_buf() - for _, client in pairs(vim.lsp.get_clients({ bufnr = bufnr })) do + for _, client in pairs(lsp.get_clients({ bufnr = bufnr })) do client:_remove_workspace_folder(workspace_folder) end print(workspace_folder, 'is not currently part of the workspace') @@ -670,8 +1003,7 @@ end --- |hl-LspReferenceRead| --- |hl-LspReferenceWrite| function M.document_highlight() - local params = util.make_position_params() - request(ms.textDocument_documentHighlight, params) + lsp.buf_request(0, ms.textDocument_documentHighlight, client_positional_params()) end --- Removes document highlights from current buffer. @@ -773,7 +1105,8 @@ local function on_code_action_results(results, opts) local a_cmd = action.command if a_cmd then local command = type(a_cmd) == 'table' and a_cmd or action - client:_exec_cmd(command, ctx) + --- @cast command lsp.Command + client:exec_cmd(command, ctx) end end @@ -794,16 +1127,11 @@ local function on_code_action_results(results, opts) -- command: string -- arguments?: any[] -- - local client = assert(vim.lsp.get_client_by_id(choice.ctx.client_id)) + local client = assert(lsp.get_client_by_id(choice.ctx.client_id)) local action = choice.action local bufnr = assert(choice.ctx.bufnr, 'Must have buffer number') - local reg = client.dynamic_capabilities:get(ms.textDocument_codeAction, { bufnr = bufnr }) - - local supports_resolve = vim.tbl_get(reg or {}, 'registerOptions', 'resolveProvider') - or client.supports_method(ms.codeAction_resolve) - - if not action.edit and client and supports_resolve then + if not action.edit and client.supports_method(ms.codeAction_resolve) then client.request(ms.codeAction_resolve, action, function(err, resolved_action) if err then if action.command then @@ -827,11 +1155,19 @@ local function on_code_action_results(results, opts) return end - ---@param item {action: lsp.Command|lsp.CodeAction} + ---@param item {action: lsp.Command|lsp.CodeAction, ctx: lsp.HandlerContext} local function format_item(item) - local title = item.action.title:gsub('\r\n', '\\r\\n') - return title:gsub('\n', '\\n') + local clients = lsp.get_clients({ bufnr = item.ctx.bufnr }) + local title = item.action.title:gsub('\r\n', '\\r\\n'):gsub('\n', '\\n') + + if #clients == 1 then + return title + end + + local source = lsp.get_client_by_id(item.ctx.client_id).name + return ('%s [%s]'):format(title, source) end + local select_opts = { prompt = 'Code actions:', kind = 'codeaction', @@ -847,7 +1183,7 @@ end ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction ---@see vim.lsp.protocol.CodeActionTriggerKind function M.code_action(opts) - validate({ options = { opts, 't', true } }) + validate('options', opts, 'table', true) opts = opts or {} -- Detect old API call code_action(context) which should now be -- code_action({ context = context} ) @@ -857,16 +1193,16 @@ function M.code_action(opts) end local context = opts.context and vim.deepcopy(opts.context) or {} if not context.triggerKind then - context.triggerKind = vim.lsp.protocol.CodeActionTriggerKind.Invoked + context.triggerKind = lsp.protocol.CodeActionTriggerKind.Invoked end local mode = api.nvim_get_mode().mode local bufnr = api.nvim_get_current_buf() local win = api.nvim_get_current_win() - local clients = vim.lsp.get_clients({ bufnr = bufnr, method = ms.textDocument_codeAction }) + local clients = lsp.get_clients({ bufnr = bufnr, method = ms.textDocument_codeAction }) local remaining = #clients if remaining == 0 then - if next(vim.lsp.get_clients({ bufnr = bufnr })) then - vim.notify(vim.lsp._unsupported_method(ms.textDocument_codeAction), vim.log.levels.WARN) + if next(lsp.get_clients({ bufnr = bufnr })) then + vim.notify(lsp._unsupported_method(ms.textDocument_codeAction), vim.log.levels.WARN) end return end @@ -903,8 +1239,8 @@ function M.code_action(opts) if context.diagnostics then params.context = context else - local ns_push = vim.lsp.diagnostic.get_namespace(client.id, false) - local ns_pull = vim.lsp.diagnostic.get_namespace(client.id, true) + local ns_push = lsp.diagnostic.get_namespace(client.id, false) + local ns_pull = lsp.diagnostic.get_namespace(client.id, true) local diagnostics = {} local lnum = api.nvim_win_get_cursor(0)[1] - 1 vim.list_extend(diagnostics, vim.diagnostic.get(bufnr, { namespace = ns_pull, lnum = lnum })) @@ -921,20 +1257,20 @@ function M.code_action(opts) end end +--- @deprecated --- Executes an LSP server command. --- @param command_params lsp.ExecuteCommandParams --- @see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand function M.execute_command(command_params) - validate({ - command = { command_params.command, 's' }, - arguments = { command_params.arguments, 't', true }, - }) + validate('command', command_params.command, 'string') + validate('arguments', command_params.arguments, 'table', true) + vim.deprecate('execute_command', 'client:exec_cmd', '0.12') command_params = { command = command_params.command, arguments = command_params.arguments, workDoneToken = command_params.workDoneToken, } - request(ms.workspace_executeCommand, command_params) + lsp.buf_request(0, ms.workspace_executeCommand, command_params) end return M diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua index e3c82f4169..11ecb87507 100644 --- a/runtime/lua/vim/lsp/client.lua +++ b/runtime/lua/vim/lsp/client.lua @@ -91,7 +91,7 @@ local validate = vim.validate --- (default: client-id) --- @field name? string --- ---- Language ID as string. Defaults to the filetype. +--- Language ID as string. Defaults to the buffer filetype. --- @field get_language_id? fun(bufnr: integer, filetype: string): string --- --- The encoding that the LSP server expects. Client does not verify this is correct. @@ -216,6 +216,7 @@ local validate = vim.validate --- --- The capabilities provided by the client (editor or tool) --- @field capabilities lsp.ClientCapabilities +--- @field private registrations table<string,lsp.Registration[]> --- @field dynamic_capabilities lsp.DynamicCapabilities --- --- Sends a request to the server. @@ -291,7 +292,7 @@ local client_index = 0 --- @param filename (string) path to check --- @return boolean # true if {filename} exists and is a directory, false otherwise local function is_dir(filename) - validate({ filename = { filename, 's' } }) + validate('filename', filename, 'string') local stat = uv.fs_stat(filename) return stat and stat.type == 'directory' or false end @@ -312,9 +313,7 @@ local valid_encodings = { --- @param encoding string? Encoding to normalize --- @return string # normalized encoding name local function validate_encoding(encoding) - validate({ - encoding = { encoding, 's', true }, - }) + validate('encoding', encoding, 'string', true) if not encoding then return valid_encodings.UTF16 end @@ -350,27 +349,23 @@ end --- Validates a client configuration as given to |vim.lsp.start_client()|. --- @param config vim.lsp.ClientConfig local function validate_config(config) - validate({ - config = { config, 't' }, - }) - validate({ - handlers = { config.handlers, 't', true }, - capabilities = { config.capabilities, 't', true }, - cmd_cwd = { config.cmd_cwd, optional_validator(is_dir), 'directory' }, - cmd_env = { config.cmd_env, 't', true }, - detached = { config.detached, 'b', true }, - name = { config.name, 's', true }, - on_error = { config.on_error, 'f', true }, - on_exit = { config.on_exit, { 'f', 't' }, true }, - on_init = { config.on_init, { 'f', 't' }, true }, - on_attach = { config.on_attach, { 'f', 't' }, true }, - settings = { config.settings, 't', true }, - commands = { config.commands, 't', true }, - before_init = { config.before_init, { 'f', 't' }, true }, - offset_encoding = { config.offset_encoding, 's', true }, - flags = { config.flags, 't', true }, - get_language_id = { config.get_language_id, 'f', true }, - }) + validate('config', config, 'table') + validate('handlers', config.handlers, 'table', true) + validate('capabilities', config.capabilities, 'table', true) + validate('cmd_cwd', config.cmd_cwd, optional_validator(is_dir), 'directory') + validate('cmd_env', config.cmd_env, 'table', true) + validate('detached', config.detached, 'boolean', true) + validate('name', config.name, 'string', true) + validate('on_error', config.on_error, 'function', true) + validate('on_exit', config.on_exit, { 'function', 'table' }, true) + validate('on_init', config.on_init, { 'function', 'table' }, true) + validate('on_attach', config.on_attach, { 'function', 'table' }, true) + validate('settings', config.settings, 'table', true) + validate('commands', config.commands, 'table', true) + validate('before_init', config.before_init, { 'function', 'table' }, true) + validate('offset_encoding', config.offset_encoding, 'string', true) + validate('flags', config.flags, 'table', true) + validate('get_language_id', config.get_language_id, 'function', true) assert( ( @@ -409,18 +404,16 @@ local function get_name(id, config) return tostring(id) end ---- @param workspace_folders lsp.WorkspaceFolder[]? ---- @param root_dir string? +--- @param workspace_folders string|lsp.WorkspaceFolder[]? --- @return lsp.WorkspaceFolder[]? -local function get_workspace_folders(workspace_folders, root_dir) - if workspace_folders then +local function get_workspace_folders(workspace_folders) + if type(workspace_folders) == 'table' then return workspace_folders - end - if root_dir then + elseif type(workspace_folders) == 'string' then return { { - uri = vim.uri_from_fname(root_dir), - name = root_dir, + uri = vim.uri_from_fname(workspace_folders), + name = workspace_folders, }, } end @@ -457,13 +450,13 @@ function Client.create(config) requests = {}, attached_buffers = {}, server_capabilities = {}, - dynamic_capabilities = lsp._dynamic.new(id), + registrations = {}, commands = config.commands or {}, settings = config.settings or {}, flags = config.flags or {}, get_language_id = config.get_language_id or default_get_language_id, capabilities = config.capabilities or lsp.protocol.make_client_capabilities(), - workspace_folders = get_workspace_folders(config.workspace_folders, config.root_dir), + workspace_folders = get_workspace_folders(config.workspace_folders or config.root_dir), root_dir = config.root_dir, _before_init_cb = config.before_init, _on_init_cbs = ensure_list(config.on_init), @@ -484,6 +477,28 @@ function Client.create(config) messages = { name = name, messages = {}, progress = {}, status = {} }, } + --- @class lsp.DynamicCapabilities + --- @nodoc + self.dynamic_capabilities = { + capabilities = self.registrations, + client_id = id, + register = function(_, registrations) + return self:_register_dynamic(registrations) + end, + unregister = function(_, unregistrations) + return self:_unregister_dynamic(unregistrations) + end, + get = function(_, method, opts) + return self:_get_registration(method, opts and opts.bufnr) + end, + supports_registration = function(_, method) + return self:_supports_registration(method) + end, + supports = function(_, method, opts) + return self:_get_registration(method, opts and opts.bufnr) ~= nil + end, + } + self.request = method_wrapper(self, Client._request) self.request_sync = method_wrapper(self, Client._request_sync) self.notify = method_wrapper(self, Client._notify) @@ -640,7 +655,7 @@ end --- @param bufnr (integer|nil) Buffer number to resolve. Defaults to current buffer --- @return integer bufnr local function resolve_bufnr(bufnr) - validate({ bufnr = { bufnr, 'n', true } }) + validate('bufnr', bufnr, 'number', true) if bufnr == nil or bufnr == 0 then return api.nvim_get_current_buf() end @@ -806,7 +821,7 @@ end --- @return boolean status true if notification was successful. false otherwise --- @see |vim.lsp.client.notify()| function Client:_cancel_request(id) - validate({ id = { id, 'n' } }) + validate('id', id, 'number') local request = self.requests[id] if request and request.type == 'pending' then request.type = 'cancel' @@ -852,6 +867,105 @@ function Client:_stop(force) end) end +--- Get options for a method that is registered dynamically. +--- @param method string +function Client:_supports_registration(method) + local capability = vim.tbl_get(self.capabilities, unpack(vim.split(method, '/'))) + return type(capability) == 'table' and capability.dynamicRegistration +end + +--- @private +--- @param registrations lsp.Registration[] +function Client:_register_dynamic(registrations) + -- remove duplicates + self:_unregister_dynamic(registrations) + for _, reg in ipairs(registrations) do + local method = reg.method + if not self.registrations[method] then + self.registrations[method] = {} + end + table.insert(self.registrations[method], reg) + end +end + +--- @param registrations lsp.Registration[] +function Client:_register(registrations) + self:_register_dynamic(registrations) + + local unsupported = {} --- @type string[] + + for _, reg in ipairs(registrations) do + local method = reg.method + if method == ms.workspace_didChangeWatchedFiles then + vim.lsp._watchfiles.register(reg, self.id) + elseif not self:_supports_registration(method) then + unsupported[#unsupported + 1] = method + end + end + + if #unsupported > 0 then + local warning_tpl = 'The language server %s triggers a registerCapability ' + .. 'handler for %s despite dynamicRegistration set to false. ' + .. 'Report upstream, this warning is harmless' + log.warn(string.format(warning_tpl, self.name, table.concat(unsupported, ', '))) + end +end + +--- @private +--- @param unregistrations lsp.Unregistration[] +function Client:_unregister_dynamic(unregistrations) + for _, unreg in ipairs(unregistrations) do + local sreg = self.registrations[unreg.method] + -- Unegister dynamic capability + for i, reg in ipairs(sreg or {}) do + if reg.id == unreg.id then + table.remove(sreg, i) + break + end + end + end +end + +--- @param unregistrations lsp.Unregistration[] +function Client:_unregister(unregistrations) + self:_unregister_dynamic(unregistrations) + for _, unreg in ipairs(unregistrations) do + if unreg.method == ms.workspace_didChangeWatchedFiles then + vim.lsp._watchfiles.unregister(unreg, self.id) + end + end +end + +--- @private +function Client:_get_language_id(bufnr) + return self.get_language_id(bufnr, vim.bo[bufnr].filetype) +end + +--- @param method string +--- @param bufnr? integer +--- @return lsp.Registration? +function Client:_get_registration(method, bufnr) + bufnr = bufnr or vim.api.nvim_get_current_buf() + for _, reg in ipairs(self.registrations[method] or {}) do + if not reg.registerOptions or not reg.registerOptions.documentSelector then + return reg + end + local documentSelector = reg.registerOptions.documentSelector + local language = self:_get_language_id(bufnr) + local uri = vim.uri_from_bufnr(bufnr) + local fname = vim.uri_to_fname(uri) + for _, filter in ipairs(documentSelector) do + if + not (filter.language and language ~= filter.language) + and not (filter.scheme and not vim.startswith(uri, filter.scheme .. ':')) + and not (filter.pattern and not vim.glob.to_lpeg(filter.pattern):match(fname)) + then + return reg + end + end + end +end + --- @private --- Checks whether a client is stopped. --- @@ -865,10 +979,9 @@ end --- or via workspace/executeCommand (if supported by the server) --- --- @param command lsp.Command ---- @param context? {bufnr: integer} +--- @param context? {bufnr?: integer} --- @param handler? lsp.Handler only called if a server command ---- @param on_unsupported? function handler invoked when the command is not supported by the client. -function Client:_exec_cmd(command, context, handler, on_unsupported) +function Client:exec_cmd(command, context, handler) context = vim.deepcopy(context or {}, true) --[[@as lsp.HandlerContext]] context.bufnr = context.bufnr or api.nvim_get_current_buf() context.client_id = self.id @@ -881,25 +994,23 @@ function Client:_exec_cmd(command, context, handler, on_unsupported) local command_provider = self.server_capabilities.executeCommandProvider local commands = type(command_provider) == 'table' and command_provider.commands or {} + if not vim.list_contains(commands, cmdname) then - if on_unsupported then - on_unsupported() - else - vim.notify_once( - string.format( - 'Language server `%s` does not support command `%s`. This command may require a client extension.', - self.name, - cmdname - ), - vim.log.levels.WARN - ) - end + vim.notify_once( + string.format( + 'Language server `%s` does not support command `%s`. This command may require a client extension.', + self.name, + cmdname + ), + vim.log.levels.WARN + ) return end -- Not using command directly to exclude extra properties, -- see https://github.com/python-lsp/python-lsp-server/issues/146 + --- @type lsp.ExecuteCommandParams local params = { - command = command.command, + command = cmdname, arguments = command.arguments, } self.request(ms.workspace_executeCommand, params, handler, context.bufnr) @@ -917,12 +1028,11 @@ function Client:_text_document_did_open_handler(bufnr) return end - local filetype = vim.bo[bufnr].filetype self.notify(ms.textDocument_didOpen, { textDocument = { version = lsp.util.buf_versions[bufnr], uri = vim.uri_from_bufnr(bufnr), - languageId = self.get_language_id(bufnr, filetype), + languageId = self:_get_language_id(bufnr), text = lsp._buf_get_full_text(bufnr), }, }) @@ -987,12 +1097,37 @@ function Client:_supports_method(method, opts) if vim.tbl_get(self.server_capabilities, unpack(required_capability)) then return true end - if self.dynamic_capabilities:supports_registration(method) then - return self.dynamic_capabilities:supports(method, opts) + + local rmethod = lsp._resolve_to_request[method] + if rmethod then + if self:_supports_registration(rmethod) then + local reg = self:_get_registration(rmethod, opts and opts.bufnr) + return vim.tbl_get(reg or {}, 'registerOptions', 'resolveProvider') or false + end + else + if self:_supports_registration(method) then + return self:_get_registration(method, opts and opts.bufnr) ~= nil + end end return false end +--- Get options for a method that is registered dynamically. +--- @param method string +--- @param bufnr? integer +--- @return lsp.LSPAny? +function Client:_get_registration_options(method, bufnr) + if not self:_supports_registration(method) then + return + end + + local reg = self:_get_registration(method, bufnr) + + if reg then + return reg.registerOptions + end +end + --- @private --- Handles a notification sent by an LSP server by invoking the --- corresponding handler. @@ -1070,7 +1205,7 @@ function Client:_add_workspace_folder(dir) end end - local wf = assert(get_workspace_folders(nil, dir)) + local wf = assert(get_workspace_folders(dir)) self:_notify(ms.workspace_didChangeWorkspaceFolders, { event = { added = wf, removed = {} }, @@ -1085,7 +1220,7 @@ end --- Remove a directory to the workspace folders. --- @param dir string? function Client:_remove_workspace_folder(dir) - local wf = assert(get_workspace_folders(nil, dir)) + local wf = assert(get_workspace_folders(dir)) self:_notify(ms.workspace_didChangeWorkspaceFolders, { event = { added = {}, removed = wf }, diff --git a/runtime/lua/vim/lsp/codelens.lua b/runtime/lua/vim/lsp/codelens.lua index c1b6bfb28c..fdbdda695a 100644 --- a/runtime/lua/vim/lsp/codelens.lua +++ b/runtime/lua/vim/lsp/codelens.lua @@ -48,7 +48,7 @@ local function execute_lens(lens, bufnr, client_id) local client = vim.lsp.get_client_by_id(client_id) assert(client, 'Client is required to execute lens, client_id=' .. client_id) - client:_exec_cmd(lens.command, { bufnr = bufnr }, function(...) + client:exec_cmd(lens.command, { bufnr = bufnr }, function(...) vim.lsp.handlers[ms.workspace_executeCommand](...) M.refresh() end) @@ -261,7 +261,7 @@ end ---@param err lsp.ResponseError? ---@param result lsp.CodeLens[] ---@param ctx lsp.HandlerContext -function M.on_codelens(err, result, ctx, _) +function M.on_codelens(err, result, ctx) if err then active_refreshes[assert(ctx.bufnr)] = nil log.error('codelens', err) diff --git a/runtime/lua/vim/lsp/completion.lua b/runtime/lua/vim/lsp/completion.lua index 71ea2df100..92bc110a97 100644 --- a/runtime/lua/vim/lsp/completion.lua +++ b/runtime/lua/vim/lsp/completion.lua @@ -113,12 +113,11 @@ local function parse_snippet(input) end --- @param item lsp.CompletionItem ---- @param suffix? string -local function apply_snippet(item, suffix) +local function apply_snippet(item) if item.textEdit then - vim.snippet.expand(item.textEdit.newText .. suffix) + vim.snippet.expand(item.textEdit.newText) elseif item.insertText then - vim.snippet.expand(item.insertText .. suffix) + vim.snippet.expand(item.insertText) end end @@ -221,6 +220,20 @@ local function get_doc(item) return '' end +---@param value string +---@param prefix string +---@return boolean +local function match_item_by_value(value, prefix) + if vim.o.completeopt:find('fuzzy') ~= nil then + return next(vim.fn.matchfuzzy({ value }, prefix)) ~= nil + end + + if vim.o.ignorecase and (not vim.o.smartcase or not prefix:find('%u')) then + return vim.startswith(value:lower(), prefix:lower()) + end + return vim.startswith(value, prefix) +end + --- Turns the result of a `textDocument/completion` request into vim-compatible --- |complete-items|. --- @@ -245,8 +258,16 @@ function M._lsp_to_complete_items(result, prefix, client_id) else ---@param item lsp.CompletionItem matches = function(item) - local text = item.filterText or item.label - return next(vim.fn.matchfuzzy({ text }, prefix)) ~= nil + if item.filterText then + return match_item_by_value(item.filterText, prefix) + end + + if item.textEdit then + -- server took care of filtering + return true + end + + return match_item_by_value(item.label, prefix) end end @@ -272,7 +293,7 @@ function M._lsp_to_complete_items(result, prefix, client_id) icase = 1, dup = 1, empty = 1, - hl_group = hl_group, + abbr_hlgroup = hl_group, user_data = { nvim = { lsp = { @@ -316,7 +337,7 @@ local function adjust_start_col(lnum, line, items, encoding) end end if min_start_char then - return lsp.util._str_byteindex_enc(line, min_start_char, encoding) + return vim.str_byteindex(line, encoding, min_start_char, false) else return nil end @@ -539,35 +560,24 @@ local function on_complete_done() -- Remove the already inserted word. local start_char = cursor_col - #completed_item.word - local line = api.nvim_buf_get_lines(bufnr, cursor_row, cursor_row + 1, true)[1] - api.nvim_buf_set_text(bufnr, cursor_row, start_char, cursor_row, #line, { '' }) - return line:sub(cursor_col + 1) + api.nvim_buf_set_text(bufnr, cursor_row, start_char, cursor_row, cursor_col, { '' }) end - --- @param suffix? string - local function apply_snippet_and_command(suffix) + local function apply_snippet_and_command() if expand_snippet then - apply_snippet(completion_item, suffix) + apply_snippet(completion_item) end local command = completion_item.command if command then - client:_exec_cmd(command, { bufnr = bufnr }, nil, function() - vim.lsp.log.warn( - string.format( - 'Language server `%s` does not support command `%s`. This command may require a client extension.', - client.name, - command.command - ) - ) - end) + client:exec_cmd(command, { bufnr = bufnr }) end end if completion_item.additionalTextEdits and next(completion_item.additionalTextEdits) then - local suffix = clear_word() + clear_word() lsp.util.apply_text_edits(completion_item.additionalTextEdits, bufnr, offset_encoding) - apply_snippet_and_command(suffix) + apply_snippet_and_command() elseif resolve_provider and type(completion_item) == 'table' then local changedtick = vim.b[bufnr].changedtick @@ -577,7 +587,7 @@ local function on_complete_done() return end - local suffix = clear_word() + clear_word() if err then vim.notify_once(err.message, vim.log.levels.WARN) elseif result and result.additionalTextEdits then @@ -587,16 +597,16 @@ local function on_complete_done() end end - apply_snippet_and_command(suffix) + apply_snippet_and_command() end, bufnr) else - local suffix = clear_word() - apply_snippet_and_command(suffix) + clear_word() + apply_snippet_and_command() end end --- @class vim.lsp.completion.BufferOpts ---- @field autotrigger? boolean Whether to trigger completion automatically. Default: false +--- @field autotrigger? boolean Default: false When true, completion triggers automatically based on the server's `triggerCharacters`. --- @field convert? fun(item: lsp.CompletionItem): table Transforms an LSP CompletionItem to |complete-items|. ---@param client_id integer diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua index c10312484b..8fd30c7668 100644 --- a/runtime/lua/vim/lsp/diagnostic.lua +++ b/runtime/lua/vim/lsp/diagnostic.lua @@ -9,14 +9,6 @@ local augroup = api.nvim_create_augroup('vim_lsp_diagnostic', {}) local DEFAULT_CLIENT_ID = -1 -local function get_client_id(client_id) - if client_id == nil then - client_id = DEFAULT_CLIENT_ID - end - - return client_id -end - ---@param severity lsp.DiagnosticSeverity local function severity_lsp_to_vim(severity) if type(severity) == 'string' then @@ -33,25 +25,6 @@ local function severity_vim_to_lsp(severity) return severity end ----@param lines string[]? ----@param lnum integer ----@param col integer ----@param offset_encoding string ----@return integer -local function line_byte_from_position(lines, lnum, col, offset_encoding) - if not lines or offset_encoding == 'utf-8' then - return col - end - - local line = lines[lnum + 1] - local ok, result = pcall(vim.str_byteindex, line, col, offset_encoding == 'utf-16') - if ok then - return result --- @type integer - end - - return col -end - ---@param bufnr integer ---@return string[]? local function get_buf_lines(bufnr) @@ -118,12 +91,13 @@ local function diagnostic_lsp_to_vim(diagnostics, bufnr, client_id) ) message = diagnostic.message.value end + local line = buf_lines and buf_lines[start.line + 1] or '' --- @type vim.Diagnostic return { lnum = start.line, - col = line_byte_from_position(buf_lines, start.line, start.character, offset_encoding), + col = vim.str_byteindex(line, offset_encoding, start.character, false), end_lnum = _end.line, - end_col = line_byte_from_position(buf_lines, _end.line, _end.character, offset_encoding), + end_col = vim.str_byteindex(line, offset_encoding, _end.character, false), severity = severity_lsp_to_vim(diagnostic.severity), message = message, source = diagnostic.source, @@ -195,7 +169,7 @@ local _client_pull_namespaces = {} ---@param client_id integer The id of the LSP client ---@param is_pull boolean? Whether the namespace is for a pull or push client. Defaults to push function M.get_namespace(client_id, is_pull) - vim.validate({ client_id = { client_id, 'n' } }) + vim.validate('client_id', client_id, 'number') local client = vim.lsp.get_client_by_id(client_id) if is_pull then @@ -236,8 +210,7 @@ end --- @param client_id? integer --- @param diagnostics vim.Diagnostic[] --- @param is_pull boolean ---- @param config? vim.diagnostic.Opts -local function handle_diagnostics(uri, client_id, diagnostics, is_pull, config) +local function handle_diagnostics(uri, client_id, diagnostics, is_pull) local fname = vim.uri_to_fname(uri) if #diagnostics == 0 and vim.fn.bufexists(fname) == 0 then @@ -249,91 +222,39 @@ local function handle_diagnostics(uri, client_id, diagnostics, is_pull, config) return end - client_id = get_client_id(client_id) - local namespace = M.get_namespace(client_id, is_pull) - - if config then - --- @cast config table<string, table> - for _, opt in pairs(config) do - convert_severity(opt) - end - -- Persist configuration to ensure buffer reloads use the same - -- configuration. To make lsp.with configuration work (See :help - -- lsp-handler-configuration) - vim.diagnostic.config(config, namespace) + if client_id == nil then + client_id = DEFAULT_CLIENT_ID end + local namespace = M.get_namespace(client_id, is_pull) + vim.diagnostic.set(namespace, bufnr, diagnostic_lsp_to_vim(diagnostics, bufnr, client_id)) end --- |lsp-handler| for the method "textDocument/publishDiagnostics" --- ---- See |vim.diagnostic.config()| for configuration options. Handler-specific ---- configuration can be set using |vim.lsp.with()|: ---- ---- ```lua ---- vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with( ---- vim.lsp.diagnostic.on_publish_diagnostics, { ---- -- Enable underline, use default values ---- underline = true, ---- -- Enable virtual text, override spacing to 4 ---- virtual_text = { ---- spacing = 4, ---- }, ---- -- Use a function to dynamically turn signs off ---- -- and on, using buffer local variables ---- signs = function(namespace, bufnr) ---- return vim.b[bufnr].show_signs == true ---- end, ---- -- Disable a feature ---- update_in_insert = false, ---- } ---- ) ---- ``` +--- See |vim.diagnostic.config()| for configuration options. --- ---@param _ lsp.ResponseError? ---@param result lsp.PublishDiagnosticsParams ---@param ctx lsp.HandlerContext ----@param config? vim.diagnostic.Opts Configuration table (see |vim.diagnostic.config()|). -function M.on_publish_diagnostics(_, result, ctx, config) - handle_diagnostics(result.uri, ctx.client_id, result.diagnostics, false, config) +function M.on_publish_diagnostics(_, result, ctx) + handle_diagnostics(result.uri, ctx.client_id, result.diagnostics, false) end --- |lsp-handler| for the method "textDocument/diagnostic" --- ---- See |vim.diagnostic.config()| for configuration options. Handler-specific ---- configuration can be set using |vim.lsp.with()|: ---- ---- ```lua ---- vim.lsp.handlers["textDocument/diagnostic"] = vim.lsp.with( ---- vim.lsp.diagnostic.on_diagnostic, { ---- -- Enable underline, use default values ---- underline = true, ---- -- Enable virtual text, override spacing to 4 ---- virtual_text = { ---- spacing = 4, ---- }, ---- -- Use a function to dynamically turn signs off ---- -- and on, using buffer local variables ---- signs = function(namespace, bufnr) ---- return vim.b[bufnr].show_signs == true ---- end, ---- -- Disable a feature ---- update_in_insert = false, ---- } ---- ) ---- ``` +--- See |vim.diagnostic.config()| for configuration options. --- ---@param _ lsp.ResponseError? ---@param result lsp.DocumentDiagnosticReport ---@param ctx lsp.HandlerContext ----@param config vim.diagnostic.Opts Configuration table (see |vim.diagnostic.config()|). -function M.on_diagnostic(_, result, ctx, config) +function M.on_diagnostic(_, result, ctx) if result == nil or result.kind == 'unchanged' then return end - handle_diagnostics(ctx.params.textDocument.uri, ctx.client_id, result.items, true, config) + handle_diagnostics(ctx.params.textDocument.uri, ctx.client_id, result.items, true) end --- Clear push diagnostics and diagnostic cache. diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index 44548fec92..5c28d88b38 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -5,10 +5,21 @@ local util = require('vim.lsp.util') local api = vim.api local completion = require('vim.lsp.completion') ---- @type table<string,lsp.Handler> +--- @type table<string, lsp.Handler> local M = {} --- FIXME: DOC: Expose in vimdocs +--- @deprecated +--- Client to server response handlers. +--- @type table<vim.lsp.protocol.Method.ClientToServer, lsp.Handler> +local RCS = {} + +--- Server to client request handlers. +--- @type table<vim.lsp.protocol.Method.ServerToClient, lsp.Handler> +local RSC = {} + +--- Server to client notification handlers. +--- @type table<vim.lsp.protocol.Method.ServerToClient, lsp.Handler> +local NSC = {} --- Writes to error buffer. ---@param ... string Will be concatenated before being written @@ -18,14 +29,15 @@ local function err_message(...) end --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand -M[ms.workspace_executeCommand] = function(_, _, _, _) +RCS[ms.workspace_executeCommand] = function(_, _, _) -- Error handling is done implicitly by wrapping all handlers; see end of this file end --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#progress ---@param params lsp.ProgressParams ---@param ctx lsp.HandlerContext -M[ms.dollar_progress] = function(_, params, ctx) +---@diagnostic disable-next-line:no-unknown +RSC[ms.dollar_progress] = function(_, params, ctx) local client = vim.lsp.get_client_by_id(ctx.client_id) if not client then err_message('LSP[id=', tostring(ctx.client_id), '] client has shut down during progress update') @@ -59,26 +71,26 @@ M[ms.dollar_progress] = function(_, params, ctx) end --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_workDoneProgress_create ----@param result lsp.WorkDoneProgressCreateParams +---@param params lsp.WorkDoneProgressCreateParams ---@param ctx lsp.HandlerContext -M[ms.window_workDoneProgress_create] = function(_, result, ctx) +RSC[ms.window_workDoneProgress_create] = function(_, params, ctx) local client = vim.lsp.get_client_by_id(ctx.client_id) if not client then err_message('LSP[id=', tostring(ctx.client_id), '] client has shut down during progress update') return vim.NIL end - client.progress:push(result) + client.progress:push(params) return vim.NIL end --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_showMessageRequest ----@param result lsp.ShowMessageRequestParams -M[ms.window_showMessageRequest] = function(_, result) - local actions = result.actions or {} +---@param params lsp.ShowMessageRequestParams +RSC[ms.window_showMessageRequest] = function(_, params) + local actions = params.actions or {} local co, is_main = coroutine.running() if co and not is_main then local opts = { - prompt = result.message .. ': ', + prompt = params.message .. ': ', format_item = function(action) return (action.title:gsub('\r\n', '\\r\\n')):gsub('\n', '\\n') end, @@ -92,7 +104,7 @@ M[ms.window_showMessageRequest] = function(_, result) end) return coroutine.yield() else - local option_strings = { result.message, '\nRequest Actions:' } + local option_strings = { params.message, '\nRequest Actions:' } for i, action in ipairs(actions) do local title = action.title:gsub('\r\n', '\\r\\n') title = title:gsub('\n', '\\n') @@ -108,65 +120,37 @@ M[ms.window_showMessageRequest] = function(_, result) end --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#client_registerCapability ---- @param result lsp.RegistrationParams -M[ms.client_registerCapability] = function(_, result, ctx) - local client_id = ctx.client_id - local client = assert(vim.lsp.get_client_by_id(client_id)) - - client.dynamic_capabilities:register(result.registrations) - for bufnr, _ in pairs(client.attached_buffers) do +--- @param params lsp.RegistrationParams +RSC[ms.client_registerCapability] = function(_, params, ctx) + local client = assert(vim.lsp.get_client_by_id(ctx.client_id)) + client:_register(params.registrations) + for bufnr in pairs(client.attached_buffers) do vim.lsp._set_defaults(client, bufnr) end - - ---@type string[] - local unsupported = {} - for _, reg in ipairs(result.registrations) do - if reg.method == ms.workspace_didChangeWatchedFiles then - vim.lsp._watchfiles.register(reg, ctx) - elseif not client.dynamic_capabilities:supports_registration(reg.method) then - unsupported[#unsupported + 1] = reg.method - end - end - if #unsupported > 0 then - local warning_tpl = 'The language server %s triggers a registerCapability ' - .. 'handler for %s despite dynamicRegistration set to false. ' - .. 'Report upstream, this warning is harmless' - local client_name = client and client.name or string.format('id=%d', client_id) - local warning = string.format(warning_tpl, client_name, table.concat(unsupported, ', ')) - log.warn(warning) - end return vim.NIL end --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#client_unregisterCapability ---- @param result lsp.UnregistrationParams -M[ms.client_unregisterCapability] = function(_, result, ctx) - local client_id = ctx.client_id - local client = assert(vim.lsp.get_client_by_id(client_id)) - client.dynamic_capabilities:unregister(result.unregisterations) - - for _, unreg in ipairs(result.unregisterations) do - if unreg.method == ms.workspace_didChangeWatchedFiles then - vim.lsp._watchfiles.unregister(unreg, ctx) - end - end +--- @param params lsp.UnregistrationParams +RSC[ms.client_unregisterCapability] = function(_, params, ctx) + local client = assert(vim.lsp.get_client_by_id(ctx.client_id)) + client:_unregister(params.unregisterations) return vim.NIL end +-- TODO(lewis6991): Do we need to notify other servers? --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit -M[ms.workspace_applyEdit] = function(_, workspace_edit, ctx) +RSC[ms.workspace_applyEdit] = function(_, params, ctx) assert( - workspace_edit, + params, 'workspace/applyEdit must be called with `ApplyWorkspaceEditParams`. Server is violating the specification' ) -- TODO(ashkan) Do something more with label? - local client_id = ctx.client_id - local client = assert(vim.lsp.get_client_by_id(client_id)) - if workspace_edit.label then - print('Workspace edit', workspace_edit.label) + local client = assert(vim.lsp.get_client_by_id(ctx.client_id)) + if params.label then + print('Workspace edit', params.label) end - local status, result = - pcall(util.apply_workspace_edit, workspace_edit.edit, client.offset_encoding) + local status, result = pcall(util.apply_workspace_edit, params.edit, client.offset_encoding) return { applied = status, failureReason = result, @@ -182,24 +166,23 @@ local function lookup_section(table, section) end --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_configuration ---- @param result lsp.ConfigurationParams -M[ms.workspace_configuration] = function(_, result, ctx) - local client_id = ctx.client_id - local client = vim.lsp.get_client_by_id(client_id) +--- @param params lsp.ConfigurationParams +RSC[ms.workspace_configuration] = function(_, params, ctx) + local client = vim.lsp.get_client_by_id(ctx.client_id) if not client then err_message( 'LSP[', - client_id, + ctx.client_id, '] client has shut down after sending a workspace/configuration request' ) return end - if not result.items then + if not params.items then return {} end local response = {} - for _, item in ipairs(result.items) do + for _, item in ipairs(params.items) do if item.section then local value = lookup_section(client.settings, item.section) -- For empty sections with no explicit '' key, return settings as is @@ -216,57 +199,34 @@ M[ms.workspace_configuration] = function(_, result, ctx) end --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_workspaceFolders -M[ms.workspace_workspaceFolders] = function(_, _, ctx) - local client_id = ctx.client_id - local client = vim.lsp.get_client_by_id(client_id) +RSC[ms.workspace_workspaceFolders] = function(_, _, ctx) + local client = vim.lsp.get_client_by_id(ctx.client_id) if not client then - err_message('LSP[id=', client_id, '] client has shut down after sending the message') + err_message('LSP[id=', ctx.client_id, '] client has shut down after sending the message') return end return client.workspace_folders or vim.NIL end -M[ms.textDocument_publishDiagnostics] = function(...) +NSC[ms.textDocument_publishDiagnostics] = function(...) return vim.lsp.diagnostic.on_publish_diagnostics(...) end -M[ms.textDocument_diagnostic] = function(...) +--- @private +RCS[ms.textDocument_diagnostic] = function(...) return vim.lsp.diagnostic.on_diagnostic(...) end -M[ms.textDocument_codeLens] = function(...) +--- @private +RCS[ms.textDocument_codeLens] = function(...) return vim.lsp.codelens.on_codelens(...) end -M[ms.textDocument_inlayHint] = function(...) +--- @private +RCS[ms.textDocument_inlayHint] = function(...) return vim.lsp.inlay_hint.on_inlayhint(...) end ---- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references -M[ms.textDocument_references] = function(_, result, ctx, config) - if not result or vim.tbl_isempty(result) then - vim.notify('No references found') - return - end - - local client = assert(vim.lsp.get_client_by_id(ctx.client_id)) - config = config or {} - local title = 'References' - local items = util.locations_to_items(result, client.offset_encoding) - - local list = { title = title, items = items, context = ctx } - if config.loclist then - vim.fn.setloclist(0, {}, ' ', list) - vim.cmd.lopen() - elseif config.on_list then - assert(vim.is_callable(config.on_list), 'on_list is not a function') - config.on_list(list) - else - vim.fn.setqflist({}, ' ', list) - vim.cmd('botright copen') - end -end - --- Return a function that converts LSP responses to list items and opens the list --- --- The returned function has an optional {config} parameter that accepts |vim.lsp.ListOpts| @@ -276,6 +236,7 @@ end ---@param title_fn fun(ctx: lsp.HandlerContext): string Function to call to generate list title ---@return lsp.Handler local function response_to_list(map_result, entity, title_fn) + --- @diagnostic disable-next-line:redundant-parameter return function(_, result, ctx, config) if not result or vim.tbl_isempty(result) then vim.notify('No ' .. entity .. ' found') @@ -299,8 +260,9 @@ local function response_to_list(map_result, entity, title_fn) end end +--- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentSymbol -M[ms.textDocument_documentSymbol] = response_to_list( +RCS[ms.textDocument_documentSymbol] = response_to_list( util.symbols_to_items, 'document symbols', function(ctx) @@ -309,13 +271,15 @@ M[ms.textDocument_documentSymbol] = response_to_list( end ) +--- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_symbol -M[ms.workspace_symbol] = response_to_list(util.symbols_to_items, 'symbols', function(ctx) +RCS[ms.workspace_symbol] = response_to_list(util.symbols_to_items, 'symbols', function(ctx) return string.format("Symbols matching '%s'", ctx.params.query) end) +--- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rename -M[ms.textDocument_rename] = function(_, result, ctx, _) +RCS[ms.textDocument_rename] = function(_, result, ctx) if not result then vim.notify("Language server couldn't provide rename result", vim.log.levels.INFO) return @@ -324,8 +288,9 @@ M[ms.textDocument_rename] = function(_, result, ctx, _) util.apply_workspace_edit(result, client.offset_encoding) end +--- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rangeFormatting -M[ms.textDocument_rangeFormatting] = function(_, result, ctx, _) +RCS[ms.textDocument_rangeFormatting] = function(_, result, ctx) if not result then return end @@ -333,8 +298,9 @@ M[ms.textDocument_rangeFormatting] = function(_, result, ctx, _) util.apply_text_edits(result, ctx.bufnr, client.offset_encoding) end +--- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_formatting -M[ms.textDocument_formatting] = function(_, result, ctx, _) +RCS[ms.textDocument_formatting] = function(_, result, ctx) if not result then return end @@ -342,8 +308,9 @@ M[ms.textDocument_formatting] = function(_, result, ctx, _) util.apply_text_edits(result, ctx.bufnr, client.offset_encoding) end +--- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion -M[ms.textDocument_completion] = function(_, result, _, _) +RCS[ms.textDocument_completion] = function(_, result, _) if vim.tbl_isempty(result or {}) then return end @@ -358,6 +325,7 @@ M[ms.textDocument_completion] = function(_, result, _, _) vim.fn.complete(textMatch + 1, matches) end +--- @deprecated --- |lsp-handler| for the method "textDocument/hover" --- --- ```lua @@ -378,6 +346,7 @@ end --- - border: (default=nil) --- - Add borders to the floating window --- - See |vim.lsp.util.open_floating_preview()| for more options. +--- @diagnostic disable-next-line:redundant-parameter function M.hover(_, result, ctx, config) config = config or {} config.focus_id = ctx.method @@ -408,60 +377,14 @@ function M.hover(_, result, ctx, config) return util.open_floating_preview(contents, format, config) end +--- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_hover -M[ms.textDocument_hover] = M.hover - ---- Jumps to a location. Used as a handler for multiple LSP methods. ----@param _ nil not used ----@param result (table) result of LSP method; a location or a list of locations. ----@param ctx (lsp.HandlerContext) table containing the context of the request, including the method ----@param config? vim.lsp.LocationOpts ----(`textDocument/definition` can return `Location` or `Location[]` -local function location_handler(_, result, ctx, config) - if result == nil or vim.tbl_isempty(result) then - log.info(ctx.method, 'No location found') - return nil - end - local client = assert(vim.lsp.get_client_by_id(ctx.client_id)) - - config = config or {} - - -- textDocument/definition can return Location or Location[] - -- https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_definition - if not vim.islist(result) then - result = { result } - end +--- @diagnostic disable-next-line: deprecated +RCS[ms.textDocument_hover] = M.hover - local title = 'LSP locations' - local items = util.locations_to_items(result, client.offset_encoding) - - if config.on_list then - assert(vim.is_callable(config.on_list), 'on_list is not a function') - config.on_list({ title = title, items = items }) - return - end - if #result == 1 then - util.jump_to_location(result[1], client.offset_encoding, config.reuse_win) - return - end - if config.loclist then - vim.fn.setloclist(0, {}, ' ', { title = title, items = items }) - vim.cmd.lopen() - else - vim.fn.setqflist({}, ' ', { title = title, items = items }) - vim.cmd('botright copen') - end -end - ---- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_declaration -M[ms.textDocument_declaration] = location_handler ---- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_definition -M[ms.textDocument_definition] = location_handler ---- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_typeDefinition -M[ms.textDocument_typeDefinition] = location_handler ---- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_implementation -M[ms.textDocument_implementation] = location_handler +local sig_help_ns = api.nvim_create_namespace('vim_lsp_signature_help') +--- @deprecated remove in 0.13 --- |lsp-handler| for the method "textDocument/signatureHelp". --- --- The active parameter is highlighted with |hl-LspSignatureActiveParameter|. @@ -476,12 +399,13 @@ M[ms.textDocument_implementation] = location_handler --- ``` --- ---@param _ lsp.ResponseError? ----@param result lsp.SignatureHelp Response from the language server +---@param result lsp.SignatureHelp? Response from the language server ---@param ctx lsp.HandlerContext Client context ---@param config table Configuration table. --- - border: (default=nil) --- - Add borders to the floating window --- - See |vim.lsp.util.open_floating_preview()| for more options +--- @diagnostic disable-next-line:redundant-parameter function M.signature_help(_, result, ctx, config) config = config or {} config.focus_id = ctx.method @@ -509,19 +433,27 @@ function M.signature_help(_, result, ctx, config) return end local fbuf, fwin = util.open_floating_preview(lines, 'markdown', config) + -- Highlight the active parameter. if hl then - -- Highlight the second line if the signature is wrapped in a Markdown code block. - local line = vim.startswith(lines[1], '```') and 1 or 0 - api.nvim_buf_add_highlight(fbuf, -1, 'LspSignatureActiveParameter', line, unpack(hl)) + vim.hl.range( + fbuf, + sig_help_ns, + 'LspSignatureActiveParameter', + { hl[1], hl[2] }, + { hl[3], hl[4] } + ) end return fbuf, fwin end +--- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_signatureHelp -M[ms.textDocument_signatureHelp] = M.signature_help +--- @diagnostic disable-next-line:deprecated +RCS[ms.textDocument_signatureHelp] = M.signature_help +--- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentHighlight -M[ms.textDocument_documentHighlight] = function(_, result, ctx, _) +RCS[ms.textDocument_documentHighlight] = function(_, result, ctx) if not result then return end @@ -564,11 +496,13 @@ local function make_call_hierarchy_handler(direction) end end +--- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#callHierarchy_incomingCalls -M[ms.callHierarchy_incomingCalls] = make_call_hierarchy_handler('from') +RCS[ms.callHierarchy_incomingCalls] = make_call_hierarchy_handler('from') +--- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#callHierarchy_outgoingCalls -M[ms.callHierarchy_outgoingCalls] = make_call_hierarchy_handler('to') +RCS[ms.callHierarchy_outgoingCalls] = make_call_hierarchy_handler('to') --- Displays type hierarchy in the quickfix window. local function make_type_hierarchy_handler() @@ -603,17 +537,19 @@ local function make_type_hierarchy_handler() end end +--- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#typeHierarchy_incomingCalls -M[ms.typeHierarchy_subtypes] = make_type_hierarchy_handler() +RCS[ms.typeHierarchy_subtypes] = make_type_hierarchy_handler() +--- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#typeHierarchy_outgoingCalls -M[ms.typeHierarchy_supertypes] = make_type_hierarchy_handler() +RCS[ms.typeHierarchy_supertypes] = make_type_hierarchy_handler() --- @see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_logMessage ---- @param result lsp.LogMessageParams -M[ms.window_logMessage] = function(_, result, ctx, _) - local message_type = result.type - local message = result.message +--- @param params lsp.LogMessageParams +NSC['window/logMessage'] = function(_, params, ctx) + local message_type = params.type + local message = params.message local client_id = ctx.client_id local client = vim.lsp.get_client_by_id(client_id) local client_name = client and client.name or string.format('id=%d', client_id) @@ -629,14 +565,14 @@ M[ms.window_logMessage] = function(_, result, ctx, _) else log.debug(message) end - return result + return params end --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_showMessage ---- @param result lsp.ShowMessageParams -M[ms.window_showMessage] = function(_, result, ctx, _) - local message_type = result.type - local message = result.message +--- @param params lsp.ShowMessageParams +NSC['window/showMessage'] = function(_, params, ctx) + local message_type = params.type + local message = params.message local client_id = ctx.client_id local client = vim.lsp.get_client_by_id(client_id) local client_name = client and client.name or string.format('id=%d', client_id) @@ -650,15 +586,16 @@ M[ms.window_showMessage] = function(_, result, ctx, _) local message_type_name = protocol.MessageType[message_type] api.nvim_out_write(string.format('LSP[%s][%s] %s\n', client_name, message_type_name, message)) end - return result + return params end +--- @private --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_showDocument ---- @param result lsp.ShowDocumentParams -M[ms.window_showDocument] = function(_, result, ctx, _) - local uri = result.uri +--- @param params lsp.ShowDocumentParams +RSC[ms.window_showDocument] = function(_, params, ctx) + local uri = params.uri - if result.external then + if params.external then -- TODO(lvimuser): ask the user for confirmation local cmd, err = vim.ui.open(uri) local ret = cmd and cmd:wait(2000) or nil @@ -686,35 +623,39 @@ M[ms.window_showDocument] = function(_, result, ctx, _) local location = { uri = uri, - range = result.selection, + range = params.selection, } local success = util.show_document(location, client.offset_encoding, { reuse_win = true, - focus = result.takeFocus, + focus = params.takeFocus, }) return { success = success or false } end ---@see https://microsoft.github.io/language-server-protocol/specification/#workspace_inlayHint_refresh -M[ms.workspace_inlayHint_refresh] = function(err, result, ctx, config) - return vim.lsp.inlay_hint.on_refresh(err, result, ctx, config) +RSC[ms.workspace_inlayHint_refresh] = function(err, result, ctx) + return vim.lsp.inlay_hint.on_refresh(err, result, ctx) end ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#semanticTokens_refreshRequest -M[ms.workspace_semanticTokens_refresh] = function(err, result, ctx, _config) +RSC[ms.workspace_semanticTokens_refresh] = function(err, result, ctx) return vim.lsp.semantic_tokens._refresh(err, result, ctx) end +--- @nodoc +--- @type table<string, lsp.Handler> +M = vim.tbl_extend('force', M, RSC, NSC, RCS) + -- Add boilerplate error validation and logging for all of these. for k, fn in pairs(M) do + --- @diagnostic disable-next-line:redundant-parameter M[k] = function(err, result, ctx, config) if log.trace() then log.trace('default_handler', ctx.method, { err = err, result = result, ctx = vim.inspect(ctx), - config = config, }) end @@ -735,6 +676,7 @@ for k, fn in pairs(M) do return end + --- @diagnostic disable-next-line:redundant-parameter return fn(err, result, ctx, config) end end diff --git a/runtime/lua/vim/lsp/health.lua b/runtime/lua/vim/lsp/health.lua index 18066a84db..0d314108fe 100644 --- a/runtime/lua/vim/lsp/health.lua +++ b/runtime/lua/vim/lsp/health.lua @@ -39,12 +39,27 @@ local function check_active_clients() elseif type(client.config.cmd) == 'function' then cmd = tostring(client.config.cmd) end + local dirs_info ---@type string + if client.workspace_folders and #client.workspace_folders > 1 then + dirs_info = string.format( + ' Workspace folders:\n %s', + vim + .iter(client.workspace_folders) + ---@param folder lsp.WorkspaceFolder + :map(function(folder) + return folder.name + end) + :join('\n ') + ) + else + dirs_info = string.format( + ' Root directory: %s', + client.root_dir and vim.fn.fnamemodify(client.root_dir, ':~') + ) or nil + end report_info(table.concat({ string.format('%s (id: %d)', client.name, client.id), - string.format( - ' Root directory: %s', - client.root_dir and vim.fn.fnamemodify(client.root_dir, ':~') or nil - ), + dirs_info, string.format(' Command: %s', cmd), string.format(' Settings: %s', vim.inspect(client.settings, { newline = '\n ' })), string.format( diff --git a/runtime/lua/vim/lsp/inlay_hint.lua b/runtime/lua/vim/lsp/inlay_hint.lua index 61059180fe..f1ae9a8e9e 100644 --- a/runtime/lua/vim/lsp/inlay_hint.lua +++ b/runtime/lua/vim/lsp/inlay_hint.lua @@ -37,7 +37,7 @@ local augroup = api.nvim_create_augroup('vim_lsp_inlayhint', {}) ---@param result lsp.InlayHint[]? ---@param ctx lsp.HandlerContext ---@private -function M.on_inlayhint(err, result, ctx, _) +function M.on_inlayhint(err, result, ctx) if err then log.error('inlayhint', err) return @@ -65,37 +65,29 @@ function M.on_inlayhint(err, result, ctx, _) if num_unprocessed == 0 then client_hints[client_id] = {} bufstate.version = ctx.version - api.nvim__redraw({ buf = bufnr, valid = true }) + api.nvim__redraw({ buf = bufnr, valid = true, flush = false }) return end local lines = api.nvim_buf_get_lines(bufnr, 0, -1, false) - ---@param position lsp.Position - ---@return integer - local function pos_to_byte(position) - local col = position.character - if col > 0 then - local line = lines[position.line + 1] or '' - return util._str_byteindex_enc(line, col, client.offset_encoding) - end - return col - end for _, hint in ipairs(result) do local lnum = hint.position.line - hint.position.character = pos_to_byte(hint.position) + local line = lines and lines[lnum + 1] or '' + hint.position.character = + vim.str_byteindex(line, client.offset_encoding, hint.position.character, false) table.insert(new_lnum_hints[lnum], hint) end client_hints[client_id] = new_lnum_hints bufstate.version = ctx.version - api.nvim__redraw({ buf = bufnr, valid = true }) + api.nvim__redraw({ buf = bufnr, valid = true, flush = false }) end --- |lsp-handler| for the method `workspace/inlayHint/refresh` ---@param ctx lsp.HandlerContext ---@private -function M.on_refresh(err, _, ctx, _) +function M.on_refresh(err, _, ctx) if err then return vim.NIL end @@ -145,7 +137,7 @@ end --- @return vim.lsp.inlay_hint.get.ret[] --- @since 12 function M.get(filter) - vim.validate({ filter = { filter, 'table', true } }) + vim.validate('filter', filter, 'table', true) filter = filter or {} local bufnr = filter.bufnr @@ -223,7 +215,7 @@ local function clear(bufnr) end end api.nvim_buf_clear_namespace(bufnr, namespace, 0, -1) - api.nvim__redraw({ buf = bufnr, valid = true }) + api.nvim__redraw({ buf = bufnr, valid = true, flush = false }) end --- Disable inlay hints for a buffer @@ -375,11 +367,11 @@ api.nvim_set_decoration_provider(namespace, { --- @return boolean --- @since 12 function M.is_enabled(filter) - vim.validate({ filter = { filter, 'table', true } }) + vim.validate('filter', filter, 'table', true) filter = filter or {} local bufnr = filter.bufnr - vim.validate({ bufnr = { bufnr, 'number', true } }) + vim.validate('bufnr', bufnr, 'number', true) if bufnr == nil then return globalstate.enabled elseif bufnr == 0 then @@ -406,7 +398,8 @@ end --- @param filter vim.lsp.inlay_hint.enable.Filter? --- @since 12 function M.enable(enable, filter) - vim.validate({ enable = { enable, 'boolean', true }, filter = { filter, 'table', true } }) + vim.validate('enable', enable, 'boolean', true) + vim.validate('filter', filter, 'table', true) enable = enable == nil or enable filter = filter or {} diff --git a/runtime/lua/vim/lsp/log.lua b/runtime/lua/vim/lsp/log.lua index 4f177b47fd..ec78dd3dc5 100644 --- a/runtime/lua/vim/lsp/log.lua +++ b/runtime/lua/vim/lsp/log.lua @@ -32,12 +32,12 @@ local function notify(msg, level) end end -local logfilename = vim.fs.joinpath(vim.fn.stdpath('log'), 'lsp.log') +local logfilename = vim.fs.joinpath(vim.fn.stdpath('log') --[[@as string]], 'lsp.log') -- TODO: Ideally the directory should be created in open_logfile(), right -- before opening the log file, but open_logfile() can be called from libuv -- callbacks, where using fn.mkdir() is not allowed. -vim.fn.mkdir(vim.fn.stdpath('log'), 'p') +vim.fn.mkdir(vim.fn.stdpath('log') --[[@as string]], 'p') --- Returns the log filename. ---@return string log filename @@ -82,6 +82,7 @@ end for level, levelnr in pairs(log_levels) do -- Also export the log level on the root object. + ---@diagnostic disable-next-line: no-unknown log[level] = levelnr -- Add a reverse lookup. @@ -93,7 +94,7 @@ end --- @return fun(...:any): boolean? local function create_logger(level, levelnr) return function(...) - if levelnr < current_log_level then + if not log.should_log(levelnr) then return false end local argc = select('#', ...) @@ -169,7 +170,7 @@ end --- Checks whether the level is sufficient for logging. ---@param level integer log level ----@return bool : true if would log, false if not +---@return boolean : true if would log, false if not function log.should_log(level) return level >= current_log_level end diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua index 1699fff0c1..7db48b0c06 100644 --- a/runtime/lua/vim/lsp/protocol.lua +++ b/runtime/lua/vim/lsp/protocol.lua @@ -12,6 +12,8 @@ end local sysname = vim.uv.os_uname().sysname +--- @class vim.lsp.protocol.constants +--- @nodoc local constants = { --- @enum lsp.DiagnosticSeverity DiagnosticSeverity = { @@ -314,7 +316,9 @@ local constants = { }, } --- Protocol for the Microsoft Language Server Protocol (mslsp) +--- Protocol for the Microsoft Language Server Protocol (mslsp) +--- @class vim.lsp.protocol : vim.lsp.protocol.constants +--- @nodoc local protocol = {} --- @diagnostic disable:no-unknown @@ -334,7 +338,9 @@ function protocol.make_client_capabilities() return { general = { positionEncodings = { + 'utf-8', 'utf-16', + 'utf-32', }, }, textDocument = { @@ -615,9 +621,109 @@ function protocol.resolve_capabilities(server_capabilities) end -- Generated by gen_lsp.lua, keep at end of file. +--- @alias vim.lsp.protocol.Method.ClientToServer +--- | 'callHierarchy/incomingCalls', +--- | 'callHierarchy/outgoingCalls', +--- | 'codeAction/resolve', +--- | 'codeLens/resolve', +--- | 'completionItem/resolve', +--- | 'documentLink/resolve', +--- | '$/setTrace', +--- | 'exit', +--- | 'initialize', +--- | 'initialized', +--- | 'inlayHint/resolve', +--- | 'notebookDocument/didChange', +--- | 'notebookDocument/didClose', +--- | 'notebookDocument/didOpen', +--- | 'notebookDocument/didSave', +--- | 'shutdown', +--- | 'textDocument/codeAction', +--- | 'textDocument/codeLens', +--- | 'textDocument/colorPresentation', +--- | 'textDocument/completion', +--- | 'textDocument/declaration', +--- | 'textDocument/definition', +--- | 'textDocument/diagnostic', +--- | 'textDocument/didChange', +--- | 'textDocument/didClose', +--- | 'textDocument/didOpen', +--- | 'textDocument/didSave', +--- | 'textDocument/documentColor', +--- | 'textDocument/documentHighlight', +--- | 'textDocument/documentLink', +--- | 'textDocument/documentSymbol', +--- | 'textDocument/foldingRange', +--- | 'textDocument/formatting', +--- | 'textDocument/hover', +--- | 'textDocument/implementation', +--- | 'textDocument/inlayHint', +--- | 'textDocument/inlineCompletion', +--- | 'textDocument/inlineValue', +--- | 'textDocument/linkedEditingRange', +--- | 'textDocument/moniker', +--- | 'textDocument/onTypeFormatting', +--- | 'textDocument/prepareCallHierarchy', +--- | 'textDocument/prepareRename', +--- | 'textDocument/prepareTypeHierarchy', +--- | 'textDocument/rangeFormatting', +--- | 'textDocument/rangesFormatting', +--- | 'textDocument/references', +--- | 'textDocument/rename', +--- | 'textDocument/selectionRange', +--- | 'textDocument/semanticTokens/full', +--- | 'textDocument/semanticTokens/full/delta', +--- | 'textDocument/semanticTokens/range', +--- | 'textDocument/signatureHelp', +--- | 'textDocument/typeDefinition', +--- | 'textDocument/willSave', +--- | 'textDocument/willSaveWaitUntil', +--- | 'typeHierarchy/subtypes', +--- | 'typeHierarchy/supertypes', +--- | 'window/workDoneProgress/cancel', +--- | 'workspaceSymbol/resolve', +--- | 'workspace/diagnostic', +--- | 'workspace/didChangeConfiguration', +--- | 'workspace/didChangeWatchedFiles', +--- | 'workspace/didChangeWorkspaceFolders', +--- | 'workspace/didCreateFiles', +--- | 'workspace/didDeleteFiles', +--- | 'workspace/didRenameFiles', +--- | 'workspace/executeCommand', +--- | 'workspace/symbol', +--- | 'workspace/willCreateFiles', +--- | 'workspace/willDeleteFiles', +--- | 'workspace/willRenameFiles', + +--- @alias vim.lsp.protocol.Method.ServerToClient +--- | 'client/registerCapability', +--- | 'client/unregisterCapability', +--- | '$/logTrace', +--- | 'telemetry/event', +--- | 'textDocument/publishDiagnostics', +--- | 'window/logMessage', +--- | 'window/showDocument', +--- | 'window/showMessage', +--- | 'window/showMessageRequest', +--- | 'window/workDoneProgress/create', +--- | 'workspace/applyEdit', +--- | 'workspace/codeLens/refresh', +--- | 'workspace/configuration', +--- | 'workspace/diagnostic/refresh', +--- | 'workspace/foldingRange/refresh', +--- | 'workspace/inlayHint/refresh', +--- | 'workspace/inlineValue/refresh', +--- | 'workspace/semanticTokens/refresh', +--- | 'workspace/workspaceFolders', + +--- @alias vim.lsp.protocol.Method +--- | vim.lsp.protocol.Method.ClientToServer +--- | vim.lsp.protocol.Method.ServerToClient + +-- Generated by gen_lsp.lua, keep at end of file. --- ----@enum vim.lsp.protocol.Methods ----@see https://microsoft.github.io/language-server-protocol/specification/#metaModel +--- @enum vim.lsp.protocol.Methods +--- @see https://microsoft.github.io/language-server-protocol/specification/#metaModel --- LSP method names. protocol.Methods = { --- A request to resolve the incoming calls for a given `CallHierarchyItem`. diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index e79dbd2db3..6c8564845f 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -1,7 +1,7 @@ local uv = vim.uv local log = require('vim.lsp.log') local protocol = require('vim.lsp.protocol') -local validate, schedule, schedule_wrap = vim.validate, vim.schedule, vim.schedule_wrap +local validate, schedule_wrap = vim.validate, vim.schedule_wrap local is_win = vim.fn.has('win32') == 1 @@ -152,9 +152,7 @@ end ---@param err table The error object ---@return string error_message The formatted error message function M.format_rpc_error(err) - validate({ - err = { err, 't' }, - }) + validate('err', err, 'table') -- There is ErrorCodes in the LSP specification, -- but in ResponseError.code it is not used and the actual type is number. @@ -329,10 +327,8 @@ end ---@return boolean success `true` if request could be sent, `false` if not ---@return integer? message_id if request could be sent, `nil` if not function Client:request(method, params, callback, notify_reply_callback) - validate({ - callback = { callback, 'f' }, - notify_reply_callback = { notify_reply_callback, 'f', true }, - }) + validate('callback', callback, 'function') + validate('notify_reply_callback', notify_reply_callback, 'function', true) self.message_index = self.message_index + 1 local message_id = self.message_index local result = self:encode_and_send({ @@ -413,49 +409,44 @@ function Client:handle_body(body) local err --- @type lsp.ResponseError|nil -- Schedule here so that the users functions don't trigger an error and -- we can still use the result. - schedule(function() - coroutine.wrap(function() - local status, result - status, result, err = self:try_call( - M.client_errors.SERVER_REQUEST_HANDLER_ERROR, - self.dispatchers.server_request, - decoded.method, - decoded.params - ) - log.debug( - 'server_request: callback result', - { status = status, result = result, err = err } - ) - if status then - if result == nil and err == nil then - error( - string.format( - 'method %q: either a result or an error must be sent to the server in response', - decoded.method - ) - ) - end - if err then - ---@cast err lsp.ResponseError - assert( - type(err) == 'table', - 'err must be a table. Use rpc_response_error to help format errors.' - ) - ---@type string - local code_name = assert( - protocol.ErrorCodes[err.code], - 'Errors must use protocol.ErrorCodes. Use rpc_response_error to help format errors.' + vim.schedule(coroutine.wrap(function() + local status, result + status, result, err = self:try_call( + M.client_errors.SERVER_REQUEST_HANDLER_ERROR, + self.dispatchers.server_request, + decoded.method, + decoded.params + ) + log.debug('server_request: callback result', { status = status, result = result, err = err }) + if status then + if result == nil and err == nil then + error( + string.format( + 'method %q: either a result or an error must be sent to the server in response', + decoded.method ) - err.message = err.message or code_name - end - else - -- On an exception, result will contain the error message. - err = M.rpc_response_error(protocol.ErrorCodes.InternalError, result) - result = nil + ) + end + if err then + ---@cast err lsp.ResponseError + assert( + type(err) == 'table', + 'err must be a table. Use rpc_response_error to help format errors.' + ) + ---@type string + local code_name = assert( + protocol.ErrorCodes[err.code], + 'Errors must use protocol.ErrorCodes. Use rpc_response_error to help format errors.' + ) + err.message = err.message or code_name end - self:send_response(decoded.id, err, result) - end)() - end) + else + -- On an exception, result will contain the error message. + err = M.rpc_response_error(protocol.ErrorCodes.InternalError, result) + result = nil + end + self:send_response(decoded.id, err, result) + end)) -- This works because we are expecting vim.NIL here elseif decoded.id and (decoded.result ~= vim.NIL or decoded.error ~= vim.NIL) then -- We sent a number, so we expect a number. @@ -465,9 +456,7 @@ function Client:handle_body(body) local notify_reply_callbacks = self.notify_reply_callbacks local notify_reply_callback = notify_reply_callbacks and notify_reply_callbacks[result_id] if notify_reply_callback then - validate({ - notify_reply_callback = { notify_reply_callback, 'f' }, - }) + validate('notify_reply_callback', notify_reply_callback, 'function') notify_reply_callback(result_id) notify_reply_callbacks[result_id] = nil end @@ -498,9 +487,7 @@ function Client:handle_body(body) local callback = message_callbacks and message_callbacks[result_id] if callback then message_callbacks[result_id] = nil - validate({ - callback = { callback, 'f' }, - }) + validate('callback', callback, 'function') if decoded.error then decoded.error = setmetatable(decoded.error, { __tostring = M.format_rpc_error, @@ -734,10 +721,8 @@ end function M.start(cmd, dispatchers, extra_spawn_params) log.info('Starting RPC client', { cmd = cmd, extra = extra_spawn_params }) - validate({ - cmd = { cmd, 't' }, - dispatchers = { dispatchers, 't', true }, - }) + validate('cmd', cmd, 'table') + validate('dispatchers', dispatchers, 'table', true) extra_spawn_params = extra_spawn_params or {} diff --git a/runtime/lua/vim/lsp/semantic_tokens.lua b/runtime/lua/vim/lsp/semantic_tokens.lua index 8182457dd0..215e5f41aa 100644 --- a/runtime/lua/vim/lsp/semantic_tokens.lua +++ b/runtime/lua/vim/lsp/semantic_tokens.lua @@ -99,11 +99,12 @@ local function tokens_to_ranges(data, bufnr, client, request) local legend = client.server_capabilities.semanticTokensProvider.legend local token_types = legend.tokenTypes local token_modifiers = legend.tokenModifiers + local encoding = client.offset_encoding local lines = api.nvim_buf_get_lines(bufnr, 0, -1, false) local ranges = {} ---@type STTokenRange[] local start = uv.hrtime() - local ms_to_ns = 1000 * 1000 + local ms_to_ns = 1e6 local yield_interval_ns = 5 * ms_to_ns local co, is_main = coroutine.running() @@ -135,20 +136,13 @@ local function tokens_to_ranges(data, bufnr, client, request) -- data[i+3] +1 because Lua tables are 1-indexed local token_type = token_types[data[i + 3] + 1] - local modifiers = modifiers_from_number(data[i + 4], token_modifiers) - - local function _get_byte_pos(col) - if col > 0 then - local buf_line = lines[line + 1] or '' - return util._str_byteindex_enc(buf_line, col, client.offset_encoding) - end - return col - end - - local start_col = _get_byte_pos(start_char) - local end_col = _get_byte_pos(start_char + data[i + 2]) if token_type then + local modifiers = modifiers_from_number(data[i + 4], token_modifiers) + local end_char = start_char + data[i + 2] + local buf_line = lines and lines[line + 1] or '' + local start_col = vim.str_byteindex(buf_line, encoding, start_char, false) + local end_col = vim.str_byteindex(buf_line, encoding, end_char, false) ranges[#ranges + 1] = { line = line, start_col = start_col, @@ -386,6 +380,37 @@ function STHighlighter:process_response(response, client, version) api.nvim__redraw({ buf = self.bufnr, valid = true }) end +--- @param bufnr integer +--- @param ns integer +--- @param token STTokenRange +--- @param hl_group string +--- @param priority integer +local function set_mark(bufnr, ns, token, hl_group, priority) + vim.api.nvim_buf_set_extmark(bufnr, ns, token.line, token.start_col, { + hl_group = hl_group, + end_col = token.end_col, + priority = priority, + strict = false, + }) +end + +--- @param lnum integer +--- @param foldend integer? +--- @return boolean, integer? +local function check_fold(lnum, foldend) + if foldend and lnum <= foldend then + return true, foldend + end + + local folded = vim.fn.foldclosed(lnum) + + if folded == -1 then + return false, nil + end + + return folded ~= lnum, vim.fn.foldclosedend(lnum) +end + --- on_win handler for the decoration provider (see |nvim_set_decoration_provider|) --- --- If there is a current result for the buffer and the version matches the @@ -439,13 +464,14 @@ function STHighlighter:on_win(topline, botline) -- finishes, clangd sends a refresh request which lets the client -- re-synchronize the tokens. - local set_mark = function(token, hl_group, delta) - vim.api.nvim_buf_set_extmark(self.bufnr, state.namespace, token.line, token.start_col, { - hl_group = hl_group, - end_col = token.end_col, - priority = vim.highlight.priorities.semantic_tokens + delta, - strict = false, - }) + local function set_mark0(token, hl_group, delta) + set_mark( + self.bufnr, + state.namespace, + token, + hl_group, + vim.hl.priorities.semantic_tokens + delta + ) end local ft = vim.bo[self.bufnr].filetype @@ -453,13 +479,19 @@ function STHighlighter:on_win(topline, botline) local first = lower_bound(highlights, topline, 1, #highlights + 1) local last = upper_bound(highlights, botline, first, #highlights + 1) - 1 + --- @type boolean?, integer? + local is_folded, foldend + for i = first, last do local token = highlights[i] - if not token.marked then - set_mark(token, string.format('@lsp.type.%s.%s', token.type, ft), 0) - for modifier, _ in pairs(token.modifiers) do - set_mark(token, string.format('@lsp.mod.%s.%s', modifier, ft), 1) - set_mark(token, string.format('@lsp.typemod.%s.%s.%s', token.type, modifier, ft), 2) + + is_folded, foldend = check_fold(token.line + 1, foldend) + + if not is_folded and not token.marked then + set_mark0(token, string.format('@lsp.type.%s.%s', token.type, ft), 0) + for modifier in pairs(token.modifiers) do + set_mark0(token, string.format('@lsp.mod.%s.%s', modifier, ft), 1) + set_mark0(token, string.format('@lsp.typemod.%s.%s.%s', token.type, modifier, ft), 2) end token.marked = true @@ -565,10 +597,8 @@ local M = {} --- - debounce (integer, default: 200): Debounce token requests --- to the server by the given number in milliseconds function M.start(bufnr, client_id, opts) - vim.validate({ - bufnr = { bufnr, 'n', false }, - client_id = { client_id, 'n', false }, - }) + vim.validate('bufnr', bufnr, 'number') + vim.validate('client_id', client_id, 'number') if bufnr == 0 then bufnr = api.nvim_get_current_buf() @@ -622,10 +652,8 @@ end ---@param bufnr (integer) Buffer number, or `0` for current buffer ---@param client_id (integer) The ID of the |vim.lsp.Client| function M.stop(bufnr, client_id) - vim.validate({ - bufnr = { bufnr, 'n', false }, - client_id = { client_id, 'n', false }, - }) + vim.validate('bufnr', bufnr, 'number') + vim.validate('client_id', client_id, 'number') if bufnr == 0 then bufnr = api.nvim_get_current_buf() @@ -708,9 +736,7 @@ end ---@param bufnr (integer|nil) filter by buffer. All buffers if nil, current --- buffer if 0 function M.force_refresh(bufnr) - vim.validate({ - bufnr = { bufnr, 'n', true }, - }) + vim.validate('bufnr', bufnr, 'number', true) local buffers = bufnr == nil and vim.tbl_keys(STHighlighter.active) or bufnr == 0 and { api.nvim_get_current_buf() } @@ -729,7 +755,7 @@ end --- @inlinedoc --- --- Priority for the applied extmark. ---- (Default: `vim.highlight.priorities.semantic_tokens + 3`) +--- (Default: `vim.hl.priorities.semantic_tokens + 3`) --- @field priority? integer --- Highlight a semantic token. @@ -757,15 +783,9 @@ function M.highlight_token(token, bufnr, client_id, hl_group, opts) return end - opts = opts or {} - local priority = opts.priority or vim.highlight.priorities.semantic_tokens + 3 + local priority = opts and opts.priority or vim.hl.priorities.semantic_tokens + 3 - vim.api.nvim_buf_set_extmark(bufnr, state.namespace, token.line, token.start_col, { - hl_group = hl_group, - end_col = token.end_col, - priority = priority, - strict = false, - }) + set_mark(bufnr, state.namespace, token, hl_group, priority) end --- |lsp-handler| for the method `workspace/semanticTokens/refresh` diff --git a/runtime/lua/vim/lsp/sync.lua b/runtime/lua/vim/lsp/sync.lua index bdfe8d51b8..3df45ebff0 100644 --- a/runtime/lua/vim/lsp/sync.lua +++ b/runtime/lua/vim/lsp/sync.lua @@ -48,45 +48,6 @@ local str_utfindex = vim.str_utfindex local str_utf_start = vim.str_utf_start local str_utf_end = vim.str_utf_end --- Given a line, byte idx, and offset_encoding convert to the --- utf-8, utf-16, or utf-32 index. ----@param line string the line to index into ----@param byte integer the byte idx ----@param offset_encoding string utf-8|utf-16|utf-32|nil (default: utf-8) ----@return integer utf_idx for the given encoding -local function byte_to_utf(line, byte, offset_encoding) - -- convert to 0 based indexing for str_utfindex - byte = byte - 1 - - local utf_idx, _ --- @type integer, integer - -- Convert the byte range to utf-{8,16,32} and convert 1-based (lua) indexing to 0-based - if offset_encoding == 'utf-16' then - _, utf_idx = str_utfindex(line, byte) - elseif offset_encoding == 'utf-32' then - utf_idx, _ = str_utfindex(line, byte) - else - utf_idx = byte - end - - -- convert to 1 based indexing - return utf_idx + 1 -end - ----@param line string ----@param offset_encoding string ----@return integer -local function compute_line_length(line, offset_encoding) - local length, _ --- @type integer, integer - if offset_encoding == 'utf-16' then - _, length = str_utfindex(line) - elseif offset_encoding == 'utf-32' then - length, _ = str_utfindex(line) - else - length = #line - end - return length -end - -- Given a line, byte idx, alignment, and offset_encoding convert to the aligned -- utf-8 index and either the utf-16, or utf-32 index. ---@param line string the line to index into @@ -101,7 +62,7 @@ local function align_end_position(line, byte, offset_encoding) char = byte -- Called in the case of extending an empty line "" -> "a" elseif byte == #line + 1 then - char = compute_line_length(line, offset_encoding) + 1 + char = str_utfindex(line, offset_encoding) + 1 else -- Modifying line, find the nearest utf codepoint local offset = str_utf_start(line, byte) @@ -111,9 +72,10 @@ local function align_end_position(line, byte, offset_encoding) byte = byte + str_utf_end(line, byte) + 1 end if byte <= #line then - char = byte_to_utf(line, byte, offset_encoding) + --- Convert to 0 based for input, and from 0 based for output + char = str_utfindex(line, offset_encoding, byte - 1) + 1 else - char = compute_line_length(line, offset_encoding) + 1 + char = str_utfindex(line, offset_encoding) + 1 end -- Extending line, find the nearest utf codepoint for the last valid character end @@ -153,7 +115,7 @@ local function compute_start_range( if line then line_idx = firstline - 1 byte_idx = #line + 1 - char_idx = compute_line_length(line, offset_encoding) + 1 + char_idx = str_utfindex(line, offset_encoding) + 1 else line_idx = firstline byte_idx = 1 @@ -190,10 +152,11 @@ local function compute_start_range( char_idx = 1 elseif start_byte_idx == #prev_line + 1 then byte_idx = start_byte_idx - char_idx = compute_line_length(prev_line, offset_encoding) + 1 + char_idx = str_utfindex(prev_line, offset_encoding) + 1 else byte_idx = start_byte_idx + str_utf_start(prev_line, start_byte_idx) - char_idx = byte_to_utf(prev_line, byte_idx, offset_encoding) + --- Convert to 0 based for input, and from 0 based for output + char_idx = vim.str_utfindex(prev_line, offset_encoding, byte_idx - 1) + 1 end -- Return the start difference (shared for new and prev lines) @@ -230,7 +193,7 @@ local function compute_end_range( return { line_idx = lastline - 1, byte_idx = #prev_line + 1, - char_idx = compute_line_length(prev_line, offset_encoding) + 1, + char_idx = str_utfindex(prev_line, offset_encoding) + 1, }, { line_idx = 1, byte_idx = 1, char_idx = 1 } end -- If firstline == new_lastline, the first change occurred on a line that was deleted. @@ -376,7 +339,7 @@ local function compute_range_length(lines, start_range, end_range, offset_encodi local start_line = lines[start_range.line_idx] local range_length --- @type integer if start_line and #start_line > 0 then - range_length = compute_line_length(start_line, offset_encoding) + range_length = str_utfindex(start_line, offset_encoding) - start_range.char_idx + 1 + line_ending_length @@ -389,7 +352,7 @@ local function compute_range_length(lines, start_range, end_range, offset_encodi for idx = start_range.line_idx + 1, end_range.line_idx - 1 do -- Length full line plus newline character if #lines[idx] > 0 then - range_length = range_length + compute_line_length(lines[idx], offset_encoding) + #line_ending + range_length = range_length + str_utfindex(lines[idx], offset_encoding) + #line_ending else range_length = range_length + line_ending_length end diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 882ec22ca6..6eab0f3da4 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -2,12 +2,8 @@ local protocol = require('vim.lsp.protocol') local validate = vim.validate local api = vim.api local list_extend = vim.list_extend -local highlight = vim.highlight local uv = vim.uv -local npcall = vim.F.npcall -local split = vim.split - local M = {} local default_border = { @@ -21,82 +17,73 @@ local default_border = { { ' ', 'NormalFloat' }, } +--- @param border string|(string|[string,string])[] +local function border_error(border) + error( + string.format( + 'invalid floating preview border: %s. :help vim.api.nvim_open_win()', + vim.inspect(border) + ), + 2 + ) +end + +local border_size = { + none = { 0, 0 }, + single = { 2, 2 }, + double = { 2, 2 }, + rounded = { 2, 2 }, + solid = { 2, 2 }, + shadow = { 1, 1 }, +} + --- Check the border given by opts or the default border for the additional --- size it adds to a float. ----@param opts table optional options for the floating window ---- - border (string or table) the border ----@return table size of border in the form of { height = height, width = width } +--- @param opts? {border:string|(string|[string,string])[]} +--- @return integer height +--- @return integer width local function get_border_size(opts) local border = opts and opts.border or default_border - local height = 0 - local width = 0 if type(border) == 'string' then - local border_size = { - none = { 0, 0 }, - single = { 2, 2 }, - double = { 2, 2 }, - rounded = { 2, 2 }, - solid = { 2, 2 }, - shadow = { 1, 1 }, - } - if border_size[border] == nil then - error( - string.format( - 'invalid floating preview border: %s. :help vim.api.nvim_open_win()', - vim.inspect(border) - ) - ) + if not border_size[border] then + border_error(border) end - height, width = unpack(border_size[border]) - else - if 8 % #border ~= 0 then - error( - string.format( - 'invalid floating preview border: %s. :help vim.api.nvim_open_win()', - vim.inspect(border) - ) - ) - end - local function border_width(id) - id = (id - 1) % #border + 1 - if type(border[id]) == 'table' then - -- border specified as a table of <character, highlight group> - return vim.fn.strdisplaywidth(border[id][1]) - elseif type(border[id]) == 'string' then - -- border specified as a list of border characters - return vim.fn.strdisplaywidth(border[id]) - end - error( - string.format( - 'invalid floating preview border: %s. :help vim.api.nvim_open_win()', - vim.inspect(border) - ) - ) - end - local function border_height(id) - id = (id - 1) % #border + 1 - if type(border[id]) == 'table' then - -- border specified as a table of <character, highlight group> - return #border[id][1] > 0 and 1 or 0 - elseif type(border[id]) == 'string' then - -- border specified as a list of border characters - return #border[id] > 0 and 1 or 0 - end - error( - string.format( - 'invalid floating preview border: %s. :help vim.api.nvim_open_win()', - vim.inspect(border) - ) - ) + return unpack(border_size[border]) + end + + if 8 % #border ~= 0 then + border_error(border) + end + + --- @param id integer + --- @return string + local function elem(id) + id = (id - 1) % #border + 1 + local e = border[id] + if type(e) == 'table' then + -- border specified as a table of <character, highlight group> + return e[1] + elseif type(e) == 'string' then + -- border specified as a list of border characters + return e end - height = height + border_height(2) -- top - height = height + border_height(6) -- bottom - width = width + border_width(4) -- right - width = width + border_width(8) -- left + --- @diagnostic disable-next-line:missing-return + border_error(border) + end + + --- @param e string + local function border_height(e) + return #e > 0 and 1 or 0 end - return { height = height, width = width } + local top, bottom = elem(2), elem(6) + local height = border_height(top) + border_height(bottom) + + local right, left = elem(4), elem(8) + local width = vim.fn.strdisplaywidth(right) + vim.fn.strdisplaywidth(left) + + return height, width end --- Splits string at newlines, optionally removing unwanted blank lines. @@ -122,79 +109,13 @@ local function split_lines(s, no_blank) end local function create_window_without_focus() - local prev = vim.api.nvim_get_current_win() + local prev = api.nvim_get_current_win() vim.cmd.new() - local new = vim.api.nvim_get_current_win() - vim.api.nvim_set_current_win(prev) + local new = api.nvim_get_current_win() + api.nvim_set_current_win(prev) return new end ---- Convert byte index to `encoding` index. ---- Convenience wrapper around vim.str_utfindex ----@param line string line to be indexed ----@param index integer|nil byte index (utf-8), or `nil` for length ----@param encoding 'utf-8'|'utf-16'|'utf-32'|nil defaults to utf-16 ----@return integer `encoding` index of `index` in `line` -function M._str_utfindex_enc(line, index, encoding) - local len32, len16 = vim.str_utfindex(line) - if not encoding then - encoding = 'utf-16' - end - if encoding == 'utf-8' then - if index then - return index - else - return #line - end - elseif encoding == 'utf-16' then - if not index or index > len16 then - return len16 - end - local _, col16 = vim.str_utfindex(line, index) - return col16 - elseif encoding == 'utf-32' then - if not index or index > len32 then - return len32 - end - local col32, _ = vim.str_utfindex(line, index) - return col32 - else - error('Invalid encoding: ' .. vim.inspect(encoding)) - end -end - ---- Convert UTF index to `encoding` index. ---- Convenience wrapper around vim.str_byteindex ----Alternative to vim.str_byteindex that takes an encoding. ----@param line string line to be indexed ----@param index integer UTF index ----@param encoding string utf-8|utf-16|utf-32| defaults to utf-16 ----@return integer byte (utf-8) index of `encoding` index `index` in `line` -function M._str_byteindex_enc(line, index, encoding) - local len = #line - if index > len then - -- LSP spec: if character > line length, default to the line length. - -- https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#position - return len - end - if not encoding then - encoding = 'utf-16' - end - if encoding == 'utf-8' then - if index then - return index - else - return len - end - elseif encoding == 'utf-16' then - return vim.str_byteindex(line, index, true) - elseif encoding == 'utf-32' then - return vim.str_byteindex(line, index) - else - error('Invalid encoding: ' .. vim.inspect(encoding)) - end -end - --- Replaces text in a range with new text. --- --- CAUTION: Changes in-place! @@ -243,6 +164,8 @@ function M.set_lines(lines, A, B, new_lines) return lines end +--- @param fn fun(x:any):any[] +--- @return function local function sort_by_key(fn) return function(a, b) local ka, kb = fn(a), fn(b) @@ -354,7 +277,7 @@ end --- Position is a https://microsoft.github.io/language-server-protocol/specifications/specification-current/#position ---@param position lsp.Position ----@param offset_encoding? string utf-8|utf-16|utf-32 +---@param offset_encoding 'utf-8'|'utf-16'|'utf-32' ---@return integer local function get_line_byte_from_position(bufnr, position, offset_encoding) -- LSP's line and characters are 0-indexed @@ -364,7 +287,7 @@ local function get_line_byte_from_position(bufnr, position, offset_encoding) -- character if col > 0 then local line = get_line(bufnr, position.line) or '' - return M._str_byteindex_enc(line, col, offset_encoding or 'utf-16') + return vim.str_byteindex(line, offset_encoding, col, false) end return col end @@ -372,14 +295,13 @@ end --- Applies a list of text edits to a buffer. ---@param text_edits lsp.TextEdit[] ---@param bufnr integer Buffer id ----@param offset_encoding string utf-8|utf-16|utf-32 +---@param offset_encoding 'utf-8'|'utf-16'|'utf-32' ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textEdit function M.apply_text_edits(text_edits, bufnr, offset_encoding) - validate({ - text_edits = { text_edits, 't', false }, - bufnr = { bufnr, 'number', false }, - offset_encoding = { offset_encoding, 'string', false }, - }) + validate('text_edits', text_edits, 'table', false) + validate('bufnr', bufnr, 'number', false) + validate('offset_encoding', offset_encoding, 'string', false) + if not next(text_edits) then return end @@ -392,10 +314,8 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding) vim.bo[bufnr].buflisted = true -- Fix reversed range and indexing each text_edits - local index = 0 - --- @param text_edit lsp.TextEdit - text_edits = vim.tbl_map(function(text_edit) - index = index + 1 + for index, text_edit in ipairs(text_edits) do + --- @cast text_edit lsp.TextEdit|{_index: integer} text_edit._index = index if @@ -407,8 +327,7 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding) text_edit.range.start = text_edit.range['end'] text_edit.range['end'] = start end - return text_edit - end, text_edits) + end -- Sort text_edits ---@param a lsp.TextEdit | { _index: integer } @@ -439,47 +358,45 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding) text_edit.newText, _ = string.gsub(text_edit.newText, '\r\n?', '\n') -- Convert from LSP style ranges to Neovim style ranges. - local e = { - start_row = text_edit.range.start.line, - start_col = get_line_byte_from_position(bufnr, text_edit.range.start, offset_encoding), - end_row = text_edit.range['end'].line, - end_col = get_line_byte_from_position(bufnr, text_edit.range['end'], offset_encoding), - text = split(text_edit.newText, '\n', { plain = true }), - } + local start_row = text_edit.range.start.line + local start_col = get_line_byte_from_position(bufnr, text_edit.range.start, offset_encoding) + local end_row = text_edit.range['end'].line + local end_col = get_line_byte_from_position(bufnr, text_edit.range['end'], offset_encoding) + local text = vim.split(text_edit.newText, '\n', { plain = true }) local max = api.nvim_buf_line_count(bufnr) -- If the whole edit is after the lines in the buffer we can simply add the new text to the end -- of the buffer. - if max <= e.start_row then - api.nvim_buf_set_lines(bufnr, max, max, false, e.text) + if max <= start_row then + api.nvim_buf_set_lines(bufnr, max, max, false, text) else - local last_line_len = #(get_line(bufnr, math.min(e.end_row, max - 1)) or '') + local last_line_len = #(get_line(bufnr, math.min(end_row, max - 1)) or '') -- Some LSP servers may return +1 range of the buffer content but nvim_buf_set_text can't -- accept it so we should fix it here. - if max <= e.end_row then - e.end_row = max - 1 - e.end_col = last_line_len + if max <= end_row then + end_row = max - 1 + end_col = last_line_len has_eol_text_edit = true else - -- If the replacement is over the end of a line (i.e. e.end_col is equal to the line length and the + -- If the replacement is over the end of a line (i.e. end_col is equal to the line length and the -- replacement text ends with a newline We can likely assume that the replacement is assumed -- to be meant to replace the newline with another newline and we need to make sure this -- doesn't add an extra empty line. E.g. when the last line to be replaced contains a '\r' -- in the file some servers (clangd on windows) will include that character in the line -- while nvim_buf_set_text doesn't count it as part of the line. if - e.end_col >= last_line_len - and text_edit.range['end'].character > e.end_col + end_col >= last_line_len + and text_edit.range['end'].character > end_col and #text_edit.newText > 0 and string.sub(text_edit.newText, -1) == '\n' then - table.remove(e.text, #e.text) + table.remove(text, #text) end end - -- Make sure we don't go out of bounds for e.end_col - e.end_col = math.min(last_line_len, e.end_col) + -- Make sure we don't go out of bounds for end_col + end_col = math.min(last_line_len, end_col) - api.nvim_buf_set_text(bufnr, e.start_row, e.start_col, e.end_row, e.end_col, e.text) + api.nvim_buf_set_text(bufnr, start_row, start_col, end_row, end_col, text) end end @@ -495,7 +412,7 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding) -- make sure we don't go out of bounds pos[1] = math.min(pos[1], max) pos[2] = math.min(pos[2], #(get_line(bufnr, pos[1] - 1) or '')) - vim.api.nvim_buf_set_mark(bufnr or 0, mark, pos[1], pos[2], {}) + api.nvim_buf_set_mark(bufnr or 0, mark, pos[1], pos[2], {}) end end @@ -513,7 +430,7 @@ end --- ---@param text_document_edit lsp.TextDocumentEdit ---@param index? integer: Optional index of the edit, if from a list of edits (or nil, if not from a list) ----@param offset_encoding? string +---@param offset_encoding? 'utf-8'|'utf-16'|'utf-32' ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentEdit function M.apply_text_document_edit(text_document_edit, index, offset_encoding) local text_document = text_document_edit.textDocument @@ -523,19 +440,15 @@ function M.apply_text_document_edit(text_document_edit, index, offset_encoding) 'apply_text_document_edit must be called with valid offset encoding', vim.log.levels.WARN ) - end - - -- For lists of text document edits, - -- do not check the version after the first edit. - local should_check_version = true - if index and index > 1 then - should_check_version = false + return end -- `VersionedTextDocumentIdentifier`s version may be null -- https://microsoft.github.io/language-server-protocol/specification#versionedTextDocumentIdentifier if - should_check_version + -- For lists of text document edits, + -- do not check the version after the first edit. + not (index and index > 1) and ( text_document.version and text_document.version > 0 @@ -553,6 +466,9 @@ local function path_components(path) return vim.split(path, '/', { plain = true }) end +--- @param path string[] +--- @param prefix string[] +--- @return boolean local function path_under_prefix(path, prefix) for i, c in ipairs(prefix) do if c ~= path[i] then @@ -562,17 +478,24 @@ local function path_under_prefix(path, prefix) return true end ---- Get list of buffers whose filename matches the given path prefix (normalized full path) +--- Get list of loaded writable buffers whose filename matches the given path +--- prefix (normalized full path). ---@param prefix string ---@return integer[] -local function get_bufs_with_prefix(prefix) - prefix = path_components(prefix) - local buffers = {} - for _, v in ipairs(vim.api.nvim_list_bufs()) do - local bname = vim.api.nvim_buf_get_name(v) - local path = path_components(vim.fs.normalize(bname, { expand_env = false })) - if path_under_prefix(path, prefix) then - table.insert(buffers, v) +local function get_writable_bufs(prefix) + local prefix_parts = path_components(prefix) + local buffers = {} --- @type integer[] + for _, buf in ipairs(api.nvim_list_bufs()) do + -- No need to care about unloaded or nofile buffers. Also :saveas won't work for them. + if + api.nvim_buf_is_loaded(buf) + and not vim.list_contains({ 'nofile', 'nowrite' }, vim.bo[buf].buftype) + then + local bname = api.nvim_buf_get_name(buf) + local path = path_components(vim.fs.normalize(bname, { expand_env = false })) + if path_under_prefix(path, prefix_parts) then + buffers[#buffers + 1] = buf + end end end return buffers @@ -616,19 +539,13 @@ function M.rename(old_fname, new_fname, opts) local buf_rename = {} ---@type table<integer, {from: string, to: string}> local old_fname_pat = '^' .. vim.pesc(old_fname_full) - for b in - vim.iter(get_bufs_with_prefix(old_fname_full)):filter(function(b) - -- No need to care about unloaded or nofile buffers. Also :saveas won't work for them. - return api.nvim_buf_is_loaded(b) - and not vim.list_contains({ 'nofile', 'nowrite' }, vim.bo[b].buftype) - end) - do + for _, b in ipairs(get_writable_bufs(old_fname_full)) do -- Renaming a buffer may conflict with another buffer that happens to have the same name. In -- most cases, this would have been already detected by the file conflict check above, but the -- conflicting buffer may not be associated with a file. For example, 'buftype' can be "nofile" -- or "nowrite", or the buffer can be a normal buffer but has not been written to the file yet. -- Renaming should fail in such cases to avoid losing the contents of the conflicting buffer. - local old_bname = vim.api.nvim_buf_get_name(b) + local old_bname = api.nvim_buf_get_name(b) local new_bname = old_bname:gsub(old_fname_pat, escape_gsub_repl(new_fname)) if vim.fn.bufexists(new_bname) == 1 then local existing_buf = vim.fn.bufnr(new_bname) @@ -702,7 +619,7 @@ end --- Applies a `WorkspaceEdit`. --- ---@param workspace_edit lsp.WorkspaceEdit ----@param offset_encoding string utf-8|utf-16|utf-32 (required) +---@param offset_encoding 'utf-8'|'utf-16'|'utf-32' (required) ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit function M.apply_workspace_edit(workspace_edit, offset_encoding) if offset_encoding == nil then @@ -710,16 +627,18 @@ function M.apply_workspace_edit(workspace_edit, offset_encoding) 'apply_workspace_edit must be called with valid offset encoding', vim.log.levels.WARN ) + return end if workspace_edit.documentChanges then for idx, change in ipairs(workspace_edit.documentChanges) do if change.kind == 'rename' then - M.rename(vim.uri_to_fname(change.oldUri), vim.uri_to_fname(change.newUri), change.options) + local options = change.options --[[@as vim.lsp.util.rename.Opts]] + M.rename(vim.uri_to_fname(change.oldUri), vim.uri_to_fname(change.newUri), options) elseif change.kind == 'create' then create_file(change) elseif change.kind == 'delete' then delete_file(change) - elseif change.kind then + elseif change.kind then --- @diagnostic disable-line:undefined-field error(string.format('Unsupported change: %q', vim.inspect(change))) else M.apply_text_document_edit(change, idx, offset_encoding) @@ -748,7 +667,7 @@ end --- then the corresponding value is returned without further modifications. --- ---@param input lsp.MarkedString|lsp.MarkedString[]|lsp.MarkupContent ----@param contents string[]|nil List of strings to extend with converted lines. Defaults to {}. +---@param contents string[]? List of strings to extend with converted lines. Defaults to {}. ---@return string[] extended with lines of converted markdown. ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_hover function M.convert_input_to_markdown_lines(input, contents) @@ -781,111 +700,117 @@ function M.convert_input_to_markdown_lines(input, contents) return contents end +--- Returns the line/column-based position in `contents` at the given offset. +--- +---@param offset integer +---@param contents string[] +---@return { [1]: integer, [2]: integer }? +local function get_pos_from_offset(offset, contents) + local i = 0 + for l, line in ipairs(contents) do + if offset >= i and offset < i + #line then + return { l - 1, offset - i + 1 } + else + i = i + #line + 1 + end + end +end + --- Converts `textDocument/signatureHelp` response to markdown lines. --- ---@param signature_help lsp.SignatureHelp Response of `textDocument/SignatureHelp` ----@param ft string|nil filetype that will be use as the `lang` for the label markdown code block ----@param triggers table|nil list of trigger characters from the lsp server. used to better determine parameter offsets ----@return string[]|nil table list of lines of converted markdown. ----@return number[]|nil table of active hl +---@param ft string? filetype that will be use as the `lang` for the label markdown code block +---@param triggers string[]? list of trigger characters from the lsp server. used to better determine parameter offsets +---@return string[]? # lines of converted markdown. +---@return Range4? # highlight range for the active parameter ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_signatureHelp function M.convert_signature_help_to_markdown_lines(signature_help, ft, triggers) - if not signature_help.signatures then - return - end --The active signature. If omitted or the value lies outside the range of --`signatures` the value defaults to zero or is ignored if `signatures.length == 0`. --Whenever possible implementors should make an active decision about --the active signature and shouldn't rely on a default value. - local contents = {} - local active_hl + local contents = {} --- @type string[] + local active_offset ---@type [integer, integer]? local active_signature = signature_help.activeSignature or 0 -- If the activeSignature is not inside the valid range, then clip it. -- In 3.15 of the protocol, activeSignature was allowed to be negative if active_signature >= #signature_help.signatures or active_signature < 0 then active_signature = 0 end - local signature = signature_help.signatures[active_signature + 1] - if not signature then - return - end + local signature = vim.deepcopy(signature_help.signatures[active_signature + 1]) local label = signature.label if ft then -- wrap inside a code block for proper rendering label = ('```%s\n%s\n```'):format(ft, label) end - list_extend(contents, split(label, '\n', { plain = true, trimempty = true })) - if signature.documentation then + list_extend(contents, vim.split(label, '\n', { plain = true, trimempty = true })) + local doc = signature.documentation + if doc then -- if LSP returns plain string, we treat it as plaintext. This avoids -- special characters like underscore or similar from being interpreted -- as markdown font modifiers - if type(signature.documentation) == 'string' then - signature.documentation = { kind = 'plaintext', value = signature.documentation } + if type(doc) == 'string' then + signature.documentation = { kind = 'plaintext', value = doc } end M.convert_input_to_markdown_lines(signature.documentation, contents) end if signature.parameters and #signature.parameters > 0 then - local active_parameter = (signature.activeParameter or signature_help.activeParameter or 0) - if active_parameter < 0 then - active_parameter = 0 - end + -- First check if the signature has an activeParameter. If it doesn't check if the response + -- had that property instead. Else just default to 0. + local active_parameter = + math.max(signature.activeParameter or signature_help.activeParameter or 0, 0) -- If the activeParameter is > #parameters, then set it to the last -- NOTE: this is not fully according to the spec, but a client-side interpretation - if active_parameter >= #signature.parameters then - active_parameter = #signature.parameters - 1 - end + active_parameter = math.min(active_parameter, #signature.parameters - 1) local parameter = signature.parameters[active_parameter + 1] - if parameter then - --[=[ - --Represents a parameter of a callable-signature. A parameter can - --have a label and a doc-comment. - interface ParameterInformation { - --The label of this parameter information. - -- - --Either a string or an inclusive start and exclusive end offsets within its containing - --signature label. (see SignatureInformation.label). The offsets are based on a UTF-16 - --string representation as `Position` and `Range` does. - -- - --*Note*: a label of type string should be a substring of its containing signature label. - --Its intended use case is to highlight the parameter label part in the `SignatureInformation.label`. - label: string | [number, number]; - --The human-readable doc-comment of this parameter. Will be shown - --in the UI but can be omitted. - documentation?: string | MarkupContent; - } - --]=] - if parameter.label then - if type(parameter.label) == 'table' then - active_hl = parameter.label - else - local offset = 1 - -- try to set the initial offset to the first found trigger character - for _, t in ipairs(triggers or {}) do - local trigger_offset = signature.label:find(t, 1, true) - if trigger_offset and (offset == 1 or trigger_offset < offset) then - offset = trigger_offset - end - end - for p, param in pairs(signature.parameters) do - offset = signature.label:find(param.label, offset, true) - if not offset then - break - end - if p == active_parameter + 1 then - active_hl = { offset - 1, offset + #parameter.label - 1 } - break - end - offset = offset + #param.label + 1 - end + local parameter_label = parameter.label + if type(parameter_label) == 'table' then + active_offset = parameter_label + else + local offset = 1 ---@type integer? + -- try to set the initial offset to the first found trigger character + for _, t in ipairs(triggers or {}) do + local trigger_offset = signature.label:find(t, 1, true) + if trigger_offset and (offset == 1 or trigger_offset < offset) then + offset = trigger_offset end end - if parameter.documentation then - M.convert_input_to_markdown_lines(parameter.documentation, contents) + for p, param in pairs(signature.parameters) do + local plabel = param.label + assert(type(plabel) == 'string', 'Expected label to be a string') + offset = signature.label:find(plabel, offset, true) + if not offset then + break + end + if p == active_parameter + 1 then + active_offset = { offset - 1, offset + #parameter_label - 1 } + break + end + offset = offset + #param.label + 1 end end + if parameter.documentation then + M.convert_input_to_markdown_lines(parameter.documentation, contents) + end end + + local active_hl = nil + if active_offset then + -- Account for the start of the markdown block. + if ft then + active_offset[1] = active_offset[1] + #contents[1] + active_offset[2] = active_offset[2] + #contents[1] + end + + local a_start = get_pos_from_offset(active_offset[1], contents) + local a_end = get_pos_from_offset(active_offset[2], contents) + if a_start and a_end then + active_hl = { a_start[1], a_start[2], a_end[1], a_end[2] } + end + end + return contents, active_hl end @@ -894,32 +819,15 @@ end --- ---@param width integer window width (in character cells) ---@param height integer window height (in character cells) ----@param opts table optional ---- - offset_x (integer) offset to add to `col` ---- - offset_y (integer) offset to add to `row` ---- - border (string or table) override `border` ---- - focusable (string or table) override `focusable` ---- - zindex (string or table) override `zindex`, defaults to 50 ---- - relative ("mouse"|"cursor") defaults to "cursor" ---- - anchor_bias ("auto"|"above"|"below") defaults to "auto" ---- - "auto": place window based on which side of the cursor has more lines ---- - "above": place the window above the cursor unless there are not enough lines ---- to display the full window height. ---- - "below": place the window below the cursor unless there are not enough lines ---- to display the full window height. ----@return table Options +---@param opts? vim.lsp.util.open_floating_preview.Opts +---@return vim.api.keyset.win_config function M.make_floating_popup_options(width, height, opts) - validate({ - opts = { opts, 't', true }, - }) + validate('opts', opts, 'table', true) opts = opts or {} - validate({ - ['opts.offset_x'] = { opts.offset_x, 'n', true }, - ['opts.offset_y'] = { opts.offset_y, 'n', true }, - }) + validate('opts.offset_x', opts.offset_x, 'number', true) + validate('opts.offset_y', opts.offset_y, 'number', true) local anchor = '' - local row, col local lines_above = opts.relative == 'mouse' and vim.fn.getmousepos().line - 1 or vim.fn.winline() - 1 @@ -927,7 +835,7 @@ function M.make_floating_popup_options(width, height, opts) local anchor_bias = opts.anchor_bias or 'auto' - local anchor_below + local anchor_below --- @type boolean? if anchor_bias == 'below' then anchor_below = (lines_below > lines_above) or (height <= lines_below) @@ -938,7 +846,8 @@ function M.make_floating_popup_options(width, height, opts) anchor_below = lines_below > lines_above end - local border_height = get_border_size(opts).height + local border_height = get_border_size(opts) + local row, col --- @type integer?, integer? if anchor_below then anchor = anchor .. 'N' height = math.max(math.min(lines_below - border_height, height), 0) @@ -960,7 +869,7 @@ function M.make_floating_popup_options(width, height, opts) end local title = (opts.border and opts.title) and opts.title or nil - local title_pos + local title_pos --- @type 'left'|'center'|'right'? if title then title_pos = opts.title_pos or 'center' @@ -982,13 +891,21 @@ function M.make_floating_popup_options(width, height, opts) } end +--- @class vim.lsp.util.show_document.Opts +--- @inlinedoc +--- +--- Jump to existing window if buffer is already open. +--- @field reuse_win? boolean +--- +--- Whether to focus/jump to location if possible. +--- (defaults: true) +--- @field focus? boolean + --- Shows document and optionally jumps to the location. --- ---@param location lsp.Location|lsp.LocationLink ----@param offset_encoding string|nil utf-8|utf-16|utf-32 ----@param opts table|nil options ---- - reuse_win (boolean) Jump to existing window if buffer is already open. ---- - focus (boolean) Whether to focus/jump to location if possible. Defaults to true. +---@param offset_encoding 'utf-8'|'utf-16'|'utf-32'? +---@param opts? vim.lsp.util.show_document.Opts ---@return boolean `true` if succeeded function M.show_document(location, offset_encoding, opts) -- location may be Location or LocationLink @@ -998,6 +915,7 @@ function M.show_document(location, offset_encoding, opts) end if offset_encoding == nil then vim.notify_once('show_document must be called with valid offset encoding', vim.log.levels.WARN) + return false end local bufnr = vim.uri_to_bufnr(uri) @@ -1041,18 +959,13 @@ end --- Jumps to a location. --- +---@deprecated use `vim.lsp.util.show_document` with `{focus=true}` instead ---@param location lsp.Location|lsp.LocationLink ----@param offset_encoding string|nil utf-8|utf-16|utf-32 ----@param reuse_win boolean|nil Jump to existing window if buffer is already open. +---@param offset_encoding 'utf-8'|'utf-16'|'utf-32'? +---@param reuse_win boolean? Jump to existing window if buffer is already open. ---@return boolean `true` if the jump succeeded function M.jump_to_location(location, offset_encoding, reuse_win) - if offset_encoding == nil then - vim.notify_once( - 'jump_to_location must be called with valid offset encoding', - vim.log.levels.WARN - ) - end - + vim.deprecate('vim.lsp.util.jump_to_location', nil, '0.12') return M.show_document(location, offset_encoding, { reuse_win = reuse_win, focus = true }) end @@ -1063,9 +976,9 @@ end --- - for LocationLink, targetRange is shown (e.g., body of function definition) --- ---@param location lsp.Location|lsp.LocationLink ----@param opts table ----@return integer|nil buffer id of float window ----@return integer|nil window id of float window +---@param opts? vim.lsp.util.open_floating_preview.Opts +---@return integer? buffer id of float window +---@return integer? window id of float window function M.preview_location(location, opts) -- location may be LocationLink or Location (more useful for the former) local uri = location.targetUri or location.uri @@ -1092,7 +1005,7 @@ end local function find_window_by_var(name, value) for _, win in ipairs(api.nvim_list_wins()) do - if npcall(api.nvim_win_get_var, win, name) == value then + if vim.w[win][name] == value then return win end end @@ -1158,8 +1071,10 @@ local function collapse_blank_lines(contents) end local function get_markdown_fences() - local fences = {} - for _, fence in pairs(vim.g.markdown_fenced_languages or {}) do + local fences = {} --- @type table<string,string> + for _, fence in + pairs(vim.g.markdown_fenced_languages or {} --[[@as string[] ]]) + do local lang, syntax = fence:match('^(.*)=(.*)$') if lang then fences[lang] = syntax @@ -1179,7 +1094,7 @@ end --- ---@param bufnr integer ---@param contents string[] of lines to show in window ----@param opts table with optional fields +---@param opts? table with optional fields --- - height of floating window --- - width of floating window --- - wrap_at character to wrap at for computing height @@ -1188,10 +1103,8 @@ end --- - separator insert separator after code block ---@return table stripped content function M.stylize_markdown(bufnr, contents, opts) - validate({ - contents = { contents, 't' }, - opts = { opts, 't', true }, - }) + validate('contents', contents, 'table') + validate('opts', opts, 'table', true) opts = opts or {} -- table of fence types to {ft, begin, end} @@ -1203,8 +1116,11 @@ function M.stylize_markdown(bufnr, contents, opts) text = { 'text', '<text>', '</text>' }, } - local match_begin = function(line) + --- @param line string + --- @return {type:string,ft:string}? + local function match_begin(line) for type, pattern in pairs(matchers) do + --- @type string? local ret = line:match(string.format('^%%s*%s%%s*$', pattern[2])) if ret then return { @@ -1215,7 +1131,10 @@ function M.stylize_markdown(bufnr, contents, opts) end end - local match_end = function(line, match) + --- @param line string + --- @param match {type:string,ft:string} + --- @return string + local function match_end(line, match) local pattern = matchers[match.type] return line:match(string.format('^%%s*%s%%s*$', pattern[3])) end @@ -1224,76 +1143,80 @@ function M.stylize_markdown(bufnr, contents, opts) contents = vim.split(table.concat(contents, '\n'), '\n', { trimempty = true }) local stripped = {} - local highlights = {} + local highlights = {} --- @type {ft:string,start:integer,finish:integer}[] -- keep track of lnums that contain markdown - local markdown_lines = {} - do - local i = 1 - while i <= #contents do - local line = contents[i] - local match = match_begin(line) - if match then - local start = #stripped - i = i + 1 - while i <= #contents do - line = contents[i] - if match_end(line, match) then - i = i + 1 - break - end - table.insert(stripped, line) + local markdown_lines = {} --- @type table<integer,boolean> + + local i = 1 + while i <= #contents do + local line = contents[i] + local match = match_begin(line) + if match then + local start = #stripped + i = i + 1 + while i <= #contents do + line = contents[i] + if match_end(line, match) then i = i + 1 + break end - table.insert(highlights, { - ft = match.ft, - start = start + 1, - finish = #stripped, - }) - -- add a separator, but not on the last line - if opts.separator and i < #contents then - table.insert(stripped, '---') - markdown_lines[#stripped] = true - end - else - -- strip any empty lines or separators prior to this separator in actual markdown - if line:match('^---+$') then - while - markdown_lines[#stripped] - and (stripped[#stripped]:match('^%s*$') or stripped[#stripped]:match('^---+$')) - do - markdown_lines[#stripped] = false - table.remove(stripped, #stripped) - end - end - -- add the line if its not an empty line following a separator - if - not ( - line:match('^%s*$') - and markdown_lines[#stripped] - and stripped[#stripped]:match('^---+$') - ) - then - table.insert(stripped, line) - markdown_lines[#stripped] = true - end + table.insert(stripped, line) i = i + 1 end + table.insert(highlights, { + ft = match.ft, + start = start + 1, + finish = #stripped, + }) + -- add a separator, but not on the last line + if opts.separator and i < #contents then + table.insert(stripped, '---') + markdown_lines[#stripped] = true + end + else + -- strip any empty lines or separators prior to this separator in actual markdown + if line:match('^---+$') then + while + markdown_lines[#stripped] + and (stripped[#stripped]:match('^%s*$') or stripped[#stripped]:match('^---+$')) + do + markdown_lines[#stripped] = false + table.remove(stripped, #stripped) + end + end + -- add the line if its not an empty line following a separator + if + not ( + line:match('^%s*$') + and markdown_lines[#stripped] + and stripped[#stripped]:match('^---+$') + ) + then + table.insert(stripped, line) + markdown_lines[#stripped] = true + end + i = i + 1 end end -- Handle some common html escape sequences - stripped = vim.tbl_map(function(line) - local escapes = { - ['>'] = '>', - ['<'] = '<', - ['"'] = '"', - ['''] = "'", - [' '] = ' ', - [' '] = ' ', - ['&'] = '&', - } - return (string.gsub(line, '&[^ ;]+;', escapes)) - end, stripped) + --- @type string[] + stripped = vim.tbl_map( + --- @param line string + function(line) + local escapes = { + ['>'] = '>', + ['<'] = '<', + ['"'] = '"', + ['''] = "'", + [' '] = ' ', + [' '] = ' ', + ['&'] = '&', + } + return (line:gsub('&[^ ;]+;', escapes)) + end, + stripped + ) -- Compute size of float needed to show (wrapped) lines opts.wrap_at = opts.wrap_at or (vim.wo['wrap'] and api.nvim_win_get_width(0)) @@ -1312,7 +1235,7 @@ function M.stylize_markdown(bufnr, contents, opts) local idx = 1 -- keep track of syntaxes we already included. -- no need to include the same syntax more than once - local langs = {} + local langs = {} --- @type table<string,boolean> local fences = get_markdown_fences() local function apply_syntax_to_region(ft, start, finish) if ft == '' then @@ -1335,6 +1258,7 @@ function M.stylize_markdown(bufnr, contents, opts) if #api.nvim_get_runtime_file(('syntax/%s.vim'):format(ft), true) == 0 then return end + --- @diagnostic disable-next-line:param-type-mismatch pcall(vim.cmd, string.format('syntax include %s syntax/%s.vim', lang, ft)) langs[lang] = true end @@ -1390,10 +1314,8 @@ end ---@return string[] table of lines containing normalized Markdown ---@see https://github.github.com/gfm function M._normalize_markdown(contents, opts) - validate({ - contents = { contents, 't' }, - opts = { opts, 't', true }, - }) + validate('contents', contents, 'table') + validate('opts', opts, 'table', true) opts = opts or {} -- 1. Carriage returns are removed @@ -1412,7 +1334,7 @@ end --- Closes the preview window --- ---@param winnr integer window id of preview window ----@param bufnrs table|nil optional list of ignored buffers +---@param bufnrs table? optional list of ignored buffers local function close_preview_window(winnr, bufnrs) vim.schedule(function() -- exit if we are in one of ignored buffers @@ -1460,20 +1382,13 @@ end ---@private --- Computes size of float needed to show contents (with optional wrapping) --- ----@param contents table of lines to show in window ----@param opts? table with optional fields ---- - height of floating window ---- - width of floating window ---- - wrap_at character to wrap at for computing height ---- - max_width maximal width of floating window ---- - max_height maximal height of floating window +---@param contents string[] of lines to show in window +---@param opts? vim.lsp.util.open_floating_preview.Opts ---@return integer width size of float ---@return integer height size of float function M._make_floating_popup_size(contents, opts) - validate({ - contents = { contents, 't' }, - opts = { opts, 't', true }, - }) + validate('contents', contents, 'table') + validate('opts', opts, 'table', true) opts = opts or {} local width = opts.width @@ -1481,7 +1396,7 @@ function M._make_floating_popup_size(contents, opts) local wrap_at = opts.wrap_at local max_width = opts.max_width local max_height = opts.max_height - local line_widths = {} + local line_widths = {} --- @type table<integer,integer> if not width then width = 0 @@ -1492,17 +1407,15 @@ function M._make_floating_popup_size(contents, opts) end end - local border_width = get_border_size(opts).width + local _, border_width = get_border_size(opts) local screen_width = api.nvim_win_get_width(0) width = math.min(width, screen_width) -- make sure borders are always inside the screen - if width + border_width > screen_width then - width = width - (width + border_width - screen_width) - end + width = math.min(width, screen_width - border_width) - if wrap_at and wrap_at > width then - wrap_at = width + if wrap_at then + wrap_at = math.min(wrap_at, width) end if max_width then @@ -1534,7 +1447,6 @@ function M._make_floating_popup_size(contents, opts) end --- @class vim.lsp.util.open_floating_preview.Opts ---- @inlinedoc --- --- Height of floating window --- @field height? integer @@ -1569,6 +1481,29 @@ end --- window with the same {focus_id} --- (default: `true`) --- @field focus? boolean +--- +--- offset to add to `col` +--- @field offset_x? integer +--- +--- offset to add to `row` +--- @field offset_y? integer +--- @field border? string|(string|[string,string])[] override `border` +--- @field zindex? integer override `zindex`, defaults to 50 +--- @field title? string +--- @field title_pos? 'left'|'center'|'right' +--- +--- (default: `'cursor'`) +--- @field relative? 'mouse'|'cursor' +--- +--- - "auto": place window based on which side of the cursor has more lines +--- - "above": place the window above the cursor unless there are not enough lines +--- to display the full window height. +--- - "below": place the window below the cursor unless there are not enough lines +--- to display the full window height. +--- (default: `'auto'`) +--- @field anchor_bias? 'auto'|'above'|'below' +--- +--- @field _update_win? integer --- Shows contents in a floating window. --- @@ -1580,11 +1515,9 @@ end ---@return integer bufnr of newly created float window ---@return integer winid of newly created float window preview window function M.open_floating_preview(contents, syntax, opts) - validate({ - contents = { contents, 't' }, - syntax = { syntax, 's', true }, - opts = { opts, 't', true }, - }) + validate('contents', contents, 'table') + validate('syntax', syntax, 'string', true) + validate('opts', opts, 'table', true) opts = opts or {} opts.wrap = opts.wrap ~= false -- wrapping by default opts.focus = opts.focus ~= false @@ -1592,43 +1525,49 @@ function M.open_floating_preview(contents, syntax, opts) local bufnr = api.nvim_get_current_buf() - -- check if this popup is focusable and we need to focus - if opts.focus_id and opts.focusable ~= false and opts.focus then - -- Go back to previous window if we are in a focusable one - local current_winnr = api.nvim_get_current_win() - if npcall(api.nvim_win_get_var, current_winnr, opts.focus_id) then - api.nvim_command('wincmd p') - return bufnr, current_winnr - end - do - local win = find_window_by_var(opts.focus_id, bufnr) - if win and api.nvim_win_is_valid(win) and vim.fn.pumvisible() == 0 then - -- focus and return the existing buf, win - api.nvim_set_current_win(win) - api.nvim_command('stopinsert') - return api.nvim_win_get_buf(win), win + local floating_winnr = opts._update_win + + -- Create/get the buffer + local floating_bufnr --- @type integer + if floating_winnr then + floating_bufnr = api.nvim_win_get_buf(floating_winnr) + else + -- check if this popup is focusable and we need to focus + if opts.focus_id and opts.focusable ~= false and opts.focus then + -- Go back to previous window if we are in a focusable one + local current_winnr = api.nvim_get_current_win() + if vim.w[current_winnr][opts.focus_id] then + api.nvim_command('wincmd p') + return bufnr, current_winnr + end + do + local win = find_window_by_var(opts.focus_id, bufnr) + if win and api.nvim_win_is_valid(win) and vim.fn.pumvisible() == 0 then + -- focus and return the existing buf, win + api.nvim_set_current_win(win) + api.nvim_command('stopinsert') + return api.nvim_win_get_buf(win), win + end end end - end - -- check if another floating preview already exists for this buffer - -- and close it if needed - local existing_float = npcall(api.nvim_buf_get_var, bufnr, 'lsp_floating_preview') - if existing_float and api.nvim_win_is_valid(existing_float) then - api.nvim_win_close(existing_float, true) + -- check if another floating preview already exists for this buffer + -- and close it if needed + local existing_float = vim.b[bufnr].lsp_floating_preview + if existing_float and api.nvim_win_is_valid(existing_float) then + api.nvim_win_close(existing_float, true) + end + floating_bufnr = api.nvim_create_buf(false, true) end - -- Create the buffer - local floating_bufnr = api.nvim_create_buf(false, true) - -- Set up the contents, using treesitter for markdown local do_stylize = syntax == 'markdown' and vim.g.syntax_on ~= nil + if do_stylize then local width = M._make_floating_popup_size(contents, opts) contents = M._normalize_markdown(contents, { width = width }) vim.bo[floating_bufnr].filetype = 'markdown' vim.treesitter.start(floating_bufnr) - api.nvim_buf_set_lines(floating_bufnr, 0, -1, false, contents) else -- Clean up input: trim empty lines contents = vim.split(table.concat(contents, '\n'), '\n', { trimempty = true }) @@ -1636,19 +1575,47 @@ function M.open_floating_preview(contents, syntax, opts) if syntax then vim.bo[floating_bufnr].syntax = syntax end - api.nvim_buf_set_lines(floating_bufnr, 0, -1, true, contents) end - -- Compute size of float needed to show (wrapped) lines - if opts.wrap then - opts.wrap_at = opts.wrap_at or api.nvim_win_get_width(0) + vim.bo[floating_bufnr].modifiable = true + api.nvim_buf_set_lines(floating_bufnr, 0, -1, false, contents) + + if floating_winnr then + api.nvim_win_set_config(floating_winnr, { + border = opts.border, + title = opts.title, + }) else - opts.wrap_at = nil - end - local width, height = M._make_floating_popup_size(contents, opts) + -- Compute size of float needed to show (wrapped) lines + if opts.wrap then + opts.wrap_at = opts.wrap_at or api.nvim_win_get_width(0) + else + opts.wrap_at = nil + end - local float_option = M.make_floating_popup_options(width, height, opts) - local floating_winnr = api.nvim_open_win(floating_bufnr, false, float_option) + -- TODO(lewis6991): These function assume the current window to determine options, + -- therefore it won't work for opts._update_win and the current window if the floating + -- window + local width, height = M._make_floating_popup_size(contents, opts) + local float_option = M.make_floating_popup_options(width, height, opts) + + floating_winnr = api.nvim_open_win(floating_bufnr, false, float_option) + + api.nvim_buf_set_keymap( + floating_bufnr, + 'n', + 'q', + '<cmd>bdelete<cr>', + { silent = true, noremap = true, nowait = true } + ) + close_preview_autocmd(opts.close_events, floating_winnr, { floating_bufnr, bufnr }) + + -- save focus_id + if opts.focus_id then + api.nvim_win_set_var(floating_winnr, opts.focus_id, bufnr) + end + api.nvim_buf_set_var(bufnr, 'lsp_floating_preview', floating_winnr) + end if do_stylize then vim.wo[floating_winnr].conceallevel = 2 @@ -1656,25 +1623,11 @@ function M.open_floating_preview(contents, syntax, opts) vim.wo[floating_winnr].foldenable = false -- Disable folding. vim.wo[floating_winnr].wrap = opts.wrap -- Soft wrapping. vim.wo[floating_winnr].breakindent = true -- Slightly better list presentation. + vim.wo[floating_winnr].smoothscroll = true -- Scroll by screen-line instead of buffer-line. vim.bo[floating_bufnr].modifiable = false vim.bo[floating_bufnr].bufhidden = 'wipe' - api.nvim_buf_set_keymap( - floating_bufnr, - 'n', - 'q', - '<cmd>bdelete<cr>', - { silent = true, noremap = true, nowait = true } - ) - close_preview_autocmd(opts.close_events, floating_winnr, { floating_bufnr, bufnr }) - - -- save focus_id - if opts.focus_id then - api.nvim_win_set_var(floating_winnr, opts.focus_id, bufnr) - end - api.nvim_buf_set_var(bufnr, 'lsp_floating_preview', floating_winnr) - return floating_bufnr, floating_winnr end @@ -1683,9 +1636,8 @@ do --[[ References ]] --- Removes document highlights from a buffer. --- - ---@param bufnr integer|nil Buffer id + ---@param bufnr integer? Buffer id function M.buf_clear_references(bufnr) - validate({ bufnr = { bufnr, { 'n' }, true } }) api.nvim_buf_clear_namespace(bufnr or 0, reference_ns, 0, -1) end @@ -1693,29 +1645,18 @@ do --[[ References ]] --- ---@param bufnr integer Buffer id ---@param references lsp.DocumentHighlight[] objects to highlight - ---@param offset_encoding string One of "utf-8", "utf-16", "utf-32". + ---@param offset_encoding 'utf-8'|'utf-16'|'utf-32' ---@see https://microsoft.github.io/language-server-protocol/specification/#textDocumentContentChangeEvent function M.buf_highlight_references(bufnr, references, offset_encoding) - validate({ - bufnr = { bufnr, 'n', true }, - offset_encoding = { offset_encoding, 'string', false }, - }) + validate('bufnr', bufnr, 'number', true) + validate('offset_encoding', offset_encoding, 'string', false) for _, reference in ipairs(references) do - local start_line, start_char = - reference['range']['start']['line'], reference['range']['start']['character'] - local end_line, end_char = - reference['range']['end']['line'], reference['range']['end']['character'] + local range = reference.range + local start_line = range.start.line + local end_line = range['end'].line - local start_idx = get_line_byte_from_position( - bufnr, - { line = start_line, character = start_char }, - offset_encoding - ) - local end_idx = get_line_byte_from_position( - bufnr, - { line = start_line, character = end_char }, - offset_encoding - ) + local start_idx = get_line_byte_from_position(bufnr, range.start, offset_encoding) + local end_idx = get_line_byte_from_position(bufnr, range['end'], offset_encoding) local document_highlight_kind = { [protocol.DocumentHighlightKind.Text] = 'LspReferenceText', @@ -1723,13 +1664,13 @@ do --[[ References ]] [protocol.DocumentHighlightKind.Write] = 'LspReferenceWrite', } local kind = reference['kind'] or protocol.DocumentHighlightKind.Text - highlight.range( + vim.hl.range( bufnr, reference_ns, document_highlight_kind[kind], { start_line, start_idx }, { end_line, end_idx }, - { priority = vim.highlight.priorities.user } + { priority = vim.hl.priorities.user } ) end end @@ -1739,16 +1680,6 @@ local position_sort = sort_by_key(function(v) return { v.start.line, v.start.character } end) ----@class vim.lsp.util.locations_to_items.ret ----@inlinedoc ----@field filename string ----@field lnum integer 1-indexed line number ----@field end_lnum integer 1-indexed end line number ----@field col integer 1-indexed column ----@field end_col integer 1-indexed end column ----@field text string ----@field user_data lsp.Location|lsp.LocationLink - --- Returns the items with the byte position calculated correctly and in sorted --- order, for display in quickfix and location lists. --- @@ -1759,9 +1690,9 @@ end) --- |setloclist()|. --- ---@param locations lsp.Location[]|lsp.LocationLink[] ----@param offset_encoding string offset_encoding for locations utf-8|utf-16|utf-32 ---- default to first client of buffer ----@return vim.lsp.util.locations_to_items.ret[] +---@param offset_encoding? 'utf-8'|'utf-16'|'utf-32' +--- default to first client of buffer +---@return vim.quickfix.entry[] # See |setqflist()| for the format function M.locations_to_items(locations, offset_encoding) if offset_encoding == nil then vim.notify_once( @@ -1771,28 +1702,19 @@ function M.locations_to_items(locations, offset_encoding) offset_encoding = vim.lsp.get_clients({ bufnr = 0 })[1].offset_encoding end - local items = {} + local items = {} --- @type vim.quickfix.entry[] + ---@type table<string, {start: lsp.Position, end: lsp.Position, location: lsp.Location|lsp.LocationLink}[]> - local grouped = setmetatable({}, { - __index = function(t, k) - local v = {} - rawset(t, k, v) - return v - end, - }) + local grouped = {} for _, d in ipairs(locations) do -- locations may be Location or LocationLink local uri = d.uri or d.targetUri local range = d.range or d.targetSelectionRange + grouped[uri] = grouped[uri] or {} table.insert(grouped[uri], { start = range.start, ['end'] = range['end'], location = d }) end - ---@type string[] - local keys = vim.tbl_keys(grouped) - table.sort(keys) - -- TODO(ashkan) I wish we could do this lazily. - for _, uri in ipairs(keys) do - local rows = grouped[uri] + for uri, rows in vim.spairs(grouped) do table.sort(rows, position_sort) local filename = vim.uri_to_fname(uri) @@ -1814,10 +1736,10 @@ function M.locations_to_items(locations, offset_encoding) local end_row = end_pos.line local line = lines[row] or '' local end_line = lines[end_row] or '' - local col = M._str_byteindex_enc(line, pos.character, offset_encoding) - local end_col = M._str_byteindex_enc(end_line, end_pos.character, offset_encoding) + local col = vim.str_byteindex(line, offset_encoding, pos.character, false) + local end_col = vim.str_byteindex(end_line, offset_encoding, end_pos.character, false) - table.insert(items, { + items[#items + 1] = { filename = filename, lnum = row + 1, end_lnum = end_row + 1, @@ -1825,58 +1747,51 @@ function M.locations_to_items(locations, offset_encoding) end_col = end_col + 1, text = line, user_data = temp.location, - }) + } end end return items end --- According to LSP spec, if the client set "symbolKind.valueSet", --- the client must handle it properly even if it receives a value outside the specification. --- https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentSymbol -function M._get_symbol_kind_name(symbol_kind) - return protocol.SymbolKind[symbol_kind] or 'Unknown' -end - --- Converts symbols to quickfix list items. --- ----@param symbols table DocumentSymbol[] or SymbolInformation[] +---@param symbols lsp.DocumentSymbol[]|lsp.SymbolInformation[] ---@param bufnr? integer +---@return vim.quickfix.entry[] # See |setqflist()| for the format function M.symbols_to_items(symbols, bufnr) - local function _symbols_to_items(_symbols, _items, _bufnr) - for _, symbol in ipairs(_symbols) do - if symbol.location then -- SymbolInformation type - local range = symbol.location.range - local kind = M._get_symbol_kind_name(symbol.kind) - table.insert(_items, { - filename = vim.uri_to_fname(symbol.location.uri), - lnum = range.start.line + 1, - col = range.start.character + 1, - kind = kind, - text = '[' .. kind .. '] ' .. symbol.name, - }) - elseif symbol.selectionRange then -- DocumentSymbole type - local kind = M._get_symbol_kind_name(symbol.kind) - table.insert(_items, { - -- bufnr = _bufnr, - filename = api.nvim_buf_get_name(_bufnr), - lnum = symbol.selectionRange.start.line + 1, - col = symbol.selectionRange.start.character + 1, - kind = kind, - text = '[' .. kind .. '] ' .. symbol.name, - }) - if symbol.children then - for _, v in ipairs(_symbols_to_items(symbol.children, _items, _bufnr)) do - for _, s in ipairs(v) do - table.insert(_items, s) - end - end - end - end + bufnr = bufnr or 0 + local items = {} --- @type vim.quickfix.entry[] + for _, symbol in ipairs(symbols) do + --- @type string?, lsp.Position? + local filename, pos + + if symbol.location then + --- @cast symbol lsp.SymbolInformation + filename = vim.uri_to_fname(symbol.location.uri) + pos = symbol.location.range.start + elseif symbol.selectionRange then + --- @cast symbol lsp.DocumentSymbol + filename = api.nvim_buf_get_name(bufnr) + pos = symbol.selectionRange.start + end + + if filename and pos then + local kind = protocol.SymbolKind[symbol.kind] or 'Unknown' + items[#items + 1] = { + filename = filename, + lnum = pos.line + 1, + col = pos.character + 1, + kind = kind, + text = '[' .. kind .. '] ' .. symbol.name, + } + end + + if symbol.children then + list_extend(items, M.symbols_to_items(symbol.children, bufnr)) end - return _items end - return _symbols_to_items(symbols, {}, bufnr or 0) + + return items end --- Removes empty lines from the beginning and end. @@ -1899,7 +1814,7 @@ function M.trim_empty_lines(lines) break end end - return list_extend({}, lines, start, finish) + return vim.list_slice(lines, start, finish) end --- Accepts markdown lines and tries to reduce them to a filetype if they @@ -1932,8 +1847,8 @@ function M.try_trim_markdown_code_blocks(lines) return 'markdown' end ----@param window integer|nil: window handle or 0 for current, defaults to current ----@param offset_encoding? string utf-8|utf-16|utf-32|nil defaults to `offset_encoding` of first client of buffer of `window` +---@param window integer?: window handle or 0 for current, defaults to current +---@param offset_encoding? 'utf-8'|'utf-16'|'utf-32'? defaults to `offset_encoding` of first client of buffer of `window` local function make_position_param(window, offset_encoding) window = window or 0 local buf = api.nvim_win_get_buf(window) @@ -1945,15 +1860,15 @@ local function make_position_param(window, offset_encoding) return { line = 0, character = 0 } end - col = M._str_utfindex_enc(line, col, offset_encoding) + col = vim.str_utfindex(line, offset_encoding, col, false) return { line = row, character = col } end --- Creates a `TextDocumentPositionParams` object for the current buffer and cursor position. --- ----@param window integer|nil: window handle or 0 for current, defaults to current ----@param offset_encoding string|nil utf-8|utf-16|utf-32|nil defaults to `offset_encoding` of first client of buffer of `window` +---@param window integer?: window handle or 0 for current, defaults to current +---@param offset_encoding 'utf-8'|'utf-16'|'utf-32'? defaults to `offset_encoding` of first client of buffer of `window` ---@return lsp.TextDocumentPositionParams ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentPositionParams function M.make_position_params(window, offset_encoding) @@ -1970,11 +1885,9 @@ end ---@param bufnr integer buffer handle or 0 for current, defaults to current ---@return string encoding first client if there is one, nil otherwise function M._get_offset_encoding(bufnr) - validate({ - bufnr = { bufnr, 'n', true }, - }) + validate('bufnr', bufnr, 'number', true) - local offset_encoding + local offset_encoding --- @type 'utf-8'|'utf-16'|'utf-32'? for _, client in pairs(vim.lsp.get_clients({ bufnr = bufnr })) do if client.offset_encoding == nil then @@ -2005,8 +1918,8 @@ end --- `textDocument/codeAction`, `textDocument/colorPresentation`, --- `textDocument/rangeFormatting`. --- ----@param window integer|nil: window handle or 0 for current, defaults to current ----@param offset_encoding "utf-8"|"utf-16"|"utf-32"|nil defaults to `offset_encoding` of first client of buffer of `window` +---@param window integer? window handle or 0 for current, defaults to current +---@param offset_encoding "utf-8"|"utf-16"|"utf-32"? defaults to `offset_encoding` of first client of buffer of `window` ---@return table { textDocument = { uri = `current_file_uri` }, range = { start = ---`current_position`, end = `current_position` } } function M.make_range_params(window, offset_encoding) @@ -2022,33 +1935,33 @@ end --- Using the given range in the current buffer, creates an object that --- is similar to |vim.lsp.util.make_range_params()|. --- ----@param start_pos integer[]|nil {row,col} mark-indexed position. +---@param start_pos [integer,integer]? {row,col} mark-indexed position. --- Defaults to the start of the last visual selection. ----@param end_pos integer[]|nil {row,col} mark-indexed position. +---@param end_pos [integer,integer]? {row,col} mark-indexed position. --- Defaults to the end of the last visual selection. ----@param bufnr integer|nil buffer handle or 0 for current, defaults to current ----@param offset_encoding "utf-8"|"utf-16"|"utf-32"|nil defaults to `offset_encoding` of first client of `bufnr` +---@param bufnr integer? buffer handle or 0 for current, defaults to current +---@param offset_encoding 'utf-8'|'utf-16'|'utf-32'? defaults to `offset_encoding` of first client of `bufnr` ---@return table { textDocument = { uri = `current_file_uri` }, range = { start = ---`start_position`, end = `end_position` } } function M.make_given_range_params(start_pos, end_pos, bufnr, offset_encoding) - validate({ - start_pos = { start_pos, 't', true }, - end_pos = { end_pos, 't', true }, - offset_encoding = { offset_encoding, 's', true }, - }) + validate('start_pos', start_pos, 'table', true) + validate('end_pos', end_pos, 'table', true) + validate('offset_encoding', offset_encoding, 'string', true) bufnr = bufnr or api.nvim_get_current_buf() offset_encoding = offset_encoding or M._get_offset_encoding(bufnr) - local A = list_extend({}, start_pos or api.nvim_buf_get_mark(bufnr, '<')) - local B = list_extend({}, end_pos or api.nvim_buf_get_mark(bufnr, '>')) + --- @type [integer, integer] + local A = { unpack(start_pos or api.nvim_buf_get_mark(bufnr, '<')) } + --- @type [integer, integer] + local B = { unpack(end_pos or api.nvim_buf_get_mark(bufnr, '>')) } -- convert to 0-index A[1] = A[1] - 1 B[1] = B[1] - 1 -- account for offset_encoding. if A[2] > 0 then - A = { A[1], M.character_offset(bufnr, A[1], A[2], offset_encoding) } + A[2] = M.character_offset(bufnr, A[1], A[2], offset_encoding) end if B[2] > 0 then - B = { B[1], M.character_offset(bufnr, B[1], B[2], offset_encoding) } + B[2] = M.character_offset(bufnr, B[1], B[2], offset_encoding) end -- we need to offset the end character position otherwise we loose the last -- character of the selection, as LSP end position is exclusive @@ -2067,7 +1980,7 @@ end --- Creates a `TextDocumentIdentifier` object for the current buffer. --- ----@param bufnr integer|nil: Buffer handle, defaults to current +---@param bufnr integer?: Buffer handle, defaults to current ---@return lsp.TextDocumentIdentifier ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentIdentifier function M.make_text_document_params(bufnr) @@ -2085,10 +1998,10 @@ end --- Returns indentation size. --- ---@see 'shiftwidth' ----@param bufnr integer|nil: Buffer handle, defaults to current +---@param bufnr integer?: Buffer handle, defaults to current ---@return integer indentation size function M.get_effective_tabstop(bufnr) - validate({ bufnr = { bufnr, 'n', true } }) + validate('bufnr', bufnr, 'number', true) local bo = bufnr and vim.bo[bufnr] or vim.bo local sw = bo.shiftwidth return (sw == 0 and bo.tabstop) or sw @@ -2096,11 +2009,11 @@ end --- Creates a `DocumentFormattingParams` object for the current buffer and cursor position. --- ----@param options lsp.FormattingOptions|nil with valid `FormattingOptions` entries +---@param options lsp.FormattingOptions? with valid `FormattingOptions` entries ---@return lsp.DocumentFormattingParams object ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_formatting function M.make_formatting_params(options) - validate({ options = { options, 't', true } }) + validate('options', options, 'table', true) options = vim.tbl_extend('keep', options or {}, { tabSize = M.get_effective_tabstop(), insertSpaces = vim.bo.expandtab, @@ -2116,7 +2029,8 @@ end ---@param buf integer buffer number (0 for current) ---@param row integer 0-indexed line ---@param col integer 0-indexed byte offset in line ----@param offset_encoding string utf-8|utf-16|utf-32 defaults to `offset_encoding` of first client of `buf` +---@param offset_encoding? 'utf-8'|'utf-16'|'utf-32' +--- defaults to `offset_encoding` of first client of `buf` ---@return integer `offset_encoding` index of the character in line {row} column {col} in buffer {buf} function M.character_offset(buf, row, col, offset_encoding) local line = get_line(buf, row) @@ -2127,7 +2041,7 @@ function M.character_offset(buf, row, col, offset_encoding) ) offset_encoding = vim.lsp.get_clients({ bufnr = buf })[1].offset_encoding end - return M._str_utfindex_enc(line, col, offset_encoding) + return vim.str_utfindex(line, offset_encoding, col, false) end --- Helper function to return nested values in language server settings @@ -2139,6 +2053,7 @@ end function M.lookup_section(settings, section) vim.deprecate('vim.lsp.util.lookup_section()', 'vim.tbl_get() with `vim.split`', '0.12') for part in vim.gsplit(section, '.', { plain = true }) do + --- @diagnostic disable-next-line:no-unknown settings = settings[part] if settings == nil then return vim.NIL @@ -2153,7 +2068,7 @@ end ---@param bufnr integer ---@param start_line integer ---@param end_line integer ----@param offset_encoding lsp.PositionEncodingKind +---@param offset_encoding 'utf-8'|'utf-16'|'utf-32' ---@return lsp.Range local function make_line_range_params(bufnr, start_line, end_line, offset_encoding) local last_line = api.nvim_buf_line_count(bufnr) - 1 @@ -2161,7 +2076,7 @@ local function make_line_range_params(bufnr, start_line, end_line, offset_encodi ---@type lsp.Position local end_pos - if end_line == last_line and not vim.api.nvim_get_option_value('endofline', { buf = bufnr }) then + if end_line == last_line and not vim.bo[bufnr].endofline then end_pos = { line = end_line, character = M.character_offset(bufnr, end_line, #get_line(bufnr, end_line), offset_encoding), @@ -2201,9 +2116,7 @@ function M._refresh(method, opts) local textDocument = M.make_text_document_params(bufnr) - local only_visible = opts.only_visible or false - - if only_visible then + if opts.only_visible then for _, window in ipairs(api.nvim_list_wins()) do if api.nvim_win_get_buf(window) == bufnr then local first = vim.fn.line('w0', window) diff --git a/runtime/lua/vim/provider/health.lua b/runtime/lua/vim/provider/health.lua index 47c2080e3c..5ecb00f49b 100644 --- a/runtime/lua/vim/provider/health.lua +++ b/runtime/lua/vim/provider/health.lua @@ -449,7 +449,7 @@ end --- Get the latest Nvim Python client (pynvim) version from PyPI. local function latest_pypi_version() local pypi_version = 'unable to get pypi response' - local pypi_response = download('https://pypi.python.org/pypi/pynvim/json') + local pypi_response = download('https://pypi.org/pypi/pynvim/json') if pypi_response ~= '' then local pcall_ok, output = pcall(vim.fn.json_decode, pypi_response) if not pcall_ok then diff --git a/runtime/lua/vim/secure.lua b/runtime/lua/vim/secure.lua index 266725cce2..7b1d071270 100644 --- a/runtime/lua/vim/secure.lua +++ b/runtime/lua/vim/secure.lua @@ -26,7 +26,7 @@ end --- ---@param trust table<string, string> Trust table to write local function write_trust(trust) - vim.validate({ trust = { trust, 't' } }) + vim.validate('trust', trust, 'table') local f = assert(io.open(vim.fn.stdpath('state') .. '/trust', 'w')) local t = {} ---@type string[] @@ -49,7 +49,7 @@ end ---@return (string|nil) The contents of the given file if it exists and is --- trusted, or nil otherwise. function M.read(path) - vim.validate({ path = { path, 's' } }) + vim.validate('path', path, 'string') local fullpath = vim.uv.fs_realpath(vim.fs.normalize(path)) if not fullpath then return nil @@ -132,17 +132,11 @@ end ---@return boolean success true if operation was successful ---@return string msg full path if operation was successful, else error message function M.trust(opts) - vim.validate({ - path = { opts.path, 's', true }, - bufnr = { opts.bufnr, 'n', true }, - action = { - opts.action, - function(m) - return m == 'allow' or m == 'deny' or m == 'remove' - end, - [["allow" or "deny" or "remove"]], - }, - }) + vim.validate('path', opts.path, 'string', true) + vim.validate('bufnr', opts.bufnr, 'number', true) + vim.validate('action', opts.action, function(m) + return m == 'allow' or m == 'deny' or m == 'remove' + end, [["allow" or "deny" or "remove"]]) ---@cast opts vim.trust.opts local path = opts.path diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 4d06cdd77d..4f2373b182 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -109,7 +109,9 @@ function vim.gsplit(s, sep, opts) if type(opts) == 'boolean' then plain = opts -- For backwards compatibility. else - vim.validate({ s = { s, 's' }, sep = { sep, 's' }, opts = { opts, 't', true } }) + vim.validate('s', s, 'string') + vim.validate('sep', sep, 'string') + vim.validate('opts', opts, 'table', true) opts = opts or {} plain, trimempty = opts.plain, opts.trimempty end @@ -249,7 +251,8 @@ end ---@param t table<any, T> Table ---@return table : Table of transformed values function vim.tbl_map(func, t) - vim.validate({ func = { func, 'c' }, t = { t, 't' } }) + vim.validate('func', func, 'callable') + vim.validate('t', t, 'table') --- @cast t table<any,any> local rettab = {} --- @type table<any,any> @@ -266,7 +269,8 @@ end ---@param t table<any, T> (table) Table ---@return T[] : Table of filtered values function vim.tbl_filter(func, t) - vim.validate({ func = { func, 'c' }, t = { t, 't' } }) + vim.validate('func', func, 'callable') + vim.validate('t', t, 'table') --- @cast t table<any,any> local rettab = {} --- @type table<any,any> @@ -303,12 +307,13 @@ end ---@param opts? vim.tbl_contains.Opts Keyword arguments |kwargs|: ---@return boolean `true` if `t` contains `value` function vim.tbl_contains(t, value, opts) - vim.validate({ t = { t, 't' }, opts = { opts, 't', true } }) + vim.validate('t', t, 'table') + vim.validate('opts', opts, 'table', true) --- @cast t table<any,any> local pred --- @type fun(v: any): boolean? if opts and opts.predicate then - vim.validate({ value = { value, 'c' } }) + vim.validate('value', value, 'callable') pred = value else pred = function(v) @@ -550,12 +555,10 @@ end ---@param finish integer? Final index on src. Defaults to `#src` ---@return T dst function vim.list_extend(dst, src, start, finish) - vim.validate({ - dst = { dst, 't' }, - src = { src, 't' }, - start = { start, 'n', true }, - finish = { finish, 'n', true }, - }) + vim.validate('dst', dst, 'table') + vim.validate('src', src, 'table') + vim.validate('start', start, 'number', true) + vim.validate('finish', finish, 'number', true) for i = start or 1, finish or #src do table.insert(dst, src[i]) end @@ -778,231 +781,227 @@ function vim.endswith(s, suffix) end do - --- @alias vim.validate.Type - --- | 't' | 'table' - --- | 's' | 'string' - --- | 'n' | 'number' - --- | 'f' | 'function' - --- | 'c' | 'callable' - --- | 'nil' - --- | 'thread' - --- | 'userdata - - local type_names = { - ['table'] = 'table', - t = 'table', - ['string'] = 'string', - s = 'string', - ['number'] = 'number', - n = 'number', - ['boolean'] = 'boolean', + --- @alias vim.validate.Validator + --- | type + --- | 'callable' + --- | (type|'callable')[] + --- | fun(v:any):boolean, string? + + local type_aliases = { b = 'boolean', - ['function'] = 'function', - f = 'function', - ['callable'] = 'callable', c = 'callable', - ['nil'] = 'nil', - ['thread'] = 'thread', - ['userdata'] = 'userdata', + f = 'function', + n = 'number', + s = 'string', + t = 'table', } --- @nodoc - --- @class vim.validate.Spec [any, string|string[], boolean] + --- @class vim.validate.Spec --- @field [1] any Argument value - --- @field [2] string|string[]|fun(v:any):boolean, string? Type name, or callable - --- @field [3]? boolean + --- @field [2] vim.validate.Validator Argument validator + --- @field [3]? boolean|string Optional flag or error message - local function _is_type(val, t) + local function is_type(val, t) return type(val) == t or (t == 'callable' and vim.is_callable(val)) end --- @param param_name string - --- @param spec vim.validate.Spec + --- @param val any + --- @param validator vim.validate.Validator + --- @param message? string + --- @param allow_alias? boolean Allow short type names: 'n', 's', 't', 'b', 'f', 'c' --- @return string? - local function is_param_valid(param_name, spec) - if type(spec) ~= 'table' then - return string.format('opt[%s]: expected table, got %s', param_name, type(spec)) - end + local function is_valid(param_name, val, validator, message, allow_alias) + if type(validator) == 'string' then + local expected = allow_alias and type_aliases[validator] or validator - local val = spec[1] -- Argument value - local types = spec[2] -- Type name, or callable - local optional = (true == spec[3]) - - if type(types) == 'string' then - types = { types } - end + if not expected then + return string.format('invalid type name: %s', validator) + end - if vim.is_callable(types) then + if not is_type(val, expected) then + return string.format('%s: expected %s, got %s', param_name, expected, type(val)) + end + elseif vim.is_callable(validator) then -- Check user-provided validation function - local valid, optional_message = types(val) + local valid, opt_msg = validator(val) if not valid then - local error_message = - string.format('%s: expected %s, got %s', param_name, (spec[3] or '?'), tostring(val)) - if optional_message ~= nil then - error_message = string.format('%s. Info: %s', error_message, optional_message) + local err_msg = + string.format('%s: expected %s, got %s', param_name, message or '?', tostring(val)) + + if opt_msg then + err_msg = string.format('%s. Info: %s', err_msg, opt_msg) end - return error_message + return err_msg end - elseif type(types) == 'table' then - local success = false - for i, t in ipairs(types) do - local t_name = type_names[t] - if not t_name then + elseif type(validator) == 'table' then + for _, t in ipairs(validator) do + local expected = allow_alias and type_aliases[t] or t + if not expected then return string.format('invalid type name: %s', t) end - types[i] = t_name - if (optional and val == nil) or _is_type(val, t_name) then - success = true - break + if is_type(val, expected) then + return -- success end end - if not success then - return string.format( - '%s: expected %s, got %s', - param_name, - table.concat(types, '|'), - type(val) - ) + + -- Normalize validator types for error message + if allow_alias then + for i, t in ipairs(validator) do + validator[i] = type_aliases[t] or t + end end + + return string.format( + '%s: expected %s, got %s', + param_name, + table.concat(validator, '|'), + type(val) + ) else - return string.format('invalid type name: %s', tostring(types)) + return string.format('invalid validator: %s', tostring(validator)) end end - --- @param opt table<vim.validate.Type,vim.validate.Spec> - --- @return boolean, string? - local function is_valid(opt) - if type(opt) ~= 'table' then - return false, string.format('opt: expected table, got %s', type(opt)) - end - + --- @param opt table<type|'callable',vim.validate.Spec> + --- @return string? + local function validate_spec(opt) local report --- @type table<string,string>? for param_name, spec in pairs(opt) do - local msg = is_param_valid(param_name, spec) - if msg then + local err_msg --- @type string? + if type(spec) ~= 'table' then + err_msg = string.format('opt[%s]: expected table, got %s', param_name, type(spec)) + else + local value, validator = spec[1], spec[2] + local msg = type(spec[3]) == 'string' and spec[3] or nil --[[@as string?]] + local optional = spec[3] == true + if not (optional and value == nil) then + err_msg = is_valid(param_name, value, validator, msg, true) + end + end + + if err_msg then report = report or {} - report[param_name] = msg + report[param_name] = err_msg end end if report then for _, msg in vim.spairs(report) do -- luacheck: ignore - return false, msg + return msg end end - - return true end --- Validate function arguments. --- --- This function has two valid forms: --- - --- 1. vim.validate(name: str, value: any, type: string, optional?: bool) - --- 2. vim.validate(spec: table) + --- 1. `vim.validate(name, value, validator[, optional][, message])` --- - --- Form 1 validates that argument {name} with value {value} has the type - --- {type}. {type} must be a value returned by |lua-type()|. If {optional} is - --- true, then {value} may be null. This form is significantly faster and - --- should be preferred for simple cases. + --- Validates that argument {name} with value {value} satisfies + --- {validator}. If {optional} is given and is `true`, then {value} may be + --- `nil`. If {message} is given, then it is used as the expected type in the + --- error message. --- - --- Example: + --- Example: --- - --- ```lua - --- function vim.startswith(s, prefix) - --- vim.validate('s', s, 'string') - --- vim.validate('prefix', prefix, 'string') - --- ... - --- end - --- ``` + --- ```lua + --- function vim.startswith(s, prefix) + --- vim.validate('s', s, 'string') + --- vim.validate('prefix', prefix, 'string') + --- ... + --- end + --- ``` --- - --- Form 2 validates a parameter specification (types and values). Specs are - --- evaluated in alphanumeric order, until the first failure. + --- 2. `vim.validate(spec)` (deprecated) + --- where `spec` is of type + --- `table<string,[value:any, validator: vim.validate.Validator, optional_or_msg? : boolean|string]>)` --- - --- Usage example: + --- Validates a argument specification. + --- Specs are evaluated in alphanumeric order, until the first failure. --- - --- ```lua - --- function user.new(name, age, hobbies) - --- vim.validate{ - --- name={name, 'string'}, - --- age={age, 'number'}, - --- hobbies={hobbies, 'table'}, - --- } - --- ... - --- end - --- ``` + --- Example: + --- + --- ```lua + --- function user.new(name, age, hobbies) + --- vim.validate{ + --- name={name, 'string'}, + --- age={age, 'number'}, + --- hobbies={hobbies, 'table'}, + --- } + --- ... + --- end + --- ``` --- --- Examples with explicit argument values (can be run directly): --- --- ```lua - --- vim.validate{arg1={{'foo'}, 'table'}, arg2={'foo', 'string'}} + --- vim.validate('arg1', {'foo'}, 'table') + --- --> NOP (success) + --- vim.validate('arg2', 'foo', 'string') --- --> NOP (success) --- - --- vim.validate{arg1={1, 'table'}} + --- vim.validate('arg1', 1, 'table') --- --> error('arg1: expected table, got number') --- - --- vim.validate{arg1={3, function(a) return (a % 2) == 0 end, 'even number'}} + --- vim.validate('arg1', 3, function(a) return (a % 2) == 0 end, 'even number') --- --> error('arg1: expected even number, got 3') --- ``` --- --- If multiple types are valid they can be given as a list. --- --- ```lua - --- vim.validate{arg1={{'foo'}, {'table', 'string'}}, arg2={'foo', {'table', 'string'}}} + --- vim.validate('arg1', {'foo'}, {'table', 'string'}) + --- vim.validate('arg2', 'foo', {'table', 'string'}) --- -- NOP (success) --- - --- vim.validate{arg1={1, {'string', 'table'}}} + --- vim.validate('arg1', 1, {'string', 'table'}) --- -- error('arg1: expected string|table, got number') --- ``` --- - ---@param opt table<vim.validate.Type,vim.validate.Spec> (table) Names of parameters to validate. Each key is a parameter - --- name; each value is a tuple in one of these forms: - --- 1. (arg_value, type_name, optional) - --- - arg_value: argument value - --- - type_name: string|table type name, one of: ("table", "t", "string", - --- "s", "number", "n", "boolean", "b", "function", "f", "nil", - --- "thread", "userdata") or list of them. - --- - optional: (optional) boolean, if true, `nil` is valid - --- 2. (arg_value, fn, msg) - --- - arg_value: argument value - --- - fn: any function accepting one argument, returns true if and - --- only if the argument is valid. Can optionally return an additional - --- informative error message as the second returned value. - --- - msg: (optional) error string if validation fails - --- @overload fun(name: string, val: any, expected: string, optional?: boolean) - function vim.validate(opt, ...) - local ok = false - local err_msg ---@type string? - local narg = select('#', ...) - if narg == 0 then - ok, err_msg = is_valid(opt) - elseif narg >= 2 then - -- Overloaded signature for fast/simple cases - local name = opt --[[@as string]] - local v, expected, optional = ... ---@type string, string, boolean? - local actual = type(v) - - ok = (actual == expected) or (v == nil and optional == true) + --- @note `validator` set to a value returned by |lua-type()| provides the + --- best performance. + --- + --- @param name string Argument name + --- @param value string Argument value + --- @param validator vim.validate.Validator + --- - (`string|string[]`): Any value that can be returned from |lua-type()| in addition to + --- `'callable'`: `'boolean'`, `'callable'`, `'function'`, `'nil'`, `'number'`, `'string'`, `'table'`, + --- `'thread'`, `'userdata'`. + --- - (`fun(val:any): boolean, string?`) A function that returns a boolean and an optional + --- string message. + --- @param optional? boolean Argument is optional (may be omitted) + --- @param message? string message when validation fails + --- @overload fun(name: string, val: any, validator: vim.validate.Validator, message: string) + --- @overload fun(spec: table<string,[any, vim.validate.Validator, boolean|string]>) + function vim.validate(name, value, validator, optional, message) + local err_msg --- @type string? + if validator then -- Form 1 + -- Check validator as a string first to optimize the common case. + local ok = (type(value) == validator) or (value == nil and optional == true) if not ok then - err_msg = ('%s: expected %s, got %s%s'):format( - name, - expected, - actual, - v and (' (%s)'):format(v) or '' - ) + local msg = type(optional) == 'string' and optional or message --[[@as string?]] + -- Check more complicated validators + err_msg = is_valid(name, value, validator, msg, false) end + elseif type(name) == 'table' then -- Form 2 + vim.deprecate('vim.validate', 'vim.validate(name, value, validator, optional_or_msg)', '1.0') + err_msg = validate_spec(name) else error('invalid arguments') end - if not ok then + if err_msg then error(err_msg, 2) end end end + --- Returns true if object `f` can be called as a function. --- ---@param f any Any object @@ -1143,7 +1142,7 @@ end --- @param mod T --- @return T function vim._defer_require(root, mod) - return setmetatable({}, { + return setmetatable({ _submodules = mod }, { ---@param t table<string, any> ---@param k string __index = function(t, k) @@ -1157,6 +1156,34 @@ function vim._defer_require(root, mod) }) end +--- @private +--- Creates a module alias/shim that lazy-loads a target module. +--- +--- Unlike `vim.defaulttable()` this also: +--- - implements __call +--- - calls vim.deprecate() +--- +--- @param old_name string Name of the deprecated module, which will be shimmed. +--- @param new_name string Name of the new module, which will be loaded by require(). +function vim._defer_deprecated_module(old_name, new_name) + return setmetatable({}, { + ---@param _ table<string, any> + ---@param k string + __index = function(_, k) + vim.deprecate(old_name, new_name, '2.0.0', nil, false) + --- @diagnostic disable-next-line:no-unknown + local target = require(new_name) + return target[k] + end, + __call = function(self) + vim.deprecate(old_name, new_name, '2.0.0', nil, false) + --- @diagnostic disable-next-line:no-unknown + local target = require(new_name) + return target(self) + end, + }) +end + --- @nodoc --- @class vim.context.mods --- @field bo? table<string, any> @@ -1193,11 +1220,14 @@ local state_restore_order = { 'bo', 'wo', 'go', 'env' } --- @param context vim.context.mods --- @return vim.context.state local get_context_state = function(context) + --- @type vim.context.state local res = { bo = {}, env = {}, go = {}, wo = {} } -- Use specific order from possibly most to least intrusive for _, scope in ipairs(scope_order) do - for name, _ in pairs(context[scope] or {}) do + for name, _ in + pairs(context[scope] or {} --[[@as table<string,any>]]) + do local sc = scope == 'o' and scope_map[vim.api.nvim_get_option_info2(name, {}).scope] or scope -- Do not override already set state and fall back to `vim.NIL` for @@ -1291,7 +1321,10 @@ function vim._with(context, f) -- Apply some parts of the context in specific order -- NOTE: triggers `OptionSet` event for _, scope in ipairs(scope_order) do - for name, context_value in pairs(context[scope] or {}) do + for name, context_value in + pairs(context[scope] or {} --[[@as table<string,any>]]) + do + --- @diagnostic disable-next-line:no-unknown vim[scope][name] = context_value end end @@ -1302,7 +1335,10 @@ function vim._with(context, f) -- Restore relevant cached values in specific order, global scope last -- NOTE: triggers `OptionSet` event for _, scope in ipairs(state_restore_order) do - for name, cached_value in pairs(state[scope]) do + for name, cached_value in + pairs(state[scope] --[[@as table<string,any>]]) + do + --- @diagnostic disable-next-line:no-unknown vim[scope][name] = cached_value end end diff --git a/runtime/lua/vim/termcap.lua b/runtime/lua/vim/termcap.lua index 1da2e71839..4aa41bba9b 100644 --- a/runtime/lua/vim/termcap.lua +++ b/runtime/lua/vim/termcap.lua @@ -17,10 +17,8 @@ local M = {} --- otherwise. {seq} is the control sequence for the capability if found, or nil for --- boolean capabilities. function M.query(caps, cb) - vim.validate({ - caps = { caps, { 'string', 'table' } }, - cb = { cb, 'f' }, - }) + vim.validate('caps', caps, { 'string', 'table' }) + vim.validate('cb', cb, 'function') if type(caps) ~= 'table' then caps = { caps } @@ -40,7 +38,7 @@ function M.query(caps, cb) local k, rest = resp:match('^\027P1%+r(%x+)(.*)$') if k and rest then local cap = vim.text.hexdecode(k) - if not pending[cap] then + if not cap or not pending[cap] then -- Received a response for a capability we didn't request. This can happen if there are -- multiple concurrent XTGETTCAP requests return diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index ed7d31e1f7..dca89f413c 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -133,10 +133,8 @@ end --- ---@return vim.treesitter.LanguageTree object to use for parsing function M.get_string_parser(str, lang, opts) - vim.validate({ - str = { str, 'string' }, - lang = { lang, 'string' }, - }) + vim.validate('str', str, 'string') + vim.validate('lang', lang, 'string') return LanguageTree.new(str, lang, opts) end @@ -152,8 +150,7 @@ function M.is_ancestor(dest, source) return false end - -- child_containing_descendant returns nil if dest is a direct parent - return source:parent() == dest or dest:child_containing_descendant(source) ~= nil + return dest:child_with_descendant(source) ~= nil end --- Returns the node's range or an unpacked range table @@ -168,7 +165,7 @@ function M.get_node_range(node_or_range) if type(node_or_range) == 'table' then return unpack(node_or_range) else - return node_or_range:range() + return node_or_range:range(false) end end @@ -244,11 +241,9 @@ end --- ---@return boolean True if the {node} contains the {range} function M.node_contains(node, range) - vim.validate({ - -- allow a table so nodes can be mocked - node = { node, { 'userdata', 'table' } }, - range = { range, M._range.validate, 'integer list with 4 or 6 elements' }, - }) + -- allow a table so nodes can be mocked + vim.validate('node', node, { 'userdata', 'table' }) + vim.validate('range', range, M._range.validate, 'integer list with 4 or 6 elements') return M._range.contains({ node:range() }, range) end diff --git a/runtime/lua/vim/treesitter/_meta/tsnode.lua b/runtime/lua/vim/treesitter/_meta/tsnode.lua index acc9f8d24e..d982b6a505 100644 --- a/runtime/lua/vim/treesitter/_meta/tsnode.lua +++ b/runtime/lua/vim/treesitter/_meta/tsnode.lua @@ -15,7 +15,7 @@ error('Cannot require a meta file') local TSNode = {} -- luacheck: no unused --- Get the node's immediate parent. ---- Prefer |TSNode:child_containing_descendant()| +--- Prefer |TSNode:child_with_descendant()| --- for iterating over the node's ancestors. --- @return TSNode? function TSNode:parent() end @@ -71,8 +71,24 @@ function TSNode:named_child(index) end --- Get the node's child that contains {descendant}. --- @param descendant TSNode --- @return TSNode? +--- @deprecated function TSNode:child_containing_descendant(descendant) end +--- Get the node's child that contains {descendant} (includes {descendant}). +--- +--- For example, with the following node hierarchy: +--- +--- ``` +--- a -> b -> c +--- +--- a:child_with_descendant(c) == b +--- a:child_with_descendant(b) == b +--- a:child_with_descendant(a) == nil +--- ``` +--- @param descendant TSNode +--- @return TSNode? +function TSNode:child_with_descendant(descendant) end + --- Get the node's start position. Return three values: the row, column and --- total byte count (all zero-based). --- @return integer, integer, integer diff --git a/runtime/lua/vim/treesitter/_query_linter.lua b/runtime/lua/vim/treesitter/_query_linter.lua index c5e4b86e1e..a825505378 100644 --- a/runtime/lua/vim/treesitter/_query_linter.lua +++ b/runtime/lua/vim/treesitter/_query_linter.lua @@ -240,8 +240,12 @@ function M.omnifunc(findstart, base) table.insert(items, text) end end - for _, s in pairs(parser_info.symbols) do - local text = s[2] and s[1] or string.format('%q', s[1]):gsub('\n', 'n') ---@type string + for text, named in + pairs(parser_info.symbols --[[@as table<string, boolean>]]) + do + if not named then + text = string.format('%q', text:sub(2, -2)):gsub('\n', 'n') ---@type string + end if text:find(base, 1, true) then table.insert(items, text) end diff --git a/runtime/lua/vim/treesitter/dev.lua b/runtime/lua/vim/treesitter/dev.lua index 90c3720b80..26817cdba5 100644 --- a/runtime/lua/vim/treesitter/dev.lua +++ b/runtime/lua/vim/treesitter/dev.lua @@ -330,9 +330,7 @@ end --- --- @param opts vim.treesitter.dev.inspect_tree.Opts? function M.inspect_tree(opts) - vim.validate({ - opts = { opts, 't', true }, - }) + vim.validate('opts', opts, 'table', true) opts = opts or {} @@ -529,15 +527,22 @@ function M.inspect_tree(opts) end, }) - api.nvim_create_autocmd('BufHidden', { + api.nvim_create_autocmd({ 'BufHidden', 'BufUnload', 'QuitPre' }, { group = group, buffer = buf, - once = true, callback = function() + -- don't close inpector window if source buffer + -- has more than one open window + if #vim.fn.win_findbuf(buf) > 1 then + return + end + -- close all tree windows for _, window in pairs(vim.fn.win_findbuf(b)) do close_win(window) end + + return true end, }) end @@ -667,10 +672,10 @@ function M.edit_query(lang) api.nvim_buf_clear_namespace(query_buf, edit_ns, 0, -1) end, }) - api.nvim_create_autocmd('BufHidden', { + api.nvim_create_autocmd({ 'BufHidden', 'BufUnload' }, { group = group, buffer = buf, - desc = 'Close the editor window when the source buffer is hidden', + desc = 'Close the editor window when the source buffer is hidden or unloaded', once = true, callback = function() close_win(query_win) diff --git a/runtime/lua/vim/treesitter/health.lua b/runtime/lua/vim/treesitter/health.lua index 637f9ea543..53b64d1dec 100644 --- a/runtime/lua/vim/treesitter/health.lua +++ b/runtime/lua/vim/treesitter/health.lua @@ -4,10 +4,21 @@ local health = vim.health --- Performs a healthcheck for treesitter integration function M.check() - local parsers = vim.api.nvim_get_runtime_file('parser/*', true) + health.start('Treesitter features') + + health.info( + string.format( + 'Treesitter ABI support: min %d, max %d', + vim.treesitter.minimum_language_version, + ts.language_version + ) + ) - health.info(string.format('Nvim runtime ABI version: %d', ts.language_version)) + local can_wasm = vim._ts_add_language_from_wasm ~= nil + health.info(string.format('WASM parser support: %s', tostring(can_wasm))) + health.start('Treesitter parsers') + local parsers = vim.api.nvim_get_runtime_file('parser/*', true) for _, parser in pairs(parsers) do local parsername = vim.fn.fnamemodify(parser, ':t:r') local is_loadable, err_or_nil = pcall(ts.language.add, parsername) @@ -28,9 +39,6 @@ function M.check() ) end end - - local can_wasm = vim._ts_add_language_from_wasm ~= nil - health.info(string.format('Can load WASM parsers: %s', tostring(can_wasm))) end return M diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index a94c408f4e..8ce8652f7d 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -93,9 +93,6 @@ function TSHighlighter.new(tree, opts) opts = opts or {} ---@type { queries: table<string,string> } self.tree = tree tree:register_cbs({ - on_bytes = function(...) - self:on_bytes(...) - end, on_detach = function() self:on_detach() end, @@ -215,13 +212,6 @@ function TSHighlighter:for_each_highlight_state(fn) end ---@package ----@param start_row integer ----@param new_end integer -function TSHighlighter:on_bytes(_, _, start_row, _, _, _, _, _, new_end) - api.nvim__redraw({ buf = self.bufnr, range = { start_row, start_row + new_end + 1 } }) -end - ----@package function TSHighlighter:on_detach() self:destroy() end @@ -230,7 +220,7 @@ end ---@param changes Range6[] function TSHighlighter:on_changedtree(changes) for _, ch in ipairs(changes) do - api.nvim__redraw({ buf = self.bufnr, range = { ch[1], ch[4] + 1 } }) + api.nvim__redraw({ buf = self.bufnr, range = { ch[1], ch[4] + 1 }, flush = false }) end end @@ -328,7 +318,7 @@ local function on_line_impl(self, buf, line, is_spell_nav) -- The "priority" attribute can be set at the pattern level or on a particular capture local priority = ( tonumber(metadata.priority or metadata[capture] and metadata[capture].priority) - or vim.highlight.priorities.treesitter + or vim.hl.priorities.treesitter ) + spell_pri_offset -- The "conceal" attribute can be set at the pattern level or on a particular capture diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua index 9f7807e036..446051dfd7 100644 --- a/runtime/lua/vim/treesitter/language.lua +++ b/runtime/lua/vim/treesitter/language.lua @@ -108,11 +108,9 @@ function M.add(lang, opts) local path = opts.path local symbol_name = opts.symbol_name - vim.validate({ - lang = { lang, 'string' }, - path = { path, 'string', true }, - symbol_name = { symbol_name, 'string', true }, - }) + vim.validate('lang', lang, 'string') + vim.validate('path', path, 'string', true) + vim.validate('symbol_name', symbol_name, 'string', true) -- parser names are assumed to be lowercase (consistent behavior on case-insensitive file systems) lang = lang:lower() @@ -156,10 +154,8 @@ end --- @param lang string Name of parser --- @param filetype string|string[] Filetype(s) to associate with lang function M.register(lang, filetype) - vim.validate({ - lang = { lang, 'string' }, - filetype = { filetype, { 'string', 'table' } }, - }) + vim.validate('lang', lang, 'string') + vim.validate('filetype', filetype, { 'string', 'table' }) for _, f in ipairs(ensure_list(filetype)) do if f ~= '' then @@ -170,7 +166,12 @@ end --- Inspects the provided language. --- ---- Inspecting provides some useful information on the language like node names, ... +--- Inspecting provides some useful information on the language like node and field names, ABI +--- version, and whether the language came from a WASM module. +--- +--- Node names are returned in a table mapping each node name to a `boolean` indicating whether or +--- not the node is named (i.e., not anonymous). Anonymous nodes are surrounded with double quotes +--- (`"`). --- ---@param lang string Language ---@return table diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index fd68c2b910..4b42164dc8 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -1037,7 +1037,7 @@ end --- Registers callbacks for the [LanguageTree]. ---@param cbs table<TSCallbackNameOn,function> An [nvim_buf_attach()]-like table argument with the following handlers: ---- - `on_bytes` : see [nvim_buf_attach()], but this will be called _after_ the parsers callback. +--- - `on_bytes` : see [nvim_buf_attach()]. --- - `on_changedtree` : a callback that will be called every time the tree has syntactical changes. --- It will be passed two arguments: a table of the ranges (as node ranges) that --- changed and the changed tree. diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index 4614967799..1677e8d364 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -626,7 +626,7 @@ local directive_handlers = { --- Adds a new predicate to be used in queries --- ---@param name string Name of the predicate, without leading # ----@param handler fun(match: table<integer,TSNode[]>, pattern: integer, source: integer|string, predicate: any[], metadata: vim.treesitter.query.TSMetadata) +---@param handler fun(match: table<integer,TSNode[]>, pattern: integer, source: integer|string, predicate: any[], metadata: vim.treesitter.query.TSMetadata): boolean? --- - see |vim.treesitter.query.add_directive()| for argument meanings ---@param opts? vim.treesitter.query.add_predicate.Opts function M.add_predicate(name, handler, opts) diff --git a/runtime/lua/vim/ui.lua b/runtime/lua/vim/ui.lua index 532decf5e9..cd159f0172 100644 --- a/runtime/lua/vim/ui.lua +++ b/runtime/lua/vim/ui.lua @@ -20,7 +20,8 @@ local M = {} --- end) --- ``` --- ----@param items any[] Arbitrary items +---@generic T +---@param items T[] Arbitrary items ---@param opts table Additional options --- - prompt (string|nil) --- Text of the prompt. Defaults to `Select one of:` @@ -32,19 +33,19 @@ local M = {} --- Plugins reimplementing `vim.ui.select` may wish to --- use this to infer the structure or semantics of --- `items`, or the context in which select() was called. ----@param on_choice fun(item: any|nil, idx: integer|nil) +---@param on_choice fun(item: T|nil, idx: integer|nil) --- Called once the user made a choice. --- `idx` is the 1-based index of `item` within `items`. --- `nil` if the user aborted the dialog. function M.select(items, opts, on_choice) - vim.validate({ - items = { items, 'table', false }, - on_choice = { on_choice, 'function', false }, - }) + vim.validate('items', items, 'table') + vim.validate('on_choice', on_choice, 'function') opts = opts or {} local choices = { opts.prompt or 'Select one of:' } local format_item = opts.format_item or tostring - for i, item in ipairs(items) do + for i, item in + ipairs(items --[[@as any[] ]]) + do table.insert(choices, string.format('%d: %s', i, format_item(item))) end local choice = vim.fn.inputlist(choices) @@ -86,10 +87,8 @@ end --- an empty string if nothing was entered), or --- `nil` if the user aborted the dialog. function M.input(opts, on_confirm) - vim.validate({ - opts = { opts, 'table', true }, - on_confirm = { on_confirm, 'function', false }, - }) + vim.validate('opts', opts, 'table', true) + vim.validate('on_confirm', on_confirm, 'function') opts = (opts and not vim.tbl_isempty(opts)) and opts or vim.empty_dict() @@ -135,9 +134,7 @@ end --- ---@see |vim.system()| function M.open(path, opt) - vim.validate({ - path = { path, 'string' }, - }) + vim.validate('path', path, 'string') local is_uri = path:match('%w+:') if not is_uri then path = vim.fs.normalize(path) @@ -165,8 +162,10 @@ function M.open(path, opt) cmd = { 'wslview', path } elseif vim.fn.executable('explorer.exe') == 1 then cmd = { 'explorer.exe', path } + elseif vim.fn.executable('lemonade') == 1 then + cmd = { 'lemonade', 'open', path } else - return nil, 'vim.ui.open: no handler found (tried: wslview, explorer.exe, xdg-open)' + return nil, 'vim.ui.open: no handler found (tried: wslview, explorer.exe, xdg-open, lemonade)' end return vim.system(cmd, job_opt), nil @@ -207,7 +206,9 @@ function M._get_urls() if vim.treesitter.node_contains(node, range) then local url = metadata[id] and metadata[id].url if url and match[url] then - for _, n in ipairs(match[url]) do + for _, n in + ipairs(match[url] --[[@as TSNode[] ]]) + do urls[#urls + 1] = vim.treesitter.get_node_text(n, bufnr, { metadata = metadata[url] }) end diff --git a/runtime/macmap.vim b/runtime/macmap.vim deleted file mode 100644 index dc76f15f96..0000000000 --- a/runtime/macmap.vim +++ /dev/null @@ -1,75 +0,0 @@ -" System gvimrc file for Mac OS X -" Author: Benji Fisher <benji@member.AMS.org> -" Last Change: Thu Mar 09 09:00 AM 2006 EST -" -" Define Mac-standard keyboard shortcuts. - -" We don't change 'cpoptions' here, because it would not be set properly when -" a .vimrc file is found later. Thus don't use line continuation and use -" <special> in mappings. - -nnoremap <special> <D-n> :confirm enew<CR> -vmap <special> <D-n> <Esc><D-n>gv -imap <special> <D-n> <C-O><D-n> -cmap <special> <D-n> <C-C><D-n> -omap <special> <D-n> <Esc><D-n> - -nnoremap <special> <D-o> :browse confirm e<CR> -vmap <special> <D-o> <Esc><D-o>gv -imap <special> <D-o> <C-O><D-o> -cmap <special> <D-o> <C-C><D-o> -omap <special> <D-o> <Esc><D-o> - -nnoremap <silent> <special> <D-w> :if winheight(2) < 0 <Bar> confirm enew <Bar> else <Bar> confirm close <Bar> endif<CR> -vmap <special> <D-w> <Esc><D-w>gv -imap <special> <D-w> <C-O><D-w> -cmap <special> <D-w> <C-C><D-w> -omap <special> <D-w> <Esc><D-w> - -nnoremap <silent> <special> <D-s> :if expand("%") == ""<Bar>browse confirm w<Bar> else<Bar>confirm w<Bar>endif<CR> -vmap <special> <D-s> <Esc><D-s>gv -imap <special> <D-s> <C-O><D-s> -cmap <special> <D-s> <C-C><D-s> -omap <special> <D-s> <Esc><D-s> - -nnoremap <special> <D-S-s> :browse confirm saveas<CR> -vmap <special> <D-S-s> <Esc><D-s>gv -imap <special> <D-S-s> <C-O><D-s> -cmap <special> <D-S-s> <C-C><D-s> -omap <special> <D-S-s> <Esc><D-s> - -" From the Edit menu of SimpleText: -nnoremap <special> <D-z> u -vmap <special> <D-z> <Esc><D-z>gv -imap <special> <D-z> <C-O><D-z> -cmap <special> <D-z> <C-C><D-z> -omap <special> <D-z> <Esc><D-z> - -vnoremap <special> <D-x> "+x - -vnoremap <special> <D-c> "+y - -cnoremap <special> <D-c> <C-Y> - -nnoremap <special> <D-v> "+gP -cnoremap <special> <D-v> <C-R>+ -execute 'vnoremap <script> <special> <D-v>' paste#paste_cmd['v'] -execute 'inoremap <script> <special> <D-v>' paste#paste_cmd['i'] - -nnoremap <silent> <special> <D-a> :if &slm != ""<Bar>exe ":norm gggH<C-O>G"<Bar> else<Bar>exe ":norm ggVG"<Bar>endif<CR> -vmap <special> <D-a> <Esc><D-a> -imap <special> <D-a> <Esc><D-a> -cmap <special> <D-a> <C-C><D-a> -omap <special> <D-a> <Esc><D-a> - -nnoremap <special> <D-f> / -vmap <special> <D-f> <Esc><D-f> -imap <special> <D-f> <Esc><D-f> -cmap <special> <D-f> <C-C><D-f> -omap <special> <D-f> <Esc><D-f> - -nnoremap <special> <D-g> n -vmap <special> <D-g> <Esc><D-g> -imap <special> <D-g> <C-O><D-g> -cmap <special> <D-g> <C-C><D-g> -omap <special> <D-g> <Esc><D-g> diff --git a/runtime/macros/editexisting.vim b/runtime/macros/editexisting.vim deleted file mode 100644 index b21777d861..0000000000 --- a/runtime/macros/editexisting.vim +++ /dev/null @@ -1,119 +0,0 @@ -" Vim Plugin: Edit the file with an existing Vim if possible -" Maintainer: The Vim Project <https://github.com/vim/vim> -" Last Change: 2023 Aug 13 - -" This is a plugin, drop it in your (Unix) ~/.vim/plugin or (Win32) -" $VIM/vimfiles/plugin directory. Or make a symbolic link, so that you -" automatically use the latest version. - -" This plugin serves two purposes: -" 1. On startup, if we were invoked with one file name argument and the file -" is not modified then try to find another Vim instance that is editing -" this file. If there is one then bring it to the foreground and exit. -" 2. When a file is edited and a swap file exists for it, try finding that -" other Vim and bring it to the foreground. Requires Vim 7, because it -" uses the SwapExists autocommand event. -if v:version < 700 - finish -endif - -" Function that finds the Vim instance that is editing "filename" and brings -" it to the foreground. -func s:EditElsewhere(filename) - let fname_esc = substitute(a:filename, "'", "''", "g") - - let servers = serverlist() - while servers != '' - " Get next server name in "servername"; remove it from "servers". - let i = match(servers, "\n") - if i == -1 - let servername = servers - let servers = '' - else - let servername = strpart(servers, 0, i) - let servers = strpart(servers, i + 1) - endif - - " Skip ourselves. - if servername ==? v:servername - continue - endif - - " Check if this server is editing our file. - if remote_expr(servername, "bufloaded('" . fname_esc . "')") - " Yes, bring it to the foreground. - if has("win32") - call remote_foreground(servername) - endif - call remote_expr(servername, "foreground()") - - if remote_expr(servername, "exists('*EditExisting')") - " Make sure the file is visible in a window (not hidden). - " If v:swapcommand exists and is set, send it to the server. - if exists("v:swapcommand") - let c = substitute(v:swapcommand, "'", "''", "g") - call remote_expr(servername, "EditExisting('" . fname_esc . "', '" . c . "')") - else - call remote_expr(servername, "EditExisting('" . fname_esc . "', '')") - endif - endif - - if !(has('vim_starting') && has('gui_running') && has('gui_win32')) - " Tell the user what is happening. Not when the GUI is starting - " though, it would result in a message box. - echomsg "File is being edited by " . servername - sleep 2 - endif - return 'q' - endif - endwhile - return '' -endfunc - -" When the plugin is loaded and there is one file name argument: Find another -" Vim server that is editing this file right now. -if argc() == 1 && !&modified - if s:EditElsewhere(expand("%:p")) == 'q' - quit - endif -endif - -" Setup for handling the situation that an existing swap file is found. -try - au! SwapExists * let v:swapchoice = s:EditElsewhere(expand("<afile>:p")) -catch - " Without SwapExists we don't do anything for ":edit" commands -endtry - -" Function used on the server to make the file visible and possibly execute a -" command. -func! EditExisting(fname, command) - " Get the window number of the file in the current tab page. - let winnr = bufwinnr(a:fname) - if winnr <= 0 - " Not found, look in other tab pages. - let bufnr = bufnr(a:fname) - for i in range(tabpagenr('$')) - if index(tabpagebuflist(i + 1), bufnr) >= 0 - " Make this tab page the current one and find the window number. - exe 'tabnext ' . (i + 1) - let winnr = bufwinnr(a:fname) - break - endif - endfor - endif - - if winnr > 0 - exe winnr . "wincmd w" - elseif exists('*fnameescape') - exe "split " . fnameescape(a:fname) - else - exe "split " . escape(a:fname, " \t\n*?[{`$\\%#'\"|!<") - endif - - if a:command != '' - exe "normal! " . a:command - endif - - redraw -endfunc diff --git a/runtime/macros/justify.vim b/runtime/macros/justify.vim deleted file mode 100644 index 011a911401..0000000000 --- a/runtime/macros/justify.vim +++ /dev/null @@ -1,3 +0,0 @@ -" Load the justify package. -" For those users who were loading the justify plugin from here. -packadd justify diff --git a/runtime/macros/matchit.vim b/runtime/macros/matchit.vim deleted file mode 100644 index d4f8cb22e8..0000000000 --- a/runtime/macros/matchit.vim +++ /dev/null @@ -1,2 +0,0 @@ -" This file is a compatibility stub for any plugins which source it. -" Nvim already loads the matchit plugin by default; see ':help pi_matchit.txt'. diff --git a/runtime/macros/shellmenu.vim b/runtime/macros/shellmenu.vim deleted file mode 100644 index 4eb72a556a..0000000000 --- a/runtime/macros/shellmenu.vim +++ /dev/null @@ -1,3 +0,0 @@ -" Load the shellmenu package. -" For those users who were loading the shellmenu plugin from here. -packadd shellmenu diff --git a/runtime/macros/swapmous.vim b/runtime/macros/swapmous.vim deleted file mode 100644 index 5884d83473..0000000000 --- a/runtime/macros/swapmous.vim +++ /dev/null @@ -1,3 +0,0 @@ -" Load the swapmouse package. -" For those users who were loading the swapmous plugin from here. -packadd swapmouse diff --git a/runtime/menu.vim b/runtime/menu.vim index 4576ca0ab7..662eea9403 100644 --- a/runtime/menu.vim +++ b/runtime/menu.vim @@ -1130,7 +1130,7 @@ else endif tmenu ToolBar.LoadSesn Choose a session to load tmenu ToolBar.SaveSesn Save current session - tmenu ToolBar.RunScript Choose a Vim Script to run + tmenu ToolBar.RunScript Choose a Vim script to run tmenu ToolBar.Make Make current project (:make) tmenu ToolBar.RunCtags Build tags in current directory tree (!ctags -R .) tmenu ToolBar.TagJump Jump to tag under cursor diff --git a/runtime/optwin.vim b/runtime/optwin.vim index da70ff1afe..48a4bd2816 100644 --- a/runtime/optwin.vim +++ b/runtime/optwin.vim @@ -626,6 +626,8 @@ call <SID>AddOption("terse", gettext("add 's' flag in 'shortmess' (don't show se call <SID>BinOptionG("terse", &terse) call <SID>AddOption("shortmess", gettext("list of flags to make messages shorter")) call <SID>OptionG("shm", &shm) +call <SID>AddOption("msghistory", gettext("how many messages are remembered")) +call append("$", " \tset mhi=" . &mhi) call <SID>AddOption("showcmd", gettext("show (partial) command keys in location given by 'showcmdloc'")) let &sc = s:old_sc call <SID>BinOptionG("sc", &sc) diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim index 9412a821e8..fd8c4b8817 100644 --- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim +++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim @@ -1688,10 +1688,14 @@ func s:CreateBreakpoint(id, subid, enabled) let hiName = "debugBreakpoint" endif let label = '' - if exists('g:termdebug_config') - let label = get(g:termdebug_config, 'sign', '') - endif - if label == '' + if exists('g:termdebug_config') && has_key(g:termdebug_config, 'sign') + let label = g:termdebug_config['sign'] + elseif exists('g:termdebug_config') && has_key(g:termdebug_config, 'sign_decimal') + let label = printf('%02d', a:id) + if a:id > 99 + let label = '9+' + endif + else let label = printf('%02X', a:id) if a:id > 255 let label = 'F+' diff --git a/runtime/plugin/matchparen.vim b/runtime/plugin/matchparen.vim index 2899612dce..661a34b578 100644 --- a/runtime/plugin/matchparen.vim +++ b/runtime/plugin/matchparen.vim @@ -17,6 +17,9 @@ endif if !exists("g:matchparen_insert_timeout") let g:matchparen_insert_timeout = 60 endif +if !exists("g:matchparen_disable_cursor_hl") + let g:matchparen_disable_cursor_hl = 0 +endif let s:has_matchaddpos = exists('*matchaddpos') @@ -189,10 +192,18 @@ func s:Highlight_Matching_Pair() " If a match is found setup match highlighting. if m_lnum > 0 && m_lnum >= stoplinetop && m_lnum <= stoplinebottom if s:has_matchaddpos - call add(w:matchparen_ids, matchaddpos('MatchParen', [[c_lnum, c_col - before], [m_lnum, m_col]], 10)) + if !g:matchparen_disable_cursor_hl + call add(w:matchparen_ids, matchaddpos('MatchParen', [[c_lnum, c_col - before], [m_lnum, m_col]], 10)) + else + call add(w:matchparen_ids, matchaddpos('MatchParen', [[m_lnum, m_col]], 10)) + endif else - exe '3match MatchParen /\(\%' . c_lnum . 'l\%' . (c_col - before) . - \ 'c\)\|\(\%' . m_lnum . 'l\%' . m_col . 'c\)/' + if !g:matchparen_disable_cursor_hl + exe '3match MatchParen /\(\%' . c_lnum . 'l\%' . (c_col - before) . + \ 'c\)\|\(\%' . m_lnum . 'l\%' . m_col . 'c\)/' + else + exe '3match MatchParen /\(\%' . m_lnum . 'l\%' . m_col . 'c\)/' + endif call add(w:matchparen_ids, 3) endif let w:paren_hl_on = 1 diff --git a/runtime/plugin/netrwPlugin.vim b/runtime/plugin/netrwPlugin.vim index c70e6518ff..775b650e71 100644 --- a/runtime/plugin/netrwPlugin.vim +++ b/runtime/plugin/netrwPlugin.vim @@ -1,9 +1,12 @@ " netrwPlugin.vim: Handles file transfer and remote directory listing across a network " PLUGIN SECTION " Maintainer: This runtime file is looking for a new maintainer. -" Date: Feb 09, 2021 +" Date: Sep 09, 2021 " Last Change: " 2024 May 08 by Vim Project: cleanup legacy Win9X checks +" 2024 Oct 27 by Vim Project: cleanup gx mapping +" 2024 Oct 28 by Vim Project: further improvements +" 2024 Oct 31 by Vim Project: use autoloaded functions " Former Maintainer: Charles E Campbell " GetLatestVimScripts: 1075 1 :AutoInstall: netrw.vim " Copyright: Copyright (C) 1999-2021 Charles E. Campbell {{{1 @@ -31,6 +34,10 @@ set cpo&vim " --------------------------------------------------------------------- " Public Interface: {{{1 +" Commands Launch/URL {{{2 +command -complete=shellcmd -nargs=1 Launch call netrw#Launch(trim(<q-args>)) +command -complete=file -nargs=1 Open call netrw#Open(trim(<q-args>)) +" " }}} " Local Browsing Autocmds: {{{2 augroup FileExplorer au! diff --git a/runtime/tools/emoji_list.lua b/runtime/scripts/emoji_list.lua index 63bbbe4371..63bbbe4371 100644 --- a/runtime/tools/emoji_list.lua +++ b/runtime/scripts/emoji_list.lua diff --git a/runtime/macros/less.bat b/runtime/scripts/less.bat index 7395a70003..f80bf9209e 100644 --- a/runtime/macros/less.bat +++ b/runtime/scripts/less.bat @@ -4,7 +4,7 @@ rem Read stdin if no arguments were given. rem Written by Ken Takata. if "%1"=="" ( - nvim --cmd "let no_plugin_maps = 1" -c "runtime! macros/less.vim" - + nvim --cmd "let no_plugin_maps = 1" -c "runtime! scripts/less.vim" - ) else ( - nvim --cmd "let no_plugin_maps = 1" -c "runtime! macros/less.vim" %* + nvim --cmd "let no_plugin_maps = 1" -c "runtime! scripts/less.vim" %* ) diff --git a/runtime/macros/less.sh b/runtime/scripts/less.sh index 125162f10a..4ff32b0529 100755 --- a/runtime/macros/less.sh +++ b/runtime/scripts/less.sh @@ -8,9 +8,9 @@ if test -t 1; then echo "Missing filename" 1>&2 exit fi - nvim --cmd 'let no_plugin_maps = 1' -c 'runtime! macros/less.vim' - + nvim --cmd 'let no_plugin_maps = 1' -c 'runtime! scripts/less.vim' - else - nvim --cmd 'let no_plugin_maps = 1' -c 'runtime! macros/less.vim' "$@" + nvim --cmd 'let no_plugin_maps = 1' -c 'runtime! scripts/less.vim' "$@" fi else # Output is not a terminal, cat arguments or stdin diff --git a/runtime/macros/less.vim b/runtime/scripts/less.vim index 8df29d96e6..8df29d96e6 100644 --- a/runtime/macros/less.vim +++ b/runtime/scripts/less.vim diff --git a/runtime/mswin.vim b/runtime/scripts/mswin.vim index 689bc792cf..689bc792cf 100644 --- a/runtime/mswin.vim +++ b/runtime/scripts/mswin.vim diff --git a/runtime/syntax/8th.vim b/runtime/syntax/8th.vim index a88a5a294a..e53c185df1 100644 --- a/runtime/syntax/8th.vim +++ b/runtime/syntax/8th.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: 8th -" Version: 23.09.01 -" Last Change: 2023 Dec 19 +" Version: 24.08 +" Last Change: 2024 Nov 07 " Maintainer: Ron Aaron <ron@aaron-tech.com> " URL: https://8th-dev.com/ " Filetypes: *.8th @@ -36,16 +36,16 @@ com! -nargs=+ Builtin syn keyword eighthBuiltin <args> Builtin gen-secret 2fa:gen-secret gen-url 2fa:gen-url validate-code 2fa:validate-code cb AWS:cb cli AWS:cli -Builtin cmd AWS:cmd cp AWS:cp rc AWS:rc call DBUS:call init DBUS:init + DOM:+ - DOM:- attr! DOM:attr! -Builtin attr@ DOM:attr@ attrs DOM:attrs children DOM:children css-parse DOM:css-parse each DOM:each -Builtin find DOM:find new DOM:new type DOM:type ! G:! !if G:!if #! G:#! ## G:## #if G:#if ' G:' ( G:( -Builtin (* G:(* (:) G:(:) (code) G:(code) (defer) G:(defer) (dump) G:(dump) (getc) G:(getc) (gets) G:(gets) +Builtin cmd AWS:cmd cp AWS:cp rc AWS:rc LIBS DBUS:LIBS call DBUS:call init DBUS:init + DOM:+ - DOM:- +Builtin attr! DOM:attr! attr@ DOM:attr@ attrs DOM:attrs children DOM:children css-parse DOM:css-parse +Builtin each DOM:each find DOM:find new DOM:new type DOM:type ! G:! !if G:!if #! G:#! ## G:## #if G:#if +Builtin ' G:' ( G:( (:) G:(:) (code) G:(code) (defer) G:(defer) (dump) G:(dump) (getc) G:(getc) (gets) G:(gets) Builtin (interp) G:(interp) (log) G:(log) (needs) G:(needs) (parseln) G:(parseln) (putc) G:(putc) (puts) G:(puts) -Builtin (stat) G:(stat) (with) G:(with) ) G:) +hook G:+hook +ref G:+ref ,# G:,# -- G:-- -----BEGIN G:-----BEGIN +Builtin (stat) G:(stat) (with) G:(with) ) G:) +hook G:+hook +ref G:+ref ,# G:,# -----BEGIN G:-----BEGIN Builtin -Inf G:-Inf -Inf? G:-Inf? -hook G:-hook -ref G:-ref -rot G:-rot . G:. .# G:.# .hook G:.hook Builtin .needs G:.needs .r G:.r .s G:.s .s-truncate G:.s-truncate .stats G:.stats .ver G:.ver .with G:.with Builtin 0; G:0; 2dip G:2dip 2drop G:2drop 2dup G:2dup 2nip G:2nip 2over G:2over 2swap G:2swap 2tuck G:2tuck -Builtin 3drop G:3drop 3drop G:3drop 3dup G:3dup 3rev G:3rev 4drop G:4drop 8thdt? G:8thdt? 8thsku G:8thsku +Builtin 3drop G:3drop 3drop G:3drop 3dup G:3dup 3rev G:3rev 4drop G:4drop 8thdt? G:8thdt? 8thsku? G:8thsku? Builtin 8thver? G:8thver? 8thvernum? G:8thvernum? : G:: ; G:; ;; G:;; ;;; G:;;; ;with G:;with >clip G:>clip Builtin >json G:>json >kind G:>kind >n G:>n >r G:>r >s G:>s ?: G:?: ?@ G:?@ @ G:@ BITMAP: G:BITMAP: Builtin ENUM: G:ENUM: FLAG: G:FLAG: I G:I Inf G:Inf Inf? G:Inf? J G:J K G:K NaN G:NaN NaN? G:NaN? SED-CHECK G:SED-CHECK @@ -59,16 +59,17 @@ Builtin counting-allocations G:counting-allocations cr G:cr critical: G:critica Builtin curlang G:curlang curry G:curry curry: G:curry: decimal G:decimal default: G:default: defer: G:defer: Builtin deferred: G:deferred: deg>rad G:deg>rad depth G:depth die G:die dip G:dip drop G:drop dstack G:dstack Builtin dump G:dump dup G:dup dup>r G:dup>r dup? G:dup? e# G:e# enum: G:enum: error? G:error? eval G:eval -Builtin eval! G:eval! eval0 G:eval0 expect G:expect extra! G:extra! extra@ G:extra@ false G:false fnv G:fnv -Builtin fourth G:fourth free G:free func: G:func: getc G:getc getcwd G:getcwd getenv G:getenv gets G:gets -Builtin handler G:handler header G:header help G:help hex G:hex i: G:i: i; G:i; isa? G:isa? items-used G:items-used -Builtin jcall G:jcall jclass G:jclass jmethod G:jmethod json! G:json! json-8th> G:json-8th> json-nesting G:json-nesting -Builtin json-pretty G:json-pretty json-throw G:json-throw json> G:json> json@ G:json@ k32 G:k32 keep G:keep -Builtin l: G:l: last G:last lib G:lib libbin G:libbin libc G:libc literal G:literal locals: G:locals: -Builtin lock G:lock lock-to G:lock-to locked? G:locked? log G:log log-syslog G:log-syslog log-task G:log-task -Builtin log-time G:log-time log-time-local G:log-time-local long-days G:long-days long-months G:long-months -Builtin longjmp G:longjmp lookup G:lookup loop G:loop loop- G:loop- map? G:map? mark G:mark mark? G:mark? -Builtin mobile? G:mobile? n# G:n# name>os G:name>os name>sem G:name>sem ndrop G:ndrop needs G:needs +Builtin eval! G:eval! eval0 G:eval0 exit G:exit expect G:expect extra! G:extra! extra@ G:extra@ false G:false +Builtin fnv G:fnv fourth G:fourth free G:free func: G:func: getc G:getc getcwd G:getcwd getenv G:getenv +Builtin gets G:gets goto G:goto handler G:handler header G:header help G:help help_db G:help_db here G:here +Builtin hex G:hex i: G:i: i; G:i; isa? G:isa? items-used G:items-used jcall G:jcall jclass G:jclass +Builtin jmethod G:jmethod json! G:json! json-8th> G:json-8th> json-nesting G:json-nesting json-pretty G:json-pretty +Builtin json-throw G:json-throw json> G:json> json@ G:json@ k32 G:k32 keep G:keep l: G:l: last G:last +Builtin lib G:lib libbin G:libbin libc G:libc libimg G:libimg literal G:literal locals: G:locals: lock G:lock +Builtin lock-to G:lock-to locked? G:locked? log G:log log-syslog G:log-syslog log-task G:log-task log-time G:log-time +Builtin log-time-local G:log-time-local long-days G:long-days long-months G:long-months longjmp G:longjmp +Builtin lookup G:lookup loop G:loop loop- G:loop- map? G:map? mark G:mark mark? G:mark? mobile? G:mobile? +Builtin n# G:n# name>os G:name>os name>sem G:name>sem ndrop G:ndrop needs G:needs needs-throws G:needs-throws Builtin new G:new next-arg G:next-arg nip G:nip noop G:noop not G:not nothrow G:nothrow ns G:ns ns: G:ns: Builtin ns>ls G:ns>ls ns>s G:ns>s ns? G:ns? null G:null null; G:null; null? G:null? nullvar G:nullvar Builtin number? G:number? of: G:of: off G:off on G:on onexit G:onexit only G:only op! G:op! or G:or @@ -76,128 +77,132 @@ Builtin os G:os os-names G:os-names os>long-name G:os>long-name os>name G:os>na Builtin pack G:pack parse G:parse parse-csv G:parse-csv parse-date G:parse-date parsech G:parsech parseln G:parseln Builtin parsews G:parsews pick G:pick poke G:poke pool-clear G:pool-clear pool-clear-all G:pool-clear-all Builtin prior G:prior private G:private process-args G:process-args process-args-fancy G:process-args-fancy -Builtin process-args-help G:process-args-help process-args-vars G:process-args-vars prompt G:prompt -Builtin public G:public putc G:putc puts G:puts quote G:quote r! G:r! r> G:r> r@ G:r@ rad>deg G:rad>deg -Builtin rand-jit G:rand-jit rand-jsf G:rand-jsf rand-native G:rand-native rand-normal G:rand-normal -Builtin rand-pcg G:rand-pcg rand-pcg-seed G:rand-pcg-seed rand-range G:rand-range rand-select G:rand-select -Builtin randbuf-pcg G:randbuf-pcg random G:random rdrop G:rdrop recurse G:recurse recurse-stack G:recurse-stack -Builtin ref@ G:ref@ reg! G:reg! reg@ G:reg@ regbin@ G:regbin@ remaining-args G:remaining-args repeat G:repeat -Builtin required? G:required? requires G:requires reset G:reset roll G:roll rop! G:rop! rot G:rot rpick G:rpick -Builtin rreset G:rreset rroll G:rroll rstack G:rstack rswap G:rswap rusage G:rusage s>ns G:s>ns same? G:same? -Builtin scriptdir G:scriptdir scriptfile G:scriptfile sem G:sem sem-post G:sem-post sem-rm G:sem-rm -Builtin sem-wait G:sem-wait sem-wait? G:sem-wait? sem>name G:sem>name semi-throw G:semi-throw set-wipe G:set-wipe -Builtin setenv G:setenv setjmp G:setjmp settings! G:settings! settings![] G:settings![] settings@ G:settings@ -Builtin settings@? G:settings@? settings@[] G:settings@[] sh G:sh sh$ G:sh$ short-days G:short-days -Builtin short-months G:short-months sleep G:sleep sleep-msec G:sleep-msec sleep-until G:sleep-until -Builtin slog G:slog space G:space stack-check G:stack-check stack-size G:stack-size step G:step sthrow G:sthrow -Builtin string? G:string? struct: G:struct: swap G:swap tab-hook G:tab-hook tell-conflict G:tell-conflict -Builtin tempdir G:tempdir tempfilename G:tempfilename third G:third throw G:throw thrownull G:thrownull -Builtin times G:times tlog G:tlog tri G:tri true G:true tuck G:tuck type-check G:type-check typeassert G:typeassert -Builtin uid G:uid uname G:uname unlock G:unlock unpack G:unpack until G:until until! G:until! while G:while -Builtin while! G:while! with: G:with: word? G:word? words G:words words-like G:words-like words/ G:words/ -Builtin xchg G:xchg xor G:xor >auth HTTP:>auth (curry) I:(curry) notimpl I:notimpl sh I:sh trace-word I:trace-word -Builtin call JSONRPC:call auth-string OAuth:auth-string gen-nonce OAuth:gen-nonce params OAuth:params -Builtin call SOAP:call ! a:! + a:+ - a:- / a:/ 2each a:2each 2map a:2map 2map+ a:2map+ 2map= a:2map= -Builtin <> a:<> = a:= @ a:@ @? a:@? _@ a:_@ all a:all any a:any bsearch a:bsearch centroid a:centroid -Builtin clear a:clear close a:close cmp a:cmp diff a:diff dot a:dot each a:each each! a:each! each-par a:each-par -Builtin each-slice a:each-slice exists? a:exists? filter a:filter filter-par a:filter-par generate a:generate -Builtin group a:group indexof a:indexof insert a:insert intersect a:intersect join a:join len a:len -Builtin map a:map map+ a:map+ map-par a:map-par map= a:map= maxlen a:maxlen mean a:mean mean&variance a:mean&variance -Builtin merge a:merge new a:new op! a:op! open a:open pigeon a:pigeon pivot a:pivot pop a:pop push a:push +Builtin process-args-help G:process-args-help prompt G:prompt public G:public putc G:putc puts G:puts +Builtin quote G:quote r! G:r! r> G:r> r@ G:r@ rad>deg G:rad>deg rand-jit G:rand-jit rand-jsf G:rand-jsf +Builtin rand-native G:rand-native rand-normal G:rand-normal rand-pcg G:rand-pcg rand-pcg-seed G:rand-pcg-seed +Builtin rand-range G:rand-range rand-select G:rand-select randbuf-pcg G:randbuf-pcg random G:random +Builtin rdrop G:rdrop recurse G:recurse recurse-stack G:recurse-stack ref@ G:ref@ reg! G:reg! reg@ G:reg@ +Builtin regbin@ G:regbin@ remaining-args G:remaining-args repeat G:repeat requires G:requires reset G:reset +Builtin roll G:roll rop! G:rop! rot G:rot rpick G:rpick rreset G:rreset rroll G:rroll rstack G:rstack +Builtin rswap G:rswap rusage G:rusage s>ns G:s>ns same? G:same? scriptdir G:scriptdir scriptfile G:scriptfile +Builtin sem G:sem sem-post G:sem-post sem-rm G:sem-rm sem-wait G:sem-wait sem-wait? G:sem-wait? sem>name G:sem>name +Builtin semi-throw G:semi-throw set-wipe G:set-wipe setenv G:setenv setjmp G:setjmp settings! G:settings! +Builtin settings![] G:settings![] settings@ G:settings@ settings@? G:settings@? settings@[] G:settings@[] +Builtin sh G:sh sh$ G:sh$ short-days G:short-days short-months G:short-months sleep G:sleep sleep-msec G:sleep-msec +Builtin sleep-until G:sleep-until slog G:slog space G:space stack-check G:stack-check stack-size G:stack-size +Builtin step G:step sthrow G:sthrow string? G:string? struct: G:struct: swap G:swap tab-hook G:tab-hook +Builtin tell-conflict G:tell-conflict tempdir G:tempdir tempfilename G:tempfilename third G:third throw G:throw +Builtin thrownull G:thrownull times G:times tlog G:tlog toggle G:toggle tri G:tri true G:true tuck G:tuck +Builtin type-check G:type-check typeassert G:typeassert uid G:uid uname G:uname unlock G:unlock unpack G:unpack +Builtin until G:until until! G:until! while G:while while! G:while! with: G:with: word? G:word? words G:words +Builtin words-like G:words-like words/ G:words/ xchg G:xchg xor G:xor >auth HTTP:>auth (curry) I:(curry) +Builtin appopts I:appopts notimpl I:notimpl sh I:sh trace-word I:trace-word call JSONRPC:call auth-string OAuth:auth-string +Builtin gen-nonce OAuth:gen-nonce params OAuth:params call SOAP:call ! a:! + a:+ - a:- / a:/ 2each a:2each +Builtin 2len a:2len 2map a:2map 2map+ a:2map+ 2map= a:2map= <> a:<> = a:= @ a:@ @? a:@? _@ a:_@ _len a:_len +Builtin all a:all any a:any bsearch a:bsearch centroid a:centroid clear a:clear close a:close cmp a:cmp +Builtin diff a:diff dot a:dot each a:each each! a:each! each-par a:each-par each-slice a:each-slice +Builtin exists? a:exists? filter a:filter filter-par a:filter-par generate a:generate group a:group +Builtin indexof a:indexof insert a:insert intersect a:intersect join a:join len a:len map a:map map+ a:map+ +Builtin map-par a:map-par map= a:map= maxlen a:maxlen mean a:mean mean&variance a:mean&variance merge a:merge +Builtin new a:new op! a:op! open a:open pigeon a:pigeon pivot a:pivot pop a:pop push a:push push' a:push' Builtin qsort a:qsort randeach a:randeach reduce a:reduce reduce+ a:reduce+ remove a:remove rev a:rev Builtin rindexof a:rindexof shift a:shift shuffle a:shuffle slice a:slice slice+ a:slice+ slide a:slide Builtin smear a:smear sort a:sort split a:split squash a:squash switch a:switch union a:union uniq a:uniq Builtin unzip a:unzip x a:x x-each a:x-each xchg a:xchg y a:y zip a:zip 8thdir app:8thdir asset app:asset Builtin atrun app:atrun atrun app:atrun atrun app:atrun basedir app:basedir basename app:basename config-file-name app:config-file-name Builtin current app:current datadir app:datadir display-moved app:display-moved exename app:exename -Builtin localechanged app:localechanged lowmem app:lowmem main app:main name app:name oncrash app:oncrash -Builtin opts! app:opts! opts@ app:opts@ orientation app:orientation orientation! app:orientation! pid app:pid -Builtin post-main app:post-main pre-main app:pre-main privdir app:privdir raise app:raise read-config app:read-config -Builtin read-config-map app:read-config-map read-config-var app:read-config-var request-perm app:request-perm -Builtin restart app:restart resumed app:resumed signal app:signal standalone app:standalone subdir app:subdir -Builtin suspended app:suspended sysquit app:sysquit terminated app:terminated timeout app:timeout trap app:trap -Builtin dawn astro:dawn do-dawn astro:do-dawn do-dusk astro:do-dusk do-rise astro:do-rise dusk astro:dusk -Builtin latitude astro:latitude location! astro:location! longitude astro:longitude sunrise astro:sunrise -Builtin genkeys auth:genkeys secret auth:secret session-id auth:session-id session-key auth:session-key +Builtin localechanged app:localechanged lowmem app:lowmem main app:main name app:name onback app:onback +Builtin oncrash app:oncrash opts! app:opts! opts@ app:opts@ orientation app:orientation orientation! app:orientation! +Builtin pid app:pid post-main app:post-main pre-main app:pre-main privdir app:privdir raise app:raise +Builtin read-config app:read-config read-config-map app:read-config-map read-config-var app:read-config-var +Builtin request-perm app:request-perm restart app:restart resumed app:resumed signal app:signal standalone app:standalone +Builtin standalone! app:standalone! subdir app:subdir suspended app:suspended sysquit app:sysquit terminated app:terminated +Builtin ticks app:ticks timeout app:timeout trap app:trap dawn astro:dawn do-dawn astro:do-dawn do-dusk astro:do-dusk +Builtin do-rise astro:do-rise dusk astro:dusk latitude astro:latitude location! astro:location! longitude astro:longitude +Builtin sunrise astro:sunrise genkeys auth:genkeys secret auth:secret session-id auth:session-id session-key auth:session-key Builtin validate auth:validate ! b:! + b:+ / b:/ 1+ b:1+ 1- b:1- <> b:<> = b:= >base16 b:>base16 >base32 b:>base32 -Builtin >base64 b:>base64 >base85 b:>base85 >hex b:>hex >mpack b:>mpack @ b:@ append b:append base16> b:base16> -Builtin base32> b:base32> base64> b:base64> base85> b:base85> bit! b:bit! bit@ b:bit@ clear b:clear -Builtin compress b:compress conv b:conv each b:each each! b:each! each-slice b:each-slice expand b:expand -Builtin fill b:fill getb b:getb hex> b:hex> len b:len mem> b:mem> move b:move mpack-compat b:mpack-compat +Builtin >base64 b:>base64 >base85 b:>base85 >hex b:>hex >mpack b:>mpack @ b:@ ICONVLIBS b:ICONVLIBS +Builtin append b:append base16> b:base16> base32> b:base32> base64> b:base64> base85> b:base85> bit! b:bit! +Builtin bit@ b:bit@ clear b:clear compress b:compress conv b:conv each b:each each! b:each! each-slice b:each-slice +Builtin expand b:expand fill b:fill getb b:getb hex> b:hex> len b:len mem> b:mem> move b:move mpack-compat b:mpack-compat Builtin mpack-date b:mpack-date mpack-ignore b:mpack-ignore mpack> b:mpack> n! b:n! n+ b:n+ n@ b:n@ Builtin new b:new op b:op op! b:op! pad b:pad rev b:rev search b:search shmem b:shmem slice b:slice Builtin splice b:splice ungetb b:ungetb unpad b:unpad writable b:writable xor b:xor +block bc:+block Builtin .blocks bc:.blocks add-block bc:add-block block-hash bc:block-hash block@ bc:block@ first-block bc:first-block Builtin hash bc:hash last-block bc:last-block load bc:load new bc:new save bc:save set-sql bc:set-sql Builtin validate bc:validate validate-block bc:validate-block add bloom:add filter bloom:filter in? bloom:in? -Builtin parse bson:parse accept bt:accept ch! bt:ch! ch@ bt:ch@ connect bt:connect disconnect bt:disconnect +Builtin parse bson:parse LIBS bt:LIBS accept bt:accept ch! bt:ch! ch@ bt:ch@ connect bt:connect disconnect bt:disconnect Builtin init bt:init leconnect bt:leconnect lescan bt:lescan listen bt:listen on? bt:on? read bt:read Builtin scan bt:scan service? bt:service? services? bt:services? write bt:write * c:* * c:* + c:+ + c:+ -Builtin = c:= = c:= >ri c:>ri >ri c:>ri abs c:abs abs c:abs arg c:arg arg c:arg conj c:conj conj c:conj -Builtin im c:im n> c:n> new c:new new c:new re c:re (.hebrew) cal:(.hebrew) (.islamic) cal:(.islamic) -Builtin .hebrew cal:.hebrew .islamic cal:.islamic >hebepoch cal:>hebepoch >jdn cal:>jdn Adar cal:Adar -Builtin Adar2 cal:Adar2 Adar2 cal:Adar2 Av cal:Av Elul cal:Elul Heshvan cal:Heshvan Iyar cal:Iyar Kislev cal:Kislev -Builtin Nissan cal:Nissan Shevat cal:Shevat Sivan cal:Sivan Tammuz cal:Tammuz Tevet cal:Tevet Tishrei cal:Tishrei -Builtin days-in-hebrew-year cal:days-in-hebrew-year displaying-hebrew cal:displaying-hebrew fixed>hebrew cal:fixed>hebrew -Builtin fixed>islamic cal:fixed>islamic gershayim cal:gershayim hanukkah cal:hanukkah hebrew-epoch cal:hebrew-epoch -Builtin hebrew>fixed cal:hebrew>fixed hebrewtoday cal:hebrewtoday hmonth-name cal:hmonth-name islamic.epoch cal:islamic.epoch -Builtin islamic>fixed cal:islamic>fixed islamictoday cal:islamictoday jdn> cal:jdn> last-day-of-hebrew-month cal:last-day-of-hebrew-month +Builtin = c:= = c:= >polar c:>polar >polar c:>polar >ri c:>ri >ri c:>ri ^ c:^ ^ c:^ abs c:abs abs c:abs +Builtin arg c:arg arg c:arg conj c:conj conj c:conj im c:im im c:im log c:log log c:log n> c:n> n> c:n> +Builtin new c:new new c:new polar> c:polar> polar> c:polar> re c:re re c:re (.hebrew) cal:(.hebrew) +Builtin (.islamic) cal:(.islamic) .hebrew cal:.hebrew .islamic cal:.islamic >hebepoch cal:>hebepoch +Builtin >jdn cal:>jdn Adar cal:Adar Adar2 cal:Adar2 Av cal:Av Elul cal:Elul Heshvan cal:Heshvan Iyar cal:Iyar +Builtin Kislev cal:Kislev Nissan cal:Nissan Shevat cal:Shevat Sivan cal:Sivan Tammuz cal:Tammuz Tevet cal:Tevet +Builtin Tishrei cal:Tishrei days-in-hebrew-year cal:days-in-hebrew-year displaying-hebrew cal:displaying-hebrew +Builtin fixed>hebrew cal:fixed>hebrew fixed>islamic cal:fixed>islamic gershayim cal:gershayim hanukkah cal:hanukkah +Builtin hebrew-epoch cal:hebrew-epoch hebrew-leap-year? cal:hebrew-leap-year? hebrew>fixed cal:hebrew>fixed +Builtin hebrewtoday cal:hebrewtoday hmonth-name cal:hmonth-name islamic.epoch cal:islamic.epoch islamic>fixed cal:islamic>fixed +Builtin islamictoday cal:islamictoday jdn> cal:jdn> last-day-of-hebrew-month cal:last-day-of-hebrew-month Builtin number>hebrew cal:number>hebrew omer cal:omer pesach cal:pesach purim cal:purim rosh-chodesh? cal:rosh-chodesh? Builtin rosh-hashanah cal:rosh-hashanah shavuot cal:shavuot taanit-esther cal:taanit-esther tisha-beav cal:tisha-beav -Builtin yom-haatsmaut cal:yom-haatsmaut yom-kippur cal:yom-kippur >redir con:>redir accept con:accept -Builtin accept-nl con:accept-nl accept-pwd con:accept-pwd alert con:alert ansi? con:ansi? black con:black -Builtin blue con:blue clreol con:clreol cls con:cls ctrld-empty con:ctrld-empty cyan con:cyan down con:down -Builtin file>history con:file>history free con:free getxy con:getxy gotoxy con:gotoxy green con:green -Builtin history-handler con:history-handler history>file con:history>file key con:key key? con:key? -Builtin left con:left load-history con:load-history magenta con:magenta max-history con:max-history -Builtin onBlack con:onBlack onBlue con:onBlue onCyan con:onCyan onGreen con:onGreen onMagenta con:onMagenta -Builtin onRed con:onRed onWhite con:onWhite onYellow con:onYellow print con:print red con:red redir> con:redir> -Builtin redir? con:redir? right con:right save-history con:save-history size? con:size? up con:up white con:white -Builtin yellow con:yellow >aes128gcm cr:>aes128gcm >aes256gcm cr:>aes256gcm >cp cr:>cp >cpe cr:>cpe -Builtin >decrypt cr:>decrypt >edbox cr:>edbox >encrypt cr:>encrypt >nbuf cr:>nbuf >rsabox cr:>rsabox -Builtin >uuid cr:>uuid aad? cr:aad? aes128box-sig cr:aes128box-sig aes128gcm> cr:aes128gcm> aes256box-sig cr:aes256box-sig -Builtin aes256gcm> cr:aes256gcm> aesgcm cr:aesgcm blakehash cr:blakehash chacha20box-sig cr:chacha20box-sig -Builtin chachapoly cr:chachapoly cipher! cr:cipher! cipher@ cr:cipher@ ciphers cr:ciphers cp> cr:cp> -Builtin cpe> cr:cpe> decrypt cr:decrypt decrypt+ cr:decrypt+ decrypt> cr:decrypt> ebox-sig cr:ebox-sig -Builtin ecc-curves cr:ecc-curves ecc-genkey cr:ecc-genkey ecc-secret cr:ecc-secret ecc-sign cr:ecc-sign -Builtin ecc-verify cr:ecc-verify ed25519 cr:ed25519 ed25519-secret cr:ed25519-secret ed25519-sign cr:ed25519-sign -Builtin ed25519-verify cr:ed25519-verify edbox-sig cr:edbox-sig edbox> cr:edbox> encrypt cr:encrypt -Builtin encrypt+ cr:encrypt+ encrypt> cr:encrypt> ensurekey cr:ensurekey genkey cr:genkey hash cr:hash -Builtin hash! cr:hash! hash+ cr:hash+ hash>b cr:hash>b hash>s cr:hash>s hash@ cr:hash@ hashes cr:hashes -Builtin hmac cr:hmac hotp cr:hotp iv? cr:iv? pem-read cr:pem-read pem-write cr:pem-write pwd-valid? cr:pwd-valid? -Builtin pwd/ cr:pwd/ pwd>hash cr:pwd>hash rand cr:rand randbuf cr:randbuf randkey cr:randkey restore cr:restore -Builtin root-certs cr:root-certs rsa_decrypt cr:rsa_decrypt rsa_encrypt cr:rsa_encrypt rsa_sign cr:rsa_sign -Builtin rsa_verify cr:rsa_verify rsabox-sig cr:rsabox-sig rsabox> cr:rsabox> rsagenkey cr:rsagenkey +Builtin yom-haatsmaut cal:yom-haatsmaut yom-kippur cal:yom-kippur >hsva clr:>hsva complement clr:complement +Builtin dist clr:dist gradient clr:gradient hsva> clr:hsva> invert clr:invert nearest-name clr:nearest-name +Builtin parse clr:parse >redir con:>redir accept con:accept accept-nl con:accept-nl accept-pwd con:accept-pwd +Builtin alert con:alert ansi? con:ansi? black con:black blue con:blue clreol con:clreol cls con:cls +Builtin ctrld-empty con:ctrld-empty cyan con:cyan down con:down file>history con:file>history free con:free +Builtin getxy con:getxy gotoxy con:gotoxy green con:green history-handler con:history-handler history>file con:history>file +Builtin init con:init key con:key key? con:key? left con:left load-history con:load-history magenta con:magenta +Builtin max-history con:max-history onBlack con:onBlack onBlue con:onBlue onCyan con:onCyan onGreen con:onGreen +Builtin onMagenta con:onMagenta onRed con:onRed onWhite con:onWhite onYellow con:onYellow print con:print +Builtin red con:red redir> con:redir> redir? con:redir? right con:right save-history con:save-history +Builtin size? con:size? up con:up white con:white yellow con:yellow >aes128gcm cr:>aes128gcm >aes256gcm cr:>aes256gcm +Builtin >cp cr:>cp >cpe cr:>cpe >decrypt cr:>decrypt >edbox cr:>edbox >encrypt cr:>encrypt >nbuf cr:>nbuf +Builtin >rsabox cr:>rsabox >uuid cr:>uuid aad? cr:aad? aes128box-sig cr:aes128box-sig aes128gcm> cr:aes128gcm> +Builtin aes256box-sig cr:aes256box-sig aes256gcm> cr:aes256gcm> aesgcm cr:aesgcm blakehash cr:blakehash +Builtin chacha20box-sig cr:chacha20box-sig chachapoly cr:chachapoly cipher! cr:cipher! cipher@ cr:cipher@ +Builtin ciphers cr:ciphers cp> cr:cp> cpe> cr:cpe> decrypt cr:decrypt decrypt+ cr:decrypt+ decrypt> cr:decrypt> +Builtin ebox-sig cr:ebox-sig ecc-curves cr:ecc-curves ecc-genkey cr:ecc-genkey ecc-secret cr:ecc-secret +Builtin ecc-sign cr:ecc-sign ecc-verify cr:ecc-verify ed25519 cr:ed25519 ed25519-secret cr:ed25519-secret +Builtin ed25519-sign cr:ed25519-sign ed25519-verify cr:ed25519-verify edbox-sig cr:edbox-sig edbox> cr:edbox> +Builtin encrypt cr:encrypt encrypt+ cr:encrypt+ encrypt> cr:encrypt> ensurekey cr:ensurekey genkey cr:genkey +Builtin hash cr:hash hash! cr:hash! hash+ cr:hash+ hash>b cr:hash>b hash>s cr:hash>s hash@ cr:hash@ +Builtin hashes cr:hashes hmac cr:hmac hotp cr:hotp iv? cr:iv? pem-read cr:pem-read pem-write cr:pem-write +Builtin pwd-valid? cr:pwd-valid? pwd/ cr:pwd/ pwd>hash cr:pwd>hash rand cr:rand randbuf cr:randbuf +Builtin randkey cr:randkey restore cr:restore root-certs cr:root-certs rsa_decrypt cr:rsa_decrypt rsa_encrypt cr:rsa_encrypt +Builtin rsa_sign cr:rsa_sign rsa_verify cr:rsa_verify rsabox-sig cr:rsabox-sig rsabox> cr:rsabox> rsagenkey cr:rsagenkey Builtin save cr:save sbox-sig cr:sbox-sig sha1-hmac cr:sha1-hmac shard cr:shard tag? cr:tag? totp cr:totp Builtin totp-epoch cr:totp-epoch totp-time-step cr:totp-time-step unshard cr:unshard uuid cr:uuid uuid> cr:uuid> -Builtin validate-pgp-sig cr:validate-pgp-sig validate-pwd cr:validate-pwd + d:+ +day d:+day +hour d:+hour -Builtin +min d:+min +msec d:+msec - d:- .time d:.time / d:/ = d:= >fixed d:>fixed >hmds d:>hmds >hmds: d:>hmds: -Builtin >msec d:>msec >unix d:>unix >ymd d:>ymd ?= d:?= Fri d:Fri Mon d:Mon Sat d:Sat Sun d:Sun Thu d:Thu -Builtin Tue d:Tue Wed d:Wed adjust-dst d:adjust-dst alarm d:alarm approx! d:approx! approx? d:approx? -Builtin approximates! d:approximates! between d:between cmp d:cmp d. d:d. default-now d:default-now +Builtin validate-pgp-sig cr:validate-pgp-sig validate-pwd cr:validate-pwd (.time) d:(.time) + d:+ +day d:+day +Builtin +hour d:+hour +min d:+min +msec d:+msec - d:- .time d:.time / d:/ = d:= >fixed d:>fixed >hmds d:>hmds +Builtin >hmds: d:>hmds: >msec d:>msec >unix d:>unix >ymd d:>ymd ?= d:?= Fri d:Fri Mon d:Mon Sat d:Sat +Builtin Sun d:Sun Thu d:Thu Tue d:Tue Wed d:Wed adjust-dst d:adjust-dst alarm d:alarm approx! d:approx! +Builtin approx? d:approx? approximates! d:approximates! between d:between cmp d:cmp d. d:d. default-now d:default-now Builtin doy d:doy dst-ofs d:dst-ofs dst? d:dst? dstinfo d:dstinfo dstquery d:dstquery dstzones? d:dstzones? Builtin elapsed-timer d:elapsed-timer elapsed-timer-hmds d:elapsed-timer-hmds elapsed-timer-msec d:elapsed-timer-msec Builtin elapsed-timer-seconds d:elapsed-timer-seconds first-dow d:first-dow fixed> d:fixed> fixed>dow d:fixed>dow Builtin format d:format join d:join last-dow d:last-dow last-month d:last-month last-week d:last-week -Builtin last-year d:last-year msec d:msec msec> d:msec> new d:new next-dow d:next-dow next-month d:next-month -Builtin next-week d:next-week next-year d:next-year parse d:parse parse-approx d:parse-approx parse-range d:parse-range -Builtin prev-dow d:prev-dow rfc5322 d:rfc5322 start-timer d:start-timer ticks d:ticks ticks/sec d:ticks/sec -Builtin timer d:timer timer-ctrl d:timer-ctrl tzadjust d:tzadjust unix> d:unix> unknown d:unknown unknown? d:unknown? -Builtin updatetz d:updatetz year@ d:year@ ymd d:ymd ymd> d:ymd> add-func db:add-func aes! db:aes! again? db:again? +Builtin last-year d:last-year leap? d:leap? mdays d:mdays msec d:msec msec> d:msec> new d:new next-dow d:next-dow +Builtin next-month d:next-month next-week d:next-week next-year d:next-year parse d:parse parse-approx d:parse-approx +Builtin parse-range d:parse-range prev-dow d:prev-dow rfc5322 d:rfc5322 start-timer d:start-timer ticks d:ticks +Builtin ticks/sec d:ticks/sec timer d:timer timer-ctrl d:timer-ctrl tzadjust d:tzadjust unix> d:unix> +Builtin unknown d:unknown unknown? d:unknown? updatetz d:updatetz year@ d:year@ ymd d:ymd ymd> d:ymd> +Builtin MYSQLLIB db:MYSQLLIB ODBCLIB db:ODBCLIB add-func db:add-func aes! db:aes! again? db:again? Builtin begin db:begin bind db:bind bind-exec db:bind-exec bind-exec{} db:bind-exec{} close db:close Builtin col db:col col{} db:col{} commit db:commit db db:db dbpush db:dbpush disuse db:disuse each db:each Builtin err-handler db:err-handler exec db:exec exec-cb db:exec-cb exec-name db:exec-name exec{} db:exec{} Builtin get db:get get-sub db:get-sub key db:key kind? db:kind? last-rowid db:last-rowid mysql? db:mysql? Builtin odbc? db:odbc? open db:open open? db:open? prep-name db:prep-name prepare db:prepare query db:query Builtin query-all db:query-all rekey db:rekey rollback db:rollback set db:set set-sub db:set-sub sql@ db:sql@ -Builtin sql[] db:sql[] sql[np] db:sql[np] sql{np} db:sql{np} sql{} db:sql{} use db:use zip db:zip bp dbg:bp -Builtin bt dbg:bt except-task@ dbg:except-task@ go dbg:go line-info dbg:line-info prompt dbg:prompt -Builtin stop dbg:stop trace dbg:trace trace-enter dbg:trace-enter trace-leave dbg:trace-leave / f:/ -Builtin >posix f:>posix abspath f:abspath absrel f:absrel append f:append associate f:associate atime f:atime -Builtin autodel f:autodel canwrite? f:canwrite? chmod f:chmod close f:close copy f:copy copydir f:copydir -Builtin create f:create ctime f:ctime dir? f:dir? dname f:dname eachbuf f:eachbuf eachline f:eachline -Builtin enssep f:enssep eof? f:eof? exec f:exec exists? f:exists? flush f:flush fname f:fname getb f:getb -Builtin getc f:getc getline f:getline getmod f:getmod glob f:glob glob-links f:glob-links glob-nocase f:glob-nocase +Builtin sql[] db:sql[] sql[np] db:sql[np] sql{np} db:sql{np} sql{} db:sql{} use db:use zip db:zip .state dbg:.state +Builtin bp dbg:bp bt dbg:bt except-task@ dbg:except-task@ go dbg:go prompt dbg:prompt see dbg:see stop dbg:stop +Builtin trace dbg:trace trace-enter dbg:trace-enter trace-leave dbg:trace-leave pso ds:pso / f:/ >posix f:>posix +Builtin abspath f:abspath absrel f:absrel append f:append associate f:associate atime f:atime autodel f:autodel +Builtin canwrite? f:canwrite? chmod f:chmod close f:close copy f:copy copydir f:copydir create f:create +Builtin ctime f:ctime dir? f:dir? dname f:dname eachbuf f:eachbuf eachline f:eachline enssep f:enssep +Builtin eof? f:eof? exec f:exec exists? f:exists? flush f:flush fname f:fname getb f:getb getc f:getc +Builtin getline f:getline getmod f:getmod glob f:glob glob-links f:glob-links glob-nocase f:glob-nocase Builtin gunz f:gunz homedir f:homedir homedir! f:homedir! include f:include ioctl f:ioctl join f:join Builtin launch f:launch link f:link link> f:link> link? f:link? lock f:lock mkdir f:mkdir mmap f:mmap Builtin mmap-range f:mmap-range mmap-range? f:mmap-range? mtime f:mtime mv f:mv name@ f:name@ open f:open @@ -209,9 +214,9 @@ Builtin ungetc f:ungetc unzip f:unzip unzip-entry f:unzip-entry watch f:watch w Builtin zip+ f:zip+ zip@ f:zip@ zipentry f:zipentry zipnew f:zipnew zipopen f:zipopen zipsave f:zipsave Builtin atlas! font:atlas! atlas@ font:atlas@ default-size font:default-size default-size@ font:default-size@ Builtin info font:info ls font:ls measure font:measure new font:new oversample font:oversample pixels font:pixels -Builtin pixels? font:pixels? system font:system system font:system distance geo:distance km/deg-lat geo:km/deg-lat -Builtin km/deg-lon geo:km/deg-lon nearest geo:nearest +edge gr:+edge +edge+w gr:+edge+w +node gr:+node -Builtin connect gr:connect edges gr:edges edges! gr:edges! m! gr:m! m@ gr:m@ neighbors gr:neighbors +Builtin pixels? font:pixels? system font:system system font:system media? g:media? distance geo:distance +Builtin km/deg-lat geo:km/deg-lat km/deg-lon geo:km/deg-lon nearest geo:nearest +edge gr:+edge +edge+w gr:+edge+w +Builtin +node gr:+node connect gr:connect edges gr:edges edges! gr:edges! m! gr:m! m@ gr:m@ neighbors gr:neighbors Builtin new gr:new node-edges gr:node-edges nodes gr:nodes traverse gr:traverse weight! gr:weight! Builtin + h:+ clear h:clear cmp! h:cmp! len h:len max! h:max! new h:new peek h:peek pop h:pop push h:push Builtin unique h:unique parse html:parse arm? hw:arm? camera hw:camera camera-img hw:camera-img camera-limits hw:camera-limits @@ -219,163 +224,171 @@ Builtin camera? hw:camera? cpu? hw:cpu? device? hw:device? displays? hw:display Builtin finger-match hw:finger-match finger-support hw:finger-support gpio hw:gpio gpio! hw:gpio! gpio-mmap hw:gpio-mmap Builtin gpio@ hw:gpio@ i2c hw:i2c i2c! hw:i2c! i2c!reg hw:i2c!reg i2c@ hw:i2c@ i2c@reg hw:i2c@reg isround? hw:isround? Builtin iswatch? hw:iswatch? mac? hw:mac? mem? hw:mem? model? hw:model? poll hw:poll sensor hw:sensor -Builtin start hw:start stop hw:stop uid? hw:uid? fetch-full imap:fetch-full fetch-uid-mail imap:fetch-uid-mail +Builtin start hw:start stop hw:stop touch? hw:touch? uid? hw:uid? fetch-full imap:fetch-full fetch-uid-mail imap:fetch-uid-mail Builtin login imap:login logout imap:logout new imap:new search imap:search select-inbox imap:select-inbox Builtin >file img:>file >fmt img:>fmt copy img:copy crop img:crop data img:data desat img:desat draw img:draw Builtin draw-sub img:draw-sub fill img:fill fillrect img:fillrect filter img:filter flip img:flip from-svg img:from-svg Builtin line img:line new img:new pikchr img:pikchr pix! img:pix! pix@ img:pix@ qr-gen img:qr-gen qr-parse img:qr-parse Builtin rect img:rect rotate img:rotate scale img:scale scroll img:scroll size img:size countries iso:countries -Builtin languages iso:languages utils/help library:utils/help find loc:find sort loc:sort ! m:! !? m:!? -Builtin + m:+ +? m:+? - m:- <> m:<> = m:= >arr m:>arr @ m:@ @? m:@? _! m:_! _@ m:_@ alias m:alias arr> m:arr> -Builtin bitmap m:bitmap clear m:clear data m:data each m:each exists? m:exists? filter m:filter ic m:ic -Builtin iter m:iter iter-all m:iter-all keys m:keys len m:len map m:map merge m:merge new m:new op! m:op! -Builtin open m:open slice m:slice vals m:vals xchg m:xchg zip m:zip ! mat:! * mat:* + mat:+ = mat:= -Builtin @ mat:@ affine mat:affine col mat:col data mat:data det mat:det dim? mat:dim? get-n mat:get-n -Builtin ident mat:ident inv mat:inv m. mat:m. minor mat:minor n* mat:n* new mat:new new-minor mat:new-minor -Builtin rotate mat:rotate row mat:row same-size? mat:same-size? scale mat:scale shear mat:shear trans mat:trans -Builtin translate mat:translate xform mat:xform 2console md:2console 2html md:2html 2nk md:2nk color meta:color -Builtin console meta:console gui meta:gui meta meta:meta ! n:! * n:* */ n:*/ + n:+ +! n:+! - n:- / n:/ -Builtin /mod n:/mod 1+ n:1+ 1- n:1- < n:< = n:= > n:> >bool n:>bool BIGE n:BIGE BIGPI n:BIGPI E n:E -Builtin PI n:PI ^ n:^ _mod n:_mod abs n:abs acos n:acos acos n:acos andor n:andor asin n:asin asin n:asin -Builtin atan n:atan atan n:atan atan2 n:atan2 band n:band between n:between bfloat n:bfloat bic n:bic +Builtin languages iso:languages utils/help library:utils/help bearing loc:bearing find loc:find sort loc:sort +Builtin ! m:! !? m:!? + m:+ +? m:+? - m:- <> m:<> = m:= >arr m:>arr @ m:@ @? m:@? _! m:_! _@ m:_@ _@? m:_@? +Builtin alias m:alias arr> m:arr> bitmap m:bitmap clear m:clear data m:data each m:each exists? m:exists? +Builtin filter m:filter ic m:ic iter m:iter iter-all m:iter-all keys m:keys len m:len map m:map merge m:merge +Builtin new m:new op! m:op! open m:open slice m:slice vals m:vals xchg m:xchg zip m:zip ! mat:! * mat:* +Builtin + mat:+ = mat:= @ mat:@ affine mat:affine col mat:col data mat:data det mat:det dim? mat:dim? +Builtin get-n mat:get-n ident mat:ident inv mat:inv m. mat:m. minor mat:minor n* mat:n* new mat:new +Builtin new-minor mat:new-minor rotate mat:rotate row mat:row same-size? mat:same-size? scale mat:scale +Builtin shear mat:shear trans mat:trans translate mat:translate xform mat:xform 2console md:2console +Builtin 2html md:2html 2nk md:2nk color meta:color console meta:console gui meta:gui meta meta:meta +Builtin ! n:! * n:* */ n:*/ + n:+ +! n:+! - n:- / n:/ /mod n:/mod 1+ n:1+ 1- n:1- < n:< = n:= > n:> +Builtin >bool n:>bool BIGE n:BIGE BIGPI n:BIGPI E n:E PI n:PI ^ n:^ _mod n:_mod abs n:abs acos n:acos +Builtin acosd n:acosd acosh n:acosh andor n:andor asin n:asin asind n:asind asinh n:asinh atan n:atan +Builtin atan2 n:atan2 atand n:atand atanh n:atanh band n:band between n:between bfloat n:bfloat bic n:bic Builtin bint n:bint binv n:binv bnot n:bnot bor n:bor bxor n:bxor cast n:cast ceil n:ceil clamp n:clamp -Builtin cmp n:cmp comb n:comb cos n:cos cosd n:cosd emod n:emod exp n:exp expm1 n:expm1 expmod n:expmod -Builtin float n:float floor n:floor fmod n:fmod frac n:frac gcd n:gcd int n:int invmod n:invmod kind? n:kind? -Builtin lcm n:lcm lerp n:lerp ln n:ln ln1p n:ln1p lnerp n:lnerp max n:max median n:median min n:min -Builtin mod n:mod neg n:neg odd? n:odd? perm n:perm prime? n:prime? quantize n:quantize quantize! n:quantize! -Builtin r+ n:r+ range n:range rot32l n:rot32l rot32r n:rot32r round n:round round2 n:round2 rounding n:rounding -Builtin running-variance n:running-variance running-variance-finalize n:running-variance-finalize sgn n:sgn -Builtin shl n:shl shr n:shr sin n:sin sind n:sind sqr n:sqr sqrt n:sqrt tan n:tan tand n:tand trunc n:trunc -Builtin ~= n:~= ! net:! !? net:!? - net:- >base64url net:>base64url >url net:>url @ net:@ @? net:@? -Builtin CGI net:CGI DGRAM net:DGRAM INET4 net:INET4 INET6 net:INET6 PROTO_TCP net:PROTO_TCP PROTO_UDP net:PROTO_UDP -Builtin REMOTE_IP net:REMOTE_IP STREAM net:STREAM accept net:accept active? net:active? addrinfo>o net:addrinfo>o -Builtin again? net:again? alloc-and-read net:alloc-and-read alloc-buf net:alloc-buf base64url> net:base64url> -Builtin bind net:bind cgi-get net:cgi-get cgi-http-header net:cgi-http-header cgi-init net:cgi-init -Builtin cgi-init-stunnel net:cgi-init-stunnel cgi-out net:cgi-out close net:close closed? net:closed? -Builtin connect net:connect curnet net:curnet debug? net:debug? delete net:delete get net:get getaddrinfo net:getaddrinfo -Builtin getpeername net:getpeername head net:head ifaces? net:ifaces? ipv6? net:ipv6? listen net:listen -Builtin map>url net:map>url mime-type net:mime-type net-socket net:net-socket opts net:opts port-is-ssl? net:port-is-ssl? +Builtin cmp n:cmp comb n:comb cos n:cos cosd n:cosd cosh n:cosh emod n:emod erf n:erf erfc n:erfc exp n:exp +Builtin expm1 n:expm1 expmod n:expmod float n:float floor n:floor fmod n:fmod frac n:frac gcd n:gcd +Builtin int n:int invmod n:invmod kind? n:kind? lcm n:lcm lerp n:lerp ln n:ln ln1p n:ln1p lnerp n:lnerp +Builtin logistic n:logistic max n:max median n:median min n:min mod n:mod neg n:neg odd? n:odd? perm n:perm +Builtin prime? n:prime? quantize n:quantize quantize! n:quantize! r+ n:r+ range n:range rot32l n:rot32l +Builtin rot32r n:rot32r round n:round round2 n:round2 rounding n:rounding running-variance n:running-variance +Builtin running-variance-finalize n:running-variance-finalize sgn n:sgn shl n:shl shr n:shr sin n:sin +Builtin sincos n:sincos sind n:sind sinh n:sinh sqr n:sqr sqrt n:sqrt tan n:tan tand n:tand tanh n:tanh +Builtin trunc n:trunc ~= n:~= ! net:! !? net:!? - net:- >base64url net:>base64url >url net:>url @ net:@ +Builtin @? net:@? CGI net:CGI DGRAM net:DGRAM INET4 net:INET4 INET6 net:INET6 PROTO_TCP net:PROTO_TCP +Builtin PROTO_UDP net:PROTO_UDP REMOTE_IP net:REMOTE_IP REMOTE_IP net:REMOTE_IP STREAM net:STREAM accept net:accept +Builtin active? net:active? addrinfo>o net:addrinfo>o again? net:again? alloc-and-read net:alloc-and-read +Builtin alloc-buf net:alloc-buf avail? net:avail? base64url> net:base64url> bind net:bind cgi-get net:cgi-get +Builtin cgi-http-header net:cgi-http-header cgi-init net:cgi-init cgi-init-stunnel net:cgi-init-stunnel +Builtin cgi-out net:cgi-out close net:close closed? net:closed? connect net:connect curnet net:curnet +Builtin debug? net:debug? delete net:delete dns net:dns get net:get getaddrinfo net:getaddrinfo getpeername net:getpeername +Builtin head net:head ifaces? net:ifaces? ipv6? net:ipv6? launch net:launch listen net:listen map>url net:map>url +Builtin mime-type net:mime-type net-socket net:net-socket opts net:opts port-is-ssl? net:port-is-ssl? Builtin post net:post proxy! net:proxy! put net:put read net:read read-all net:read-all read-buf net:read-buf Builtin recvfrom net:recvfrom s>url net:s>url sendto net:sendto server net:server setsockopt net:setsockopt Builtin socket net:socket tcp-connect net:tcp-connect tlserr net:tlserr tlshello net:tlshello udp-connect net:udp-connect -Builtin url> net:url> user-agent net:user-agent vpncheck net:vpncheck wait net:wait webserver net:webserver -Builtin write net:write (begin) nk:(begin) (chart-begin) nk:(chart-begin) (chart-begin-colored) nk:(chart-begin-colored) -Builtin (chart-end) nk:(chart-end) (end) nk:(end) (group-begin) nk:(group-begin) (group-end) nk:(group-end) -Builtin (property) nk:(property) >img nk:>img addfont nk:addfont anti-alias nk:anti-alias any-clicked? nk:any-clicked? -Builtin bounds nk:bounds bounds! nk:bounds! button nk:button button-color nk:button-color button-label nk:button-label -Builtin button-set-behavior nk:button-set-behavior button-symbol nk:button-symbol button-symbol-label nk:button-symbol-label -Builtin center-rect nk:center-rect chart-add-slot nk:chart-add-slot chart-add-slot-colored nk:chart-add-slot-colored -Builtin chart-push nk:chart-push chart-push-slot nk:chart-push-slot checkbox nk:checkbox circle nk:circle -Builtin clicked? nk:clicked? close-this! nk:close-this! close-this? nk:close-this? close? nk:close? -Builtin color-picker nk:color-picker combo nk:combo combo-begin-color nk:combo-begin-color combo-begin-label nk:combo-begin-label -Builtin combo-cb nk:combo-cb combo-end nk:combo-end contextual-begin nk:contextual-begin contextual-close nk:contextual-close +Builtin url> net:url> user-agent net:user-agent valid-email? net:valid-email? vpncheck net:vpncheck +Builtin wait net:wait webserver net:webserver write net:write (begin) nk:(begin) (chart-begin) nk:(chart-begin) +Builtin (chart-begin-colored) nk:(chart-begin-colored) (chart-end) nk:(chart-end) (end) nk:(end) (group-begin) nk:(group-begin) +Builtin (group-end) nk:(group-end) (property) nk:(property) >img nk:>img GLLIBS nk:GLLIBS GLXLIBS nk:GLXLIBS +Builtin addfont nk:addfont anti-alias nk:anti-alias any-clicked? nk:any-clicked? bounds nk:bounds bounds! nk:bounds! +Builtin button nk:button button-color nk:button-color button-label nk:button-label button-set-behavior nk:button-set-behavior +Builtin button-symbol nk:button-symbol button-symbol-label nk:button-symbol-label chart-add-slot nk:chart-add-slot +Builtin chart-add-slot-colored nk:chart-add-slot-colored chart-push nk:chart-push chart-push-slot nk:chart-push-slot +Builtin checkbox nk:checkbox circle nk:circle clicked? nk:clicked? close-this! nk:close-this! close-this? nk:close-this? +Builtin close? nk:close? color-chooser nk:color-chooser color-picker nk:color-picker combo nk:combo +Builtin combo-begin-color nk:combo-begin-color combo-begin-label nk:combo-begin-label combo-cb nk:combo-cb +Builtin combo-end nk:combo-end contextual-begin nk:contextual-begin contextual-close nk:contextual-close Builtin contextual-end nk:contextual-end contextual-item-image-text nk:contextual-item-image-text contextual-item-symbol-text nk:contextual-item-symbol-text Builtin contextual-item-text nk:contextual-item-text cp! nk:cp! cp@ nk:cp@ curpos nk:curpos cursor-load nk:cursor-load Builtin cursor-set nk:cursor-set cursor-show nk:cursor-show display-info nk:display-info display@ nk:display@ Builtin do nk:do down? nk:down? draw-image nk:draw-image draw-image-at nk:draw-image-at draw-image-centered nk:draw-image-centered Builtin draw-sub-image nk:draw-sub-image draw-text nk:draw-text draw-text-centered nk:draw-text-centered -Builtin draw-text-high nk:draw-text-high draw-text-wrap nk:draw-text-wrap drivers nk:drivers edit-focus nk:edit-focus -Builtin edit-string nk:edit-string event nk:event event-boost nk:event-boost event-msec nk:event-msec -Builtin event-wait nk:event-wait event? nk:event? fill-arc nk:fill-arc fill-circle nk:fill-circle fill-color nk:fill-color -Builtin fill-poly nk:fill-poly fill-rect nk:fill-rect fill-rect-color nk:fill-rect-color fill-triangle nk:fill-triangle -Builtin finger nk:finger flags! nk:flags! flags@ nk:flags@ flash nk:flash fullscreen nk:fullscreen -Builtin gesture nk:gesture get nk:get get-row-height nk:get-row-height getfont nk:getfont getmap nk:getmap -Builtin getmap! nk:getmap! gl? nk:gl? grid nk:grid grid-push nk:grid-push group-scroll-ofs nk:group-scroll-ofs -Builtin group-scroll-ofs! nk:group-scroll-ofs! hovered? nk:hovered? hrule nk:hrule image nk:image init nk:init -Builtin input-button nk:input-button input-key nk:input-key input-motion nk:input-motion input-scroll nk:input-scroll -Builtin input-string nk:input-string key-down? nk:key-down? key-pressed? nk:key-pressed? key-released? nk:key-released? -Builtin label nk:label label-colored nk:label-colored label-wrap nk:label-wrap label-wrap-colored nk:label-wrap-colored -Builtin layout-bounds nk:layout-bounds layout-grid-begin nk:layout-grid-begin layout-grid-end nk:layout-grid-end -Builtin layout-push-dynamic nk:layout-push-dynamic layout-push-static nk:layout-push-static layout-push-variable nk:layout-push-variable -Builtin layout-ratio-from-pixel nk:layout-ratio-from-pixel layout-reset-row-height nk:layout-reset-row-height -Builtin layout-row nk:layout-row layout-row-begin nk:layout-row-begin layout-row-dynamic nk:layout-row-dynamic -Builtin layout-row-end nk:layout-row-end layout-row-height nk:layout-row-height layout-row-push nk:layout-row-push -Builtin layout-row-static nk:layout-row-static layout-row-template-begin nk:layout-row-template-begin +Builtin draw-text-high nk:draw-text-high draw-text-wrap nk:draw-text-wrap driver nk:driver drivers nk:drivers +Builtin dropped nk:dropped dropping nk:dropping edit-focus nk:edit-focus edit-string nk:edit-string +Builtin event nk:event event-boost nk:event-boost event-msec nk:event-msec event-wait nk:event-wait +Builtin event? nk:event? fill-arc nk:fill-arc fill-circle nk:fill-circle fill-color nk:fill-color fill-poly nk:fill-poly +Builtin fill-rect nk:fill-rect fill-rect-color nk:fill-rect-color fill-triangle nk:fill-triangle finger nk:finger +Builtin flags! nk:flags! flags@ nk:flags@ flash nk:flash fullscreen nk:fullscreen gesture nk:gesture +Builtin get nk:get get-row-height nk:get-row-height getfont nk:getfont getmap nk:getmap getmap! nk:getmap! +Builtin gl? nk:gl? grid nk:grid grid-peek nk:grid-peek grid-push nk:grid-push group-scroll-ofs nk:group-scroll-ofs +Builtin group-scroll-ofs! nk:group-scroll-ofs! hints nk:hints hovered? nk:hovered? hrule nk:hrule image nk:image +Builtin init nk:init input-button nk:input-button input-key nk:input-key input-motion nk:input-motion +Builtin input-scroll nk:input-scroll input-string nk:input-string key-down? nk:key-down? key-pressed? nk:key-pressed? +Builtin key-released? nk:key-released? knob nk:knob label nk:label label-colored nk:label-colored label-wrap nk:label-wrap +Builtin label-wrap-colored nk:label-wrap-colored layout-bounds nk:layout-bounds layout-grid-begin nk:layout-grid-begin +Builtin layout-grid-end nk:layout-grid-end layout-push-dynamic nk:layout-push-dynamic layout-push-static nk:layout-push-static +Builtin layout-push-variable nk:layout-push-variable layout-ratio-from-pixel nk:layout-ratio-from-pixel +Builtin layout-reset-row-height nk:layout-reset-row-height layout-row nk:layout-row layout-row-begin nk:layout-row-begin +Builtin layout-row-dynamic nk:layout-row-dynamic layout-row-end nk:layout-row-end layout-row-height nk:layout-row-height +Builtin layout-row-push nk:layout-row-push layout-row-static nk:layout-row-static layout-row-template-begin nk:layout-row-template-begin Builtin layout-row-template-end nk:layout-row-template-end layout-space-begin nk:layout-space-begin Builtin layout-space-end nk:layout-space-end layout-space-push nk:layout-space-push layout-widget-bounds nk:layout-widget-bounds Builtin line-rel nk:line-rel line-to nk:line-to list-begin nk:list-begin list-end nk:list-end list-new nk:list-new -Builtin list-range nk:list-range m! nk:m! m@ nk:m@ make-style nk:make-style max-vertex-element nk:max-vertex-element +Builtin list-ofs nk:list-ofs list-range nk:list-range m! nk:m! m@ nk:m@ make-style nk:make-style max-vertex-element nk:max-vertex-element Builtin maximize nk:maximize measure nk:measure measure-font nk:measure-font menu-begin nk:menu-begin Builtin menu-close nk:menu-close menu-end nk:menu-end menu-item-image nk:menu-item-image menu-item-label nk:menu-item-label Builtin menu-item-symbol nk:menu-item-symbol menubar-begin nk:menubar-begin menubar-end nk:menubar-end Builtin minimize nk:minimize mouse-pos nk:mouse-pos move-back nk:move-back move-rel nk:move-rel move-to nk:move-to Builtin msg nk:msg msgdlg nk:msgdlg ontop nk:ontop option nk:option pen-color nk:pen-color pen-width nk:pen-width -Builtin plot nk:plot plot-fn nk:plot-fn pop-font nk:pop-font popup-begin nk:popup-begin popup-close nk:popup-close -Builtin popup-end nk:popup-end popup-scroll-ofs nk:popup-scroll-ofs popup-scroll-ofs! nk:popup-scroll-ofs! -Builtin progress nk:progress prop-int nk:prop-int pt-in? nk:pt-in? pt-open nk:pt-open pt>local nk:pt>local -Builtin pt>rect nk:pt>rect pt>screen nk:pt>screen pt>x nk:pt>x pts>rect nk:pts>rect push-font nk:push-font -Builtin raise nk:raise rect! nk:rect! rect-center nk:rect-center rect-intersect nk:rect-intersect rect-ofs nk:rect-ofs -Builtin rect-open nk:rect-open rect-pad nk:rect-pad rect-rel nk:rect-rel rect-shrink nk:rect-shrink -Builtin rect-to nk:rect-to rect-union nk:rect-union rect/high nk:rect/high rect/wide nk:rect/wide rect= nk:rect= -Builtin rect>local nk:rect>local rect>pos nk:rect>pos rect>pts nk:rect>pts rect>pts4 nk:rect>pts4 rect>screen nk:rect>screen -Builtin rect>size nk:rect>size rect>x nk:rect>x rect@ nk:rect@ released? nk:released? render nk:render -Builtin render-timed nk:render-timed restore nk:restore rotate nk:rotate rotate-rel nk:rotate-rel save nk:save -Builtin scale nk:scale scancode? nk:scancode? screen-saver nk:screen-saver screen-size nk:screen-size -Builtin screen-win-close nk:screen-win-close selectable nk:selectable set nk:set set-font nk:set-font -Builtin set-num-vertices nk:set-num-vertices set-radius nk:set-radius setpos nk:setpos setwin nk:setwin -Builtin show nk:show slider nk:slider slider-int nk:slider-int space nk:space spacing nk:spacing stroke-arc nk:stroke-arc -Builtin stroke-circle nk:stroke-circle stroke-curve nk:stroke-curve stroke-line nk:stroke-line stroke-polygon nk:stroke-polygon -Builtin stroke-polyline nk:stroke-polyline stroke-rect nk:stroke-rect stroke-tri nk:stroke-tri style-from-table nk:style-from-table -Builtin swipe nk:swipe swipe-dir-threshold nk:swipe-dir-threshold swipe-threshold nk:swipe-threshold -Builtin text nk:text text-align nk:text-align text-font nk:text-font text-pad nk:text-pad text? nk:text? -Builtin timer-delay nk:timer-delay timer? nk:timer? tooltip nk:tooltip translate nk:translate tree-pop nk:tree-pop -Builtin tree-state-push nk:tree-state-push use-style nk:use-style vsync nk:vsync widget nk:widget widget-bounds nk:widget-bounds +Builtin pix! nk:pix! plot nk:plot plot-fn nk:plot-fn polygon nk:polygon pop-font nk:pop-font popup-begin nk:popup-begin +Builtin popup-close nk:popup-close popup-end nk:popup-end popup-scroll-ofs nk:popup-scroll-ofs popup-scroll-ofs! nk:popup-scroll-ofs! +Builtin progress nk:progress prop-int nk:prop-int pt-in? nk:pt-in? pt>local nk:pt>local pt>screen nk:pt>screen +Builtin push-font nk:push-font raise nk:raise rect-rel nk:rect-rel rect-to nk:rect-to rect>local nk:rect>local +Builtin rect>screen nk:rect>screen released? nk:released? render nk:render render-timed nk:render-timed +Builtin rendering nk:rendering restore nk:restore rotate nk:rotate rotate-rel nk:rotate-rel rtl! nk:rtl! +Builtin rtl? nk:rtl? save nk:save scale nk:scale scancode? nk:scancode? screen-saver nk:screen-saver +Builtin screen-size nk:screen-size screen-win-close nk:screen-win-close selectable nk:selectable set nk:set +Builtin set-font nk:set-font set-num-vertices nk:set-num-vertices set-radius nk:set-radius setpos nk:setpos +Builtin setwin nk:setwin show nk:show slider nk:slider slider-int nk:slider-int space nk:space spacing nk:spacing +Builtin stroke-arc nk:stroke-arc stroke-circle nk:stroke-circle stroke-curve nk:stroke-curve stroke-line nk:stroke-line +Builtin stroke-polygon nk:stroke-polygon stroke-polyline nk:stroke-polyline stroke-rect nk:stroke-rect +Builtin stroke-tri nk:stroke-tri style-from-table nk:style-from-table swipe nk:swipe swipe-dir-threshold nk:swipe-dir-threshold +Builtin swipe-threshold nk:swipe-threshold text nk:text text-align nk:text-align text-font nk:text-font +Builtin text-pad nk:text-pad text? nk:text? timer-delay nk:timer-delay timer? nk:timer? toast nk:toast +Builtin tooltip nk:tooltip translate nk:translate tree-pop nk:tree-pop tree-state-push nk:tree-state-push +Builtin triangle nk:triangle use-style nk:use-style vsync nk:vsync widget nk:widget widget-bounds nk:widget-bounds Builtin widget-disable nk:widget-disable widget-fitting nk:widget-fitting widget-high nk:widget-high Builtin widget-hovered? nk:widget-hovered? widget-mouse-click-down? nk:widget-mouse-click-down? widget-mouse-clicked? nk:widget-mouse-clicked? -Builtin widget-pos nk:widget-pos widget-size nk:widget-size widget-size nk:widget-size widget-wide nk:widget-wide -Builtin win nk:win win-bounds nk:win-bounds win-bounds! nk:win-bounds! win-close nk:win-close win-closed? nk:win-closed? -Builtin win-collapse nk:win-collapse win-collapsed? nk:win-collapsed? win-content-bounds nk:win-content-bounds +Builtin widget-pos nk:widget-pos widget-size nk:widget-size widget-size-allot nk:widget-size-allot +Builtin widget-wide nk:widget-wide win nk:win win-bounds nk:win-bounds win-bounds! nk:win-bounds! win-close nk:win-close +Builtin win-closed? nk:win-closed? win-collapse nk:win-collapse win-collapsed? nk:win-collapsed? win-content-bounds nk:win-content-bounds Builtin win-focus nk:win-focus win-focused? nk:win-focused? win-hidden? nk:win-hidden? win-high nk:win-high -Builtin win-hovered? nk:win-hovered? win-pos nk:win-pos win-scroll-ofs nk:win-scroll-ofs win-scroll-ofs! nk:win-scroll-ofs! -Builtin win-show nk:win-show win-size nk:win-size win-wide nk:win-wide win? nk:win? x>pt nk:x>pt x>rect nk:x>rect -Builtin MAX ns:MAX ! o:! + o:+ +? o:+? ??? o:??? @ o:@ class o:class exec o:exec isa o:isa method o:method -Builtin mutate o:mutate new o:new super o:super chroot os:chroot devname os:devname docker? os:docker? -Builtin env os:env lang os:lang locales os:locales notify os:notify power-state os:power-state region os:region -Builtin waitpid os:waitpid bezier pdf:bezier bezierq pdf:bezierq circle pdf:circle color pdf:color -Builtin ellipse pdf:ellipse font pdf:font img pdf:img line pdf:line new pdf:new page pdf:page page-size pdf:page-size -Builtin rect pdf:rect save pdf:save size pdf:size text pdf:text text-rotate pdf:text-rotate text-size pdf:text-size -Builtin text-width pdf:text-width text-wrap pdf:text-wrap text-wrap-rotate pdf:text-wrap-rotate cast ptr:cast +Builtin win-hovered? nk:win-hovered? win-icon! nk:win-icon! win-pos nk:win-pos win-scroll-ofs nk:win-scroll-ofs +Builtin win-scroll-ofs! nk:win-scroll-ofs! win-show nk:win-show win-size nk:win-size win-title! nk:win-title! +Builtin win-wide nk:win-wide win? nk:win? MAX ns:MAX ! o:! + o:+ +? o:+? ??? o:??? @ o:@ class o:class +Builtin exec o:exec isa o:isa method o:method mutate o:mutate new o:new super o:super POSIX os:POSIX +Builtin chroot os:chroot devname os:devname docker? os:docker? env os:env lang os:lang locales os:locales +Builtin notify os:notify power-state os:power-state region os:region waitpid os:waitpid bezier pdf:bezier +Builtin bezierq pdf:bezierq circle pdf:circle color pdf:color ellipse pdf:ellipse font pdf:font img pdf:img +Builtin line pdf:line new pdf:new page pdf:page page-size pdf:page-size rect pdf:rect save pdf:save +Builtin size pdf:size text pdf:text text-rotate pdf:text-rotate text-size pdf:text-size text-width pdf:text-width +Builtin text-wrap pdf:text-wrap text-wrap-rotate pdf:text-wrap-rotate cast ptr:cast deref ptr:deref Builtin len ptr:len null? ptr:null? pack ptr:pack unpack ptr:unpack unpack_orig ptr:unpack_orig publish pubsub:publish Builtin qsize pubsub:qsize subscribe pubsub:subscribe + q:+ clear q:clear len q:len new q:new notify q:notify Builtin overwrite q:overwrite peek q:peek pick q:pick pop q:pop push q:push remove q:remove shift q:shift Builtin size q:size slide q:slide throwing q:throwing wait q:wait ++match r:++match +/ r:+/ +match r:+match -Builtin / r:/ @ r:@ len r:len match r:match new r:new rx r:rx str r:str * rat:* + rat:+ - rat:- / rat:/ -Builtin >n rat:>n >s rat:>s new rat:new proper rat:proper ! s:! * s:* + s:+ - s:- / s:/ /scripts s:/scripts -Builtin <+ s:<+ <> s:<> = s:= =ic s:=ic >base64 s:>base64 >ucs2 s:>ucs2 @ s:@ append s:append base64> s:base64> -Builtin clear s:clear cmp s:cmp cmpi s:cmpi compress s:compress count-match s:count-match days! s:days! -Builtin dist s:dist each s:each each! s:each! eachline s:eachline escape s:escape expand s:expand fill s:fill -Builtin fold s:fold globmatch s:globmatch hexupr s:hexupr insert s:insert intl s:intl intl! s:intl! -Builtin lang s:lang lc s:lc lc? s:lc? len s:len lsub s:lsub ltrim s:ltrim map s:map months! s:months! -Builtin n> s:n> new s:new norm s:norm reduce s:reduce repinsert s:repinsert replace s:replace replace! s:replace! -Builtin rev s:rev rsearch s:rsearch rsub s:rsub rtrim s:rtrim scan-match s:scan-match script? s:script? -Builtin search s:search size s:size slice s:slice soundex s:soundex strfmap s:strfmap strfmt s:strfmt -Builtin term s:term text-wrap s:text-wrap tr s:tr translate s:translate trim s:trim tsub s:tsub uc s:uc -Builtin uc? s:uc? ucs2> s:ucs2> utf8? s:utf8? zt s:zt close sio:close enum sio:enum open sio:open opts! sio:opts! -Builtin opts@ sio:opts@ read sio:read write sio:write @ slv:@ auto slv:auto build slv:build constraint slv:constraint -Builtin dump slv:dump edit slv:edit named-variable slv:named-variable new slv:new relation slv:relation -Builtin reset slv:reset suggest slv:suggest term slv:term update slv:update v[] slv:v[] variable slv:variable -Builtin v{} slv:v{} new smtp:new send smtp:send apply-filter snd:apply-filter devices? snd:devices? -Builtin end-record snd:end-record filter snd:filter freq snd:freq gain snd:gain gain? snd:gain? init snd:init -Builtin len snd:len loop snd:loop loop? snd:loop? mix snd:mix new snd:new pause snd:pause play snd:play -Builtin played snd:played rate snd:rate ready? snd:ready? record snd:record resume snd:resume seek snd:seek -Builtin stop snd:stop stopall snd:stopall volume snd:volume volume? snd:volume? + st:+ . st:. clear st:clear -Builtin len st:len ndrop st:ndrop new st:new op! st:op! peek st:peek pick st:pick pop st:pop push st:push -Builtin roll st:roll shift st:shift size st:size slide st:slide swap st:swap throwing st:throwing >buf struct:>buf -Builtin arr> struct:arr> buf struct:buf buf> struct:buf> byte struct:byte double struct:double field! struct:field! +Builtin / r:/ @ r:@ len r:len match r:match match[] r:match[] matchall[] r:matchall[] new r:new rx r:rx +Builtin str r:str * rat:* + rat:+ - rat:- / rat:/ >n rat:>n >s rat:>s new rat:new proper rat:proper +Builtin ! rect:! /high rect:/high /wide rect:/wide = rect:= >a rect:>a >pts rect:>pts >pts4 rect:>pts4 +Builtin @ rect:@ center rect:center center-pt rect:center-pt intersect rect:intersect new rect:new +Builtin new-pt rect:new-pt ofs rect:ofs open rect:open pad rect:pad pos rect:pos pt-open rect:pt-open +Builtin pt>a rect:pt>a pt>rect rect:pt>rect pts> rect:pts> restrict rect:restrict shrink rect:shrink +Builtin size rect:size union rect:union ! s:! * s:* + s:+ - s:- / s:/ /scripts s:/scripts /ws s:/ws +Builtin 2len s:2len <+ s:<+ <> s:<> = s:= =ic s:=ic >base64 s:>base64 >ucs2 s:>ucs2 @ s:@ _len s:_len +Builtin append s:append base64> s:base64> clear s:clear cmp s:cmp cmpi s:cmpi compress s:compress count-match s:count-match +Builtin days! s:days! dist s:dist each s:each each! s:each! eachline s:eachline escape s:escape expand s:expand +Builtin fill s:fill fold s:fold gen-uid s:gen-uid globmatch s:globmatch hexupr s:hexupr insert s:insert +Builtin intl s:intl intl! s:intl! lang s:lang lc s:lc lc? s:lc? len s:len lsub s:lsub ltrim s:ltrim +Builtin map s:map months! s:months! n> s:n> new s:new norm s:norm reduce s:reduce repinsert s:repinsert +Builtin replace s:replace replace! s:replace! rev s:rev rsearch s:rsearch rsub s:rsub rtl s:rtl rtrim s:rtrim +Builtin scan-match s:scan-match script? s:script? search s:search size s:size slice s:slice soundex s:soundex +Builtin strfmap s:strfmap strfmt s:strfmt term s:term text-wrap s:text-wrap tr s:tr translate s:translate +Builtin trim s:trim tsub s:tsub uc s:uc uc? s:uc? ucs2> s:ucs2> utf8? s:utf8? zt s:zt close sio:close +Builtin enum sio:enum open sio:open opts! sio:opts! opts@ sio:opts@ read sio:read write sio:write @ slv:@ +Builtin auto slv:auto build slv:build constraint slv:constraint dump slv:dump edit slv:edit named-variable slv:named-variable +Builtin new slv:new relation slv:relation reset slv:reset suggest slv:suggest term slv:term update slv:update +Builtin v[] slv:v[] variable slv:variable v{} slv:v{} new smtp:new send smtp:send apply-filter snd:apply-filter +Builtin devices? snd:devices? end-record snd:end-record filter snd:filter freq snd:freq gain snd:gain +Builtin gain? snd:gain? init snd:init len snd:len loop snd:loop loop? snd:loop? mix snd:mix new snd:new +Builtin pause snd:pause play snd:play played snd:played rate snd:rate ready? snd:ready? record snd:record +Builtin resume snd:resume seek snd:seek stop snd:stop stopall snd:stopall volume snd:volume volume? snd:volume? +Builtin + st:+ . st:. clear st:clear dot-depth st:dot-depth len st:len list st:list ndrop st:ndrop +Builtin new st:new op! st:op! peek st:peek pick st:pick pop st:pop push st:push roll st:roll shift st:shift +Builtin size st:size slide st:slide swap st:swap throwing st:throwing >buf struct:>buf arr> struct:arr> +Builtin buf struct:buf buf> struct:buf> byte struct:byte double struct:double field! struct:field! Builtin field@ struct:field@ float struct:float ignore struct:ignore int struct:int long struct:long -Builtin struct; struct:struct; word struct:word ! t:! @ t:@ by-name t:by-name cor t:cor cor-drop t:cor-drop -Builtin curtask t:curtask def-queue t:def-queue def-stack t:def-stack done? t:done? dtor t:dtor err! t:err! -Builtin err? t:err? errno? t:errno? extra t:extra getq t:getq handler t:handler handler@ t:handler@ -Builtin kill t:kill list t:list main t:main max-exceptions t:max-exceptions name! t:name! name@ t:name@ -Builtin notify t:notify parent t:parent pop t:pop priority t:priority push t:push push! t:push! q-notify t:q-notify -Builtin q-wait t:q-wait qlen t:qlen result t:result set-affinity t:set-affinity setq t:setq start t:start -Builtin task t:task task-n t:task-n task-stop t:task-stop ticks t:ticks wait t:wait yield t:yield yield! t:yield! -Builtin add tree:add binary tree:binary bk tree:bk btree tree:btree cmp! tree:cmp! data tree:data del tree:del -Builtin find tree:find iter tree:iter next tree:next nodes tree:nodes parent tree:parent parse tree:parse -Builtin prev tree:prev root tree:root search tree:search trie tree:trie ! w:! (is) w:(is) @ w:@ alias: w:alias: -Builtin cb w:cb deprecate w:deprecate dlcall w:dlcall dlopen w:dlopen dlsym w:dlsym exec w:exec exec? w:exec? -Builtin ffifail w:ffifail find w:find forget w:forget is w:is name w:name undo w:undo close ws:close -Builtin decode ws:decode encode ws:encode encode-nomask ws:encode-nomask gen-accept-header ws:gen-accept-header +Builtin struct; struct:struct; word struct:word ! t:! @ t:@ by-name t:by-name curtask t:curtask def-queue t:def-queue +Builtin def-stack t:def-stack done? t:done? dtor t:dtor err! t:err! err? t:err? errno? t:errno? extra t:extra +Builtin getq t:getq handler t:handler handler@ t:handler@ kill t:kill list t:list main t:main max-exceptions t:max-exceptions +Builtin name! t:name! name@ t:name@ notify t:notify parent t:parent pop t:pop priority t:priority push t:push +Builtin push! t:push! q-notify t:q-notify q-wait t:q-wait qlen t:qlen result t:result set-affinity t:set-affinity +Builtin setq t:setq task t:task task-n t:task-n task-stop t:task-stop ticks t:ticks wait t:wait add tree:add +Builtin binary tree:binary bk tree:bk btree tree:btree cmp! tree:cmp! data tree:data del tree:del find tree:find +Builtin iter tree:iter next tree:next nodes tree:nodes parent tree:parent parse tree:parse prev tree:prev +Builtin root tree:root search tree:search trie tree:trie ! w:! (is) w:(is) @ w:@ alias: w:alias: cb w:cb +Builtin deprecate w:deprecate dlcall w:dlcall dlopen w:dlopen dlsym w:dlsym exec w:exec exec? w:exec? +Builtin ffifail w:ffifail find w:find forget w:forget is w:is name w:name undo w:undo xt w:xt xt> w:xt> +Builtin close ws:close decode ws:decode encode ws:encode encode-nomask ws:encode-nomask gen-accept-header ws:gen-accept-header Builtin gen-accept-key ws:gen-accept-key opcodes ws:opcodes open ws:open >s xml:>s >txt xml:>txt md-init xml:md-init Builtin md-parse xml:md-parse parse xml:parse parse-html xml:parse-html parse-stream xml:parse-stream Builtin getmsg[] zmq:getmsg[] sendmsg[] zmq:sendmsg[] @@ -413,8 +426,9 @@ syn match eighthBuiltin /db:bind-exec\[]/ syn match eighthBuiltin /db:exec\[]/ syn match eighthBuiltin /db:col\[]/ -" TODO -syn region eighthComment start="\zs\\" end="$" contains=eighthTodo +syn region eighthComment start="\zs\\" end="$" contains=eighthTodo,@Spell +syn region eighthComment start="\zs--\s" end="$" contains=eighthTodo,@Spell +syn region eighthComment start="\zs(\*\_[:space:]" end="\_[:space:]\*)\ze" contains=eightTodo,@Spell " The default methods for highlighting. Can be overriden later. hi def link eighthTodo Todo @@ -452,6 +466,7 @@ hi def link jsonArray Special hi def link jsonNull Function hi def link jsonBool Boolean +delcommand Builtin let b:current_syntax = "8th" let &cpo = s:cpo_save unlet s:cpo_save diff --git a/runtime/syntax/awk.vim b/runtime/syntax/awk.vim index 3082c1cb5c..4e7c0d1e72 100644 --- a/runtime/syntax/awk.vim +++ b/runtime/syntax/awk.vim @@ -2,7 +2,7 @@ " Language: awk, nawk, gawk, mawk " Maintainer: Doug Kearns <dougkearns@gmail.com> " Previous Maintainer: Antonio Colombo <azc100@gmail.com> -" Last Change: 2020 Aug 18 +" Last Change: 2024 Oct 28 " AWK ref. is: Alfred V. Aho, Brian W. Kernighan, Peter J. Weinberger " The AWK Programming Language, Addison-Wesley, 1988 @@ -92,7 +92,7 @@ syn match awkSpecialCharacter display contained "\\x[0-9A-Fa-f]\+" syn match awkFieldVars "\$\d\+" " catch errors caused by wrong parenthesis -syn region awkParen transparent start="(" end=")" contains=ALLBUT,awkParenError,awkSpecialCharacter,awkArrayElement,awkArrayArray,awkTodo,awkRegExp,awkBrktRegExp,awkBrackets,awkCharClass,awkComment +syn region awkParen transparent start="(" end=")" contains=ALLBUT,awkParenError,awkSpecialCharacter,awkArrayElement,awkArrayArray,awkTodo,awkRegExp,awkBrktRegExp,awkBrackets,awkCharClass syn match awkParenError display ")" "syn match awkInParen display contained "[{}]" diff --git a/runtime/syntax/cfg.vim b/runtime/syntax/cfg.vim index f347b1379f..4b5ebf5c25 100644 --- a/runtime/syntax/cfg.vim +++ b/runtime/syntax/cfg.vim @@ -2,6 +2,7 @@ " Language: Good old CFG files " Maintainer: Igor N. Prischepoff (igor@tyumbit.ru, pri_igor@mail.ru) " Last change: 2012 Aug 11 +" 2024 Nov 14 by Vim project: // only denotes a comment when starting a line (#16051) " quit when a syntax file was already loaded if exists ("b:current_syntax") @@ -27,17 +28,17 @@ syn match CfgSection "{.*}" syn match CfgString "\".*\"" contained syn match CfgString "'.*'" contained -" Comments (Everything before '#' or '//' or ';') +" Comments (Everything before '#' or ';' or leading '//') syn match CfgComment "#.*" syn match CfgComment ";.*" -syn match CfgComment "\/\/.*" +syn match CfgComment "^\s*\/\/.*" " Define the default highlighting. " Only when an item doesn't have highlighting yet hi def link CfgOnOff Label -hi def link CfgComment Comment -hi def link CfgSection Type -hi def link CfgString String +hi def link CfgComment Comment +hi def link CfgSection Type +hi def link CfgString String hi def link CfgParams Keyword hi def link CfgValues Constant hi def link CfgDirectory Directory diff --git a/runtime/syntax/help.vim b/runtime/syntax/help.vim index fd128bb0b5..c8ad8bfe4a 100644 --- a/runtime/syntax/help.vim +++ b/runtime/syntax/help.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: Vim help file " Maintainer: The Vim Project <https://github.com/vim/vim> -" Last Change: 2024 Oct 05 +" Last Change: 2024 Oct 16 " Former Maintainer: Bram Moolenaar <Bram@vim.org> " Quit when a (custom) syntax file was already loaded @@ -43,7 +43,8 @@ syn match helpOption "'[a-z]\{2,\}'" syn match helpOption "'t_..'" syn match helpNormal "'ab'" syn match helpCommand "`[^` \t]\+`"hs=s+1,he=e-1 contains=helpBacktick -syn match helpCommand "\(^\|[^a-z"[]\)\zs`[^`]\+`\ze\([^a-z\t."']\|$\)"hs=s+1,he=e-1 contains=helpBacktick +" doesn't allow a . directly after an ending backtick. See :helpgrep `[^`,]\+ [^`,]\+`\. +syn match helpCommand "\(^\|[^a-z"[]\)\zs`[^`]\+`\ze\([^a-z\t."']\|[.?!]\?$\)"hs=s+1,he=e-1 contains=helpBacktick syn match helpHeader "\s*\zs.\{-}\ze\s\=\~$" nextgroup=helpIgnore syn match helpGraphic ".* \ze`$" nextgroup=helpIgnore if has("conceal") @@ -52,6 +53,7 @@ else syn match helpIgnore "." contained endif syn keyword helpNote note Note NOTE note: Note: NOTE: Notes Notes: +syn match helpNote "\c(note\(:\|\>\)"ms=s+1 syn keyword helpWarning WARNING WARNING: Warning: syn keyword helpDeprecated DEPRECATED DEPRECATED: Deprecated: syn match helpSpecial "\<N\>" @@ -64,6 +66,10 @@ syn match helpSpecial "\[N]" syn match helpSpecial "N N"he=s+1 syn match helpSpecial "Nth"me=e-2 syn match helpSpecial "N-1"me=e-2 +" highlighting N for :resize in windows.txt +syn match helpSpecial "] -N\>"ms=s+3 +syn match helpSpecial "+N\>"ms=s+1 +syn match helpSpecial "\[+-]N\>"ms=s+4 " highlighting N of cinoptions-values in indent.txt syn match helpSpecial "^\t-\?\zsNs\?\s"me=s+1 " highlighting N of cinoptions-values in indent.txt @@ -92,6 +98,7 @@ syn match helpSpecial "\[group]" syn match helpNormal "\[\(readonly\|fifo\|socket\|converted\|crypted\)]" syn match helpSpecial "CTRL-." +syn match helpSpecial "CTRL-<\a\+>" syn match helpSpecial "CTRL-SHIFT-." syn match helpSpecial "CTRL-Break" syn match helpSpecial "CTRL-PageUp" @@ -138,7 +145,7 @@ syn match helpUnderlined "\t[* ]Underlined\t\+[a-z].*" syn match helpError "\t[* ]Error\t\+[a-z].*" syn match helpTodo "\t[* ]Todo\t\+[a-z].*" -syn match helpURL `\v<(((https?|ftp|gopher)://|(mailto|file|news):)[^' <>"]+|(www|web|w3)[a-z0-9_-]*\.[a-z0-9._-]+\.[^' <>"]+)[a-zA-Z0-9/]` +syn match helpURL `\v<(((https?|ftp|gopher)://|(mailto|file|news):)[^'" \t<>{}]+|(www|web|w3)[a-z0-9_-]*\.[a-z0-9._-]+\.[^'" \t<>{}]+)[a-zA-Z0-9/]` syn match helpDiffAdded "\t[* ]Added\t\+[a-z].*" syn match helpDiffChanged "\t[* ]Changed\t\+[a-z].*" @@ -150,16 +157,6 @@ if s:i > 0 exe "runtime syntax/help_" . strpart(expand("%"), s:i + 1, 2) . ".vim" endif -" Italian -if v:lang =~ '\<IT\>' || v:lang =~ '_IT\>' || v:lang =~? "italian" - syn keyword helpNote nota Nota NOTA nota: Nota: NOTA: notare Notare NOTARE notare: Notare: NOTARE: - syn match helpSpecial "Nma"me=e-2 - syn match helpSpecial "Nme"me=e-2 - syn match helpSpecial "Nmi"me=e-2 - syn match helpSpecial "Nmo"me=e-2 - syn match helpSpecial "\[interv.]" -endif - syn sync minlines=40 diff --git a/runtime/syntax/help_it.vim b/runtime/syntax/help_it.vim new file mode 100644 index 0000000000..e76851d446 --- /dev/null +++ b/runtime/syntax/help_it.vim @@ -0,0 +1,17 @@ +" Vim syntax file +" Language: Italian Vim program help files *.itx +" Maintainer: The Vim Project <https://github.com/vim/vim> +" Last Change: 2024 Oct 16 +" +" This script is sourced from syntax/help.vim. + +syn keyword helpNote nota Nota NOTA nota: Nota: NOTA: notare Notare NOTARE notare: Notare: NOTARE: +syn match helpNote "\c(nota\(:\|\>\)"ms=s+1 +syn match helpSpecial "Nma"me=e-2 +syn match helpSpecial "Nme"me=e-2 +syn match helpSpecial "Nmi"me=e-2 +syn match helpSpecial "Nmo"me=e-2 +syn match helpSpecial "\[interv.]" +syn region helpNotVi start="{non" start="{solo" start="{disponibile" end="}" contains=helpLeadBlank,helpHyperTextJump + +" vim: ts=8 sw=2 diff --git a/runtime/syntax/idris2.vim b/runtime/syntax/idris2.vim new file mode 100644 index 0000000000..e3e3d0dcee --- /dev/null +++ b/runtime/syntax/idris2.vim @@ -0,0 +1,86 @@ +" Vim syntax file +" Language: Idris 2 +" Maintainer: Idris Hackers (https://github.com/edwinb/idris2-vim), Serhii Khoma <srghma@gmail.com> +" Last Change: 2024 Nov 05 +" Original Author: raichoo (raichoo@googlemail.com) +" License: Vim (see :h license) +" Repository: https://github.com/ShinKage/idris2-nvim +" + +if exists("b:current_syntax") + finish +endif + +syn match idris2TypeDecl "[a-zA-Z][a-zA-z0-9_']*\s\+:\s\+" contains=idris2Identifier,idris2Operators +syn region idris2Parens matchgroup=idris2Delimiter start="(" end=")" contains=TOP,idris2TypeDecl +syn region idris2Brackets matchgroup=idris2Delimiter start="\[" end="]" contains=TOP,idris2TypeDecl +syn region idris2Block matchgroup=idris2Delimiter start="{" end="}" contains=TOP,idris2TypeDecl +syn region idris2SnocBrackets matchgroup=idris2Delimiter start="\[<" end="]" contains=TOP +syn region idris2ListBrackets matchgroup=idris2Delimiter start="\[>" end="]" contains=TOP +syn keyword idris2Module module namespace +syn keyword idris2Import import +syn keyword idris2Structure data record interface implementation +syn keyword idris2Where where +syn keyword idris2Visibility public abstract private export +syn keyword idris2Block parameters mutual using +syn keyword idris2Totality total partial covering +syn keyword idris2Annotation auto impossible default constructor +syn keyword idris2Statement do case of rewrite with proof +syn keyword idris2Let let in +syn keyword idris2Forall forall +syn keyword idris2DataOpt noHints uniqueSearch search external noNewtype containedin=idris2Brackets +syn keyword idris2Conditional if then else +syn match idris2Number "\<[0-9]\+\>\|\<0[xX][0-9a-fA-F]\+\>\|\<0[oO][0-7]\+\>" +syn match idris2Float "\<[0-9]\+\.[0-9]\+\([eE][-+]\=[0-9]\+\)\=\>" +syn match idris2Delimiter "[,;]" +syn keyword idris2Infix prefix infix infixl infixr +syn match idris2Operators "\([-!#$%&\*\+./<=>\?@\\^|~:]\|\<_\>\)" +syn match idris2Type "\<[A-Z][a-zA-Z0-9_']*\>" +syn keyword idris2Todo TODO FIXME XXX HACK contained +syn match idris2LineComment "---*\([^-!#$%&\*\+./<=>\?@\\^|~].*\)\?$" contains=idris2Todo,@Spell +syn match idris2DocComment "|||\([^-!#$%&\*\+./<=>\?@\\^|~].*\)\?$" contains=idris2Todo,@Spell +syn match idris2MetaVar "?[a-zA-Z_][A-Za-z0-9_']*" +syn match idris2Pragma "%\(hide\|logging\|auto_lazy\|unbound_implicits\|prefix_record_projections\|ambiguity_depth\|nf_metavar_threshold\|search_timeout\|pair\|rewrite\|integerLit\|stringLit\|charLit\|doubleLit\|name\|start\|allow_overloads\|language\|default\|transform\|hint\|globalhint\|defaulthint\|inline\|noinline\|extern\|macro\|spec\|foreign\|nomangle\|builtin\|MkWorld\|World\|search\|runElab\|tcinline\|auto_implicit_depth\)" +syn match idris2Char "'[^'\\]'\|'\\.'\|'\\u[0-9a-fA-F]\{4}'" +syn match idris2Backtick "`[A-Za-z][A-Za-z0-9_']*`" +syn region idris2String start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=@Spell +syn region idris2BlockComment start="{-" end="-}" contains=idris2BlockComment,idris2Todo,@Spell +syn match idris2Identifier "[a-zA-Z][a-zA-z0-9_']*" contained + +" Default Highlighting {{{1 + +highlight def link idris2Deprecated Error +highlight def link idris2Identifier Identifier +highlight def link idris2Import Structure +highlight def link idris2Module Structure +highlight def link idris2Structure Structure +highlight def link idris2Statement Statement +highlight def link idris2Forall Structure +highlight def link idris2DataOpt Statement +highlight def link idris2DSL Statement +highlight def link idris2Block Statement +highlight def link idris2Annotation Statement +highlight def link idris2Where Structure +highlight def link idris2Let Structure +highlight def link idris2Totality Statement +highlight def link idris2Visibility Statement +highlight def link idris2Conditional Conditional +highlight def link idris2Pragma Statement +highlight def link idris2Number Number +highlight def link idris2Float Float +highlight def link idris2Delimiter Delimiter +highlight def link idris2Infix PreProc +highlight def link idris2Operators Operator +highlight def link idris2Type Include +highlight def link idris2DocComment Comment +highlight def link idris2LineComment Comment +highlight def link idris2BlockComment Comment +highlight def link idris2Todo Todo +highlight def link idris2MetaVar Macro +highlight def link idris2String String +highlight def link idris2Char String +highlight def link idris2Backtick Operator + +let b:current_syntax = "idris2" + +" vim: nowrap sw=2 sts=2 ts=8 noexpandtab ft=vim diff --git a/runtime/syntax/ipkg.vim b/runtime/syntax/ipkg.vim new file mode 100644 index 0000000000..218c243983 --- /dev/null +++ b/runtime/syntax/ipkg.vim @@ -0,0 +1,66 @@ +" Vim syntax file +" Language: Ipkg +" Maintainer: Idris Hackers (https://github.com/edwinb/idris2-vim), Serhii Khoma <srghma@gmail.com> +" Last Change: 2020 May 19 +" Version: 0.1 +" Author: ShinKage +" License: Vim (see :h license) +" Repository: https://github.com/ShinKage/idris2-nvim +" +" Syntax highlight for Idris 2 Package Descriptors (idris-lang.org) +" + +if exists("b:current_syntax") + finish +endif + +" we want to use line continuations (\) BEGINNING +let s:cpo_save = &cpo +set cpo&vim + +syn keyword ipkgKey + \ package + \ authors + \ maintainers + \ license + \ brief + \ readme + \ homepage + \ sourceloc + \ bugtracker + \ options + \ opts + \ sourcedir + \ builddir + \ outputdir + \ prebuild + \ postbuild + \ preinstall + \ postinstall + \ preclean + \ postclean + \ version + \ langversion + \ modules + \ main + \ executable + \ depends + +" we want to use line continuations (\) END +let &cpo = s:cpo_save +unlet s:cpo_save + +syn region ipkgString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=@Spell +syn match ipkgVersion "[0-9]*\([.][0-9]*\)*" +syn match ipkgName "[a-zA-Z][a-zA-z0-9_']*\([.][a-zA-Z][a-zA-z0-9_']*\)*" contained +syn match ipkgOperator "\(,\|&&\|<\|<=\|==\|>=\|>\)" +syn match ipkgComment "---*\([^-!#$%&\*\+./<=>\?@\\^|~].*\)\?$" contains=@Spell + +highlight def link ipkgKey Statement +highlight def link ipkgString String +highlight def link ipkgVersion Number +highlight def link ipkgName Identifier +highlight def link ipkgOperator Operator +highlight def link ipkgComment Comment + +let b:current_syntax = "ipkg" diff --git a/runtime/syntax/java.vim b/runtime/syntax/java.vim index 307fc26349..b3e17b55f6 100644 --- a/runtime/syntax/java.vim +++ b/runtime/syntax/java.vim @@ -3,7 +3,7 @@ " Maintainer: Aliaksei Budavei <0x000c70 AT gmail DOT com> " Former Maintainer: Claudio Fleiner <claudio@fleiner.com> " Repository: https://github.com/zzzyxwvut/java-vim.git -" Last Change: 2024 Oct 03 +" Last Change: 2024 Oct 10 " Please check ":help java.vim" for comments on some of the options " available. @@ -724,10 +724,15 @@ if exists("g:java_highlight_debug") hi def link DebugType Type endif +" Complement javaBlock and javaInParen for highlighting. +syn region javaBlockOther transparent matchgroup=javaBlockOtherStart start="{" end="}" + " Try not to fold top-level-type bodies under assumption that there is " but one such body. -exec 'syn region javaBlock transparent start="\%(^\|^\S[^:]\+\)\@' . s:ff.Peek('120', '') . '<!{" end="}" fold' +exec 'syn region javaBlock transparent matchgroup=javaBlockStart start="\%(^\|^\S[^:]\+\)\@' . s:ff.Peek('120', '') . '<!{" end="}" fold' +" See "D.2.1 Anonymous Classes" at +" https://web.archive.org/web/20010821025330/java.sun.com/docs/books/jls/first_edition/html/1.1Update.html#12959. if exists("g:java_mark_braces_in_parens_as_errors") syn match javaInParen contained "[{}]" hi def link javaInParen javaError diff --git a/runtime/syntax/jinja.vim b/runtime/syntax/jinja.vim index 6000855ff7..fa32c05f17 100644 --- a/runtime/syntax/jinja.vim +++ b/runtime/syntax/jinja.vim @@ -2,8 +2,9 @@ " Language: Jinja " Maintainer: Gregory Anders " Upstream: https://gitlab.com/HiPhish/jinja.vim +" Last Change: 2024 Oct 16 -if exists('b:current_syntax') +if exists('b:current_syntax') && b:current_syntax =~? 'jinja' finish endif diff --git a/runtime/syntax/lf.vim b/runtime/syntax/lf.vim new file mode 100644 index 0000000000..e4cf014865 --- /dev/null +++ b/runtime/syntax/lf.vim @@ -0,0 +1,236 @@ +" Vim syntax file +" Language: lf file manager configuration file (lfrc) +" Maintainer: Andis Sprinkis <andis@sprinkis.com> +" Former Maintainer: Cameron Wright +" Former URL: https://github.com/andis-sprinkis/lf-vim +" Last Change: 13 October 2024 +" +" The shell syntax highlighting is configurable. See $VIMRUNTIME/doc/syntax.txt +" lf version: 32 + +if exists("b:current_syntax") + finish +endif + +let b:current_syntax = "lf" + +"{{{ Comment Matching +syn match lfComment '#.*$' +"}}} + +"{{{ String Matching +syn match lfString "'.*'" +syn match lfString '".*"' contains=lfVar,lfSpecial +"}}} + +"{{{ Match lf Variables +syn match lfVar '\$f\|\$fx\|\$fs\|\$id' +"}}} + +"{{{ Keywords +syn keyword lfKeyword set setlocal cmd map cmap skipwhite +"}}} + +"{{{ Options Keywords +syn keyword lfOptions + \ quit + \ up + \ half-up + \ page-up + \ scroll-up + \ down + \ half-down + \ page-down + \ scroll-down + \ updir + \ open + \ jump-next + \ jump-prev + \ top + \ bottom + \ high + \ middle + \ low + \ toggle + \ invert + \ invert-below + \ unselect + \ glob-select + \ glob-unselect + \ calcdirsize + \ clearmaps + \ copy + \ cut + \ paste + \ clear + \ sync + \ draw + \ redraw + \ load + \ reload + \ echo + \ echomsg + \ echoerr + \ cd + \ select + \ delete + \ rename + \ source + \ push + \ read + \ shell + \ shell-pipe + \ shell-wait + \ shell-async + \ find + \ find-back + \ find-next + \ find-prev + \ search + \ search-back + \ search-next + \ search-prev + \ filter + \ setfilter + \ mark-save + \ mark-load + \ mark-remove + \ tag + \ tag-toggle + \ cmd-escape + \ cmd-complete + \ cmd-menu-complete + \ cmd-menu-complete-back + \ cmd-menu-accept + \ cmd-enter + \ cmd-interrupt + \ cmd-history-next + \ cmd-history-prev + \ cmd-left + \ cmd-right + \ cmd-home + \ cmd-end + \ cmd-delete + \ cmd-delete-back + \ cmd-delete-home + \ cmd-delete-end + \ cmd-delete-unix-word + \ cmd-yank + \ cmd-transpose + \ cmd-transpose-word + \ cmd-word + \ cmd-word-back + \ cmd-delete-word + \ cmd-delete-word-back + \ cmd-capitalize-word + \ cmd-uppercase-word + \ cmd-lowercase-word + \ anchorfind + \ autoquit + \ borderfmt + \ cleaner + \ copyfmt + \ cursoractivefmt + \ cursorparentfmt + \ cursorpreviewfmt + \ cutfmt + \ dircache + \ dircounts + \ dirfirst + \ dironly + \ dirpreviews + \ drawbox + \ dupfilefmt + \ errorfmt + \ filesep + \ findlen + \ globfilter + \ globsearch + \ hidden + \ hiddenfiles + \ hidecursorinactive + \ history + \ icons + \ ifs + \ ignorecase + \ ignoredia + \ incfilter + \ incsearch + \ info + \ infotimefmtnew + \ infotimefmtold + \ mouse + \ number + \ numberfmt + \ period + \ preserve + \ preview + \ previewer + \ promptfmt + \ ratios + \ relativenumber + \ reverse + \ roundbox + \ ruler + \ rulerfmt + \ scrolloff + \ selectfmt + \ selmode + \ shell + \ shellflag + \ shellopts + \ sixel + \ smartcase + \ smartdia + \ sortby + \ statfmt + \ tabstop + \ tagfmt + \ tempmarks + \ timefmt + \ truncatechar + \ truncatepct + \ waitmsg + \ wrapscan + \ wrapscroll + \ pre-cd + \ on-cd + \ on-select + \ on-redraw + \ on-quit +"}}} + +"{{{ Special Matching +syn match lfSpecial '<.*>\|\\.' +"}}} + +"{{{ Shell Script Matching for cmd +let s:shell_syntax = get(g:, 'lf_shell_syntax', "syntax/sh.vim") +let s:shell_syntax = get(b:, 'lf_shell_syntax', s:shell_syntax) +unlet b:current_syntax +exe 'syn include @Shell '.s:shell_syntax +let b:current_syntax = "lf" +syn region lfIgnore start=".{{\n" end="^}}" + \ keepend contains=lfExternalShell,lfExternalPatch +syn match lfShell '\$[a-zA-Z].*$ + \\|:[a-zA-Z].*$ + \\|%[a-zA-Z].*$ + \\|![a-zA-Z].*$ + \\|&[a-zA-Z].*$' + \ transparent contains=@Shell,lfExternalPatch +syn match lfExternalShell "^.*$" transparent contained contains=@Shell +syn match lfExternalPatch "^\s*cmd\ .*\ .{{$\|^}}$" contained +"}}} + +"{{{ Link Highlighting +hi def link lfComment Comment +hi def link lfVar Type +hi def link lfSpecial Special +hi def link lfString String +hi def link lfKeyword Statement +hi def link lfOptions Constant +hi def link lfConstant Constant +hi def link lfExternalShell Normal +hi def link lfExternalPatch Special +hi def link lfIgnore Special +"}}} diff --git a/runtime/syntax/lidris2.vim b/runtime/syntax/lidris2.vim new file mode 100644 index 0000000000..328ffdf685 --- /dev/null +++ b/runtime/syntax/lidris2.vim @@ -0,0 +1,25 @@ +" Vim syntax file +" Language: Literate Idris 2 +" Maintainer: Idris Hackers (https://github.com/edwinb/idris2-vim), Serhii Khoma <srghma@gmail.com> +" Last Change: 2020 May 19 +" Version: 0.1 +" License: Vim (see :h license) +" Repository: https://github.com/ShinKage/idris2-nvim +" +" This is just a minimal adaption of the Literate Haskell syntax file. + +" quit when a syntax file was already loaded +if exists("b:current_syntax") + finish +endif + +" Read Idris highlighting. +syntax include @idris2Top syntax/idris2.vim + +" Recognize blocks of Bird tracks, highlight as Idris. +syntax region lidris2BirdTrackBlock start="^>" end="\%(^[^>]\)\@=" contains=@idris2Top,lidris2BirdTrack +syntax match lidris2BirdTrack "^>" contained + +hi def link lidris2BirdTrack Comment + +let b:current_syntax = "lidris2" diff --git a/runtime/syntax/modula2/opt/r10.vim b/runtime/syntax/modula2/opt/r10.vim index 775f498dfb..5172be54c6 100644 --- a/runtime/syntax/modula2/opt/r10.vim +++ b/runtime/syntax/modula2/opt/r10.vim @@ -157,7 +157,7 @@ syn match modula2Base16Num "0[ux][0-9A-F]\+\('[0-9A-F]\+\)*" "| which greatly diminishes readability and thereby increases the opportunity "| for error during maintenance. Ideally, regular expressions should be split "| into small human readable pieces with interleaved comments that explain -"| precisely what each piece is doing. Vimscript imposes poor design. :-( +"| precisely what each piece is doing. Vim script imposes poor design. :-( syn match modula2Base10Num \ "\(\(0[bux]\@!\|[1-9]\)[0-9]*\('[0-9]\+\)*\)\(\.[0-9]\+\('[0-9]\+\)*\(e[+-]\?[0-9]\+\('[0-9]\+\)*\)\?\)\?" diff --git a/runtime/syntax/mss.vim b/runtime/syntax/mss.vim new file mode 100644 index 0000000000..de95d1d2ad --- /dev/null +++ b/runtime/syntax/mss.vim @@ -0,0 +1,23 @@ +" Vim syntax file +" Language: Vivado mss file +" Maintainer: The Vim Project <https://github.com/vim/vim> +" Last Change: 2024 Oct 22 +" Document: https://docs.amd.com/r/2020.2-English/ug1400-vitis-embedded/Microprocessor-Software-Specification-MSS +" Maintainer: Wu, Zhenyu <wuzhenyu@ustc.edu> + +if exists("b:current_syntax") + finish +endif + +syn case ignore +syn match mssComment "#.*$" contains=@Spell +syn keyword mssKeyword BEGIN END PARAMETER +syn keyword mssType OS PROCESSOR DRIVER LIBRARY +syn keyword mssConstant VERSION PROC_INSTANCE HW_INSTANCE OS_NAME OS_VER DRIVER_NAME DRIVER_VER LIBRARY_NAME LIBRARY_VER STDIN STDOUT XMDSTUB_PERIPHERAL ARCHIVER COMPILER COMPILER_FLAGS EXTRA_COMPILER_FLAGS + +hi def link mssComment Comment +hi def link mssKeyword Keyword +hi def link mssType Type +hi def link mssConstant Constant + +let b:current_syntax = "mss" diff --git a/runtime/syntax/nasm.vim b/runtime/syntax/nasm.vim index e1dfc1db12..22d7c2729a 100644 --- a/runtime/syntax/nasm.vim +++ b/runtime/syntax/nasm.vim @@ -3,16 +3,16 @@ " Maintainer: Andrii Sokolov <andriy145@gmail.com> " Original Author: Manuel M.H. Stol <Manuel.Stol@allieddata.nl> " Former Maintainer: Manuel M.H. Stol <Manuel.Stol@allieddata.nl> -" Contributors: +" Contributors: " Leonard König <leonard.r.koenig@gmail.com> (C string highlighting), " Peter Stanhope <dev.rptr@gmail.com> (Add missing 64-bit mode registers) -" Frédéric Hamel <rederic.hamel123@gmail.com> (F16c support, partial AVX +" Frédéric Hamel <frederic.hamel123@gmail.com> (F16c support, partial AVX " support, other) -" Last Change: 2023 Sep 7 +" sarvel <sarvel@protonmail.com> (Complete set of supported instructions) +" Last Change: 2024 Oct 8 " NASM Home: http://www.nasm.us/ - " Setup Syntax: " quit when a syntax file was already loaded if exists("b:current_syntax") @@ -22,7 +22,6 @@ endif syn case ignore - " Vim search and movement commands on identifers " Comments at start of a line inside which to skip search for indentifiers setlocal comments=:; @@ -89,16 +88,20 @@ syn match nasmString +\("[^"]\{-}"\|'[^']\{-}'\)+ " Highlight C escape- and format-sequences within ``-strings syn match nasmCString +\(`[^`]\{-}`\)+ contains=nasmCStringEscape,nasmCStringFormat extend syn case ignore -syn match nasmBinNumber "\<[0-1]\+b\>" -syn match nasmBinNumber "\<\~[0-1]\+b\>"lc=1 -syn match nasmOctNumber "\<\o\+q\>" -syn match nasmOctNumber "\<\~\o\+q\>"lc=1 -syn match nasmDecNumber "\<\d\+\>" -syn match nasmDecNumber "\<\~\d\+\>"lc=1 -syn match nasmHexNumber "\<\(\d\x*h\|0x\x\+\|\$\d\x*\)\>" -syn match nasmHexNumber "\<\~\(\d\x*h\|0x\x\+\|\$\d\x*\)\>"lc=1 -syn match nasmFltNumber "\<\d\+\.\d*\(e[+-]\=\d\+\)\=\>" -syn keyword nasmFltNumber Inf Infinity Indefinite NaN SNaN QNaN +syn match nasmBinNumber "\<\([01][01_]*[by]\|0[by][01_]\+\)\>" +syn match nasmBinNumber "\<\~\([01][01_]*[by]\|0[by][01_]\+\)\>"lc=1 +syn match nasmOctNumber "\<\(\o[0-7_]*[qo]\|0[qo][0-7_]\+\)\>" +syn match nasmOctNumber "\<\~\(\o[0-7_]*[qo]\|0[qo][0-7_]\+\)\>"lc=1 +syn match nasmDecNumber "\<\(\d[0-9_]*\|\d[0-9_]*d\|0d[0-9_]\+\)\>" +syn match nasmDecNumber "\<\~\(\d[0-9_]*\|\d[0-9_]*d\|0d[0-9_]\+\)\>"lc=1 +syn match nasmHexNumber "\<\(\d[0-9a-f_]*h\|0[xh][0-9a-f_]\+\|\$\d[0-9a-f_]*\)\>" +syn match nasmHexNumber "\<\~\(\d[0-9a-f_]*h\|0[xh][0-9a-f_]\+\|\$\d[0-9a-f_]*\)\>"lc=1 +syn match nasmBinFloat "\<\(0[by][01_]*\.[01_]*\(p[+-]\=[0-9_]*\)\=\)\|\(0[by][01_]*p[+-]\=[0-9_]*\)\>" +syn match nasmOctFloat "\<\(0[qo][0-7_]*\.[0-7_]*\(p[+-]\=[0-9_]*\)\=\)\|\(0[qo][0-7_]*p[+-]\=[0-9_]*\)\>" +syn match nasmDecFloat "\<\(\d[0-9_]*\.[0-9_]*\(e[+-]\=[0-9_]*\)\=\)\|\(\d[0-9_]*e[+-]\=[0-9_]*\)\>" +syn match nasmHexFloat "\<\(0[xh][0-9a-f_]\+\.[0-9a-f_]*\(p[+-]\=[0-9_]*\)\=\)\|\(0[xh][0-9a-f_]\+p[+-]\=[0-9_]*\)\>" +syn keyword nasmSpecFloat Inf NaN SNaN QNaN __?Infinity?__ __?NaN?__ __?SNaN?__ __?QNaN?__ +syn match nasmBcdConst "\<\(\d[0-9_]*p\|0p[0-9_]\+\)\>" syn match nasmNumberError "\<\~\s*\d\+\.\d*\(e[+-]\=\d\+\)\=\>" @@ -108,8 +111,8 @@ syn keyword nasmTypeError DF EXTRN FWORD RESF TBYTE syn keyword nasmType FAR NEAR SHORT syn keyword nasmType BYTE WORD DWORD QWORD DQWORD HWORD DHWORD TWORD syn keyword nasmType CDECL FASTCALL NONE PASCAL STDCALL -syn keyword nasmStorage DB DW DD DQ DDQ DT -syn keyword nasmStorage RESB RESW RESD RESQ RESDQ REST +syn keyword nasmStorage DB DW DD DQ DT DO DY DZ +syn keyword nasmStorage RESB RESW RESD RESQ REST RESO RESY RESZ syn keyword nasmStorage EXTERN GLOBAL COMMON " Structured storage types syn match nasmTypeError "\<\(AT\|I\=\(END\)\=\(STRUCT\=\|UNION\)\|I\=END\)\>" @@ -272,7 +275,6 @@ syn keyword nasmConstant __BITS__ __DATE__ __FILE__ __FORMAT__ __LINE__ syn keyword nasmConstant __NASM_MAJOR__ __NASM_MINOR__ __NASM_VERSION__ syn keyword nasmConstant __TIME__ " Instruction modifiers -syn match nasmInstructnError "\<TO\>" syn match nasmInstrModifier "\(^\|:\)\s*[C-GS]S\>"ms=e-1 syn keyword nasmInstrModifier A16 A32 O16 O32 syn match nasmInstrModifier "\<F\(ADD\|MUL\|\(DIV\|SUB\)R\=\)\s\+TO\>"lc=5,ms=e-1 @@ -290,7 +292,7 @@ syn keyword nasmStdDirective ENDPROC EPILOGUE LOCALS PROC PROLOGUE USES syn keyword nasmStdDirective ENDIF ELSE ELIF ELSIF IF "syn keyword nasmStdDirective BREAK CASE DEFAULT ENDSWITCH SWITCH "syn keyword nasmStdDirective CASE OF ENDCASE -syn keyword nasmStdDirective DO ENDFOR ENDWHILE FOR REPEAT UNTIL WHILE EXIT +syn keyword nasmStdDirective ENDFOR ENDWHILE FOR REPEAT UNTIL WHILE EXIT syn case ignore " Format specific directives: (all formats) " (excluded: extension directives to section, global, common and extern) @@ -302,193 +304,726 @@ syn keyword nasmFmtDirective _GLOBAL_OFFSET_TABLE_ __GLOBAL_OFFSET_TABLE_ syn keyword nasmFmtDirective ..start ..got ..gotoff ..gotpc ..plt ..sym syn case ignore - - +" Instruction errors: +" Instruction modifiers +syn match nasmInstructnError "\<TO\>" " Standard Instructions: -syn match nasmInstructnError "\<\(F\=CMOV\|SET\)N\=\a\{0,2}\>" +syn match nasmInstructnError "\<\(F\=CMOV\|SET\|J\)N\=\a\{0,2}\>" +syn match nasmInstructnError "\<CMP\a\{0,2}XADD\>" syn keyword nasmInstructnError CMPS MOVS LCS LODS STOS XLAT -syn match nasmStdInstruction "\<MOV\>" syn match nasmInstructnError "\<MOV\s[^,;[]*\<CS\>\s*[^:]"he=e-1 -syn match nasmStdInstruction "\<\(CMOV\|J\|SET\)\(N\=\([ABGL]E\=\|[CEOSZ]\)\|P[EO]\=\)\>" -syn match nasmStdInstruction "\<POP\>" -syn keyword nasmStdInstruction AAA AAD AAM AAS ADC ADD AND -syn keyword nasmStdInstruction BOUND BSF BSR BSWAP BT[C] BTR BTS -syn keyword nasmStdInstruction CALL CBW CDQ CDQE CLC CLD CMC CMP CMPSB CMPSD CMPSW CMPSQ -syn keyword nasmStdInstruction CMPXCHG CMPXCHG8B CPUID CWD[E] CQO -syn keyword nasmStdInstruction DAA DAS DEC DIV ENTER -syn keyword nasmStdInstruction IDIV IMUL INC INT[O] IRET[D] IRETW IRETQ -syn keyword nasmStdInstruction JCXZ JECXZ JMP -syn keyword nasmStdInstruction LAHF LDS LEA LEAVE LES LFS LGS LODSB LODSD LODSQ -syn keyword nasmStdInstruction LODSW LOOP[E] LOOPNE LOOPNZ LOOPZ LSS -syn keyword nasmStdInstruction MOVSB MOVSD MOVSW MOVSX MOVSQ MOVZX MUL NEG NOP NOT -syn keyword nasmStdInstruction OR POPA[D] POPAW POPF[D] POPFW POPFQ -syn keyword nasmStdInstruction PUSH[AD] PUSHAW PUSHF[D] PUSHFW PUSHFQ -syn keyword nasmStdInstruction PAUSE -syn keyword nasmStdInstruction RCL RCR RETF RET[N] ROL ROR -syn keyword nasmStdInstruction SAHF SAL SAR SBB SCASB SCASD SCASW -syn keyword nasmStdInstruction SHL[D] SHR[D] STC STD STOSB STOSD STOSW STOSQ SUB -syn keyword nasmStdInstruction TEST XADD XCHG XLATB XOR -syn keyword nasmStdInstruction LFENCE MFENCE SFENCE - - -" System Instructions: (usually privileged) -" Verification of pointer parameters -syn keyword nasmSysInstruction ARPL LAR LSL VERR VERW -" Addressing descriptor tables -syn keyword nasmSysInstruction LLDT SLDT LGDT SGDT -" Multitasking -syn keyword nasmSysInstruction LTR STR -" Coprocessing and Multiprocessing (requires fpu and multiple cpu's resp.) -syn keyword nasmSysInstruction CLTS LOCK WAIT " Input and Output syn keyword nasmInstructnError INS OUTS -syn keyword nasmSysInstruction IN INSB INSW INSD OUT OUTSB OUTSB OUTSW OUTSD -" Interrupt control -syn keyword nasmSysInstruction CLI STI LIDT SIDT -" System control -syn match nasmSysInstruction "\<MOV\s[^;]\{-}\<CR\o\>"me=s+3 -syn keyword nasmSysInstruction HLT INVD LMSW -syn keyword nasmSseInstruction PREFETCHT0 PREFETCHT1 PREFETCHT2 PREFETCHNTA -syn keyword nasmSseInstruction RSM SFENCE SMSW SYSENTER SYSEXIT UD2 WBINVD -" TLB (Translation Lookahead Buffer) testing -syn match nasmSysInstruction "\<MOV\s[^;]\{-}\<TR\o\>"me=s+3 -syn keyword nasmSysInstruction INVLPG - -" Debugging Instructions: (privileged) -syn match nasmDbgInstruction "\<MOV\s[^;]\{-}\<DR\o\>"me=s+3 -syn keyword nasmDbgInstruction INT1 INT3 RDMSR RDTSC RDPMC WRMSR - - -" Floating Point Instructions: (requires FPU) -syn match nasmFpuInstruction "\<FCMOVN\=\([AB]E\=\|[CEPUZ]\)\>" -syn keyword nasmFpuInstruction F2XM1 FABS FADD[P] FBLD FBSTP -syn keyword nasmFpuInstruction FCHS FCLEX FCOM[IP] FCOMP[P] FCOS -syn keyword nasmFpuInstruction FDECSTP FDISI FDIV[P] FDIVR[P] FENI FFREE -syn keyword nasmFpuInstruction FIADD FICOM[P] FIDIV[R] FILD -syn keyword nasmFpuInstruction FIMUL FINCSTP FINIT FIST[P] FISUB[R] -syn keyword nasmFpuInstruction FLD[1] FLDCW FLDENV FLDL2E FLDL2T FLDLG2 -syn keyword nasmFpuInstruction FLDLN2 FLDPI FLDZ FMUL[P] -syn keyword nasmFpuInstruction FNCLEX FNDISI FNENI FNINIT FNOP FNSAVE -syn keyword nasmFpuInstruction FNSTCW FNSTENV FNSTSW FNSTSW -syn keyword nasmFpuInstruction FPATAN FPREM[1] FPTAN FRNDINT FRSTOR -syn keyword nasmFpuInstruction FSAVE FSCALE FSETPM FSIN FSINCOS FSQRT -syn keyword nasmFpuInstruction FSTCW FSTENV FST[P] FSTSW FSUB[P] FSUBR[P] -syn keyword nasmFpuInstruction FTST FUCOM[IP] FUCOMP[P] -syn keyword nasmFpuInstruction FXAM FXCH FXTRACT FYL2X FYL2XP1 - - -" Multi Media Xtension Packed Instructions: (requires MMX unit) " Standard MMX instructions: (requires MMX1 unit) syn match nasmInstructnError "\<P\(ADD\|SUB\)U\=S\=[DQ]\=\>" syn match nasmInstructnError "\<PCMP\a\{0,2}[BDWQ]\=\>" -syn keyword nasmMmxInstruction EMMS MOVD MOVQ -syn keyword nasmMmxInstruction PACKSSDW PACKSSWB PACKUSWB PADDB PADDD PADDW -syn keyword nasmMmxInstruction PADDSB PADDSW PADDUSB PADDUSW PAND[N] -syn keyword nasmMmxInstruction PCMPEQB PCMPEQD PCMPEQW PCMPGTB PCMPGTD PCMPGTW -syn keyword nasmMmxInstruction PMACHRIW PMADDWD PMULHW PMULLW POR -syn keyword nasmMmxInstruction PSLLD PSLLQ PSLLW PSRAD PSRAW PSRLD PSRLQ PSRLW -syn keyword nasmMmxInstruction PSUBB PSUBD PSUBW PSUBSB PSUBSW PSUBUSB PSUBUSW -syn keyword nasmMmxInstruction PUNPCKHBW PUNPCKHDQ PUNPCKHWD -syn keyword nasmMmxInstruction PUNPCKLBW PUNPCKLDQ PUNPCKLWD PXOR -" Extended MMX instructions: (requires MMX2/SSE unit) -syn keyword nasmMmxInstruction MASKMOVQ MOVNTQ -syn keyword nasmMmxInstruction PAVGB PAVGW PEXTRW PINSRW PMAXSW PMAXUB -syn keyword nasmMmxInstruction PMINSW PMINUB PMOVMSKB PMULHUW PSADBW PSHUFW - - " Streaming SIMD Extension Packed Instructions: (requires SSE unit) syn match nasmInstructnError "\<CMP\a\{1,5}[PS]S\>" -syn match nasmSseInstruction "\<CMP\(N\=\(EQ\|L[ET]\)\|\(UN\)\=ORD\)\=[PS]S\>" -syn keyword nasmSseInstruction ADDPS ADDSS ANDNPS ANDPS -syn keyword nasmSseInstruction COMISS CVTPI2PS CVTPS2PI -syn keyword nasmSseInstruction CVTSI2SS CVTSS2SI CVTTPS2PI CVTTSS2SI -syn keyword nasmSseInstruction DIVPS DIVSS FXRSTOR FXSAVE LDMXCSR -syn keyword nasmSseInstruction MAXPS MAXSS MINPS MINSS MOVAPS MOVHLPS MOVHPS -syn keyword nasmSseInstruction MOVLHPS MOVLPS MOVMSKPS MOVNTPS MOVSS MOVUPS -syn keyword nasmSseInstruction MULPS MULSS -syn keyword nasmSseInstruction ORPS RCPPS RCPSS RSQRTPS RSQRTSS -syn keyword nasmSseInstruction SHUFPS SQRTPS SQRTSS STMXCSR SUBPS SUBSS -syn keyword nasmSseInstruction UCOMISS UNPCKHPS UNPCKLPS XORPS - -" F16c Instructions -syn keyword nasmF16CInstruction VCVTPH2PS VCVTPS2PH - " AVX Instructions -syn keyword nasmAVXInstruction VCVTDQ2PD VCVTDQ2PS VCVTPD2DQ VCVTPD2P VCVTPD2PS -syn keyword nasmAVXInstruction VCVTPS2DQ VCVTPS2PD -syn keyword nasmAVXInstruction VCVTSD2SI VCVTSD2SS VCVTSI2SD VCVTSI2SS VCVTSS2SD VCVTSS2SI -syn keyword nasmAVXInstruction VMAXPS VMAXSS VMINPS VMINSS VMOVAPS VMOVHLPS VMOVHPS -syn keyword nasmAVXInstruction VMAXPD VMAXSD VMINPD VMINSD VMOVAPD VMOVHLPD VMOVHPD -syn keyword nasmAVXInstruction VMOVLHPS VMOVLPS VMOVMSKPS VMOVNTPS VMOVSS VMOVUPS -syn keyword nasmAVXInstruction VMULPS VMULSS VPXOR - syn match nasmInstructnError "\<VP\a\{3}R\a\>" -syn match nasmAVXInstruction "\<VP\(INS\|EXT\)R[BDQW]\>" - -syn keyword nasmAVXInstruction VORPS VPABSB VPABSD VPABSW -syn keyword nasmAVXInstruction PACKSSDW VPACKSSWB VPACKUSDW VPACKUSWB VPADDD -syn keyword nasmAVXInstruction PADDQ VPADDSB VPADDSW VPADDUSB VPADDUSW -syn keyword nasmAVXInstruction PADDW VPALIGNR VPAND VPANDN VPAVGB -syn keyword nasmAVXInstruction PAVGW VPBLENDD VPBLENDVB VPBLENDW VPBROADCASTB -syn keyword nasmAVXInstruction PBROADCASTD VPBROADCASTQ VPBROADCASTW VPCLMULQDQ VPCMOV -syn keyword nasmAVXInstruction PCMPEQB VPCMPEQD VPCMPEQQ VPCMPEQW VPCMPESTRI -syn keyword nasmAVXInstruction PCMPESTRM VPCMPGTB VPCMPGTD VPCMPGTQ VPCMPGTW -syn keyword nasmAVXInstruction PCMPISTRI VPCMPISTRM VPCOMB VPCOMD VPCOMQ -syn keyword nasmAVXInstruction PCOMUB VPCOMUD VPCOMUQ VPCOMUW VPCOMW -syn keyword nasmAVXInstruction PERM2FVPERM2IVPERMD VPERMIL2PD VPERMIL2PS VPERMILPD VPERMILPS -syn keyword nasmAVXInstruction PERMPD VPERMPS VPERMQ VPEXTRB VPEXTRD -syn keyword nasmAVXInstruction PEXTRQ VPEXTRW VPGATHERDD VPGATHERDQ VPGATHERQD -syn keyword nasmAVXInstruction PGATHERQQ VPHADDBD VPHADDBQ VPHADDBW VPHADDD -syn keyword nasmAVXInstruction PHADDDQ VPHADDSW VPHADDUBQ VPHADDUBW VPHADDUDQ -syn keyword nasmAVXInstruction PHADDUWD VPHADDUWQ VPHADDW VPHADDWD VPHADDWQ -syn keyword nasmAVXInstruction PHMINPOSUW VPHSUBBW VPHSUBD VPHSUBDQ VPHSUBSW -syn keyword nasmAVXInstruction PHSUBW VPHSUBWD VPINSRB VPINSRD VPINSRQ -syn keyword nasmAVXInstruction PINSRW VPMACSDD VPMACSDQH -syn keyword nasmAVXInstruction VPMACSDQL VPMACSSDD VPMACSSDQL VPMACSSQH VPMACSSWD -syn keyword nasmAVXInstruction VPMACSSWW VPMACSWD VPMACSWW VPMADCSSWD VPMADCSWD -syn keyword nasmAVXInstruction VPMADDUBSW VPMADDWD VPMASKMOVD VPMASKMOVQ VPMAXSB -syn keyword nasmAVXInstruction VPMAXSD VPMAXSW VPMAXUB VPMAXUD VPMAXUW -syn keyword nasmAVXInstruction VPMINSB VPMINSD VPMINSW VPMINUB VPMINUD -syn keyword nasmAVXInstruction VPMINUW VPMOVMSKB VPMOVSXBD VPMOVSXBQ VPMOVSXBW -syn keyword nasmAVXInstruction VPMOVSXDQ VPMOVSXWD VPMOVSXWQ VPMOVZXBD VPMOVZXBQ -syn keyword nasmAVXInstruction VPMOVZXBW VPMOVZXDQ VPMOVZXWD VPMOVZXWQ VPMULDQ -syn keyword nasmAVXInstruction VPMULHRSW VPMULHUW VPMULHW VPMULLD VPMULLW -syn keyword nasmAVXInstruction VPMULUDQ VPOR VPPERM VPROTB VPROTD -syn keyword nasmAVXInstruction VPROTQ VPROTW VPSADBW VPSHAB VPSHAD -syn keyword nasmAVXInstruction VPSHAQ VPSHAW VPSHLB VPSHLD VPSHLQ -syn keyword nasmAVXInstruction VPSHLW VPSHUFB VPSHUFD VPSHUFHW VPSHUFLW -syn keyword nasmAVXInstruction VPSIGNB VPSIGND VPSIGNW VPSLLD VPSLLDQ -syn keyword nasmAVXInstruction VPSLLQ VPSLLVD VPSLLVQ VPSLLW VPSRAD -syn keyword nasmAVXInstruction VPSRAVD VPSRAW VPSRLD VPSRLDQ VPSRLQ -syn keyword nasmAVXInstruction VPSRLVD VPSRLVQ VPSRLW VPSUBB VPSUBD -syn keyword nasmAVXInstruction VPSUBQ VPSUBSB VPSUBSW VPSUBUSB VPSUBUSW -syn keyword nasmAVXInstruction VPSUBW VPTEST VPUNPCKHBW VPUNPCKHDQ VPUNPCKHQDQ -syn keyword nasmAVXInstruction VPUNPCKHWD VPUNPCKLBW VPUNPCKLDQ VPUNPCKLQDQ VPUNPCKLWD -syn keyword nasmAVXInstruction VPXOR VRCPPS - - -" Three Dimensional Now Packed Instructions: (requires 3DNow! unit) -syn keyword nasmNowInstruction FEMMS PAVGUSB PF2ID PFACC PFADD PFCMPEQ PFCMPGE -syn keyword nasmNowInstruction PFCMPGT PFMAX PFMIN PFMUL PFRCP PFRCPIT1 -syn keyword nasmNowInstruction PFRCPIT2 PFRSQIT1 PFRSQRT PFSUB[R] PI2FD -syn keyword nasmNowInstruction PMULHRWA PREFETCH[W] - - -" Vendor Specific Instructions: + + +" Instructions: +" Standard +syn keyword nasmInstructionStandard AAA AAD AAM AAS ADC +syn keyword nasmInstructionStandard ADD AND ARPL +syn keyword nasmInstructionStandard BOUND BSF BSR BSWAP BT +syn keyword nasmInstructionStandard BTC BTR BTS CALL CBW +syn keyword nasmInstructionStandard CDQ CDQE CLC CLD CLI +syn keyword nasmInstructionStandard CLTS CMC CMP CMPSB CMPSD +syn keyword nasmInstructionStandard CMPSQ CMPSW CMPXCHG CMPXCHG486 CMPXCHG8B +syn keyword nasmInstructionStandard CMPXCHG16B CPUID CQO +syn keyword nasmInstructionStandard CWD CWDE DAA DAS DEC +syn keyword nasmInstructionStandard DIV EMMS ENTER EQU +syn keyword nasmInstructionStandard F2XM1 FABS FADD FADDP FBLD +syn keyword nasmInstructionStandard FBSTP FCHS FCLEX FCMOVB FCMOVBE +syn keyword nasmInstructionStandard FCMOVE FCMOVNB FCMOVNBE FCMOVNE FCMOVNU +syn keyword nasmInstructionStandard FCMOVU FCOM FCOMI FCOMIP FCOMP +syn keyword nasmInstructionStandard FCOMPP FCOS FDECSTP FDISI FDIV +syn keyword nasmInstructionStandard FDIVP FDIVR FDIVRP FEMMS FENI +syn keyword nasmInstructionStandard FFREE FFREEP FIADD FICOM FICOMP +syn keyword nasmInstructionStandard FIDIV FIDIVR FILD FIMUL FINCSTP +syn keyword nasmInstructionStandard FINIT FIST FISTP FISTTP FISUB +syn keyword nasmInstructionStandard FISUBR FLD FLD1 FLDCW FLDENV +syn keyword nasmInstructionStandard FLDL2E FLDL2T FLDLG2 FLDLN2 FLDPI +syn keyword nasmInstructionStandard FLDZ FMUL FMULP FNCLEX FNDISI +syn keyword nasmInstructionStandard FNENI FNINIT FNOP FNSAVE FNSTCW +syn keyword nasmInstructionStandard FNSTENV FNSTSW FPATAN FPREM FPREM1 +syn keyword nasmInstructionStandard FPTAN FRNDINT FRSTOR FSAVE FSCALE +syn keyword nasmInstructionStandard FSETPM FSIN FSINCOS FSQRT FST +syn keyword nasmInstructionStandard FSTCW FSTENV FSTP FSTSW FSUB +syn keyword nasmInstructionStandard FSUBP FSUBR FSUBRP FTST FUCOM +syn keyword nasmInstructionStandard FUCOMI FUCOMIP FUCOMP FUCOMPP FXAM +syn keyword nasmInstructionStandard FXCH FXTRACT FYL2X FYL2XP1 HLT +syn keyword nasmInstructionStandard IBTS ICEBP IDIV IMUL IN +syn keyword nasmInstructionStandard INC INSB INSD INSW INT +syn keyword nasmInstructionStandard INTO +syn keyword nasmInstructionStandard INVD INVPCID INVLPG INVLPGA IRET +syn keyword nasmInstructionStandard IRETD IRETQ IRETW JCXZ JECXZ +syn keyword nasmInstructionStandard JRCXZ JMP JMPE LAHF LAR +syn keyword nasmInstructionStandard LDS LEA LEAVE LES LFENCE +syn keyword nasmInstructionStandard LFS LGDT LGS LIDT LLDT +syn keyword nasmInstructionStandard LMSW LOADALL LOADALL286 LODSB LODSD +syn keyword nasmInstructionStandard LODSQ LODSW LOOP LOOPE LOOPNE +syn keyword nasmInstructionStandard LOOPNZ LOOPZ LSL LSS LTR +syn keyword nasmInstructionStandard MFENCE MONITOR MONITORX MOV MOVD +syn keyword nasmInstructionStandard MOVQ MOVSB MOVSD MOVSQ MOVSW +syn keyword nasmInstructionStandard MOVSX MOVSXD MOVSX MOVZX MUL +syn keyword nasmInstructionStandard MWAIT MWAITX NEG NOP NOT +syn keyword nasmInstructionStandard OR OUT OUTSB OUTSD OUTSW +syn keyword nasmInstructionStandard PACKSSDW PACKSSWB PACKUSWB PADDB PADDD +syn keyword nasmInstructionStandard PADDSB PADDSW PADDUSB PADDUSW +syn keyword nasmInstructionStandard PADDW PAND PANDN PAUSE +syn keyword nasmInstructionStandard PAVGUSB PCMPEQB PCMPEQD PCMPEQW PCMPGTB +syn keyword nasmInstructionStandard PCMPGTD PCMPGTW PF2ID PFACC +syn keyword nasmInstructionStandard PFADD PFCMPEQ PFCMPGE PFCMPGT PFMAX +syn keyword nasmInstructionStandard PFMIN PFMUL PFRCP PFRCPIT1 PFRCPIT2 +syn keyword nasmInstructionStandard PFRSQIT1 PFRSQRT PFSUB PFSUBR PI2FD +syn keyword nasmInstructionStandard PMADDWD PMULHRWA +syn keyword nasmInstructionStandard PMULHW PMULLW +syn keyword nasmInstructionStandard POP POPA POPAD +syn keyword nasmInstructionStandard POPAW POPF POPFD POPFQ POPFW +syn keyword nasmInstructionStandard POR PREFETCH PREFETCHW PSLLD PSLLQ +syn keyword nasmInstructionStandard PSLLW PSRAD PSRAW PSRLD PSRLQ +syn keyword nasmInstructionStandard PSRLW PSUBB PSUBD PSUBSB +syn keyword nasmInstructionStandard PSUBSW PSUBUSB PSUBUSW PSUBW PUNPCKHBW +syn keyword nasmInstructionStandard PUNPCKHDQ PUNPCKHWD PUNPCKLBW PUNPCKLDQ PUNPCKLWD +syn keyword nasmInstructionStandard PUSH PUSHA PUSHAD PUSHAW PUSHF +syn keyword nasmInstructionStandard PUSHFD PUSHFQ PUSHFW PXOR RCL +syn keyword nasmInstructionStandard RCR +syn keyword nasmInstructionStandard RDTSCP RET RETF RETN RETW +syn keyword nasmInstructionStandard RETFW RETNW RETD RETFD RETND +syn keyword nasmInstructionStandard RETQ RETFQ RETNQ ROL ROR +syn keyword nasmInstructionStandard RSM RSTS +syn keyword nasmInstructionStandard SAHF SAL SALC SAR SBB +syn keyword nasmInstructionStandard SCASB SCASD SCASQ SCASW SFENCE +syn keyword nasmInstructionStandard SGDT SHL SHLD SHR SHRD +syn keyword nasmInstructionStandard SIDT SLDT SKINIT SMI +syn keyword nasmInstructionStandard SMSW STC STD STI +syn keyword nasmInstructionStandard STOSB STOSD STOSQ STOSW STR +syn keyword nasmInstructionStandard SUB SWAPGS +syn keyword nasmInstructionStandard SYSCALL SYSENTER SYSEXIT SYSRET TEST +syn keyword nasmInstructionStandard UD0 UD1 UD2B UD2 UD2A +syn keyword nasmInstructionStandard UMOV VERR VERW FWAIT WBINVD +syn keyword nasmInstructionStandard XADD XBTS XCHG +syn keyword nasmInstructionStandard XLATB XLAT XOR CMOVA CMOVAE +syn keyword nasmInstructionStandard CMOVB CMOVBE CMOVC CMOVE CMOVG +syn keyword nasmInstructionStandard CMOVGE CMOVL CMOVLE CMOVNA CMOVNAE +syn keyword nasmInstructionStandard CMOVNB CMOVNBE CMOVNC CMOVNE CMOVNG +syn keyword nasmInstructionStandard CMOVNGE CMOVNL CMOVNLE CMOVNO CMOVNP +syn keyword nasmInstructionStandard CMOVNS CMOVNZ CMOVO CMOVP CMOVPE +syn keyword nasmInstructionStandard CMOVPO CMOVS CMOVZ JA JAE +syn keyword nasmInstructionStandard JB JBE JC JCXZ JE +syn keyword nasmInstructionStandard JECXZ JG JGE JL JLE +syn keyword nasmInstructionStandard JNA JNAE JNB JNBE JNC +syn keyword nasmInstructionStandard JNE JNG JNGE JNL JNLE +syn keyword nasmInstructionStandard JNO JNP JNS JNZ JO +syn keyword nasmInstructionStandard JP JPE JPO JRCXZ JS +syn keyword nasmInstructionStandard JZ SETA SETAE SETB SETBE +syn keyword nasmInstructionStandard SETC SETE SETG SETGE SETL +syn keyword nasmInstructionStandard SETLE SETNA SETNAE SETNB SETNBE +syn keyword nasmInstructionStandard SETNC SETNE SETNG SETNGE SETNL +syn keyword nasmInstructionStandard SETNLE SETNO SETNP SETNS SETNZ +syn keyword nasmInstructionStandard SETO SETP SETPE SETPO SETS +syn keyword nasmInstructionStandard SETZ +" SIMD +syn keyword nasmInstructionSIMD ADDPS ADDSS ANDNPS ANDPS CMPEQPS +syn keyword nasmInstructionSIMD CMPEQSS CMPLEPS CMPLESS CMPLTPS CMPLTSS +syn keyword nasmInstructionSIMD CMPNEQPS CMPNEQSS CMPNLEPS CMPNLESS CMPNLTPS +syn keyword nasmInstructionSIMD CMPNLTSS CMPORDPS CMPORDSS CMPUNORDPS CMPUNORDSS +syn keyword nasmInstructionSIMD CMPPS CMPSS COMISS CVTPI2PS CVTPS2PI +syn keyword nasmInstructionSIMD CVTSI2SS CVTSS2SI CVTTPS2PI CVTTSS2SI DIVPS +syn keyword nasmInstructionSIMD DIVSS LDMXCSR MAXPS MAXSS MINPS +syn keyword nasmInstructionSIMD MINSS MOVAPS MOVHPS MOVLHPS MOVLPS +syn keyword nasmInstructionSIMD MOVHLPS MOVMSKPS MOVNTPS MOVSS MOVUPS +syn keyword nasmInstructionSIMD MULPS MULSS ORPS RCPPS RCPSS +syn keyword nasmInstructionSIMD RSQRTPS RSQRTSS SHUFPS SQRTPS SQRTSS +syn keyword nasmInstructionSIMD STMXCSR SUBPS SUBSS UCOMISS UNPCKHPS +syn keyword nasmInstructionSIMD UNPCKLPS XORPS +" SSE +syn keyword nasmInstructionSSE FXRSTOR FXRSTOR64 FXSAVE FXSAVE64 +" XSAVE +syn keyword nasmInstructionXSAVE XGETBV XSETBV XSAVE XSAVE64 XSAVEC +syn keyword nasmInstructionXSAVE XSAVEC64 XSAVEOPT XSAVEOPT64 XSAVES XSAVES64 +syn keyword nasmInstructionXSAVE XRSTOR XRSTOR64 XRSTORS XRSTORS64 +" MEM +syn keyword nasmInstructionMEM PREFETCHNTA PREFETCHT0 PREFETCHT1 PREFETCHT2 PREFETCHIT0 +syn keyword nasmInstructionMEM PREFETCHIT1 SFENCE +" MMX +syn keyword nasmInstructionMMX MASKMOVQ MOVNTQ PAVGB PAVGW PEXTRW +syn keyword nasmInstructionMMX PINSRW PMAXSW PMAXUB PMINSW PMINUB +syn keyword nasmInstructionMMX PMOVMSKB PMULHUW PSADBW PSHUFW +" 3DNOW +syn keyword nasmInstruction3DNOW PF2IW PFNACC PFPNACC PI2FW PSWAPD +" SSE2 +syn keyword nasmInstructionSSE2 MASKMOVDQU CLFLUSH MOVNTDQ MOVNTI MOVNTPD +syn keyword nasmInstructionSSE2 LFENCE MFENCE +" WMMX +syn keyword nasmInstructionWMMX MOVD MOVDQA MOVDQU MOVDQ2Q MOVQ +syn keyword nasmInstructionWMMX MOVQ2DQ PACKSSWB PACKSSDW PACKUSWB PADDB +syn keyword nasmInstructionWMMX PADDW PADDD PADDQ PADDSB PADDSW +syn keyword nasmInstructionWMMX PADDUSB PADDUSW PAND PANDN PAVGB +syn keyword nasmInstructionWMMX PAVGW PCMPEQB PCMPEQW PCMPEQD PCMPGTB +syn keyword nasmInstructionWMMX PCMPGTW PCMPGTD PEXTRW PINSRW PMADDWD +syn keyword nasmInstructionWMMX PMAXSW PMAXUB PMINSW PMINUB PMOVMSKB +syn keyword nasmInstructionWMMX PMULHUW PMULHW PMULLW PMULUDQ POR +syn keyword nasmInstructionWMMX PSADBW PSHUFD PSHUFHW PSHUFLW PSLLDQ +syn keyword nasmInstructionWMMX PSLLW PSLLD PSLLQ PSRAW PSRAD +syn keyword nasmInstructionWMMX PSRLDQ PSRLW PSRLD PSRLQ PSUBB +syn keyword nasmInstructionWMMX PSUBW PSUBD PSUBQ PSUBSB PSUBSW +syn keyword nasmInstructionWMMX PSUBUSB PSUBUSW PUNPCKHBW PUNPCKHWD PUNPCKHDQ +syn keyword nasmInstructionWMMX PUNPCKHQDQ PUNPCKLBW PUNPCKLWD PUNPCKLDQ PUNPCKLQDQ +syn keyword nasmInstructionWMMX PXOR +" WSSD +syn keyword nasmInstructionWSSD ADDPD ADDSD ANDNPD ANDPD CMPEQPD +syn keyword nasmInstructionWSSD CMPEQSD CMPLEPD CMPLESD CMPLTPD CMPLTSD +syn keyword nasmInstructionWSSD CMPNEQPD CMPNEQSD CMPNLEPD CMPNLESD CMPNLTPD +syn keyword nasmInstructionWSSD CMPNLTSD CMPORDPD CMPORDSD CMPUNORDPD CMPUNORDSD +syn keyword nasmInstructionWSSD CMPPD CMPSD COMISD CVTDQ2PD CVTDQ2PS +syn keyword nasmInstructionWSSD CVTPD2DQ CVTPD2PI CVTPD2PS CVTPI2PD CVTPS2DQ +syn keyword nasmInstructionWSSD CVTPS2PD CVTSD2SI CVTSD2SS CVTSI2SD CVTSS2SD +syn keyword nasmInstructionWSSD CVTTPD2PI CVTTPD2DQ CVTTPS2DQ CVTTSD2SI DIVPD +syn keyword nasmInstructionWSSD DIVSD MAXPD MAXSD MINPD MINSD +syn keyword nasmInstructionWSSD MOVAPD MOVHPD MOVLPD MOVMSKPD MOVSD +syn keyword nasmInstructionWSSD MOVUPD MULPD MULSD ORPD SHUFPD +syn keyword nasmInstructionWSSD SQRTPD SQRTSD SUBPD SUBSD UCOMISD +syn keyword nasmInstructionWSSD UNPCKHPD UNPCKLPD XORPD +" PRESSCOT +syn keyword nasmInstructionPRESSCOT ADDSUBPD ADDSUBPS HADDPD HADDPS HSUBPD +syn keyword nasmInstructionPRESSCOT HSUBPS LDDQU MOVDDUP MOVSHDUP MOVSLDUP +" VMXSVM +syn keyword nasmInstructionVMXSVM CLGI STGI VMCALL VMCLEAR VMFUNC +syn keyword nasmInstructionVMXSVM VMLAUNCH VMLOAD VMMCALL VMPTRLD VMPTRST +syn keyword nasmInstructionVMXSVM VMREAD VMRESUME VMRUN VMSAVE VMWRITE +syn keyword nasmInstructionVMXSVM VMXOFF VMXON +" PTVMX +syn keyword nasmInstructionPTVMX INVEPT INVVPID +" SEVSNPAMD +syn keyword nasmInstructionSEVSNPAMD PVALIDATE RMPADJUST VMGEXIT +" TEJAS +syn keyword nasmInstructionTEJAS PABSB PABSW PABSD PALIGNR PHADDW +syn keyword nasmInstructionTEJAS PHADDD PHADDSW PHSUBW PHSUBD PHSUBSW +syn keyword nasmInstructionTEJAS PMADDUBSW PMULHRSW PSHUFB PSIGNB PSIGNW +syn keyword nasmInstructionTEJAS PSIGND +" AMD_SSE4A +syn keyword nasmInstructionAMD_SSE4A EXTRQ INSERTQ MOVNTSD MOVNTSS +" BARCELONA +syn keyword nasmInstructionBARCELONA LZCNT +" PENRY +syn keyword nasmInstructionPENRY BLENDPD BLENDPS BLENDVPD BLENDVPS DPPD +syn keyword nasmInstructionPENRY DPPS EXTRACTPS INSERTPS MOVNTDQA MPSADBW +syn keyword nasmInstructionPENRY PACKUSDW PBLENDVB PBLENDW PCMPEQQ PEXTRB +syn keyword nasmInstructionPENRY PEXTRD PEXTRQ PEXTRW PHMINPOSUW PINSRB +syn keyword nasmInstructionPENRY PINSRD PINSRQ PMAXSB PMAXSD PMAXUD +syn keyword nasmInstructionPENRY PMAXUW PMINSB PMINSD PMINUD PMINUW +syn keyword nasmInstructionPENRY PMOVSXBW PMOVSXBD PMOVSXBQ PMOVSXWD PMOVSXWQ +syn keyword nasmInstructionPENRY PMOVSXDQ PMOVZXBW PMOVZXBD PMOVZXBQ PMOVZXWD +syn keyword nasmInstructionPENRY PMOVZXWQ PMOVZXDQ PMULDQ PMULLD PTEST +syn keyword nasmInstructionPENRY ROUNDPD ROUNDPS ROUNDSD ROUNDSS +" NEHALEM +syn keyword nasmInstructionNEHALEM CRC32 PCMPESTRI PCMPESTRM PCMPISTRI PCMPISTRM +syn keyword nasmInstructionNEHALEM PCMPGTQ POPCNT +" SMX +syn keyword nasmInstructionSMX GETSEC +" GEODE_3DNOW +syn keyword nasmInstructionGEODE_3DNOW PFRCPV PFRSQRTV +" INTEL_NEW +syn keyword nasmInstructionINTEL_NEW MOVBE +" AES +syn keyword nasmInstructionAES AESENC AESENCLAST AESDEC AESDECLAST AESIMC +syn keyword nasmInstructionAES AESKEYGENASSIST +" AVX_AES +syn keyword nasmInstructionAVX_AES VAESENC VAESENCLAST VAESDEC VAESDECLAST VAESIMC +syn keyword nasmInstructionAVX_AES VAESKEYGENASSIST +" INTEL_PUB +syn keyword nasmInstructionINTEL_PUB VAESENC VAESENCLAST VAESDEC VAESDECLAST VAESENC +syn keyword nasmInstructionINTEL_PUB VAESENCLAST VAESDEC VAESDECLAST VAESENC VAESENCLAST +syn keyword nasmInstructionINTEL_PUB VAESDEC VAESDECLAST +" AVX +syn keyword nasmInstructionAVX VADDPD VADDPS VADDSD VADDSS VADDSUBPD +syn keyword nasmInstructionAVX VADDSUBPS VANDPD VANDPS VANDNPD VANDNPS +syn keyword nasmInstructionAVX VBLENDPD VBLENDPS VBLENDVPD VBLENDVPS VBROADCASTSS +syn keyword nasmInstructionAVX VBROADCASTSD VBROADCASTF128 VCMPEQ_OSPD VCMPEQPD VCMPLT_OSPD +syn keyword nasmInstructionAVX VCMPLTPD VCMPLE_OSPD VCMPLEPD VCMPUNORD_QPD VCMPUNORDPD +syn keyword nasmInstructionAVX VCMPNEQ_UQPD VCMPNEQPD VCMPNLT_USPD VCMPNLTPD VCMPNLE_USPD +syn keyword nasmInstructionAVX VCMPNLEPD VCMPORD_QPD VCMPORDPD VCMPEQ_UQPD VCMPNGE_USPD +syn keyword nasmInstructionAVX VCMPNGEPD VCMPNGT_USPD VCMPNGTPD VCMPFALSE_OQPD VCMPFALSEPD +syn keyword nasmInstructionAVX VCMPNEQ_OQPD VCMPGE_OSPD VCMPGEPD VCMPGT_OSPD VCMPGTPD +syn keyword nasmInstructionAVX VCMPTRUE_UQPD VCMPTRUEPD VCMPEQ_OSPD VCMPLT_OQPD VCMPLE_OQPD +syn keyword nasmInstructionAVX VCMPUNORD_SPD VCMPNEQ_USPD VCMPNLT_UQPD VCMPNLE_UQPD VCMPORD_SPD +syn keyword nasmInstructionAVX VCMPEQ_USPD VCMPNGE_UQPD VCMPNGT_UQPD VCMPFALSE_OSPD VCMPNEQ_OSPD +syn keyword nasmInstructionAVX VCMPGE_OQPD VCMPGT_OQPD VCMPTRUE_USPD VCMPPD VCMPEQ_OSPS +syn keyword nasmInstructionAVX VCMPEQPS VCMPLT_OSPS VCMPLTPS VCMPLE_OSPS VCMPLEPS +syn keyword nasmInstructionAVX VCMPUNORD_QPS VCMPUNORDPS VCMPNEQ_UQPS VCMPNEQPS VCMPNLT_USPS +syn keyword nasmInstructionAVX VCMPNLTPS VCMPNLE_USPS VCMPNLEPS VCMPORD_QPS VCMPORDPS +syn keyword nasmInstructionAVX VCMPEQ_UQPS VCMPNGE_USPS VCMPNGEPS VCMPNGT_USPS VCMPNGTPS +syn keyword nasmInstructionAVX VCMPFALSE_OQPS VCMPFALSEPS VCMPNEQ_OQPS VCMPGE_OSPS VCMPGEPS +syn keyword nasmInstructionAVX VCMPGT_OSPS VCMPGTPS VCMPTRUE_UQPS VCMPTRUEPS VCMPEQ_OSPS +syn keyword nasmInstructionAVX VCMPLT_OQPS VCMPLE_OQPS VCMPUNORD_SPS VCMPNEQ_USPS VCMPNLT_UQPS +syn keyword nasmInstructionAVX VCMPNLE_UQPS VCMPORD_SPS VCMPEQ_USPS VCMPNGE_UQPS VCMPNGT_UQPS +syn keyword nasmInstructionAVX VCMPFALSE_OSPS VCMPNEQ_OSPS VCMPGE_OQPS VCMPGT_OQPS VCMPTRUE_USPS +syn keyword nasmInstructionAVX VCMPPS VCMPEQ_OSSD VCMPEQSD VCMPLT_OSSD VCMPLTSD +syn keyword nasmInstructionAVX VCMPLE_OSSD VCMPLESD VCMPUNORD_QSD VCMPUNORDSD VCMPNEQ_UQSD +syn keyword nasmInstructionAVX VCMPNEQSD VCMPNLT_USSD VCMPNLTSD VCMPNLE_USSD VCMPNLESD +syn keyword nasmInstructionAVX VCMPORD_QSD VCMPORDSD VCMPEQ_UQSD VCMPNGE_USSD VCMPNGESD +syn keyword nasmInstructionAVX VCMPNGT_USSD VCMPNGTSD VCMPFALSE_OQSD VCMPFALSESD VCMPNEQ_OQSD +syn keyword nasmInstructionAVX VCMPGE_OSSD VCMPGESD VCMPGT_OSSD VCMPGTSD VCMPTRUE_UQSD +syn keyword nasmInstructionAVX VCMPTRUESD VCMPEQ_OSSD VCMPLT_OQSD VCMPLE_OQSD VCMPUNORD_SSD +syn keyword nasmInstructionAVX VCMPNEQ_USSD VCMPNLT_UQSD VCMPNLE_UQSD VCMPORD_SSD VCMPEQ_USSD +syn keyword nasmInstructionAVX VCMPNGE_UQSD VCMPNGT_UQSD VCMPFALSE_OSSD VCMPNEQ_OSSD VCMPGE_OQSD +syn keyword nasmInstructionAVX VCMPGT_OQSD VCMPTRUE_USSD VCMPSD VCMPEQ_OSSS VCMPEQSS +syn keyword nasmInstructionAVX VCMPLT_OSSS VCMPLTSS VCMPLE_OSSS VCMPLESS VCMPUNORD_QSS +syn keyword nasmInstructionAVX VCMPUNORDSS VCMPNEQ_UQSS VCMPNEQSS VCMPNLT_USSS VCMPNLTSS +syn keyword nasmInstructionAVX VCMPNLE_USSS VCMPNLESS VCMPORD_QSS VCMPORDSS VCMPEQ_UQSS +syn keyword nasmInstructionAVX VCMPNGE_USSS VCMPNGESS VCMPNGT_USSS VCMPNGTSS VCMPFALSE_OQSS +syn keyword nasmInstructionAVX VCMPFALSESS VCMPNEQ_OQSS VCMPGE_OSSS VCMPGESS VCMPGT_OSSS +syn keyword nasmInstructionAVX VCMPGTSS VCMPTRUE_UQSS VCMPTRUESS VCMPEQ_OSSS VCMPLT_OQSS +syn keyword nasmInstructionAVX VCMPLE_OQSS VCMPUNORD_SSS VCMPNEQ_USSS VCMPNLT_UQSS VCMPNLE_UQSS +syn keyword nasmInstructionAVX VCMPORD_SSS VCMPEQ_USSS VCMPNGE_UQSS VCMPNGT_UQSS VCMPFALSE_OSSS +syn keyword nasmInstructionAVX VCMPNEQ_OSSS VCMPGE_OQSS VCMPGT_OQSS VCMPTRUE_USSS VCMPSS +syn keyword nasmInstructionAVX VCOMISD VCOMISS VCVTDQ2PD VCVTDQ2PS VCVTPD2DQ +syn keyword nasmInstructionAVX VCVTPD2PS VCVTPS2DQ VCVTPS2PD VCVTSD2SI VCVTSD2SS +syn keyword nasmInstructionAVX VCVTSI2SD VCVTSI2SS VCVTSS2SD VCVTSS2SI VCVTTPD2DQ +syn keyword nasmInstructionAVX VCVTTPS2DQ VCVTTSD2SI VCVTTSS2SI VDIVPD VDIVPS +syn keyword nasmInstructionAVX VDIVSD VDIVSS VDPPD VDPPS VEXTRACTF128 +syn keyword nasmInstructionAVX VEXTRACTPS VHADDPD VHADDPS VHSUBPD VHSUBPS +syn keyword nasmInstructionAVX VINSERTF128 VINSERTPS VLDDQU VLDQQU VLDDQU +syn keyword nasmInstructionAVX VLDMXCSR VMASKMOVDQU VMASKMOVPS VMASKMOVPD VMAXPD +syn keyword nasmInstructionAVX VMAXPS VMAXSD VMAXSS VMINPD VMINPS +syn keyword nasmInstructionAVX VMINSD VMINSS VMOVAPD VMOVAPS VMOVD +syn keyword nasmInstructionAVX VMOVQ VMOVDDUP VMOVDQA VMOVQQA VMOVDQA +syn keyword nasmInstructionAVX VMOVDQU VMOVQQU VMOVDQU VMOVHLPS VMOVHPD +syn keyword nasmInstructionAVX VMOVHPS VMOVLHPS VMOVLPD VMOVLPS VMOVMSKPD +syn keyword nasmInstructionAVX VMOVMSKPS VMOVNTDQ VMOVNTQQ VMOVNTDQ VMOVNTDQA +syn keyword nasmInstructionAVX VMOVNTPD VMOVNTPS VMOVSD VMOVSHDUP VMOVSLDUP +syn keyword nasmInstructionAVX VMOVSS VMOVUPD VMOVUPS VMPSADBW VMULPD +syn keyword nasmInstructionAVX VMULPS VMULSD VMULSS VORPD VORPS +syn keyword nasmInstructionAVX VPABSB VPABSW VPABSD VPACKSSWB VPACKSSDW +syn keyword nasmInstructionAVX VPACKUSWB VPACKUSDW VPADDB VPADDW VPADDD +syn keyword nasmInstructionAVX VPADDQ VPADDSB VPADDSW VPADDUSB VPADDUSW +syn keyword nasmInstructionAVX VPALIGNR VPAND VPANDN VPAVGB VPAVGW +syn keyword nasmInstructionAVX VPBLENDVB VPBLENDW VPCMPESTRI VPCMPESTRM VPCMPISTRI +syn keyword nasmInstructionAVX VPCMPISTRM VPCMPEQB VPCMPEQW VPCMPEQD VPCMPEQQ +syn keyword nasmInstructionAVX VPCMPGTB VPCMPGTW VPCMPGTD VPCMPGTQ VPERMILPD +syn keyword nasmInstructionAVX VPERMILPS VPERM2F128 VPEXTRB VPEXTRW VPEXTRD +syn keyword nasmInstructionAVX VPEXTRQ VPHADDW VPHADDD VPHADDSW VPHMINPOSUW +syn keyword nasmInstructionAVX VPHSUBW VPHSUBD VPHSUBSW VPINSRB VPINSRW +syn keyword nasmInstructionAVX VPINSRD VPINSRQ VPMADDWD VPMADDUBSW VPMAXSB +syn keyword nasmInstructionAVX VPMAXSW VPMAXSD VPMAXUB VPMAXUW VPMAXUD +syn keyword nasmInstructionAVX VPMINSB VPMINSW VPMINSD VPMINUB VPMINUW +syn keyword nasmInstructionAVX VPMINUD VPMOVMSKB VPMOVSXBW VPMOVSXBD VPMOVSXBQ +syn keyword nasmInstructionAVX VPMOVSXWD VPMOVSXWQ VPMOVSXDQ VPMOVZXBW VPMOVZXBD +syn keyword nasmInstructionAVX VPMOVZXBQ VPMOVZXWD VPMOVZXWQ VPMOVZXDQ VPMULHUW +syn keyword nasmInstructionAVX VPMULHRSW VPMULHW VPMULLW VPMULLD VPMULUDQ +syn keyword nasmInstructionAVX VPMULDQ VPOR VPSADBW VPSHUFB VPSHUFD +syn keyword nasmInstructionAVX VPSHUFHW VPSHUFLW VPSIGNB VPSIGNW VPSIGND +syn keyword nasmInstructionAVX VPSLLDQ VPSRLDQ VPSLLW VPSLLD VPSLLQ +syn keyword nasmInstructionAVX VPSRAW VPSRAD VPSRLW VPSRLD VPSRLQ +syn keyword nasmInstructionAVX VPTEST VPSUBB VPSUBW VPSUBD VPSUBQ +syn keyword nasmInstructionAVX VPSUBSB VPSUBSW VPSUBUSB VPSUBUSW VPUNPCKHBW +syn keyword nasmInstructionAVX VPUNPCKHWD VPUNPCKHDQ VPUNPCKHQDQ VPUNPCKLBW VPUNPCKLWD +syn keyword nasmInstructionAVX VPUNPCKLDQ VPUNPCKLQDQ VPXOR VRCPPS VRCPSS +syn keyword nasmInstructionAVX VRSQRTPS VRSQRTSS VROUNDPD VROUNDPS VROUNDSD +syn keyword nasmInstructionAVX VROUNDSS VSHUFPD VSHUFPS VSQRTPD VSQRTPS +syn keyword nasmInstructionAVX VSQRTSD VSQRTSS VSTMXCSR VSUBPD VSUBPS +syn keyword nasmInstructionAVX VSUBSD VSUBSS VTESTPS VTESTPD VUCOMISD +syn keyword nasmInstructionAVX VUCOMISS VUNPCKHPD VUNPCKHPS VUNPCKLPD VUNPCKLPS +syn keyword nasmInstructionAVX VXORPD VXORPS VZEROALL VZEROUPPER +" INTEL_CMUL +syn keyword nasmInstructionINTEL_CMUL PCLMULLQLQDQ PCLMULHQLQDQ PCLMULLQHQDQ PCLMULHQHQDQ PCLMULQDQ +" INTEL_AVX_CMUL +syn keyword nasmInstructionINTEL_AVX_CMUL VPCLMULLQLQDQ VPCLMULHQLQDQ VPCLMULLQHQDQ VPCLMULHQHQDQ VPCLMULQDQ +syn keyword nasmInstructionINTEL_AVX_CMUL VPCLMULLQLQDQ VPCLMULHQLQDQ VPCLMULLQHQDQ VPCLMULHQHQDQ VPCLMULQDQ +syn keyword nasmInstructionINTEL_AVX_CMUL VPCLMULLQLQDQ VPCLMULHQLQDQ VPCLMULLQHQDQ VPCLMULHQHQDQ VPCLMULQDQ +syn keyword nasmInstructionINTEL_AVX_CMUL VPCLMULLQLQDQ VPCLMULHQLQDQ VPCLMULLQHQDQ VPCLMULHQHQDQ VPCLMULQDQ +syn keyword nasmInstructionINTEL_AVX_CMUL VPCLMULLQLQDQ VPCLMULHQLQDQ VPCLMULLQHQDQ VPCLMULHQHQDQ VPCLMULQDQ +" INTEL_FMA +syn keyword nasmInstructionINTEL_FMA VFMADD132PS VFMADD132PD VFMADD312PS VFMADD312PD VFMADD213PS +syn keyword nasmInstructionINTEL_FMA VFMADD213PD VFMADD123PS VFMADD123PD VFMADD231PS VFMADD231PD +syn keyword nasmInstructionINTEL_FMA VFMADD321PS VFMADD321PD VFMADDSUB132PS VFMADDSUB132PD VFMADDSUB312PS +syn keyword nasmInstructionINTEL_FMA VFMADDSUB312PD VFMADDSUB213PS VFMADDSUB213PD VFMADDSUB123PS VFMADDSUB123PD +syn keyword nasmInstructionINTEL_FMA VFMADDSUB231PS VFMADDSUB231PD VFMADDSUB321PS VFMADDSUB321PD VFMSUB132PS +syn keyword nasmInstructionINTEL_FMA VFMSUB132PD VFMSUB312PS VFMSUB312PD VFMSUB213PS VFMSUB213PD +syn keyword nasmInstructionINTEL_FMA VFMSUB123PS VFMSUB123PD VFMSUB231PS VFMSUB231PD VFMSUB321PS +syn keyword nasmInstructionINTEL_FMA VFMSUB321PD VFMSUBADD132PS VFMSUBADD132PD VFMSUBADD312PS VFMSUBADD312PD +syn keyword nasmInstructionINTEL_FMA VFMSUBADD213PS VFMSUBADD213PD VFMSUBADD123PS VFMSUBADD123PD VFMSUBADD231PS +syn keyword nasmInstructionINTEL_FMA VFMSUBADD231PD VFMSUBADD321PS VFMSUBADD321PD VFNMADD132PS VFNMADD132PD +syn keyword nasmInstructionINTEL_FMA VFNMADD312PS VFNMADD312PD VFNMADD213PS VFNMADD213PD VFNMADD123PS +syn keyword nasmInstructionINTEL_FMA VFNMADD123PD VFNMADD231PS VFNMADD231PD VFNMADD321PS VFNMADD321PD +syn keyword nasmInstructionINTEL_FMA VFNMSUB132PS VFNMSUB132PD VFNMSUB312PS VFNMSUB312PD VFNMSUB213PS +syn keyword nasmInstructionINTEL_FMA VFNMSUB213PD VFNMSUB123PS VFNMSUB123PD VFNMSUB231PS VFNMSUB231PD +syn keyword nasmInstructionINTEL_FMA VFNMSUB321PS VFNMSUB321PD VFMADD132SS VFMADD132SD VFMADD312SS +syn keyword nasmInstructionINTEL_FMA VFMADD312SD VFMADD213SS VFMADD213SD VFMADD123SS VFMADD123SD +syn keyword nasmInstructionINTEL_FMA VFMADD231SS VFMADD231SD VFMADD321SS VFMADD321SD VFMSUB132SS +syn keyword nasmInstructionINTEL_FMA VFMSUB132SD VFMSUB312SS VFMSUB312SD VFMSUB213SS VFMSUB213SD +syn keyword nasmInstructionINTEL_FMA VFMSUB123SS VFMSUB123SD VFMSUB231SS VFMSUB231SD VFMSUB321SS +syn keyword nasmInstructionINTEL_FMA VFMSUB321SD VFNMADD132SS VFNMADD132SD VFNMADD312SS VFNMADD312SD +syn keyword nasmInstructionINTEL_FMA VFNMADD213SS VFNMADD213SD VFNMADD123SS VFNMADD123SD VFNMADD231SS +syn keyword nasmInstructionINTEL_FMA VFNMADD231SD VFNMADD321SS VFNMADD321SD VFNMSUB132SS VFNMSUB132SD +syn keyword nasmInstructionINTEL_FMA VFNMSUB312SS VFNMSUB312SD VFNMSUB213SS VFNMSUB213SD VFNMSUB123SS +syn keyword nasmInstructionINTEL_FMA VFNMSUB123SD VFNMSUB231SS VFNMSUB231SD VFNMSUB321SS VFNMSUB321SD +" INTEL_POST32 +syn keyword nasmInstructionINTEL_POST32 RDFSBASE RDGSBASE RDRAND WRFSBASE WRGSBASE +syn keyword nasmInstructionINTEL_POST32 VCVTPH2PS VCVTPS2PH ADCX ADOX RDSEED +" SUPERVISOR +syn keyword nasmInstructionSUPERVISOR CLAC STAC +" VIA_SECURITY +syn keyword nasmInstructionVIA_SECURITY XSTORE XCRYPTECB XCRYPTCBC XCRYPTCTR XCRYPTCFB +syn keyword nasmInstructionVIA_SECURITY XCRYPTOFB MONTMUL XSHA1 XSHA256 +" AMD_PROFILING +syn keyword nasmInstructionAMD_PROFILING LLWPCB SLWPCB LWPVAL LWPINS +" XOP_FMA4 +syn keyword nasmInstructionXOP_FMA4 VFMADDPD VFMADDPS VFMADDSD VFMADDSS VFMADDSUBPD +syn keyword nasmInstructionXOP_FMA4 VFMADDSUBPS VFMSUBADDPD VFMSUBADDPS VFMSUBPD VFMSUBPS +syn keyword nasmInstructionXOP_FMA4 VFMSUBSD VFMSUBSS VFNMADDPD VFNMADDPS VFNMADDSD +syn keyword nasmInstructionXOP_FMA4 VFNMADDSS VFNMSUBPD VFNMSUBPS VFNMSUBSD VFNMSUBSS +syn keyword nasmInstructionXOP_FMA4 VFRCZPD VFRCZPS VFRCZSD VFRCZSS VPCMOV +syn keyword nasmInstructionXOP_FMA4 VPCOMB VPCOMD VPCOMQ VPCOMUB VPCOMUD +syn keyword nasmInstructionXOP_FMA4 VPCOMUQ VPCOMUW VPCOMW VPHADDBD VPHADDBQ +syn keyword nasmInstructionXOP_FMA4 VPHADDBW VPHADDDQ VPHADDUBD VPHADDUBQ VPHADDUBW +syn keyword nasmInstructionXOP_FMA4 VPHADDUDQ VPHADDUWD VPHADDUWQ VPHADDWD VPHADDWQ +syn keyword nasmInstructionXOP_FMA4 VPHSUBBW VPHSUBDQ VPHSUBWD VPMACSDD VPMACSDQH +syn keyword nasmInstructionXOP_FMA4 VPMACSDQL VPMACSSDD VPMACSSDQH VPMACSSDQL VPMACSSWD +syn keyword nasmInstructionXOP_FMA4 VPMACSSWW VPMACSWD VPMACSWW VPMADCSSWD VPMADCSWD +syn keyword nasmInstructionXOP_FMA4 VPPERM VPROTB VPROTD VPROTQ VPROTW +syn keyword nasmInstructionXOP_FMA4 VPSHAB VPSHAD VPSHAQ VPSHAW VPSHLB +syn keyword nasmInstructionXOP_FMA4 VPSHLD VPSHLQ VPSHLW +" AVX2 +syn keyword nasmInstructionAVX2 VMPSADBW VPABSB VPABSW VPABSD VPACKSSWB +syn keyword nasmInstructionAVX2 VPACKSSDW VPACKUSDW VPACKUSWB VPADDB VPADDW +syn keyword nasmInstructionAVX2 VPADDD VPADDQ VPADDSB VPADDSW VPADDUSB +syn keyword nasmInstructionAVX2 VPADDUSW VPALIGNR VPAND VPANDN VPAVGB +syn keyword nasmInstructionAVX2 VPAVGW VPBLENDVB VPBLENDW VPCMPEQB VPCMPEQW +syn keyword nasmInstructionAVX2 VPCMPEQD VPCMPEQQ VPCMPGTB VPCMPGTW VPCMPGTD +syn keyword nasmInstructionAVX2 VPCMPGTQ VPHADDW VPHADDD VPHADDSW VPHSUBW +syn keyword nasmInstructionAVX2 VPHSUBD VPHSUBSW VPMADDUBSW VPMADDWD VPMAXSB +syn keyword nasmInstructionAVX2 VPMAXSW VPMAXSD VPMAXUB VPMAXUW VPMAXUD +syn keyword nasmInstructionAVX2 VPMINSB VPMINSW VPMINSD VPMINUB VPMINUW +syn keyword nasmInstructionAVX2 VPMINUD VPMOVMSKB VPMOVSXBW VPMOVSXBD VPMOVSXBQ +syn keyword nasmInstructionAVX2 VPMOVSXWD VPMOVSXWQ VPMOVSXDQ VPMOVZXBW VPMOVZXBD +syn keyword nasmInstructionAVX2 VPMOVZXBQ VPMOVZXWD VPMOVZXWQ VPMOVZXDQ VPMULDQ +syn keyword nasmInstructionAVX2 VPMULHRSW VPMULHUW VPMULHW VPMULLW VPMULLD +syn keyword nasmInstructionAVX2 VPMULUDQ VPOR VPSADBW VPSHUFB VPSHUFD +syn keyword nasmInstructionAVX2 VPSHUFHW VPSHUFLW VPSIGNB VPSIGNW VPSIGND +syn keyword nasmInstructionAVX2 VPSLLDQ VPSLLW VPSLLD VPSLLQ VPSRAW +syn keyword nasmInstructionAVX2 VPSRAD VPSRLDQ VPSRLW VPSRLD VPSRLQ +syn keyword nasmInstructionAVX2 VPSUBB VPSUBW VPSUBD VPSUBQ VPSUBSB +syn keyword nasmInstructionAVX2 VPSUBSW VPSUBUSB VPSUBUSW VPUNPCKHBW VPUNPCKHWD +syn keyword nasmInstructionAVX2 VPUNPCKHDQ VPUNPCKHQDQ VPUNPCKLBW VPUNPCKLWD VPUNPCKLDQ +syn keyword nasmInstructionAVX2 VPUNPCKLQDQ VPXOR VMOVNTDQA VBROADCASTSS VBROADCASTSD +syn keyword nasmInstructionAVX2 VBROADCASTI128 VPBLENDD VPBROADCASTB VPBROADCASTW VPBROADCASTD +syn keyword nasmInstructionAVX2 VPBROADCASTQ VPERMD VPERMPD VPERMPS VPERMQ +syn keyword nasmInstructionAVX2 VPERM2I128 VEXTRACTI128 VINSERTI128 VPMASKMOVD VPMASKMOVQ +syn keyword nasmInstructionAVX2 VPMASKMOVD VPMASKMOVQ VPSLLVD VPSLLVQ VPSLLVD +syn keyword nasmInstructionAVX2 VPSLLVQ VPSRAVD VPSRLVD VPSRLVQ VPSRLVD +syn keyword nasmInstructionAVX2 VPSRLVQ VGATHERDPD VGATHERQPD VGATHERDPD VGATHERQPD +syn keyword nasmInstructionAVX2 VGATHERDPS VGATHERQPS VGATHERDPS VGATHERQPS VPGATHERDD +syn keyword nasmInstructionAVX2 VPGATHERQD VPGATHERDD VPGATHERQD VPGATHERDQ VPGATHERQQ +syn keyword nasmInstructionAVX2 VPGATHERDQ VPGATHERQQ +" TRANSACTIONS +syn keyword nasmInstructionTRANSACTIONS XABORT XBEGIN XEND XTEST +" BMI_ABM +syn keyword nasmInstructionBMI_ABM ANDN BEXTR BLCI BLCIC BLSI +syn keyword nasmInstructionBMI_ABM BLSIC BLCFILL BLSFILL BLCMSK BLSMSK +syn keyword nasmInstructionBMI_ABM BLSR BLCS BZHI MULX PDEP +syn keyword nasmInstructionBMI_ABM PEXT RORX SARX SHLX SHRX +syn keyword nasmInstructionBMI_ABM TZCNT TZMSK T1MSKC PREFETCHWT1 +" MPE +syn keyword nasmInstructionMPE BNDMK BNDCL BNDCU BNDCN BNDMOV +syn keyword nasmInstructionMPE BNDLDX BNDSTX +" SHA +syn keyword nasmInstructionSHA SHA1MSG1 SHA1MSG2 SHA1NEXTE SHA1RNDS4 SHA256MSG1 +syn keyword nasmInstructionSHA SHA256MSG2 SHA256RNDS2 VSHA512MSG1 VSHA512MSG2 VSHA512RNDS2 +" SM3 +syn keyword nasmInstructionSM3 VSM3MSG1 VSM3MSG2 VSM3RNDS2 +" SM4 +syn keyword nasmInstructionSM4 VSM4KEY4 VSM4RNDS4 +" AVX_NOEXCEPT +syn keyword nasmInstructionAVX_NOEXCEPT VBCSTNEBF16PS VBCSTNESH2PS VCVTNEEBF162PS VCVTNEEPH2PS VCVTNEOBF162PS +syn keyword nasmInstructionAVX_NOEXCEPT VCVTNEOPH2PS VCVTNEPS2BF16 +" AVX_VECTOR_NN +syn keyword nasmInstructionAVX_VECTOR_NN VPDPBSSD VPDPBSSDS VPDPBSUD VPDPBSUDS VPDPBUUD +syn keyword nasmInstructionAVX_VECTOR_NN VPDPBUUDS +" AVX_IFMA +syn keyword nasmInstructionAVX_IFMA VPMADD52HUQ VPMADD52LUQ +" AVX512_MASK +syn keyword nasmInstructionAVX512_MASK KADDB KADDD KADDQ KADDW KANDB +syn keyword nasmInstructionAVX512_MASK KANDD KANDNB KANDND KANDNQ KANDNW +syn keyword nasmInstructionAVX512_MASK KANDQ KANDW KMOVB KMOVD KMOVQ +syn keyword nasmInstructionAVX512_MASK KMOVW KNOTB KNOTD KNOTQ KNOTW +syn keyword nasmInstructionAVX512_MASK KORB KORD KORQ KORW KORTESTB +syn keyword nasmInstructionAVX512_MASK KORTESTD KORTESTQ KORTESTW KSHIFTLB KSHIFTLD +syn keyword nasmInstructionAVX512_MASK KSHIFTLQ KSHIFTLW KSHIFTRB KSHIFTRD KSHIFTRQ +syn keyword nasmInstructionAVX512_MASK KSHIFTRW KTESTB KTESTD KTESTQ KTESTW +syn keyword nasmInstructionAVX512_MASK KUNPCKBW KUNPCKDQ KUNPCKWD KXNORB KXNORD +syn keyword nasmInstructionAVX512_MASK KXNORQ KXNORW KXORB KXORD KXORQ +syn keyword nasmInstructionAVX512_MASK KXORW +" AVX512_MASK_REG +syn keyword nasmInstructionAVX512_MASK_REG KADD KAND KANDN KAND KMOV +syn keyword nasmInstructionAVX512_MASK_REG KNOT KOR KORTEST KSHIFTL KSHIFTR +syn keyword nasmInstructionAVX512_MASK_REG KTEST KUNPCK KXNOR KXOR +" AVX512 +syn keyword nasmInstructionAVX512 VADDPD VADDPS VADDSD VADDSS VALIGND +syn keyword nasmInstructionAVX512 VALIGNQ VANDNPD VANDNPS VANDPD VANDPS +syn keyword nasmInstructionAVX512 VBLENDMPD VBLENDMPS VBROADCASTF32X2 VBROADCASTF32X4 VBROADCASTF32X8 +syn keyword nasmInstructionAVX512 VBROADCASTF64X2 VBROADCASTF64X4 VBROADCASTI32X2 VBROADCASTI32X4 VBROADCASTI32X8 +syn keyword nasmInstructionAVX512 VBROADCASTI64X2 VBROADCASTI64X4 VBROADCASTSD VBROADCASTSS VCMPEQPD +syn keyword nasmInstructionAVX512 VCMPEQPS VCMPEQSD VCMPEQSS VCMPEQ_OQPD VCMPEQ_OQPS +syn keyword nasmInstructionAVX512 VCMPEQ_OQSD VCMPEQ_OQSS VCMPLTPD VCMPLTPS VCMPLTSD +syn keyword nasmInstructionAVX512 VCMPLTSS VCMPLT_OSPD VCMPLT_OSPS VCMPLT_OSSD VCMPLT_OSSS +syn keyword nasmInstructionAVX512 VCMPLEPD VCMPLEPS VCMPLESD VCMPLESS VCMPLE_OSPD +syn keyword nasmInstructionAVX512 VCMPLE_OSPS VCMPLE_OSSD VCMPLE_OSSS VCMPUNORDPD VCMPUNORDPS +syn keyword nasmInstructionAVX512 VCMPUNORDSD VCMPUNORDSS VCMPUNORD_QPD VCMPUNORD_QPS VCMPUNORD_QSD +syn keyword nasmInstructionAVX512 VCMPUNORD_QSS VCMPNEQPD VCMPNEQPS VCMPNEQSD VCMPNEQSS +syn keyword nasmInstructionAVX512 VCMPNEQ_UQPD VCMPNEQ_UQPS VCMPNEQ_UQSD VCMPNEQ_UQSS VCMPNLTPD +syn keyword nasmInstructionAVX512 VCMPNLTPS VCMPNLTSD VCMPNLTSS VCMPNLT_USPD VCMPNLT_USPS +syn keyword nasmInstructionAVX512 VCMPNLT_USSD VCMPNLT_USSS VCMPNLEPD VCMPNLEPS VCMPNLESD +syn keyword nasmInstructionAVX512 VCMPNLESS VCMPNLE_USPD VCMPNLE_USPS VCMPNLE_USSD VCMPNLE_USSS +syn keyword nasmInstructionAVX512 VCMPORDPD VCMPORDPS VCMPORDSD VCMPORDSS VCMPORD_QPD +syn keyword nasmInstructionAVX512 VCMPORD_QPS VCMPORD_QSD VCMPORD_QSS VCMPEQ_UQPD VCMPEQ_UQPS +syn keyword nasmInstructionAVX512 VCMPEQ_UQSD VCMPEQ_UQSS VCMPNGEPD VCMPNGEPS VCMPNGESD +syn keyword nasmInstructionAVX512 VCMPNGESS VCMPNGE_USPD VCMPNGE_USPS VCMPNGE_USSD VCMPNGE_USSS +syn keyword nasmInstructionAVX512 VCMPNGTPD VCMPNGTPS VCMPNGTSD VCMPNGTSS VCMPNGT_USPD +syn keyword nasmInstructionAVX512 VCMPNGT_USPS VCMPNGT_USSD VCMPNGT_USSS VCMPFALSEPD VCMPFALSEPS +syn keyword nasmInstructionAVX512 VCMPFALSESD VCMPFALSESS VCMPFALSE_OQPD VCMPFALSE_OQPS VCMPFALSE_OQSD +syn keyword nasmInstructionAVX512 VCMPFALSE_OQSS VCMPNEQ_OQPD VCMPNEQ_OQPS VCMPNEQ_OQSD VCMPNEQ_OQSS +syn keyword nasmInstructionAVX512 VCMPGEPD VCMPGEPS VCMPGESD VCMPGESS VCMPGE_OSPD +syn keyword nasmInstructionAVX512 VCMPGE_OSPS VCMPGE_OSSD VCMPGE_OSSS VCMPGTPD VCMPGTPS +syn keyword nasmInstructionAVX512 VCMPGTSD VCMPGTSS VCMPGT_OSPD VCMPGT_OSPS VCMPGT_OSSD +syn keyword nasmInstructionAVX512 VCMPGT_OSSS VCMPTRUEPD VCMPTRUEPS VCMPTRUESD VCMPTRUESS +syn keyword nasmInstructionAVX512 VCMPTRUE_UQPD VCMPTRUE_UQPS VCMPTRUE_UQSD VCMPTRUE_UQSS VCMPEQ_OSPD +syn keyword nasmInstructionAVX512 VCMPEQ_OSPS VCMPEQ_OSSD VCMPEQ_OSSS VCMPLT_OQPD VCMPLT_OQPS +syn keyword nasmInstructionAVX512 VCMPLT_OQSD VCMPLT_OQSS VCMPLE_OQPD VCMPLE_OQPS VCMPLE_OQSD +syn keyword nasmInstructionAVX512 VCMPLE_OQSS VCMPUNORD_SPD VCMPUNORD_SPS VCMPUNORD_SSD VCMPUNORD_SSS +syn keyword nasmInstructionAVX512 VCMPNEQ_USPD VCMPNEQ_USPS VCMPNEQ_USSD VCMPNEQ_USSS VCMPNLT_UQPD +syn keyword nasmInstructionAVX512 VCMPNLT_UQPS VCMPNLT_UQSD VCMPNLT_UQSS VCMPNLE_UQPD VCMPNLE_UQPS +syn keyword nasmInstructionAVX512 VCMPNLE_UQSD VCMPNLE_UQSS VCMPORD_SPD VCMPORD_SPS VCMPORD_SSD +syn keyword nasmInstructionAVX512 VCMPORD_SSS VCMPEQ_USPD VCMPEQ_USPS VCMPEQ_USSD VCMPEQ_USSS +syn keyword nasmInstructionAVX512 VCMPNGE_UQPD VCMPNGE_UQPS VCMPNGE_UQSD VCMPNGE_UQSS VCMPNGT_UQPD +syn keyword nasmInstructionAVX512 VCMPNGT_UQPS VCMPNGT_UQSD VCMPNGT_UQSS VCMPFALSE_OSPD VCMPFALSE_OSPS +syn keyword nasmInstructionAVX512 VCMPFALSE_OSSD VCMPFALSE_OSSS VCMPNEQ_OSPD VCMPNEQ_OSPS VCMPNEQ_OSSD +syn keyword nasmInstructionAVX512 VCMPNEQ_OSSS VCMPGE_OQPD VCMPGE_OQPS VCMPGE_OQSD VCMPGE_OQSS +syn keyword nasmInstructionAVX512 VCMPGT_OQPD VCMPGT_OQPS VCMPGT_OQSD VCMPGT_OQSS VCMPTRUE_USPD +syn keyword nasmInstructionAVX512 VCMPTRUE_USPS VCMPTRUE_USSD VCMPTRUE_USSS VCMPPD VCMPPS +syn keyword nasmInstructionAVX512 VCMPSD VCMPSS VCOMISD VCOMISS VCOMPRESSPD +syn keyword nasmInstructionAVX512 VCOMPRESSPS VCVTDQ2PD VCVTDQ2PS VCVTPD2DQ VCVTPD2PS +syn keyword nasmInstructionAVX512 VCVTPD2QQ VCVTPD2UDQ VCVTPD2UQQ VCVTPH2PS VCVTPS2DQ +syn keyword nasmInstructionAVX512 VCVTPS2PD VCVTPS2PH VCVTPS2QQ VCVTPS2UDQ VCVTPS2UQQ +syn keyword nasmInstructionAVX512 VCVTQQ2PD VCVTQQ2PS VCVTSD2SI VCVTSD2SS VCVTSD2USI +syn keyword nasmInstructionAVX512 VCVTSI2SD VCVTSI2SS VCVTSS2SD VCVTSS2SI VCVTSS2USI +syn keyword nasmInstructionAVX512 VCVTTPD2DQ VCVTTPD2QQ VCVTTPD2UDQ VCVTTPD2UQQ VCVTTPS2DQ +syn keyword nasmInstructionAVX512 VCVTTPS2QQ VCVTTPS2UDQ VCVTTPS2UQQ VCVTTSD2SI VCVTTSD2USI +syn keyword nasmInstructionAVX512 VCVTTSS2SI VCVTTSS2USI VCVTUDQ2PD VCVTUDQ2PS VCVTUQQ2PD +syn keyword nasmInstructionAVX512 VCVTUQQ2PS VCVTUSI2SD VCVTUSI2SS VDBPSADBW VDIVPD +syn keyword nasmInstructionAVX512 VDIVPS VDIVSD VDIVSS VEXP2PD VEXP2PS +syn keyword nasmInstructionAVX512 VEXPANDPD VEXPANDPS VEXTRACTF32X4 VEXTRACTF32X8 VEXTRACTF64X2 +syn keyword nasmInstructionAVX512 VEXTRACTF64X4 VEXTRACTI32X4 VEXTRACTI32X8 VEXTRACTI64X2 VEXTRACTI64X4 +syn keyword nasmInstructionAVX512 VEXTRACTPS VFIXUPIMMPD VFIXUPIMMPS VFIXUPIMMSD VFIXUPIMMSS +syn keyword nasmInstructionAVX512 VFMADD132PD VFMADD132PS VFMADD132SD VFMADD132SS VFMADD213PD +syn keyword nasmInstructionAVX512 VFMADD213PS VFMADD213SD VFMADD213SS VFMADD231PD VFMADD231PS +syn keyword nasmInstructionAVX512 VFMADD231SD VFMADD231SS VFMADDSUB132PD VFMADDSUB132PS VFMADDSUB213PD +syn keyword nasmInstructionAVX512 VFMADDSUB213PS VFMADDSUB231PD VFMADDSUB231PS VFMSUB132PD VFMSUB132PS +syn keyword nasmInstructionAVX512 VFMSUB132SD VFMSUB132SS VFMSUB213PD VFMSUB213PS VFMSUB213SD +syn keyword nasmInstructionAVX512 VFMSUB213SS VFMSUB231PD VFMSUB231PS VFMSUB231SD VFMSUB231SS +syn keyword nasmInstructionAVX512 VFMSUBADD132PD VFMSUBADD132PS VFMSUBADD213PD VFMSUBADD213PS VFMSUBADD231PD +syn keyword nasmInstructionAVX512 VFMSUBADD231PS VFNMADD132PD VFNMADD132PS VFNMADD132SD VFNMADD132SS +syn keyword nasmInstructionAVX512 VFNMADD213PD VFNMADD213PS VFNMADD213SD VFNMADD213SS VFNMADD231PD +syn keyword nasmInstructionAVX512 VFNMADD231PS VFNMADD231SD VFNMADD231SS VFNMSUB132PD VFNMSUB132PS +syn keyword nasmInstructionAVX512 VFNMSUB132SD VFNMSUB132SS VFNMSUB213PD VFNMSUB213PS VFNMSUB213SD +syn keyword nasmInstructionAVX512 VFNMSUB213SS VFNMSUB231PD VFNMSUB231PS VFNMSUB231SD VFNMSUB231SS +syn keyword nasmInstructionAVX512 VFPCLASSPD VFPCLASSPS VFPCLASSSD VFPCLASSSS VGATHERDPD +syn keyword nasmInstructionAVX512 VGATHERDPS VGATHERPF0DPD VGATHERPF0DPS VGATHERPF0QPD VGATHERPF0QPS +syn keyword nasmInstructionAVX512 VGATHERPF1DPD VGATHERPF1DPS VGATHERPF1QPD VGATHERPF1QPS VGATHERQPD +syn keyword nasmInstructionAVX512 VGATHERQPS VGETEXPPD VGETEXPPS VGETEXPSD VGETEXPSS +syn keyword nasmInstructionAVX512 VGETMANTPD VGETMANTPS VGETMANTSD VGETMANTSS VINSERTF32X4 +syn keyword nasmInstructionAVX512 VINSERTF32X8 VINSERTF64X2 VINSERTF64X4 VINSERTI32X4 VINSERTI32X8 +syn keyword nasmInstructionAVX512 VINSERTI64X2 VINSERTI64X4 VINSERTPS VMAXPD VMAXPS +syn keyword nasmInstructionAVX512 VMAXSD VMAXSS VMINPD VMINPS VMINSD +syn keyword nasmInstructionAVX512 VMINSS VMOVAPD VMOVAPS VMOVD VMOVDDUP +syn keyword nasmInstructionAVX512 VMOVDQA32 VMOVDQA64 VMOVDQU16 VMOVDQU32 VMOVDQU64 +syn keyword nasmInstructionAVX512 VMOVDQU8 VMOVHLPS VMOVHPD VMOVHPS VMOVLHPS +syn keyword nasmInstructionAVX512 VMOVLPD VMOVLPS VMOVNTDQ VMOVNTDQA VMOVNTPD +syn keyword nasmInstructionAVX512 VMOVNTPS VMOVQ VMOVSD VMOVSHDUP VMOVSLDUP +syn keyword nasmInstructionAVX512 VMOVSS VMOVUPD VMOVUPS VMULPD VMULPS +syn keyword nasmInstructionAVX512 VMULSD VMULSS VORPD VORPS VPABSB +syn keyword nasmInstructionAVX512 VPABSD VPABSQ VPABSW VPACKSSDW VPACKSSWB +syn keyword nasmInstructionAVX512 VPACKUSDW VPACKUSWB VPADDB VPADDD VPADDQ +syn keyword nasmInstructionAVX512 VPADDSB VPADDSW VPADDUSB VPADDUSW VPADDW +syn keyword nasmInstructionAVX512 VPALIGNR VPANDD VPANDND VPANDNQ VPANDQ +syn keyword nasmInstructionAVX512 VPAVGB VPAVGW VPBLENDMB VPBLENDMD VPBLENDMQ +syn keyword nasmInstructionAVX512 VPBLENDMW VPBROADCASTB VPBROADCASTD VPBROADCASTMB2Q VPBROADCASTMW2D +syn keyword nasmInstructionAVX512 VPBROADCASTQ VPBROADCASTW VPCMPEQB VPCMPEQD VPCMPEQQ +syn keyword nasmInstructionAVX512 VPCMPEQW VPCMPGTB VPCMPGTD VPCMPGTQ VPCMPGTW +syn keyword nasmInstructionAVX512 VPCMPEQB VPCMPEQD VPCMPEQQ VPCMPEQUB VPCMPEQUD +syn keyword nasmInstructionAVX512 VPCMPEQUQ VPCMPEQUW VPCMPEQW VPCMPGEB VPCMPGED +syn keyword nasmInstructionAVX512 VPCMPGEQ VPCMPGEUB VPCMPGEUD VPCMPGEUQ VPCMPGEUW +syn keyword nasmInstructionAVX512 VPCMPGEW VPCMPGTB VPCMPGTD VPCMPGTQ VPCMPGTUB +syn keyword nasmInstructionAVX512 VPCMPGTUD VPCMPGTUQ VPCMPGTUW VPCMPGTW VPCMPLEB +syn keyword nasmInstructionAVX512 VPCMPLED VPCMPLEQ VPCMPLEUB VPCMPLEUD VPCMPLEUQ +syn keyword nasmInstructionAVX512 VPCMPLEUW VPCMPLEW VPCMPLTB VPCMPLTD VPCMPLTQ +syn keyword nasmInstructionAVX512 VPCMPLTUB VPCMPLTUD VPCMPLTUQ VPCMPLTUW VPCMPLTW +syn keyword nasmInstructionAVX512 VPCMPNEQB VPCMPNEQD VPCMPNEQQ VPCMPNEQUB VPCMPNEQUD +syn keyword nasmInstructionAVX512 VPCMPNEQUQ VPCMPNEQUW VPCMPNEQW VPCMPNGTB VPCMPNGTD +syn keyword nasmInstructionAVX512 VPCMPNGTQ VPCMPNGTUB VPCMPNGTUD VPCMPNGTUQ VPCMPNGTUW +syn keyword nasmInstructionAVX512 VPCMPNGTW VPCMPNLEB VPCMPNLED VPCMPNLEQ VPCMPNLEUB +syn keyword nasmInstructionAVX512 VPCMPNLEUD VPCMPNLEUQ VPCMPNLEUW VPCMPNLEW VPCMPNLTB +syn keyword nasmInstructionAVX512 VPCMPNLTD VPCMPNLTQ VPCMPNLTUB VPCMPNLTUD VPCMPNLTUQ +syn keyword nasmInstructionAVX512 VPCMPNLTUW VPCMPNLTW VPCMPB VPCMPD VPCMPQ +syn keyword nasmInstructionAVX512 VPCMPUB VPCMPUD VPCMPUQ VPCMPUW VPCMPW +syn keyword nasmInstructionAVX512 VPCOMPRESSD VPCOMPRESSQ VPCONFLICTD VPCONFLICTQ VPERMB +syn keyword nasmInstructionAVX512 VPERMD VPERMI2B VPERMI2D VPERMI2PD VPERMI2PS +syn keyword nasmInstructionAVX512 VPERMI2Q VPERMI2W VPERMILPD VPERMILPS VPERMPD +syn keyword nasmInstructionAVX512 VPERMPS VPERMQ VPERMT2B VPERMT2D VPERMT2PD +syn keyword nasmInstructionAVX512 VPERMT2PS VPERMT2Q VPERMT2W VPERMW VPEXPANDD +syn keyword nasmInstructionAVX512 VPEXPANDQ VPEXTRB VPEXTRD VPEXTRQ VPEXTRW +syn keyword nasmInstructionAVX512 VPGATHERDD VPGATHERDQ VPGATHERQD VPGATHERQQ VPINSRB +syn keyword nasmInstructionAVX512 VPINSRD VPINSRQ VPINSRW VPLZCNTD VPLZCNTQ +syn keyword nasmInstructionAVX512 VPMADD52HUQ VPMADD52LUQ VPMADDUBSW VPMADDWD VPMAXSB +syn keyword nasmInstructionAVX512 VPMAXSD VPMAXSQ VPMAXSW VPMAXUB VPMAXUD +syn keyword nasmInstructionAVX512 VPMAXUQ VPMAXUW VPMINSB VPMINSD VPMINSQ +syn keyword nasmInstructionAVX512 VPMINSW VPMINUB VPMINUD VPMINUQ VPMINUW +syn keyword nasmInstructionAVX512 VPMOVB2M VPMOVD2M VPMOVDB VPMOVDW VPMOVM2B +syn keyword nasmInstructionAVX512 VPMOVM2D VPMOVM2Q VPMOVM2W VPMOVQ2M VPMOVQB +syn keyword nasmInstructionAVX512 VPMOVQD VPMOVQW VPMOVSDB VPMOVSDW VPMOVSQB +syn keyword nasmInstructionAVX512 VPMOVSQD VPMOVSQW VPMOVSWB VPMOVSXBD VPMOVSXBQ +syn keyword nasmInstructionAVX512 VPMOVSXBW VPMOVSXDQ VPMOVSXWD VPMOVSXWQ VPMOVUSDB +syn keyword nasmInstructionAVX512 VPMOVUSDW VPMOVUSQB VPMOVUSQD VPMOVUSQW VPMOVUSWB +syn keyword nasmInstructionAVX512 VPMOVW2M VPMOVWB VPMOVZXBD VPMOVZXBQ VPMOVZXBW +syn keyword nasmInstructionAVX512 VPMOVZXDQ VPMOVZXWD VPMOVZXWQ VPMULDQ VPMULHRSW +syn keyword nasmInstructionAVX512 VPMULHUW VPMULHW VPMULLD VPMULLQ VPMULLW +syn keyword nasmInstructionAVX512 VPMULTISHIFTQB VPMULUDQ VPORD VPORQ VPROLD +syn keyword nasmInstructionAVX512 VPROLQ VPROLVD VPROLVQ VPRORD VPRORQ +syn keyword nasmInstructionAVX512 VPRORVD VPRORVQ VPSADBW VPSCATTERDD VPSCATTERDQ +syn keyword nasmInstructionAVX512 VPSCATTERQD VPSCATTERQQ VPSHUFB VPSHUFD VPSHUFHW +syn keyword nasmInstructionAVX512 VPSHUFLW VPSLLD VPSLLDQ VPSLLQ VPSLLVD +syn keyword nasmInstructionAVX512 VPSLLVQ VPSLLVW VPSLLW VPSRAD VPSRAQ +syn keyword nasmInstructionAVX512 VPSRAVD VPSRAVQ VPSRAVW VPSRAW VPSRLD +syn keyword nasmInstructionAVX512 VPSRLDQ VPSRLQ VPSRLVD VPSRLVQ VPSRLVW +syn keyword nasmInstructionAVX512 VPSRLW VPSUBB VPSUBD VPSUBQ VPSUBSB +syn keyword nasmInstructionAVX512 VPSUBSW VPSUBUSB VPSUBUSW VPSUBW VPTERNLOGD +syn keyword nasmInstructionAVX512 VPTERNLOGQ VPTESTMB VPTESTMD VPTESTMQ VPTESTMW +syn keyword nasmInstructionAVX512 VPTESTNMB VPTESTNMD VPTESTNMQ VPTESTNMW VPUNPCKHBW +syn keyword nasmInstructionAVX512 VPUNPCKHDQ VPUNPCKHQDQ VPUNPCKHWD VPUNPCKLBW VPUNPCKLDQ +syn keyword nasmInstructionAVX512 VPUNPCKLQDQ VPUNPCKLWD VPXORD VPXORQ VRANGEPD +syn keyword nasmInstructionAVX512 VRANGEPS VRANGESD VRANGESS VRCP14PD VRCP14PS +syn keyword nasmInstructionAVX512 VRCP14SD VRCP14SS VRCP28PD VRCP28PS VRCP28SD +syn keyword nasmInstructionAVX512 VRCP28SS VREDUCEPD VREDUCEPS VREDUCESD VREDUCESS +syn keyword nasmInstructionAVX512 VRNDSCALEPD VRNDSCALEPS VRNDSCALESD VRNDSCALESS VRSQRT14PD +syn keyword nasmInstructionAVX512 VRSQRT14PS VRSQRT14SD VRSQRT14SS VRSQRT28PD VRSQRT28PS +syn keyword nasmInstructionAVX512 VRSQRT28SD VRSQRT28SS VSCALEFPD VSCALEFPS VSCALEFSD +syn keyword nasmInstructionAVX512 VSCALEFSS VSCATTERDPD VSCATTERDPS VSCATTERPF0DPD VSCATTERPF0DPS +syn keyword nasmInstructionAVX512 VSCATTERPF0QPD VSCATTERPF0QPS VSCATTERPF1DPD VSCATTERPF1DPS VSCATTERPF1QPD +syn keyword nasmInstructionAVX512 VSCATTERPF1QPS VSCATTERQPD VSCATTERQPS VSHUFF32X4 VSHUFF64X2 +syn keyword nasmInstructionAVX512 VSHUFI32X4 VSHUFI64X2 VSHUFPD VSHUFPS VSQRTPD +syn keyword nasmInstructionAVX512 VSQRTPS VSQRTSD VSQRTSS VSUBPD VSUBPS +syn keyword nasmInstructionAVX512 VSUBSD VSUBSS VUCOMISD VUCOMISS VUNPCKHPD +syn keyword nasmInstructionAVX512 VUNPCKHPS VUNPCKLPD VUNPCKLPS VXORPD VXORPS +" PROTECTION +syn keyword nasmInstructionPROTECTION RDPKRU WRPKRU +" RDPID +syn keyword nasmInstructionRDPID RDPID +" NMEM +syn keyword nasmInstructionNMEM CLFLUSHOPT CLWB PCOMMIT +syn keyword nasmInstructionNMEM CLZERO +" INTEL_EXTENSIONS +syn keyword nasmInstructionINTEL_EXTENSIONS CLDEMOTE MOVDIRI MOVDIR64B PCONFIG TPAUSE +syn keyword nasmInstructionINTEL_EXTENSIONS UMONITOR UMWAIT WBNOINVD +" GALOISFIELD +syn keyword nasmInstructionGALOISFIELD GF2P8AFFINEINVQB VGF2P8AFFINEINVQB GF2P8AFFINEQB VGF2P8AFFINEQB GF2P8MULB +syn keyword nasmInstructionGALOISFIELD VGF2P8MULB +" AVX512_BMI +syn keyword nasmInstructionAVX512_BMI VPCOMPRESSB VPCOMPRESSW VPEXPANDB VPEXPANDW VPSHLDW +syn keyword nasmInstructionAVX512_BMI VPSHLDD VPSHLDQ VPSHLDVW VPSHLDVD VPSHLDVQ +syn keyword nasmInstructionAVX512_BMI VPSHRDW VPSHRDD VPSHRDQ VPSHRDVW VPSHRDVD +syn keyword nasmInstructionAVX512_BMI VPSHRDVQ +" AVX512_VNNI +syn keyword nasmInstructionAVX512_VNNI VPDPBUSD VPDPBUSDS VPDPWSSD VPDPWSSDS +" AVX512_BITALG +syn keyword nasmInstructionAVX512_BITALG VPOPCNTB VPOPCNTW VPOPCNTD VPOPCNTQ VPSHUFBITQMB +" AVX512_FMA +syn keyword nasmInstructionAVX512_FMA V4FMADDPS V4FNMADDPS V4FMADDSS V4FNMADDSS +" AVX512_DP +syn keyword nasmInstructionAVX512_DP V4DPWSSDS V4DPWSSD +" SGX +syn keyword nasmInstructionSGX ENCLS ENCLU ENCLV +" CET +syn keyword nasmInstructionCET CLRSSBSY ENDBR32 ENDBR64 INCSSPD INCSSPQ +syn keyword nasmInstructionCET RDSSPD RDSSPQ RSTORSSP SAVEPREVSSP SETSSBSY +syn keyword nasmInstructionCET WRUSSD WRUSSQ WRSSD WRSSQ +" INTEL_EXTENSION +syn keyword nasmInstructionINTEL_EXTENSION ENQCMD ENQCMDS PCONFIG SERIALIZE WBNOINVD +syn keyword nasmInstructionINTEL_EXTENSION XRESLDTRK XSUSLDTRK +" AVX512_BF16 +syn keyword nasmInstructionAVX512_BF16 VCVTNE2PS2BF16 VCVTNEPS2BF16 VDPBF16PS +" AVX512_MASK_INTERSECT +syn keyword nasmInstructionAVX512_MASK_INTERSECT VP2INTERSECTD +" AMX +syn keyword nasmInstructionAMX LDTILECFG STTILECFG TDPBF16PS TDPBSSD TDPBSUD +syn keyword nasmInstructionAMX TDPBUSD TDPBUUD TILELOADD TILELOADDT1 TILERELEASE +syn keyword nasmInstructionAMX TILESTORED TILEZERO +" AVX512_FP16 +syn keyword nasmInstructionAVX512_FP16 VADDPH VADDSH VCMPPH VCMPSH VCOMISH +syn keyword nasmInstructionAVX512_FP16 VCVTDQ2PH VCVTPD2PH VCVTPH2DQ VCVTPH2PD VCVTPH2PS +syn keyword nasmInstructionAVX512_FP16 VCVTPH2PSX VCVTPH2QQ VCVTPH2UDQ VCVTPH2UQQ VCVTPH2UW +syn keyword nasmInstructionAVX512_FP16 VCVTPH2W VCVTPS2PH VCVTQQ2PH VCVTSD2SH VCVTSH2SD +syn keyword nasmInstructionAVX512_FP16 VCVTSH2SI VCVTSH2SS VCVTSH2USI VCVTSI2SH VCVTSS2SH +syn keyword nasmInstructionAVX512_FP16 VCVTTPH2DQ VCVTTPH2QQ VCVTTPH2UDQ VCVTTPH2UQQ VCVTTPH2UW +syn keyword nasmInstructionAVX512_FP16 VCVTTPH2W VCVTTSH2SI VCVTTSH2USI VCVTUDQ2PH VCVTUQQ2PH +syn keyword nasmInstructionAVX512_FP16 VCVTUSI2SH VCVTUSI2SS VCVTUW2PH VCVTW2PH VDIVPH +syn keyword nasmInstructionAVX512_FP16 VDIVSH VFCMADDCPH VFMADDCPH VFCMADDCSH VFMADDCSH +syn keyword nasmInstructionAVX512_FP16 VFCMULCPCH VFMULCPCH VFCMULCSH VFMULCSH VFMADDSUB132PH +syn keyword nasmInstructionAVX512_FP16 VFMADDSUB213PH VFMADDSUB231PH VFMSUBADD132PH VFMSUBADD213PH VFMSUBADD231PH +syn keyword nasmInstructionAVX512_FP16 VPMADD132PH VPMADD213PH VPMADD231PH VFMADD132PH VFMADD213PH +syn keyword nasmInstructionAVX512_FP16 VFMADD231PH VPMADD132SH VPMADD213SH VPMADD231SH VPNMADD132SH +syn keyword nasmInstructionAVX512_FP16 VPNMADD213SH VPNMADD231SH VPMSUB132PH VPMSUB213PH VPMSUB231PH +syn keyword nasmInstructionAVX512_FP16 VFMSUB132PH VFMSUB213PH VFMSUB231PH VPMSUB132SH VPMSUB213SH +syn keyword nasmInstructionAVX512_FP16 VPMSUB231SH VPNMSUB132SH VPNMSUB213SH VPNMSUB231SH VFPCLASSPH +syn keyword nasmInstructionAVX512_FP16 VFPCLASSSH VGETEXPPH VGETEXPSH VGETMANTPH VGETMANTSH +syn keyword nasmInstructionAVX512_FP16 VGETMAXPH VGETMAXSH VGETMINPH VGETMINSH VMOVSH +syn keyword nasmInstructionAVX512_FP16 VMOVW VMULPH VMULSH VRCPPH VRCPSH +syn keyword nasmInstructionAVX512_FP16 VREDUCEPH VREDUCESH VENDSCALEPH VENDSCALESH VRSQRTPH +syn keyword nasmInstructionAVX512_FP16 VRSQRTSH VSCALEFPH VSCALEFSH VSQRTPH VSQRTSH +syn keyword nasmInstructionAVX512_FP16 VSUBPH VSUBSH VUCOMISH +" RAO-INT +syn keyword nasmInstructionRAO_INT AADD AAND AXOR +" USERINT +syn keyword nasmInstructionUSERINT CLUI SENDUIPI STUI TESTUI UIRET +" CMPCCXADD +syn keyword nasmInstructionCMPCCXADD CMPOXADD CMPNOXADD CMPBXADD CMPNBXADD CMPZXADD +syn keyword nasmInstructionCMPCCXADD CMPNZXADD CMPBEXADD CMPNBEXADD CMPSXADD CMPNSXADD +syn keyword nasmInstructionCMPCCXADD CMPPXADD CMPNPXADD CMPLXADD CMPNLXADD CMPLEXADD +syn keyword nasmInstructionCMPCCXADD CMPNLEXADD +" FRET +syn keyword nasmInstructionFRET ERETS ERETU LKGS +" WRMSRNS_MSRLIST +syn keyword nasmInstructionWRMSRNS_MSRLIST WRMSRNS RDMSRLIST WRMSRLIST +" HRESET +syn keyword nasmInstructionHRESET HRESET +" PTWRITE +syn keyword nasmInstructionPTWRITE PTWRITE +" HINTNOP +syn keyword nasmInstructionHINTNOP HINT_NOP0 HINT_NOP1 HINT_NOP2 HINT_NOP3 HINT_NOP4 +syn keyword nasmInstructionHINTNOP HINT_NOP5 HINT_NOP6 HINT_NOP7 HINT_NOP8 HINT_NOP9 +syn keyword nasmInstructionHINTNOP HINT_NOP10 HINT_NOP11 HINT_NOP12 HINT_NOP13 HINT_NOP14 +syn keyword nasmInstructionHINTNOP HINT_NOP15 HINT_NOP16 HINT_NOP17 HINT_NOP18 HINT_NOP19 +syn keyword nasmInstructionHINTNOP HINT_NOP20 HINT_NOP21 HINT_NOP22 HINT_NOP23 HINT_NOP24 +syn keyword nasmInstructionHINTNOP HINT_NOP25 HINT_NOP26 HINT_NOP27 HINT_NOP28 HINT_NOP29 +syn keyword nasmInstructionHINTNOP HINT_NOP30 HINT_NOP31 HINT_NOP32 HINT_NOP33 HINT_NOP34 +syn keyword nasmInstructionHINTNOP HINT_NOP35 HINT_NOP36 HINT_NOP37 HINT_NOP38 HINT_NOP39 +syn keyword nasmInstructionHINTNOP HINT_NOP40 HINT_NOP41 HINT_NOP42 HINT_NOP43 HINT_NOP44 +syn keyword nasmInstructionHINTNOP HINT_NOP45 HINT_NOP46 HINT_NOP47 HINT_NOP48 HINT_NOP49 +syn keyword nasmInstructionHINTNOP HINT_NOP50 HINT_NOP51 HINT_NOP52 HINT_NOP53 HINT_NOP54 +syn keyword nasmInstructionHINTNOP HINT_NOP55 HINT_NOP56 HINT_NOP57 HINT_NOP58 HINT_NOP59 +syn keyword nasmInstructionHINTNOP HINT_NOP60 HINT_NOP61 HINT_NOP62 HINT_NOP63 " Cyrix instructions (requires Cyrix processor) -syn keyword nasmCrxInstruction PADDSIW PAVEB PDISTIB PMAGW PMULHRW[C] PMULHRIW +syn keyword nasmCrxInstruction PADDSIW PAVEB PDISTIB PMAGW PMULHRWC PMULHRIW syn keyword nasmCrxInstruction PMVGEZB PMVLZB PMVNZB PMVZB PSUBSIW syn keyword nasmCrxInstruction RDSHR RSDC RSLDT SMINT SMINTOLD SVDC SVLDT SVTS -syn keyword nasmCrxInstruction WRSHR -" AMD instructions (requires AMD processor) -syn keyword nasmAmdInstruction SYSCALL SYSRET - - -" Undocumented Instructions: -syn match nasmUndInstruction "\<POP\s[^;]*\<CS\>"me=s+3 -syn keyword nasmUndInstruction CMPXCHG486 IBTS ICEBP INT01 INT03 LOADALL -syn keyword nasmUndInstruction LOADALL286 LOADALL386 SALC SMI UD1 UMOV XBTS +syn keyword nasmCrxInstruction WRSHR BB0_RESET BB1_RESET +syn keyword nasmCrxInstruction CPU_WRITE CPU_READ DMINT RDM PMACHRIW +" Debugging Instructions: (privileged) +syn keyword nasmDbgInstruction INT1 INT3 RDMSR RDTSC RDPMC WRMSR INT01 INT03 " Synchronize Syntax: @@ -529,7 +1064,12 @@ hi def link nasmBinNumber Number hi def link nasmOctNumber Number hi def link nasmDecNumber Number hi def link nasmHexNumber Number -hi def link nasmFltNumber Float +hi def link nasmBinFloat Float +hi def link nasmOctFloat Float +hi def link nasmDecFloat Float +hi def link nasmHexFloat Float +hi def link nasmSpecFloat Float +hi def link nasmBcdConst Float hi def link nasmNumberError Error " Identifier Group: @@ -563,6 +1103,7 @@ hi def link nasmStdDirective Operator hi def link nasmFmtDirective Keyword " Register Group: +hi def link nasmRegisterError Error hi def link nasmCtrlRegister Special hi def link nasmDebugRegister Debug hi def link nasmTestRegister Special @@ -570,19 +1111,81 @@ hi def link nasmRegisterError Error hi def link nasmMemRefError Error " Instruction Group: -hi def link nasmStdInstruction Statement -hi def link nasmSysInstruction Statement -hi def link nasmDbgInstruction Debug -hi def link nasmFpuInstruction Statement -hi def link nasmMmxInstruction Statement -hi def link nasmSseInstruction Statement -hi def link nasmF16cInstruction Statement -hi def link nasmAVXInstruction Statement -hi def link nasmNowInstruction Statement -hi def link nasmAmdInstruction Special -hi def link nasmCrxInstruction Special -hi def link nasmUndInstruction Todo hi def link nasmInstructnError Error +hi def link nasmCrxInstruction Special +hi def link nasmDbgInstruction Debug +hi def link nasmInstructionStandard Statement +hi def link nasmInstructionSIMD Statement +hi def link nasmInstructionSSE Statement +hi def link nasmInstructionXSAVE Statement +hi def link nasmInstructionMEM Statement +hi def link nasmInstructionMMX Statement +hi def link nasmInstruction3DNOW Statement +hi def link nasmInstructionSSE2 Statement +hi def link nasmInstructionWMMX Statement +hi def link nasmInstructionWSSD Statement +hi def link nasmInstructionPRESSCOT Statement +hi def link nasmInstructionVMXSVM Statement +hi def link nasmInstructionPTVMX Statement +hi def link nasmInstructionSEVSNPAMD Statement +hi def link nasmInstructionTEJAS Statement +hi def link nasmInstructionAMD_SSE4A Statement +hi def link nasmInstructionBARCELONA Statement +hi def link nasmInstructionPENRY Statement +hi def link nasmInstructionNEHALEM Statement +hi def link nasmInstructionSMX Statement +hi def link nasmInstructionGEODE_3DNOW Statement +hi def link nasmInstructionINTEL_NEW Statement +hi def link nasmInstructionAES Statement +hi def link nasmInstructionAVX_AES Statement +hi def link nasmInstructionINTEL_PUB Statement +hi def link nasmInstructionAVX Statement +hi def link nasmInstructionINTEL_CMUL Statement +hi def link nasmInstructionINTEL_AVX_CMUL Statement +hi def link nasmInstructionINTEL_FMA Statement +hi def link nasmInstructionINTEL_POST32 Statement +hi def link nasmInstructionSUPERVISOR Statement +hi def link nasmInstructionVIA_SECURITY Statement +hi def link nasmInstructionAMD_PROFILING Statement +hi def link nasmInstructionXOP_FMA4 Statement +hi def link nasmInstructionAVX2 Statement +hi def link nasmInstructionTRANSACTIONS Statement +hi def link nasmInstructionBMI_ABM Statement +hi def link nasmInstructionMPE Statement +hi def link nasmInstructionSHA Statement +hi def link nasmInstructionSM3 Statement +hi def link nasmInstructionSM4 Statement +hi def link nasmInstructionAVX_NOEXCEPT Statement +hi def link nasmInstructionAVX_VECTOR_NN Statement +hi def link nasmInstructionAVX_IFMA Statement +hi def link nasmInstructionAVX512_MASK Statement +hi def link nasmInstructionAVX512_MASK_REG Statement +hi def link nasmInstructionAVX512 Statement +hi def link nasmInstructionPROTECTION Statement +hi def link nasmInstructionRDPID Statement +hi def link nasmInstructionNMEM Statement +hi def link nasmInstructionINTEL_EXTENSIONS Statement +hi def link nasmInstructionGALOISFIELD Statement +hi def link nasmInstructionAVX512_BMI Statement +hi def link nasmInstructionAVX512_VNNI Statement +hi def link nasmInstructionAVX512_BITALG Statement +hi def link nasmInstructionAVX512_FMA Statement +hi def link nasmInstructionAVX512_DP Statement +hi def link nasmInstructionSGX Statement +hi def link nasmInstructionCET Statement +hi def link nasmInstructionINTEL_EXTENSION Statement +hi def link nasmInstructionAVX512_BF16 Statement +hi def link nasmInstructionAVX512_MASK_INTERSECT Statement +hi def link nasmInstructionAMX Statement +hi def link nasmInstructionAVX512_FP16 Statement +hi def link nasmInstructionRAO_INT Statement +hi def link nasmInstructionUSERINT Statement +hi def link nasmInstructionCMPCCXADD Statement +hi def link nasmInstructionFRET Statement +hi def link nasmInstructionWRMSRNS_MSRLIST Statement +hi def link nasmInstructionHRESET Statement +hi def link nasmInstructionHINTNOP Statement +hi def link nasmInstructionPTWRITE Statement let b:current_syntax = "nasm" diff --git a/runtime/syntax/neomuttlog.vim b/runtime/syntax/neomuttlog.vim new file mode 100644 index 0000000000..27f73493bd --- /dev/null +++ b/runtime/syntax/neomuttlog.vim @@ -0,0 +1,69 @@ +" Vim syntax file +" Language: NeoMutt log files +" Maintainer: Richard Russon <rich@flatcap.org> +" Last Change: 2024 Oct 12 + +" quit when a syntax file was already loaded +if exists("b:current_syntax") + finish +endif + +syntax match neolog_date "\v^\[\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\] *" conceal +syntax match neolog_version "\v<NeoMutt-\d{8}(-\d+-\x+)*(-dirty)*>" +syntax match neolog_banner "\v^\[\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\] .*" contains=neolog_date,neolog_version +syntax match neolog_function "\v%26v\i+\(\)" + +syntax match neolog_perror_key "\v%22v\<P\> " conceal transparent +syntax match neolog_error_key "\v%22v\<E\> " conceal transparent +syntax match neolog_warning_key "\v%22v\<W\> " conceal transparent +syntax match neolog_message_key "\v%22v\<M\> " conceal transparent +syntax match neolog_debug1_key "\v%22v\<1\> " conceal transparent +syntax match neolog_debug2_key "\v%22v\<2\> " conceal transparent +syntax match neolog_debug3_key "\v%22v\<3\> " conceal transparent +syntax match neolog_debug4_key "\v%22v\<4\> " conceal transparent +syntax match neolog_debug5_key "\v%22v\<5\> " conceal transparent +syntax match neolog_notify_key "\v%22v\<N\> " conceal transparent + +syntax match neolog_perror "\v%22v\<P\> .*" contains=neolog_perror_key,neolog_function +syntax match neolog_error "\v%22v\<E\> .*" contains=neolog_error_key,neolog_function +syntax match neolog_warning "\v%22v\<W\> .*" contains=neolog_warning_key,neolog_function +syntax match neolog_message "\v%22v\<M\> .*" contains=neolog_message_key,neolog_function +syntax match neolog_debug1 "\v%22v\<1\> .*" contains=neolog_debug1_key,neolog_function +syntax match neolog_debug2 "\v%22v\<2\> .*" contains=neolog_debug2_key,neolog_function +syntax match neolog_debug3 "\v%22v\<3\> .*" contains=neolog_debug3_key,neolog_function +syntax match neolog_debug4 "\v%22v\<4\> .*" contains=neolog_debug4_key,neolog_function +syntax match neolog_debug5 "\v%22v\<5\> .*" contains=neolog_debug5_key,neolog_function +syntax match neolog_notify "\v%22v\<N\> .*" contains=neolog_notify_key,neolog_function + +if !exists('g:neolog_disable_default_colors') + highlight neolog_date ctermfg=cyan guifg=#40ffff + highlight neolog_banner ctermfg=magenta guifg=#ff00ff + highlight neolog_version cterm=reverse gui=reverse + highlight neolog_function guibg=#282828 + + highlight neolog_perror ctermfg=red guifg=#ff8080 + highlight neolog_error ctermfg=red guifg=#ff8080 + highlight neolog_warning ctermfg=yellow guifg=#ffff80 + highlight neolog_message ctermfg=green guifg=#80ff80 + highlight neolog_debug1 ctermfg=white guifg=#ffffff + highlight neolog_debug2 ctermfg=white guifg=#ffffff + highlight neolog_debug3 ctermfg=grey guifg=#c0c0c0 + highlight neolog_debug4 ctermfg=grey guifg=#c0c0c0 + highlight neolog_debug5 ctermfg=grey guifg=#c0c0c0 + highlight neolog_notify ctermfg=grey guifg=#c0c0c0 +endif + +highlight link neolog_perror_key neolog_perror +highlight link neolog_error_key neolog_error +highlight link neolog_warning_key neolog_warning +highlight link neolog_message_key neolog_message +highlight link neolog_debug1_key neolog_debug1 +highlight link neolog_debug2_key neolog_debug2 +highlight link neolog_debug3_key neolog_debug3 +highlight link neolog_debug4_key neolog_debug4 +highlight link neolog_debug5_key neolog_debug5 +highlight link neolog_notify_key neolog_notify + +let b:current_syntax = "neomuttlog" + +" vim: ts=2 et tw=100 sw=2 sts=0 ft=vim diff --git a/runtime/syntax/neomuttrc.vim b/runtime/syntax/neomuttrc.vim index 421b11ffa3..815e160bbb 100644 --- a/runtime/syntax/neomuttrc.vim +++ b/runtime/syntax/neomuttrc.vim @@ -2,10 +2,10 @@ " Language: NeoMutt setup files " Maintainer: Richard Russon <rich@flatcap.org> " Previous Maintainer: Guillaume Brogi <gui-gui@netcourrier.com> -" Last Change: 2022-04-08 +" Last Change: 2024 Oct 12 " Original version based on syntax/muttrc.vim -" This file covers NeoMutt 2022-04-08 +" This file covers NeoMutt 2024-10-02 " quit when a syntax file was already loaded if exists("b:current_syntax") @@ -22,7 +22,7 @@ setlocal isk=@,48-57,_,- syntax match muttrcComment "^# .*$" contains=@Spell syntax match muttrcComment "^#[^ ].*$" syntax match muttrcComment "^#$" -syntax match muttrcComment "[^\\]#.*$"lc=1 +syntax match muttrcComment "[^\\]#.*$"lc=1 contains=@Spell " Escape sequences (back-tick and pipe goes here too) syntax match muttrcEscape +\\[#tnr"'Cc ]+ @@ -34,7 +34,7 @@ syntax region muttrcString contained keepend start=+"+ms=e skip=+\\"+ end=+"+ co syntax region muttrcString contained keepend start=+'+ms=e skip=+\\'+ end=+'+ contains=muttrcEscape,muttrcCommand,muttrcAction syntax match muttrcStringNL contained skipwhite skipnl "\s*\\$" nextgroup=muttrcString,muttrcStringNL -syntax region muttrcShellString matchgroup=muttrcEscape keepend start=+`+ skip=+\\`+ end=+`+ contains=muttrcVarStr,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcCommand +syntax region muttrcShellString matchgroup=muttrcEscape keepend start=+`+ skip=+\\`+ end=+`+ contains=muttrcVarString,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcCommand syntax match muttrcRXChars contained /[^\\][][.*?+]\+/hs=s+1 syntax match muttrcRXChars contained /[][|()][.*?+]*/ @@ -67,21 +67,21 @@ syntax match muttrcRXDef contained "-rx\s\+" skipwhite nextgroup=muttrcRXPat syntax match muttrcSpecial +\(['"]\)!\1+ -syntax match muttrcSetStrAssignment contained skipwhite /=\s*\%(\\\?\$\)\?[0-9A-Za-z_-]\+/hs=s+1 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr contains=muttrcVariable,muttrcEscapedVariable -syntax region muttrcSetStrAssignment contained skipwhite keepend start=+=\s*"+hs=s+1 end=+"+ skip=+\\"+ nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr contains=muttrcString -syntax region muttrcSetStrAssignment contained skipwhite keepend start=+=\s*'+hs=s+1 end=+'+ skip=+\\'+ nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr contains=muttrcString -syntax match muttrcSetBoolAssignment contained skipwhite /=\s*\\\?\$\w\+/hs=s+1 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr contains=muttrcVariable,muttrcEscapedVariable -syntax match muttrcSetBoolAssignment contained skipwhite /=\s*\%(yes\|no\)/hs=s+1 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax match muttrcSetBoolAssignment contained skipwhite /=\s*"\%(yes\|no\)"/hs=s+1 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax match muttrcSetBoolAssignment contained skipwhite /=\s*'\%(yes\|no\)'/hs=s+1 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax match muttrcSetQuadAssignment contained skipwhite /=\s*\\\?\$\w\+/hs=s+1 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr contains=muttrcVariable,muttrcEscapedVariable -syntax match muttrcSetQuadAssignment contained skipwhite /=\s*\%(ask-\)\?\%(yes\|no\)/hs=s+1 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax match muttrcSetQuadAssignment contained skipwhite /=\s*"\%(ask-\)\?\%(yes\|no\)"/hs=s+1 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax match muttrcSetQuadAssignment contained skipwhite /=\s*'\%(ask-\)\?\%(yes\|no\)'/hs=s+1 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax match muttrcSetNumAssignment contained skipwhite /=\s*\\\?\$\w\+/hs=s+1 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr contains=muttrcVariable,muttrcEscapedVariable -syntax match muttrcSetNumAssignment contained skipwhite /=\s*\d\+/hs=s+1 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax match muttrcSetNumAssignment contained skipwhite /=\s*"\d\+"/hs=s+1 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax match muttrcSetNumAssignment contained skipwhite /=\s*'\d\+'/hs=s+1 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr +syntax match muttrcSetStrAssignment contained skipwhite /=\s*\%(\\\?\$\)\?[0-9A-Za-z_-]\+/hs=s+1 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString contains=muttrcVariable,muttrcEscapedVariable +syntax region muttrcSetStrAssignment contained skipwhite keepend start=+=\s*"+hs=s+1 end=+"+ skip=+\\"+ nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString contains=muttrcString +syntax region muttrcSetStrAssignment contained skipwhite keepend start=+=\s*'+hs=s+1 end=+'+ skip=+\\'+ nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString contains=muttrcString +syntax match muttrcSetBoolAssignment contained skipwhite /=\s*\\\?\$\w\+/hs=s+1 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString contains=muttrcVariable,muttrcEscapedVariable +syntax match muttrcSetBoolAssignment contained skipwhite /=\s*\%(yes\|no\)/hs=s+1 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax match muttrcSetBoolAssignment contained skipwhite /=\s*"\%(yes\|no\)"/hs=s+1 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax match muttrcSetBoolAssignment contained skipwhite /=\s*'\%(yes\|no\)'/hs=s+1 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax match muttrcSetQuadAssignment contained skipwhite /=\s*\\\?\$\w\+/hs=s+1 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString contains=muttrcVariable,muttrcEscapedVariable +syntax match muttrcSetQuadAssignment contained skipwhite /=\s*\%(ask-\)\?\%(yes\|no\)/hs=s+1 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax match muttrcSetQuadAssignment contained skipwhite /=\s*"\%(ask-\)\?\%(yes\|no\)"/hs=s+1 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax match muttrcSetQuadAssignment contained skipwhite /=\s*'\%(ask-\)\?\%(yes\|no\)'/hs=s+1 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax match muttrcSetNumAssignment contained skipwhite /=\s*\\\?\$\w\+/hs=s+1 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString contains=muttrcVariable,muttrcEscapedVariable +syntax match muttrcSetNumAssignment contained skipwhite /=\s*\d\+/hs=s+1 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax match muttrcSetNumAssignment contained skipwhite /=\s*"\d\+"/hs=s+1 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax match muttrcSetNumAssignment contained skipwhite /=\s*'\d\+'/hs=s+1 nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString " Now catch some email addresses and headers (purified version from mail.vim) syntax match muttrcEmail "[a-zA-Z0-9._-]\+@[a-zA-Z0-9./-]\+" @@ -101,38 +101,9 @@ syntax match muttrcStrftimeEscapes contained /%[AaBbCcDdeFGgHhIjklMmnpRrSsTtUuVv syntax match muttrcStrftimeEscapes contained /%E[cCxXyY]/ syntax match muttrcStrftimeEscapes contained /%O[BdeHImMSuUVwWy]/ -syntax region muttrcAliasFormatStr contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcAliasFormatEscapes,muttrcAliasFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcAliasFormatStr contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcAliasFormatEscapes,muttrcAliasFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcAttachFormatStr contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcAttachFormatEscapes,muttrcAttachFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcAttachFormatStr contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcAttachFormatEscapes,muttrcAttachFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcComposeFormatStr contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcComposeFormatEscapes,muttrcComposeFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcComposeFormatStr contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcComposeFormatEscapes,muttrcComposeFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcFolderFormatStr contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcFolderFormatEscapes,muttrcFolderFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcFolderFormatStr contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcFolderFormatEscapes,muttrcFolderFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcGroupIndexFormatStr contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcGroupIndexFormatEscapes,muttrcGroupIndexFormatConditionals,muttrcFormatErrors,muttrcTimeEscapes nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcGroupIndexFormatStr contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcGroupIndexFormatEscapes,muttrcGroupIndexFormatConditionals,muttrcFormatErrors,muttrcTimeEscapes nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcIndexFormatStr contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcIndexFormatEscapes,muttrcIndexFormatConditionals,muttrcFormatErrors,muttrcTimeEscapes nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcIndexFormatStr contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcIndexFormatEscapes,muttrcIndexFormatConditionals,muttrcFormatErrors,muttrcTimeEscapes nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcMixFormatStr contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcMixFormatEscapes,muttrcMixFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcMixFormatStr contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcMixFormatEscapes,muttrcMixFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcPatternFormatStr contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcPatternFormatEscapes,muttrcPatternFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcPatternFormatStr contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcPatternFormatEscapes,muttrcPatternFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcPGPCmdFormatStr contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcPGPCmdFormatEscapes,muttrcPGPCmdFormatConditionals,muttrcVariable,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcPGPCmdFormatStr contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcPGPCmdFormatEscapes,muttrcPGPCmdFormatConditionals,muttrcVariable,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcPGPFormatStr contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcPGPFormatEscapes,muttrcPGPFormatConditionals,muttrcFormatErrors,muttrcPGPTimeEscapes nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcPGPFormatStr contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcPGPFormatEscapes,muttrcPGPFormatConditionals,muttrcFormatErrors,muttrcPGPTimeEscapes nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcQueryFormatStr contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcQueryFormatEscapes,muttrcQueryFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcQueryFormatStr contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcQueryFormatEscapes,muttrcQueryFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcSidebarFormatStr contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcSidebarFormatEscapes,muttrcSidebarFormatConditionals,muttrcFormatErrors,muttrcTimeEscapes nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcSidebarFormatStr contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcSidebarFormatEscapes,muttrcSidebarFormatConditionals,muttrcFormatErrors,muttrcTimeEscapes nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcSmimeFormatStr contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcSmimeFormatEscapes,muttrcSmimeFormatConditionals,muttrcVariable,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcSmimeFormatStr contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcSmimeFormatEscapes,muttrcSmimeFormatConditionals,muttrcVariable,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcStatusFormatStr contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcStatusFormatEscapes,muttrcStatusFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcStatusFormatStr contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcStatusFormatEscapes,muttrcStatusFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcStrftimeFormatStr contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcStrftimeEscapes,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax region muttrcStrftimeFormatStr contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcStrftimeEscapes,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr - -" Format escapes and conditionals +" Defines syntax matches for muttrc[baseName]Escapes, muttrc[baseName]Conditionals +" If padding==1, also match `%>` `%|` `%*` expandos +" If conditional==1, some expandos support %X? format syntax match muttrcFormatConditionals2 contained /[^?]*?/ function! s:escapesConditionals(baseName, sequence, padding, conditional) exec 'syntax match muttrc' . a:baseName . 'Escapes contained /%\%(\%(-\?[0-9]\+\)\?\%(\.[0-9]\+\)\?\)\?[:_]\?\%(' . a:sequence . '\|%\)/' @@ -146,65 +117,107 @@ function! s:escapesConditionals(baseName, sequence, padding, conditional) endif endfunction -" CHECKED 2022-04-08 -" Ref: alias_format_str() in alias/dlg_alias.c -call s:escapesConditionals('AliasFormat', '[acfnrt]', 1, 0) -" Ref: attach_format_str() in attach/dlg_attach.c +" CHECKED 2024 Oct 12 +" Ref: AliasFormatDef in alias/config.c +call s:escapesConditionals('AliasFormat', '[acfnrtY]', 1, 0) +" Ref: AttachFormatDef in mutt_config.c call s:escapesConditionals('AttachFormat', '[CcDdeFfIMmnQsTtuX]', 1, 1) -" Ref: compose_format_str() in compose/cbar.c +" Ref: AutocryptFormatDef in autocrypt/config.c +call s:escapesConditionals('AutocryptFormat', '[aknps]', 1, 0) +" Ref: ComposeFormatDef in compose/config.c call s:escapesConditionals('ComposeFormat', '[ahlv]', 1, 1) -" Ref: folder_format_str() in browser/browser.c -call s:escapesConditionals('FolderFormat', '[CDdFfgilmNnstu]', 1, 0) -" Ref: group_index_format_str() in nntp/browse.c -call s:escapesConditionals('GroupIndexFormat', '[CdfMNns]', 1, 1) -" Ref: index_format_str() in hdrline.c +" Ref: FolderFormatDef in browser/config.c +call s:escapesConditionals('FolderFormat', '[aCDdFfgilmNnpstu[]', 1, 1) +" Ref: GreetingFormatDef in send/config.c +call s:escapesConditionals('GreetingFormat', '[nuv]', 0, 0) +" Ref: GroupIndexFormatDef in browser/config.c +call s:escapesConditionals('GroupIndexFormat', '[aCdfMNnps]', 1, 0) +" Ref: HistoryFormatDef in history/config.c +call s:escapesConditionals('HistoryFormat', '[Cs]', 1, 0) +" Ref: IndexFormatDef in mutt_config.c call s:escapesConditionals('IndexFormat', '[AaBbCDdEefgHIiJKLlMmNnOPqRrSsTtuvWXxYyZ(<[{]\|@\i\+@\|G[a-zA-Z]\+\|Fp\=\|z[cst]\|cr\=', 1, 1) -" Ref: mix_format_str() in remailer.c -call s:escapesConditionals('MixFormat', '[acns]', 1, 0) -" Ref: pattern_format_str() in pattern/dlg_pattern.c +" Ref: PatternFormatDef in pattern/config.c call s:escapesConditionals('PatternFormat', '[den]', 1, 0) -" Ref: pgp_command_format_str() in ncrypt/pgpinvoke.c -call s:escapesConditionals('PGPCmdFormat', '[afprs]', 0, 1) -" Ref: crypt_format_str() in ncrypt/dlg_gpgme.c -" Ref: pgp_entry_format_str() in ncrypt/dlg_pgp.c -" Note: crypt_format_str() supports 'p', but pgp_entry_fmt() does not -call s:escapesConditionals('PGPFormat', '[AaCcFfKkLlnptu[]', 0, 0) -" Ref: query_format_str() in alias/dlg_query.c -call s:escapesConditionals('QueryFormat', '[acent]', 1, 1) -" Ref: sidebar_format_str() in sidebar/window.c -call s:escapesConditionals('SidebarFormat', '[!BDdFLNnorStZ]', 1, 1) -" Ref: smime_command_format_str() in ncrypt/smime.c -call s:escapesConditionals('SmimeFormat', '[aCcdfiks]', 0, 1) -" Ref: status_format_str() in status.c +" Ref: PgpCommandFormatDef in ncrypt/config.c +call s:escapesConditionals('PgpCommandFormat', '[afprs]', 0, 1) +" Ref: PgpEntryFormatDef in ncrypt/config.c +call s:escapesConditionals('PgpEntryFormat', '[AaCcFfIiKkLlnptu[]', 1, 1) +" Ref: QueryFormatDef in alias/config.c +call s:escapesConditionals('QueryFormat', '[acentY]', 1, 1) +" Ref: SidebarFormatDef in sidebar/config.c +call s:escapesConditionals('SidebarFormat', '[!aBDdFLNnoprStZ]', 1, 1) +" Ref: SmimeCommandFormatDef in ncrypt/config.c +call s:escapesConditionals('SmimeCommandFormat', '[aCcdfiks]', 0, 1) +" Ref: StatusFormatDef in mutt_config.c call s:escapesConditionals('StatusFormat', '[bDdFfhLlMmnoPpRrSsTtuVv]', 1, 1) -syntax region muttrcPGPTimeEscapes contained start=+%\[+ end=+\]+ contains=muttrcStrftimeEscapes +syntax region muttrcAliasFormatString contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcAliasFormatEscapes,muttrcAliasFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcAliasFormatString contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcAliasFormatEscapes,muttrcAliasFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcAttachFormatString contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcAttachFormatEscapes,muttrcAttachFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcAttachFormatString contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcAttachFormatEscapes,muttrcAttachFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcAutocryptFormatString contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcAutocryptFormatEscapes,muttrcAutocryptFormatConditionals,muttrcFormatErrors,muttrcTimeEscapes nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcAutocryptFormatString contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcAutocryptFormatEscapes,muttrcAutocryptFormatConditionals,muttrcFormatErrors,muttrcTimeEscapes nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcComposeFormatString contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcComposeFormatEscapes,muttrcComposeFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcComposeFormatString contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcComposeFormatEscapes,muttrcComposeFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcFolderFormatString contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcFolderFormatEscapes,muttrcFolderFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcFolderFormatString contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcFolderFormatEscapes,muttrcFolderFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcGreetingFormatString contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcGreetingFormatEscapes,muttrcGreetingFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcGreetingFormatString contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcGreetingFormatEscapes,muttrcGreetingFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcGroupIndexFormatString contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcGroupIndexFormatEscapes,muttrcGroupIndexFormatConditionals,muttrcFormatErrors,muttrcTimeEscapes nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcGroupIndexFormatString contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcGroupIndexFormatEscapes,muttrcGroupIndexFormatConditionals,muttrcFormatErrors,muttrcTimeEscapes nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcHistoryFormatString contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcHistoryFormatEscapes,muttrcHistoryFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcHistoryFormatString contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcHistoryFormatEscapes,muttrcHistoryFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcIndexFormatString contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcIndexFormatEscapes,muttrcIndexFormatConditionals,muttrcFormatErrors,muttrcTimeEscapes nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcIndexFormatString contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcIndexFormatEscapes,muttrcIndexFormatConditionals,muttrcFormatErrors,muttrcTimeEscapes nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcPatternFormatString contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcPatternFormatEscapes,muttrcPatternFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcPatternFormatString contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcPatternFormatEscapes,muttrcPatternFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcPgpCommandFormatString contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcPgpCommandFormatEscapes,muttrcPgpCommandFormatConditionals,muttrcVariable,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcPgpCommandFormatString contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcPgpCommandFormatEscapes,muttrcPgpCommandFormatConditionals,muttrcVariable,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcPgpEntryFormatString contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcPgpEntryFormatEscapes,muttrcPgpEntryFormatConditionals,muttrcFormatErrors,muttrcPgpTimeEscapes nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcPgpEntryFormatString contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcPgpEntryFormatEscapes,muttrcPgpEntryFormatConditionals,muttrcFormatErrors,muttrcPgpTimeEscapes nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcQueryFormatString contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcQueryFormatEscapes,muttrcQueryFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcQueryFormatString contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcQueryFormatEscapes,muttrcQueryFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcSidebarFormatString contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcSidebarFormatEscapes,muttrcSidebarFormatConditionals,muttrcFormatErrors,muttrcTimeEscapes nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcSidebarFormatString contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcSidebarFormatEscapes,muttrcSidebarFormatConditionals,muttrcFormatErrors,muttrcTimeEscapes nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcSmimeCommandFormatString contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcSmimeCommandFormatEscapes,muttrcSmimeCommandFormatConditionals,muttrcVariable,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcSmimeCommandFormatString contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcSmimeCommandFormatEscapes,muttrcSmimeCommandFormatConditionals,muttrcVariable,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcStatusFormatString contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcStatusFormatEscapes,muttrcStatusFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcStatusFormatString contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcStatusFormatEscapes,muttrcStatusFormatConditionals,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcStrftimeFormatString contained skipwhite keepend start=+"+ skip=+\\"+ end=+"+ contains=muttrcStrftimeEscapes,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax region muttrcStrftimeFormatString contained skipwhite keepend start=+'+ skip=+\\'+ end=+'+ contains=muttrcStrftimeEscapes,muttrcFormatErrors nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString + +" Format escapes and conditionals +syntax match muttrcFormatConditionals2 contained /[^?]*?/ + +syntax region muttrcPgpTimeEscapes contained start=+%\[+ end=+\]+ contains=muttrcStrftimeEscapes syntax region muttrcTimeEscapes contained start=+%(+ end=+)+ contains=muttrcStrftimeEscapes syntax region muttrcTimeEscapes contained start=+%<+ end=+>+ contains=muttrcStrftimeEscapes syntax region muttrcTimeEscapes contained start=+%\[+ end=+\]+ contains=muttrcStrftimeEscapes syntax region muttrcTimeEscapes contained start=+%{+ end=+}+ contains=muttrcStrftimeEscapes -syntax match muttrcVarEqualsAliasFmt contained skipwhite "=" nextgroup=muttrcAliasFormatStr -syntax match muttrcVarEqualsAttachFmt contained skipwhite "=" nextgroup=muttrcAttachFormatStr -syntax match muttrcVarEqualsComposeFmt contained skipwhite "=" nextgroup=muttrcComposeFormatStr -syntax match muttrcVarEqualsFolderFmt contained skipwhite "=" nextgroup=muttrcFolderFormatStr -syntax match muttrcVarEqualsGrpIdxFmt contained skipwhite "=" nextgroup=muttrcGroupIndexFormatStr -syntax match muttrcVarEqualsIdxFmt contained skipwhite "=" nextgroup=muttrcIndexFormatStr -syntax match muttrcVarEqualsMixFmt contained skipwhite "=" nextgroup=muttrcMixFormatStr -syntax match muttrcVarEqualsPatternFmt contained skipwhite "=" nextgroup=muttrcPatternFormatStr -syntax match muttrcVarEqualsPGPCmdFmt contained skipwhite "=" nextgroup=muttrcPGPCmdFormatStr -syntax match muttrcVarEqualsPGPFmt contained skipwhite "=" nextgroup=muttrcPGPFormatStr -syntax match muttrcVarEqualsQueryFmt contained skipwhite "=" nextgroup=muttrcQueryFormatStr -syntax match muttrcVarEqualsSdbFmt contained skipwhite "=" nextgroup=muttrcSidebarFormatStr -syntax match muttrcVarEqualsSmimeFmt contained skipwhite "=" nextgroup=muttrcSmimeFormatStr -syntax match muttrcVarEqualsStatusFmt contained skipwhite "=" nextgroup=muttrcStatusFormatStr -syntax match muttrcVarEqualsStrftimeFmt contained skipwhite "=" nextgroup=muttrcStrftimeFormatStr - -syntax match muttrcVPrefix contained /[?&]/ nextgroup=muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr - -" CHECKED 2022-04-08 +syntax match muttrcVarEqualsAliasFormat contained skipwhite "=" nextgroup=muttrcAliasFormatString +syntax match muttrcVarEqualsAttachFormat contained skipwhite "=" nextgroup=muttrcAttachFormatString +syntax match muttrcVarEqualsAutocryptFormat contained skipwhite "=" nextgroup=muttrcAutocryptFormatString +syntax match muttrcVarEqualsComposeFormat contained skipwhite "=" nextgroup=muttrcComposeFormatString +syntax match muttrcVarEqualsFolderFormat contained skipwhite "=" nextgroup=muttrcFolderFormatString +syntax match muttrcVarEqualsGreetingFormat contained skipwhite "=" nextgroup=muttrcGreetingFormatString +syntax match muttrcVarEqualsGroupIndexFormat contained skipwhite "=" nextgroup=muttrcGroupIndexFormatString +syntax match muttrcVarEqualsHistoryFormat contained skipwhite "=" nextgroup=muttrcHistoryFormatString +syntax match muttrcVarEqualsIndexFormat contained skipwhite "=" nextgroup=muttrcIndexFormatString +syntax match muttrcVarEqualsPatternFormat contained skipwhite "=" nextgroup=muttrcPatternFormatString +syntax match muttrcVarEqualsPgpCommandFormat contained skipwhite "=" nextgroup=muttrcPgpCommandFormatString +syntax match muttrcVarEqualsPgpEntryFormat contained skipwhite "=" nextgroup=muttrcPgpEntryFormatString +syntax match muttrcVarEqualsQueryFormat contained skipwhite "=" nextgroup=muttrcQueryFormatString +syntax match muttrcVarEqualsSidebarFormat contained skipwhite "=" nextgroup=muttrcSidebarFormatString +syntax match muttrcVarEqualsSmimeCommandFormat contained skipwhite "=" nextgroup=muttrcSmimeCommandFormatString +syntax match muttrcVarEqualsStatusFormat contained skipwhite "=" nextgroup=muttrcStatusFormatString +syntax match muttrcVarEqualsStrftimeFormat contained skipwhite "=" nextgroup=muttrcStrftimeFormatString + +syntax match muttrcVPrefix contained /[?&]/ nextgroup=muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString + +" CHECKED 2024 Oct 12 " List of the different screens in NeoMutt (see MenuNames in menu/type.c) -syntax keyword muttrcMenu contained alias attach autocrypt browser compose editor generic index key_select_pgp key_select_smime mix pager pgp postpone query smime +syntax keyword muttrcMenu contained alias attach autocrypt browser compose dialog editor generic index key_select_pgp key_select_smime pager pgp postpone query smime syntax match muttrcMenuList "\S\+" contained contains=muttrcMenu syntax match muttrcMenuCommas /,/ contained @@ -239,10 +252,12 @@ syntax match muttrcEscapedVariable contained "\\\$[a-zA-Z_-]\+" syntax match muttrcBadAction contained "[^<>]\+" contains=muttrcEmail syntax match muttrcAction contained "<[^>]\{-}>" contains=muttrcBadAction,muttrcFunction,muttrcKeyName -" CHECKED 2022-04-08 +" CHECKED 2024 Oct 12 " First, hooks that take regular expressions: -syntax match muttrcRXHookNot contained /!\s*/ skipwhite nextgroup=muttrcRXHookString,muttrcRXHookStringNL -syntax match muttrcRXHooks /\<\%(account\|append\|close\|crypt\|folder\|mbox\|open\|pgp\)-hook\>/ skipwhite nextgroup=muttrcRXHookNot,muttrcRXHookString,muttrcRXHookStringNL +syntax match muttrcRXHookNot contained /!\s*/ skipwhite nextgroup=muttrcRXHookString,muttrcRXHookStringNL +syntax match muttrcRXHookNoRegex contained /-noregex/ skipwhite nextgroup=muttrcRXHookString,muttrcRXHookStringNL +syntax match muttrcRXHooks /\<\%(account\|append\|close\|crypt\|open\|pgp\|shutdown\|startup\|timeout\)-hook\>/ skipwhite nextgroup=muttrcRXHookNot,muttrcRXHookString,muttrcRXHookStringNL +syntax match muttrcRXHooks /\<\%(folder\|mbox\)-hook\>/ skipwhite nextgroup=muttrcRXHookNoRegex,muttrcRXHookNot,muttrcRXHookString,muttrcRXHookStringNL " Now, hooks that take patterns syntax match muttrcPatHookNot contained /!\s*/ skipwhite nextgroup=muttrcPattern @@ -252,11 +267,11 @@ syntax match muttrcPatHooks /\<\%(message\|reply\|send\|send2\|save\|fcc\|fcc-sa " Global hooks that take a command syntax keyword muttrcHooks skipwhite shutdown-hook startup-hook timeout-hook nextgroup=muttrcCommand -syntax match muttrcBindFunction contained /\S\+\>/ skipwhite contains=muttrcFunction +syntax match muttrcBindFunction contained /\S\+\>/ skipwhite contains=muttrcFunction syntax match muttrcBindFunctionNL contained /\s*\\$/ skipwhite skipnl nextgroup=muttrcBindFunction,muttrcBindFunctionNL -syntax match muttrcBindKey contained /\S\+/ skipwhite contains=muttrcKey nextgroup=muttrcBindFunction,muttrcBindFunctionNL -syntax match muttrcBindKeyNL contained /\s*\\$/ skipwhite skipnl nextgroup=muttrcBindKey,muttrcBindKeyNL -syntax match muttrcBindMenuList contained /\S\+/ skipwhite contains=muttrcMenu,muttrcMenuCommas nextgroup=muttrcBindKey,muttrcBindKeyNL +syntax match muttrcBindKey contained /\S\+/ skipwhite contains=muttrcKey nextgroup=muttrcBindFunction,muttrcBindFunctionNL +syntax match muttrcBindKeyNL contained /\s*\\$/ skipwhite skipnl nextgroup=muttrcBindKey,muttrcBindKeyNL +syntax match muttrcBindMenuList contained /\S\+/ skipwhite contains=muttrcMenu,muttrcMenuCommas nextgroup=muttrcBindKey,muttrcBindKeyNL syntax match muttrcBindMenuListNL contained /\s*\\$/ skipwhite skipnl nextgroup=muttrcBindMenuList,muttrcBindMenuListNL syntax region muttrcMacroDescr contained keepend skipwhite start=+\s*\S+ms=e skip=+\\ + end=+ \|$+me=s @@ -300,7 +315,7 @@ syntax match muttrcAliasNL contained /\s*\\$/ skipwhite skipnl nextgroup=muttrc syntax match muttrcUnAliasKey contained "\s*\w\+\s*" skipwhite nextgroup=muttrcUnAliasKey,muttrcUnAliasNL syntax match muttrcUnAliasNL contained /\s*\\$/ skipwhite skipnl nextgroup=muttrcUnAliasKey,muttrcUnAliasNL -" CHECKED 2022-04-08 +" CHECKED 2024 Oct 12 " List of letters in Flags in pattern/flags.c " Parameter: none syntax match muttrcSimplePat contained "!\?\^\?[~][ADEFGgklNOPpQRSTUuVv#$=]" @@ -309,7 +324,7 @@ syntax match muttrcSimplePat contained "!\?\^\?[~][mnXz]\s*\%([<>-][0-9]\+[kM]\? " Parameter: date syntax match muttrcSimplePat contained "!\?\^\?[~][dr]\s*\%(\%(-\?[0-9]\{1,2}\%(/[0-9]\{1,2}\%(/[0-9]\{2}\%([0-9]\{2}\)\?\)\?\)\?\%([+*-][0-9]\+[ymwd]\)*\)\|\%(\%([0-9]\{1,2}\%(/[0-9]\{1,2}\%(/[0-9]\{2}\%([0-9]\{2}\)\?\)\?\)\?\%([+*-][0-9]\+[ymwd]\)*\)-\%([0-9]\{1,2}\%(/[0-9]\{1,2}\%(/[0-9]\{2}\%([0-9]\{2}\)\?\)\?\)\?\%([+*-][0-9]\+[ymwd]\)\?\)\?\)\|\%([<>=][0-9]\+[ymwd]\)\|\%(`[^`]\+`\)\|\%(\$[a-zA-Z0-9_-]\+\)\)" contains=muttrcShellString,muttrcVariable " Parameter: regex -syntax match muttrcSimplePat contained "!\?\^\?[~][BbCcefHhIiLMstwxYy]\s*" nextgroup=muttrcSimplePatRXContainer +syntax match muttrcSimplePat contained "!\?\^\?[~][BbCcefHhIiKLMstwxYy]\s*" nextgroup=muttrcSimplePatRXContainer " Parameter: pattern syntax match muttrcSimplePat contained "!\?\^\?[%][BbCcefHhiLstxy]\s*" nextgroup=muttrcSimplePatString " Parameter: pattern @@ -341,21 +356,25 @@ syntax match muttrcPattern contained skipwhite /[.]/ syntax region muttrcPatternInner contained keepend start=+"[~=%!(^]+ms=s+1 skip=+\\"+ end=+"+me=e-1 contains=muttrcSimplePat,muttrcUnHighlightSpace,muttrcSimplePatMetas syntax region muttrcPatternInner contained keepend start=+'[~=%!(^]+ms=s+1 skip=+\\'+ end=+'+me=e-1 contains=muttrcSimplePat,muttrcUnHighlightSpace,muttrcSimplePatMetas -" Colour definitions takes object, foreground and background arguments (regexps excluded). +" Colour definitions takes object, foreground and background arguments (regexes excluded). syntax match muttrcColorMatchCount contained "[0-9]\+" syntax match muttrcColorMatchCountNL contained skipwhite skipnl "\s*\\$" nextgroup=muttrcColorMatchCount,muttrcColorMatchCountNL syntax region muttrcColorRXPat contained start=+\s*'+ skip=+\\'+ end=+'\s*+ keepend skipwhite contains=muttrcRXString2 nextgroup=muttrcColorMatchCount,muttrcColorMatchCountNL syntax region muttrcColorRXPat contained start=+\s*"+ skip=+\\"+ end=+"\s*+ keepend skipwhite contains=muttrcRXString2 nextgroup=muttrcColorMatchCount,muttrcColorMatchCountNL syntax keyword muttrcColor contained black blue cyan default green magenta red white yellow syntax keyword muttrcColor contained brightblack brightblue brightcyan brightdefault brightgreen brightmagenta brightred brightwhite brightyellow +syntax keyword muttrcColor contained lightblack lightblue lightcyan lightdefault lightgreen lightmagenta lightred lightwhite lightyellow +syntax keyword muttrcColor contained alertblack alertblue alertcyan alertdefault alertgreen alertmagenta alertred alertwhite alertyellow syntax match muttrcColor contained "\<\%(bright\)\=color\d\{1,3}\>" +syntax match muttrcColor contained "#[0-9a-fA-F]\{6}\>" + " Now for the structure of the color line syntax match muttrcColorRXNL contained skipnl "\s*\\$" nextgroup=muttrcColorRXPat,muttrcColorRXNL -syntax match muttrcColorBG contained /\s*[$]\?\w\+/ contains=muttrcColor,muttrcVariable,muttrcUnHighlightSpace nextgroup=muttrcColorRXPat,muttrcColorRXNL +syntax match muttrcColorBG contained /\s*[#$]\?\w\+/ contains=muttrcColor,muttrcVariable,muttrcUnHighlightSpace nextgroup=muttrcColorRXPat,muttrcColorRXNL syntax match muttrcColorBGNL contained skipnl "\s*\\$" nextgroup=muttrcColorBG,muttrcColorBGNL -syntax match muttrcColorFG contained /\s*[$]\?\w\+/ contains=muttrcColor,muttrcVariable,muttrcUnHighlightSpace nextgroup=muttrcColorBG,muttrcColorBGNL +syntax match muttrcColorFG contained /\s*[#$]\?\w\+/ contains=muttrcColor,muttrcVariable,muttrcUnHighlightSpace nextgroup=muttrcColorBG,muttrcColorBGNL syntax match muttrcColorFGNL contained skipnl "\s*\\$" nextgroup=muttrcColorFG,muttrcColorFGNL -syntax match muttrcColorContext contained /\s*[$]\?\w\+/ contains=muttrcColorField,muttrcVariable,muttrcUnHighlightSpace,muttrcColorCompose nextgroup=muttrcColorFG,muttrcColorFGNL +syntax match muttrcColorContext contained /\s*[#$]\?\w\+/ contains=muttrcColorField,muttrcVariable,muttrcUnHighlightSpace,muttrcColorCompose nextgroup=muttrcColorFG,muttrcColorFGNL syntax match muttrcColorNL contained skipnl "\s*\\$" nextgroup=muttrcColorContext,muttrcColorNL,muttrcColorCompose syntax match muttrcColorKeyword contained /^\s*color\s\+/ nextgroup=muttrcColorContext,muttrcColorNL,muttrcColorCompose " And now color's brother: @@ -370,25 +389,26 @@ syntax match muttrcUnColorIndexNL contained skipwhite skipnl /\s*\\$/ nextgroup= syntax match muttrcUnColorKeyword contained skipwhite /^\s*uncolor\s\+/ nextgroup=muttrcUnColorIndex,muttrcUnColorIndexNL syntax region muttrcUnColorLine keepend start=+^\s*uncolor\s+ skip=+\\$+ end=+$+ contains=muttrcUnColorKeyword,muttrcComment,muttrcUnHighlightSpace -syntax keyword muttrcMonoAttrib contained bold none normal reverse standout underline +syntax keyword muttrcMonoAttrib contained bold italic none normal reverse standout underline syntax keyword muttrcMono contained mono skipwhite nextgroup=muttrcColorField,muttrcColorCompose syntax match muttrcMonoLine "^\s*mono\s\+\S\+" skipwhite nextgroup=muttrcMonoAttrib contains=muttrcMono -" CHECKED 2022-04-08 -" List of fields in ColorFields in color/commmand.c +" CHECKED 2024 Oct 12 +" List of fields in ColorFields in color/command.c syntax keyword muttrcColorField skipwhite contained \ attachment attach_headers body bold error hdrdefault header index index_author \ index_collapsed index_date index_flags index_label index_number index_size index_subject - \ index_tag index_tags indicator markers message normal options progress prompt quoted - \ search sidebar_divider sidebar_flagged sidebar_highlight sidebar_indicator sidebar_new - \ sidebar_ordinary sidebar_spoolfile sidebar_unread signature status tilde tree underline - \ warning nextgroup=muttrcColor + \ index_tag index_tags indicator italic markers message normal options progress prompt + \ search sidebar_background sidebar_divider sidebar_flagged sidebar_highlight + \ sidebar_indicator sidebar_new sidebar_ordinary sidebar_spool_file sidebar_unread signature + \ status stripe_even stripe_odd tilde tree underline warning + \ nextgroup=muttrcColor syntax match muttrcColorField contained "\<quoted\d\=\>" syntax match muttrcColorCompose skipwhite contained /\s*compose\s*/ nextgroup=muttrcColorComposeField -" CHECKED 2022-04-08 +" CHECKED 2024 Oct 12 " List of fields in ComposeColorFields in color/command.c syntax keyword muttrcColorComposeField skipwhite contained \ header security_both security_encrypt security_none security_sign @@ -409,37 +429,39 @@ function! s:boolQuadGen(type, vars, deprecated) exec 'syntax keyword muttrcVar' . l:type . ' ' . join(l:invvars) else let l:type = a:type - exec 'syntax keyword muttrcVar' . l:type . ' skipwhite contained ' . join(a:vars) . ' nextgroup=muttrcSet' . l:orig_type . 'Assignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr' - exec 'syntax keyword muttrcVar' . l:type . ' skipwhite contained ' . join(l:novars) . ' nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr' - exec 'syntax keyword muttrcVar' . l:type . ' skipwhite contained ' . join(l:invvars) . ' nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr' + exec 'syntax keyword muttrcVar' . l:type . ' skipwhite contained ' . join(a:vars) . ' nextgroup=muttrcSet' . l:orig_type . 'Assignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString' + exec 'syntax keyword muttrcVar' . l:type . ' skipwhite contained ' . join(l:novars) . ' nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString' + exec 'syntax keyword muttrcVar' . l:type . ' skipwhite contained ' . join(l:invvars) . ' nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString' endif endfunction -" CHECKED 2022-04-08 +" CHECKED 2024 Oct 12 " List of DT_BOOL in MuttVars in mutt_config.c call s:boolQuadGen('Bool', [ \ 'abort_backspace', 'allow_8bit', 'allow_ansi', 'arrow_cursor', 'ascii_chars', 'ask_bcc', - \ 'ask_cc', 'ask_follow_up', 'ask_x_comment_to', 'attach_save_without_prompting', + \ 'ask_cc', 'ask_followup_to', 'ask_x_comment_to', 'attach_save_without_prompting', \ 'attach_split', 'autocrypt', 'autocrypt_reply', 'auto_edit', 'auto_subscribe', 'auto_tag', \ 'beep', 'beep_new', 'bounce_delivered', 'braille_friendly', - \ 'browser_abbreviate_mailboxes', 'change_folder_next', 'check_mbox_size', 'check_new', - \ 'collapse_all', 'collapse_flagged', 'collapse_unread', 'compose_show_user_headers', + \ 'browser_abbreviate_mailboxes', 'browser_sort_dirs_first', 'change_folder_next', + \ 'check_mbox_size', 'check_new', 'collapse_all', 'collapse_flagged', 'collapse_unread', + \ 'color_directcolor', 'compose_confirm_detach_first', 'compose_show_user_headers', \ 'confirm_append', 'confirm_create', 'copy_decode_weed', 'count_alternatives', \ 'crypt_auto_encrypt', 'crypt_auto_pgp', 'crypt_auto_sign', 'crypt_auto_smime', - \ 'crypt_confirm_hook', 'crypt_opportunistic_encrypt', + \ 'crypt_confirm_hook', 'crypt_encryption_info', 'crypt_opportunistic_encrypt', \ 'crypt_opportunistic_encrypt_strong_keys', 'crypt_protected_headers_read', - \ 'crypt_protected_headers_save', 'crypt_protected_headers_write', 'crypt_reply_encrypt', - \ 'crypt_reply_sign', 'crypt_reply_sign_encrypted', 'crypt_timestamp', 'crypt_use_gpgme', - \ 'crypt_use_pka', 'delete_untag', 'digest_collapse', 'duplicate_threads', 'edit_headers', - \ 'encode_from', 'fast_reply', 'fcc_before_send', 'fcc_clear', 'flag_safe', 'followup_to', - \ 'force_name', 'forward_decode', 'forward_decrypt', 'forward_quote', 'forward_references', - \ 'hdrs', 'header', 'header_color_partial', 'help', 'hidden_host', 'hide_limited', - \ 'hide_missing', 'hide_thread_subject', 'hide_top_limited', 'hide_top_missing', - \ 'history_remove_dups', 'honor_disposition', 'idn_decode', 'idn_encode', - \ 'ignore_list_reply_to', 'imap_check_subscribed', 'imap_condstore', 'imap_deflate', - \ 'imap_idle', 'imap_list_subscribed', 'imap_passive', 'imap_peek', 'imap_qresync', - \ 'imap_rfc5161', 'imap_server_noise', 'implicit_autoview', 'include_encrypted', + \ 'crypt_protected_headers_save', 'crypt_protected_headers_weed', + \ 'crypt_protected_headers_write', 'crypt_reply_encrypt', 'crypt_reply_sign', + \ 'crypt_reply_sign_encrypted', 'crypt_timestamp', 'crypt_use_gpgme', 'crypt_use_pka', + \ 'delete_untag', 'digest_collapse', 'duplicate_threads', 'edit_headers', 'encode_from', + \ 'fast_reply', 'fcc_before_send', 'fcc_clear', 'flag_safe', 'followup_to', 'force_name', + \ 'forward_decode', 'forward_decrypt', 'forward_quote', 'forward_references', 'hdrs', + \ 'header', 'header_color_partial', 'help', 'hidden_host', 'hide_limited', 'hide_missing', + \ 'hide_thread_subject', 'hide_top_limited', 'hide_top_missing', 'history_remove_dups', + \ 'honor_disposition', 'idn_decode', 'idn_encode', 'ignore_list_reply_to', + \ 'imap_check_subscribed', 'imap_condstore', 'imap_deflate', 'imap_idle', + \ 'imap_list_subscribed', 'imap_passive', 'imap_peek', 'imap_qresync', 'imap_rfc5161', + \ 'imap_send_id', 'imap_server_noise', 'implicit_auto_view', 'include_encrypted', \ 'include_only_first', 'keep_flagged', 'local_date_header', 'mailcap_sanitize', \ 'maildir_check_cur', 'maildir_header_cache_verify', 'maildir_trash', 'mail_check_recent', \ 'mail_check_stats', 'markers', 'mark_old', 'menu_move_off', 'menu_scroll', @@ -469,166 +491,175 @@ call s:boolQuadGen('Bool', [ \ 'virtual_spool_file', 'wait_key', 'weed', 'wrap_search', 'write_bcc', 'x_comment_to' \ ], 0) -" CHECKED 2022-04-08 +" CHECKED 2024 Oct 12 " Deprecated Bools " List of DT_SYNONYM or DT_DEPRECATED Bools in MuttVars in mutt_config.c call s:boolQuadGen('Bool', [ - \ 'askbcc', 'askcc', 'autoedit', 'confirmappend', 'confirmcreate', 'crypt_autoencrypt', - \ 'crypt_autopgp', 'crypt_autosign', 'crypt_autosmime', 'crypt_confirmhook', - \ 'crypt_replyencrypt', 'crypt_replysign', 'crypt_replysignencrypted', 'edit_hdrs', - \ 'envelope_from', 'forw_decode', 'forw_decrypt', 'forw_quote', 'header_cache_compress', - \ 'ignore_linear_white_space', 'imap_servernoise', 'include_onlyfirst', 'metoo', - \ 'mime_subject', 'pgp_autoencrypt', 'pgp_autoinline', 'pgp_autosign', - \ 'pgp_auto_traditional', 'pgp_create_traditional', 'pgp_replyencrypt', 'pgp_replyinline', - \ 'pgp_replysign', 'pgp_replysignencrypted', 'reverse_realname', 'ssl_usesystemcerts', + \ 'askbcc', 'askcc', 'ask_follow_up', 'autoedit', 'confirmappend', 'confirmcreate', + \ 'crypt_autoencrypt', 'crypt_autopgp', 'crypt_autosign', 'crypt_autosmime', + \ 'crypt_confirmhook', 'crypt_replyencrypt', 'crypt_replysign', 'crypt_replysignencrypted', + \ 'cursor_overlay', 'edit_hdrs', 'envelope_from', 'forw_decode', 'forw_decrypt', + \ 'forw_quote', 'header_cache_compress', 'ignore_linear_white_space', 'imap_servernoise', + \ 'implicit_autoview', 'include_onlyfirst', 'metoo', 'mime_subject', 'pgp_autoencrypt', + \ 'pgp_autoinline', 'pgp_autosign', 'pgp_auto_traditional', 'pgp_create_traditional', + \ 'pgp_replyencrypt', 'pgp_replyinline', 'pgp_replysign', 'pgp_replysignencrypted', + \ 'pgp_self_encrypt_as', 'reverse_realname', 'smime_self_encrypt_as', 'ssl_usesystemcerts', \ 'use_8bitmime', 'virtual_spoolfile', 'xterm_set_titles' \ ], 1) -" CHECKED 2022-04-08 +" CHECKED 2024 Oct 12 " List of DT_QUAD in MuttVars in mutt_config.c call s:boolQuadGen('Quad', [ \ 'abort_noattach', 'abort_nosubject', 'abort_unmodified', 'bounce', 'catchup_newsgroup', \ 'copy', 'crypt_verify_sig', 'delete', 'fcc_attach', 'followup_to_poster', \ 'forward_attachments', 'forward_edit', 'honor_followup_to', 'include', 'mime_forward', \ 'mime_forward_rest', 'move', 'pgp_mime_auto', 'pop_delete', 'pop_reconnect', 'postpone', - \ 'post_moderated', 'print', 'quit', 'recall', 'reply_to', 'ssl_starttls', + \ 'post_moderated', 'print', 'quit', 'recall', 'reply_to', 'ssl_starttls' \ ], 0) -" CHECKED 2022-04-08 +" CHECKED 2024 Oct 12 " Deprecated Quads " List of DT_SYNONYM or DT_DEPRECATED Quads in MuttVars in mutt_config.c call s:boolQuadGen('Quad', [ \ 'mime_fwd', 'pgp_encrypt_self', 'pgp_verify_sig', 'smime_encrypt_self' \ ], 1) -" CHECKED 2022-04-08 +" CHECKED 2024 Oct 12 " List of DT_NUMBER or DT_LONG in MuttVars in mutt_config.c syntax keyword muttrcVarNum skipwhite contained - \ connect_timeout debug_level header_cache_compress_level history imap_fetch_chunk_size - \ imap_keepalive imap_pipeline_depth imap_poll_timeout mail_check mail_check_stats_interval - \ menu_context net_inc nm_db_limit nm_open_timeout nm_query_window_current_position + \ debug_level header_cache_compress_level history imap_fetch_chunk_size imap_keep_alive + \ imap_pipeline_depth imap_poll_timeout mail_check mail_check_stats_interval menu_context + \ net_inc nm_db_limit nm_open_timeout nm_query_window_current_position \ nm_query_window_duration nntp_context nntp_poll pager_context pager_index_lines \ pager_read_delay pager_skip_quoted_context pgp_timeout pop_check_interval read_inc \ reflow_wrap save_history score_threshold_delete score_threshold_flag score_threshold_read \ search_context sendmail_wait sidebar_component_depth sidebar_width sleep_time - \ smime_timeout ssl_min_dh_prime_bits timeout time_inc toggle_quoted_show_levels wrap - \ wrap_headers write_inc - \ nextgroup=muttrcSetNumAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -" CHECKED 2022-04-08 + \ smime_timeout socket_timeout ssl_min_dh_prime_bits timeout time_inc + \ toggle_quoted_show_levels wrap wrap_headers write_inc + \ nextgroup=muttrcSetNumAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +" CHECKED 2024 Oct 12 " Deprecated Numbers -syntax keyword muttrcVarDeprecatedNum contained skipwhite - \ header_cache_pagesize pop_checkinterval skip_quoted_offset +syntax keyword muttrcVarDeprecatedNum + \ connect_timeout header_cache_pagesize imap_keepalive pop_checkinterval skip_quoted_offset -" CHECKED 2022-04-08 +" CHECKED 2024 Oct 12 " List of DT_STRING in MuttVars in mutt_config.c " Special cases first, and all the rest at the end " Formats themselves must be updated in their respective groups " See s:escapesConditionals -syntax match muttrcVarStr contained skipwhite 'my_[a-zA-Z0-9_]\+' nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr -syntax keyword muttrcVarStr contained skipwhite alias_format nextgroup=muttrcVarEqualsAliasFmt -syntax keyword muttrcVarStr contained skipwhite attach_format nextgroup=muttrcVarEqualsAttachFmt -syntax keyword muttrcVarStr contained skipwhite compose_format nextgroup=muttrcVarEqualsComposeFmt -syntax keyword muttrcVarStr contained skipwhite folder_format vfolder_format nextgroup=muttrcVarEqualsFolderFmt -syntax keyword muttrcVarStr contained skipwhite attribution forward_format index_format message_format pager_format nextgroup=muttrcVarEqualsIdxFmt -syntax keyword muttrcVarStr contained skipwhite mix_entry_format nextgroup=muttrcVarEqualsMixFmt -syntax keyword muttrcVarStr contained skipwhite pattern_format nextgroup=muttrcVarEqualsPatternFmt -syntax keyword muttrcVarStr contained skipwhite +syntax match muttrcVarString contained skipwhite 'my_[a-zA-Z0-9_]\+' nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString +syntax keyword muttrcVarString contained skipwhite alias_format nextgroup=muttrcVarEqualsAliasFormat +syntax keyword muttrcVarString contained skipwhite attach_format nextgroup=muttrcVarEqualsAttachFormat +syntax keyword muttrcVarString contained skipwhite autocrypt_acct_format nextgroup=muttrcVarEqualsAutocryptFormat +syntax keyword muttrcVarString contained skipwhite compose_format nextgroup=muttrcVarEqualsComposeFormat +syntax keyword muttrcVarString contained skipwhite folder_format mailbox_folder_format nextgroup=muttrcVarEqualsFolderFormat +syntax keyword muttrcVarString contained skipwhite greeting nextgroup=muttrcVarEqualsGreetingFormat +syntax keyword muttrcVarString contained skipwhite history_format nextgroup=muttrcVarEqualsHistoryFormat +syntax keyword muttrcVarString contained skipwhite + \ attribution_intro attribution_trailer forward_attribution_intro forward_attribution_trailer + \ forward_format indent_string index_format message_format pager_format + \ nextgroup=muttrcVarEqualsIndexFormat +syntax keyword muttrcVarString contained skipwhite pattern_format nextgroup=muttrcVarEqualsPatternFormat +syntax keyword muttrcVarString contained skipwhite \ pgp_clear_sign_command pgp_decode_command pgp_decrypt_command pgp_encrypt_only_command \ pgp_encrypt_sign_command pgp_export_command pgp_get_keys_command pgp_import_command \ pgp_list_pubring_command pgp_list_secring_command pgp_sign_command pgp_verify_command \ pgp_verify_key_command - \ nextgroup=muttrcVarEqualsPGPCmdFmt -syntax keyword muttrcVarStr contained skipwhite pgp_entry_format nextgroup=muttrcVarEqualsPGPFmt -syntax keyword muttrcVarStr contained skipwhite query_format nextgroup=muttrcVarEqualsQueryFmt -syntax keyword muttrcVarStr contained skipwhite + \ nextgroup=muttrcVarEqualsPgpCommandFormat +syntax keyword muttrcVarString contained skipwhite pgp_entry_format nextgroup=muttrcVarEqualsPgpEntryFormat +syntax keyword muttrcVarString contained skipwhite query_format nextgroup=muttrcVarEqualsQueryFormat +syntax keyword muttrcVarString contained skipwhite \ smime_decrypt_command smime_encrypt_command smime_get_cert_command \ smime_get_cert_email_command smime_get_signer_cert_command smime_import_cert_command \ smime_pk7out_command smime_sign_command smime_verify_command smime_verify_opaque_command - \ nextgroup=muttrcVarEqualsSmimeFmt -syntax keyword muttrcVarStr contained skipwhite status_format ts_icon_format ts_status_format nextgroup=muttrcVarEqualsStatusFmt -syntax keyword muttrcVarStr contained skipwhite date_format nextgroup=muttrcVarEqualsStrftimeFmt -syntax keyword muttrcVarStr contained skipwhite group_index_format nextgroup=muttrcVarEqualsGrpIdxFmt -syntax keyword muttrcVarStr contained skipwhite sidebar_format nextgroup=muttrcVarEqualsSdbFmt -syntax keyword muttrcVarStr contained skipwhite + \ nextgroup=muttrcVarEqualsSmimeCommandFormat +syntax keyword muttrcVarString contained skipwhite status_format ts_icon_format ts_status_format nextgroup=muttrcVarEqualsStatusFormat +syntax keyword muttrcVarString contained skipwhite date_format nextgroup=muttrcVarEqualsStrftimeFormat +syntax keyword muttrcVarString contained skipwhite group_index_format nextgroup=muttrcVarEqualsGroupIndexFormat +syntax keyword muttrcVarString contained skipwhite sidebar_format nextgroup=muttrcVarEqualsSidebarFormat +syntax keyword muttrcVarString contained skipwhite \ abort_key arrow_string assumed_charset attach_charset attach_sep attribution_locale - \ autocrypt_acct_format charset config_charset content_type crypt_protected_headers_subject - \ default_hook dsn_notify dsn_return empty_subject forward_attribution_intro - \ forward_attribution_trailer greeting header_cache_backend header_cache_compress_method + \ charset config_charset content_type crypt_protected_headers_subject default_hook + \ dsn_notify dsn_return empty_subject header_cache_backend header_cache_compress_method \ hidden_tags hostname imap_authenticators imap_delim_chars imap_headers imap_login - \ imap_pass imap_user indent_string mailcap_path mark_macro_prefix mh_seq_flagged - \ mh_seq_replied mh_seq_unseen newsgroups_charset news_server nm_default_url nm_exclude_tags - \ nm_flagged_tag nm_query_type nm_query_window_current_search nm_query_window_or_terms - \ nm_query_window_timebase nm_record_tags nm_replied_tag nm_unread_tag nntp_authenticators - \ nntp_pass nntp_user pgp_default_key pgp_sign_as pipe_sep pop_authenticators pop_host - \ pop_pass pop_user postpone_encrypt_as post_indent_string preconnect preferred_languages - \ real_name send_charset show_multipart_alternative sidebar_delim_chars sidebar_divider_char - \ sidebar_indent_string simple_search smime_default_key smime_encrypt_with smime_sign_as - \ smime_sign_digest_alg smtp_authenticators smtp_pass smtp_url smtp_user spam_separator - \ ssl_ciphers - \ nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr + \ imap_pass imap_user mailcap_path maildir_field_delimiter mark_macro_prefix mh_seq_flagged + \ mh_seq_replied mh_seq_unseen newsgroups_charset newsrc news_server nm_config_profile + \ nm_default_url nm_exclude_tags nm_flagged_tag nm_query_type nm_query_window_current_search + \ nm_query_window_or_terms nm_query_window_timebase nm_record_tags nm_replied_tag + \ nm_unread_tag nntp_authenticators nntp_pass nntp_user pgp_default_key pgp_sign_as pipe_sep + \ pop_authenticators pop_host pop_pass pop_user postpone_encrypt_as preconnect + \ preferred_languages real_name send_charset show_multipart_alternative sidebar_delim_chars + \ sidebar_divider_char sidebar_indent_string simple_search smime_default_key + \ smime_encrypt_with smime_sign_as smime_sign_digest_alg smtp_authenticators smtp_pass + \ smtp_url smtp_user spam_separator ssl_ciphers + \ nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString " Deprecated strings -syntax keyword muttrcVarDeprecatedStr - \ abort_noattach_regexp attach_keyword escape forw_format hdr_format indent_str msg_format - \ nm_default_uri pgp_clearsign_command pgp_getkeys_command pgp_self_encrypt_as - \ post_indent_str print_cmd quote_regexp realname reply_regexp smime_self_encrypt_as - \ spoolfile visual xterm_icon xterm_title - -" CHECKED 2022-04-08 +syntax keyword muttrcVarDeprecatedString + \ abort_noattach_regexp attach_keyword attribution escape forw_format hdr_format indent_str + \ message_cachedir mixmaster mix_entry_format msg_format nm_default_uri + \ pgp_clearsign_command pgp_getkeys_command pgp_self_encrypt_as post_indent_str + \ post_indent_string print_cmd quote_regexp realname reply_regexp smime_self_encrypt_as + \ spoolfile tmpdir vfolder_format visual xterm_icon xterm_title + +" CHECKED 2024 Oct 12 " List of DT_ADDRESS -syntax keyword muttrcVarStr contained skipwhite envelope_from_address from nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr +syntax keyword muttrcVarString contained skipwhite envelope_from_address from nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString " List of DT_ENUM -syntax keyword muttrcVarStr contained skipwhite mbox_type use_threads nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr +syntax keyword muttrcVarString contained skipwhite mbox_type use_threads nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString " List of DT_MBTABLE -syntax keyword muttrcVarStr contained skipwhite crypt_chars flag_chars from_chars status_chars to_chars nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr - -" CHECKED 2022-04-08 -" List of DT_PATH or DT_MAILBOX -syntax keyword muttrcVarStr contained skipwhite - \ alias_file attach_save_dir autocrypt_dir certificate_file debug_file - \ entropy_file folder header_cache history_file mbox message_cachedir newsrc - \ news_cache_dir postponed record signature smime_ca_location - \ smime_certificates smime_keys spool_file ssl_ca_certificates_file ssl_client_cert - \ tmpdir trash - \ nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr +syntax keyword muttrcVarString contained skipwhite crypt_chars flag_chars from_chars status_chars to_chars nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString + +" CHECKED 2024 Oct 12 +" List of DT_PATH or D_STRING_MAILBOX +syntax keyword muttrcVarString contained skipwhite + \ alias_file attach_save_dir autocrypt_dir certificate_file debug_file entropy_file folder + \ header_cache history_file mbox message_cache_dir news_cache_dir nm_config_file postponed + \ record signature smime_ca_location smime_certificates smime_keys spool_file + \ ssl_ca_certificates_file ssl_client_cert tmp_dir trash + \ nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString " List of DT_COMMAND (excluding pgp_*_command and smime_*_command) -syntax keyword muttrcVarStr contained skipwhite - \ display_filter editor inews ispell mixmaster new_mail_command pager - \ print_command query_command sendmail shell external_search_command - \ imap_oauth_refresh_command pop_oauth_refresh_command - \ mime_type_query_command smtp_oauth_refresh_command tunnel - \ nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr - -" CHECKED 2022-04-08 +syntax keyword muttrcVarString contained skipwhite + \ account_command display_filter editor external_search_command imap_oauth_refresh_command + \ inews ispell mime_type_query_command new_mail_command pager pop_oauth_refresh_command + \ print_command query_command sendmail shell smtp_oauth_refresh_command tunnel + \ nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString + +" CHECKED 2024 Oct 12 " List of DT_REGEX -syntax keyword muttrcVarStr contained skipwhite - \ abort_noattach_regex gecos_mask mask pgp_decryption_okay pgp_good_sign quote_regex +syntax keyword muttrcVarString contained skipwhite + \ abort_noattach_regex gecos_mask mask pgp_decryption_okay pgp_good_sign quote_regex \ reply_regex smileys - \ nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr + \ nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString " List of DT_SORT -syntax keyword muttrcVarStr contained skipwhite +syntax keyword muttrcVarString contained skipwhite \ pgp_sort_keys sidebar_sort_method sort sort_alias sort_aux sort_browser - \ nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr + \ nextgroup=muttrcSetStrAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString -" CHECKED 2022-04-08 -" List of commands in mutt_commands in mutt_commands.c +" CHECKED 2024 Oct 12 +" List of commands in mutt_commands in commands.c " Remember to remove hooks, they have already been dealt with syntax keyword muttrcCommand skipwhite alias nextgroup=muttrcAliasGroupDef,muttrcAliasKey,muttrcAliasNL syntax keyword muttrcCommand skipwhite bind nextgroup=muttrcBindMenuList,muttrcBindMenuListNL syntax keyword muttrcCommand skipwhite exec nextgroup=muttrcFunction syntax keyword muttrcCommand skipwhite macro nextgroup=muttrcMacroMenuList,muttrcMacroMenuListNL syntax keyword muttrcCommand skipwhite nospam nextgroup=muttrcNoSpamPattern -syntax keyword muttrcCommand skipwhite set unset reset toggle nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr +syntax keyword muttrcCommand skipwhite set unset reset toggle nextgroup=muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarString syntax keyword muttrcCommand skipwhite spam nextgroup=muttrcSpamPattern syntax keyword muttrcCommand skipwhite unalias nextgroup=muttrcUnAliasKey,muttrcUnAliasNL syntax keyword muttrcCommand skipwhite unhook nextgroup=muttrcHooks syntax keyword muttrcCommand skipwhite \ alternative_order attachments auto_view cd echo finish hdr_order ifdef ifndef ignore lua \ lua-source mailboxes mailto_allow mime_lookup my_hdr named-mailboxes push score setenv - \ sidebar_whitelist source subjectrx subscribe-to tag-formats tag-transforms + \ sidebar_pin sidebar_unpin source subjectrx subscribe-to tag-formats tag-transforms \ unalternative_order unattachments unauto_view unbind uncolor unhdr_order unignore unmacro - \ unmailboxes unmailto_allow unmime_lookup unmono unmy_hdr unscore unsetenv - \ unsidebar_whitelist unsubjectrx unsubscribe-from unvirtual-mailboxes virtual-mailboxes + \ unmailboxes unmailto_allow unmime_lookup unmono unmy_hdr unscore unsetenv unsubjectrx + \ unsubscribe-from unvirtual-mailboxes version virtual-mailboxes + +" CHECKED 2024 Oct 12 +" Deprecated commands +syntax keyword muttrcDeprecatedCommand skipwhite + \ sidebar_whitelist unsidebar_whitelist function! s:genFunctions(functions) for f in a:functions @@ -636,68 +667,67 @@ function! s:genFunctions(functions) endfor endfunction -" CHECKED 2022-04-08 +" CHECKED 2024 Oct 12 " List of functions in functions.c " Note: 'noop' is included but is elsewhere in the source call s:genFunctions(['noop', - \ 'accept', 'alias-dialog', 'append', 'attach-file', 'attach-key', 'attach-message', - \ 'attach-news-message', 'autocrypt-acct-menu', 'autocrypt-menu', 'backspace', - \ 'backward-char', 'backward-word', 'bol', 'bottom', 'bottom-page', 'bounce-message', - \ 'break-thread', 'buffy-cycle', 'buffy-list', 'capitalize-word', 'catchup', 'chain-next', - \ 'chain-prev', 'change-dir', 'change-folder', 'change-folder-readonly', 'change-newsgroup', - \ 'change-newsgroup-readonly', 'change-vfolder', 'check-new', 'check-stats', - \ 'check-traditional-pgp', 'clear-flag', 'collapse-all', 'collapse-parts', - \ 'collapse-thread', 'complete', 'complete-query', 'compose-to-sender', 'copy-file', - \ 'copy-message', 'create-account', 'create-alias', 'create-mailbox', 'current-bottom', - \ 'current-middle', 'current-top', 'decode-copy', 'decode-save', 'decrypt-copy', - \ 'decrypt-save', 'delete', 'delete-account', 'delete-char', 'delete-entry', - \ 'delete-mailbox', 'delete-message', 'delete-pattern', 'delete-subthread', 'delete-thread', - \ 'descend-directory', 'detach-file', 'display-address', 'display-filename', - \ 'display-message', 'display-toggle-weed', 'downcase-word', 'edit', 'edit-bcc', 'edit-cc', - \ 'edit-content-id', 'edit-description', 'edit-encoding', 'edit-fcc', 'edit-file', - \ 'edit-followup-to', 'edit-from', 'edit-headers', 'edit-label', 'edit-language', - \ 'edit-message', 'edit-mime', 'edit-newsgroups', 'edit-or-view-raw-message', - \ 'edit-raw-message', 'edit-reply-to', 'edit-subject', 'edit-to', 'edit-type', - \ 'edit-x-comment-to', 'end-cond', 'enter-command', 'enter-mask', 'entire-thread', 'eol', - \ 'error-history', 'exit', 'extract-keys', 'fetch-mail', 'filter-entry', 'first-entry', - \ 'flag-message', 'followup-message', 'forget-passphrase', 'forward-char', - \ 'forward-message', 'forward-to-group', 'forward-word', 'get-attachment', 'get-children', - \ 'get-message', 'get-parent', 'goto-folder', 'goto-parent', 'group-alternatives', - \ 'group-chat-reply', 'group-multilingual', 'group-related', 'group-reply', 'half-down', - \ 'half-up', 'help', 'history-down', 'history-search', 'history-up', 'imap-fetch-mail', - \ 'imap-logout-all', 'insert', 'ispell', 'jump', 'kill-eol', 'kill-eow', 'kill-line', - \ 'kill-word', 'last-entry', 'limit', 'limit-current-thread', 'link-threads', 'list-reply', - \ 'list-subscribe', 'list-unsubscribe', 'mail', 'mail-key', 'mailbox-cycle', 'mailbox-list', - \ 'mark-as-new', 'mark-message', 'middle-page', 'mix', 'modify-labels', - \ 'modify-labels-then-hide', 'modify-tags', 'modify-tags-then-hide', 'move-down', 'move-up', - \ 'new-mime', 'next-entry', 'next-line', 'next-new', 'next-new-then-unread', 'next-page', - \ 'next-subthread', 'next-thread', 'next-undeleted', 'next-unread', 'next-unread-mailbox', - \ 'parent-message', 'pgp-menu', 'pipe-entry', 'pipe-message', 'post-message', - \ 'postpone-message', 'previous-entry', 'previous-line', 'previous-new', - \ 'previous-new-then-unread', 'previous-page', 'previous-subthread', 'previous-thread', - \ 'previous-undeleted', 'previous-unread', 'print-entry', 'print-message', 'purge-message', - \ 'purge-thread', 'quasi-delete', 'query', 'query-append', 'quit', 'quote-char', - \ 'read-subthread', 'read-thread', 'recall-message', 'reconstruct-thread', 'redraw-screen', - \ 'refresh', 'reload-active', 'rename-attachment', 'rename-file', 'rename-mailbox', 'reply', - \ 'resend-message', 'root-message', 'save-entry', 'save-message', 'search', 'search-next', - \ 'search-opposite', 'search-reverse', 'search-toggle', 'select-entry', 'select-new', - \ 'send-message', 'set-flag', 'shell-escape', 'show-limit', 'show-log-messages', - \ 'show-version', 'sidebar-first', 'sidebar-last', 'sidebar-next', 'sidebar-next-new', - \ 'sidebar-open', 'sidebar-page-down', 'sidebar-page-up', 'sidebar-prev', - \ 'sidebar-prev-new', 'sidebar-toggle-virtual', 'sidebar-toggle-visible', 'skip-headers', - \ 'skip-quoted', 'smime-menu', 'sort', 'sort-alias', 'sort-alias-reverse', 'sort-mailbox', - \ 'sort-reverse', 'subscribe', 'subscribe-pattern', 'sync-mailbox', 'tag-entry', - \ 'tag-message', 'tag-pattern', 'tag-prefix', 'tag-prefix-cond', 'tag-subthread', - \ 'tag-thread', 'toggle-active', 'toggle-disposition', 'toggle-mailboxes', 'toggle-new', - \ 'toggle-prefer-encrypt', 'toggle-quoted', 'toggle-read', 'toggle-recode', - \ 'toggle-subscribed', 'toggle-unlink', 'toggle-write', 'top', 'top-page', - \ 'transpose-chars', 'uncatchup', 'undelete-entry', 'undelete-message', 'undelete-pattern', - \ 'undelete-subthread', 'undelete-thread', 'ungroup-attachment', 'unsubscribe', - \ 'unsubscribe-pattern', 'untag-pattern', 'upcase-word', 'update-encoding', 'verify-key', - \ 'vfolder-from-query', 'vfolder-from-query-readonly', 'vfolder-window-backward', - \ 'vfolder-window-forward', 'vfolder-window-reset', 'view-attach', 'view-attachments', - \ 'view-file', 'view-mailcap', 'view-name', 'view-pager', 'view-raw-message', 'view-text', - \ 'what-key', 'write-fcc' + \ 'alias-dialog', 'attach-file', 'attach-key', 'attach-message', 'attach-news-message', + \ 'autocrypt-acct-menu', 'autocrypt-menu', 'backspace', 'backward-char', 'backward-word', + \ 'bol', 'bottom', 'bottom-page', 'bounce-message', 'break-thread', 'buffy-cycle', + \ 'buffy-list', 'capitalize-word', 'catchup', 'change-dir', 'change-folder', + \ 'change-folder-readonly', 'change-newsgroup', 'change-newsgroup-readonly', + \ 'change-vfolder', 'check-new', 'check-stats', 'check-traditional-pgp', 'clear-flag', + \ 'collapse-all', 'collapse-parts', 'collapse-thread', 'complete', 'complete-query', + \ 'compose-to-sender', 'copy-file', 'copy-message', 'create-account', 'create-alias', + \ 'create-mailbox', 'current-bottom', 'current-middle', 'current-top', 'decode-copy', + \ 'decode-save', 'decrypt-copy', 'decrypt-save', 'delete-account', 'delete-char', + \ 'delete-entry', 'delete-mailbox', 'delete-message', 'delete-pattern', 'delete-subthread', + \ 'delete-thread', 'descend-directory', 'detach-file', 'display-address', + \ 'display-filename', 'display-message', 'display-toggle-weed', 'downcase-word', 'edit', + \ 'edit-bcc', 'edit-cc', 'edit-content-id', 'edit-description', 'edit-encoding', 'edit-fcc', + \ 'edit-file', 'edit-followup-to', 'edit-from', 'edit-headers', 'edit-label', + \ 'edit-language', 'edit-message', 'edit-mime', 'edit-newsgroups', + \ 'edit-or-view-raw-message', 'edit-raw-message', 'edit-reply-to', 'edit-subject', + \ 'edit-to', 'edit-type', 'edit-x-comment-to', 'end-cond', 'enter-command', 'enter-mask', + \ 'entire-thread', 'eol', 'error-history', 'exit', 'extract-keys', 'fetch-mail', + \ 'filter-entry', 'first-entry', 'flag-message', 'followup-message', 'forget-passphrase', + \ 'forward-char', 'forward-message', 'forward-to-group', 'forward-word', 'get-attachment', + \ 'get-children', 'get-message', 'get-parent', 'goto-folder', 'goto-parent', + \ 'group-alternatives', 'group-chat-reply', 'group-multilingual', 'group-related', + \ 'group-reply', 'half-down', 'half-up', 'help', 'history-down', 'history-search', + \ 'history-up', 'imap-fetch-mail', 'imap-logout-all', 'ispell', 'jump', 'kill-eol', + \ 'kill-eow', 'kill-line', 'kill-whole-line', 'kill-word', 'last-entry', 'limit', + \ 'limit-current-thread', 'link-threads', 'list-reply', 'list-subscribe', + \ 'list-unsubscribe', 'mail', 'mail-key', 'mailbox-cycle', 'mailbox-list', 'mark-as-new', + \ 'mark-message', 'middle-page', 'modify-labels', 'modify-labels-then-hide', 'modify-tags', + \ 'modify-tags-then-hide', 'move-down', 'move-up', 'new-mime', 'next-entry', 'next-line', + \ 'next-new', 'next-new-then-unread', 'next-page', 'next-subthread', 'next-thread', + \ 'next-undeleted', 'next-unread', 'next-unread-mailbox', 'parent-message', 'pgp-menu', + \ 'pipe-entry', 'pipe-message', 'post-message', 'postpone-message', 'previous-entry', + \ 'previous-line', 'previous-new', 'previous-new-then-unread', 'previous-page', + \ 'previous-subthread', 'previous-thread', 'previous-undeleted', 'previous-unread', + \ 'print-entry', 'print-message', 'purge-message', 'purge-thread', 'quasi-delete', 'query', + \ 'query-append', 'quit', 'quote-char', 'read-subthread', 'read-thread', 'recall-message', + \ 'reconstruct-thread', 'redraw-screen', 'refresh', 'reload-active', 'rename-attachment', + \ 'rename-file', 'rename-mailbox', 'reply', 'resend-message', 'root-message', 'save-entry', + \ 'save-message', 'search', 'search-next', 'search-opposite', 'search-reverse', + \ 'search-toggle', 'select-entry', 'select-new', 'send-message', 'set-flag', 'shell-escape', + \ 'show-limit', 'show-log-messages', 'show-version', 'sidebar-first', 'sidebar-last', + \ 'sidebar-next', 'sidebar-next-new', 'sidebar-open', 'sidebar-page-down', + \ 'sidebar-page-up', 'sidebar-prev', 'sidebar-prev-new', 'sidebar-toggle-virtual', + \ 'sidebar-toggle-visible', 'skip-headers', 'skip-quoted', 'smime-menu', 'sort', + \ 'sort-alias', 'sort-alias-reverse', 'sort-mailbox', 'sort-reverse', 'subscribe', + \ 'subscribe-pattern', 'sync-mailbox', 'tag-entry', 'tag-message', 'tag-pattern', + \ 'tag-prefix', 'tag-prefix-cond', 'tag-subthread', 'tag-thread', 'toggle-active', + \ 'toggle-disposition', 'toggle-mailboxes', 'toggle-new', 'toggle-prefer-encrypt', + \ 'toggle-quoted', 'toggle-read', 'toggle-recode', 'toggle-subscribed', 'toggle-unlink', + \ 'toggle-write', 'top', 'top-page', 'transpose-chars', 'uncatchup', 'undelete-entry', + \ 'undelete-message', 'undelete-pattern', 'undelete-subthread', 'undelete-thread', + \ 'ungroup-attachment', 'unsubscribe', 'unsubscribe-pattern', 'untag-pattern', + \ 'upcase-word', 'update-encoding', 'verify-key', 'vfolder-from-query', + \ 'vfolder-from-query-readonly', 'vfolder-window-backward', 'vfolder-window-forward', + \ 'vfolder-window-reset', 'view-attach', 'view-attachments', 'view-file', 'view-mailcap', + \ 'view-name', 'view-pager', 'view-raw-message', 'view-text', 'what-key', 'write-fcc' \ ]) " Define the default highlighting. @@ -713,29 +743,23 @@ highlight def link muttrcBadAction Error highlight def link muttrcBindFunction Error highlight def link muttrcBindMenuList Error highlight def link muttrcColorBG Error -highlight def link muttrcColorBGH Error -highlight def link muttrcColorBGI Error highlight def link muttrcColorContext Error highlight def link muttrcColorFG Error -highlight def link muttrcColorFGH Error -highlight def link muttrcColorFGI Error highlight def link muttrcColorLine Error +highlight def link muttrcDeprecatedCommand Error highlight def link muttrcFormatErrors Error highlight def link muttrcGroupLine Error -highlight def link muttrcListsLine Error highlight def link muttrcPattern Error -highlight def link muttrcSubscribeLine Error highlight def link muttrcUnColorLine Error highlight def link muttrcVarDeprecatedBool Error +highlight def link muttrcVarDeprecatedNum Error highlight def link muttrcVarDeprecatedQuad Error -highlight def link muttrcVarDeprecatedStr Error +highlight def link muttrcVarDeprecatedString Error highlight def link muttrcAliasEncEmail Identifier highlight def link muttrcAliasKey Identifier highlight def link muttrcColorCompose Identifier highlight def link muttrcColorComposeField Identifier -highlight def link muttrcColorContextH Identifier -highlight def link muttrcColorContextI Identifier highlight def link muttrcColorField Identifier highlight def link muttrcMenu Identifier highlight def link muttrcSimplePat Identifier @@ -744,7 +768,7 @@ highlight def link muttrcUnColorIndex Identifier highlight def link muttrcVarBool Identifier highlight def link muttrcVarNum Identifier highlight def link muttrcVarQuad Identifier -highlight def link muttrcVarStr Identifier +highlight def link muttrcVarString Identifier highlight def link muttrcCommand Keyword @@ -769,52 +793,61 @@ highlight def link muttrcUnColorKeyword muttrcCommand highlight def link muttrcAliasFormatEscapes muttrcEscape highlight def link muttrcAttachFormatEscapes muttrcEscape +highlight def link muttrcAutocryptFormatEscapes muttrcEscape highlight def link muttrcComposeFormatEscapes muttrcEscape highlight def link muttrcFolderFormatEscapes muttrcEscape +highlight def link muttrcGreetingFormatEscapes muttrcEscape highlight def link muttrcGroupIndexFormatEscapes muttrcEscape +highlight def link muttrcHistoryFormatEscapes muttrcEscape highlight def link muttrcIndexFormatEscapes muttrcEscape -highlight def link muttrcMixFormatEscapes muttrcEscape highlight def link muttrcPatternFormatEscapes muttrcEscape -highlight def link muttrcPGPCmdFormatEscapes muttrcEscape -highlight def link muttrcPGPFormatEscapes muttrcEscape -highlight def link muttrcPGPTimeEscapes muttrcEscape +highlight def link muttrcPgpCommandFormatEscapes muttrcEscape +highlight def link muttrcPgpEntryFormatEscapes muttrcEscape +highlight def link muttrcPgpTimeEscapes muttrcEscape highlight def link muttrcQueryFormatEscapes muttrcEscape highlight def link muttrcShellString muttrcEscape highlight def link muttrcSidebarFormatEscapes muttrcEscape -highlight def link muttrcSmimeFormatEscapes muttrcEscape +highlight def link muttrcSmimeCommandFormatEscapes muttrcEscape highlight def link muttrcStatusFormatEscapes muttrcEscape highlight def link muttrcTimeEscapes muttrcEscape -highlight def link muttrcAliasFormatConditionals muttrcFormatConditionals2 -highlight def link muttrcAttachFormatConditionals muttrcFormatConditionals2 -highlight def link muttrcComposeFormatConditionals muttrcFormatConditionals2 -highlight def link muttrcFolderFormatConditionals muttrcFormatConditionals2 -highlight def link muttrcIndexFormatConditionals muttrcFormatConditionals2 -highlight def link muttrcMixFormatConditionals muttrcFormatConditionals2 -highlight def link muttrcPatternFormatConditionals muttrcFormatConditionals2 -highlight def link muttrcPGPCmdFormatConditionals muttrcFormatConditionals2 -highlight def link muttrcPGPFormatConditionals muttrcFormatConditionals2 -highlight def link muttrcSmimeFormatConditionals muttrcFormatConditionals2 -highlight def link muttrcStatusFormatConditionals muttrcFormatConditionals2 +highlight def link muttrcAliasFormatConditionals muttrcFormatConditionals2 +highlight def link muttrcAttachFormatConditionals muttrcFormatConditionals2 +highlight def link muttrcAutocryptFormatConditionals muttrcFormatConditionals2 +highlight def link muttrcComposeFormatConditionals muttrcFormatConditionals2 +highlight def link muttrcFolderFormatConditionals muttrcFormatConditionals2 +highlight def link muttrcGreetingFormatConditionals muttrcFormatConditionals2 +highlight def link muttrcGroupIndexFormatConditionals muttrcFormatConditionals2 +highlight def link muttrcHistoryFormatConditionals muttrcFormatConditionals2 +highlight def link muttrcIndexFormatConditionals muttrcFormatConditionals2 +highlight def link muttrcPatternFormatConditionals muttrcFormatConditionals2 +highlight def link muttrcPgpCommandFormatConditionals muttrcFormatConditionals2 +highlight def link muttrcPgpEntryFormatConditionals muttrcFormatConditionals2 +highlight def link muttrcQueryFormatConditionals muttrcFormatConditionals2 +highlight def link muttrcSidebarFormatConditionals muttrcFormatConditionals2 +highlight def link muttrcSmimeCommandFormatConditionals muttrcFormatConditionals2 +highlight def link muttrcStatusFormatConditionals muttrcFormatConditionals2 highlight def link muttrcAddrDef muttrcGroupFlag highlight def link muttrcRXDef muttrcGroupFlag -highlight def link muttrcAliasFormatStr muttrcString -highlight def link muttrcAttachFormatStr muttrcString -highlight def link muttrcComposeFormatStr muttrcString -highlight def link muttrcFolderFormatStr muttrcString -highlight def link muttrcGroupIndexFormatStr muttrcString -highlight def link muttrcIndexFormatStr muttrcString -highlight def link muttrcMixFormatStr muttrcString -highlight def link muttrcPatternFormatStr muttrcString -highlight def link muttrcPGPCmdFormatStr muttrcString -highlight def link muttrcPGPFormatStr muttrcString -highlight def link muttrcQueryFormatStr muttrcString -highlight def link muttrcSidebarFormatStr muttrcString -highlight def link muttrcSmimeFormatStr muttrcString -highlight def link muttrcStatusFormatStr muttrcString -highlight def link muttrcStrftimeFormatStr muttrcString +highlight def link muttrcAliasFormatString muttrcString +highlight def link muttrcAttachFormatString muttrcString +highlight def link muttrcAutocryptFormatString muttrcString +highlight def link muttrcComposeFormatString muttrcString +highlight def link muttrcFolderFormatString muttrcString +highlight def link muttrcGreetingFormatString muttrcString +highlight def link muttrcGroupIndexFormatString muttrcString +highlight def link muttrcHistoryFormatString muttrcString +highlight def link muttrcIndexFormatString muttrcString +highlight def link muttrcPatternFormatString muttrcString +highlight def link muttrcPgpCommandFormatString muttrcString +highlight def link muttrcPgpEntryFormatString muttrcString +highlight def link muttrcQueryFormatString muttrcString +highlight def link muttrcSidebarFormatString muttrcString +highlight def link muttrcSmimeCommandFormatString muttrcString +highlight def link muttrcStatusFormatString muttrcString +highlight def link muttrcStrftimeFormatString muttrcString highlight def link muttrcSetNumAssignment Number @@ -843,7 +876,6 @@ highlight def link muttrcMacroBodyNL SpecialChar highlight def link muttrcMacroDescrNL SpecialChar highlight def link muttrcMacroKeyNL SpecialChar highlight def link muttrcMacroMenuListNL SpecialChar -highlight def link muttrcPatternNL SpecialChar highlight def link muttrcRXChars SpecialChar highlight def link muttrcStringNL SpecialChar highlight def link muttrcUnAliasNL SpecialChar @@ -860,7 +892,6 @@ highlight def link muttrcRXString2 String highlight def link muttrcSetStrAssignment String highlight def link muttrcString String -highlight def link muttrcAliasParens Type highlight def link muttrcAttachmentsFlag Type highlight def link muttrcColor Type highlight def link muttrcFormatConditionals2 Type diff --git a/runtime/syntax/org.vim b/runtime/syntax/org.vim new file mode 100644 index 0000000000..89c8de31b4 --- /dev/null +++ b/runtime/syntax/org.vim @@ -0,0 +1,71 @@ +" Vim syntax file +" Language: Org +" Maintainer: Luca Saccarola <github.e41mv@aleeas.com> +" Last Change: 2024 Nov 14 +" +" Reference Specification: Org mode manual +" GNU Info: `$ info Org` +" Web: <https://orgmode.org/manual/index.html> + +" Quit when a (custom) syntax file was already loaded +if exists("b:current_syntax") + finish +endif +let b:current_syntax = 'org' + +syn case ignore + +" Bold +syn region orgBold matchgroup=orgBoldDelimiter start="\(^\|[- '"({\]]\)\@<=\*\ze[^ ]" end="^\@!\*\([^\k\*]\|$\)\@=" keepend +hi def link orgBold markdownBold +hi def link orgBoldDelimiter orgBold + +" Italic +syn region orgItalic matchgroup=orgItalicDelimiter start="\(^\|[- '"({\]]\)\@<=\/\ze[^ ]" end="^\@!\/\([^\k\/]\|$\)\@=" keepend +hi def link orgItalic markdownItalic +hi def link orgItalicDelimiter orgItalic + +" Strikethrogh +syn region orgStrikethrough matchgroup=orgStrikethroughDelimiter start="\(^\|[ '"({\]]\)\@<=+\ze[^ ]" end="^\@!+\([^\k+]\|$\)\@=" keepend +hi def link orgStrikethrough markdownStrike +hi def link orgStrikethroughDelimiter orgStrikethrough + +" Underline +syn region orgUnderline matchgroup=orgUnderlineDelimiter start="\(^\|[- '"({\]]\)\@<=_\ze[^ ]" end="^\@!_\([^\k_]\|$\)\@=" keepend + +" Headlines +syn match orgHeadline "^\*\+\s\+.*$" keepend +hi def link orgHeadline Title + +" Line Comment +syn match orgLineComment /^\s*#\s\+.*$/ keepend +hi def link orgLineComment Comment + +" Block Comment +syn region orgBlockComment matchgroup=orgBlockCommentDelimiter start="\c^\s*#+BEGIN_COMMENT" end="\c^\s*#+END_COMMENT" keepend +hi def link orgBlockComment Comment +hi def link orgBlockCommentDelimiter Comment + +" Lists +syn match orgUnorderedListMarker "^\s*[-+]\s\+" keepend +hi def link orgUnorderedListMarker markdownOrderedListMarker +syn match orgOrderedListMarker "^\s*\(\d\|\a\)\+[.)]\s\+" keepend +hi def link orgOrderedListMarker markdownOrderedListMarker +" +" Verbatim +syn region orgVerbatimInline matchgroup=orgVerbatimInlineDelimiter start="\(^\|[- '"({\]]\)\@<==\ze[^ ]" end="^\@!=\([^\k=]\|$\)\@=" keepend +hi def link orgVerbatimInline markdownCodeBlock +hi def link orgVerbatimInlineDelimiter orgVerbatimInline +syn region orgVerbatimBlock matchgroup=orgVerbatimBlockDelimiter start="\c^\s*#+BEGIN_.*" end="\c^\s*#+END_.*" keepend +hi def link orgVerbatimBlock orgCode +hi def link orgVerbatimBlockDelimiter orgVerbatimBlock + +" Code +syn region orgCodeInline matchgroup=orgCodeInlineDelimiter start="\(^\|[- '"({\]]\)\@<=\~\ze[^ ]" end="^\@!\~\([^\k\~]\|$\)\@=" keepend +highlight def link orgCodeInline markdownCodeBlock +highlight def link orgCodeInlineDelimiter orgCodeInline +syn region orgCodeBlock matchgroup=orgCodeBlockDelimiter start="\c^\s*#+BEGIN_SRC.*" end="\c^\s*#+END_SRC" keepend +highlight def link orgCodeBlock markdownCodeBlock +highlight def link orgCodeBlockDelimiter orgCodeBlock + +" vim: ts=8 sts=2 sw=2 et diff --git a/runtime/syntax/racket.vim b/runtime/syntax/racket.vim index fcd64a7c9b..7dcca6082c 100644 --- a/runtime/syntax/racket.vim +++ b/runtime/syntax/racket.vim @@ -4,7 +4,7 @@ " Previous Maintainer: Will Langstroth <will@langstroth.com> " URL: https://github.com/benknoble/vim-racket " Description: Contains all of the keywords in #lang racket -" Last Change: 2023 Sep 22 +" Last Change: 2024 Apr 14 " Initializing: if exists("b:current_syntax") @@ -30,7 +30,7 @@ endif " http://docs.racket-lang.org/reference/index.html " syntax keyword racketSyntax module module* module+ require provide quote -syntax keyword racketSyntax #%datum #%expression #%top #%variable-reference #%app +syntax keyword racketSyntax #%module-begin #%datum #%expression #%top #%variable-reference #%app syntax keyword racketSyntax lambda case-lambda let let* letrec syntax keyword racketSyntax let-values let*-values let-syntax letrec-syntax syntax keyword racketSyntax let-syntaxes letrec-syntaxes letrec-syntaxes+values diff --git a/runtime/syntax/shared/debversions.vim b/runtime/syntax/shared/debversions.vim index 56f18b969a..404a0a49e3 100644 --- a/runtime/syntax/shared/debversions.vim +++ b/runtime/syntax/shared/debversions.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: Debian version information " Maintainer: Debian Vim Maintainers -" Last Change: 2024 May 25 +" Last Change: 2024 Nov 04 " URL: https://salsa.debian.org/vim-team/vim-debian/blob/main/syntax/shared/debversions.vim let s:cpo = &cpo @@ -11,7 +11,7 @@ let g:debSharedSupportedVersions = [ \ 'oldstable', 'stable', 'testing', 'unstable', 'experimental', 'sid', 'rc-buggy', \ 'bullseye', 'bookworm', 'trixie', 'forky', \ - \ 'focal', 'jammy', 'mantic', 'noble', 'oracular', + \ 'focal', 'jammy', 'noble', 'oracular', 'plucky', \ 'devel' \ ] let g:debSharedUnsupportedVersions = [ @@ -23,8 +23,8 @@ let g:debSharedUnsupportedVersions = [ \ 'gutsy', 'hardy', 'intrepid', 'jaunty', 'karmic', 'lucid', \ 'maverick', 'natty', 'oneiric', 'precise', 'quantal', 'raring', 'saucy', \ 'trusty', 'utopic', 'vivid', 'wily', 'xenial', 'yakkety', 'zesty', - \ 'artful', 'bionic', 'cosmic', 'disco', 'eoan', 'hirsute', - \ 'impish', 'kinetic', 'lunar', 'groovy' + \ 'artful', 'bionic', 'cosmic', 'disco', 'eoan', 'groovy', + \ 'hirsute', 'impish', 'kinetic', 'lunar', 'mantic', \ ] let &cpo=s:cpo diff --git a/runtime/syntax/skill.vim b/runtime/syntax/skill.vim index 47afffc0a9..dd4c191b6f 100644 --- a/runtime/syntax/skill.vim +++ b/runtime/syntax/skill.vim @@ -1,13 +1,14 @@ " Vim syntax file " Language: SKILL " Maintainer: Toby Schaffer <jtschaff@eos.ncsu.edu> -" Last Change: 2003 May 11 " Comments: SKILL is a Lisp-like programming language for use in EDA " tools from Cadence Design Systems. It allows you to have " a programming environment within the Cadence environment " that gives you access to the complete tool set and design " database. This file also defines syntax highlighting for " certain Design Framework II interface functions. +" Last Change: 2003 May 11 +" 2024 Oct 08 by Vim Project: allow double backslashes in skillString " quit when a syntax file was already loaded if exists("b:current_syntax") @@ -509,7 +510,7 @@ syn match skilltechFunctions "(\(tech\|tc\)\u\a\+\>"hs=s+1 syn match skilltechFunctions "\<\(tech\|tc\)\u\a\+("he=e-1 " strings -syn region skillString start=+"+ skip=+\\"+ end=+"+ +syn region skillString start=+"+ skip=+\\\@<!\\"+ end=+"+ syn keyword skillTodo contained TODO FIXME XXX syn keyword skillNote contained NOTE IMPORTANT diff --git a/runtime/syntax/structurizr.vim b/runtime/syntax/structurizr.vim index 363ee70438..c10f1a4569 100644 --- a/runtime/syntax/structurizr.vim +++ b/runtime/syntax/structurizr.vim @@ -1,10 +1,9 @@ " Vim syntax file " Language: Structurizr DSL " Maintainer: Bastian Venthur <venthur@debian.org> -" Last Change: 2022-05-22 +" Last Change: 2024-11-06 " Remark: For a language reference, see -" https://github.com/structurizr/dsl - +" https://docs.structurizr.com/dsl/language if exists("b:current_syntax") finish @@ -20,7 +19,11 @@ syn region scomment start="/\*" end="\*/" " keywords syn keyword skeyword animation syn keyword skeyword autoLayout +syn keyword skeyword background +syn keyword skeyword border syn keyword skeyword branding +syn keyword skeyword color +syn keyword skeyword colour syn keyword skeyword component syn keyword skeyword configuration syn keyword skeyword container @@ -37,48 +40,74 @@ syn keyword skeyword element syn keyword skeyword enterprise syn keyword skeyword exclude syn keyword skeyword filtered +syn keyword skeyword font +syn keyword skeyword fontsize syn keyword skeyword group syn keyword skeyword healthcheck +syn keyword skeyword height +syn keyword skeyword icon +syn keyword skeyword image syn keyword skeyword include syn keyword skeyword infrastructurenode syn keyword skeyword instances +syn keyword skeyword logo +syn keyword skeyword metadata syn keyword skeyword model +syn keyword skeyword opacity syn keyword skeyword person syn keyword skeyword perspectives syn keyword skeyword properties syn keyword skeyword relationship +syn keyword skeyword routing +syn keyword skeyword scope +syn keyword skeyword shape syn keyword skeyword softwaresystem syn keyword skeyword softwaresysteminstance +syn keyword skeyword stroke +syn keyword skeyword strokewidth syn keyword skeyword styles syn keyword skeyword systemcontext syn keyword skeyword systemlandscape +syn keyword skeyword tag syn keyword skeyword tags syn keyword skeyword technology syn keyword skeyword terminology syn keyword skeyword theme syn keyword skeyword themes +syn keyword skeyword thickness +syn keyword skeyword this syn keyword skeyword title syn keyword skeyword url syn keyword skeyword users syn keyword skeyword views +syn keyword skeyword visibility +syn keyword skeyword width syn keyword skeyword workspace syn match skeyword "\!adrs\s\+" -syn match skeyword "\!constant\s\+" +syn match skeyword "\!components\s\+" syn match skeyword "\!docs\s\+" +syn match skeyword "\!element\s\+" +syn match skeyword "\!elements\s\+" +syn match skeyword "\!extend\s\+" syn match skeyword "\!identifiers\s\+" syn match skeyword "\!impliedrelationships\s\+" syn match skeyword "\!include\s\+" syn match skeyword "\!plugin\s\+" syn match skeyword "\!ref\s\+" +syn match skeyword "\!relationship\s\+" +syn match skeyword "\!relationships\s\+" syn match skeyword "\!script\s\+" syn region sstring oneline start='"' end='"' syn region sblock start='{' end='}' fold transparent +syn match soperator "\->\s+" + hi def link sstring string hi def link scomment comment hi def link skeyword keyword +hi def link soperator operator let b:current_syntax = "structurizr" diff --git a/runtime/syntax/swayconfig.vim b/runtime/syntax/swayconfig.vim index d09d476a5a..94b9a913fc 100644 --- a/runtime/syntax/swayconfig.vim +++ b/runtime/syntax/swayconfig.vim @@ -3,7 +3,7 @@ " Original Author: Josef Litos (JosefLitos/i3config.vim) " Maintainer: James Eapen <james.eapen@vai.org> " Version: 1.2.4 -" Last Change: 2024-05-24 +" Last Change: 2024 Oct 17 " References: " http://i3wm.org/docs/userguide.html#configuring @@ -29,7 +29,7 @@ syn keyword i3ConfigConditionProp app_id pid shell contained syn keyword i3ConfigWorkspaceDir prev_on_output next_on_output contained -syn match i3ConfigBindArgument /--\(locked\|to-code\|no-repeat\|input-device=[^ '"]*\|no-warn\) / contained contains=i3ConfigShOper,@i3ConfigStrVar nextgroup=i3ConfigBindArgument,i3ConfigBindCombo +syn match i3ConfigBindArgument /--\(locked\|to-code\|no-repeat\|input-device=[^ '"]*\|no-warn\|inhibited\) / contained contains=i3ConfigShOper,@i3ConfigStrVar nextgroup=i3ConfigBindArgument,i3ConfigBindCombo syn region i3ConfigBindArgument start=/--input-device=['"]/ end=/\s/ contained contains=@i3ConfigIdent,i3ConfigShOper,i3ConfigString nextgroup=i3ConfigBindArgument,i3ConfigBindCombo syn region i3ConfigBindCombo matchgroup=i3ConfigParen start=/{$/ end=/^\s*}$/ contained contains=i3ConfigBindArgument,i3ConfigBindCombo,i3ConfigComment fold keepend extend diff --git a/runtime/syntax/tex.vim b/runtime/syntax/tex.vim index d782bd4845..77a40e11d3 100644 --- a/runtime/syntax/tex.vim +++ b/runtime/syntax/tex.vim @@ -109,9 +109,9 @@ if s:tex_fold_enabled && &fdm == "manual" setl fdm=syntax endif if s:tex_fold_enabled && has("folding") - com! -nargs=* TexFold <args> fold + com! -nargs=* TexFold <args> fold else - com! -nargs=* TexFold <args> + com! -nargs=* TexFold <args> endif " (La)TeX keywords: uses the characters 0-9,a-z,A-Z,192-255 only... {{{1 @@ -424,7 +424,7 @@ if s:tex_fast =~# 'b' syn region texEmphStyle matchgroup=texTypeStyle start="\\texts[cfl]\s*{" matchgroup=texTypeStyle end="}" concealends contains=@texBoldGroup,@Spell syn region texEmphStyle matchgroup=texTypeStyle start="\\textup\s*{" matchgroup=texTypeStyle end="}" concealends contains=@texBoldGroup,@Spell syn region texEmphStyle matchgroup=texTypeStyle start="\\texttt\s*{" matchgroup=texTypeStyle end="}" concealends contains=@texBoldGroup,@Spell - else + else syn region texBoldStyle matchgroup=texTypeStyle start="\\textbf\s*{" matchgroup=texTypeStyle end="}" concealends contains=@texBoldGroup syn region texBoldItalStyle matchgroup=texTypeStyle start="\\textit\s*{" matchgroup=texTypeStyle end="}" concealends contains=@texItalGroup syn region texItalStyle matchgroup=texTypeStyle start="\\textit\s*{" matchgroup=texTypeStyle end="}" concealends contains=@texItalGroup diff --git a/runtime/syntax/typst.vim b/runtime/syntax/typst.vim index 82fdadb3d5..dae1424780 100644 --- a/runtime/syntax/typst.vim +++ b/runtime/syntax/typst.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: Typst " Maintainer: Gregory Anders <greg@gpanders.com> -" Last Change: 2024-07-14 +" Last Change: 2024 Nov 02 " Based on: https://github.com/kaarmu/typst.vim if exists('b:current_syntax') @@ -18,8 +18,8 @@ syntax cluster typstCommon " Common > Comment {{{2 syntax cluster typstComment \ contains=typstCommentBlock,typstCommentLine -syntax match typstCommentBlock - \ #/\*\%(\_.\{-}\)\*/# +syntax region typstCommentBlock + \ start="/\*" end="\*/" keepend \ contains=typstCommentTodo,@Spell syntax match typstCommentLine \ #//.*# diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim index 9073c6e7bf..3ad04e2957 100644 --- a/runtime/syntax/vim.vim +++ b/runtime/syntax/vim.vim @@ -74,12 +74,22 @@ syn case match com! -nargs=* Vim9 execute <q-args> s:vim9script ? "" : "contained" com! -nargs=* VimL execute <q-args> s:vim9script ? "contained" : "" -if exists("g:vimsyn_folding") && g:vimsyn_folding =~# '[afhHlmpPrt]' +if exists("g:vimsyn_folding") && g:vimsyn_folding =~# '[acefhiHlmpPrt]' if g:vimsyn_folding =~# 'a' com! -nargs=* VimFolda <args> fold else com! -nargs=* VimFolda <args> endif + if g:vimsyn_folding =~# 'c' + com! -nargs=* VimFoldc <args> fold + else + com! -nargs=* VimFoldc <args> + endif + if g:vimsyn_folding =~# 'e' + com! -nargs=* VimFolde <args> fold + else + com! -nargs=* VimFolde <args> + endif if g:vimsyn_folding =~# 'f' com! -nargs=* VimFoldf <args> fold else @@ -95,6 +105,11 @@ if exists("g:vimsyn_folding") && g:vimsyn_folding =~# '[afhHlmpPrt]' else com! -nargs=* VimFoldH <args> endif + if g:vimsyn_folding =~# 'i' + com! -nargs=* VimFoldi <args> fold + else + com! -nargs=* VimFoldi <args> + endif if g:vimsyn_folding =~# 'l' com! -nargs=* VimFoldl <args> fold else @@ -127,7 +142,10 @@ if exists("g:vimsyn_folding") && g:vimsyn_folding =~# '[afhHlmpPrt]' endif else com! -nargs=* VimFolda <args> + com! -nargs=* VimFoldc <args> + com! -nargs=* VimFolde <args> com! -nargs=* VimFoldf <args> + com! -nargs=* VimFoldi <args> com! -nargs=* VimFoldh <args> com! -nargs=* VimFoldH <args> com! -nargs=* VimFoldl <args> @@ -177,8 +195,8 @@ syn match vimNumber '\%(^\|\A\)\zs#\x\{6}' skipwhite nextgroup=vimGlobal,vimSub syn case match " All vimCommands are contained by vimIsCommand. {{{2 -syn cluster vimCmdList contains=vimAbb,vimAddress,vimAutoCmd,vimAugroup,vimBehave,vimCall,vimCatch,vimConst,vimDef,vimDelcommand,@vimEcho,vimEnddef,vimEndfunction,vimExecute,vimIsCommand,vimExtCmd,vimFor,vimFunction,vimFuncFold,vimGlobal,vimHighlight,vimLet,vimLoadkeymap,vimMap,vimMark,vimMatch,vimNotFunc,vimNorm,vimSet,vimSleep,vimSyntax,vimThrow,vimUnlet,vimUnmap,vimUserCmd,vimMenu,vimMenutranslate,@vim9CmdList -syn cluster vim9CmdList contains=vim9Const,vim9Final,vim9For,vim9Var +syn cluster vimCmdList contains=vimAbb,vimAddress,vimAutoCmd,vimAugroup,vimBehave,vimCall,vimCatch,vimConst,vimDef,vimDefFold,vimDelcommand,@vimEcho,vimEnddef,vimEndfunction,vimExecute,vimIsCommand,vimExtCmd,vimFor,vimFunction,vimFuncFold,vimGlobal,vimHighlight,vimLet,vimLoadkeymap,vimMap,vimMark,vimMatch,vimNotFunc,vimNormal,vimSet,vimSleep,vimSyntax,vimThrow,vimUnlet,vimUnmap,vimUserCmd,vimMenu,vimMenutranslate,@vim9CmdList +syn cluster vim9CmdList contains=vim9Class,vim9Const,vim9Enum,vim9Export,vim9Final,vim9For,vim9Interface,vim9Type,vim9Var syn match vimCmdSep "[:|]\+" skipwhite nextgroup=@vimCmdList,vimSubst1 syn match vimIsCommand "\<\%(\h\w*\|[23]mat\%[ch]\)\>" contains=vimCommand syn match vimBang contained "!" @@ -189,6 +207,7 @@ syn match vimVar "\s\zs&t_\S[a-zA-Z0-9]\>" syn match vimVar "\s\zs&t_k;" syn match vimFBVar contained "\<[bwglstav]:\h[a-zA-Z0-9#_]*\>" syn keyword vimCommand contained in +syn match vimBang contained "!" syn cluster vimExprList contains=vimEnvvar,vimFunc,vimNumber,vimOper,vimOperParen,vimLetRegister,vimString,vimVar,@vim9ExprList syn cluster vim9ExprList contains=vim9Boolean,vim9Null @@ -220,6 +239,12 @@ syn keyword vimThrow th[row] skipwhite nextgroup=@vimExprList syn keyword vimCatch cat[ch] skipwhite nextgroup=vimCatchPattern syn region vimCatchPattern contained matchgroup=Delimiter start="\z([!#$%&'()*+,-./:;<=>?@[\]^_`{}~]\)" skip="\\\\\|\\\z1" end="\z1" contains=@vimSubstList oneline +" Export {{{2 +" ====== +if s:vim9script + syn keyword vim9Export export skipwhite nextgroup=vim9Abstract,vim9ClassBody,vim9Const,vim9Def,vim9EnumBody,vim9Final,vim9InterfaceBody,vim9Type,vim9Var +endif + " Filetypes {{{2 " ========= syn match vimFiletype "\<filet\%[ype]\(\s\+\I\i*\)*" skipwhite contains=vimFTCmd,vimFTOption,vimFTError @@ -264,7 +289,7 @@ endif syn cluster vimFuncList contains=vimFuncBang,vimFunctionError,vimFuncKey,vimFuncSID,Tag syn cluster vimDefList contains=vimFuncBang,vimFunctionError,vimDefKey,vimFuncSID,Tag -syn cluster vimFuncBodyCommon contains=@vimCmdList,vimCmplxRepeat,vimContinue,vimCtrlChar,vimDef,vimEnvvar,vimFBVar,vimFunc,vimFunction,vimLetHereDoc,vimNotation,vimNotFunc,vimNumber,vimOper,vimOperParen,vimRegister,vimSearch,vimSpecFile,vimString,vimSubst,vimFuncFold +syn cluster vimFuncBodyCommon contains=@vimCmdList,vimCmplxRepeat,vimContinue,vimCtrlChar,vimDef,vimEnvvar,vimFBVar,vimFunc,vimFunction,vimLetHereDoc,vimNotation,vimNotFunc,vimNumber,vimOper,vimOperParen,vimRegister,vimSearch,vimSpecFile,vimString,vimSubst,vimFuncFold,vimDefFold syn cluster vimFuncBodyList contains=@vimFuncBodyCommon,vimComment,vimLineComment,vimFuncVar,vimInsert,vimConst,vimLet syn cluster vimDefBodyList contains=@vimFuncBodyCommon,vim9Comment,vim9LineComment,vim9Const,vim9Final,vim9Var,vim9Null,vim9Boolean,vim9For @@ -273,7 +298,6 @@ syn match vimFunction "\<fu\%[nction]\>" skipwhite nextgroup=vimCmdSep,vimCommen syn match vimDef "\<def\>" skipwhite nextgroup=vimCmdSep,vimComment,vimFuncPattern contains=vimDefKey syn match vimFunction "\<fu\%[nction]\>!\=\s*\%(<[sS][iI][dD]>\|[sg]:\)\=\%(\i\|[#.]\|{.\{-1,}}\)\+" contains=@vimFuncList skipwhite nextgroup=vimFuncParams -syn match vimDef "\<def\s\+new\%(\i\|{.\{-1,}}\)\+" contains=@vimDefList nextgroup=vimDefParams syn match vimDef "\<def\>!\=\s*\%(<[sS][iI][dD]>\|[sg]:\)\=\%(\i\|[#.]\|{.\{-1,}}\)\+" contains=@vimDefList nextgroup=vimDefParams syn match vimFuncComment contained +".*+ skipwhite skipempty nextgroup=vimFuncBody,vimEndfunction @@ -300,9 +324,8 @@ syn match vimEndfunction "\<endf\%[unction]\>" skipwhite nextgroup=vimCmdSep,vim syn match vimEnddef "\<enddef\>" skipwhite nextgroup=vimCmdSep,vim9Comment,vimCommentError if exists("g:vimsyn_folding") && g:vimsyn_folding =~# 'f' - syn region vimFuncFold start="\<fu\%[nction]\>!\=\s*\%(<[sS][iI][dD]>\|[sg]:\)\=\%(\i\|[#.]\|{.\{-1,}}\)\+\s*(" end="\<endf\%[unction]\>" contains=vimFunction fold keepend extend transparent - syn region vimFuncFold start="\<def\>!\=\s*\%(<[sS][iI][dD]>\|[sg]:\)\=\%(\i\|[#.]\)\+(" end="\<enddef\>" contains=vimDef fold keepend extend transparent - syn region vimFuncFold start="\<def\s\+new\i\+(" end="\<enddef\>" contains=vimDef fold keepend extend transparent + syn region vimFuncFold start="\<fu\%[nction]\>!\=\s*\%(<[sS][iI][dD]>\|[sg]:\)\=\%(\i\|[#.]\|{.\{-1,}}\)\+\s*(" end="\<endf\%[unction]\>" contains=vimFunction fold keepend extend transparent + syn region vimDefFold start="\<def\>!\=\s*\%(<[sS][iI][dD]>\|[sg]:\)\=\%(\i\|[#.]\)\+(" end="\<enddef\>" contains=vimDef fold keepend extend transparent endif syn match vimFuncVar contained "a:\%(\K\k*\|\d\+\)\>" @@ -323,6 +346,100 @@ syn match vimUserType contained "\<\u\w*\>" syn cluster vimType contains=vimType,vimCompoundType,vimUserType +" Classes, Enums And Interfaces: {{{2 +" ============================= + +if s:vim9script + " Methods {{{3 + syn match vim9MethodDef contained "\<def\>" skipwhite nextgroup=vim9MethodDefName + syn match vim9MethodDefName contained "\<\h\w*\>" nextgroup=vim9MethodDefParams contains=@vim9MethodName + syn region vim9MethodDefParams contained + \ matchgroup=Delimiter start="(" end=")" + \ skipwhite skipnl nextgroup=vim9MethodDefBody,vimDefComment,vimEnddef,vim9MethodDefReturnType,vimCommentError + \ contains=vimDefParam,vim9Comment,vimFuncParamEquals + syn region vim9MethodDefReturnType contained + \ start=":\s" end="$" matchgroup=vim9Comment end="\ze[#"]" + \ skipwhite skipnl nextgroup=vim9MethodDefBody,vimDefComment,vimCommentError + \ contains=vimTypeSep + \ transparent + syn region vim9MethodDefBody contained + \ start="^.\=" matchgroup=vimCommand end="\<enddef\>" + \ skipwhite nextgroup=vimCmdSep,vim9Comment,vimCommentError + \ contains=@vim9MethodDefBodyList + + syn cluster vim9MethodDefBodyList contains=@vimDefBodyList,vim9This,vim9Super + + if !exists("g:vimsyn_noerror") && !exists("g:vimsyn_novimfunctionerror") + syn match vim9MethodNameError contained "\<[a-z0-9]\i\>" + endif + syn match vim9MethodName contained "\<new\i*\>" + syn keyword vim9MethodName contained empty len string + + syn cluster vim9MethodName contains=vim9MethodName,vim9MethodNameError + + if exists("g:vimsyn_folding") && g:vimsyn_folding =~# 'f' + syn region vim9MethodDefFold contained start="\%(^\s*\%(:\=static\s\+\)\=\)\@16<=:\=def\s\+\h\i*(" end="^\s*:\=enddef\>" contains=vim9MethodDef fold keepend extend transparent + syn region vim9MethodDefFold contained start="^\s*:\=def\s\+new\i*(" end="^\s*:\=enddef\>" contains=vim9MethodDef fold keepend extend transparent + endif + + syn cluster vim9MethodDef contains=vim9MethodDef,vim9MethodDefFold + + " Classes {{{3 + syn cluster vim9ClassBodyList contains=vim9Abstract,vim9Class,vim9Comment,vim9LineComment,@vim9Continue,@vimExprList,vim9Extends,vim9Implements,@vim9MethodDef,vim9Public,vim9Static,vim9Const,vim9Final,vim9This,vim9Super,vim9Var + + syn match vim9Class contained "\<class\>" skipwhite nextgroup=vim9ClassName + syn match vim9ClassName contained "\<\u\w*\>" skipwhite skipnl nextgroup=vim9Extends,vim9Implements + syn match vim9SuperClass contained "\<\u\w*\>" skipwhite skipnl nextgroup=vim9Implements + syn match vim9ImplementedInterface contained "\<\u\w*\>" skipwhite skipnl nextgroup=vim9InterfaceListComma,vim9Extends + syn match vim9InterfaceListComma contained "," skipwhite skipnl nextgroup=vim9ImplementedInterface + syn keyword vim9Abstract abstract skipwhite skipnl nextgroup=vim9ClassBody,vim9AbstractDef + syn keyword vim9Extends contained extends skipwhite skipnl nextgroup=vim9SuperClass + syn keyword vim9Implements contained implements skipwhite skipnl nextgroup=vim9ImplementedInterface + syn keyword vim9Public contained public + syn keyword vim9Static contained static + syn keyword vim9This contained this + syn keyword vim9Super contained super + + VimFoldc syn region vim9ClassBody start="\<class\>" matchgroup=vimCommand end="\<endclass\>" contains=@vim9ClassBodyList transparent + + " Enums {{{3 + syn cluster vim9EnumBodyList contains=vim9Comment,vim9LineComment,@vim9Continue,vim9Enum,vim9Implements,@vim9MethodDef,vim9Const,vim9Final,vim9Var + + syn match vim9Enum contained "\<enum\>" skipwhite nextgroup=vim9EnumName + syn match vim9EnumName contained "\<\u\w*\>" skipwhite skipnl nextgroup=vim9Implements + + VimFolde syn region vim9EnumBody start="\<enum\>" matchgroup=vimCommand end="\<endenum\>" contains=@vim9EnumBodyList transparent + + " Interfaces {{{3 + " TODO: limit to decl only - no init values + syn cluster vim9InterfaceBodyList contains=vim9Comment,vim9LineComment,@vim9Continue,vim9Extends,vim9Interface,vim9AbstractDef,vim9Var + + syn match vim9Interface contained "\<interface\>" skipwhite nextgroup=vim9InterfaceName + syn match vim9InterfaceName contained "\<\u\w*\>" skipwhite skipnl nextgroup=vim9Extends + + syn keyword vim9AbstractDef contained def skipwhite nextgroup=vim9AbstractDefName + syn match vim9AbstractDefName contained "\<\h\w*\>" skipwhite nextgroup=vim9AbstractDefParams contains=@vim9MethodName + syn region vim9AbstractDefParams contained + \ matchgroup=Delimiter start="(" end=")" + \ skipwhite skipnl nextgroup=vimDefComment,vim9AbstractDefReturnType,vimCommentError + \ contains=vimDefParam,vim9Comment,vimFuncParamEquals + syn region vim9AbstractDefReturnType contained + \ start=":\s" end="$" matchgroup=vim9Comment end="\ze[#"]" + \ skipwhite skipnl nextgroup=vimDefComment,vimCommentError + \ contains=vimTypeSep + \ transparent + + VimFoldi syn region vim9InterfaceBody start="\<interface\>" matchgroup=vimCommand end="\<endinterface\>" contains=@vim9InterfaceBodyList transparent + + " type {{{3 + syn match vim9Type "\<ty\%[pe]\>" skipwhite nextgroup=vim9TypeAlias,vim9TypeAliasError + syn match vim9TypeAlias contained "\<\u\w*\>" skipwhite nextgroup=vim9TypeEquals + syn match vim9TypeEquals contained "=" skipwhite nextgroup=@vimType + if !exists("g:vimsyn_noerror") && !exists("g:vimsyn_notypealiaserror") + syn match vim9TypeAliasError contained "\<\U\w*" + endif +endif + " Keymaps: {{{2 " ======= @@ -381,7 +498,7 @@ endif syn case ignore syn keyword vimUserCmdAttrKey contained a[ddr] ban[g] bar bu[ffer] com[plete] cou[nt] k[eepscript] n[args] ra[nge] re[gister] " GEN_SYN_VIM: vimUserCmdAttrCmplt, START_STR='syn keyword vimUserCmdAttrCmplt contained', END_STR='' -syn keyword vimUserCmdAttrCmplt contained arglist augroup behave breakpoint buffer color command compiler cscope diff_buffer dir dir_in_path environment event expression file file_in_path filetype function help highlight history keymap locale mapclear mapping menu messages option packadd runtime scriptnames shellcmd sign syntax syntime tag tag_listfiles user var +syn keyword vimUserCmdAttrCmplt contained arglist augroup behave breakpoint buffer color command compiler cscope diff_buffer dir dir_in_path environment event expression file file_in_path filetype function help highlight history keymap locale mapclear mapping menu messages option packadd runtime scriptnames shellcmd shellcmdline sign syntax syntime tag tag_listfiles user var syn keyword vimUserCmdAttrCmplt contained custom customlist nextgroup=vimUserCmdAttrCmpltFunc,vimUserCmdError syn match vimUserCmdAttrCmpltFunc contained ",\%([sS]:\|<[sS][iI][dD]>\)\=\%(\h\w*\%([.#]\h\w*\)\+\|\h\w*\)"hs=s+1 nextgroup=vimUserCmdError " GEN_SYN_VIM: vimUserCmdAttrAddr, START_STR='syn keyword vimUserCmdAttrAddr contained', END_STR='' @@ -541,7 +658,7 @@ Vim9 syn keyword vim9Const const skipwhite nextgroup=vim9Variable,vim9VariableLi Vim9 syn keyword vim9Final final skipwhite nextgroup=vim9Variable,vim9VariableList Vim9 syn keyword vim9Var var skipwhite nextgroup=vim9Variable,vim9VariableList -syn match vim9Variable contained "\<\h\w*\>" skipwhite nextgroup=vimTypeSep,vimLetHereDoc +syn match vim9Variable contained "\<\h\w*\>" skipwhite nextgroup=vimTypeSep,vimLetHereDoc,vimOper syn region vim9VariableList contained start="\[" end="]" contains=vim9Variable,@vimContinue " For: {{{2 @@ -668,7 +785,7 @@ syn case match " (following Gautam Iyer's suggestion) " ========================== syn match vimFunc "\%(\%([sSgGbBwWtTlL]:\|<[sS][iI][dD]>\)\=\%(\w\+\.\)*\I[a-zA-Z0-9_.]*\)\ze\s*(" contains=vimFuncEcho,vimFuncName,vimUserFunc,vimExecute -syn match vimUserFunc contained "\%(\%([sSgGbBwWtTlL]:\|<[sS][iI][dD]>\)\=\%(\w\+\.\)*\I[a-zA-Z0-9_.]*\)\|\<\u[a-zA-Z0-9.]*\>\|\<if\>" contains=vimNotation +syn match vimUserFunc contained "\%(\%([sSgGbBwWtTlL]:\|<[sS][iI][dD]>\)\=\%(\w\+\.\)*\I[a-zA-Z0-9_.]*\)\|\<\u[a-zA-Z0-9.]*\>\|\<if\>" contains=vimNotation,vim9MethodName syn keyword vimFuncEcho contained ec ech echo syn match vimMap "\<map\%(\s\+(\)\@=" skipwhite nextgroup=vimMapBang,vimMapMod,vimMapLhs @@ -696,10 +813,10 @@ syn keyword vimMatchNone contained none syn case match syn region vimMatchPattern contained matchgroup=Delimiter start="\z([!#$%&'()*+,-./:;<=>?@[\]^_`{}~]\)" skip="\\\\\|\\\z1" end="\z1" contains=@vimSubstList oneline -" Norm: {{{2 -" ==== -syn match vimNorm "\<norm\%[al]!\=" skipwhite nextgroup=vimNormCmds -syn match vimNormCmds contained ".*$" +" Normal: {{{2 +" ====== +syn match vimNormal "\<norm\%[al]\>!\=" skipwhite nextgroup=vimNormalArg contains=vimBang +syn region vimNormalArg contained start="\S" skip=+\n\s*\\\|\n\s*["#]\\ + end="$" contains=@vimContinue " Sleep: {{{2 " ===== @@ -886,7 +1003,10 @@ syn match vimShebang "\%^#!.*" display syn match vimContinue "^\s*\zs\\" syn match vimContinueComment '^\s*\zs["#]\\ .*' -syn cluster vimContinue contains=vimContinue,vimContinueComment +syn match vim9ContinueComment "^\s*\zs#\\ .*" +syn cluster vimContinue contains=vimContinue,vimContinueComment +syn cluster vim9Continue contains=vimContinue,vim9ContinueComment + syn region vimString start="^\s*\\\z(['"]\)" skip='\\\\\|\\\z1' end="\z1" oneline keepend contains=@vimStringGroup,vimContinue syn match vimCommentTitleLeader '"\s\+'ms=s+1 contained syn match vim9CommentTitleLeader '#\s\+'ms=s+1 contained @@ -1145,6 +1265,8 @@ if !exists("skip_vim_syntax_inits") hi def link vimSynCaseError vimError hi def link vimSynFoldMethodError vimError hi def link vimBufnrWarn vimWarn + + hi def link vim9TypeAliasError vimError endif hi def link vimAbb vimCommand @@ -1255,8 +1377,9 @@ if !exists("skip_vim_syntax_inits") hi def link vimMenuPriority Number hi def link vimMenuStatus Special hi def link vimMenutranslateComment vimComment + hi def link vim9MethodName vimFuncName hi def link vimMtchComment vimComment - hi def link vimNorm vimCommand + hi def link vimNormal vimCommand hi def link vimNotation Special hi def link vimNotFunc vimCommand hi def link vimNotPatSep vimString @@ -1348,19 +1471,36 @@ if !exists("skip_vim_syntax_inits") hi def link vimVar Identifier hi def link vimWarn WarningMsg + hi def link vim9Abstract vimCommand hi def link vim9Boolean Boolean + hi def link vim9Class vimCommand hi def link vim9Comment Comment hi def link vim9CommentError vimError hi def link vim9CommentTitle PreProc hi def link vim9Const vimCommand + hi def link vim9ContinueComment vimContinueComment + hi def link vim9Enum vimCommand + hi def link vim9Export vimCommand + hi def link vim9Extends Keyword hi def link vim9Final vimCommand hi def link vim9For vimCommand + hi def link vim9Implements Keyword + hi def link vim9AbstractDef vimCommand + hi def link vim9Interface vimCommand hi def link vim9LineComment vimComment + hi def link vim9MethodDef vimCommand + hi def link vim9MethodNameError vimFunctionError hi def link vim9Null Constant - hi def link vim9Var vimCommand + hi def link vim9Public vimCommand + hi def link vim9Static vimCommand + hi def link vim9Super Identifier + hi def link vim9This Identifier + hi def link vim9Type vimCommand + hi def link vim9TypeEquals vimOper hi def link vim9Variable vimVar - hi def link vim9Vim9Script vimCommand + hi def link vim9Var vimCommand hi def link vim9Vim9ScriptArg Special + hi def link vim9Vim9Script vimCommand hi def link nvimAutoEvent vimAutoEvent hi def link nvimHLGroup vimHLGroup @@ -1374,9 +1514,12 @@ let b:current_syntax = "vim" delc Vim9 delc VimL delc VimFolda +delc VimFoldc +delc VimFolde delc VimFoldf delc VimFoldh delc VimFoldH +delc VimFoldi delc VimFoldl delc VimFoldm delc VimFoldp diff --git a/runtime/tools/check_colors.vim b/runtime/tools/check_colors.vim deleted file mode 100644 index 035914980d..0000000000 --- a/runtime/tools/check_colors.vim +++ /dev/null @@ -1,252 +0,0 @@ -" This script tests a color scheme for some errors and lists potential errors. -" Load the scheme and source this script, like this: -" :edit colors/desert.vim | :so tools/check_colors.vim - -let s:save_cpo= &cpo -set cpo&vim - -func! Test_check_colors() - let l:savedview = winsaveview() - call cursor(1,1) - - " err is - " { - " colors_name: "message", - " init: "message", - " background: "message", - " ....etc - " highlight: { - " 'Normal': "Missing ...", - " 'Conceal': "Missing ..." - " ....etc - " } - " } - let err = {} - - " 1) Check g:colors_name is existing - if search('\<\%(g:\)\?colors_name\>', 'cnW') == 0 - let err['colors_name'] = 'g:colors_name not set' - else - let err['colors_name'] = 'OK' - endif - - " 2) Check for some well-defined highlighting groups - let hi_groups = [ - \ 'ColorColumn', - \ 'Comment', - \ 'Conceal', - \ 'Constant', - \ 'Cursor', - \ 'CursorColumn', - \ 'CursorLine', - \ 'CursorLineNr', - \ 'DiffAdd', - \ 'DiffChange', - \ 'DiffDelete', - \ 'DiffText', - \ 'Directory', - \ 'EndOfBuffer', - \ 'Error', - \ 'ErrorMsg', - \ 'FoldColumn', - \ 'Folded', - \ 'Identifier', - \ 'Ignore', - \ 'IncSearch', - \ 'LineNr', - \ 'MatchParen', - \ 'ModeMsg', - \ 'MoreMsg', - \ 'NonText', - \ 'Normal', - \ 'Pmenu', - \ 'PmenuSbar', - \ 'PmenuSel', - \ 'PmenuThumb', - \ 'PreProc', - \ 'Question', - \ 'QuickFixLine', - \ 'Search', - \ 'SignColumn', - \ 'Special', - \ 'SpecialKey', - \ 'SpellBad', - \ 'SpellCap', - \ 'SpellLocal', - \ 'SpellRare', - \ 'Statement', - \ 'StatusLine', - \ 'StatusLineNC', - \ 'StatusLineTerm', - \ 'StatusLineTermNC', - \ 'TabLine', - \ 'TabLineFill', - \ 'TabLineSel', - \ 'Title', - \ 'Todo', - \ 'ToolbarButton', - \ 'ToolbarLine', - \ 'Type', - \ 'Underlined', - \ 'VertSplit', - \ 'Visual', - \ 'VisualNOS', - \ 'WarningMsg', - \ 'WildMenu', - \ ] - let groups = {} - for group in hi_groups - if search('\c@suppress\s\+\<' .. group .. '\>', 'cnW') - " skip check, if the script contains a line like - " @suppress Visual: - continue - endif - if search('hi\%[ghlight]!\= \+link \+' .. group, 'cnW') " Linked group - continue - endif - if !search('hi\%[ghlight] \+\<' .. group .. '\>', 'cnW') - let groups[group] = 'No highlight definition for ' .. group - continue - endif - if !search('hi\%[ghlight] \+\<' .. group .. '\>.*[bf]g=', 'cnW') - let groups[group] = 'Missing foreground or background color for ' .. group - continue - endif - if search('hi\%[ghlight] \+\<' .. group .. '\>.*guibg=', 'cnW') && - \ !search('hi\%[ghlight] \+\<' .. group .. '\>.*ctermbg=', 'cnW') - \ && group != 'Cursor' - let groups[group] = 'Missing bg terminal color for ' .. group - continue - endif - if !search('hi\%[ghlight] \+\<' .. group .. '\>.*guifg=', 'cnW') - \ && group !~ '^Diff' - let groups[group] = 'Missing guifg definition for ' .. group - continue - endif - if !search('hi\%[ghlight] \+\<' .. group .. '\>.*ctermfg=', 'cnW') - \ && group !~ '^Diff' - \ && group != 'Cursor' - let groups[group] = 'Missing ctermfg definition for ' .. group - continue - endif - " do not check for background colors, they could be intentionally left out - call cursor(1,1) - endfor - let err['highlight'] = groups - - " 3) Check, that it does not set background highlighting - " Doesn't ':hi Normal ctermfg=253 ctermfg=233' also set the background sometimes? - let bg_set = '\(set\?\|setl\(ocal\)\?\) .*\(background\|bg\)=\(dark\|light\)' - let bg_let = 'let \%([&]\%([lg]:\)\?\)\%(background\|bg\)\s*=\s*\([''"]\?\)\w\+\1' - let bg_pat = '\%(' .. bg_set .. '\|' .. bg_let .. '\)' - let line = search(bg_pat, 'cnW') - if search(bg_pat, 'cnW') - exe line - if search('hi \U\w\+\s\+\S', 'cbnW') - let err['background'] = 'Should not set background option after :hi statement' - endif - else - let err['background'] = 'OK' - endif - call cursor(1,1) - - " 4) Check, that t_Co is checked - let pat = '[&]t_Co\s*[<>=]=\?\s*\d\+' - if !search(pat, 'ncW') - let err['t_Co'] = 'Does not check terminal for capable colors' - endif - - " 5) Initializes correctly, e.g. should have a section like - " hi clear - " if exists("syntax_on") - " syntax reset - " endif - let pat = 'hi\%[ghlight]\s*clear\n\s*if\s*exists(\([''"]\)syntax_on\1)\n\s*syn\%[tax]\s*reset\n\s*endif' - if !search(pat, 'cnW') - let err['init'] = 'No initialization' - endif - - " 6) Does not use :syn on - if search('syn\%[tax]\s\+on', 'cnW') - let err['background'] = 'Should not issue :syn on' - endif - - " 7) Does not define filetype specific groups like vimCommand, htmlTag, - let hi_groups = filter(getcompletion('', 'filetype'), { _,v -> v !~# '\%[no]syn\%(color\|load\|tax\)' }) - let ft_groups = [] - " let group = '\%('.join(hi_groups, '\|').'\)' " More efficient than a for loop, but less informative - for group in hi_groups - let pat = '\Chi\%[ghlight]!\= *\%[link] \+\zs' .. group .. '\w\+\>\ze \+.' " Skips `hi clear` - if search(pat, 'cW') - call add(ft_groups, matchstr(getline('.'), pat)) - endif - call cursor(1,1) - endfor - if !empty(ft_groups) - let err['filetype'] = get(err, 'filetype', 'Should not define: ') . join(uniq(sort(ft_groups))) - endif - - " 8) Were debugPC and debugBreakpoint defined? - for group in ['debugPC', 'debugBreakpoint'] - let pat = '\Chi\%[ghlight]!\= *\%[link] \+\zs' .. group .. '\>' - if search(pat, 'cnW') - let line = search(pat, 'cW') - let err['filetype'] = get(err, 'filetype', 'Should not define: ') . matchstr(getline('.'), pat). ' ' - endif - call cursor(1,1) - endfor - - " 9) Normal should be defined first, not use reverse, fg or bg - call cursor(1,1) - let pat = 'hi\%[ghlight] \+\%(link\|clear\)\@!\w\+\>' - call search(pat, 'cW') " Look for the first hi def, skipping `hi link` and `hi clear` - if getline('.') !~# '\m\<Normal\>' - let err['highlight']['Normal'] = 'Should be defined first' - elseif getline('.') =~# '\m\%(=\%(fg\|bg\)\)' - let err['highlight']['Normal'] = "Should not use 'fg' or 'bg'" - elseif getline('.') =~# '\m=\%(inv\|rev\)erse' - let err['highlight']['Normal'] = 'Should not use reverse mode' - endif - - call winrestview(l:savedview) - let g:err = err - - " print Result - call Result(err) -endfu - - -fu! Result(err) - let do_groups = 0 - echohl Title|echomsg "---------------"|echohl Normal - for key in sort(keys(a:err)) - if key ==# 'highlight' - let do_groups = !empty(a:err[key]) - continue - else - if a:err[key] !~ 'OK' - echohl Title - endif - echomsg printf("%15s: %s", key, a:err[key]) - echohl Normal - endif - endfor - echohl Title|echomsg "---------------"|echohl Normal - if do_groups - echohl Title | echomsg "Groups" | echohl Normal - for v1 in sort(keys(a:err['highlight'])) - echomsg printf("%25s: %s", v1, a:err['highlight'][v1]) - endfor - endif -endfu - -try - call Test_check_colors() -catch - echohl ErrorMsg - echomsg v:exception - echohl NONE -finally - let &cpo = s:save_cpo - unlet s:save_cpo -endtry diff --git a/runtime/tutor/en/vim-01-beginner.tutor b/runtime/tutor/en/vim-01-beginner.tutor index e6b81d63b9..95d4f4eafd 100644 --- a/runtime/tutor/en/vim-01-beginner.tutor +++ b/runtime/tutor/en/vim-01-beginner.tutor @@ -302,7 +302,7 @@ it would be easier to simply type two d's to delete a line. 3. Now move to the fourth line. - 4. Type `2dd`{normal} to delete two lines. + 4. Type `2dd`{normal} to delete two lines, then press `u`{normal} twice to undo all three lines. 1) Roses are red, 2) Mud is fun, @@ -689,7 +689,7 @@ NOTE: Pressing [v](v) starts [Visual selection](visual-mode). You can move the c 1. Place the cursor just above this line. NOTE: After executing Step 2 you will see text from Lesson 5.3. Then move - DOWN to see this lesson again. + DOWN to see this lesson again. Press `u`{normal} to undo after you are done. 2. Now retrieve your TEST file using the command @@ -736,12 +736,12 @@ NOTE: You can also read the output of an external command. For example, 2. Type the lowercase letter `o`{normal} to [open](o) up a line BELOW the cursor and place you in Insert mode. - 3. Now type some text and press `<Esc>`{normal} to exit Insert mode. + 3. Now type some text and press `<Esc>`{normal} to exit Insert mode. Remove your opened lines after you're done. After typing `o`{normal} the cursor is placed on the open line in Insert mode. 4. To open up a line ABOVE the cursor, simply type a [capital O](O), rather - than a lowercase `o`{normal}. Try this on the line below. + than a lowercase `o`{normal}. Try this on the line below. Remove your opened lines after you're done. Open up a line above this by typing O while the cursor is on this line. |