diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2024-05-24 19:18:11 +0000 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2024-05-24 19:18:11 +0000 |
commit | ff7ed8f586589d620a806c3758fac4a47a8e7e15 (patch) | |
tree | 729bbcb92231538fa61dab6c3d890b025484b7f5 /runtime | |
parent | 376914f419eb08fdf4c1a63a77e1f035898a0f10 (diff) | |
parent | 28c04948a1c887a1cc0cb64de79fa32631700466 (diff) | |
download | rneovim-ff7ed8f586589d620a806c3758fac4a47a8e7e15.tar.gz rneovim-ff7ed8f586589d620a806c3758fac4a47a8e7e15.tar.bz2 rneovim-ff7ed8f586589d620a806c3758fac4a47a8e7e15.zip |
Merge remote-tracking branch 'upstream/master' into mix_20240309
Diffstat (limited to 'runtime')
354 files changed, 11196 insertions, 6733 deletions
diff --git a/runtime/autoload/health.vim b/runtime/autoload/health.vim deleted file mode 100644 index a7dbedab08..0000000000 --- a/runtime/autoload/health.vim +++ /dev/null @@ -1,40 +0,0 @@ -function! s:deprecate(type) abort - let deprecate = v:lua.vim.deprecate('health#report_' . a:type, 'vim.health.' . a:type, '0.11') - redraw | echo 'Running healthchecks...' - if deprecate isnot v:null - call v:lua.vim.health.warn(deprecate) - endif -endfunction - -function! health#report_start(name) abort - call v:lua.vim.health.start(a:name) - call s:deprecate('start') -endfunction - -function! health#report_info(msg) abort - call v:lua.vim.health.info(a:msg) - call s:deprecate('info') -endfunction - -function! health#report_ok(msg) abort - call v:lua.vim.health.ok(a:msg) - call s:deprecate('ok') -endfunction - -function! health#report_warn(msg, ...) abort - if a:0 > 0 - call v:lua.vim.health.warn(a:msg, a:1) - else - call v:lua.vim.health.warn(a:msg) - endif - call s:deprecate('warn') -endfunction - -function! health#report_error(msg, ...) abort - if a:0 > 0 - call v:lua.vim.health.error(a:msg, a:1) - else - call v:lua.vim.health.error(a:msg) - endif - call s:deprecate('error') -endfunction diff --git a/runtime/autoload/netrw.vim b/runtime/autoload/netrw.vim index fa08bb3848..ae602c5be6 100644 --- a/runtime/autoload/netrw.vim +++ b/runtime/autoload/netrw.vim @@ -8,6 +8,10 @@ " 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 +" 2024 May 08 by Vim Project: cleanup legacy Win9X checks +" 2024 May 09 by Vim Project: remove hard-coded private.ppk +" 2024 May 10 by Vim Project: recursively delete directories by default " Former Maintainer: Charles E Campbell " GetLatestVimScripts: 1075 1 :AutoInstall: netrw.vim " Copyright: Copyright (C) 2016 Charles E. Campbell {{{1 @@ -280,20 +284,15 @@ if !exists("g:netrw_scp_cmd") if executable("scp") call s:NetrwInit("g:netrw_scp_cmd" , "scp -q") elseif executable("pscp") - if (has("win32") || has("win95") || has("win64") || has("win16")) && filereadable('c:\private.ppk') - call s:NetrwInit("g:netrw_scp_cmd", 'pscp -i c:\private.ppk') - else - call s:NetrwInit("g:netrw_scp_cmd", 'pscp -q') - endif + call s:NetrwInit("g:netrw_scp_cmd", 'pscp -q') else call s:NetrwInit("g:netrw_scp_cmd" , "scp -q") endif endif - call s:NetrwInit("g:netrw_sftp_cmd" , "sftp") call s:NetrwInit("g:netrw_ssh_cmd" , "ssh") -if (has("win32") || has("win95") || has("win64") || has("win16")) +if has("win32") \ && exists("g:netrw_use_nt_rcp") \ && g:netrw_use_nt_rcp \ && executable( $SystemRoot .'/system32/rcp.exe') @@ -308,12 +307,8 @@ endif " Default values for netrw's global variables {{{2 " Cygwin Detection ------- {{{3 if !exists("g:netrw_cygwin") - if has("win32") || has("win95") || has("win64") || has("win16") - if has("win32unix") && &shell =~ '\%(\<bash\>\|\<zsh\>\)\%(\.exe\)\=$' - let g:netrw_cygwin= 1 - else - let g:netrw_cygwin= 0 - endif + if has("win32unix") && &shell =~ '\%(\<bash\>\|\<zsh\>\)\%(\.exe\)\=$' + let g:netrw_cygwin= 1 else let g:netrw_cygwin= 0 endif @@ -369,10 +364,6 @@ endif call s:NetrwInit("g:netrw_keepdir",1) if !exists("g:netrw_list_cmd") if g:netrw_scp_cmd =~ '^pscp' && executable("pscp") - if (has("win32") || has("win95") || has("win64") || has("win16")) && filereadable("c:\\private.ppk") - " provide a pscp-based listing command - let g:netrw_scp_cmd ="pscp -i C:\\private.ppk" - endif if exists("g:netrw_list_cmd_options") let g:netrw_list_cmd= g:netrw_scp_cmd." -ls USEPORT HOSTNAME: ".g:netrw_list_cmd_options else @@ -400,7 +391,7 @@ if !exists("g:netrw_localcmdshell") let g:netrw_localcmdshell= "" endif if !exists("g:netrw_localcopycmd") - if has("win32") || has("win95") || has("win64") || has("win16") + if has("win32") if g:netrw_cygwin let g:netrw_localcopycmd= "cp" else @@ -414,7 +405,7 @@ if !exists("g:netrw_localcopycmd") endif endif if !exists("g:netrw_localcopydircmd") - if has("win32") || has("win95") || has("win64") || has("win16") + if has("win32") if g:netrw_cygwin let g:netrw_localcopydircmd = "cp" let g:netrw_localcopydircmdopt= " -R" @@ -436,7 +427,7 @@ if exists("g:netrw_local_mkdir") let g:netrw_localmkdir= g:netrw_local_mkdir call netrw#ErrorMsg(s:NOTE,"g:netrw_local_mkdir is deprecated in favor of g:netrw_localmkdir",87) endif -if has("win32") || has("win95") || has("win64") || has("win16") +if has("win32") if g:netrw_cygwin call s:NetrwInit("g:netrw_localmkdir","mkdir") else @@ -452,7 +443,7 @@ if exists("g:netrw_local_movecmd") call netrw#ErrorMsg(s:NOTE,"g:netrw_local_movecmd is deprecated in favor of g:netrw_localmovecmd",88) endif if !exists("g:netrw_localmovecmd") - if has("win32") || has("win95") || has("win64") || has("win16") + if has("win32") if g:netrw_cygwin let g:netrw_localmovecmd= "mv" else @@ -485,7 +476,7 @@ call s:NetrwInit("g:netrw_mousemaps" , (exists("+mouse") && &mouse =~# '[anh call s:NetrwInit("g:netrw_retmap" , 0) if has("unix") || (exists("g:netrw_cygwin") && g:netrw_cygwin) call s:NetrwInit("g:netrw_chgperm" , "chmod PERM FILENAME") -elseif has("win32") || has("win95") || has("win64") || has("win16") +elseif has("win32") call s:NetrwInit("g:netrw_chgperm" , "cacls FILENAME /e /p PERM") else call s:NetrwInit("g:netrw_chgperm" , "chmod PERM FILENAME") @@ -544,14 +535,13 @@ if !exists("g:netrw_xstrlen") endif endif call s:NetrwInit("g:NetrwTopLvlMenu","Netrw.") -call s:NetrwInit("g:netrw_win95ftp",1) call s:NetrwInit("g:netrw_winsize",50) call s:NetrwInit("g:netrw_wiw",1) if g:netrw_winsize > 100|let g:netrw_winsize= 100|endif " --------------------------------------------------------------------- " Default values for netrw's script variables: {{{2 call s:NetrwInit("g:netrw_fname_escape",' ?&;%') -if has("win32") || has("win95") || has("win64") || has("win16") +if has("win32") call s:NetrwInit("g:netrw_glob_escape",'*?`{[]$') else call s:NetrwInit("g:netrw_glob_escape",'*[]?`{~$\') @@ -683,7 +673,7 @@ fun! netrw#Explore(indx,dosplit,style,...) " record current directory let curdir = simplify(b:netrw_curdir) let curfiledir = substitute(expand("%:p"),'^\(.*[/\\]\)[^/\\]*$','\1','e') - if !exists("g:netrw_cygwin") && (has("win32") || has("win95") || has("win64") || has("win16")) + if !exists("g:netrw_cygwin") && has("win32") let curdir= substitute(curdir,'\','/','g') endif " call Decho("curdir<".curdir."> curfiledir<".curfiledir.">",'~'.expand("<slnum>")) @@ -836,7 +826,7 @@ fun! netrw#Explore(indx,dosplit,style,...) " handle .../**/.../filepat " call Decho("case starpat=4: Explore .../**/.../filepat",'~'.expand("<slnum>")) let prefixdir= substitute(dirname,'^\(.\{-}\)\*\*.*$','\1','') - if prefixdir =~ '^/' || (prefixdir =~ '^\a:/' && (has("win32") || has("win95") || has("win64") || has("win16"))) + if prefixdir =~ '^/' || (prefixdir =~ '^\a:/' && has("win32")) let b:netrw_curdir = prefixdir else let b:netrw_curdir= getcwd().'/'.prefixdir @@ -873,7 +863,7 @@ fun! netrw#Explore(indx,dosplit,style,...) else if dirname == "" let dirname= getcwd() - elseif (has("win32") || has("win95") || has("win64") || has("win16")) && !g:netrw_cygwin + elseif has("win32") && !g:netrw_cygwin " Windows : check for a drive specifier, or else for a remote share name ('\\Foo' or '//Foo', " depending on whether backslashes have been converted to forward slashes by earlier code). if dirname !~ '^[a-zA-Z]:' && dirname !~ '^\\\\\w\+' && dirname !~ '^//\w\+' @@ -1382,7 +1372,7 @@ fun! netrw#Obtain(islocal,fname,...) " call Decho("obtain a file from local ".b:netrw_curdir." to ".tgtdir,'~'.expand("<slnum>")) if exists("b:netrw_curdir") && getcwd() != b:netrw_curdir let topath= s:ComposePath(tgtdir,"") - if (has("win32") || has("win95") || has("win64") || has("win16")) + if has("win32") " transfer files one at time " call Decho("transfer files one at a time",'~'.expand("<slnum>")) for fname in fnamelist @@ -1761,7 +1751,9 @@ fun! s:NetrwOptionsRestore(vt) " 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>")) - if filereadable(expand("%")) + + " filereadable() returns zero for remote files (e.g. scp://localhost//etc/fstab) + if filereadable(expand("%")) || expand("%") =~# '^\w\+://\f\+/' " call Decho("..doing filetype detect anyway") 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>")) @@ -2251,7 +2243,7 @@ fun! netrw#NetRead(mode,...) endif " 'C' in 'C:\path\to\file' is handled as hostname on windows. " This is workaround to avoid mis-handle windows local-path: - if g:netrw_scp_cmd =~ '^scp' && (has("win32") || has("win95") || has("win64") || has("win16")) + if g:netrw_scp_cmd =~ '^scp' && has("win32") let tmpfile_get = substitute(tr(tmpfile, '\', '/'), '^\(\a\):[/\\]\(.*\)$', '/\1/\2', '') else let tmpfile_get = tmpfile @@ -2680,7 +2672,7 @@ fun! netrw#NetWrite(...) range let url= g:netrw_choice call s:NetrwExe(s:netrw_silentxfer."!".g:netrw_http_put_cmd." ".s:ShellEscape(tmpfile,1)." ".s:ShellEscape(url,1) ) elseif !exists("g:netrw_quiet") - call netrw#ErrorMsg(s:ERROR,"can't write to http using <".g:netrw_http_put_cmd.">".",16) + call netrw#ErrorMsg(s:ERROR,"can't write to http using <".g:netrw_http_put_cmd.">",16) endif "......................................... @@ -3171,7 +3163,7 @@ fun! s:NetrwMethod(choice) if exists("s:netrw_hup[host]") call NetUserPass("ftp:".host) - elseif (has("win32") || has("win95") || has("win64") || has("win16")) && s:netrw_ftp_cmd =~# '-[sS]:' + elseif has("win32") && s:netrw_ftp_cmd =~# '-[sS]:' " call Decho("has -s: : s:netrw_ftp_cmd<".s:netrw_ftp_cmd.">",'~'.expand("<slnum>")) " call Decho(" g:netrw_ftp_cmd<".g:netrw_ftp_cmd.">",'~'.expand("<slnum>")) if g:netrw_ftp_cmd =~# '-[sS]:\S*MACHINE\>' @@ -3286,38 +3278,6 @@ fun! s:NetrwMethod(choice) " call Dret("s:NetrwMethod : b:netrw_method=".b:netrw_method." g:netrw_port=".g:netrw_port) endfun -" ------------------------------------------------------------------------ -" NetReadFixup: this sort of function is typically written by the user {{{2 -" to handle extra junk that their system's ftp dumps -" into the transfer. This function is provided as an -" example and as a fix for a Windows 95 problem: in my -" experience, win95's ftp always dumped four blank lines -" at the end of the transfer. -if has("win95") && exists("g:netrw_win95ftp") && g:netrw_win95ftp - fun! NetReadFixup(method, line1, line2) -" call Dfunc("NetReadFixup(method<".a:method."> line1=".a:line1." line2=".a:line2.")") - - " sanity checks -- attempt to convert inputs to integers - let method = a:method + 0 - let line1 = a:line1 + 0 - let line2 = a:line2 + 0 - if type(method) != 0 || type(line1) != 0 || type(line2) != 0 || method < 0 || line1 <= 0 || line2 <= 0 -" call Dret("NetReadFixup") - return - endif - - if method == 3 " ftp (no <.netrc>) - let fourblanklines= line2 - 3 - if fourblanklines >= line1 - exe "sil NetrwKeepj ".fourblanklines.",".line2."g/^\s*$/d" - call histdel("/",-1) - endif - endif - -" call Dret("NetReadFixup") - endfun -endif - " --------------------------------------------------------------------- " NetUserPass: set username and password for subsequent ftp transfer {{{2 " Usage: :call NetUserPass() -- will prompt for userid and password @@ -3940,7 +3900,7 @@ fun! s:NetrwBrowse(islocal,dirname) if b:netrw_curdir =~ '[/\\]$' let b:netrw_curdir= substitute(b:netrw_curdir,'[/\\]$','','e') endif - if b:netrw_curdir =~ '\a:$' && (has("win32") || has("win95") || has("win64") || has("win16")) + if b:netrw_curdir =~ '\a:$' && has("win32") let b:netrw_curdir= b:netrw_curdir."/" endif if b:netrw_curdir == '' @@ -4094,7 +4054,7 @@ fun! s:NetrwFile(fname) let b:netrw_curdir= getcwd() endif - if !exists("g:netrw_cygwin") && (has("win32") || has("win95") || has("win64") || has("win16")) + if !exists("g:netrw_cygwin") && has("win32") if fname =~ '^\' || fname =~ '^\a:\' " windows, but full path given let ret= fname @@ -4814,7 +4774,7 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) call s:SavePosn(s:netrw_posn) NetrwKeepj call s:NetrwOptionsSave("s:") NetrwKeepj call s:NetrwOptionsSafe(a:islocal) - if (has("win32") || has("win95") || has("win64") || has("win16")) + if has("win32") let dirname = substitute(b:netrw_curdir,'\\','/','ge') else let dirname = b:netrw_curdir @@ -5061,7 +5021,7 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...) endif " call Decho("go-up: amiga: dirname<".dirname."> (go up one dir)",'~'.expand("<slnum>")) - elseif !g:netrw_cygwin && (has("win32") || has("win95") || has("win64") || has("win16")) + elseif !g:netrw_cygwin && has("win32") " windows if a:islocal let dirname= substitute(dirname,'^\(.*\)/\([^/]\+\)/$','\1','') @@ -5346,7 +5306,7 @@ fun! netrw#BrowseX(fname,remote) " set up the filename " (lower case the extension, make a local copy of a remote file) let exten= substitute(a:fname,'.*\.\(.\{-}\)','\1','e') - if has("win32") || has("win95") || has("win64") || has("win16") + if has("win32") let exten= substitute(exten,'^.*$','\L&\E','') endif if exten =~ "[\\/]" @@ -5393,12 +5353,12 @@ fun! netrw#BrowseX(fname,remote) " by default, g:netrw_suppress_gx_mesg is true if g:netrw_suppress_gx_mesg if &srr =~ "%s" - if (has("win32") || has("win95") || has("win64") || has("win16")) + if has("win32") let redir= substitute(&srr,"%s","nul","") else let redir= substitute(&srr,"%s","/dev/null","") endif - elseif (has("win32") || has("win95") || has("win64") || has("win16")) + elseif has("win32") let redir= &srr . "nul" else let redir= &srr . "/dev/null" @@ -5441,7 +5401,7 @@ fun! netrw#BrowseX(fname,remote) call s:NetrwExe("sil !".viewer." ".viewopt.s:ShellEscape(fname,1).redir) let ret= v:shell_error - elseif has("win32") || has("win64") + 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)) @@ -7164,7 +7124,7 @@ fun! s:NetrwMarkFileCopy(islocal,...) let args= join(map(deepcopy(s:netrwmarkfilelist_{bufnr('%')}),"s:ShellEscape(b:netrw_curdir.\"/\".v:val)")) let tgt = s:ShellEscape(s:netrwmftgt) endif - if !g:netrw_cygwin && (has("win32") || has("win95") || has("win64") || has("win16")) + if !g:netrw_cygwin && has("win32") let args= substitute(args,'/','\\','g') let tgt = substitute(tgt, '/','\\','g') endif @@ -7178,7 +7138,7 @@ fun! s:NetrwMarkFileCopy(islocal,...) " call Decho("args<".args."> is a directory",'~'.expand("<slnum>")) let copycmd= g:netrw_localcopydircmd " call Decho("using copydircmd<".copycmd.">",'~'.expand("<slnum>")) - if !g:netrw_cygwin && (has("win32") || has("win95") || has("win64") || has("win16")) + if !g:netrw_cygwin && has("win32") " window's xcopy doesn't copy a directory to a target properly. Instead, it copies a directory's " contents to a target. One must append the source directory name to the target to get xcopy to " do the right thing. @@ -7796,7 +7756,7 @@ fun! s:NetrwMarkFileMove(islocal) endif let tgt = s:ShellEscape(s:netrwmftgt) " call Decho("tgt<".tgt.">",'~'.expand("<slnum>")) - if !g:netrw_cygwin && (has("win32") || has("win95") || has("win64") || has("win16")) + if !g:netrw_cygwin && has("win32") let tgt= substitute(tgt, '/','\\','g') " call Decho("windows exception: tgt<".tgt.">",'~'.expand("<slnum>")) if g:netrw_localmovecmd =~ '\s' @@ -7817,7 +7777,7 @@ fun! s:NetrwMarkFileMove(islocal) " Jul 19, 2022: fixing file move when g:netrw_keepdir is 1 let fname= b:netrw_curdir."/".fname endif - if !g:netrw_cygwin && (has("win32") || has("win95") || has("win64") || has("win16")) + if !g:netrw_cygwin && has("win32") let fname= substitute(fname,'/','\\','g') endif " call Decho("system(".movecmd." ".s:ShellEscape(fname)." ".tgt.")",'~'.expand("<slnum>")) @@ -10236,7 +10196,7 @@ fun! s:NetrwRemoteFtpCmd(path,listcmd) endif " cleanup for Windows " {{{3 - if has("win32") || has("win95") || has("win64") || has("win16") + if has("win32") sil! NetrwKeepj %s/\r$//e NetrwKeepj call histdel("/",-1) endif @@ -10744,7 +10704,7 @@ fun! netrw#FileUrlEdit(fname) let fname= substitute(fname,'^file://localhost/','file:///','') " call Decho("fname<".fname.">",'~'.expand("<slnum>")) endif - if (has("win32") || has("win95") || has("win64") || has("win16")) + if has("win32") if fname =~ '^file:///\=\a[|:]/' " call Decho('converting file:///\a|/ -to- file://\a:/','~'.expand("<slnum>")) let fname = substitute(fname,'^file:///\=\(\a\)[|:]/','file://\1:/','') @@ -10754,7 +10714,7 @@ fun! netrw#FileUrlEdit(fname) let fname2396 = netrw#RFC2396(fname) let fname2396e= fnameescape(fname2396) let plainfname= substitute(fname2396,'file://\(.*\)','\1',"") - if (has("win32") || has("win95") || has("win64") || has("win16")) + if has("win32") " call Decho("windows exception for plainfname",'~'.expand("<slnum>")) if plainfname =~ '^/\+\a:' " call Decho('removing leading "/"s','~'.expand("<slnum>")) @@ -10966,7 +10926,7 @@ fun! s:LocalFastBrowser() let s:netrw_events= 1 augroup AuNetrwEvent au! - if (has("win32") || has("win95") || has("win64") || has("win16")) + if has("win32") " call Decho("installing autocmd: ShellCmdPost",'~'.expand("<slnum>")) au ShellCmdPost * call s:LocalBrowseRefresh() else @@ -11008,7 +10968,7 @@ fun! s:LocalListing() let filelist = filelist + s:NetrwGlob(dirname,".*",0) " call Decho("filelist=".string(filelist),'~'.expand("<slnum>")) - if g:netrw_cygwin == 0 && (has("win32") || has("win95") || has("win64") || has("win16")) + if g:netrw_cygwin == 0 && has("win32") " call Decho("filelist=".string(filelist),'~'.expand("<slnum>")) elseif index(filelist,'..') == -1 && b:netrw_curdir !~ '/' " include ../ in the glob() entry if its missing @@ -11054,7 +11014,7 @@ fun! s:LocalListing() let pfile= filename."/" elseif exists("b:netrw_curdir") && b:netrw_curdir !~ '^.*://' && !isdirectory(s:NetrwFile(filename)) - if (has("win32") || has("win95") || has("win64") || has("win16")) + 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>")) @@ -11388,7 +11348,7 @@ fun! s:NetrwLocalRmFile(path,fname,all) if !all echohl Statement call inputsave() - let ok= input("Confirm deletion of directory<".rmfile."> ","[{y(es)},n(o),a(ll),q(uit)] ") + let ok= input("Confirm *recursive* deletion of directory<".rmfile."> ","[{y(es)},n(o),a(ll),q(uit)] ") call inputrestore() let ok= substitute(ok,'\[{y(es)},n(o),a(ll),q(uit)]\s*','','e') if ok == "" @@ -11401,7 +11361,7 @@ fun! s:NetrwLocalRmFile(path,fname,all) let rmfile= substitute(rmfile,'[\/]$','','e') if all || ok =~# 'y\%[es]' || ok == "" - if delete(rmfile,"d") + if delete(rmfile,"rf") call netrw#ErrorMsg(s:ERROR,"unable to delete directory <".rmfile.">!",103) endif endif @@ -11531,7 +11491,7 @@ endfun " netrw#WinPath: tries to insure that the path is windows-acceptable, whether cygwin is used or not {{{2 fun! netrw#WinPath(path) " call Dfunc("netrw#WinPath(path<".a:path.">)") - if (!g:netrw_cygwin || &shell !~ '\%(\<bash\>\|\<zsh\>\)\%(\.exe\)\=$') && (has("win32") || has("win95") || has("win64") || has("win16")) + if (!g:netrw_cygwin || &shell !~ '\%(\<bash\>\|\<zsh\>\)\%(\.exe\)\=$') && has("win32") " remove cygdrive prefix, if present let path = substitute(a:path,g:netrw_cygdrive.'/\(.\)','\1:','') " remove trailing slash (Win95) @@ -11591,11 +11551,11 @@ fun! s:ComposePath(base,subdir) endif " COMBAK: test on windows with changing to root directory: :e C:/ - elseif a:subdir =~ '^\a:[/\\]\([^/\\]\|$\)' && (has("win32") || has("win95") || has("win64") || has("win16")) + elseif a:subdir =~ '^\a:[/\\]\([^/\\]\|$\)' && has("win32") " call Decho("windows",'~'.expand("<slnum>")) let ret= a:subdir - elseif a:base =~ '^\a:[/\\]\([^/\\]\|$\)' && (has("win32") || has("win95") || has("win64") || has("win16")) + elseif a:base =~ '^\a:[/\\]\([^/\\]\|$\)' && has("win32") " call Decho("windows",'~'.expand("<slnum>")) if a:base =~ '[/\\]$' let ret= a:base.a:subdir @@ -11707,7 +11667,7 @@ fun! s:GetTempfile(fname) " o/s dependencies if g:netrw_cygwin != 0 let tmpfile = substitute(tmpfile,'^\(\a\):',g:netrw_cygdrive.'/\1','e') - elseif has("win32") || has("win95") || has("win64") || has("win16") + elseif has("win32") if !exists("+shellslash") || !&ssl let tmpfile = substitute(tmpfile,'/','\','g') endif @@ -11923,7 +11883,7 @@ fun! s:NetrwDelete(path) " call Dfunc("s:NetrwDelete(path<".a:path.">)") let path = netrw#WinPath(a:path) - if !g:netrw_cygwin && (has("win32") || has("win95") || has("win64") || has("win16")) + if !g:netrw_cygwin && has("win32") if exists("+shellslash") let sskeep= &shellslash setl noshellslash @@ -12114,7 +12074,7 @@ fun! s:NetrwLcd(newdir) " 'root' (ie. '\'). The share name may start with either backslashes ('\\Foo') or " forward slashes ('//Foo'), depending on whether backslashes have been converted to " forward slashes by earlier code; so check for both. - if (has("win32") || has("win95") || has("win64") || has("win16")) && !g:netrw_cygwin + if has("win32") && !g:netrw_cygwin if a:newdir =~ '^\\\\\w\+' || a:newdir =~ '^//\w\+' let dirname = '\' exe 'NetrwKeepj sil lcd '.fnameescape(dirname) @@ -12587,7 +12547,7 @@ endfun " --------------------------------------------------------------------- " s:ShellEscape: shellescape(), or special windows handling {{{2 fun! s:ShellEscape(s, ...) - if (has('win32') || has('win64')) && $SHELL == '' && &shellslash + if has('win32') && $SHELL == '' && &shellslash return printf('"%s"', substitute(a:s, '"', '""', 'g')) endif let f = a:0 > 0 ? a:1 : 0 diff --git a/runtime/autoload/netrwSettings.vim b/runtime/autoload/netrwSettings.vim index 5525c0d035..3452602272 100644 --- a/runtime/autoload/netrwSettings.vim +++ b/runtime/autoload/netrwSettings.vim @@ -3,6 +3,8 @@ " Maintainer: This runtime file is looking for a new maintainer. " Former Maintainer: Charles E Campbell " Version: 18 +" Last Change: +" 2024 May 08 by Vim Project: cleanup legacy Win9X checks " Copyright: Copyright (C) 1999-2007 Charles E. Campbell {{{1 " Permission is hereby granted to use and distribute this code, " with or without modifications, provided that this copyright @@ -91,7 +93,6 @@ fun! netrwSettings#NetrwSettings() put = 'let g:netrw_sshport = '.g:netrw_sshport put = 'let g:netrw_silent = '.g:netrw_silent put = 'let g:netrw_use_nt_rcp = '.g:netrw_use_nt_rcp - put = 'let g:netrw_win95ftp = '.g:netrw_win95ftp let s:netrw_xfer_stop= line(".") put ='' put ='+ Netrw Messages' diff --git a/runtime/autoload/provider/clipboard.vim b/runtime/autoload/provider/clipboard.vim index 05f6bdb871..82e0953196 100644 --- a/runtime/autoload/provider/clipboard.vim +++ b/runtime/autoload/provider/clipboard.vim @@ -67,7 +67,8 @@ function! provider#clipboard#Error() abort endfunction function! provider#clipboard#Executable() abort - if exists('g:clipboard') + " Setting g:clipboard to v:false explicitly opts-in to using the "builtin" clipboard providers below + if exists('g:clipboard') && g:clipboard isnot# v:false if type({}) isnot# type(g:clipboard) \ || type({}) isnot# type(get(g:clipboard, 'copy', v:null)) \ || type({}) isnot# type(get(g:clipboard, 'paste', v:null)) diff --git a/runtime/autoload/zig/fmt.vim b/runtime/autoload/zig/fmt.vim deleted file mode 100644 index b78c1994dd..0000000000 --- a/runtime/autoload/zig/fmt.vim +++ /dev/null @@ -1,100 +0,0 @@ -" Adapted from fatih/vim-go: autoload/go/fmt.vim -" -" Copyright 2011 The Go Authors. All rights reserved. -" Use of this source code is governed by a BSD-style -" license that can be found in the LICENSE file. -" -" Upstream: https://github.com/ziglang/zig.vim - -function! zig#fmt#Format() abort - " Save cursor position and many other things. - let view = winsaveview() - - if !executable('zig') - echohl Error | echomsg "no zig binary found in PATH" | echohl None - return - endif - - let cmdline = 'zig fmt --stdin --ast-check' - let current_buf = bufnr('') - - " The formatted code is output on stdout, the errors go on stderr. - if exists('*systemlist') - silent let out = systemlist(cmdline, current_buf) - else - silent let out = split(system(cmdline, current_buf)) - endif - if len(out) == 1 - if out[0] == "error: unrecognized parameter: '--ast-check'" - let cmdline = 'zig fmt --stdin' - if exists('*systemlist') - silent let out = systemlist(cmdline, current_buf) - else - silent let out = split(system(cmdline, current_buf)) - endif - endif - endif - let err = v:shell_error - - - if err == 0 - " remove undo point caused via BufWritePre. - try | silent undojoin | catch | endtry - - " Replace the file content with the formatted version. - if exists('*deletebufline') - call deletebufline(current_buf, len(out), line('$')) - else - silent execute ':' . len(out) . ',' . line('$') . ' delete _' - endif - call setline(1, out) - - " No errors detected, close the loclist. - call setloclist(0, [], 'r') - lclose - elseif get(g:, 'zig_fmt_parse_errors', 1) - let errors = s:parse_errors(expand('%'), out) - - call setloclist(0, [], 'r', { - \ 'title': 'Errors', - \ 'items': errors, - \ }) - - let max_win_height = get(g:, 'zig_fmt_max_window_height', 5) - " Prevent the loclist from becoming too long. - let win_height = min([max_win_height, len(errors)]) - " Open the loclist, but only if there's at least one error to show. - execute 'silent! lwindow ' . win_height - endif - - call winrestview(view) - - if err != 0 - echohl Error | echomsg "zig fmt returned error" | echohl None - return - endif - - " Run the syntax highlighter on the updated content and recompute the folds if - " needed. - syntax sync fromstart -endfunction - -" parse_errors parses the given errors and returns a list of parsed errors -function! s:parse_errors(filename, lines) abort - " list of errors to be put into location list - let errors = [] - for line in a:lines - let tokens = matchlist(line, '^\(.\{-}\):\(\d\+\):\(\d\+\)\s*\(.*\)') - if !empty(tokens) - call add(errors,{ - \"filename": a:filename, - \"lnum": tokens[2], - \"col": tokens[3], - \"text": tokens[4], - \ }) - endif - endfor - - return errors -endfunction -" vim: sw=2 ts=2 et diff --git a/runtime/colors/vim.lua b/runtime/colors/vim.lua index 5a29ba0ec6..7231418f5f 100644 --- a/runtime/colors/vim.lua +++ b/runtime/colors/vim.lua @@ -158,18 +158,22 @@ hi('@boolean', { link = 'Boolean' }) hi('@number.float', { link = 'Float' }) -- Functions -hi('@function', { link = 'Function' }) -hi('@function.builtin', { link = 'Special' }) -hi('@function.macro', { link = 'Macro' }) -hi('@variable.parameter', { link = 'Identifier' }) -hi('@function.method', { link = 'Function' }) -hi('@variable.member', { link = 'Identifier' }) -hi('@property', { link = 'Identifier' }) -hi('@constructor', { link = 'Special' }) +hi('@function', { link = 'Function' }) +hi('@function.builtin', { link = 'Special' }) +hi('@function.macro', { link = 'Macro' }) +hi('@function.method', { link = 'Function' }) +hi('@variable.parameter', { link = 'Identifier' }) +hi('@variable.parameter.builtin', { link = 'Special' }) +hi('@variable.member', { link = 'Identifier' }) +hi('@property', { link = 'Identifier' }) +hi('@attribute', { link = 'Macro' }) +hi('@attribute.builtin', { link = 'Special' }) +hi('@constructor', { link = 'Special' }) -- Keywords hi('@keyword.conditional', { link = 'Conditional' }) hi('@keyword.repeat', { link = 'Repeat' }) +hi('@keyword.type', { link = 'Structure' }) hi('@label', { link = 'Label' }) hi('@operator', { link = 'Operator' }) hi('@keyword', { link = 'Keyword' }) @@ -178,12 +182,12 @@ hi('@keyword.exception', { link = 'Exception' }) hi('@variable', { link = 'Identifier' }) hi('@type', { link = 'Type' }) hi('@type.definition', { link = 'Typedef' }) -hi('@keyword.storage', { link = 'StorageClass' }) hi('@module', { link = 'Identifier' }) hi('@keyword.import', { link = 'Include' }) hi('@keyword.directive', { link = 'PreProc' }) hi('@keyword.debug', { link = 'Debug' }) hi('@tag', { link = 'Tag' }) +hi('@tag.builtin', { link = 'Special' }) -- LSP semantic tokens hi('@lsp.type.class', { link = 'Structure' }) diff --git a/runtime/compiler/ant.vim b/runtime/compiler/ant.vim index 0605c69fab..6219b01c36 100644 --- a/runtime/compiler/ant.vim +++ b/runtime/compiler/ant.vim @@ -2,16 +2,13 @@ " Compiler: ant " Maintainer: Johannes Zellner <johannes@zellner.org> " Last Change: Mi, 13 Apr 2005 22:50:07 CEST +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish endif let current_compiler = "ant" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/bcc.vim b/runtime/compiler/bcc.vim index 5bd284a581..2d9d4fbb36 100644 --- a/runtime/compiler/bcc.vim +++ b/runtime/compiler/bcc.vim @@ -2,16 +2,13 @@ " Compiler: bcc - Borland C " Maintainer: Emile van Raaij (eraaij@xs4all.nl) " Last Change: 2004 Mar 27 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish endif let current_compiler = "bcc" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - " A workable errorformat for Borland C CompilerSet errorformat=%*[^0-9]%n\ %f\ %l:\ %m diff --git a/runtime/compiler/bdf.vim b/runtime/compiler/bdf.vim index b062e847aa..2aaa93bc27 100644 --- a/runtime/compiler/bdf.vim +++ b/runtime/compiler/bdf.vim @@ -1,7 +1,9 @@ " Vim compiler file " Compiler: BDF to PCF Conversion " Previous Maintainer: Nikolai Weibull <now@bitwi.se> -" Latest Revision: 2006-04-19 +" Contributors: Enno Nagel +" Last Change: 2024 Mar 29 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish @@ -11,9 +13,8 @@ let current_compiler = "bdf" let s:cpo_save = &cpo set cpo-=C -setlocal makeprg=bdftopcf\ $* - -setlocal errorformat=%ABDF\ %trror\ on\ line\ %l:\ %m, +CompilerSet makeprg=bdftopcf\ $* +CompilerSet errorformat=%ABDF\ %trror\ on\ line\ %l:\ %m, \%-Z%p^, \%Cbdftopcf:\ bdf\ input\\,\ %f\\,\ corrupt, \%-G%.%# diff --git a/runtime/compiler/cargo.vim b/runtime/compiler/cargo.vim index aa9b01e93c..bbea45dee7 100644 --- a/runtime/compiler/cargo.vim +++ b/runtime/compiler/cargo.vim @@ -2,6 +2,7 @@ " Compiler: Cargo Compiler " Maintainer: Damien Radtke <damienradtke@gmail.com> " Latest Revision: 2023-09-11 +" 2024 Apr 05 by The Vim Project (removed :CompilerSet definition) " For bugs, patches and license go to https://github.com/rust-lang/rust.vim if exists('current_compiler') @@ -15,10 +16,6 @@ let s:save_cpo = &cpo set cpo&vim " vint: +ProhibitAbbreviationOption -if exists(':CompilerSet') != 2 - command -nargs=* CompilerSet setlocal <args> -endif - if exists('g:cargo_makeprg_params') execute 'CompilerSet makeprg=cargo\ '.escape(g:cargo_makeprg_params, ' \|"').'\ $*' else diff --git a/runtime/compiler/checkstyle.vim b/runtime/compiler/checkstyle.vim index 4ebd9e15b5..3c17ee45bf 100644 --- a/runtime/compiler/checkstyle.vim +++ b/runtime/compiler/checkstyle.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: Checkstyle " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2020 Aug 2 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "checkstyle" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/cm3.vim b/runtime/compiler/cm3.vim index 3de51282e6..0ec360855c 100644 --- a/runtime/compiler/cm3.vim +++ b/runtime/compiler/cm3.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: Critical Mass Modula-3 Compiler " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2021 Apr 08 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "cm3" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/context.vim b/runtime/compiler/context.vim index cb78c96df0..3d626ffa60 100644 --- a/runtime/compiler/context.vim +++ b/runtime/compiler/context.vim @@ -9,10 +9,6 @@ endif let s:keepcpo= &cpo set cpo&vim -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - " If makefile exists and we are not asked to ignore it, we use standard make " (do not redefine makeprg) if get(b:, 'context_ignore_makefile', get(g:, 'context_ignore_makefile', 0)) || @@ -20,11 +16,12 @@ if get(b:, 'context_ignore_makefile', get(g:, 'context_ignore_makefile', 0)) || let current_compiler = 'context' " The following assumes that the current working directory is set to the " directory of the file to be typeset - let &l:makeprg = get(b:, 'context_mtxrun', get(g:, 'context_mtxrun', 'mtxrun')) + let s:makeprg = get(b:, 'context_mtxrun', get(g:, 'context_mtxrun', 'mtxrun')) \ . ' --script context --autogenerate --nonstopmode --synctex=' \ . (get(b:, 'context_synctex', get(g:, 'context_synctex', 0)) ? '1' : '0') \ . ' ' . get(b:, 'context_extra_options', get(g:, 'context_extra_options', '')) \ . ' ' . shellescape(expand('%:p:t')) + execute 'CompilerSet makeprg=' .. escape(s:makeprg, ' ') else let current_compiler = 'make' endif diff --git a/runtime/compiler/cs.vim b/runtime/compiler/cs.vim index 4f6dd3cdfd..123dff854f 100644 --- a/runtime/compiler/cs.vim +++ b/runtime/compiler/cs.vim @@ -3,6 +3,7 @@ " Maintainer: Yichao Zhou (broken.zhou@gmail.com) " Previous Maintainer: Joseph H. Yao (hyao@sina.com) " Last Change: Jul 22, 2019 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish @@ -11,10 +12,6 @@ let current_compiler = "cs" let s:keepcpo= &cpo set cpo&vim -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet errorformat& CompilerSet errorformat+=%f(%l\\,%v):\ %t%*[^:]:\ %m, \%trror%*[^:]:\ %m, diff --git a/runtime/compiler/csslint.vim b/runtime/compiler/csslint.vim index 14c4289a24..608cc74864 100644 --- a/runtime/compiler/csslint.vim +++ b/runtime/compiler/csslint.vim @@ -1,16 +1,13 @@ " Vim compiler file " Compiler: csslint for CSS -" Maintainer: Daniel Moch <daniel@danielmoch.com> -" Last Change: 2016 May 21 +" Maintainer: Daniel Moch <daniel@danielmoch.com> +" Last Change: 2016 May 21 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish endif let current_compiler = "csslint" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet makeprg=csslint\ --format=compact CompilerSet errorformat=%-G,%-G%f:\ lint\ free!,%f:\ line\ %l\\,\ col\ %c\\,\ %trror\ -\ %m,%f:\ line\ %l\\,\ col\ %c\\,\ %tarning\ -\ %m,%f:\ line\ %l\\,\ col\ %c\\,\ %m diff --git a/runtime/compiler/cucumber.vim b/runtime/compiler/cucumber.vim index 17ce3627c1..8089a5ee5c 100644 --- a/runtime/compiler/cucumber.vim +++ b/runtime/compiler/cucumber.vim @@ -2,16 +2,13 @@ " Compiler: Cucumber " Maintainer: Tim Pope <vimNOSPAM@tpope.org> " Last Change: 2016 Aug 29 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish endif let current_compiler = "cucumber" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo-=C diff --git a/runtime/compiler/dart.vim b/runtime/compiler/dart.vim index f9ebfe1b27..9577236bee 100644 --- a/runtime/compiler/dart.vim +++ b/runtime/compiler/dart.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: Dart VM " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2019 May 08 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "dart" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/dart2js.vim b/runtime/compiler/dart2js.vim index b6a4e4d530..a05dead2a9 100644 --- a/runtime/compiler/dart2js.vim +++ b/runtime/compiler/dart2js.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: Dart to JavaScript Compiler " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2019 May 08 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "dart2js" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/dart2native.vim b/runtime/compiler/dart2native.vim index 51bdab0cc3..6604fc4bd4 100644 --- a/runtime/compiler/dart2native.vim +++ b/runtime/compiler/dart2native.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: Dart to Native Compiler " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2019 May 08 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "dart2native" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/dartanalyser.vim b/runtime/compiler/dartanalyser.vim index e691d80b61..48a976a016 100644 --- a/runtime/compiler/dartanalyser.vim +++ b/runtime/compiler/dartanalyser.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: Dart Analyzer " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2019 May 08 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "dartanalyzer" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/dartdevc.vim b/runtime/compiler/dartdevc.vim index e8d1988ed6..16e4ed7ced 100644 --- a/runtime/compiler/dartdevc.vim +++ b/runtime/compiler/dartdevc.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: Dart Development Compiler " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2019 May 08 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "dartdevc" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/dartdoc.vim b/runtime/compiler/dartdoc.vim index 26b38d8dd4..78f0d241a4 100644 --- a/runtime/compiler/dartdoc.vim +++ b/runtime/compiler/dartdoc.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: Dart Documentation Generator " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2019 May 08 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "dartdoc" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/dartfmt.vim b/runtime/compiler/dartfmt.vim index 2e4ab02ad3..d204df8a73 100644 --- a/runtime/compiler/dartfmt.vim +++ b/runtime/compiler/dartfmt.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: Dart Formatter " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2019 May 08 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "dartfmt" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/decada.vim b/runtime/compiler/decada.vim index 0bf5487c89..11b0cb412a 100644 --- a/runtime/compiler/decada.vim +++ b/runtime/compiler/decada.vim @@ -14,6 +14,7 @@ " 08.09.2006 MK Correct double load protection. " Help Page: compiler-decada "------------------------------------------------------------------------------ +" Last Change: 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if (exists("current_compiler") && current_compiler == "decada") || version < 700 finish @@ -34,13 +35,6 @@ if !exists("g:decada") call g:decada.Set_Session () endif -if exists(":CompilerSet") != 2 - " - " plugin loaded by other means then the "compiler" command - " - command -nargs=* CompilerSet setlocal <args> -endif - execute "CompilerSet makeprg=" . escape (g:decada.Make_Command, ' ') execute "CompilerSet errorformat=" . escape (g:decada.Error_Format, ' ') diff --git a/runtime/compiler/dot.vim b/runtime/compiler/dot.vim index 0327739aae..145411ebd3 100644 --- a/runtime/compiler/dot.vim +++ b/runtime/compiler/dot.vim @@ -1,15 +1,15 @@ " Vim compiler file " Compiler: ATT dot " Maintainer: Marcos Macedo <bar4ka@bol.com.br> -" Last Change: 2004 May 16 +" Last Change: 2024 March 21 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish endif let current_compiler = "dot" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet makeprg=dot\ -T$*\ \"%:p\"\ -o\ \"%:p:r.$*\" +" matches error messages as below skipping final part after line number +" Error: ./file.dot: syntax error in line 1 near 'rankdir' +CompilerSet errorformat=%trror:\ %f:\ %m\ in\ line\ %l%.%# diff --git a/runtime/compiler/dotnet.vim b/runtime/compiler/dotnet.vim index ac64084663..1290357221 100644 --- a/runtime/compiler/dotnet.vim +++ b/runtime/compiler/dotnet.vim @@ -2,6 +2,7 @@ " Compiler: dotnet build (.NET CLI) " Maintainer: Nick Jensen <nickspoon@gmail.com> " Last Change: 2022-12-06 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) " License: Vim (see :h license) " Repository: https://github.com/nickspoons/vim-cs @@ -10,10 +11,6 @@ if exists("current_compiler") endif let current_compiler = "dotnet" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/erlang.vim b/runtime/compiler/erlang.vim index e22887e05e..b30b5c11e7 100644 --- a/runtime/compiler/erlang.vim +++ b/runtime/compiler/erlang.vim @@ -2,6 +2,7 @@ " Compiler: Erlang " Maintainer: Dmitry Vasiliev <dima at hlabs dot org> " Last Change: 2019 Jul 23 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish diff --git a/runtime/compiler/eruby.vim b/runtime/compiler/eruby.vim index a81a3f3b77..815d082f86 100644 --- a/runtime/compiler/eruby.vim +++ b/runtime/compiler/eruby.vim @@ -3,17 +3,13 @@ " Maintainer: Doug Kearns <dougkearns@gmail.com> " URL: https://github.com/vim-ruby/vim-ruby " Release Coordinator: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2018 Jan 25 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "eruby" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo-=C diff --git a/runtime/compiler/eslint.vim b/runtime/compiler/eslint.vim index 7d57acbdf4..db7a665991 100644 --- a/runtime/compiler/eslint.vim +++ b/runtime/compiler/eslint.vim @@ -2,15 +2,12 @@ " Compiler: ESLint for JavaScript " Maintainer: Romain Lafourcade <romainlafourcade@gmail.com> " Last Change: 2020 August 20 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish endif let current_compiler = "eslint" -if exists(":CompilerSet") != 2 - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet makeprg=npx\ eslint\ --format\ compact CompilerSet errorformat=%f:\ line\ %l\\,\ col\ %c\\,\ %m,%-G%.%# diff --git a/runtime/compiler/fbc.vim b/runtime/compiler/fbc.vim index 1c29392da8..afedc32dff 100644 --- a/runtime/compiler/fbc.vim +++ b/runtime/compiler/fbc.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: FreeBASIC Compiler " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2015 Jan 10 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "fbc" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/fortran_F.vim b/runtime/compiler/fortran_F.vim index d9cb47cc1f..7f6ec818e0 100644 --- a/runtime/compiler/fortran_F.vim +++ b/runtime/compiler/fortran_F.vim @@ -3,17 +3,14 @@ " URL: http://www.unb.ca/chem/ajit/compiler/fortran_F.vim " Maintainer: Ajit J. Thakkar (ajit AT unb.ca); <http://www.unb.ca/chem/ajit/> " Version: 0.2 -" Last Change: 2004 Mar 27 +" Last Change: 2004 Mar 27 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish endif let current_compiler = "fortran_F" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cposet=&cpoptions set cpoptions-=C diff --git a/runtime/compiler/fortran_cv.vim b/runtime/compiler/fortran_cv.vim index bc217bdc66..ea46d99af4 100644 --- a/runtime/compiler/fortran_cv.vim +++ b/runtime/compiler/fortran_cv.vim @@ -2,16 +2,13 @@ " Compiler: Compaq Visual Fortran " Maintainer: Joh.-G. Simon (johann-guenter.simon@linde-le.com) " Last Change: 11/05/2002 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish endif let current_compiler = "fortran_cv" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cposet = &cpoptions set cpoptions-=C diff --git a/runtime/compiler/fortran_elf90.vim b/runtime/compiler/fortran_elf90.vim index 34c33cfaf8..903701e8e6 100644 --- a/runtime/compiler/fortran_elf90.vim +++ b/runtime/compiler/fortran_elf90.vim @@ -4,17 +4,14 @@ " URL: http://www.unb.ca/chem/ajit/compiler/fortran_elf90.vim " Maintainer: Ajit J. Thakkar (ajit AT unb.ca); <http://www.unb.ca/chem/ajit/> " Version: 0.2 -" Last Change: 2004 Mar 27 +" Last Change: 2004 Mar 27 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish endif let current_compiler = "fortran_elf90" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cposet=&cpoptions set cpoptions-=C diff --git a/runtime/compiler/fortran_g77.vim b/runtime/compiler/fortran_g77.vim index 744ce6a334..dcac2a7c9a 100644 --- a/runtime/compiler/fortran_g77.vim +++ b/runtime/compiler/fortran_g77.vim @@ -2,6 +2,7 @@ " Compiler: g77 (GNU Fortran) " Maintainer: Ralf Wildenhues <Ralf.Wildenhues@gmx.de> " Last Change: $Date: 2004/06/13 18:17:36 $ +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) " $Revision: 1.1 $ if exists("current_compiler") @@ -9,10 +10,6 @@ if exists("current_compiler") endif let current_compiler = "fortran_g77" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo-=C diff --git a/runtime/compiler/fortran_lf95.vim b/runtime/compiler/fortran_lf95.vim index 685fee7b4a..2cb71589b2 100644 --- a/runtime/compiler/fortran_lf95.vim +++ b/runtime/compiler/fortran_lf95.vim @@ -3,17 +3,14 @@ " URL: http://www.unb.ca/chem/ajit/compiler/fortran_lf95.vim " Maintainer: Ajit J. Thakkar (ajit AT unb.ca); <http://www.unb.ca/chem/ajit/> " Version: 0.2 -" Last Change: 2004 Mar 27 +" Last Change: 2004 Mar 27 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish endif let current_compiler = "fortran_lf95" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cposet=&cpoptions set cpoptions-=C diff --git a/runtime/compiler/fpc.vim b/runtime/compiler/fpc.vim index de8e2fe3dc..0d321ab4c7 100644 --- a/runtime/compiler/fpc.vim +++ b/runtime/compiler/fpc.vim @@ -2,16 +2,13 @@ " Compiler: FPC 2.1 " Maintainer: Jaroslaw Blasiok <jaro3000@o2.pl> " Last Change: 2005 October 07 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish endif let current_compiler = "fpc" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - " NOTE: compiler must be run with -vb to write whole source path, not only file " name. CompilerSet errorformat=%f(%l\\,%c)\ %m diff --git a/runtime/compiler/g95.vim b/runtime/compiler/g95.vim index ecb3212cbe..e0b3a688f2 100644 --- a/runtime/compiler/g95.vim +++ b/runtime/compiler/g95.vim @@ -2,6 +2,7 @@ " Maintainer: H Xu <xuhdev@gmail.com> " Version: 0.1.3 " Last Change: 2012 Apr 30 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) " Homepage: http://www.vim.org/scripts/script.php?script_id=3492 " https://bitbucket.org/xuhdev/compiler-g95.vim " License: Same as Vim @@ -13,10 +14,6 @@ let current_compiler = 'g95' let s:keepcpo= &cpo set cpo&vim -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet errorformat= \%AIn\ file\ %f:%l, \%-C%p1, diff --git a/runtime/compiler/gawk.vim b/runtime/compiler/gawk.vim index a109eb8642..f2a360d5f3 100644 --- a/runtime/compiler/gawk.vim +++ b/runtime/compiler/gawk.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: GNU Awk " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2020 Feb 10 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "gawk" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/gcc.vim b/runtime/compiler/gcc.vim index 30e5149f9f..7b6ebb98f4 100644 --- a/runtime/compiler/gcc.vim +++ b/runtime/compiler/gcc.vim @@ -1,10 +1,11 @@ " Vim compiler file -" Compiler: GNU C Compiler -" Previous Maintainer: Nikolai Weibull <now@bitwi.se> -" Latest Revision: 2010-10-14 -" changed pattern for entering/leaving directories -" by Daniel Hahler, 2019 Jul 12 -" added line suggested by Anton Lindqvist 2016 Mar 31 +" Compiler: GNU C Compiler +" Previous Maintainer: Nikolai Weibull <now@bitwi.se> +" Last Change: 2010 Oct 14 +" changed pattern for entering/leaving directories +" by Daniel Hahler, 2019 Jul 12 +" added line suggested by Anton Lindqvist 2016 Mar 31 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish diff --git a/runtime/compiler/gfortran.vim b/runtime/compiler/gfortran.vim index 1e4e5cf4f4..1fea3bcb18 100644 --- a/runtime/compiler/gfortran.vim +++ b/runtime/compiler/gfortran.vim @@ -2,6 +2,7 @@ " Maintainer: H Xu <xuhdev@gmail.com> " Version: 0.1.3 " Last Change: 2012 Apr 30 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) " Homepage: http://www.vim.org/scripts/script.php?script_id=3496 " https://bitbucket.org/xuhdev/compiler-gfortran.vim " License: Same as Vim @@ -13,10 +14,6 @@ let current_compiler = 'gfortran' let s:keepcpo= &cpo set cpo&vim -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet errorformat= \%A%f:%l.%c:, \%-Z%trror:\ %m, diff --git a/runtime/compiler/gjs.vim b/runtime/compiler/gjs.vim index e033764030..b1be8cf3e6 100644 --- a/runtime/compiler/gjs.vim +++ b/runtime/compiler/gjs.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: GJS (Gnome JavaScript Bindings) " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2019 Jul 10 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "gjs" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/gm2.vim b/runtime/compiler/gm2.vim index 5053912200..954da9d0e7 100644 --- a/runtime/compiler/gm2.vim +++ b/runtime/compiler/gm2.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: GNU Modula-2 Compiler " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2024 Jan 04 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "gm2" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/gnat.vim b/runtime/compiler/gnat.vim index 3ad1eb4e3f..086edbede3 100644 --- a/runtime/compiler/gnat.vim +++ b/runtime/compiler/gnat.vim @@ -52,13 +52,6 @@ if !exists("g:gnat") call g:gnat.Set_Session () endif -if exists(":CompilerSet") != 2 - " - " plugin loaded by other means then the "compiler" command - " - command -nargs=* CompilerSet setlocal <args> -endif - execute "CompilerSet makeprg=" . escape (g:gnat.Get_Command('Make'), ' ') execute "CompilerSet errorformat=" . escape (g:gnat.Error_Format, ' ') diff --git a/runtime/compiler/go.vim b/runtime/compiler/go.vim index cf638f23d6..9c1a6f3119 100644 --- a/runtime/compiler/go.vim +++ b/runtime/compiler/go.vim @@ -2,16 +2,13 @@ " Compiler: Go " Maintainer: David Barnett (https://github.com/google/vim-ft-go) " Last Change: 2014 Aug 16 +" 2024 Apr 05 by The Vim Project (removed :CompilerSet definition) if exists('current_compiler') finish endif let current_compiler = 'go' -if exists(':CompilerSet') != 2 - command -nargs=* CompilerSet setlocal <args> -endif - let s:save_cpo = &cpo set cpo-=C diff --git a/runtime/compiler/haml.vim b/runtime/compiler/haml.vim index 9464c3dc85..99c171d76c 100644 --- a/runtime/compiler/haml.vim +++ b/runtime/compiler/haml.vim @@ -2,16 +2,13 @@ " Compiler: Haml " Maintainer: Tim Pope <vimNOSPAM@tpope.org> " Last Change: 2016 Aug 29 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish endif let current_compiler = "haml" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo-=C diff --git a/runtime/compiler/hare.vim b/runtime/compiler/hare.vim index c0fa68cc00..c98bbb9c63 100644 --- a/runtime/compiler/hare.vim +++ b/runtime/compiler/hare.vim @@ -2,6 +2,7 @@ " Compiler: Hare Compiler " Maintainer: Amelia Clarke <me@rsaihe.dev> " Last Change: 2022-09-21 +" 2024 Apr 05 by The Vim Project (removed :CompilerSet definition) if exists("g:current_compiler") finish @@ -11,10 +12,6 @@ let g:current_compiler = "hare" let s:cpo_save = &cpo set cpo&vim -if exists(':CompilerSet') != 2 - command -nargs=* CompilerSet setlocal <args> -endif - if filereadable("Makefile") || filereadable("makefile") CompilerSet makeprg=make else diff --git a/runtime/compiler/hp_acc.vim b/runtime/compiler/hp_acc.vim index 15d5ce5f19..f6ccc57c73 100644 --- a/runtime/compiler/hp_acc.vim +++ b/runtime/compiler/hp_acc.vim @@ -3,6 +3,7 @@ " Maintainer: Matthias Ulrich <matthias-ulrich@web.de> " URL: http://www.subhome.de/vim/hp_acc.vim " Last Change: 2012 Apr 30 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) " " aCC --version says: "HP ANSI C++ B3910B A.03.13" " This compiler has been tested on: @@ -22,10 +23,6 @@ let current_compiler = "hp_acc" let s:keepcpo= &cpo set cpo&vim -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet errorformat=%A%trror\ %n\:\ \"%f\"\\,\ line\ %l\ \#\ %m, \%A%tarning\ (suggestion)\ %n\:\ \"%f\"\\,\ line\ %l\ \#\ %m\ %#, \%A%tarning\ %n\:\ \"%f\"\\,\ line\ %l\ \#\ %m\ %#, diff --git a/runtime/compiler/icc.vim b/runtime/compiler/icc.vim index 751fba65c7..37958f1c94 100644 --- a/runtime/compiler/icc.vim +++ b/runtime/compiler/icc.vim @@ -2,16 +2,13 @@ " Compiler: icc - Intel C++ " Maintainer: Peter Puck <PtrPck@netscape.net> " Last Change: 2004 Mar 27 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish endif let current_compiler = "icc" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - " I think that Intel is calling the compiler icl under Windows CompilerSet errorformat=%-Z%p^,%f(%l):\ remark\ #%n:%m,%f(%l)\ :\ (col.\ %c)\ remark:\ %m,%E%f(%l):\ error:\ %m,%E%f(%l):\ error:\ #%n:\ %m,%W%f(%l):\ warning\ #%n:\ %m,%W%f(%l):\ warning:\ %m,%-C%.%# diff --git a/runtime/compiler/icon.vim b/runtime/compiler/icon.vim index 40f67930f7..8b46af2a13 100644 --- a/runtime/compiler/icon.vim +++ b/runtime/compiler/icon.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: Icon Compiler " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2022 Jun 16 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "icont" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/ifort.vim b/runtime/compiler/ifort.vim index 3a60d0cd12..8c58ba685d 100644 --- a/runtime/compiler/ifort.vim +++ b/runtime/compiler/ifort.vim @@ -2,6 +2,7 @@ " Maintainer: H Xu <xuhdev@gmail.com> " Version: 0.1.1 " Last Change: 2012 Apr 30 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) " Homepage: http://www.vim.org/scripts/script.php?script_id=3497 " https://bitbucket.org/xuhdev/compiler-ifort.vim " License: Same as Vim @@ -13,10 +14,6 @@ let current_compiler = 'ifort' let s:keepcpo= &cpo set cpo&vim -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet errorformat= \%A%f(%l):\ %trror\ \#%n:\ %m, \%A%f(%l):\ %tarning\ \#%n:\ %m, diff --git a/runtime/compiler/intel.vim b/runtime/compiler/intel.vim index 254d13b6d8..cde62b1c48 100644 --- a/runtime/compiler/intel.vim +++ b/runtime/compiler/intel.vim @@ -2,6 +2,7 @@ " Compiler: Intel C++ 7.1 " Maintainer: David Harrison <david_jr@users.sourceforge.net> " Last Change: 2012 Apr 30 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish @@ -10,10 +11,6 @@ let current_compiler = "intel" let s:keepcpo= &cpo set cpo&vim -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet errorformat=%E%f(%l):\ error:\ %m, \%W%f(%l):\ warning:\ %m, \%I%f(%l):\ remark\ #%n:\ %m, diff --git a/runtime/compiler/irix5_c.vim b/runtime/compiler/irix5_c.vim index f440e74f05..f70bfb1ea7 100644 --- a/runtime/compiler/irix5_c.vim +++ b/runtime/compiler/irix5_c.vim @@ -2,6 +2,7 @@ " Compiler: SGI IRIX 5.3 cc " Maintainer: David Harrison <david_jr@users.sourceforge.net> " Last Change: 2012 Apr 30 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish @@ -10,10 +11,6 @@ let current_compiler = "irix5_c" let s:keepcpo= &cpo set cpo&vim -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet errorformat=\%Ecfe:\ Error:\ %f\\,\ line\ %l:\ %m, \%Wcfe:\ Warning:\ %n:\ %f\\,\ line\ %l:\ %m, \%Wcfe:\ Warning\ %n:\ %f\\,\ line\ %l:\ %m, diff --git a/runtime/compiler/irix5_cpp.vim b/runtime/compiler/irix5_cpp.vim index 0112dc1cbc..85ab8c67f2 100644 --- a/runtime/compiler/irix5_cpp.vim +++ b/runtime/compiler/irix5_cpp.vim @@ -2,6 +2,7 @@ " Compiler: SGI IRIX 5.3 CC or NCC " Maintainer: David Harrison <david_jr@users.sourceforge.net> " Last Change: 2012 Apr 30 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish @@ -10,10 +11,6 @@ let current_compiler = "irix5_cpp" let s:keepcpo= &cpo set cpo&vim -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet errorformat=%E\"%f\"\\,\ line\ %l:\ error(%n):\ , \%E\"%f\"\\,\ line\ %l:\ error(%n):\ %m, \%W\"%f\"\\,\ line\ %l:\ warning(%n):\ %m, diff --git a/runtime/compiler/javac.vim b/runtime/compiler/javac.vim index 8507efd67c..f5fe84124f 100644 --- a/runtime/compiler/javac.vim +++ b/runtime/compiler/javac.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: Java Development Kit Compiler " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2019 Oct 21 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "javac" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/jest.vim b/runtime/compiler/jest.vim index a4bb549de1..663123c30f 100644 --- a/runtime/compiler/jest.vim +++ b/runtime/compiler/jest.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: Jest " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2021 Nov 20 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "jest" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/jikes.vim b/runtime/compiler/jikes.vim index 2d4500e894..f12c2cf5f1 100644 --- a/runtime/compiler/jikes.vim +++ b/runtime/compiler/jikes.vim @@ -2,6 +2,7 @@ " Compiler: Jikes " Maintainer: Dan Sharp <dwsharp at hotmail dot com> " Last Change: 2019 Jul 23 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) " URL: http://dwsharp.users.sourceforge.net/vim/compiler if exists("current_compiler") @@ -9,10 +10,6 @@ if exists("current_compiler") endif let current_compiler = "jikes" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - " Jikes defaults to printing output on stderr CompilerSet makeprg=jikes\ -Xstdout\ +E\ \"%:S\" CompilerSet errorformat=%f:%l:%v:%*\\d:%*\\d:%*\\s%m diff --git a/runtime/compiler/jjs.vim b/runtime/compiler/jjs.vim index 09a973683a..543d9ca3d4 100644 --- a/runtime/compiler/jjs.vim +++ b/runtime/compiler/jjs.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: Nashorn Shell " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2018 Jan 9 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "jjs" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/jq.vim b/runtime/compiler/jq.vim new file mode 100644 index 0000000000..a656223e51 --- /dev/null +++ b/runtime/compiler/jq.vim @@ -0,0 +1,25 @@ +" Vim compiler file +" Compiler: jq +" Maintainer: Vito <vito.blog@gmail.com> +" Last Change: 2024 Apr 17 +" Upstream: https://github.com/vito-c/jq.vim + +if exists('b:current_compiler') + finish +endif +let b:current_compiler = 'jq' + +let s:save_cpoptions = &cpoptions +set cpoptions&vim + +if has('unix') + CompilerSet makeprg=jq\ -f\ %:S\ /dev/null +else + CompilerSet makeprg=jq\ -f\ %:S\ nul +endif +CompilerSet errorformat=%E%m\ at\ \\<%o\\>\\,\ line\ %l:, + \%Z, + \%-G%.%# + +let &cpoptions = s:save_cpoptions +unlet s:save_cpoptions diff --git a/runtime/compiler/jshint.vim b/runtime/compiler/jshint.vim index 865591cd2b..9879ef49e5 100644 --- a/runtime/compiler/jshint.vim +++ b/runtime/compiler/jshint.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: JSHint " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2019 Jul 10 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "jshint" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/jsonlint.vim b/runtime/compiler/jsonlint.vim index 5466dcc7f4..6283b1b01f 100644 --- a/runtime/compiler/jsonlint.vim +++ b/runtime/compiler/jsonlint.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: JSON Lint " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2019 Jul 10 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "jsonlint" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/mcs.vim b/runtime/compiler/mcs.vim index c606586870..0c265b3de5 100644 --- a/runtime/compiler/mcs.vim +++ b/runtime/compiler/mcs.vim @@ -1,8 +1,9 @@ " Vim compiler file -" Compiler: Mono C# Compiler -" Maintainer: Jarek Sobiecki <harijari@go2.pl> -" Last Updated By: Peter Collingbourne -" Latest Revision: 2012 Jul 19 +" Compiler: Mono C# Compiler +" Maintainer: Jarek Sobiecki <harijari@go2.pl> +" Contributors: Peter Collingbourne and Enno Nagel +" Last Change: 2024 Mar 29 +" 2024 Apr 05 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish @@ -12,7 +13,8 @@ let current_compiler = "mcs" let s:cpo_save = &cpo set cpo-=C -setlocal errorformat= +CompilerSet makeprg=mcs +CompilerSet errorformat= \%D%.%#Project\ \"%f/%[%^/\"]%#\"%.%#, \%X%.%#Done\ building\ project\ \"%f/%[%^/\"]%#\"%.%#, \%-G%\\s%.%#, diff --git a/runtime/compiler/mips_c.vim b/runtime/compiler/mips_c.vim index a0ebfe7ba2..544f314a1a 100644 --- a/runtime/compiler/mips_c.vim +++ b/runtime/compiler/mips_c.vim @@ -2,6 +2,7 @@ " Compiler: SGI IRIX 6.5 MIPS C (cc) " Maintainer: David Harrison <david_jr@users.sourceforge.net> " Last Change: 2012 Apr 30 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish @@ -10,10 +11,6 @@ let current_compiler = "mips_c" let s:keepcpo= &cpo set cpo&vim -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet errorformat=%Ecc\-%n\ %.%#:\ ERROR\ File\ =\ %f\%\\,\ Line\ =\ %l, \%Wcc\-%n\ %.%#:\ WARNING\ File\ =\ %f\%\\,\ Line\ =\ %l, \%Icc\-%n\ %.%#:\ REMARK\ File\ =\ %f\%\\,\ Line\ =\ %l, diff --git a/runtime/compiler/mipspro_c89.vim b/runtime/compiler/mipspro_c89.vim index 20eb70d3fe..4d6bdabeef 100644 --- a/runtime/compiler/mipspro_c89.vim +++ b/runtime/compiler/mipspro_c89.vim @@ -2,6 +2,7 @@ " Compiler: SGI IRIX 6.5 MIPSPro C (c89) " Maintainer: David Harrison <david_jr@users.sourceforge.net> " Last Change: 2012 Apr 30 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish @@ -10,10 +11,6 @@ let current_compiler = "mipspro_c89" let s:keepcpo= &cpo set cpo&vim -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet errorformat=%Ecc\-%n\ %.%#:\ ERROR\ File\ =\ %f\%\\,\ Line\ =\ %l, \%Wcc\-%n\ %.%#:\ WARNING\ File\ =\ %f\%\\,\ Line\ =\ %l, \%Icc\-%n\ %.%#:\ REMARK\ File\ =\ %f\%\\,\ Line\ =\ %l, diff --git a/runtime/compiler/mipspro_cpp.vim b/runtime/compiler/mipspro_cpp.vim index 2f43af8455..9aac2a6564 100644 --- a/runtime/compiler/mipspro_cpp.vim +++ b/runtime/compiler/mipspro_cpp.vim @@ -2,6 +2,7 @@ " Compiler: SGI IRIX 6.5 MIPSPro C++ (CC) " Maintainer: David Harrison <david_jr@users.sourceforge.net> " Last Change: 2012 Apr 30 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish @@ -10,10 +11,6 @@ let current_compiler = "mipspro_cpp" let s:keepcpo= &cpo set cpo&vim -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet errorformat=%Ecc\-%n\ %.%#:\ ERROR\ File\ =\ %f\%\\,\ Line\ =\ %l, \%Wcc\-%n\ %.%#:\ WARNING\ File\ =\ %f\%\\,\ Line\ =\ %l, \%Icc\-%n\ %.%#:\ REMARK\ File\ =\ %f\%\\,\ Line\ =\ %l, diff --git a/runtime/compiler/modelsim_vcom.vim b/runtime/compiler/modelsim_vcom.vim index 6aa1bde0b3..8c6b8063ad 100644 --- a/runtime/compiler/modelsim_vcom.vim +++ b/runtime/compiler/modelsim_vcom.vim @@ -1,7 +1,9 @@ " Vim Compiler File " Compiler: Modelsim Vcom " Maintainer: Paul Baleme <pbaleme@mail.com> -" Last Change: September 8, 2003 +" Contributors: Enno Nagel +" Last Change: 2024 Mar 29 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) " Thanks to: allanherriman@hotmail.com if exists("current_compiler") @@ -9,12 +11,9 @@ if exists("current_compiler") endif let current_compiler = "modelsim_vcom" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif +CompilerSet makeprg=vcom "setlocal errorformat=\*\*\ %tRROR:\ %f(%l):\ %m,%tRROR:\ %f(%l):\ %m,%tARNING\[%*[0-9]\]:\ %f(%l):\ %m,\*\*\ %tRROR:\ %m,%tRROR:\ %m,%tARNING\[%*[0-9]\]:\ %m - "setlocal errorformat=%tRROR:\ %f(%l):\ %m,%tARNING\[%*[0-9]\]:\ %m CompilerSet errorformat=\*\*\ %tRROR:\ %f(%l):\ %m,\*\*\ %tRROR:\ %m,\*\*\ %tARNING:\ %m,\*\*\ %tOTE:\ %m,%tRROR:\ %f(%l):\ %m,%tARNING\[%*[0-9]\]:\ %f(%l):\ %m,%tRROR:\ %m,%tARNING\[%*[0-9]\]:\ %m diff --git a/runtime/compiler/msbuild.vim b/runtime/compiler/msbuild.vim index 3652ca0e04..c871efaf3d 100644 --- a/runtime/compiler/msbuild.vim +++ b/runtime/compiler/msbuild.vim @@ -2,6 +2,7 @@ " Compiler: Microsoft Visual Studio C# " Maintainer: Chiel ten Brinke (ctje92@gmail.com) " Last Change: 2013 May 13 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish @@ -10,10 +11,6 @@ let current_compiler = "msbuild" let s:keepcpo= &cpo set cpo&vim -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet errorformat=\ %#%f(%l\\\,%c):\ %m CompilerSet makeprg=msbuild\ /nologo\ /v:q\ /property:GenerateFullPaths=true diff --git a/runtime/compiler/msvc.vim b/runtime/compiler/msvc.vim index 0d5660c103..3d40de5b7f 100644 --- a/runtime/compiler/msvc.vim +++ b/runtime/compiler/msvc.vim @@ -2,6 +2,7 @@ " Compiler: Microsoft Visual C " Maintainer: The Vim Project <https://github.com/vim/vim> " Last Change: 2023 Aug 10 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) " Former Maintainer: Bram Moolenaar <Bram@vim.org> if exists("current_compiler") diff --git a/runtime/compiler/neato.vim b/runtime/compiler/neato.vim index bd184b7f6e..0f36734130 100644 --- a/runtime/compiler/neato.vim +++ b/runtime/compiler/neato.vim @@ -1,15 +1,15 @@ " Vim compiler file " Compiler: ATT neato " Maintainer: Marcos Macedo <bar4ka@bol.com.br> -" Last Change: 2004 May 16 +" Last Change: 2024 March 21 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish endif let current_compiler = "neato" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet makeprg=neato\ -T$*\ \"%:p\"\ -o\ \"%:p:r.$*\" +" matches error messages as below skipping final part after line number +" Error: ./file.dot: syntax error in line 1 near 'rankdir' +CompilerSet errorformat=%trror:\ %f:\ %m\ in\ line\ %l%.%# diff --git a/runtime/compiler/ocaml.vim b/runtime/compiler/ocaml.vim index faa8af1f5f..754289fc14 100644 --- a/runtime/compiler/ocaml.vim +++ b/runtime/compiler/ocaml.vim @@ -3,6 +3,7 @@ " Maintainer: Markus Mottl <markus.mottl@gmail.com> " URL: https://github.com/ocaml/vim-ocaml " Last Change: +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) " 2020 Mar 28 - Improved error format (Thomas Leonard) " 2017 Nov 26 - Improved error format (Markus Mottl) " 2013 Aug 27 - Added a new OCaml error format (Markus Mottl) diff --git a/runtime/compiler/onsgmls.vim b/runtime/compiler/onsgmls.vim index 68925ef459..4306f99de5 100644 --- a/runtime/compiler/onsgmls.vim +++ b/runtime/compiler/onsgmls.vim @@ -2,16 +2,13 @@ " Compiler: onsgmls " Maintainer: Robert Rowsome <rowsome@wam.umd.edu> " Last Change: 2019 Jul 23 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish endif let current_compiler = "onsgmls" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo-=C diff --git a/runtime/compiler/pandoc.vim b/runtime/compiler/pandoc.vim new file mode 100644 index 0000000000..6c151930c5 --- /dev/null +++ b/runtime/compiler/pandoc.vim @@ -0,0 +1,55 @@ +" Vim compiler file +" Compiler: Pandoc +" Maintainer: Konfekt +" +" Expects output file extension, say `:make html` or `:make pdf`. +" Passes additional arguments to pandoc, say `:make html --self-contained`. + +if exists("current_compiler") + finish +endif + +let s:keepcpo = &cpo +set cpo&vim + +let current_compiler = 'pandoc' + +" As of 2024-04-08 pandoc supports the following text input formats with +" an ftplugin on Github: +let s:supported_filetypes = + \ [ 'bibtex', 'markdown', 'creole', 'json', 'csv', 'tsv', 'docbook', + \ 'xml', 'fb2', 'html', 'jira', 'tex', 'mediawiki', 'nroff', 'org', + \ 'rtf', 'rst', 't2t', 'textile', 'twiki', 'typst', 'vimwiki' ] +" .. and out of those the following are included in Vim's runtime: +" 'xml', 'tex', 'html', 'rst', 'json', 'nroff', 'markdown' + +silent! function s:PandocFiletype(filetype) abort + let ft = a:filetype + if ft ==# 'pandoc' + return 'markdown' + elseif ft ==# 'tex' + return 'latex' + elseif ft ==# 'xml' + " Pandoc does not support XML as a generic input format, but it does support + " EndNote XML and Jats XML out of which the latter seems more universal. + return 'jats' + elseif ft ==# 'text' || empty(ft) + return 'markdown' + elseif index(s:supported_filetypes, &ft) >= 0 + return ft + else + echomsg 'Unsupported filetype: ' . ft . ', falling back to Markdown as input format!' + return 'markdown' + endif +endfunction +execute 'CompilerSet makeprg=pandoc\ --standalone' . + \ '\ --metadata\ title=%:t:r:S' . + \ '\ --metadata\ lang=' . matchstr(&spelllang, '^\a\a') . + \ '\ --from=' . s:PandocFiletype(&filetype) . + \ '\ ' . escape(get(b:, 'pandoc_compiler_args', get(g:, 'pandoc_compiler_args', '')), ' ') . + \ '\ --output\ %:r:S.$*\ %:S' + +CompilerSet errorformat="%f",\ line\ %l:\ %m + +let &cpo = s:keepcpo +unlet s:keepcpo diff --git a/runtime/compiler/pbx.vim b/runtime/compiler/pbx.vim index 9e81ea7355..5a45f7ffe0 100644 --- a/runtime/compiler/pbx.vim +++ b/runtime/compiler/pbx.vim @@ -2,16 +2,13 @@ " Compiler: Apple Project Builder " Maintainer: Alexander von Below (public@vonBelow.Com) " Last Change: 2004 Mar 27 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish endif let current_compiler = "pbx" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - " The compiler actually is gcc, so the errorformat is unchanged CompilerSet errorformat& diff --git a/runtime/compiler/perl.vim b/runtime/compiler/perl.vim index 21e384fb85..6aeaac3fa1 100644 --- a/runtime/compiler/perl.vim +++ b/runtime/compiler/perl.vim @@ -6,16 +6,13 @@ " Bugs/requests: https://github.com/vim-perl/vim-perl/issues " License: Vim License (see :help license) " Last Change: 2021 Nov 2 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish endif let current_compiler = "perl" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:savecpo = &cpo set cpo&vim diff --git a/runtime/compiler/perlcritic.vim b/runtime/compiler/perlcritic.vim index cf0678eeb2..4b5f34dd2e 100644 --- a/runtime/compiler/perlcritic.vim +++ b/runtime/compiler/perlcritic.vim @@ -6,16 +6,13 @@ " Bugs/requests: https://github.com/vim-perl/vim-perl/issues " License: Vim License (see :help license) " Last Change: 2021 Oct 20 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish endif let current_compiler = "perlcritic" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/php.vim b/runtime/compiler/php.vim index 92f93b89fc..f5d521098b 100644 --- a/runtime/compiler/php.vim +++ b/runtime/compiler/php.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: PHP CLI " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2013 Jun 25 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "php" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo-=C diff --git a/runtime/compiler/pip_compile.vim b/runtime/compiler/pip_compile.vim new file mode 100644 index 0000000000..ca4d509660 --- /dev/null +++ b/runtime/compiler/pip_compile.vim @@ -0,0 +1,43 @@ +" the Requirements File Format syntax support for Vim +" Version: 1.8.0 +" Author: raimon <raimon49@hotmail.com> +" Upstream: https://github.com/raimon49/requirements.txt.vim +" License: MIT LICENSE +" The MIT License (MIT) +" +" Copyright (c) 2015 raimon +" +" Permission is hereby granted, free of charge, to any person obtaining a copy +" of this software and associated documentation files (the "Software"), to deal +" in the Software without restriction, including without limitation the rights +" to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +" copies of the Software, and to permit persons to whom the Software is +" furnished to do so, subject to the following conditions: +" +" The above copyright notice and this permission notice shall be included in all +" copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +" OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +" SOFTWARE. + +if exists('b:current_compiler') + finish +endif +let b:current_compiler = 'pip_compile' + +let s:save_cpoptions = &cpoptions +set cpoptions&vim + +CompilerSet makeprg=pip-compile\ %:S +CompilerSet errorformat=%ECould\ not\ find\ a\ version\ that\ matches\ %o\ (from\ -r\ %f\ (line\ %l)), + \%C%m, + \%Z, + \%-G%.%# +let &cpoptions = s:save_cpoptions +unlet s:save_cpoptions +" vim: et sw=4 ts=4 sts=4: diff --git a/runtime/compiler/podchecker.vim b/runtime/compiler/podchecker.vim index 2cd4e13660..20faaa4bcc 100644 --- a/runtime/compiler/podchecker.vim +++ b/runtime/compiler/podchecker.vim @@ -6,16 +6,13 @@ " Bugs/requests: https://github.com/vim-perl/vim-perl/issues " License: Vim License (see :help license) " Last Change: 2021 Oct 20 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish endif let current_compiler = "podchecker" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/powershell.vim b/runtime/compiler/powershell.vim index 45d5ec2191..821fea4085 100644 --- a/runtime/compiler/powershell.vim +++ b/runtime/compiler/powershell.vim @@ -1,17 +1,16 @@ " Vim compiler file " Compiler: powershell " URL: https://github.com/PProvost/vim-ps1 -" Last Change: 2020 Mar 30 +" Contributors: Enno Nagel +" Last Change: 2024 Mar 29 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) +" 2024 Apr 05 by The Vim Project (avoid leaving behind g:makeprg) if exists("current_compiler") finish endif let current_compiler = "powershell" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo-=C @@ -37,7 +36,7 @@ let g:ps1_efm_show_error_categories = get(g:, 'ps1_efm_show_error_categories', 0 " Use absolute path because powershell requires explicit relative paths " (./file.ps1 is okay, but # expands to file.ps1) -let &l:makeprg = g:ps1_makeprg_cmd .' %:p:S' +let s:makeprg = g:ps1_makeprg_cmd .. ' %:p:S' " Parse file, line, char from callstacks: " Write-Ouput : The term 'Write-Ouput' is not recognized as the name of a @@ -50,6 +49,8 @@ let &l:makeprg = g:ps1_makeprg_cmd .' %:p:S' " + CategoryInfo : ObjectNotFound: (Write-Ouput:String) [], CommandNotFoundException " + FullyQualifiedErrorId : CommandNotFoundException +execute 'CompilerSet makeprg=' .. escape(s:makeprg, ' ') + " Showing error in context with underlining. CompilerSet errorformat=%+G+%m " Error summary. diff --git a/runtime/compiler/pylint.vim b/runtime/compiler/pylint.vim index 93079ce61d..14e9696dbb 100644 --- a/runtime/compiler/pylint.vim +++ b/runtime/compiler/pylint.vim @@ -2,15 +2,12 @@ " 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 let current_compiler = "pylint" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet makeprg=pylint\ --output-format=text\ --msg-template=\"{path}:{line}:{column}:{C}:\ [{symbol}]\ {msg}\"\ --reports=no CompilerSet errorformat=%A%f:%l:%c:%t:\ %m,%A%f:%l:\ %m,%A%f:(%l):\ %m,%-Z%p^%.%#,%-G%.%# diff --git a/runtime/compiler/pyunit.vim b/runtime/compiler/pyunit.vim index 2a4ea92b68..2368346dd2 100644 --- a/runtime/compiler/pyunit.vim +++ b/runtime/compiler/pyunit.vim @@ -2,15 +2,12 @@ " Compiler: Unit testing tool for Python " Maintainer: Max Ischenko <mfi@ukr.net> " Last Change: 2004 Mar 27 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish endif let current_compiler = "pyunit" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet efm=%C\ %.%#,%A\ \ File\ \"%f\"\\,\ line\ %l%.%#,%Z%[%^\ ]%\\@=%m diff --git a/runtime/compiler/raco.vim b/runtime/compiler/raco.vim index bd10859aa9..d35d86b8c2 100644 --- a/runtime/compiler/raco.vim +++ b/runtime/compiler/raco.vim @@ -3,12 +3,9 @@ " Maintainer: D. Ben Knoble <ben.knoble+github@gmail.com> " URL: https://github.com/benknoble/vim-racket " Last Change: 2022 Aug 12 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) let current_compiler = 'raco' -if exists(":CompilerSet") != 2 - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet makeprg=raco CompilerSet errorformat=%f:%l:%c:%m diff --git a/runtime/compiler/racomake.vim b/runtime/compiler/racomake.vim index dae95fec42..bd2c327037 100644 --- a/runtime/compiler/racomake.vim +++ b/runtime/compiler/racomake.vim @@ -3,12 +3,9 @@ " Maintainer: D. Ben Knoble <ben.knoble+github@gmail.com> " URL: https://github.com/benknoble/vim-racket " Last Change: 2022 Aug 12 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) let current_compiler = 'racomake' -if exists(":CompilerSet") != 2 - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet makeprg=raco\ make\ --\ % CompilerSet errorformat=%f:%l:%c:%m diff --git a/runtime/compiler/racosetup.vim b/runtime/compiler/racosetup.vim index 1efe8a15a2..e16faf081a 100644 --- a/runtime/compiler/racosetup.vim +++ b/runtime/compiler/racosetup.vim @@ -3,12 +3,9 @@ " Maintainer: D. Ben Knoble <ben.knoble+github@gmail.com> " URL: https://github.com/benknoble/vim-racket " Last Change: 2022 Aug 12 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) let current_compiler = 'racosetup' -if exists(":CompilerSet") != 2 - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet makeprg=raco\ setup CompilerSet errorformat=%f:%l:%c:%m diff --git a/runtime/compiler/racotest.vim b/runtime/compiler/racotest.vim index d2a1a3c0f3..3ac11737d2 100644 --- a/runtime/compiler/racotest.vim +++ b/runtime/compiler/racotest.vim @@ -3,12 +3,9 @@ " Maintainer: D. Ben Knoble <ben.knoble+github@gmail.com> " URL: https://github.com/benknoble/vim-racket " Last Change: 2022 Aug 12 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) let current_compiler = 'racotest' -if exists(":CompilerSet") != 2 - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet makeprg=raco\ test\ % CompilerSet errorformat=location:%f:%l:%c diff --git a/runtime/compiler/rake.vim b/runtime/compiler/rake.vim index 3d11a31f89..5b3c7f4092 100644 --- a/runtime/compiler/rake.vim +++ b/runtime/compiler/rake.vim @@ -4,16 +4,13 @@ " URL: https://github.com/vim-ruby/vim-ruby " Release Coordinator: Doug Kearns <dougkearns@gmail.com> " Last Change: 2018 Mar 02 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish endif let current_compiler = "rake" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo-=C diff --git a/runtime/compiler/rhino.vim b/runtime/compiler/rhino.vim index 30f3dd3252..b6fc9c8d8c 100644 --- a/runtime/compiler/rhino.vim +++ b/runtime/compiler/rhino.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: Rhino Shell (JavaScript in Java) " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2019 Jul 10 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "rhino" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/rime_deployer.vim b/runtime/compiler/rime_deployer.vim new file mode 100644 index 0000000000..e0c8daef6e --- /dev/null +++ b/runtime/compiler/rime_deployer.vim @@ -0,0 +1,30 @@ +" Vim Compiler File +" Language: rime_deployer +" Maintainer: Wu, Zhenyu <wuzhenyu@ustc.edu> +" URL: https://rime.im +" Latest Revision: 2024-04-09 + +if exists('b:current_compiler') + finish +endif +let b:current_compiler = 'rime_deployer' + +let s:save_cpoptions = &cpoptions +set cpoptions&vim + +" Android Termux +let s:prefix = getenv('PREFIX') +if s:prefix == v:null + let s:prefix = '/usr' +endif +" Android, NixOS, GNU/Linux, BSD +for s:shared_data_dir in ['/sdcard/rime-data', '/run/current-system/sw/share/rime-data', '/usr/local/share/rime-data', s:prefix . '/share/rime-data'] + if isdirectory(s:shared_data_dir) + break + endif +endfor +execute 'CompilerSet makeprg=rime_deployer\ --build\ %:p:h:S\' s:shared_data_dir +unlet s:prefix s:shared_data_dir + +let &cpoptions = s:save_cpoptions +unlet s:save_cpoptions diff --git a/runtime/compiler/rspec.vim b/runtime/compiler/rspec.vim index 0cfce04572..ee848f703a 100644 --- a/runtime/compiler/rspec.vim +++ b/runtime/compiler/rspec.vim @@ -4,16 +4,13 @@ " URL: https://github.com/vim-ruby/vim-ruby " Release Coordinator: Doug Kearns <dougkearns@gmail.com> " Last Change: 2018 Aug 07 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish endif let current_compiler = "rspec" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo-=C diff --git a/runtime/compiler/rst.vim b/runtime/compiler/rst.vim index 392bea6ae0..72b6a58b67 100644 --- a/runtime/compiler/rst.vim +++ b/runtime/compiler/rst.vim @@ -2,7 +2,8 @@ " Compiler: sphinx >= 1.0.8, http://www.sphinx-doc.org " Description: reStructuredText Documentation Format " Previous Maintainer: Nikolai Weibull <now@bitwi.se> -" Latest Revision: 2017-03-31 +" Last Change: 2017 Mar 31 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish @@ -12,10 +13,6 @@ let current_compiler = "rst" let s:cpo_save = &cpo set cpo&vim -if exists(":CompilerSet") != 2 - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet errorformat= \%f\\:%l:\ %tEBUG:\ %m, \%f\\:%l:\ %tNFO:\ %m, diff --git a/runtime/compiler/rubocop.vim b/runtime/compiler/rubocop.vim index 7764b4ad20..9d2f01499f 100644 --- a/runtime/compiler/rubocop.vim +++ b/runtime/compiler/rubocop.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: RuboCop " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2019 Jul 10 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "rubocop" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/ruby.vim b/runtime/compiler/ruby.vim index 82d4d1c876..70dff5bf24 100644 --- a/runtime/compiler/ruby.vim +++ b/runtime/compiler/ruby.vim @@ -5,16 +5,13 @@ " URL: https://github.com/vim-ruby/vim-ruby " Release Coordinator: Doug Kearns <dougkearns@gmail.com> " Last Change: 2019 Jan 06 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish endif let current_compiler = "ruby" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo-=C diff --git a/runtime/compiler/rubyunit.vim b/runtime/compiler/rubyunit.vim index 48e8fa41ab..e59873fa21 100644 --- a/runtime/compiler/rubyunit.vim +++ b/runtime/compiler/rubyunit.vim @@ -4,16 +4,13 @@ " URL: https://github.com/vim-ruby/vim-ruby " Release Coordinator: Doug Kearns <dougkearns@gmail.com> " Last Change: 2014 Mar 23 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish endif let current_compiler = "rubyunit" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo-=C diff --git a/runtime/compiler/rustc.vim b/runtime/compiler/rustc.vim index efcf24ed80..b3c8091987 100644 --- a/runtime/compiler/rustc.vim +++ b/runtime/compiler/rustc.vim @@ -14,10 +14,6 @@ let s:save_cpo = &cpo set cpo&vim " vint: +ProhibitAbbreviationOption -if exists(":CompilerSet") != 2 - command -nargs=* CompilerSet setlocal <args> -endif - if get(g:, 'rustc_makeprg_no_percent', 0) CompilerSet makeprg=rustc else diff --git a/runtime/compiler/sass.vim b/runtime/compiler/sass.vim index 9c540ac443..d0ed65cfa5 100644 --- a/runtime/compiler/sass.vim +++ b/runtime/compiler/sass.vim @@ -2,16 +2,13 @@ " Compiler: Sass " Maintainer: Tim Pope <vimNOSPAM@tpope.org> " Last Change: 2016 Aug 29 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish endif let current_compiler = "sass" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo-=C diff --git a/runtime/compiler/scdoc.vim b/runtime/compiler/scdoc.vim index c37969f89c..364ddc179c 100644 --- a/runtime/compiler/scdoc.vim +++ b/runtime/compiler/scdoc.vim @@ -2,6 +2,7 @@ " Compiler: scdoc " Maintainer: Gregory Anders <contact@gpanders.com> " Last Updated: 2019-10-24 +" 2024 Apr 05 by The Vim Project (removed :CompilerSet definition) " Upstream: https://github.com/gpanders/vim-scdoc if exists('current_compiler') @@ -9,9 +10,5 @@ if exists('current_compiler') endif let current_compiler = 'scdoc' -if exists(':CompilerSet') != 2 - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet makeprg=scdoc\ <\ %\ 2>&1 CompilerSet errorformat=Error\ at\ %l:%c:\ %m,%-G%.%# diff --git a/runtime/compiler/se.vim b/runtime/compiler/se.vim index 38fd10c131..c9332277e5 100644 --- a/runtime/compiler/se.vim +++ b/runtime/compiler/se.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: se (Liberty Eiffel Compiler) " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2013 Jun 29 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "se" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo-=C diff --git a/runtime/compiler/shellcheck.vim b/runtime/compiler/shellcheck.vim index 7550439aa2..5eeddc69c1 100644 --- a/runtime/compiler/shellcheck.vim +++ b/runtime/compiler/shellcheck.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: ShellCheck " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2020 Sep 4 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "shellcheck" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/sml.vim b/runtime/compiler/sml.vim index a0b13b6c8a..e829e20e8c 100644 --- a/runtime/compiler/sml.vim +++ b/runtime/compiler/sml.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: SML/NJ Compiler " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2022 Feb 09 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "sml" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/spectral.vim b/runtime/compiler/spectral.vim index bd13c51f43..f1ea8653e5 100644 --- a/runtime/compiler/spectral.vim +++ b/runtime/compiler/spectral.vim @@ -2,16 +2,13 @@ " Compiler: Spectral for YAML " Maintainer: Romain Lafourcade <romainlafourcade@gmail.com> " Last Change: 2021 July 21 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish endif let current_compiler = "spectral" -if exists(":CompilerSet") != 2 - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet makeprg=spectral\ lint\ %\ -f\ text CompilerSet errorformat=%f:%l:%c\ %t%.%\\{-}\ %m diff --git a/runtime/compiler/splint.vim b/runtime/compiler/splint.vim index 3d7ada6d1d..e00460149c 100644 --- a/runtime/compiler/splint.vim +++ b/runtime/compiler/splint.vim @@ -3,6 +3,7 @@ " Maintainer: Ralf Wildenhues <Ralf.Wildenhues@gmx.de> " Splint Home: http://www.splint.org/ " Last Change: 2019 Jul 23 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) " $Revision: 1.3 $ if exists("current_compiler") @@ -10,10 +11,6 @@ if exists("current_compiler") endif let current_compiler = "splint" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo-=C diff --git a/runtime/compiler/standard.vim b/runtime/compiler/standard.vim index 50b7c97ca7..fdc79ae2ba 100644 --- a/runtime/compiler/standard.vim +++ b/runtime/compiler/standard.vim @@ -2,15 +2,12 @@ " Compiler: Standard for JavaScript " Maintainer: Romain Lafourcade <romainlafourcade@gmail.com> " Last Change: 2020 August 20 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish endif let current_compiler = "standard" -if exists(":CompilerSet") != 2 - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet makeprg=npx\ standard CompilerSet errorformat=%f:%l:%c:\ %m,%-G%.%# diff --git a/runtime/compiler/stylelint.vim b/runtime/compiler/stylelint.vim index 784a61d46a..22acea9eb0 100644 --- a/runtime/compiler/stylelint.vim +++ b/runtime/compiler/stylelint.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: Stylelint " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2020 Jun 10 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "stylelint" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/tcl.vim b/runtime/compiler/tcl.vim index 81af185f5e..1e6d1f39e1 100644 --- a/runtime/compiler/tcl.vim +++ b/runtime/compiler/tcl.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: tcl " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2004 Nov 27 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "tcl" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet makeprg=tcl CompilerSet errorformat=%EError:\ %m,%+Z\ %\\{4}(file\ \"%f\"\ line\ %l),%-G%.%# diff --git a/runtime/compiler/tex.vim b/runtime/compiler/tex.vim index 65e15cf6e2..282b3a0588 100644 --- a/runtime/compiler/tex.vim +++ b/runtime/compiler/tex.vim @@ -1,7 +1,10 @@ " Vim compiler file " Compiler: TeX " Maintainer: Artem Chuprina <ran@ran.pp.ru> -" Last Change: 2012 Apr 30 +" Contributors: Enno Nagel +" Last Change: 2024 Mar 29 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) +" 2024 Apr 05 by The Vim Project (avoid leaving behind g:makeprg) if exists("current_compiler") finish @@ -9,10 +12,6 @@ endif let s:keepcpo= &cpo set cpo&vim -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - " If makefile exists and we are not asked to ignore it, we use standard make " (do not redefine makeprg) if exists('b:tex_ignore_makefile') || exists('g:tex_ignore_makefile') || @@ -27,7 +26,8 @@ if exists('b:tex_ignore_makefile') || exists('g:tex_ignore_makefile') || else let current_compiler = "latex" endif - let &l:makeprg=current_compiler.' -interaction=nonstopmode' + let s:makeprg=current_compiler .. ' -interaction=nonstopmode' + execute 'CompilerSet makeprg=' .. escape(s:makeprg, ' ') else let current_compiler = 'make' endif diff --git a/runtime/compiler/tidy.vim b/runtime/compiler/tidy.vim index 3f8e68ebf2..9e72207862 100644 --- a/runtime/compiler/tidy.vim +++ b/runtime/compiler/tidy.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: HTML Tidy " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2020 Sep 4 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "tidy" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/ts-node.vim b/runtime/compiler/ts-node.vim index 14f0ea790c..1b46d3bf5a 100644 --- a/runtime/compiler/ts-node.vim +++ b/runtime/compiler/ts-node.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: TypeScript Runner " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2020 Feb 10 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "node" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/tsc.vim b/runtime/compiler/tsc.vim index a246fc7751..76f525baa6 100644 --- a/runtime/compiler/tsc.vim +++ b/runtime/compiler/tsc.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: TypeScript Compiler " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2020 Feb 10 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "tsc" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/typedoc.vim b/runtime/compiler/typedoc.vim index 3be06f3d4e..7a152e85fd 100644 --- a/runtime/compiler/typedoc.vim +++ b/runtime/compiler/typedoc.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: TypeDoc " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2020 Feb 10 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "typedoc" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/vimdoc.vim b/runtime/compiler/vimdoc.vim new file mode 100644 index 0000000000..a30355f855 --- /dev/null +++ b/runtime/compiler/vimdoc.vim @@ -0,0 +1,20 @@ +" Vim Compiler File +" Language: vimdoc +" Maintainer: Wu, Zhenyu <wuzhenyu@ustc.edu> +" Latest Revision: 2024-04-13 +" +" If you can not find 'vimdoc' in the package manager of your distribution e.g +" 'pip', then you may need to build it from its source. + +if exists('b:current_compiler') + finish +endif +let b:current_compiler = 'vimdoc' + +let s:save_cpoptions = &cpoptions +set cpoptions&vim + +CompilerSet makeprg=vimdoc + +let &cpoptions = s:save_cpoptions +unlet s:save_cpoptions diff --git a/runtime/compiler/xbuild.vim b/runtime/compiler/xbuild.vim index b508a4616a..42c7c65f53 100644 --- a/runtime/compiler/xbuild.vim +++ b/runtime/compiler/xbuild.vim @@ -2,6 +2,7 @@ " Compiler: Mono C# " Maintainer: Chiel ten Brinke (ctje92@gmail.com) " Last Change: 2013 May 13 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish @@ -11,10 +12,6 @@ let current_compiler = "xbuild" let s:keepcpo= &cpo set cpo&vim -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet errorformat=\ %#%f(%l\\\,%c):\ %m CompilerSet makeprg=xbuild\ /nologo\ /v:q\ /property:GenerateFullPaths=true diff --git a/runtime/compiler/xmllint.vim b/runtime/compiler/xmllint.vim index 79d38b4d14..16eebb45ce 100644 --- a/runtime/compiler/xmllint.vim +++ b/runtime/compiler/xmllint.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: Libxml2 Command-Line Tool " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2020 Jul 30 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "xmllint" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/xmlwf.vim b/runtime/compiler/xmlwf.vim index 3de9d08d55..2e38ca4aba 100644 --- a/runtime/compiler/xmlwf.vim +++ b/runtime/compiler/xmlwf.vim @@ -2,6 +2,7 @@ " Compiler: xmlwf " Maintainer: Robert Rowsome <rowsome@wam.umd.edu> " Last Change: 2019 Jul 23 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish @@ -11,10 +12,6 @@ let current_compiler = "xmlwf" let s:cpo_save = &cpo set cpo&vim -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet makeprg=xmlwf\ %:S CompilerSet errorformat=%f:%l%c:%m diff --git a/runtime/compiler/xo.vim b/runtime/compiler/xo.vim index 525657d4bb..74804ca6d0 100644 --- a/runtime/compiler/xo.vim +++ b/runtime/compiler/xo.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: XO " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2019 Jul 10 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "xo" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/compiler/yamllint.vim b/runtime/compiler/yamllint.vim index 889b04b63c..88e2efb27a 100644 --- a/runtime/compiler/yamllint.vim +++ b/runtime/compiler/yamllint.vim @@ -2,15 +2,12 @@ " Compiler: Yamllint for YAML " Maintainer: Romain Lafourcade <romainlafourcade@gmail.com> " Last Change: 2021 July 21 +" 2024 Apr 03 by The Vim Project (removed :CompilerSet definition) if exists("current_compiler") finish endif let current_compiler = "yamllint" -if exists(":CompilerSet") != 2 - command -nargs=* CompilerSet setlocal <args> -endif - CompilerSet makeprg=yamllint\ -f\ parsable diff --git a/runtime/compiler/zig.vim b/runtime/compiler/zig.vim index 2cc6831329..44014a3775 100644 --- a/runtime/compiler/zig.vim +++ b/runtime/compiler/zig.vim @@ -10,10 +10,6 @@ let current_compiler = "zig" let s:save_cpo = &cpo set cpo&vim -if exists(":CompilerSet") != 2 - command -nargs=* CompilerSet setlocal <args> -endif - " a subcommand must be provided for the this compiler (test, build-exe, etc) if has('patch-7.4.191') CompilerSet makeprg=zig\ \$*\ \%:S diff --git a/runtime/compiler/zig_build.vim b/runtime/compiler/zig_build.vim index 0441267b64..5a61c9f423 100644 --- a/runtime/compiler/zig_build.vim +++ b/runtime/compiler/zig_build.vim @@ -1,6 +1,7 @@ " Vim compiler file " Compiler: Zig Compiler (zig build) " Upstream: https://github.com/ziglang/zig.vim +" Last Change: 2024 Apr 05 by The Vim Project (removed :CompilerSet definition) if exists('current_compiler') finish @@ -11,11 +12,6 @@ let current_compiler = 'zig_build' let s:save_cpo = &cpo set cpo&vim - -if exists(':CompilerSet') != 2 - command -nargs=* CompilerSet setlocal <args> -endif - if exists('g:zig_build_makeprg_params') execute 'CompilerSet makeprg=zig\ build\ '.escape(g:zig_build_makeprg_params, ' \|"').'\ $*' else diff --git a/runtime/compiler/zig_build_exe.vim b/runtime/compiler/zig_build_exe.vim index 20f0bb3366..259d0e267b 100644 --- a/runtime/compiler/zig_build_exe.vim +++ b/runtime/compiler/zig_build_exe.vim @@ -1,6 +1,7 @@ " Vim compiler file " Compiler: Zig Compiler (zig build-exe) " Upstream: https://github.com/ziglang/zig.vim +" Last Change: 2024 Apr 05 by The Vim Project (removed :CompilerSet definition) if exists('current_compiler') finish @@ -11,11 +12,6 @@ let current_compiler = 'zig_build_exe' let s:save_cpo = &cpo set cpo&vim - -if exists(':CompilerSet') != 2 - command -nargs=* CompilerSet setlocal <args> -endif - if has('patch-7.4.191') CompilerSet makeprg=zig\ build-exe\ \%:S\ \$* else diff --git a/runtime/compiler/zig_test.vim b/runtime/compiler/zig_test.vim index a82d2a6378..dafeb6f1e3 100644 --- a/runtime/compiler/zig_test.vim +++ b/runtime/compiler/zig_test.vim @@ -1,6 +1,7 @@ " Vim compiler file " Compiler: Zig Compiler (zig test) " Upstream: https://github.com/ziglang/zig.vim +" Last Change: 2024 Apr 05 by The Vim Project (removed :CompilerSet definition) if exists('current_compiler') finish @@ -11,11 +12,6 @@ let current_compiler = 'zig_test' let s:save_cpo = &cpo set cpo&vim - -if exists(':CompilerSet') != 2 - command -nargs=* CompilerSet setlocal <args> -endif - if has('patch-7.4.191') CompilerSet makeprg=zig\ test\ \%:S\ \$* else diff --git a/runtime/compiler/zsh.vim b/runtime/compiler/zsh.vim index 5703c1fc44..bd195582c1 100644 --- a/runtime/compiler/zsh.vim +++ b/runtime/compiler/zsh.vim @@ -1,17 +1,13 @@ " Vim compiler file " Compiler: Zsh " Maintainer: Doug Kearns <dougkearns@gmail.com> -" Last Change: 2020 Sep 6 +" Last Change: 2024 Apr 03 if exists("current_compiler") finish endif let current_compiler = "zsh" -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal <args> -endif - let s:cpo_save = &cpo set cpo&vim diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index 87269ad147..2aa147770d 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -112,7 +112,11 @@ Basic types ~ Dictionary (msgpack: map) Object < - Note: empty Array is accepted as a valid argument for Dictionary parameter. + Note: + - Empty Array is accepted as a valid Dictionary parameter. + - Functions cannot cross RPC boundaries. But API functions (e.g. + |nvim_create_autocmd()|) may support Lua function parameters for non-RPC + invocations. Special types (msgpack EXT) ~ @@ -504,8 +508,9 @@ Extended marks (extmarks) represent buffer annotations that track text changes in the buffer. They can represent cursors, folds, misspelled words, anything that needs to track a logical location in the buffer over time. |api-indexing| -Extmark position works like "bar" cursor: it exists between characters. Thus, -the maximum extmark index on a line is 1 more than the character index: > +Extmark position works like a "vertical bar" cursor: it exists between +characters. Thus, the maximum extmark index on a line is 1 more than the +character index: > f o o b a r line contents 0 1 2 3 4 5 character positions (0-based) @@ -579,109 +584,6 @@ created for extmark changes. ============================================================================== Global Functions *api-global* -nvim__get_runtime({pat}, {all}, {opts}) *nvim__get_runtime()* - Find files in runtime directories - - Attributes: ~ - |api-fast| - - Parameters: ~ - • {pat} pattern of files to search for - • {all} whether to return all matches or only the first - • {opts} is_lua: only search Lua subdirs - - Return: ~ - list of absolute paths to the found files - -nvim__id({obj}) *nvim__id()* - Returns object given as argument. - - This API function is used for testing. One should not rely on its presence - in plugins. - - Parameters: ~ - • {obj} Object to return. - - Return: ~ - its argument. - -nvim__id_array({arr}) *nvim__id_array()* - Returns array given as argument. - - This API function is used for testing. One should not rely on its presence - in plugins. - - Parameters: ~ - • {arr} Array to return. - - Return: ~ - its argument. - -nvim__id_dictionary({dct}) *nvim__id_dictionary()* - Returns dictionary given as argument. - - This API function is used for testing. One should not rely on its presence - in plugins. - - Parameters: ~ - • {dct} Dictionary to return. - - Return: ~ - its argument. - -nvim__id_float({flt}) *nvim__id_float()* - Returns floating-point value given as argument. - - This API function is used for testing. One should not rely on its presence - in plugins. - - Parameters: ~ - • {flt} Value to return. - - Return: ~ - its argument. - -nvim__inspect_cell({grid}, {row}, {col}) *nvim__inspect_cell()* - NB: if your UI doesn't use hlstate, this will not return hlstate first - time. - -nvim__invalidate_glyph_cache() *nvim__invalidate_glyph_cache()* - For testing. The condition in schar_cache_clear_if_full is hard to reach, - so this function can be used to force a cache clear in a test. - -nvim__stats() *nvim__stats()* - Gets internal stats. - - Return: ~ - Map of various internal stats. - -nvim_call_atomic({calls}) *nvim_call_atomic()* - Calls many API methods atomically. - - This has two main usages: - 1. To perform several requests from an async context atomically, i.e. - without interleaving redraws, RPC requests from other clients, or user - interactions (however API methods may trigger autocommands or event - processing which have such side effects, e.g. |:sleep| may wake - timers). - 2. To minimize RPC overhead (roundtrips) of a sequence of many requests. - - Attributes: ~ - |RPC| only - - Parameters: ~ - • {calls} an array of calls, where each call is described by an array - with two elements: the request name, and an array of - arguments. - - Return: ~ - Array of two elements. The first is an array of return values. The - second is NIL if all calls succeeded. If a call resulted in an error, - it is a three-element array with the zero-based index of the call - which resulted in an error, the error type and the error message. If - an error occurred, the values from all preceding calls will still be - returned. - nvim_chan_send({chan}, {data}) *nvim_chan_send()* Send data to channel `id`. For a job, it writes it to the stdin of the process. For the stdio channel |channel-stdio|, it writes to Nvim's @@ -700,21 +602,6 @@ nvim_chan_send({chan}, {data}) *nvim_chan_send()* • {chan} id of the channel • {data} data to write. 8-bit clean: can contain NUL bytes. -nvim_complete_set({index}, {opts}) *nvim_complete_set()* - Set info for the completion candidate index. if the info was shown in a - window, then the window and buffer ids are returned for further - customization. If the text was not shown, an empty dict is returned. - - Parameters: ~ - • {index} the completion candidate index - • {opts} Optional parameters. - • info: (string) info text. - - Return: ~ - Dictionary containing these keys: - • winid: (number) floating window id - • bufnr: (number) buffer id in floating window - nvim_create_buf({listed}, {scratch}) *nvim_create_buf()* Creates a new, empty, unnamed buffer. @@ -1574,23 +1461,127 @@ nvim_strwidth({text}) *nvim_strwidth()* Return: ~ Number of cells -nvim_subscribe({event}) *nvim_subscribe()* - Subscribes to event broadcasts. +nvim__complete_set({index}, {opts}) *nvim__complete_set()* + EXPERIMENTAL: this API may change in the future. - Attributes: ~ - |RPC| only + Sets info for the completion item at the given index. If the info text was + shown in a window, returns the window and buffer ids, or empty dict if not + shown. Parameters: ~ - • {event} Event type string + • {index} Completion candidate index + • {opts} Optional parameters. + • info: (string) info text. + + Return: ~ + Dictionary containing these keys: + • winid: (number) floating window id + • bufnr: (number) buffer id in floating window -nvim_unsubscribe({event}) *nvim_unsubscribe()* - Unsubscribes to event broadcasts. +nvim__get_runtime({pat}, {all}, {opts}) *nvim__get_runtime()* + Find files in runtime directories Attributes: ~ - |RPC| only + |api-fast| + + Parameters: ~ + • {pat} pattern of files to search for + • {all} whether to return all matches or only the first + • {opts} is_lua: only search Lua subdirs + + Return: ~ + list of absolute paths to the found files + +nvim__id({obj}) *nvim__id()* + Returns object given as argument. + + This API function is used for testing. One should not rely on its presence + in plugins. + + Parameters: ~ + • {obj} Object to return. + + Return: ~ + its argument. + +nvim__id_array({arr}) *nvim__id_array()* + Returns array given as argument. + + This API function is used for testing. One should not rely on its presence + in plugins. + + Parameters: ~ + • {arr} Array to return. + + Return: ~ + its argument. + +nvim__id_dictionary({dct}) *nvim__id_dictionary()* + Returns dictionary given as argument. + + This API function is used for testing. One should not rely on its presence + in plugins. + + Parameters: ~ + • {dct} Dictionary to return. + + Return: ~ + its argument. + +nvim__id_float({flt}) *nvim__id_float()* + Returns floating-point value given as argument. + + This API function is used for testing. One should not rely on its presence + in plugins. + + Parameters: ~ + • {flt} Value to return. + + Return: ~ + its argument. + +nvim__inspect_cell({grid}, {row}, {col}) *nvim__inspect_cell()* + NB: if your UI doesn't use hlstate, this will not return hlstate first + time. + +nvim__invalidate_glyph_cache() *nvim__invalidate_glyph_cache()* + For testing. The condition in schar_cache_clear_if_full is hard to reach, + so this function can be used to force a cache clear in a test. + +nvim__redraw({opts}) *nvim__redraw()* + EXPERIMENTAL: this API may change in the future. + + Instruct Nvim to redraw various components. Parameters: ~ - • {event} Event type string + • {opts} Optional parameters. + • win: Target a specific |window-ID| as described below. + • buf: Target a specific buffer number as described below. + • flush: Update the screen with pending updates. + • valid: When present mark `win`, `buf`, or all windows for + redraw. When `true`, only redraw changed lines (useful for + decoration providers). When `false`, forcefully redraw. + • range: Redraw a range in `buf`, the buffer in `win` or the + current buffer (useful for decoration providers). Expects a + tuple `[first, last]` with the first and last line number of + the range, 0-based end-exclusive |api-indexing|. + • cursor: Immediately update cursor position on the screen in + `win` or the current window. + • statuscolumn: Redraw the 'statuscolumn' in `buf`, `win` or + all windows. + • statusline: Redraw the 'statusline' in `buf`, `win` or all + windows. + • winbar: Redraw the 'winbar' in `buf`, `win` or all windows. + • tabline: Redraw the 'tabline'. + + See also: ~ + • |:redraw| + +nvim__stats() *nvim__stats()* + Gets internal stats. + + Return: ~ + Map of various internal stats. ============================================================================== @@ -2447,7 +2438,7 @@ nvim_buf_set_mark({buffer}, {name}, {line}, {col}, {opts}) • |nvim_buf_get_mark()| nvim_buf_set_name({buffer}, {name}) *nvim_buf_set_name()* - Sets the full file name for a buffer + Sets the full file name for a buffer, like |:file_f| Parameters: ~ • {buffer} Buffer handle, or 0 for current buffer @@ -2767,8 +2758,8 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {opts}) • url: A URL to associate with this extmark. In the TUI, the OSC 8 control sequence is used to generate a clickable hyperlink to this URL. - • scoped: boolean that indicates that the extmark should - only be displayed in the namespace scope. (experimental) + • scoped: boolean (EXPERIMENTAL) enables "scoping" for the + extmark. See |nvim__win_add_ns()| Return: ~ Id of the created/updated extmark @@ -2850,34 +2841,41 @@ nvim_set_decoration_provider({ns_id}, {opts}) ["end", tick] < -nvim_win_add_ns({window}, {ns_id}) *nvim_win_add_ns()* - Adds the namespace scope to the window. +nvim__win_add_ns({window}, {ns_id}) *nvim__win_add_ns()* + EXPERIMENTAL: this API will change in the future. + + Scopes a namespace to the a window, so extmarks in the namespace will be + active only in the given window. Parameters: ~ • {window} Window handle, or 0 for current window - • {ns_id} the namespace to add + • {ns_id} Namespace Return: ~ true if the namespace was added, else false -nvim_win_get_ns({window}) *nvim_win_get_ns()* - Gets all the namespaces scopes associated with a window. +nvim__win_del_ns({window}, {ns_id}) *nvim__win_del_ns()* + EXPERIMENTAL: this API will change in the future. + + Unscopes a namespace (un-binds it from the given scope). Parameters: ~ • {window} Window handle, or 0 for current window + • {ns_id} the namespace to remove Return: ~ - a list of namespaces ids + true if the namespace was removed, else false + +nvim__win_get_ns({window}) *nvim__win_get_ns()* + EXPERIMENTAL: this API will change in the future. -nvim_win_remove_ns({window}, {ns_id}) *nvim_win_remove_ns()* - Removes the namespace scope from the window. + Gets the namespace scopes for a given window. Parameters: ~ • {window} Window handle, or 0 for current window - • {ns_id} the namespace to remove Return: ~ - true if the namespace was removed, else false + a list of namespaces ids ============================================================================== @@ -3271,9 +3269,8 @@ nvim_open_win({buffer}, {enter}, {config}) *nvim_open_win()* • footer_pos: Footer position. Must be set with `footer` option. Value can be one of "left", "center", or "right". Default is `"left"`. - • noautocmd: If true then no buffer-related autocommand - events such as |BufEnter|, |BufLeave| or |BufWinEnter| may - fire from calling this function. + • noautocmd: If true then all autocommands are blocked for + the duration of the call. • fixed: If true when anchor is NW or SW, the float window would be kept fixed even if the window would be truncated. • hide: If true the floating window will be hidden. @@ -3297,11 +3294,11 @@ nvim_win_get_config({window}) *nvim_win_get_config()* Map defining the window configuration, see |nvim_open_win()| nvim_win_set_config({window}, {config}) *nvim_win_set_config()* - Configures window layout. Currently only for floating and external windows - (including changing a split window to those layouts). + Configures window layout. Cannot be used to move the last window in a + tabpage to a different one. - When reconfiguring a floating window, absent option keys will not be - changed. `row`/`col` and `relative` must be reconfigured together. + When reconfiguring a window, absent option keys will not be changed. + `row`/`col` and `relative` must be reconfigured together. Parameters: ~ • {window} Window handle, or 0 for current window @@ -3475,7 +3472,8 @@ nvim_create_autocmd({event}, {opts}) *nvim_create_autocmd()* Vimscript function name, if string) called when the event(s) is triggered. Lua callback can return a truthy value (not `false` or `nil`) to delete the autocommand. - Receives a table argument with these keys: + Receives one argument, a table with these keys: + *event-args* • id: (number) autocommand id • event: (string) name of the triggered event |autocmd-events| @@ -3484,7 +3482,7 @@ nvim_create_autocmd({event}, {opts}) *nvim_create_autocmd()* • buf: (number) expanded value of <abuf> • file: (string) expanded value of <afile> • data: (any) arbitrary data passed from - |nvim_exec_autocmds()| + |nvim_exec_autocmds()| *event-data* • command (string) optional: Vim command to execute on event. Cannot be used with {callback} • once (boolean) optional: defaults to false. Run the diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt index 8890872e1a..ca816851dd 100644 --- a/runtime/doc/autocmd.txt +++ b/runtime/doc/autocmd.txt @@ -466,6 +466,16 @@ CompleteDone After Insert mode completion is done. Either CompleteDonePre if you need it. |v:completed_item| gives the completed item. + Sets these |v:event| keys: + reason Reason for completion being + done. Can be one of: + - "accept": completion was + accepted using |complete_CTRL-Y|. + - "cancel": completion was cancelled + using |complete_CTRL-E|, pressing + a non-keyword character, or + triggering a new completion. + *CursorHold* CursorHold When the user doesn't press a key for the time specified with 'updatetime'. Not triggered @@ -884,6 +894,9 @@ SafeState When nothing is pending, going to wait for the *SessionLoadPost* SessionLoadPost After loading the session file created using the |:mksession| command. + *SessionWritePost* +SessionWritePost After writing a session file by calling + the |:mksession| command. *ShellCmdPost* ShellCmdPost After executing a shell command with |:!cmd|, |:make| and |:grep|. Can be used to check for @@ -900,18 +913,18 @@ ShellFilterPost After executing a shell command with ":{range}!cmd", ":w !cmd" or ":r !cmd". Can be used to check for any changed files. *SourcePre* -SourcePre Before sourcing a vim/lua file. |:source| +SourcePre Before sourcing a Vimscript/Lua file. |:source| <afile> is the name of the file being sourced. *SourcePost* -SourcePost After sourcing a vim/lua file. |:source| +SourcePost After sourcing a Vimscript/Lua file. |:source| <afile> is the name of the file being sourced. Not triggered when sourcing was interrupted. Also triggered after a SourceCmd autocommand was triggered. *SourceCmd* -SourceCmd When sourcing a vim/lua file. |:source| +SourceCmd When sourcing a Vimscript/Lua file. |:source| <afile> is the name of the file being sourced. - The autocommand must source this file. + The autocommand must source that file. |Cmd-event| *SpellFileMissing* SpellFileMissing When trying to load a spell checking file and @@ -986,18 +999,16 @@ TermClose When a |terminal| job ends. Sets these |v:event| keys: status *TermRequest* -TermRequest When a |terminal| job emits an OSC or DCS - sequence. Sets |v:termrequest|. When used from - Lua, the request string is included in the - "data" field of the autocommand callback. +TermRequest When a |:terminal| child process emits an OSC + or DCS sequence. Sets |v:termrequest|. The + |event-data| is the request string. *TermResponse* TermResponse When Nvim receives an OSC or DCS response from - the terminal. Sets |v:termresponse|. When used - from Lua, the response string is included in - the "data" field of the autocommand callback. - May be triggered halfway through another event - (file I/O, a shell command, or anything else - that takes time). Example: >lua + the host terminal. Sets |v:termresponse|. The + |event-data| is the response string. May be + triggered during another event (file I/O, + a shell command, or anything else that takes + time). Example: >lua -- Query the terminal palette for the RGB value of color 1 -- (red) using OSC 4 diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index c5f3946871..ff7d5f9ce8 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -1268,7 +1268,6 @@ executable({expr}) *executable()* The result is a Number: 1 exists 0 does not exist - -1 not implemented on this system |exepath()| can be used to get the full path of an executable. execute({command} [, {silent}]) *execute()* @@ -1588,6 +1587,7 @@ feedkeys({string} [, {mode}]) *feedkeys()* 't' Handle keys as if typed; otherwise they are handled as if coming from a mapping. This matters for undo, opening folds, etc. + 'L' Lowlevel input. Other flags are not used. 'i' Insert the string instead of appending (see above). 'x' Execute commands until typeahead is empty. This is similar to using ":normal!". You can call feedkeys() @@ -2196,16 +2196,16 @@ getchangelist([{buf}]) *getchangelist()* position refers to the position in the list. For other buffers, it is set to the length of the list. -getchar([expr]) *getchar()* +getchar([{expr}]) *getchar()* Get a single character from the user or input stream. - If [expr] is omitted, wait until a character is available. - If [expr] is 0, only get a character when one is available. + If {expr} is omitted, wait until a character is available. + If {expr} is 0, only get a character when one is available. Return zero otherwise. - If [expr] is 1, only check if a character is available, it is + If {expr} is 1, only check if a character is available, it is not consumed. Return zero if no character available. If you prefer always getting a string use |getcharstr()|. - Without [expr] and when [expr] is 0 a whole character or + Without {expr} and when {expr} is 0 a whole character or special key is returned. If it is a single character, the result is a Number. Use |nr2char()| to convert it to a String. Otherwise a String is returned with the encoded character. @@ -2215,11 +2215,11 @@ getchar([expr]) *getchar()* also a String when a modifier (shift, control, alt) was used that is not included in the character. - When [expr] is 0 and Esc is typed, there will be a short delay + When {expr} is 0 and Esc is typed, there will be a short delay while Vim waits to see if this is the start of an escape sequence. - When [expr] is 1 only the first byte is returned. For a + When {expr} is 1 only the first byte is returned. For a one-byte character it is the character itself as a number. Use nr2char() to convert it to a String. @@ -2311,13 +2311,13 @@ getcharsearch() *getcharsearch()* nnoremap <expr> , getcharsearch().forward ? ',' : ';' < Also see |setcharsearch()|. -getcharstr([expr]) *getcharstr()* +getcharstr([{expr}]) *getcharstr()* Get a single character from the user or input stream as a string. - If [expr] is omitted, wait until a character is available. - If [expr] is 0 or false, only get a character when one is + If {expr} is omitted, wait until a character is available. + If {expr} is 0 or false, only get a character when one is available. Return an empty string otherwise. - If [expr] is 1 or true, only check if a character is + If {expr} is 1 or true, only check if a character is available, it is not consumed. Return an empty string if no character is available. Otherwise this works like |getchar()|, except that a number @@ -2969,6 +2969,38 @@ getregion({pos1}, {pos2} [, {opts}]) *getregion()* \ getpos('v'), getpos('.'), #{ type: mode() })<CR> < +getregionpos({pos1}, {pos2} [, {opts}]) *getregionpos()* + Same as |getregion()|, but returns a list of positions + describing the buffer text segments bound by {pos1} and + {pos2}. + The segments are a pair of positions for every line: > + [[{start_pos}, {end_pos}], ...] +< + The position is a |List| with four numbers: + [bufnum, lnum, col, off] + "bufnum" is the buffer number. + "lnum" and "col" are the position in the buffer. The first + column is 1. + If the "off" number of a starting position is non-zero, it is + the offset in screen columns from the start of the character. + E.g., a position within a <Tab> or after the last character. + If the "off" number of an ending position is non-zero, it is + the offset of the character's first cell not included in the + selection, otherwise all its cells are included. + + Apart from the options supported by |getregion()|, {opts} also + supports the following: + + eol If |TRUE|, indicate positions beyond + the end of a line with "col" values + one more than the length of the line. + If |FALSE|, positions are limited + within their lines, and if a line is + empty or the selection is entirely + beyond the end of a line, a "col" + value of 0 is used for both positions. + (default: |FALSE|) + getregtype([{regname}]) *getregtype()* The result is a String, which is type of register {regname}. The value will be one of: @@ -3014,7 +3046,7 @@ getscriptinfo([{opts}]) *getscriptinfo()* Examples: >vim echo getscriptinfo({'name': 'myscript'}) - echo getscriptinfo({'sid': 15}).variables + echo getscriptinfo({'sid': 15})[0].variables < gettabinfo([{tabnr}]) *gettabinfo()* @@ -4981,9 +5013,9 @@ mkdir({name} [, {flags} [, {prot}]]) *mkdir()* *E73 successful or FALSE if the directory creation failed or partly failed. -mode([expr]) *mode()* +mode([{expr}]) *mode()* Return a string that indicates the current mode. - If [expr] is supplied and it evaluates to a non-zero Number or + If {expr} is supplied and it evaluates to a non-zero Number or a non-empty String (|non-zero-arg|), then the full mode is returned, otherwise only the first letter is returned. Also see |state()|. @@ -5486,6 +5518,9 @@ printf({fmt}, {expr1} ...) *printf()* echo printf("%1$*2$.*3$f", 1.4142135, 6, 2) < 1.41 + You will get an overflow error |E1510|, when the field-width + or precision will result in a string longer than 6400 chars. + *E1500* You cannot mix positional and non-positional arguments: >vim echo printf("%s%1$s", "One", "Two") @@ -6054,6 +6089,7 @@ search({pattern} [, {flags} [, {stopline} [, {timeout} [, {skip}]]]]) *search()* When a match has been found its line number is returned. If there is no match a 0 is returned and the cursor doesn't move. No error message is given. + To get the matched string, use |matchbufline()|. {flags} is a String, which can contain these character flags: 'b' search Backward instead of forward @@ -6958,10 +6994,11 @@ shellescape({string} [, {special}]) *shellescape()* Otherwise encloses {string} in single-quotes and replaces all "'" with "'\''". - If {special} is a |non-zero-arg|: - - Special items such as "!", "%", "#" and "<cword>" will be - preceded by a backslash. The backslash will be removed again - by the |:!| command. + The {special} argument adds additional escaping of keywords + used in Vim commands. If it is a |non-zero-arg|: + - Special items such as "!", "%", "#" and "<cword>" (as listed + in |expand()|) will be preceded by a backslash. + The backslash will be removed again by the |:!| command. - The <NL> character is escaped. If 'shell' contains "csh" in the tail: @@ -7407,7 +7444,8 @@ slice({expr}, {start} [, {end}]) *slice()* Similar to using a |slice| "expr[start : end]", but "end" is used exclusive. And for a string the indexes are used as character indexes instead of byte indexes. - Also, composing characters are not counted. + Also, composing characters are treated as a part of the + preceding base character. When {end} is omitted the slice continues to the last item. When {end} is -1 the last item is omitted. Returns an empty value if {start} or {end} are invalid. @@ -7754,8 +7792,8 @@ strcharpart({src}, {start} [, {len} [, {skipcc}]]) *strcharpart()* of byte index and length. When {skipcc} is omitted or zero, composing characters are counted separately. - When {skipcc} set to 1, Composing characters are ignored, - similar to |slice()|. + When {skipcc} set to 1, composing characters are treated as a + part of the preceding base character, similar to |slice()|. When a character index is used where a character does not exist it is omitted and counted as one character. For example: >vim @@ -7769,7 +7807,7 @@ strchars({string} [, {skipcc}]) *strchars()* in String {string}. When {skipcc} is omitted or zero, composing characters are counted separately. - When {skipcc} set to 1, Composing characters are ignored. + When {skipcc} set to 1, composing characters are ignored. |strcharlen()| always does this. Returns zero on error. @@ -7871,10 +7909,10 @@ string({expr}) *string()* for infinite and NaN floating-point values representations which use |str2float()|. Strings are also dumped literally, only single quote is escaped, which does not allow using YAML - for parsing back binary strings. |eval()| should always work for - strings and floats though and this is the only official - method, use |msgpackdump()| or |json_encode()| if you need to - share data with other application. + for parsing back binary strings. |eval()| should always work + for strings and floats though, and this is the only official + method. Use |msgpackdump()| or |json_encode()| if you need to + share data with other applications. strlen({string}) *strlen()* The result is a Number, which is the length of the String @@ -8203,6 +8241,10 @@ synconcealed({lnum}, {col}) *synconcealed()* synconcealed(lnum, 5) [1, 'X', 2] synconcealed(lnum, 6) [0, '', 0] + Note: Doesn't consider |matchadd()| highlighting items, + since syntax and matching highlighting are two different + mechanisms |syntax-vs-match|. + synstack({lnum}, {col}) *synstack()* Return a |List|, which is the stack of syntax items at the position {lnum} and {col} in the current window. {lnum} is @@ -8897,14 +8939,13 @@ win_screenpos({nr}) *win_screenpos()* [1, 1], unless there is a tabline, then it is [2, 1]. {nr} can be the window number or the |window-ID|. Use zero for the current window. - Returns [0, 0] if the window cannot be found in the current - tabpage. + Returns [0, 0] if the window cannot be found. win_splitmove({nr}, {target} [, {options}]) *win_splitmove()* - Move the window {nr} to a new split of the window {target}. - This is similar to moving to {target}, creating a new window - using |:split| but having the same contents as window {nr}, and - then closing {nr}. + Temporarily switch to window {target}, then move window {nr} + to a new split adjacent to {target}. + Unlike commands such as |:split|, no new windows are created + (the |window-ID| of window {nr} is unchanged after the move). Both {nr} and {target} can be window numbers or |window-ID|s. Both must be in the current tab page. @@ -9007,7 +9048,9 @@ winnr([{arg}]) *winnr()* # the number of the last accessed window (where |CTRL-W_p| goes to). If there is no previous window or it is in another tab page 0 is - returned. + returned. May refer to the current window in + some cases (e.g. when evaluating 'statusline' + expressions). {N}j the number of the Nth window below the current window (where |CTRL-W_j| goes to). {N}k the number of the Nth window above the current diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt index 703addf51a..9ff16165d7 100644 --- a/runtime/doc/change.txt +++ b/runtime/doc/change.txt @@ -281,6 +281,13 @@ gr{char} Replace the virtual characters under the cursor with that have a special meaning in Insert mode, such as most CTRL-keys, cannot be used. + *gr-default* + Nvim creates default mappings with "gr" as a prefix, + which may inhibit the behavior of |gr|. Use the + following to restore the builtin behavior: > + nnoremap <nowait> gr gr +< + *digraph-arg* The argument for Normal mode commands like |r| and |t| is a single character. When 'cpo' doesn't contain the 'D' flag, this character can also be entered @@ -1291,8 +1298,8 @@ expression (like with the "/" command). The expression must evaluate to a String. A Number is always automatically converted to a String. For the "p" and ":put" command, if the result is a Float it's converted into a String. If the result is a List each element is -turned into a String and used as a line. A Dictionary or FuncRef results in -an error message (use string() to convert). +turned into a String and used as a line. A Dictionary is converted into a +String. A Funcref results in an error message (use string() to convert). If the "= register is used for the "p" command, the String is split up at <NL> characters. If the String ends in a <NL>, it is regarded as a linewise diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt index 57a4223c53..f306067a9c 100644 --- a/runtime/doc/cmdline.txt +++ b/runtime/doc/cmdline.txt @@ -274,14 +274,6 @@ CTRL-P command-line completion (see |cmdline-completion|) CTRL-A command-line completion (see |cmdline-completion|) CTRL-L command-line completion (see |cmdline-completion|) - *c_CTRL-_* -CTRL-_ Switch between Hebrew and English keyboard mode, which is - private to the command-line and not related to hkmap. - This is useful when Hebrew text entry is required in the - command-line, searches, abbreviations, etc. Applies only if - the 'allowrevins' option is set. - See |rileft.txt|. - *c_CTRL-^* CTRL-^ Toggle the use of language |:lmap| mappings and/or Input Method. diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt index 5ac4ad4ce2..646ba72bd8 100644 --- a/runtime/doc/deprecated.txt +++ b/runtime/doc/deprecated.txt @@ -12,21 +12,112 @@ They should not be used in new scripts, and old scripts should be updated. ============================================================================== Deprecated features +------------------------------------------------------------------------------ +DEPRECATED IN 0.11 *deprecated-0.11* + +API +- nvim_subscribe() Plugins must maintain their own "multicast" channels list. +- nvim_unsubscribe() Plugins must maintain their own "multicast" channels list. + + +------------------------------------------------------------------------------ +DEPRECATED IN 0.10 *deprecated-0.10* + +API +• *nvim_buf_get_option()* Use |nvim_get_option_value()| instead. +• *nvim_buf_set_option()* Use |nvim_set_option_value()| instead. +• *nvim_call_atomic()* Use |nvim_exec_lua()| instead. +• *nvim_get_option()* Use |nvim_get_option_value()| instead. +• *nvim_set_option()* Use |nvim_set_option_value()| instead. +• *nvim_win_get_option()* Use |nvim_get_option_value()| instead. +• *nvim_win_set_option()* Use |nvim_set_option_value()| instead. + +CHECKHEALTH +• *health#report_error* *vim.health.report_error()* Use |vim.health.error()| instead. +• *health#report_info* *vim.health.report_info()* Use |vim.health.info()| instead. +• *health#report_ok* *vim.health.report_ok()* Use |vim.health.ok()| instead. +• *health#report_start* *vim.health.report_start()* Use |vim.health.start()| instead. +• *health#report_warn* *vim.health.report_warn()* Use |vim.health.warn()| instead. + +DIAGNOSTICS +• Configuring |diagnostic-signs| using |:sign-define| or |sign_define()|. Use + the "signs" key of |vim.diagnostic.config()| instead. +• vim.diagnostic functions: + • *vim.diagnostic.disable()* Use |vim.diagnostic.enable()| + • *vim.diagnostic.is_disabled()* Use |vim.diagnostic.is_enabled()| + • Legacy signature: `vim.diagnostic.enable(buf:number, namespace:number)` + +LSP +• *vim.lsp.util.get_progress_messages()* Use |vim.lsp.status()| instead. +• *vim.lsp.get_active_clients()* Use |vim.lsp.get_clients()| instead. +• *vim.lsp.for_each_buffer_client()* Use |vim.lsp.get_clients()| instead. +• *vim.lsp.util.trim_empty_lines()* Use |vim.split()| with `trimempty` instead. +• *vim.lsp.util.try_trim_markdown_code_blocks()* +• *vim.lsp.util.set_lines()* +• *vim.lsp.util.extract_completion_items()* +• *vim.lsp.util.parse_snippet()* +• *vim.lsp.util.text_document_completion_list_to_complete_items()* +• *vim.lsp.util.lookup_section()* Use |vim.tbl_get()| instead: > + local keys = vim.split(section, '.', { plain = true }) + local vim.tbl_get(table, unpack(keys)) + +LUA +• *vim.loop* Use |vim.uv| instead. +• *vim.tbl_add_reverse_lookup()* +• *vim.tbl_flatten()* Use |Iter:flatten()| instead. +• *vim.tbl_islist()* Use |vim.islist()| instead. + +OPTIONS +• The "term_background" UI option |ui-ext-options| is deprecated and no longer + populated. Background color detection is now performed in Lua by the Nvim + core, not the TUI. + +TREESITTER +• *LanguageTree:for_each_child()* Use |LanguageTree:children()| (non-recursive) instead. + + +------------------------------------------------------------------------------ +DEPRECATED IN 0.9 *deprecated-0.9* + +API +- *nvim_get_hl_by_name()* Use |nvim_get_hl()| instead. +- *nvim_get_hl_by_id()* Use |nvim_get_hl()| instead. + +TREESITTER +- *vim.treesitter.language.require_language()* Use |vim.treesitter.language.add()| instead. +- *vim.treesitter.get_node_at_pos()* Use |vim.treesitter.get_node()| instead. +- *vim.treesitter.get_node_at_cursor()* Use |vim.treesitter.get_node()| + and |TSNode:type()| instead. +• The following top level Treesitter functions have been moved: + - *vim.treesitter.inspect_language()* -> |vim.treesitter.language.inspect()| + - *vim.treesitter.get_query_files()* -> |vim.treesitter.query.get_files()| + - *vim.treesitter.set_query()* -> |vim.treesitter.query.set()| + - *vim.treesitter.query.set_query()* -> |vim.treesitter.query.set()| + - *vim.treesitter.get_query()* -> |vim.treesitter.query.get()| + - *vim.treesitter.query.get_query()* -> |vim.treesitter.query.get()| + - *vim.treesitter.parse_query()* -> |vim.treesitter.query.parse()| + - *vim.treesitter.query.parse_query()* -> |vim.treesitter.query.parse()| + - *vim.treesitter.add_predicate()* -> |vim.treesitter.query.add_predicate()| + - *vim.treesitter.add_directive()* -> |vim.treesitter.query.add_directive()| + - *vim.treesitter.list_predicates()* -> |vim.treesitter.query.list_predicates()| + - *vim.treesitter.list_directives()* -> |vim.treesitter.query.list_directives()| + - *vim.treesitter.query.get_range()* -> |vim.treesitter.get_range()| + - *vim.treesitter.query.get_node_text()* -> |vim.treesitter.get_node_text()| + +LUA + - *nvim_exec()* Use |nvim_exec2()| instead. + - *vim.pretty_print()* Use |vim.print()| instead. + + +------------------------------------------------------------------------------ +DEPRECATED IN 0.8 OR EARLIER + API - *nvim_buf_clear_highlight()* Use |nvim_buf_clear_namespace()| instead. - *nvim_buf_set_virtual_text()* Use |nvim_buf_set_extmark()| instead. - *nvim_command_output()* Use |nvim_exec2()| instead. - *nvim_execute_lua()* Use |nvim_exec_lua()| instead. -- *nvim_get_hl_by_name()* Use |nvim_get_hl()| instead. -- *nvim_get_hl_by_id()* Use |nvim_get_hl()| instead. -- *nvim_exec()* Use |nvim_exec2()| instead. - *nvim_get_option_info()* Use |nvim_get_option_info2()| instead. -- *nvim_buf_get_option()* Use |nvim_get_option_value()| instead. -- *nvim_buf_set_option()* Use |nvim_set_option_value()| instead. -- *nvim_get_option()* Use |nvim_get_option_value()| instead. -- *nvim_set_option()* Use |nvim_set_option_value()| instead. -- *nvim_win_get_option()* Use |nvim_get_option_value()| instead. -- *nvim_win_set_option()* Use |nvim_set_option_value()| instead. COMMANDS - *:rv* *:rviminfo* Deprecated alias to |:rshada| command. @@ -60,11 +151,6 @@ FUNCTIONS - *buffer_name()* Obsolete name for |bufname()|. - *buffer_number()* Obsolete name for |bufnr()|. - *file_readable()* Obsolete name for |filereadable()|. -- *health#report_error* *vim.health.report_error()* Use |vim.health.error()| instead. -- *health#report_info* *vim.health.report_info()* Use |vim.health.info()| instead. -- *health#report_ok* *vim.health.report_ok()* Use |vim.health.ok()| instead. -- *health#report_start* *vim.health.report_start()* Use |vim.health.start()| instead. -- *health#report_warn* *vim.health.report_warn()* Use |vim.health.warn()| instead. - *highlight_exists()* Obsolete name for |hlexists()|. - *highlightID()* Obsolete name for |hlID()|. - *inputdialog()* Use |input()| instead. @@ -85,7 +171,7 @@ For each of the functions below, use the corresponding function in |vim.diagnostic.get()| instead of |vim.lsp.diagnostic.get()|. - *vim.lsp.diagnostic.clear()* Use |vim.diagnostic.hide()| instead. -- *vim.lsp.diagnostic.disable()* +- *vim.lsp.diagnostic.disable()* Use |vim.diagnostic.enable()| instead. - *vim.lsp.diagnostic.display()* Use |vim.diagnostic.show()| instead. - *vim.lsp.diagnostic.enable()* - *vim.lsp.diagnostic.get()* @@ -140,36 +226,9 @@ LSP FUNCTIONS {async=false} instead. - *vim.lsp.buf.range_formatting()* Use |vim.lsp.formatexpr()| or |vim.lsp.buf.format()| instead. -- *vim.lsp.util.get_progress_messages()* Use |vim.lsp.status()| or access - `progress` of |vim.lsp.Client| -- *vim.lsp.get_active_clients()* Use |vim.lsp.get_clients()| -- *vim.lsp.for_each_buffer_client()* Use |vim.lsp.get_clients()| -- *vim.lsp.util.lookup_section()* Use |vim.tbl_get()| and - |vim.split()| with {plain=true} instead. -- *vim.lsp.util.trim_empty_lines()* Use |vim.split()| with `trimempty` instead. -- *vim.lsp.util.try_trim_markdown_code_blocks()* -- *vim.lsp.util.set_lines()* -- *vim.lsp.util.extract_completion_items()* -- *vim.lsp.util.parse_snippet()* -- *vim.lsp.util.text_document_completion_list_to_complete_items()* - -TREESITTER FUNCTIONS -- *vim.treesitter.language.require_language()* Use |vim.treesitter.language.add()| - instead. -- *vim.treesitter.get_node_at_pos()* Use |vim.treesitter.get_node()| - instead. -- *vim.treesitter.get_node_at_cursor()* Use |vim.treesitter.get_node()| - and |TSNode:type()| instead. -- *vim.treesitter.query.get_query()* Use |vim.treesitter.query.get()| - instead. -- *LanguageTree:for_each_child()* Use |LanguageTree:children()| - (non-recursive) instead. LUA - vim.register_keystroke_callback() Use |vim.on_key()| instead. -- *vim.pretty_print()* Use |vim.print()| instead. -- *vim.loop* Use |vim.uv| instead. -- *vim.tbl_add_reverse_lookup()* NORMAL COMMANDS - *]f* *[f* Same as "gf". @@ -211,8 +270,10 @@ UI EXTENSIONS by the Nvim core directly instead of the TUI. VARIABLES -- *b:terminal_job_pid* PID of the top-level process in a |:terminal|. - Use `jobpid(&channel)` instead. +- *b:terminal_job_pid* Use `jobpid(&channel)` instead. +- *b:terminal_job_id* Use `&channel` instead. To access in non-current buffer: + - Lua: `vim.bo[bufnr].channel` + - Vimscript: `getbufvar(bufnr, '&channel')` vim:noet:tw=78:ts=8:ft=help:norl: diff --git a/runtime/doc/dev_style.txt b/runtime/doc/dev_style.txt index 85aeddd425..6c805963a9 100644 --- a/runtime/doc/dev_style.txt +++ b/runtime/doc/dev_style.txt @@ -6,7 +6,7 @@ Nvim style guide *dev-style* -This is style guide for developers working on Nvim's source code. +Style guidelines for developers working Nvim's source code. License: CC-By 3.0 https://creativecommons.org/licenses/by/3.0/ diff --git a/runtime/doc/dev_theme.txt b/runtime/doc/dev_theme.txt index 29a2da0d90..532506abcb 100644 --- a/runtime/doc/dev_theme.txt +++ b/runtime/doc/dev_theme.txt @@ -4,9 +4,9 @@ NVIM REFERENCE MANUAL -Nvim theme style guide *dev-theme* +Nvim colorscheme guidelines *dev-theme* -This is style guide for developers working on Nvim's default color scheme. +Style guidelines for developing Nvim's default colorscheme. License: CC-By 3.0 https://creativecommons.org/licenses/by/3.0/ @@ -17,19 +17,15 @@ Design - Be "Neovim branded", i.e. have mostly "green-blue" feel plus one or two colors reserved for very occasional user attention. - - Be oriented for 'termguicolors' (true colors) while being extra minimal for 'notermguicolors' (16 colors) as fallback. - - Be accessible, i.e. have high enough contrast ratio (as defined in https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef). This means to have value at least 7 for |hl-Normal| and 4.5 for some common cases (|hl-Visual|, `Comment` with set 'cursorline', colored syntax, `Diff*`, |hl-Search|). - - Be suitable for dark and light backgrounds via exchange of dark and light palettes. - - Be usable, i.e. provide enough visual feedback for common objects. @@ -38,39 +34,29 @@ Palettes - There are two separate palettes: dark and light. They all contain the same set of colors exported as `NvimDark*` and `NvimLight*` colors respectively. - - The dark palette is used for background in the dark color scheme and for foreground in the light color scheme; and vice versa. This introduces recognizable visual system without too standing out. - - Actual computation of palettes should be done in a perceptually uniform color space. Oklch is a good choice. - - Each palette has the following colors (descriptions are for dark background; reverse for light one): - - Four shades of colored "cold" greys for general UI. - - Dark ones (from darkest to lightest) are reserved as background for |hl-NormalFloat| (considered as "black"), |hl-Normal| (background), |hl-CursorLine|, |hl-Visual|. - - Light ones (also from darkest to lightest) are reserved for `Comment`, |hl-StatusLine|/|hl-TabLine|, |hl-Normal| (foreground), and color considered as "white". - - Six colors to provide enough terminal colors: red, yellow, green, cyan, blue, magenta. They should have (reasonably) similar lightness and chroma to make them visually coherent. Lightness should be as equal to the palette's basic grey (which is used for |hl-Normal|) as possible. They should have (reasonably) different hues to make them visually separable. - - For 16 colors: - - Greys are not used and are replaced with the foreground and background colors of the terminal emulator. - - Non-grey colors fall back to terminal colors as ordered in ANSI codes (https://en.wikipedia.org/wiki/ANSI_escape_code#3-bit_and_4-bit), that is red (1, 9), green (2, 10), yellow (3, 11), blue (4, 12), @@ -78,33 +64,25 @@ Palettes To increase contrast, colors 1-6 are used for light background and 9-14 for dark background. - ============================================================================== Highlight groups Use: - Grey shades for general UI according to their design. - - Bold text for keywords (`Statement` highlight group). This is an important choice to increase accessibility for people with color deficiencies, as it doesn't rely on actual color. - - Green for strings, |hl-DiffAdd| (as background), |hl-DiagnosticOk|, and some minor text UI elements. - - Cyan as main syntax color, i.e. for function usage (`Function` highlight group), |hl-DiffText|, |hl-DiagnosticInfo|, and some minor text UI elements. - - Red to generally mean high user attention, i.e. errors; in particular for |hl-ErrorMsg|, |hl-DiffDelete|, |hl-DiagnosticError|. - - Yellow very sparingly to mean mild user attention, i.e. warnings. That is, |hl-DiagnosticWarn| and |hl-WarningMsg|. - - Blue very sparingly as |hl-DiagnosticHint| and some additional important syntax group (like `Identifier`). - - Magenta very carefully (if at all). In case of 16 colors: @@ -113,9 +91,7 @@ In case of 16 colors: colors can be used as foreground". This means that in any foreground/background combination there should be background and one non-background color. - - Use 0 (black) or 15 (bright white) as foreground for non-grey background, depending on whether normal background is light or dark. - vim:tw=78:ts=8:et:ft=help:norl: diff --git a/runtime/doc/dev_tools.txt b/runtime/doc/dev_tools.txt index 3ee48bec90..52513db31d 100644 --- a/runtime/doc/dev_tools.txt +++ b/runtime/doc/dev_tools.txt @@ -14,10 +14,10 @@ itself. See also |debug.txt| for advice that applies to Vim. ============================================================================== Backtraces *dev-tools-backtrace* -LINUX ~ +LINUX -Core dumps are disabled by default on Ubuntu -https://stackoverflow.com/a/18368068, CentOS and others. To enable core dumps: +Core dumps are disabled by default on Ubuntu, CentOS and others. +To enable core dumps: >bash ulimit -c unlimited < @@ -25,21 +25,29 @@ On systemd-based systems getting a backtrace is as easy as: >bash coredumpctl -1 gdb < -It's an optional tool, so you may need to install it: +`coredumpctl` is an optional tool, so you may need to install it: >bash sudo apt install systemd-coredump < -The full backtrace is most useful, send us the `bt.txt` file: +The full backtrace is most useful; please send us the `backtrace.txt` file +when reporting a bug related to a crash: >bash - 2>&1 coredumpctl -1 gdb | tee -a bt.txt - thread apply all bt full + 2>&1 coredumpctl -1 gdb | tee -a backtrace.txt + (gdb) thread apply all bt full < -On older systems a `core` file will appear in the current directory. To get -a backtrace from the `core` file: + +On systems without `coredumpctl`, you may find a `core` dump file appearing +in the current directory or in other locations. On Linux systems where +`apport` is installed (such as Ubuntu), the directory where core dump files +are saved can be `/var/lib/apport/coredump` or elsewhere, depending on the +system configuration (see `/proc/sys/kernel/core_pattern`). See also: +https://stackoverflow.com/a/18368068 + +To get a backtrace from the `./core` dump file: >bash - gdb build/bin/nvim core 2>&1 | tee backtrace.txt - thread apply all bt full + gdb build/bin/nvim ./core 2>&1 | tee backtrace.txt + (gdb) thread apply all bt full < MACOS @@ -76,7 +84,7 @@ core dumps with `/etc/launchd.conf`). ============================================================================== Gdb *dev-tools-gdb* -USING GDB TO STEP THROUGH FUNCTIONAL TESTS ~ +USING GDB TO STEP THROUGH FUNCTIONAL TESTS Use `TEST_TAG` to run tests matching busted tags (of the form `#foo` e.g. `it("test #foo ...", ...)`): @@ -86,20 +94,19 @@ Use `TEST_TAG` to run tests matching busted tags (of the form `#foo` e.g. Then, in another terminal: >bash gdb build/bin/nvim - target remote localhost:7777 -< -- See also test/functional/helpers.lua https://github.com/neovim/neovim/blob/3098b18a2b63a841351f6d5e3697cb69db3035ef/test/functional/helpers.lua#L38-L44. + (gdb) target remote localhost:7777 +-- See `nvim_argv` in https://github.com/neovim/neovim/blob/master/test/functional/testnvim.lua. -USING LLDB TO STEP THROUGH UNIT TESTS ~ +USING LLDB TO STEP THROUGH UNIT TESTS ->bash +> lldb .deps/usr/bin/luajit -- .deps/usr/bin/busted --lpath="./build/?.lua" test/unit/ < +USING GDB -USING GDB ~ - -To attach to a running `nvim` process with a pid of 1234: +To attach to a running `nvim` process with a pid of 1234 (Tip: the pid of a +running Nvim instance can be obtained by calling |getpid()|), for instance: >bash gdb -tui -p 1234 build/bin/nvim < @@ -118,8 +125,7 @@ The `gdb` interactive prompt will appear. At any time you can: need for a gdb "frontend". - `<up>` and `<down>` to scroll the source file view - -GDB "REVERSE DEBUGGING" ~ +GDB REVERSE DEBUGGING - `set record full insn-number-max unlimited` - `continue` for a bit (at least until `main()` is executed @@ -127,8 +133,7 @@ GDB "REVERSE DEBUGGING" ~ - provoke the bug, then use `revert-next`, `reverse-step`, etc. to rewind the debugger - -USING GDBSERVER ~ +USING GDBSERVER You may want to connect multiple `gdb` clients to the same running `nvim` process, or you may want to connect to a remote `nvim` process with a local @@ -146,12 +151,12 @@ debugging session in another terminal: < Once you've entered `gdb`, you need to attach to the remote session: > - target remote localhost:6666 + (gdb) target remote localhost:6666 < In case gdbserver puts the TUI as a background process, the TUI can become unable to read input from pty (and receives SIGTTIN signal) and/or output data (SIGTTOU signal). To force the TUI as the foreground process, you can add -> +>c signal (SIGTTOU, SIG_IGN); if (!tcsetpgrp(data->input.in_fd, getpid())) { perror("tcsetpgrp failed"); @@ -159,8 +164,7 @@ unable to read input from pty (and receives SIGTTIN signal) and/or output data < to `tui.c:terminfo_start`. - -USING GDBSERVER IN TMUX ~ +USING GDBSERVER IN TMUX Consider using a custom makefile https://github.com/neovim/neovim/blob/master/BUILD.md#custom-makefile to @@ -185,8 +189,8 @@ Here `gdb_start.sh` includes `gdb` commands to be called when the debugger starts. It needs to attach to the server started by the `dbg-start` rule. For example: > - target remote localhost:6666 - br main + (gdb) target remote localhost:6666 + (gdb) br main < vim:tw=78:ts=8:et:ft=help:norl: diff --git a/runtime/doc/dev_vimpatch.txt b/runtime/doc/dev_vimpatch.txt index 96307dc7df..d6e4ced054 100644 --- a/runtime/doc/dev_vimpatch.txt +++ b/runtime/doc/dev_vimpatch.txt @@ -185,7 +185,7 @@ information. mch_memmove memmove vim_memset copy_chars copy_spaces memset vim_strbyte strchr - vim_strncpy strncpy xstrlcpy + vim_strncpy strncpy xstrlcpy/xmemcpyz vim_strcat strncat xstrlcat VIM_ISWHITE ascii_iswhite IS_WHITE_OR_NUL ascii_iswhite_or_nul @@ -209,6 +209,8 @@ information. utf_off2cells grid_off2cells ml_get_curline get_cursor_line_ptr ml_get_cursor get_cursor_pos_ptr + ml_get_curline_len get_cursor_line_len + ml_get_cursor_len get_cursor_pos_len screen_char ui_line screen_line grid_put_linebuf screen_* (most functions) grid_* diff --git a/runtime/doc/develop.txt b/runtime/doc/develop.txt index 767f46ad1e..d7837dc2fe 100644 --- a/runtime/doc/develop.txt +++ b/runtime/doc/develop.txt @@ -4,7 +4,7 @@ NVIM REFERENCE MANUAL -Development of Nvim *development* *dev* +Development of Nvim *development* *dev* This reference describes design constraints and guidelines, for developing Nvim applications or Nvim itself. @@ -16,13 +16,13 @@ Nvim is free and open source. Everybody is encouraged to contribute. Type |gO| to see the table of contents. ============================================================================== -Design goals *design-goals* +Design goals *design-goals* Most important things come first (roughly). Some items conflict; this is intentional. A balance must be found. -NVIM IS... IMPROVED *design-improved* +NVIM IS... IMPROVED *design-improved* The Neo bits of Nvim should make it a better Vim, without becoming a completely different editor. @@ -35,7 +35,7 @@ completely different editor. never break. -NVIM IS... WELL DOCUMENTED *design-documented* +NVIM IS... WELL DOCUMENTED *design-documented* - A feature that isn't documented is a useless feature. A patch for a new feature must include the documentation. @@ -44,7 +44,7 @@ NVIM IS... WELL DOCUMENTED *design-documented* item is easier to find. -NVIM IS... FAST AND SMALL *design-speed-size* +NVIM IS... FAST AND SMALL *design-speed-size* Keep Nvim small and fast. This directly affects versatility and usability. - Computers are becoming faster and bigger each year. Vim can grow too, but @@ -59,7 +59,7 @@ Keep Nvim small and fast. This directly affects versatility and usability. ("composability"). -NVIM IS... MAINTAINABLE *design-maintain* +NVIM IS... MAINTAINABLE *design-maintain* - The source code should not become a mess. It should be reliable code. - Use comments in a useful way! Quoting the function name and argument names @@ -70,7 +70,7 @@ NVIM IS... MAINTAINABLE *design-maintain* knowledge spread to other parts of the code. -NVIM IS... NOT *design-not* +NVIM IS... NOT *design-not* Nvim is not an operating system; instead it should be composed with other tools or hosted as a component. Marvim once said: "Unlike Emacs, Nvim does not @@ -78,10 +78,10 @@ include the kitchen sink... but it's good for plumbing." ============================================================================== -Developer guidelines *dev-guidelines* +Developer guidelines *dev-guidelines* -PROVIDERS *dev-provider* +PROVIDERS *dev-provider* A primary goal of Nvim is to allow extension of the editor without special knowledge in the core. Some core functions are delegated to "providers" @@ -115,7 +115,7 @@ For example, the Python provider is implemented by the to 2 only if a valid external Python host is found. Then `has("python")` reflects whether Python support is working. - *provider-reload* + *provider-reload* Sometimes a GUI or other application may want to force a provider to "reload". To reload a provider, undefine its "loaded" flag, then use |:runtime| to reload it: >vim @@ -124,7 +124,7 @@ Sometimes a GUI or other application may want to force a provider to :runtime autoload/provider/clipboard.vim -DOCUMENTATION *dev-doc* +DOCUMENTATION *dev-doc* - "Just say it". Avoid mushy, colloquial phrasing in all documentation (docstrings, user manual, website materials, newsletters, …). Don't mince @@ -159,6 +159,12 @@ DOCUMENTATION *dev-doc* not "the user host terminal". - Use "tui-" to prefix help tags related to the host terminal, and "TUI" in prose if possible. +- Rough guidelines on where Lua documentation should end up: + - Nvim API functions `vim.api.nvim_*` should be in `api.txt`. + - If the module is big and not relevant to generic and lower-level Lua + functionality, then it's a strong candidate for separation. Example: + `treesitter.txt` + - Otherwise, add them to `lua.txt` Documentation format ~ @@ -230,7 +236,7 @@ in src/nvim/api/win_config.c like this: > Lua docstrings ~ - *dev-lua-doc* + *dev-lua-doc* Lua documentation lives in the source code, as docstrings on the function definitions. The |lua-vim| :help is generated from the docstrings. @@ -289,7 +295,7 @@ vim.paste in runtime/lua/vim/_editor.lua like this: > --- @returns false if client should cancel the paste. -LUA STDLIB DESIGN GUIDELINES *dev-lua* +LUA STDLIB DESIGN GUIDELINES *dev-lua* See also |dev-naming|. @@ -304,14 +310,22 @@ See also |dev-naming|. - accept iterable instead of table - exception: in some cases iterable doesn't make sense, e.g. spair() sorts the input by definition, so there is no reason for it to accept an - iterable, because the input needs to be "hydrated", it can't operate on + iterable, because the input needs to be "reified"; it can't operate on a "stream". - return iterable instead of table - mimic the pairs() or ipairs() interface if the function is intended to be used in a "for" loop. + - when a result-or-error interface is needed, return `result|nil, nil|errmsg`: > + ---@return Foo|nil # Result object, or nil if not found. + ---@return nil|string # Error message on failure, or nil on success. +< + - Examples: |vim.ui.open()| |io.open()| |luv-error-handling| + *dev-patterns* Interface conventions ~ +Where possible, these patterns apply to _both_ Lua and the API: + - When accepting a buffer id, etc., 0 means "current buffer", nil means "all buffers". Likewise for window id, tabpage id, etc. - Examples: |vim.lsp.codelens.clear()| |vim.diagnostic.enable()| @@ -322,8 +336,19 @@ Interface conventions ~ filter(table, opts, function() … end) BAD: filter(function() … end, table, opts) - -API DESIGN GUIDELINES *dev-api* +- "Enable" ("toggle") interface and behavior: + - `enable(…, nil)` and `enable(…, {buf=nil})` are synonyms and control the + the "global" enablement of a feature. + - `is_enabled(nil)` and `is_enabled({buf=nil})`, likewise, query the + global state of the feature. + - `enable(…, {buf: number})` sets a buffer-local "enable" flag. + - `is_enabled({buf: number})`, likewise, queries the buffer-local state of + the feature. + - See |vim.lsp.inlay_hint.enable()| and |vim.lsp.inlay_hint.is_enabled()| + for a reference implementation of these "best practices". + - NOTE: open questions: https://github.com/neovim/neovim/issues/28603 + +API DESIGN GUIDELINES *dev-api* See also |dev-naming|. @@ -363,32 +388,45 @@ Naming conventions ~ In general, look for precedent when choosing a name, that is, look at existing (non-deprecated) functions. In particular, see below... - *dev-name-common* + *dev-name-common* Use existing common {verb} names (actions) if possible: - add: Appends or inserts into a collection - attach: Listens to something to get events from it (TODO: rename to "on"?) - call: Calls a function + - cancel: Cancels or dismisses an event or interaction, typically + user-initiated and without error. (Compare "abort", which + cancels and signals error/failure.) - clear: Clears state but does not destroy the container - create: Creates a new (non-trivial) thing (TODO: rename to "def"?) - del: Deletes a thing (or group of things) - detach: Dispose attached listener (TODO: rename to "un"?) + - enable: Enables/disables functionality. Signature should be + `enable(enable?:boolean, filter?:table)`. - eval: Evaluates an expression - - exec: Executes code + - exec: Executes code, may return a result - fmt: Formats - get: Gets things (often by a query) - inspect: Presents a high-level, often interactive, view + - is_enabled: Checks if functionality is enabled. - open: Opens something (a buffer, window, …) - parse: Parses something into a structured form - set: Sets a thing (or group of things) + - start: Spin up a long-lived process. Prefer "enable" except when + "start" is obviously more appropriate. + - stop: Inverse of "start". Teardown a long-lived process. - try_{verb}: Best-effort operation, failure returns null or error obj Do NOT use these deprecated verbs: + - disable: Prefer `enable(enable: boolean)`. + - exit: Prefer "cancel" (or "stop" if appropriate). + - is_disabled: Prefer `is_enabled()`. - list: Redundant with "get" - - show: Redundant with "print", "echo" - notify: Redundant with "print", "echo" + - show: Redundant with "print", "echo" + - toggle: Prefer `enable(not is_enabled())`. -Use consistent names for {noun} (nouns) in API functions: buffer is called -"buf" everywhere, not "buffer" in some places and "buf" in others. +Use consistent names for {topic} in API functions: buffer is called "buf" +everywhere, not "buffer" in some places and "buf" in others. - buf: Buffer - chan: |channel| - cmd: Command @@ -401,12 +439,12 @@ Use consistent names for {noun} (nouns) in API functions: buffer is called - win: Window Do NOT use these deprecated nouns: - - buffer + - buffer Use "buf" instead - callback Use on_foo instead - - command - - window + - command Use "cmd" instead + - window Use "win" instead - *dev-name-events* + *dev-name-events* Use the "on_" prefix to name event-handling callbacks and also the interface for "registering" such handlers (on_key). The dual nature is acceptable to avoid a confused collection of naming conventions for these related concepts. @@ -420,14 +458,17 @@ Use this format to name API (RPC) events: > Example: > nvim_buf_changedtick_event < - *dev-name-api* + *dev-api-name* Use this format to name new RPC |API| functions: > - nvim_{noun}_{verb}_{arbitrary-qualifiers} + nvim_{topic}_{verb}_{arbitrary-qualifiers} -If the function acts on an object then {noun} is the name of that object -(e.g. "buf" or "win"). If the function operates in a "global" context then -{noun} is usually omitted (but consider "namespacing" your global operations -with a {noun} that groups functions under a common concept). +Do not add new nvim_buf/nvim_win/nvim_tabpage APIs, unless you are certain the +concept will NEVER be applied to more than one "scope". That is, {topic} +should be the TOPIC ("ns", "extmark", "option", …) that acts on the scope(s) +(buf/win/tabpage/global), it should NOT be the scope. Instead the scope should +be a parameter (typically manifest as mutually-exclusive buf/win/… flags like +|nvim_get_option_value()|, or less commonly as a `scope: string` field like +|nvim_get_option_info2()|). - Example: `nvim_get_keymap('v')` operates in a global context (first parameter is not a Buffer). The "get" verb indicates that it gets anything @@ -437,9 +478,61 @@ with a {noun} that groups functions under a common concept). and uses the "del" {verb}. -API-CLIENT *dev-api-client* +INTERFACE PATTERNS *dev-api-patterns* + +Prefer adding a single `nvim_{topic}_{verb}_…` interface for a given topic. + +Example: > - *api-client* + nvim_ns_add( + ns_id: int, + filter: { + handle: integer (buf/win/tabpage id) + scope: "global" | "win" | "buf" | "tabpage" + } + ): { ok: boolean } + + nvim_ns_get( + ns_id: int, + filter: { + handle: integer (buf/win/tabpage id) + scope: "global" | "win" | "buf" | "tabpage" + } + ): { ids: int[] } + + nvim_ns_del( + ns_id: int, + filter: { + handle: integer (buf/win/tabpage id) + scope: "global" | "win" | "buf" | "tabpage" + } + ): { ok: boolean } + + +Anti-Example: + +Creating separate `nvim_xx`, `nvim_buf_xx`, `nvim_win_xx`, and +`nvim_tabpage_xx`, functions all for the same `xx` topic, requires 4x the +amount of documentation, tests, boilerplate, and interfaces, which users must +comprehend, maintainers must maintain, etc. Thus the following is NOT +recommended (compare these 12(!) functions to the above 3 functions): > + + nvim_add_ns(…) + nvim_buf_add_ns(…) + nvim_win_add_ns(…) + nvim_tabpage_add_ns(…) + nvim_del_ns(…) + nvim_buf_del_ns(…) + nvim_win_del_ns(…) + nvim_tabpage_del_ns(…) + nvim_get_ns(…) + nvim_buf_get_ns(…) + nvim_win_get_ns(…) + nvim_tabpage_get_ns(…) + +API-CLIENT *dev-api-client* + + *api-client* API clients wrap the Nvim |API| to provide idiomatic "SDKs" for their respective platforms (see |jargon|). You can build a new API client for your favorite platform or programming language. @@ -447,9 +540,10 @@ favorite platform or programming language. List of API clients: https://github.com/neovim/neovim/wiki/Related-projects#api-clients - *pynvim* -The Python client is the reference implementation for API clients. - https://github.com/neovim/pynvim + *node-client* *pynvim* +These clients can be considered the "reference implementation" for API clients: +- https://github.com/neovim/node-client +- https://github.com/neovim/pynvim Standard Features ~ @@ -500,7 +594,7 @@ API client implementation guidelines ~ https://github.com/msgpack-rpc/msgpack-rpc -EXTERNAL UI *dev-ui* +EXTERNAL UI *dev-ui* External UIs should be aware of the |api-contract|. In particular, future versions of Nvim may add new items to existing events. The API is strongly @@ -526,6 +620,8 @@ External UIs are expected to implement these common features: published in this event. See also "mouse_on", "mouse_off". - UIs generally should NOT set |$NVIM_APPNAME| (unless explicitly requested by the user). +- Support the text decorations/attributes given by |ui-event-hl_attr_define|. + The "url" attr should be presented as a clickable hyperlink. vim:tw=78:ts=8:sw=4:et:ft=help:norl: diff --git a/runtime/doc/diagnostic.txt b/runtime/doc/diagnostic.txt index c9e783ca62..36616b9a0d 100644 --- a/runtime/doc/diagnostic.txt +++ b/runtime/doc/diagnostic.txt @@ -371,8 +371,10 @@ Lua module: vim.diagnostic *diagnostic-api* A table with the following keys: Fields: ~ - • {namespace}? (`integer`) Limit diagnostics to the given namespace. - • {lnum}? (`integer`) Limit diagnostics to the given line number. + • {namespace}? (`integer[]|integer`) Limit diagnostics to one or more + namespaces. + • {lnum}? (`integer`) Limit diagnostics to those spanning the + specified line number. • {severity}? (`vim.diagnostic.SeverityFilter`) See |diagnostic-severity|. @@ -387,7 +389,7 @@ Lua module: vim.diagnostic *diagnostic-api* |nvim_win_get_cursor()|. • {wrap}? (`boolean`, default: `true`) Whether to loop around file or not. Similar to 'wrapscan'. - • {severity} (`vim.diagnostic.Severity`) See + • {severity}? (`vim.diagnostic.SeverityFilter`) See |diagnostic-severity|. • {float}? (`boolean|vim.diagnostic.Opts.Float`, default: `true`) If `true`, call @@ -432,7 +434,7 @@ Lua module: vim.diagnostic *diagnostic-api* • {update_in_insert}? (`boolean`, default: `false`) Update diagnostics in Insert mode (if `false`, diagnostics are updated on |InsertLeave|) - • {severity_sort}? (`boolean|{reverse?:boolean}`, default: `false) + • {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 @@ -496,6 +498,7 @@ Lua module: vim.diagnostic *diagnostic-api* diagnostic instead of prepending it. Overrides the setting from |vim.diagnostic.config()|. • {focus_id}? (`string`) + • {border}? (`string`) see |nvim_open_win()|. *vim.diagnostic.Opts.Signs* @@ -615,23 +618,20 @@ count({bufnr}, {opts}) *vim.diagnostic.count()* (`table`) Table with actually present severity values as keys (see |diagnostic-severity|) and integer counts as values. -disable({bufnr}, {namespace}) *vim.diagnostic.disable()* - Disable diagnostics in the given buffer. +enable({enable}, {filter}) *vim.diagnostic.enable()* + Enables or disables diagnostics. - Parameters: ~ - • {bufnr} (`integer?`) Buffer number, or 0 for current buffer. When - omitted, disable diagnostics in all buffers. - • {namespace} (`integer?`) Only disable diagnostics for the given - namespace. - -enable({bufnr}, {namespace}) *vim.diagnostic.enable()* - Enable diagnostics in the given buffer. + To "toggle", pass the inverse of `is_enabled()`: >lua + vim.diagnostic.enable(not vim.diagnostic.is_enabled()) +< Parameters: ~ - • {bufnr} (`integer?`) Buffer number, or 0 for current buffer. When - omitted, enable diagnostics in all buffers. - • {namespace} (`integer?`) Only enable diagnostics for the given - namespace. + • {enable} (`boolean?`) true/nil to enable, false to disable + • {filter} (`table?`) Optional filters |kwargs|, or `nil` for all. + • {ns_id}? (`integer`) Diagnostic namespace, or `nil` for + all. + • {bufnr}? (`integer`) Buffer number, or 0 for current + buffer, or `nil` for all buffers. fromqflist({list}) *vim.diagnostic.fromqflist()* Convert a list of quickfix items to a list of diagnostics. @@ -732,7 +732,7 @@ hide({namespace}, {bufnr}) *vim.diagnostic.hide()* diagnostics, use |vim.diagnostic.reset()|. To hide diagnostics and prevent them from re-displaying, use - |vim.diagnostic.disable()|. + |vim.diagnostic.enable()|. Parameters: ~ • {namespace} (`integer?`) Diagnostic namespace. When omitted, hide @@ -740,14 +740,15 @@ hide({namespace}, {bufnr}) *vim.diagnostic.hide()* • {bufnr} (`integer?`) Buffer number, or 0 for current buffer. When omitted, hide diagnostics in all buffers. -is_disabled({bufnr}, {namespace}) *vim.diagnostic.is_disabled()* - Check whether diagnostics are disabled in a given buffer. +is_enabled({filter}) *vim.diagnostic.is_enabled()* + Check whether diagnostics are enabled. Parameters: ~ - • {bufnr} (`integer?`) Buffer number, or 0 for current buffer. - • {namespace} (`integer?`) Diagnostic namespace. When omitted, checks - if all diagnostics are disabled in {bufnr}. Otherwise, - only checks if diagnostics from {namespace} are disabled. + • {filter} (`table?`) Optional filters |kwargs|, or `nil` for all. + • {ns_id}? (`integer`) Diagnostic namespace, or `nil` for + all. + • {bufnr}? (`integer`) Buffer number, or 0 for current + buffer, or `nil` for all buffers. Return: ~ (`boolean`) diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt index 1a4572e94a..662d89895d 100644 --- a/runtime/doc/editing.txt +++ b/runtime/doc/editing.txt @@ -632,9 +632,12 @@ list of the current window. :[count]arge[dit][!] [++opt] [+cmd] {name} .. *:arge* *:argedit* Add {name}s to the argument list and edit it. - When {name} already exists in the argument list, this - entry is edited. - This is like using |:argadd| and then |:edit|. + There is no check for duplicates, it is possible to + add a file to the argument list twice |:argded|. + This is like using |:argadd| and then |:edit| (with + the small exception that |:edit| does not change the + argument list, so the argument list pointer isn't + changed). Spaces in filenames have to be escaped with "\". [count] is used like with |:argadd|. If the current file cannot be |abandon|ed {name}s will @@ -653,12 +656,12 @@ list of the current window. If the argument list is "a b c", and "b" is the current argument, then these commands result in: command new argument list ~ - :argadd x a b x c - :0argadd x x a b c - :1argadd x a x b c - :$argadd x a b c x + :argadd x a [b] x c + :0argadd x x a [b] c + :1argadd x a x [b] c + :$argadd x a [b] c x And after the last one: - :+2argadd y a b c x y + :+2argadd y a [b] c x y There is no check for duplicates, it is possible to add a file to the argument list twice. You can use |:argdedupe| to fix it afterwards: > diff --git a/runtime/doc/editorconfig.txt b/runtime/doc/editorconfig.txt index a2281a7b7c..0b20c77801 100644 --- a/runtime/doc/editorconfig.txt +++ b/runtime/doc/editorconfig.txt @@ -3,79 +3,35 @@ NVIM REFERENCE MANUAL + Type |gO| to see the table of contents. +============================================================================== EditorConfig integration *editorconfig* -Nvim supports EditorConfig. When a file is opened, Nvim searches all parent -directories of that file for ".editorconfig" files, parses them, and applies -any properties that match the opened file. Think of it like 'modeline' for an -entire (recursive) directory. For more information see -https://editorconfig.org/. +Nvim supports EditorConfig. When a file is opened, after running |ftplugin|s +and |FileType| autocommands, Nvim searches all parent directories of that file +for ".editorconfig" files, parses them, and applies any properties that match +the opened file. Think of it like 'modeline' for an entire (recursive) +directory. For more information see https://editorconfig.org/. *g:editorconfig* *b:editorconfig* -EditorConfig is enabled by default. To disable it, add to your config: >lua +EditorConfig is enabled by default. To disable it, add to your config: >lua vim.g.editorconfig = false < + (Vimscript: `let g:editorconfig = v:false`). It can also be disabled per-buffer by setting the |b:editorconfig| buffer-local variable to `false`. Nvim stores the applied properties in |b:editorconfig| if it is not `false`. - *editorconfig-properties* -The following properties are supported by default: - - *editorconfig_root* -root If "true", then stop searching for .editorconfig files - in parent directories. This property must be at the - top-level of the .editorconfig file (i.e. it must not - be within a glob section). - - *editorconfig_charset* -charset One of "utf-8", "utf-8-bom", "latin1", "utf-16be", or - "utf-16le". Sets the 'fileencoding' and 'bomb' - options. - - *editorconfig_end_of_line* -end_of_line One of "lf", "crlf", or "cr". These correspond to - setting 'fileformat' to "unix", "dos", or "mac", - respectively. - - *editorconfig_indent_style* -indent_style One of "tab" or "space". Sets the 'expandtab' option. - - *editorconfig_indent_size* -indent_size A number indicating the size of a single indent. - Alternatively, use the value "tab" to use the value of - the tab_width property. Sets the 'shiftwidth' and - 'softtabstop' options. - If this value is not "tab" and the tab_width property - is not set, 'tabstop' is also set to this value. - - *editorconfig_insert_final_newline* -insert_final_newline "true" or "false" to ensure the file always has a - trailing newline as its last byte. Sets the - 'fixendofline' and 'endofline' options. - - *editorconfig_max_line_length* -max_line_length A number indicating the maximum length of a single - line. Sets the 'textwidth' option. - - *editorconfig_tab_width* -tab_width The display size of a single tab character. Sets the - 'tabstop' option. - - *editorconfig_trim_trailing_whitespace* -trim_trailing_whitespace - When "true", trailing whitespace is automatically - removed when the buffer is written. - *editorconfig-custom-properties* + New properties can be added by adding a new entry to the "properties" table. The table key is a property name and the value is a callback function which -accepts the number of the buffer to be modified, the value of the property -in the .editorconfig file, and (optionally) a table containing all of the -other properties and their values (useful for properties which depend on other +accepts the number of the buffer to be modified, the value of the property in +the `.editorconfig` file, and (optionally) a table containing all of the other +properties and their values (useful for properties which depend on other properties). The value is always a string and must be coerced if necessary. Example: >lua @@ -86,4 +42,48 @@ Example: >lua vim.b[bufnr].foo = val end < - vim:tw=78:ts=8:et:sw=4:ft=help:norl: + + *editorconfig-properties* + +The following properties are supported by default: + + +charset *editorconfig.charset* + One of `"utf-8"`, `"utf-8-bom"`, `"latin1"`, `"utf-16be"`, or + `"utf-16le"`. Sets the 'fileencoding' and 'bomb' options. + +end_of_line *editorconfig.end_of_line* + One of `"lf"`, `"crlf"`, or `"cr"`. These correspond to setting + 'fileformat' to "unix", "dos", or "mac", respectively. + +indent_size *editorconfig.indent_size* + A number indicating the size of a single indent. Alternatively, use the + value "tab" to use the value of the tab_width property. Sets the + 'shiftwidth' and 'softtabstop' options. If this value is not "tab" and the + tab_width property is not set, 'tabstop' is also set to this value. + +indent_style *editorconfig.indent_style* + One of `"tab"` or `"space"`. Sets the 'expandtab' option. + +insert_final_newline *editorconfig.insert_final_newline* + `"true"` or `"false"` to ensure the file always has a trailing newline as + its last byte. Sets the 'fixendofline' and 'endofline' options. + +max_line_length *editorconfig.max_line_length* + A number indicating the maximum length of a single line. Sets the + 'textwidth' option. + +root *editorconfig.root* + If "true", then stop searching for `.editorconfig` files in parent + directories. This property must be at the top-level of the `.editorconfig` + file (i.e. it must not be within a glob section). + +tab_width *editorconfig.tab_width* + The display size of a single tab character. Sets the 'tabstop' option. + +trim_trailing_whitespace *editorconfig.trim_trailing_whitespace* + When `"true"`, trailing whitespace is automatically removed when the + buffer is written. + + + vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl: diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index ef416fe56f..7b4dba5a50 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -2144,6 +2144,10 @@ text... :cons[t] {var-name} = {expr1} :cons[t] [{name1}, {name2}, ...] = {expr1} :cons[t] [{name}, ..., ; {lastname}] = {expr1} +:cons[t] {var-name} =<< [trim] [eval] {marker} +text... +text... +{marker} Similar to |:let|, but additionally lock the variable after setting the value. This is the same as locking the variable with |:lockvar| just after |:let|, thus: > diff --git a/runtime/doc/faq.txt b/runtime/doc/faq.txt index 09bf829512..7d2774c191 100644 --- a/runtime/doc/faq.txt +++ b/runtime/doc/faq.txt @@ -29,13 +29,6 @@ Use the stable (release) https://github.com/neovim/neovim/releases/latest version for a more predictable experience. -CAN I USE RUBY-BASED VIM PLUGINS (E.G. LUSTYEXPLORER)? ~ - -Yes, starting with Nvim 0.1.5 PR #4980 -https://github.com/neovim/neovim/pull/4980 the legacy Vim `if_ruby` interface -is supported. - - CAN I USE LUA-BASED VIM PLUGINS (E.G. NEOCOMPLETE)? ~ No. Starting with Nvim 0.2 PR #4411 @@ -288,19 +281,17 @@ Run the following from the command line: >bash locale | grep -E '(LANG|LC_CTYPE|LC_ALL)=(.*\.)?(UTF|utf)-?8' < -If there's no results, then you might not be using a UTF-8 locale. See the -following issues: -#1601 https://github.com/neovim/neovim/issues/1601 -#1858 https://github.com/neovim/neovim/issues/1858 -#2386 https://github.com/neovim/neovim/issues/2386 +If there's no results, you might not be using a UTF-8 locale. See these issues: +- https://github.com/neovim/neovim/issues/1601 +- https://github.com/neovim/neovim/issues/1858 +- https://github.com/neovim/neovim/issues/2386 ESC IN TMUX OR GNU SCREEN IS DELAYED ~ This is a common problem https://www.google.com/?q=tmux%20vim%20escape%20delay in `tmux` / `screen` -(see also tmux/#131 -https://github.com/tmux/tmux/issues/131#issuecomment-145853211). The +(see also https://github.com/tmux/tmux/issues/131#issuecomment-145853211). The corresponding timeout needs to be tweaked to a low value (10-20ms). `.tmux.conf`: @@ -317,11 +308,11 @@ corresponding timeout needs to be tweaked to a low value (10-20ms). "WHY DOESN'T THIS HAPPEN IN VIM?" It does happen (try `vim -N -u NONE`), but if you hit a key quickly after -ESC_ then Vim interprets the ESC as ESC instead of ALT (META). You won't +ESC then Vim interprets the ESC as ESC instead of ALT (META). You won't notice the delay unless you closely observe the cursor. The tradeoff is that Vim won't understand ALT (META) key-chords, so for example `nnoremap <M-a>` -won't work. ALT (META) key-chords always work in Nvim. See also `:help -xterm-cursor-keys` in Vim. +won't work. ALT (META) key-chords always work in Nvim. +See also `:help xterm-cursor-keys` in Vim. Nvim 0.3 mimics the Vim behavior while still fully supporting ALT mappings. See |i_ALT|. @@ -329,7 +320,7 @@ Nvim 0.3 mimics the Vim behavior while still fully supporting ALT mappings. See ESC IN GNU SCREEN IS LOST WHEN MOUSE MODE IS ENABLED ~ -This happens because of a bug in screen https://savannah.gnu.org/bugs/?60196: +This happens because of a bug in screen https://savannah.gnu.org/bugs/?60196 : in mouse mode, screen assumes that `ESC` is part of a mouse sequence and will wait an unlimited time for the rest of the sequence, regardless of `maptimeout`. Until it's fixed in screen, there's no known workaround for @@ -339,10 +330,11 @@ passed through to Nvim. CALLING INPUTLIST(), ECHOMSG, ... IN FILETYPE PLUGINS AND AUTOCMD DOES NOT WORK ~ -#10008 https://github.com/neovim/neovim/issues/10008, -#10116 https://github.com/neovim/neovim/issues/10116, -#12288 https://github.com/neovim/neovim/issues/12288, -# vim/vim#4379 https://github.com/vim/vim/issues/4379. +- https://github.com/neovim/neovim/issues/10008 +- https://github.com/neovim/neovim/issues/10116 +- https://github.com/neovim/neovim/issues/12288 +- https://github.com/vim/vim/issues/4379 + This is because Nvim sets `shortmess+=F` by default. Vim behaves the same way with `set shortmes+=F`. There are plans to improve this, but meanwhile as a workaround, use `set shortmess-=F` or use `unsilent` as follows. @@ -400,8 +392,8 @@ CMAKE ERRORS ~ `configure_file Problem configuring file` This is probably a permissions issue, which can happen if you run `make` as the -root user, then later run an unprivileged `make`. To fix this, run `rm -rf -build` and try again. +root user, then later run an unprivileged `make`. To fix this, run +`rm -rf build` and try again. GENERATING HELPTAGS FAILED ~ @@ -434,7 +426,7 @@ WHY EMBED LUA INSTEAD OF X? ~ - Nvim also uses Lua internally as an alternative to C. Extra performance is useful there, as opposed to a slow language like Python or Vim9script. - LuaJIT is one of the fastest runtimes on the planet, 10x faster than Python - and "Vim9script" https://vimhelp.org/vim9.txt.html, 100x faster than + and "Vim9script" https://vimhelp.org/vim9.txt.html , 100x faster than Vimscript. - Python/JS cost more than Lua in terms of size and portability, and there are already numerous Python/JS-based editors. So Python/JS would make Nvim diff --git a/runtime/doc/filetype.txt b/runtime/doc/filetype.txt index 071a45c9c3..5eae78744c 100644 --- a/runtime/doc/filetype.txt +++ b/runtime/doc/filetype.txt @@ -155,6 +155,8 @@ variables can be used to overrule the filetype used for certain extensions: `*.inc` g:filetype_inc `*.lsl` g:filetype_lsl `*.m` g:filetype_m |ft-mathematica-syntax| + `*.markdown,*.mdown,*.mkd,*.mkdn,*.mdwn,*.md` + g:filetype_md |ft-pandoc-syntax| `*.mod` g:filetype_mod `*.p` g:filetype_p |ft-pascal-syntax| `*.pl` g:filetype_pl @@ -400,6 +402,31 @@ So to enable this only for ruby, set the following variable: > If both, the global `plugin_exec` and the `<filetype>_exec` specific variable are set, the filetype specific variable should have precedent. + +ASCIIDOC *ft-asciidoc-plugin* + +To enable |folding| use this: > + let g:asciidoc_folding = 1 + +To disable nesting of folded headers use this: > + let g:asciidoc_foldnested = 0 + +To disable folding everything under the title use this: > + let asciidoc_fold_under_title = 0 + + +ARDUINO *ft-arduino-plugin* + +By default the following options are set, in accordance with the default +settings of Arduino IDE: > + + setlocal expandtab tabstop=2 softtabstop=2 shiftwidth=2 + +To disable this behavior, set the following variable in your vimrc: > + + let g:arduino_recommended_style = 0 + + AWK *ft-awk-plugin* Support for features specific to GNU Awk, like @include, can be enabled by @@ -527,18 +554,6 @@ under it. If not found, a new entry and item is prepended to the beginning of the Changelog. -ASCIIDOC *ft-asciidoc-plugin* - -To enable |folding| use this: > - let g:asciidoc_folding = 1 - -To disable nesting of folded headers use this: > - let g:asciidoc_foldnested = 0 - -To disable folding everything under the title use this: > - let asciidoc_fold_under_title = 0 - - FORTRAN *ft-fortran-plugin* Options: @@ -587,6 +602,37 @@ The mapping can be disabled with: > let g:no_gprof_maps = 1 +JAVA *ft-java-plugin* + +Whenever the variable "g:ftplugin_java_source_path" is defined and its value +is a filename whose extension is either ".jar" or ".zip", e.g.: > + let g:ftplugin_java_source_path = '/path/to/src.jar' + let g:ftplugin_java_source_path = '/path/to/src.zip' +< +and the |zip| plugin has already been sourced, the |gf| command can be used to +open the archive and the |n| command can be used to look for the selected type +and the <Return> key can be used to load a listed file. + +Note that the effect of using the "gf" command WITHIN a buffer loaded with the +Zip plugin depends on the version of the Zip plugin. For the Zip plugin +versions that do not support Jar type archives, consider creating symbolic +links with the ".zip" extension for each Jar archive of interest and assigning +any such file to the variable from now on. + +Otherwise, for the defined variable "g:ftplugin_java_source_path", the local +value of the 'path' option will be further modified by prefixing the value of +the variable, e.g.: > + let g:ftplugin_java_source_path = $JDK_SRC_PATH + let &l:path = g:ftplugin_java_source_path . ',' . &l:path +< +and the "gf" command can be used on a fully-qualified type to look for a file +in the "path" and to try to load it. + +Remember to manually trigger the |FileType| event from a buffer with a Java +file loaded in it each time after assigning a new value to the variable: > + doautocmd FileType +< + MAIL *ft-mail-plugin* Options: @@ -626,8 +672,10 @@ Man Open the manpage for the <cWORD> (man buffers) or <cword> (non-man buffers) under the cursor. Man! Display the current buffer contents as a manpage. -|:Man| accepts command modifiers. For example, to use a vertical split: > +|:Man| accepts command modifiers. For example, to use a vertical split: >vim :vertical Man printf +To reuse the current window: >vim + :hide Man printf Local mappings: K or CTRL-] Jump to the manpage for the <cWORD> under the @@ -647,14 +695,14 @@ Variables: empty. Enabled by default. Set |FALSE| to enable soft wrapping. -To use Nvim as a manpager: > +To use Nvim as a manpager: >sh export MANPAGER='nvim +Man!' Note that when running `man` from the shell and with that `MANPAGER` in your environment, `man` will pre-format the manpage using `groff`. Thus, Nvim will inevitably display the manual page as it was passed to it from stdin. One of the caveats of this is that the width will _always_ be hard-wrapped and not -soft wrapped as with `g:man_hardwrap=0`. You can set in your environment: > +soft wrapped as with `g:man_hardwrap=0`. You can set in your environment: >sh export MANWIDTH=999 So `groff`'s pre-formatting output will be the same as with `g:man_hardwrap=0` i.e soft-wrapped. @@ -662,6 +710,10 @@ So `groff`'s pre-formatting output will be the same as with `g:man_hardwrap=0` i To disable bold highlighting: > :highlight link manBold Normal +An alternative to using `MANPAGER` in shell can be redefined `man`, for example: >sh + man() { + nvim "+hide Man $1" + } MARKDOWN *ft-markdown-plugin* @@ -942,6 +994,31 @@ The mappings can be disabled with: > let g:no_vim_maps = 1 +ZIG *ft-zig-plugin* + + *g:zig_recommended_style* +By default the following indentation options are set, in accordance with Zig's +recommended style (https://ziglang.org/documentation/master/): > + + setlocal expandtab shiftwidth=4 softtabstop=4 tabstop=8 +< +To disable this behavior, set |g:zig_recommended_style| to 0: > + + let g:zig_recommended_style = 0 +< + *g:zig_std_dir* +The path to the Zig standard library. The Zig |ftplugin| reads |g:zig_std_dir| +and appends it to the 'path' for Zig files. Where the Zig standard library +is located is system and installation method dependent. + +One can automatically set |g:zig_std_dir| using `zig env`: > + + let g:zig_std_dir = json_decode(system('zig env'))['std_dir'] +< +This can, for example, be put in a FileType |:autocmd| or user |ftplugin| to +only load when a Zig file is opened. + + ZIMBU *ft-zimbu-plugin* The Zimbu 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 bf62dba539..a64d722177 100644 --- a/runtime/doc/gui.txt +++ b/runtime/doc/gui.txt @@ -443,18 +443,18 @@ You can define the special menu "PopUp". This is the menu that is displayed when the right mouse button is pressed, if 'mousemodel' is set to popup or popup_setpos. -The default "PopUp" menu is: > - aunmenu PopUp - vnoremenu PopUp.Cut "+x - vnoremenu PopUp.Copy "+y - anoremenu PopUp.Paste "+gP - vnoremenu PopUp.Paste "+P - vnoremenu PopUp.Delete "_x - nnoremenu PopUp.Select\ All ggVG - vnoremenu PopUp.Select\ All gg0oG$ - inoremenu PopUp.Select\ All <C-Home><C-O>VG - anoremenu PopUp.-1- <Nop> - anoremenu PopUp.How-to\ disable\ mouse <Cmd>help disable-mouse<CR> +The default "PopUp" menu is: >vim + vnoremenu PopUp.Cut "+x + vnoremenu PopUp.Copy "+y + anoremenu PopUp.Paste "+gP + vnoremenu PopUp.Paste "+P + vnoremenu PopUp.Delete "_x + nnoremenu PopUp.Select\ All ggVG + vnoremenu PopUp.Select\ All gg0oG$ + inoremenu PopUp.Select\ All <C-Home><C-O>VG + anoremenu PopUp.Inspect <Cmd>Inspect<CR> + anoremenu PopUp.-1- <Nop> + anoremenu PopUp.How-to\ disable\ mouse <Cmd>help disable-mouse<CR> < Showing What Menus Are Mapped To *showing-menus* diff --git a/runtime/doc/pi_health.txt b/runtime/doc/health.txt index bcc933d8b2..e879f11351 100644 --- a/runtime/doc/pi_health.txt +++ b/runtime/doc/health.txt @@ -1,11 +1,14 @@ -*pi_health.txt* Healthcheck framework +*health.txt* Nvim -Author: TJ DeVries <devries.timothyj@gmail.com> - Type |gO| to see the table of contents. + NVIM REFERENCE MANUAL + + + Type |gO| to see the table of contents. ============================================================================== -Introduction *health* +Checkhealth *health* + health.vim is a minimal framework to help users troubleshoot configuration and any other environment conditions that a plugin might care about. Nvim ships @@ -18,12 +21,11 @@ To run all healthchecks, use: >vim < Plugin authors are encouraged to write new healthchecks. |health-dev| -============================================================================== -Commands *health-commands* +Commands *health-commands* - *:che* *:checkhealth* + *:che* *:checkhealth* :che[ckhealth] Run all healthchecks. - *E5009* + *E5009* Nvim depends on |$VIMRUNTIME|, 'runtimepath' and 'packpath' to find the standard "runtime files" for syntax highlighting, filetype-specific behavior, and standard plugins (including @@ -33,7 +35,7 @@ Commands *health-commands* :che[ckhealth] {plugins} Run healthcheck(s) for one or more plugins. E.g. to run only the standard Nvim healthcheck: >vim - :checkhealth nvim + :checkhealth vim.health < To run the healthchecks for the "foo" and "bar" plugins (assuming they are on 'runtimepath' and they have implemented @@ -46,33 +48,8 @@ Commands *health-commands* :checkhealth vim.lsp vim.treesitter :checkhealth vim* < -============================================================================== -Functions *health-functions* *vim.health* - -The Lua "health" module can be used to create new healthchecks. To get started -see |health-dev|. -vim.health.start({name}) *vim.health.start()* - Starts a new report. Most plugins should call this only once, but if - you want different sections to appear in your report, call this once - per section. - -vim.health.info({msg}) *vim.health.info()* - Reports an informational message. - -vim.health.ok({msg}) *vim.health.ok()* - Reports a "success" message. - -vim.health.warn({msg} [, {advice}]) *vim.health.warn()* - Reports a warning. {advice} is an optional list of suggestions to - present to the user. - -vim.health.error({msg} [, {advice}]) *vim.health.error()* - Reports an error. {advice} is an optional list of suggestions to - present to the user. - -============================================================================== -Create a healthcheck *health-dev* +Create a healthcheck *health-dev* *vim.health* Healthchecks are functions that check the user environment, configuration, or any other prerequisites that a plugin cares about. Nvim ships with @@ -119,4 +96,39 @@ with your plugin name: >lua return M -vim:et:tw=78:ts=8:ft=help:fdm=marker +error({msg}, {...}) *vim.health.error()* + Reports an error. + + Parameters: ~ + • {msg} (`string`) + • {...} (`string|string[]`) Optional advice + +info({msg}) *vim.health.info()* + Reports an informational message. + + Parameters: ~ + • {msg} (`string`) + +ok({msg}) *vim.health.ok()* + Reports a "success" message. + + Parameters: ~ + • {msg} (`string`) + +start({name}) *vim.health.start()* + Starts a new report. Most plugins should call this only once, but if you + want different sections to appear in your report, call this once per + section. + + Parameters: ~ + • {name} (`string`) + +warn({msg}, {...}) *vim.health.warn()* + Reports a warning. + + Parameters: ~ + • {msg} (`string`) + • {...} (`string|string[]`) Optional advice + + + vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl: diff --git a/runtime/doc/hebrew.txt b/runtime/doc/hebrew.txt index e38385e13a..c19b4b9835 100644 --- a/runtime/doc/hebrew.txt +++ b/runtime/doc/hebrew.txt @@ -14,7 +14,7 @@ currently helping support these features. ------------------------------------------------------------------------------ Introduction -Hebrew-specific options are 'hkmap', 'hkmapp' 'keymap'=hebrew and 'aleph'. +Hebrew-specific 'keymap' values are "hebrew" and "hebrewp". Hebrew-useful options are 'delcombine', 'allowrevins', 'revins', 'rightleft' and 'rightleftcmd'. @@ -30,7 +30,7 @@ Details + 'rightleft' ('rl') sets window orientation to right-to-left. This means that the logical text 'ABC' will be displayed as 'CBA', and will start drawing at the right edge of the window, not the left edge. - + 'keymap' ('kmp') sets keyboard mapping. use values "hebrew" or "heprewp" + + 'keymap' ('kmp') sets keyboard mapping. use values "hebrew" or "hebrewp" (the latter option enables phonetic mapping) + 'delcombine' ('deco'), boolean, allows one to remove the niqud or te`amim by pressing 'x' on a character (with associated niqud). @@ -41,35 +41,23 @@ Details + Encoding: + Under Unix, ISO 8859-8 encoding (Hebrew letters codes: 224-250). + Under MS DOS, PC encoding (Hebrew letters codes: 128-154). - These are defaults, that can be overridden using the 'aleph' option. + You should prefer using UTF8, as it supports the combining-characters ('deco' does nothing if UTF8 encoding is not active). + Vim arguments: - + `vim -H file` starts editing a Hebrew file, i.e. 'rightleft' and 'hkmap' - are set. + + `vim -H file` starts editing a Hebrew file, i.e. 'rightleft' is set and + 'keymap' is set to "hebrew". + Keyboard: - + The 'allowrevins' option enables the CTRL-_ command in Insert mode and - in Command-line mode. + + The 'allowrevins' option enables the CTRL-_ command in Insert mode. - + CTRL-_ in insert/replace modes toggles 'revins' and 'hkmap' as follows: - - When in rightleft window, 'revins' is toggled, since - English will likely be inserted in this case. - - When in norightleft window, 'revins' is toggled, since Hebrew - will likely be inserted in this case. + + CTRL-_ in Insert mode toggles 'revins'. CTRL-_ moves the cursor to the end of the typed text. - + CTRL-_ in command mode only toggles keyboard mapping (see Bugs below). - This setting is independent of 'hkmap' option, which only applies to - insert/replace mode. - Note: On some keyboards, CTRL-_ is mapped to CTRL-?. - + Keyboard mapping while 'hkmap' is set (standard Israeli keyboard): + + Keyboard mapping while 'keymap' is "hebrew" (standard Israeli keyboard): q w e r t y u i o p / ' ק ר א ט ו ן ם פ @@ -80,11 +68,8 @@ Details z x c v b n m , . / ז ס ב ה נ מ צ ת ץ . - This is also the keymap when 'keymap=hebrew' is set. The advantage of - 'keymap' is that it works properly when using UTF8, e.g. it inserts the - correct characters; 'hkmap' does not. The 'keymap' keyboard can also - insert niqud and te`amim. To see what those mappings are, look at the - keymap file 'hebrew.vim' etc. + The 'keymap' keyboard can also insert niqud and te`amim. To see what + those mappings are, look at the keymap file hebrew.vim etc. Typing backwards @@ -102,13 +87,7 @@ If the 'showmode' option is set, "-- REVERSE INSERT --" will be shown in the status line when reverse Insert mode is active. When the 'allowrevins' option is set, reverse Insert mode can be also entered -via CTRL-_, which has some extra functionality: First, keyboard mapping is -changed according to the window orientation -- if in a left-to-right window, -'revins' is used to enter Hebrew text, so the keyboard changes to Hebrew -('hkmap' is set); if in a right-to-left window, 'revins' is used to enter -English text, so the keyboard changes to English ('hkmap' is reset). Second, -when exiting 'revins' via CTRL-_, the cursor moves to the end of the typed -text (if possible). +and exited via CTRL-_. ------------------------------------------------------------------------------ diff --git a/runtime/doc/help.txt b/runtime/doc/help.txt index 7545d2c621..43f80101ed 100644 --- a/runtime/doc/help.txt +++ b/runtime/doc/help.txt @@ -114,6 +114,7 @@ API (EXTENSIBILITY/SCRIPTING/PLUGINS) |vimscript-functions| Vimscript functions |testing.txt| Vimscript testing functions |remote-plugin| Nvim remote plugins +|health| Health checking ------------------------------------------------------------------------------ PROGRAMMING LANGUAGE SUPPORT @@ -175,7 +176,6 @@ DEVELOPING NVIM Standard plugins ~ *standard-plugin-list* |pi_gzip.txt| Reading and writing compressed files -|pi_health.txt| Healthcheck framework |pi_msgpack.txt| msgpack utilities |pi_netrw.txt| Reading and writing files over a network |pi_paren.txt| Highlight matching parens diff --git a/runtime/doc/helphelp.txt b/runtime/doc/helphelp.txt index efcc6afae9..46b3ab507d 100644 --- a/runtime/doc/helphelp.txt +++ b/runtime/doc/helphelp.txt @@ -305,7 +305,7 @@ Hints for translators: using the "tag@en" notation. - Make a package with all the files and the tags file available for download. Users can drop it in one of the "doc" directories and start use it. - Report this to Bram, so that he can add a link on www.vim.org. + Report to the development team, so they can add a link on www.vim.org. - Use the |:helptags| command to generate the tags files. It will find all languages in the specified directory. diff --git a/runtime/doc/indent.txt b/runtime/doc/indent.txt index c20143bc6e..a890d531ac 100644 --- a/runtime/doc/indent.txt +++ b/runtime/doc/indent.txt @@ -1232,5 +1232,5 @@ By default, the yaml indent script does not try to detect multiline scalars. If you want to enable this, set the following variable: > let g:yaml_indent_multiline_scalar = 1 - +< vim:tw=78:ts=8:noet:ft=help:norl: diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt index c1a8aec40e..79f10b33f1 100644 --- a/runtime/doc/index.txt +++ b/runtime/doc/index.txt @@ -92,8 +92,7 @@ tag char action in Insert mode ~ CTRL-\ others not used |i_CTRL-]| CTRL-] trigger abbreviation |i_CTRL-^| CTRL-^ toggle use of |:lmap| mappings -|i_CTRL-_| CTRL-_ When 'allowrevins' set: change language - (Hebrew) +|i_CTRL-_| CTRL-_ When 'allowrevins' set: toggle 'revins' <Space> to '~' not used, except '0' and '^' followed by CTRL-D @@ -699,7 +698,6 @@ tag char note action in Normal mode ~ tag char note action in Normal mode ~ ------------------------------------------------------------------------------ ~ -g_CTRL-A g CTRL-A dump a memory profile |g_CTRL-G| g CTRL-G show information about current cursor position |g_CTRL-H| g CTRL-H start Select block mode @@ -1073,8 +1071,6 @@ tag command action in Command-line editing mode ~ CTRL-\ others not used |c_CTRL-]| CTRL-] trigger abbreviation |c_CTRL-^| CTRL-^ toggle use of |:lmap| mappings -|c_CTRL-_| CTRL-_ when 'allowrevins' set: change language - (Hebrew) |c_<Del>| <Del> delete the character under the cursor |c_<Left>| <Left> cursor left diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt index 34affb22e9..91b0d41f1c 100644 --- a/runtime/doc/insert.txt +++ b/runtime/doc/insert.txt @@ -225,11 +225,7 @@ CTRL-Y Insert the character which is above the cursor. able to copy characters from a long line. *i_CTRL-_* -CTRL-_ Switch between insert direction, by toggling 'revins', as follows: - - When in a rightleft window, 'revins' is toggled, - since English will likely be inserted in this case. - - When in a norightleft window, 'revins' is toggled, - since a rightleft language will likely be inserted in this case. +CTRL-_ Switch between insert direction, by toggling 'revins'. CTRL-_ moves the cursor to the end of the typed text. diff --git a/runtime/doc/intro.txt b/runtime/doc/intro.txt index c9211291d0..4c757cc1f6 100644 --- a/runtime/doc/intro.txt +++ b/runtime/doc/intro.txt @@ -69,11 +69,11 @@ If Nvim crashes, try to get a backtrace. See |debug.txt|. Sponsor Vim/Nvim development *sponsor* *register* Fixing bugs and adding new features takes a lot of time and effort. To show -your appreciation for the work and motivate Bram and others to continue -working on Vim please send a donation. +your appreciation for the work and motivate developers to continue working on +Vim please send a donation. -Since Bram is back to a paid job the money will now be used to help children -in Uganda. See |uganda|. But at the same time donations increase Bram's +The money you donated will be mainly used to help children in Uganda. See +|uganda|. But at the same time donations increase the development team motivation to keep working on Vim! For the most recent information about sponsoring look on the Vim web site: diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index eb37cb2a6f..50fffca497 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -12,7 +12,7 @@ enhanced LSP tools. https://microsoft.github.io/language-server-protocol/ -LSP facilitates features like go-to-definition, find-references, hover, +LSP facilitates features like go-to-definition, find references, hover, completion, rename, format, refactor, etc., using semantic whole-project analysis (unlike |ctags|). @@ -25,26 +25,36 @@ Nvim provides an LSP client, but the servers are provided by third parties. Follow these steps to get LSP features: 1. Install language servers using your package manager or by following the - upstream installation instruction. You can find language servers here: + upstream installation instructions. You can find language servers here: https://microsoft.github.io/language-server-protocol/implementors/servers/ -2. Configure the LSP client per language server. See |vim.lsp.start()| or use - this minimal example as a guide: >lua - - vim.lsp.start({ - name = 'my-server-name', - cmd = {'name-of-language-server-executable'}, - root_dir = vim.fs.dirname(vim.fs.find({'setup.py', 'pyproject.toml'}, { upward = true })[1]), +2. Use |vim.lsp.start()| to start the LSP server (or attach to an existing + one) when a file is opened. Example: >lua + -- Create an event handler for the FileType autocommand + vim.api.nvim_create_autocmd('FileType', { + -- This handler will fire when the buffer's 'filetype' is "python" + pattern = 'python', + callback = function(ev) + vim.lsp.start({ + name = 'my-server-name', + cmd = {'name-of-language-server-executable', '--option', 'arg1', 'arg2'}, + + -- Set the "root directory" to the parent directory of the file in the + -- current buffer (`ev.buf`) that contains either a "setup.py" or a + -- "pyproject.toml" file. Files that share a root directory will reuse + -- the connection to the same LSP server. + root_dir = vim.fs.root(ev.buf, {'setup.py', 'pyproject.toml'}), + }) + end, }) < -3. Check that the server attached to the buffer: > - :lua =vim.lsp.get_clients() +3. Check that the buffer is attached to the server: >vim + :checkhealth lsp -4. Configure keymaps and autocmds to use LSP features. See |lsp-config|. +4. (Optional) Configure keymaps and autocommands to use LSP features. |lsp-config| - *lsp-config* *lsp-defaults* -When the LSP client starts it enables diagnostics |vim.diagnostic| (see +When the Nvim LSP client starts it enables diagnostics |vim.diagnostic| (see |vim.diagnostic.config()| to customize). It also sets various default options, listed below, if (1) the language server supports the functionality and (2) the options are empty or were set by the builtin runtime (ftplugin) files. The @@ -57,51 +67,47 @@ options are not restored when the LSP client is stopped or detached. |CTRL-W_}| to utilize the language server. - 'formatexpr' is set to |vim.lsp.formatexpr()|, so you can format lines via |gq| if the language server supports it. - - To opt out of this use |gw| instead of gq, or set 'formatexpr' on LspAttach. + - To opt out of this use |gw| instead of gq, or clear 'formatexpr' on |LspAttach|. - |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* +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()| +- 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 +|vim.keymap.del()| or |:unmap| (see also |gr-default|). + *lsp-defaults-disable* -To override the above defaults, set or unset the options on |LspAttach|: >lua +To override or delete any of the above defaults, set or unset the options on +|LspAttach|: >lua + vim.api.nvim_create_autocmd('LspAttach', { callback = function(ev) vim.bo[ev.buf].formatexpr = nil vim.bo[ev.buf].omnifunc = nil - vim.keymap.del("n", "K", { buffer = ev.buf }) - end, - }) - -To use other LSP features like hover, rename, etc. you can set other keymaps -on |LspAttach|. Example: >lua - vim.api.nvim_create_autocmd('LspAttach', { - callback = function(args) - vim.keymap.set('n', 'K', vim.lsp.buf.hover, { buffer = args.buf }) + vim.keymap.del('n', 'K', { buffer = ev.buf }) end, }) +< + *lsp-config* +To use other LSP features, set keymaps on |LspAttach|. Not all language +servers provide the same capabilities. To ensure you only set keymaps if the +language server supports a feature, guard keymaps behind capability checks. +Example: >lua -The most common functions are: - -- |vim.lsp.buf.hover()| -- |vim.lsp.buf.format()| -- |vim.lsp.buf.references()| -- |vim.lsp.buf.implementation()| -- |vim.lsp.buf.code_action()| - - -Not all language servers provide the same capabilities. To ensure you only set -keymaps if the language server supports a feature, you can guard the keymap -calls behind capability checks: ->lua vim.api.nvim_create_autocmd('LspAttach', { callback = function(args) local client = vim.lsp.get_client_by_id(args.data.client_id) - if client.server_capabilities.hoverProvider then - vim.keymap.set('n', 'K', vim.lsp.buf.hover, { buffer = args.buf }) + if client.supports_method('textDocument/implementation') then + -- Create a keymap for vim.lsp.buf.implementation end end, }) < - To learn what capabilities are available you can run the following command in a buffer with a started LSP client: >vim @@ -182,6 +188,7 @@ won't run if your server doesn't support them. - textDocument/hover - textDocument/implementation* - textDocument/inlayHint +- textDocument/prepareTypeHierarchy - textDocument/publishDiagnostics - textDocument/rangeFormatting - textDocument/references @@ -190,6 +197,8 @@ won't run if your server doesn't support them. - textDocument/semanticTokens/full/delta - textDocument/signatureHelp - textDocument/typeDefinition* +- typeHierarchy/subtypes +- typeHierarchy/supertypes - window/logMessage - window/showMessage - window/showDocument @@ -454,23 +463,44 @@ You probably want these inside a |ColorScheme| autocommand. Use |LspTokenUpdate| and |vim.lsp.semantic_tokens.highlight_token()| for more complex highlighting. -The following groups are linked by default to standard |group-name|s: - -@lsp.type.class Structure -@lsp.type.decorator Function -@lsp.type.enum Structure -@lsp.type.enumMember Constant -@lsp.type.function Function -@lsp.type.interface Structure -@lsp.type.macro Macro -@lsp.type.method Function -@lsp.type.namespace Structure -@lsp.type.parameter Identifier -@lsp.type.property Identifier -@lsp.type.struct Structure -@lsp.type.type Type -@lsp.type.typeParameter TypeDef -@lsp.type.variable Identifier +The following is a list of standard captures used in queries for Nvim, +highlighted according to the current colorscheme (use |:Inspect| on one to see +the exact definition): + +@lsp.type.class Identifiers that declare or reference a class type +@lsp.type.comment Tokens that represent a comment +@lsp.type.decorator Identifiers that declare or reference decorators and annotations +@lsp.type.enum Identifiers that declare or reference an enumeration type +@lsp.type.enumMember Identifiers that declare or reference an enumeration property, constant, or member +@lsp.type.event Identifiers that declare an event property +@lsp.type.function Identifiers that declare a function +@lsp.type.interface Identifiers that declare or reference an interface type +@lsp.type.keyword Tokens that represent a language keyword +@lsp.type.macro Identifiers that declare a macro +@lsp.type.method Identifiers that declare a member function or method +@lsp.type.modifier Tokens that represent a modifier +@lsp.type.namespace Identifiers that declare or reference a namespace, module, or package +@lsp.type.number Tokens that represent a number literal +@lsp.type.operator Tokens that represent an operator +@lsp.type.parameter Identifiers that declare or reference a function or method parameters +@lsp.type.property Identifiers that declare or reference a member property, member field, or member variable +@lsp.type.regexp Tokens that represent a regular expression literal +@lsp.type.string Tokens that represent a string literal +@lsp.type.struct Identifiers that declare or reference a struct type +@lsp.type.type Identifiers that declare or reference a type that is not covered above +@lsp.type.typeParameter Identifiers that declare or reference a type parameter +@lsp.type.variable Identifiers that declare or reference a local or global variable + +@lsp.mod.abstract Types and member functions that are abstract +@lsp.mod.async Functions that are marked async +@lsp.mod.declaration Declarations of symbols +@lsp.mod.defaultLibrary Symbols that are part of the standard library +@lsp.mod.definition Definitions of symbols, for example, in header files +@lsp.mod.deprecated Symbols that should no longer be used +@lsp.mod.documentation Occurrences of symbols in documentation +@lsp.mod.modification Variable references where the variable is assigned to +@lsp.mod.readonly Readonly variables and member fields (constants) +@lsp.mod.static Class members (static members) ============================================================================== EVENTS *lsp-events* @@ -533,14 +563,14 @@ LspNotify *LspNotify* LspProgress *LspProgress* Upon receipt of a progress notification from the server. Notifications can be polled from a `progress` ring buffer of a |vim.lsp.Client| or use - |vim.lsp.status()| to get an aggregate message + |vim.lsp.status()| to get an aggregate message. If the server sends a "work done progress", the `pattern` is set to `kind` (one of `begin`, `report` or `end`). When used from Lua, the event contains a `data` table with `client_id` and - `result` properties. `result` will contain the request params sent by the - server. + `params` properties. `params` will contain the request params sent by the + server (see `lsp.ProgressParams`). Example: >vim autocmd LspProgress * redrawstatus @@ -683,8 +713,8 @@ buf_request_sync({bufnr}, {method}, {params}, {timeout_ms}) milliseconds to wait for a result. Return (multiple): ~ - (`table<integer, {err: lsp.ResponseError, result: any}>?`) result Map - of client_id:request_result. + (`table<integer, {error: lsp.ResponseError?, result: any}>?`) result + Map of client_id:request_result. (`string?`) err On timeout, cancel, or error, `err` is a string describing the failure reason, and `result` is nil. @@ -812,7 +842,7 @@ start({config}, {opts}) *vim.lsp.start()* vim.lsp.start({ name = 'my-server-name', cmd = {'name-of-language-server-executable'}, - root_dir = vim.fs.dirname(vim.fs.find({'pyproject.toml', 'setup.py'}, { upward = true })[1]), + root_dir = vim.fs.root(0, {'pyproject.toml', 'setup.py'}), }) < @@ -824,7 +854,7 @@ 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.find()| and |vim.fs.dirname()| to detect the root by traversing + |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. • `workspace_folders` list of `{ uri:string, name: string }` tables @@ -845,12 +875,14 @@ start({config}, {opts}) *vim.lsp.start()* |vim.lsp.ClientConfig|. • {opts} (`table?`) Optional keyword arguments • {reuse_client} - (`fun(client: vim.lsp.Client, config: table): boolean`) + (`fun(client: vim.lsp.Client, config: vim.lsp.ClientConfig): boolean`) Predicate used to decide if a client should be re-used. Used on all running clients. The default implementation re-uses a client if name and root_dir matches. • {bufnr} (`integer`) Buffer handle to attach to if starting or re-using a client (0 for current). + • {silent}? (`boolean`) Suppress error reporting if the LSP + server fails to start (default false). Return: ~ (`integer?`) client_id @@ -862,10 +894,11 @@ start_client({config}) *vim.lsp.start_client()* • {config} (`vim.lsp.ClientConfig`) Configuration for the server. See |vim.lsp.ClientConfig|. - Return: ~ + Return (multiple): ~ (`integer?`) client_id |vim.lsp.get_client_by_id()| Note: client may not be fully initialized. Use `on_init` to do any actions once the client has been initialized. + (`string?`) Error message, if any status() *vim.lsp.status()* Consumes the latest progress messages from all clients and formats them as @@ -886,8 +919,8 @@ stop_client({client_id}, {force}) *vim.lsp.stop_client()* for this client, then force-shutdown is attempted. Parameters: ~ - • {client_id} (`integer|vim.lsp.Client`) id or |vim.lsp.Client| object, - or list thereof + • {client_id} (`integer|integer[]|vim.lsp.Client[]`) id, list of id's, + or list of |vim.lsp.Client| objects • {force} (`boolean?`) shutdown forcefully tagfunc({pattern}, {flags}) *vim.lsp.tagfunc()* @@ -978,9 +1011,9 @@ Lua module: vim.lsp.client *lsp-client* case-sensitive. • {flags} (`table`) A table with flags for the client. The current (experimental) flags are: - • {allow_incremental_sync}? (`boolean`) Allow - using incremental sync for buffer edits - (defailt: `true`) + • {allow_incremental_sync}? (`boolean`, + default: `true`) Allow using incremental + sync for buffer edits • {debounce_text_changes} (`integer`, default: `150`) Debounce `didChange` notifications to the server by the given number in @@ -995,7 +1028,7 @@ Lua module: vim.lsp.client *lsp-client* • {capabilities} (`lsp.ClientCapabilities`) The capabilities provided by the client (editor or tool) • {dynamic_capabilities} (`lsp.DynamicCapabilities`) - • {request} (`fun(method: string, params: table?, handler: lsp.Handler?, bufnr: integer): boolean, integer?`) + • {request} (`fun(method: string, params: table?, handler: lsp.Handler?, bufnr: integer?): boolean, integer?`) Sends a request to the server. This is a thin wrapper around {client.rpc.request} with some additional checking. If {handler} is not @@ -1049,7 +1082,7 @@ Lua module: vim.lsp.client *lsp-client* *vim.lsp.ClientConfig* Fields: ~ - • {cmd} (`string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient?`) + • {cmd} (`string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient`) command string[] that launches the language server (treated as in |jobstart()|, must be absolute or on `$PATH`, shell constructs like @@ -1149,9 +1182,9 @@ Lua module: vim.lsp.client *lsp-client* initialize request. Invalid/empty values will • {flags}? (`table`) A table with flags for the client. The current (experimental) flags are: - • {allow_incremental_sync}? (`boolean`) Allow - using incremental sync for buffer edits - (defailt: `true`) + • {allow_incremental_sync}? (`boolean`, default: + `true`) Allow using incremental sync for + buffer edits • {debounce_text_changes} (`integer`, default: `150`) Debounce `didChange` notifications to the server by the given number in @@ -1187,12 +1220,11 @@ Lua module: vim.lsp.buf *lsp-buf* vim.lsp.buf.references(nil, { on_list = on_list }) < - If you prefer loclist do something like this: >lua - local function on_list(options) - vim.fn.setloclist(0, {}, ' ', options) - vim.cmd.lopen() - end + If you prefer loclist instead of qflist: >lua + vim.lsp.buf.definition({ loclist = true }) + vim.lsp.buf.references(nil, { loclist = true }) < + • {loclist}? (`boolean`) *vim.lsp.LocationOpts* Extends: |vim.lsp.ListOpts| @@ -1221,30 +1253,30 @@ add_workspace_folder({workspace_folder}) clear_references() *vim.lsp.buf.clear_references()* Removes document highlights from current buffer. -code_action({options}) *vim.lsp.buf.code_action()* +code_action({opts}) *vim.lsp.buf.code_action()* Selects a code action available at the current cursor position. Parameters: ~ - • {options} (`table?`) A table with the following fields: - • {context}? (`lsp.CodeActionContext`) Corresponds to - `CodeActionContext` of the LSP specification: - • {diagnostics}? (`table`) LSP `Diagnostic[]`. Inferred - from the current position if not provided. - • {only}? (`table`) List of LSP `CodeActionKind`s used to - filter the code actions. Most language servers support - values like `refactor` or `quickfix`. - • {triggerKind}? (`integer`) The reason why code actions - were requested. - • {filter}? (`fun(x: lsp.CodeAction|lsp.Command):boolean`) - Predicate taking an `CodeAction` and returning a boolean. - • {apply}? (`boolean`) When set to `true`, and there is - just one remaining action (after filtering), the action - is applied without user query. - • {range}? (`{start: integer[], end: integer[]}`) Range for - which code actions should be requested. If in visual mode - this defaults to the active selection. Table must contain - `start` and `end` keys with {row,col} tuples using - mark-like indexing. See |api-indexing| + • {opts} (`table?`) A table with the following fields: + • {context}? (`lsp.CodeActionContext`) Corresponds to + `CodeActionContext` of the LSP specification: + • {diagnostics}? (`table`) LSP `Diagnostic[]`. Inferred from + the current position if not provided. + • {only}? (`table`) List of LSP `CodeActionKind`s used to + filter the code actions. Most language servers support + values like `refactor` or `quickfix`. + • {triggerKind}? (`integer`) The reason why code actions + were requested. + • {filter}? (`fun(x: lsp.CodeAction|lsp.Command):boolean`) + Predicate taking an `CodeAction` and returning a boolean. + • {apply}? (`boolean`) When set to `true`, and there is just + one remaining action (after filtering), the action is + applied without user query. + • {range}? (`{start: integer[], end: integer[]}`) Range for + which code actions should be requested. If in visual mode + this defaults to the active selection. Table must contain + `start` and `end` keys with {row,col} tuples using mark-like + indexing. See |api-indexing| See also: ~ • https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction @@ -1263,7 +1295,7 @@ completion({context}) *vim.lsp.buf.completion()* See also: ~ • vim.lsp.protocol.CompletionTriggerKind -declaration({options}) *vim.lsp.buf.declaration()* +declaration({opts}) *vim.lsp.buf.declaration()* Jumps to the declaration of the symbol under the cursor. Note: ~ @@ -1271,13 +1303,13 @@ declaration({options}) *vim.lsp.buf.declaration()* |vim.lsp.buf.definition()| instead. Parameters: ~ - • {options} (`vim.lsp.LocationOpts?`) See |vim.lsp.LocationOpts|. + • {opts} (`vim.lsp.LocationOpts?`) See |vim.lsp.LocationOpts|. -definition({options}) *vim.lsp.buf.definition()* +definition({opts}) *vim.lsp.buf.definition()* Jumps to the definition of the symbol under the cursor. Parameters: ~ - • {options} (`vim.lsp.LocationOpts?`) See |vim.lsp.LocationOpts|. + • {opts} (`vim.lsp.LocationOpts?`) See |vim.lsp.LocationOpts|. document_highlight() *vim.lsp.buf.document_highlight()* Send request to the server to resolve document highlights for the current @@ -1293,11 +1325,11 @@ document_highlight() *vim.lsp.buf.document_highlight()* highlights. |hl-LspReferenceText| |hl-LspReferenceRead| |hl-LspReferenceWrite| -document_symbol({options}) *vim.lsp.buf.document_symbol()* +document_symbol({opts}) *vim.lsp.buf.document_symbol()* Lists all symbols in the current buffer in the quickfix window. Parameters: ~ - • {options} (`vim.lsp.ListOpts?`) See |vim.lsp.ListOpts|. + • {opts} (`vim.lsp.ListOpts?`) See |vim.lsp.ListOpts|. execute_command({command_params}) *vim.lsp.buf.execute_command()* Executes an LSP server command. @@ -1308,53 +1340,53 @@ execute_command({command_params}) *vim.lsp.buf.execute_command()* See also: ~ • https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand -format({options}) *vim.lsp.buf.format()* +format({opts}) *vim.lsp.buf.format()* Formats a buffer using the attached (and optionally filtered) language server clients. Parameters: ~ - • {options} (`table?`) A table with the following fields: - • {formatting_options}? (`table`) Can be used to specify - FormattingOptions. Some unspecified options will be - automatically derived from the current Nvim options. See - https://microsoft.github.io/language-server-protocol/specification/#formattingOptions - • {timeout_ms}? (`integer`, default: `1000`) Time in - milliseconds to block for formatting requests. No effect - if async=true. - • {bufnr}? (`integer`, default: current buffer) Restrict - formatting to the clients attached to the given buffer. - • {filter}? (`fun(client: vim.lsp.Client): boolean?`) - Predicate used to filter clients. Receives a client as - argument and must return a boolean. Clients matching the - predicate are included. Example: >lua - -- Never request typescript-language-server for formatting - vim.lsp.buf.format { - filter = function(client) return client.name ~= "tsserver" end - } + • {opts} (`table?`) A table with the following fields: + • {formatting_options}? (`table`) Can be used to specify + FormattingOptions. Some unspecified options will be + automatically derived from the current Nvim options. See + https://microsoft.github.io/language-server-protocol/specification/#formattingOptions + • {timeout_ms}? (`integer`, default: `1000`) Time in + milliseconds to block for formatting requests. No effect if + async=true. + • {bufnr}? (`integer`, default: current buffer) Restrict + formatting to the clients attached to the given buffer. + • {filter}? (`fun(client: vim.lsp.Client): boolean?`) + Predicate used to filter clients. Receives a client as + argument and must return a boolean. Clients matching the + predicate are included. Example: >lua + -- Never request typescript-language-server for formatting + vim.lsp.buf.format { + filter = function(client) return client.name ~= "tsserver" end + } < - • {async}? (`boolean`, default: false) If true the method - won't block. Editing the buffer while formatting - asynchronous can lead to unexpected changes. - • {id}? (`integer`) Restrict formatting to the client with - ID (client.id) matching this field. - • {name}? (`string`) Restrict formatting to the client with - name (client.name) matching this field. - • {range}? (`{start:integer[],end:integer[]}`, default: - current selection in visual mode, `nil` in other modes, - formatting the full buffer) Range to format. Table must - contain `start` and `end` keys with {row,col} tuples - using (1,0) indexing. + • {async}? (`boolean`, default: false) If true the method + won't block. Editing the buffer while formatting + asynchronous can lead to unexpected changes. + • {id}? (`integer`) Restrict formatting to the client with ID + (client.id) matching this field. + • {name}? (`string`) Restrict formatting to the client with + name (client.name) matching this field. + • {range}? (`{start:integer[],end:integer[]}`, default: + current selection in visual mode, `nil` in other modes, + formatting the full buffer) Range to format. Table must + contain `start` and `end` keys with {row,col} tuples using + (1,0) indexing. hover() *vim.lsp.buf.hover()* Displays hover information about the symbol under the cursor in a floating window. Calling the function twice will jump into the floating window. -implementation({options}) *vim.lsp.buf.implementation()* +implementation({opts}) *vim.lsp.buf.implementation()* Lists all the implementations for the symbol under the cursor in the quickfix window. Parameters: ~ - • {options} (`vim.lsp.LocationOpts?`) See |vim.lsp.LocationOpts|. + • {opts} (`vim.lsp.LocationOpts?`) See |vim.lsp.LocationOpts|. incoming_calls() *vim.lsp.buf.incoming_calls()* Lists all the call sites of the symbol under the cursor in the |quickfix| @@ -1369,13 +1401,13 @@ outgoing_calls() *vim.lsp.buf.outgoing_calls()* |quickfix| window. If the symbol can resolve to multiple items, the user can pick one in the |inputlist()|. -references({context}, {options}) *vim.lsp.buf.references()* +references({context}, {opts}) *vim.lsp.buf.references()* Lists all the references to the symbol under the cursor in the quickfix window. Parameters: ~ • {context} (`table?`) Context for the request - • {options} (`vim.lsp.ListOpts?`) See |vim.lsp.ListOpts|. + • {opts} (`vim.lsp.ListOpts?`) See |vim.lsp.ListOpts|. See also: ~ • https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references @@ -1388,13 +1420,13 @@ remove_workspace_folder({workspace_folder}) Parameters: ~ • {workspace_folder} (`string?`) -rename({new_name}, {options}) *vim.lsp.buf.rename()* +rename({new_name}, {opts}) *vim.lsp.buf.rename()* Renames all references to the symbol under the cursor. Parameters: ~ • {new_name} (`string?`) If not provided, the user will be prompted for a new name using |vim.ui.input()|. - • {options} (`table?`) Additional options: + • {opts} (`table?`) Additional options: • {filter}? (`fun(client: vim.lsp.Client): boolean?`) Predicate used to filter clients. Receives a client as argument and must return a boolean. Clients matching the @@ -1407,13 +1439,21 @@ signature_help() *vim.lsp.buf.signature_help()* Displays signature information about the symbol under the cursor in a floating window. -type_definition({options}) *vim.lsp.buf.type_definition()* +type_definition({opts}) *vim.lsp.buf.type_definition()* Jumps to the definition of the type of the symbol under the cursor. Parameters: ~ - • {options} (`vim.lsp.LocationOpts?`) See |vim.lsp.LocationOpts|. + • {opts} (`vim.lsp.LocationOpts?`) See |vim.lsp.LocationOpts|. -workspace_symbol({query}, {options}) *vim.lsp.buf.workspace_symbol()* +typehierarchy({kind}) *vim.lsp.buf.typehierarchy()* + Lists all the subtypes or supertypes of the symbol under the cursor in the + |quickfix| window. If the symbol can resolve to multiple items, the user + can pick one using |vim.ui.select()|. + + Parameters: ~ + • {kind} (`"subtypes"|"supertypes"`) + +workspace_symbol({query}, {opts}) *vim.lsp.buf.workspace_symbol()* Lists all symbols in the current workspace in the quickfix window. The list is filtered against {query}; if the argument is omitted from the @@ -1421,8 +1461,8 @@ workspace_symbol({query}, {options}) *vim.lsp.buf.workspace_symbol()* string means no filtering is done. Parameters: ~ - • {query} (`string?`) optional - • {options} (`vim.lsp.ListOpts?`) See |vim.lsp.ListOpts|. + • {query} (`string?`) optional + • {opts} (`vim.lsp.ListOpts?`) See |vim.lsp.ListOpts|. ============================================================================== @@ -1567,19 +1607,18 @@ save({lenses}, {bufnr}, {client_id}) *vim.lsp.codelens.save()* ============================================================================== Lua module: vim.lsp.inlay_hint *lsp-inlay_hint* -enable({bufnr}, {enable}) *vim.lsp.inlay_hint.enable()* - Enables or disables inlay hints for a buffer. +enable({enable}, {filter}) *vim.lsp.inlay_hint.enable()* + Enables or disables inlay hints for the {filter}ed scope. To "toggle", pass the inverse of `is_enabled()`: >lua - vim.lsp.inlay_hint.enable(0, not vim.lsp.inlay_hint.is_enabled()) + vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled()) < - Note: ~ - • This API is pre-release (unstable). - Parameters: ~ - • {bufnr} (`integer?`) Buffer handle, or 0 or nil for current • {enable} (`boolean?`) true/nil to enable, false to disable + • {filter} (`table?`) Optional filters |kwargs|, or `nil` for all. + • {bufnr} (`integer?`) Buffer number, or 0 for current + buffer, or nil for all. get({filter}) *vim.lsp.inlay_hint.get()* Get the list of inlay hints, (optionally) restricted by buffer or range. @@ -1588,7 +1627,8 @@ get({filter}) *vim.lsp.inlay_hint.get()* local hint = vim.lsp.inlay_hint.get({ bufnr = 0 })[1] -- 0 for current buffer local client = vim.lsp.get_client_by_id(hint.client_id) - resolved_hint = client.request_sync('inlayHint/resolve', hint.inlay_hint, 100, 0).result + local resp = client.request_sync('inlayHint/resolve', hint.inlay_hint, 100, 0) + local resolved_hint = assert(resp and resp.result, resp.err) vim.lsp.util.apply_text_edits(resolved_hint.textEdits, 0, client.encoding) location = resolved_hint.label[1].location @@ -1598,9 +1638,6 @@ get({filter}) *vim.lsp.inlay_hint.get()* }) < - Note: ~ - • This API is pre-release (unstable). - Parameters: ~ • {filter} (`table?`) Optional filters |kwargs|: • {bufnr} (`integer?`) @@ -1612,13 +1649,13 @@ get({filter}) *vim.lsp.inlay_hint.get()* • {client_id} (`integer`) • {inlay_hint} (`lsp.InlayHint`) -is_enabled({bufnr}) *vim.lsp.inlay_hint.is_enabled()* - - Note: ~ - • This API is pre-release (unstable). +is_enabled({filter}) *vim.lsp.inlay_hint.is_enabled()* + Query whether inlay hint is enabled in the {filter}ed scope Parameters: ~ - • {bufnr} (`integer?`) Buffer handle, or 0 or nil for current + • {filter} (`table`) Optional filters |kwargs|, or `nil` for all. + • {bufnr} (`integer?`) Buffer number, or 0 for current + buffer, or nil for all. Return: ~ (`boolean`) @@ -1668,9 +1705,10 @@ highlight_token({token}, {bufnr}, {client_id}, {hl_group}, {opts}) use inside |LspTokenUpdate| callbacks. Parameters: ~ - • {token} (`table`) a semantic token, found as `args.data.token` in - |LspTokenUpdate|. - • {bufnr} (`integer`) the buffer to highlight + • {token} (`table`) A semantic token, found as `args.data.token` in + |LspTokenUpdate| + • {bufnr} (`integer`) The buffer to highlight, or `0` for current + buffer • {client_id} (`integer`) The ID of the |vim.lsp.Client| • {hl_group} (`string`) Highlight group name • {opts} (`table?`) Optional parameters: @@ -1691,8 +1729,8 @@ start({bufnr}, {client_id}, {opts}) *vim.lsp.semantic_tokens.start()* < Parameters: ~ - • {bufnr} (`integer`) - • {client_id} (`integer`) + • {bufnr} (`integer`) Buffer number, or `0` for current buffer + • {client_id} (`integer`) The ID of the |vim.lsp.Client| • {opts} (`table?`) Optional keyword arguments • debounce (integer, default: 200): Debounce token requests to the server by the given number in @@ -1708,8 +1746,8 @@ stop({bufnr}, {client_id}) *vim.lsp.semantic_tokens.stop()* from the buffer. Parameters: ~ - • {bufnr} (`integer`) - • {client_id} (`integer`) + • {bufnr} (`integer`) Buffer number, or `0` for current buffer + • {client_id} (`integer`) The ID of the |vim.lsp.Client| ============================================================================== @@ -2096,7 +2134,7 @@ rename({old_fname}, {new_fname}, {opts}) *vim.lsp.util.rename()* It deletes existing buffers that conflict with the renamed file name only when • `opts` requests overwriting; or - • the conflicting buffers are not loaded, so that deleting thme does not + • the conflicting buffers are not loaded, so that deleting them does not result in data loss. Parameters: ~ @@ -2208,32 +2246,20 @@ Lua module: vim.lsp.rpc *lsp-rpc* • {terminate} (`fun()`) -connect({host}, {port}) *vim.lsp.rpc.connect()* - Create a LSP RPC client factory that connects via TCP to the given host - and port. - - Return a function that can be passed to the `cmd` field for - |vim.lsp.start_client()| or |vim.lsp.start()|. - - Parameters: ~ - • {host} (`string`) host to connect to - • {port} (`integer`) port to connect to - - Return: ~ - (`fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient`) - - *vim.lsp.rpc.domain_socket_connect()* -domain_socket_connect({pipe_path}) - Create a LSP RPC client factory that connects via named pipes (Windows) or - unix domain sockets (Unix) to the given pipe_path (file path on Unix and - name on Windows). +connect({host_or_path}, {port}) *vim.lsp.rpc.connect()* + Create a LSP RPC client factory that connects to either: + • a named pipe (windows) + • a domain socket (unix) + • a host and port via TCP Return a function that can be passed to the `cmd` field for |vim.lsp.start_client()| or |vim.lsp.start()|. Parameters: ~ - • {pipe_path} (`string`) file path of the domain socket (Unix) or name - of the named pipe (Windows) to connect to + • {host_or_path} (`string`) host to connect to or path to a pipe/domain + socket + • {port} (`integer?`) TCP port to connect to. If absent the + first argument must be a pipe Return: ~ (`fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient`) @@ -2318,7 +2344,7 @@ start({cmd}, {dispatchers}, {extra_spawn_params}) *vim.lsp.rpc.start()* See |vim.system()| Return: ~ - (`vim.lsp.rpc.PublicClient?`) Client RPC object, with these methods: + (`vim.lsp.rpc.PublicClient`) Client RPC object, with these methods: • `notify()` |vim.lsp.rpc.notify()| • `request()` |vim.lsp.rpc.request()| • `is_closing()` returns a boolean indicating if the RPC is closing. diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index 367b5c36d2..3d8453c5a2 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -34,10 +34,11 @@ Nvim ever ships with Lua 5.4+, a Lua 5.1 compatibility shim will be provided so that old plugins continue to work transparently. *lua-luajit* -Nvim is built with luajit on platforms which support it, which provides -extra functionality. Lua code in |init.lua| and plugins can assume its presence -on installations on common platforms. For maximum compatibility with less -common platforms, availability can be checked using the `jit` global variable: >lua +On supported platforms, Nvim is built with LuaJIT, which provides extra +functionality (compared to PUC Lua) such as "bit" and various utilities (see +|lua-profile|). Lua code in |init.lua| and plugins can assume its presence on +many platforms, but for maximum compatibility should check the `jit` global +variable: >lua if jit then -- code for luajit else @@ -45,9 +46,21 @@ common platforms, availability can be checked using the `jit` global variable: > end < *lua-bit* -In particular, the luajit "bit" extension module is _always_ available. -A fallback implementation is included when nvim is built with PUC Lua 5.1, -and will be transparently used when `require("bit")` is invoked. +The LuaJIT "bit" extension module is _always_ available: when built with PUC +Lua, Nvim includes a fallback implementation which provides `require("bit")`. + + *lua-profile* +To profile Lua code (with LuaJIT-enabled Nvim), the basic steps are: >lua + -- Start a profiling session: + require('jit.p').start('ri1', '/tmp/profile') + + -- Perform arbitrary tasks (use plugins, scripts, etc.) ... + + -- Stop the session. Profile is written to /tmp/profile. + require('jit.p').stop() + +See https://luajit.org/ext_profiler.html or the "p.lua" source for details: > + :lua vim.cmd.edit(package.searchpath('jit.p', package.path)) ============================================================================== LUA CONCEPTS AND IDIOMS *lua-concepts* @@ -244,8 +257,8 @@ arguments separated by " " (space) instead of "\t" (tab). *:lua=* *:lua* :lua {chunk} Executes Lua chunk {chunk}. If {chunk} starts with "=" the rest of the - chunk is evaluated as an expression and printed. `:lua =expr` or `:=expr` is - equivalent to `:lua print(vim.inspect(expr))`. + chunk is evaluated as an expression and printed. `:lua =expr` and `:=expr` + are equivalent to `:lua vim.print(expr)`. Examples: >vim :lua vim.api.nvim_command('echo "Hello, Nvim!"') @@ -530,6 +543,16 @@ Example: File-change detection *watch-file* vim.api.nvim_command( "command! -nargs=1 Watch call luaeval('watch_file(_A)', expand('<args>'))") < + *fswatch-limitations* +When on Linux and using fswatch, you may need to increase the maximum number +of `inotify` watches and queued events as the default limit can be too low. To +increase the limit, run: >sh + sysctl fs.inotify.max_user_watches=100000 + sysctl fs.inotify.max_queued_events=100000 +< +This will increase the limit to 100000 watches and queued events. These lines +can be added to `/etc/sysctl.conf` to make the changes persistent. + Example: TCP echo-server *tcp-server* 1. Save this code to a file. 2. Execute it with ":luafile %". @@ -582,24 +605,13 @@ A subset of the `vim.*` API is available in threads. This includes: ============================================================================== VIM.HIGHLIGHT *vim.highlight* -Nvim includes a function for highlighting a selection on yank. - -To enable it, add the following to your `init.vim`: >vim - au TextYankPost * silent! lua vim.highlight.on_yank() -< - -You can customize the highlight group and the duration of the highlight via: >vim - au TextYankPost * silent! lua vim.highlight.on_yank {higroup="IncSearch", timeout=150} -< +vim.highlight.on_yank({opts}) *vim.highlight.on_yank()* + Highlight the yanked text during a |TextYankPost| event. -If you want to exclude visual selections from highlighting on yank, use: >vim - au TextYankPost * silent! lua vim.highlight.on_yank {on_visual=false} + Add the following to your `init.vim`: >vim + autocmd TextYankPost * silent! lua vim.highlight.on_yank {higroup='Visual', timeout=300} < - -vim.highlight.on_yank({opts}) *vim.highlight.on_yank()* - Highlight the yanked text - Parameters: ~ • {opts} (`table?`) Optional parameters • higroup highlight group for yanked region (default @@ -633,12 +645,14 @@ vim.highlight.range({bufnr}, {ns}, {higroup}, {start}, {finish}, {opts}) tuple or string accepted by |getpos()| • {finish} (`integer[]|string`) End of region as a (line, column) tuple or string accepted by |getpos()| - • {opts} (`table?`) Optional parameters - • regtype type of range (see |setreg()|, default charwise) - • inclusive boolean indicating whether the range is - end-inclusive (default false) - • priority number indicating priority of highlight (default - priorities.user) + • {opts} (`table?`) A table with the following fields: + • {regtype}? (`string`, default: `'charwise'`) Type of + range. See |setreg()| + • {inclusive}? (`boolean`, default: `false`) Indicates + whether the range is end-inclusive + • {priority}? (`integer`, default: + `vim.highlight.priorities.user`) Indicates priority of + highlight ============================================================================== @@ -666,44 +680,47 @@ vim.diff({a}, {b}, {opts}) *vim.diff()* Parameters: ~ • {a} (`string`) First string to compare • {b} (`string`) Second string to compare - • {opts} (`table<string,any>`) Optional parameters: - • `on_hunk` (callback): Invoked for each hunk in the diff. - Return a negative number to cancel the callback for any - remaining hunks. Args: - • `start_a` (integer): Start line of hunk in {a}. - • `count_a` (integer): Hunk size in {a}. - • `start_b` (integer): Start line of hunk in {b}. - • `count_b` (integer): Hunk size in {b}. - • `result_type` (string): Form of the returned diff: - • "unified": (default) String in unified format. - • "indices": Array of hunk locations. Note: This option is + • {opts} (`table`) Optional parameters: + • {on_hunk} + (`fun(start_a: integer, count_a: integer, start_b: integer, count_b: integer): integer`) + Invoked for each hunk in the diff. Return a negative number + to cancel the callback for any remaining hunks. Arguments: + • `start_a` (`integer`): Start line of hunk in {a}. + • `count_a` (`integer`): Hunk size in {a}. + • `start_b` (`integer`): Start line of hunk in {b}. + • `count_b` (`integer`): Hunk size in {b}. + • {result_type} (`'unified'|'indices'`, default: `'unified'`) + Form of the returned diff: + • `unified`: String in unified format. + • `indices`: Array of hunk locations. Note: This option is ignored if `on_hunk` is used. - • `linematch` (boolean|integer): Run linematch on the + • {linematch} (`boolean|integer`) Run linematch on the resulting hunks from xdiff. When integer, only hunks upto this size in lines are run through linematch. Requires `result_type = indices`, ignored otherwise. - • `algorithm` (string): Diff algorithm to use. Values: - • "myers" the default algorithm - • "minimal" spend extra time to generate the smallest + • {algorithm} (`'myers'|'minimal'|'patience'|'histogram'`, + default: `'myers'`) Diff algorithm to use. Values: + • `myers`: the default algorithm + • `minimal`: spend extra time to generate the smallest possible diff - • "patience" patience diff algorithm - • "histogram" histogram diff algorithm - • `ctxlen` (integer): Context length - • `interhunkctxlen` (integer): Inter hunk context length - • `ignore_whitespace` (boolean): Ignore whitespace - • `ignore_whitespace_change` (boolean): Ignore whitespace + • `patience`: patience diff algorithm + • `histogram`: histogram diff algorithm + • {ctxlen} (`integer`) Context length + • {interhunkctxlen} (`integer`) Inter hunk context length + • {ignore_whitespace} (`boolean`) Ignore whitespace + • {ignore_whitespace_change} (`boolean`) Ignore whitespace change - • `ignore_whitespace_change_at_eol` (boolean) Ignore + • {ignore_whitespace_change_at_eol} (`boolean`) Ignore whitespace change at end-of-line. - • `ignore_cr_at_eol` (boolean) Ignore carriage return at + • {ignore_cr_at_eol} (`boolean`) Ignore carriage return at end-of-line - • `ignore_blank_lines` (boolean) Ignore blank lines - • `indent_heuristic` (boolean): Use the indent heuristic for + • {ignore_blank_lines} (`boolean`) Ignore blank lines + • {indent_heuristic} (`boolean`) Use the indent heuristic for the internal diff library. Return: ~ - (`string|table?`) See {opts.result_type}. `nil` if {opts.on_hunk} is - given. + (`string|integer[]`) See {opts.result_type}. `nil` if {opts.on_hunk} + is given. ============================================================================== @@ -817,8 +834,8 @@ vim.spell.check({str}) *vim.spell.check()* • {str} (`string`) Return: ~ - (`{[1]: string, [2]: string, [3]: string}[]`) List of tuples with - three items: + (`{[1]: string, [2]: 'bad'|'rare'|'local'|'caps', [3]: integer}[]`) + List of tuples with three items: • The badly spelled word. • The type of the spelling error: "bad" spelling mistake "rare" rare word "local" word only valid in another region "caps" word should @@ -899,7 +916,7 @@ vim.empty_dict() *vim.empty_dict()* Return: ~ (`table`) -vim.iconv({str}, {from}, {to}, {opts}) *vim.iconv()* +vim.iconv({str}, {from}, {to}) *vim.iconv()* 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 are replaced with "?". The @@ -908,9 +925,8 @@ vim.iconv({str}, {from}, {to}, {opts}) *vim.iconv()* Parameters: ~ • {str} (`string`) Text to convert - • {from} (`number`) Encoding of {str} - • {to} (`number`) Target encoding - • {opts} (`table<string,any>?`) + • {from} (`string`) Encoding of {str} + • {to} (`string`) Target encoding Return: ~ (`string?`) Converted string if conversion succeeds, `nil` otherwise. @@ -950,20 +966,20 @@ vim.schedule({fn}) *vim.schedule()* |textlock| or other temporary restrictions. Parameters: ~ - • {fn} (`function`) + • {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 by |vim.str_byteindex()|. An {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} (`number`) - • {use_utf16} (`any?`) + • {index} (`integer`) + • {use_utf16} (`boolean?`) vim.str_utf_end({str}, {index}) *vim.str_utf_end()* Gets the distance (in bytes) from the last byte of the codepoint @@ -981,10 +997,10 @@ vim.str_utf_end({str}, {index}) *vim.str_utf_end()* Parameters: ~ • {str} (`string`) - • {index} (`number`) + • {index} (`integer`) Return: ~ - (`number`) + (`integer`) vim.str_utf_pos({str}) *vim.str_utf_pos()* Gets a list of the starting byte positions of each UTF-8 codepoint in the @@ -996,7 +1012,7 @@ vim.str_utf_pos({str}) *vim.str_utf_pos()* • {str} (`string`) Return: ~ - (`table`) + (`integer[]`) vim.str_utf_start({str}, {index}) *vim.str_utf_start()* Gets the distance (in bytes) from the starting byte of the codepoint @@ -1017,10 +1033,10 @@ vim.str_utf_start({str}, {index}) *vim.str_utf_start()* Parameters: ~ • {str} (`string`) - • {index} (`number`) + • {index} (`integer`) Return: ~ - (`number`) + (`integer`) vim.str_utfindex({str}, {index}) *vim.str_utfindex()* Convert byte index to UTF-32 and UTF-16 indices. If {index} is not @@ -1033,7 +1049,7 @@ vim.str_utfindex({str}, {index}) *vim.str_utfindex()* Parameters: ~ • {str} (`string`) - • {index} (`number?`) + • {index} (`integer?`) Return (multiple): ~ (`integer`) UTF-32 index @@ -1161,6 +1177,7 @@ Lua list copies the list object to Vimscript and does NOT modify the Lua list: > vim.print(list) --> "{ 1, 2, 3 }" < + vim.call({func}, {...}) *vim.call()* Invokes |vim-function| or |user-function| {func} with arguments {...}. See also |vim.fn|. @@ -1239,6 +1256,7 @@ vim.v *vim.v* |v:| variables. Invalid or unset key returns `nil`. + *lua-options* *lua-vim-options* *lua-vim-set* @@ -1262,6 +1280,7 @@ window-scoped options. Note that this must NOT be confused with |local-options| and |:setlocal|. There is also |vim.go| that only accesses the global value of a |global-local| option, see |:setglobal|. + *vim.opt_local* *vim.opt_global* *vim.opt* @@ -1406,7 +1425,7 @@ Option:remove({value}) *vim.opt:remove()* Parameters: ~ • {value} (`string`) Value to remove -vim.bo *vim.bo* +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. @@ -1456,7 +1475,7 @@ vim.o *vim.o* print(vim.o.foo) -- error: invalid key < -vim.wo *vim.wo* +vim.wo[{winid}][{bufnr}] *vim.wo* Get or set window-scoped |options| for the window with handle {winid} and buffer with number {bufnr}. Like `:setlocal` if setting a |global-local| option or if {bufnr} is provided, like `:set` otherwise. If {winid} is @@ -1625,12 +1644,14 @@ vim.on_key({fn}, {ns_id}) *vim.on_key()* Note: ~ • {fn} will be removed on error. • {fn} will not be cleared by |nvim_buf_clear_namespace()| - • {fn} will receive the keys after mappings have been evaluated Parameters: ~ - • {fn} (`fun(key: string)?`) Function invoked on every key press. - |i_CTRL-V| Passing in nil when {ns_id} is specified removes - the callback associated with namespace {ns_id}. + • {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. • {ns_id} (`integer?`) Namespace ID. If nil or 0, generates and returns a new |nvim_create_namespace()| id. @@ -1795,6 +1816,7 @@ vim.system({cmd}, {opts}, {on_exit}) *vim.system()* Return: ~ (`vim.SystemObj`) Object with the fields: + • cmd (string[]) Command name and args • pid (integer) Process ID • wait (fun(timeout: integer|nil): SystemCompleted) Wait for the process to complete. Upon timeout the process is sent the KILL @@ -2011,6 +2033,43 @@ vim.is_callable({f}) *vim.is_callable()* Return: ~ (`boolean`) `true` if `f` is callable, else `false` +vim.isarray({t}) *vim.isarray()* + Tests if `t` is an "array": a table indexed only by integers (potentially + non-contiguous). + + If the indexes start from 1 and are contiguous then the array is also a + list. |vim.islist()| + + Empty table `{}` is an array, unless it was created by |vim.empty_dict()| + or returned as a dict-like |API| or Vimscript result, for example from + |rpcrequest()| or |vim.fn|. + + Parameters: ~ + • {t} (`table?`) + + Return: ~ + (`boolean`) `true` if array-like table, else `false`. + + See also: ~ + • https://github.com/openresty/luajit2#tableisarray + +vim.islist({t}) *vim.islist()* + Tests if `t` is a "list": a table indexed only by contiguous integers + starting from 1 (what |lua-length| calls a "regular array"). + + Empty table `{}` is a list, unless it was created by |vim.empty_dict()| or + returned as a dict-like |API| or Vimscript result, for example from + |rpcrequest()| or |vim.fn|. + + Parameters: ~ + • {t} (`table?`) + + Return: ~ + (`boolean`) `true` if list-like table, else `false`. + + See also: ~ + • |vim.isarray()| + vim.list_contains({t}, {value}) *vim.list_contains()* Checks if a list-like table (integer keys without gaps) contains `value`. @@ -2190,8 +2249,8 @@ vim.tbl_deep_extend({behavior}, {...}) *vim.tbl_deep_extend()* Merges recursively two or more tables. Parameters: ~ - • {behavior} (`"error"|"keep"|"force"`) (string) Decides what to do if - a key is found in more than one map: + • {behavior} (`'error'|'keep'|'force'`) Decides what to do if a key is + found in more than one map: • "error": raise an error • "keep": use value from the leftmost map • "force": use value from the rightmost map @@ -2207,8 +2266,8 @@ vim.tbl_extend({behavior}, {...}) *vim.tbl_extend()* Merges two or more tables. Parameters: ~ - • {behavior} (`string`) Decides what to do if a key is found in more - than one map: + • {behavior} (`'error'|'keep'|'force'`) Decides what to do if a key is + found in more than one map: • "error": raise an error • "keep": use value from the leftmost map • "force": use value from the rightmost map @@ -2230,20 +2289,6 @@ vim.tbl_filter({func}, {t}) *vim.tbl_filter()* Return: ~ (`any[]`) Table of filtered values -vim.tbl_flatten({t}) *vim.tbl_flatten()* - Creates a copy of a list-like table such that any nested tables are - "unrolled" and appended to the result. - - Parameters: ~ - • {t} (`table`) List-like table - - Return: ~ - (`table`) Flattened copy of the given list-like table - - See also: ~ - • From - https://github.com/premake/premake-core/blob/master/src/base/table.lua - vim.tbl_get({o}, {...}) *vim.tbl_get()* Index into a table (first argument) via string keys passed as subsequent arguments. Return `nil` if the key does not exist. @@ -2261,26 +2306,6 @@ vim.tbl_get({o}, {...}) *vim.tbl_get()* Return: ~ (`any`) Nested value indexed by key (if it exists), else nil -vim.tbl_isarray({t}) *vim.tbl_isarray()* - Tests if `t` is an "array": a table indexed only by integers (potentially - non-contiguous). - - If the indexes start from 1 and are contiguous then the array is also a - list. |vim.tbl_islist()| - - Empty table `{}` is an array, unless it was created by |vim.empty_dict()| - or returned as a dict-like |API| or Vimscript result, for example from - |rpcrequest()| or |vim.fn|. - - Parameters: ~ - • {t} (`table`) - - Return: ~ - (`boolean`) `true` if array-like table, else `false`. - - See also: ~ - • https://github.com/openresty/luajit2#tableisarray - vim.tbl_isempty({t}) *vim.tbl_isempty()* Checks if a table is empty. @@ -2293,23 +2318,6 @@ vim.tbl_isempty({t}) *vim.tbl_isempty()* See also: ~ • https://github.com/premake/premake-core/blob/master/src/base/table.lua -vim.tbl_islist({t}) *vim.tbl_islist()* - Tests if `t` is a "list": a table indexed only by contiguous integers - starting from 1 (what |lua-length| calls a "regular array"). - - Empty table `{}` is a list, unless it was created by |vim.empty_dict()| or - returned as a dict-like |API| or Vimscript result, for example from - |rpcrequest()| or |vim.fn|. - - Parameters: ~ - • {t} (`table`) - - Return: ~ - (`boolean`) `true` if list-like table, else `false`. - - See also: ~ - • |vim.tbl_isarray()| - vim.tbl_keys({t}) *vim.tbl_keys()* Return a list of all keys used in a table. However, the order of the return table of keys is not guaranteed. @@ -2358,7 +2366,8 @@ vim.trim({s}) *vim.trim()* • https://www.lua.org/pil/20.2.html vim.validate({opt}) *vim.validate()* - Validates a parameter specification (types and values). + 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) @@ -2551,17 +2560,22 @@ vim.ui.open({path}) *vim.ui.open()* Expands "~/" and environment variables in filesystem paths. Examples: >lua + -- Asynchronous. vim.ui.open("https://neovim.io/") vim.ui.open("~/path/to/file") - vim.ui.open("$VIMRUNTIME") + -- Synchronous (wait until the process exits). + local cmd, err = vim.ui.open("$VIMRUNTIME") + if cmd then + cmd:wait() + end < Parameters: ~ • {path} (`string`) Path or URL to open Return (multiple): ~ - (`vim.SystemCompleted?`) Command result, or nil if not found. - (`string?`) Error message on failure + (`vim.SystemObj?`) Command object, or nil if not found. + (`string?`) Error message on failure, or nil on success. See also: ~ • |vim.system()| @@ -2672,7 +2686,6 @@ vim.filetype.add({filetypes}) *vim.filetype.add()* vim.filetype.add { pattern = { ['.*'] = { - priority = -math.huge, function(path, bufnr) local content = vim.api.nvim_buf_get_lines(bufnr, 0, 1, false)[1] or '' if vim.regex([[^#!.*\\<mine\\>]]):match_str(content) ~= nil then @@ -2681,6 +2694,7 @@ vim.filetype.add({filetypes}) *vim.filetype.add()* return 'drawing' end end, + { priority = -math.huge }, }, }, } @@ -2781,9 +2795,9 @@ vim.keymap.del({modes}, {lhs}, {opts}) *vim.keymap.del()* Parameters: ~ • {modes} (`string|string[]`) • {lhs} (`string`) - • {opts} (`table?`) A table of optional arguments: - • "buffer": (integer|boolean) Remove a mapping from the given - buffer. When `0` or `true`, use the current buffer. + • {opts} (`table?`) A table with the following fields: + • {buffer}? (`integer|boolean`) Remove a mapping from the + given buffer. When `0` or `true`, use the current buffer. See also: ~ • |vim.keymap.set()| @@ -2805,20 +2819,20 @@ vim.keymap.set({mode}, {lhs}, {rhs}, {opts}) *vim.keymap.set()* < Parameters: ~ - • {mode} (`string|table`) Mode short-name, see |nvim_set_keymap()|. Can - also be list of modes to create mapping on multiple modes. + • {mode} (`string|string[]`) Mode short-name, see |nvim_set_keymap()|. + Can also be list of modes to create mapping on multiple modes. • {lhs} (`string`) Left-hand side |{lhs}| of the mapping. • {rhs} (`string|function`) Right-hand side |{rhs}| of the mapping, can be a Lua function. - • {opts} (`table?`) Table of |:map-arguments|. - • Same as |nvim_set_keymap()| {opts}, except: - • "replace_keycodes" defaults to `true` if "expr" is `true`. - • "noremap": inverse of "remap" (see below). - • Also accepts: - • "buffer": (integer|boolean) Creates buffer-local mapping, - `0` or `true` for current buffer. - • "remap": (boolean) Make the mapping recursive. Inverse of - "noremap". Defaults to `false`. + • {opts} (`table?`) Table of |:map-arguments|. Same as + |nvim_set_keymap()| {opts}, except: + • {replace_keycodes} defaults to `true` if "expr" is `true`. + + Also accepts: + • {buffer}? (`integer|boolean`) Creates buffer-local mapping, + `0` or `true` for current buffer. + • {remap}? (`boolean`, default: `false`) Make the mapping + recursive. Inverse of {noremap}. See also: ~ • |nvim_set_keymap()| @@ -2881,13 +2895,6 @@ vim.fs.find({names}, {opts}) *vim.fs.find()* narrow the search to find only that type. Examples: >lua - -- location of Cargo.toml from the current buffer's path - local cargo = vim.fs.find('Cargo.toml', { - upward = true, - stop = vim.uv.os_homedir(), - path = vim.fs.dirname(vim.api.nvim_buf_get_name(0)), - }) - -- list all test directories under the runtime directory local test_dirs = vim.fs.find( {'test', 'tst', 'testdir'}, @@ -2939,26 +2946,41 @@ vim.fs.joinpath({...}) *vim.fs.joinpath()* vim.fs.normalize({path}, {opts}) *vim.fs.normalize()* Normalize a path to a standard format. A tilde (~) character at the - beginning of the path is expanded to the user's home directory and any - backslash (\) characters are converted to forward slashes (/). Environment - variables are also expanded. + beginning of the path is expanded to the user's home directory and + environment variables are also expanded. "." and ".." components are also + resolved, except when the path is relative and trying to resolve it would + result in an absolute path. + • "." as the only part in a relative path: + • "." => "." + • "././" => "." + • ".." when it leads outside the current directory + • "foo/../../bar" => "../bar" + • "../../foo" => "../../foo" + • ".." in the root directory returns the root directory. + • "/../../" => "/" + + On Windows, backslash (\) characters are converted to forward slashes (/). Examples: >lua - vim.fs.normalize('C:\\\\Users\\\\jdoe') - -- 'C:/Users/jdoe' - - vim.fs.normalize('~/src/neovim') - -- '/home/jdoe/src/neovim' - - vim.fs.normalize('$XDG_CONFIG_HOME/nvim/init.vim') - -- '/Users/jdoe/.config/nvim/init.vim' + [[C:\Users\jdoe]] => "C:/Users/jdoe" + "~/src/neovim" => "/home/jdoe/src/neovim" + "$XDG_CONFIG_HOME/nvim/init.vim" => "/Users/jdoe/.config/nvim/init.vim" + "~/src/nvim/api/../tui/./tui.c" => "/home/jdoe/src/nvim/tui/tui.c" + "./foo/bar" => "foo/bar" + "foo/../../../bar" => "../../bar" + "/home/jdoe/../../../bar" => "/bar" + "C:foo/../../baz" => "C:../baz" + "C:/foo/../../baz" => "C:/baz" + [[\\?\UNC\server\share\foo\..\..\..\bar]] => "//?/UNC/server/share/bar" < Parameters: ~ • {path} (`string`) Path to normalize • {opts} (`table?`) A table with the following fields: - • {expand_env} (`boolean`, default: `true`) Expand environment - variables. + • {expand_env}? (`boolean`, default: `true`) Expand + environment variables. + • {win}? (`boolean`, default: `true` in Windows, `false` + otherwise) Path is a Windows path. Return: ~ (`string`) Normalized path @@ -2988,6 +3010,39 @@ vim.fs.parents({start}) *vim.fs.parents()* (`nil`) (`string?`) +vim.fs.root({source}, {marker}) *vim.fs.root()* + Find the first parent directory containing a specific "marker", relative + to a file path or buffer. + + If the buffer is unnamed (has no backing file) or has a non-empty + 'buftype' then the search begins from Nvim's |current-directory|. + + Example: >lua + -- Find the root of a Python project, starting from file 'main.py' + vim.fs.root(vim.fs.joinpath(vim.env.PWD, 'main.py'), {'pyproject.toml', 'setup.py' }) + + -- Find the root of a git repository + vim.fs.root(0, '.git') + + -- Find the parent directory containing any file with a .csproj extension + vim.fs.root(0, function(name, path) + return name:match('%.csproj$') ~= nil + end) +< + + Parameters: ~ + • {source} (`integer|string`) Buffer number (0 for current buffer) or + file path (absolute or relative to the |current-directory|) + to begin the search from. + • {marker} (`string|string[]|fun(name: string, path: string): boolean`) + A marker, or list of markers, to search for. If a function, + the function is called for each evaluated item and should + return true if {name} and {path} are a match. + + Return: ~ + (`string?`) Directory path containing one of the given markers, or nil + if no directory was found. + ============================================================================== Lua module: vim.glob *vim.glob* @@ -3022,11 +3077,10 @@ vim.glob.to_lpeg({pattern}) *vim.glob.to_lpeg()* VIM.LPEG *vim.lpeg* -LPeg is a pattern-matching library for Lua, based on -Parsing Expression Grammars (https://bford.info/packrat/) (PEGs). +LPeg is a pattern-matching library for Lua, based on Parsing Expression +Grammars (PEGs). https://bford.info/packrat/ - *lua-lpeg* - *vim.lpeg.Pattern* + *lua-lpeg* *vim.lpeg.Pattern* The LPeg library for parsing expression grammars is included as `vim.lpeg` (https://www.inf.puc-rio.br/~roberto/lpeg/). @@ -3419,10 +3473,11 @@ vim.lpeg.version() *vim.lpeg.version()* VIM.RE *vim.re* The `vim.re` module provides a conventional regex-like syntax for pattern -usage within LPeg |vim.lpeg|. +usage within LPeg |vim.lpeg|. (Unrelated to |vim.regex| which provides Vim +|regexp| from Lua.) See https://www.inf.puc-rio.br/~roberto/lpeg/re.html for the original -documentation including regex syntax and more concrete examples. +documentation including regex syntax and examples. vim.re.compile({string}, {defs}) *vim.re.compile()* @@ -3553,7 +3608,7 @@ vim.secure.trust({opts}) *vim.secure.trust()* The trust database is located at |$XDG_STATE_HOME|/nvim/trust. Parameters: ~ - • {opts} (`table?`) A table with the following fields: + • {opts} (`table`) A table with the following fields: • {action} (`'allow'|'deny'|'remove'`) - `'allow'` to add a file to the trust database and trust it, • `'deny'` to add a file to the trust database and deny it, @@ -3764,7 +3819,6 @@ vim.version.range({spec}) *vim.version.range()* (`table?`) A table with the following fields: • {from} (`vim.Version`) • {to}? (`vim.Version`) - • {has} (`fun(self: vim.VersionRangeversion: string|vim.Version)`) See also: ~ • https://github.com/npm/node-semver#ranges @@ -3780,6 +3834,7 @@ chained to create iterator "pipelines": the output of each pipeline stage is input to the next stage. The first stage depends on the type passed to `vim.iter()`: • List tables (arrays, |lua-list|) yield only the value of each element. + • Holes (nil values) are allowed. • Use |Iter:enumerate()| to also pass the index to the next stage. • Or initialize with ipairs(): `vim.iter(ipairs(…))`. • Non-list tables (|lua-dict|) yield both the key and value of each element. @@ -3833,27 +3888,6 @@ Examples: >lua -- { "a", "b" } < -In addition to the |vim.iter()| function, the |vim.iter| module provides -convenience functions like |vim.iter.filter()| and |vim.iter.totable()|. - - -filter({f}, {src}) *vim.iter.filter()* - Filters a table or other |iterable|. >lua - -- Equivalent to: - vim.iter(src):filter(f):totable() -< - - Parameters: ~ - • {f} (`fun(...):boolean`) Filter function. Accepts the current - iterator or table values as arguments and returns true if those - values should be kept in the final table - • {src} (`table|function`) Table or iterator function to filter - - Return: ~ - (`table`) - - See also: ~ - • |Iter:filter()| Iter:all({pred}) *Iter:all()* Returns true if all items in the iterator match the given predicate. @@ -3897,6 +3931,7 @@ Iter:enumerate() *Iter:enumerate()* < Example: >lua + local it = vim.iter(vim.gsplit('abc', '')):enumerate() it:next() -- 1 'a' @@ -3931,6 +3966,7 @@ Iter:find({f}) *Iter:find()* found. Examples: >lua + local it = vim.iter({ 3, 6, 9, 12 }) it:find(12) -- 12 @@ -3973,18 +4009,23 @@ Iter:flatten({depth}) *Iter:flatten()* (`Iter`) Iter:fold({init}, {f}) *Iter:fold()* - Folds ("reduces") an iterator into a single value. + Folds ("reduces") an iterator into a single value. *Iter:reduce()* Examples: >lua -- Create a new table with only even values - local t = { a = 1, b = 2, c = 3, d = 4 } - local it = vim.iter(t) - it:filter(function(k, v) return v % 2 == 0 end) - it:fold({}, function(t, k, v) - t[k] = v - return t - end) - -- { b = 2, d = 4 } + vim.iter({ a = 1, b = 2, c = 3, d = 4 }) + :filter(function(k, v) return v % 2 == 0 end) + :fold({}, function(acc, k, v) + acc[k] = v + return acc + end) --> { b = 2, d = 4 } + + -- Get the "maximum" item of an iterable. + vim.iter({ -99, -4, 3, 42, 0, 0, 7 }) + :fold({}, function(acc, v) + acc.max = math.max(v, acc.max or v) + return acc + end) --> { max = 42 } < Parameters: ~ @@ -4011,6 +4052,7 @@ Iter:last() *Iter:last()* Drains the iterator and returns the last item. Example: >lua + local it = vim.iter(vim.gsplit('abcdefg', '')) it:last() -- 'g' @@ -4023,6 +4065,9 @@ Iter:last() *Iter:last()* Return: ~ (`any`) + See also: ~ + • Iter.rpeek + Iter:map({f}) *Iter:map()* Maps the items of an iterator pipeline to the values returned by `f`. @@ -4051,6 +4096,7 @@ Iter:next() *Iter:next()* Gets the next value from the iterator. Example: >lua + local it = vim.iter(string.gmatch('1 2 3', '%d+')):map(tonumber) it:next() -- 1 @@ -4063,51 +4109,28 @@ Iter:next() *Iter:next()* Return: ~ (`any`) -Iter:nextback() *Iter:nextback()* - "Pops" a value from a |list-iterator| (gets the last value and decrements - the tail). - - Example: >lua - local it = vim.iter({1, 2, 3, 4}) - it:nextback() - -- 4 - it:nextback() - -- 3 -< - - Return: ~ - (`any`) - Iter:nth({n}) *Iter:nth()* Gets the nth value of an iterator (and advances to it). + If `n` is negative, offsets from the end of a |list-iterator|. + Example: >lua local it = vim.iter({ 3, 6, 9, 12 }) it:nth(2) -- 6 it:nth(2) -- 12 -< - - Parameters: ~ - • {n} (`number`) The index of the value to return. - - Return: ~ - (`any`) - -Iter:nthback({n}) *Iter:nthback()* - Gets the nth value from the end of a |list-iterator| (and advances to it). - Example: >lua - local it = vim.iter({ 3, 6, 9, 12 }) - it:nthback(2) + local it2 = vim.iter({ 3, 6, 9, 12 }) + it2:nth(-2) -- 9 - it:nthback(2) + it2:nth(-2) -- 3 < Parameters: ~ - • {n} (`number`) The index of the value to return. + • {n} (`number`) Index of the value to return. May be negative if the + source is a |list-iterator|. Return: ~ (`any`) @@ -4116,6 +4139,7 @@ Iter:peek() *Iter:peek()* Gets the next value in a |list-iterator| without consuming it. Example: >lua + local it = vim.iter({ 3, 6, 9, 12 }) it:peek() -- 3 @@ -4128,19 +4152,16 @@ Iter:peek() *Iter:peek()* Return: ~ (`any`) -Iter:peekback() *Iter:peekback()* - Gets the last value of a |list-iterator| without consuming it. - - See also |Iter:last()|. +Iter:pop() *Iter:pop()* + "Pops" a value from a |list-iterator| (gets the last value and decrements + the tail). Example: >lua local it = vim.iter({1, 2, 3, 4}) - it:peekback() - -- 4 - it:peekback() - -- 4 - it:nextback() + it:pop() -- 4 + it:pop() + -- 3 < Return: ~ @@ -4150,6 +4171,7 @@ Iter:rev() *Iter:rev()* Reverses a |list-iterator| pipeline. Example: >lua + local it = vim.iter({ 3, 6, 9, 12 }):rev() it:totable() -- { 12, 9, 6, 3 } @@ -4159,13 +4181,14 @@ Iter:rev() *Iter:rev()* (`Iter`) Iter:rfind({f}) *Iter:rfind()* - Gets the first value in a |list-iterator| that satisfies a predicate, - starting from the end. + Gets the first value satisfying a predicate, from the end of a + |list-iterator|. Advances the iterator. Returns nil and drains the iterator if no value is found. Examples: >lua + local it = vim.iter({ 1, 2, 3, 2, 1 }):enumerate() it:rfind(1) -- 5 1 @@ -4182,13 +4205,34 @@ Iter:rfind({f}) *Iter:rfind()* See also: ~ • Iter.find -Iter:skip({n}) *Iter:skip()* - Skips `n` values of an iterator pipeline. +Iter:rpeek() *Iter:rpeek()* + Gets the last value of a |list-iterator| without consuming it. Example: >lua - local it = vim.iter({ 3, 6, 9, 12 }):skip(2) + local it = vim.iter({1, 2, 3, 4}) + it:rpeek() + -- 4 + it:rpeek() + -- 4 + it:pop() + -- 4 +< + + Return: ~ + (`any`) + + See also: ~ + • Iter.last + +Iter:rskip({n}) *Iter:rskip()* + Discards `n` values from the end of a |list-iterator| pipeline. + + Example: >lua + local it = vim.iter({ 1, 2, 3, 4, 5 }):rskip(2) it:next() - -- 9 + -- 1 + it:pop() + -- 3 < Parameters: ~ @@ -4197,15 +4241,14 @@ Iter:skip({n}) *Iter:skip()* Return: ~ (`Iter`) -Iter:skipback({n}) *Iter:skipback()* - Skips `n` values backwards from the end of a |list-iterator| pipeline. +Iter:skip({n}) *Iter:skip()* + Skips `n` values of an iterator pipeline. Example: >lua - local it = vim.iter({ 1, 2, 3, 4, 5 }):skipback(2) + + local it = vim.iter({ 3, 6, 9, 12 }):skip(2) it:next() - -- 1 - it:nextback() - -- 3 + -- 9 < Parameters: ~ @@ -4217,7 +4260,7 @@ Iter:skipback({n}) *Iter:skipback()* Iter:slice({first}, {last}) *Iter:slice()* Sets the start and end of a |list-iterator| pipeline. - Equivalent to `:skip(first - 1):skipback(len - last + 1)`. + Equivalent to `:skip(first - 1):rskip(len - last + 1)`. Parameters: ~ • {first} (`number`) @@ -4249,9 +4292,9 @@ Iter:totable() *Iter:totable()* Collect the iterator into a table. The resulting table depends on the initial source in the iterator - pipeline. List-like tables and function iterators will be collected into a - list-like table. If multiple values are returned from the final stage in - the iterator pipeline, each value will be included in a table. + pipeline. Array-like tables and function iterators will be collected into + an array-like table. If multiple values are returned from the final stage + in the iterator pipeline, each value will be included in a table. Examples: >lua vim.iter(string.gmatch('100 20 50', '%d+')):map(tonumber):totable() @@ -4264,90 +4307,65 @@ Iter:totable() *Iter:totable()* -- { { 'a', 1 }, { 'c', 3 } } < - The generated table is a list-like table with consecutive, numeric + The generated table is an array-like table with consecutive, numeric indices. To create a map-like table with arbitrary keys, use |Iter:fold()|. Return: ~ (`table`) -map({f}, {src}) *vim.iter.map()* - Maps a table or other |iterable|. >lua - -- Equivalent to: - vim.iter(src):map(f):totable() -< - - Parameters: ~ - • {f} (`fun(...): any?`) Map function. Accepts the current iterator - or table values as arguments and returns one or more new - values. Nil values are removed from the final table. - • {src} (`table|function`) Table or iterator function to filter - Return: ~ - (`table`) - - See also: ~ - • |Iter:map()| +============================================================================== +Lua module: vim.snippet *vim.snippet* -totable({f}) *vim.iter.totable()* - Collects an |iterable| into a table. >lua - -- Equivalent to: - vim.iter(f):totable() -< +*vim.snippet.ActiveFilter* - Parameters: ~ - • {f} (`function`) Iterator function + Fields: ~ + • {direction} (`vim.snippet.Direction`) Navigation direction. -1 for + previous, 1 for next. - Return: ~ - (`table`) +vim.snippet.active({filter}) *vim.snippet.active()* + Returns `true` if there's an active snippet in the current buffer, + applying the given filter if provided. -============================================================================== -Lua module: vim.snippet *vim.snippet* + You can use this function to navigate a snippet as follows: >lua + vim.keymap.set({ 'i', 's' }, '<Tab>', function() + if vim.snippet.active({ direction = 1 }) then + return '<cmd>lua vim.snippet.jump(1)<cr>' + else + return '<Tab>' + end + end, { expr = true }) +< -vim.snippet.active() *vim.snippet.active()* - Returns `true` if there's an active snippet in the current buffer. + Parameters: ~ + • {filter} (`vim.snippet.ActiveFilter?`) Filter to constrain the search + with: + • `direction` (vim.snippet.Direction): Navigation direction. + Will return `true` if the snippet can be jumped in the + given direction. See |vim.snippet.ActiveFilter|. Return: ~ (`boolean`) -vim.snippet.exit() *vim.snippet.exit()* - Exits the current snippet. - vim.snippet.expand({input}) *vim.snippet.expand()* Expands the given snippet text. Refer to https://microsoft.github.io/language-server-protocol/specification/#snippet_syntax for the specification of valid input. - Tabstops are highlighted with hl-SnippetTabstop. + Tabstops are highlighted with |hl-SnippetTabstop|. Parameters: ~ • {input} (`string`) vim.snippet.jump({direction}) *vim.snippet.jump()* - Jumps within the active snippet in the given direction. If the jump isn't - possible, the function call does nothing. - - You can use this function to navigate a snippet as follows: >lua - vim.keymap.set({ 'i', 's' }, '<Tab>', function() - if vim.snippet.jumpable(1) then - return '<cmd>lua vim.snippet.jump(1)<cr>' - else - return '<Tab>' - end - end, { expr = true }) -< + Jumps to the next (or previous) placeholder in the current snippet, if + possible. - Parameters: ~ - • {direction} (`vim.snippet.Direction`) Navigation direction. -1 for - previous, 1 for next. - -vim.snippet.jumpable({direction}) *vim.snippet.jumpable()* - Returns `true` if there is an active snippet which can be jumped in the - given direction. You can use this function to navigate a snippet as - follows: >lua + For example, map `<Tab>` to jump while a snippet is active: >lua vim.keymap.set({ 'i', 's' }, '<Tab>', function() - if vim.snippet.jumpable(1) then + if vim.snippet.active({ direction = 1 }) then return '<cmd>lua vim.snippet.jump(1)<cr>' else return '<Tab>' @@ -4359,8 +4377,8 @@ vim.snippet.jumpable({direction}) *vim.snippet.jumpable()* • {direction} (`vim.snippet.Direction`) Navigation direction. -1 for previous, 1 for next. - Return: ~ - (`boolean`) +vim.snippet.stop() *vim.snippet.stop()* + Exits the current snippet. ============================================================================== diff --git a/runtime/doc/luaref.txt b/runtime/doc/luaref.txt index e7b62f4c6c..cd0b648560 100644 --- a/runtime/doc/luaref.txt +++ b/runtime/doc/luaref.txt @@ -932,7 +932,7 @@ implicit extra parameter `self`. Thus, the statement is syntactic sugar for - `t.a.b.c:f = function (self, (` `params` `)` `body` `end` + `t.a.b.c:f = function (` `self`, `params` `)` `body` `end` ============================================================================== 2.6 Visibility Rules *lua-visibility* diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index 68206dd494..9ec34d5d52 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -604,7 +604,7 @@ instead. Example: > map <Leader>A oanother line<Esc> Works like: > map \A oanother line<Esc> -But after: +But after: > let mapleader = "," It works like: > map ,A oanother line<Esc> diff --git a/runtime/doc/message.txt b/runtime/doc/message.txt index c3154fc372..afe64300e7 100644 --- a/runtime/doc/message.txt +++ b/runtime/doc/message.txt @@ -114,6 +114,13 @@ wiped out a buffer which contains a mark or is referenced in another way. You cannot have two buffers with exactly the same name. This includes the path leading to the file. + *E1513* > + Cannot switch buffer. 'winfixbuf' is enabled + +If a window has 'winfixbuf' enabled, you cannot change that window's current +buffer. You need to set 'nowinfixbuf' before continuing. You may use [!] to +force the window to switch buffers, if your command supports it. + *E72* > Close error on swap file diff --git a/runtime/doc/news-0.10.txt b/runtime/doc/news-0.10.txt new file mode 100644 index 0000000000..8a0e7e92e7 --- /dev/null +++ b/runtime/doc/news-0.10.txt @@ -0,0 +1,473 @@ +*news-10.txt* Nvim + + + NVIM REFERENCE MANUAL + + +Notable changes since Nvim 0.9 *news-0.10* + +For changes in the previous release, see |news-0.9|. + + Type |gO| to see the table of contents. + +============================================================================== +BREAKING CHANGES + +These changes may require adaptations in your config or plugins. + +• API: + • |nvim_open_win()| now blocks all autocommands when `noautocmd` is set, + rather than just those from setting the `buffer` to display in the window. + +• Defaults: + • Default color scheme has been updated to be "Nvim branded" and accessible. + Use `:colorscheme vim` to revert to the old legacy color scheme. + • These Nvim specific highlight groups are now defined in a meaningfully + different way and might need an update: + • |hl-FloatBorder| is linked to |hl-NormalFloat| instead of |hl-WinSeparator|. + • |hl-NormalFloat| is not linked to |hl-Pmenu|. + • |hl-WinBar| has different background. + • |hl-WinBarNC| is similar to |hl-WinBar| but not bold. + • |hl-WinSeparator| is linked to |hl-Normal| instead of |hl-VertSplit|. + • This also might result into some color schemes looking differently due + to them relying on implicit assumptions about how highlight groups are + defined by default. To account for this, define all attributes of + highlight groups explicitly. Alternatively, use `:colorscheme vim` or + `:source $VIMRUNTIME/colors/vim.lua` to restore previous definitions. + • 'termguicolors' is enabled by default when Nvim is able to determine that + the host terminal emulator supports 24-bit color. + +• Editor: + • When switching windows, |CursorMoved| autocommands trigger when Nvim is + back on the main loop rather than immediately. This is more compatible + with Vim. + • "#" followed by a digit no longer stands for a function key at the start + of the lhs of a mapping. + • |shm-q| now fully hides macro recording message instead of only shortening it. + • Signs placed through the legacy |sign-commands| are now stored and + displayed as |extmarks| internally. Along with the following changes: + • A sign placed twice in the same group with the same identifier will be + moved. + • Legacy signs are always deleted along with the line it is placed on. + • Legacy and extmark signs will show up in both |:sign-place-list| and + |nvim_buf_get_extmarks()|. + • Legacy and extmark signs are displayed and listed with the same priority: + line number -> priority -> sign id -> recently placed + • `:behave` was removed. + • If you used `:behave xterm`, the following is equivalent: >vim + + set mousemodel=extend +< + • If you used `:behave mswin`, the following is equivalent: >vim + + set selection=exclusive + set selectmode=mouse,key + set mousemodel=popup + set keymodel=startsel,stopsel +< +• Events: + • Returning any truthy value from a callback passed to + |nvim_create_autocmd()| (rather than just `true`) will delete the + autocommand. + +• LSP: + • |LanguageTree:parse()| will no longer parse injections by default and now + requires an explicit range argument to be passed. If injections are + required, provide an explicit range via `parser:parse({ start_row, end_row })`. + • |vim.lsp.util.parse_snippet()| will now strictly follow the snippet + grammar defined by LSP, and hence previously parsed snippets might now be + considered invalid input. + • |vim.lsp.codelens.refresh()| now takes an `opts` argument. With this + change, the default behavior of just refreshing the current buffer has + been replaced by refreshing all buffers. + • |vim.lsp.util.extract_completion_items()| will no longer return reliable + results, since it does not apply `itemDefaults` when its input is + a `CompletionList`. Moreover, since support for LSP + `completionList.itemDefaults` was added, some third party plugins might be + negatively impacted in case the language servers support the feature but + the plugin does not. If necessary, the respective capability can be + removed when calling |vim.lsp.protocol.make_client_capabilities()|. + • |LspRequest| and LspProgressUpdate (renamed to |LspProgress|) autocmds + were promoted from |User| autocmds to first class citizens. + +• Lua: + • |-l| ensures output ends with a newline if the script prints messages and + doesn't cause Nvim to exit. + • Removed functions from the |vim.json| module: + • Unnecessary, undocumented functions which caused global side-effects. + • `vim.json.null` is redundant with `vim.NIL`. + • `vim.json.array_mt` (and related) is redundant with `vim.empty_dict()`. + • |vim.islist()| now checks whether a table is actually list-like (i.e., has + integer keys without gaps and starting from 1). For the previous behavior + (only check for integer keys, allow gaps or not starting with 1), use + |vim.isarray()|. + • Renamed `vim.treesitter.playground` to `vim.treesitter.dev`. + +• Options: + • Removed some Vim 5.0<= option compatibilities: + • 'backspace' no longer supports number values. Instead: + • for `backspace=0` set `backspace=` (empty) + • for `backspace=1` set `backspace=indent,eol` + • for `backspace=2` set `backspace=indent,eol,start` (default behavior in Nvim) + • for `backspace=3` set `backspace=indent,eol,nostop` + • 'backupdir' and 'directory' will no longer remove a `>` at the start of + the option. + • |OptionSet| autocommand args |v:option_new|, |v:option_old|, + |v:option_oldlocal|, |v:option_oldglobal| now have the type of the option + instead of always being strings. |v:option_old| is now the old global + value for all global-local options, instead of just string global-local + options. + • Local value for a global-local number/boolean option is now unset when the + option is set (e.g. using |:set| or |nvim_set_option_value()|) without + a scope, which means they now behave the same way as string options. + +• Plugins: + • |:TOhtml| has been rewritten in Lua to support Nvim-specific decorations, + and many options have been removed. + +• Treesitter: + • Treesitter highlight groups have been renamed to be more in line with + upstream tree-sitter and Helix to make it easier to share queries. The + full list is documented in |treesitter-highlight-groups|. + +• TUI: + • In some cases, the cursor in the Nvim |TUI| used to blink even without + configuring 'guicursor' as mentioned in |cursor-blinking|. This was a bug + that has now been fixed. If your cursor has stopped blinking, add the + following (or similar, adapted to user preference) to your |config| file: >vim + set guicursor+=n-v-c:blinkon500-blinkoff500 +< + +============================================================================== +NEW FEATURES + +The following new features were added. + +• API: + • Passing 0 to |nvim_get_chan_info()| gets info about the current channel. + • |nvim_buf_set_extmark()| supports inline virtual text. + • |nvim_win_text_height()| computes the number of screen lines occupied + by a range of text in a given window. + • New RPC client type `msgpack-rpc` is added for |nvim_set_client_info()| to + support fully MessagePack-RPC compliant clients. + • Floating windows can now be hidden by setting `hide` in |nvim_open_win()| or + |nvim_win_set_config()|. + • |nvim_input_mouse()| supports mouse buttons "x1" and "x2". + • Added "force_crlf" option field in |nvim_open_term()|. + • Added |nvim_tabpage_set_win()| to set the current window of a tabpage. + • |nvim__win_add_ns()| can bind a |namespace| to a window-local scope(s). + • Extmarks opt-in to this scoping via the `scoped` flag of |nvim_buf_set_extmark()|. + • Mapping APIs now support abbreviations when mode short-name has suffix "a". + • Floating windows can now show footer with new `footer` and `footer_pos` + config fields. Uses |hl-FloatFooter| by default. + • |extmarks| can set a "url" highlight attribute, so the text region can + become a clickable hyperlink (assuming UI support). The TUI renders URLs + using the OSC 8 control sequence, enabling clickable text in supporting + terminals. + • |nvim_open_win()| and |nvim_win_set_config()| now support opening normal + (split) windows, moving floating windows into split windows, and opening + windows in non-current tabpages. + • Flags added to |nvim_buf_set_extmark()|: + • "undo_restore": opt-out extmarks of precise undo tracking. + • "invalidate": automatically hide or delete extmarks. + • "virt_text_repeat_linebreak": repeat virtual text on wrapped lines. + • Extmarks now fully support multi-line ranges, and a single extmark can be + used to highlight a range of arbitrary length. The |nvim_buf_set_extmark()| + API function already allowed you to define such ranges, but highlight + regions were not rendered consistently for a range that covers more than + one line break. This has now been fixed. Signs defined as part of + a multi-line extmark also apply to every line in the range, not just the + first. In addition, |nvim_buf_get_extmarks()| has gained an "overlap" + option to return such ranges even if they started before the specified + position. + +• Defaults: + • The `workspace/didChangeWatchedFiles` LSP client capability is now enabled + by default on Mac and Windows. Disabled on Linux since there currently + isn't a viable backend for watching files that scales well for large + directories. + • On Windows 'isfname' does not include ":". Drive letters are handled + correctly without it. (Use |gF| for filepaths suffixed with ":line:col"). + • 'comments' includes "fb:•". + • 'shortmess' includes the "C" flag. + • 'grepprg' uses the -H and -I flags for grep by default, + and defaults to using ripgrep if available. + • "]d" and "[d" in Normal mode map to |vim.diagnostic.goto_next()| and + |vim.diagnostic.goto_prev()|, respectively. |]d-default| |[d-default| + • <C-W>d (and <C-W><C-D>) map to |vim.diagnostic.open_float()| + |CTRL-W_d-default| + • |vim.lsp.start()| sets the following default keymaps (assuming server + support): + • |K| in Normal mode maps to |vim.lsp.buf.hover()|, unless 'keywordprg' + was customized before calling |vim.lsp.start()|. + • Automatic linting of treesitter query files (see |ft-query-plugin|). + Can be disabled via: >lua + vim.g.query_lint_on = {} +< + • Enabled treesitter highlighting for: + • Treesitter query files + • Vim help files + • Lua files + +• Editor: + • Better cmdline completion for string option value. |complete-set-option| + • Try it with `:set listchars=<Tab>` + • By default, the swapfile "ATTENTION" |E325| dialog is skipped if the + swapfile is owned by a running Nvim process, instead of prompting. If you + always want the swapfile dialog, delete the default SwapExists handler: + `autocmd! nvim_swapfile`. |default-autocmds| + • Navigating the |jumplist| with CTRL+O, CTRL+I behaves more intuitively + when deleting buffers, and avoids "invalid buffer" cases. #25461 + • |:fclose| command. + • |v_Q-default| and |v_@-default| repeat a register for each line of a linewise + visual selection. + • Clicking on a tabpage in the tabline with the middle mouse button closes it. + • |:checkhealth| buffer can be opened in a split window using modifiers like + |:vertical|, |:horizontal| and |:botright|. + +• Events: + • |vim.on_key()| callbacks receive a second argument for keys typed before + mappings are applied. + +• LSP: + • LSP method names are available in |vim.lsp.protocol.Methods|. + • Implemented LSP inlay hints: |lsp-inlay_hint| + https://microsoft.github.io/language-server-protocol/specification/#textDocument_inlayHint + • Implemented pull diagnostic textDocument/diagnostic: |vim.lsp.diagnostic.on_diagnostic()| + https://microsoft.github.io/language-server-protocol/specification/#textDocument_diagnostic + • Implemented LSP type hierarchy: |vim.lsp.buf.typehierarchy()| + https://microsoft.github.io/language-server-protocol/specification/#textDocument_prepareTypeHierarchy + • |vim.lsp.status()| consumes the last progress messages as a string. + • LSP client now always saves and restores named buffer marks when applying + text edits. + • LSP client now supports the `positionEncoding` server capability. If a server + responds with the `positionEncoding` capability in its initialization + response, Nvim automatically sets the client's `offset_encoding` field. + • Dynamic registration of LSP capabilities. An implication of this change is + that checking a client's `server_capabilities` is no longer a sufficient + 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 + windows. + • |vim.lsp.util.locations_to_items()| sets the `user_data` of each item to + the original LSP `Location` or `LocationLink`. + • Added support for connecting to servers using named pipes (Windows) or + Unix domain sockets (Unix) via |vim.lsp.rpc.connect()|. + • Added support for `completionList.itemDefaults`, reducing overhead when + computing completion items where properties often share the same value + (e.g. `commitCharacters`). Note that this might affect plugins and + language servers that don't support the feature, and in such cases the + respective capability can be unset. + • |vim.lsp.start()| accepts a "silent" option for suppressing messages + if an LSP server failed to start. + • |vim.lsp.buf.definition()|, |vim.lsp.buf.declaration()|, + |vim.lsp.buf.type_definition()|, and |vim.lsp.buf.implementation()| now + support the `loclist` field of |vim.lsp.ListOpts|. + +• Lua: + • |:lua| with a |[range]| executes that range as Lua code, in any buffer. + • |:source| without arguments treats a buffer with 'filetype' of "lua" as + Lua code regardless of its extension. + • Vimscript function |exists()| supports checking |v:lua| functions. + • |vim.iter()| is a generic interface for all |iterable| objects (tables, + |iterator|s). + • |vim.snippet| provides a mode for expanding and navigating snippets. + • |vim.ringbuf()| is a generic ring buffer (data structure). + • |vim.deepcopy()| gained a `noref` argument to avoid hashing table values. + • |vim.keycode()| translates keycodes in a string. + • |vim.system()| runs commands / starts processes. + • |vim.lpeg| and |vim.re| expose the bundled Lpeg expression grammar parser + and its regex interface. + • |vim.base64.encode()| and |vim.base64.decode()| encode and decode strings + using Base64 encoding. + • |vim.text.hexencode()| and |vim.text.hexdecode()| convert strings to and + from byte representations. + • |vim.ui.open()| opens URIs using the system default handler (macOS `open`, + Windows `explorer`, Linux `xdg-open`, etc.) + • |vim.wo| can now be double indexed for |:setlocal| behaviour. Currently + only `0` for the buffer index is supported. + • Improved messages for type errors in `vim.api.*` calls (including `opts` params). + • Lua type annotations for: + • `vim.*` + • `vim.fn.*` + • `vim.api.*` + • `vim.v.*` + • Functions that take a severity as an optional parameter (e.g. + |vim.diagnostic.get()|) now also accept a list of severities |vim.diagnostic.severity| + • |vim.diagnostic.count()| returns the number of diagnostics for a given + buffer and/or namespace, by severity. This is a faster alternative to + |vim.diagnostic.get()| when only the number of diagnostics is needed, but + not the diagnostics themselves. + • |vim.diagnostic.is_enabled()| + • |vim.version.le()|, |vim.version.ge()| + • |vim.fs.root()| finds project root directories from a list of "root + markers". + • |vim.tbl_contains()| now works for general tables and allows specifying + a predicate function that is checked for each value. (Use + |vim.list_contains()| for checking list-like tables (integer keys without + gaps) for literal values.) + • |vim.region()| can use a string accepted by |getpos()| as position. + +• Options: + • 'winfixbuf' keeps a window focused onto a specific buffer + • 'smoothscroll' option to scroll by screen line rather than by text line + when 'wrap' is set. + • 'foldtext' now supports virtual text format. |fold-foldtext| + • 'foldtext' can be set to an empty string to disable and render the line: + as normal with regular highlighting and no line wrapping. + • 'complete' option supports "f" flag for completing buffer names. + • 'completeopt' option supports "popup" flag to show extra information in + a floating window. + • 'errorfile' (|-q|) accepts `-` as an alias for stdin. + +• Performance: + • 'diffopt' "linematch" scoring algorithm now favours larger and less groups + https://github.com/neovim/neovim/pull/23611 + • Treesitter highlighting now parses injections incrementally during + screen redraws only for the line range being rendered. This significantly + improves performance in large files with many injections. + • 'breakindent' performance is significantly improved for wrapped lines. + • Cursor movement, insertion with [count] and |screenpos()| are now faster. + +• Plugins: + • Nvim now includes |commenting| support. + • |:Man| supports the `:hide` modifier to open page in the current window. + • |:Man| respects 'wrapmargin' + +• Startup: + • |$NVIM_APPNAME| can be set to a relative path instead of only a name. + • |--startuptime| reports startup times for both processes (TUI + server) as + separate sections. + +• Terminal: + • |:terminal| accepts some |:command-modifiers| (specifically |:horizontal| + and those that affect splitting a window). + • Terminal buffers emit a |TermRequest| autocommand event when the child + process emits an OSC or DCS control sequence. + • Terminal buffers respond to OSC background and foreground requests. + |default-autocmds| + +• Treesitter: + • Bundled parsers and queries (highlight, folds) for Markdown, Python, and + Bash. + • |:InspectTree| shows root nodes. + • |:InspectTree| now supports |folding|. + • |:InspectTree| shows node ranges in 0-based instead of 1-based indexing. + • |vim.treesitter.foldexpr()| now recognizes folds captured using a + quantified query pattern. + • |vim.treesitter.query.omnifunc()| provides completion in treesitter query + files (set by default). + • |vim.treesitter.query.edit()| provides live editing of treesitter queries. + • |Query:iter_matches()| now has the ability to set the maximum start depth + for matches. + • `@injection.language` now has smarter resolution and will fall back to + language aliases (e.g., filetype or custom shorthands) registered via + |vim.treesitter.language.register()| and/or attempt lower case variants of + the text. + • `@injection.filename` will try to match the node text via + |vim.filetype.match()| and treat the result as a language name in the same + way as `@injection.language`. + • The `#set!` directive supports `injection.self` and `injection.parent` for + injecting either the current node's language or the parent + |LanguageTree|'s language, respectively. + • The `#set!` directive can set the "url" property of a node to have the + node emit a hyperlink. Hyperlinks are UI specific: in the TUI, the OSC 8 + control sequence is used. + • Improved error messages for query parsing. + +• TUI: + • Builtin TUI can now recognize "super" (|<D-|) and "meta" (|<T-|) modifiers + in a terminal emulator that supports |tui-csiu|. + • The |TermResponse| event can be used with |v:termresponse| to read escape + sequence responses from the host terminal. + • A clipboard provider which uses OSC 52 to copy the selection to the system + clipboard is now bundled by default and will be automatically enabled under + certain conditions. |clipboard-osc52| + • 'termsync' option asks the host terminal to buffer screen updates until + the redraw cycle is complete. Requires support from the host terminal. + +• UI: + • Enhanced support for rendering multibyte characters using composing + characters: the maximum limit was increased from 1+6 codepoints to + 31 bytes, which is guaranteed to fit all chars from before but often more. + • NOTE: the regexp engine still has a hard-coded limit of considering + 6 composing chars only. + + +============================================================================== +CHANGED FEATURES + +These existing features changed their behavior. + +• API: + • |nvim_buf_call()| and |nvim_win_call()| now preserve any return value (NB: + not multiple return values) + +• Editor: + • |gx| now uses |vim.ui.open()| and not netrw. To customize, you can redefine + `vim.ui.open` or remap `gx`. To continue using netrw (deprecated): >vim + :call netrw#BrowseX(expand(exists("g:netrw_gx") ? g:netrw_gx : '<cfile>'), netrw#CheckIfRemote())<CR> + +• LSP: + • LSP hover and signature help now use Treesitter for highlighting of + Markdown content. Note that highlighting of code examples requires + a matching parser and may be affected by custom queries. + • |LspRequest| autocmd callbacks contain more information about the LSP + request status update that occurred. + +• Lua: + • |vim.wait()| cannot be called in |api-fast|. + • |vim.diagnostic.config()| now accepts virtual text relevant options to + |nvim_buf_set_extmark()| (e.g. "virt_text_pos" and "hl_mode") in its + "virtual_text" table, which gives users more control over how diagnostic + virtual text is displayed. + • |vim.diagnostic.get()| and |vim.diagnostic.count()| accept multiple + namespaces rather than just a single namespace. + • |vim.diagnostic.enable()| gained new parameters, and the old signature is + deprecated. + • |vim.diagnostic.config()| now accepts a function for the virtual_text.prefix + option, which allows for rendering e.g., diagnostic severities differently. + +• Options: + • Attempting to set an invalid keycode option (e.g. `set t_foo=123`) no + longer gives an error. + +• Terminal: + • Terminal buffers started with no arguments (and use 'shell') close + automatically if the job exited without error, eliminating the (often + unwanted) "[Process exited 0]" message. |default-autocmds| + +• Treesitter: + • |Query:iter_matches()|, |vim.treesitter.query.add_predicate()|, and + |vim.treesitter.query.add_directive()| accept a new `all` option which + ensures that all matching nodes are returned as a table. The default option + `all=false` returns only a single node, breaking captures with quantifiers + like `(comment)+ @comment`; it is only provided for backward compatibility + and will be removed after Nvim 0.10. + • |vim.treesitter.query.add_predicate()| and + |vim.treesitter.query.add_directive()| now accept an options table rather + than a boolean "force" argument. To force a predicate or directive to + override an existing predicate or directive, use `{ force = true }`. + +============================================================================== +REMOVED FEATURES + +These deprecated features were removed. + +• Vimball support, including `:Vimuntar` command + +• Support for legacy treesitter injection queries + +• 'shortmess' flags: + • |shm-f|. Always use "(3 of 5)", never "(file 3 of 5)". + • |shm-i|. Always use "[noeol]". + • |shm-x|. Always use "[dos]", "[unix]" and "[mac]". + • |shm-n|. Always use "[New]". + +============================================================================== +DEPRECATIONS + +See |deprecated-0.10|. + + vim:tw=78:ts=8:sw=2:et:ft=help:norl: diff --git a/runtime/doc/news-0.9.txt b/runtime/doc/news-0.9.txt index 789bc9e0bc..7905d6c3e3 100644 --- a/runtime/doc/news-0.9.txt +++ b/runtime/doc/news-0.9.txt @@ -4,7 +4,7 @@ NVIM REFERENCE MANUAL -Notable changes in Nvim 0.9 from 0.8 *news-0.9* +Notable changes since Nvim 0.8 *news-0.9* Type |gO| to see the table of contents. @@ -162,7 +162,7 @@ The following new APIs or features were added. • |vim.diagnostic| now supports LSP DiagnosticsTag. See: https://microsoft.github.io/language-server-protocol/specification/#diagnosticTag -• |vim.diagnostic.is_disabled()| checks if diagnostics are disabled in a given +• vim.diagnostic.is_disabled() checks if diagnostics are disabled in a given buffer or namespace. • Treesitter captures can now be transformed by directives. This will allow @@ -290,34 +290,6 @@ The following deprecated functions or APIs were removed. ============================================================================== DEPRECATIONS -The following functions are now deprecated and will be removed in the next -release. - -• |vim.treesitter.language.add()| replaces `vim.treesitter.language.require_language()` - -• |vim.treesitter.get_node_at_pos()| and |vim.treesitter.get_node_at_cursor()| - are both deprecated in favor of |vim.treesitter.get_node()|. - -• `vim.api.nvim_get_hl_by_name()`, `vim.api.nvim_get_hl_by_id()` were deprecated, use |nvim_get_hl()| instead. - -• The following top level Treesitter functions have been moved: - `vim.treesitter.inspect_language()` -> `vim.treesitter.language.inspect()` - `vim.treesitter.get_query_files()` -> `vim.treesitter.query.get_files()` - `vim.treesitter.set_query()` -> `vim.treesitter.query.set()` - `vim.treesitter.query.set_query()` -> `vim.treesitter.query.set()` - `vim.treesitter.get_query()` -> `vim.treesitter.query.get()` - `vim.treesitter.query.get_query()` -> `vim.treesitter.query.get()` - `vim.treesitter.parse_query()` -> `vim.treesitter.query.parse()` - `vim.treesitter.query.parse_query()` -> `vim.treesitter.query.parse()` - `vim.treesitter.add_predicate()` -> `vim.treesitter.query.add_predicate()` - `vim.treesitter.add_directive()` -> `vim.treesitter.query.add_directive()` - `vim.treesitter.list_predicates()` -> `vim.treesitter.query.list_predicates()` - `vim.treesitter.list_directives()` -> `vim.treesitter.query.list_directives()` - `vim.treesitter.query.get_range()` -> `vim.treesitter.get_range()` - `vim.treesitter.query.get_node_text()` -> `vim.treesitter.get_node_text()` - -• |nvim_exec()| is now deprecated in favor of |nvim_exec2()|. - -• Renamed |vim.pretty_print()| to |vim.print()|. +See |deprecated-0.9|. vim:tw=78:ts=8:sw=2:et:ft=help:norl: diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 3029414500..708e127136 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -4,529 +4,156 @@ NVIM REFERENCE MANUAL -Notable changes in Nvim 0.10 from 0.9 *news* +Notable changes since Nvim 0.10 *news* -For changes in Nvim 0.9, see |news-0.9|. +For changes in the previous release, see |news-0.10|. Type |gO| to see the table of contents. ============================================================================== -BREAKING CHANGES *news-breaking* - -The following changes may require adaptations in user config or plugins. - -• In some cases, the cursor in the Nvim |TUI| used to blink even without - configuring 'guicursor' as mentioned in |cursor-blinking|. This was a bug - that has now been fixed. If your cursor has stopped blinking, add the - following (or similar, adapted to user preference) to your |config| file: >vim - - set guicursor+=n-v-c:blinkon500-blinkoff500 -< -• |vim.tbl_islist()| now checks whether a table is actually list-like (i.e., - has integer keys without gaps and starting from 1). For the previous - behavior (only check for integer keys, allow gaps or not starting with 1), - use |vim.tbl_isarray()|. - -• "#" followed by a digit no longer stands for a function key at the start of - the lhs of a mapping. - -• `:behave` was removed. - - If you used `:behave xterm`, the following is equivalent: >vim - - set mousemodel=extend -< - - If you used `:behave mswin`, the following is equivalent: >vim - - set selection=exclusive - set selectmode=mouse,key - set mousemodel=popup - set keymodel=startsel,stopsel -< -• When switching windows, |CursorMoved| autocommands trigger when Nvim is back - in the main loop rather than immediately. This is more compatible with Vim. - -• |-l| ensures output ends with a newline if the script prints messages and - doesn't cause Nvim to exit. - -• |LspRequest| and LspProgressUpdate (renamed to |LspProgress|) autocmds were - promoted from a |User| autocmd to first class citizen. - -• Renamed `vim.treesitter.playground` to `vim.treesitter.dev`. - -• Removed functions from the |vim.json| module: - • Unnecessary, undocumented functions which caused global side-effects. - • `vim.json.null` is redundant with `vim.NIL`. - • `vim.json.array_mt` (and related) is redundant with `vim.empty_dict()`. - -• Removed some Vim 5.0<= option compatibilities: - • |'backspace'| no longer supports number values. Instead: - • for `backspace=0` set `backspace=` (empty) - • for `backspace=1` set `backspace=indent,eol` - • for `backspace=2` set `backspace=indent,eol,start` (default behavior in Nvim) - • for `backspace=3` set `backspace=indent,eol,nostop` - • |'backupdir'| and |'directory'| will no longer remove a `>` at the start - of the option. - -• |LanguageTree:parse()| will no longer parse injections by default and - now requires an explicit range argument to be passed. If injections are - required, provide an explicit range via `parser:parse({ start_row, end_row })`. - -• |vim.lsp.util.parse_snippet()| will now strictly follow the snippet grammar - defined by LSP, and hence previously parsed snippets might now be considered - invalid input. - -• |OptionSet| autocommand args |v:option_new|, |v:option_old|, - |v:option_oldlocal|, |v:option_oldglobal| now have the type of the option - instead of always being strings. |v:option_old| is now the old global value - for all global-local options, instead of just string global-local options. - -• Local value for a global-local number/boolean option is now unset when - the option is set (e.g. using |:set| or |nvim_set_option_value()|) without a - scope, which means they now behave the same way as string options. - -• Signs placed through the legacy |sign-commands| are now stored and displayed - as |extmarks| internally. Along with the following changes: - • A sign placed twice in the same group with the same identifier will be moved. - • Legacy signs are always deleted along with the line it is placed on. - • Legacy and extmark signs will show up in both |:sign-place-list| and |nvim_buf_get_extmarks()|. - • Legacy and extmark signs are displayed and listed with the same priority: - line number -> priority -> sign id -> recently placed - -• Default color scheme has been updated to be "Nvim branded" and accessible. - Use `:colorscheme vim` to revert to the old legacy color scheme. - - Here is a list of Nvim specific highlight groups which are now defined in - a meaningfully different way and might need an update: - • |hl-FloatBorder| is linked to |hl-NormalFloat| instead of |hl-WinSeparator|. - • |hl-NormalFloat| is not linked to |hl-Pmenu|. - • |hl-WinBar| has different background. - • |hl-WinBarNC| is similar to |hl-WinBar| but not bold. - • |hl-WinSeparator| is linked to |hl-Normal| instead of |hl-VertSplit|. - - This also might result into some color schemes looking differently due to - them relying on implicit assumptions about how highlight groups are defined - by default. To account for this, define all attributes of highlight groups - explicitly. Alternatively, use `:colorscheme vim` or `:source - $VIMRUNTIME/colors/vim.lua` to restore previous definitions. - -• 'termguicolors' is enabled by default when Nvim is able to determine that - the host terminal emulator supports 24-bit color. - -• Treesitter highlight groups have been renamed to be more in line with - upstream tree-sitter and Helix to make it easier to share queries. The full - list is documented in |treesitter-highlight-groups|. - -• |vim.lsp.codelens.refresh()| now takes an `opts` argument. With this change, - the default behavior of just refreshing the current buffer has been replaced by - refreshing all buffers. - -• |shm-q| now fully hides macro recording message instead of only shortening it. - -• Returning any truthy value from a callback passed to |nvim_create_autocmd()| - (rather than just `true`) will delete the autocommand. - -• |vim.lsp.util.extract_completion_items()| will no longer return reliable - results, since it does not apply `itemDefaults` when its input is a - `CompletionList`. - Moreover, since support for LSP `completionList.itemDefaults` was added, - some third party plugins might be negatively impacted in case the language - servers support the feature but the plugin does not. - If necessary, the respective capability can be - removed when calling |vim.lsp.protocol.make_client_capabilities()|. - -• |:TOhtml| has been rewritten in Lua to support Neovim-specific decorations, - and many options have been removed. - -============================================================================== BREAKING CHANGES IN HEAD *news-breaking-dev* -The following breaking changes were made during the development cycle to -unreleased features on Nvim HEAD. + ====== Remove this section before release. ====== -• Removed `vim.treesitter.foldtext` as transparent foldtext is now supported - https://github.com/neovim/neovim/pull/20750 +The following changes to UNRELEASED features were made during the development +cycle (Nvim HEAD, the "master" branch). ============================================================================== -NEW FEATURES *news-features* - -The following new APIs and features were added. - -• Performance: - • 'diffopt' "linematch" scoring algorithm now favours larger and less groups - https://github.com/neovim/neovim/pull/23611 - • Treesitter highlighting now parses injections incrementally during - screen redraws only for the line range being rendered. This significantly - improves performance in large files with many injections. - • 'breakindent' performance is significantly improved for wrapped lines. - • Cursor movement, insertion with [count] and |screenpos()| are now faster. - -• |vim.iter()| provides a generic iterator interface for tables and Lua - iterators |for-in|. - -• |vim.ringbuf()| creates ring buffers. - -• |vim.keycode()| translates keycodes in a string. - -• |'smoothscroll'| option to scroll by screen line rather than by text line - when |'wrap'| is set. - -• |nvim_buf_set_extmark()| supports inline virtual text. - -• 'foldtext' now supports virtual text format. |fold-foldtext| - -• |'foldtext'| can be set to an empty string to disable and render the line: - as normal with regular highlighting and no line wrapping. - -• The terminal buffer now supports reflow (wrapped lines adapt when the buffer - is resized horizontally). Note: Lines that are not visible and kept in - |'scrollback'| are not reflown. - -• |vim.system()| for running system commands. - -• |vim.lpeg| and |vim.re| expose the bundled Lpeg expression grammar parser - and its regex interface. - -• |nvim_win_text_height()| computes the number of screen lines occupied - by a range of text in a given window. - -• Mapping APIs now support abbreviations when mode short-name has suffix "a". - -• Better cmdline completion for string option value. |complete-set-option| - -• Builtin TUI can now recognize "super" (|<D-|) and "meta" (|<T-|) modifiers in a - terminal emulator that supports |tui-csiu|. - -• Editor - • By default, the swapfile "ATTENTION" |E325| dialog is skipped if the - swapfile is owned by a running Nvim process, instead of prompting. If you - always want the swapfile dialog, delete the default SwapExists handler: - `autocmd! nvim_swapfile`. |default-autocmds| - -• LSP - • LSP method names are available in |vim.lsp.protocol.Methods|. - • Implemented LSP inlay hints: |lsp-inlay_hint| - https://microsoft.github.io/language-server-protocol/specification/#textDocument_inlayHint - • Implemented pull diagnostic textDocument/diagnostic: |vim.lsp.diagnostic.on_diagnostic()| - https://microsoft.github.io/language-server-protocol/specification/#textDocument_diagnostic - • |vim.lsp.status()| consumes the last progress messages as a string. - • LSP client now always saves and restores named buffer marks when applying - text edits. - • LSP client now supports the `positionEncoding` server capability. If a server - responds with the `positionEncoding` capability in its initialization - response, Nvim automatically sets the client's `offset_encoding` field. - • Dynamic registration of LSP capabilities. An implication of this change is - that checking a client's `server_capabilities` is no longer a sufficient - 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 - windows. - • |vim.lsp.util.locations_to_items()| sets the `user_data` of each item to - the original LSP `Location` or `LocationLink`. - • Added support for connecting to servers using named pipes (Windows) or - unix domain sockets (Unix) via |vim.lsp.rpc.domain_socket_connect()|. - • Added support for `completionList.itemDefaults`, reducing overhead when - computing completion items where properties often share the same value - (e.g. `commitCharacters`). Note that this might affect plugins and - language servers that don't support the feature, and in such cases the - respective capability can be unset. - -• Treesitter - • Bundled parsers and queries (highlight, folds) for Markdown, Python, and - Bash. - • |vim.treesitter.query.omnifunc()| for treesitter query files (set by - default). - • |Query:iter_matches()| now has the ability to set the maximum start depth - for matches. - • `@injection.language` now has smarter resolution and will fall back to - language aliases (e.g., filetype or custom shorthands) registered via - |vim.treesitter.language.register()| and/or attempt lower case variants of - the text. - • The `#set!` directive now supports `injection.self` and `injection.parent` - for injecting either the current node's language or the parent - |LanguageTree|'s language, respectively. - • |vim.treesitter.query.edit()| allows live editing of treesitter - queries. - • Improved error messages for query parsing. - • |:InspectTree| shows node ranges in 0-based indexing instead of 1-based - indexing. - • |:InspectTree| shows root nodes - • |:InspectTree| now supports |folding| - -• |vim.ui.open()| opens URIs using the system default handler (macOS `open`, - Windows `explorer`, Linux `xdg-open`, etc.) - -• |vim.wo| can now be double indexed for |:setlocal| behaviour. Currently only - `0` for the buffer index is currently supported. - -• Lua type annotations for: - • `vim.*` - • `vim.fn.*` - • `vim.api.*` - • `vim.v.*` - -• Improved messages for type errors in `vim.api.*` calls (including `opts` params) +BREAKING CHANGES *news-breaking* -• Functions that take a severity as an optional parameter (e.g. - |vim.diagnostic.get()|) now also accept a list of severities |vim.diagnostic.severity| +These changes may require adaptations in your config or plugins. -• New RPC client type `msgpack-rpc` is added for |nvim_set_client_info()| to - support fully MessagePack-RPC compliant clients. +API -• Floating windows can now show footer with new `footer` and `footer_pos` - config fields. Uses |hl-FloatFooter| by default. +• `vim.rpcnotify(0)` and `rpcnotify(0)` broadcast to ALL channels. Previously + they would "multicast" only to subscribed channels (controlled by + `nvim_subscribe()`). Plugins and clients that want "multicast" behavior must + now maintain their own list of channels. + • In the future, |vim.rpcnotify()| may accept a list of channels, if there + is demand for this use-case. -• Floating windows can now be hidden by setting `hide` in |nvim_open_win()| or - |nvim_win_set_config()|. +DEFAULTS -• |:terminal| command now accepts some |:command-modifiers| (specifically - |:horizontal| and those that affect splitting a window). +• TODO -• |$NVIM_APPNAME| can be set to a relative path instead of only a name. +EDITOR -• |:fclose| command. +• The order in which signs are placed was changed. Higher priority signs will now appear left of lower priority signs. -• |vim.snippet| handles expansion of snippets in LSP format. +EVENTS -• 'complete' option supports "f" flag for completing buffer names. +• TODO -• |vim.base64.encode()| and |vim.base64.decode()| encode and decode strings - using Base64 encoding. - -• The |TermResponse| autocommand event can be used with |v:termresponse| to - read escape sequence responses from the terminal. - -• A clipboard provider which uses OSC 52 to copy the selection to the system - clipboard is now bundled by default and will be automatically enabled under - certain conditions. |clipboard-osc52| - -• 'termsync' option asks the terminal emulator to buffer screen updates until - the redraw cycle is complete. Requires support from the terminal. - -• |vim.text.hexencode()| and |vim.text.hexdecode()| convert strings to and - from byte representations. +LSP -• 'completeopt' option supports "popup" flag to show extra information in a - floating window. +• TODO -• |nvim_input_mouse()| supports mouse buttons "x1" and "x2". +LUA -• |v_Q-default| and |v_@-default| repeat a register for each line of a visual - selection. +• TODO -• |vim.diagnostic.count()| returns the number of diagnostics for a given - buffer and/or namespace, by severity. This is a faster alternative to - |vim.diagnostic.get()| when only the number of diagnostics is needed, but - not the diagnostics themselves. +OPTIONS -• |vim.deepcopy()| has a `noref` argument to avoid hashing table values. +• TODO -• Terminal buffers emit a |TermRequest| autocommand event when the child - process emits an OSC or DCS control sequence. +PLUGINS -• Terminal buffers respond to OSC background and foreground requests. |default-autocmds| +• TODO -• |vim.version.le()| and |vim.version.ge()| are added to |vim.version|. +TREESITTER -• |extmarks| can be associated with a URL and URLs are included as a new - highlight attribute. The TUI will display URLs using the OSC 8 control - sequence, enabling clickable text in supporting terminals. +• TODO -• Added |nvim_tabpage_set_win()| to set the current window of a tabpage. +TUI -• Clicking on a tabpage in the tabline with the middle mouse button closes it. +• TODO -• |namespace| can now have window scopes. |nvim_win_add_ns()| +============================================================================== +NEW FEATURES *news-features* -• |extmarks| option `scoped`: only show the extmarks in its namespace's scope. +The following new features were added. -============================================================================== -CHANGED FEATURES *news-changed* +API -The following changes to existing APIs or features add new behavior. +• TODO -• |vim.tbl_contains()| now works for general tables and allows specifying a - predicate function that is checked for each value. (Use |vim.list_contains()| - for checking list-like tables (integer keys without gaps) for literal values.) +DEFAULTS -• |vim.region()| can use a string accepted by |getpos()| as position. +• Keymaps: + - |grn| in Normal mode maps to |vim.lsp.buf.rename()| + - |grr| in Normal mode maps to |vim.lsp.buf.references()| + - |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()| -• |vim.diagnostic.config()| now accepts a function for the virtual_text.prefix - option, which allows for rendering e.g., diagnostic severities differently. +EDITOR -• Defaults: - • On Windows 'isfname' does not include ":". Drive letters are handled - correctly without it. (Use |gF| for filepaths suffixed with ":line:col"). - • 'comments' includes "fb:•". - • 'shortmess' includes the "C" flag. - • Automatic linting of treesitter query files (see |ft-query-plugin|). - Can be disabled via: >lua - vim.g.query_lint_on = {} -< - • Enabled treesitter highlighting for treesitter query files. - • Enabled treesitter highlighting for help files. - • Enabled treesitter highlighting for Lua files. +• TODO -• The `workspace/didChangeWatchedFiles` LSP client capability is now enabled - by default. - • On Mac or Windows, `libuv.fs_watch` is used as the backend. - • On Linux, `fswatch` (recommended) is used as the backend if available, - otherwise `libuv.fs_event` is used on each subdirectory. +EVENTS -• |LspRequest| autocmd callbacks now contain additional information about the LSP - request status update that occurred. +• TODO -• |:source| without arguments treats a buffer with its 'filetype' set to "lua" - as Lua code regardless of its extension. +LSP -• |:lua| with a |[range]| executes that range in the current buffer as Lua code - regardless of its extension. +• TODO -• |:checkhealth| buffer now implements |folding|. The initial folding status is - defined by the 'foldenable' option. +LUA -• |:Man| now respects 'wrapmargin' +• TODO -• |gx| now uses |vim.ui.open()| and not netrw. To customize, you can redefine - `vim.ui.open` or remap `gx`. To continue using netrw (deprecated): >vim +OPTIONS - :call netrw#BrowseX(expand(exists("g:netrw_gx")? g:netrw_gx : '<cfile>'), netrw#CheckIfRemote())<CR> +• TODO -• |vim.lsp.start()| now maps |K| to use |vim.lsp.buf.hover()| if the server - supports it, unless |'keywordprg'| was customized before calling - |vim.lsp.start()|. +PERFORMANCE -• Terminal buffers started with no arguments (and use 'shell') close - automatically if the job exited without error, eliminating the (often - unwanted) "[Process exited 0]" message. +• TODO -• |vim.diagnostic.config()| now accepts virtual text relevant options to - |nvim_buf_set_extmark()| (e.g. "virt_text_pos" and "hl_mode") in its - "virtual_text" table, which gives users more control over how diagnostic - virtual text is displayed. +PLUGINS -• Extmarks now fully support multi-line ranges, and a single extmark can be - used to highlight a range of arbitrary length. The |nvim_buf_set_extmark()| - API function already allowed you to define such ranges, but highlight regions - were not rendered consistently for a range that covers more than one line break. - This has now been fixed. Signs defined as part of a multi-line extmark also - apply to every line in the range, not just the first. - In addition, |nvim_buf_get_extmarks()| has gained an "overlap" option to - return such ranges even if they started before the specified position. +• TODO -• The following flags were added to |nvim_buf_set_extmark()|: - - "undo_restore": opt-out extmarks of precise undo tracking. - - "invalidate": automatically hide or delete extmarks. - - "virt_text_repeat_linebreak": repeat virtual text on wrapped lines. +STARTUP -• LSP hover and signature help now use Treesitter for highlighting of Markdown - content. - Note that syntax highlighting of code examples requires a matching parser - and may be affected by custom queries. +• TODO -• Support for rendering multibyte characters using composing characters has been - enhanced. The maximum limit have been increased from 1+6 codepoints to - 31 bytes, which is guaranteed to fit all chars from before but often more. +TERMINAL - NOTE: the regexp engine still has a hard-coded limit of considering - 6 composing chars only. +• TODO -• |vim.wait()| is no longer allowed to be called in |api-fast|. +TREESITTER -• Vimscript function |exists()| supports checking |v:lua| functions. +• TODO -• Added "force_crlf" option field in |nvim_open_term()|. +TUI -• Attempting to set an invalid keycode option (e.g. `set t_foo=123`) no longer - gives an error. +• TODO -• Passing 0 to |nvim_get_chan_info()| gets info about the current channel. +UI -• |:checkhealth| buffer can now be opened in a split window using modifiers like - |:vertical|, |:horizontal| and |:botright|. +• TODO -• |nvim_open_win()| and |nvim_win_set_config()| now support opening normal (split) - windows, and moving floating windows into split windows. -• 'errorfile' (|-q|) accepts `-` as an alias for stdin. +• |CompleteDone| now sets the `reason` key in `v:event` which specifies the reason + for completion being done. -• |--startuptime| reports the startup times for both processes (TUI + server) as separate sections. +============================================================================== +CHANGED FEATURES *news-changed* -• |nvim_buf_call()| and |nvim_win_call()| now preserves any return value (NB: not multiple return values) +These existing features changed their behavior. -• Treesitter - • |Query:iter_matches()|, |vim.treesitter.query.add_predicate()|, and - |vim.treesitter.query.add_directive()| accept a new `all` option which - ensures that all matching nodes are returned as a table. The default option - `all=false` returns only a single node, breaking captures with quantifiers - like `(comment)+ @comment; it is only provided for backward compatibility - and will be removed after Nvim 0.10. - • |vim.treesitter.query.add_predicate()| and - |vim.treesitter.query.add_directive()| now accept an options table rather - than a boolean "force" argument. To force a predicate or directive to - override an existing predicate or directive, use `{ force = true }`. +• N/A ============================================================================== REMOVED FEATURES *news-removed* -The following deprecated functions or APIs were removed. - -• Vimball support - - :Vimuntar command - -• Support for legacy treesitter injection queries +These deprecated features were removed. -• 'shortmess' flags: - - |shm-f|. Always uses "(3 of 5)", never "(file 3 of 5)" - - |shm-i|. Always use "[noeol]". - - |shm-x|. Always use "[dos]", "[unix]" and "[mac]" - - |shm-n|. Always use "[New]". +• N/A ============================================================================== DEPRECATIONS *news-deprecations* -The following functions are now deprecated and will be removed in a future -release. - -• Configuring |diagnostic-signs| using |:sign-define| or |sign_define()|. Use - the "signs" key of |vim.diagnostic.config()| instead. - -• Checkhealth functions: - - |health#report_error|, |vim.health.report_error()| Use |vim.health.error()| instead. - - |health#report_info|, |vim.health.report_info()| Use |vim.health.info()| instead. - - |health#report_ok|, |vim.health.report_ok()| Use |vim.health.ok()| instead. - - |health#report_start|, |vim.health.report_start()| Use |vim.health.start()| instead. - - |health#report_warn|, |vim.health.report_warn()| Use |vim.health.warn()| instead. - -• |API| functions: - - |nvim_buf_get_option()| Use |nvim_get_option_value()| instead. - - |nvim_buf_set_option()| Use |nvim_set_option_value()| instead. - - |nvim_get_option()| Use |nvim_get_option_value()| instead. - - |nvim_set_option()| Use |nvim_set_option_value()| instead. - - |nvim_win_get_option()| Use |nvim_get_option_value()| instead. - - |nvim_win_set_option()| Use |nvim_set_option_value()| instead. - -• vim.lsp functions: - - |vim.lsp.util.get_progress_messages()| Use |vim.lsp.status()| instead. - - |vim.lsp.get_active_clients()| Use |vim.lsp.get_clients()| instead. - - |vim.lsp.for_each_buffer_client()| Use |vim.lsp.get_clients()| instead. - - |vim.lsp.util.trim_empty_lines()| Use |vim.split()| with `trimempty` instead. - - |vim.lsp.util.try_trim_markdown_code_blocks()| - - |vim.lsp.util.set_lines()| - - |vim.lsp.util.extract_completion_items()| - - |vim.lsp.util.parse_snippet()| - - |vim.lsp.util.text_document_completion_list_to_complete_items()| - -• `vim.loop` has been renamed to |vim.uv|. - -• vim.treesitter functions: - - |LanguageTree:for_each_child()| Use |LanguageTree:children()| (non-recursive) instead. - -• The "term_background" UI option |ui-ext-options| is deprecated and no longer - populated. Background color detection is now performed in Lua by the Nvim - core, not the TUI. - -• vim.shared functions: - - |vim.tbl_add_reverse_lookup()| +See |deprecated-0.11|. vim:tw=78:ts=8:sw=2:et:ft=help:norl: diff --git a/runtime/doc/nvim_terminal_emulator.txt b/runtime/doc/nvim_terminal_emulator.txt index d4e05cee26..a6ebc7e958 100644 --- a/runtime/doc/nvim_terminal_emulator.txt +++ b/runtime/doc/nvim_terminal_emulator.txt @@ -126,6 +126,46 @@ color index is just forwarded. Editor highlighting (|syntax-highlighting|, |highlight-groups|, etc.) has higher precedence: it is applied after terminal colors are resolved. +------------------------------------------------------------------------------ +EVENTS *terminal-events* + +Applications running in a :terminal buffer can send requests, which Nvim +exposes via the |TermRequest| event. + +OSC 7: change working directory *terminal-osc7* + +To handle OSC 7 emitted from :terminal processes, this code will :cd to the +directory indicated in the request. >lua + + vim.api.nvim_create_autocmd({ 'TermRequest' }, { + desc = 'Handles OSC 7 dir change requests', + callback = function(ev) + if string.sub(vim.v.termrequest, 1, 4) == '\x1b]7;' then + local dir = string.gsub(vim.v.termrequest, '\x1b]7;file://[^/]*', '') + if vim.fn.isdirectory(dir) == 0 then + vim.notify('invalid dir: '..dir) + return + end + vim.api.nvim_buf_set_var(ev.buf, 'osc7_dir', dir) + if vim.o.autochdir and vim.api.nvim_get_current_buf() == ev.buf then + vim.cmd.cd(dir) + end + end + end + }) + vim.api.nvim_create_autocmd({ 'BufEnter', 'WinEnter', 'DirChanged' }, { + callback = function(ev) + if vim.b.osc7_dir and vim.fn.isdirectory(vim.b.osc7_dir) == 1 then + vim.cmd.cd(vim.b.osc7_dir) + end + end + }) + +To try it out, select the above code and source it with `:'<,'>lua`, then run +this command in a :terminal buffer: > + + printf "\033]7;file://./foo/bar\033\\" + ============================================================================== Status Variables *terminal-status* diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 133b2bc33c..5570e62ab8 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -270,6 +270,7 @@ created, thus they behave slightly differently: Option Reason ~ 'previewwindow' there can only be a single one 'scroll' specific to existing window + 'winfixbuf' specific to existing window 'winfixheight' specific to existing window 'winfixwidth' specific to existing window @@ -638,10 +639,9 @@ A jump table for the options with a short description can be found at |Q_op|. *'allowrevins'* *'ari'* *'noallowrevins'* *'noari'* 'allowrevins' 'ari' boolean (default off) global - Allow CTRL-_ in Insert and Command-line mode. This is default off, to - avoid that users that accidentally type CTRL-_ instead of SHIFT-_ get - into reverse Insert mode, and don't know how to get out. See - 'revins'. + Allow CTRL-_ in Insert mode. This is default off, to avoid that users + that accidentally type CTRL-_ instead of SHIFT-_ get into reverse + Insert mode, and don't know how to get out. See 'revins'. *'ambiwidth'* *'ambw'* 'ambiwidth' 'ambw' string (default "single") @@ -1442,7 +1442,7 @@ A jump table for the options with a short description can be found at |Q_op|. 'commentstring' 'cms' string (default "") local to buffer A template for a comment. The "%s" in the value is replaced with the - comment text. For example, C uses "/*%s*/". Currently only used to + comment text. For example, C uses "/*%s*/". Used for |commenting| and to add markers for folding, see |fold-marker|. *'complete'* *'cpt'* *E535* @@ -2851,25 +2851,33 @@ A jump table for the options with a short description can be found at |Q_op|. This is a scanf-like string that uses the same format as the 'errorformat' option: see |errorformat|. + If ripgrep ('grepprg') is available, this option defaults to `%f:%l:%c:%m`. + *'grepprg'* *'gp'* -'grepprg' 'gp' string (default "grep -n ", - Unix: "grep -n $* /dev/null") +'grepprg' 'gp' string (default see below) global or local to buffer |global-local| Program to use for the |:grep| command. This option may contain '%' and '#' characters, which are expanded like when used in a command- line. The placeholder "$*" is allowed to specify where the arguments will be included. Environment variables are expanded |:set_env|. See |option-backslash| about including spaces and backslashes. - When your "grep" accepts the "-H" argument, use this to make ":grep" - also work well with a single file: >vim - set grepprg=grep\ -nH -< Special value: When 'grepprg' is set to "internal" the |:grep| command + Special value: When 'grepprg' is set to "internal" the |:grep| command works like |:vimgrep|, |:lgrep| like |:lvimgrep|, |:grepadd| like |:vimgrepadd| and |:lgrepadd| like |:lvimgrepadd|. See also the section |:make_makeprg|, since most of the comments there apply equally to 'grepprg'. This option cannot be set from a |modeline| or in the |sandbox|, for security reasons. + This option defaults to: + - `rg --vimgrep -uu ` if ripgrep is available (|:checkhealth|), + - `grep -HIn $* /dev/null` on Unix, + - `findstr /n $* nul` on Windows. + Ripgrep can perform additional filtering such as using .gitignore rules + and skipping hidden files. This is disabled by default (see the -u option) + to more closely match the behaviour of standard grep. + You can make ripgrep match Vim's case handling using the + -i/--ignore-case and -S/--smart-case options. + An |OptionSet| autocmd can be used to set it up to match automatically. *'guicursor'* *'gcr'* *E545* *E546* *E548* *E549* 'guicursor' 'gcr' string (default "n-v-c-sm:block,i-ci-ve:ver25,r-cr-o:hor20") @@ -4952,9 +4960,6 @@ A jump table for the options with a short description can be found at |Q_op|. Minimum is 1, maximum is 100000. Only in |terminal| buffers. - Note: Lines that are not visible and kept in scrollback are not - reflown when the terminal buffer is resized horizontally. - *'scrollbind'* *'scb'* *'noscrollbind'* *'noscb'* 'scrollbind' 'scb' boolean (default off) local to window @@ -5696,8 +5701,7 @@ A jump table for the options with a short description can be found at |Q_op|. highlighted with |hl-NonText|. You may also want to add "lastline" to the 'display' option to show as much of the last line as possible. - NOTE: only partly implemented, currently works with CTRL-E, CTRL-Y - and scrolling with the mouse. + NOTE: partly implemented, doesn't work yet for |gj| and |gk|. *'softtabstop'* *'sts'* 'softtabstop' 'sts' number (default 0) @@ -6271,6 +6275,8 @@ A jump table for the options with a short description can be found at |Q_op|. "split" when both are present. uselast If included, jump to the previously used window when jumping to errors with |quickfix| commands. + If a window has 'winfixbuf' enabled, 'switchbuf' is currently not + applied to the split window. *'synmaxcol'* *'smc'* 'synmaxcol' 'smc' number (default 3000) @@ -6349,7 +6355,7 @@ A jump table for the options with a short description can be found at |Q_op|. appear wrong in many places. The value must be more than 0 and less than 10000. - There are four main ways to use tabs in Vim: + There are five main ways to use tabs in Vim: 1. Always keep 'tabstop' at 8, set 'softtabstop' and 'shiftwidth' to 4 (or 3 or whatever you prefer) and use 'noexpandtab'. Then Vim will use a mix of tabs and spaces, but typing <Tab> and <BS> will @@ -6882,6 +6888,7 @@ A jump table for the options with a short description can be found at |Q_op|. Level Messages ~ ---------------------------------------------------------------------- + 1 Enables Lua tracing (see above). Does not produce messages. 2 When a file is ":source"'ed, or |shada| file is read or written. 3 UI info, terminal capabilities. 4 Shell commands. @@ -7216,11 +7223,20 @@ A jump table for the options with a short description can be found at |Q_op|. will scroll 'window' minus two lines, with a minimum of one. When 'window' is equal to 'lines' minus one CTRL-F and CTRL-B scroll in a much smarter way, taking care of wrapping lines. - When resizing the Vim window, the value is smaller than 1 or more than - or equal to 'lines' it will be set to 'lines' minus 1. + When resizing the Vim window, and the value is smaller than 1 or more + than or equal to 'lines' it will be set to 'lines' minus 1. Note: Do not confuse this with the height of the Vim window, use 'lines' for that. + *'winfixbuf'* *'wfb'* *'nowinfixbuf'* *'nowfb'* +'winfixbuf' 'wfb' boolean (default off) + local to window + If enabled, the window and the buffer it is displaying are paired. + For example, attempting to change the buffer with |:edit| will fail. + Other commands which change a window's buffer such as |:cnext| will + also skip any window with 'winfixbuf' enabled. However if an Ex + command has a "!" modifier, it can force switching buffers. + *'winfixheight'* *'wfh'* *'nowinfixheight'* *'nowfh'* 'winfixheight' 'wfh' boolean (default off) local to window |local-noglobal| diff --git a/runtime/doc/pattern.txt b/runtime/doc/pattern.txt index 17136ee650..1ef182127c 100644 --- a/runtime/doc/pattern.txt +++ b/runtime/doc/pattern.txt @@ -1375,6 +1375,19 @@ Finally, these constructs are unique to Perl: ============================================================================== 10. Highlighting matches *match-highlight* + *syntax-vs-match* + Note that the match highlight mechanism is independent + of |syntax-highlighting|, which is (usually) a buffer-local + highlighting, while matching is window-local, both methods + can be freely mixed. Match highlighting functions give you + a bit more flexibility in when and how to apply, but are + typically only used for temporary highlighting, without strict + rules. Both methods can be used to conceal text. + + Thus the matching functions like |matchadd()| won't consider + syntax rules and functions like |synconcealed()| and the + other way around. + *:mat* *:match* :mat[ch] {group} /{pattern}/ Define a pattern to highlight in the current window. It will diff --git a/runtime/doc/pi_netrw.txt b/runtime/doc/pi_netrw.txt index d8fcd066a8..81acd9cf7e 100644 --- a/runtime/doc/pi_netrw.txt +++ b/runtime/doc/pi_netrw.txt @@ -446,10 +446,6 @@ settings are described below, in |netrw-browser-options|, and in messages don't always seem to show up this way, but one doesn't have to quit the window. - *g:netrw_win95ftp* =1 if using Win95, will remove four trailing blank - lines that o/s's ftp "provides" on transfers - =0 force normal ftp behavior (no trailing line removal) - *g:netrw_cygwin* =1 assume scp under windows is from cygwin. Also permits network browsing to use ls with time and size sorting (default if windows) @@ -825,8 +821,6 @@ set in the user's <.vimrc> file: (see also |netrw-settings| |netrw-protocol|) g:netrw_uid Holds current user-id for ftp. g:netrw_use_nt_rcp =0 don't use WinNT/2K/XP's rcp (default) =1 use WinNT/2K/XP's rcp, binary mode - g:netrw_win95ftp =0 use unix-style ftp even if win95/98/ME/etc - =1 use default method to do ftp > ----------------------------------------------------------------------- < *netrw-internal-variables* @@ -955,21 +949,8 @@ messages) you may write a NetReadFixup() function: endfunction > The NetReadFixup() function will be called if it exists and thus allows you to -customize your reading process. As a further example, <netrw.vim> contains -just such a function to handle Windows 95 ftp. For whatever reason, Windows -95's ftp dumps four blank lines at the end of a transfer, and so it is -desirable to automate their removal. Here's some code taken from <netrw.vim> -itself: -> - if has("win95") && g:netrw_win95ftp - fun! NetReadFixup(method, line1, line2) - if method == 3 " ftp (no <.netrc>) - let fourblanklines= line2 - 3 - silent fourblanklines .. "," .. line2 .. "g/^\s*/d" - endif - endfunction - endif -> +customize your reading process. + (Related topics: |ftp| |netrw-userpass| |netrw-start|) ============================================================================== @@ -2048,11 +2029,7 @@ passwords: better way to do that: I can use a regular ssh account which uses a password to access the material without the need to key-in the password each time. It's good for security and convenience. I tried ssh public key - authorization + ssh-agent, implementing this, and it works! Here are two - links with instructions: - - http://www.ibm.com/developerworks/library/l-keyc2/ - http://sial.org/howto/openssh/publickey-auth/ + authorization + ssh-agent, implementing this, and it works! Ssh hints: @@ -3397,16 +3374,7 @@ Example: Clear netrw's marked file list via a mapping on gu > (This section is likely to grow as I get feedback) (also see |netrw-debug|) *netrw-p1* - P1. I use windows 95, and my ftp dumps four blank lines at the {{{2 - end of every read. - - See |netrw-fixup|, and put the following into your - <.vimrc> file: - - let g:netrw_win95ftp= 1 - - *netrw-p2* - P2. I use Windows, and my network browsing with ftp doesn't sort by {{{2 + P1. I use Windows, and my network browsing with ftp doesn't sort by {{{2 time or size! -or- The remote system is a Windows server; why don't I get sorts by time or size? @@ -3432,8 +3400,8 @@ Example: Clear netrw's marked file list via a mapping on gu > modify its listing behavior. - *netrw-p3* - P3. I tried rcp://user@host/ (or protocol other than ftp) and netrw {{{2 + *netrw-p2* + P2. I tried rcp://user@host/ (or protocol other than ftp) and netrw {{{2 used ssh! That wasn't what I asked for... Netrw has two methods for browsing remote directories: ssh @@ -3441,8 +3409,8 @@ Example: Clear netrw's marked file list via a mapping on gu > When it comes time to do download a file (not just a directory listing), netrw will use the given protocol to do so. - *netrw-p4* - P4. I would like long listings to be the default. {{{2 + *netrw-p3* + P3. I would like long listings to be the default. {{{2 Put the following statement into your |vimrc|: > @@ -3451,8 +3419,8 @@ Example: Clear netrw's marked file list via a mapping on gu > Check out |netrw-browser-var| for more customizations that you can set. - *netrw-p5* - P5. My times come up oddly in local browsing {{{2 + *netrw-p4* + P4. My times come up oddly in local browsing {{{2 Does your system's strftime() accept the "%c" to yield dates such as "Sun Apr 27 11:49:23 1997"? If not, do a @@ -3461,16 +3429,16 @@ Example: Clear netrw's marked file list via a mapping on gu > let g:netrw_timefmt= "%X" (where X is the option) < - *netrw-p6* - P6. I want my current directory to track my browsing. {{{2 + *netrw-p5* + P5. I want my current directory to track my browsing. {{{2 How do I do that? Put the following line in your |vimrc|: > let g:netrw_keepdir= 0 < - *netrw-p7* - P7. I use Chinese (or other non-ascii) characters in my filenames, {{{2 + *netrw-p6* + P6. I use Chinese (or other non-ascii) characters in my filenames, {{{2 and netrw (Explore, Sexplore, Hexplore, etc) doesn't display them! (taken from an answer provided by Wu Yongwei on the vim @@ -3484,8 +3452,8 @@ Example: Clear netrw's marked file list via a mapping on gu > (...it is one more reason to recommend that people use utf-8!) - *netrw-p8* - P8. I'm getting "ssh is not executable on your system" -- what do I {{{2 + *netrw-p7* + P7. I'm getting "ssh is not executable on your system" -- what do I {{{2 do? (Dudley Fox) Most people I know use putty for windows ssh. It @@ -3567,8 +3535,8 @@ Example: Clear netrw's marked file list via a mapping on gu > of the others will use the string in g:netrw_ssh_cmd by default. - *netrw-p9* *netrw-ml_get* - P9. I'm browsing, changing directory, and bang! ml_get errors {{{2 + *netrw-p8* *netrw-ml_get* + P8. I'm browsing, changing directory, and bang! ml_get errors {{{2 appear and I have to kill vim. Any way around this? Normally netrw attempts to avoid writing swapfiles for @@ -3578,8 +3546,8 @@ Example: Clear netrw's marked file list via a mapping on gu > in your <.vimrc>: > let g:netrw_use_noswf= 0 < - *netrw-p10* - P10. I'm being pestered with "[something] is a directory" and {{{2 + *netrw-p9* + P9. I'm being pestered with "[something] is a directory" and {{{2 "Press ENTER or type command to continue" prompts... The "[something] is a directory" prompt is issued by Vim, @@ -3589,8 +3557,8 @@ Example: Clear netrw's marked file list via a mapping on gu > I also suggest that you set your |'cmdheight'| to 2 (or more) in your <.vimrc> file. - *netrw-p11* - P11. I want to have two windows; a thin one on the left and my {{{2 + *netrw-p10* + P10. I want to have two windows; a thin one on the left and my {{{2 editing window on the right. How may I accomplish this? You probably want netrw running as in a side window. If so, you @@ -3615,8 +3583,8 @@ Example: Clear netrw's marked file list via a mapping on gu > <middlemouse> to select the file. - *netrw-p12* - P12. My directory isn't sorting correctly, or unwanted letters are {{{2 + *netrw-p11* + P11. My directory isn't sorting correctly, or unwanted letters are {{{2 appearing in the listed filenames, or things aren't lining up properly in the wide listing, ... @@ -3625,8 +3593,8 @@ Example: Clear netrw's marked file list via a mapping on gu > Multibyte encodings use two (or more) bytes per character. You may need to change |g:netrw_sepchr| and/or |g:netrw_xstrlen|. - *netrw-p13* - P13. I'm a Windows + putty + ssh user, and when I attempt to {{{2 + *netrw-p12* + P12. I'm a Windows + putty + ssh user, and when I attempt to {{{2 browse, the directories are missing trailing "/"s so netrw treats them as file transfers instead of as attempts to browse subdirectories. How may I fix this? @@ -3646,8 +3614,8 @@ Example: Clear netrw's marked file list via a mapping on gu > "let g:netrw_sftp_cmd = "d:\\dev\\putty\\PSFTP.exe" "let g:netrw_scp_cmd = "d:\\dev\\putty\\PSCP.exe" < - *netrw-p14* - P14. I would like to speed up writes using Nwrite and scp/ssh {{{2 + *netrw-p13* + P13. I would like to speed up writes using Nwrite and scp/ssh {{{2 style connections. How? (Thomer M. Gil) Try using ssh's ControlMaster and ControlPath (see the ssh_config @@ -3673,8 +3641,8 @@ Example: Clear netrw's marked file list via a mapping on gu > vim scp://host.domain.com//home/user/.bashrc < - *netrw-p15* - P15. How may I use a double-click instead of netrw's usual single {{{2 + *netrw-p14* + P14. How may I use a double-click instead of netrw's usual single {{{2 click to open a file or directory? (Ben Fritz) First, disable netrw's mapping with > @@ -3686,8 +3654,8 @@ Example: Clear netrw's marked file list via a mapping on gu > all netrw's mouse mappings, not just the <leftmouse> one. (see |g:netrw_mousemaps|) - *netrw-p16* - P16. When editing remote files (ex. :e ftp://hostname/path/file), {{{2 + *netrw-p15* + P15. When editing remote files (ex. :e ftp://hostname/path/file), {{{2 under Windows I get an |E303| message complaining that its unable to open a swap file. @@ -3695,8 +3663,8 @@ Example: Clear netrw's marked file list via a mapping on gu > directory. Start netrw from your $HOME or other writable directory. - *netrw-p17* - P17. Netrw is closing buffers on its own. {{{2 + *netrw-p16* + P16. Netrw is closing buffers on its own. {{{2 What steps will reproduce the problem? 1. :Explore, navigate directories, open a file 2. :Explore, open another file @@ -3709,15 +3677,15 @@ Example: Clear netrw's marked file list via a mapping on gu > It appears that the buffers are not exactly closed; a ":ls!" will show them (although ":ls" does not). - *netrw-P18* - P18. How to locally edit a file that's only available via {{{2 + *netrw-P17* + P17. How to locally edit a file that's only available via {{{2 another server accessible via ssh? See http://stackoverflow.com/questions/12469645/ "Using Vim to Remotely Edit A File on ServerB Only Accessible From ServerA" - *netrw-P19* - P19. How do I get numbering on in directory listings? {{{2 + *netrw-P18* + P18. How do I get numbering on in directory listings? {{{2 With |g:netrw_bufsettings|, you can control netrw's buffer settings; try putting > let g:netrw_bufsettings="noma nomod nu nobl nowrap ro nornu" @@ -3725,8 +3693,8 @@ Example: Clear netrw's marked file list via a mapping on gu > instead, try > let g:netrw_bufsettings="noma nomod nonu nobl nowrap ro rnu" < - *netrw-P20* - P20. How may I have gvim start up showing a directory listing? {{{2 + *netrw-P19* + P19. How may I have gvim start up showing a directory listing? {{{2 Try putting the following code snippet into your .vimrc: > augroup VimStartup au! @@ -3738,8 +3706,8 @@ Example: Clear netrw's marked file list via a mapping on gu > This snippet assumes that you have client-server enabled (ie. a "huge" vim version). - *netrw-P21* - P21. I've made a directory (or file) with an accented character, {{{2 + *netrw-P20* + P20. I've made a directory (or file) with an accented character, {{{2 but netrw isn't letting me enter that directory/read that file: Its likely that the shell or o/s is using a different encoding @@ -3749,8 +3717,8 @@ Example: Clear netrw's marked file list via a mapping on gu > au FileType netrw set enc=latin1 < - *netrw-P22* - P22. I get an error message when I try to copy or move a file: {{{2 + *netrw-P21* + P21. I get an error message when I try to copy or move a file: {{{2 > **error** (netrw) tried using g:netrw_localcopycmd<cp>; it doesn't work! < diff --git a/runtime/doc/pi_tar.txt b/runtime/doc/pi_tar.txt index dd1edb5707..c8570044e5 100644 --- a/runtime/doc/pi_tar.txt +++ b/runtime/doc/pi_tar.txt @@ -147,7 +147,8 @@ Copyright 2005-2017: *tar-copyright* v2 * converted to use Vim7's new autoload feature by Bram Moolenaar v1 (original) * Michael Toren - (see http://michael.toren.net/code/) + (see http://michael.toren.net/code/ + link seems dead) ============================================================================== vim:tw=78:ts=8:noet:ft=help diff --git a/runtime/doc/provider.txt b/runtime/doc/provider.txt index b8182347f8..a39f4bc5d7 100644 --- a/runtime/doc/provider.txt +++ b/runtime/doc/provider.txt @@ -185,7 +185,7 @@ See 'clipboard' for details and options. The presence of a working clipboard tool implicitly enables the '+' and "*" registers. Nvim looks for these clipboard tools, in order of priority: - - |g:clipboard| + - |g:clipboard| (unless unset or `false`) - pbcopy, pbpaste (macOS) - wl-copy, wl-paste (if $WAYLAND_DISPLAY is set) - waycopy, waypaste (if $WAYLAND_DISPLAY is set) diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt index 9037ecc0f9..5d3c0cbdc2 100644 --- a/runtime/doc/quickfix.txt +++ b/runtime/doc/quickfix.txt @@ -275,7 +275,8 @@ processing a quickfix or location list command, it will be aborted. current window is used instead of the quickfix list. *:cb* *:cbuffer* *E681* -:cb[uffer][!] [bufnr] Read the error list from the current buffer. +:[range]cb[uffer][!] [bufnr] + Read the error list from the current buffer. When [bufnr] is given it must be the number of a loaded buffer. That buffer will then be used instead of the current buffer. @@ -284,26 +285,31 @@ processing a quickfix or location list command, it will be aborted. See |:cc| for [!]. *:lb* *:lbuffer* -:lb[uffer][!] [bufnr] Same as ":cbuffer", except the location list for the +:[range]lb[uffer][!] [bufnr] + Same as ":cbuffer", except the location list for the current window is used instead of the quickfix list. *:cgetb* *:cgetbuffer* -:cgetb[uffer] [bufnr] Read the error list from the current buffer. Just +:[range]cgetb[uffer] [bufnr] + Read the error list from the current buffer. Just like ":cbuffer" but don't jump to the first error. *:lgetb* *:lgetbuffer* -:lgetb[uffer] [bufnr] Same as ":cgetbuffer", except the location list for +:[range]lgetb[uffer] [bufnr] + Same as ":cgetbuffer", except the location list for the current window is used instead of the quickfix list. *:cad* *:cadd* *:caddbuffer* -:cad[dbuffer] [bufnr] Read the error list from the current buffer and add +:[range]cad[dbuffer] [bufnr] + Read the error list from the current buffer and add the errors to the current quickfix list. If a quickfix list is not present, then a new list is created. Otherwise, same as ":cbuffer". *:laddb* *:laddbuffer* -:laddb[uffer] [bufnr] Same as ":caddbuffer", except the location list for +:[range]laddb[uffer] [bufnr] + Same as ":caddbuffer", except the location list for the current window is used instead of the quickfix list. @@ -1282,6 +1288,15 @@ g:compiler_gcc_ignore_unmatched_lines commands run from make are generating false positives. +PANDOC *quickfix-pandoc* *compiler-pandoc* + +The Pandoc compiler plugin expects that an output file type extension is +passed to make, say :make html or :make pdf. + +Additional arguments can be passed to pandoc: + +- either by appending them to make, say `:make html --self-contained` . +- or setting them in `b:pandoc_compiler_args` or `g:pandoc_compiler_args` PERL *quickfix-perl* *compiler-perl* diff --git a/runtime/doc/quickref.txt b/runtime/doc/quickref.txt index 572dc8a841..c0d00d16cb 100644 --- a/runtime/doc/quickref.txt +++ b/runtime/doc/quickref.txt @@ -620,8 +620,7 @@ In Insert or Command-line mode: the help Short explanation of each option: *option-list* -'aleph' 'al' ASCII code of the letter Aleph (Hebrew) -'allowrevins' 'ari' allow CTRL-_ in Insert and Command-line mode +'allowrevins' 'ari' allow CTRL-_ in Insert mode 'ambiwidth' 'ambw' what to do with Unicode chars of ambiguous width 'arabic' 'arab' for Arabic as a default second language 'arabicshape' 'arshape' do shaping for Arabic characters @@ -739,8 +738,6 @@ Short explanation of each option: *option-list* 'helplang' 'hlg' preferred help languages 'hidden' 'hid' don't unload buffer when it is |abandon|ed 'history' 'hi' number of command-lines that are remembered -'hkmap' 'hk' Hebrew keyboard mapping -'hkmapp' 'hkp' phonetic Hebrew keyboard mapping 'hlsearch' 'hls' highlight matches with last search pattern 'icon' let Vim set the text of the window icon 'iconstring' string to use for the Vim icon text @@ -939,6 +936,7 @@ Short explanation of each option: *option-list* 'wildoptions' 'wop' specifies how command line completion is done 'winaltkeys' 'wak' when the windows system handles ALT keys 'window' 'wi' nr of lines to scroll for CTRL-F and CTRL-B +'winfixbuf' 'wfb' keep window focused on a single buffer 'winfixheight' 'wfh' keep window height when opening/closing windows 'winfixwidth' 'wfw' keep window width when opening/closing windows 'winheight' 'wh' minimum number of lines for the current window @@ -1140,7 +1138,7 @@ Context-sensitive completion on the command-line: |-b| -b binary mode |-l| -l lisp mode |-A| -A Arabic mode ('arabic' is set) -|-H| -H Hebrew mode ('hkmap' and 'rightleft' are set) +|-H| -H Hebrew mode (Hebrew keymap & 'rightleft' are set) |-V| -V Verbose, give informative messages |-r| -r give list of swap files |-r| -r {file} .. recover aborted edit session diff --git a/runtime/doc/remote_plugin.txt b/runtime/doc/remote_plugin.txt index cfe4b08000..694c339ef2 100644 --- a/runtime/doc/remote_plugin.txt +++ b/runtime/doc/remote_plugin.txt @@ -30,9 +30,9 @@ check whether a plugin host is available for their chosen programming language. Plugin hosts are programs that provide a high-level environment for plugins, taking care of most boilerplate involved in defining commands, autocmds, and -functions that are implemented over |RPC| connections. Hosts are loaded only -when one of their registered plugins require it, keeping Nvim's startup as -fast as possible, even if many plugins/hosts are installed. +functions implemented over |RPC| connections. Hosts are loaded only when one +of their registered plugins require it, keeping Nvim's startup as fast as +possible, even if many plugins/hosts are installed. ============================================================================== 3. Example *remote-plugin-example* diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt index ae827fa06f..2263b20d1a 100644 --- a/runtime/doc/repeat.txt +++ b/runtime/doc/repeat.txt @@ -149,8 +149,8 @@ q Stops recording. @@ Repeat the previous @{0-9a-z":*} [count] times. *v_@-default* -{Visual}@{0-9a-z".=*+} In Visual mode, execute the contents of the register -{Visual}@@ but for each selected line. +{Visual}@{0-9a-z".=*+} In linewise Visual mode, execute the contents of the +{Visual}@@ register for each selected line. See |visual-repeat|, |default-mappings|. *Q* @@ -158,8 +158,8 @@ Q Repeat the last recorded register [count] times. See |reg_recorded()|. *v_Q-default* -{Visual}Q In Visual mode, repeat the last recorded register for - each selected line. +{Visual}Q In linewise Visual mode, repeat the last recorded + register for each selected line. See |visual-repeat|, |default-mappings|. *:@* diff --git a/runtime/doc/sign.txt b/runtime/doc/sign.txt index 0360ce67f6..6fa260be40 100644 --- a/runtime/doc/sign.txt +++ b/runtime/doc/sign.txt @@ -72,9 +72,10 @@ on the same line, the attributes of the sign with the highest priority is used independently of the sign group. The default priority for a sign is 10. The priority is assigned at the time of placing a sign. -When two signs with the same priority are present, and one has an icon or text -in the signcolumn while the other has line highlighting, then both are -displayed. +When multiple signs that each have an icon or text are present, signs are +ordered with increasing priority from left to right, up until the maximum +width set in 'signcolumn'. Lower priority signs that do not fit are hidden. +Highest priority signs with highlight attributes are always shown. When the line on which the sign is placed is deleted, the sign is removed along with it. diff --git a/runtime/doc/spell.txt b/runtime/doc/spell.txt index 29e4a7b0aa..269d52352d 100644 --- a/runtime/doc/spell.txt +++ b/runtime/doc/spell.txt @@ -51,6 +51,17 @@ To search for the next misspelled word: *[S* [S Like "]S" but search backwards. + *]r* +]r Move to next "rare" word after the cursor. + A count before the command can be used to repeat. + 'wrapscan' applies. + + *[r* +[r Like "]r" but search backwards, find the "rare" + word before the cursor. Doesn't recognize words + split over two lines, thus may stop at words that are + not highlighted as rare. + To add words to your own word list: diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt index a6619bc381..fb8ed0344b 100644 --- a/runtime/doc/starting.txt +++ b/runtime/doc/starting.txt @@ -139,7 +139,7 @@ argument. --cmd {command} *--cmd* {command} will be executed before processing any vimrc file. - Otherwise it acts like -c {command}. You can use up to 10 of + Otherwise, it acts like -c {command}. You can use up to 10 of these commands, independently from "-c" commands. *-S* @@ -260,7 +260,8 @@ argument. -A Arabic mode. Sets the 'arabic' option on. *-H* --H Hebrew mode. Sets the 'rightleft' option on and 'keymap' to "hebrew" +-H Hebrew mode. Sets the 'rightleft' option on and the 'keymap' + option to "hebrew". *-V* *verbose* -V[N] Verbose. Sets the 'verbose' option to [N] (default: 10). @@ -306,7 +307,7 @@ argument. few windows will be editing an empty file. *-O* --O[N] Open N windows, split vertically. Otherwise it's like -o. +-O[N] Open N windows, split vertically. Otherwise, it's like -o. If both the -o and the -O option are given, the last one on the command line determines how the windows will be split. @@ -325,8 +326,10 @@ argument. This can be used to start Vim in a special mode, with special mappings and settings. A shell alias can be used to make - this easy to use. For example: > - alias vimc vim -u ~/.config/nvim/c_init.vim !* + this easy to use. For example, in a C shell descendant: > + alias vimc 'nvim -u ~/.config/nvim/c_init.vim \!*' +< And in a Bash shell: > + alias vimc='nvim -u ~/.config/nvim/c_init.vim' < Also consider using autocommands; see |autocommand|. When {vimrc} is "NONE" (all uppercase), all initializations @@ -544,7 +547,7 @@ accordingly, proceeding as follows: This means that Nvim will figure out the values of 'shellpipe' and 'shellredir' for you, unless you have set them yourself. -12. Set 'updatecount' to zero, if "-n" command argument used +12. Set 'updatecount' to zero, if "-n" command argument used. 13. Set binary options if the |-b| flag was given. @@ -581,11 +584,11 @@ Avoiding trojan horses ~ *trojan-horse* While reading the "vimrc" or the "exrc" file in the current directory, some commands can be disabled for security reasons by setting the 'secure' option. -This is always done when executing the command from a tags file. Otherwise it -would be possible that you accidentally use a vimrc or tags file that somebody -else created and contains nasty commands. The disabled commands are the ones -that start a shell, the ones that write to a file, and ":autocmd". The ":map" -commands are echoed, so you can see which keys are being mapped. +This is always done when executing the command from a tags file. Otherwise, +it would be possible that you accidentally use a vimrc or tags file that +somebody else created and contains nasty commands. The disabled commands are +the ones that start a shell, the ones that write to a file, and ":autocmd". +The ":map" commands are echoed, so you can see which keys are being mapped. If you want Vim to execute all commands in a local vimrc file, you can reset the 'secure' option in the EXINIT or VIMINIT environment variable or in the global exrc or vimrc file. This is not possible in vimrc or @@ -743,7 +746,7 @@ these are terminal or file dependent. Note that the options 'binary', 'paste' and 'readonly' are included, this might not always be what you want. -When special keys are used in mappings, The 'cpoptions' option will be +When special keys are used in mappings, the 'cpoptions' option will be temporarily set to its Vim default, to avoid the mappings to be misinterpreted. This makes the file incompatible with Vi, but makes sure it can be used with different terminals. @@ -797,8 +800,8 @@ You can quickly start editing with a previously saved View or Session with the *:mks* *:mksession* :mks[ession][!] [file] Write a Vim script that restores the current editing session. - When [!] is included an existing file is overwritten. - When [file] is omitted "Session.vim" is used. + When [!] is included, an existing file is overwritten. + When [file] is omitted, "Session.vim" is used. The output of ":mksession" is like ":mkvimrc", but additional commands are added to the file. Which ones depends on the 'sessionoptions' option. The @@ -810,16 +813,16 @@ resulting file, when executed with a ":source" command: 3. Closes all windows in the current tab page, except the current one; closes all tab pages except the current one (this results in currently loaded buffers to be unloaded, some may become hidden if 'hidden' is set or - otherwise specified); wipes out the current buffer, if it is empty - and unnamed. -4. Restores the current directory if 'sessionoptions' contains "curdir", or - sets the current directory to where the Session file is if 'sessionoptions' - contains "sesdir". + otherwise specified); wipes out the current buffer, if it is empty and + unnamed. +4. Restores the current directory, if 'sessionoptions' contains "curdir", or + sets the current directory to where the Session file is, if + 'sessionoptions' contains "sesdir". 5. Restores GUI Vim window position, if 'sessionoptions' contains "winpos". 6. Restores screen size, if 'sessionoptions' contains "resize". 7. Reloads the buffer list, with the last cursor positions. If 'sessionoptions' contains "buffers" then all buffers are restored, - including hidden and unloaded buffers. Otherwise only buffers in windows + including hidden and unloaded buffers. Otherwise, only buffers in windows are restored. 8. Restores all windows with the same layout. If 'sessionoptions' contains "help", help windows are restored. If 'sessionoptions' contains "blank", @@ -846,14 +849,14 @@ A session includes all tab pages, unless "tabpages" was removed from The |SessionLoadPost| autocmd event is triggered after a session file is loaded/sourced. *SessionLoad-variable* -While the session file is loading the SessionLoad global variable is set to 1. -Plugins can use this to postpone some work until the SessionLoadPost event is -triggered. +While the session file is loading, the SessionLoad global variable is set to +1. Plugins can use this to postpone some work until the SessionLoadPost event +is triggered. *:mkvie* *:mkview* :mkvie[w][!] [file] Write a Vim script that restores the contents of the current window. - When [!] is included an existing file is overwritten. + When [!] is included, an existing file is overwritten. When [file] is omitted or is a number from 1 to 9, a name is generated and 'viewdir' prepended. When the last path part of 'viewdir' does not exist, this @@ -868,14 +871,13 @@ triggered. The output of ":mkview" contains these items: 1. The argument list used in the window. When the global argument list is - used it is reset to the global list. + used, it is reset to the global list. The index in the argument list is also restored. 2. The file being edited in the window. If there is no file, the window is made empty. -3. Restore mappings, abbreviations and options local to the window if - 'viewoptions' contains "options" or "localoptions". For the options it - restores only values that are local to the current buffer and values local - to the window. +3. Restore mappings, abbreviations and options local to the window, if + 'viewoptions' contains "options" or "localoptions". Only option values + that are local to the current buffer and the current window are restored. When storing the view as part of a session and "options" is in 'sessionoptions', global values for local options will be stored too. 4. Restore folds when using manual folding and 'viewoptions' contains @@ -909,7 +911,7 @@ Note that Views and Sessions are not perfect: The combination of ":mkview" and ":loadview" can be used to store up to ten different views of a file. These are remembered in the directory specified with the 'viewdir' option. The views are stored using the file name. If a -file is renamed or accessed through a (symbolic) link the view will not be +file is renamed or accessed through a (symbolic) link, the view will not be found. You might want to clean up your 'viewdir' directory now and then. @@ -969,7 +971,7 @@ Notes for Unix: allow just anybody to read and write your ShaDa file! - Vim will not overwrite a ShaDa file that is not writable by the current "real" user. This helps for when you did "su" to become root, but your - $HOME is still set to a normal user's home directory. Otherwise Vim would + $HOME is still set to a normal user's home directory. Otherwise, Vim would create a ShaDa file owned by root that nobody else can read. - The ShaDa file cannot be a symbolic link. This is to avoid security issues. @@ -1001,11 +1003,11 @@ using this command: > vim -c "normal '0" -In a csh compatible shell you could make an alias for it: > +In a C shell descendant, you could make an alias for it: > alias lvim vim -c '"'normal "'"0'"' -For a bash-like shell: > +For a Bash-like shell: > alias lvim='vim -c "normal '\''0"' @@ -1099,15 +1101,15 @@ MANUALLY READING AND WRITING *shada-read-write* Two commands can be used to read and write the ShaDa file manually. This can be used to exchange registers between two running Vim programs: First type ":wsh" in one and then ":rsh" in the other. Note that if the register -already contained something, then ":rsh!" would be required. Also note -however that this means everything will be overwritten with information from +already contained something, then ":rsh!" would be required. Also note, +however, that this means everything will be overwritten with information from the first Vim, including the command line history, etc. The ShaDa file itself can be edited by hand too, although we suggest you start with an existing one to get the format right. You need to understand MessagePack (or, more likely, find software that is able to use it) format to do this. This can be useful in order to create a second file, say -"~/.my.shada" which could contain certain settings that you always want when +"~/.my.shada", which could contain certain settings that you always want when you first start Nvim. For example, you can preload registers with particular data, or put certain commands in the command line history. A line in your |config| file like > @@ -1171,8 +1173,8 @@ running) you have additional options: described in |shada-error-handling|). If 'shada' is empty, marks for up to 100 files will be written. When you get error "E929: All .tmp.X files exist, - cannot write ShaDa file!" check that no old temp files - were left behind (e.g. + cannot write ShaDa file!", check that no old temp + files were left behind (e.g. ~/.local/state/nvim/shada/main.shada.tmp*). Note: Executing :wshada will reset all |'quote| marks. @@ -1192,7 +1194,7 @@ running) you have additional options: the list is edited. If you get the |press-enter| prompt you can press "q" and still get the prompt to enter a file number. - Use ! to abandon a modified buffer. |abandon| + Use [!] to abandon a modified buffer. |abandon| SHADA FILE FORMAT *shada-format* diff --git a/runtime/doc/support.txt b/runtime/doc/support.txt index 80a035068a..5b8b32fa16 100644 --- a/runtime/doc/support.txt +++ b/runtime/doc/support.txt @@ -13,12 +13,13 @@ Supported platforms *supported-platforms* `System` `Tier` `Versions` `Tested versions` Linux 1 >= 2.6.32, glibc >= 2.12 Ubuntu 22.04 -macOS (Intel) 1 >= 10.15 macOS 12 -Windows 64-bit 1 >= 8 (see note below) Windows Server 2022 +macOS (Intel) 1 >= 11 macOS 12 +macOS (M1) 2 >= 11 macOS 14 +Windows 64-bit 1 >= Windows 10 Version 1809 Windows Server 2022 FreeBSD 1 >= 10 FreeBSD 13 -macOS (M1) 2 >= 10.15 OpenBSD 2 >= 7 MinGW 2 MinGW-w64 +Windows 64-bit 3 < Windows 10 Version 1809 Note: Windows 10 "Version 1809" or later is required for |:terminal|. To check your Windows version, run the "winver" command and look for "Version xxxx" @@ -33,7 +34,7 @@ Support types ~ systems are maintained to the best of our ability, without being a top priority. -* Tier 3: Not tested and no guarantees, but may work. +* Tier 3: Not tested and no guarantees, and not all features may work. Adding support for a new platform ~ diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index c02752a2b7..7893822a66 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -461,8 +461,24 @@ nasm_loose_syntax unofficial parser allowed syntax not as Error nasm_ctx_outside_macro contexts outside macro not as Error nasm_no_warn potentially risky syntax not as ToDo +ASTRO *astro.vim* *ft-astro-syntax* -ASPPERL and ASPVBS *ft-aspperl-syntax* *ft-aspvbs-syntax* +Configuration + +The following variables control certain syntax highlighting features. +You can add them to your .vimrc: > + let g:astro_typescript = "enable" +< +Enables TypeScript and TSX for ".astro" files. Default Value: "disable" > + let g:astro_stylus = "enable" +< +Enables Stylus for ".astro" files. Default Value: "disable" + +NOTE: You need to install an external plugin to support stylus in astro files. + + +ASPPERL *ft-aspperl-syntax* +ASPVBS *ft-aspvbs-syntax* `*.asp` and `*.asa` files could be either Perl or Visual Basic script. Since it's hard to detect this you can set two global variables to tell Vim what you are @@ -998,9 +1014,9 @@ Two syntax highlighting files exist for Euphoria. One for Euphoria version 3.1.1, which is the default syntax highlighting file, and one for Euphoria version 4.0.5 or later. -Euphoria version 3.1.1 (https://www.rapideuphoria.com/) is still necessary -for developing applications for the DOS platform, which Euphoria version 4 -(https://www.openeuphoria.org/) does not support. +Euphoria version 3.1.1 (https://www.rapideuphoria.com/ link seems dead) is +still necessary for developing applications for the DOS platform, which +Euphoria version 4 (https://www.openeuphoria.org/) does not support. The following file extensions are auto-detected as Euphoria file type: > @@ -1057,7 +1073,8 @@ Elixir. FLEXWIKI *flexwiki.vim* *ft-flexwiki-syntax* -FlexWiki is an ASP.NET-based wiki package available at https://www.flexwiki.com +FlexWiki is an ASP.NET-based wiki package available at +https://www.flexwiki.com NOTE: This site currently doesn't work, on Wikipedia is mentioned that development stopped in 2009. @@ -1527,15 +1544,25 @@ Function names are not highlighted, as the way to find functions depends on how you write Java code. The syntax file knows two possible ways to highlight functions: -If you write function declarations that are always indented by either -a tab, 8 spaces or 2 spaces you may want to set > +If you write function declarations that are consistently indented by either +a tab, or a space . . . or eight space character(s), you may want to set > :let java_highlight_functions="indent" + :let java_highlight_functions="indent1" + :let java_highlight_functions="indent2" + :let java_highlight_functions="indent3" + :let java_highlight_functions="indent4" + :let java_highlight_functions="indent5" + :let java_highlight_functions="indent6" + :let java_highlight_functions="indent7" + :let java_highlight_functions="indent8" +Note that in terms of 'shiftwidth', this is the leftmost step of indentation. However, if you follow the Java guidelines about how functions and classes are -supposed to be named (with respect to upper and lowercase), use > +supposed to be named (with respect to upper- and lowercase) and there is any +amount of indentation, you may want to set > :let java_highlight_functions="style" -If both options do not work for you, but you would still want function -declarations to be highlighted create your own definitions by changing the -definitions in java.vim or by creating your own java.vim which includes the +If neither setting does work for you, but you would still want function +declarations to be highlighted, create your own definitions by changing the +definitions in java.vim or by creating your own java.vim that includes the original one and then adds the code to highlight functions. In Java 1.1 the functions System.out.println() and System.err.println() should @@ -1599,6 +1626,15 @@ To disable syntax highlighting of errors: > let g:vim_json_warnings = 0 +JQ *jq.vim* *jq_quote_highlight* *ft-jq-syntax* + +To disable numbers having their own color add the following to your vimrc: > + hi link jqNumber Normal + +If you want quotes to have different highlighting than strings > + let g:jq_quote_highlight = 1 + + LACE *lace.vim* *ft-lace-syntax* Lace (Language for Assembly of Classes in Eiffel) is case insensitive, but the @@ -1764,10 +1800,19 @@ MARKDOWN *ft-markdown-syntax* If you have long regions there might be wrong highlighting. At the cost of slowing down displaying, you can have the engine look further back to sync on -the start of a region, for example 500 lines: > +the start of a region, for example 500 lines (default is 50): > :let g:markdown_minlines = 500 +If you want to enable fenced code block syntax highlighting in your markdown +documents you can enable like this: > + + :let g:markdown_fenced_languages = ['html', 'python', 'bash=sh'] + +To disable markdown syntax concealing add the following to your vimrc: > + + :let g:markdown_syntax_conceal = 0 + MATHEMATICA *mma.vim* *ft-mma-syntax* *ft-mathematica-syntax* @@ -1985,6 +2030,95 @@ by the camlp4 preprocessor. Setting the variable > prevents highlighting of "end" as error, which is useful when sources contain very long structures that Vim does not synchronize anymore. +PANDOC *ft-pandoc-syntax* + +By default, markdown files will be detected as filetype "markdown". +Alternatively, you may want them to be detected as filetype "pandoc" instead. +To do so, set the following: > + + :let g:markdown_md = 'pandoc' + +The pandoc syntax plugin uses |conceal| for pretty highlighting. Default is 1 > + + :let g:pandoc#syntax#conceal#use = 1 + +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: + + - titleblock + - image + - block + - subscript + - superscript + - strikeout + - atx + - codeblock_start + - codeblock_delim + - footnote + - definition + - list + - newline + - dashes + - ellipses + - quotes + - inlinecode + - inlinemath + +You can customize the way concealing works. For example, if you prefer to mark +footnotes with the `*` symbol: > + + :let g:pandoc#syntax#conceal#cchar_overrides = {"footnote" : "*"} + +To conceal the urls in links, use: > + + :let g:pandoc#syntax#conceal#urls = 1 + +Prevent highlighting specific codeblock types so that they remain Normal. +Codeblock types include "definition" for codeblocks inside definition blocks +and "delimited" for delimited codeblocks. Default = [] > + + :let g:pandoc#syntax#codeblocks#ignore = ['definition'] + +Use embedded highlighting for delimited codeblocks where a language is +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: > + + :let g:pandoc#syntax#codeblocks#embeds#langs = ["ruby", "bash=sh"] + +To use italics and strong in emphases. Default = 1 > + + :let g:pandoc#syntax#style#emphases = 1 + +"0" will add "block" to g:pandoc#syntax#conceal#blacklist, because otherwise +you couldn't tell where the styles are applied. + +To add underline subscript, superscript and strikeout text styles. Default = 1 > + + :let g:pandoc#syntax#style#underline_special = 1 + +Detect and highlight definition lists. Disabling this can improve performance. +Default = 1 (i.e., enabled by default) > + + :let g:pandoc#syntax#style#use_definition_lists = 1 + +The pandoc syntax script also comes with the following commands: > + + :PandocHighlight LANG + +Enables embedded highlighting for language LANG in codeblocks. Uses the +syntax for items in g:pandoc#syntax#codeblocks#embeds#langs. > + + :PandocUnhighlight LANG + +Disables embedded highlighting for language LANG in codeblocks. PAPP *papp.vim* *ft-papp-syntax* @@ -2099,8 +2233,8 @@ perl_string_as_statement, it will be highlighted as in the second line. The syncing has 3 options. The first two switch off some triggering of synchronization and should only be needed in case it fails to work properly. If while scrolling all of a sudden the whole screen changes color completely -then you should try and switch off one of those. Let me know if you can -figure out the line that causes the mistake. +then you should try and switch off one of those. Let the developer know if +you can figure out the line that causes the mistake. One triggers on "^\s*sub\s*" and the other on "^[$@%]" more or less. > @@ -3173,7 +3307,7 @@ The g:vimsyn_embed option allows users to select what, if any, types of embedded script highlighting they wish to have. > g:vimsyn_embed == 0 : disable (don't embed any scripts) - g:vimsyn_embed == 'lPr' : support embedded lua, python and ruby + g:vimsyn_embed == 'lpPr' : support embedded lua, perl, python and ruby < This option is disabled by default. *g:vimsyn_folding* @@ -3183,7 +3317,11 @@ Some folding is now supported with syntax/vim.vim: > g:vimsyn_folding == 0 or doesn't exist: no syntax-based folding g:vimsyn_folding =~ 'a' : augroups g:vimsyn_folding =~ 'f' : fold functions + g:vimsyn_folding =~ 'h' : fold heredocs + g:vimsyn_folding =~ 'l' : fold lua script + g:vimsyn_folding =~ 'p' : fold perl script g:vimsyn_folding =~ 'P' : fold python script + g:vimsyn_folding =~ 'r' : fold ruby script < *g:vimsyn_noerror* Not all error highlighting that syntax/vim.vim does may be correct; Vim script @@ -3708,7 +3846,9 @@ Whether or not it is actually concealed depends on the value of the 'conceallevel' option. The 'concealcursor' option is used to decide whether concealable items in the current line are displayed unconcealed to be able to edit the line. -Another way to conceal text is with |matchadd()|. + +Another way to conceal text is with |matchadd()|, but internally this works a +bit differently |syntax-vs-match|. concealends *:syn-concealends* @@ -3716,7 +3856,9 @@ When the "concealends" argument is given, the start and end matches of the region, but not the contents of the region, are marked as concealable. Whether or not they are actually concealed depends on the setting on the 'conceallevel' option. The ends of a region can only be concealed separately -in this way when they have their own highlighting via "matchgroup" +in this way when they have their own highlighting via "matchgroup". The +|synconcealed()| function can be used to retrieve information about conealed +items. cchar *:syn-cchar* *E844* @@ -4767,11 +4909,11 @@ guisp={color-name} *guisp* Colors which define Nvim's default color scheme: NvimDarkBlue NvimLightBlue NvimDarkCyan NvimLightCyan + NvimDarkGray1 NvimLightGray1 + NvimDarkGray2 NvimLightGray2 + NvimDarkGray3 NvimLightGray3 + NvimDarkGray4 NvimLightGray4 NvimDarkGreen NvimLightGreen - NvimDarkGrey1 NvimLightGrey1 - NvimDarkGrey2 NvimLightGrey2 - NvimDarkGrey3 NvimLightGrey3 - NvimDarkGrey4 NvimLightGrey4 NvimDarkMagenta NvimLightMagenta NvimDarkRed NvimLightRed NvimDarkYellow NvimLightYellow @@ -4868,7 +5010,7 @@ MatchParen Character under the cursor or just before it, if it *hl-ModeMsg* ModeMsg 'showmode' message (e.g., "-- INSERT --"). *hl-MsgArea* -MsgArea Area for messages and cmdline. +MsgArea Area for messages and command-line, see also 'cmdheight'. *hl-MsgSeparator* MsgSeparator Separator for scrolled messages |msgsep|. *hl-MoreMsg* @@ -4914,6 +5056,8 @@ QuickFixLine Current |quickfix| item in the quickfix window. Combined with *hl-Search* Search Last search pattern highlighting (see 'hlsearch'). Also used for similar items that need to stand out. + *hl-SnippetTabstop* +SnippetTabstop Tabstops in snippets. |vim.snippet| *hl-SpecialKey* SpecialKey Unprintable characters: Text displayed differently from what it really is. But not 'listchars' whitespace. |hl-Whitespace| diff --git a/runtime/doc/tabpage.txt b/runtime/doc/tabpage.txt index 49b2773253..2f50e31ee5 100644 --- a/runtime/doc/tabpage.txt +++ b/runtime/doc/tabpage.txt @@ -187,7 +187,7 @@ gt *i_CTRL-<PageDown>* *i_<C-PageDown>* :1tabnext " go to the first tab page :$tabnext " go to the last tab page :tabnext $ " as above - :tabnext # " go to the last accessed tab page + :tabnext # " go to the last accessed tab page :tabnext - " go to the previous tab page :tabnext -1 " as above :tabnext + " go to the next tab page @@ -216,8 +216,8 @@ gT Go to the previous tab page. Wraps around from the first one :tabl[ast] Go to the last tab page. <C-Tab> *CTRL-<Tab>* *<C-Tab>* -CTRL-W g<Tab> *g<Tab>* *CTRL-W_g<Tab>* -g<Tab> Go to the last accessed tab page. +g<Tab> *g<Tab>* *CTRL-W_g<Tab>* +CTRL-W g<Tab> Go to the last accessed tab page. Other commands: *:tabs* @@ -239,18 +239,17 @@ REORDERING TAB PAGES: Move the current tab page to after tab page N. Use zero to make the current tab page the first one. N is counted before the move, thus if the second tab is the current one, - `:tabmove 1` and `:tabmove 2` have no effect. + `:tabmove 1` and `:tabmove 2` have no effect. Without N the tab page is made the last one. > - :.tabmove " do nothing - :-tabmove " move the tab page to the left - :+tabmove " move the tab page to the right - :0tabmove " move the tab page to the beginning of the tab - " list + :.tabmove " do nothing + :-tabmove " move the tab page to the left + :+tabmove " move the tab page to the right + :0tabmove " move the tab page to the first :tabmove 0 " as above :tabmove " move the tab page to the last :$tabmove " as above :tabmove $ " as above - :tabmove # " move the tab page after the last accessed + :tabmove # " move the tab page after the last accessed " tab page :tabm[ove] +[N] diff --git a/runtime/doc/tagsrch.txt b/runtime/doc/tagsrch.txt index 2b5b253a09..ef1654d365 100644 --- a/runtime/doc/tagsrch.txt +++ b/runtime/doc/tagsrch.txt @@ -400,19 +400,24 @@ the pattern. *tag-!* If the tag is in the current file this will always work. Otherwise the performed actions depend on whether the current file was changed, whether a ! -is added to the command and on the 'autowrite' option: - - tag in file autowrite ~ -current file changed ! option action ~ - --------------------------------------------------------------------------- - yes x x x goto tag - no no x x read other file, goto tag - no yes yes x abandon current file, read other file, goto - tag - no yes no on write current file, read other file, goto - tag - no yes no off fail - --------------------------------------------------------------------------- +is added to the command and on the 'autowrite' and 'winfixbuf' options: + + tag in file winfixbuf autowrite ~ +current file changed ! option option action ~ + ----------------------------------------------------------------------------- + yes x x off x goto tag + no no x off x read other file, goto tag + no yes yes off x abandon current file, + read other file, goto tag + no yes no off on write current file, + read other file, goto tag + no yes no off off fail + yes x yes x x goto tag + no no no on x fail + no yes no on x fail + no yes no on on fail + no yes no on off fail + ----------------------------------------------------------------------------- - If the tag is in the current file, the command will always work. - If the tag is in another file and the current file was not changed, the @@ -428,6 +433,8 @@ current file changed ! option action ~ the changes, use the ":w" command and then use ":tag" without an argument. This works because the tag is put on the stack anyway. If you want to lose the changes you can use the ":tag!" command. +- If the tag is in another file and the window includes 'winfixbuf', the + command will fail. If the tag is in the same file then it may succeed. *tag-security* Note that Vim forbids some commands, for security reasons. This works like @@ -773,9 +780,17 @@ CTRL-W i Open a new window, with the cursor on the first line beginning of the file. If a count is given, the count'th matching line is displayed. + *[d-default* + Mapped to |vim.diagnostic.goto_prev()| by default. + |default-mappings| + *]d* ]d like "[d", but start at the current cursor position. + *]d-default* + Mapped to |vim.diagnostic.goto_next()| by default. + |default-mappings| + *:ds* *:dsearch* :[range]ds[earch][!] [count] [/]string[/] Like "[d" and "]d", but search in [range] lines @@ -822,6 +837,10 @@ CTRL-W d Open a new window, with the cursor on the first beginning of the file. If a count is given, the count'th matching line is jumped to. + *CTRL-W_d-default* + Mapped to |vim.diagnostic.open_float()| by default. + |default-mappings| + *:dsp* *:dsplit* :[range]dsp[lit][!] [count] [/]string[/] Like "CTRL-W d", but search in [range] lines diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index 5f33802ad5..0b84bb60d4 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -18,18 +18,31 @@ changes. This documentation may also not fully reflect the latest changes. PARSER FILES *treesitter-parsers* Parsers are the heart of treesitter. They are libraries that treesitter will -search for in the `parser` runtime directory. By default, Nvim bundles parsers -for C, Lua, Vimscript, Vimdoc and Treesitter query files, but parsers can be -installed via a plugin like https://github.com/nvim-treesitter/nvim-treesitter -or even manually. +search for in the `parser` runtime directory. + +Nvim includes these parsers: + +- C +- Lua +- Markdown +- Vimscript +- Vimdoc +- Treesitter query files |ft-query-plugin| + +You can install more parsers manually, or with a plugin like +https://github.com/nvim-treesitter/nvim-treesitter . Parsers are searched for as `parser/{lang}.*` in any 'runtimepath' directory. If multiple parsers for the same language are found, the first one is used. (NOTE: This typically implies the priority "user config > plugins > bundled".) -A parser can also be loaded manually using a full path: >lua + +To load a parser from its filepath: >lua vim.treesitter.language.add('python', { path = "/path/to/python.so" }) < +Parser names are assumed to be lower case if the file system is +case-sensitive. + To associate certain |filetypes| with a treesitter language (name of parser), use |vim.treesitter.language.register()|. For example, to use the `xml` treesitter parser for buffers with filetype `svg` or `xslt`, use: >lua @@ -65,6 +78,8 @@ An instance `TSNode` of a treesitter node supports the following methods. TSNode:parent() *TSNode:parent()* Get the node's immediate parent. + Prefer |TSNode:child_containing_descendant()| + for iterating over the node's ancestors. TSNode:next_sibling() *TSNode:next_sibling()* Get the node's next sibling. @@ -101,6 +116,9 @@ TSNode:named_child({index}) *TSNode:named_child()* Get the node's named child at the given {index}, where zero represents the first named child. +TSNode:child_containing_descendant({descendant}) *TSNode:child_containing_descendant()* + Get the node's child that contains {descendant}. + TSNode:start() *TSNode:start()* Get the node's start position. Return three values: the row, column and total byte count (all zero-based). @@ -149,7 +167,7 @@ TSNode:sexpr() *TSNode:sexpr()* Get an S-expression representing the node as a string. TSNode:id() *TSNode:id()* - Get an unique identifier for the node inside its own tree. + Get a unique identifier for the node inside its own tree. No guarantees are made about this identifier's internal representation, except for being a primitive Lua type with value equality (so not a @@ -469,10 +487,11 @@ The following is a list of standard captures used in queries for Nvim, highlighted according to the current colorscheme (use |:Inspect| on one to see the exact definition): -@variable various variable names -@variable.builtin built-in variable names (e.g. `this` / `self`) -@variable.parameter parameters of a function -@variable.member object and struct fields +@variable various variable names +@variable.builtin built-in variable names (e.g. `this`, `self`) +@variable.parameter parameters of a function +@variable.parameter.builtin special parameters (e.g. `_`, `it`) +@variable.member object and struct fields @constant constant identifiers @constant.builtin built-in constant values @@ -480,7 +499,7 @@ the exact definition): @module modules or namespaces @module.builtin built-in modules or namespaces -@label GOTO and other labels (e.g. `label:` in C), including heredoc labels +@label `GOTO` and other labels (e.g. `label:` in C), including heredoc labels @string string literals @string.documentation string documenting code (e.g. Python docstrings) @@ -501,9 +520,9 @@ the exact definition): @type type or class definitions and annotations @type.builtin built-in types @type.definition identifiers in type definitions (e.g. `typedef <type> <identifier>` in C) -@type.qualifier type qualifiers (e.g. `const`) -@attribute attribute annotations (e.g. Python decorators) +@attribute attribute annotations (e.g. Python decorators, Rust lifetimes) +@attribute.builtin builtin annotations (e.g. `@property` in Python) @property the key in key/value pairs @function function definitions @@ -515,27 +534,28 @@ the exact definition): @function.method.call method calls @constructor constructor calls and definitions -@operator symbolic operators (e.g. `+` / `*`) +@operator symbolic operators (e.g. `+`, `*`) @keyword keywords not fitting into specific categories @keyword.coroutine keywords related to coroutines (e.g. `go` in Go, `async/await` in Python) @keyword.function keywords that define a function (e.g. `func` in Go, `def` in Python) -@keyword.operator operators that are English words (e.g. `and` / `or`) -@keyword.import keywords for including modules (e.g. `import` / `from` in Python) -@keyword.storage modifiers that affect storage in memory or life-time -@keyword.repeat keywords related to loops (e.g. `for` / `while`) +@keyword.operator operators that are English words (e.g. `and`, `or`) +@keyword.import keywords for including modules (e.g. `import`, `from` in Python) +@keyword.type keywords defining composite types (e.g. `struct`, `enum`) +@keyword.modifier keywords defining type modifiers (e.g. `const`, `static`, `public`) +@keyword.repeat keywords related to loops (e.g. `for`, `while`) @keyword.return keywords like `return` and `yield` @keyword.debug keywords related to debugging -@keyword.exception keywords related to exceptions (e.g. `throw` / `catch`) +@keyword.exception keywords related to exceptions (e.g. `throw`, `catch`) -@keyword.conditional keywords related to conditionals (e.g. `if` / `else`) -@keyword.conditional.ternary ternary operator (e.g. `?` / `:`) +@keyword.conditional keywords related to conditionals (e.g. `if`, `else`) +@keyword.conditional.ternary ternary operator (e.g. `?`, `:`) @keyword.directive various preprocessor directives and shebangs @keyword.directive.define preprocessor definition directives -@punctuation.delimiter delimiters (e.g. `;` / `.` / `,`) -@punctuation.bracket brackets (e.g. `()` / `{}` / `[]`) +@punctuation.delimiter delimiters (e.g. `;`, `.`, `,`) +@punctuation.bracket brackets (e.g. `()`, `{}`, `[]`) @punctuation.special special symbols (e.g. `{}` in string interpolation) @comment line and block comments @@ -543,7 +563,7 @@ the exact definition): @comment.error error-type comments (e.g. `ERROR`, `FIXME`, `DEPRECATED`) @comment.warning warning-type comments (e.g. `WARNING`, `FIX`, `HACK`) -@comment.todo todo-type comments (e.g. `TODO`, `WIP`, `FIXME`) +@comment.todo todo-type comments (e.g. `TODO`, `WIP`) @comment.note note-type comments (e.g. `NOTE`, `INFO`, `XXX`) @markup.strong bold text @@ -552,10 +572,15 @@ the exact definition): @markup.underline underlined text (only for literal underline markup!) @markup.heading headings, titles (including markers) +@markup.heading.1 top-level heading +@markup.heading.2 section heading +@markup.heading.3 subsection heading +@markup.heading.4 and so on +@markup.heading.5 and so forth +@markup.heading.6 six levels ought to be enough for anybody @markup.quote block quotes @markup.math math environments (e.g. `$ ... $` in LaTeX) -@markup.environment environments (e.g. in LaTeX) @markup.link text references, footnotes, citations, etc. @markup.link.label link, reference descriptions @@ -573,6 +598,7 @@ the exact definition): @diff.delta changed text (for diff files) @tag XML-style tag names (e.g. in XML, HTML, etc.) +@tag.builtin XML-style tag names (e.g. HTML5 tags) @tag.attribute XML-style tag attributes @tag.delimiter XML-style tag delimiters @@ -646,6 +672,10 @@ parent tree. The language injection query allows you to specify these • `@injection.language` - indicates that the captured node’s text may contain the name of a language that should be used to re-parse the `@injection.content`. + • `@injection.filename` - indicates that the captured node’s text may + contain a filename; the corresponding filetype is then looked-up up via + |vim.filetype.match()| and treated as the name of a language that should + be used to re-parse the `@injection.content`. The language injection behavior can also be configured by some properties associated with patterns: @@ -719,8 +749,7 @@ get_captures_at_pos({bufnr}, {row}, {col}) • {col} (`integer`) Position column Return: ~ - (`table[]`) List of captures - `{ capture = "name", metadata = { ... } }` + (`{capture: string, lang: string, metadata: table}[]`) get_node({opts}) *vim.treesitter.get_node()* Returns the smallest named node at the given position @@ -978,7 +1007,7 @@ add_directive({name}, {handler}, {opts}) Parameters: ~ • {name} (`string`) Name of the directive, without leading # - • {handler} (`function`) + • {handler} (`fun(match: table<integer,TSNode[]>, pattern: integer, source: integer|string, predicate: any[], metadata: table)`) • match: A table mapping capture IDs to a list of captured nodes • pattern: the index of the matching pattern in the query @@ -986,10 +1015,10 @@ add_directive({name}, {handler}, {opts}) • predicate: list of strings containing the full directive being called, e.g. `(node (#set! conceal "-"))` would get the predicate `{ "#set!", "conceal", "-" }` - • {opts} (`table<string, any>`) Optional options: - • force (boolean): Override an existing predicate of the - same name - • all (boolean): Use the correct implementation of the + • {opts} (`table`) A table with the following fields: + • {force}? (`boolean`) Override an existing predicate of + the same name + • {all}? (`boolean`) Use the correct implementation of the match table where capture IDs map to a list of nodes instead of a single node. Defaults to false (for backward compatibility). This option will eventually become the @@ -1001,13 +1030,13 @@ add_predicate({name}, {handler}, {opts}) Parameters: ~ • {name} (`string`) Name of the predicate, without leading # - • {handler} (`function`) + • {handler} (`fun(match: table<integer,TSNode[]>, pattern: integer, source: integer|string, predicate: any[], metadata: table)`) • see |vim.treesitter.query.add_directive()| for argument meanings - • {opts} (`table<string, any>`) Optional options: - • force (boolean): Override an existing predicate of the - same name - • all (boolean): Use the correct implementation of the + • {opts} (`table`) A table with the following fields: + • {force}? (`boolean`) Override an existing predicate of + the same name + • {all}? (`boolean`) Use the correct implementation of the match table where capture IDs map to a list of nodes instead of a single node. Defaults to false (for backward compatibility). This option will eventually become the @@ -1079,13 +1108,13 @@ list_directives() *vim.treesitter.query.list_directives()* Lists the currently available directives to use in queries. Return: ~ - (`string[]`) List of supported directives. + (`string[]`) Supported directives. list_predicates() *vim.treesitter.query.list_predicates()* Lists the currently available predicates to use in queries. Return: ~ - (`string[]`) List of supported predicates. + (`string[]`) Supported predicates. omnifunc({findstart}, {base}) *vim.treesitter.query.omnifunc()* Omnifunc for completing node names and predicates in treesitter queries. @@ -1132,10 +1161,10 @@ Query:iter_captures({node}, {source}, {start}, {stop}) i.e., to get syntax highlight matches in the current viewport). When omitted, the {start} and {stop} row values are used from the given node. - The iterator returns three values: a numeric id identifying the capture, - the captured node, and metadata from any directives processing the match. - The following example shows how to get captures by name: >lua - for id, node, metadata in query:iter_captures(tree:root(), bufnr, first, last) do + The iterator returns four values: a numeric id identifying the capture, + the captured node, metadata from any directives processing the match, and + the match itself. The following example shows how to get captures by name: >lua + for id, node, metadata, match in query:iter_captures(tree:root(), bufnr, first, last) do local name = query.captures[id] -- name of the capture in the query -- typically useful info about the node: local type = node:type() -- type of the captured node @@ -1144,6 +1173,10 @@ Query:iter_captures({node}, {source}, {start}, {stop}) end < + Note: ~ + • Captures are only returned if the query pattern of a specific capture + contained predicates. + Parameters: ~ • {node} (`TSNode`) under which the search will occur • {source} (`integer|string`) Source buffer or string to extract text @@ -1154,8 +1187,8 @@ Query:iter_captures({node}, {source}, {start}, {stop}) Defaults to `node:end_()`. Return: ~ - (`fun(end_line: integer?): integer, TSNode, vim.treesitter.query.TSMetadata`) - capture id, capture node, metadata + (`fun(end_line: integer?): integer, TSNode, vim.treesitter.query.TSMetadata, TSQueryMatch`) + capture id, capture node, metadata, match *Query:iter_matches()* Query:iter_matches({node}, {source}, {start}, {stop}, {opts}) @@ -1198,6 +1231,8 @@ Query:iter_matches({node}, {source}, {start}, {stop}, {opts}) • max_start_depth (integer) if non-zero, sets the maximum start depth for each match. This is used to prevent traversing too deep into a tree. + • match_limit (integer) Set the maximum number of + in-progress matches (Default: 256). • all (boolean) When set, the returned match table maps capture IDs to a list of nodes. Older versions of iter_matches incorrectly mapped capture IDs to a single @@ -1291,7 +1326,11 @@ LanguageTree:included_regions() *LanguageTree:included_regions()* (`table<integer, Range6[]>`) LanguageTree:invalidate({reload}) *LanguageTree:invalidate()* - Invalidates this parser and all its children + Invalidates this parser and its children. + + Should only be called when the tracked state of the LanguageTree is not + valid against the parse tree in treesitter. Doesn't clear filesystem + cache. Called often, so needs to be fast. Parameters: ~ • {reload} (`boolean?`) @@ -1319,7 +1358,7 @@ LanguageTree:language_for_range({range}) • {range} (`Range4`) `{ start_line, start_col, end_line, end_col }` Return: ~ - (`vim.treesitter.LanguageTree`) Managing {range} + (`vim.treesitter.LanguageTree`) tree Managing {range} *LanguageTree:named_node_for_range()* LanguageTree:named_node_for_range({range}, {opts}) @@ -1327,12 +1366,12 @@ LanguageTree:named_node_for_range({range}, {opts}) Parameters: ~ • {range} (`Range4`) `{ start_line, start_col, end_line, end_col }` - • {opts} (`table?`) Optional keyword arguments: - • ignore_injections boolean Ignore injected languages - (default true) + • {opts} (`table?`) A table with the following fields: + • {ignore_injections}? (`boolean`, default: `true`) Ignore + injected languages Return: ~ - (`TSNode?`) Found node + (`TSNode?`) LanguageTree:parse({range}) *LanguageTree:parse()* Recursively parse all regions in the language tree using @@ -1359,8 +1398,9 @@ LanguageTree:register_cbs({cbs}, {recursive}) Registers callbacks for the |LanguageTree|. Parameters: ~ - • {cbs} (`table`) An |nvim_buf_attach()|-like table argument with - the following handlers: + • {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_changedtree` : a callback that will be called every @@ -1387,9 +1427,9 @@ LanguageTree:tree_for_range({range}, {opts}) Parameters: ~ • {range} (`Range4`) `{ start_line, start_col, end_line, end_col }` - • {opts} (`table?`) Optional keyword arguments: - • ignore_injections boolean Ignore injected languages - (default true) + • {opts} (`table?`) A table with the following fields: + • {ignore_injections}? (`boolean`, default: `true`) Ignore + injected languages Return: ~ (`TSTree?`) diff --git a/runtime/doc/uganda.txt b/runtime/doc/uganda.txt index 42e275c230..0b281dc3a0 100644 --- a/runtime/doc/uganda.txt +++ b/runtime/doc/uganda.txt @@ -199,7 +199,7 @@ visited about once a year to check the progress (at our own cost). I have visited the centre myself many times, starting in 1993. The visit reports are on the ICCF web site. -If you have any further questions, send me e-mail: <Bram@vim.org>. +If you have any further questions, send e-mail: <Bram@vim.org>. The address of the centre is: Kibaale Children's Centre @@ -219,9 +219,8 @@ Canada: Contact Kuwasha in Surrey, Canada. They take care of the Canadian sponsors for the children in Kibaale. Kuwasha forwards 100% of the money to the project in Uganda. You can send them a one time donation directly. - Please send me a note so that I know what has been donated - because of Vim. Look on their site for information about - sponsorship: https://www.kuwasha.net/ + Look on their site for information about sponsorship: + https://www.kuwasha.net/ If you make a donation to Kuwasha you will receive a tax receipt which can be submitted with your tax return. diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt index b8d47923ca..1f5132bd30 100644 --- a/runtime/doc/ui.txt +++ b/runtime/doc/ui.txt @@ -331,8 +331,8 @@ numerical highlight ids to the actual attributes. `blend`: blend level (0-100). Could be used by UIs to support blending floating windows to the background or to signal a transparent cursor. - `url`: a URL associated with this highlight. UIs can - display this URL however they wish. + `url`: URL associated with this highlight. UIs should + present the region as a clickable hyperlink. For absent color keys the default color should be used. Don't store the default value in the table, rather a sentinel value, so that @@ -656,6 +656,11 @@ tabs. the screen and copy it to the viewport destination once `win_viewport` is received. +["win_viewport_margins", grid, win, top, bottom, left, right] ~ + Indicates the margins of a window grid which are _not_ part of the + viewport as indicated by the `win_viewport` event. This happens + e.g. in the presence of 'winbar' and floating window borders. + ["win_extmark", grid, win, ns_id, mark_id, row, col] ~ Updates the position of an extmark which is currently visible in a window. Only emitted if the mark has the `ui_watched` attribute. @@ -772,9 +777,10 @@ This UI extension delegates presentation of messages and dialogs. Messages that would otherwise render in the message/cmdline screen space, are emitted as UI events. -Nvim will not allocate screen space for the cmdline or messages, and -'cmdheight' will be forced zero. Cmdline state is emitted as |ui-cmdline| -events, which the UI must handle. +Nvim will not allocate screen space for the cmdline or messages. 'cmdheight' +will be set to zero, but can be changed and used for the replacing cmdline or +message window. Cmdline state is emitted as |ui-cmdline| events, which the UI +must handle. ["msg_show", kind, content, replace_last] ~ Display a message to the user. diff --git a/runtime/doc/usr_01.txt b/runtime/doc/usr_01.txt index 6b94806941..d285a35f26 100644 --- a/runtime/doc/usr_01.txt +++ b/runtime/doc/usr_01.txt @@ -85,7 +85,7 @@ The Vim user manual and reference manual are Copyright (c) 1988 by Bram Moolenaar. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later. The latest version is presently available at: - https://www.opencontent.org/openpub/ + https://opencontent.org/openpub/ People who contribute to the manuals must agree with the above copyright notice. diff --git a/runtime/doc/usr_30.txt b/runtime/doc/usr_30.txt index a0d22482c3..98dbefae46 100644 --- a/runtime/doc/usr_30.txt +++ b/runtime/doc/usr_30.txt @@ -246,7 +246,7 @@ code block the cursor is in: > =a{ -I you have really badly indented code, you can re-indent the whole file with: +If you have really badly indented code, you can re-indent the whole file with: > gg=G diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index 56750420e9..ab2eecdfaf 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -794,6 +794,7 @@ Cursor and mark position: *cursor-functions* *mark-functions* Working with text in the current buffer: *text-functions* getline() get a line or list of lines from the buffer getregion() get a region of text from the buffer + getregionpos() get a list of positions for a region setline() replace a line in the buffer append() append line or list of lines in the buffer indent() indent of a specific line @@ -948,7 +949,7 @@ Syntax and highlighting: *syntax-functions* *highlighting-functions* synIDattr() get a specific attribute of a syntax ID synIDtrans() get translated syntax ID synstack() get list of syntax IDs at a specific position - synconcealed() get info about concealing + synconcealed() get info about (syntax) concealing diff_hlID() get highlight ID for diff mode at a position matchadd() define a pattern to highlight (a "match") matchaddpos() define a list of positions to highlight @@ -2500,13 +2501,9 @@ When you write a compiler file and put it in your personal runtime directory variable to make the default file skip the settings. *:CompilerSet* The second mechanism is to use ":set" for ":compiler!" and ":setlocal" for -":compiler". Vim defines the ":CompilerSet" user command for this. However, -older Vim versions don't, thus your plugin should define it then. This is an -example: > +":compiler". Vim defines the ":CompilerSet" user command for this. This is +an example: > - if exists(":CompilerSet") != 2 - command -nargs=* CompilerSet setlocal <args> - endif CompilerSet errorformat& " use the default 'errorformat' CompilerSet makeprg=nmake diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt index 33f57580c7..0287271d4c 100644 --- a/runtime/doc/various.txt +++ b/runtime/doc/various.txt @@ -14,6 +14,7 @@ Various commands *various* *CTRL-L* CTRL-L Clears and redraws the screen. The redraw may happen later, after processing typeahead. + See also |nvim__redraw()|. *CTRL-L-default* By default, also clears search highlighting |:nohlsearch| and updates diffs |:diffupdate|. @@ -21,6 +22,7 @@ CTRL-L Clears and redraws the screen. The redraw may happen *:mod* *:mode* :mod[e] Clears and redraws the screen. + See also |nvim__redraw()|. *:redr* *:redraw* :redr[aw][!] Redraws pending screen updates now, or the entire @@ -28,6 +30,7 @@ CTRL-L Clears and redraws the screen. The redraw may happen |:mode| or |CTRL-L|. Useful to update the screen during a script or function (or a mapping if 'lazyredraw' set). + See also |nvim__redraw()|. *:redraws* *:redrawstatus* :redraws[tatus][!] Redraws the status line and window bar of the current @@ -35,11 +38,12 @@ CTRL-L Clears and redraws the screen. The redraw may happen included. Redraws the commandline instead if it contains the 'ruler'. Useful if 'statusline' or 'winbar' includes an item that doesn't cause automatic updating. + See also |nvim__redraw()|. *:redrawt* *:redrawtabline* :redrawt[abline] Redraw the tabline. Useful to update the tabline when 'tabline' includes an item that doesn't trigger - automatic updating. + automatic updating. See also |nvim__redraw()|. *N<Del>* <Del> When entering a number: Remove the last digit. @@ -396,6 +400,7 @@ gx Opens the current filepath or URL (decided by |:command| - filter by command name |:files| - filter by file name |:highlight| - filter by highlight group + |:history| - filter by history commands |:jumps| - filter by file name |:let| - filter by variable name |:list| - filter whole line @@ -557,5 +562,47 @@ LessInitFunc in your vimrc, for example: > set nocursorcolumn nocursorline endfunc < +============================================================================== +3. Commenting *commenting* + +Nvim supports commenting and uncommenting of lines based on 'commentstring'. + +Acting on a single line behaves as follows: +- If the line matches 'commentstring', the comment markers are removed (e.g. + `/*foo*/` is transformed to `foo`). +- Otherwise the comment markers are added to the current line (e.g. `foo` is + transformed to `/*foo*/`). Blank lines are ignored. + +Acting on multiple lines behaves as follows: +- If each affected non-blank line matches 'commentstring', then all comment + markers are removed. +- Otherwise all affected lines are converted to comments; blank lines are + transformed to empty comments (e.g. `/**/`). Comment markers are aligned to + the least indented line. + +Matching 'commentstring' does not account for whitespace in comment markers. +Removing comment markers is first attempted exactly, with fallback to using +markers trimmed from whitespace. + +If the filetype of the buffer is associated with a language for which a +|treesitter| parser is installed, then |vim.filetype.get_option()| is called +to look up the value of 'commentstring' corresponding to the cursor position. +(This can be different from the buffer's 'commentstring' in case of +|treesitter-language-injections|.) + + *gc* *gc-default* +gc{motion} Comment or uncomment lines covered by {motion}. + + *gcc* *gcc-default* +gcc Comment or uncomment [count] lines starting at cursor. + + *v_gc* *v_gc-default* +{Visual}gc Comment or uncomment the selected line(s). + + *o_gc* *o_gc-default* +gc Text object for the largest contiguous block of + non-blank commented lines around the cursor (e.g. + `gcgc` uncomments a comment block; `dgc` deletes it). + Works only in Operator-pending mode. vim:noet:tw=78:ts=8:ft=help:norl: diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index b0caf9fdaf..5d894bb5e1 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -1,19 +1,19 @@ *vim_diff.txt* Nvim - NVIM REFERENCE MANUAL + NVIM REFERENCE MANUAL -Differences between Nvim and Vim *vim-differences* +Differences between Nvim and Vim *vim-differences* Nvim differs from Vim in many ways, although editor and Vimscript (not Vim9script) features are mostly identical. This document is a complete and centralized reference of the differences. - Type |gO| to see the table of contents. + Type |gO| to see the table of contents. ============================================================================== -Configuration *nvim-config* +Configuration *nvim-config* User configuration and data files are found in standard |base-directories| (see also |$NVIM_APPNAME|). Note in particular: @@ -24,7 +24,7 @@ User configuration and data files are found in standard |base-directories| session information. |shada| ============================================================================== -Defaults *nvim-defaults* +Defaults *nvim-defaults* - Filetype detection is enabled by default. This can be disabled by adding ":filetype off" to |init.vim|. @@ -52,6 +52,8 @@ Defaults *nvim-defaults* - 'encoding' is UTF-8 (cf. 'fileencoding' for file-content encoding) - 'fillchars' defaults (in effect) to "vert:│,fold:·,foldsep:│" - 'formatoptions' defaults to "tcqj" +- 'grepprg' uses the -H and -I flags for regular grep, + and defaults to using ripgrep if available - 'hidden' is enabled - 'history' defaults to 10000 (the maximum) - 'hlsearch' is enabled @@ -80,6 +82,7 @@ Defaults *nvim-defaults* - 'tags' defaults to "./tags;,tags" - 'termguicolors' is enabled by default if Nvim can detect support from the host terminal +- 'ttimeout' is enabled - 'ttimeoutlen' defaults to 50 - 'ttyfast' is always set - 'undodir' defaults to ~/.local/state/nvim/undo// (|xdg|), auto-created @@ -96,7 +99,7 @@ Defaults *nvim-defaults* - |g:vimsyn_embed| defaults to "l" to enable Lua highlighting DEFAULT MOUSE - *default-mouse* *disable-mouse* + *default-mouse* *disable-mouse* By default the mouse is enabled, and <RightMouse> opens a |popup-menu| with standard actions ("Cut", "Copy", "Paste", …). Mouse is NOT enabled in |command-mode| or the |more-prompt|, so you can temporarily disable it just by @@ -120,7 +123,7 @@ To remove the "How-to disable mouse" menu item and the separator above it: >vim aunmenu PopUp.-1- < DEFAULT MAPPINGS - *default-mappings* + *default-mappings* Nvim creates the following default mappings at |startup|. You can disable any of these in your config by simply removing the mapping, e.g. ":unmap Y". @@ -133,11 +136,21 @@ of these in your config by simply removing the mapping, e.g. ":unmap Y". - @ |v_@-default| - # |v_#-default| - * |v_star-default| +- gc |gc-default| |v_gc-default| |o_gc-default| +- gcc |gcc-default| +- gr prefix |gr-default| + - |grn| + - |grr| + - |gra| +- <C-S> |i_CTRL-S| +- ]d |]d-default| +- [d |[d-default| +- <C-W>d |CTRL-W_d-default| - Nvim LSP client defaults |lsp-defaults| - K |K-lsp-default| DEFAULT AUTOCOMMANDS - *default-autocmds* + *default-autocmds* Default autocommands exist in the following groups. Use ":autocmd! {group}" to remove them and ":autocmd {group}" to see how they're defined. @@ -161,7 +174,7 @@ nvim_swapfile: swapfile…" message. ============================================================================== -New Features *nvim-features* +New Features *nvim-features* MAJOR COMPONENTS @@ -186,7 +199,7 @@ USER EXPERIENCE Working intuitively and consistently is a major goal of Nvim. - *feature-compile* + *feature-compile* - Nvim always includes ALL features, in contrast to Vim (which ships various combinations of 100+ optional features). |feature-compile| Think of it as a leaner version of Vim's "HUGE" build. This reduces surface area for bugs, @@ -233,182 +246,176 @@ by Nvim developers. FEATURES Command-line: - The expression prompt (|@=|, |c_CTRL-R_=|, |i_CTRL-R_=|) is highlighted +- The expression prompt (|@=|, |c_CTRL-R_=|, |i_CTRL-R_=|) is highlighted using a built-in Vimscript expression parser. |expr-highlight| - *E5408* *E5409* - |input()|, |inputdialog()| support custom highlighting. |input()-highlight| - *g:Nvim_color_cmdline* - (Experimental) Command-line (|:|) is colored by callback defined in - `g:Nvim_color_cmdline` (this callback is for testing only, and will be - removed in the future). +- *E5408* *E5409* |input()|, |inputdialog()| support custom highlighting. + |input()-highlight| +- (Experimental) *g:Nvim_color_cmdline* Command-line (|:|) is colored by + callback defined in `g:Nvim_color_cmdline` (this callback is for testing + only, and will be removed in the future). Commands: - |:checkhealth| - |:drop| is always available - |:Man| is available by default, with many improvements such as completion - |:match| can be invoked before highlight group is defined - |:source| works with Lua +- |:checkhealth| +- |:drop| is always available +- |:Man| is available by default, with many improvements such as completion +- |:match| can be invoked before highlight group is defined +- |:source| works with Lua User commands can support |:command-preview| to show results as you type - |:write| with "++p" flag creates parent directories. +- |:write| with "++p" flag creates parent directories. Events: - |RecordingEnter| - |RecordingLeave| - |SearchWrapped| - |Signal| - |TabNewEntered| - |TermClose| - |TermOpen| - |UIEnter| - |UILeave| +- |RecordingEnter| +- |RecordingLeave| +- |SearchWrapped| +- |Signal| +- |TabNewEntered| +- |TermClose| +- |TermOpen| +- |UIEnter| +- |UILeave| Functions: - |dictwatcheradd()| notifies a callback whenever a |Dict| is modified - |dictwatcherdel()| - |menu_get()| - |msgpackdump()|, |msgpackparse()| provide msgpack de/serialization - |stdpath()| - |system()|, |systemlist()| can run {cmd} directly (without 'shell') - |matchadd()| can be called before highlight group is defined - |tempname()| tries to recover if the Nvim |tempdir| disappears. - |writefile()| with "p" flag creates parent directories. +- |dictwatcheradd()| notifies a callback whenever a |Dict| is modified +- |dictwatcherdel()| +- |menu_get()| +- |msgpackdump()|, |msgpackparse()| provide msgpack de/serialization +- |stdpath()| +- |system()|, |systemlist()| can run {cmd} directly (without 'shell') +- |matchadd()| can be called before highlight group is defined +- |tempname()| tries to recover if the Nvim |tempdir| disappears. +- |writefile()| with "p" flag creates parent directories. Highlight groups: - |highlight-blend| controls blend level for a highlight group - |expr-highlight| highlight groups (prefixed with "Nvim") - |hl-NormalFloat| highlights floating window - |hl-FloatBorder| highlights border of a floating window - |hl-FloatTitle| highlights title of a floating window - |hl-FloatFooter| highlights footer of a floating window - |hl-NormalNC| highlights non-current windows - |hl-MsgArea| highlights messages/cmdline area - |hl-MsgSeparator| highlights separator for scrolled messages - |hl-Substitute| - |hl-TermCursor| - |hl-TermCursorNC| - |hl-WinSeparator| highlights window separators - |hl-Whitespace| highlights 'listchars' whitespace - |hl-WinBar| highlights 'winbar' - |hl-WinBarNC| highlights non-current window 'winbar' +- |highlight-blend| controls blend level for a highlight group +- |expr-highlight| highlight groups (prefixed with "Nvim") +- |hl-NormalFloat| highlights floating window +- |hl-FloatBorder| highlights border of a floating window +- |hl-FloatTitle| highlights title of a floating window +- |hl-FloatFooter| highlights footer of a floating window +- |hl-NormalNC| highlights non-current windows +- |hl-MsgArea| highlights messages/cmdline area +- |hl-MsgSeparator| highlights separator for scrolled messages +- |hl-Substitute| +- |hl-TermCursor| +- |hl-TermCursorNC| +- |hl-WinSeparator| highlights window separators +- |hl-Whitespace| highlights 'listchars' whitespace +- |hl-WinBar| highlights 'winbar' +- |hl-WinBarNC| highlights non-current window 'winbar' Input/Mappings: - ALT (|META|) chords always work (even in the |TUI|). Map |<M-| with any key: +- ALT (|META|) chords always work (even in the |TUI|). Map |<M-| with any key: <M-1>, <M-BS>, <M-Del>, <M-Ins>, <M-/>, <M-\>, <M-Space>, <M-Enter>, etc. - Case-sensitive: <M-a> and <M-A> are two different keycodes. - - ALT may behave like <Esc> if not mapped. |i_ALT| |v_ALT| |c_ALT| + - Case-sensitive: <M-a> and <M-A> are two different keycodes. +- ALT may behave like <Esc> if not mapped. |i_ALT| |v_ALT| |c_ALT| Normal commands: - |gO| shows a filetype-defined "outline" of the current buffer. - |Q| replays the last recorded macro instead of switching to Ex mode (|gQ|). +- |gO| shows a filetype-defined "outline" of the current buffer. +- |Q| replays the last recorded macro instead of switching to Ex mode (|gQ|). 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. - - 'autoread' works in the terminal (if it supports "focus" events) - 'cpoptions' flags: |cpo-_| - 'diffopt' "linematch" feature - 'exrc' searches for ".nvim.lua", ".nvimrc", or ".exrc" files. The + +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. + +- 'autoread' works in the terminal (if it supports "focus" events) +- 'cpoptions' flags: |cpo-_| +- 'diffopt' "linematch" feature +- 'exrc' searches for ".nvim.lua", ".nvimrc", or ".exrc" files. The user is prompted whether to trust the file. - 'fillchars' flags: "msgsep", "horiz", "horizup", "horizdown", +- 'fillchars' flags: "msgsep", "horiz", "horizup", "horizdown", "vertleft", "vertright", "verthoriz" - 'foldcolumn' supports up to 9 dynamic/fixed columns - 'guicursor' works in the terminal (TUI) - 'inccommand' shows interactive results for |:substitute|-like commands +- 'foldcolumn' supports up to 9 dynamic/fixed columns +- 'guicursor' works in the terminal (TUI) +- 'inccommand' shows interactive results for |:substitute|-like commands and |:command-preview| commands - 'jumpoptions' "view" tries to restore the |mark-view| when moving through - the |jumplist|, |changelist|, |alternate-file| or using |mark-motions|. - 'laststatus' global statusline support - 'mousescroll' amount to scroll by when scrolling with a mouse - 'pumblend' pseudo-transparent popupmenu - 'scrollback' - 'shortmess' "F" flag does not affect output from autocommands - 'signcolumn' supports up to 9 dynamic/fixed columns - 'statuscolumn' full control of columns using 'statusline' format - 'tabline' middle-click on tabpage label closes tabpage, +- 'jumpoptions' "view" tries to restore the |mark-view| when moving through +- the |jumplist|, |changelist|, |alternate-file| or using |mark-motions|. +- 'laststatus' global statusline support +- 'mousescroll' amount to scroll by when scrolling with a mouse +- 'pumblend' pseudo-transparent popupmenu +- 'scrollback' +- 'shortmess' + - "F" flag does not affect output from autocommands. + - "q" flag fully hides macro recording message. +- 'signcolumn' supports up to 9 dynamic/fixed columns +- 'statuscolumn' full control of columns using 'statusline' format +- 'tabline' middle-click on tabpage label closes tabpage, and %@Func@foo%X can call any function on mouse-click - 'termpastefilter' - 'ttimeout', 'ttimeoutlen' behavior was simplified - 'winblend' pseudo-transparency in floating windows |api-floatwin| - 'winhighlight' window-local highlights +- 'termpastefilter' +- 'ttimeout', 'ttimeoutlen' behavior was simplified +- 'winblend' pseudo-transparency in floating windows |api-floatwin| +- 'winhighlight' window-local highlights Providers: - If a Python interpreter is available on your `$PATH`, |:python| and +- If a Python interpreter is available on your `$PATH`, |:python| and |:python3| are always available. See |provider-python|. Shell: - Shell output (|:!|, |:make|, …) is always routed through the UI, so it +- Shell output (|:!|, |:make|, …) is always routed through the UI, so it cannot "mess up" the screen. (You can still use "chansend(v:stderr,…)" if you want to mess up the screen :) - - Nvim throttles (skips) messages from shell commands (|:!|, |:grep|, |:make|) +- Nvim throttles (skips) messages from shell commands (|:!|, |:grep|, |:make|) if there is too much output. No data is lost, this only affects display and improves performance. |:terminal| output is never throttled. - - |:!| does not support "interactive" commands. Use |:terminal| instead. +- |:!| does not support "interactive" commands. Use |:terminal| instead. (GUI Vim has a similar limitation, see ":help gui-pty" in Vim.) - - :!start is not special-cased on Windows. - - |system()| does not support writing/reading "backgrounded" commands. |E5677| +- :!start is not special-cased on Windows. +- |system()| does not support writing/reading "backgrounded" commands. |E5677| Signs: - Signs are removed if the associated line is deleted. - Signs placed twice with the same identifier in the same group are moved. +- Signs are removed if the associated line is deleted. +- Signs placed twice with the same identifier in the same group are moved. Startup: - |-e| and |-es| invoke the same "improved Ex mode" as -E and -Es. - |-E| and |-Es| read stdin as text (into buffer 1). - |-es| and |-Es| have improved behavior: +- |-e| and |-es| invoke the same "improved Ex mode" as -E and -Es. +- |-E| and |-Es| read stdin as text (into buffer 1). +- |-es| and |-Es| have improved behavior: - Quits automatically, don't need "-c qa!". - Skips swap-file dialog. - |-s| reads Normal commands from stdin if the script name is "-". - Reading text (instead of commands) from stdin |--|: +- |-s| reads Normal commands from stdin if the script name is "-". +- Reading text (instead of commands) from stdin |--|: - works by default: "-" file is optional - works in more cases: |-Es|, file args TUI: - *:set-termcap* - Start Nvim with 'verbose' level 3 to show terminal capabilities: > - nvim -V3 + *:set-termcap* +- Start Nvim with 'verbose' level 3 to show terminal capabilities: > + nvim -V3 < - *'term'* *E529* *E530* *E531* - 'term' reflects the terminal type derived from |$TERM| and other environment + *'term'* *E529* *E530* *E531* +- 'term' reflects the terminal type derived from |$TERM| and other environment checks. For debugging only; not reliable during startup. >vim - :echo &term -< "builtin_x" means one of the |builtin-terms| was chosen, because the expected + :echo &term +- "builtin_x" means one of the |builtin-terms| was chosen, because the expected terminfo file was not found on the system. - - Nvim will use 256-colour capability on Linux virtual terminals. Vim uses +- Nvim will use 256-colour capability on Linux virtual terminals. Vim uses only 8 colours plus bright foreground on Linux VTs. - - Vim combines what is in its |builtin-terms| with what it reads from terminfo, +- Vim combines what is in its |builtin-terms| with what it reads from terminfo, and has a 'ttybuiltin' setting to control how that combination works. Nvim uses one or the other, it does not attempt to merge the two. UI/Display: - |Visual| selection highlights the character at cursor. |visual-use| - - messages: When showing messages longer than 'cmdheight', only +- |Visual| selection highlights the character at cursor. |visual-use| +- messages: When showing messages longer than 'cmdheight', only scroll the message lines, not the entire screen. The separator line is decorated by |hl-MsgSeparator| and the "msgsep" flag of 'fillchars'. *msgsep* Variables: - |v:progpath| is always absolute ("full") - |v:windowid| is always available (for use by external UIs) - |OptionSet| autocommand args |v:option_new|, |v:option_old|, - |v:option_oldlocal|, |v:option_oldglobal| have the type of the option +- |v:progpath| is always absolute ("full") +- |v:windowid| is always available (for use by external UIs) +- |OptionSet| autocommand args |v:option_new|, |v:option_old|, +- |v:option_oldlocal|, |v:option_oldglobal| have the type of the option instead of always being strings. |v:option_old| is now the old global value for all global-local options, instead of just string global-local options. Vimscript: - |:redir| nested in |execute()| works. +- |:redir| nested in |execute()| works. ============================================================================== -Upstreamed features *nvim-upstreamed* +Upstreamed features *nvim-upstreamed* These Nvim features were later integrated into Vim. @@ -423,45 +430,44 @@ These Nvim features were later integrated into Vim. - 'statusline' supports unlimited alignment sections ============================================================================== -Other changes *nvim-changed* +Other changes *nvim-changed* This section documents various low-level behavior changes. |mkdir()| behaviour changed: -1. Assuming /tmp/foo does not exist and /tmp can be written to - mkdir('/tmp/foo/bar', 'p', 0700) will create both /tmp/foo and /tmp/foo/bar - with 0700 permissions. Vim mkdir will create /tmp/foo with 0755. -2. If you try to create an existing directory with `'p'` (e.g. mkdir('/', - 'p')) mkdir() will silently exit. In Vim this was an error. -3. mkdir() error messages now include strerror() text when mkdir fails. +- 1. Assuming /tmp/foo does not exist and /tmp can be written to + mkdir('/tmp/foo/bar', 'p', 0700) will create both /tmp/foo and + /tmp/foo/bar with 0700 permissions. Vim mkdir will create /tmp/foo with + 0755. +- 2. If you try to create an existing directory with `'p'` (e.g. mkdir('/', + 'p')) mkdir() will silently exit. In Vim this was an error. +- 3. mkdir() error messages now include strerror() text when mkdir fails. |string()| and |:echo| behaviour changed: -1. No maximum recursion depth limit is applied to nested container - structures. -2. |string()| fails immediately on nested containers, not when recursion limit - was exceeded. -3. When |:echo| encounters duplicate containers like >vim - +- 1. No maximum recursion depth limit is applied to nested container + structures. +- 2. |string()| fails immediately on nested containers, not when recursion + limit was exceeded. +- 3. When |:echo| encounters duplicate containers like >vim let l = [] echo [l, l] -< - it does not use "[...]" (was: "[[], [...]]", now: "[[], []]"). "..." is - only used for recursive containers. -4. |:echo| printing nested containers adds "@level" after "..." designating - the level at which recursive container was printed: |:echo-self-refer|. - Same thing applies to |string()| (though it uses construct like - "{E724@level}"), but this is not reliable because |string()| continues to - error out. -5. Stringifyed infinite and NaN values now use |str2float()| and can be evaled - back. -6. (internal) Trying to print or stringify VAR_UNKNOWN in Vim results in - nothing, E908, in Nvim it is internal error. +< it does not use "[...]" (was: "[[], [...]]", now: "[[], []]"). "..." is + only used for recursive containers. +- 4. |:echo| printing nested containers adds "@level" after "..." designating + the level at which recursive container was printed: |:echo-self-refer|. + Same thing applies to |string()| (though it uses construct like + "{E724@level}"), but this is not reliable because |string()| continues to + error out. +- 5. Stringifyed infinite and NaN values now use |str2float()| and can be + evaled back. +- 6. (internal) Trying to print or stringify VAR_UNKNOWN in Vim results in + nothing, E908, in Nvim it is internal error. |json_decode()| behaviour changed: -1. It may output |msgpack-special-dict|. -2. |msgpack-special-dict| is emitted also in case of duplicate keys, while in - Vim it errors out. -3. It accepts only valid JSON. Trailing commas are not accepted. +- 1. It may output |msgpack-special-dict|. +- 2. |msgpack-special-dict| is emitted also in case of duplicate keys, while + in Vim it errors out. +- 3. It accepts only valid JSON. Trailing commas are not accepted. |json_encode()| behaviour slightly changed: now |msgpack-special-dict| values are accepted, but |v:none| is not. @@ -505,38 +511,37 @@ Lua interface (|lua.txt|): 'runtimepath'. |lua-module-load| Commands: - |:doautocmd| does not warn about "No matching autocommands". - |:wincmd| accepts a count. - `:write!` does not show a prompt if the file was updated externally. - |:=| does not accept |ex-flags|. With an arg it is equivalent to |:lua=| +- |:doautocmd| does not warn about "No matching autocommands". +- |:wincmd| accepts a count. +- `:write!` does not show a prompt if the file was updated externally. +- |:=| does not accept |ex-flags|. With an arg it is equivalent to |:lua=| Command-line: - The meanings of arrow keys do not change depending on 'wildoptions'. +- The meanings of arrow keys do not change depending on 'wildoptions'. Functions: - |input()| and |inputdialog()| support for each other’s features (return on +- |input()| and |inputdialog()| support for each other’s features (return on cancel and completion respectively) via dictionary argument (replaces all other arguments if used), and "cancelreturn" can have any type if passed in a dictionary. - |input()| and |inputdialog()| support user-defined cmdline highlighting. +- |input()| and |inputdialog()| support user-defined cmdline highlighting. Highlight groups: - |hl-ColorColumn|, |hl-CursorColumn| are lower priority than most other +- |hl-ColorColumn|, |hl-CursorColumn| are lower priority than most other groups - |hl-CurSearch| highlights match under cursor instead of last match found +- |hl-CurSearch| highlights match under cursor instead of last match found using |n| or |N| - |hl-CursorLine| is low-priority unless foreground color is set - |hl-VertSplit| superseded by |hl-WinSeparator| - Highlight groups names are allowed to contain `@` characters. - It is an error to define a highlight group with a name that doesn't match - the regexp `[a-zA-Z0-9_.@-]*` (see |group-name|). - -Macro/|recording| behavior - Replay of a macro recorded during :lmap produces the same actions as when it +- |hl-CursorLine| is low-priority unless foreground color is set +- |hl-VertSplit| superseded by |hl-WinSeparator| +- Highlight groups names are allowed to contain `@` characters. + - It is an error to define a highlight group with a name that doesn't match + the regexp `[a-zA-Z0-9_.@-]*` (see |group-name|). + +Macro (|recording|) behavior: +- Replay of a macro recorded during :lmap produces the same actions as when it was recorded. In Vim if a macro is recorded while using :lmap'ped keys then the behaviour during record and replay differs. - - 'keymap' is implemented via :lmap instead of :lnoremap so that you can use +- 'keymap' is implemented via :lmap instead of :lnoremap so that you can use macros and 'keymap' at the same time. This also means you can use |:imap| on the results of keys from 'keymap'. @@ -547,13 +552,13 @@ Mappings: lhs of a mapping. Motion: - The |jumplist| avoids useless/phantom jumps. +- The |jumplist| avoids useless/phantom jumps. Performance: - Folds are not updated during insert-mode. +- Folds are not updated during insert-mode. Syntax highlighting: - syncolor.vim has been removed. Nvim now sets up default highlighting groups +- syncolor.vim has been removed. Nvim now sets up default highlighting groups automatically for both light and dark backgrounds, regardless of whether or not syntax highlighting is enabled. This means that |:syntax-on| and |:syntax-enable| are now identical. Users who previously used an @@ -561,10 +566,10 @@ Syntax highlighting: colorscheme. |:colorscheme| Vimscript compatibility: - `count` does not alias to |v:count| - `errmsg` does not alias to |v:errmsg| - `shell_error` does not alias to |v:shell_error| - `this_session` does not alias to |v:this_session| +- `count` does not alias to |v:count| +- `errmsg` does not alias to |v:errmsg| +- `shell_error` does not alias to |v:shell_error| +- `this_session` does not alias to |v:this_session| Working directory (Vim implemented some of these after Nvim): - |DirChanged| and |DirChangedPre| can be triggered when switching to another @@ -582,11 +587,8 @@ Autocommands: - |TermResponse| is fired for any OSC sequence received from the terminal, instead of the Primary Device Attributes response. |v:termresponse| -Options: -- |shm-q| fully hides macro recording message instead of only shortening it. - ============================================================================== -Missing features *nvim-missing* +Missing features *nvim-missing* These legacy Vim features are not yet implemented: @@ -596,75 +598,75 @@ These legacy Vim features are not yet implemented: - *'previewpopup'* ============================================================================== -Removed legacy features *nvim-removed* +Removed legacy features *nvim-removed* These Vim features were intentionally removed from Nvim. Aliases: - ex (alias for "nvim -e") - exim (alias for "nvim -E") - gex (GUI) - gview (GUI) - gvim (GUI) - gvimdiff (GUI) - rgview (GUI) - rgvim (GUI) - rview - rvim - view (alias for "nvim -R") - vimdiff (alias for "nvim -d" |diff-mode|) +- ex (alias for "nvim -e") +- exim (alias for "nvim -E") +- gex (GUI) +- gview (GUI) +- gvim (GUI) +- gvimdiff (GUI) +- rgview (GUI) +- rgvim (GUI) +- rview +- rvim +- view (alias for "nvim -R") +- vimdiff (alias for "nvim -d" |diff-mode|) Commands: - :behave - :fixdel - *hardcopy* `:hardcopy` was removed. Instead, use `:TOhtml` and print the +- :behave +- :fixdel +- *hardcopy* `:hardcopy` was removed. Instead, use `:TOhtml` and print the resulting HTML using a web browser or other HTML viewer. - :helpfind - :mode (no longer accepts an argument) - :open - :Print - :promptfind - :promptrepl - :scriptversion (always version 1) - :shell - :sleep! (does not hide the cursor; same as :sleep) - :smile - :tearoff - :cstag - :cscope - :lcscope - :scscope - :Vimuntar - The old `:TOhtml`, replaced by a Lua version (contains many differences) +- :helpfind +- :mode (no longer accepts an argument) +- :open +- :Print +- :promptfind +- :promptrepl +- :scriptversion (always version 1) +- :shell +- :sleep! (does not hide the cursor; same as :sleep) +- :smile +- :tearoff +- :cstag +- :cscope +- :lcscope +- :scscope +- :Vimuntar +- `:TOhtml` was replaced by a Lua version (with various differences) Compile-time features: - Emacs tags support - X11 integration (see |x11-selection|) +- Emacs tags support +- X11 integration (see |x11-selection|) Cscope: *cscope* - Cscope support was removed in favour of plugin-based solutions such as: +- Cscope support was removed in favour of plugin-based solutions such as: https://github.com/dhananjaylatkar/cscope_maps.nvim Eval: - Vim9script - *cscope_connection()* - *err_teapot()* - *js_encode()* - *js_decode()* - *v:none* (used by Vim to represent JavaScript "undefined"); use |v:null| instead. - *v:sizeofint* - *v:sizeoflong* - *v:sizeofpointer* +- Vim9script +- *cscope_connection()* +- *err_teapot()* +- *js_encode()* +- *js_decode()* +- *v:none* (used by Vim to represent JavaScript "undefined"); use |v:null| instead. +- *v:sizeofint* +- *v:sizeoflong* +- *v:sizeofpointer* Events: - *SafeStateAgain* - *SigUSR1* Use |Signal| to detect `SIGUSR1` signal instead. +- *SafeStateAgain* +- *SigUSR1* Use |Signal| to detect `SIGUSR1` signal instead. Highlight groups: - *hl-StatusLineTerm* *hl-StatusLineTermNC* are unnecessary because Nvim - supports 'winhighlight' window-local highlights. - For example, to mimic Vim's StatusLineTerm: >vim +- *hl-StatusLineTerm* *hl-StatusLineTermNC* are unnecessary because Nvim + supports 'winhighlight' window-local highlights. For example, to mimic Vim's + StatusLineTerm: >vim hi StatusLineTerm ctermfg=black ctermbg=green hi StatusLineTermNC ctermfg=green autocmd TermOpen,WinEnter * if &buftype=='terminal' @@ -673,48 +675,45 @@ Highlight groups: < Options: - *'aleph'* *'al'* - antialias - 'backspace' no longer supports number values. Instead: +- *'aleph'* *'al'* +- antialias +- 'backspace' no longer supports number values. Instead: - for `backspace=0` set `backspace=` (empty) - for `backspace=1` set `backspace=indent,eol` - for `backspace=2` set `backspace=indent,eol,start` (default behavior in Nvim) - for `backspace=3` set `backspace=indent,eol,nostop` - *'balloondelay'* *'bdlay'* - *'ballooneval'* *'beval'* *'noballooneval'* *'nobeval'* - *'balloonexpr'* *'bexpr'* - bioskey (MS-DOS) - conskey (MS-DOS) - *'cp'* *'nocompatible'* *'nocp'* *'compatible'* (Nvim is always "nocompatible".) - 'cpoptions' (gjpkHw<*- and all POSIX flags were removed) - *'cryptmethod'* *'cm'* *'key'* (Vim encryption implementation) - cscopepathcomp - cscopeprg - cscopequickfix - cscoperelative - cscopetag - cscopetagorder - cscopeverbose - *'ed'* *'edcompatible'* *'noed'* *'noedcompatible'* - 'encoding' ("utf-8" is always used) - esckeys - 'guioptions' "t" flag was removed - *'guifontset'* *'gfs'* (Use 'guifont' instead.) - *'guipty'* (Nvim uses pipes and PTYs consistently on all platforms.) - 'highlight' (Names of builtin |highlight-groups| cannot be changed.) - *'hkmap'* *'hk'* use `set keymap=hebrew` instead. - *'hkmapp'* *'hkp'* use `set keymap=hebrewp` instead. - keyprotocol - - *'pastetoggle'* *'pt'* Just Paste It.™ |paste| is handled automatically when +- *'balloondelay'* *'bdlay'* +- *'ballooneval'* *'beval'* *'noballooneval'* *'nobeval'* +- *'balloonexpr'* *'bexpr'* +- bioskey (MS-DOS) +- conskey (MS-DOS) +- *'cp'* *'nocompatible'* *'nocp'* *'compatible'* (Nvim is always "nocompatible".) +- 'cpoptions' (gjpkHw<*- and all POSIX flags were removed) +- *'cryptmethod'* *'cm'* *'key'* (Vim encryption implementation) +- cscopepathcomp +- cscopeprg +- cscopequickfix +- cscoperelative +- cscopetag +- cscopetagorder +- cscopeverbose +- *'ed'* *'edcompatible'* *'noed'* *'noedcompatible'* +- 'encoding' ("utf-8" is always used) +- esckeys +- 'guioptions' "t" flag was removed +- *'guifontset'* *'gfs'* (Use 'guifont' instead.) +- *'guipty'* (Nvim uses pipes and PTYs consistently on all platforms.) +- 'highlight' (Names of builtin |highlight-groups| cannot be changed.) +- *'hkmap'* *'hk'* use `set keymap=hebrew` instead. +- *'hkmapp'* *'hkp'* use `set keymap=hebrewp` instead. +- keyprotocol +- *'pastetoggle'* *'pt'* Just Paste It.™ |paste| is handled automatically when you paste text using your terminal's or GUI's paste feature (CTRL-SHIFT-v, CMD-v (macOS), middle-click, …). - - *'imactivatefunc'* *'imaf'* - *'imactivatekey'* *'imak'* - *'imstatusfunc'* *'imsf'* - *'insertmode'* *'im'* Use the following script to emulate 'insertmode': ->vim +- *'imactivatefunc'* *'imaf'* +- *'imactivatekey'* *'imak'* +- *'imstatusfunc'* *'imsf'* +- *'insertmode'* *'im'* Use the following script to emulate 'insertmode': >vim autocmd BufWinEnter * startinsert inoremap <Esc> <C-X><C-Z><C-]> inoremap <C-C> <C-X><C-Z> @@ -740,50 +739,44 @@ Options: end end) EOF -< - *'macatsui'* - *'maxcombine'* *'mco'* - Nvim counts maximum character sizes in bytes, not codepoints. This is - guaranteed to be big enough to always fit all chars properly displayed - in vim with 'maxcombine' set to 6. - - You can still edit text with larger characters than fits in the screen buffer, - you just can't see them. Use |g8| or |ga|. See |mbyte-combining|. - - NOTE: the rexexp engine still has a hard-coded limit of considering +- *'macatsui'* +- *'maxcombine'* *'mco'* : Nvim counts maximum character sizes in bytes, not + codepoints. This is guaranteed to be big enough to always fit all chars + properly displayed in vim with 'maxcombine' set to 6. + - You can still edit text with larger characters than fits in the screen + buffer, you just can't see them. Use |g8| or |ga|. See |mbyte-combining|. + - NOTE: the rexexp engine still has a hard-coded limit of considering 6 composing chars only. - - *'maxmem'* Nvim delegates memory-management to the OS. - *'maxmemtot'* Nvim delegates memory-management to the OS. - printoptions - *'printdevice'* - *'printencoding'* - *'printexpr'* - *'printfont'* - *'printheader'* - *'printmbcharset'* - *'prompt'* *'noprompt'* - *'remap'* *'noremap'* - *'restorescreen'* *'rs'* *'norestorescreen'* *'nors'* - *'secure'* - Everything is allowed in 'exrc' files since they must be explicitly marked - trusted. - *'shelltype'* - 'shortmess' flags: *shm-f* *shm-n* *shm-x* *shm-i* (behave like always on) - *'shortname'* *'sn'* *'noshortname'* *'nosn'* - *'swapsync'* *'sws'* - *'termencoding'* *'tenc'* (Vim 7.4.852 also removed this for Windows) - *'terse'* *'noterse'* (Add "s" to 'shortmess' instead) - textauto - textmode - *'toolbar'* *'tb'* - *'toolbariconsize'* *'tbis'* - *'ttybuiltin'* *'tbi'* *'nottybuiltin'* *'notbi'* - *'ttyfast'* *'tf'* *'nottyfast'* *'notf'* - *'ttymouse'* *'ttym'* - *'ttyscroll'* *'tsl'* - *'ttytype'* *'tty'* - weirdinvert +- *'maxmem'* Nvim delegates memory-management to the OS. +- *'maxmemtot'* Nvim delegates memory-management to the OS. +- printoptions +- *'printdevice'* +- *'printencoding'* +- *'printexpr'* +- *'printfont'* +- *'printheader'* +- *'printmbcharset'* +- *'prompt'* *'noprompt'* +- *'remap'* *'noremap'* +- *'restorescreen'* *'rs'* *'norestorescreen'* *'nors'* +- *'secure'* : Everything is allowed in 'exrc' files, because they must be + explicitly marked as "trusted". +- *'shelltype'* +- 'shortmess' flags: *shm-f* *shm-n* *shm-x* *shm-i* (behave like always on) +- *'shortname'* *'sn'* *'noshortname'* *'nosn'* +- *'swapsync'* *'sws'* +- *'termencoding'* *'tenc'* (Vim 7.4.852 also removed this for Windows) +- *'terse'* *'noterse'* (Add "s" to 'shortmess' instead) +- textauto +- textmode +- *'toolbar'* *'tb'* +- *'toolbariconsize'* *'tbis'* +- *'ttybuiltin'* *'tbi'* *'nottybuiltin'* *'notbi'* +- *'ttyfast'* *'tf'* *'nottyfast'* *'notf'* +- *'ttymouse'* *'ttym'* +- *'ttyscroll'* *'tsl'* +- *'ttytype'* *'tty'* +- weirdinvert Plugins: @@ -799,47 +792,47 @@ Providers: - *if_tcl* Startup: - --literal (file args are always literal; to expand wildcards on Windows, use - |:n| e.g. `nvim +"n *"`) - Easy mode: eview, evim, nvim -y - Restricted mode: rview, rvim, nvim -Z - Vi mode: nvim -v +- `--literal`: File args are always literal; to expand wildcards on Windows, + use |:n| e.g. `nvim +"n *"` +- Easy mode: eview, evim, nvim -y +- Restricted mode: rview, rvim, nvim -Z +- Vi mode: nvim -v Test functions: - test_alloc_fail() - test_autochdir() - test_disable_char_avail() - test_feedinput() - test_garbagecollect_soon - test_getvalue() - test_ignore_error() - test_null_blob() - test_null_channel() - test_null_dict() - test_null_function() - test_null_job() - test_null_list() - test_null_partial() - test_null_string() - test_option_not_set() - test_override() - test_refcount() - test_scrollbar() - test_setmouse() - test_settime() - test_srand_seed() +- test_alloc_fail() +- test_autochdir() +- test_disable_char_avail() +- test_feedinput() +- test_garbagecollect_soon +- test_getvalue() +- test_ignore_error() +- test_null_blob() +- test_null_channel() +- test_null_dict() +- test_null_function() +- test_null_job() +- test_null_list() +- test_null_partial() +- test_null_string() +- test_option_not_set() +- test_override() +- test_refcount() +- test_scrollbar() +- test_setmouse() +- test_settime() +- test_srand_seed() TUI: - *t_xx* *termcap-options* *t_AB* *t_Sb* *t_vb* *t_SI* - Nvim does not have special `t_XX` options nor <t_XX> keycodes to configure + *t_xx* *termcap-options* *t_AB* *t_Sb* *t_vb* *t_SI* +- Nvim does not have special `t_XX` options nor <t_XX> keycodes to configure terminal capabilities. Instead Nvim treats the terminal as any other UI, e.g. 'guicursor' sets the terminal cursor style if possible. - *termcap* - Nvim never uses the termcap database, only |terminfo| and |builtin-terms|. + *termcap* +- Nvim never uses the termcap database, only |terminfo| and |builtin-terms|. - *xterm-8bit* *xterm-8-bit* - Xterm can be run in a mode where it uses true 8-bit CSI. Supporting this + *xterm-8bit* *xterm-8-bit* +- Xterm can be run in a mode where it uses true 8-bit CSI. Supporting this requires autodetection of whether the terminal is in UTF-8 mode or non-UTF-8 mode, as the 8-bit CSI character has to be written differently in each case. Vim issues a "request version" sequence to the terminal at startup and looks diff --git a/runtime/doc/visual.txt b/runtime/doc/visual.txt index a20fb6d31e..6d3aaa62dd 100644 --- a/runtime/doc/visual.txt +++ b/runtime/doc/visual.txt @@ -366,15 +366,15 @@ one of the last commands to extend the highlighted text, the repeating will be applied up to the rightmost column of the longest line. Any count passed to the `.` command is not used. -Visual mode |default-mappings| "@" and "Q" can repeat commands in a register -for all selected lines. See |v_@-default| and |v_Q-default| for details. For -example, given the text: +Visual mode |default-mappings| "@" and "Q" repeat a register for all selected +lines if the selection is linewise. See |v_@-default| and |v_Q-default| for +details. For example, given the text: 123(hello)321 456(world)654 456(NOT THIS)654 -With register "x" containing the commands `yi(VP`, Visually selecting the +With register "x" containing the commands `yi(VP`, visually selecting the first two lines and typing `@x` produces: hello diff --git a/runtime/doc/vvars.txt b/runtime/doc/vvars.txt index e71e31abf8..15d836a83d 100644 --- a/runtime/doc/vvars.txt +++ b/runtime/doc/vvars.txt @@ -60,9 +60,10 @@ v:collate *v:completed_item* *completed_item-variable* v:completed_item - Dictionary containing the most recent |complete-items| after - |CompleteDone|. Empty if the completion failed, or after - leaving and re-entering insert mode. + Dictionary containing the |complete-items| for the most + recently completed word after |CompleteDone|. Empty if the + completion failed, or after leaving and re-entering insert + mode. Note: Plugins can modify the value to emulate the builtin |CompleteDone| event behavior. @@ -186,6 +187,7 @@ v:event changed_window Is |v:true| if the event fired while changing window (or tab) on |DirChanged|. status Job status or exit code, -1 means "unknown". |TermClose| + reason Reason for completion being done. |CompleteDone| *v:exception* *exception-variable* v:exception diff --git a/runtime/doc/windows.txt b/runtime/doc/windows.txt index b71e7c80ab..4791e73929 100644 --- a/runtime/doc/windows.txt +++ b/runtime/doc/windows.txt @@ -502,35 +502,33 @@ horizontally split windows. CTRL-W H does it the other way around. *CTRL-W_K* CTRL-W K Move the current window to be at the very top, using the full - width of the screen. This works like closing the current - window and then creating another one with ":topleft split", - except that the current window contents is used for the new - window. + width of the screen. This works like `:topleft split`, except + it is applied to the current window and no new window is + created. *CTRL-W_J* CTRL-W J Move the current window to be at the very bottom, using the - full width of the screen. This works like closing the current - window and then creating another one with ":botright split", - except that the current window contents is used for the new - window. + full width of the screen. This works like `:botright split`, + except it is applied to the current window and no new window + is created. *CTRL-W_H* CTRL-W H Move the current window to be at the far left, using the - full height of the screen. This works like closing the - current window and then creating another one with - `:vert topleft split`, except that the current window contents - is used for the new window. + full height of the screen. This works like + `:vert topleft split`, except it is applied to the current + window and no new window is created. *CTRL-W_L* CTRL-W L Move the current window to be at the far right, using the full - height of the screen. This works like closing the - current window and then creating another one with - `:vert botright split`, except that the current window - contents is used for the new window. + height of the screen. This works like `:vert botright split`, + except it is applied to the current window and no new window + is created. *CTRL-W_T* CTRL-W T Move the current window to a new tab page. This fails if there is only one window in the current tab page. + This works like `:tab split`, except the previous window is + closed. When a count is specified the new tab page will be opened before the tab page with this index. Otherwise it comes after the current tab page. diff --git a/runtime/filetype.lua b/runtime/filetype.lua index 3f2a7c2960..4880ed55ef 100644 --- a/runtime/filetype.lua +++ b/runtime/filetype.lua @@ -11,7 +11,12 @@ vim.api.nvim_create_autocmd({ 'BufRead', 'BufNewFile', 'StdinReadPost' }, { if not vim.api.nvim_buf_is_valid(args.buf) then return end - local ft, on_detect = vim.filetype.match({ filename = args.match, buf = args.buf }) + local ft, on_detect = vim.filetype.match({ + -- The unexpanded file name is needed here. #27914 + -- Neither args.file nor args.match are guaranteed to be unexpanded. + filename = vim.fn.bufname(args.buf), + buf = args.buf, + }) if not ft then -- Generic configuration file used as fallback ft = require('vim.filetype.detect').conf(args.file, args.buf) diff --git a/runtime/ftplugin/arduino.vim b/runtime/ftplugin/arduino.vim new file mode 100644 index 0000000000..dae3dd83d3 --- /dev/null +++ b/runtime/ftplugin/arduino.vim @@ -0,0 +1,66 @@ +" Vim filetype plugin file +" Language: Arduino +" Maintainer: The Vim Project <https://github.com/vim/vim> +" Ken Takata <https://github.com/k-takata> +" Last Change: 2024 Apr 12 +" +" Most of the part was copied from c.vim. + +" Only do this when not done yet for this buffer +if exists("b:did_ftplugin") + finish +endif + +" Don't load another plugin for this buffer +let b:did_ftplugin = 1 + +" Using line continuation here. +let s:cpo_save = &cpo +set cpo-=C + +let b:undo_ftplugin = "setl fo< com< ofu< cms< def< inc<" + +if !exists("g:arduino_recommended_style") || g:arduino_recommended_style != 0 + " Use the default setting of Arduino IDE. + setlocal expandtab tabstop=2 softtabstop=2 shiftwidth=2 + let b:undo_ftplugin ..= " et< ts< sts< sw<" +endif + +" Set 'formatoptions' to break comment lines but not other lines, +" and insert the comment leader when hitting <CR> or using "o". +setlocal fo-=t fo+=croql + +" These options have the right value as default, but the user may have +" overruled that. +setlocal commentstring& define& include& + +" Set completion with CTRL-X CTRL-O to autoloaded function. +if exists('&ofu') + setlocal ofu=ccomplete#Complete +endif + +" Set 'comments' to format dashed lists in comments. +" Also include ///, used for Doxygen. +setlocal comments=sO:*\ -,mO:*\ \ ,exO:*/,s1:/*,mb:*,ex:*/,:///,:// + +" When the matchit plugin is loaded, this makes the % command skip parens and +" braces in comments properly. +if !exists("b:match_words") + let b:match_words = '^\s*#\s*if\(\|def\|ndef\)\>:^\s*#\s*elif\>:^\s*#\s*else\>:^\s*#\s*endif\>' + let b:match_skip = 's:comment\|string\|character\|special' + let b:undo_ftplugin ..= " | unlet! b:match_skip b:match_words" +endif + +" Win32 and GTK can filter files in the browse dialog +if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter") + let b:browsefilter = "Arduino Source Files (*.ino, *.pde)\t*.ino;*.pde\n" + if has("win32") + let b:browsefilter ..= "All Files (*.*)\t*\n" + else + let b:browsefilter ..= "All Files (*)\t*\n" + endif + let b:undo_ftplugin ..= " | unlet! b:browsefilter" +endif + +let &cpo = s:cpo_save +unlet s:cpo_save diff --git a/runtime/ftplugin/asm.vim b/runtime/ftplugin/asm.vim index f6a92d57d7..0ae1610394 100644 --- a/runtime/ftplugin/asm.vim +++ b/runtime/ftplugin/asm.vim @@ -1,13 +1,23 @@ " Vim filetype plugin file " Language: asm " Maintainer: Colin Caine <cmcaine at the common googlemail domain> -" Last Change: 23 May 2020 +" Last Change: 2020 May 23 " 2023 Aug 28 by Vim Project (undo_ftplugin) +" 2024 Apr 09 by Vim Project (add Matchit support) if exists("b:did_ftplugin") | finish | endif let b:did_ftplugin = 1 +setl include=^\\s*%\\s*include setl comments=:;,s1:/*,mb:*,ex:*/,:// setl commentstring=;%s -let b:undo_ftplugin = "setl commentstring< comments<" +let b:undo_ftplugin = "setl commentstring< comments< include<" + +" Matchit support +if !exists('b:match_words') + let b:match_skip = 's:comment\|string\|character\|special' + let b:match_words = '^\s*%\s*if\%(\|num\|idn\|nidn\)\>:^\s*%\s*elif\>:^\s*%\s*else\>:^\s*%\s*endif\>,^\s*%\s*macro\>:^\s*%\s*endmacro\>,^\s*%\s*rep\>:^\s*%\s*endrep\>' + let b:match_ignorecase = 1 + let b:undo_ftplugin ..= " | unlet! b:match_ignorecase b:match_words b:match_skip" +endif diff --git a/runtime/ftplugin/astro.vim b/runtime/ftplugin/astro.vim new file mode 100644 index 0000000000..0b0e03447b --- /dev/null +++ b/runtime/ftplugin/astro.vim @@ -0,0 +1,186 @@ +" Vim filetype plugin file +" Language: Astro +" Maintainer: Romain Lafourcade <romainlafourcade@gmail.com> +" Last Change: 2024 Apr 21 + +if exists("b:did_ftplugin") + finish +endif +let b:did_ftplugin = 1 + +let s:cpo_save = &cpo +set cpo-=C + +function! s:IdentifyScope(start, end) abort + let pos_start = searchpairpos(a:start, '', a:end, 'bnW') + let pos_end = searchpairpos(a:start, '', a:end, 'nW') + + return pos_start != [0, 0] + \ && pos_end != [0, 0] + \ && pos_start[0] != getpos('.')[1] +endfunction + +function! s:AstroComments() abort + if s:IdentifyScope('^---\n\s*\S', '^---\n\n') + \ || s:IdentifyScope('^\s*<script', '^\s*<\/script>') + " ECMAScript comments + setlocal comments=sO:*\ -,mO:*\ \ ,exO:*/,s1:/*,mb:*,ex:*/,:// + setlocal commentstring=//%s + + elseif s:IdentifyScope('^\s*<style', '^\s*<\/style>') + " CSS comments + setlocal comments=s1:/*,mb:*,ex:*/ + setlocal commentstring=/*%s*/ + + else + " HTML comments + setlocal comments=s:<!--,m:\ \ \ \ ,e:--> + setlocal commentstring=<!--%s--> + endif +endfunction + +" https://code.visualstudio.com/docs/languages/jsconfig +function! s:CollectPathsFromConfig() abort + let config_json = findfile('tsconfig.json', '.;') + + if empty(config_json) + let config_json = findfile('jsconfig.json', '.;') + + if empty(config_json) + return + endif + endif + + let paths_from_config = config_json + \ ->readfile() + \ ->filter({ _, val -> val =~ '^\s*[\[\]{}"0-9]' }) + \ ->join() + \ ->json_decode() + \ ->get('compilerOptions', {}) + \ ->get('paths', {}) + + if !empty(paths_from_config) + let b:astro_paths = paths_from_config + \ ->map({key, val -> [ + \ key->glob2regpat(), + \ val[0]->substitute('\/\*$', '', '') + \ ]}) + \ ->values() + endif + + let b:undo_ftplugin ..= " | unlet! b:astro_paths" +endfunction + +function! s:AstroInclude(filename) abort + let decorated_filename = a:filename + \ ->substitute("^", "@", "") + + let found_path = b: + \ ->get("astro_paths", []) + \ ->indexof({ key, val -> decorated_filename =~ val[0]}) + + if found_path != -1 + let alias = b:astro_paths[found_path][0] + let path = b:astro_paths[found_path][1] + \ ->substitute('\(\/\)*$', '/', '') + + return decorated_filename + \ ->substitute(alias, path, '') + endif + + return a:filename +endfunction + +let b:undo_ftplugin = "setlocal" + \ .. " formatoptions<" + \ .. " path<" + \ .. " suffixesadd<" + \ .. " matchpairs<" + \ .. " comments<" + \ .. " commentstring<" + \ .. " iskeyword<" + \ .. " define<" + \ .. " include<" + \ .. " includeexpr<" + +" Create self-resetting autocommand group +augroup Astro + autocmd! * <buffer> +augroup END + +" Set 'formatoptions' to break comment lines but not other lines, +" and insert the comment leader when hitting <CR> or using "o". +setlocal formatoptions-=t +setlocal formatoptions+=croql + +" Remove irrelevant part of 'path'. +setlocal path-=/usr/include + +" Seed 'path' with default directories for :find, gf, etc. +setlocal path+=src/** +setlocal path+=public/** + +" Help Vim find extension-less filenames +let &l:suffixesadd = + \ ".astro" + \ .. ",.js,.jsx,.es,.es6,.cjs,.mjs,.jsm" + \ .. ",.json" + \ .. ",.scss,.sass,.css" + \ .. ",.svelte" + \ .. ",.ts,.tsx,.d.ts" + \ .. ",.vue" + +" From $VIMRUNTIME/ftplugin/html.vim +setlocal matchpairs+=<:> + +" Matchit configuration +if exists("loaded_matchit") + let b:match_ignorecase = 0 + + " From $VIMRUNTIME/ftplugin/javascript.vim + let b:match_words = + \ '\<do\>:\<while\>,' + \ .. '<\@<=\([^ \t>/]\+\)\%(\s\+[^>]*\%([^/]>\|$\)\|>\|$\):<\@<=/\1>,' + \ .. '<\@<=\%([^ \t>/]\+\)\%(\s\+[^/>]*\|$\):/>' + + " From $VIMRUNTIME/ftplugin/html.vim + let b:match_words ..= + \ '<!--:-->,' + \ .. '<:>,' + \ .. '<\@<=[ou]l\>[^>]*\%(>\|$\):<\@<=li\>:<\@<=/[ou]l>,' + \ .. '<\@<=dl\>[^>]*\%(>\|$\):<\@<=d[td]\>:<\@<=/dl>,' + \ .. '<\@<=\([^/!][^ \t>]*\)[^>]*\%(>\|$\):<\@<=/\1>' + + let b:undo_ftplugin ..= " | unlet! b:match_ignorecase b:match_words" +endif + +" Change what constitutes a word, mainly useful for CSS/SASS +setlocal iskeyword+=- +setlocal iskeyword+=$ +setlocal iskeyword+=% + +" Define paths/aliases for module resolution +call s:CollectPathsFromConfig() + +" Find ESM imports +setlocal include=^\\s*\\(import\\\|import\\s\\+[^\/]\\+from\\)\\s\\+['\"] + +" Process aliases if file can't be found +setlocal includeexpr=s:AstroInclude(v:fname) + +" Set 'define' to a comprehensive value +" From $VIMRUNTIME/ftplugin/javascript.vim and +" $VIMRUNTIME/ftplugin/sass.vim +let &l:define = + \ '\(^\s*(*async\s\+function\|(*function\)' + \ .. '\|^\s*\(\*\|static\|async\|get\|set\|\i\+\.\)' + \ .. '\|^\s*\(\ze\i\+\)\(([^)]*).*{$\|\s*[:=,]\)' + + +" Set &comments and &commentstring according to current scope +autocmd Astro CursorMoved <buffer> call s:AstroComments() + +let &cpo = s:cpo_save +unlet s:cpo_save + +" vim: textwidth=78 tabstop=8 shiftwidth=4 softtabstop=4 expandtab diff --git a/runtime/ftplugin/bp.vim b/runtime/ftplugin/bp.vim new file mode 100644 index 0000000000..5ddebe5233 --- /dev/null +++ b/runtime/ftplugin/bp.vim @@ -0,0 +1,14 @@ +" Blueprint build system filetype plugin file +" Language: Blueprint +" Maintainer: Bruno BELANYI <bruno.vim@belanyi.fr> +" Latest Revision: 2024-04-19 + +if exists("b:did_ftplugin") + finish +endif +let b:did_ftplugin = 1 + +setlocal comments=b://,s1:/*,mb:*,ex:*/ +setlocal commentstring=//\ %s + +let b:undo_ftplugin = "setlocal comments< commentstring<" diff --git a/runtime/ftplugin/cgdbrc.vim b/runtime/ftplugin/cgdbrc.vim new file mode 100644 index 0000000000..46cf135c5c --- /dev/null +++ b/runtime/ftplugin/cgdbrc.vim @@ -0,0 +1,21 @@ +" Vim filetype plugin file +" Language: cgdbrc +" Maintainer: Wu, Zhenyu <wuzhenyu@ustc.edu> +" Documentation: https://cgdb.github.io/docs/Configuring-CGDB.html +" Latest Revision: 2024-04-09 + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +let s:save_cpoptions = &cpoptions +set cpoptions&vim + +let b:undo_ftplugin = 'setl com< cms<' + +setlocal commentstring=#%s +setlocal comments=:# + +let &cpoptions = s:save_cpoptions +unlet s:save_cpoptions diff --git a/runtime/ftplugin/checkhealth.vim b/runtime/ftplugin/checkhealth.vim index 4b530e6f7c..62a1970b4a 100644 --- a/runtime/ftplugin/checkhealth.vim +++ b/runtime/ftplugin/checkhealth.vim @@ -9,9 +9,6 @@ endif runtime! ftplugin/help.vim setlocal wrap breakindent linebreak -setlocal foldexpr=getline(v:lnum-1)=~'^=\\{78}$'?'>1':(getline(v:lnum)=~'^=\\{78}'?0:'=') -setlocal foldmethod=expr -setlocal foldtext=v:lua.require('vim.health').foldtext() let &l:iskeyword='!-~,^*,^|,^",192-255' if exists("b:undo_ftplugin") diff --git a/runtime/ftplugin/cmake.vim b/runtime/ftplugin/cmake.vim index 94c007629b..9fcf87a759 100644 --- a/runtime/ftplugin/cmake.vim +++ b/runtime/ftplugin/cmake.vim @@ -2,6 +2,7 @@ " Language: CMake " Maintainer: Keith Smiley <keithbsmiley@gmail.com> " Last Change: 2018 Aug 30 +" 2024 Apr 20 - add include and suffixadd (Vim Project) " Only do this when not done yet for this buffer if exists("b:did_ftplugin") @@ -15,7 +16,7 @@ set cpo&vim " Don't load another plugin for this buffer let b:did_ftplugin = 1 -let b:undo_ftplugin = "setl commentstring<" +let b:undo_ftplugin = "setl inc< sua< commentstring<" if exists('loaded_matchit') let b:match_words = '\<if\>:\<elseif\>\|\<else\>:\<endif\>' @@ -27,6 +28,8 @@ if exists('loaded_matchit') let b:undo_ftplugin .= "| unlet b:match_words" endif +setlocal include=\s*include +setlocal suffixesadd=.cmake,-config.cmake setlocal commentstring=#\ %s " restore 'cpo' and clean up buffer variable diff --git a/runtime/ftplugin/dart.vim b/runtime/ftplugin/dart.vim new file mode 100644 index 0000000000..42c90c212f --- /dev/null +++ b/runtime/ftplugin/dart.vim @@ -0,0 +1,15 @@ +" Vim filetype plugin +" Language: dart +" Maintainer: Riley Bruins <ribru17@gmail.com> +" Last Change: 2024 May 18 + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +" Set 'comments' to format dashed lists in comments. +" Also include ///, used for Doxygen. +setl comments=sO:*\ -,mO:*\ \ ,exO:*/,s1:/*,mb:*,ex:*/,:///,:// commentstring=//\ %s + +let b:undo_ftplugin = 'setl com< cms<' diff --git a/runtime/ftplugin/deb822sources.vim b/runtime/ftplugin/deb822sources.vim new file mode 100644 index 0000000000..4936f42bf9 --- /dev/null +++ b/runtime/ftplugin/deb822sources.vim @@ -0,0 +1,16 @@ +" Language: Debian sources.list +" Maintainer: Debian Vim Maintainers <team+vim@tracker.debian.org> +" Last Change: 2024 Mar 20 +" License: Vim License +" URL: https://salsa.debian.org/vim-team/vim-debian/blob/main/ftplugin/deb822sources.vim + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin=1 + +setlocal comments=:# +setlocal commentstring=#%s +setlocal formatoptions-=t + +let b:undo_ftplugin = 'setlocal comments< commentstring< formatoptions<' diff --git a/runtime/ftplugin/dts.vim b/runtime/ftplugin/dts.vim new file mode 100644 index 0000000000..42e38338b7 --- /dev/null +++ b/runtime/ftplugin/dts.vim @@ -0,0 +1,16 @@ +" Vim filetype plugin file +" Language: dts/dtsi (device tree files) +" Maintainer: Wu, Zhenyu <wuzhenyu@ustc.edu> +" Latest Revision: 2024 Apr 12 + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +let b:undo_ftplugin = 'setl inc< cms< com<' + +setlocal include=^\\%(#include\\\|/include/\\) +" same as C +setlocal commentstring& +setlocal comments=sO:*\ -,mO:*\ \ ,exO:*/,s1:/*,mb:*,ex:*/,:///,:// diff --git a/runtime/ftplugin/gdb.vim b/runtime/ftplugin/gdb.vim index 2473b13af0..7c10633be4 100644 --- a/runtime/ftplugin/gdb.vim +++ b/runtime/ftplugin/gdb.vim @@ -1,12 +1,20 @@ " Vim filetype plugin file " Language: gdb " Maintainer: Michaël Peeters <NOSPAMm.vim@noekeon.org> -" Last Changed: 26 Oct 2017 +" Last Changed: 2017-10-26 +" 2024-04-10: - add Matchit support (by Vim Project) if exists("b:did_ftplugin") | finish | endif let b:did_ftplugin = 1 setlocal commentstring=#%s +setlocal include=^\\s*source " Undo the stuff we changed. -let b:undo_ftplugin = "setlocal cms<" +let b:undo_ftplugin = "setlocal cms< include<" + +" Matchit support +if !exists('b:match_words') + let b:match_words = '\<\%(if\|while\|define\|document\)\>:\<else\>:\<end\>' + let b:undo_ftplugin ..= " | unlet! b:match_words" +endif diff --git a/runtime/ftplugin/graphql.vim b/runtime/ftplugin/graphql.vim new file mode 100644 index 0000000000..56f6e36e20 --- /dev/null +++ b/runtime/ftplugin/graphql.vim @@ -0,0 +1,13 @@ +" Vim filetype plugin +" Language: graphql +" Maintainer: Riley Bruins <ribru17@gmail.com> +" Last Change: 2024 May 18 + +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/hyprlang.vim b/runtime/ftplugin/hyprlang.vim new file mode 100644 index 0000000000..5c186c3c5e --- /dev/null +++ b/runtime/ftplugin/hyprlang.vim @@ -0,0 +1,13 @@ +" Vim filetype plugin +" Language: hyprlang +" Maintainer: ribru17 <ribru17@gmail.com> +" Last Change: 2024 May 18 + +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/java.vim b/runtime/ftplugin/java.vim index bb7e7cd72c..fa2b61075f 100644 --- a/runtime/ftplugin/java.vim +++ b/runtime/ftplugin/java.vim @@ -1,10 +1,9 @@ " Vim filetype plugin file " Language: Java -" -" This runtime file is looking for a new maintainer. -" -" Former maintainer: Dan Sharp -" Last Change: 2012 Mar 11 +" Maintainer: Aliaksei Budavei <0x000c70 AT gmail DOT com> +" Former Maintainer: Dan Sharp +" Repository: https://github.com/zzzyxwvut/java-vim.git +" Last Change: 2024 Apr 18 " 2024 Jan 14 by Vim Project (browsefilter) if exists("b:did_ftplugin") | finish | endif @@ -23,8 +22,36 @@ set suffixes+=.class " name to / and append .java to the name, then search the path. setlocal includeexpr=substitute(v:fname,'\\.','/','g') setlocal suffixesadd=.java -if exists("g:ftplugin_java_source_path") - let &l:path=g:ftplugin_java_source_path . ',' . &l:path + +" Clean up in case this file is sourced again. +unlet! s:zip_func_upgradable + +" Documented in ":help ft-java-plugin". +if exists("g:ftplugin_java_source_path") && + \ type(g:ftplugin_java_source_path) == type("") + if filereadable(g:ftplugin_java_source_path) + if exists("#zip") && + \ g:ftplugin_java_source_path =~# '.\.\%(jar\|zip\)$' + if !exists("s:zip_files") + let s:zip_files = {} + endif + + let s:zip_files[bufnr('%')] = g:ftplugin_java_source_path + let s:zip_files[0] = g:ftplugin_java_source_path + let s:zip_func_upgradable = 1 + + function! JavaFileTypeZipFile() abort + let @/ = substitute(v:fname, '\.', '\\/', 'g') . '.java' + return get(s:zip_files, bufnr('%'), s:zip_files[0]) + endfunction + + " E120 for "inex=s:JavaFileTypeZipFile()" before v8.2.3900. + setlocal includeexpr=JavaFileTypeZipFile() + setlocal suffixesadd< + endif + else + let &l:path = g:ftplugin_java_source_path . ',' . &l:path + endif endif " Set 'formatoptions' to break comment lines but not other lines, @@ -53,6 +80,25 @@ let b:undo_ftplugin = "setlocal suffixes< suffixesadd<" . \ " formatoptions< comments< commentstring< path< includeexpr<" . \ " | unlet! b:browsefilter" +" See ":help vim9-mix". +if !has("vim9script") + let &cpo = s:save_cpo + unlet s:save_cpo + finish +endif + +if exists("s:zip_func_upgradable") + delfunction! JavaFileTypeZipFile + + def! s:JavaFileTypeZipFile(): string + @/ = substitute(v:fname, '\.', '\\/', 'g') .. '.java' + return get(zip_files, bufnr('%'), zip_files[0]) + enddef + + setlocal includeexpr=s:JavaFileTypeZipFile() + setlocal suffixesadd< +endif + " Restore the saved compatibility options. let &cpo = s:save_cpo unlet s:save_cpo diff --git a/runtime/ftplugin/jj.vim b/runtime/ftplugin/jj.vim new file mode 100644 index 0000000000..cc5d700a30 --- /dev/null +++ b/runtime/ftplugin/jj.vim @@ -0,0 +1,19 @@ +" Vim filetype plugin +" Language: jj description +" Maintainer: Gregory Anders <greg@gpanders.com> +" Last Change: 2024 May 8 + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +" Use the same formatoptions and textwidth as the gitcommit ftplugin +setlocal nomodeline formatoptions+=tl textwidth=72 +setlocal formatoptions-=c formatoptions-=r formatoptions-=o formatoptions-=q formatoptions+=n +setlocal formatlistpat=^\\s*\\d\\+[\\]:.)}]\\s\\+\\\|^\\s*[-*+]\\s\\+ + +setlocal comments=b:JJ: +setlocal commentstring=JJ:\ %s + +let b:undo_ftplugin = 'setl modeline< formatoptions< textwidth< formatlistpat< comments< commentstring<' diff --git a/runtime/ftplugin/jq.vim b/runtime/ftplugin/jq.vim new file mode 100644 index 0000000000..88958e80dd --- /dev/null +++ b/runtime/ftplugin/jq.vim @@ -0,0 +1,16 @@ +" Vim compiler file +" Language: jq +" Maintainer: Vito <vito.blog@gmail.com> +" Last Change: 2024 Apr 29 +" Upstream: https://github.com/vito-c/jq.vim + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +setlocal include=^\\s*\\%(import\\\|include\\) +setlocal commentstring=#%s +compiler jq + +let b:undo_ftplugin = 'setl commentstring< include<' diff --git a/runtime/ftplugin/kconfig.vim b/runtime/ftplugin/kconfig.vim index 940ba7427f..767490701b 100644 --- a/runtime/ftplugin/kconfig.vim +++ b/runtime/ftplugin/kconfig.vim @@ -1,9 +1,9 @@ " Vim filetype plugin file " Vim syntax file -" Maintainer: Christian Brabandt <cb@256bit.org> -" Previous Maintainer: Nikolai Weibull <now@bitwi.se> -" Latest Revision: 2015-05-29 -" License: Vim (see :h license) +" Maintainer: Christian Brabandt <cb@256bit.org> +" Previous Maintainer: Nikolai Weibull <now@bitwi.se> +" Latest Revision: 2024-04-12 +" License: Vim (see :h license) " Repository: https://github.com/chrisbra/vim-kconfig if exists("b:did_ftplugin") @@ -11,17 +11,12 @@ if exists("b:did_ftplugin") endif let b:did_ftplugin = 1 -let s:cpo_save = &cpo -set cpo&vim - -let b:undo_ftplugin = "setl com< cms< fo<" +let b:undo_ftplugin = "setl inc< com< cms< fo<" +setlocal include=source\\s\\+ setlocal comments=:# commentstring=#\ %s formatoptions-=t formatoptions+=croql " For matchit.vim if exists("loaded_matchit") let b:match_words = '^\<menu\>:\<endmenu\>,^\<if\>:\<endif\>,^\<choice\>:\<endchoice\>' endif - -let &cpo = s:cpo_save -unlet s:cpo_save diff --git a/runtime/ftplugin/man.vim b/runtime/ftplugin/man.vim index 277ce3c0b3..fdeaae4c3f 100644 --- a/runtime/ftplugin/man.vim +++ b/runtime/ftplugin/man.vim @@ -24,7 +24,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(b:, 'pager') + 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 diff --git a/runtime/ftplugin/nim.vim b/runtime/ftplugin/nim.vim new file mode 100644 index 0000000000..4ab8b7b536 --- /dev/null +++ b/runtime/ftplugin/nim.vim @@ -0,0 +1,13 @@ +" Vim filetype plugin +" Language: nim +" Maintainer: Riley Bruins <ribru17@gmail.com> +" Last Change: 2024 May 19 + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +setl comments=exO:]#,fs1:#[,mb:*,ex:]#,:# commentstring=#\ %s + +let b:undo_ftplugin = 'setl com< cms<' diff --git a/runtime/ftplugin/ondir.vim b/runtime/ftplugin/ondir.vim new file mode 100644 index 0000000000..0854578c91 --- /dev/null +++ b/runtime/ftplugin/ondir.vim @@ -0,0 +1,18 @@ +" Vim filetype plugin file +" Language: ondir <https://github.com/alecthomas/ondir> +" Maintainer: Jon Parise <jon@indelible.org> + +if exists('b:did_ftplugin') + finish +endif + +let s:cpo_save = &cpoptions + +setlocal comments=:# commentstring=#\ %s + +let b:undo_ftplugin = 'setl comments< commentstring<' + +let &cpoptions = s:cpo_save +unlet s:cpo_save + +" vim: et ts=4 sw=2 sts=2: diff --git a/runtime/ftplugin/prisma.vim b/runtime/ftplugin/prisma.vim new file mode 100644 index 0000000000..8b733da64c --- /dev/null +++ b/runtime/ftplugin/prisma.vim @@ -0,0 +1,13 @@ +" Vim filetype plugin +" Language: prisma +" Maintainer: Riley Bruins <ribru17@gmail.com> +" Last Change: 2024 May 19 + +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/purescript.vim b/runtime/ftplugin/purescript.vim new file mode 100644 index 0000000000..b3300bb324 --- /dev/null +++ b/runtime/ftplugin/purescript.vim @@ -0,0 +1,14 @@ +" Vim filetype plugin +" Language: purescript +" Maintainer: Riley Bruins <ribru17@gmail.com> +" Last Change: 2024 May 19 + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +setl comments=s1f:{-,mb:\ ,ex:-},:--\ \|,:-- +setl commentstring=--\ %s + +let b:undo_ftplugin = 'setl com< cms<' diff --git a/runtime/ftplugin/python.vim b/runtime/ftplugin/python.vim index 79acaa6f08..c000296726 100644 --- a/runtime/ftplugin/python.vim +++ b/runtime/ftplugin/python.vim @@ -1,10 +1,9 @@ " Vim filetype plugin file " Language: python -" Maintainer: Tom Picton <tom@tompicton.co.uk> +" Maintainer: Tom Picton <tom@tompicton.com> " Previous Maintainer: James Sully <sullyj3@gmail.com> " Previous Maintainer: Johannes Zellner <johannes@zellner.org> -" Last Change: Mon, 5 October 2020 -" 2024 Jan 14 by Vim Project (browsefilter) +" Last Change: 2024/05/13 " https://github.com/tpict/vim-ftplugin-python if exists("b:did_ftplugin") | finish | endif @@ -15,7 +14,7 @@ set cpo&vim setlocal cinkeys-=0# setlocal indentkeys-=0# setlocal include=^\\s*\\(from\\\|import\\) -setlocal define=^\\s*\\(def\\\|class\\) +setlocal define=^\\s*\\(\\(async\\s\\+\\)\\?def\\\|class\\) " For imports with leading .., append / and replace additional .s with ../ let b:grandparent_match = '^\(.\.\)\(\.*\)' @@ -57,14 +56,14 @@ let b:next_end='\v\S\n*(%$\|^(\s*\n*)*(class\|def\|async def)\|^\S)' let b:prev_end='\v\S\n*(^(\s*\n*)*(class\|def\|async def)\|^\S)' if !exists('g:no_plugin_maps') && !exists('g:no_python_maps') - execute "nnoremap <silent> <buffer> ]] :call <SID>Python_jump('n', '". b:next_toplevel."', 'W', v:count1)<cr>" - execute "nnoremap <silent> <buffer> [[ :call <SID>Python_jump('n', '". b:prev_toplevel."', 'Wb', v:count1)<cr>" - execute "nnoremap <silent> <buffer> ][ :call <SID>Python_jump('n', '". b:next_endtoplevel."', 'W', v:count1, 0)<cr>" - execute "nnoremap <silent> <buffer> [] :call <SID>Python_jump('n', '". b:prev_endtoplevel."', 'Wb', v:count1, 0)<cr>" - execute "nnoremap <silent> <buffer> ]m :call <SID>Python_jump('n', '". b:next."', 'W', v:count1)<cr>" - execute "nnoremap <silent> <buffer> [m :call <SID>Python_jump('n', '". b:prev."', 'Wb', v:count1)<cr>" - execute "nnoremap <silent> <buffer> ]M :call <SID>Python_jump('n', '". b:next_end."', 'W', v:count1, 0)<cr>" - execute "nnoremap <silent> <buffer> [M :call <SID>Python_jump('n', '". b:prev_end."', 'Wb', v:count1, 0)<cr>" + execute "nnoremap <silent> <buffer> ]] :<C-U>call <SID>Python_jump('n', '". b:next_toplevel."', 'W', v:count1)<cr>" + execute "nnoremap <silent> <buffer> [[ :<C-U>call <SID>Python_jump('n', '". b:prev_toplevel."', 'Wb', v:count1)<cr>" + execute "nnoremap <silent> <buffer> ][ :<C-U>call <SID>Python_jump('n', '". b:next_endtoplevel."', 'W', v:count1, 0)<cr>" + execute "nnoremap <silent> <buffer> [] :<C-U>call <SID>Python_jump('n', '". b:prev_endtoplevel."', 'Wb', v:count1, 0)<cr>" + execute "nnoremap <silent> <buffer> ]m :<C-U>call <SID>Python_jump('n', '". b:next."', 'W', v:count1)<cr>" + execute "nnoremap <silent> <buffer> [m :<C-U>call <SID>Python_jump('n', '". b:prev."', 'Wb', v:count1)<cr>" + execute "nnoremap <silent> <buffer> ]M :<C-U>call <SID>Python_jump('n', '". b:next_end."', 'W', v:count1, 0)<cr>" + execute "nnoremap <silent> <buffer> [M :<C-U>call <SID>Python_jump('n', '". b:prev_end."', 'Wb', v:count1, 0)<cr>" execute "onoremap <silent> <buffer> ]] :call <SID>Python_jump('o', '". b:next_toplevel."', 'W', v:count1)<cr>" execute "onoremap <silent> <buffer> [[ :call <SID>Python_jump('o', '". b:prev_toplevel."', 'Wb', v:count1)<cr>" diff --git a/runtime/ftplugin/requirements.vim b/runtime/ftplugin/requirements.vim new file mode 100644 index 0000000000..fcfc1ac269 --- /dev/null +++ b/runtime/ftplugin/requirements.vim @@ -0,0 +1,43 @@ +" the Requirements File Format syntax support for Vim +" Version: 1.8.0 +" Author: raimon <raimon49@hotmail.com> +" Upstream: https://github.com/raimon49/requirements.txt.vim +" License: MIT LICENSE +" The MIT License (MIT) +" +" Copyright (c) 2015 raimon +" +" Permission is hereby granted, free of charge, to any person obtaining a copy +" of this software and associated documentation files (the "Software"), to deal +" in the Software without restriction, including without limitation the rights +" to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +" copies of the Software, and to permit persons to whom the Software is +" furnished to do so, subject to the following conditions: +" +" The above copyright notice and this permission notice shall be included in all +" copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +" OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +" SOFTWARE. +if exists("b:did_ftplugin") + finish +endif +let b:did_ftplugin = 1 + +let s:save_cpoptions = &cpoptions +set cpoptions&vim + +let b:undo_ftplugin = "setl iskeyword< commentstring<" +" pip options contain "-" +setlocal iskeyword+=- +setlocal commentstring=#\ %s +compiler pip_compile + +let &cpoptions = s:save_cpoptions +unlet s:save_cpoptions +" vim: et sw=4 ts=4 sts=4: diff --git a/runtime/ftplugin/rescript.vim b/runtime/ftplugin/rescript.vim new file mode 100644 index 0000000000..dd94c68799 --- /dev/null +++ b/runtime/ftplugin/rescript.vim @@ -0,0 +1,13 @@ +" Vim filetype plugin +" Language: rescript +" Maintainer: Riley Bruins <ribru17@gmail.com> +" Last Change: 2024 May 21 + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +setl comments=sO:*\ -,mO:*\ \ ,exO:*/,s1:/*,mb:*,ex:*/,:// commentstring=//\ %s + +let b:undo_ftplugin = 'setl com< cms<' diff --git a/runtime/ftplugin/roc.vim b/runtime/ftplugin/roc.vim new file mode 100644 index 0000000000..c66510874d --- /dev/null +++ b/runtime/ftplugin/roc.vim @@ -0,0 +1,14 @@ +" Roc filetype plugin file +" Language: Roc +" Maintainer: nat-418 <93013864+nat-418@users.noreply.github.com> +" Latest Revision: 2024-04-5 + +if exists("b:did_ftplugin") + finish +endif +let b:did_ftplugin = 1 + +setlocal comments=:##,:# +setlocal commentstring=#\ %s + +let b:undo_ftplugin = "setl com< cms<" diff --git a/runtime/ftplugin/rust.vim b/runtime/ftplugin/rust.vim index 7f1a86ea95..fb15b444d0 100644 --- a/runtime/ftplugin/rust.vim +++ b/runtime/ftplugin/rust.vim @@ -1,7 +1,7 @@ " Language: Rust " Description: Vim ftplugin for Rust " Maintainer: Chris Morgan <me@chrismorgan.info> -" Last Change: 2023-09-11 +" Last Change: 2024-03-17 " For bugs, patches and license go to https://github.com/rust-lang/rust.vim if exists("b:did_ftplugin") @@ -94,14 +94,15 @@ if has('conceal') && get(g:, 'rust_conceal', 0) endif " Motion Commands {{{1 - -" Bind motion commands to support hanging indents -nnoremap <silent> <buffer> [[ :call rust#Jump('n', 'Back')<CR> -nnoremap <silent> <buffer> ]] :call rust#Jump('n', 'Forward')<CR> -xnoremap <silent> <buffer> [[ :call rust#Jump('v', 'Back')<CR> -xnoremap <silent> <buffer> ]] :call rust#Jump('v', 'Forward')<CR> -onoremap <silent> <buffer> [[ :call rust#Jump('o', 'Back')<CR> -onoremap <silent> <buffer> ]] :call rust#Jump('o', 'Forward')<CR> +if !exists("g:no_plugin_maps") && !exists("g:no_rust_maps") + " Bind motion commands to support hanging indents + nnoremap <silent> <buffer> [[ :call rust#Jump('n', 'Back')<CR> + nnoremap <silent> <buffer> ]] :call rust#Jump('n', 'Forward')<CR> + xnoremap <silent> <buffer> [[ :call rust#Jump('v', 'Back')<CR> + xnoremap <silent> <buffer> ]] :call rust#Jump('v', 'Forward')<CR> + onoremap <silent> <buffer> [[ :call rust#Jump('o', 'Back')<CR> + onoremap <silent> <buffer> ]] :call rust#Jump('o', 'Forward')<CR> +endif " Commands {{{1 @@ -176,12 +177,12 @@ let b:undo_ftplugin = " \|delcommand -buffer RustInfoToClipboard \|delcommand -buffer RustInfoToFile \|delcommand -buffer RustTest - \|nunmap <buffer> [[ - \|nunmap <buffer> ]] - \|xunmap <buffer> [[ - \|xunmap <buffer> ]] - \|ounmap <buffer> [[ - \|ounmap <buffer> ]] + \|silent! nunmap <buffer> [[ + \|silent! nunmap <buffer> ]] + \|silent! xunmap <buffer> [[ + \|silent! xunmap <buffer> ]] + \|silent! ounmap <buffer> [[ + \|silent! ounmap <buffer> ]] \|setlocal matchpairs-=<:> \|unlet b:match_skip \" diff --git a/runtime/ftplugin/sh.vim b/runtime/ftplugin/sh.vim index 6d2093bf83..c47aa520e9 100644 --- a/runtime/ftplugin/sh.vim +++ b/runtime/ftplugin/sh.vim @@ -4,7 +4,7 @@ " Previous Maintainer: Dan Sharp " Contributor: Enno Nagel <ennonagel+vim@gmail.com> " Eisuke Kawashima -" Last Change: 2024 Feb 27 +" Last Change: 2024 May 06 by Vim Project (MANPAGER=) if exists("b:did_ftplugin") finish @@ -46,11 +46,11 @@ endif if get(b:, "is_bash", 0) if !has("gui_running") && executable("less") - command! -buffer -nargs=1 ShKeywordPrg silent exe '!bash -c "{ help "<args>" 2>/dev/null || man "<args>"; } | LESS= less"' | redraw! + command! -buffer -nargs=1 ShKeywordPrg silent exe '!bash -c "{ help "<args>" 2>/dev/null || MANPAGER= man "<args>"; } | LESS= less"' | redraw! elseif has("terminal") command! -buffer -nargs=1 ShKeywordPrg silent exe ':term bash -c "help "<args>" 2>/dev/null || man "<args>""' else - command! -buffer -nargs=1 ShKeywordPrg echo system('bash -c "help <args>" 2>/dev/null || man "<args>"') + command! -buffer -nargs=1 ShKeywordPrg echo system('bash -c "help <args>" 2>/dev/null || MANPAGER= man "<args>"') endif setlocal keywordprg=:ShKeywordPrg let b:undo_ftplugin ..= " | setl kp< | sil! delc -buffer ShKeywordPrg" diff --git a/runtime/ftplugin/slint.vim b/runtime/ftplugin/slint.vim new file mode 100644 index 0000000000..ac8057f39d --- /dev/null +++ b/runtime/ftplugin/slint.vim @@ -0,0 +1,15 @@ +" Vim filetype plugin +" Language: slint +" Maintainer: Riley Bruins <ribru17@gmail.com> +" Last Change: 2024 May 19 + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +" Set 'comments' to format dashed lists in comments. +" Also include ///, used for Doxygen. +setl comments=sO:*\ -,mO:*\ \ ,exO:*/,s1:/*,mb:*,ex:*/,:///,:// commentstring=//\ %s + +let b:undo_ftplugin = 'setl com< cms<' diff --git a/runtime/ftplugin/sql.vim b/runtime/ftplugin/sql.vim index c85232f51b..61b7e67255 100644 --- a/runtime/ftplugin/sql.vim +++ b/runtime/ftplugin/sql.vim @@ -4,6 +4,7 @@ " Maintainer: David Fishburn <dfishburn dot vim at gmail dot com> " Last Change: 2017 Mar 07 " 2024 Jan 14 by Vim Project (browsefilter) +" 2024 May 18 by Vim Project (set comment options) " Download: http://vim.sourceforge.net/script.php?script_id=454 " For more details please use: @@ -105,6 +106,8 @@ set cpo&vim setlocal formatoptions-=t setlocal formatoptions+=c +setlocal comments=:-- commentstring=--\ %s + " Functions/Commands to allow the user to change SQL syntax dialects " through the use of :SQLSetType <tab> for completion. " This works with both Vim 6 and 7. @@ -266,7 +269,7 @@ if exists("b:did_ftplugin") && exists("b:current_ftplugin") && b:current_ftplugi finish endif -let b:undo_ftplugin = "setl comments< formatoptions< define< omnifunc<" . +let b:undo_ftplugin = "setl comments< commentstring< formatoptions< define< omnifunc<" . \ " | unlet! b:browsefilter b:match_words" " Don't load another plugin for this buffer diff --git a/runtime/ftplugin/sshdconfig.vim b/runtime/ftplugin/sshdconfig.vim new file mode 100644 index 0000000000..3d394549bc --- /dev/null +++ b/runtime/ftplugin/sshdconfig.vim @@ -0,0 +1,10 @@ +" Vim filetype plugin file +" Language: OpenSSH server configuration file +" Maintainer: Yinzuo Jiang <jiangyinzuo@foxmail.com> +" Latest Revision: 2024-05-17 + +if exists("b:did_ftplugin") + finish +endif + +runtime! ftplugin/conf.vim diff --git a/runtime/ftplugin/stylus.vim b/runtime/ftplugin/stylus.vim new file mode 100644 index 0000000000..1c5f14eebe --- /dev/null +++ b/runtime/ftplugin/stylus.vim @@ -0,0 +1,54 @@ +" Vim filetype plugin +" Language: Stylus +" Maintainer: Marc Harter +" Credits: Tim Pope + +" Only do this when not done yet for this buffer +if exists("b:did_ftplugin") + finish +endif + +let s:save_cpo = &cpo +set cpo-=C + +" Define some defaults in case the included ftplugins don't set them. +let s:undo_ftplugin = "" +let s:browsefilter = "All Files (*.*)\t*.*\n" + +runtime! ftplugin/html.vim ftplugin/html_*.vim ftplugin/html/*.vim +unlet! b:did_ftplugin + +" Override our defaults if these were set by an included ftplugin. +if exists("b:undo_ftplugin") + let s:undo_ftplugin = b:undo_ftplugin + unlet b:undo_ftplugin +endif +if exists("b:browsefilter") + let s:browsefilter = b:browsefilter + unlet b:browsefilter +endif + +" Change the browse dialog on Win32 to show mainly Styl-related files +if has("gui_win32") + let b:browsefilter="Stylus Files (*.styl)\t*.styl\n" . s:browsefilter +endif + +setlocal comments= commentstring=//\ %s +setlocal suffixesadd=.styl +setlocal formatoptions+=r + +" Add '-' and '#' to the what makes up a keyword. +" This means that 'e' and 'w' work properly now, for properties +" and valid variable names. +setl iskeyword+=#,- + +" Add a Stylus command (to see if it's valid) +command -buffer Stylus !clear; cat % |stylus + + +let b:undo_ftplugin = "setl sua< isk< cms< com< fo< " + \ " | unlet! b:browsefilter b:match_words | " . s:undo_ftplugin + +let &cpo = s:save_cpo + +" vim:set sw=2: diff --git a/runtime/ftplugin/tutor.vim b/runtime/ftplugin/tutor.vim index 30783d9799..45ee582cba 100644 --- a/runtime/ftplugin/tutor.vim +++ b/runtime/ftplugin/tutor.vim @@ -19,7 +19,7 @@ setlocal noundofile setlocal keywordprg=:help setlocal iskeyword=@,-,_ -" The user will have to enable the folds himself, but we provide the foldexpr +" The user will have to enable the folds themself, but we provide the foldexpr " function. setlocal foldmethod=manual setlocal foldexpr=tutor#TutorFolds() diff --git a/runtime/ftplugin/typst.vim b/runtime/ftplugin/typst.vim new file mode 100644 index 0000000000..c2d7811ace --- /dev/null +++ b/runtime/ftplugin/typst.vim @@ -0,0 +1,14 @@ +" Vim filetype plugin +" Language: typst +" Maintainer: Riley Bruins <ribru17@gmail.com> +" Last Change: 2024 May 19 + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +setlocal comments=sO:*\ -,mO:*\ \ ,exO:*/,s1:/*,mb:*,ex:*/,:// +setlocal commentstring=//\ %s + +let b:undo_ftplugin = 'setl com< cms<' diff --git a/runtime/ftplugin/uci.vim b/runtime/ftplugin/uci.vim new file mode 100644 index 0000000000..984dab6c5f --- /dev/null +++ b/runtime/ftplugin/uci.vim @@ -0,0 +1,21 @@ +" Vim ftplugin file +" Language: OpenWrt Unified Configuration Interface +" Maintainer: Colin Caine <complaints@cmcaine.co.uk> +" Upstream: https://github.com/cmcaine/vim-uci +" Last Change: 2024 Apr 17 +" +" For more information on uci, see https://openwrt.org/docs/guide-user/base-system/uci + +if exists("b:did_ftplugin") + finish +endif +let b:did_ftplugin = 1 + +" UCI files are indented with tabs. +setl noexpandtab +setl shiftwidth=0 +setl softtabstop=0 + +setl commentstring=#\ %s + +let b:undo_ftplugin = "setlocal et< cms< sts< sw<" diff --git a/runtime/ftplugin/v.vim b/runtime/ftplugin/v.vim new file mode 100644 index 0000000000..4d4f60d797 --- /dev/null +++ b/runtime/ftplugin/v.vim @@ -0,0 +1,15 @@ +" Vim filetype plugin +" Language: v +" Maintainer: Riley Bruins <ribru17@gmail.com> +" Last Change: 2024 May 19 + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +" Set 'comments' to format dashed lists in comments. +" Also include ///, used for Doxygen. +setl comments=sO:*\ -,mO:*\ \ ,exO:*/,s1:/*,mb:*,ex:*/,:///,:// commentstring=//\ %s + +let b:undo_ftplugin = 'setl com< cms<' diff --git a/runtime/ftplugin/verilog.vim b/runtime/ftplugin/verilog.vim index 83c3754e05..c20be25865 100644 --- a/runtime/ftplugin/verilog.vim +++ b/runtime/ftplugin/verilog.vim @@ -3,6 +3,7 @@ " Maintainer: Chih-Tsun Huang <cthuang@cs.nthu.edu.tw> " Last Change: 2017 Aug 25 by Chih-Tsun Huang " 2024 Jan 14 by Vim Project (browsefilter) +" 2024 May 20 by Riley Bruins <ribru17@gmail.com> (commentstring) " URL: http://www.cs.nthu.edu.tw/~cthuang/vim/ftplugin/verilog.vim " " Credits: @@ -22,7 +23,7 @@ let s:cpo_save = &cpo set cpo&vim " Undo the plugin effect -let b:undo_ftplugin = "setlocal fo< com< tw<" +let b:undo_ftplugin = "setlocal fo< com< tw< cms<" \ . "| unlet! b:browsefilter b:match_ignorecase b:match_words" " Set 'formatoptions' to break comment lines but not other lines, @@ -31,6 +32,7 @@ setlocal fo-=t fo+=croqlm1 " Set 'comments' to format dashed lists in comments. setlocal comments=sO:*\ -,mO:*\ \ ,exO:*/,s1:/*,mb:*,ex:*/,:// +setlocal commentstring=//\ %s " Format comments to be up to 78 characters long if &textwidth == 0 diff --git a/runtime/ftplugin/vim.vim b/runtime/ftplugin/vim.vim index f5dae0f94e..5c99df7f5a 100644 --- a/runtime/ftplugin/vim.vim +++ b/runtime/ftplugin/vim.vim @@ -1,7 +1,7 @@ " Vim filetype plugin -" Language: Vim -" Maintainer: The Vim Project <https://github.com/vim/vim> -" Last Change: 2023 Aug 10 +" Language: Vim +" Maintainer: Doug Kearns <dougkearns@gmail.com> +" Last Change: 2024 Apr 13 " Former Maintainer: Bram Moolenaar <Bram@vim.org> " Only do this when not done yet for this buffer @@ -50,7 +50,7 @@ setlocal isk+=# setlocal keywordprg=:help " Comments starts with # in Vim9 script. We have to guess which one to use. -if "\n" .. getline(1, 10)->join("\n") =~# '\n\s*vim9\%[script]\>' +if "\n" .. getline(1, 32)->join("\n") =~# '\n\s*vim9\%[script]\>' setlocal commentstring=#%s else setlocal commentstring=\"%s diff --git a/runtime/ftplugin/yaml.vim b/runtime/ftplugin/yaml.vim index db7cbd7ddb..8bfc45e4c8 100644 --- a/runtime/ftplugin/yaml.vim +++ b/runtime/ftplugin/yaml.vim @@ -16,6 +16,13 @@ let b:undo_ftplugin = "setl com< cms< et< fo<" setlocal comments=:# commentstring=#\ %s expandtab setlocal formatoptions-=t formatoptions+=croql +" rime input method engine uses `*.custom.yaml` as its config files +if expand('%:r:e') ==# 'custom' + compiler rime_deployer + setlocal include=__include:\\s* + let b:undo_ftplugin ..= " inc<" +endif + if !exists("g:yaml_recommended_style") || g:yaml_recommended_style != 0 let b:undo_ftplugin ..= " sw< sts<" setlocal shiftwidth=2 softtabstop=2 diff --git a/runtime/ftplugin/zathurarc.vim b/runtime/ftplugin/zathurarc.vim new file mode 100644 index 0000000000..259fb137a1 --- /dev/null +++ b/runtime/ftplugin/zathurarc.vim @@ -0,0 +1,22 @@ +" Vim filetype plugin file +" Language: Zathurarc +" Maintainer: Wu, Zhenyu <wuzhenyu@ustc.edu> +" Documentation: https://pwmt.org/projects/zathura/documentation/ +" Upstream: https://github.com/Freed-Wu/zathurarc.vim +" Latest Revision: 2024-04-02 + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +let s:save_cpoptions = &cpoptions +set cpoptions&vim + +let b:undo_ftplugin = 'setlocal comments< commentstring< include<' +setlocal comments=:# +setlocal commentstring=#\ %s +setlocal include=^\sinclude + +let &cpoptions = s:save_cpoptions +unlet s:save_cpoptions diff --git a/runtime/ftplugin/zig.vim b/runtime/ftplugin/zig.vim index 28b8cd5a67..ea229b6a49 100644 --- a/runtime/ftplugin/zig.vim +++ b/runtime/ftplugin/zig.vim @@ -1,68 +1,52 @@ " Vim filetype plugin file -" Language: Zig -" Upstream: https://github.com/ziglang/zig.vim +" Language: Zig +" Maintainer: Mathias Lindgren <math.lindgren@gmail.com> +" Last Change: 2024 May 21 +" Based on: https://github.com/ziglang/zig.vim -" Only do this when not done yet for this buffer if exists("b:did_ftplugin") finish endif let b:did_ftplugin = 1 -let s:cpo_orig = &cpo +let s:cpo_save = &cpo set cpo&vim compiler zig_build " Match Zig builtin fns setlocal iskeyword+=@-@ - -" Recommended code style, no tabs and 4-space indentation -setlocal expandtab -setlocal tabstop=8 -setlocal softtabstop=4 -setlocal shiftwidth=4 - setlocal formatoptions-=t formatoptions+=croql - -setlocal suffixesadd=.zig,.zir +setlocal suffixesadd=.zig,.zir,.zon +let &l:define='\v(<fn>|<const>|<var>|^\s*\#\s*define)' +let b:undo_ftplugin = 'setl isk< fo< sua< mp< def<' + +if get(g:, 'zig_recommended_style', 1) + setlocal expandtab + setlocal tabstop=8 + setlocal softtabstop=4 + setlocal shiftwidth=4 + let b:undo_ftplugin .= ' | setl et< ts< sts< sw<' +endif if has('comments') setlocal comments=:///,://!,:// setlocal commentstring=//\ %s + let b:undo_ftplugin .= ' | setl com< cms<' endif if has('find_in_path') let &l:includeexpr='substitute(v:fname, "^([^.])$", "\1.zig", "")' let &l:include='\v(\@import>|\@cInclude>|^\s*\#\s*include)' -endif - -let &l:define='\v(<fn>|<const>|<var>|^\s*\#\s*define)' - -" Safety check: don't execute zig from current directory -if !exists('g:zig_std_dir') && exists('*json_decode') && - \ executable('zig') && dist#vim#IsSafeExecutable('zig', 'zig') - silent let s:env = system('zig env') - if v:shell_error == 0 - let g:zig_std_dir = json_decode(s:env)['std_dir'] - endif - unlet! s:env + let b:undo_ftplugin .= ' | setl inex< inc<' endif if exists('g:zig_std_dir') - let &l:path = g:zig_std_dir . ',' . &l:path + let &l:path .= ',' . g:zig_std_dir + let b:undo_ftplugin .= ' | setl pa<' endif -let b:undo_ftplugin = - \ 'setl isk< et< ts< sts< sw< fo< sua< mp< com< cms< inex< inc< pa<' - -augroup vim-zig - autocmd! * <buffer> - autocmd BufWritePre <buffer> if get(g:, 'zig_fmt_autosave', 1) | call zig#fmt#Format() | endif -augroup END - -let b:undo_ftplugin .= '|au! vim-zig * <buffer>' - -let &cpo = s:cpo_orig -unlet s:cpo_orig +let &cpo = s:cpo_save +unlet s:cpo_save " vim: tabstop=8 shiftwidth=4 softtabstop=4 expandtab diff --git a/runtime/ftplugin/zsh.vim b/runtime/ftplugin/zsh.vim index 40986fccbe..aee890024f 100644 --- a/runtime/ftplugin/zsh.vim +++ b/runtime/ftplugin/zsh.vim @@ -2,7 +2,7 @@ " Language: Zsh shell script " Maintainer: Christian Brabandt <cb@256bit.org> " Previous Maintainer: Nikolai Weibull <now@bitwi.se> -" Latest Revision: 2023-10-07 +" Latest Revision: 2024 May 06 by Vim Project (MANPAGER=) " License: Vim (see :h license) " Repository: https://github.com/chrisbra/vim-zsh @@ -24,7 +24,7 @@ if executable('zsh') && &shell !~# '/\%(nologin\|false\)$' elseif has('terminal') command! -buffer -nargs=1 ZshKeywordPrg silent exe ':term zsh -c "autoload -Uz run-help; run-help <args>"' else - command! -buffer -nargs=1 ZshKeywordPrg echo system('zsh -c "autoload -Uz run-help; run-help <args> 2>/dev/null"') + command! -buffer -nargs=1 ZshKeywordPrg echo system('MANPAGER= zsh -c "autoload -Uz run-help; run-help <args> 2>/dev/null"') endif if !exists('current_compiler') compiler zsh diff --git a/runtime/indent/arduino.vim b/runtime/indent/arduino.vim new file mode 100644 index 0000000000..88717ac00d --- /dev/null +++ b/runtime/indent/arduino.vim @@ -0,0 +1,16 @@ +" Vim indent file +" Language: Arduino +" Maintainer: The Vim Project <https://github.com/vim/vim> +" Ken Takata <https://github.com/k-takata> +" Last Change: 2024 Apr 03 + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") + finish +endif +let b:did_indent = 1 + +" Use C indenting. +setlocal cindent + +let b:undo_indent = "setl cin<" diff --git a/runtime/indent/asm.vim b/runtime/indent/asm.vim new file mode 100644 index 0000000000..054612b9d6 --- /dev/null +++ b/runtime/indent/asm.vim @@ -0,0 +1,29 @@ +" Vim indent file +" Language: asm +" Maintainer: Philip Jones <philj56@gmail.com> +" Upstream: https://github.com/philj56/vim-asm-indent +" Last Change: 2017-Jul-01 +" 2024 Apr 25 by Vim Project (undo_indent) + +if exists("b:did_indent") + finish +endif +let b:did_indent = 1 + +setlocal indentexpr=s:getAsmIndent() +setlocal indentkeys=<:>,!^F,o,O + +let b:undo_indent = "setlocal indentexpr< indentkeys<" + +function! s:getAsmIndent() + let line = getline(v:lnum) + let ind = shiftwidth() + + " If the line is a label (starts with ':' terminated keyword), + " then don't indent + if line =~ '^\s*\k\+:' + let ind = 0 + endif + + return ind +endfunction diff --git a/runtime/indent/astro.vim b/runtime/indent/astro.vim new file mode 100644 index 0000000000..25a2aa0c29 --- /dev/null +++ b/runtime/indent/astro.vim @@ -0,0 +1,88 @@ +" Vim indent file (experimental). +" Language: Astro +" Author: Wuelner Martínez <wuelner.martinez@outlook.com> +" Maintainer: Wuelner Martínez <wuelner.martinez@outlook.com> +" URL: https://github.com/wuelnerdotexe/vim-astro +" Last Change: 2022 Aug 07 +" Based On: Evan Lecklider's vim-svelte +" Changes: See https://github.com/evanleck/vim-svelte +" Credits: See vim-svelte on github + +" Only load this indent file when no other was loaded yet. +if exists('b:did_indent') + finish +endif + +let b:html_indent_script1 = 'inc' +let b:html_indent_style1 = 'inc' + +" Embedded HTML indent. +runtime! indent/html.vim +let s:html_indent = &l:indentexpr +unlet b:did_indent + +let b:did_indent = 1 + +setlocal indentexpr=GetAstroIndent() +setlocal indentkeys=<>>,/,0{,{,},0},0),0],0\,<<>,,!^F,*<Return>,o,O,e,; + +let b:undo_indent = 'setl inde< indk<' + +" Only define the function once. +if exists('*GetAstroIndent') + finish +endif + +let s:cpoptions_save = &cpoptions +setlocal cpoptions&vim + +function! GetAstroIndent() + let l:current_line_number = v:lnum + + if l:current_line_number == 0 + return 0 + endif + + let l:current_line = getline(l:current_line_number) + + if l:current_line =~ '^\s*</\?\(script\|style\)' + return 0 + endif + + let l:previous_line_number = prevnonblank(l:current_line_number - 1) + let l:previous_line = getline(l:previous_line_number) + let l:previous_line_indent = indent(l:previous_line_number) + + if l:previous_line =~ '^\s*</\?\(script\|style\)' + return l:previous_line_indent + shiftwidth() + endif + + execute 'let l:indent = ' . s:html_indent + + if searchpair('<style>', '', '</style>', 'bW') && + \ l:previous_line =~ ';$' && l:current_line !~ '}' + return l:previous_line_indent + endif + + if synID(l:previous_line_number, match( + \ l:previous_line, '\S' + \ ) + 1, 0) == hlID('htmlTag') && synID(l:current_line_number, match( + \ l:current_line, '\S' + \ ) + 1, 0) != hlID('htmlEndTag') + let l:indents_match = l:indent == l:previous_line_indent + let l:previous_closes = l:previous_line =~ '/>$' + + if l:indents_match && + \ !l:previous_closes && l:previous_line =~ '<\(\u\|\l\+:\l\+\)' + return l:previous_line_indent + shiftwidth() + elseif !l:indents_match && l:previous_closes + return l:previous_line_indent + endif + endif + + return l:indent +endfunction + +let &cpoptions = s:cpoptions_save +unlet s:cpoptions_save +" vim: ts=8 diff --git a/runtime/indent/json5.vim b/runtime/indent/json5.vim new file mode 100644 index 0000000000..5977a4b912 --- /dev/null +++ b/runtime/indent/json5.vim @@ -0,0 +1,11 @@ +" Vim indent file +" Language: JSON5 +" Maintainer: The Vim Project <https://github.com/vim/vim> +" Last Change: 2024-03-26 + +if exists("b:did_indent") + finish +endif + +" Same as jsonc indenting for now +runtime! indent/jsonc.vim diff --git a/runtime/indent/stylus.vim b/runtime/indent/stylus.vim new file mode 100644 index 0000000000..89634f0914 --- /dev/null +++ b/runtime/indent/stylus.vim @@ -0,0 +1,121 @@ +" Vim indent file +" Language: Stylus +" Maintainer: Marc Harter +" Last Change: 2010 May 21 +" Based On: sass.vim from Tim Pope +" +if exists("b:did_indent") + finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetStylusIndent() +setlocal indentkeys=o,O,*<Return>,},],0),!^F +let b:undo_indent = "setl indentexpr< indentkeys<" + +if exists("*GetStylusIndent") " only define once + finish +endif + +function s:prevnonblanknoncomment(lnum) + let lnum = a:lnum + while lnum > 1 + let lnum = prevnonblank(lnum) + let line = getline(lnum) + if line =~ '\*/' + while lnum > 1 && line !~ '/\*' + let lnum -= 1 + endwhile + if line =~ '^\s*/\*' + let lnum -= 1 + else + break + endif + else + break + endif + endwhile + return lnum +endfunction + +function s:count_braces(lnum, count_open) + let n_open = 0 + let n_close = 0 + let line = getline(a:lnum) + let pattern = '[{}]' + let i = match(line, pattern) + while i != -1 + if synIDattr(synID(a:lnum, i + 1, 0), 'name') !~ 'css\%(Comment\|StringQ\{1,2}\)' + if line[i] == '{' + let n_open += 1 + elseif line[i] == '}' + if n_open > 0 + let n_open -= 1 + else + let n_close += 1 + endif + endif + endif + let i = match(line, pattern, i + 1) + endwhile + return a:count_open ? n_open : n_close +endfunction + +" function CheckCSSIndent() +" let line = getline(v:lnum) +" if line =~ '^\s*\*' +" return cindent(v:lnum) +" endif +" +" let pnum = s:prevnonblanknoncomment(v:lnum - 1) +" if pnum == 0 +" return 0 +" endif + +function! GetStylusIndent() + let line = getline(v:lnum) + if line =~ '^\s*\*' + return cindent(v:lnum) + endif + + let pnum = s:prevnonblanknoncomment(v:lnum - 1) + if pnum == 0 + return 0 + endif + + let lnum = prevnonblank(v:lnum-1) + if lnum == 0 + return 0 + endif + + let pline = getline(pnum) + + if pline =~ '[}{]' + return indent(pnum) + s:count_braces(pnum, 1) * &sw - s:count_braces(v:lnum, 0) * &sw + endif + + let line = substitute(getline(lnum),'[\s()]\+$','','') " get last line strip ending whitespace + let cline = substitute(substitute(getline(v:lnum),'\s\+$','',''),'^\s\+','','') " get current line, trimmed + let lastcol = strlen(line) " get last col in prev line + let line = substitute(line,'^\s\+','','') " then remove preceeding whitespace + let indent = indent(lnum) " get indent on prev line + let cindent = indent(v:lnum) " get indent on current line + let increase = indent + &sw " increase indent by the shift width + if indent == indent(lnum) + let indent = cindent <= indent ? indent : increase + endif + + let group = synIDattr(synID(lnum,lastcol,1),'name') + + " if group !~? 'css.*' && line =~? ')\s*$' " match user functions + " return increase + if group =~? '\v^%(cssTagName|cssClassName|cssIdentifier|cssSelectorOp|cssSelectorOp2|cssBraces|cssAttributeSelector|cssPseudo|stylusId|stylusClass)$' + return increase + elseif (group == 'stylusUserFunction') && (indent(lnum) == '0') " mixin definition + return increase + else + return indent + endif +endfunction + +" vim:set sw=2; diff --git a/runtime/lua/_vim9script.lua b/runtime/lua/_vim9script.lua index ca0e913d51..23c078cb87 100644 --- a/runtime/lua/_vim9script.lua +++ b/runtime/lua/_vim9script.lua @@ -82,7 +82,7 @@ local vim9 = (function() end M.index = function(obj, idx) - if vim.tbl_islist(obj) then + if vim.islist(obj) then if idx < 0 then return obj[#obj + idx + 1] else @@ -127,7 +127,7 @@ local vim9 = (function() assert(type(finish) == 'number') local slicer - if vim.tbl_islist(obj) then + if vim.islist(obj) then slicer = vim.list_slice elseif type(obj) == 'string' then slicer = string.sub @@ -168,7 +168,7 @@ local vim9 = (function() end M.iter = function(expr) - if vim.tbl_islist(expr) then + if vim.islist(expr) then return ipairs(expr) else return pairs(expr) @@ -234,7 +234,7 @@ vim9['convert'] = (function() elseif type(val) == 'table' then if vim.tbl_isempty(val) then return vim.empty_dict() - elseif vim.tbl_islist(val) then + elseif vim.islist(val) then error(string.format('Cannot pass list to dictionary? %s', vim.inspect(val))) else return val @@ -280,7 +280,7 @@ vim9['fn'] = (function() error("haven't written this code yet") end - if vim.tbl_islist(right) then + if vim.islist(right) then vim.list_extend(left, right) return left else diff --git a/runtime/lua/editorconfig.lua b/runtime/lua/editorconfig.lua index 49d63807a6..dcd7425c29 100644 --- a/runtime/lua/editorconfig.lua +++ b/runtime/lua/editorconfig.lua @@ -1,31 +1,79 @@ -local M = {} +--- @brief +--- Nvim supports EditorConfig. When a file is opened, after running |ftplugin|s +--- and |FileType| autocommands, Nvim searches all parent directories of that file +--- for ".editorconfig" files, parses them, and applies any properties that match +--- the opened file. Think of it like 'modeline' for an entire (recursive) +--- directory. For more information see https://editorconfig.org/. + +--- @brief [g:editorconfig]() [b:editorconfig]() +--- +--- EditorConfig is enabled by default. To disable it, add to your config: +--- ```lua +--- vim.g.editorconfig = false +--- ``` +--- +--- (Vimscript: `let g:editorconfig = v:false`). It can also be disabled +--- per-buffer by setting the [b:editorconfig] buffer-local variable to `false`. +--- +--- Nvim stores the applied properties in [b:editorconfig] if it is not `false`. + +--- @brief [editorconfig-custom-properties]() +--- +--- New properties can be added by adding a new entry to the "properties" table. +--- The table key is a property name and the value is a callback function which +--- accepts the number of the buffer to be modified, the value of the property +--- in the `.editorconfig` file, and (optionally) a table containing all of the +--- other properties and their values (useful for properties which depend on other +--- properties). The value is always a string and must be coerced if necessary. +--- Example: +--- +--- ```lua +--- +--- require('editorconfig').properties.foo = function(bufnr, val, opts) +--- if opts.charset and opts.charset ~= "utf-8" then +--- error("foo can only be set when charset is utf-8", 0) +--- end +--- vim.b[bufnr].foo = val +--- end +--- +--- ``` + +--- @brief [editorconfig-properties]() +--- +--- The following properties are supported by default: --- @type table<string,fun(bufnr: integer, val: string, opts?: table)> -M.properties = {} +local properties = {} +--- @private --- Modified version of the builtin assert that does not include error position information --- ----@param v any Condition ----@param message string Error message to display if condition is false or nil ----@return any v if not false or nil, otherwise an error is displayed ---- ----@private +--- @param v any Condition +--- @param message string Error message to display if condition is false or nil +--- @return any v if not false or nil, otherwise an error is displayed local function assert(v, message) return v or error(message, 0) end +--- @private --- Show a warning message ---- ----@param msg string Message to show ---- ----@private +--- @param msg string Message to show local function warn(msg, ...) - vim.notify_once(string.format(msg, ...), vim.log.levels.WARN, { + vim.notify_once(msg:format(...), vim.log.levels.WARN, { title = 'editorconfig', }) end -function M.properties.charset(bufnr, val) +--- If "true", then stop searching for `.editorconfig` files in parent +--- directories. This property must be at the top-level of the +--- `.editorconfig` file (i.e. it must not be within a glob section). +function properties.root() + -- Unused +end + +--- One of `"utf-8"`, `"utf-8-bom"`, `"latin1"`, `"utf-16be"`, or `"utf-16le"`. +--- Sets the 'fileencoding' and 'bomb' options. +function properties.charset(bufnr, val) assert( vim.list_contains({ 'utf-8', 'utf-8-bom', 'latin1', 'utf-16be', 'utf-16le' }, val), 'charset must be one of "utf-8", "utf-8-bom", "latin1", "utf-16be", or "utf-16le"' @@ -40,14 +88,18 @@ function M.properties.charset(bufnr, val) end end -function M.properties.end_of_line(bufnr, val) +--- One of `"lf"`, `"crlf"`, or `"cr"`. +--- These correspond to setting 'fileformat' to "unix", "dos", or "mac", +--- respectively. +function properties.end_of_line(bufnr, val) vim.bo[bufnr].fileformat = assert( ({ lf = 'unix', crlf = 'dos', cr = 'mac' })[val], 'end_of_line must be one of "lf", "crlf", or "cr"' ) end -function M.properties.indent_style(bufnr, val, opts) +--- One of `"tab"` or `"space"`. Sets the 'expandtab' option. +function properties.indent_style(bufnr, val, opts) assert(val == 'tab' or val == 'space', 'indent_style must be either "tab" or "space"') vim.bo[bufnr].expandtab = val == 'space' if val == 'tab' and not opts.indent_size then @@ -56,7 +108,11 @@ function M.properties.indent_style(bufnr, val, opts) end end -function M.properties.indent_size(bufnr, val, opts) +--- A number indicating the size of a single indent. Alternatively, use the +--- value "tab" to use the value of the tab_width property. Sets the +--- 'shiftwidth' and 'softtabstop' options. If this value is not "tab" and +--- the tab_width property is not set, 'tabstop' is also set to this value. +function properties.indent_size(bufnr, val, opts) if val == 'tab' then vim.bo[bufnr].shiftwidth = 0 vim.bo[bufnr].softtabstop = 0 @@ -70,11 +126,14 @@ function M.properties.indent_size(bufnr, val, opts) end end -function M.properties.tab_width(bufnr, val) +--- The display size of a single tab character. Sets the 'tabstop' option. +function properties.tab_width(bufnr, val) vim.bo[bufnr].tabstop = assert(tonumber(val), 'tab_width must be a number') end -function M.properties.max_line_length(bufnr, val) +--- A number indicating the maximum length of a single +--- line. Sets the 'textwidth' option. +function properties.max_line_length(bufnr, val) local n = tonumber(val) if n then vim.bo[bufnr].textwidth = n @@ -84,7 +143,8 @@ function M.properties.max_line_length(bufnr, val) end end -function M.properties.trim_trailing_whitespace(bufnr, val) +--- When `"true"`, trailing whitespace is automatically removed when the buffer is written. +function properties.trim_trailing_whitespace(bufnr, val) assert( val == 'true' or val == 'false', 'trim_trailing_whitespace must be either "true" or "false"' @@ -109,7 +169,9 @@ function M.properties.trim_trailing_whitespace(bufnr, val) end end -function M.properties.insert_final_newline(bufnr, val) +--- `"true"` or `"false"` to ensure the file always has a trailing newline as its last byte. +--- Sets the 'fixendofline' and 'endofline' options. +function properties.insert_final_newline(bufnr, val) assert(val == 'true' or val == 'false', 'insert_final_newline must be either "true" or "false"') vim.bo[bufnr].fixendofline = val == 'true' @@ -128,63 +190,56 @@ function M.properties.insert_final_newline(bufnr, val) end end ---- Modified version of |glob2regpat()| that does not match path separators on *. +--- @private +--- Modified version of [glob2regpat()] that does not match path separators on `*`. --- ---- This function replaces single instances of * with the regex pattern [^/]*. However, the star in ---- the replacement pattern also gets interpreted by glob2regpat, so we insert a placeholder, pass ---- it through glob2regpat, then replace the placeholder with the actual regex pattern. +--- This function replaces single instances of `*` with the regex pattern `[^/]*`. +--- However, the star in the replacement pattern also gets interpreted by glob2regpat, +--- so we insert a placeholder, pass it through glob2regpat, then replace the +--- placeholder with the actual regex pattern. --- ----@param glob string Glob to convert into a regular expression ----@return string Regular expression ---- ----@private +--- @param glob string Glob to convert into a regular expression +--- @return string regex Regular expression local function glob2regpat(glob) local placeholder = '@@PLACEHOLDER@@' - return ( - string.gsub( - vim.fn.glob2regpat( - vim.fn.substitute( - string.gsub(glob, '{(%d+)%.%.(%d+)}', '[%1-%2]'), - '\\*\\@<!\\*\\*\\@!', - placeholder, - 'g' - ) - ), - placeholder, - '[^/]*' - ) + local glob1 = vim.fn.substitute( + glob:gsub('{(%d+)%.%.(%d+)}', '[%1-%2]'), + '\\*\\@<!\\*\\*\\@!', + placeholder, + 'g' ) + local regpat = vim.fn.glob2regpat(glob1) + return (regpat:gsub(placeholder, '[^/]*')) end +--- @private --- Parse a single line in an EditorConfig file ---- ----@param line string Line ----@return string|nil If the line contains a pattern, the glob pattern ----@return string|nil If the line contains a key-value pair, the key ----@return string|nil If the line contains a key-value pair, the value ---- ----@private +--- @param line string Line +--- @return string? glob pattern if the line contains a pattern +--- @return string? key if the line contains a key-value pair +--- @return string? value if the line contains a key-value pair local function parse_line(line) - if line:find('^%s*[^ #;]') then - local glob = (line:match('%b[]') or ''):match('^%s*%[(.*)%]%s*$') - if glob then - return glob, nil, nil - end + if not line:find('^%s*[^ #;]') then + return + end - local key, val = line:match('^%s*([^:= ][^:=]-)%s*[:=]%s*(.-)%s*$') - if key ~= nil and val ~= nil then - return nil, key:lower(), val:lower() - end + --- @type string? + local glob = (line:match('%b[]') or ''):match('^%s*%[(.*)%]%s*$') + if glob then + return glob + end + + local key, val = line:match('^%s*([^:= ][^:=]-)%s*[:=]%s*(.-)%s*$') + if key ~= nil and val ~= nil then + return nil, key:lower(), val:lower() end end ---- Parse options from an .editorconfig file ---- ----@param filepath string File path of the file to apply EditorConfig settings to ----@param dir string Current directory ----@return table<string,string|boolean> Table of options to apply to the given file ---- ----@private +--- @private +--- Parse options from an `.editorconfig` file +--- @param filepath string File path of the file to apply EditorConfig settings to +--- @param dir string Current directory +--- @return table<string,string|boolean> Table of options to apply to the given file local function parse(filepath, dir) local pat --- @type vim.regex? local opts = {} --- @type table<string,string|boolean> @@ -215,11 +270,14 @@ local function parse(filepath, dir) return opts end ---- Configure the given buffer with options from an .editorconfig file ---- ----@param bufnr integer Buffer number to configure ---- ----@private +local M = {} + +-- Exposed for use in syntax/editorconfig.vim` +M.properties = properties + +--- @private +--- Configure the given buffer with options from an `.editorconfig` file +--- @param bufnr integer Buffer number to configure function M.config(bufnr) bufnr = bufnr or vim.api.nvim_get_current_buf() if not vim.api.nvim_buf_is_valid(bufnr) then @@ -249,6 +307,7 @@ function M.config(bufnr) if val ~= 'unset' then local func = M.properties[opt] if func then + --- @type boolean, string? local ok, err = pcall(func, bufnr, val, opts) if ok then applied[opt] = val diff --git a/runtime/lua/man.lua b/runtime/lua/man.lua index ac15aff60c..02e841030f 100644 --- a/runtime/lua/man.lua +++ b/runtime/lua/man.lua @@ -411,15 +411,13 @@ local function find_man() return false end ----@param pager boolean -local function set_options(pager) +local function set_options() vim.bo.swapfile = false vim.bo.buftype = 'nofile' vim.bo.bufhidden = 'unload' vim.bo.modified = false vim.bo.readonly = true vim.bo.modifiable = false - vim.b.pager = pager vim.bo.filetype = 'man' end @@ -475,7 +473,7 @@ local function put_page(page) vim.cmd([[silent! keeppatterns keepjumps %s/\s\{199,}/\=repeat(' ', 10)/g]]) vim.cmd('1') -- Move cursor to first line highlight_man_page() - set_options(false) + set_options() end local function format_candidate(path, psect) @@ -662,7 +660,8 @@ function M.init_pager() vim.cmd.file({ 'man://' .. fn.fnameescape(ref):lower(), mods = { silent = true } }) end - set_options(true) + vim.g.pager = true + set_options() end ---@param count integer @@ -716,11 +715,11 @@ function M.open_page(count, smods, args) local target = ('%s(%s)'):format(name, sect) local ok, ret = pcall(function() - if smods.tab == -1 and find_man() then - vim.cmd.tag({ target, mods = { silent = true, keepalt = true } }) + smods.silent = true + smods.keepalt = true + if smods.hide or (smods.tab == -1 and find_man()) then + vim.cmd.tag({ target, mods = smods }) else - smods.silent = true - smods.keepalt = true vim.cmd.stag({ target, mods = smods }) end end) @@ -730,7 +729,7 @@ function M.open_page(count, smods, args) if not ok then error(ret) else - set_options(false) + set_options() end vim.b.man_sect = sect diff --git a/runtime/lua/provider/clipboard/health.lua b/runtime/lua/provider/clipboard/health.lua deleted file mode 100644 index dc33cb0ab0..0000000000 --- a/runtime/lua/provider/clipboard/health.lua +++ /dev/null @@ -1,40 +0,0 @@ -local health = vim.health -local executable = health.executable - -local M = {} - -function M.check() - health.start('Clipboard (optional)') - - if - os.getenv('TMUX') - and executable('tmux') - and executable('pbpaste') - and not health.cmd_ok('pbpaste') - then - local tmux_version = string.match(vim.fn.system('tmux -V'), '%d+%.%d+') - local advice = { - 'Install tmux 2.6+. https://superuser.com/q/231130', - 'or use tmux with reattach-to-user-namespace. https://superuser.com/a/413233', - } - health.error('pbcopy does not work with tmux version: ' .. tmux_version, advice) - end - - local clipboard_tool = vim.fn['provider#clipboard#Executable']() - if vim.g.clipboard ~= nil and clipboard_tool == '' then - local error_message = vim.fn['provider#clipboard#Error']() - health.error( - error_message, - "Use the example in :help g:clipboard as a template, or don't set g:clipboard at all." - ) - elseif clipboard_tool:find('^%s*$') then - health.warn( - 'No clipboard tool found. Clipboard registers (`"+` and `"*`) will not work.', - ':help clipboard' - ) - else - health.ok('Clipboard tool found: ' .. clipboard_tool) - end -end - -return M diff --git a/runtime/lua/provider/node/health.lua b/runtime/lua/provider/node/health.lua deleted file mode 100644 index a434f8a92b..0000000000 --- a/runtime/lua/provider/node/health.lua +++ /dev/null @@ -1,105 +0,0 @@ -local health = vim.health -local executable = health.executable -local iswin = vim.loop.os_uname().sysname == 'Windows_NT' - -local M = {} - -function M.check() - health.start('Node.js provider (optional)') - - if health.provider_disabled('node') then - return - end - - if - not executable('node') - or (not executable('npm') and not executable('yarn') and not executable('pnpm')) - then - health.warn( - '`node` and `npm` (or `yarn`, `pnpm`) must be in $PATH.', - 'Install Node.js and verify that `node` and `npm` (or `yarn`, `pnpm`) commands work.' - ) - return - end - - -- local node_v = vim.fn.split(system({'node', '-v'}), "\n")[1] or '' - local ok, node_v = health.cmd_ok({ 'node', '-v' }) - health.info('Node.js: ' .. node_v) - if not ok or vim.version.lt(node_v, '6.0.0') then - health.warn('Nvim node.js host does not support Node ' .. node_v) - -- Skip further checks, they are nonsense if nodejs is too old. - return - end - if vim.fn['provider#node#can_inspect']() == 0 then - health.warn( - 'node.js on this system does not support --inspect-brk so $NVIM_NODE_HOST_DEBUG is ignored.' - ) - end - - local node_detect_table = vim.fn['provider#node#Detect']() - local host = node_detect_table[1] - if host:find('^%s*$') then - health.warn('Missing "neovim" npm (or yarn, pnpm) package.', { - 'Run in shell: npm install -g neovim', - 'Run in shell (if you use yarn): yarn global add neovim', - 'Run in shell (if you use pnpm): pnpm install -g neovim', - 'You may disable this provider (and warning) by adding `let g:loaded_node_provider = 0` to your init.vim', - }) - return - end - health.info('Nvim node.js host: ' .. host) - - local manager = 'npm' - if executable('yarn') then - manager = 'yarn' - elseif executable('pnpm') then - manager = 'pnpm' - end - - local latest_npm_cmd = ( - iswin and 'cmd /c ' .. manager .. ' info neovim --json' or manager .. ' info neovim --json' - ) - local latest_npm - ok, latest_npm = health.cmd_ok(vim.split(latest_npm_cmd, ' ')) - if not ok or latest_npm:find('^%s$') then - health.error( - 'Failed to run: ' .. latest_npm_cmd, - { "Make sure you're connected to the internet.", 'Are you behind a firewall or proxy?' } - ) - return - end - - local pcall_ok, pkg_data = pcall(vim.json.decode, latest_npm) - if not pcall_ok then - return 'error: ' .. latest_npm - end - local latest_npm_subtable = pkg_data['dist-tags'] or {} - latest_npm = latest_npm_subtable['latest'] or 'unable to parse' - - local current_npm_cmd = { 'node', host, '--version' } - local current_npm - ok, current_npm = health.cmd_ok(current_npm_cmd) - if not ok then - health.error( - 'Failed to run: ' .. table.concat(current_npm_cmd, ' '), - { 'Report this issue with the output of: ', table.concat(current_npm_cmd, ' ') } - ) - return - end - - if latest_npm ~= 'unable to parse' and vim.version.lt(current_npm, latest_npm) then - local message = 'Package "neovim" is out-of-date. Installed: ' - .. current_npm - .. ' latest: ' - .. latest_npm - health.warn(message({ - 'Run in shell: npm install -g neovim', - 'Run in shell (if you use yarn): yarn global add neovim', - 'Run in shell (if you use pnpm): pnpm install -g neovim', - })) - else - health.ok('Latest "neovim" npm/yarn/pnpm package is installed: ' .. current_npm) - end -end - -return M diff --git a/runtime/lua/provider/perl/health.lua b/runtime/lua/provider/perl/health.lua deleted file mode 100644 index 535093d793..0000000000 --- a/runtime/lua/provider/perl/health.lua +++ /dev/null @@ -1,90 +0,0 @@ -local health = vim.health - -local M = {} - -function M.check() - health.start('Perl provider (optional)') - - if health.provider_disabled('perl') then - return - end - - local perl_exec, perl_warnings = vim.provider.perl.detect() - - if not perl_exec then - health.warn(assert(perl_warnings), { - 'See :help provider-perl for more information.', - 'You may disable this provider (and warning) by adding `let g:loaded_perl_provider = 0` to your init.vim', - }) - health.warn('No usable perl executable found') - return - end - - health.info('perl executable: ' .. perl_exec) - - -- we cannot use cpanm that is on the path, as it may not be for the perl - -- set with g:perl_host_prog - local ok = health.cmd_ok({ perl_exec, '-W', '-MApp::cpanminus', '-e', '' }) - if not ok then - return { perl_exec, '"App::cpanminus" module is not installed' } - end - - local latest_cpan_cmd = { - perl_exec, - '-MApp::cpanminus::fatscript', - '-e', - 'my $app = App::cpanminus::script->new; $app->parse_options ("--info", "-q", "Neovim::Ext"); exit $app->doit', - } - local latest_cpan - ok, latest_cpan = health.cmd_ok(latest_cpan_cmd) - if not ok or latest_cpan:find('^%s*$') then - health.error( - 'Failed to run: ' .. table.concat(latest_cpan_cmd, ' '), - { "Make sure you're connected to the internet.", 'Are you behind a firewall or proxy?' } - ) - return - elseif latest_cpan[1] == '!' then - local cpanm_errs = vim.split(latest_cpan, '!') - if cpanm_errs[1]:find("Can't write to ") then - local advice = {} - for i = 2, #cpanm_errs do - advice[#advice + 1] = cpanm_errs[i] - end - - health.warn(cpanm_errs[1], advice) - -- Last line is the package info - latest_cpan = cpanm_errs[#cpanm_errs] - else - health.error('Unknown warning from command: ' .. latest_cpan_cmd, cpanm_errs) - return - end - end - latest_cpan = vim.fn.matchstr(latest_cpan, [[\(\.\?\d\)\+]]) - if latest_cpan:find('^%s*$') then - health.error('Cannot parse version number from cpanm output: ' .. latest_cpan) - return - end - - local current_cpan_cmd = { perl_exec, '-W', '-MNeovim::Ext', '-e', 'print $Neovim::Ext::VERSION' } - local current_cpan - ok, current_cpan = health.cmd_ok(current_cpan_cmd) - if not ok then - health.error( - 'Failed to run: ' .. table.concat(current_cpan_cmd, ' '), - { 'Report this issue with the output of: ', table.concat(current_cpan_cmd, ' ') } - ) - return - end - - if vim.version.lt(current_cpan, latest_cpan) then - local message = 'Module "Neovim::Ext" is out-of-date. Installed: ' - .. current_cpan - .. ', latest: ' - .. latest_cpan - health.warn(message, 'Run in shell: cpanm -n Neovim::Ext') - else - health.ok('Latest "Neovim::Ext" cpan module is installed: ' .. current_cpan) - end -end - -return M diff --git a/runtime/lua/provider/ruby/health.lua b/runtime/lua/provider/ruby/health.lua deleted file mode 100644 index 04f6e303e6..0000000000 --- a/runtime/lua/provider/ruby/health.lua +++ /dev/null @@ -1,71 +0,0 @@ -local health = vim.health -local executable = health.executable -local iswin = vim.loop.os_uname().sysname == 'Windows_NT' - -local M = {} - -function M.check() - health.start('Ruby provider (optional)') - - if health.provider_disabled('ruby') then - return - end - - if not executable('ruby') or not executable('gem') then - health.warn( - '`ruby` and `gem` must be in $PATH.', - 'Install Ruby and verify that `ruby` and `gem` commands work.' - ) - return - end - health.info('Ruby: ' .. health.system({ 'ruby', '-v' })) - - local ruby_detect_table = vim.provider.ruby.detect() - local host = ruby_detect_table[1] - if (not host) or host:find('^%s*$') then - health.warn('`neovim-ruby-host` not found.', { - 'Run `gem install neovim` to ensure the neovim RubyGem is installed.', - 'Run `gem environment` to ensure the gem bin directory is in $PATH.', - 'If you are using rvm/rbenv/chruby, try "rehashing".', - 'See :help g:ruby_host_prog for non-standard gem installations.', - 'You may disable this provider (and warning) by adding `let g:loaded_ruby_provider = 0` to your init.vim', - }) - return - end - health.info('Host: ' .. host) - - local latest_gem_cmd = (iswin and 'cmd /c gem list -ra "^^neovim$"' or 'gem list -ra ^neovim$') - local ok, latest_gem = health.cmd_ok(vim.split(latest_gem_cmd, ' ')) - if not ok or latest_gem:find('^%s*$') then - health.error( - 'Failed to run: ' .. latest_gem_cmd, - { "Make sure you're connected to the internet.", 'Are you behind a firewall or proxy?' } - ) - return - end - local gem_split = vim.split(latest_gem, [[neovim (\|, \|)$]]) - latest_gem = gem_split[1] or 'not found' - - local current_gem_cmd = { host, '--version' } - local current_gem - ok, current_gem = health.cmd_ok(current_gem_cmd) - if not ok then - health.error( - 'Failed to run: ' .. table.concat(current_gem_cmd, ' '), - { 'Report this issue with the output of: ', table.concat(current_gem_cmd, ' ') } - ) - return - end - - if vim.version.lt(current_gem, latest_gem) then - local message = 'Gem "neovim" is out-of-date. Installed: ' - .. current_gem - .. ', latest: ' - .. latest_gem - health.warn(message, 'Run in shell: gem update neovim') - else - health.ok('Latest "neovim" gem is installed: ' .. current_gem) - end -end - -return M diff --git a/runtime/lua/vim/_comment.lua b/runtime/lua/vim/_comment.lua new file mode 100644 index 0000000000..044cd69716 --- /dev/null +++ b/runtime/lua/vim/_comment.lua @@ -0,0 +1,263 @@ +---@nodoc +---@class vim._comment.Parts +---@field left string Left part of comment +---@field right string Right part of comment + +--- Get 'commentstring' at cursor +---@param ref_position integer[] +---@return string +local function get_commentstring(ref_position) + local buf_cs = vim.bo.commentstring + + local has_ts_parser, ts_parser = pcall(vim.treesitter.get_parser) + if not has_ts_parser then + return buf_cs + end + + -- Try to get 'commentstring' associated with local tree-sitter language. + -- This is useful for injected languages (like markdown with code blocks). + local row, col = ref_position[1] - 1, ref_position[2] + local ref_range = { row, col, row, col + 1 } + + -- - Get 'commentstring' from the deepest LanguageTree which both contains + -- reference range and has valid 'commentstring' (meaning it has at least + -- one associated 'filetype' with valid 'commentstring'). + -- In simple cases using `parser:language_for_range()` would be enough, but + -- it fails for languages without valid 'commentstring' (like 'comment'). + local ts_cs, res_level = nil, 0 + + ---@param lang_tree vim.treesitter.LanguageTree + local function traverse(lang_tree, level) + if not lang_tree:contains(ref_range) then + return + end + + local lang = lang_tree:lang() + local filetypes = vim.treesitter.language.get_filetypes(lang) + for _, ft in ipairs(filetypes) do + local cur_cs = vim.filetype.get_option(ft, 'commentstring') + if cur_cs ~= '' and level > res_level then + ts_cs = cur_cs + end + end + + for _, child_lang_tree in pairs(lang_tree:children()) do + traverse(child_lang_tree, level + 1) + end + end + traverse(ts_parser, 1) + + return ts_cs or buf_cs +end + +--- Compute comment parts from 'commentstring' +---@param ref_position integer[] +---@return vim._comment.Parts +local function get_comment_parts(ref_position) + local cs = get_commentstring(ref_position) + + if cs == nil or cs == '' then + vim.api.nvim_echo({ { "Option 'commentstring' is empty.", 'WarningMsg' } }, true, {}) + return { left = '', right = '' } + end + + if not (type(cs) == 'string' and cs:find('%%s') ~= nil) then + error(vim.inspect(cs) .. " is not a valid 'commentstring'.") + end + + -- Structure of 'commentstring': <left part> <%s> <right part> + local left, right = cs:match('^(.-)%%s(.-)$') + return { left = left, right = right } +end + +--- Make a function that checks if a line is commented +---@param parts vim._comment.Parts +---@return fun(line: string): boolean +local function make_comment_check(parts) + local l_esc, r_esc = vim.pesc(parts.left), vim.pesc(parts.right) + + -- Commented line has the following structure: + -- <whitespace> <trimmed left> <anything> <trimmed right> <whitespace> + local regex = '^%s-' .. vim.trim(l_esc) .. '.*' .. vim.trim(r_esc) .. '%s-$' + + return function(line) + return line:find(regex) ~= nil + end +end + +--- Compute comment-related information about lines +---@param lines string[] +---@param parts vim._comment.Parts +---@return string indent +---@return boolean is_commented +local function get_lines_info(lines, parts) + local comment_check = make_comment_check(parts) + + local is_commented = true + local indent_width = math.huge + ---@type string + local indent + + for _, l in ipairs(lines) do + -- Update lines indent: minimum of all indents except blank lines + local _, indent_width_cur, indent_cur = l:find('^(%s*)') + + -- Ignore blank lines completely when making a decision + if indent_width_cur < l:len() then + -- NOTE: Copying actual indent instead of recreating it with `indent_width` + -- allows to handle both tabs and spaces + if indent_width_cur < indent_width then + ---@diagnostic disable-next-line:cast-local-type + indent_width, indent = indent_width_cur, indent_cur + end + + -- Update comment info: commented if every non-blank line is commented + if is_commented then + is_commented = comment_check(l) + end + end + end + + -- `indent` can still be `nil` in case all `lines` are empty + return indent or '', is_commented +end + +--- Compute whether a string is blank +---@param x string +---@return boolean is_blank +local function is_blank(x) + return x:find('^%s*$') ~= nil +end + +--- Make a function which comments a line +---@param parts vim._comment.Parts +---@param indent string +---@return fun(line: string): string +local function make_comment_function(parts, indent) + local prefix, nonindent_start, suffix = indent .. parts.left, indent:len() + 1, parts.right + local blank_comment = indent .. vim.trim(parts.left) .. vim.trim(parts.right) + + return function(line) + if is_blank(line) then + return blank_comment + end + return prefix .. line:sub(nonindent_start) .. suffix + end +end + +--- Make a function which uncomments a line +---@param parts vim._comment.Parts +---@return fun(line: string): string +local function make_uncomment_function(parts) + local l_esc, r_esc = vim.pesc(parts.left), vim.pesc(parts.right) + local regex = '^(%s*)' .. l_esc .. '(.*)' .. r_esc .. '(%s-)$' + local regex_trimmed = '^(%s*)' .. vim.trim(l_esc) .. '(.*)' .. vim.trim(r_esc) .. '(%s-)$' + + return function(line) + -- Try regex with exact comment parts first, fall back to trimmed parts + local indent, new_line, trail = line:match(regex) + if new_line == nil then + indent, new_line, trail = line:match(regex_trimmed) + end + + -- Return original if line is not commented + if new_line == nil then + return line + end + + -- Prevent trailing whitespace + if is_blank(new_line) then + indent, trail = '', '' + end + + return indent .. new_line .. trail + end +end + +--- Comment/uncomment buffer range +---@param line_start integer +---@param line_end integer +---@param ref_position? integer[] +local function toggle_lines(line_start, line_end, ref_position) + ref_position = ref_position or { line_start, 0 } + local parts = get_comment_parts(ref_position) + local lines = vim.api.nvim_buf_get_lines(0, line_start - 1, line_end, false) + local indent, is_comment = get_lines_info(lines, parts) + + local f = is_comment and make_uncomment_function(parts) or make_comment_function(parts, indent) + + -- Direct `nvim_buf_set_lines()` essentially removes both regular and + -- extended marks (squashes to empty range at either side of the region) + -- inside region. Use 'lockmarks' to preserve regular marks. + -- Preserving extmarks is not a universally good thing to do: + -- - Good for non-highlighting in text area extmarks (like showing signs). + -- - Debatable for highlighting in text area (like LSP semantic tokens). + -- Mostly because it causes flicker as highlighting is preserved during + -- comment toggling. + package.loaded['vim._comment']._lines = vim.tbl_map(f, lines) + local lua_cmd = string.format( + 'vim.api.nvim_buf_set_lines(0, %d, %d, false, package.loaded["vim._comment"]._lines)', + line_start - 1, + line_end + ) + vim.cmd.lua({ lua_cmd, mods = { lockmarks = true } }) + package.loaded['vim._comment']._lines = nil +end + +--- Operator which toggles user-supplied range of lines +---@param mode string? +---|"'line'" +---|"'char'" +---|"'block'" +local function operator(mode) + -- Used without arguments as part of expression mapping. Otherwise it is + -- called as 'operatorfunc'. + if mode == nil then + vim.o.operatorfunc = "v:lua.require'vim._comment'.operator" + return 'g@' + end + + -- Compute target range + local mark_from, mark_to = "'[", "']" + local lnum_from, col_from = vim.fn.line(mark_from), vim.fn.col(mark_from) + local lnum_to, col_to = vim.fn.line(mark_to), vim.fn.col(mark_to) + + -- Do nothing if "from" mark is after "to" (like in empty textobject) + if (lnum_from > lnum_to) or (lnum_from == lnum_to and col_from > col_to) then + return + end + + -- NOTE: use cursor position as reference for possibly computing local + -- tree-sitter-based 'commentstring'. Recompute every time for a proper + -- dot-repeat. In Visual and sometimes Normal mode it uses start position. + toggle_lines(lnum_from, lnum_to, vim.api.nvim_win_get_cursor(0)) + return '' +end + +--- Select contiguous commented lines at cursor +local function textobject() + local lnum_cur = vim.fn.line('.') + local parts = get_comment_parts({ lnum_cur, vim.fn.col('.') }) + local comment_check = make_comment_check(parts) + + if not comment_check(vim.fn.getline(lnum_cur)) then + return + end + + -- Compute commented range + local lnum_from = lnum_cur + while (lnum_from >= 2) and comment_check(vim.fn.getline(lnum_from - 1)) do + lnum_from = lnum_from - 1 + end + + local lnum_to = lnum_cur + local n_lines = vim.api.nvim_buf_line_count(0) + while (lnum_to <= n_lines - 1) and comment_check(vim.fn.getline(lnum_to + 1)) do + lnum_to = lnum_to + 1 + end + + -- Select range linewise for operator to act upon + vim.cmd('normal! ' .. lnum_from .. 'GV' .. lnum_to .. 'G') +end + +return { operator = operator, textobject = textobject, toggle_lines = toggle_lines } diff --git a/runtime/lua/vim/_defaults.lua b/runtime/lua/vim/_defaults.lua index 91baee1a1e..5b964b84a0 100644 --- a/runtime/lua/vim/_defaults.lua +++ b/runtime/lua/vim/_defaults.lua @@ -1,3 +1,31 @@ +--- Default user commands +do + vim.api.nvim_create_user_command('Inspect', function(cmd) + if cmd.bang then + vim.print(vim.inspect_pos()) + else + vim.show_pos() + end + end, { desc = 'Inspect highlights and extmarks at the cursor', bang = true }) + + vim.api.nvim_create_user_command('InspectTree', function(cmd) + if cmd.mods ~= '' or cmd.count ~= 0 then + local count = cmd.count ~= 0 and cmd.count or '' + local new = cmd.mods ~= '' and 'new' or 'vnew' + + vim.treesitter.inspect_tree({ + command = ('%s %s%s'):format(cmd.mods, count, new), + }) + else + vim.treesitter.inspect_tree() + end + end, { desc = 'Inspect treesitter language tree for buffer', count = true }) + + vim.api.nvim_create_user_command('EditQuery', function(cmd) + vim.treesitter.query.edit(cmd.fargs[1]) + end, { desc = 'Edit treesitter query', nargs = '?' }) +end + --- Default mappings do --- Default maps for * and # in visual mode. @@ -50,42 +78,126 @@ do --- See |&-default| vim.keymap.set('n', '&', ':&&<CR>', { desc = ':help &-default' }) - --- Use Q in visual mode to execute a macro on each line of the selection. #21422 + --- Use Q in Visual mode to execute a macro on each line of the selection. #21422 + --- This only make sense in linewise Visual mode. #28287 --- --- Applies to @x and includes @@ too. vim.keymap.set( 'x', 'Q', - ':normal! @<C-R>=reg_recorded()<CR><CR>', - { silent = true, desc = ':help v_Q-default' } + "mode() == 'V' ? ':normal! @<C-R>=reg_recorded()<CR><CR>' : 'Q'", + { silent = true, expr = true, desc = ':help v_Q-default' } ) vim.keymap.set( 'x', '@', - "':normal! @'.getcharstr().'<CR>'", + "mode() == 'V' ? ':normal! @'.getcharstr().'<CR>' : '@'", { silent = true, expr = true, desc = ':help v_@-default' } ) - --- Map |gx| to call |vim.ui.open| on the identifier under the cursor + + --- Map |gx| to call |vim.ui.open| on the <cfile> at cursor. do local function do_open(uri) - local _, err = vim.ui.open(uri) - if err then - vim.notify(err, vim.log.levels.ERROR) + local cmd, err = vim.ui.open(uri) + local rv = cmd and cmd:wait(1000) or nil + if cmd and rv and rv.code ~= 0 then + err = ('vim.ui.open: command %s (%d): %s'):format( + (rv.code == 124 and 'timeout' or 'failed'), + rv.code, + vim.inspect(cmd.cmd) + ) end + return err end local gx_desc = 'Opens filepath or URI under cursor with the system handler (file explorer, web browser, …)' vim.keymap.set({ 'n' }, 'gx', function() - do_open(vim.fn.expand('<cfile>')) + local err = do_open(require('vim.ui')._get_url()) + if err then + vim.notify(err, vim.log.levels.ERROR) + end end, { desc = gx_desc }) vim.keymap.set({ 'x' }, 'gx', function() local lines = vim.fn.getregion(vim.fn.getpos('.'), vim.fn.getpos('v'), { type = vim.fn.mode() }) -- Trim whitespace on each line and concatenate. - do_open(table.concat(vim.iter(lines):map(vim.trim):totable())) + local err = do_open(table.concat(vim.iter(lines):map(vim.trim):totable())) + if err then + vim.notify(err, vim.log.levels.ERROR) + end end, { desc = gx_desc }) end + + --- Default maps for built-in commenting. + --- + --- See |gc-default| and |gcc-default|. + do + local operator_rhs = function() + return require('vim._comment').operator() + end + vim.keymap.set({ 'n', 'x' }, 'gc', operator_rhs, { expr = true, desc = 'Toggle comment' }) + + local line_rhs = function() + return require('vim._comment').operator() .. '_' + end + vim.keymap.set('n', 'gcc', line_rhs, { expr = true, desc = 'Toggle comment line' }) + + local textobject_rhs = function() + require('vim._comment').textobject() + end + vim.keymap.set({ 'o' }, 'gc', textobject_rhs, { desc = 'Comment textobject' }) + end + + --- Default maps for LSP functions. + --- + --- These are mapped unconditionally to avoid different behavior depending on whether an LSP + --- 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|. + do + vim.keymap.set('n', 'grn', function() + vim.lsp.buf.rename() + end, { desc = 'vim.lsp.buf.rename()' }) + + vim.keymap.set({ 'n', 'x' }, 'gra', function() + vim.lsp.buf.code_action() + end, { desc = 'vim.lsp.buf.code_action()' }) + + vim.keymap.set('n', 'grr', function() + vim.lsp.buf.references() + end, { desc = 'vim.lsp.buf.references()' }) + + vim.keymap.set('i', '<C-S>', function() + vim.lsp.buf.signature_help() + end, { desc = 'vim.lsp.buf.signature_help()' }) + end + + --- Map [d and ]d to move to the previous/next diagnostic. Map <C-W>d to open a floating window + --- for the diagnostic under the cursor. + --- + --- See |[d-default|, |]d-default|, and |CTRL-W_d-default|. + do + vim.keymap.set('n', ']d', function() + vim.diagnostic.goto_next({ float = false }) + end, { desc = 'Jump to the next diagnostic' }) + + vim.keymap.set('n', '[d', function() + vim.diagnostic.goto_prev({ float = false }) + end, { desc = 'Jump to the previous diagnostic' }) + + vim.keymap.set('n', '<C-W>d', function() + vim.diagnostic.open_float() + end, { desc = 'Show diagnostics under the cursor' }) + + vim.keymap.set( + 'n', + '<C-W><C-D>', + '<C-W>d', + { remap = true, desc = 'Show diagnostics under the cursor' } + ) + end end --- Default menus @@ -93,7 +205,6 @@ do --- Right click popup menu -- TODO VimScript, no l10n vim.cmd([[ - aunmenu * vnoremenu PopUp.Cut "+x vnoremenu PopUp.Copy "+y anoremenu PopUp.Paste "+gP @@ -102,6 +213,7 @@ do nnoremenu PopUp.Select\ All ggVG vnoremenu PopUp.Select\ All gg0oG$ inoremenu PopUp.Select\ All <C-Home><C-O>VG + anoremenu PopUp.Inspect <Cmd>Inspect<CR> anoremenu PopUp.-1- <Nop> anoremenu PopUp.How-to\ disable\ mouse <Cmd>help disable-mouse<CR> ]]) @@ -128,7 +240,7 @@ do end local info = vim.api.nvim_get_chan_info(vim.bo[args.buf].channel) local argv = info.argv or {} - if #argv == 1 and argv[1] == vim.o.shell then + if table.concat(argv, ' ') == vim.o.shell then vim.api.nvim_buf_delete(args.buf, { force = true }) end end, @@ -136,8 +248,9 @@ do vim.api.nvim_create_autocmd('TermRequest', { group = nvim_terminal_augroup, - desc = 'Respond to OSC foreground/background color requests', + desc = 'Handles OSC foreground/background color requests', callback = function(args) + --- @type integer local channel = vim.bo[args.buf].channel if channel == 0 then return @@ -181,232 +294,146 @@ do return end vim.v.swapchoice = 'e' -- Choose "(E)dit". - vim.notify(('W325: Ignoring swapfile from Nvim process %d'):format(info.pid)) + vim.notify( + ('W325: Ignoring swapfile from Nvim process %d'):format(info.pid), + vim.log.levels.WARN + ) end, }) -end - --- Only do the following when the TUI is attached -local tty = nil -for _, ui in ipairs(vim.api.nvim_list_uis()) do - if ui.chan == 1 and ui.stdout_tty then - tty = ui - break - end -end -if tty then - local group = vim.api.nvim_create_augroup('nvim_tty', {}) - - --- Set an option after startup (so that OptionSet is fired), but only if not - --- already set by the user. - --- - --- @param option string Option name - --- @param value any Option value - local function setoption(option, value) - if vim.api.nvim_get_option_info2(option, {}).was_set then - -- Don't do anything if option is already set - return - end - - -- Wait until Nvim is finished starting to set the option to ensure the - -- OptionSet event fires. - if vim.v.vim_did_enter == 1 then - vim.o[option] = value - else - vim.api.nvim_create_autocmd('VimEnter', { - group = group, - once = true, - nested = true, - callback = function() - setoption(option, value) - end, - }) + -- Only do the following when the TUI is attached + local tty = nil + for _, ui in ipairs(vim.api.nvim_list_uis()) do + if ui.chan == 1 and ui.stdout_tty then + tty = ui + break end end - --- Guess value of 'background' based on terminal color. - --- - --- We write Operating System Command (OSC) 11 to the terminal to request the - --- terminal's background color. We then wait for a response. If the response - --- matches `rgba:RRRR/GGGG/BBBB/AAAA` where R, G, B, and A are hex digits, then - --- compute the luminance[1] of the RGB color and classify it as light/dark - --- accordingly. Note that the color components may have anywhere from one to - --- four hex digits, and require scaling accordingly as values out of 4, 8, 12, - --- or 16 bits. Also note the A(lpha) component is optional, and is parsed but - --- ignored in the calculations. - --- - --- [1] https://en.wikipedia.org/wiki/Luma_%28video%29 - do - --- Parse a string of hex characters as a color. - --- - --- The string can contain 1 to 4 hex characters. The returned value is - --- between 0.0 and 1.0 (inclusive) representing the intensity of the color. - --- - --- For instance, if only a single hex char "a" is used, then this function - --- returns 0.625 (10 / 16), while a value of "aa" would return 0.664 (170 / - --- 256). + if tty then + local group = vim.api.nvim_create_augroup('nvim_tty', {}) + + --- Set an option after startup (so that OptionSet is fired), but only if not + --- already set by the user. --- - --- @param c string Color as a string of hex chars - --- @return number? Intensity of the color - local function parsecolor(c) - if #c == 0 or #c > 4 then - return nil + --- @param option string Option name + --- @param value any Option value + local function setoption(option, value) + if vim.api.nvim_get_option_info2(option, {}).was_set then + -- Don't do anything if option is already set + return end - local val = tonumber(c, 16) - if not val then - return nil + -- Wait until Nvim is finished starting to set the option to ensure the + -- OptionSet event fires. + if vim.v.vim_did_enter == 1 then + --- @diagnostic disable-next-line:no-unknown + vim.o[option] = value + else + vim.api.nvim_create_autocmd('VimEnter', { + group = group, + once = true, + nested = true, + callback = function() + setoption(option, value) + end, + }) end - - local max = tonumber(string.rep('f', #c), 16) - return val / max end - --- Parse an OSC 11 response - --- - --- Either of the two formats below are accepted: - --- - --- OSC 11 ; rgb:<red>/<green>/<blue> - --- - --- or + --- Guess value of 'background' based on terminal color. --- - --- OSC 11 ; rgba:<red>/<green>/<blue>/<alpha> + --- We write Operating System Command (OSC) 11 to the terminal to request the + --- terminal's background color. We then wait for a response. If the response + --- matches `rgba:RRRR/GGGG/BBBB/AAAA` where R, G, B, and A are hex digits, then + --- compute the luminance[1] of the RGB color and classify it as light/dark + --- accordingly. Note that the color components may have anywhere from one to + --- four hex digits, and require scaling accordingly as values out of 4, 8, 12, + --- or 16 bits. Also note the A(lpha) component is optional, and is parsed but + --- ignored in the calculations. --- - --- where - --- - --- <red>, <green>, <blue>, <alpha> := h | hh | hhh | hhhh - --- - --- The alpha component is ignored, if present. - --- - --- @param resp string OSC 11 response - --- @return string? Red component - --- @return string? Green component - --- @return string? Blue component - local function parseosc11(resp) - local r, g, b - r, g, b = resp:match('^\027%]11;rgb:(%x+)/(%x+)/(%x+)$') - if not r and not g and not b then - local a - r, g, b, a = resp:match('^\027%]11;rgba:(%x+)/(%x+)/(%x+)/(%x+)$') - if not a or #a > 4 then - return nil, nil, nil + --- [1] https://en.wikipedia.org/wiki/Luma_%28video%29 + do + --- Parse a string of hex characters as a color. + --- + --- The string can contain 1 to 4 hex characters. The returned value is + --- between 0.0 and 1.0 (inclusive) representing the intensity of the color. + --- + --- For instance, if only a single hex char "a" is used, then this function + --- returns 0.625 (10 / 16), while a value of "aa" would return 0.664 (170 / + --- 256). + --- + --- @param c string Color as a string of hex chars + --- @return number? Intensity of the color + local function parsecolor(c) + if #c == 0 or #c > 4 then + return nil end - end - if r and g and b and #r <= 4 and #g <= 4 and #b <= 4 then - return r, g, b - end - - return nil, nil, nil - end - - local timer = assert(vim.uv.new_timer()) - - local id = vim.api.nvim_create_autocmd('TermResponse', { - group = group, - nested = true, - callback = function(args) - local resp = args.data ---@type string - local r, g, b = parseosc11(resp) - if r and g and b then - local rr = parsecolor(r) - local gg = parsecolor(g) - local bb = parsecolor(b) - - if rr and gg and bb then - local luminance = (0.299 * rr) + (0.587 * gg) + (0.114 * bb) - local bg = luminance < 0.5 and 'dark' or 'light' - setoption('background', bg) - end - - return true + local val = tonumber(c, 16) + if not val then + return nil end - end, - }) - - io.stdout:write('\027]11;?\007') - timer:start(1000, 0, function() - -- Delete the autocommand if no response was received - vim.schedule(function() - -- Suppress error if autocommand has already been deleted - pcall(vim.api.nvim_del_autocmd, id) - end) - - if not timer:is_closing() then - timer:close() + local max = tonumber(string.rep('f', #c), 16) + return val / max end - end) - end - --- If the TUI (term_has_truecolor) was able to determine that the host - --- terminal supports truecolor, enable 'termguicolors'. Otherwise, query the - --- terminal (using both XTGETTCAP and SGR + DECRQSS). If the terminal's - --- response indicates that it does support truecolor enable 'termguicolors', - --- but only if the user has not already disabled it. - do - if tty.rgb then - -- The TUI was able to determine truecolor support - setoption('termguicolors', true) - else - local caps = {} ---@type table<string, boolean> - require('vim.termcap').query({ 'Tc', 'RGB', 'setrgbf', 'setrgbb' }, function(cap, found) - if not found then - return + --- Parse an OSC 11 response + --- + --- Either of the two formats below are accepted: + --- + --- OSC 11 ; rgb:<red>/<green>/<blue> + --- + --- or + --- + --- OSC 11 ; rgba:<red>/<green>/<blue>/<alpha> + --- + --- where + --- + --- <red>, <green>, <blue>, <alpha> := h | hh | hhh | hhhh + --- + --- The alpha component is ignored, if present. + --- + --- @param resp string OSC 11 response + --- @return string? Red component + --- @return string? Green component + --- @return string? Blue component + local function parseosc11(resp) + local r, g, b + r, g, b = resp:match('^\027%]11;rgb:(%x+)/(%x+)/(%x+)$') + if not r and not g and not b then + local a + r, g, b, a = resp:match('^\027%]11;rgba:(%x+)/(%x+)/(%x+)/(%x+)$') + if not a or #a > 4 then + return nil, nil, nil + end end - caps[cap] = true - if caps.Tc or caps.RGB or (caps.setrgbf and caps.setrgbb) then - setoption('termguicolors', true) + if r and g and b and #r <= 4 and #g <= 4 and #b <= 4 then + return r, g, b end - end) - local timer = assert(vim.uv.new_timer()) + return nil, nil, nil + end - -- Arbitrary colors to set in the SGR sequence - local r = 1 - local g = 2 - local b = 3 + local timer = assert(vim.uv.new_timer()) local id = vim.api.nvim_create_autocmd('TermResponse', { group = group, nested = true, callback = function(args) local resp = args.data ---@type string - local decrqss = resp:match('^\027P1%$r([%d;:]+)m$') - - if decrqss then - -- The DECRQSS SGR response first contains attributes separated by - -- semicolons, followed by the SGR itself with parameters separated - -- by colons. Some terminals include "0" in the attribute list - -- unconditionally; others do not. Our SGR sequence did not set any - -- attributes, so there should be no attributes in the list. - local attrs = vim.split(decrqss, ';') - if #attrs ~= 1 and (#attrs ~= 2 or attrs[1] ~= '0') then - return true - end - - -- The returned SGR sequence should begin with 48:2 - local sgr = attrs[#attrs]:match('^48:2:([%d:]+)$') - if not sgr then - return true - end - - -- The remaining elements of the SGR sequence should be the 3 colors - -- we set. Some terminals also include an additional parameter - -- (which can even be empty!), so handle those cases as well - local params = vim.split(sgr, ':') - if #params ~= 3 and (#params ~= 4 or (params[1] ~= '' and params[1] ~= '1')) then - return true - end - - if - tonumber(params[#params - 2]) == r - and tonumber(params[#params - 1]) == g - and tonumber(params[#params]) == b - then - setoption('termguicolors', true) + local r, g, b = parseosc11(resp) + if r and g and b then + local rr = parsecolor(r) + local gg = parsecolor(g) + local bb = parsecolor(b) + + if rr and gg and bb then + local luminance = (0.299 * rr) + (0.587 * gg) + (0.114 * bb) + local bg = luminance < 0.5 and 'dark' or 'light' + setoption('background', bg) end return true @@ -414,15 +441,7 @@ if tty then end, }) - -- Write SGR followed by DECRQSS. This sets the background color then - -- immediately asks the terminal what the background color is. If the - -- terminal responds to the DECRQSS with the same SGR sequence that we - -- sent then the terminal supports truecolor. - local decrqss = '\027P$qm\027\\' - if os.getenv('TMUX') then - decrqss = string.format('\027Ptmux;%s\027\\', decrqss:gsub('\027', '\027\027')) - end - io.stdout:write(string.format('\027[48;2;%d;%d;%dm%s', r, g, b, decrqss)) + io.stdout:write('\027]11;?\007') timer:start(1000, 0, function() -- Delete the autocommand if no response was received @@ -436,5 +455,114 @@ if tty then end end) end + + --- If the TUI (term_has_truecolor) was able to determine that the host + --- terminal supports truecolor, enable 'termguicolors'. Otherwise, query the + --- terminal (using both XTGETTCAP and SGR + DECRQSS). If the terminal's + --- response indicates that it does support truecolor enable 'termguicolors', + --- but only if the user has not already disabled it. + do + if tty.rgb then + -- The TUI was able to determine truecolor support + setoption('termguicolors', true) + else + local caps = {} ---@type table<string, boolean> + require('vim.termcap').query({ 'Tc', 'RGB', 'setrgbf', 'setrgbb' }, function(cap, found) + if not found then + return + end + + caps[cap] = true + if caps.Tc or caps.RGB or (caps.setrgbf and caps.setrgbb) then + setoption('termguicolors', true) + end + end) + + local timer = assert(vim.uv.new_timer()) + + -- Arbitrary colors to set in the SGR sequence + local r = 1 + local g = 2 + local b = 3 + + local id = vim.api.nvim_create_autocmd('TermResponse', { + group = group, + nested = true, + callback = function(args) + local resp = args.data ---@type string + local decrqss = resp:match('^\027P1%$r([%d;:]+)m$') + + if decrqss then + -- The DECRQSS SGR response first contains attributes separated by + -- semicolons, followed by the SGR itself with parameters separated + -- by colons. Some terminals include "0" in the attribute list + -- unconditionally; others do not. Our SGR sequence did not set any + -- attributes, so there should be no attributes in the list. + local attrs = vim.split(decrqss, ';') + if #attrs ~= 1 and (#attrs ~= 2 or attrs[1] ~= '0') then + return false + end + + -- The returned SGR sequence should begin with 48:2 + local sgr = attrs[#attrs]:match('^48:2:([%d:]+)$') + if not sgr then + return false + end + + -- The remaining elements of the SGR sequence should be the 3 colors + -- we set. Some terminals also include an additional parameter + -- (which can even be empty!), so handle those cases as well + local params = vim.split(sgr, ':') + if #params ~= 3 and (#params ~= 4 or (params[1] ~= '' and params[1] ~= '1')) then + return true + end + + if + tonumber(params[#params - 2]) == r + and tonumber(params[#params - 1]) == g + and tonumber(params[#params]) == b + then + setoption('termguicolors', true) + end + + return true + end + end, + }) + + -- Write SGR followed by DECRQSS. This sets the background color then + -- immediately asks the terminal what the background color is. If the + -- terminal responds to the DECRQSS with the same SGR sequence that we + -- sent then the terminal supports truecolor. + local decrqss = '\027P$qm\027\\' + if os.getenv('TMUX') then + decrqss = string.format('\027Ptmux;%s\027\\', decrqss:gsub('\027', '\027\027')) + end + -- Reset attributes first, as other code may have set attributes. + io.stdout:write(string.format('\027[0m\027[48;2;%d;%d;%dm%s', r, g, b, decrqss)) + + timer:start(1000, 0, function() + -- Delete the autocommand if no response was received + vim.schedule(function() + -- Suppress error if autocommand has already been deleted + pcall(vim.api.nvim_del_autocmd, id) + end) + + if not timer:is_closing() then + timer:close() + end + end) + end + end + end +end + +--- Default options +do + --- Default 'grepprg' to ripgrep if available. + if vim.fn.executable('rg') == 1 then + -- Use -uu to make ripgrep not check ignore files/skip dot-files + vim.o.grepprg = 'rg --vimgrep -uu ' + vim.o.grepformat = '%f:%l:%c:%m' end end diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 6cf77b4648..5e9be509c8 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -74,7 +74,6 @@ vim.log = { --- Examples: --- --- ```lua ---- --- local on_exit = function(obj) --- print(obj.code) --- print(obj.signal) @@ -122,6 +121,7 @@ vim.log = { --- asynchronously. Receives SystemCompleted object, see return of SystemObj:wait(). --- --- @return vim.SystemObj Object with the fields: +--- - cmd (string[]) Command name and args --- - pid (integer) Process ID --- - wait (fun(timeout: integer|nil): SystemCompleted) Wait for the process to complete. Upon --- timeout the process is sent the KILL signal (9) and the exit code is set to 124. Cannot @@ -655,11 +655,14 @@ local on_key_cbs = {} --- @type table<integer,function> --- ---@note {fn} will be removed on error. ---@note {fn} will not be cleared by |nvim_buf_clear_namespace()| ----@note {fn} will receive the keys after mappings have been evaluated --- ----@param fn fun(key: string)? Function invoked on every key press. |i_CTRL-V| ---- Passing in nil when {ns_id} is specified removes the ---- callback associated with namespace {ns_id}. +---@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 ns_id integer? Namespace ID. If nil or 0, generates and returns a --- new |nvim_create_namespace()| id. --- @@ -685,11 +688,11 @@ end --- Executes the on_key callbacks. ---@private -function vim._on_key(char) +function vim._on_key(buf, typed_buf) local failed_ns_ids = {} local failed_messages = {} for k, v in pairs(on_key_cbs) do - local ok, err_msg = pcall(v, char) + local ok, err_msg = pcall(v, buf, typed_buf) if not ok then vim.on_key(nil, k) table.insert(failed_ns_ids, k) @@ -1028,6 +1031,42 @@ function vim._cs_remote(rcid, server_addr, connect_error, args) } end +do + local function truncated_echo(msg) + -- Truncate message to avoid hit-enter-prompt + local max_width = vim.o.columns * math.max(vim.o.cmdheight - 1, 0) + vim.v.echospace + local msg_truncated = string.sub(msg, 1, max_width) + vim.api.nvim_echo({ { msg_truncated, 'WarningMsg' } }, true, {}) + end + + local notified = false + + function vim._truncated_echo_once(msg) + if not notified then + truncated_echo(msg) + notified = true + return true + end + return false + end +end + +--- This is basically the same as debug.traceback(), except the full paths are shown. +local function traceback() + local level = 4 + local backtrace = { 'stack traceback:' } + while true do + local info = debug.getinfo(level, 'Sl') + if not info then + break + end + local msg = (' %s:%s'):format(info.source:sub(2), info.currentline) + table.insert(backtrace, msg) + level = level + 1 + end + return table.concat(backtrace, '\n') +end + --- Shows a deprecation message to the user. --- ---@param name string Deprecated feature (function, API, etc.). @@ -1039,55 +1078,46 @@ end --- ---@return string|nil # Deprecated message, or nil if no message was shown. function vim.deprecate(name, alternative, version, plugin, backtrace) - vim.validate { - name = { name, 'string' }, - alternative = { alternative, 'string', true }, - version = { version, 'string', true }, - plugin = { plugin, 'string', true }, - } plugin = plugin or 'Nvim' - - -- Only issue warning if feature is hard-deprecated as specified by MAINTAIN.md. - -- e.g., when planned to be removed in version = '0.12' (soft-deprecated since 0.10-dev), - -- show warnings since 0.11, including 0.11-dev (hard_deprecated_since = 0.11-dev). if plugin == 'Nvim' then - local current_version = vim.version() ---@type vim.Version - local removal_version = assert(vim.version.parse(version)) - local is_hard_deprecated ---@type boolean - - if removal_version.minor > 0 then - local hard_deprecated_since = assert(vim.version._version({ - major = removal_version.major, - minor = removal_version.minor - 1, - patch = 0, - prerelease = 'dev', -- Show deprecation warnings in devel (nightly) version as well - })) - is_hard_deprecated = (current_version >= hard_deprecated_since) - else - -- Assume there will be no next minor version before bumping up the major version; - -- therefore we can always show a warning. - assert(removal_version.minor == 0, vim.inspect(removal_version)) - is_hard_deprecated = true - end + 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 + local major, minor = version:match('(%d+)%.(%d+)') + major, minor = tonumber(major), tonumber(minor) + 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 return end - end - local msg = ('%s is deprecated'):format(name) - msg = alternative and ('%s, use %s instead.'):format(msg, alternative) or (msg .. '.') - msg = ('%s%s\nThis feature will be removed in %s version %s'):format( - msg, - (plugin == 'Nvim' and ' :help deprecated' or ''), - plugin, - version - ) - local displayed = vim.notify_once(msg, vim.log.levels.WARN) - if displayed and backtrace ~= false then - vim.notify(debug.traceback('', 2):sub(2), vim.log.levels.WARN) + local msg = ('%s is deprecated. Run ":checkhealth vim.deprecated" for more information'):format( + name + ) + + 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 }, + } + + local msg = ('%s is deprecated'):format(name) + msg = alternative and ('%s, use %s instead.'):format(msg, alternative) or (msg .. '.') + msg = ('%s\nFeature will be removed in %s %s'):format(msg, plugin, version) + local displayed = vim.notify_once(msg, vim.log.levels.WARN) + if displayed and backtrace ~= false then + vim.notify(debug.traceback('', 2):sub(2), vim.log.levels.WARN) + end + return displayed and msg or nil end - return displayed and msg or nil end require('vim._options') diff --git a/runtime/lua/vim/_inspector.lua b/runtime/lua/vim/_inspector.lua index afbd6211cd..f5d1640c82 100644 --- a/runtime/lua/vim/_inspector.lua +++ b/runtime/lua/vim/_inspector.lua @@ -55,8 +55,8 @@ function vim.inspect_pos(bufnr, row, col, filter) bufnr = bufnr == 0 and vim.api.nvim_get_current_buf() or bufnr local results = { - treesitter = {}, - syntax = {}, + treesitter = {}, --- @type table[] + syntax = {}, --- @type table[] extmarks = {}, semantic_tokens = {}, buffer = bufnr, @@ -93,7 +93,7 @@ function vim.inspect_pos(bufnr, row, col, filter) end -- namespace id -> name map - local nsmap = {} + local nsmap = {} --- @type table<integer,string> for name, id in pairs(vim.api.nvim_get_namespaces()) do nsmap[id] = name end diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index cb4c8749b8..6edf2a5a96 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -14,14 +14,21 @@ function vim.api.nvim__buf_debug_extmarks(buffer, keys, dot) end --- @private --- @param buffer integer ---- @param first integer ---- @param last integer -function vim.api.nvim__buf_redraw_range(buffer, first, last) end +--- @return table<string,any> +function vim.api.nvim__buf_stats(buffer) end --- @private ---- @param buffer integer +--- EXPERIMENTAL: this API may change in the future. +--- +--- Sets info for the completion item at the given index. If the info text was +--- shown in a window, returns the window and buffer ids, or empty dict if not +--- shown. +--- +--- @param index integer Completion candidate index +--- @param opts vim.api.keyset.complete_set Optional parameters. +--- • info: (string) info text. --- @return table<string,any> -function vim.api.nvim__buf_stats(buffer) end +function vim.api.nvim__complete_set(index, opts) end --- @private --- @return string @@ -93,6 +100,32 @@ function vim.api.nvim__inspect_cell(grid, row, col) end function vim.api.nvim__invalidate_glyph_cache() end --- @private +--- EXPERIMENTAL: this API may change in the future. +--- +--- Instruct Nvim to redraw various components. +--- +--- @param opts vim.api.keyset.redraw Optional parameters. +--- • win: Target a specific `window-ID` as described below. +--- • buf: Target a specific buffer number as described below. +--- • flush: Update the screen with pending updates. +--- • valid: When present mark `win`, `buf`, or all windows for +--- redraw. When `true`, only redraw changed lines (useful for +--- decoration providers). When `false`, forcefully redraw. +--- • range: Redraw a range in `buf`, the buffer in `win` or the +--- current buffer (useful for decoration providers). Expects a +--- tuple `[first, last]` with the first and last line number of +--- the range, 0-based end-exclusive `api-indexing`. +--- • cursor: Immediately update cursor position on the screen in +--- `win` or the current window. +--- • statuscolumn: Redraw the 'statuscolumn' in `buf`, `win` or +--- all windows. +--- • statusline: Redraw the 'statusline' in `buf`, `win` or all +--- windows. +--- • winbar: Redraw the 'winbar' in `buf`, `win` or all windows. +--- • tabline: Redraw the 'tabline'. +function vim.api.nvim__redraw(opts) end + +--- @private --- @return any[] function vim.api.nvim__runtime_inspect() end @@ -111,6 +144,36 @@ function vim.api.nvim__stats() end --- @return any function vim.api.nvim__unpack(str) end +--- @private +--- EXPERIMENTAL: this API will change in the future. +--- +--- Scopes a namespace to the a window, so extmarks in the namespace will be +--- active only in the given window. +--- +--- @param window integer Window handle, or 0 for current window +--- @param ns_id integer Namespace +--- @return boolean +function vim.api.nvim__win_add_ns(window, ns_id) end + +--- @private +--- EXPERIMENTAL: this API will change in the future. +--- +--- Unscopes a namespace (un-binds it from the given scope). +--- +--- @param window integer Window handle, or 0 for current window +--- @param ns_id integer the namespace to remove +--- @return boolean +function vim.api.nvim__win_del_ns(window, ns_id) end + +--- @private +--- EXPERIMENTAL: this API will change in the future. +--- +--- Gets the namespace scopes for a given window. +--- +--- @param window integer Window handle, or 0 for current window +--- @return integer[] +function vim.api.nvim__win_get_ns(window) end + --- Adds a highlight to buffer. --- --- Useful for plugins that dynamically generate highlights to a buffer (like @@ -623,8 +686,8 @@ function vim.api.nvim_buf_line_count(buffer) end --- • url: A URL to associate with this extmark. In the TUI, the --- OSC 8 control sequence is used to generate a clickable --- hyperlink to this URL. ---- • scoped: boolean that indicates that the extmark should only ---- be displayed in the namespace scope. (experimental) +--- • scoped: boolean (EXPERIMENTAL) enables "scoping" for the +--- extmark. See `nvim__win_add_ns()` --- @return integer function vim.api.nvim_buf_set_extmark(buffer, ns_id, line, col, opts) end @@ -669,7 +732,7 @@ function vim.api.nvim_buf_set_lines(buffer, start, end_, strict_indexing, replac --- @return boolean function vim.api.nvim_buf_set_mark(buffer, name, line, col, opts) end ---- Sets the full file name for a buffer +--- Sets the full file name for a buffer, like `:file_f` --- --- @param buffer integer Buffer handle, or 0 for current buffer --- @param name string Buffer name @@ -822,16 +885,6 @@ function vim.api.nvim_command(command) end --- @return string function vim.api.nvim_command_output(command) end ---- Set info for the completion candidate index. if the info was shown in a ---- window, then the window and buffer ids are returned for further ---- customization. If the text was not shown, an empty dict is returned. ---- ---- @param index integer the completion candidate index ---- @param opts vim.api.keyset.complete_set Optional parameters. ---- • info: (string) info text. ---- @return table<string,any> -function vim.api.nvim_complete_set(index, opts) end - --- Create or get an autocommand group `autocmd-groups`. --- --- To get an existing group id, do: @@ -897,8 +950,8 @@ function vim.api.nvim_create_augroup(name, opts) end --- • callback (function|string) optional: Lua function (or --- Vimscript function name, if string) called when the event(s) --- is triggered. Lua callback can return a truthy value (not ---- `false` or `nil`) to delete the autocommand. Receives a ---- table argument with these keys: +--- `false` or `nil`) to delete the autocommand. Receives one +--- argument, a table with these keys: *event-args* --- • id: (number) autocommand id --- • event: (string) name of the triggered event --- `autocmd-events` @@ -907,7 +960,7 @@ function vim.api.nvim_create_augroup(name, opts) end --- • buf: (number) expanded value of <abuf> --- • file: (string) expanded value of <afile> --- • data: (any) arbitrary data passed from ---- `nvim_exec_autocmds()` +--- `nvim_exec_autocmds()` *event-data* --- • command (string) optional: Vim command to execute on event. --- Cannot be used with {callback} --- • once (boolean) optional: defaults to false. Run the @@ -1718,9 +1771,8 @@ function vim.api.nvim_open_term(buffer, opts) end --- • footer_pos: Footer position. Must be set with `footer` --- option. Value can be one of "left", "center", or "right". --- Default is `"left"`. ---- • noautocmd: If true then no buffer-related autocommand ---- events such as `BufEnter`, `BufLeave` or `BufWinEnter` may ---- fire from calling this function. +--- • noautocmd: If true then all autocommands are blocked for +--- the duration of the call. --- • fixed: If true when anchor is NW or SW, the float window --- would be kept fixed even if the window would be truncated. --- • hide: If true the floating window will be hidden. @@ -2092,13 +2144,6 @@ function vim.api.nvim_tabpage_set_var(tabpage, name, value) end --- @param win integer Window handle, must already belong to {tabpage} function vim.api.nvim_tabpage_set_win(tabpage, win) end ---- Adds the namespace scope to the window. ---- ---- @param window integer Window handle, or 0 for current window ---- @param ns_id integer the namespace to add ---- @return boolean -function vim.api.nvim_win_add_ns(window, ns_id) end - --- Calls a function with window as temporary current window. --- --- @param window integer Window handle, or 0 for current window @@ -2151,12 +2196,6 @@ function vim.api.nvim_win_get_cursor(window) end --- @return integer function vim.api.nvim_win_get_height(window) end ---- Gets all the namespaces scopes associated with a window. ---- ---- @param window integer Window handle, or 0 for current window ---- @return integer[] -function vim.api.nvim_win_get_ns(window) end - --- Gets the window number --- --- @param window integer Window handle, or 0 for current window @@ -2210,24 +2249,17 @@ function vim.api.nvim_win_hide(window) end --- @return boolean function vim.api.nvim_win_is_valid(window) end ---- Removes the namespace scope from the window. ---- ---- @param window integer Window handle, or 0 for current window ---- @param ns_id integer the namespace to remove ---- @return boolean -function vim.api.nvim_win_remove_ns(window, ns_id) end - --- Sets the current buffer in a window, without side effects --- --- @param window integer Window handle, or 0 for current window --- @param buffer integer Buffer handle function vim.api.nvim_win_set_buf(window, buffer) end ---- Configures window layout. Currently only for floating and external windows ---- (including changing a split window to those layouts). +--- Configures window layout. Cannot be used to move the last window in a +--- tabpage to a different one. --- ---- When reconfiguring a floating window, absent option keys will not be ---- changed. `row`/`col` and `relative` must be reconfigured together. +--- When reconfiguring a window, absent option keys will not be changed. +--- `row`/`col` and `relative` must be reconfigured together. --- --- @param window integer Window handle, or 0 for current window --- @param config vim.api.keyset.win_config Map defining the window configuration, see `nvim_open_win()` diff --git a/runtime/lua/vim/_meta/api_keysets.lua b/runtime/lua/vim/_meta/api_keysets.lua index 37e4372196..f7cd92a3b2 100644 --- a/runtime/lua/vim/_meta/api_keysets.lua +++ b/runtime/lua/vim/_meta/api_keysets.lua @@ -207,6 +207,18 @@ error('Cannot require a meta file') --- @field buf? integer --- @field filetype? string +--- @class vim.api.keyset.redraw +--- @field flush? boolean +--- @field cursor? boolean +--- @field valid? boolean +--- @field statuscolumn? boolean +--- @field statusline? boolean +--- @field tabline? boolean +--- @field winbar? boolean +--- @field range? any[] +--- @field win? integer +--- @field buf? integer + --- @class vim.api.keyset.runtime --- @field is_lua? boolean --- @field do_source? boolean @@ -253,7 +265,6 @@ error('Cannot require a meta file') --- @field undo_restore? boolean --- @field url? string --- @field scoped? boolean ---- @field _subpriority? integer --- @class vim.api.keyset.user_command --- @field addr? any diff --git a/runtime/lua/vim/_meta/api_keysets_extra.lua b/runtime/lua/vim/_meta/api_keysets_extra.lua index d61dd2c02f..76b56b04e7 100644 --- a/runtime/lua/vim/_meta/api_keysets_extra.lua +++ b/runtime/lua/vim/_meta/api_keysets_extra.lua @@ -124,7 +124,7 @@ error('Cannot require a meta file') --- @field commalist boolean --- @field flaglist boolean --- @field was_set boolean ---- @field last_set_id integer +--- @field last_set_sid integer --- @field last_set_linenr integer --- @field last_set_chan integer --- @field type 'string'|'boolean'|'number' diff --git a/runtime/lua/vim/_meta/base64.lua b/runtime/lua/vim/_meta/base64.lua index f25b4af234..8ba59e1703 100644 --- a/runtime/lua/vim/_meta/base64.lua +++ b/runtime/lua/vim/_meta/base64.lua @@ -3,11 +3,11 @@ --- Encode {str} using Base64. --- --- @param str string String to encode ---- @return string Encoded string +--- @return string : Encoded string function vim.base64.encode(str) end --- Decode a Base64 encoded string. --- --- @param str string Base64 encoded string ---- @return string Decoded string +--- @return string : Decoded string function vim.base64.decode(str) end diff --git a/runtime/lua/vim/_meta/builtin.lua b/runtime/lua/vim/_meta/builtin.lua index 9a67667f02..75737bd040 100644 --- a/runtime/lua/vim/_meta/builtin.lua +++ b/runtime/lua/vim/_meta/builtin.lua @@ -115,19 +115,19 @@ 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 by |vim.str_byteindex()|. +--- 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 number ---- @param use_utf16? any +--- @param index integer +--- @param use_utf16? boolean 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. --- @param str string ---- @return table +--- @return integer[] function vim.str_utf_pos(str) end --- Gets the distance (in bytes) from the starting byte of the codepoint (character) that {index} @@ -148,8 +148,8 @@ function vim.str_utf_pos(str) end --- ``` --- --- @param str string ---- @param index number ---- @return number +--- @param index integer +--- @return integer function vim.str_utf_start(str, index) end --- Gets the distance (in bytes) from the last byte of the codepoint (character) that {index} points @@ -168,8 +168,8 @@ function vim.str_utf_start(str, index) end --- ``` --- --- @param str string ---- @param index number ---- @return number +--- @param index integer +--- @return integer function vim.str_utf_end(str, index) end --- Convert byte index to UTF-32 and UTF-16 indices. If {index} is not @@ -180,7 +180,7 @@ function vim.str_utf_end(str, index) end --- {index} in the middle of a UTF-8 sequence is rounded upwards to the end of --- that sequence. --- @param str string ---- @param index? number +--- @param index? integer --- @return integer UTF-32 index --- @return integer UTF-16 index function vim.str_utfindex(str, index) end @@ -193,15 +193,14 @@ function vim.str_utfindex(str, index) end --- can accept, see ":Man 3 iconv". --- --- @param str string Text to convert ---- @param from number Encoding of {str} ---- @param to number Target encoding ---- @param opts? table<string,any> ---- @return string|nil Converted string if conversion succeeds, `nil` otherwise. +--- @param from string Encoding of {str} +--- @param to string Target encoding +--- @return string? : Converted string if conversion succeeds, `nil` otherwise. function vim.iconv(str, from, to, opts) end --- Schedules {fn} to be invoked soon by the main event-loop. Useful --- to avoid |textlock| or other temporary restrictions. ---- @param fn function +--- @param fn fun() function vim.schedule(fn) end --- Wait for {time} in milliseconds until {callback} returns `true`. @@ -215,7 +214,6 @@ function vim.schedule(fn) end --- Examples: --- --- ```lua ---- --- --- --- -- Wait for 100 ms, allowing other events to process --- vim.wait(100, function() end) diff --git a/runtime/lua/vim/_meta/builtin_types.lua b/runtime/lua/vim/_meta/builtin_types.lua index 0bbc3e9bc8..9f0d2e7038 100644 --- a/runtime/lua/vim/_meta/builtin_types.lua +++ b/runtime/lua/vim/_meta/builtin_types.lua @@ -127,3 +127,11 @@ --- @field skipcol integer --- @field topfill integer --- @field topline integer + +--- @class vim.fn.getscriptinfo.ret +--- @field autoload false +--- @field functions? string[] +--- @field name string +--- @field sid string +--- @field variables? table<string, any> +--- @field version 1 diff --git a/runtime/lua/vim/_meta/diff.lua b/runtime/lua/vim/_meta/diff.lua index f265139448..617bc87f59 100644 --- a/runtime/lua/vim/_meta/diff.lua +++ b/runtime/lua/vim/_meta/diff.lua @@ -1,5 +1,46 @@ ---@meta +--- Optional parameters: +--- @class vim.diff.Opts +--- @inlinedoc +--- +--- Invoked for each hunk in the diff. Return a negative number +--- to cancel the callback for any remaining hunks. +--- Arguments: +--- - `start_a` (`integer`): Start line of hunk in {a}. +--- - `count_a` (`integer`): Hunk size in {a}. +--- - `start_b` (`integer`): Start line of hunk in {b}. +--- - `count_b` (`integer`): Hunk size in {b}. +--- @field on_hunk fun(start_a: integer, count_a: integer, start_b: integer, count_b: integer): integer +--- +--- Form of the returned diff: +--- - `unified`: String in unified format. +--- - `indices`: Array of hunk locations. +--- Note: This option is ignored if `on_hunk` is used. +--- (default: `'unified'`) +--- @field result_type 'unified'|'indices' +--- +--- Run linematch on the resulting hunks from xdiff. When integer, only hunks +--- upto this size in lines are run through linematch. +--- Requires `result_type = indices`, ignored otherwise. +--- @field linematch boolean|integer +--- +--- Diff algorithm to use. Values: +--- - `myers`: the default algorithm +--- - `minimal`: spend extra time to generate the smallest possible diff +--- - `patience`: patience diff algorithm +--- - `histogram`: histogram diff algorithm +--- (default: `'myers'`) +--- @field algorithm 'myers'|'minimal'|'patience'|'histogram' +--- @field ctxlen integer Context length +--- @field interhunkctxlen integer Inter hunk context length +--- @field ignore_whitespace boolean Ignore whitespace +--- @field ignore_whitespace_change boolean Ignore whitespace change +--- @field ignore_whitespace_change_at_eol boolean Ignore whitespace change at end-of-line. +--- @field ignore_cr_at_eol boolean Ignore carriage return at end-of-line +--- @field ignore_blank_lines boolean Ignore blank lines +--- @field indent_heuristic boolean Use the indent heuristic for the internal diff library. + -- luacheck: no unused args --- Run diff on strings {a} and {b}. Any indices returned by this function, @@ -24,47 +65,7 @@ --- ---@param a string First string to compare ---@param b string Second string to compare ----@param opts table<string,any> Optional parameters: ---- - `on_hunk` (callback): ---- Invoked for each hunk in the diff. Return a negative number ---- to cancel the callback for any remaining hunks. ---- Args: ---- - `start_a` (integer): Start line of hunk in {a}. ---- - `count_a` (integer): Hunk size in {a}. ---- - `start_b` (integer): Start line of hunk in {b}. ---- - `count_b` (integer): Hunk size in {b}. ---- - `result_type` (string): Form of the returned diff: ---- - "unified": (default) String in unified format. ---- - "indices": Array of hunk locations. ---- Note: This option is ignored if `on_hunk` is used. ---- - `linematch` (boolean|integer): Run linematch on the resulting hunks ---- from xdiff. When integer, only hunks upto this size in ---- lines are run through linematch. Requires `result_type = indices`, ---- ignored otherwise. ---- - `algorithm` (string): ---- Diff algorithm to use. Values: ---- - "myers" the default algorithm ---- - "minimal" spend extra time to generate the ---- smallest possible diff ---- - "patience" patience diff algorithm ---- - "histogram" histogram diff algorithm ---- - `ctxlen` (integer): Context length ---- - `interhunkctxlen` (integer): ---- Inter hunk context length ---- - `ignore_whitespace` (boolean): ---- Ignore whitespace ---- - `ignore_whitespace_change` (boolean): ---- Ignore whitespace change ---- - `ignore_whitespace_change_at_eol` (boolean) ---- Ignore whitespace change at end-of-line. ---- - `ignore_cr_at_eol` (boolean) ---- Ignore carriage return at end-of-line ---- - `ignore_blank_lines` (boolean) ---- Ignore blank lines ---- - `indent_heuristic` (boolean): ---- Use the indent heuristic for the internal ---- diff library. ---- ----@return string|table|nil +---@param opts vim.diff.Opts +---@return string|integer[][]? --- See {opts.result_type}. `nil` if {opts.on_hunk} is given. function vim.diff(a, b, opts) end diff --git a/runtime/lua/vim/_meta/lpeg.lua b/runtime/lua/vim/_meta/lpeg.lua index 1ce40f3340..73b3375c82 100644 --- a/runtime/lua/vim/_meta/lpeg.lua +++ b/runtime/lua/vim/_meta/lpeg.lua @@ -6,11 +6,10 @@ error('Cannot require a meta file') -- with types being renamed to include the vim namespace and with some descriptions made less verbose. --- @brief <pre>help ---- LPeg is a pattern-matching library for Lua, based on ---- Parsing Expression Grammars (https://bford.info/packrat/) (PEGs). +--- LPeg is a pattern-matching library for Lua, based on Parsing Expression +--- Grammars (PEGs). https://bford.info/packrat/ --- ---- *lua-lpeg* ---- *vim.lpeg.Pattern* +--- *lua-lpeg* *vim.lpeg.Pattern* --- The LPeg library for parsing expression grammars is included as `vim.lpeg` --- (https://www.inf.puc-rio.br/~roberto/lpeg/). --- diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua index 757720d8fb..428b7c4d4f 100644 --- a/runtime/lua/vim/_meta/options.lua +++ b/runtime/lua/vim/_meta/options.lua @@ -11,10 +11,9 @@ vim.bo = vim.bo ---@field [integer] vim.wo vim.wo = vim.wo ---- Allow CTRL-_ in Insert and Command-line mode. This is default off, to ---- avoid that users that accidentally type CTRL-_ instead of SHIFT-_ get ---- into reverse Insert mode, and don't know how to get out. See ---- 'revins'. +--- Allow CTRL-_ in Insert mode. This is default off, to avoid that users +--- that accidentally type CTRL-_ instead of SHIFT-_ get into reverse +--- Insert mode, and don't know how to get out. See 'revins'. --- --- @type boolean vim.o.allowrevins = false @@ -975,7 +974,7 @@ vim.bo.comments = vim.o.comments vim.bo.com = vim.bo.comments --- A template for a comment. The "%s" in the value is replaced with the ---- comment text. For example, C uses "/*%s*/". Currently only used to +--- comment text. For example, C uses "/*%s*/". Used for `commenting` and to --- add markers for folding, see `fold-marker`. --- --- @type string @@ -2626,6 +2625,8 @@ vim.go.gd = vim.go.gdefault --- This is a scanf-like string that uses the same format as the --- 'errorformat' option: see `errorformat`. --- +--- If ripgrep ('grepprg') is available, this option defaults to `%f:%l:%c:%m`. +--- --- @type string vim.o.grepformat = "%f:%l:%m,%f:%l%m,%f %l%m" vim.o.gfm = vim.o.grepformat @@ -2637,12 +2638,6 @@ vim.go.gfm = vim.go.grepformat --- line. The placeholder "$*" is allowed to specify where the arguments --- will be included. Environment variables are expanded `:set_env`. See --- `option-backslash` about including spaces and backslashes. ---- When your "grep" accepts the "-H" argument, use this to make ":grep" ---- also work well with a single file: ---- ---- ```vim ---- set grepprg=grep\ -nH ---- ``` --- Special value: When 'grepprg' is set to "internal" the `:grep` command --- works like `:vimgrep`, `:lgrep` like `:lvimgrep`, `:grepadd` like --- `:vimgrepadd` and `:lgrepadd` like `:lvimgrepadd`. @@ -2650,9 +2645,19 @@ vim.go.gfm = vim.go.grepformat --- apply equally to 'grepprg'. --- This option cannot be set from a `modeline` or in the `sandbox`, for --- security reasons. ---- ---- @type string -vim.o.grepprg = "grep -n $* /dev/null" +--- This option defaults to: +--- - `rg --vimgrep -uu ` if ripgrep is available (`:checkhealth`), +--- - `grep -HIn $* /dev/null` on Unix, +--- - `findstr /n $* nul` on Windows. +--- Ripgrep can perform additional filtering such as using .gitignore rules +--- and skipping hidden files. This is disabled by default (see the -u option) +--- to more closely match the behaviour of standard grep. +--- You can make ripgrep match Vim's case handling using the +--- -i/--ignore-case and -S/--smart-case options. +--- An `OptionSet` autocmd can be used to set it up to match automatically. +--- +--- @type string +vim.o.grepprg = "grep -HIn $* /dev/null" vim.o.gp = vim.o.grepprg vim.bo.grepprg = vim.o.grepprg vim.bo.gp = vim.bo.grepprg @@ -5195,9 +5200,6 @@ vim.wo.scr = vim.wo.scroll --- Minimum is 1, maximum is 100000. --- Only in `terminal` buffers. --- ---- Note: Lines that are not visible and kept in scrollback are not ---- reflown when the terminal buffer is resized horizontally. ---- --- @type integer vim.o.scrollback = -1 vim.o.scbk = vim.o.scrollback @@ -6079,8 +6081,7 @@ vim.go.sta = vim.go.smarttab --- highlighted with `hl-NonText`. --- You may also want to add "lastline" to the 'display' option to show as --- much of the last line as possible. ---- NOTE: only partly implemented, currently works with CTRL-E, CTRL-Y ---- and scrolling with the mouse. +--- NOTE: partly implemented, doesn't work yet for `gj` and `gk`. --- --- @type boolean vim.o.smoothscroll = false @@ -6746,6 +6747,8 @@ vim.bo.swf = vim.bo.swapfile --- "split" when both are present. --- uselast If included, jump to the previously used window when --- jumping to errors with `quickfix` commands. +--- If a window has 'winfixbuf' enabled, 'switchbuf' is currently not +--- applied to the split window. --- --- @type string vim.o.switchbuf = "uselast" @@ -6847,7 +6850,7 @@ vim.go.tpm = vim.go.tabpagemax --- appear wrong in many places. --- The value must be more than 0 and less than 10000. --- ---- There are four main ways to use tabs in Vim: +--- There are five main ways to use tabs in Vim: --- 1. Always keep 'tabstop' at 8, set 'softtabstop' and 'shiftwidth' to 4 --- (or 3 or whatever you prefer) and use 'noexpandtab'. Then Vim --- will use a mix of tabs and spaces, but typing <Tab> and <BS> will @@ -7443,6 +7446,7 @@ vim.bo.vts = vim.bo.vartabstop --- --- Level Messages ~ --- ---------------------------------------------------------------------- +--- 1 Enables Lua tracing (see above). Does not produce messages. --- 2 When a file is ":source"'ed, or `shada` file is read or written. --- 3 UI info, terminal capabilities. --- 4 Shell commands. @@ -7863,8 +7867,8 @@ vim.wo.winbl = vim.wo.winblend --- will scroll 'window' minus two lines, with a minimum of one. --- When 'window' is equal to 'lines' minus one CTRL-F and CTRL-B scroll --- in a much smarter way, taking care of wrapping lines. ---- When resizing the Vim window, the value is smaller than 1 or more than ---- or equal to 'lines' it will be set to 'lines' minus 1. +--- When resizing the Vim window, and the value is smaller than 1 or more +--- than or equal to 'lines' it will be set to 'lines' minus 1. --- Note: Do not confuse this with the height of the Vim window, use --- 'lines' for that. --- @@ -7874,6 +7878,18 @@ vim.o.wi = vim.o.window vim.go.window = vim.o.window vim.go.wi = vim.go.window +--- If enabled, the window and the buffer it is displaying are paired. +--- For example, attempting to change the buffer with `:edit` will fail. +--- Other commands which change a window's buffer such as `:cnext` will +--- also skip any window with 'winfixbuf' enabled. However if an Ex +--- command has a "!" modifier, it can force switching buffers. +--- +--- @type boolean +vim.o.winfixbuf = false +vim.o.wfb = vim.o.winfixbuf +vim.wo.winfixbuf = vim.o.winfixbuf +vim.wo.wfb = vim.wo.winfixbuf + --- Keep the window height when windows are opened or closed and --- 'equalalways' is set. Also for `CTRL-W_=`. Set by default for the --- `preview-window` and `quickfix-window`. diff --git a/runtime/lua/vim/_meta/re.lua b/runtime/lua/vim/_meta/re.lua index 14c94c7824..d16751fbbf 100644 --- a/runtime/lua/vim/_meta/re.lua +++ b/runtime/lua/vim/_meta/re.lua @@ -8,11 +8,11 @@ error('Cannot require a meta file') -- See 'lpeg.html' for license --- @brief ---- The `vim.re` module provides a conventional regex-like syntax for pattern usage ---- within LPeg |vim.lpeg|. +--- The `vim.re` module provides a conventional regex-like syntax for pattern usage within LPeg +--- |vim.lpeg|. (Unrelated to |vim.regex| which provides Vim |regexp| from Lua.) --- ---- See https://www.inf.puc-rio.br/~roberto/lpeg/re.html for the original ---- documentation including regex syntax and more concrete examples. +--- See https://www.inf.puc-rio.br/~roberto/lpeg/re.html for the original documentation including +--- regex syntax and examples. --- Compiles the given {string} and returns an equivalent LPeg pattern. The given string may define --- either an expression or a grammar. The optional {defs} table provides extra Lua values to be used @@ -30,8 +30,8 @@ function vim.re.compile(string, defs) end --- @param subject string --- @param pattern vim.lpeg.Pattern|string --- @param init? integer ---- @return integer|nil the index where the occurrence starts, nil if no match ---- @return integer|nil the index where the occurrence ends, nil if no match +--- @return integer|nil : the index where the occurrence starts, nil if no match +--- @return integer|nil : the index where the occurrence ends, nil if no match function vim.re.find(subject, pattern, init) end --- Does a global substitution, replacing all occurrences of {pattern} in the given {subject} by diff --git a/runtime/lua/vim/_meta/spell.lua b/runtime/lua/vim/_meta/spell.lua index 57f2180895..c636db3b53 100644 --- a/runtime/lua/vim/_meta/spell.lua +++ b/runtime/lua/vim/_meta/spell.lua @@ -3,11 +3,11 @@ -- luacheck: no unused args --- Check {str} for spelling errors. Similar to the Vimscript function ---- |spellbadword()|. +--- [spellbadword()]. --- --- Note: The behaviour of this function is dependent on: 'spelllang', --- 'spellfile', 'spellcapcheck' and 'spelloptions' which can all be local to ---- the buffer. Consider calling this with |nvim_buf_call()|. +--- the buffer. Consider calling this with [nvim_buf_call()]. --- --- Example: --- @@ -20,7 +20,7 @@ --- ``` --- --- @param str string ---- @return {[1]: string, [2]: string, [3]: string}[] +--- @return {[1]: string, [2]: 'bad'|'rare'|'local'|'caps', [3]: integer}[] --- List of tuples with three items: --- - The badly spelled word. --- - The type of the spelling error: diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index ac25547212..f4daacfb7d 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -1598,11 +1598,10 @@ function vim.fn.eventhandler() end --- The result is a Number: --- 1 exists --- 0 does not exist ---- -1 not implemented on this system --- |exepath()| can be used to get the full path of an executable. --- --- @param expr any ---- @return 0|1|-1 +--- @return 0|1 function vim.fn.executable(expr) end --- Execute {command} and capture its output. @@ -1959,6 +1958,7 @@ function vim.fn.extendnew(expr1, expr2, expr3) end --- 't' Handle keys as if typed; otherwise they are handled as --- if coming from a mapping. This matters for undo, --- opening folds, etc. +--- 'L' Lowlevel input. Other flags are not used. --- 'i' Insert the string instead of appending (see above). --- 'x' Execute commands until typeahead is empty. This is --- similar to using ":normal!". You can call feedkeys() @@ -2703,14 +2703,14 @@ function vim.fn.getcellwidths() end function vim.fn.getchangelist(buf) end --- Get a single character from the user or input stream. ---- If [expr] is omitted, wait until a character is available. ---- If [expr] is 0, only get a character when one is available. +--- If {expr} is omitted, wait until a character is available. +--- If {expr} is 0, only get a character when one is available. --- Return zero otherwise. ---- If [expr] is 1, only check if a character is available, it is +--- If {expr} is 1, only check if a character is available, it is --- not consumed. Return zero if no character available. --- If you prefer always getting a string use |getcharstr()|. --- ---- Without [expr] and when [expr] is 0 a whole character or +--- Without {expr} and when {expr} is 0 a whole character or --- special key is returned. If it is a single character, the --- result is a Number. Use |nr2char()| to convert it to a String. --- Otherwise a String is returned with the encoded character. @@ -2720,11 +2720,11 @@ function vim.fn.getchangelist(buf) end --- also a String when a modifier (shift, control, alt) was used --- that is not included in the character. --- ---- When [expr] is 0 and Esc is typed, there will be a short delay +--- When {expr} is 0 and Esc is typed, there will be a short delay --- while Vim waits to see if this is the start of an escape --- sequence. --- ---- When [expr] is 1 only the first byte is returned. For a +--- When {expr} is 1 only the first byte is returned. For a --- one-byte character it is the character itself as a number. --- Use nr2char() to convert it to a String. --- @@ -2828,10 +2828,10 @@ function vim.fn.getcharsearch() end --- Get a single character from the user or input stream as a --- string. ---- If [expr] is omitted, wait until a character is available. ---- If [expr] is 0 or false, only get a character when one is +--- If {expr} is omitted, wait until a character is available. +--- If {expr} is 0 or false, only get a character when one is --- available. Return an empty string otherwise. ---- If [expr] is 1 or true, only check if a character is +--- If {expr} is 1 or true, only check if a character is --- available, it is not consumed. Return an empty string --- if no character is available. --- Otherwise this works like |getchar()|, except that a number @@ -3581,6 +3581,43 @@ function vim.fn.getreginfo(regname) end --- @return string[] function vim.fn.getregion(pos1, pos2, opts) end +--- Same as |getregion()|, but returns a list of positions +--- describing the buffer text segments bound by {pos1} and +--- {pos2}. +--- The segments are a pair of positions for every line: > +--- [[{start_pos}, {end_pos}], ...] +--- < +--- The position is a |List| with four numbers: +--- [bufnum, lnum, col, off] +--- "bufnum" is the buffer number. +--- "lnum" and "col" are the position in the buffer. The first +--- column is 1. +--- If the "off" number of a starting position is non-zero, it is +--- the offset in screen columns from the start of the character. +--- E.g., a position within a <Tab> or after the last character. +--- If the "off" number of an ending position is non-zero, it is +--- the offset of the character's first cell not included in the +--- selection, otherwise all its cells are included. +--- +--- Apart from the options supported by |getregion()|, {opts} also +--- supports the following: +--- +--- eol If |TRUE|, indicate positions beyond +--- the end of a line with "col" values +--- one more than the length of the line. +--- If |FALSE|, positions are limited +--- within their lines, and if a line is +--- empty or the selection is entirely +--- beyond the end of a line, a "col" +--- value of 0 is used for both positions. +--- (default: |FALSE|) +--- +--- @param pos1 table +--- @param pos2 table +--- @param opts? table +--- @return integer[][][] +function vim.fn.getregionpos(pos1, pos2, opts) end + --- The result is a String, which is type of register {regname}. --- The value will be one of: --- "v" for |charwise| text @@ -3628,11 +3665,11 @@ function vim.fn.getregtype(regname) end --- --- Examples: >vim --- echo getscriptinfo({'name': 'myscript'}) ---- echo getscriptinfo({'sid': 15}).variables +--- echo getscriptinfo({'sid': 15})[0].variables --- < --- --- @param opts? table ---- @return any +--- @return vim.fn.getscriptinfo.ret[] function vim.fn.getscriptinfo(opts) end --- If {tabnr} is not specified, then information about all the @@ -5993,7 +6030,7 @@ function vim.fn.min(expr) end function vim.fn.mkdir(name, flags, prot) end --- Return a string that indicates the current mode. ---- If [expr] is supplied and it evaluates to a non-zero Number or +--- If {expr} is supplied and it evaluates to a non-zero Number or --- a non-empty String (|non-zero-arg|), then the full mode is --- returned, otherwise only the first letter is returned. --- Also see |state()|. @@ -6520,6 +6557,9 @@ function vim.fn.prevnonblank(lnum) end --- echo printf("%1$*2$.*3$f", 1.4142135, 6, 2) --- < 1.41 --- +--- You will get an overflow error |E1510|, when the field-width +--- or precision will result in a string longer than 6400 chars. +--- --- *E1500* --- You cannot mix positional and non-positional arguments: >vim --- echo printf("%s%1$s", "One", "Two") @@ -6580,7 +6620,7 @@ function vim.fn.prevnonblank(lnum) end --- --- @param fmt any --- @param expr1? any ---- @return any +--- @return string function vim.fn.printf(fmt, expr1) end --- Returns the effective prompt text for buffer {buf}. {buf} can @@ -7259,6 +7299,7 @@ function vim.fn.screenstring(row, col) end --- When a match has been found its line number is returned. --- If there is no match a 0 is returned and the cursor doesn't --- move. No error message is given. +--- To get the matched string, use |matchbufline()|. --- --- {flags} is a String, which can contain these character flags: --- 'b' search Backward instead of forward @@ -8289,10 +8330,11 @@ function vim.fn.sha256(string) end --- Otherwise encloses {string} in single-quotes and replaces all --- "'" with "'\''". --- ---- If {special} is a |non-zero-arg|: ---- - Special items such as "!", "%", "#" and "<cword>" will be ---- preceded by a backslash. The backslash will be removed again ---- by the |:!| command. +--- The {special} argument adds additional escaping of keywords +--- used in Vim commands. If it is a |non-zero-arg|: +--- - Special items such as "!", "%", "#" and "<cword>" (as listed +--- in |expand()|) will be preceded by a backslash. +--- The backslash will be removed again by the |:!| command. --- - The <NL> character is escaped. --- --- If 'shell' contains "csh" in the tail: @@ -8796,7 +8838,8 @@ function vim.fn.sinh(expr) end --- Similar to using a |slice| "expr[start : end]", but "end" is --- used exclusive. And for a string the indexes are used as --- character indexes instead of byte indexes. ---- Also, composing characters are not counted. +--- Also, composing characters are treated as a part of the +--- preceding base character. --- When {end} is omitted the slice continues to the last item. --- When {end} is -1 the last item is omitted. --- Returns an empty value if {start} or {end} are invalid. @@ -9204,8 +9247,8 @@ function vim.fn.strcharlen(string) end --- of byte index and length. --- When {skipcc} is omitted or zero, composing characters are --- counted separately. ---- When {skipcc} set to 1, Composing characters are ignored, ---- similar to |slice()|. +--- When {skipcc} set to 1, composing characters are treated as a +--- part of the preceding base character, similar to |slice()|. --- When a character index is used where a character does not --- exist it is omitted and counted as one character. For --- example: >vim @@ -9225,7 +9268,7 @@ function vim.fn.strcharpart(src, start, len, skipcc) end --- in String {string}. --- When {skipcc} is omitted or zero, composing characters are --- counted separately. ---- When {skipcc} set to 1, Composing characters are ignored. +--- When {skipcc} set to 1, composing characters are ignored. --- |strcharlen()| always does this. --- --- Returns zero on error. @@ -9348,10 +9391,10 @@ function vim.fn.stridx(haystack, needle, start) end --- for infinite and NaN floating-point values representations --- which use |str2float()|. Strings are also dumped literally, --- only single quote is escaped, which does not allow using YAML ---- for parsing back binary strings. |eval()| should always work for ---- strings and floats though and this is the only official ---- method, use |msgpackdump()| or |json_encode()| if you need to ---- share data with other application. +--- for parsing back binary strings. |eval()| should always work +--- for strings and floats though, and this is the only official +--- method. Use |msgpackdump()| or |json_encode()| if you need to +--- share data with other applications. --- --- @param expr any --- @return string @@ -9747,6 +9790,10 @@ function vim.fn.synIDtrans(synID) end --- synconcealed(lnum, 5) [1, 'X', 2] --- synconcealed(lnum, 6) [0, '', 0] --- +--- Note: Doesn't consider |matchadd()| highlighting items, +--- since syntax and matching highlighting are two different +--- mechanisms |syntax-vs-match|. +--- --- @param lnum integer --- @param col integer --- @return {[1]: integer, [2]: string, [3]: integer} @@ -10591,17 +10638,16 @@ function vim.fn.win_move_statusline(nr, offset) end --- [1, 1], unless there is a tabline, then it is [2, 1]. --- {nr} can be the window number or the |window-ID|. Use zero --- for the current window. ---- Returns [0, 0] if the window cannot be found in the current ---- tabpage. +--- Returns [0, 0] if the window cannot be found. --- --- @param nr integer --- @return any function vim.fn.win_screenpos(nr) end ---- Move the window {nr} to a new split of the window {target}. ---- This is similar to moving to {target}, creating a new window ---- using |:split| but having the same contents as window {nr}, and ---- then closing {nr}. +--- Temporarily switch to window {target}, then move window {nr} +--- to a new split adjacent to {target}. +--- Unlike commands such as |:split|, no new windows are created +--- (the |window-ID| of window {nr} is unchanged after the move). --- --- Both {nr} and {target} can be window numbers or |window-ID|s. --- Both must be in the current tab page. @@ -10724,7 +10770,9 @@ function vim.fn.winline() end --- # the number of the last accessed window (where --- |CTRL-W_p| goes to). If there is no previous --- window or it is in another tab page 0 is ---- returned. +--- returned. May refer to the current window in +--- some cases (e.g. when evaluating 'statusline' +--- expressions). --- {N}j the number of the Nth window below the --- current window (where |CTRL-W_j| goes to). --- {N}k the number of the Nth window above the current diff --git a/runtime/lua/vim/_meta/vvars.lua b/runtime/lua/vim/_meta/vvars.lua index ee6d8ddf35..e00402ab3f 100644 --- a/runtime/lua/vim/_meta/vvars.lua +++ b/runtime/lua/vim/_meta/vvars.lua @@ -54,9 +54,10 @@ vim.v.cmdbang = ... --- @type string vim.v.collate = ... ---- Dictionary containing the most recent `complete-items` after ---- `CompleteDone`. Empty if the completion failed, or after ---- leaving and re-entering insert mode. +--- Dictionary containing the `complete-items` for the most +--- recently completed word after `CompleteDone`. Empty if the +--- completion failed, or after leaving and re-entering insert +--- mode. --- Note: Plugins can modify the value to emulate the builtin --- `CompleteDone` event behavior. --- @type any @@ -194,6 +195,7 @@ vim.v.errors = ... --- changed_window Is `v:true` if the event fired while --- changing window (or tab) on `DirChanged`. --- status Job status or exit code, -1 means "unknown". `TermClose` +--- reason Reason for completion being done. `CompleteDone` --- @type any vim.v.event = ... diff --git a/runtime/lua/vim/_options.lua b/runtime/lua/vim/_options.lua index 13ad6cc58f..b41e298dd7 100644 --- a/runtime/lua/vim/_options.lua +++ b/runtime/lua/vim/_options.lua @@ -642,7 +642,7 @@ end --- @param t table<any,any> --- @param val any local function remove_one_item(t, val) - if vim.tbl_islist(t) then + if vim.islist(t) then local remove_index = nil for i, v in ipairs(t) do if v == val then diff --git a/runtime/lua/vim/_system.lua b/runtime/lua/vim/_system.lua index e97a5fc6c3..d603971495 100644 --- a/runtime/lua/vim/_system.lua +++ b/runtime/lua/vim/_system.lua @@ -18,6 +18,7 @@ local uv = vim.uv --- @field stderr? string --- @class vim.SystemState +--- @field cmd string[] --- @field handle? uv.uv_process_t --- @field timer? uv.uv_timer_t --- @field pid? integer @@ -56,6 +57,7 @@ local function close_handles(state) end --- @class vim.SystemObj +--- @field cmd string[] --- @field pid integer --- @field private _state vim.SystemState --- @field wait fun(self: vim.SystemObj, timeout?: integer): vim.SystemCompleted @@ -68,6 +70,7 @@ local SystemObj = {} --- @return vim.SystemObj local function new_systemobj(state) return setmetatable({ + cmd = state.cmd, pid = state.pid, _state = state, }, { __index = SystemObj }) diff --git a/runtime/lua/vim/_watch.lua b/runtime/lua/vim/_watch.lua index 97c5481ad1..02b3f536c2 100644 --- a/runtime/lua/vim/_watch.lua +++ b/runtime/lua/vim/_watch.lua @@ -200,11 +200,13 @@ function M.watchdirs(path, opts, callback) local max_depth = 100 for name, type in vim.fs.dir(path, { depth = max_depth }) do - local filepath = vim.fs.joinpath(path, name) - if type == 'directory' and not skip(filepath, opts) then - local handle = assert(uv.new_fs_event()) - handles[filepath] = handle - handle:start(filepath, {}, create_on_change(filepath)) + if type == 'directory' then + local filepath = vim.fs.joinpath(path, name) + if not skip(filepath, opts) then + local handle = assert(uv.new_fs_event()) + handles[filepath] = handle + handle:start(filepath, {}, create_on_change(filepath)) + end end end @@ -290,6 +292,10 @@ function M.fswatch(path, opts, callback) if data and #vim.trim(data) > 0 then vim.schedule(function() + if vim.fn.has('linux') == 1 and vim.startswith(data, 'Event queue overflow') then + data = 'inotify(7) limit reached, see :h fswatch-limitations for more info.' + end + vim.notify('fswatch: ' .. data, vim.log.levels.ERROR) end) end @@ -303,6 +309,8 @@ function M.fswatch(path, opts, callback) fswatch_output_handler(line, opts, callback) end end, + -- --latency is locale dependent but tostring() isn't and will always have '.' as decimal point. + env = { LC_NUMERIC = 'C' }, }) return function() diff --git a/runtime/lua/vim/deprecated/health.lua b/runtime/lua/vim/deprecated/health.lua new file mode 100644 index 0000000000..0f6b1f578c --- /dev/null +++ b/runtime/lua/vim/deprecated/health.lua @@ -0,0 +1,42 @@ +local M = {} +local health = vim.health + +local deprecated = {} + +function M.check() + if next(deprecated) == nil then + health.ok('No deprecated functions detected') + return + end + + for name, v in vim.spairs(deprecated) do + health.start('') + + local version, backtraces, alternative = v[1], v[2], v[3] + local major, minor = version:match('(%d+)%.(%d+)') + major, minor = tonumber(major), tonumber(minor) + local removal_version = string.format('nvim-%d.%d', major, minor) + local will_be_removed = vim.fn.has(removal_version) == 1 and 'was removed' or 'will be removed' + + local msg = ('%s is deprecated. Feature %s in Nvim %s'):format(name, will_be_removed, version) + local msg_alternative = alternative and ('use %s instead.'):format(alternative) + local advice = { msg_alternative } + table.insert(advice, backtraces) + advice = vim.iter(advice):flatten():totable() + health.warn(msg, advice) + end +end + +function M.add(name, version, backtrace, alternative) + if deprecated[name] == nil then + deprecated[name] = { version, { backtrace }, alternative } + return + end + + local it = vim.iter(deprecated[name][2]) + if it:find(backtrace) == nil then + table.insert(deprecated[name][2], backtrace) + end +end + +return M diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index d5075d7d3d..348204abb7 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -76,7 +76,7 @@ local M = {} --- before lower severities (e.g. ERROR is displayed before WARN). --- Options: --- - {reverse}? (boolean) Reverse sort order ---- (default: `false) +--- (default: `false`) --- @field severity_sort? boolean|{reverse?:boolean} --- @class (private) vim.diagnostic.OptsResolved @@ -152,6 +152,8 @@ local M = {} --- @field suffix? string|table|(fun(diagnostic:vim.Diagnostic,i:integer,total:integer): string, string) --- --- @field focus_id? string +--- +--- @field border? string see |nvim_open_win()|. --- @class vim.diagnostic.Opts.Underline --- @@ -239,6 +241,17 @@ local M = {} --- whole line the sign is placed in. --- @field linehl? table<vim.diagnostic.Severity,string> +-- TODO: inherit from `vim.diagnostic.Opts`, implement its fields. +--- Optional filters |kwargs|, or `nil` for all. +--- @class vim.diagnostic.Filter +--- @inlinedoc +--- +--- Diagnostic namespace, or `nil` for all. +--- @field ns_id? integer +--- +--- Buffer number, or 0 for current buffer, or `nil` for all buffers. +--- @field bufnr? integer + --- @nodoc --- @enum vim.diagnostic.Severity M.severity = { @@ -361,43 +374,46 @@ local function to_severity(severity) end --- @param severity vim.diagnostic.SeverityFilter ---- @param diagnostics vim.Diagnostic[] ---- @return vim.Diagnostic[] -local function filter_by_severity(severity, diagnostics) - if not severity then - return diagnostics - end - +--- @return fun(vim.Diagnostic):boolean +local function severity_predicate(severity) if type(severity) ~= 'table' then severity = assert(to_severity(severity)) - --- @param t vim.Diagnostic - return vim.tbl_filter(function(t) - return t.severity == severity - end, diagnostics) + ---@param d vim.Diagnostic + return function(d) + return d.severity == severity + end end - if severity.min or severity.max then --- @cast severity {min:vim.diagnostic.Severity,max:vim.diagnostic.Severity} local min_severity = to_severity(severity.min) or M.severity.HINT local max_severity = to_severity(severity.max) or M.severity.ERROR - --- @param t vim.Diagnostic - return vim.tbl_filter(function(t) - return t.severity <= min_severity and t.severity >= max_severity - end, diagnostics) + --- @param d vim.Diagnostic + return function(d) + return d.severity <= min_severity and d.severity >= max_severity + end end --- @cast severity vim.diagnostic.Severity[] - local severities = {} --- @type table<vim.diagnostic.Severity,true> for _, s in ipairs(severity) do severities[assert(to_severity(s))] = true end - --- @param t vim.Diagnostic - return vim.tbl_filter(function(t) - return severities[t.severity] - end, diagnostics) + --- @param d vim.Diagnostic + return function(d) + return severities[d.severity] + end +end + +--- @param severity vim.diagnostic.SeverityFilter +--- @param diagnostics vim.Diagnostic[] +--- @return vim.Diagnostic[] +local function filter_by_severity(severity, diagnostics) + if not severity then + return diagnostics + end + return vim.tbl_filter(severity_predicate(severity), diagnostics) end --- @param bufnr integer @@ -682,6 +698,13 @@ local function get_diagnostics(bufnr, opts, clamp) opts = opts or {} local namespace = opts.namespace + + if type(namespace) == 'number' then + namespace = { namespace } + end + + ---@cast namespace integer[] + local diagnostics = {} -- Memoized results of buf_line_count per bufnr @@ -696,10 +719,18 @@ local function get_diagnostics(bufnr, opts, clamp) end, }) + local match_severity = opts.severity and severity_predicate(opts.severity) + or function(_) + return true + end + ---@param b integer ---@param d vim.Diagnostic local function add(b, d) - if not opts.lnum or d.lnum == opts.lnum then + if + match_severity(d) + and (not opts.lnum or (opts.lnum >= d.lnum and opts.lnum <= (d.end_lnum or d.lnum))) + then if clamp and api.nvim_buf_is_loaded(b) then local line_count = buf_line_count[b] - 1 if @@ -742,15 +773,15 @@ local function get_diagnostics(bufnr, opts, clamp) end elseif bufnr == nil then for b, t in pairs(diagnostic_cache) do - add_all_diags(b, t[namespace] or {}) + for _, iter_namespace in ipairs(namespace) do + add_all_diags(b, t[iter_namespace] or {}) + end end else bufnr = get_bufnr(bufnr) - add_all_diags(bufnr, diagnostic_cache[bufnr][namespace] or {}) - end - - if opts.severity then - diagnostics = filter_by_severity(opts.severity, diagnostics) + for _, iter_namespace in ipairs(namespace) do + add_all_diags(bufnr, diagnostic_cache[bufnr][iter_namespace] or {}) + end end return diagnostics @@ -781,21 +812,52 @@ local function set_list(loclist, opts) end end +--- Jump to the diagnostic with the highest severity. First sort the +--- diagnostics by severity. The first diagnostic then contains the highest severity, and we can +--- discard all diagnostics with a lower severity. +--- @param diagnostics vim.Diagnostic[] +local function filter_highest(diagnostics) + table.sort(diagnostics, function(a, b) + return a.severity < b.severity + end) + + -- Find the first diagnostic where the severity does not match the highest severity, and remove + -- that element and all subsequent elements from the array + local worst = (diagnostics[1] or {}).severity + local len = #diagnostics + for i = 2, len do + if diagnostics[i].severity ~= worst then + for j = i, len do + diagnostics[j] = nil + end + break + end + end +end + --- @param position {[1]: integer, [2]: integer} --- @param search_forward boolean --- @param bufnr integer --- @param opts vim.diagnostic.GotoOpts ---- @param namespace integer +--- @param namespace integer[]|integer --- @return vim.Diagnostic? local function next_diagnostic(position, search_forward, bufnr, opts, namespace) position[1] = position[1] - 1 bufnr = get_bufnr(bufnr) local wrap = if_nil(opts.wrap, true) - local line_count = api.nvim_buf_line_count(bufnr) - local diagnostics = - get_diagnostics(bufnr, vim.tbl_extend('keep', opts, { namespace = namespace }), true) + + local get_opts = vim.deepcopy(opts) + get_opts.namespace = get_opts.namespace or namespace + + local diagnostics = get_diagnostics(bufnr, get_opts, true) + + if opts._highest then + filter_highest(diagnostics) + end + local line_diagnostics = diagnostic_lines(diagnostics) + local line_count = api.nvim_buf_line_count(bufnr) for i = 0, line_count do local offset = i * (search_forward and 1 or -1) local lnum = position[1] + offset @@ -814,14 +876,14 @@ local function next_diagnostic(position, search_forward, bufnr, opts, namespace) return a.col < b.col end is_next = function(d) - return math.min(d.col, line_length - 1) > position[2] + return math.min(d.col, math.max(line_length - 1, 0)) > position[2] end else sort_diagnostics = function(a, b) return a.col > b.col end is_next = function(d) - return math.min(d.col, line_length - 1) < position[2] + return math.min(d.col, math.max(line_length - 1, 0)) < position[2] end end table.sort(line_diagnostics[lnum], sort_diagnostics) @@ -952,7 +1014,7 @@ function M.set(namespace, bufnr, diagnostics, opts) bufnr = { bufnr, 'n' }, diagnostics = { diagnostics, - vim.tbl_islist, + vim.islist, 'a list of diagnostics', }, opts = { opts, 't', true }, @@ -1115,10 +1177,10 @@ end --- A table with the following keys: --- @class vim.diagnostic.GetOpts --- ---- Limit diagnostics to the given namespace. ---- @field namespace? integer +--- Limit diagnostics to one or more namespaces. +--- @field namespace? integer[]|integer --- ---- Limit diagnostics to the given line number. +--- Limit diagnostics to those spanning the specified line number. --- @field lnum? integer --- --- See |diagnostic-severity|. @@ -1137,7 +1199,11 @@ end --- @field wrap? boolean --- --- See |diagnostic-severity|. ---- @field severity vim.diagnostic.Severity +--- @field severity? vim.diagnostic.SeverityFilter +--- +--- Go to the diagnostic with the highest severity. +--- (default: `false`) +--- @field package _highest? boolean --- --- If `true`, call |vim.diagnostic.open_float()| after moving. --- If a table, pass the table as the {opts} parameter to |vim.diagnostic.open_float()|. @@ -1164,7 +1230,7 @@ M.handlers.signs = { bufnr = { bufnr, 'n' }, diagnostics = { diagnostics, - vim.tbl_islist, + vim.islist, 'a list of diagnostics', }, opts = { opts, 't', true }, @@ -1213,9 +1279,7 @@ M.handlers.signs = { vim.deprecate( 'Defining diagnostic signs with :sign-define or sign_define()', 'vim.diagnostic.config()', - '0.12', - nil, - false + '0.12' ) if not opts.signs.text then @@ -1287,7 +1351,7 @@ M.handlers.underline = { bufnr = { bufnr, 'n' }, diagnostics = { diagnostics, - vim.tbl_islist, + vim.islist, 'a list of diagnostics', }, opts = { opts, 't', true }, @@ -1360,7 +1424,7 @@ M.handlers.virtual_text = { bufnr = { bufnr, 'n' }, diagnostics = { diagnostics, - vim.tbl_islist, + vim.islist, 'a list of diagnostics', }, opts = { opts, 't', true }, @@ -1481,7 +1545,7 @@ end --- diagnostics, use |vim.diagnostic.reset()|. --- --- To hide diagnostics and prevent them from re-displaying, use ---- |vim.diagnostic.disable()|. +--- |vim.diagnostic.enable()|. --- ---@param namespace integer? Diagnostic namespace. When omitted, hide --- diagnostics from all namespaces. @@ -1506,25 +1570,32 @@ function M.hide(namespace, bufnr) end end ---- Check whether diagnostics are disabled in a given buffer. +--- Check whether diagnostics are enabled. --- ----@param bufnr integer? Buffer number, or 0 for current buffer. ----@param namespace integer? Diagnostic namespace. When omitted, checks if ---- all diagnostics are disabled in {bufnr}. ---- Otherwise, only checks if diagnostics from ---- {namespace} are disabled. ----@return boolean -function M.is_disabled(bufnr, namespace) - bufnr = get_bufnr(bufnr) - if namespace and M.get_namespace(namespace).disabled then - return true +--- @param filter vim.diagnostic.Filter? +--- @return boolean +--- @since 12 +function M.is_enabled(filter) + filter = filter or {} + if filter.ns_id and M.get_namespace(filter.ns_id).disabled then + return false + elseif filter.bufnr == nil then + -- See enable() logic. + return vim.tbl_isempty(diagnostic_disabled) and not diagnostic_disabled[1] end + local bufnr = get_bufnr(filter.bufnr) if type(diagnostic_disabled[bufnr]) == 'table' then - return diagnostic_disabled[bufnr][namespace] + return not diagnostic_disabled[bufnr][filter.ns_id] end - return diagnostic_disabled[bufnr] ~= nil + return diagnostic_disabled[bufnr] == nil +end + +--- @deprecated use `vim.diagnostic.is_enabled()` +function M.is_disabled(bufnr, namespace) + vim.deprecate('vim.diagnostic.is_disabled()', 'vim.diagnostic.is_enabled()', '0.12') + return not M.is_enabled { bufnr = bufnr or 0, ns_id = namespace } end --- Display diagnostics for the given namespace and buffer. @@ -1547,7 +1618,7 @@ function M.show(namespace, bufnr, diagnostics, opts) diagnostics = { diagnostics, function(v) - return v == nil or vim.tbl_islist(v) + return v == nil or vim.islist(v) end, 'a list of diagnostics', }, @@ -1570,7 +1641,7 @@ function M.show(namespace, bufnr, diagnostics, opts) return end - if M.is_disabled(bufnr, namespace) then + if not M.is_enabled { bufnr = bufnr or 0, ns_id = namespace } then return end @@ -1668,7 +1739,7 @@ function M.open_float(opts, ...) if scope == 'line' then --- @param d vim.Diagnostic diagnostics = vim.tbl_filter(function(d) - return d.lnum == lnum + return lnum >= d.lnum and lnum <= d.end_lnum end, diagnostics) elseif scope == 'cursor' then -- LSP servers can send diagnostics with `end_col` past the length of the line @@ -1912,71 +1983,95 @@ function M.setloclist(opts) set_list(true, opts) end ---- Disable diagnostics in the given buffer. ---- ----@param bufnr integer? Buffer number, or 0 for current buffer. When ---- omitted, disable diagnostics in all buffers. ----@param namespace integer? Only disable diagnostics for the given namespace. +--- @deprecated use `vim.diagnostic.enable(false, …)` function M.disable(bufnr, namespace) - vim.validate({ bufnr = { bufnr, 'n', true }, namespace = { namespace, 'n', true } }) - if bufnr == nil then - if namespace == nil then - -- Disable everything (including as yet non-existing buffers and - -- namespaces) by setting diagnostic_disabled to an empty table and set - -- its metatable to always return true. This metatable is removed - -- in enable() - diagnostic_disabled = setmetatable({}, { - __index = function() - return true - end, - }) - else - local ns = M.get_namespace(namespace) - ns.disabled = true - end + vim.deprecate('vim.diagnostic.disable()', 'vim.diagnostic.enable(false, …)', '0.12') + M.enable(false, { bufnr = bufnr, ns_id = namespace }) +end + +--- Enables or disables diagnostics. +--- +--- To "toggle", pass the inverse of `is_enabled()`: +--- +--- ```lua +--- vim.diagnostic.enable(not vim.diagnostic.is_enabled()) +--- ``` +--- +--- @param enable (boolean|nil) true/nil to enable, false to disable +--- @param filter vim.diagnostic.Filter? +function M.enable(enable, filter) + -- Deprecated signature. Drop this in 0.12 + local legacy = (enable or filter) + and vim.tbl_contains({ 'number', 'nil' }, type(enable)) + and vim.tbl_contains({ 'number', 'nil' }, type(filter)) + + if legacy then + vim.deprecate( + 'vim.diagnostic.enable(buf:number, namespace:number)', + 'vim.diagnostic.enable(enable:boolean, filter:table)', + '0.12' + ) + + vim.validate({ + enable = { enable, 'n', true }, -- Legacy `bufnr` arg. + filter = { filter, 'n', true }, -- Legacy `namespace` arg. + }) + + local ns_id = type(filter) == 'number' and filter or nil + filter = {} + filter.ns_id = ns_id + filter.bufnr = type(enable) == 'number' and enable or nil + enable = true else - bufnr = get_bufnr(bufnr) - if namespace == nil then - diagnostic_disabled[bufnr] = true - else - if type(diagnostic_disabled[bufnr]) ~= 'table' then - diagnostic_disabled[bufnr] = {} - end - diagnostic_disabled[bufnr][namespace] = true - end + filter = filter or {} + vim.validate({ + enable = { enable, 'b', true }, + filter = { filter, 't', true }, + }) end - M.hide(namespace, bufnr) -end + enable = enable == nil and true or enable + local bufnr = filter.bufnr ---- Enable diagnostics in the given buffer. ---- ----@param bufnr integer? Buffer number, or 0 for current buffer. When ---- omitted, enable diagnostics in all buffers. ----@param namespace integer? Only enable diagnostics for the given namespace. -function M.enable(bufnr, namespace) - vim.validate({ bufnr = { bufnr, 'n', true }, namespace = { namespace, 'n', true } }) if bufnr == nil then - if namespace == nil then - -- Enable everything by setting diagnostic_disabled to an empty table - diagnostic_disabled = {} + if filter.ns_id == nil then + diagnostic_disabled = ( + enable + -- Enable everything by setting diagnostic_disabled to an empty table. + and {} + -- Disable everything (including as yet non-existing buffers and namespaces) by setting + -- diagnostic_disabled to an empty table and set its metatable to always return true. + or setmetatable({}, { + __index = function() + return true + end, + }) + ) else - local ns = M.get_namespace(namespace) - ns.disabled = false + local ns = M.get_namespace(filter.ns_id) + ns.disabled = not enable end else bufnr = get_bufnr(bufnr) - if namespace == nil then - diagnostic_disabled[bufnr] = nil + if filter.ns_id == nil then + diagnostic_disabled[bufnr] = (not enable) and true or nil else if type(diagnostic_disabled[bufnr]) ~= 'table' then - return + if enable then + return + else + diagnostic_disabled[bufnr] = {} + end end - diagnostic_disabled[bufnr][namespace] = nil + diagnostic_disabled[bufnr][filter.ns_id] = (not enable) and true or nil end end - M.show(namespace, bufnr) + if enable then + M.show(filter.ns_id, bufnr) + else + M.hide(filter.ns_id, bufnr) + end end --- Parse a diagnostic from a string. @@ -2059,7 +2154,7 @@ function M.toqflist(diagnostics) vim.validate({ diagnostics = { diagnostics, - vim.tbl_islist, + vim.islist, 'a list of diagnostics', }, }) @@ -2099,7 +2194,7 @@ function M.fromqflist(list) vim.validate({ list = { list, - vim.tbl_islist, + vim.islist, 'a list of quickfix items', }, }) diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index fba76f93b2..d1fdd0aa16 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -14,7 +14,8 @@ local M = {} local function starsetf(ft, opts) return { function(path, bufnr) - local f = type(ft) == 'function' and ft(path, bufnr) or ft + -- Note: when `ft` is a function its return value may be nil. + local f = type(ft) ~= 'function' and ft or ft(path, bufnr) if not vim.g.ft_ignore_pat then return f end @@ -236,6 +237,7 @@ local extension = { bbclass = 'bitbake', bl = 'blank', blp = 'blueprint', + bp = 'bp', bsd = 'bsdl', bsdl = 'bsdl', bst = 'bst', @@ -246,13 +248,15 @@ local extension = { bzl = 'bzl', bazel = 'bzl', BUILD = 'bzl', + mdh = 'c', + epro = 'c', qc = 'c', cabal = 'cabal', cairo = 'cairo', capnp = 'capnp', cdc = 'cdc', cdl = 'cdl', - toc = 'cdrtoc', + toc = detect_line1('\\contentsline', 'tex', 'cdrtoc'), cfc = 'cf', cfm = 'cf', cfi = 'cf', @@ -282,6 +286,7 @@ local extension = { cbl = 'cobol', atg = 'coco', recipe = 'conaryrecipe', + ctags = 'conf', hook = function(path, bufnr) return M._getline(bufnr, 1) == '[Trigger]' and 'confini' or nil end, @@ -335,6 +340,7 @@ local extension = { si = 'cuplsim', cyn = 'cynpp', cypher = 'cypher', + dfy = 'dafny', dart = 'dart', drt = 'dart', ds = 'datascript', @@ -366,6 +372,7 @@ local extension = { dtsi = 'dts', dtso = 'dts', its = 'dts', + keymap = 'dts', dylan = 'dylan', intr = 'dylanintr', lid = 'dylanlid', @@ -465,6 +472,7 @@ local extension = { glsl = 'glsl', gn = 'gn', gni = 'gn', + gnuplot = 'gnuplot', gpi = 'gnuplot', go = 'go', gp = 'gp', @@ -502,7 +510,16 @@ local extension = { vc = 'hercules', heex = 'heex', hex = 'hex', + ['a43'] = 'hex', + ['a90'] = 'hex', ['h32'] = 'hex', + ['h80'] = 'hex', + ['h86'] = 'hex', + ihex = 'hex', + ihe = 'hex', + ihx = 'hex', + int = 'hex', + mcs = 'hex', hjson = 'hjson', m3u = 'hlsplaylist', m3u8 = 'hlsplaylist', @@ -530,6 +547,7 @@ local extension = { inf = 'inform', INF = 'inform', ii = 'initng', + inko = 'inko', inp = detect.inp, ms = detect_seq(detect.nroff, 'xmath'), iss = 'iss', @@ -554,6 +572,7 @@ local extension = { jsx = 'javascriptreact', clp = 'jess', jgr = 'jgraph', + jjdescription = 'jj', j73 = 'jovial', jov = 'jovial', jovial = 'jovial', @@ -565,7 +584,14 @@ local extension = { geojson = 'json', webmanifest = 'json', ipynb = 'json', + ['jupyterlab-settings'] = 'json', + ['sublime-project'] = 'json', + ['sublime-settings'] = 'json', + ['sublime-workspace'] = 'json', ['json-patch'] = 'json', + bd = 'json', + bda = 'json', + xci = 'json', json5 = 'json5', jsonc = 'jsonc', jsonl = 'jsonl', @@ -609,12 +635,13 @@ local extension = { el = 'lisp', lsp = 'lisp', asd = 'lisp', + stsg = 'lisp', lt = 'lite', lite = 'lite', livemd = 'livebook', lgt = 'logtalk', lotos = 'lotos', - lot = 'lotos', + lot = detect_line1('\\contentsline', 'tex', 'lotos'), lout = 'lout', lou = 'lout', ulpc = 'lpc', @@ -625,6 +652,7 @@ local extension = { nse = 'lua', rockspec = 'lua', lua = 'lua', + tlu = 'lua', luau = 'luau', lrc = 'lyrics', m = detect.m, @@ -644,12 +672,12 @@ local extension = { mws = 'maple', mpl = 'maple', mv = 'maple', - mkdn = 'markdown', - md = 'markdown', - mdwn = 'markdown', - mkd = 'markdown', - markdown = 'markdown', - mdown = 'markdown', + mkdn = detect.markdown, + md = detect.markdown, + mdwn = detect.markdown, + mkd = detect.markdown, + markdown = detect.markdown, + mdown = detect.markdown, mhtml = 'mason', comp = 'mason', mason = 'mason', @@ -744,12 +772,19 @@ local extension = { ora = 'ora', org = 'org', org_archive = 'org', + pandoc = 'pandoc', + pdk = 'pandoc', + pd = 'pandoc', + pdc = 'pandoc', pxsl = 'papp', papp = 'papp', pxml = 'papp', pas = 'pascal', - lpr = 'pascal', + lpr = detect_line1('<%?xml', 'xml', 'pascal'), dpr = 'pascal', + txtpb = 'pbtxt', + textproto = 'pbtxt', + textpb = 'pbtxt', pbtxt = 'pbtxt', g = 'pccts', pcmk = 'pcmk', @@ -810,6 +845,7 @@ local extension = { psf = 'psf', psl = 'psl', pug = 'pug', + purs = 'purescript', arr = 'pyret', pxd = 'pyrex', pyx = 'pyrex', @@ -869,6 +905,7 @@ local extension = { Snw = 'rnoweb', robot = 'robot', resource = 'robot', + roc = 'roc', ron = 'ron', rsc = 'routeros', x = 'rpcgen', @@ -911,11 +948,13 @@ local extension = { sexp = 'sexplib', bash = detect.bash, bats = detect.bash, + cygport = detect.bash, ebuild = detect.bash, eclass = detect.bash, env = detect.sh, ksh = detect.ksh, sh = detect.sh, + mdd = 'sh', sieve = 'sieve', siv = 'sieve', sig = detect.sig, @@ -933,6 +972,7 @@ local extension = { cdf = 'skill', sl = 'slang', ice = 'slice', + slint = 'slint', score = 'slrnsc', sol = 'solidity', smali = 'smali', @@ -983,6 +1023,8 @@ local extension = { mata = 'stata', ado = 'stata', stp = 'stp', + styl = 'stylus', + stylus = 'stylus', quark = 'supercollider', sface = 'surface', svelte = 'svelte', @@ -1005,6 +1047,7 @@ local extension = { tk = 'tcl', jacl = 'tcl', tl = 'teal', + templ = 'templ', tmpl = 'template', ti = 'terminfo', dtx = 'tex', @@ -1012,6 +1055,26 @@ local extension = { bbl = 'tex', latex = 'tex', sty = 'tex', + pgf = 'tex', + nlo = 'tex', + nls = 'tex', + thm = 'tex', + eps_tex = 'tex', + pygtex = 'tex', + pygstyle = 'tex', + clo = 'tex', + aux = 'tex', + brf = 'tex', + ind = 'tex', + lof = 'tex', + loe = 'tex', + nav = 'tex', + vrb = 'tex', + ins = 'tex', + tikz = 'tex', + bbx = 'tex', + cbx = 'tex', + beamer = 'tex', cls = detect.cls, texi = 'texinfo', txi = 'texinfo', @@ -1035,6 +1098,7 @@ local extension = { mts = 'typescript', cts = 'typescript', tsx = 'typescriptreact', + tsp = 'typespec', uc = 'uc', uit = 'uil', uil = 'uil', @@ -1062,6 +1126,7 @@ local extension = { vdmrt = 'vdmrt', vdmsl = 'vdmsl', vdm = 'vdmsl', + vto = 'vento', vr = 'vera', vri = 'vera', vrh = 'vera', @@ -1110,6 +1175,14 @@ local extension = { csproj = 'xml', wpl = 'xml', xmi = 'xml', + xpr = 'xml', + xpfm = 'xml', + spfm = 'xml', + bxml = 'xml', + xcu = 'xml', + xlb = 'xml', + xlc = 'xml', + xba = 'xml', xpm = detect_line1('XPM2', 'xpm2', 'xpm'), xpm2 = 'xpm2', xqy = 'xquery', @@ -1127,6 +1200,7 @@ local extension = { yml = 'yaml', yaml = 'yaml', eyaml = 'yaml', + mplstyle = 'yaml', yang = 'yang', yuck = 'yuck', z8a = 'z8a', @@ -1136,6 +1210,8 @@ local extension = { zut = 'zimbutempl', zs = 'zserio', zsh = 'zsh', + zunit = 'zsh', + ['zsh-theme'] = 'zsh', vala = 'vala', web = detect.web, pl = detect.pl, @@ -1229,7 +1305,12 @@ local filename = { ['/etc/default/cdrdao'] = 'cdrdaoconf', ['/etc/defaults/cdrdao'] = 'cdrdaoconf', ['cfengine.conf'] = 'cfengine', + cgdbrc = 'cgdbrc', + ['init.trans'] = 'clojure', + ['.trans'] = 'clojure', ['CMakeLists.txt'] = 'cmake', + ['CMakeCache.txt'] = 'cmakecache', + ['.cling_history'] = 'cpp', ['.alias'] = detect.csh, ['.cshrc'] = detect.csh, ['.login'] = detect.csh, @@ -1237,6 +1318,12 @@ local filename = { ['csh.login'] = detect.csh, ['csh.logout'] = detect.csh, ['auto.master'] = 'conf', + ['texdoc.cnf'] = 'conf', + ['.x11vncrc'] = 'conf', + ['.chktexrc'] = 'conf', + ['.ripgreprc'] = 'conf', + ripgreprc = 'conf', + ['.mbsyncrc'] = 'conf', ['configure.in'] = 'config', ['configure.ac'] = 'config', crontab = 'crontab', @@ -1262,12 +1349,31 @@ local filename = { npmrc = 'dosini', ['/etc/yum.conf'] = 'dosini', ['.npmrc'] = 'dosini', - ['/etc/pacman.conf'] = 'confini', + ['pip.conf'] = 'dosini', + ['setup.cfg'] = 'dosini', + ['pudb.cfg'] = 'dosini', + ['.coveragerc'] = 'dosini', + ['.pypirc'] = 'dosini', + ['.pylintrc'] = 'dosini', + ['pylintrc'] = 'dosini', + ['.replyrc'] = 'dosini', + ['.gitlint'] = 'dosini', + ['.oelint.cfg'] = 'dosini', + ['psprint.conf'] = 'dosini', + sofficerc = 'dosini', + ['mimeapps.list'] = 'dosini', + ['.wakatime.cfg'] = 'dosini', + ['nfs.conf'] = 'dosini', + ['nfsmount.conf'] = 'dosini', + ['.notmuch-config'] = 'dosini', + ['pacman.conf'] = 'confini', + ['paru.conf'] = 'confini', ['mpv.conf'] = 'confini', dune = 'dune', jbuild = 'dune', ['dune-workspace'] = 'dune', ['dune-project'] = 'dune', + Earthfile = 'earthfile', ['.editorconfig'] = 'editorconfig', ['elinks.conf'] = 'elinks', ['mix.lock'] = 'elixir', @@ -1302,7 +1408,7 @@ local filename = { ['.gnashpluginrc'] = 'gnash', gnashpluginrc = 'gnash', gnashrc = 'gnash', - ['.gnuplot'] = 'gnuplot', + ['.gnuplot_history'] = 'gnuplot', ['go.sum'] = 'gosum', ['go.work.sum'] = 'gosum', ['go.work'] = 'gowork', @@ -1328,6 +1434,10 @@ local filename = { ['/etc/host.conf'] = 'hostconf', ['/etc/hosts.allow'] = 'hostsaccess', ['/etc/hosts.deny'] = 'hostsaccess', + ['hyprland.conf'] = 'hyprlang', + ['hyprpaper.conf'] = 'hyprlang', + ['hypridle.conf'] = 'hyprlang', + ['hyprlock.conf'] = 'hyprlang', ['/.icewm/menu'] = 'icemenu', ['.indent.pro'] = 'indent', indentrc = 'indent', @@ -1335,17 +1445,21 @@ local filename = { ['ipf.conf'] = 'ipfilter', ['ipf6.conf'] = 'ipfilter', ['ipf.rules'] = 'ipfilter', + ['.node_repl_history'] = 'javascript', ['Pipfile.lock'] = 'json', ['.firebaserc'] = 'json', ['.prettierrc'] = 'json', ['.stylelintrc'] = 'json', + ['flake.lock'] = 'json', ['.babelrc'] = 'jsonc', ['.eslintrc'] = 'jsonc', ['.hintrc'] = 'jsonc', + ['.jscsrc'] = 'jsonc', ['.jsfmtrc'] = 'jsonc', ['.jshintrc'] = 'jsonc', ['.luaurc'] = 'jsonc', ['.swrc'] = 'jsonc', + ['.vsconfig'] = 'jsonc', ['.justfile'] = 'just', Kconfig = 'kconfig', ['Kconfig.debug'] = 'kconfig', @@ -1365,10 +1479,14 @@ local filename = { ['.lsl'] = detect.lsl, ['.busted'] = 'lua', ['.luacheckrc'] = 'lua', + ['.lua_history'] = 'lua', + ['config.ld'] = 'lua', + ['rock_manifest'] = 'lua', ['lynx.cfg'] = 'lynx', ['m3overrides'] = 'm3build', ['m3makefile'] = 'm3build', ['cm3.cfg'] = 'm3quake', + ['.m4_history'] = 'm4', ['.followup'] = 'mail', ['.article'] = 'mail', ['.letter'] = 'mail', @@ -1376,6 +1494,7 @@ local filename = { ['/etc/mail/aliases'] = 'mailaliases', mailcap = 'mailcap', ['.mailcap'] = 'mailcap', + Kbuild = 'make', ['/etc/man.conf'] = 'manconf', ['man.config'] = 'manconf', ['maxima-init.mac'] = 'maxima', @@ -1389,6 +1508,8 @@ local filename = { ['mplayer.conf'] = 'mplayerconf', mrxvtrc = 'mrxvtrc', ['.mrxvtrc'] = 'mrxvtrc', + ['.msmtprc'] = 'msmtp', + ['.mysql_history'] = 'mysql', ['/etc/nanorc'] = 'nanorc', Neomuttrc = 'neomuttrc', ['.netrc'] = 'netrc', @@ -1397,6 +1518,7 @@ local filename = { ['.octaverc'] = 'octave', octaverc = 'octave', ['octave.conf'] = 'octave', + ['.ondirrc'] = 'ondir', opam = 'opam', ['pacman.log'] = 'pacmanlog', ['/etc/pam.conf'] = 'pamconf', @@ -1441,8 +1563,11 @@ local filename = { ['MANIFEST.in'] = 'pymanifest', ['.pythonstartup'] = 'python', ['.pythonrc'] = 'python', + ['.python_history'] = 'python', + ['.jline-jython.history'] = 'python', SConstruct = 'python', qmldir = 'qmldir', + ['.Rhistory'] = 'r', ['.Rprofile'] = 'r', Rprofile = 'r', ['Rprofile.site'] = 'r', @@ -1452,12 +1577,16 @@ local filename = { ['.inputrc'] = 'readline', ['.reminders'] = 'remind', ['requirements.txt'] = 'requirements', + ['constraints.txt'] = 'requirements', + ['requirements.in'] = 'requirements', ['resolv.conf'] = 'resolv', ['robots.txt'] = 'robots', Gemfile = 'ruby', Puppetfile = 'ruby', ['.irbrc'] = 'ruby', irbrc = 'ruby', + ['.irb_history'] = 'ruby', + irb_history = 'ruby', Vagrantfile = 'ruby', ['smb.conf'] = 'samba', screenrc = 'screen', @@ -1467,10 +1596,15 @@ local filename = { ['/etc/services'] = 'services', ['/etc/serial.conf'] = 'setserial', ['/etc/udev/cdsymlinks.conf'] = 'sh', + ['.ash_history'] = 'sh', + ['makepkg.conf'] = 'sh', + ['.makepkg.conf'] = 'sh', + ['user-dirs.dirs'] = 'sh', + ['user-dirs.defaults'] = 'sh', + ['.xprofile'] = 'sh', ['bash.bashrc'] = detect.bash, bashrc = detect.bash, ['.bashrc'] = detect.bash, - ['.env'] = detect.sh, ['.kshrc'] = detect.ksh, ['.profile'] = detect.sh, ['/etc/profile'] = detect.sh, @@ -1484,6 +1618,7 @@ local filename = { ['/etc/slp.spi'] = 'slpspi', ['.slrnrc'] = 'slrnrc', ['sendmail.cf'] = 'sm', + ['.sqlite_history'] = 'sql', ['squid.conf'] = 'squid', ['ssh_config'] = 'sshconfig', ['sshd_config'] = 'sshdconfig', @@ -1496,7 +1631,10 @@ local filename = { ['undo.data'] = 'taskdata', ['.tclshrc'] = 'tcl', ['.wishrc'] = 'tcl', + ['.tclsh-history'] = 'tcl', ['tclsh.rc'] = 'tcl', + ['.xsctcmdhistory'] = 'tcl', + ['.xsdbcmdhistory'] = 'tcl', ['texmf.cnf'] = 'texmf', COPYING = 'text', README = 'text', @@ -1513,13 +1651,17 @@ local filename = { ['Gopkg.lock'] = 'toml', ['/.cargo/credentials'] = 'toml', ['Cargo.lock'] = 'toml', + ['.black'] = 'toml', + black = detect_line1('tool%.black', 'toml', nil), ['trustees.conf'] = 'trustees', + ['.ts_node_repl_history'] = 'typescript', ['/etc/udev/udev.conf'] = 'udevconf', ['/etc/updatedb.conf'] = 'updatedb', ['fdrupstream.log'] = 'upstreamlog', vgrindefs = 'vgrindefs', ['.exrc'] = 'vim', ['_exrc'] = 'vim', + ['.netrwhist'] = 'vim', ['_viminfo'] = 'viminfo', ['.viminfo'] = 'viminfo', ['.wgetrc'] = 'wget', @@ -1541,15 +1683,20 @@ local filename = { fglrxrc = 'xml', ['/etc/blkid.tab'] = 'xml', ['/etc/blkid.tab.old'] = 'xml', + ['fonts.conf'] = 'xml', ['.clangd'] = 'yaml', ['.clang-format'] = 'yaml', ['.clang-tidy'] = 'yaml', + ['yarn.lock'] = 'yaml', + matplotlibrc = 'yaml', + zathurarc = 'zathurarc', ['/etc/zprofile'] = 'zsh', ['.zlogin'] = 'zsh', ['.zlogout'] = 'zsh', ['.zshrc'] = 'zsh', ['.zprofile'] = 'zsh', ['.zcompdump'] = 'zsh', + ['.zsh_history'] = 'zsh', ['.zshenv'] = 'zsh', ['.zfbfmarks'] = 'zsh', -- END FILENAME @@ -1599,9 +1746,8 @@ local pattern = { ['.*%.blade%.php'] = 'blade', ['bzr_log%..*'] = 'bzr', ['.*enlightenment/.*%.cfg'] = 'c', - ['${HOME}/cabal%.config'] = 'cabalconfig', - ['${HOME}/%.config/cabal/config'] = 'cabalconfig', - ['${XDG_CONFIG_HOME}/cabal/config'] = 'cabalconfig', + ['.*/%.cabal/config'] = 'cabalconfig', + ['.*/cabal/config'] = 'cabalconfig', ['cabal%.project%..*'] = starsetf('cabalproject'), ['.*/%.calendar/.*'] = starsetf('calendar'), ['.*/share/calendar/.*/calendar%..*'] = starsetf('calendar'), @@ -1619,6 +1765,7 @@ local pattern = { }, ['[cC]hange[lL]og.*'] = starsetf(detect.changelog), ['.*%.%.ch'] = 'chill', + ['.*/etc/translate%-shell'] = 'clojure', ['.*%.cmake%.in'] = 'cmake', -- */cmus/rc and */.cmus/rc ['.*/%.?cmus/rc'] = 'cmusrc', @@ -1653,8 +1800,12 @@ local pattern = { ['php%.ini%-.*'] = 'dosini', ['.*/%.aws/config'] = 'confini', ['.*/%.aws/credentials'] = 'confini', - ['.*/etc/pacman%.conf'] = 'confini', ['.*/etc/yum%.conf'] = 'dosini', + ['.*/lxqt/.*%.conf'] = 'dosini', + ['.*/screengrab/.*%.conf'] = 'dosini', + ['.*/bpython/config'] = 'dosini', + ['.*/mypy/config'] = 'dosini', + ['.*/flatpak/repo/config'] = 'dosini', ['.*lvs'] = 'dracula', ['.*lpe'] = 'dracula', ['.*/dtrace/.*%.d'] = 'dtrace', @@ -1745,12 +1896,14 @@ local pattern = { ['.*%.[Ss][Uu][Bb]'] = 'krl', ['lilo%.conf.*'] = starsetf('lilo'), ['.*/etc/logcheck/.*%.d.*/.*'] = starsetf('logcheck'), + ['.*/ldscripts/.*'] = 'ld', ['.*lftp/rc'] = 'lftp', ['.*/%.libao'] = 'libao', ['.*/etc/libao%.conf'] = 'libao', ['.*/etc/.*limits%.conf'] = 'limits', ['.*/etc/limits'] = 'limits', ['.*/etc/.*limits%.d/.*%.conf'] = 'limits', + ['.*/supertux2/config'] = 'lisp', ['.*/LiteStep/.*/.*%.rc'] = 'litestep', ['.*/etc/login%.access'] = 'loginaccess', ['.*/etc/login%.defs'] = 'logindefs', @@ -1889,6 +2042,7 @@ local pattern = { ['.*%.[1-9]'] = detect.nroff, ['.*%.ml%.cppo'] = 'ocaml', ['.*%.mli%.cppo'] = 'ocaml', + ['.*/octave/history'] = 'octave', ['.*%.opam%.template'] = 'opam', ['.*/openvpn/.*/.*%.conf'] = 'openvpn', ['.*%.[Oo][Pp][Ll]'] = 'opl', @@ -1918,6 +2072,9 @@ local pattern = { ['.*/queries/.*%.scm'] = 'query', -- treesitter queries (Neovim only) ['.*,v'] = 'rcs', ['%.reminders.*'] = starsetf('remind'), + ['.*%-requirements%.txt'] = 'requirements', + ['requirements/.*%.txt'] = 'requirements', + ['requires/.*%.txt'] = 'requirements', ['[rR]akefile.*'] = starsetf('ruby'), ['[rR]antfile'] = 'ruby', ['[rR]akefile'] = 'ruby', @@ -1927,7 +2084,9 @@ local pattern = { ['.*/etc/services'] = 'services', ['.*/etc/serial%.conf'] = 'setserial', ['.*/etc/udev/cdsymlinks%.conf'] = 'sh', + ['.*/neofetch/config%.conf'] = 'sh', ['%.bash[_%-]aliases'] = detect.bash, + ['%.bash[_%-]history'] = detect.bash, ['%.bash[_%-]logout'] = detect.bash, ['%.bash[_%-]profile'] = detect.bash, ['%.kshrc.*'] = detect.ksh, @@ -1979,6 +2138,7 @@ local pattern = { ['.*termcap.*'] = starsetf(function(path, bufnr) return require('vim.filetype.detect').printcap('term') end), + ['.*/tex/latex/.*%.cfg'] = 'tex', ['.*%.t%.html'] = 'tilde', ['%.?tmux.*%.conf'] = 'tmux', ['%.?tmux.*%.conf.*'] = { 'tmux', { priority = -1 } }, @@ -1996,6 +2156,7 @@ local pattern = { ['.*/%.init/.*%.conf'] = 'upstart', ['.*/usr/share/upstart/.*%.override'] = 'upstart', ['.*%.[Ll][Oo][Gg]'] = detect.log, + ['.*/etc/config/.*'] = starsetf(detect.uci), ['.*%.vhdl_[0-9].*'] = starsetf('vhdl'), ['.*%.ws[fc]'] = 'wsh', ['.*/Xresources/.*'] = starsetf('xdefaults'), @@ -2022,6 +2183,7 @@ local pattern = { -- Increase priority to run before the pattern below ['XF86Config%-4.*'] = starsetf(detect.xfree86_v4, { priority = -math.huge + 1 }), ['XF86Config.*'] = starsetf(detect.xfree86_v3), + ['.*/%.bundle/config'] = 'yaml', ['%.zcompdump.*'] = starsetf('zsh'), -- .zlog* and zlog* ['%.?zlog.*'] = starsetf('zsh'), @@ -2029,7 +2191,7 @@ local pattern = { ['%.?zsh.*'] = starsetf('zsh'), -- Ignored extension ['.*~'] = function(path, bufnr) - local short = path:gsub('~$', '', 1) + local short = path:gsub('~+$', '', 1) if path ~= short and short ~= '' then return M.match({ buf = bufnr, filename = fn.fnameescape(short) }) end @@ -2157,7 +2319,6 @@ end --- vim.filetype.add { --- pattern = { --- ['.*'] = { ---- priority = -math.huge, --- function(path, bufnr) --- local content = vim.api.nvim_buf_get_lines(bufnr, 0, 1, false)[1] or '' --- if vim.regex([[^#!.*\\<mine\\>]]):match_str(content) ~= nil then @@ -2166,6 +2327,7 @@ end --- return 'drawing' --- end --- end, +--- { priority = -math.huge }, --- }, --- }, --- } @@ -2385,7 +2547,9 @@ function M.match(args) end -- Next, check file extension - local ext = fn.fnamemodify(name, ':e') + -- Don't use fnamemodify() with :e modifier here, + -- as that's empty when there is only an extension. + local ext = name:match('%.([^.]-)$') or '' ft, on_detect = dispatch(extension[ext], path, bufnr) if ft then return ft, on_detect diff --git a/runtime/lua/vim/filetype/detect.lua b/runtime/lua/vim/filetype/detect.lua index 3db4f2bcdc..ba86d8de5a 100644 --- a/runtime/lua/vim/filetype/detect.lua +++ b/runtime/lua/vim/filetype/detect.lua @@ -458,6 +458,9 @@ end --- @type vim.filetype.mapfn function M.def(_, bufnr) + if getline(bufnr, 1):find('%%%%') then + return 'tex' + end if vim.g.filetype_def == 'modula2' or is_modula2(bufnr) then return modula2(bufnr) end @@ -738,7 +741,9 @@ end --- @type vim.filetype.mapfn function M.inp(_, bufnr) - if getline(bufnr, 1):find('^%*') then + if getline(bufnr, 1):find('%%%%') then + return 'tex' + elseif getline(bufnr, 1):find('^%*') then return 'abaqus' else for _, line in ipairs(getlines(bufnr, 1, 500)) do @@ -889,6 +894,11 @@ local function m4(contents) end end +--- @type vim.filetype.mapfn +function M.markdown(_, _) + return vim.g.filetype_md or 'markdown' +end + --- Rely on the file to start with a comment. --- MS message text files use ';', Sendmail files use '#' or 'dnl' --- @type vim.filetype.mapfn @@ -1131,12 +1141,14 @@ end --- Distinguish between "default", Prolog and Cproto prototype file. --- @type vim.filetype.mapfn function M.proto(_, bufnr) - -- Cproto files have a comment in the first line and a function prototype in - -- the second line, it always ends in ";". Indent files may also have - -- comments, thus we can't match comments to see the difference. - -- IDL files can have a single ';' in the second line, require at least one - -- character before the ';'. - if getline(bufnr, 2):find('.;$') then + if getline(bufnr, 2):find('/%* Generated automatically %*/') then + return 'c' + elseif getline(bufnr, 2):find('.;$') then + -- Cproto files have a comment in the first line and a function prototype in + -- the second line, it always ends in ";". Indent files may also have + -- comments, thus we can't match comments to see the difference. + -- IDL files can have a single ';' in the second line, require at least one + -- character before the ';'. return 'cpp' end -- Recognize Prolog by specific text in the first non-empty line; @@ -1574,6 +1586,26 @@ function M.typ(_, bufnr) return 'typst' end +--- @type vim.filetype.mapfn +function M.uci(_, bufnr) + -- Return "uci" iff the file has a config or package statement near the + -- top of the file and all preceding lines were comments or blank. + for _, line in ipairs(getlines(bufnr, 1, 3)) do + -- Match a config or package statement at the start of the line. + if + line:find('^%s*[cp]%s+%S') + or line:find('^%s*config%s+%S') + or line:find('^%s*package%s+%S') + then + return 'uci' + end + -- Match a line that is either all blank or blank followed by a comment + if not (line:find('^%s*$') or line:find('^%s*#')) then + break + end + end +end + -- Determine if a .v file is Verilog, V, or Coq --- @type vim.filetype.mapfn function M.v(_, bufnr) diff --git a/runtime/lua/vim/fs.lua b/runtime/lua/vim/fs.lua index f9fe122f01..b05220ee2c 100644 --- a/runtime/lua/vim/fs.lua +++ b/runtime/lua/vim/fs.lua @@ -1,6 +1,7 @@ local M = {} local iswin = vim.uv.os_uname().sysname == 'Windows_NT' +local os_sep = iswin and '\\' or '/' --- Iterate over all the parents of the given path. --- @@ -47,19 +48,23 @@ function M.dirname(file) return nil end vim.validate({ file = { file, 's' } }) - if iswin and file:match('^%w:[\\/]?$') then - return (file:gsub('\\', '/')) - elseif not file:match('[\\/]') then + if iswin then + file = file:gsub(os_sep, '/') --[[@as string]] + if file:match('^%w:/?$') then + return file + end + end + if not file:match('/') then return '.' elseif file == '/' or file:match('^/[^/]+$') then return '/' end ---@type string - local dir = file:match('[/\\]$') and file:sub(1, #file - 1) or file:match('^([/\\]?.+)[/\\]') + local dir = file:match('/$') and file:sub(1, #file - 1) or file:match('^(/?.+)/') if iswin and dir:match('^%w:$') then return dir .. '/' end - return (dir:gsub('\\', '/')) + return dir end --- Return the basename of the given path @@ -72,10 +77,13 @@ function M.basename(file) return nil end vim.validate({ file = { file, 's' } }) - if iswin and file:match('^%w:[\\/]?$') then - return '' + if iswin then + file = file:gsub(os_sep, '/') --[[@as string]] + if file:match('^%w:/?$') then + return '' + end end - return file:match('[/\\]$') and '' or (file:match('[^\\/]*$'):gsub('\\', '/')) + return file:match('/$') and '' or (file:match('[^/]*$')) end --- Concatenate directories and/or file paths into a single path with normalization @@ -112,8 +120,9 @@ function M.dir(path, opts) skip = { opts.skip, { 'function' }, true }, }) + path = M.normalize(path) if not opts.depth or opts.depth == 1 then - local fs = vim.uv.fs_scandir(M.normalize(path)) + local fs = vim.uv.fs_scandir(path) return function() if not fs then return @@ -129,7 +138,7 @@ function M.dir(path, opts) --- @type string, integer local dir0, level = unpack(table.remove(dirs, 1)) local dir = level == 1 and dir0 or M.joinpath(path, dir0) - local fs = vim.uv.fs_scandir(M.normalize(dir)) + local fs = vim.uv.fs_scandir(dir) while fs do local name, t = vim.uv.fs_scandir_next(fs) if not name then @@ -189,13 +198,6 @@ end --- Examples: --- --- ```lua ---- -- location of Cargo.toml from the current buffer's path ---- local cargo = vim.fs.find('Cargo.toml', { ---- upward = true, ---- stop = vim.uv.os_homedir(), ---- path = vim.fs.dirname(vim.api.nvim_buf_get_name(0)), ---- }) ---- --- -- list all test directories under the runtime directory --- local test_dirs = vim.fs.find( --- {'test', 'tst', 'testdir'}, @@ -326,29 +328,204 @@ function M.find(names, opts) return matches end +--- Find the first parent directory containing a specific "marker", relative to a file path or +--- buffer. +--- +--- If the buffer is unnamed (has no backing file) or has a non-empty 'buftype' then the search +--- begins from Nvim's |current-directory|. +--- +--- Example: +--- +--- ```lua +--- -- Find the root of a Python project, starting from file 'main.py' +--- vim.fs.root(vim.fs.joinpath(vim.env.PWD, 'main.py'), {'pyproject.toml', 'setup.py' }) +--- +--- -- Find the root of a git repository +--- vim.fs.root(0, '.git') +--- +--- -- Find the parent directory containing any file with a .csproj extension +--- vim.fs.root(0, function(name, path) +--- return name:match('%.csproj$') ~= nil +--- end) +--- ``` +--- +--- @param source integer|string Buffer number (0 for current buffer) or file path (absolute or +--- relative to the |current-directory|) to begin the search from. +--- @param marker (string|string[]|fun(name: string, path: string): boolean) A marker, or list +--- of markers, to search for. If a function, the function is called for each +--- evaluated item and should return true if {name} and {path} are a match. +--- @return string? # Directory path containing one of the given markers, or nil if no directory was +--- found. +function M.root(source, marker) + assert(source, 'missing required argument: source') + assert(marker, 'missing required argument: marker') + + local path ---@type string + if type(source) == 'string' then + path = source + elseif type(source) == 'number' then + if vim.bo[source].buftype ~= '' then + path = assert(vim.uv.cwd()) + else + path = vim.api.nvim_buf_get_name(source) + end + else + error('invalid type for argument "source": expected string or buffer number') + end + + local paths = M.find(marker, { + upward = true, + path = vim.fn.fnamemodify(path, ':p:h'), + }) + + if #paths == 0 then + return nil + end + + return vim.fs.dirname(paths[1]) +end + +--- Split a Windows path into a prefix and a body, such that the body can be processed like a POSIX +--- path. The path must use forward slashes as path separator. +--- +--- Does not check if the path is a valid Windows path. Invalid paths will give invalid results. +--- +--- Examples: +--- - `//./C:/foo/bar` -> `//./C:`, `/foo/bar` +--- - `//?/UNC/server/share/foo/bar` -> `//?/UNC/server/share`, `/foo/bar` +--- - `//./system07/C$/foo/bar` -> `//./system07`, `/C$/foo/bar` +--- - `C:/foo/bar` -> `C:`, `/foo/bar` +--- - `C:foo/bar` -> `C:`, `foo/bar` +--- +--- @param path string Path to split. +--- @return string, string, boolean : prefix, body, whether path is invalid. +local function split_windows_path(path) + local prefix = '' + + --- Match pattern. If there is a match, move the matched pattern from the path to the prefix. + --- Returns the matched pattern. + --- + --- @param pattern string Pattern to match. + --- @return string|nil Matched pattern + local function match_to_prefix(pattern) + local match = path:match(pattern) + + if match then + prefix = prefix .. match --[[ @as string ]] + path = path:sub(#match + 1) + end + + return match + end + + local function process_unc_path() + return match_to_prefix('[^/]+/+[^/]+/+') + end + + if match_to_prefix('^//[?.]/') then + -- Device paths + local device = match_to_prefix('[^/]+/+') + + -- Return early if device pattern doesn't match, or if device is UNC and it's not a valid path + if not device or (device:match('^UNC/+$') and not process_unc_path()) then + return prefix, path, false + end + elseif match_to_prefix('^//') then + -- Process UNC path, return early if it's invalid + if not process_unc_path() then + return prefix, path, false + end + elseif path:match('^%w:') then + -- Drive paths + prefix, path = path:sub(1, 2), path:sub(3) + end + + -- If there are slashes at the end of the prefix, move them to the start of the body. This is to + -- ensure that the body is treated as an absolute path. For paths like C:foo/bar, there are no + -- slashes at the end of the prefix, so it will be treated as a relative path, as it should be. + local trailing_slash = prefix:match('/+$') + + if trailing_slash then + prefix = prefix:sub(1, -1 - #trailing_slash) + path = trailing_slash .. path --[[ @as string ]] + end + + return prefix, path, true +end + +--- Resolve `.` and `..` components in a POSIX-style path. This also removes extraneous slashes. +--- `..` is not resolved if the path is relative and resolving it requires the path to be absolute. +--- If a relative path resolves to the current directory, an empty string is returned. +--- +--- @see M.normalize() +--- @param path string Path to resolve. +--- @return string Resolved path. +local function path_resolve_dot(path) + local is_path_absolute = vim.startswith(path, '/') + local new_path_components = {} + + for component in vim.gsplit(path, '/') do + if component == '.' or component == '' then -- luacheck: ignore 542 + -- Skip `.` components and empty components + elseif component == '..' then + if #new_path_components > 0 and new_path_components[#new_path_components] ~= '..' then + -- For `..`, remove the last component if we're still inside the current directory, except + -- when the last component is `..` itself + table.remove(new_path_components) + elseif is_path_absolute then -- luacheck: ignore 542 + -- Reached the root directory in absolute path, do nothing + else + -- Reached current directory in relative path, add `..` to the path + table.insert(new_path_components, component) + end + else + table.insert(new_path_components, component) + end + end + + return (is_path_absolute and '/' or '') .. table.concat(new_path_components, '/') +end + --- @class vim.fs.normalize.Opts --- @inlinedoc --- --- Expand environment variables. --- (default: `true`) ---- @field expand_env boolean - ---- Normalize a path to a standard format. A tilde (~) character at the ---- beginning of the path is expanded to the user's home directory and any ---- backslash (\) characters are converted to forward slashes (/). Environment ---- variables are also expanded. +--- @field expand_env? boolean --- ---- Examples: +--- @field package _fast? boolean --- ---- ```lua ---- vim.fs.normalize('C:\\\\Users\\\\jdoe') ---- -- 'C:/Users/jdoe' +--- Path is a Windows path. +--- (default: `true` in Windows, `false` otherwise) +--- @field win? boolean + +--- Normalize a path to a standard format. A tilde (~) character at the beginning of the path is +--- expanded to the user's home directory and environment variables are also expanded. "." and ".." +--- components are also resolved, except when the path is relative and trying to resolve it would +--- result in an absolute path. +--- - "." as the only part in a relative path: +--- - "." => "." +--- - "././" => "." +--- - ".." when it leads outside the current directory +--- - "foo/../../bar" => "../bar" +--- - "../../foo" => "../../foo" +--- - ".." in the root directory returns the root directory. +--- - "/../../" => "/" --- ---- vim.fs.normalize('~/src/neovim') ---- -- '/home/jdoe/src/neovim' +--- On Windows, backslash (\) characters are converted to forward slashes (/). --- ---- vim.fs.normalize('$XDG_CONFIG_HOME/nvim/init.vim') ---- -- '/Users/jdoe/.config/nvim/init.vim' +--- Examples: +--- ```lua +--- [[C:\Users\jdoe]] => "C:/Users/jdoe" +--- "~/src/neovim" => "/home/jdoe/src/neovim" +--- "$XDG_CONFIG_HOME/nvim/init.vim" => "/Users/jdoe/.config/nvim/init.vim" +--- "~/src/nvim/api/../tui/./tui.c" => "/home/jdoe/src/nvim/tui/tui.c" +--- "./foo/bar" => "foo/bar" +--- "foo/../../../bar" => "../../bar" +--- "/home/jdoe/../../../bar" => "/bar" +--- "C:foo/../../baz" => "C:../baz" +--- "C:/foo/../../baz" => "C:/baz" +--- [[\\?\UNC\server\share\foo\..\..\..\bar]] => "//?/UNC/server/share/bar" --- ``` --- ---@param path (string) Path to normalize @@ -357,28 +534,79 @@ end function M.normalize(path, opts) opts = opts or {} - vim.validate({ - path = { path, { 'string' } }, - expand_env = { opts.expand_env, { 'boolean' }, true }, - }) + if not opts._fast then + vim.validate({ + path = { path, { 'string' } }, + expand_env = { opts.expand_env, { 'boolean' }, true }, + win = { opts.win, { 'boolean' }, true }, + }) + end + + local win = opts.win == nil and iswin or not not opts.win + local os_sep_local = win and '\\' or '/' + + -- Empty path is already normalized + if path == '' then + return '' + end - if path:sub(1, 1) == '~' then + -- Expand ~ to users home directory + if vim.startswith(path, '~') then local home = vim.uv.os_homedir() or '~' - if home:sub(-1) == '\\' or home:sub(-1) == '/' then + if home:sub(-1) == os_sep_local then home = home:sub(1, -2) end path = home .. path:sub(2) end + -- Expand environment variables if `opts.expand_env` isn't `false` if opts.expand_env == nil or opts.expand_env then path = path:gsub('%$([%w_]+)', vim.uv.os_getenv) end - path = path:gsub('\\', '/'):gsub('/+', '/') - if iswin and path:match('^%w:/$') then - return path + if win then + -- Convert path separator to `/` + path = path:gsub(os_sep_local, '/') + end + + -- Check for double slashes at the start of the path because they have special meaning + local double_slash = false + if not opts._fast then + double_slash = vim.startswith(path, '//') and not vim.startswith(path, '///') + end + + local prefix = '' + + if win then + local is_valid --- @type boolean + -- Split Windows paths into prefix and body to make processing easier + prefix, path, is_valid = split_windows_path(path) + + -- If path is not valid, return it as-is + if not is_valid then + return prefix .. path + end + + -- Remove extraneous slashes from the prefix + prefix = prefix:gsub('/+', '/') + end + + if not opts._fast then + -- Resolve `.` and `..` components and remove extraneous slashes from path, then recombine prefix + -- and path. + path = path_resolve_dot(path) end - return (path:gsub('(.)/$', '%1')) + + -- Preserve leading double slashes as they indicate UNC paths and DOS device paths in + -- Windows and have implementation-defined behavior in POSIX. + path = (double_slash and '/' or '') .. prefix .. path + + -- Change empty path to `.` + if path == '' then + path = '.' + end + + return path end return M diff --git a/runtime/lua/vim/func.lua b/runtime/lua/vim/func.lua index 206d1bae95..f71659ffb4 100644 --- a/runtime/lua/vim/func.lua +++ b/runtime/lua/vim/func.lua @@ -32,10 +32,11 @@ local M = {} --- first n arguments passed to {fn}. --- --- @param fn F Function to memoize. +--- @param strong? boolean Do not use a weak table --- @return F # Memoized version of {fn} --- @nodoc -function M._memoize(hash, fn) - return require('vim.func._memoize')(hash, fn) +function M._memoize(hash, fn, strong) + return require('vim.func._memoize')(hash, fn, strong) end return M diff --git a/runtime/lua/vim/func/_memoize.lua b/runtime/lua/vim/func/_memoize.lua index 835bf64c93..65210351bf 100644 --- a/runtime/lua/vim/func/_memoize.lua +++ b/runtime/lua/vim/func/_memoize.lua @@ -36,15 +36,19 @@ end --- @generic F: function --- @param hash integer|string|fun(...): any --- @param fn F +--- @param strong? boolean --- @return F -return function(hash, fn) +return function(hash, fn, strong) vim.validate({ hash = { hash, { 'number', 'string', 'function' } }, fn = { fn, 'function' }, }) ---@type table<any,table<any,any>> - local cache = setmetatable({}, { __mode = 'kv' }) + local cache = {} + if not strong then + setmetatable(cache, { __mode = 'kv' }) + end hash = resolve_hash(hash) diff --git a/runtime/lua/vim/health.lua b/runtime/lua/vim/health.lua index f6f7abef8f..f40f04a064 100644 --- a/runtime/lua/vim/health.lua +++ b/runtime/lua/vim/health.lua @@ -1,43 +1,96 @@ +--- @brief +---<pre>help +--- health.vim is a minimal framework to help users troubleshoot configuration and +--- any other environment conditions that a plugin might care about. Nvim ships +--- with healthchecks for configuration, performance, python support, ruby +--- support, clipboard support, and more. +--- +--- To run all healthchecks, use: >vim +--- +--- :checkhealth +--- < +--- Plugin authors are encouraged to write new healthchecks. |health-dev| +--- +--- Commands *health-commands* +--- +--- *:che* *:checkhealth* +--- :che[ckhealth] Run all healthchecks. +--- *E5009* +--- Nvim depends on |$VIMRUNTIME|, 'runtimepath' and 'packpath' to +--- find the standard "runtime files" for syntax highlighting, +--- filetype-specific behavior, and standard plugins (including +--- :checkhealth). If the runtime files cannot be found then +--- those features will not work. +--- +--- :che[ckhealth] {plugins} +--- Run healthcheck(s) for one or more plugins. E.g. to run only +--- the standard Nvim healthcheck: >vim +--- :checkhealth vim.health +--- < +--- To run the healthchecks for the "foo" and "bar" plugins +--- (assuming they are on 'runtimepath' and they have implemented +--- the Lua `require("foo.health").check()` interface): >vim +--- :checkhealth foo bar +--- < +--- To run healthchecks for Lua submodules, use dot notation or +--- "*" to refer to all submodules. For example Nvim provides +--- `vim.lsp` and `vim.treesitter`: >vim +--- :checkhealth vim.lsp vim.treesitter +--- :checkhealth vim* +--- < +--- +--- Create a healthcheck *health-dev* *vim.health* +--- +--- Healthchecks are functions that check the user environment, configuration, or +--- any other prerequisites that a plugin cares about. Nvim ships with +--- healthchecks in: +--- - $VIMRUNTIME/autoload/health/ +--- - $VIMRUNTIME/lua/vim/lsp/health.lua +--- - $VIMRUNTIME/lua/vim/treesitter/health.lua +--- - and more... +--- +--- To add a new healthcheck for your own plugin, simply create a "health.lua" +--- module on 'runtimepath' that returns a table with a "check()" function. Then +--- |:checkhealth| will automatically find and invoke the function. +--- +--- For example if your plugin is named "foo", define your healthcheck module at +--- one of these locations (on 'runtimepath'): +--- - lua/foo/health/init.lua +--- - lua/foo/health.lua +--- +--- If your plugin also provides a submodule named "bar" for which you want +--- a separate healthcheck, define the healthcheck at one of these locations: +--- - lua/foo/bar/health/init.lua +--- - lua/foo/bar/health.lua +--- +--- All such health modules must return a Lua table containing a `check()` +--- function. +--- +--- Copy this sample code into `lua/foo/health.lua`, replacing "foo" in the path +--- with your plugin name: >lua +--- +--- local M = {} +--- +--- M.check = function() +--- vim.health.start("foo report") +--- -- make sure setup function parameters are ok +--- if check_setup() then +--- vim.health.ok("Setup is correct") +--- else +--- vim.health.error("Setup is incorrect") +--- end +--- -- do some more checking +--- -- ... +--- end +--- +--- return M +---</pre> + local M = {} local s_output = {} ---@type string[] ---- Returns the fold text of the current healthcheck section -function M.foldtext() - local foldtext = vim.fn.foldtext() - - if vim.bo.filetype ~= 'checkhealth' then - return foldtext - end - - if vim.b.failedchecks == nil then - vim.b.failedchecks = vim.empty_dict() - end - - if vim.b.failedchecks[foldtext] == nil then - local warning = '- WARNING ' - local warninglen = string.len(warning) - local err = '- ERROR ' - local errlen = string.len(err) - local failedchecks = vim.b.failedchecks - failedchecks[foldtext] = false - - local foldcontent = vim.api.nvim_buf_get_lines(0, vim.v.foldstart - 1, vim.v.foldend, false) - for _, line in ipairs(foldcontent) do - if string.sub(line, 1, warninglen) == warning or string.sub(line, 1, errlen) == err then - failedchecks[foldtext] = true - break - end - end - - vim.b.failedchecks = failedchecks - end - - return vim.b.failedchecks[foldtext] and '+WE' .. foldtext:sub(4) or foldtext -end - ---- @param path string path to search for the healthcheck ---- @return string[] { name, func, type } representing a healthcheck +-- From a path return a list [{name}, {func}, {type}] representing a healthcheck local function filepath_to_healthcheck(path) path = vim.fs.normalize(path) local name --- @type string @@ -178,7 +231,9 @@ local function collect_output(output) vim.list_extend(s_output, vim.split(output, '\n')) end ---- Starts a new report. +--- Starts a new report. Most plugins should call this only once, but if +--- you want different sections to appear in your report, call this once +--- per section. --- --- @param name string function M.start(name) @@ -186,7 +241,7 @@ function M.start(name) collect_output(input) end ---- Reports a message in the current section. +--- Reports an informational message. --- --- @param msg string function M.info(msg) @@ -194,7 +249,7 @@ function M.info(msg) collect_output(input) end ---- Reports a successful healthcheck. +--- Reports a "success" message. --- --- @param msg string function M.ok(msg) @@ -202,7 +257,7 @@ function M.ok(msg) collect_output(input) end ---- Reports a health warning. +--- Reports a warning. --- --- @param msg string --- @param ... string|string[] Optional advice @@ -211,7 +266,7 @@ function M.warn(msg, ...) collect_output(input) end ---- Reports a failed healthcheck. +--- Reports an error. --- --- @param msg string --- @param ... string|string[] Optional advice @@ -220,54 +275,7 @@ function M.error(msg, ...) collect_output(input) end ---- @param type string -local function deprecate(type) - local before = string.format('vim.health.report_%s()', type) - local after = string.format('vim.health.%s()', type) - local message = vim.deprecate(before, after, '0.11') - if message then - M.warn(message) - end - vim.cmd.redraw() - vim.print('Running healthchecks...') -end - ---- @deprecated ---- @param name string -function M.report_start(name) - deprecate('start') - M.start(name) -end - ---- @deprecated ---- @param msg string -function M.report_info(msg) - deprecate('info') - M.info(msg) -end - ---- @deprecated ---- @param msg string -function M.report_ok(msg) - deprecate('ok') - M.ok(msg) -end - ---- @deprecated ---- @param msg string -function M.report_warn(msg, ...) - deprecate('warn') - M.warn(msg, ...) -end - ---- @deprecated ---- @param msg string -function M.report_error(msg, ...) - deprecate('error') - M.error(msg, ...) -end - -function M.provider_disabled(provider) +function M._provider_disabled(provider) local loaded_var = 'loaded_' .. provider .. '_provider' local v = vim.g[loaded_var] if v == 0 then @@ -307,7 +315,7 @@ local function shellify(cmd) return table.concat(escaped, ' ') end -function M.cmd_ok(cmd) +function M._cmd_ok(cmd) local out = vim.fn.system(cmd) return vim.v.shell_error == 0, out end @@ -320,7 +328,7 @@ end --- - stderr (boolean): Append stderr to stdout --- - ignore_error (boolean): If true, ignore error output --- - timeout (number): Number of seconds to wait before timing out (default 30) -function M.system(cmd, args) +function M._system(cmd, args) args = args or {} local stdin = args.stdin or '' local stderr = vim.F.if_nil(args.stderr, false) @@ -341,7 +349,7 @@ function M.system(cmd, args) if jobid < 1 then local message = - string.format('Command error (job=%d): %s (in %s)', jobid, shellify(cmd), vim.loop.cwd()) + string.format('Command error (job=%d): %s (in %s)', jobid, shellify(cmd), vim.uv.cwd()) error(message) return opts.output, 1 end @@ -360,7 +368,7 @@ function M.system(cmd, args) jobid, shell_error_code, shellify(cmd), - vim.loop.cwd() + vim.uv.cwd() ) if opts.output:find('%S') then emsg = string.format('%s\noutput: %s', emsg, opts.output) @@ -386,7 +394,7 @@ local path2name = function(path) path = path:gsub('^.*/lua/', '') -- Remove the filename (health.lua) - path = vim.fn.fnamemodify(path, ':h') + path = vim.fs.dirname(path) -- Change slashes to dots path = path:gsub('/', '.') @@ -401,17 +409,20 @@ end local PATTERNS = { '/autoload/health/*.vim', '/lua/**/**/health.lua', '/lua/**/**/health/init.lua' } --- :checkhealth completion function used by cmdexpand.c get_healthcheck_names() M._complete = function() - local names = vim.tbl_flatten(vim.tbl_map(function(pattern) - return vim.tbl_map(path2name, vim.api.nvim_get_runtime_file(pattern, true)) - end, PATTERNS)) - -- Remove duplicates - local unique = {} - vim.tbl_map(function(f) - unique[f] = true - end, names) + local unique = vim + .iter(vim.tbl_map(function(pattern) + return vim.tbl_map(path2name, vim.api.nvim_get_runtime_file(pattern, true)) + end, PATTERNS)) + :flatten() + :fold({}, function(t, name) + t[name] = true -- Remove duplicates + return t + end) -- vim.health is this file, which is not a healthcheck unique['vim'] = nil - return vim.tbl_keys(unique) + local rv = vim.tbl_keys(unique) + table.sort(rv) + return rv end --- Runs the specified healthchecks. @@ -497,11 +508,4 @@ function M._check(mods, plugin_names) vim.print('') end -local fn_bool = function(key) - return function(...) - return vim.fn[key](...) == 1 - end -end -M.executable = fn_bool('executable') - return M diff --git a/runtime/lua/nvim/health.lua b/runtime/lua/vim/health/health.lua index 0480e4df4e..5bc03199ee 100644 --- a/runtime/lua/nvim/health.lua +++ b/runtime/lua/vim/health/health.lua @@ -1,23 +1,11 @@ local M = {} local health = require('vim.health') -local fn_bool = function(key) - return function(...) - return vim.fn[key](...) == 1 - end -end - -local has = fn_bool('has') -local executable = fn_bool('executable') -local empty = fn_bool('empty') -local filereadable = fn_bool('filereadable') -local filewritable = fn_bool('filewritable') - local shell_error = function() return vim.v.shell_error ~= 0 end -local suggest_faq = 'https://github.com/neovim/neovim/blob/docs/install/BUILD.md#building' +local suggest_faq = 'https://github.com/neovim/neovim/blob/master/BUILD.md#building' local function check_runtime() health.start('Runtime') @@ -62,11 +50,11 @@ local function check_config() local init_lua = vim.fn.stdpath('config') .. '/init.lua' local init_vim = vim.fn.stdpath('config') .. '/init.vim' - local vimrc = empty(vim.env.MYVIMRC) and init_lua or vim.env.MYVIMRC + local vimrc = vim.env.MYVIMRC and vim.fn.expand(vim.env.MYVIMRC) or init_lua - if not filereadable(vimrc) and not filereadable(init_vim) then + if vim.fn.filereadable(vimrc) == 0 and vim.fn.filereadable(init_vim) == 0 then ok = false - local has_vim = filereadable(vim.fn.expand('~/.vimrc')) + local has_vim = vim.fn.filereadable(vim.fn.expand('~/.vimrc')) == 1 health.warn( ('%s user config file: %s'):format( -1 == vim.fn.getfsize(vimrc) and 'Missing' or 'Unreadable', @@ -77,7 +65,7 @@ local function check_config() end -- If $VIM is empty we don't care. Else make sure it is valid. - if not empty(vim.env.VIM) and not filereadable(vim.env.VIM .. '/runtime/doc/nvim.txt') then + if vim.env.VIM and vim.fn.filereadable(vim.env.VIM .. '/runtime/doc/nvim.txt') == 0 then ok = false health.error('$VIM is invalid: ' .. vim.env.VIM) end @@ -121,17 +109,17 @@ local function check_config() local writeable = true local shadaopt = vim.fn.split(vim.o.shada, ',') local shadafile = ( - empty(vim.o.shada) and vim.o.shada + vim.o.shada == '' and vim.o.shada or vim.fn.substitute(vim.fn.matchstr(shadaopt[#shadaopt], '^n.\\+'), '^n', '', '') ) shadafile = ( - empty(vim.o.shadafile) - and (empty(shadafile) and vim.fn.stdpath('state') .. '/shada/main.shada' or vim.fn.expand( + vim.o.shadafile == '' + and (shadafile == '' and vim.fn.stdpath('state') .. '/shada/main.shada' or vim.fn.expand( shadafile )) or (vim.o.shadafile == 'NONE' and '' or vim.o.shadafile) ) - if not empty(shadafile) and empty(vim.fn.glob(shadafile)) then + if shadafile ~= '' and vim.fn.glob(shadafile) == '' then -- Since this may be the first time Nvim has been run, try to create a shada file. if not pcall(vim.cmd.wshada) then writeable = false @@ -139,12 +127,15 @@ local function check_config() end if not writeable - or (not empty(shadafile) and (not filereadable(shadafile) or not filewritable(shadafile))) + or ( + shadafile ~= '' + and (vim.fn.filereadable(shadafile) == 0 or vim.fn.filewritable(shadafile) ~= 1) + ) then ok = false health.error( 'shada file is not ' - .. ((not writeable or filereadable(shadafile)) and 'writeable' or 'readable') + .. ((not writeable or vim.fn.filereadable(shadafile) == 1) and 'writeable' or 'readable') .. ':\n' .. shadafile ) @@ -160,7 +151,7 @@ local function check_performance() -- Check buildtype local buildtype = vim.fn.matchstr(vim.fn.execute('version'), [[\v\cbuild type:?\s*[^\n\r\t ]+]]) - if empty(buildtype) then + if buildtype == '' then health.error('failed to get build type from :version') elseif vim.regex([[\v(MinSizeRel|Release|RelWithDebInfo)]]):match_str(buildtype) then health.ok(buildtype) @@ -196,12 +187,12 @@ local function check_rplugin_manifest() local require_update = false local handle_path = function(path) local python_glob = vim.fn.glob(path .. '/rplugin/python*', true, true) - if empty(python_glob) then + if vim.tbl_isempty(python_glob) then return end local python_dir = python_glob[1] - local python_version = vim.fn.fnamemodify(python_dir, ':t') + local python_version = vim.fs.basename(python_dir) local scripts = vim.fn.glob(python_dir .. '/*.py', true, true) vim.list_extend(scripts, vim.fn.glob(python_dir .. '/*/__init__.py', true, true)) @@ -213,12 +204,12 @@ local function check_rplugin_manifest() script = vim.fn.tr(vim.fn.fnamemodify(script, ':h'), '\\', '/') end if not existing_rplugins[script] then - local msg = vim.fn.printf('"%s" is not registered.', vim.fn.fnamemodify(path, ':t')) + local msg = vim.fn.printf('"%s" is not registered.', vim.fs.basename(path)) if python_version == 'pythonx' then - if not has('python3') then + if vim.fn.has('python3') == 0 then msg = msg .. ' (python3 not available)' end - elseif not has(python_version) then + elseif vim.fn.has(python_version) == 0 then msg = msg .. vim.fn.printf(' (%s not available)', python_version) else require_update = true @@ -232,7 +223,7 @@ local function check_rplugin_manifest() end end - for _, path in ipairs(vim.fn.map(vim.fn.split(vim.o.runtimepath, ','), 'resolve(v:val)')) do + for _, path in ipairs(vim.fn.map(vim.split(vim.o.runtimepath, ','), 'resolve(v:val)')) do handle_path(path) end @@ -244,7 +235,7 @@ local function check_rplugin_manifest() end local function check_tmux() - if empty(vim.env.TMUX) or not executable('tmux') then + if not vim.env.TMUX or vim.fn.executable('tmux') == 0 then return end @@ -255,7 +246,7 @@ local function check_tmux() if shell_error() then health.error('command failed: ' .. cmd .. '\n' .. out) return 'error' - elseif empty(val) then + elseif val == '' then cmd = 'tmux show-option -qvgs ' .. option -- try session scope out = vim.fn.system(vim.fn.split(cmd)) val = vim.fn.substitute(out, [[\v(\s|\r|\n)]], '', 'g') @@ -274,7 +265,7 @@ local function check_tmux() { 'set escape-time in ~/.tmux.conf:\nset-option -sg escape-time 10', suggest_faq } local tmux_esc_time = get_tmux_option('escape-time') if tmux_esc_time ~= 'error' then - if empty(tmux_esc_time) then + if tmux_esc_time == '' then health.error('`escape-time` is not set', suggestions) elseif tonumber(tmux_esc_time) > 300 then health.error('`escape-time` (' .. tmux_esc_time .. ') is higher than 300ms', suggestions) @@ -286,7 +277,7 @@ local function check_tmux() -- check focus-events local tmux_focus_events = get_tmux_option('focus-events') if tmux_focus_events ~= 'error' then - if empty(tmux_focus_events) or tmux_focus_events ~= 'on' then + if tmux_focus_events == '' or tmux_focus_events ~= 'on' then health.warn( "`focus-events` is not enabled. |'autoread'| may not work.", { '(tmux 1.9+ only) Set `focus-events` in ~/.tmux.conf:\nset-option -g focus-events on' } @@ -301,7 +292,7 @@ local function check_tmux() local cmd = 'tmux show-option -qvg default-terminal' local out = vim.fn.system(vim.fn.split(cmd)) local tmux_default_term = vim.fn.substitute(out, [[\v(\s|\r|\n)]], '', 'g') - if empty(tmux_default_term) then + if tmux_default_term == '' then cmd = 'tmux show-option -qvgs default-terminal' out = vim.fn.system(vim.fn.split(cmd)) tmux_default_term = vim.fn.substitute(out, [[\v(\s|\r|\n)]], '', 'g') @@ -341,7 +332,7 @@ local function check_tmux() end local function check_terminal() - if not executable('infocmp') then + if vim.fn.executable('infocmp') == 0 then return end @@ -354,13 +345,12 @@ local function check_terminal() if shell_error() and ( - not has('win32') - or empty( - vim.fn.matchstr( + vim.fn.has('win32') == 0 + or vim.fn.matchstr( out, [[infocmp: couldn't open terminfo file .\+\%(conemu\|vtpcon\|win32con\)]] ) - ) + == '' ) then health.error('command failed: ' .. cmd .. '\n' .. out) @@ -368,14 +358,14 @@ local function check_terminal() health.info( vim.fn.printf( 'key_backspace (kbs) terminfo entry: `%s`', - (empty(kbs_entry) and '? (not found)' or kbs_entry) + (kbs_entry == '' and '? (not found)' or kbs_entry) ) ) health.info( vim.fn.printf( 'key_dc (kdch1) terminfo entry: `%s`', - (empty(kbs_entry) and '? (not found)' or kdch1_entry) + (kbs_entry == '' and '? (not found)' or kdch1_entry) ) ) end @@ -393,6 +383,19 @@ local function check_terminal() end end +local function check_external_tools() + health.start('External Tools') + + if vim.fn.executable('rg') == 1 then + local rg = vim.fn.exepath('rg') + local cmd = 'rg -V' + local out = vim.fn.system(vim.fn.split(cmd)) + health.ok(('%s (%s)'):format(vim.trim(out), rg)) + else + health.warn('ripgrep not available') + end +end + function M.check() check_config() check_runtime() @@ -400,6 +403,7 @@ function M.check() check_rplugin_manifest() check_terminal() check_tmux() + check_external_tools() end return M diff --git a/runtime/lua/vim/highlight.lua b/runtime/lua/vim/highlight.lua index effe280dee..f278bd357f 100644 --- a/runtime/lua/vim/highlight.lua +++ b/runtime/lua/vim/highlight.lua @@ -1,26 +1,3 @@ ----@brief ---- ---- Nvim includes a function for highlighting a selection on yank. ---- ---- To enable it, add the following to your `init.vim`: ---- ---- ```vim ---- au TextYankPost * silent! lua vim.highlight.on_yank() ---- ``` ---- ---- You can customize the highlight group and the duration of the highlight via: ---- ---- ```vim ---- au TextYankPost * silent! lua vim.highlight.on_yank {higroup="IncSearch", timeout=150} ---- ``` ---- ---- If you want to exclude visual selections from highlighting on yank, use: ---- ---- ```vim ---- au TextYankPost * silent! lua vim.highlight.on_yank {on_visual=false} ---- ``` ---- - local api = vim.api local M = {} @@ -40,6 +17,23 @@ M.priorities = { user = 200, } +--- @class vim.highlight.range.Opts +--- @inlinedoc +--- +--- Type of range. See [setreg()] +--- (default: `'charwise'`) +--- @field regtype? string +--- +--- Indicates whether the range is end-inclusive +--- (default: `false`) +--- @field inclusive? boolean +--- +--- Indicates priority of highlight +--- (default: `vim.highlight.priorities.user`) +--- @field priority? integer +--- +--- @field package _scoped? boolean + --- Apply highlight group to range of text. --- ---@param bufnr integer Buffer number to apply highlighting to @@ -47,10 +41,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 table|nil Optional parameters ---- - regtype type of range (see |setreg()|, default charwise) ---- - inclusive boolean indicating whether the range is end-inclusive (default false) ---- - priority number indicating priority of highlight (default priorities.user) +---@param opts? vim.highlight.range.Opts function M.range(bufnr, ns, higroup, start, finish, opts) opts = opts or {} local regtype = opts.regtype or 'v' @@ -80,10 +71,16 @@ function M.range(bufnr, ns, higroup, start, finish, opts) end local yank_ns = api.nvim_create_namespace('hlyank') -local yank_timer -local yank_cancel +local yank_timer --- @type uv.uv_timer_t? +local yank_cancel --- @type fun()? ---- Highlight the yanked text +--- 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} +--- ``` --- --- @param opts table|nil Optional parameters --- - higroup highlight group for yanked region (default "IncSearch") @@ -128,22 +125,23 @@ function M.on_yank(opts) local winid = vim.api.nvim_get_current_win() if yank_timer then yank_timer:close() + assert(yank_cancel) yank_cancel() end + vim.api.nvim__win_add_ns(winid, yank_ns) M.range(bufnr, yank_ns, higroup, "'[", "']", { regtype = event.regtype, inclusive = event.inclusive, priority = opts.priority or M.priorities.user, _scoped = true, }) - vim.api.nvim_win_add_ns(winid, yank_ns) yank_cancel = function() yank_timer = nil yank_cancel = nil pcall(vim.api.nvim_buf_clear_namespace, bufnr, yank_ns, 0, -1) - pcall(vim.api.nvim_win_remove_ns, winid, yank_ns) + pcall(vim.api.nvim__win_del_ns, winid, yank_ns) end yank_timer = vim.defer_fn(yank_cancel, timeout) diff --git a/runtime/lua/vim/iter.lua b/runtime/lua/vim/iter.lua index a37b7f7858..1093759efe 100644 --- a/runtime/lua/vim/iter.lua +++ b/runtime/lua/vim/iter.lua @@ -7,6 +7,7 @@ --- `vim.iter()`: --- --- - List tables (arrays, |lua-list|) yield only the value of each element. +--- - Holes (nil values) are allowed. --- - Use |Iter:enumerate()| to also pass the index to the next stage. --- - Or initialize with ipairs(): `vim.iter(ipairs(…))`. --- - Non-list tables (|lua-dict|) yield both the key and value of each element. @@ -60,9 +61,6 @@ --- vim.iter(rb):totable() --- -- { "a", "b" } --- ``` ---- ---- In addition to the |vim.iter()| function, the |vim.iter| module provides ---- convenience functions like |vim.iter.filter()| and |vim.iter.totable()|. --- LuaLS is bad at generics which this module mostly deals with --- @diagnostic disable:no-unknown @@ -83,13 +81,13 @@ end --- Special case implementations for iterators on list tables. ---@nodoc ----@class ListIter : Iter +---@class ArrayIter : Iter ---@field _table table Underlying table data ---@field _head number Index to the front of a table iterator ---@field _tail number Index to the end of a table iterator (exclusive) -local ListIter = {} -ListIter.__index = setmetatable(ListIter, Iter) -ListIter.__call = function(self) +local ArrayIter = {} +ArrayIter.__index = setmetatable(ArrayIter, Iter) +ArrayIter.__call = function(self) return self:next() end @@ -113,36 +111,34 @@ end local function sanitize(t) if type(t) == 'table' and getmetatable(t) == packedmt then - -- Remove length tag + -- Remove length tag and metatable t.n = nil + setmetatable(t, nil) end return t end ---- Flattens a single list-like table. Errors if it attempts to flatten a +--- Flattens a single array-like table. Errors if it attempts to flatten a --- dict-like table ----@param v table table which should be flattened +---@param t table table which should be flattened ---@param max_depth number depth to which the table should be flattened ---@param depth number current iteration depth ---@param result table output table that contains flattened result ---@return table|nil flattened table if it can be flattened, otherwise nil -local function flatten(v, max_depth, depth, result) - if depth < max_depth and type(v) == 'table' then - local i = 0 - for _ in pairs(v) do - i = i + 1 - - if v[i] == nil then +local function flatten(t, max_depth, depth, result) + if depth < max_depth and type(t) == 'table' then + for k, v in pairs(t) do + if type(k) ~= 'number' or k <= 0 or math.floor(k) ~= k then -- short-circuit: this is not a list like table return nil end - if flatten(v[i], max_depth, depth + 1, result) == nil then + if flatten(v, max_depth, depth + 1, result) == nil then return nil end end - else - result[#result + 1] = v + elseif t ~= nil then + result[#result + 1] = t end return result @@ -201,7 +197,7 @@ function Iter:filter(f) end ---@private -function ListIter:filter(f) +function ArrayIter:filter(f) local inc = self._head < self._tail and 1 or -1 local n = self._head for i = self._head, self._tail - inc, inc do @@ -236,11 +232,11 @@ end ---@return Iter ---@diagnostic disable-next-line:unused-local function Iter:flatten(depth) -- luacheck: no unused args - error('flatten() requires a list-like table') + error('flatten() requires an array-like table') end ---@private -function ListIter:flatten(depth) +function ArrayIter:flatten(depth) depth = depth or 1 local inc = self._head < self._tail and 1 or -1 local target = {} @@ -250,7 +246,7 @@ function ListIter:flatten(depth) -- exit early if we try to flatten a dict-like table if flattened == nil then - error('flatten() requires a list-like table') + error('flatten() requires an array-like table') end for _, v in pairs(flattened) do @@ -330,7 +326,7 @@ function Iter:map(f) end ---@private -function ListIter:map(f) +function ArrayIter:map(f) local inc = self._head < self._tail and 1 or -1 local n = self._head for i = self._head, self._tail - inc, inc do @@ -363,7 +359,7 @@ function Iter:each(f) end ---@private -function ListIter:each(f) +function ArrayIter:each(f) local inc = self._head < self._tail and 1 or -1 for i = self._head, self._tail - inc, inc do f(unpack(self._table[i])) @@ -374,7 +370,7 @@ end --- Collect the iterator into a table. --- --- The resulting table depends on the initial source in the iterator pipeline. ---- List-like tables and function iterators will be collected into a list-like +--- Array-like tables and function iterators will be collected into an array-like --- table. If multiple values are returned from the final stage in the iterator --- pipeline, each value will be included in a table. --- @@ -391,7 +387,7 @@ end --- -- { { 'a', 1 }, { 'c', 3 } } --- ``` --- ---- The generated table is a list-like table with consecutive, numeric indices. +--- The generated table is an array-like table with consecutive, numeric indices. --- To create a map-like table with arbitrary keys, use |Iter:fold()|. --- --- @@ -411,12 +407,12 @@ function Iter:totable() end ---@private -function ListIter:totable() - if self.next ~= ListIter.next or self._head >= self._tail then +function ArrayIter:totable() + if self.next ~= ArrayIter.next or self._head >= self._tail then return Iter.totable(self) end - local needs_sanitize = getmetatable(self._table[1]) == packedmt + local needs_sanitize = getmetatable(self._table[self._head]) == packedmt -- Reindex and sanitize. local len = self._tail - self._head @@ -453,20 +449,25 @@ function Iter:join(delim) return table.concat(self:totable(), delim) end ---- Folds ("reduces") an iterator into a single value. +--- Folds ("reduces") an iterator into a single value. [Iter:reduce()]() --- --- Examples: --- --- ```lua --- -- Create a new table with only even values ---- local t = { a = 1, b = 2, c = 3, d = 4 } ---- local it = vim.iter(t) ---- it:filter(function(k, v) return v % 2 == 0 end) ---- it:fold({}, function(t, k, v) ---- t[k] = v ---- return t ---- end) ---- -- { b = 2, d = 4 } +--- vim.iter({ a = 1, b = 2, c = 3, d = 4 }) +--- :filter(function(k, v) return v % 2 == 0 end) +--- :fold({}, function(acc, k, v) +--- acc[k] = v +--- return acc +--- end) --> { b = 2, d = 4 } +--- +--- -- Get the "maximum" item of an iterable. +--- vim.iter({ -99, -4, 3, 42, 0, 0, 7 }) +--- :fold({}, function(acc, v) +--- acc.max = math.max(v, acc.max or v) +--- return acc +--- end) --> { max = 42 } --- ``` --- ---@generic A @@ -491,7 +492,7 @@ function Iter:fold(init, f) end ---@private -function ListIter:fold(init, f) +function ArrayIter:fold(init, f) local acc = init local inc = self._head < self._tail and 1 or -1 for i = self._head, self._tail - inc, inc do @@ -523,7 +524,7 @@ function Iter:next() end ---@private -function ListIter:next() +function ArrayIter:next() if self._head ~= self._tail then local v = self._table[self._head] local inc = self._head < self._tail and 1 or -1 @@ -546,11 +547,11 @@ end --- ---@return Iter function Iter:rev() - error('rev() requires a list-like table') + error('rev() requires an array-like table') end ---@private -function ListIter:rev() +function ArrayIter:rev() local inc = self._head < self._tail and 1 or -1 self._head, self._tail = self._tail - inc, self._head - inc return self @@ -574,11 +575,11 @@ end --- ---@return any function Iter:peek() - error('peek() requires a list-like table') + error('peek() requires an array-like table') end ---@private -function ListIter:peek() +function ArrayIter:peek() if self._head ~= self._tail then return self._table[self._head] end @@ -633,7 +634,7 @@ function Iter:find(f) return unpack(result) end ---- Gets the first value in a |list-iterator| that satisfies a predicate, starting from the end. +--- Gets the first value satisfying a predicate, from the end of a |list-iterator|. --- --- Advances the iterator. Returns nil and drains the iterator if no value is found. --- @@ -655,11 +656,11 @@ end ---@return any ---@diagnostic disable-next-line: unused-local function Iter:rfind(f) -- luacheck: no unused args - error('rfind() requires a list-like table') + error('rfind() requires an array-like table') end ---@private -function ListIter:rfind(f) +function ArrayIter:rfind(f) if type(f) ~= 'function' then local val = f f = function(v) @@ -707,9 +708,10 @@ function Iter:take(n) end ---@private -function ListIter:take(n) - local inc = self._head < self._tail and 1 or -1 - self._tail = math.min(self._tail, self._head + n * inc) +function ArrayIter:take(n) + local inc = self._head < self._tail and n or -n + local cmp = self._head < self._tail and math.min or math.max + self._tail = cmp(self._tail, self._head + inc) return self end @@ -719,19 +721,19 @@ end --- --- ```lua --- local it = vim.iter({1, 2, 3, 4}) ---- it:nextback() +--- it:pop() --- -- 4 ---- it:nextback() +--- it:pop() --- -- 3 --- ``` --- ---@return any -function Iter:nextback() - error('nextback() requires a list-like table') +function Iter:pop() + error('pop() requires an array-like table') end --- @nodoc -function ListIter:nextback() +function ArrayIter:pop() if self._head ~= self._tail then local inc = self._head < self._tail and 1 or -1 self._tail = self._tail - inc @@ -741,27 +743,27 @@ end --- Gets the last value of a |list-iterator| without consuming it. --- ---- See also |Iter:last()|. ---- --- Example: --- --- ```lua --- local it = vim.iter({1, 2, 3, 4}) ---- it:peekback() +--- it:rpeek() --- -- 4 ---- it:peekback() +--- it:rpeek() --- -- 4 ---- it:nextback() +--- it:pop() --- -- 4 --- ``` --- +---@see Iter.last +--- ---@return any -function Iter:peekback() - error('peekback() requires a list-like table') +function Iter:rpeek() + error('rpeek() requires an array-like table') end ---@nodoc -function ListIter:peekback() +function ArrayIter:rpeek() if self._head ~= self._tail then local inc = self._head < self._tail and 1 or -1 return self._table[self._tail - inc] @@ -790,7 +792,7 @@ function Iter:skip(n) end ---@private -function ListIter:skip(n) +function ArrayIter:skip(n) local inc = self._head < self._tail and n or -n self._head = self._head + inc if (inc > 0 and self._head > self._tail) or (inc < 0 and self._head < self._tail) then @@ -799,27 +801,27 @@ function ListIter:skip(n) return self end ---- Skips `n` values backwards from the end of a |list-iterator| pipeline. +--- Discards `n` values from the end of a |list-iterator| pipeline. --- --- Example: --- --- ```lua ---- local it = vim.iter({ 1, 2, 3, 4, 5 }):skipback(2) +--- local it = vim.iter({ 1, 2, 3, 4, 5 }):rskip(2) --- it:next() --- -- 1 ---- it:nextback() +--- it:pop() --- -- 3 --- ``` --- ---@param n number Number of values to skip. ---@return Iter ---@diagnostic disable-next-line: unused-local -function Iter:skipback(n) -- luacheck: no unused args - error('skipback() requires a list-like table') +function Iter:rskip(n) -- luacheck: no unused args + error('rskip() requires an array-like table') end ---@private -function ListIter:skipback(n) +function ArrayIter:rskip(n) local inc = self._head < self._tail and n or -n self._tail = self._tail - inc if (inc > 0 and self._head > self._tail) or (inc < 0 and self._head < self._tail) then @@ -830,63 +832,49 @@ end --- Gets the nth value of an iterator (and advances to it). --- +--- If `n` is negative, offsets from the end of a |list-iterator|. +--- --- Example: --- --- ```lua ---- --- local it = vim.iter({ 3, 6, 9, 12 }) --- it:nth(2) --- -- 6 --- it:nth(2) --- -- 12 --- ---- ``` ---- ----@param n number The index of the value to return. ----@return any -function Iter:nth(n) - if n > 0 then - return self:skip(n - 1):next() - end -end - ---- Gets the nth value from the end of a |list-iterator| (and advances to it). ---- ---- Example: ---- ---- ```lua ---- ---- local it = vim.iter({ 3, 6, 9, 12 }) ---- it:nthback(2) +--- local it2 = vim.iter({ 3, 6, 9, 12 }) +--- it2:nth(-2) --- -- 9 ---- it:nthback(2) +--- it2:nth(-2) --- -- 3 ---- --- ``` --- ----@param n number The index of the value to return. +---@param n number Index of the value to return. May be negative if the source is a |list-iterator|. ---@return any -function Iter:nthback(n) +function Iter:nth(n) if n > 0 then - return self:skipback(n - 1):nextback() + return self:skip(n - 1):next() + elseif n < 0 then + return self:rskip(math.abs(n) - 1):pop() end end --- Sets the start and end of a |list-iterator| pipeline. --- ---- Equivalent to `:skip(first - 1):skipback(len - last + 1)`. +--- Equivalent to `:skip(first - 1):rskip(len - last + 1)`. --- ---@param first number ---@param last number ---@return Iter ---@diagnostic disable-next-line: unused-local function Iter:slice(first, last) -- luacheck: no unused args - error('slice() requires a list-like table') + error('slice() requires an array-like table') end ---@private -function ListIter:slice(first, last) - return self:skip(math.max(0, first - 1)):skipback(math.max(0, self._tail - last - 1)) +function ArrayIter:slice(first, last) + return self:skip(math.max(0, first - 1)):rskip(math.max(0, self._tail - last - 1)) end --- Returns true if any of the items in the iterator match the given predicate. @@ -952,6 +940,8 @@ end --- --- ``` --- +---@see Iter.rpeek +--- ---@return any function Iter:last() local last = self:next() @@ -964,7 +954,7 @@ function Iter:last() end ---@private -function ListIter:last() +function ArrayIter:last() local inc = self._head < self._tail and 1 or -1 local v = self._table[self._tail - inc] self._head = self._tail @@ -1009,7 +999,7 @@ function Iter:enumerate() end ---@private -function ListIter:enumerate() +function ArrayIter:enumerate() local inc = self._head < self._tail and 1 or -1 for i = self._head, self._tail - inc, inc do local v = self._table[i] @@ -1039,17 +1029,14 @@ function Iter.new(src, ...) local t = {} - -- O(n): scan the source table to decide if it is a list (consecutive integer indices 1…n). - local count = 0 - for _ in pairs(src) do - count = count + 1 - local v = src[count] - if v == nil then + -- O(n): scan the source table to decide if it is an array (only positive integer indices). + for k, v in pairs(src) do + if type(k) ~= 'number' or k <= 0 or math.floor(k) ~= k then return Iter.new(pairs(src)) end - t[count] = v + t[#t + 1] = v end - return ListIter.new(t) + return ArrayIter.new(t) end if type(src) == 'function' then @@ -1077,69 +1064,21 @@ function Iter.new(src, ...) return it end ---- Create a new ListIter +--- Create a new ArrayIter --- ----@param t table List-like table. Caller guarantees that this table is a valid list. +---@param t table Array-like table. Caller guarantees that this table is a valid array. Can have +--- holes (nil values). ---@return Iter ---@private -function ListIter.new(t) +function ArrayIter.new(t) local it = {} it._table = t it._head = 1 it._tail = #t + 1 - setmetatable(it, ListIter) + setmetatable(it, ArrayIter) return it end ---- Collects an |iterable| into a table. ---- ---- ```lua ---- -- Equivalent to: ---- vim.iter(f):totable() ---- ``` ---- ----@param f function Iterator function ----@return table -function M.totable(f, ...) - return Iter.new(f, ...):totable() -end - ---- Filters a table or other |iterable|. ---- ---- ```lua ---- -- Equivalent to: ---- vim.iter(src):filter(f):totable() ---- ``` ---- ----@see |Iter:filter()| ---- ----@param f fun(...):boolean Filter function. Accepts the current iterator or table values as ---- arguments and returns true if those values should be kept in the ---- final table ----@param src table|function Table or iterator function to filter ----@return table -function M.filter(f, src, ...) - return Iter.new(src, ...):filter(f):totable() -end - ---- Maps a table or other |iterable|. ---- ---- ```lua ---- -- Equivalent to: ---- vim.iter(src):map(f):totable() ---- ``` ---- ----@see |Iter:map()| ---- ----@param f fun(...): any? Map function. Accepts the current iterator or table values as ---- arguments and returns one or more new values. Nil values are removed ---- from the final table. ----@param src table|function Table or iterator function to filter ----@return table -function M.map(f, src, ...) - return Iter.new(src, ...):map(f):totable() -end - return setmetatable(M, { __call = function(_, ...) return Iter.new(...) diff --git a/runtime/lua/vim/keymap.lua b/runtime/lua/vim/keymap.lua index 84e9b4197d..ec00c56c7a 100644 --- a/runtime/lua/vim/keymap.lua +++ b/runtime/lua/vim/keymap.lua @@ -1,5 +1,20 @@ local keymap = {} +--- Table of |:map-arguments|. +--- Same as |nvim_set_keymap()| {opts}, except: +--- - {replace_keycodes} defaults to `true` if "expr" is `true`. +--- +--- Also accepts: +--- @class vim.keymap.set.Opts : vim.api.keyset.keymap +--- @inlinedoc +--- +--- Creates buffer-local mapping, `0` or `true` for current buffer. +--- @field buffer? integer|boolean +--- +--- Make the mapping recursive. Inverse of {noremap}. +--- (Default: `false`) +--- @field remap? boolean + --- Adds a new |mapping|. --- Examples: --- @@ -18,20 +33,12 @@ local keymap = {} --- vim.keymap.set('n', '[%%', '<Plug>(MatchitNormalMultiBackward)') --- ``` --- ----@param mode string|table Mode short-name, see |nvim_set_keymap()|. +---@param mode string|string[] Mode short-name, see |nvim_set_keymap()|. --- Can also be list of modes to create mapping on multiple modes. ---@param lhs string Left-hand side |{lhs}| of the mapping. ---@param rhs string|function Right-hand side |{rhs}| of the mapping, can be a Lua function. --- ----@param opts table|nil Table of |:map-arguments|. ---- - Same as |nvim_set_keymap()| {opts}, except: ---- - "replace_keycodes" defaults to `true` if "expr" is `true`. ---- - "noremap": inverse of "remap" (see below). ---- - Also accepts: ---- - "buffer": (integer|boolean) Creates buffer-local mapping, `0` or `true` ---- for current buffer. ---- - "remap": (boolean) Make the mapping recursive. Inverse of "noremap". ---- Defaults to `false`. +---@param opts? vim.keymap.set.Opts ---@see |nvim_set_keymap()| ---@see |maparg()| ---@see |mapcheck()| @@ -81,6 +88,13 @@ function keymap.set(mode, lhs, rhs, opts) end end +--- @class vim.keymap.del.Opts +--- @inlinedoc +--- +--- Remove a mapping from the given buffer. +--- When `0` or `true`, use the current buffer. +--- @field buffer? integer|boolean + --- Remove an existing mapping. --- Examples: --- @@ -92,11 +106,8 @@ end --- ---@param modes string|string[] ---@param lhs string ----@param opts table|nil A table of optional arguments: ---- - "buffer": (integer|boolean) Remove a mapping from the given buffer. ---- When `0` or `true`, use the current buffer. +---@param opts? vim.keymap.del.Opts ---@see |vim.keymap.set()| ---- function keymap.del(modes, lhs, opts) vim.validate({ mode = { modes, { 's', 't' } }, @@ -106,6 +117,7 @@ function keymap.del(modes, lhs, opts) opts = opts or {} modes = type(modes) == 'string' and { modes } or modes + --- @cast modes string[] local buffer = false ---@type false|integer if opts.buffer ~= nil then diff --git a/runtime/lua/vim/loader.lua b/runtime/lua/vim/loader.lua index d3d8948654..ea77a22416 100644 --- a/runtime/lua/vim/loader.lua +++ b/runtime/lua/vim/loader.lua @@ -85,7 +85,7 @@ function Loader.get_hash(path) end local function normalize(path) - return fs.normalize(path, { expand_env = false }) + return fs.normalize(path, { expand_env = false, _fast = true }) end --- Gets the rtp excluding after directories. diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index d5c376ba44..1592fd3151 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1,7 +1,5 @@ local api = vim.api -local tbl_isempty, tbl_extend = vim.tbl_isempty, vim.tbl_extend local validate = vim.validate -local if_nil = vim.F.if_nil local lsp = vim._defer_require('vim.lsp', { _changetracking = ..., --- @module 'vim.lsp._changetracking' @@ -45,6 +43,9 @@ lsp._request_name_to_capability = { [ms.textDocument_prepareCallHierarchy] = { 'callHierarchyProvider' }, [ms.callHierarchy_incomingCalls] = { 'callHierarchyProvider' }, [ms.callHierarchy_outgoingCalls] = { 'callHierarchyProvider' }, + [ms.textDocument_prepareTypeHierarchy] = { 'typeHierarchyProvider' }, + [ms.typeHierarchy_subtypes] = { 'typeHierarchyProvider' }, + [ms.typeHierarchy_supertypes] = { 'typeHierarchyProvider' }, [ms.textDocument_rename] = { 'renameProvider' }, [ms.textDocument_prepareRename] = { 'renameProvider', 'prepareProvider' }, [ms.textDocument_codeAction] = { 'codeActionProvider' }, @@ -63,6 +64,12 @@ lsp._request_name_to_capability = { [ms.textDocument_inlayHint] = { 'inlayHintProvider' }, [ms.textDocument_diagnostic] = { 'diagnosticProvider' }, [ms.inlayHint_resolve] = { 'inlayHintProvider', 'resolveProvider' }, + [ms.textDocument_documentLink] = { 'documentLinkProvider' }, + [ms.documentLink_resolve] = { 'documentLinkProvider', 'resolveProvider' }, + [ms.textDocument_didClose] = { 'textDocumentSync', 'openClose' }, + [ms.textDocument_didOpen] = { 'textDocumentSync', 'openClose' }, + [ms.textDocument_willSave] = { 'textDocumentSync', 'willSave' }, + [ms.textDocument_willSaveWaitUntil] = { 'textDocumentSync', 'willSaveWaitUntil' }, } -- TODO improve handling of scratch buffers with LSP attached. @@ -108,40 +115,7 @@ function lsp._buf_get_line_ending(bufnr) end -- Tracks all clients created via lsp.start_client -local active_clients = {} --- @type table<integer,vim.lsp.Client> -local all_buffer_active_clients = {} --- @type table<integer,table<integer,true>> -local uninitialized_clients = {} --- @type table<integer,vim.lsp.Client> - ----@param bufnr? integer ----@param fn fun(client: vim.lsp.Client, client_id: integer, bufnr: integer) -local function for_each_buffer_client(bufnr, fn, restrict_client_ids) - validate({ - fn = { fn, 'f' }, - restrict_client_ids = { restrict_client_ids, 't', true }, - }) - bufnr = resolve_bufnr(bufnr) - local client_ids = all_buffer_active_clients[bufnr] - if not client_ids or tbl_isempty(client_ids) then - return - end - - if restrict_client_ids and #restrict_client_ids > 0 then - local filtered_client_ids = {} --- @type table<integer,true> - for client_id in pairs(client_ids) do - if vim.list_contains(restrict_client_ids, client_id) then - filtered_client_ids[client_id] = true - end - end - client_ids = filtered_client_ids - end - - for client_id in pairs(client_ids) do - local client = active_clients[client_id] - if client then - fn(client, client_id, bufnr) - end - end -end +local all_clients = {} --- @type table<integer,vim.lsp.Client> local client_errors_base = table.maxn(lsp.rpc.client_errors) local client_errors_offset = 0 @@ -156,7 +130,7 @@ end --- Can be used to look up the string from a the number or the number --- from the string. --- @nodoc -lsp.client_errors = tbl_extend( +lsp.client_errors = vim.tbl_extend( 'error', lsp.rpc.client_errors, client_error('BEFORE_INIT_CALLBACK_ERROR'), @@ -199,16 +173,41 @@ local function once(fn) end end +--- @param client vim.lsp.Client +--- @param config vim.lsp.ClientConfig +--- @return boolean +local function reuse_client_default(client, config) + if client.name ~= config.name then + return false + end + + if config.root_dir then + 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 + return true + end + end + end + + -- TODO(lewis6991): also check config.workspace_folders + + return false +end + --- @class vim.lsp.start.Opts --- @inlinedoc --- --- Predicate used to decide if a client should be re-used. Used on all --- running clients. The default implementation re-uses a client if name and --- root_dir matches. ---- @field reuse_client fun(client: vim.lsp.Client, config: table): boolean +--- @field reuse_client fun(client: vim.lsp.Client, config: vim.lsp.ClientConfig): boolean --- --- Buffer handle to attach to if starting or re-using a client (0 for current). --- @field bufnr integer +--- +--- Suppress error reporting if the LSP server fails to start (default false). +--- @field silent? boolean --- Create a new LSP client and start a language server or reuses an already --- running client if one is found matching `name` and `root_dir`. @@ -220,7 +219,7 @@ end --- vim.lsp.start({ --- name = 'my-server-name', --- cmd = {'name-of-language-server-executable'}, ---- root_dir = vim.fs.dirname(vim.fs.find({'pyproject.toml', 'setup.py'}, { upward = true })[1]), +--- root_dir = vim.fs.root(0, {'pyproject.toml', 'setup.py'}), --- }) --- ``` --- @@ -229,9 +228,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.find()| 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()| 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. --- - `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. @@ -251,30 +250,32 @@ end --- @return integer? client_id function lsp.start(config, opts) opts = opts or {} - local reuse_client = opts.reuse_client - or function(client, conf) - return client.root_dir == conf.root_dir and client.name == conf.name - end - + local reuse_client = opts.reuse_client or reuse_client_default local bufnr = resolve_bufnr(opts.bufnr) - for _, clients in ipairs({ uninitialized_clients, lsp.get_clients() }) do - for _, client in pairs(clients) do - if reuse_client(client, config) then - lsp.buf_attach_client(bufnr, client.id) + for _, client in pairs(all_clients) do + if reuse_client(client, config) then + if lsp.buf_attach_client(bufnr, client.id) then return client.id + else + return nil end end end - local client_id = lsp.start_client(config) + local client_id, err = lsp.start_client(config) + if err then + if not opts.silent then + vim.notify(err, vim.log.levels.WARN) + end + return nil + end - if not client_id then - return -- lsp.start_client will have printed an error + if client_id and lsp.buf_attach_client(bufnr, client_id) then + return client_id end - lsp.buf_attach_client(bufnr, client_id) - return client_id + return nil end --- Consumes the latest progress messages from all clients and formats them as a string. @@ -317,6 +318,7 @@ local function is_empty_or_default(bufnr, option) end local info = api.nvim_get_option_info2(option, { buf = bufnr }) + ---@param e vim.fn.getscriptinfo.ret local scriptinfo = vim.tbl_filter(function(e) return e.sid == info.last_set_sid end, vim.fn.getscriptinfo()) @@ -355,7 +357,7 @@ function lsp._set_defaults(client, bufnr) and is_empty_or_default(bufnr, 'keywordprg') and vim.fn.maparg('K', 'n', false, false) == '' then - vim.keymap.set('n', 'K', vim.lsp.buf.hover, { buffer = bufnr }) + vim.keymap.set('n', 'K', vim.lsp.buf.hover, { buffer = bufnr, desc = 'vim.lsp.buf.hover()' }) end end) if client.supports_method(ms.textDocument_diagnostic) then @@ -383,48 +385,30 @@ local function reset_defaults(bufnr) end) end ---- @param client vim.lsp.Client -local function on_client_init(client) - local id = client.id - uninitialized_clients[id] = nil - -- Only assign after initialized. - active_clients[id] = client - -- If we had been registered before we start, then send didOpen This can - -- happen if we attach to buffers before initialize finishes or if - -- someone restarts a client. - for bufnr, client_ids in pairs(all_buffer_active_clients) do - if client_ids[id] then - client.on_attach(bufnr) - end - end -end - --- @param code integer --- @param signal integer --- @param client_id integer local function on_client_exit(code, signal, client_id) - local client = active_clients[client_id] or uninitialized_clients[client_id] - - for bufnr, client_ids in pairs(all_buffer_active_clients) do - if client_ids[client_id] then - vim.schedule(function() - if client and client.attached_buffers[bufnr] then - api.nvim_exec_autocmds('LspDetach', { - buffer = bufnr, - modeline = false, - data = { client_id = client_id }, - }) - end + local client = all_clients[client_id] + + for bufnr in pairs(client.attached_buffers) do + vim.schedule(function() + if client and client.attached_buffers[bufnr] then + api.nvim_exec_autocmds('LspDetach', { + buffer = bufnr, + modeline = false, + data = { client_id = client_id }, + }) + end - local namespace = vim.lsp.diagnostic.get_namespace(client_id) - vim.diagnostic.reset(namespace, bufnr) + local namespace = vim.lsp.diagnostic.get_namespace(client_id) + vim.diagnostic.reset(namespace, bufnr) + client.attached_buffers[bufnr] = nil - client_ids[client_id] = nil - if vim.tbl_isempty(client_ids) then - reset_defaults(bufnr) - end - end) - end + if #lsp.get_clients({ bufnr = bufnr, _uninitialized = true }) == 0 then + reset_defaults(bufnr) + end + end) end local name = client.name or 'unknown' @@ -432,8 +416,7 @@ local function on_client_exit(code, signal, client_id) -- Schedule the deletion of the client object so that it exists in the execution of LspDetach -- autocommands vim.schedule(function() - active_clients[client_id] = nil - uninitialized_clients[client_id] = nil + all_clients[client_id] = nil -- Client can be absent if executable starts, but initialize fails -- init/attach won't have happened @@ -455,51 +438,26 @@ end --- Starts and initializes a client with the given configuration. --- @param config vim.lsp.ClientConfig Configuration for the server. ---- @return integer|nil client_id |vim.lsp.get_client_by_id()| Note: client may not be ---- fully initialized. Use `on_init` to do any actions once ---- the client has been initialized. +--- @return integer? client_id |vim.lsp.get_client_by_id()| Note: client may not be +--- fully initialized. Use `on_init` to do any actions once +--- the client has been initialized. +--- @return string? # Error message, if any function lsp.start_client(config) - local client = require('vim.lsp.client').create(config) - - if not client then - return + local ok, res = pcall(require('vim.lsp.client').create, config) + if not ok then + return nil, res --[[@as string]] end - --- @diagnostic disable-next-line: invisible - table.insert(client._on_init_cbs, on_client_init) + local client = assert(res) + --- @diagnostic disable-next-line: invisible table.insert(client._on_exit_cbs, on_client_exit) - -- Store the uninitialized_clients for cleanup in case we exit before initialize finishes. - uninitialized_clients[client.id] = client + all_clients[client.id] = client client:initialize() - return client.id -end - ---- Notify all attached clients that a buffer has changed. ----@param _ integer ----@param bufnr integer ----@param changedtick integer ----@param firstline integer ----@param lastline integer ----@param new_lastline integer ----@return true? -local function text_document_did_change_handler( - _, - bufnr, - changedtick, - firstline, - lastline, - new_lastline -) - -- Detach (nvim_buf_attach) via returning True to on_lines if no clients are attached - if tbl_isempty(all_buffer_active_clients[bufnr] or {}) then - return true - end - util.buf_versions[bufnr] = changedtick - changetracking.send_changes(bufnr, firstline, lastline, new_lastline) + return client.id, nil end ---Buffer lifecycle handler for textDocument/didSave @@ -543,6 +501,117 @@ local function text_document_did_save_handler(bufnr) end end +---@param bufnr integer resolved buffer +---@param client vim.lsp.Client +local function buf_detach_client(bufnr, client) + api.nvim_exec_autocmds('LspDetach', { + buffer = bufnr, + modeline = false, + data = { client_id = client.id }, + }) + + changetracking.reset_buf(client, bufnr) + + if client.supports_method(ms.textDocument_didClose) then + local uri = vim.uri_from_bufnr(bufnr) + local params = { textDocument = { uri = uri } } + client.notify(ms.textDocument_didClose, params) + end + + client.attached_buffers[bufnr] = nil + util.buf_versions[bufnr] = nil + + local namespace = lsp.diagnostic.get_namespace(client.id) + vim.diagnostic.reset(namespace, bufnr) +end + +--- @type table<integer,true> +local attached_buffers = {} + +--- @param bufnr integer +local function buf_attach(bufnr) + if attached_buffers[bufnr] then + return + end + attached_buffers[bufnr] = true + + local uri = vim.uri_from_bufnr(bufnr) + local augroup = ('lsp_b_%d_save'):format(bufnr) + local group = api.nvim_create_augroup(augroup, { clear = true }) + api.nvim_create_autocmd('BufWritePre', { + group = group, + buffer = bufnr, + desc = 'vim.lsp: textDocument/willSave', + callback = function(ctx) + for _, client in ipairs(lsp.get_clients({ bufnr = ctx.buf })) do + local params = { + textDocument = { + uri = uri, + }, + reason = protocol.TextDocumentSaveReason.Manual, ---@type integer + } + if client.supports_method(ms.textDocument_willSave) then + client.notify(ms.textDocument_willSave, params) + end + if client.supports_method(ms.textDocument_willSaveWaitUntil) then + local result, err = + client.request_sync(ms.textDocument_willSaveWaitUntil, params, 1000, ctx.buf) + if result and result.result then + util.apply_text_edits(result.result, ctx.buf, client.offset_encoding) + elseif err then + log.error(vim.inspect(err)) + end + end + end + end, + }) + api.nvim_create_autocmd('BufWritePost', { + group = group, + buffer = bufnr, + desc = 'vim.lsp: textDocument/didSave handler', + callback = function(ctx) + text_document_did_save_handler(ctx.buf) + end, + }) + -- First time, so attach and set up stuff. + api.nvim_buf_attach(bufnr, false, { + on_lines = function(_, _, changedtick, firstline, lastline, new_lastline) + if #lsp.get_clients({ bufnr = bufnr }) == 0 then + return true -- detach + end + util.buf_versions[bufnr] = changedtick + changetracking.send_changes(bufnr, firstline, lastline, new_lastline) + end, + + on_reload = function() + local clients = lsp.get_clients({ bufnr = bufnr }) + local params = { textDocument = { uri = uri } } + for _, client in ipairs(clients) do + changetracking.reset_buf(client, bufnr) + if client.supports_method(ms.textDocument_didClose) then + client.notify(ms.textDocument_didClose, params) + end + end + for _, client in ipairs(clients) do + client:_text_document_did_open_handler(bufnr) + end + end, + + on_detach = function() + local clients = lsp.get_clients({ bufnr = bufnr, _uninitialized = true }) + for _, client in ipairs(clients) do + buf_detach_client(bufnr, client) + end + attached_buffers[bufnr] = nil + end, + + -- TODO if we know all of the potential clients ahead of time, then we + -- could conditionally set this. + -- utf_sizes = size_index > 1; + utf_sizes = true, + }) +end + --- Implements the `textDocument/did…` notifications required to track a buffer --- for any language server. --- @@ -561,92 +630,24 @@ function lsp.buf_attach_client(bufnr, client_id) log.warn(string.format('buf_attach_client called on unloaded buffer (id: %d): ', bufnr)) return false end - local buffer_client_ids = all_buffer_active_clients[bufnr] - -- This is our first time attaching to this buffer. - if not buffer_client_ids then - buffer_client_ids = {} - all_buffer_active_clients[bufnr] = buffer_client_ids - local uri = vim.uri_from_bufnr(bufnr) - local augroup = ('lsp_c_%d_b_%d_save'):format(client_id, bufnr) - local group = api.nvim_create_augroup(augroup, { clear = true }) - api.nvim_create_autocmd('BufWritePre', { - group = group, - buffer = bufnr, - desc = 'vim.lsp: textDocument/willSave', - callback = function(ctx) - for _, client in ipairs(lsp.get_clients({ bufnr = ctx.buf })) do - local params = { - textDocument = { - uri = uri, - }, - reason = protocol.TextDocumentSaveReason.Manual, - } - if vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'willSave') then - client.notify(ms.textDocument_willSave, params) - end - if vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'willSaveWaitUntil') then - local result, err = - client.request_sync(ms.textDocument_willSaveWaitUntil, params, 1000, ctx.buf) - if result and result.result then - util.apply_text_edits(result.result, ctx.buf, client.offset_encoding) - elseif err then - log.error(vim.inspect(err)) - end - end - end - end, - }) - api.nvim_create_autocmd('BufWritePost', { - group = group, - buffer = bufnr, - desc = 'vim.lsp: textDocument/didSave handler', - callback = function(ctx) - text_document_did_save_handler(ctx.buf) - end, - }) - -- First time, so attach and set up stuff. - api.nvim_buf_attach(bufnr, false, { - on_lines = text_document_did_change_handler, - on_reload = function() - local params = { textDocument = { uri = uri } } - for _, client in ipairs(lsp.get_clients({ bufnr = bufnr })) do - changetracking.reset_buf(client, bufnr) - if vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'openClose') then - client.notify(ms.textDocument_didClose, params) - end - client:_text_document_did_open_handler(bufnr) - end - end, - on_detach = function() - local params = { textDocument = { uri = uri } } - for _, client in ipairs(lsp.get_clients({ bufnr = bufnr })) do - changetracking.reset_buf(client, bufnr) - if vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'openClose') then - client.notify(ms.textDocument_didClose, params) - end - client.attached_buffers[bufnr] = nil - end - util.buf_versions[bufnr] = nil - all_buffer_active_clients[bufnr] = nil - end, - -- TODO if we know all of the potential clients ahead of time, then we - -- could conditionally set this. - -- utf_sizes = size_index > 1; - utf_sizes = true, - }) + local client = lsp.get_client_by_id(client_id) + if not client then + return false end - if buffer_client_ids[client_id] then + buf_attach(bufnr) + + if client.attached_buffers[bufnr] then return true end - -- This is our first time attaching this client to this buffer. - buffer_client_ids[client_id] = true - local client = active_clients[client_id] + client.attached_buffers[bufnr] = true + + -- This is our first time attaching this client to this buffer. -- Send didOpen for the client if it is initialized. If it isn't initialized -- then it will send didOpen on initialize. - if client then + if client.initialized then client:_on_attach(bufnr) end return true @@ -665,7 +666,7 @@ function lsp.buf_detach_client(bufnr, client_id) }) bufnr = resolve_bufnr(bufnr) - local client = lsp.get_client_by_id(client_id) + local client = all_clients[client_id] if not client or not client.attached_buffers[bufnr] then vim.notify( string.format( @@ -675,32 +676,9 @@ function lsp.buf_detach_client(bufnr, client_id) ) ) return + else + buf_detach_client(bufnr, client) end - - api.nvim_exec_autocmds('LspDetach', { - buffer = bufnr, - modeline = false, - data = { client_id = client_id }, - }) - - changetracking.reset_buf(client, bufnr) - - if vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'openClose') then - local uri = vim.uri_from_bufnr(bufnr) - local params = { textDocument = { uri = uri } } - client.notify(ms.textDocument_didClose, params) - end - - client.attached_buffers[bufnr] = nil - util.buf_versions[bufnr] = nil - - all_buffer_active_clients[bufnr][client_id] = nil - if #vim.tbl_keys(all_buffer_active_clients[bufnr]) == 0 then - all_buffer_active_clients[bufnr] = nil - end - - local namespace = lsp.diagnostic.get_namespace(client_id) - vim.diagnostic.reset(namespace, bufnr) end --- Checks if a buffer is attached for a particular client. @@ -708,7 +686,7 @@ end ---@param bufnr (integer) Buffer handle, or 0 for current ---@param client_id (integer) the client id function lsp.buf_is_attached(bufnr, client_id) - return (all_buffer_active_clients[resolve_bufnr(bufnr)] or {})[client_id] == true + return lsp.get_clients({ bufnr = bufnr, id = client_id, _uninitialized = true })[1] ~= nil end --- Gets a client by id, or nil if the id is invalid. @@ -718,7 +696,7 @@ end --- ---@return (nil|vim.lsp.Client) client rpc object function lsp.get_client_by_id(client_id) - return active_clients[client_id] or uninitialized_clients[client_id] + return all_clients[client_id] end --- Returns list of buffers attached to client_id. @@ -726,7 +704,7 @@ end ---@param client_id integer client id ---@return integer[] buffers list of buffer ids function lsp.get_buffers_by_client_id(client_id) - local client = lsp.get_client_by_id(client_id) + local client = all_clients[client_id] return client and vim.tbl_keys(client.attached_buffers) or {} end @@ -742,17 +720,22 @@ end --- By default asks the server to shutdown, unless stop was requested --- already for this client, then force-shutdown is attempted. --- ----@param client_id integer|vim.lsp.Client id or |vim.lsp.Client| object, or list thereof ----@param force boolean|nil shutdown forcefully +---@param client_id integer|integer[]|vim.lsp.Client[] id, list of id's, or list of |vim.lsp.Client| objects +---@param force? boolean shutdown forcefully function lsp.stop_client(client_id, force) + --- @type integer[]|vim.lsp.Client[] local ids = type(client_id) == 'table' and client_id or { client_id } for _, id in ipairs(ids) do - if type(id) == 'table' and id.stop ~= nil then - id.stop(force) - elseif active_clients[id] then - active_clients[id].stop(force) - elseif uninitialized_clients[id] then - uninitialized_clients[id].stop(true) + if type(id) == 'table' then + if id.stop then + id.stop(force) + end + else + --- @cast id -vim.lsp.Client + local client = all_clients[id] + if client then + client.stop(force) + end end end end @@ -772,6 +755,9 @@ end --- --- Only return clients supporting the given method --- @field method? string +--- +--- Also return uninitialized clients. +--- @field package _uninitialized? boolean --- Get active clients. --- @@ -784,15 +770,16 @@ function lsp.get_clients(filter) local clients = {} --- @type vim.lsp.Client[] - local t = filter.bufnr and (all_buffer_active_clients[resolve_bufnr(filter.bufnr)] or {}) - or active_clients - for client_id in pairs(t) do - local client = active_clients[client_id] + local bufnr = filter.bufnr and resolve_bufnr(filter.bufnr) + + for _, client in pairs(all_clients) do if client and (filter.id == nil or client.id == filter.id) + and (filter.bufnr == nil or client.attached_buffers[bufnr]) and (filter.name == nil or client.name == filter.name) and (filter.method == nil or client.supports_method(filter.method, { bufnr = filter.bufnr })) + and (filter._uninitialized or client.initialized) then clients[#clients + 1] = client end @@ -810,15 +797,9 @@ end api.nvim_create_autocmd('VimLeavePre', { desc = 'vim.lsp: exit handler', callback = function() + local active_clients = lsp.get_clients() log.info('exit_handler', active_clients) - for _, client in pairs(uninitialized_clients) do - client.stop(true) - end - -- TODO handle v:dying differently? - if tbl_isempty(active_clients) then - return - end - for _, client in pairs(active_clients) do + for _, client in pairs(all_clients) do client.stop() end @@ -827,7 +808,7 @@ api.nvim_create_autocmd('VimLeavePre', { local send_kill = false for client_id, client in pairs(active_clients) do - local timeout = if_nil(client.flags.exit_timeout, false) + local timeout = client.flags.exit_timeout if timeout then send_kill = true timeouts[client_id] = timeout @@ -910,7 +891,7 @@ function lsp.buf_request(bufnr, method, params, handler) local function _cancel_all_requests() for client_id, request_id in pairs(client_request_ids) do - local client = active_clients[client_id] + local client = all_clients[client_id] client.cancel_request(request_id) end end @@ -924,12 +905,12 @@ 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 handler fun(results: table<integer, {error: lsp.ResponseError?, result: any}>) (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:string, result:any}> + local results = {} --- @type table<integer,{error: lsp.ResponseError?, result: any}> local result_count = 0 local expected_result_count = 0 @@ -967,10 +948,10 @@ end ---@param params table? Parameters to send to the server ---@param timeout_ms integer? Maximum time in milliseconds to wait for a result. --- (default: `1000`) ----@return table<integer, {err: lsp.ResponseError, result: any}>? result Map of client_id:request_result. +---@return table<integer, {error: lsp.ResponseError?, result: any}>? result Map of client_id:request_result. ---@return string? err On timeout, cancel, or error, `err` is a string describing the failure reason, and `result` is nil. function lsp.buf_request_sync(bufnr, method, params, timeout_ms) - local request_results + local request_results ---@type table local cancel = lsp.buf_request_all(bufnr, method, params, function(it) request_results = it @@ -1106,7 +1087,7 @@ end ---@return boolean stopped true if client is stopped, false otherwise. function lsp.client_is_stopped(client_id) assert(client_id, 'missing client_id param') - return active_clients[client_id] == nil and not uninitialized_clients[client_id] + return not all_clients[client_id] end --- Gets a map of client_id:client pairs for the given buffer, where each value @@ -1172,7 +1153,11 @@ function lsp.for_each_buffer_client(bufnr, fn) 'lsp.get_clients({ bufnr = bufnr }) with regular loop', '0.12' ) - return for_each_buffer_client(bufnr, fn) + bufnr = resolve_bufnr(bufnr) + + for _, client in pairs(lsp.get_clients({ bufnr = bufnr })) do + fn(client, client.id, bufnr) + end end --- Function to manage overriding defaults for LSP handlers. diff --git a/runtime/lua/vim/lsp/_meta/protocol.lua b/runtime/lua/vim/lsp/_meta/protocol.lua index a5da5ac6b7..9a11972007 100644 --- a/runtime/lua/vim/lsp/_meta/protocol.lua +++ b/runtime/lua/vim/lsp/_meta/protocol.lua @@ -2534,8 +2534,14 @@ error('Cannot require a meta file') ---@proposed ---@field inlineCompletionProvider? boolean|lsp.InlineCompletionOptions --- +---Text document specific server capabilities. +--- +---@since 3.18.0 +---@proposed +---@field textDocument? lsp._anonym12.textDocument +--- ---Workspace specific server capabilities. ----@field workspace? lsp._anonym12.workspace +---@field workspace? lsp._anonym14.workspace --- ---Experimental server capabilities. ---@field experimental? lsp.LSPAny @@ -2598,8 +2604,10 @@ error('Cannot require a meta file') ---appears in the user interface. ---@field source? string --- ----The diagnostic's message. It usually appears in the user interface ----@field message string +---The diagnostic's message. It usually appears in the user interface. +--- +---@since 3.18.0 - support for `MarkupContent`. This is guarded by the client capability `textDocument.diagnostic.markupMessageSupport`. +---@field message string|lsp.MarkupContent --- ---Additional metadata about the diagnostic. --- @@ -2684,7 +2692,7 @@ error('Cannot require a meta file') ---capabilities. --- ---@since 3.17.0 ----@field completionItem? lsp._anonym13.completionItem +---@field completionItem? lsp._anonym15.completionItem ---Hover options. ---@class lsp.HoverOptions: lsp.WorkDoneProgressOptions @@ -2811,6 +2819,8 @@ error('Cannot require a meta file') ---errors are currently presented to the user for the given range. There is no guarantee ---that these accurately reflect the error state of the resource. The primary parameter ---to compute code actions is the provided range. +--- +---Note that the client should check the `textDocument.diagnostic.markupMessageSupport` server capability before sending diagnostics with markup messages to a server. ---@field diagnostics lsp.Diagnostic[] --- ---Requested kind of actions to return. @@ -3146,7 +3156,7 @@ error('Cannot require a meta file') ---@class lsp.NotebookDocumentSyncOptions --- ---The notebooks to be synced ----@field notebookSelector (lsp._anonym14.notebookSelector|lsp._anonym16.notebookSelector)[] +---@field notebookSelector (lsp._anonym16.notebookSelector|lsp._anonym18.notebookSelector)[] --- ---Whether save notification should be forwarded to ---the server. Will only be honored if mode === `notebook`. @@ -3514,7 +3524,7 @@ error('Cannot require a meta file') ---anymore since the information is outdated). --- ---@since 3.17.0 ----@field staleRequestSupport? lsp._anonym18.staleRequestSupport +---@field staleRequestSupport? lsp._anonym20.staleRequestSupport --- ---Client capabilities specific to regular expressions. --- @@ -3590,7 +3600,7 @@ error('Cannot require a meta file') ---create file, rename file and delete file changes. --- ---@since 3.16.0 ----@field changeAnnotationSupport? lsp._anonym19.changeAnnotationSupport +---@field changeAnnotationSupport? lsp._anonym21.changeAnnotationSupport ---@class lsp.DidChangeConfigurationClientCapabilities --- @@ -3617,20 +3627,20 @@ error('Cannot require a meta file') ---@field dynamicRegistration? boolean --- ---Specific capabilities for the `SymbolKind` in the `workspace/symbol` request. ----@field symbolKind? lsp._anonym20.symbolKind +---@field symbolKind? lsp._anonym22.symbolKind --- ---The client supports tags on `SymbolInformation`. ---Clients supporting tags have to handle unknown tags gracefully. --- ---@since 3.16.0 ----@field tagSupport? lsp._anonym21.tagSupport +---@field tagSupport? lsp._anonym23.tagSupport --- ---The client support partial workspace symbols. The client will send the ---request `workspaceSymbol/resolve` to the server to resolve additional ---properties. --- ---@since 3.17.0 ----@field resolveSupport? lsp._anonym22.resolveSupport +---@field resolveSupport? lsp._anonym24.resolveSupport ---The client capabilities of a {@link ExecuteCommandRequest}. ---@class lsp.ExecuteCommandClientCapabilities @@ -3775,9 +3785,9 @@ error('Cannot require a meta file') --- ---The client supports the following `CompletionItem` specific ---capabilities. ----@field completionItem? lsp._anonym23.completionItem +---@field completionItem? lsp._anonym25.completionItem --- ----@field completionItemKind? lsp._anonym27.completionItemKind +---@field completionItemKind? lsp._anonym29.completionItemKind --- ---Defines how the client handles whitespace and indentation ---when accepting a completion item that uses multi line @@ -3794,7 +3804,7 @@ error('Cannot require a meta file') ---capabilities. --- ---@since 3.17.0 ----@field completionList? lsp._anonym28.completionList +---@field completionList? lsp._anonym30.completionList ---@class lsp.HoverClientCapabilities --- @@ -3813,7 +3823,7 @@ error('Cannot require a meta file') --- ---The client supports the following `SignatureInformation` ---specific properties. ----@field signatureInformation? lsp._anonym29.signatureInformation +---@field signatureInformation? lsp._anonym31.signatureInformation --- ---The client supports to send additional context information for a ---`textDocument/signatureHelp` request. A client that opts into @@ -3891,7 +3901,7 @@ error('Cannot require a meta file') --- ---Specific capabilities for the `SymbolKind` in the ---`textDocument/documentSymbol` request. ----@field symbolKind? lsp._anonym31.symbolKind +---@field symbolKind? lsp._anonym33.symbolKind --- ---The client supports hierarchical document symbols. ---@field hierarchicalDocumentSymbolSupport? boolean @@ -3901,7 +3911,7 @@ error('Cannot require a meta file') ---Clients supporting tags have to handle unknown tags gracefully. --- ---@since 3.16.0 ----@field tagSupport? lsp._anonym32.tagSupport +---@field tagSupport? lsp._anonym34.tagSupport --- ---The client supports an additional label presented in the UI when ---registering a document symbol provider. @@ -3920,7 +3930,7 @@ error('Cannot require a meta file') ---set the request can only return `Command` literals. --- ---@since 3.8.0 ----@field codeActionLiteralSupport? lsp._anonym33.codeActionLiteralSupport +---@field codeActionLiteralSupport? lsp._anonym35.codeActionLiteralSupport --- ---Whether code action supports the `isPreferred` property. --- @@ -3943,7 +3953,7 @@ error('Cannot require a meta file') ---properties via a separate `codeAction/resolve` request. --- ---@since 3.16.0 ----@field resolveSupport? lsp._anonym35.resolveSupport +---@field resolveSupport? lsp._anonym37.resolveSupport --- ---Whether the client honors the change annotations in ---text edits and resource operations returned via the @@ -4051,12 +4061,12 @@ error('Cannot require a meta file') ---Specific options for the folding range kind. --- ---@since 3.17.0 ----@field foldingRangeKind? lsp._anonym36.foldingRangeKind +---@field foldingRangeKind? lsp._anonym38.foldingRangeKind --- ---Specific options for the folding range. --- ---@since 3.17.0 ----@field foldingRange? lsp._anonym37.foldingRange +---@field foldingRange? lsp._anonym39.foldingRange ---@class lsp.SelectionRangeClientCapabilities --- @@ -4075,7 +4085,7 @@ error('Cannot require a meta file') ---Clients supporting tags have to handle unknown tags gracefully. --- ---@since 3.15.0 ----@field tagSupport? lsp._anonym38.tagSupport +---@field tagSupport? lsp._anonym40.tagSupport --- ---Whether the client interprets the version property of the ---`textDocument/publishDiagnostics` notification's parameter. @@ -4119,7 +4129,7 @@ error('Cannot require a meta file') ---`request.range` are both set to true but the server only provides a ---range provider the client might not render a minimap correctly or might ---even decide to not show any semantic tokens at all. ----@field requests lsp._anonym39.requests +---@field requests lsp._anonym41.requests --- ---The token types that the client supports. ---@field tokenTypes string[] @@ -4202,7 +4212,7 @@ error('Cannot require a meta file') --- ---Indicates which properties a client can resolve lazily on an inlay ---hint. ----@field resolveSupport? lsp._anonym42.resolveSupport +---@field resolveSupport? lsp._anonym44.resolveSupport ---Client capabilities specific to diagnostic pull requests. --- @@ -4216,6 +4226,9 @@ error('Cannot require a meta file') --- ---Whether the clients supports related documents for document diagnostic pulls. ---@field relatedDocumentSupport? boolean +--- +---Whether the client supports `MarkupContent` in diagnostic messages. +---@field markupMessageSupport? boolean ---Client capabilities specific to inline completions. --- @@ -4244,7 +4257,7 @@ error('Cannot require a meta file') ---@class lsp.ShowMessageRequestClientCapabilities --- ---Capabilities specific to the `MessageActionItem` type. ----@field messageActionItem? lsp._anonym43.messageActionItem +---@field messageActionItem? lsp._anonym45.messageActionItem ---Client capabilities for the showDocument request. --- @@ -4671,7 +4684,7 @@ error('Cannot require a meta file') ---@since 3.17.0 ---@alias lsp.DocumentDiagnosticReport lsp.RelatedFullDocumentDiagnosticReport|lsp.RelatedUnchangedDocumentDiagnosticReport ----@alias lsp.PrepareRenameResult lsp.Range|lsp._anonym44.PrepareRenameResult|lsp._anonym45.PrepareRenameResult +---@alias lsp.PrepareRenameResult lsp.Range|lsp._anonym46.PrepareRenameResult|lsp._anonym47.PrepareRenameResult ---A document selector is the combination of one or many document filters. --- @@ -4692,7 +4705,7 @@ error('Cannot require a meta file') ---An event describing a change to a text document. If only a text is provided ---it is considered to be the full content of the document. ----@alias lsp.TextDocumentContentChangeEvent lsp._anonym46.TextDocumentContentChangeEvent|lsp._anonym47.TextDocumentContentChangeEvent +---@alias lsp.TextDocumentContentChangeEvent lsp._anonym48.TextDocumentContentChangeEvent|lsp._anonym49.TextDocumentContentChangeEvent ---MarkedString can be used to render human readable text. It is either a markdown string ---or a code-block that provides a language and a code snippet. The language identifier @@ -4706,7 +4719,7 @@ error('Cannot require a meta file') --- ---Note that markdown strings will be sanitized - that means html will be escaped. ---@deprecated use MarkupContent instead. ----@alias lsp.MarkedString string|lsp._anonym48.MarkedString +---@alias lsp.MarkedString string|lsp._anonym50.MarkedString ---A document filter describes a top level text document or ---a notebook cell document. @@ -4739,14 +4752,14 @@ error('Cannot require a meta file') ---\@sample A language filter that applies to all package.json paths: `{ language: 'json', pattern: '**package.json' }` --- ---@since 3.17.0 ----@alias lsp.TextDocumentFilter lsp._anonym49.TextDocumentFilter|lsp._anonym50.TextDocumentFilter|lsp._anonym51.TextDocumentFilter +---@alias lsp.TextDocumentFilter lsp._anonym51.TextDocumentFilter|lsp._anonym52.TextDocumentFilter|lsp._anonym53.TextDocumentFilter ---A notebook document filter denotes a notebook document by ---different properties. The properties will be match ---against the notebook's URI (same as with documents) --- ---@since 3.17.0 ----@alias lsp.NotebookDocumentFilter lsp._anonym52.NotebookDocumentFilter|lsp._anonym53.NotebookDocumentFilter|lsp._anonym54.NotebookDocumentFilter +---@alias lsp.NotebookDocumentFilter lsp._anonym54.NotebookDocumentFilter|lsp._anonym55.NotebookDocumentFilter|lsp._anonym56.NotebookDocumentFilter ---The glob pattern to watch relative to the base path. Glob patterns can have the following syntax: ---- `*` to match one or more characters in a path segment @@ -4856,7 +4869,19 @@ error('Cannot require a meta file') ---The client's version as defined by the client. ---@field version? string ----@class lsp._anonym12.workspace +---@class lsp._anonym13.textDocument.diagnostic +--- +---Whether the server supports `MarkupContent` in diagnostic messages. +---@field markupMessageSupport? boolean + +---@class lsp._anonym12.textDocument +--- +---Capabilities specific to the diagnostic pull model. +--- +---@since 3.18.0 +---@field diagnostic? lsp._anonym13.textDocument.diagnostic + +---@class lsp._anonym14.workspace --- ---The server supports workspace folder. --- @@ -4868,7 +4893,7 @@ error('Cannot require a meta file') ---@since 3.16.0 ---@field fileOperations? lsp.FileOperationOptions ----@class lsp._anonym13.completionItem +---@class lsp._anonym15.completionItem --- ---The server has support for completion item label ---details (see also `CompletionItemLabelDetails`) when @@ -4877,11 +4902,11 @@ error('Cannot require a meta file') ---@since 3.17.0 ---@field labelDetailsSupport? boolean ----@class lsp._anonym15.notebookSelector.cells +---@class lsp._anonym17.notebookSelector.cells --- ---@field language string ----@class lsp._anonym14.notebookSelector +---@class lsp._anonym16.notebookSelector --- ---The notebook to be synced If a string ---value is provided it matches against the @@ -4889,13 +4914,13 @@ error('Cannot require a meta file') ---@field notebook string|lsp.NotebookDocumentFilter --- ---The cells of the matching notebook to be synced. ----@field cells? lsp._anonym15.notebookSelector.cells[] +---@field cells? lsp._anonym17.notebookSelector.cells[] ----@class lsp._anonym17.notebookSelector.cells +---@class lsp._anonym19.notebookSelector.cells --- ---@field language string ----@class lsp._anonym16.notebookSelector +---@class lsp._anonym18.notebookSelector --- ---The notebook to be synced If a string ---value is provided it matches against the @@ -4903,9 +4928,9 @@ error('Cannot require a meta file') ---@field notebook? string|lsp.NotebookDocumentFilter --- ---The cells of the matching notebook to be synced. ----@field cells lsp._anonym17.notebookSelector.cells[] +---@field cells lsp._anonym19.notebookSelector.cells[] ----@class lsp._anonym18.staleRequestSupport +---@class lsp._anonym20.staleRequestSupport --- ---The client will actively cancel the request. ---@field cancel boolean @@ -4915,14 +4940,14 @@ error('Cannot require a meta file') ---response with error code `ContentModified` ---@field retryOnContentModified string[] ----@class lsp._anonym19.changeAnnotationSupport +---@class lsp._anonym21.changeAnnotationSupport --- ---Whether the client groups edits with equal labels into tree nodes, ---for instance all edits labelled with "Changes in Strings" would ---be a tree node. ---@field groupsOnLabel? boolean ----@class lsp._anonym20.symbolKind +---@class lsp._anonym22.symbolKind --- ---The symbol kind values the client supports. When this ---property exists the client also guarantees that it will @@ -4934,32 +4959,32 @@ error('Cannot require a meta file') ---the initial version of the protocol. ---@field valueSet? lsp.SymbolKind[] ----@class lsp._anonym21.tagSupport +---@class lsp._anonym23.tagSupport --- ---The tags supported by the client. ---@field valueSet lsp.SymbolTag[] ----@class lsp._anonym22.resolveSupport +---@class lsp._anonym24.resolveSupport --- ---The properties that a client can resolve lazily. Usually ---`location.range` ---@field properties string[] ----@class lsp._anonym24.completionItem.tagSupport +---@class lsp._anonym26.completionItem.tagSupport --- ---The tags supported by the client. ---@field valueSet lsp.CompletionItemTag[] ----@class lsp._anonym25.completionItem.resolveSupport +---@class lsp._anonym27.completionItem.resolveSupport --- ---The properties that a client can resolve lazily. ---@field properties string[] ----@class lsp._anonym26.completionItem.insertTextModeSupport +---@class lsp._anonym28.completionItem.insertTextModeSupport --- ---@field valueSet lsp.InsertTextMode[] ----@class lsp._anonym23.completionItem +---@class lsp._anonym25.completionItem --- ---Client supports snippets as insert text. --- @@ -4988,7 +5013,7 @@ error('Cannot require a meta file') ---a resolve call. --- ---@since 3.15.0 ----@field tagSupport? lsp._anonym24.completionItem.tagSupport +---@field tagSupport? lsp._anonym26.completionItem.tagSupport --- ---Client support insert replace edit to control different behavior if a ---completion item is inserted in the text or should replace text. @@ -5001,14 +5026,14 @@ error('Cannot require a meta file') ---and `details` could be resolved lazily. --- ---@since 3.16.0 ----@field resolveSupport? lsp._anonym25.completionItem.resolveSupport +---@field resolveSupport? lsp._anonym27.completionItem.resolveSupport --- ---The client supports the `insertTextMode` property on ---a completion item to override the whitespace handling mode ---as defined by the client (see `insertTextMode`). --- ---@since 3.16.0 ----@field insertTextModeSupport? lsp._anonym26.completionItem.insertTextModeSupport +---@field insertTextModeSupport? lsp._anonym28.completionItem.insertTextModeSupport --- ---The client has support for completion item label ---details (see also `CompletionItemLabelDetails`). @@ -5016,7 +5041,7 @@ error('Cannot require a meta file') ---@since 3.17.0 ---@field labelDetailsSupport? boolean ----@class lsp._anonym27.completionItemKind +---@class lsp._anonym29.completionItemKind --- ---The completion item kind values the client supports. When this ---property exists the client also guarantees that it will @@ -5028,7 +5053,7 @@ error('Cannot require a meta file') ---the initial version of the protocol. ---@field valueSet? lsp.CompletionItemKind[] ----@class lsp._anonym28.completionList +---@class lsp._anonym30.completionList --- ---The client supports the following itemDefaults on ---a completion list. @@ -5040,7 +5065,7 @@ error('Cannot require a meta file') ---@since 3.17.0 ---@field itemDefaults? string[] ----@class lsp._anonym30.signatureInformation.parameterInformation +---@class lsp._anonym32.signatureInformation.parameterInformation --- ---The client supports processing label offsets instead of a ---simple label string. @@ -5048,14 +5073,14 @@ error('Cannot require a meta file') ---@since 3.14.0 ---@field labelOffsetSupport? boolean ----@class lsp._anonym29.signatureInformation +---@class lsp._anonym31.signatureInformation --- ---Client supports the following content formats for the documentation ---property. The order describes the preferred format of the client. ---@field documentationFormat? lsp.MarkupKind[] --- ---Client capabilities specific to parameter information. ----@field parameterInformation? lsp._anonym30.signatureInformation.parameterInformation +---@field parameterInformation? lsp._anonym32.signatureInformation.parameterInformation --- ---The client supports the `activeParameter` property on `SignatureInformation` ---literal. @@ -5070,7 +5095,7 @@ error('Cannot require a meta file') ---@since 3.18.0 ---@field noActiveParameterSupport? boolean ----@class lsp._anonym31.symbolKind +---@class lsp._anonym33.symbolKind --- ---The symbol kind values the client supports. When this ---property exists the client also guarantees that it will @@ -5082,12 +5107,12 @@ error('Cannot require a meta file') ---the initial version of the protocol. ---@field valueSet? lsp.SymbolKind[] ----@class lsp._anonym32.tagSupport +---@class lsp._anonym34.tagSupport --- ---The tags supported by the client. ---@field valueSet lsp.SymbolTag[] ----@class lsp._anonym34.codeActionLiteralSupport.codeActionKind +---@class lsp._anonym36.codeActionLiteralSupport.codeActionKind --- ---The code action kind values the client supports. When this ---property exists the client also guarantees that it will @@ -5095,18 +5120,18 @@ error('Cannot require a meta file') ---to a default value when unknown. ---@field valueSet lsp.CodeActionKind[] ----@class lsp._anonym33.codeActionLiteralSupport +---@class lsp._anonym35.codeActionLiteralSupport --- ---The code action kind is support with the following value ---set. ----@field codeActionKind lsp._anonym34.codeActionLiteralSupport.codeActionKind +---@field codeActionKind lsp._anonym36.codeActionLiteralSupport.codeActionKind ----@class lsp._anonym35.resolveSupport +---@class lsp._anonym37.resolveSupport --- ---The properties that a client can resolve lazily. ---@field properties string[] ----@class lsp._anonym36.foldingRangeKind +---@class lsp._anonym38.foldingRangeKind --- ---The folding range kind values the client supports. When this ---property exists the client also guarantees that it will @@ -5114,7 +5139,7 @@ error('Cannot require a meta file') ---to a default value when unknown. ---@field valueSet? lsp.FoldingRangeKind[] ----@class lsp._anonym37.foldingRange +---@class lsp._anonym39.foldingRange --- ---If set, the client signals that it supports setting collapsedText on ---folding ranges to display custom labels instead of the default text. @@ -5122,52 +5147,52 @@ error('Cannot require a meta file') ---@since 3.17.0 ---@field collapsedText? boolean ----@class lsp._anonym38.tagSupport +---@class lsp._anonym40.tagSupport --- ---The tags supported by the client. ---@field valueSet lsp.DiagnosticTag[] ----@class lsp._anonym40.requests.range +---@class lsp._anonym42.requests.range ----@class lsp._anonym41.requests.full +---@class lsp._anonym43.requests.full --- ---The client will send the `textDocument/semanticTokens/full/delta` request if ---the server provides a corresponding handler. ---@field delta? boolean ----@class lsp._anonym39.requests +---@class lsp._anonym41.requests --- ---The client will send the `textDocument/semanticTokens/range` request if ---the server provides a corresponding handler. ----@field range? boolean|lsp._anonym40.requests.range +---@field range? boolean|lsp._anonym42.requests.range --- ---The client will send the `textDocument/semanticTokens/full` request if ---the server provides a corresponding handler. ----@field full? boolean|lsp._anonym41.requests.full +---@field full? boolean|lsp._anonym43.requests.full ----@class lsp._anonym42.resolveSupport +---@class lsp._anonym44.resolveSupport --- ---The properties that a client can resolve lazily. ---@field properties string[] ----@class lsp._anonym43.messageActionItem +---@class lsp._anonym45.messageActionItem --- ---Whether the client supports additional attributes which ---are preserved and send back to the server in the ---request's response. ---@field additionalPropertiesSupport? boolean ----@class lsp._anonym44.PrepareRenameResult +---@class lsp._anonym46.PrepareRenameResult --- ---@field range lsp.Range --- ---@field placeholder string ----@class lsp._anonym45.PrepareRenameResult +---@class lsp._anonym47.PrepareRenameResult --- ---@field defaultBehavior boolean ----@class lsp._anonym46.TextDocumentContentChangeEvent +---@class lsp._anonym48.TextDocumentContentChangeEvent --- ---The range of the document that changed. ---@field range lsp.Range @@ -5180,18 +5205,18 @@ error('Cannot require a meta file') ---The new text for the provided range. ---@field text string ----@class lsp._anonym47.TextDocumentContentChangeEvent +---@class lsp._anonym49.TextDocumentContentChangeEvent --- ---The new text of the whole document. ---@field text string ----@class lsp._anonym48.MarkedString +---@class lsp._anonym50.MarkedString --- ---@field language string --- ---@field value string ----@class lsp._anonym49.TextDocumentFilter +---@class lsp._anonym51.TextDocumentFilter --- ---A language id, like `typescript`. ---@field language string @@ -5202,7 +5227,7 @@ error('Cannot require a meta file') ---A glob pattern, like **/*.{ts,js}. See TextDocumentFilter for examples. ---@field pattern? string ----@class lsp._anonym50.TextDocumentFilter +---@class lsp._anonym52.TextDocumentFilter --- ---A language id, like `typescript`. ---@field language? string @@ -5213,7 +5238,7 @@ error('Cannot require a meta file') ---A glob pattern, like **/*.{ts,js}. See TextDocumentFilter for examples. ---@field pattern? string ----@class lsp._anonym51.TextDocumentFilter +---@class lsp._anonym53.TextDocumentFilter --- ---A language id, like `typescript`. ---@field language? string @@ -5224,7 +5249,7 @@ error('Cannot require a meta file') ---A glob pattern, like **/*.{ts,js}. See TextDocumentFilter for examples. ---@field pattern string ----@class lsp._anonym52.NotebookDocumentFilter +---@class lsp._anonym54.NotebookDocumentFilter --- ---The type of the enclosing notebook. ---@field notebookType string @@ -5235,7 +5260,7 @@ error('Cannot require a meta file') ---A glob pattern. ---@field pattern? string ----@class lsp._anonym53.NotebookDocumentFilter +---@class lsp._anonym55.NotebookDocumentFilter --- ---The type of the enclosing notebook. ---@field notebookType? string @@ -5246,7 +5271,7 @@ error('Cannot require a meta file') ---A glob pattern. ---@field pattern? string ----@class lsp._anonym54.NotebookDocumentFilter +---@class lsp._anonym56.NotebookDocumentFilter --- ---The type of the enclosing notebook. ---@field notebookType? string diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index 50121f30b2..49833eaeec 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -35,13 +35,13 @@ function M.hover() request(ms.textDocument_hover, params) end -local function request_with_options(name, params, options) +local function request_with_opts(name, params, opts) local req_handler --- @type function? - if options then + 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] - handler(err, result, ctx, vim.tbl_extend('force', config or {}, options)) + handler(err, result, ctx, vim.tbl_extend('force', config or {}, opts)) end end request(name, params, req_handler) @@ -62,14 +62,13 @@ end --- vim.lsp.buf.references(nil, { on_list = on_list }) --- ``` --- ---- If you prefer loclist do something like this: +--- If you prefer loclist instead of qflist: --- ```lua ---- local function on_list(options) ---- vim.fn.setloclist(0, {}, ' ', options) ---- vim.cmd.lopen() ---- end +--- vim.lsp.buf.definition({ loclist = true }) +--- vim.lsp.buf.references(nil, { loclist = true }) --- ``` --- @field on_list? fun(t: vim.lsp.LocationOpts.OnList) +--- @field loclist? boolean --- @class vim.lsp.LocationOpts.OnList --- @field items table[] Structured like |setqflist-what| @@ -83,32 +82,32 @@ end --- Jumps to the declaration of the symbol under the cursor. --- @note Many servers do not implement this method. Generally, see |vim.lsp.buf.definition()| instead. ---- @param options? vim.lsp.LocationOpts -function M.declaration(options) +--- @param opts? vim.lsp.LocationOpts +function M.declaration(opts) local params = util.make_position_params() - request_with_options(ms.textDocument_declaration, params, options) + request_with_opts(ms.textDocument_declaration, params, opts) end --- Jumps to the definition of the symbol under the cursor. ---- @param options? vim.lsp.LocationOpts -function M.definition(options) +--- @param opts? vim.lsp.LocationOpts +function M.definition(opts) local params = util.make_position_params() - request_with_options(ms.textDocument_definition, params, options) + request_with_opts(ms.textDocument_definition, params, opts) end --- Jumps to the definition of the type of the symbol under the cursor. ---- @param options? vim.lsp.LocationOpts -function M.type_definition(options) +--- @param opts? vim.lsp.LocationOpts +function M.type_definition(opts) local params = util.make_position_params() - request_with_options(ms.textDocument_typeDefinition, params, options) + request_with_opts(ms.textDocument_typeDefinition, params, opts) end --- Lists all the implementations for the symbol under the cursor in the --- quickfix window. ---- @param options? vim.lsp.LocationOpts -function M.implementation(options) +--- @param opts? vim.lsp.LocationOpts +function M.implementation(opts) local params = util.make_position_params() - request_with_options(ms.textDocument_implementation, params, options) + request_with_opts(ms.textDocument_implementation, params, opts) end --- Displays signature information about the symbol under the cursor in a @@ -213,25 +212,25 @@ end --- Formats a buffer using the attached (and optionally filtered) language --- server clients. --- ---- @param options? vim.lsp.buf.format.Opts -function M.format(options) - options = options or {} - local bufnr = options.bufnr or api.nvim_get_current_buf() +--- @param opts? vim.lsp.buf.format.Opts +function M.format(opts) + opts = opts or {} + local bufnr = opts.bufnr or api.nvim_get_current_buf() local mode = api.nvim_get_mode().mode - local range = options.range + local range = opts.range if not range and mode == 'v' or mode == 'V' then range = range_from_selection(bufnr, mode) end local method = range and ms.textDocument_rangeFormatting or ms.textDocument_formatting local clients = vim.lsp.get_clients({ - id = options.id, + id = opts.id, bufnr = bufnr, - name = options.name, + name = opts.name, method = method, }) - if options.filter then - clients = vim.tbl_filter(options.filter, clients) + if opts.filter then + clients = vim.tbl_filter(opts.filter, clients) end if #clients == 0 then @@ -250,12 +249,12 @@ function M.format(options) return params end - if options.async then + if opts.async then local function do_format(idx, client) if not client then return end - local params = set_range(client, util.make_formatting_params(options.formatting_options)) + 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] handler(...) @@ -264,9 +263,9 @@ function M.format(options) end do_format(next(clients)) else - local timeout_ms = options.timeout_ms or 1000 + local timeout_ms = opts.timeout_ms or 1000 for _, client in pairs(clients) do - local params = set_range(client, util.make_formatting_params(options.formatting_options)) + local params = set_range(client, util.make_formatting_params(opts.formatting_options)) local result, err = client.request_sync(method, params, timeout_ms, bufnr) if result and result.result then util.apply_text_edits(result.result, bufnr, client.offset_encoding) @@ -295,18 +294,18 @@ end --- ---@param new_name string|nil If not provided, the user will be prompted for a new --- name using |vim.ui.input()|. ----@param options? vim.lsp.buf.rename.Opts Additional options: -function M.rename(new_name, options) - options = options or {} - local bufnr = options.bufnr or api.nvim_get_current_buf() +---@param opts? vim.lsp.buf.rename.Opts Additional options: +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({ bufnr = bufnr, - name = options.name, + name = opts.name, -- Clients must at least support rename, prepareRename is optional method = ms.textDocument_rename, }) - if options.filter then - clients = vim.tbl_filter(options.filter, clients) + if opts.filter then + clients = vim.tbl_filter(opts.filter, clients) end if #clients == 0 then @@ -415,21 +414,21 @@ end --- ---@param context (table|nil) Context for the request ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references ----@param options? vim.lsp.ListOpts -function M.references(context, options) +---@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_options(ms.textDocument_references, params, options) + request_with_opts(ms.textDocument_references, params, opts) end --- Lists all symbols in the current buffer in the quickfix window. ---- @param options? vim.lsp.ListOpts -function M.document_symbol(options) +--- @param opts? vim.lsp.ListOpts +function M.document_symbol(opts) local params = { textDocument = util.make_text_document_params() } - request_with_options(ms.textDocument_documentSymbol, params, options) + request_with_opts(ms.textDocument_documentSymbol, params, opts) end --- @param call_hierarchy_items lsp.CallHierarchyItem[]? @@ -461,7 +460,14 @@ local function call_hierarchy(method) vim.notify(err.message, vim.log.levels.WARN) return end + if not result 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) @@ -488,6 +494,80 @@ function M.outgoing_calls() call_hierarchy(ms.callHierarchy_outgoingCalls) end +--- Lists all the subtypes or supertypes of the symbol under the +--- cursor in the |quickfix| window. If the symbol can resolve to +--- multiple items, the user can pick one using |vim.ui.select()|. +---@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) +end + --- List workspace folders. --- function M.list_workspace_folders() @@ -514,28 +594,9 @@ function M.add_workspace_folder(workspace_folder) print(workspace_folder, ' is not a valid directory') return end - local new_workspace = { - uri = vim.uri_from_fname(workspace_folder), - name = workspace_folder, - } - local params = { event = { added = { new_workspace }, removed = {} } } - local bufnr = vim.api.nvim_get_current_buf() + local bufnr = api.nvim_get_current_buf() for _, client in pairs(vim.lsp.get_clients({ bufnr = bufnr })) do - local found = false - for _, folder in pairs(client.workspace_folders or {}) do - if folder.name == workspace_folder then - found = true - print(workspace_folder, 'is already part of this workspace') - break - end - end - if not found then - client.notify(ms.workspace_didChangeWorkspaceFolders, params) - if not client.workspace_folders then - client.workspace_folders = {} - end - table.insert(client.workspace_folders, new_workspace) - end + client:_add_workspace_folder(workspace_folder) end end @@ -547,23 +608,12 @@ function M.remove_workspace_folder(workspace_folder) workspace_folder = workspace_folder or npcall(vim.fn.input, 'Workspace Folder: ', vim.fn.expand('%:p:h')) api.nvim_command('redraw') - if not (workspace_folder and #workspace_folder > 0) then + if not workspace_folder or #workspace_folder == 0 then return end - local workspace = { - uri = vim.uri_from_fname(workspace_folder), - name = workspace_folder, - } - local params = { event = { added = {}, removed = { workspace } } } - local bufnr = vim.api.nvim_get_current_buf() + local bufnr = api.nvim_get_current_buf() for _, client in pairs(vim.lsp.get_clients({ bufnr = bufnr })) do - for idx, folder in pairs(client.workspace_folders) do - if folder.name == workspace_folder then - client.notify(ms.workspace_didChangeWorkspaceFolders, params) - client.workspace_folders[idx] = nil - return - end - end + client:_remove_workspace_folder(workspace_folder) end print(workspace_folder, 'is not currently part of the workspace') end @@ -575,14 +625,14 @@ end --- string means no filtering is done. --- --- @param query string? optional ---- @param options? vim.lsp.ListOpts -function M.workspace_symbol(query, options) +--- @param opts? vim.lsp.ListOpts +function M.workspace_symbol(query, opts) query = query or npcall(vim.fn.input, 'Query: ') if query == nil then return end local params = { query = query } - request_with_options(ms.workspace_symbol, params, options) + request_with_opts(ms.workspace_symbol, params, opts) end --- Send request to the server to resolve document highlights for the current @@ -774,19 +824,19 @@ end --- Selects a code action available at the current --- cursor position. --- ----@param options? vim.lsp.buf.code_action.Opts +---@param opts? vim.lsp.buf.code_action.Opts ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction ---@see vim.lsp.protocol.CodeActionTriggerKind -function M.code_action(options) - validate({ options = { options, 't', true } }) - options = options or {} +function M.code_action(opts) + validate({ options = { opts, 't', true } }) + opts = opts or {} -- Detect old API call code_action(context) which should now be -- code_action({ context = context} ) --- @diagnostic disable-next-line:undefined-field - if options.diagnostics or options.only then - options = { options = options } + if opts.diagnostics or opts.only then + opts = { options = opts } end - local context = options.context or {} + local context = opts.context or {} if not context.triggerKind then context.triggerKind = vim.lsp.protocol.CodeActionTriggerKind.Invoked end @@ -816,17 +866,17 @@ function M.code_action(options) results[ctx.client_id] = { error = err, result = result, ctx = ctx } remaining = remaining - 1 if remaining == 0 then - on_code_action_results(results, options) + on_code_action_results(results, opts) end end for _, client in ipairs(clients) do ---@type lsp.CodeActionParams local params - if options.range then - assert(type(options.range) == 'table', 'code_action range must be a table') - local start = assert(options.range.start, 'range must have a `start` property') - local end_ = assert(options.range['end'], 'range must have a `end` property') + if opts.range then + assert(type(opts.range) == 'table', 'code_action range must be a table') + local start = assert(opts.range.start, 'range must have a `start` property') + local end_ = assert(opts.range['end'], 'range must have a `end` property') params = util.make_given_range_params(start, end_, bufnr, client.offset_encoding) elseif mode == 'v' or mode == 'V' then local range = range_from_selection(bufnr, mode) diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua index ff0db166d5..4beb7fefda 100644 --- a/runtime/lua/vim/lsp/client.lua +++ b/runtime/lua/vim/lsp/client.lua @@ -15,7 +15,7 @@ local validate = vim.validate --- @inlinedoc --- --- Allow using incremental sync for buffer edits ---- (defailt: `true`) +--- (default: `true`) --- @field allow_incremental_sync? boolean --- --- Debounce `didChange` notifications to the server by the given number in milliseconds. @@ -37,7 +37,7 @@ local validate = vim.validate --- `is_closing` and `terminate`. --- See |vim.lsp.rpc.request()|, |vim.lsp.rpc.notify()|. --- For TCP there is a builtin RPC client factory: |vim.lsp.rpc.connect()| ---- @field cmd string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient? +--- @field cmd string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient --- --- Directory to launch the `cmd` process. Not related to `root_dir`. --- (default: cwd) @@ -185,6 +185,10 @@ local validate = vim.validate --- @field root_dir string --- --- @field attached_buffers table<integer,true> +--- +--- Buffers that should be attached to upon initialize() +--- @field package _buffers_to_attach table<integer,true> +--- --- @field private _log_prefix string --- --- Track this so that we can escalate automatically if we've already tried a @@ -225,7 +229,7 @@ local validate = vim.validate --- If {status} is `true`, the function returns {request_id} as the second --- result. You can use this with `client.cancel_request(request_id)` to cancel --- the request. ---- @field request fun(method: string, params: table?, handler: lsp.Handler?, bufnr: integer): boolean, integer? +--- @field request fun(method: string, params: table?, handler: lsp.Handler?, bufnr: integer?): boolean, integer? --- --- Sends a request to the server and synchronously waits for the response. --- This is a wrapper around {client.request} @@ -416,7 +420,7 @@ local function get_workspace_folders(workspace_folders, root_dir) return { { uri = vim.uri_from_fname(root_dir), - name = string.format('%s', root_dir), + name = root_dir, }, } end @@ -502,25 +506,17 @@ function Client.create(config) } -- Start the RPC client. - local rpc --- @type vim.lsp.rpc.PublicClient? local config_cmd = config.cmd if type(config_cmd) == 'function' then - rpc = config_cmd(dispatchers) + self.rpc = config_cmd(dispatchers) else - rpc = lsp.rpc.start(config_cmd, dispatchers, { + self.rpc = lsp.rpc.start(config_cmd, dispatchers, { cwd = config.cmd_cwd, env = config.cmd_env, detached = config.detached, }) end - -- Return nil if the rpc client fails to start - if not rpc then - return - end - - self.rpc = rpc - setmetatable(self, Client) return self @@ -575,6 +571,7 @@ function Client:initialize() initializationOptions = config.init_options, capabilities = self.capabilities, trace = self._trace, + workDoneToken = '1', } self:_run_callbacks( @@ -608,8 +605,19 @@ function Client:initialize() self:_notify(ms.workspace_didChangeConfiguration, { settings = self.settings }) end + -- If server is being restarted, make sure to re-attach to any previously attached buffers. + -- Save which buffers before on_init in case new buffers are attached. + local reattach_bufs = vim.deepcopy(self.attached_buffers) + self:_run_callbacks(self._on_init_cbs, lsp.client_errors.ON_INIT_CALLBACK_ERROR, self, result) + for buf in pairs(reattach_bufs) do + -- The buffer may have been detached in the on_init callback. + if self.attached_buffers[buf] then + self:_on_attach(buf) + end + end + log.info( self._log_prefix, 'server_capabilities', @@ -647,10 +655,10 @@ end --- checks for capabilities and handler availability. --- --- @param method string LSP method name. ---- @param params table|nil LSP request params. ---- @param handler lsp.Handler|nil Response |lsp-handler| for this method. ---- @param bufnr integer Buffer handle (0 for current). ---- @return boolean status, integer|nil request_id {status} is a bool indicating +--- @param params? table LSP request params. +--- @param handler? lsp.Handler Response |lsp-handler| for this method. +--- @param bufnr? integer Buffer handle (0 for current). +--- @return boolean status, integer? request_id {status} is a bool indicating --- whether the request was successful. If it is `false`, then it will --- always be `false` (the client has shutdown). If it was --- successful, then it will return {request_id} as the @@ -693,7 +701,7 @@ function Client:_request(method, params, handler, bufnr) local request = { type = 'pending', bufnr = bufnr, method = method } self.requests[request_id] = request api.nvim_exec_autocmds('LspRequest', { - buffer = bufnr, + buffer = api.nvim_buf_is_valid(bufnr) and bufnr or nil, modeline = false, data = { client_id = self.id, request_id = request_id, request = request }, }) @@ -709,7 +717,7 @@ local wait_result_reason = { [-1] = 'timeout', [-2] = 'interrupted', [-3] = 'err --- --- @param ... string List to write to the buffer local function err_message(...) - local message = table.concat(vim.tbl_flatten({ ... })) + local message = table.concat(vim.iter({ ... }):flatten():totable()) if vim.in_fast_event() then vim.schedule(function() api.nvim_err_writeln(message) @@ -761,7 +769,7 @@ function Client:_request_sync(method, params, timeout_ms, bufnr) return request_result end ---- @private +--- @package --- Sends a notification to an LSP server. --- --- @param method string LSP method name. @@ -804,7 +812,7 @@ function Client:_cancel_request(id) if request and request.type == 'pending' then request.type = 'cancel' api.nvim_exec_autocmds('LspRequest', { - buffer = request.bufnr, + buffer = api.nvim_buf_is_valid(request.bufnr) and request.bufnr or nil, modeline = false, data = { client_id = self.id, request_id = id, request = request }, }) @@ -900,7 +908,7 @@ end --- @param bufnr integer Number of the buffer, or 0 for current function Client:_text_document_did_open_handler(bufnr) changetracking.init(self, bufnr) - if not vim.tbl_get(self.server_capabilities, 'textDocumentSync', 'openClose') then + if not self.supports_method(ms.textDocument_didOpen) then return end if not api.nvim_buf_is_loaded(bufnr) then @@ -1053,4 +1061,45 @@ function Client:_on_exit(code, signal) ) end +--- @package +--- Add a directory to the workspace folders. +--- @param dir string? +function Client:_add_workspace_folder(dir) + for _, folder in pairs(self.workspace_folders or {}) do + if folder.name == dir then + print(dir, 'is already part of this workspace') + return + end + end + + local wf = assert(get_workspace_folders(nil, dir)) + + self:_notify(ms.workspace_didChangeWorkspaceFolders, { + event = { added = wf, removed = {} }, + }) + + if not self.workspace_folders then + self.workspace_folders = {} + end + vim.list_extend(self.workspace_folders, wf) +end + +--- @package +--- Remove a directory to the workspace folders. +--- @param dir string? +function Client:_remove_workspace_folder(dir) + local wf = assert(get_workspace_folders(nil, dir)) + + self:_notify(ms.workspace_didChangeWorkspaceFolders, { + event = { added = {}, removed = wf }, + }) + + for idx, folder in pairs(self.workspace_folders) do + if folder.name == dir then + table.remove(self.workspace_folders, idx) + break + end + end +end + return Client diff --git a/runtime/lua/vim/lsp/codelens.lua b/runtime/lua/vim/lsp/codelens.lua index 48c096c0c1..c85bb6aa32 100644 --- a/runtime/lua/vim/lsp/codelens.lua +++ b/runtime/lua/vim/lsp/codelens.lua @@ -79,7 +79,7 @@ function M.run() local lenses_by_client = lens_cache_by_buf[bufnr] or {} for client, lenses in pairs(lenses_by_client) do for _, lens in pairs(lenses) do - if lens.range.start.line == (line - 1) then + if lens.range.start.line == (line - 1) and lens.command and lens.command.command ~= '' then table.insert(options, { client = client, lens = lens }) end end @@ -164,7 +164,7 @@ function M.display(lenses, bufnr, client_id) return a.range.start.character < b.range.start.character end) for j, lens in ipairs(line_lenses) do - local text = lens.command and lens.command.title or 'Unresolved lens ...' + local text = (lens.command and lens.command.title or 'Unresolved lens ...'):gsub('%s+', ' ') table.insert(chunks, { text, 'LspCodeLens' }) if j < num_line_lenses then table.insert(chunks, { ' | ', 'LspCodeLensSeparator' }) @@ -231,7 +231,7 @@ local function resolve_lenses(lenses, bufnr, client_id, callback) countdown() else assert(client) - client.request('codeLens/resolve', lens, function(_, result) + client.request(ms.codeLens_resolve, lens, function(_, result) if api.nvim_buf_is_loaded(bufnr) and result and result.command then lens.command = result.command -- Eager display to have some sort of incremental feedback @@ -299,14 +299,18 @@ function M.refresh(opts) local bufnr = opts.bufnr and resolve_bufnr(opts.bufnr) local buffers = bufnr and { bufnr } or vim.tbl_filter(api.nvim_buf_is_loaded, api.nvim_list_bufs()) - local params = { - textDocument = util.make_text_document_params(), - } for _, buf in ipairs(buffers) do if not active_refreshes[buf] then + local params = { + textDocument = util.make_text_document_params(buf), + } active_refreshes[buf] = true - vim.lsp.buf_request(buf, ms.textDocument_codeLens, params, M.on_codelens) + + local request_ids = vim.lsp.buf_request(buf, ms.textDocument_codeLens, params, M.on_codelens) + if vim.tbl_isempty(request_ids) then + active_refreshes[buf] = nil + end end end end diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index daf4fec8d2..f9d394642c 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -3,6 +3,7 @@ local protocol = require('vim.lsp.protocol') local ms = protocol.Methods local util = require('vim.lsp.util') local api = vim.api +local completion = require('vim.lsp._completion') --- @type table<string,lsp.Handler> local M = {} @@ -12,7 +13,7 @@ local M = {} --- Writes to error buffer. ---@param ... string Will be concatenated before being written local function err_message(...) - vim.notify(table.concat(vim.tbl_flatten({ ... })), vim.log.levels.ERROR) + vim.notify(table.concat(vim.iter({ ... }):flatten():totable()), vim.log.levels.ERROR) api.nvim_command('redraw') end @@ -22,16 +23,16 @@ M[ms.workspace_executeCommand] = function(_, _, _, _) end --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#progress ----@param result lsp.ProgressParams +---@param params lsp.ProgressParams ---@param ctx lsp.HandlerContext -M[ms.dollar_progress] = function(_, result, ctx) +M[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') return vim.NIL end local kind = nil - local value = result.value + local value = params.value if type(value) == 'table' then kind = value.kind @@ -39,21 +40,21 @@ M[ms.dollar_progress] = function(_, result, ctx) -- So that consumers always have it available, even if they consume a -- subset of the full sequence if kind == 'begin' then - client.progress.pending[result.token] = value.title + client.progress.pending[params.token] = value.title else - value.title = client.progress.pending[result.token] + value.title = client.progress.pending[params.token] if kind == 'end' then - client.progress.pending[result.token] = nil + client.progress.pending[params.token] = nil end end end - client.progress:push(result) + client.progress:push(params) api.nvim_exec_autocmds('LspProgress', { pattern = kind, modeline = false, - data = { client_id = ctx.client_id, result = result }, + data = { client_id = ctx.client_id, params = params }, }) end @@ -253,26 +254,24 @@ M[ms.textDocument_references] = function(_, result, ctx, config) 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, {}, ' ', { title = title, items = items, context = ctx }) - api.nvim_command('lopen') + vim.fn.setloclist(0, {}, ' ', list) + vim.cmd.lopen() elseif config.on_list then - assert(type(config.on_list) == 'function', 'on_list is not a function') - config.on_list({ title = title, items = items, context = ctx }) + assert(vim.is_callable(config.on_list), 'on_list is not a function') + config.on_list(list) else - vim.fn.setqflist({}, ' ', { title = title, items = items, context = ctx }) - api.nvim_command('botright copen') + 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 a table ---- with the following keys: ---- ---- loclist: (boolean) use the location list (default is to use the quickfix list) +--- The returned function has an optional {config} parameter that accepts |vim.lsp.ListOpts| --- ----@param map_result function `((resp, bufnr) -> list)` to convert the response +---@param map_result fun(resp, bufnr: integer): table to convert the response ---@param entity string name of the resource used in a `not found` error message ---@param title_fn fun(ctx: lsp.HandlerContext): string Function to call to generate list title ---@return lsp.Handler @@ -286,15 +285,16 @@ local function response_to_list(map_result, entity, title_fn) local title = title_fn(ctx) local items = map_result(result, ctx.bufnr) + local list = { title = title, items = items, context = ctx } if config.loclist then - vim.fn.setloclist(0, {}, ' ', { title = title, items = items, context = ctx }) - api.nvim_command('lopen') + vim.fn.setloclist(0, {}, ' ', list) + vim.cmd.lopen() elseif config.on_list then - assert(type(config.on_list) == 'function', 'on_list is not a function') - config.on_list({ title = title, items = items, context = ctx }) + assert(vim.is_callable(config.on_list), 'on_list is not a function') + config.on_list(list) else - vim.fn.setqflist({}, ' ', { title = title, items = items, context = ctx }) - api.nvim_command('botright copen') + vim.fn.setqflist({}, ' ', list) + vim.cmd('botright copen') end end end @@ -354,7 +354,7 @@ M[ms.textDocument_completion] = function(_, result, _, _) local textMatch = vim.fn.match(line_to_cursor, '\\k*$') local prefix = line_to_cursor:sub(textMatch + 1) - local matches = util.text_document_completion_list_to_complete_items(result, prefix) + local matches = completion._lsp_to_complete_items(result, prefix) vim.fn.complete(textMatch + 1, matches) end @@ -428,7 +428,7 @@ local function location_handler(_, result, ctx, config) -- textDocument/definition can return Location or Location[] -- https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_definition - if not vim.tbl_islist(result) then + if not vim.islist(result) then result = { result } end @@ -436,7 +436,7 @@ local function location_handler(_, result, ctx, config) local items = util.locations_to_items(result, client.offset_encoding) if config.on_list then - assert(type(config.on_list) == 'function', 'on_list is not a function') + assert(vim.is_callable(config.on_list), 'on_list is not a function') config.on_list({ title = title, items = items }) return end @@ -444,8 +444,13 @@ local function location_handler(_, result, ctx, config) util.jump_to_location(result[1], client.offset_encoding, config.reuse_win) return end - vim.fn.setqflist({}, ' ', { title = title, items = items }) - api.nvim_command('botright copen') + 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 @@ -555,7 +560,7 @@ local function make_call_hierarchy_handler(direction) end end vim.fn.setqflist({}, ' ', { title = 'LSP call hierarchy', items = items }) - api.nvim_command('botright copen') + vim.cmd('botright copen') end end @@ -565,6 +570,45 @@ M[ms.callHierarchy_incomingCalls] = make_call_hierarchy_handler('from') --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#callHierarchy_outgoingCalls M[ms.callHierarchy_outgoingCalls] = make_call_hierarchy_handler('to') +--- Displays type hierarchy in the quickfix window. +local function make_type_hierarchy_handler() + --- @param result lsp.TypeHierarchyItem[] + return function(_, result, ctx, _) + if not result then + return + end + local function format_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 client = assert(vim.lsp.get_client_by_id(ctx.client_id)) + local items = {} + for _, type_hierarchy_item in pairs(result) do + local col = util._get_line_byte_from_position( + ctx.bufnr, + type_hierarchy_item.range.start, + client.offset_encoding + ) + table.insert(items, { + filename = assert(vim.uri_to_fname(type_hierarchy_item.uri)), + text = format_item(type_hierarchy_item), + lnum = type_hierarchy_item.range.start.line + 1, + col = col + 1, + }) + end + vim.fn.setqflist({}, ' ', { title = 'LSP type hierarchy', items = items }) + vim.cmd('botright copen') + end +end + +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#typeHierarchy_incomingCalls +M[ms.typeHierarchy_subtypes] = make_type_hierarchy_handler() + +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#typeHierarchy_outgoingCalls +M[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, _) @@ -615,7 +659,8 @@ M[ms.window_showDocument] = function(_, result, ctx, _) if result.external then -- TODO(lvimuser): ask the user for confirmation - local ret, err = vim.ui.open(uri) + local cmd, err = vim.ui.open(uri) + local ret = cmd and cmd:wait(2000) or nil if ret == nil or ret.code ~= 0 then return { diff --git a/runtime/lua/vim/lsp/health.lua b/runtime/lua/vim/lsp/health.lua index 797a1097f9..a79ae76eb9 100644 --- a/runtime/lua/vim/lsp/health.lua +++ b/runtime/lua/vim/lsp/health.lua @@ -51,6 +51,29 @@ end local function check_watcher() vim.health.start('vim.lsp: File watcher') + + -- Only run the check if file watching has been enabled by a client. + local clients = vim.lsp.get_clients() + if + --- @param client vim.lsp.Client + vim.iter(clients):all(function(client) + local has_capability = vim.tbl_get( + client.capabilities, + 'workspace', + 'didChangeWatchedFiles', + 'dynamicRegistration' + ) + local has_dynamic_capability = + client.dynamic_capabilities:get(vim.lsp.protocol.Methods.workspace_didChangeWatchedFiles) + return has_capability == nil + or has_dynamic_capability == nil + or client.workspace_folders == nil + end) + then + report_info('file watching "(workspace/didChangeWatchedFiles)" disabled on all clients') + return + end + local watchfunc = vim.lsp._watchfiles._watchfunc assert(watchfunc) local watchfunc_name --- @type string diff --git a/runtime/lua/vim/lsp/inlay_hint.lua b/runtime/lua/vim/lsp/inlay_hint.lua index ec676ea97f..f98496456b 100644 --- a/runtime/lua/vim/lsp/inlay_hint.lua +++ b/runtime/lua/vim/lsp/inlay_hint.lua @@ -4,13 +4,30 @@ local ms = require('vim.lsp.protocol').Methods local api = vim.api local M = {} ----@class (private) vim.lsp.inlay_hint.bufstate +---@class (private) vim.lsp.inlay_hint.globalstate Global state for inlay hints +---@field enabled boolean Whether inlay hints are enabled for this scope +---@type vim.lsp.inlay_hint.globalstate +local globalstate = { + enabled = false, +} + +---@class (private) vim.lsp.inlay_hint.bufstate: vim.lsp.inlay_hint.globalstate Buffer local state for inlay hints ---@field version? integer ---@field client_hints? table<integer, table<integer, lsp.InlayHint[]>> client_id -> (lnum -> hints) ---@field applied table<integer, integer> Last version of hints applied to this line ----@field enabled boolean Whether inlay hints are enabled for this buffer ---@type table<integer, vim.lsp.inlay_hint.bufstate> -local bufstates = {} +local bufstates = vim.defaulttable(function(_) + return setmetatable({ applied = {} }, { + __index = globalstate, + __newindex = function(state, key, value) + if globalstate[key] == value then + rawset(state, key, nil) + else + rawset(state, key, value) + end + end, + }) +end) local namespace = api.nvim_create_namespace('vim_lsp_inlayhint') local augroup = api.nvim_create_augroup('vim_lsp_inlayhint', {}) @@ -34,22 +51,22 @@ function M.on_inlayhint(err, result, ctx, _) return end local bufstate = bufstates[bufnr] - if not bufstate or not bufstate.enabled then + if not bufstate.enabled then return end if not (bufstate.client_hints and bufstate.version) then bufstate.client_hints = vim.defaulttable() bufstate.version = ctx.version end - local hints_by_client = bufstate.client_hints + local client_hints = bufstate.client_hints local client = assert(vim.lsp.get_client_by_id(client_id)) - local new_hints_by_lnum = vim.defaulttable() + local new_lnum_hints = vim.defaulttable() local num_unprocessed = #result if num_unprocessed == 0 then - hints_by_client[client_id] = {} + client_hints[client_id] = {} bufstate.version = ctx.version - api.nvim__buf_redraw_range(bufnr, 0, -1) + api.nvim__redraw({ buf = bufnr, valid = true }) return end @@ -73,15 +90,15 @@ function M.on_inlayhint(err, result, ctx, _) for _, hint in ipairs(result) do local lnum = hint.position.line hint.position.character = pos_to_byte(hint.position) - table.insert(new_hints_by_lnum[lnum], hint) + table.insert(new_lnum_hints[lnum], hint) end - hints_by_client[client_id] = new_hints_by_lnum + client_hints[client_id] = new_lnum_hints bufstate.version = ctx.version - api.nvim__buf_redraw_range(bufnr, 0, -1) + api.nvim__redraw({ buf = bufnr, valid = true }) end ---- |lsp-handler| for the method `textDocument/inlayHint/refresh` +--- |lsp-handler| for the method `workspace/inlayHint/refresh` ---@param ctx lsp.HandlerContext ---@private function M.on_refresh(err, _, ctx, _) @@ -91,11 +108,7 @@ function M.on_refresh(err, _, ctx, _) for _, bufnr in ipairs(vim.lsp.get_buffers_by_client_id(ctx.client_id)) do for _, winid in ipairs(api.nvim_list_wins()) do if api.nvim_win_get_buf(winid) == bufnr then - local bufstate = bufstates[bufnr] - if bufstate then - util._refresh(ms.textDocument_inlayHint, { bufnr = bufnr }) - break - end + util._refresh(ms.textDocument_inlayHint, { bufnr = bufnr }) end end end @@ -123,7 +136,8 @@ end --- local hint = vim.lsp.inlay_hint.get({ bufnr = 0 })[1] -- 0 for current buffer --- --- local client = vim.lsp.get_client_by_id(hint.client_id) ---- resolved_hint = client.request_sync('inlayHint/resolve', hint.inlay_hint, 100, 0).result +--- local resp = client.request_sync('inlayHint/resolve', hint.inlay_hint, 100, 0) +--- local resolved_hint = assert(resp and resp.result, resp.err) --- vim.lsp.util.apply_text_edits(resolved_hint.textEdits, 0, client.encoding) --- --- location = resolved_hint.label[1].location @@ -154,7 +168,7 @@ function M.get(filter) end local bufstate = bufstates[bufnr] - if not (bufstate and bufstate.client_hints) then + if not bufstate.client_hints then return {} end @@ -175,19 +189,19 @@ function M.get(filter) end --- @type vim.lsp.inlay_hint.get.ret[] - local hints = {} + local result = {} for _, client in pairs(clients) do - local hints_by_lnum = bufstate.client_hints[client.id] - if hints_by_lnum then + local lnum_hints = bufstate.client_hints[client.id] + if lnum_hints then for lnum = range.start.line, range['end'].line do - local line_hints = hints_by_lnum[lnum] or {} - for _, hint in pairs(line_hints) do + local hints = lnum_hints[lnum] or {} + for _, hint in pairs(hints) do local line, char = hint.position.line, hint.position.character if (line > range.start.line or char >= range.start.character) and (line < range['end'].line or char <= range['end'].character) then - table.insert(hints, { + table.insert(result, { bufnr = bufnr, client_id = client.id, inlay_hint = hint, @@ -197,18 +211,15 @@ function M.get(filter) end end end - return hints + return result end --- Clear inlay hints ---@param bufnr (integer) Buffer handle, or 0 for current local function clear(bufnr) - if bufnr == nil or bufnr == 0 then + if bufnr == 0 then bufnr = api.nvim_get_current_buf() end - if not bufstates[bufnr] then - return - end local bufstate = bufstates[bufnr] local client_lens = (bufstate or {}).client_hints or {} local client_ids = vim.tbl_keys(client_lens) --- @type integer[] @@ -218,19 +229,18 @@ local function clear(bufnr) end end api.nvim_buf_clear_namespace(bufnr, namespace, 0, -1) - api.nvim__buf_redraw_range(bufnr, 0, -1) + api.nvim__redraw({ buf = bufnr, valid = true }) end --- Disable inlay hints for a buffer ----@param bufnr (integer|nil) Buffer handle, or 0 or nil for current +---@param bufnr (integer) Buffer handle, or 0 for current local function _disable(bufnr) - if bufnr == nil or bufnr == 0 then + if bufnr == 0 then bufnr = api.nvim_get_current_buf() end clear(bufnr) - if bufstates[bufnr] then - bufstates[bufnr] = { enabled = false, applied = {} } - end + bufstates[bufnr] = nil + bufstates[bufnr].enabled = false end --- Refresh inlay hints, only if we have attached clients that support it @@ -244,30 +254,38 @@ local function _refresh(bufnr, opts) end --- Enable inlay hints for a buffer ----@param bufnr (integer|nil) Buffer handle, or 0 or nil for current +---@param bufnr (integer) Buffer handle, or 0 for current local function _enable(bufnr) - if bufnr == nil or bufnr == 0 then + if bufnr == 0 then bufnr = api.nvim_get_current_buf() end - local bufstate = bufstates[bufnr] - if not bufstate then - bufstates[bufnr] = { applied = {}, enabled = true } - api.nvim_create_autocmd('LspNotify', { - buffer = bufnr, - callback = function(opts) - if - opts.data.method ~= ms.textDocument_didChange - and opts.data.method ~= ms.textDocument_didOpen - then - return - end - if bufstates[bufnr] and bufstates[bufnr].enabled then - _refresh(bufnr, { client_id = opts.data.client_id }) - end - end, - group = augroup, - }) - _refresh(bufnr) + bufstates[bufnr] = nil + bufstates[bufnr].enabled = true + _refresh(bufnr) +end + +api.nvim_create_autocmd('LspNotify', { + callback = function(args) + ---@type integer + local bufnr = args.buf + + if + args.data.method ~= ms.textDocument_didChange + and args.data.method ~= ms.textDocument_didOpen + then + return + end + if bufstates[bufnr].enabled then + _refresh(bufnr, { client_id = args.data.client_id }) + end + end, + group = augroup, +}) +api.nvim_create_autocmd('LspAttach', { + callback = function(args) + ---@type integer + local bufnr = args.buf + api.nvim_buf_attach(bufnr, false, { on_reload = function(_, cb_bufnr) clear(cb_bufnr) @@ -278,32 +296,30 @@ local function _enable(bufnr) end, on_detach = function(_, cb_bufnr) _disable(cb_bufnr) + bufstates[cb_bufnr] = nil end, }) - api.nvim_create_autocmd('LspDetach', { - buffer = bufnr, - callback = function(args) - local clients = vim.lsp.get_clients({ bufnr = bufnr, method = ms.textDocument_inlayHint }) - - if - not vim.iter(clients):any(function(c) - return c.id ~= args.data.client_id - end) - then - _disable(bufnr) - end - end, - group = augroup, - }) - else - bufstate.enabled = true - _refresh(bufnr) - end -end + end, + group = augroup, +}) +api.nvim_create_autocmd('LspDetach', { + callback = function(args) + ---@type integer + local bufnr = args.buf + local clients = vim.lsp.get_clients({ bufnr = bufnr, method = ms.textDocument_inlayHint }) + if not vim.iter(clients):any(function(c) + return c.id ~= args.data.client_id + end) then + _disable(bufnr) + end + end, + group = augroup, +}) api.nvim_set_decoration_provider(namespace, { on_win = function(_, _, bufnr, topline, botline) - local bufstate = bufstates[bufnr] + ---@type vim.lsp.inlay_hint.bufstate + local bufstate = rawget(bufstates, bufnr) if not bufstate then return end @@ -311,14 +327,18 @@ api.nvim_set_decoration_provider(namespace, { if bufstate.version ~= util.buf_versions[bufnr] then return end - local hints_by_client = assert(bufstate.client_hints) + + if not bufstate.client_hints then + return + end + local client_hints = assert(bufstate.client_hints) for lnum = topline, botline do if bufstate.applied[lnum] ~= bufstate.version then api.nvim_buf_clear_namespace(bufnr, namespace, lnum, lnum + 1) - for _, hints_by_lnum in pairs(hints_by_client) do - local line_hints = hints_by_lnum[lnum] or {} - for _, hint in pairs(line_hints) do + for _, lnum_hints in pairs(client_hints) do + local hints = lnum_hints[lnum] or {} + for _, hint in pairs(hints) do local text = '' local label = hint.label if type(label) == 'string' then @@ -349,34 +369,65 @@ api.nvim_set_decoration_provider(namespace, { end, }) ---- @param bufnr (integer|nil) Buffer handle, or 0 or nil for current +--- Query whether inlay hint is enabled in the {filter}ed scope +--- @param filter vim.lsp.inlay_hint.enable.Filter --- @return boolean --- @since 12 -function M.is_enabled(bufnr) +function M.is_enabled(filter) + vim.validate({ filter = { filter, 'table', true } }) + filter = filter or {} + local bufnr = filter.bufnr + vim.validate({ bufnr = { bufnr, 'number', true } }) - if bufnr == nil or bufnr == 0 then + if bufnr == nil then + return globalstate.enabled + elseif bufnr == 0 then bufnr = api.nvim_get_current_buf() end - return bufstates[bufnr] and bufstates[bufnr].enabled or false + return bufstates[bufnr].enabled end ---- Enables or disables inlay hints for a buffer. +--- Optional filters |kwargs|, or `nil` for all. +--- @class vim.lsp.inlay_hint.enable.Filter +--- @inlinedoc +--- Buffer number, or 0 for current buffer, or nil for all. +--- @field bufnr integer? + +--- Enables or disables inlay hints for the {filter}ed scope. --- --- To "toggle", pass the inverse of `is_enabled()`: --- --- ```lua ---- vim.lsp.inlay_hint.enable(0, not vim.lsp.inlay_hint.is_enabled()) +--- vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled()) --- ``` --- ---- @param bufnr (integer|nil) Buffer handle, or 0 or nil for current --- @param enable (boolean|nil) true/nil to enable, false to disable +--- @param filter vim.lsp.inlay_hint.enable.Filter? --- @since 12 -function M.enable(bufnr, enable) - vim.validate({ enable = { enable, 'boolean', true }, bufnr = { bufnr, 'number', true } }) - if enable == false then - _disable(bufnr) +function M.enable(enable, filter) + vim.validate({ enable = { enable, 'boolean', true }, filter = { filter, 'table', true } }) + enable = enable == nil or enable + filter = filter or {} + + if filter.bufnr == nil then + globalstate.enabled = enable + for _, bufnr in ipairs(api.nvim_list_bufs()) do + if api.nvim_buf_is_loaded(bufnr) then + if enable == false then + _disable(bufnr) + else + _enable(bufnr) + end + else + bufstates[bufnr] = nil + end + end else - _enable(bufnr) + if enable == false then + _disable(filter.bufnr) + else + _enable(filter.bufnr) + end end end diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua index 599f02425e..419c2ff644 100644 --- a/runtime/lua/vim/lsp/protocol.lua +++ b/runtime/lua/vim/lsp/protocol.lua @@ -10,6 +10,8 @@ local function get_value_set(tbl) return value_set end +local sysname = vim.uv.os_uname().sysname + -- Protocol for the Microsoft Language Server Protocol (mslsp) local protocol = {} @@ -835,7 +837,10 @@ function protocol.make_client_capabilities() refreshSupport = true, }, didChangeWatchedFiles = { - dynamicRegistration = true, + -- TODO(lewis6991): do not advertise didChangeWatchedFiles on Linux + -- or BSD since all the current backends are too limited. + -- Ref: #27807, #28058, #23291, #26520 + dynamicRegistration = sysname == 'Darwin' or sysname == 'Windows_NT', relativePatternSupport = true, }, inlayHint = { diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index 984e4f040a..3c63a12da2 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -621,95 +621,67 @@ local function merge_dispatchers(dispatchers) return merged end ---- Create a LSP RPC client factory that connects via TCP to the given host and port. +--- Create a LSP RPC client factory that connects to either: +--- +--- - a named pipe (windows) +--- - a domain socket (unix) +--- - a host and port via TCP --- --- Return a function that can be passed to the `cmd` field for --- |vim.lsp.start_client()| or |vim.lsp.start()|. --- ----@param host string host to connect to ----@param port integer port to connect to +---@param host_or_path string host to connect to or path to a pipe/domain socket +---@param port integer? TCP port to connect to. If absent the first argument must be a pipe ---@return fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient -function M.connect(host, port) +function M.connect(host_or_path, port) return function(dispatchers) dispatchers = merge_dispatchers(dispatchers) - local tcp = assert(uv.new_tcp()) + local handle = ( + port == nil + and assert( + uv.new_pipe(false), + string.format('Pipe with name %s could not be opened.', host_or_path) + ) + or assert(uv.new_tcp(), 'Could not create new TCP socket') + ) local closing = false + -- Connect returns a PublicClient synchronously so the caller + -- can immediately send messages before the connection is established + -- -> Need to buffer them until that happens + local connected = false + -- size should be enough because the client can't really do anything until initialization is done + -- which required a response from the server - implying the connection got established + local msgbuf = vim.ringbuf(10) local transport = { write = function(msg) - tcp:write(msg) - end, - is_closing = function() - return closing - end, - terminate = function() - if not closing then - closing = true - tcp:shutdown() - tcp:close() - dispatchers.on_exit(0, 0) + if connected then + local _, err = handle:write(msg) + if err and not closing then + log.error('Error on handle:write: %q', err) + end + else + msgbuf:push(msg) end end, - } - local client = new_client(dispatchers, transport) - tcp:connect(host, port, function(err) - if err then - vim.schedule(function() - vim.notify( - string.format('Could not connect to %s:%s, reason: %s', host, port, vim.inspect(err)), - vim.log.levels.WARN - ) - end) - return - end - local handle_body = function(body) - client:handle_body(body) - end - tcp:read_start(M.create_read_loop(handle_body, transport.terminate, function(read_err) - client:on_error(M.client_errors.READ_ERROR, read_err) - end)) - end) - - return public_client(client) - end -end - ---- Create a LSP RPC client factory that connects via named pipes (Windows) ---- or unix domain sockets (Unix) to the given pipe_path (file path on ---- Unix and name on Windows). ---- ---- Return a function that can be passed to the `cmd` field for ---- |vim.lsp.start_client()| or |vim.lsp.start()|. ---- ----@param pipe_path string file path of the domain socket (Unix) or name of the named pipe (Windows) to connect to ----@return fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient -function M.domain_socket_connect(pipe_path) - return function(dispatchers) - dispatchers = merge_dispatchers(dispatchers) - local pipe = - assert(uv.new_pipe(false), string.format('pipe with name %s could not be opened.', pipe_path)) - local closing = false - local transport = { - write = vim.schedule_wrap(function(msg) - pipe:write(msg) - end), is_closing = function() return closing end, terminate = function() if not closing then closing = true - pipe:shutdown() - pipe:close() + handle:shutdown() + handle:close() dispatchers.on_exit(0, 0) end end, } local client = new_client(dispatchers, transport) - pipe:connect(pipe_path, function(err) + local function on_connect(err) if err then + local address = port == nil and host_or_path or (host_or_path .. ':' .. port) vim.schedule(function() vim.notify( - string.format('Could not connect to :%s, reason: %s', pipe_path, vim.inspect(err)), + string.format('Could not connect to %s, reason: %s', address, vim.inspect(err)), vim.log.levels.WARN ) end) @@ -718,10 +690,19 @@ function M.domain_socket_connect(pipe_path) local handle_body = function(body) client:handle_body(body) end - pipe:read_start(M.create_read_loop(handle_body, transport.terminate, function(read_err) + handle:read_start(M.create_read_loop(handle_body, transport.terminate, function(read_err) client:on_error(M.client_errors.READ_ERROR, read_err) end)) - end) + connected = true + for msg in msgbuf do + handle:write(msg) + end + end + if port == nil then + handle:connect(host_or_path, on_connect) + else + handle:connect(host_or_path, port, on_connect) + end return public_client(client) end @@ -741,7 +722,7 @@ end --- @param cmd string[] Command to start the LSP server. --- @param dispatchers? vim.lsp.rpc.Dispatchers --- @param extra_spawn_params? vim.lsp.rpc.ExtraSpawnParams ---- @return vim.lsp.rpc.PublicClient? : Client RPC object, with these methods: +--- @return vim.lsp.rpc.PublicClient : Client RPC object, with these methods: --- - `notify()` |vim.lsp.rpc.notify()| --- - `request()` |vim.lsp.rpc.request()| --- - `is_closing()` returns a boolean indicating if the RPC is closing. @@ -816,8 +797,7 @@ function M.start(cmd, dispatchers, extra_spawn_params) end local msg = string.format('Spawning language server with cmd: `%s` failed%s', vim.inspect(cmd), sfx) - vim.notify(msg, vim.log.levels.WARN) - return nil + error(msg) end sysobj = sysobj_or_err --[[@as vim.SystemObj]] diff --git a/runtime/lua/vim/lsp/semantic_tokens.lua b/runtime/lua/vim/lsp/semantic_tokens.lua index 20ac0a125f..ef2502b12e 100644 --- a/runtime/lua/vim/lsp/semantic_tokens.lua +++ b/runtime/lua/vim/lsp/semantic_tokens.lua @@ -394,7 +394,7 @@ function STHighlighter:process_response(response, client, version) current_result.namespace_cleared = false -- redraw all windows displaying buffer - api.nvim__buf_redraw_range(self.bufnr, 0, -1) + api.nvim__redraw({ buf = self.bufnr, valid = true }) end --- on_win handler for the decoration provider (see |nvim_set_decoration_provider|) @@ -570,9 +570,9 @@ local M = {} --- client.server_capabilities.semanticTokensProvider = nil --- ``` --- ----@param bufnr integer ----@param client_id integer ----@param opts? table Optional keyword arguments +---@param bufnr (integer) Buffer number, or `0` for current buffer +---@param client_id (integer) The ID of the |vim.lsp.Client| +---@param opts? (table) Optional keyword arguments --- - debounce (integer, default: 200): Debounce token requests --- to the server by the given number in milliseconds function M.start(bufnr, client_id, opts) @@ -581,6 +581,10 @@ function M.start(bufnr, client_id, opts) client_id = { client_id, 'n', false }, }) + if bufnr == 0 then + bufnr = api.nvim_get_current_buf() + end + opts = opts or {} assert( (not opts.debounce or type(opts.debounce) == 'number'), @@ -626,14 +630,18 @@ end --- of `start()`, so you should only need this function to manually disengage the semantic --- token engine without fully detaching the LSP client from the buffer. --- ----@param bufnr integer ----@param client_id integer +---@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 }, }) + if bufnr == 0 then + bufnr = api.nvim_get_current_buf() + end + local highlighter = STHighlighter.active[bufnr] if not highlighter then return @@ -741,12 +749,15 @@ end --- mark will be deleted by the semantic token engine when appropriate; for --- example, when the LSP sends updated tokens. This function is intended for --- use inside |LspTokenUpdate| callbacks. ----@param token (table) a semantic token, found as `args.data.token` in |LspTokenUpdate|. ----@param bufnr (integer) the buffer to highlight +---@param token (table) A semantic token, found as `args.data.token` in |LspTokenUpdate| +---@param bufnr (integer) The buffer to highlight, or `0` for current buffer ---@param client_id (integer) The ID of the |vim.lsp.Client| ---@param hl_group (string) Highlight group name ---@param opts? vim.lsp.semantic_tokens.highlight_token.Opts Optional parameters: function M.highlight_token(token, bufnr, client_id, hl_group, opts) + if bufnr == 0 then + bufnr = api.nvim_get_current_buf() + end local highlighter = STHighlighter.active[bufnr] if not highlighter then return diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index f8e5b6a90d..5a229a1169 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -1,5 +1,4 @@ local protocol = require('vim.lsp.protocol') -local snippet = require('vim.lsp._snippet_grammar') local validate = vim.validate local api = vim.api local list_extend = vim.list_extend @@ -343,68 +342,6 @@ local function get_line_byte_from_position(bufnr, position, offset_encoding) return col end ---- Process and return progress reports from lsp server ----@private ----@deprecated Use vim.lsp.status() or access client.progress directly -function M.get_progress_messages() - vim.deprecate('vim.lsp.util.get_progress_messages()', 'vim.lsp.status()', '0.11') - local new_messages = {} - local progress_remove = {} - - for _, client in ipairs(vim.lsp.get_clients()) do - local groups = {} - for progress in client.progress do - local value = progress.value - if type(value) == 'table' and value.kind then - local group = groups[progress.token] - if not group then - group = { - done = false, - progress = true, - title = 'empty title', - } - groups[progress.token] = group - end - group.title = value.title or group.title - group.cancellable = value.cancellable or group.cancellable - if value.kind == 'end' then - group.done = true - end - group.message = value.message or group.message - group.percentage = value.percentage or group.percentage - end - end - - for _, group in pairs(groups) do - table.insert(new_messages, group) - end - - local messages = client.messages - local data = messages - for token, ctx in pairs(data.progress) do - local new_report = { - name = data.name, - title = ctx.title or 'empty title', - message = ctx.message, - percentage = ctx.percentage, - done = ctx.done, - progress = true, - } - table.insert(new_messages, new_report) - - if ctx.done then - table.insert(progress_remove, { client = client, token = token }) - end - end - end - - for _, item in ipairs(progress_remove) do - item.client.messages.progress[item.token] = nil - end - - return new_messages -end - --- Applies a list of text edits to a buffer. ---@param text_edits table list of `TextEdit` objects ---@param bufnr integer Buffer id @@ -541,38 +478,6 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding) end end --- local valid_windows_path_characters = "[^<>:\"/\\|?*]" --- local valid_unix_path_characters = "[^/]" --- https://github.com/davidm/lua-glob-pattern --- https://stackoverflow.com/questions/1976007/what-characters-are-forbidden-in-windows-and-linux-directory-names --- function M.glob_to_regex(glob) --- end - ---- Can be used to extract the completion items from a ---- `textDocument/completion` request, which may return one of ---- `CompletionItem[]`, `CompletionList` or null. ---- ---- Note that this method doesn't apply `itemDefaults` to `CompletionList`s, and hence the returned ---- results might be incorrect. ---- ----@deprecated ----@param result table The result of a `textDocument/completion` request ----@return lsp.CompletionItem[] List of completion items ----@see https://microsoft.github.io/language-server-protocol/specification#textDocument_completion -function M.extract_completion_items(result) - vim.deprecate('vim.lsp.util.extract_completion_items()', nil, '0.11') - if type(result) == 'table' and result.items then - -- result is a `CompletionList` - return result.items - elseif result ~= nil then - -- result is `CompletionItem[]` - return result - else - -- result is `null` - return {} - end -end - --- Applies a `TextDocumentEdit`, which is a list of changes to a single --- document. --- @@ -615,38 +520,6 @@ function M.apply_text_document_edit(text_document_edit, index, offset_encoding) M.apply_text_edits(text_document_edit.edits, bufnr, offset_encoding) end ---- Parses snippets in a completion entry. ---- ----@deprecated ----@param input string unparsed snippet ----@return string parsed snippet -function M.parse_snippet(input) - vim.deprecate('vim.lsp.util.parse_snippet()', nil, '0.11') - local ok, parsed = pcall(function() - return snippet.parse(input) - end) - if not ok then - return input - end - - return tostring(parsed) -end - ---- Turns the result of a `textDocument/completion` request into vim-compatible ---- |complete-items|. ---- ----@deprecated ----@param result table The result of a `textDocument/completion` call, e.g. ---- from |vim.lsp.buf.completion()|, which may be one of `CompletionItem[]`, ---- `CompletionList` or `null` ----@param prefix (string) the prefix to filter the completion items ----@return table[] items ----@see complete-items -function M.text_document_completion_list_to_complete_items(result, prefix) - vim.deprecate('vim.lsp.util.text_document_completion_list_to_complete_items()', nil, '0.11') - return vim.lsp._completion._lsp_to_complete_items(result, prefix) -end - local function path_components(path) return vim.split(path, '/', { plain = true }) end @@ -690,7 +563,7 @@ end --- --- It deletes existing buffers that conflict with the renamed file name only when --- * `opts` requests overwriting; or ---- * the conflicting buffers are not loaded, so that deleting thme does not result in data loss. +--- * the conflicting buffers are not loaded, so that deleting them does not result in data loss. --- --- @param old_fname string --- @param new_fname string diff --git a/runtime/lua/provider/python/health.lua b/runtime/lua/vim/provider/health.lua index 333890b62b..63e0da448a 100644 --- a/runtime/lua/provider/python/health.lua +++ b/runtime/lua/vim/provider/health.lua @@ -1,14 +1,235 @@ local health = vim.health -local executable = health.executable -local iswin = vim.loop.os_uname().sysname == 'Windows_NT' +local iswin = vim.uv.os_uname().sysname == 'Windows_NT' local M = {} +local function clipboard() + health.start('Clipboard (optional)') + + if + os.getenv('TMUX') + and vim.fn.executable('tmux') == 1 + and vim.fn.executable('pbpaste') == 1 + and not health._cmd_ok('pbpaste') + then + local tmux_version = string.match(vim.fn.system('tmux -V'), '%d+%.%d+') + local advice = { + 'Install tmux 2.6+. https://superuser.com/q/231130', + 'or use tmux with reattach-to-user-namespace. https://superuser.com/a/413233', + } + health.error('pbcopy does not work with tmux version: ' .. tmux_version, advice) + end + + local clipboard_tool = vim.fn['provider#clipboard#Executable']() + if vim.g.clipboard ~= nil and clipboard_tool == '' then + local error_message = vim.fn['provider#clipboard#Error']() + health.error( + error_message, + "Use the example in :help g:clipboard as a template, or don't set g:clipboard at all." + ) + elseif clipboard_tool:find('^%s*$') then + health.warn( + 'No clipboard tool found. Clipboard registers (`"+` and `"*`) will not work.', + ':help clipboard' + ) + else + health.ok('Clipboard tool found: ' .. clipboard_tool) + end +end + +local function node() + health.start('Node.js provider (optional)') + + if health._provider_disabled('node') then + return + end + + if + vim.fn.executable('node') == 0 + or ( + vim.fn.executable('npm') == 0 + and vim.fn.executable('yarn') == 0 + and vim.fn.executable('pnpm') == 0 + ) + then + health.warn( + '`node` and `npm` (or `yarn`, `pnpm`) must be in $PATH.', + 'Install Node.js and verify that `node` and `npm` (or `yarn`, `pnpm`) commands work.' + ) + return + end + + -- local node_v = vim.fn.split(system({'node', '-v'}), "\n")[1] or '' + local ok, node_v = health._cmd_ok({ 'node', '-v' }) + health.info('Node.js: ' .. node_v) + if not ok or vim.version.lt(node_v, '6.0.0') then + health.warn('Nvim node.js host does not support Node ' .. node_v) + -- Skip further checks, they are nonsense if nodejs is too old. + return + end + if vim.fn['provider#node#can_inspect']() == 0 then + health.warn( + 'node.js on this system does not support --inspect-brk so $NVIM_NODE_HOST_DEBUG is ignored.' + ) + end + + local node_detect_table = vim.fn['provider#node#Detect']() + local host = node_detect_table[1] + if host:find('^%s*$') then + health.warn('Missing "neovim" npm (or yarn, pnpm) package.', { + 'Run in shell: npm install -g neovim', + 'Run in shell (if you use yarn): yarn global add neovim', + 'Run in shell (if you use pnpm): pnpm install -g neovim', + 'You may disable this provider (and warning) by adding `let g:loaded_node_provider = 0` to your init.vim', + }) + return + end + health.info('Nvim node.js host: ' .. host) + + local manager = 'npm' + if vim.fn.executable('yarn') == 1 then + manager = 'yarn' + elseif vim.fn.executable('pnpm') == 1 then + manager = 'pnpm' + end + + local latest_npm_cmd = ( + iswin and 'cmd /c ' .. manager .. ' info neovim --json' or manager .. ' info neovim --json' + ) + local latest_npm + ok, latest_npm = health._cmd_ok(vim.split(latest_npm_cmd, ' ')) + if not ok or latest_npm:find('^%s$') then + health.error( + 'Failed to run: ' .. latest_npm_cmd, + { "Make sure you're connected to the internet.", 'Are you behind a firewall or proxy?' } + ) + return + end + + local pcall_ok, pkg_data = pcall(vim.json.decode, latest_npm) + if not pcall_ok then + return 'error: ' .. latest_npm + end + local latest_npm_subtable = pkg_data['dist-tags'] or {} + latest_npm = latest_npm_subtable['latest'] or 'unable to parse' + + local current_npm_cmd = { 'node', host, '--version' } + local current_npm + ok, current_npm = health._cmd_ok(current_npm_cmd) + if not ok then + health.error( + 'Failed to run: ' .. table.concat(current_npm_cmd, ' '), + { 'Report this issue with the output of: ', table.concat(current_npm_cmd, ' ') } + ) + return + end + + if latest_npm ~= 'unable to parse' and vim.version.lt(current_npm, latest_npm) then + local message = 'Package "neovim" is out-of-date. Installed: ' + .. current_npm:gsub('%\n$', '') + .. ', latest: ' + .. latest_npm:gsub('%\n$', '') + + health.warn(message, { + 'Run in shell: npm install -g neovim', + 'Run in shell (if you use yarn): yarn global add neovim', + 'Run in shell (if you use pnpm): pnpm install -g neovim', + }) + else + health.ok('Latest "neovim" npm/yarn/pnpm package is installed: ' .. current_npm) + end +end + +local function perl() + health.start('Perl provider (optional)') + + if health._provider_disabled('perl') then + return + end + + local perl_exec, perl_warnings = vim.provider.perl.detect() + + if not perl_exec then + health.warn(assert(perl_warnings), { + 'See :help provider-perl for more information.', + 'You may disable this provider (and warning) by adding `let g:loaded_perl_provider = 0` to your init.vim', + }) + health.warn('No usable perl executable found') + return + end + + health.info('perl executable: ' .. perl_exec) + + -- we cannot use cpanm that is on the path, as it may not be for the perl + -- set with g:perl_host_prog + local ok = health._cmd_ok({ perl_exec, '-W', '-MApp::cpanminus', '-e', '' }) + if not ok then + return { perl_exec, '"App::cpanminus" module is not installed' } + end + + local latest_cpan_cmd = { + perl_exec, + '-MApp::cpanminus::fatscript', + '-e', + 'my $app = App::cpanminus::script->new; $app->parse_options ("--info", "-q", "Neovim::Ext"); exit $app->doit', + } + local latest_cpan + ok, latest_cpan = health._cmd_ok(latest_cpan_cmd) + if not ok or latest_cpan:find('^%s*$') then + health.error( + 'Failed to run: ' .. table.concat(latest_cpan_cmd, ' '), + { "Make sure you're connected to the internet.", 'Are you behind a firewall or proxy?' } + ) + return + elseif latest_cpan[1] == '!' then + local cpanm_errs = vim.split(latest_cpan, '!') + if cpanm_errs[1]:find("Can't write to ") then + local advice = {} + for i = 2, #cpanm_errs do + advice[#advice + 1] = cpanm_errs[i] + end + + health.warn(cpanm_errs[1], advice) + -- Last line is the package info + latest_cpan = cpanm_errs[#cpanm_errs] + else + health.error('Unknown warning from command: ' .. latest_cpan_cmd, cpanm_errs) + return + end + end + latest_cpan = vim.fn.matchstr(latest_cpan, [[\(\.\?\d\)\+]]) + if latest_cpan:find('^%s*$') then + health.error('Cannot parse version number from cpanm output: ' .. latest_cpan) + return + end + + local current_cpan_cmd = { perl_exec, '-W', '-MNeovim::Ext', '-e', 'print $Neovim::Ext::VERSION' } + local current_cpan + ok, current_cpan = health._cmd_ok(current_cpan_cmd) + if not ok then + health.error( + 'Failed to run: ' .. table.concat(current_cpan_cmd, ' '), + { 'Report this issue with the output of: ', table.concat(current_cpan_cmd, ' ') } + ) + return + end + + if vim.version.lt(current_cpan, latest_cpan) then + local message = 'Module "Neovim::Ext" is out-of-date. Installed: ' + .. current_cpan + .. ', latest: ' + .. latest_cpan + health.warn(message, 'Run in shell: cpanm -n Neovim::Ext') + else + health.ok('Latest "Neovim::Ext" cpan module is installed: ' .. current_cpan) + end +end + local function is(path, ty) if not path then return false end - local stat = vim.loop.fs_stat(path) + local stat = vim.uv.fs_stat(path) if not stat then return false end @@ -60,7 +281,7 @@ local function check_bin(bin) if not is(bin, 'file') and (not iswin or not is(bin .. '.exe', 'file')) then health.error('"' .. bin .. '" was not found.') return false - elseif not executable(bin) then + elseif vim.fn.executable(bin) == 0 then health.error('"' .. bin .. '" is not executable.') return false end @@ -69,22 +290,22 @@ end -- Fetch the contents of a URL. local function download(url) - local has_curl = executable('curl') + local has_curl = vim.fn.executable('curl') == 1 if has_curl and vim.fn.system({ 'curl', '-V' }):find('Protocols:.*https') then - local out, rc = health.system({ 'curl', '-sL', url }, { stderr = true, ignore_error = true }) + local out, rc = health._system({ 'curl', '-sL', url }, { stderr = true, ignore_error = true }) if rc ~= 0 then return 'curl error with ' .. url .. ': ' .. rc else return out end - elseif executable('python') then + elseif vim.fn.executable('python') == 1 then local script = "try:\n\ from urllib.request import urlopen\n\ except ImportError:\n\ from urllib2 import urlopen\n\ response = urlopen('" .. url .. "')\n\ print(response.read().decode('utf8'))\n" - local out, rc = health.system({ 'python', '-c', script }) + local out, rc = health._system({ 'python', '-c', script }) if out == '' and rc ~= 0 then return 'python urllib.request error: ' .. rc else @@ -141,7 +362,7 @@ end local function version_info(python) local pypi_version = latest_pypi_version() - local python_version, rc = health.system({ + local python_version, rc = health._system({ python, '-c', 'import sys; print(".".join(str(x) for x in sys.version_info[:3]))', @@ -152,7 +373,7 @@ local function version_info(python) end local nvim_path - nvim_path, rc = health.system({ + nvim_path, rc = health._system({ python, '-c', 'import sys; sys.path = [p for p in sys.path if p != ""]; import neovim; print(neovim.__file__)', @@ -177,7 +398,7 @@ local function version_info(python) -- Try to get neovim.VERSION (added in 0.1.11dev). local nvim_version - nvim_version, rc = health.system({ + nvim_version, rc = health._system({ python, '-c', 'from neovim import VERSION as v; print("{}.{}.{}{}".format(v.major, v.minor, v.patch, v.prerelease))', @@ -214,7 +435,7 @@ local function version_info(python) return { python_version, nvim_version, pypi_version, version_status } end -function M.check() +local function python() health.start('Python 3 provider (optional)') local pyname = 'python3' ---@type string? @@ -224,7 +445,7 @@ function M.check() local host_prog_var = pyname .. '_host_prog' local python_multiple = {} - if health.provider_disabled(pyname) then + if health._provider_disabled(pyname) then return end @@ -266,7 +487,7 @@ function M.check() end if pyenv ~= '' then - python_exe = health.system({ pyenv, 'which', pyname }, { stderr = true }) + python_exe = health._system({ pyenv, 'which', pyname }, { stderr = true }) if python_exe == '' then health.warn('pyenv could not find ' .. pyname .. '.') end @@ -284,7 +505,7 @@ function M.check() if path_bin ~= vim.fs.normalize(python_exe) and vim.tbl_contains(python_multiple, path_bin) - and executable(path_bin) + and vim.fn.executable(path_bin) == 1 then python_multiple[#python_multiple + 1] = path_bin end @@ -472,7 +693,7 @@ function M.check() bin_dir, table.concat( vim.tbl_map(function(v) - return vim.fn.fnamemodify(v, ':t') + return vim.fs.basename(v) end, venv_bins), ', ' ) @@ -489,7 +710,7 @@ function M.check() health.info(msg) health.info( 'Python version: ' - .. health.system( + .. health._system( 'python -c "import platform, sys; sys.stdout.write(platform.python_version())"' ) ) @@ -497,4 +718,75 @@ function M.check() end end +local function ruby() + health.start('Ruby provider (optional)') + + if health._provider_disabled('ruby') then + return + end + + if vim.fn.executable('ruby') == 0 or vim.fn.executable('gem') == 0 then + health.warn( + '`ruby` and `gem` must be in $PATH.', + 'Install Ruby and verify that `ruby` and `gem` commands work.' + ) + return + end + health.info('Ruby: ' .. health._system({ 'ruby', '-v' })) + + local host, _ = vim.provider.ruby.detect() + if (not host) or host:find('^%s*$') then + health.warn('`neovim-ruby-host` not found.', { + 'Run `gem install neovim` to ensure the neovim RubyGem is installed.', + 'Run `gem environment` to ensure the gem bin directory is in $PATH.', + 'If you are using rvm/rbenv/chruby, try "rehashing".', + 'See :help g:ruby_host_prog for non-standard gem installations.', + 'You may disable this provider (and warning) by adding `let g:loaded_ruby_provider = 0` to your init.vim', + }) + return + end + health.info('Host: ' .. host) + + local latest_gem_cmd = (iswin and 'cmd /c gem list -ra "^^neovim$"' or 'gem list -ra ^neovim$') + local ok, latest_gem = health._cmd_ok(vim.split(latest_gem_cmd, ' ')) + if not ok or latest_gem:find('^%s*$') then + health.error( + 'Failed to run: ' .. latest_gem_cmd, + { "Make sure you're connected to the internet.", 'Are you behind a firewall or proxy?' } + ) + return + end + local gem_split = vim.split(latest_gem, [[neovim (\|, \|)$]]) + latest_gem = gem_split[1] or 'not found' + + local current_gem_cmd = { host, '--version' } + local current_gem + ok, current_gem = health._cmd_ok(current_gem_cmd) + if not ok then + health.error( + 'Failed to run: ' .. table.concat(current_gem_cmd, ' '), + { 'Report this issue with the output of: ', table.concat(current_gem_cmd, ' ') } + ) + return + end + + if vim.version.lt(current_gem, latest_gem) then + local message = 'Gem "neovim" is out-of-date. Installed: ' + .. current_gem + .. ', latest: ' + .. latest_gem + health.warn(message, 'Run in shell: gem update neovim') + else + health.ok('Latest "neovim" gem is installed: ' .. current_gem) + end +end + +function M.check() + clipboard() + node() + perl() + python() + ruby() +end + return M diff --git a/runtime/lua/vim/secure.lua b/runtime/lua/vim/secure.lua index 3992eef78a..41a3d3ba25 100644 --- a/runtime/lua/vim/secure.lua +++ b/runtime/lua/vim/secure.lua @@ -126,7 +126,7 @@ end --- --- The trust database is located at |$XDG_STATE_HOME|/nvim/trust. --- ----@param opts? vim.trust.opts +---@param opts vim.trust.opts ---@return boolean success true if operation was successful ---@return string msg full path if operation was successful, else error message function M.trust(opts) diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index bd553598c7..e9e4326057 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -356,7 +356,7 @@ end --- We only merge empty tables or tables that are not an array (indexed by integers) local function can_merge(v) - return type(v) == 'table' and (vim.tbl_isempty(v) or not vim.tbl_isarray(v)) + return type(v) == 'table' and (vim.tbl_isempty(v) or not vim.isarray(v)) end local function tbl_extend(behavior, deep_extend, ...) @@ -402,7 +402,7 @@ end --- ---@see |extend()| --- ----@param behavior string Decides what to do if a key is found in more than one map: +---@param behavior 'error'|'keep'|'force' Decides what to do if a key is found in more than one map: --- - "error": raise an error --- - "keep": use value from the leftmost map --- - "force": use value from the rightmost map @@ -418,7 +418,7 @@ end --- ---@generic T1: table ---@generic T2: table ----@param behavior "error"|"keep"|"force" (string) Decides what to do if a key is found in more than one map: +---@param behavior 'error'|'keep'|'force' Decides what to do if a key is found in more than one map: --- - "error": raise an error --- - "keep": use value from the leftmost map --- - "force": use value from the rightmost map @@ -502,7 +502,7 @@ end --- ---@param o table Table to index ---@param ... any Optional keys (0 or more, variadic) via which to index the table ----@return any : Nested value indexed by key (if it exists), else nil +---@return any # Nested value indexed by key (if it exists), else nil function vim.tbl_get(o, ...) local keys = { ... } if #keys == 0 then @@ -544,6 +544,7 @@ function vim.list_extend(dst, src, start, finish) return dst end +--- @deprecated --- Creates a copy of a list-like table such that any nested tables are --- "unrolled" and appended to the result. --- @@ -552,6 +553,7 @@ end ---@param t table List-like table ---@return table Flattened copy of the given list-like table function vim.tbl_flatten(t) + vim.deprecate('vim.tbl_flatten', 'vim.iter(…):flatten():totable()', '0.13') local result = {} --- @param _t table<any,any> local function _tbl_flatten(_t) @@ -578,7 +580,7 @@ end ---@return fun(table: table<K, V>, index?: K):K, V # |for-in| iterator over sorted keys and their values ---@return T function vim.spairs(t) - vim.validate({ t = { t, 't' } }) + assert(type(t) == 'table', ('expected table, got %s'):format(type(t))) --- @cast t table<any,any> -- collect the keys @@ -601,16 +603,16 @@ end --- Tests if `t` is an "array": a table indexed _only_ by integers (potentially non-contiguous). --- ---- If the indexes start from 1 and are contiguous then the array is also a list. |vim.tbl_islist()| +--- If the indexes start from 1 and are contiguous then the array is also a list. |vim.islist()| --- --- Empty table `{}` is an array, unless it was created by |vim.empty_dict()| or returned as --- a dict-like |API| or Vimscript result, for example from |rpcrequest()| or |vim.fn|. --- ---@see https://github.com/openresty/luajit2#tableisarray --- ----@param t table +---@param t? table ---@return boolean `true` if array-like table, else `false`. -function vim.tbl_isarray(t) +function vim.isarray(t) if type(t) ~= 'table' then return false end @@ -640,17 +642,23 @@ function vim.tbl_isarray(t) end end +--- @deprecated +function vim.tbl_islist(t) + vim.deprecate('vim.tbl_islist', 'vim.islist', '0.12') + return vim.islist(t) +end + --- Tests if `t` is a "list": a table indexed _only_ by contiguous integers starting from 1 (what --- |lua-length| calls a "regular array"). --- --- Empty table `{}` is a list, unless it was created by |vim.empty_dict()| or returned as --- a dict-like |API| or Vimscript result, for example from |rpcrequest()| or |vim.fn|. --- ----@see |vim.tbl_isarray()| +---@see |vim.isarray()| --- ----@param t table +---@param t? table ---@return boolean `true` if list-like table, else `false`. -function vim.tbl_islist(t) +function vim.islist(t) if type(t) ~= 'table' then return false end @@ -788,6 +796,61 @@ do return type(val) == t or (t == 'callable' and vim.is_callable(val)) end + --- @param param_name string + --- @param spec vim.validate.Spec + --- @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 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 vim.is_callable(types) then + -- Check user-provided validation function + local valid, optional_message = types(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) + end + + return error_message + 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 + 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 + end + end + if not success then + return string.format( + '%s: expected %s, got %s', + param_name, + table.concat(types, '|'), + type(val) + ) + end + else + return string.format('invalid type name: %s', tostring(types)) + end + end + --- @param opt table<vim.validate.Type,vim.validate.Spec> --- @return boolean, string? local function is_valid(opt) @@ -795,63 +858,27 @@ do return false, string.format('opt: expected table, got %s', type(opt)) end - for param_name, spec in pairs(opt) do - if type(spec) ~= 'table' then - return false, string.format('opt[%s]: expected table, got %s', param_name, type(spec)) - end - - local val = spec[1] -- Argument value - local types = spec[2] -- Type name, or callable - local optional = (true == spec[3]) + local report --- @type table<string,string>? - if type(types) == 'string' then - types = { types } + for param_name, spec in pairs(opt) do + local msg = is_param_valid(param_name, spec) + if msg then + report = report or {} + report[param_name] = msg end + end - if vim.is_callable(types) then - -- Check user-provided validation function - local valid, optional_message = types(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 = error_message .. string.format('. Info: %s', optional_message) - end - - return false, error_message - 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 - return false, 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 - end - end - if not success then - return false, - string.format( - '%s: expected %s, got %s', - param_name, - table.concat(types, '|'), - type(val) - ) - end - else - return false, string.format('invalid type name: %s', tostring(types)) + if report then + for _, msg in vim.spairs(report) do -- luacheck: ignore + return false, msg end end return true end - --- Validates a parameter specification (types and values). + --- Validates a parameter specification (types and values). Specs are evaluated in alphanumeric + --- order, until the first failure. --- --- Usage example: --- diff --git a/runtime/lua/vim/snippet.lua b/runtime/lua/vim/snippet.lua index 5e60efa778..3d8f73f362 100644 --- a/runtime/lua/vim/snippet.lua +++ b/runtime/lua/vim/snippet.lua @@ -254,9 +254,10 @@ local function display_choices(tabstop) assert(tabstop.choices, 'Tabstop has no choices') local start_col = tabstop:get_range()[2] + 1 - local matches = vim.iter.map(function(choice) - return { word = choice } - end, tabstop.choices) + local matches = {} --- @type table[] + for _, choice in ipairs(tabstop.choices) do + matches[#matches + 1] = { word = choice } + end vim.defer_fn(function() vim.fn.complete(start_col, matches) @@ -342,7 +343,7 @@ local function setup_autocmds(bufnr) or cursor_row > snippet_range[3] or (cursor_row == snippet_range[3] and cursor_col > snippet_range[4]) then - M.exit() + M.stop() return true end @@ -361,7 +362,7 @@ local function setup_autocmds(bufnr) end -- The cursor is either not on a tabstop or we reached the end, so exit the session. - M.exit() + M.stop() return true end, }) @@ -377,7 +378,7 @@ local function setup_autocmds(bufnr) (snippet_range[1] == snippet_range[3] and snippet_range[2] == snippet_range[4]) or snippet_range[3] + 1 > vim.fn.line('$') then - M.exit() + M.stop() end if not M.active() then @@ -400,7 +401,7 @@ end --- Refer to https://microsoft.github.io/language-server-protocol/specification/#snippet_syntax --- for the specification of valid input. --- ---- Tabstops are highlighted with hl-SnippetTabstop. +--- Tabstops are highlighted with |hl-SnippetTabstop|. --- --- @param input string function M.expand(input) @@ -446,17 +447,22 @@ function M.expand(input) base_indent = base_indent .. (snippet_lines[#snippet_lines]:match('(^%s*)%S') or '') --- @type string end - local lines = vim.iter.map(function(i, line) + local shiftwidth = vim.fn.shiftwidth() + local curbuf = vim.api.nvim_get_current_buf() + local expandtab = vim.bo[curbuf].expandtab + + local lines = {} --- @type string[] + for i, line in ipairs(text_to_lines(text)) do -- Replace tabs by spaces. - if vim.o.expandtab then - line = line:gsub('\t', (' '):rep(vim.fn.shiftwidth())) --- @type string + if expandtab then + line = line:gsub('\t', (' '):rep(shiftwidth)) --- @type string end -- Add the base indentation. if i > 1 then line = base_indent .. line end - return line - end, ipairs(text_to_lines(text))) + lines[#lines + 1] = line + end table.insert(snippet_text, table.concat(lines, '\n')) end @@ -526,37 +532,13 @@ end --- @alias vim.snippet.Direction -1 | 1 ---- Returns `true` if there is an active snippet which can be jumped in the given direction. ---- You can use this function to navigate a snippet as follows: +--- Jumps to the next (or previous) placeholder in the current snippet, if possible. --- ---- ```lua ---- vim.keymap.set({ 'i', 's' }, '<Tab>', function() ---- if vim.snippet.jumpable(1) then ---- return '<cmd>lua vim.snippet.jump(1)<cr>' ---- else ---- return '<Tab>' ---- end ---- end, { expr = true }) ---- ``` ---- ---- @param direction (vim.snippet.Direction) Navigation direction. -1 for previous, 1 for next. ---- @return boolean -function M.jumpable(direction) - if not M.active() then - return false - end - - return M._session:get_dest_index(direction) ~= nil -end - ---- Jumps within the active snippet in the given direction. ---- If the jump isn't possible, the function call does nothing. ---- ---- You can use this function to navigate a snippet as follows: +--- For example, map `<Tab>` to jump while a snippet is active: --- --- ```lua --- vim.keymap.set({ 'i', 's' }, '<Tab>', function() ---- if vim.snippet.jumpable(1) then +--- if vim.snippet.active({ direction = 1 }) then --- return '<cmd>lua vim.snippet.jump(1)<cr>' --- else --- return '<Tab>' @@ -598,15 +580,41 @@ function M.jump(direction) setup_autocmds(M._session.bufnr) end ---- Returns `true` if there's an active snippet in the current buffer. +--- @class vim.snippet.ActiveFilter +--- @field direction vim.snippet.Direction Navigation direction. -1 for previous, 1 for next. + +--- Returns `true` if there's an active snippet in the current buffer, +--- applying the given filter if provided. +--- +--- You can use this function to navigate a snippet as follows: +--- +--- ```lua +--- vim.keymap.set({ 'i', 's' }, '<Tab>', function() +--- if vim.snippet.active({ direction = 1 }) then +--- return '<cmd>lua vim.snippet.jump(1)<cr>' +--- else +--- return '<Tab>' +--- end +--- end, { expr = true }) +--- ``` --- +--- @param filter? vim.snippet.ActiveFilter Filter to constrain the search with: +--- - `direction` (vim.snippet.Direction): Navigation direction. Will return `true` if the snippet +--- can be jumped in the given direction. --- @return boolean -function M.active() - return M._session ~= nil and M._session.bufnr == vim.api.nvim_get_current_buf() +function M.active(filter) + local active = M._session ~= nil and M._session.bufnr == vim.api.nvim_get_current_buf() + + local in_direction = true + if active and filter and filter.direction then + in_direction = M._session:get_dest_index(filter.direction) ~= nil + end + + return active and in_direction end --- Exits the current snippet. -function M.exit() +function M.stop() if not M.active() then return end diff --git a/runtime/lua/vim/termcap.lua b/runtime/lua/vim/termcap.lua index ec29acca48..1da2e71839 100644 --- a/runtime/lua/vim/termcap.lua +++ b/runtime/lua/vim/termcap.lua @@ -12,7 +12,7 @@ local M = {} --- emulator supports the XTGETTCAP sequence. --- --- @param caps string|table A terminal capability or list of capabilities to query ---- @param cb function(cap:string, found:bool, seq:string?) Callback function which is called for +--- @param cb fun(cap:string, found:boolean, seq:string?) Callback function which is called for --- each capability in {caps}. {found} is set to true if the capability was found or false --- otherwise. {seq} is the control sequence for the capability if found, or nil for --- boolean capabilities. diff --git a/runtime/lua/vim/text.lua b/runtime/lua/vim/text.lua index 576b962838..bc90d490aa 100644 --- a/runtime/lua/vim/text.lua +++ b/runtime/lua/vim/text.lua @@ -5,7 +5,7 @@ local M = {} --- Hex encode a string. --- --- @param str string String to encode ---- @return string Hex encoded string +--- @return string : Hex encoded string function M.hexencode(str) local bytes = { str:byte(1, #str) } local enc = {} ---@type string[] @@ -18,7 +18,7 @@ end --- Hex decode a string. --- --- @param enc string String to decode ---- @return string Decoded string +--- @return string : Decoded string function M.hexdecode(enc) assert(#enc % 2 == 0, 'string must have an even number of hex characters') local str = {} ---@type string[] diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index a09619f369..db544c1ab1 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -257,7 +257,7 @@ end ---@param row integer Position row ---@param col integer Position column --- ----@return table[] List of captures `{ capture = "name", metadata = { ... } }` +---@return {capture: string, lang: string, metadata: table}[] function M.get_captures_at_pos(bufnr, row, col) if bufnr == 0 then bufnr = api.nvim_get_current_buf() @@ -327,7 +327,7 @@ function M.get_captures_at_cursor(winnr) end --- Optional keyword arguments: ---- @class vim.treesitter.get_node.Opts +--- @class vim.treesitter.get_node.Opts : vim.treesitter.LanguageTree.tree_for_range.Opts --- @inlinedoc --- --- Buffer number (nil or 0 for current buffer) diff --git a/runtime/lua/vim/treesitter/_fold.lua b/runtime/lua/vim/treesitter/_fold.lua index d96cc966de..eecf1ad6b1 100644 --- a/runtime/lua/vim/treesitter/_fold.lua +++ b/runtime/lua/vim/treesitter/_fold.lua @@ -4,10 +4,21 @@ local Range = require('vim.treesitter._range') local api = vim.api +---Treesitter folding is done in two steps: +---(1) compute the fold levels with the syntax tree and cache the result (`compute_folds_levels`) +---(2) evaluate foldexpr for each window, which reads from the cache (`foldupdate`) ---@class TS.FoldInfo ----@field levels string[] the foldexpr result for each line ----@field levels0 integer[] the raw fold levels ----@field edits? {[1]: integer, [2]: integer} line range edited since the last invocation of the callback scheduled in on_bytes. 0-indexed, end-exclusive. +--- +---@field levels string[] the cached foldexpr result for each line +---@field levels0 integer[] the cached raw fold levels +--- +---The range edited since the last invocation of the callback scheduled in on_bytes. +---Should compute fold levels in this range. +---@field on_bytes_range? Range2 +--- +---The range on which to evaluate foldexpr. +---When in insert mode, the evaluation is deferred to InsertLeave. +---@field foldupdate_range? Range2 local FoldInfo = {} FoldInfo.__index = FoldInfo @@ -80,45 +91,16 @@ function FoldInfo:add_range(srow, erow) list_insert(self.levels0, srow + 1, erow, -1) end ----@package +---@param range Range2 ---@param srow integer ---@param erow_old integer ---@param erow_new integer 0-indexed, exclusive -function FoldInfo:edit_range(srow, erow_old, erow_new) - if self.edits then - self.edits[1] = math.min(srow, self.edits[1]) - if erow_old <= self.edits[2] then - self.edits[2] = self.edits[2] + (erow_new - erow_old) - end - self.edits[2] = math.max(self.edits[2], erow_new) - else - self.edits = { srow, erow_new } +local function edit_range(range, srow, erow_old, erow_new) + range[1] = math.min(srow, range[1]) + if erow_old <= range[2] then + range[2] = range[2] + (erow_new - erow_old) end -end - ----@package ----@return integer? srow ----@return integer? erow 0-indexed, exclusive -function FoldInfo:flush_edit() - if self.edits then - local srow, erow = self.edits[1], self.edits[2] - self.edits = nil - return srow, erow - end -end - ---- If a parser doesn't have any ranges explicitly set, treesitter will ---- return a range with end_row and end_bytes with a value of UINT32_MAX, ---- so clip end_row to the max buffer line. ---- ---- TODO(lewis6991): Handle this generally ---- ---- @param bufnr integer ---- @param erow integer? 0-indexed, exclusive ---- @return integer -local function normalise_erow(bufnr, erow) - local max_erow = api.nvim_buf_line_count(bufnr) - return math.min(erow or max_erow, max_erow) + range[2] = math.max(range[2], erow_new) end -- TODO(lewis6991): Setup a decor provider so injections folds can be parsed @@ -128,9 +110,9 @@ end ---@param srow integer? ---@param erow integer? 0-indexed, exclusive ---@param parse_injections? boolean -local function get_folds_levels(bufnr, info, srow, erow, parse_injections) +local function compute_folds_levels(bufnr, info, srow, erow, parse_injections) srow = srow or 0 - erow = normalise_erow(bufnr, erow) + erow = erow or api.nvim_buf_line_count(bufnr) local parser = ts.get_parser(bufnr) @@ -149,27 +131,43 @@ local function get_folds_levels(bufnr, info, srow, erow, parse_injections) -- Collect folds starting from srow - 1, because we should first subtract the folds that end at -- srow - 1 from the level of srow - 1 to get accurate level of srow. - for id, node, metadata in query:iter_captures(tree:root(), bufnr, math.max(srow - 1, 0), erow) do - if query.captures[id] == 'fold' then - local range = ts.get_range(node, bufnr, metadata[id]) - local start, _, stop, stop_col = Range.unpack4(range) - - if stop_col == 0 then - stop = stop - 1 - end - - local fold_length = stop - start + 1 - - -- Fold only multiline nodes that are not exactly the same as previously met folds - -- Checking against just the previously found fold is sufficient if nodes - -- are returned in preorder or postorder when traversing tree - if - fold_length > vim.wo.foldminlines and not (start == prev_start and stop == prev_stop) - then - enter_counts[start + 1] = (enter_counts[start + 1] or 0) + 1 - leave_counts[stop + 1] = (leave_counts[stop + 1] or 0) + 1 - prev_start = start - prev_stop = stop + for _, match, metadata in + query:iter_matches(tree:root(), bufnr, math.max(srow - 1, 0), erow, { all = true }) + do + for id, nodes in pairs(match) do + if query.captures[id] == 'fold' then + local range = ts.get_range(nodes[1], bufnr, metadata[id]) + local start, _, stop, stop_col = Range.unpack4(range) + + for i = 2, #nodes, 1 do + local node_range = ts.get_range(nodes[i], bufnr, metadata[id]) + local node_start, _, node_stop, node_stop_col = Range.unpack4(node_range) + if node_start < start then + start = node_start + end + if node_stop > stop then + stop = node_stop + stop_col = node_stop_col + end + end + + if stop_col == 0 then + stop = stop - 1 + end + + local fold_length = stop - start + 1 + + -- Fold only multiline nodes that are not exactly the same as previously met folds + -- Checking against just the previously found fold is sufficient if nodes + -- are returned in preorder or postorder when traversing tree + if + fold_length > vim.wo.foldminlines and not (start == prev_start and stop == prev_stop) + then + enter_counts[start + 1] = (enter_counts[start + 1] or 0) + 1 + leave_counts[stop + 1] = (leave_counts[stop + 1] or 0) + 1 + prev_start = start + prev_stop = stop + end end end end @@ -215,7 +213,7 @@ local function get_folds_levels(bufnr, info, srow, erow, parse_injections) clamped = nestmax end - -- Record the "real" level, so that it can be used as "base" of later get_folds_levels(). + -- Record the "real" level, so that it can be used as "base" of later compute_folds_levels(). info.levels0[lnum] = adjusted info.levels[lnum] = prefix .. tostring(clamped) @@ -236,18 +234,17 @@ local group = api.nvim_create_augroup('treesitter/fold', {}) --- --- Nvim usually automatically updates folds when text changes, but it doesn't work here because --- FoldInfo update is scheduled. So we do it manually. -local function foldupdate(bufnr) - local function do_update() - for _, win in ipairs(vim.fn.win_findbuf(bufnr)) do - api.nvim_win_call(win, function() - if vim.wo.foldmethod == 'expr' then - vim._foldupdate() - end - end) - end +---@package +---@param srow integer +---@param erow integer 0-indexed, exclusive +function FoldInfo:foldupdate(bufnr, srow, erow) + if self.foldupdate_range then + edit_range(self.foldupdate_range, srow, erow, erow) + else + self.foldupdate_range = { srow, erow } end - if api.nvim_get_mode().mode == 'i' then + if api.nvim_get_mode().mode:match('^i') then -- foldUpdate() is guarded in insert mode. So update folds on InsertLeave if #(api.nvim_get_autocmds({ group = group, @@ -259,12 +256,25 @@ local function foldupdate(bufnr) group = group, buffer = bufnr, once = true, - callback = do_update, + callback = function() + self:do_foldupdate(bufnr) + end, }) return end - do_update() + self:do_foldupdate(bufnr) +end + +---@package +function FoldInfo:do_foldupdate(bufnr) + local srow, erow = self.foldupdate_range[1], self.foldupdate_range[2] + self.foldupdate_range = nil + for _, win in ipairs(vim.fn.win_findbuf(bufnr)) do + if vim.wo[win].foldmethod == 'expr' then + vim._foldupdate(win, srow, erow) + end + end end --- Schedule a function only if bufnr is loaded. @@ -272,7 +282,7 @@ end --- * queries seem to use the old buffer state in on_bytes for some unknown reason; --- * to avoid textlock; --- * to avoid infinite recursion: ---- get_folds_levels → parse → _do_callback → on_changedtree → get_folds_levels. +--- compute_folds_levels → parse → _do_callback → on_changedtree → compute_folds_levels. ---@param bufnr integer ---@param fn function local function schedule_if_loaded(bufnr, fn) @@ -289,16 +299,27 @@ end ---@param tree_changes Range4[] local function on_changedtree(bufnr, foldinfo, tree_changes) schedule_if_loaded(bufnr, function() + local srow_upd, erow_upd ---@type integer?, integer? + local max_erow = api.nvim_buf_line_count(bufnr) for _, change in ipairs(tree_changes) do local srow, _, erow, ecol = Range.unpack4(change) - if ecol > 0 then + -- If a parser doesn't have any ranges explicitly set, treesitter will + -- return a range with end_row and end_bytes with a value of UINT32_MAX, + -- so clip end_row to the max buffer line. + -- TODO(lewis6991): Handle this generally + if erow > max_erow then + erow = max_erow + elseif ecol > 0 then erow = erow + 1 end -- Start from `srow - foldminlines`, because this edit may have shrunken the fold below limit. - get_folds_levels(bufnr, foldinfo, math.max(srow - vim.wo.foldminlines, 0), erow) + srow = math.max(srow - vim.wo.foldminlines, 0) + compute_folds_levels(bufnr, foldinfo, srow, erow) + srow_upd = srow_upd and math.min(srow_upd, srow) or srow + erow_upd = erow_upd and math.max(erow_upd, erow) or erow end if #tree_changes > 0 then - foldupdate(bufnr) + foldinfo:foldupdate(bufnr, srow_upd, erow_upd) end end) end @@ -335,19 +356,29 @@ local function on_bytes(bufnr, foldinfo, start_row, start_col, old_row, old_col, foldinfo:add_range(end_row_old, end_row_new) end end - foldinfo:edit_range(start_row, end_row_old, end_row_new) + + if foldinfo.on_bytes_range then + edit_range(foldinfo.on_bytes_range, start_row, end_row_old, end_row_new) + else + foldinfo.on_bytes_range = { start_row, end_row_new } + end + if foldinfo.foldupdate_range then + edit_range(foldinfo.foldupdate_range, start_row, end_row_old, end_row_new) + end -- This callback must not use on_bytes arguments, because they can be outdated when the callback -- is invoked. For example, `J` with non-zero count triggers multiple on_bytes before executing - -- the scheduled callback. So we should collect the edits. + -- the scheduled callback. So we accumulate the edited ranges in `on_bytes_range`. schedule_if_loaded(bufnr, function() - local srow, erow = foldinfo:flush_edit() - if not srow then + if not foldinfo.on_bytes_range then return end + local srow, erow = foldinfo.on_bytes_range[1], foldinfo.on_bytes_range[2] + foldinfo.on_bytes_range = nil -- Start from `srow - foldminlines`, because this edit may have shrunken the fold below limit. - get_folds_levels(bufnr, foldinfo, math.max(srow - vim.wo.foldminlines, 0), erow) - foldupdate(bufnr) + srow = math.max(srow - vim.wo.foldminlines, 0) + compute_folds_levels(bufnr, foldinfo, srow, erow) + foldinfo:foldupdate(bufnr, srow, erow) end) end end @@ -366,7 +397,7 @@ function M.foldexpr(lnum) if not foldinfos[bufnr] then foldinfos[bufnr] = FoldInfo.new() - get_folds_levels(bufnr, foldinfos[bufnr]) + compute_folds_levels(bufnr, foldinfos[bufnr]) parser:register_cbs({ on_changedtree = function(tree_changes) @@ -390,10 +421,10 @@ api.nvim_create_autocmd('OptionSet', { pattern = { 'foldminlines', 'foldnestmax' }, desc = 'Refresh treesitter folds', callback = function() - for _, bufnr in ipairs(vim.tbl_keys(foldinfos)) do + for bufnr, _ in pairs(foldinfos) do foldinfos[bufnr] = FoldInfo.new() - get_folds_levels(bufnr, foldinfos[bufnr]) - foldupdate(bufnr) + compute_folds_levels(bufnr, foldinfos[bufnr]) + foldinfos[bufnr]:foldupdate(bufnr, 0, api.nvim_buf_line_count(bufnr)) end end, }) diff --git a/runtime/lua/vim/treesitter/_meta.lua b/runtime/lua/vim/treesitter/_meta.lua index 19d97d2820..177699a207 100644 --- a/runtime/lua/vim/treesitter/_meta.lua +++ b/runtime/lua/vim/treesitter/_meta.lua @@ -20,6 +20,7 @@ error('Cannot require a meta file') ---@field descendant_for_range fun(self: TSNode, start_row: integer, start_col: integer, end_row: integer, end_col: integer): TSNode? ---@field named_descendant_for_range fun(self: TSNode, start_row: integer, start_col: integer, end_row: integer, end_col: integer): TSNode? ---@field parent fun(self: TSNode): TSNode? +---@field child_containing_descendant fun(self: TSNode, descendant: TSNode): TSNode? ---@field next_sibling fun(self: TSNode): TSNode? ---@field prev_sibling fun(self: TSNode): TSNode? ---@field next_named_sibling fun(self: TSNode): TSNode? @@ -34,22 +35,6 @@ error('Cannot require a meta file') ---@field byte_length fun(self: TSNode): integer local TSNode = {} ----@param query TSQuery ----@param captures true ----@param start? integer ----@param end_? integer ----@param opts? table ----@return fun(): integer, TSNode, vim.treesitter.query.TSMatch -function TSNode:_rawquery(query, captures, start, end_, opts) end - ----@param query TSQuery ----@param captures false ----@param start? integer ----@param end_? integer ----@param opts? table ----@return fun(): integer, vim.treesitter.query.TSMatch -function TSNode:_rawquery(query, captures, start, end_, opts) end - ---@alias TSLoggerCallback fun(logtype: 'parse'|'lex', msg: string) ---@class TSParser: userdata @@ -76,9 +61,17 @@ function TSNode:_rawquery(query, captures, start, end_, opts) end ---@field captures string[] ---@field patterns table<integer, (integer|string)[][]> +--- @param lang string +vim._ts_inspect_language = function(lang) end + ---@return integer vim._ts_get_language_version = function() end +--- @param path string +--- @param lang string +--- @param symbol_name? string +vim._ts_add_language = function(path, lang, symbol_name) end + ---@return integer vim._ts_get_minimum_language_version = function() end @@ -90,3 +83,31 @@ vim._ts_parse_query = function(lang, query) end ---@param lang string ---@return TSParser vim._create_ts_parser = function(lang) end + +--- @class TSQueryMatch: userdata +--- @field captures fun(self: TSQueryMatch): table<integer,TSNode[]> +local TSQueryMatch = {} + +--- @return integer match_id +--- @return integer pattern_index +function TSQueryMatch:info() end + +--- @class TSQueryCursor: userdata +--- @field remove_match fun(self: TSQueryCursor, id: integer) +local TSQueryCursor = {} + +--- @return integer capture +--- @return TSNode captured_node +--- @return TSQueryMatch match +function TSQueryCursor:next_capture() end + +--- @return TSQueryMatch match +function TSQueryCursor:next_match() end + +--- @param node TSNode +--- @param query TSQuery +--- @param start integer? +--- @param stop integer? +--- @param opts? { max_start_depth?: integer, match_limit?: integer} +--- @return TSQueryCursor +function vim._create_ts_querycursor(node, query, start, stop, opts) end diff --git a/runtime/lua/vim/treesitter/_query_linter.lua b/runtime/lua/vim/treesitter/_query_linter.lua index 6216d4e891..12b4cbc7b9 100644 --- a/runtime/lua/vim/treesitter/_query_linter.lua +++ b/runtime/lua/vim/treesitter/_query_linter.lua @@ -122,7 +122,7 @@ local parse = vim.func._memoize(hash_parse, function(node, buf, lang) end) --- @param buf integer ---- @param match vim.treesitter.query.TSMatch +--- @param match table<integer,TSNode[]> --- @param query vim.treesitter.Query --- @param lang_context QueryLinterLanguageContext --- @param diagnostics vim.Diagnostic[] diff --git a/runtime/lua/vim/treesitter/dev.lua b/runtime/lua/vim/treesitter/dev.lua index dc2a14d238..5c91f101c0 100644 --- a/runtime/lua/vim/treesitter/dev.lua +++ b/runtime/lua/vim/treesitter/dev.lua @@ -226,7 +226,7 @@ function TSTreeView:draw(bufnr) text = string.format('(%s', item.node:type()) end else - text = string.format('"%s"', item.node:type():gsub('\n', '\\n'):gsub('"', '\\"')) + text = string.format('%q', item.node:type()):gsub('\n', 'n') end local next = self:get(i + 1) diff --git a/runtime/lua/vim/treesitter/health.lua b/runtime/lua/vim/treesitter/health.lua index a9b066d158..ed3616ef46 100644 --- a/runtime/lua/vim/treesitter/health.lua +++ b/runtime/lua/vim/treesitter/health.lua @@ -24,7 +24,7 @@ function M.check() else local lang = ts.language.inspect(parsername) health.ok( - string.format('Parser: %-10s ABI: %d, path: %s', parsername, lang._abi_version, parser) + string.format('Parser: %-20s ABI: %d, path: %s', parsername, lang._abi_version, parser) ) end end diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index 388680259a..d2f986b874 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -4,7 +4,7 @@ local Range = require('vim.treesitter._range') local ns = api.nvim_create_namespace('treesitter/highlighter') ----@alias vim.treesitter.highlighter.Iter fun(end_line: integer|nil): integer, TSNode, vim.treesitter.query.TSMetadata +---@alias vim.treesitter.highlighter.Iter fun(end_line: integer|nil): integer, TSNode, vim.treesitter.query.TSMetadata, TSQueryMatch ---@class (private) vim.treesitter.highlighter.Query ---@field private _query vim.treesitter.Query? @@ -215,7 +215,7 @@ end ---@param start_row integer ---@param new_end integer function TSHighlighter:on_bytes(_, _, start_row, _, _, _, _, _, new_end) - api.nvim__buf_redraw_range(self.bufnr, start_row, start_row + new_end + 1) + api.nvim__redraw({ buf = self.bufnr, range = { start_row, start_row + new_end + 1 } }) end ---@package @@ -227,7 +227,7 @@ end ---@param changes Range6[] function TSHighlighter:on_changedtree(changes) for _, ch in ipairs(changes) do - api.nvim__buf_redraw_range(self.bufnr, ch[1], ch[4] + 1) + api.nvim__redraw({ buf = self.bufnr, range = { ch[1], ch[4] + 1 } }) end end @@ -243,6 +243,46 @@ function TSHighlighter:get_query(lang) return self._queries[lang] end +--- @param match TSQueryMatch +--- @param bufnr integer +--- @param capture integer +--- @param metadata vim.treesitter.query.TSMetadata +--- @return string? +local function get_url(match, bufnr, capture, metadata) + ---@type string|number|nil + local url = metadata[capture] and metadata[capture].url + + if not url or type(url) == 'string' then + return url + end + + local captures = match:captures() + + if not captures[url] then + return + end + + -- Assume there is only one matching node. If there is more than one, take the URL + -- from the first. + local other_node = captures[url][1] + + return vim.treesitter.get_node_text(other_node, bufnr, { + metadata = metadata[url], + }) +end + +--- @param capture_name string +--- @return boolean?, integer +local function get_spell(capture_name) + if capture_name == 'spell' then + return true, 0 + elseif capture_name == 'nospell' then + -- Give nospell a higher priority so it always overrides spell captures. + return false, 1 + end + return nil, 0 +end + ---@param self vim.treesitter.highlighter ---@param buf integer ---@param line integer @@ -258,12 +298,16 @@ local function on_line_impl(self, buf, line, is_spell_nav) end if state.iter == nil or state.next_row < line then + -- Mainly used to skip over folds + + -- TODO(lewis6991): Creating a new iterator loses the cached predicate results for query + -- matches. Move this logic inside iter_captures() so we can maintain the cache. state.iter = state.highlighter_query:query():iter_captures(root_node, self.bufnr, line, root_end_row + 1) end while line >= state.next_row do - local capture, node, metadata = state.iter(line) + local capture, node, metadata, match = state.iter(line) local range = { root_end_row + 1, 0, root_end_row + 1, 0 } if node then @@ -275,27 +319,30 @@ local function on_line_impl(self, buf, line, is_spell_nav) local hl = state.highlighter_query:get_hl_from_capture(capture) local capture_name = state.highlighter_query:query().captures[capture] - local spell = nil ---@type boolean? - if capture_name == 'spell' then - spell = true - elseif capture_name == 'nospell' then - spell = false - end - -- Give nospell a higher priority so it always overrides spell captures. - local spell_pri_offset = capture_name == 'nospell' and 1 or 0 + local spell, spell_pri_offset = get_spell(capture_name) + + -- 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 + ) + spell_pri_offset + + -- The "conceal" attribute can be set at the pattern level or on a particular capture + local conceal = metadata.conceal or metadata[capture] and metadata[capture].conceal + + local url = get_url(match, buf, capture, metadata) if hl and end_row >= line and (not is_spell_nav or spell ~= nil) then - local priority = (tonumber(metadata.priority) or vim.highlight.priorities.treesitter) - + spell_pri_offset api.nvim_buf_set_extmark(buf, ns, start_row, start_col, { end_line = end_row, end_col = end_col, hl_group = hl, ephemeral = true, priority = priority, - conceal = metadata.conceal, + conceal = conceal, spell = spell, + url = url, }) end end diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua index 47abf65332..d0a74daa6c 100644 --- a/runtime/lua/vim/treesitter/language.lua +++ b/runtime/lua/vim/treesitter/language.lua @@ -88,6 +88,9 @@ function M.add(lang, opts) filetype = { filetype, { 'string', 'table' }, true }, }) + -- parser names are assumed to be lowercase (consistent behavior on case-insensitive file systems) + lang = lang:lower() + if vim._ts_has_language(lang) then M.register(lang, filetype) return diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index 62714d3f1b..b0812123b9 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -81,7 +81,7 @@ local TSCallbackNames = { ---List of regions this tree should manage and parse. If nil then regions are ---taken from _trees. This is mostly a short-lived cache for included_regions() ---@field private _lang string Language name ----@field private _parent_lang? string Parent language name +---@field private _parent? vim.treesitter.LanguageTree Parent LanguageTree ---@field private _source (integer|string) Buffer or string to parse ---@field private _trees table<integer, TSTree> Reference to parsed tree (one for each language). ---Each key is the index of region, which is synced with _regions and _valid. @@ -106,9 +106,8 @@ LanguageTree.__index = LanguageTree ---@param source (integer|string) Buffer or text string to parse ---@param lang string Root language of this tree ---@param opts vim.treesitter.LanguageTree.new.Opts? ----@param parent_lang? string Parent language name of this tree ---@return vim.treesitter.LanguageTree parser object -function LanguageTree.new(source, lang, opts, parent_lang) +function LanguageTree.new(source, lang, opts) language.add(lang) opts = opts or {} @@ -122,7 +121,6 @@ function LanguageTree.new(source, lang, opts, parent_lang) local self = { _source = source, _lang = lang, - _parent_lang = parent_lang, _children = {}, _trees = {}, _opts = opts, @@ -158,8 +156,10 @@ function LanguageTree:_set_logger() local lang = self:lang() - vim.fn.mkdir(vim.fn.stdpath('log'), 'p') - local logfilename = vim.fs.joinpath(vim.fn.stdpath('log'), 'treesitter.log') + local logdir = vim.fn.stdpath('log') --[[@as string]] + + vim.fn.mkdir(logdir, 'p') + local logfilename = vim.fs.joinpath(logdir, 'treesitter.log') local logfile, openerr = io.open(logfilename, 'a+') @@ -225,7 +225,10 @@ function LanguageTree:_log(...) self._logger('nvim', table.concat(msg, ' ')) end ---- Invalidates this parser and all its children +--- Invalidates this parser and its children. +--- +--- Should only be called when the tracked state of the LanguageTree is not valid against the parse +--- tree in treesitter. Doesn't clear filesystem cache. Called often, so needs to be fast. ---@param reload boolean|nil function LanguageTree:invalidate(reload) self._valid = false @@ -460,24 +463,6 @@ function LanguageTree:parse(range) return self._trees end ----@deprecated Misleading name. Use `LanguageTree:children()` (non-recursive) instead, ---- add recursion yourself if needed. ---- Invokes the callback for each |LanguageTree| and its children recursively ---- ----@param fn fun(tree: vim.treesitter.LanguageTree, lang: string) ----@param include_self boolean|nil Whether to include the invoking tree in the results -function LanguageTree:for_each_child(fn, include_self) - vim.deprecate('LanguageTree:for_each_child()', 'LanguageTree:children()', '0.11') - if include_self then - fn(self, self._lang) - end - - for _, child in pairs(self._children) do - --- @diagnostic disable-next-line:deprecated - child:for_each_child(fn, true) - end -end - --- Invokes the callback for each |LanguageTree| recursively. --- --- Note: This includes the invoking tree's child trees as well. @@ -505,19 +490,25 @@ function LanguageTree:add_child(lang) self:remove_child(lang) end - local child = LanguageTree.new(self._source, lang, self._opts, self:lang()) + local child = LanguageTree.new(self._source, lang, self._opts) -- Inherit recursive callbacks for nm, cb in pairs(self._callbacks_rec) do vim.list_extend(child._callbacks_rec[nm], cb) end + child._parent = self self._children[lang] = child self:_do_callback('child_added', self._children[lang]) return self._children[lang] end +--- @package +function LanguageTree:parent() + return self._parent +end + --- Removes a child language from this |LanguageTree|. --- ---@private @@ -752,7 +743,6 @@ local has_parser = vim.func._memoize(1, function(lang) end) --- Return parser name for language (if exists) or filetype (if registered and exists). ---- Also attempts with the input lower-cased. --- ---@param alias string language or filetype name ---@return string? # resolved parser name @@ -766,19 +756,10 @@ local function resolve_lang(alias) return alias end - if has_parser(alias:lower()) then - return alias:lower() - end - local lang = vim.treesitter.language.get_lang(alias) if lang and has_parser(lang) then return lang end - - lang = vim.treesitter.language.get_lang(alias:lower()) - if lang and has_parser(lang) then - return lang - end end ---@private @@ -792,7 +773,7 @@ function LanguageTree:_get_injection(match, metadata) local combined = metadata['injection.combined'] ~= nil local injection_lang = metadata['injection.language'] --[[@as string?]] local lang = metadata['injection.self'] ~= nil and self:lang() - or metadata['injection.parent'] ~= nil and self._parent_lang + or metadata['injection.parent'] ~= nil and self._parent:lang() or (injection_lang and resolve_lang(injection_lang)) local include_children = metadata['injection.include-children'] ~= nil @@ -802,7 +783,11 @@ function LanguageTree:_get_injection(match, metadata) -- Lang should override any other language tag if name == 'injection.language' then local text = vim.treesitter.get_node_text(node, self._source, { metadata = metadata[id] }) - lang = resolve_lang(text) + lang = resolve_lang(text:lower()) -- language names are always lower case + elseif name == 'injection.filename' then + local text = vim.treesitter.get_node_text(node, self._source, { metadata = metadata[id] }) + local ft = vim.filetype.match({ filename = text }) + lang = ft and resolve_lang(ft) elseif name == 'injection.content' then ranges = get_node_ranges(node, self._source, metadata[id], include_children) end @@ -1054,20 +1039,19 @@ function LanguageTree:_on_detach(...) end end ---- Registers callbacks for the |LanguageTree|. ----@param cbs table 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. +--- 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_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. --- - `on_child_added` : emitted when a child is added to the tree. --- - `on_child_removed` : emitted when a child is removed from the tree. ---- - `on_detach` : emitted when the buffer is detached, see |nvim_buf_detach_event|. +--- - `on_detach` : emitted when the buffer is detached, see [nvim_buf_detach_event]. --- Takes one argument, the number of the buffer. --- @param recursive? boolean Apply callbacks recursively for all children. Any new children will --- also inherit the callbacks. function LanguageTree:register_cbs(cbs, recursive) - ---@cast cbs table<TSCallbackNameOn,function> if not cbs then return end @@ -1091,7 +1075,14 @@ end ---@param range Range ---@return boolean local function tree_contains(tree, range) - return Range.contains({ tree:root():range() }, range) + local tree_ranges = tree:included_ranges(false) + + return Range.contains({ + tree_ranges[1][1], + tree_ranges[1][2], + tree_ranges[#tree_ranges][3], + tree_ranges[#tree_ranges][4], + }, range) end --- Determines whether {range} is contained in the |LanguageTree|. @@ -1108,12 +1099,18 @@ function LanguageTree:contains(range) return false end +--- @class vim.treesitter.LanguageTree.tree_for_range.Opts +--- @inlinedoc +--- +--- Ignore injected languages +--- (default: `true`) +--- @field ignore_injections? boolean + --- Gets the tree that contains {range}. --- ---@param range Range4 `{ start_line, start_col, end_line, end_col }` ----@param opts table|nil Optional keyword arguments: ---- - ignore_injections boolean Ignore injected languages (default true) ----@return TSTree|nil +---@param opts? vim.treesitter.LanguageTree.tree_for_range.Opts +---@return TSTree? function LanguageTree:tree_for_range(range, opts) opts = opts or {} local ignore = vim.F.if_nil(opts.ignore_injections, true) @@ -1139,9 +1136,8 @@ end --- Gets the smallest named node that contains {range}. --- ---@param range Range4 `{ start_line, start_col, end_line, end_col }` ----@param opts table|nil Optional keyword arguments: ---- - ignore_injections boolean Ignore injected languages (default true) ----@return TSNode | nil Found node +---@param opts? vim.treesitter.LanguageTree.tree_for_range.Opts +---@return TSNode? function LanguageTree:named_node_for_range(range, opts) local tree = self:tree_for_range(range, opts) if tree then @@ -1152,7 +1148,7 @@ end --- Gets the appropriate language that contains {range}. --- ---@param range Range4 `{ start_line, start_col, end_line, end_col }` ----@return vim.treesitter.LanguageTree Managing {range} +---@return vim.treesitter.LanguageTree tree Managing {range} function LanguageTree:language_for_range(range) for _, child in pairs(self._children) do if child:contains(range) then diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index a086f5e876..ef5c2143a7 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -1,5 +1,6 @@ local api = vim.api local language = require('vim.treesitter.language') +local memoize = vim.func._memoize local M = {} @@ -88,7 +89,7 @@ end --- ---@param lang string Language to get query for ---@param query_name string Name of the query to load (e.g., "highlights") ----@param is_included (boolean|nil) Internal parameter, most of the time left as `nil` +---@param is_included? boolean Internal parameter, most of the time left as `nil` ---@return string[] query_files List of files to load for given query and language function M.get_files(lang, query_name, is_included) local query_path = string.format('queries/%s/%s.scm', lang, query_name) @@ -211,8 +212,8 @@ end ---@param lang string Language to use for the query ---@param query_name string Name of the query (e.g. "highlights") --- ----@return vim.treesitter.Query|nil : Parsed query. `nil` if no query files are found. -M.get = vim.func._memoize('concat-2', function(lang, query_name) +---@return vim.treesitter.Query? : Parsed query. `nil` if no query files are found. +M.get = memoize('concat-2', function(lang, query_name) if explicit_queries[lang][query_name] then return explicit_queries[lang][query_name] end @@ -242,10 +243,10 @@ end) ---@param lang string Language to use for the query ---@param query string Query in s-expr syntax --- ----@return vim.treesitter.Query Parsed query +---@return vim.treesitter.Query : Parsed query --- ----@see |vim.treesitter.query.get()| -M.parse = vim.func._memoize('concat-2', function(lang, query) +---@see [vim.treesitter.query.get()] +M.parse = memoize('concat-2', function(lang, query) language.add(lang) local ts_query = vim._ts_parse_query(lang, query) @@ -258,7 +259,7 @@ end) --- handling the "any" vs "all" semantics. They are called from the --- predicate_handlers table with the appropriate arguments for each predicate. local impl = { - --- @param match vim.treesitter.query.TSMatch + --- @param match table<integer,TSNode[]> --- @param source integer|string --- @param predicate any[] --- @param any boolean @@ -293,7 +294,7 @@ local impl = { return not any end, - --- @param match vim.treesitter.query.TSMatch + --- @param match table<integer,TSNode[]> --- @param source integer|string --- @param predicate any[] --- @param any boolean @@ -333,7 +334,7 @@ local impl = { end, }) - --- @param match vim.treesitter.query.TSMatch + --- @param match table<integer,TSNode[]> --- @param source integer|string --- @param predicate any[] --- @param any boolean @@ -356,7 +357,7 @@ local impl = { end end)(), - --- @param match vim.treesitter.query.TSMatch + --- @param match table<integer,TSNode[]> --- @param source integer|string --- @param predicate any[] --- @param any boolean @@ -383,13 +384,7 @@ local impl = { end, } ----@nodoc ----@class vim.treesitter.query.TSMatch ----@field pattern? integer ----@field active? boolean ----@field [integer] TSNode[] - ----@alias TSPredicate fun(match: vim.treesitter.query.TSMatch, pattern: integer, source: integer|string, predicate: any[]): boolean +---@alias TSPredicate fun(match: table<integer,TSNode[]>, pattern: integer, source: integer|string, predicate: any[]): boolean -- Predicate handler receive the following arguments -- (match, pattern, bufnr, predicate) @@ -462,17 +457,8 @@ local predicate_handlers = { end for _, node in ipairs(nodes) do - local ancestor_types = {} --- @type table<string, boolean> - for _, type in ipairs({ unpack(predicate, 3) }) do - ancestor_types[type] = true - end - - local cur = node:parent() - while cur do - if ancestor_types[cur:type()] then - return true - end - cur = cur:parent() + if node:__has_ancestor(predicate) then + return true end end return false @@ -504,7 +490,7 @@ predicate_handlers['any-vim-match?'] = predicate_handlers['any-match?'] ---@field [integer] vim.treesitter.query.TSMetadata ---@field [string] integer|string ----@alias TSDirective fun(match: vim.treesitter.query.TSMatch, _, _, predicate: (string|integer)[], metadata: vim.treesitter.query.TSMetadata) +---@alias TSDirective fun(match: table<integer,TSNode[]>, _, _, predicate: (string|integer)[], metadata: vim.treesitter.query.TSMetadata) -- Predicate handler receive the following arguments -- (match, pattern, bufnr, predicate) @@ -534,6 +520,9 @@ local directive_handlers = { ['offset!'] = function(match, _, _, pred, metadata) local capture_id = pred[2] --[[@as integer]] local nodes = match[capture_id] + if not nodes or #nodes == 0 then + return + end assert(#nodes == 1, '#offset! does not support captures on multiple nodes') local node = nodes[1] @@ -567,6 +556,9 @@ local directive_handlers = { assert(type(id) == 'number') local nodes = match[id] + if not nodes or #nodes == 0 then + return + end assert(#nodes == 1, '#gsub! does not support captures on multiple nodes') local node = nodes[1] local text = vim.treesitter.get_node_text(node, bufnr, { metadata = metadata[id] }) or '' @@ -589,6 +581,9 @@ local directive_handlers = { assert(type(capture_id) == 'number') local nodes = match[capture_id] + if not nodes or #nodes == 0 then + return + end assert(#nodes == 1, '#trim! does not support captures on multiple nodes') local node = nodes[1] @@ -618,20 +613,23 @@ local directive_handlers = { end, } +--- @class vim.treesitter.query.add_predicate.Opts +--- @inlinedoc +--- +--- Override an existing predicate of the same name +--- @field force? boolean +--- +--- Use the correct implementation of the match table where capture IDs map to +--- a list of nodes instead of a single node. Defaults to false (for backward +--- compatibility). This option will eventually become the default and removed. +--- @field all? boolean + --- Adds a new predicate to be used in queries --- ---@param name string Name of the predicate, without leading # ----@param handler function(match: table<integer,TSNode[]>, pattern: integer, source: integer|string, predicate: any[], metadata: table) +---@param handler fun(match: table<integer,TSNode[]>, pattern: integer, source: integer|string, predicate: any[], metadata: table) --- - see |vim.treesitter.query.add_directive()| for argument meanings ----@param opts table<string, any> Optional options: ---- - force (boolean): Override an existing ---- predicate of the same name ---- - all (boolean): Use the correct ---- implementation of the match table where ---- capture IDs map to a list of nodes instead ---- of a single node. Defaults to false (for ---- backward compatibility). This option will ---- eventually become the default and removed. +---@param opts vim.treesitter.query.add_predicate.Opts function M.add_predicate(name, handler, opts) -- Backward compatibility: old signature had "force" as boolean argument if type(opts) == 'boolean' then @@ -669,20 +667,12 @@ end --- metadata table `metadata[capture_id].key = value` --- ---@param name string Name of the directive, without leading # ----@param handler function(match: table<integer,TSNode[]>, pattern: integer, source: integer|string, predicate: any[], metadata: table) +---@param handler fun(match: table<integer,TSNode[]>, pattern: integer, source: integer|string, predicate: any[], metadata: table) --- - match: A table mapping capture IDs to a list of captured nodes --- - pattern: the index of the matching pattern in the query file --- - predicate: list of strings containing the full directive being called, e.g. --- `(node (#set! conceal "-"))` would get the predicate `{ "#set!", "conceal", "-" }` ----@param opts table<string, any> Optional options: ---- - force (boolean): Override an existing ---- predicate of the same name ---- - all (boolean): Use the correct ---- implementation of the match table where ---- capture IDs map to a list of nodes instead ---- of a single node. Defaults to false (for ---- backward compatibility). This option will ---- eventually become the default and removed. +---@param opts vim.treesitter.query.add_predicate.Opts function M.add_directive(name, handler, opts) -- Backward compatibility: old signature had "force" as boolean argument if type(opts) == 'boolean' then @@ -711,13 +701,13 @@ function M.add_directive(name, handler, opts) end --- Lists the currently available directives to use in queries. ----@return string[] List of supported directives. +---@return string[] : Supported directives. function M.list_directives() return vim.tbl_keys(directive_handlers) end --- Lists the currently available predicates to use in queries. ----@return string[] List of supported predicates. +---@return string[] : Supported predicates. function M.list_predicates() return vim.tbl_keys(predicate_handlers) end @@ -731,13 +721,19 @@ local function is_directive(name) end ---@private ----@param match vim.treesitter.query.TSMatch ----@param pattern integer +---@param match TSQueryMatch ---@param source integer|string -function Query:match_preds(match, pattern, source) +function Query:match_preds(match, source) + local _, pattern = match:info() local preds = self.info.patterns[pattern] - for _, pred in pairs(preds or {}) do + if not preds then + return true + end + + local captures = match:captures() + + for _, pred in pairs(preds) do -- Here we only want to return if a predicate DOES NOT match, and -- continue on the other case. This way unknown predicates will not be considered, -- which allows some testing and easier user extensibility (#12173). @@ -759,7 +755,7 @@ function Query:match_preds(match, pattern, source) return false end - local pred_matches = handler(match, pattern, source, pred) + local pred_matches = handler(captures, pattern, source, pred) if not xor(is_not, pred_matches) then return false @@ -770,30 +766,40 @@ function Query:match_preds(match, pattern, source) end ---@private ----@param match vim.treesitter.query.TSMatch ----@param metadata vim.treesitter.query.TSMetadata -function Query:apply_directives(match, pattern, source, metadata) +---@param match TSQueryMatch +---@return vim.treesitter.query.TSMetadata metadata +function Query:apply_directives(match, source) + ---@type vim.treesitter.query.TSMetadata + local metadata = {} + local _, pattern = match:info() local preds = self.info.patterns[pattern] - for _, pred in pairs(preds or {}) do + if not preds then + return metadata + end + + local captures = match:captures() + + for _, pred in pairs(preds) do if is_directive(pred[1]) then local handler = directive_handlers[pred[1]] if not handler then error(string.format('No handler for %s', pred[1])) - return end - handler(match, pattern, source, pred, metadata) + handler(captures, pattern, source, pred, metadata) end end + + return metadata end --- Returns the start and stop value if set else the node's range. -- When the node's range is used, the stop is incremented by 1 -- to make the search inclusive. ----@param start integer|nil ----@param stop integer|nil +---@param start integer? +---@param stop integer? ---@param node TSNode ---@return integer, integer local function value_or_node_range(start, stop, node) @@ -807,6 +813,12 @@ local function value_or_node_range(start, stop, node) return start, stop end +--- @param match TSQueryMatch +--- @return integer +local function match_id_hash(_, match) + return (match:info()) +end + --- Iterate over all captures from all matches inside {node} --- --- {source} is needed if the query contains predicates; then the caller @@ -816,12 +828,13 @@ end --- as the {node}, i.e., to get syntax highlight matches in the current --- viewport). When omitted, the {start} and {stop} row values are used from the given node. --- ---- The iterator returns three values: a numeric id identifying the capture, ---- the captured node, and metadata from any directives processing the match. +--- The iterator returns four values: a numeric id identifying the capture, +--- the captured node, metadata from any directives processing the match, +--- and the match itself. --- The following example shows how to get captures by name: --- --- ```lua ---- for id, node, metadata in query:iter_captures(tree:root(), bufnr, first, last) do +--- for id, node, metadata, match in query:iter_captures(tree:root(), bufnr, first, last) do --- local name = query.captures[id] -- name of the capture in the query --- -- typically useful info about the node: --- local type = node:type() -- type of the captured node @@ -835,8 +848,10 @@ end ---@param start? integer Starting line for the search. Defaults to `node:start()`. ---@param stop? integer Stopping line for the search (end-exclusive). Defaults to `node:end_()`. --- ----@return (fun(end_line: integer|nil): integer, TSNode, vim.treesitter.query.TSMetadata): ---- capture id, capture node, metadata +---@return (fun(end_line: integer|nil): integer, TSNode, vim.treesitter.query.TSMetadata, TSQueryMatch): +--- capture id, capture node, metadata, match +--- +---@note Captures are only returned if the query pattern of a specific capture contained predicates. function Query:iter_captures(node, source, start, stop) if type(source) == 'number' and source == 0 then source = api.nvim_get_current_buf() @@ -844,24 +859,30 @@ function Query:iter_captures(node, source, start, stop) start, stop = value_or_node_range(start, stop, node) - local raw_iter = node:_rawquery(self.query, true, start, stop) ---@type fun(): integer, TSNode, vim.treesitter.query.TSMatch + local cursor = vim._create_ts_querycursor(node, self.query, start, stop, { match_limit = 256 }) + + local apply_directives = memoize(match_id_hash, self.apply_directives, true) + local match_preds = memoize(match_id_hash, self.match_preds, true) + local function iter(end_line) - local capture, captured_node, match = raw_iter() - local metadata = {} - - if match ~= nil then - local active = self:match_preds(match, match.pattern, source) - match.active = active - if not active then - if end_line and captured_node:range() > end_line then - return nil, captured_node, nil - end - return iter(end_line) -- tail call: try next match - end + local capture, captured_node, match = cursor:next_capture() - self:apply_directives(match, match.pattern, source, metadata) + if not capture then + return end - return capture, captured_node, metadata + + if not match_preds(self, match, source) then + local match_id = match:info() + cursor:remove_match(match_id) + if end_line and captured_node:range() > end_line then + return nil, captured_node, nil, nil + end + return iter(end_line) -- tail call: try next match + end + + local metadata = apply_directives(self, match, source) + + return capture, captured_node, metadata, match end return iter end @@ -903,45 +924,55 @@ end ---@param opts? table Optional keyword arguments: --- - max_start_depth (integer) if non-zero, sets the maximum start depth --- for each match. This is used to prevent traversing too deep into a tree. +--- - match_limit (integer) Set the maximum number of in-progress matches (Default: 256). --- - all (boolean) When set, the returned match table maps capture IDs to a list of nodes. --- Older versions of iter_matches incorrectly mapped capture IDs to a single node, which is --- incorrect behavior. This option will eventually become the default and removed. --- ---@return (fun(): integer, table<integer, TSNode[]>, table): pattern id, match, metadata function Query:iter_matches(node, source, start, stop, opts) - local all = opts and opts.all + opts = opts or {} + opts.match_limit = opts.match_limit or 256 + if type(source) == 'number' and source == 0 then source = api.nvim_get_current_buf() end start, stop = value_or_node_range(start, stop, node) - local raw_iter = node:_rawquery(self.query, false, start, stop, opts) ---@type fun(): integer, vim.treesitter.query.TSMatch + local cursor = vim._create_ts_querycursor(node, self.query, start, stop, opts) + local function iter() - local pattern, match = raw_iter() - local metadata = {} + local match = cursor:next_match() - if match ~= nil then - local active = self:match_preds(match, pattern, source) - if not active then - return iter() -- tail call: try next match - end + if not match then + return + end - self:apply_directives(match, pattern, source, metadata) + local match_id, pattern = match:info() + + if not self:match_preds(match, source) then + cursor:remove_match(match_id) + return iter() -- tail call: try next match end - if not all then + local metadata = self:apply_directives(match, source) + + local captures = match:captures() + + if not opts.all then -- Convert the match table into the old buggy version for backward -- compatibility. This is slow. Plugin authors, if you're reading this, set the "all" -- option! local old_match = {} ---@type table<integer, TSNode> - for k, v in pairs(match or {}) do + for k, v in pairs(captures or {}) do old_match[k] = v[#v] end return pattern, old_match, metadata end - return pattern, match, metadata + -- TODO(lewis6991): create a new function that returns {match, metadata} + return pattern, captures, metadata end return iter end diff --git a/runtime/lua/vim/ui.lua b/runtime/lua/vim/ui.lua index b0e7ca1a35..99b9b78e2a 100644 --- a/runtime/lua/vim/ui.lua +++ b/runtime/lua/vim/ui.lua @@ -114,15 +114,20 @@ end --- Examples: --- --- ```lua +--- -- Asynchronous. --- vim.ui.open("https://neovim.io/") --- vim.ui.open("~/path/to/file") ---- vim.ui.open("$VIMRUNTIME") +--- -- Synchronous (wait until the process exits). +--- local cmd, err = vim.ui.open("$VIMRUNTIME") +--- if cmd then +--- cmd:wait() +--- end --- ``` --- ---@param path string Path or URL to open --- ----@return vim.SystemCompleted|nil # Command result, or nil if not found. ----@return string|nil # Error message on failure +---@return vim.SystemObj|nil # Command object, or nil if not found. +---@return nil|string # Error message on failure, or nil on success. --- ---@see |vim.system()| function M.open(path) @@ -144,21 +149,37 @@ function M.open(path) else return nil, 'vim.ui.open: rundll32 not found' end + elseif vim.fn.executable('wslview') == 1 then + cmd = { 'wslview', path } elseif vim.fn.executable('explorer.exe') == 1 then cmd = { 'explorer.exe', path } elseif vim.fn.executable('xdg-open') == 1 then cmd = { 'xdg-open', path } else - return nil, 'vim.ui.open: no handler found (tried: explorer.exe, xdg-open)' + return nil, 'vim.ui.open: no handler found (tried: wslview, explorer.exe, xdg-open)' end - local rv = vim.system(cmd, { text = true, detach = true }):wait() - if rv.code ~= 0 then - local msg = ('vim.ui.open: command failed (%d): %s'):format(rv.code, vim.inspect(cmd)) - return rv, msg - end + return vim.system(cmd, { text = true, detach = true }), nil +end - return rv, nil +--- Gets the URL at cursor, if any. +function M._get_url() + if vim.bo.filetype == 'markdown' then + local range = vim.api.nvim_win_get_cursor(0) + vim.treesitter.get_parser():parse(range) + -- marking the node as `markdown_inline` is required. Setting it to `markdown` does not + -- work. + local current_node = vim.treesitter.get_node { lang = 'markdown_inline' } + while current_node do + local type = current_node:type() + if type == 'inline_link' or type == 'image' then + local child = assert(current_node:named_child(1)) + return vim.treesitter.get_node_text(child, 0) + end + current_node = current_node:parent() + end + end + return vim.fn.expand('<cfile>') end return M diff --git a/runtime/mswin.vim b/runtime/mswin.vim index 107a2acc2e..689bc792cf 100644 --- a/runtime/mswin.vim +++ b/runtime/mswin.vim @@ -1,7 +1,7 @@ " Set options and add mapping such that Vim behaves a lot like MS-Windows " " Maintainer: The Vim Project <https://github.com/vim/vim> -" Last Change: 2024 Mar 3 +" Last Change: 2024 Mar 13 " Former Maintainer: Bram Moolenaar <Bram@vim.org> " Bail out if this isn't wanted. @@ -27,7 +27,10 @@ set backspace=indent,eol,start whichwrap+=<,>,[,] " backspace in Visual mode deletes selection vnoremap <BS> d -if has("clipboard_working") +" the better solution would be to use has("clipboard_working"), +" but that may not be available yet while starting up, so let's just check if +" clipboard support has been compiled in and assume it will be working :/ +if has("clipboard") " CTRL-X and SHIFT-Del are Cut vnoremap <C-X> "+x vnoremap <S-Del> "+x @@ -43,7 +46,7 @@ if has("clipboard_working") cmap <C-V> <C-R>+ cmap <S-Insert> <C-R>+ else - " Use unnamed register while clipboard not exist + " Use the unnamed register when clipboard support not available " CTRL-X and SHIFT-Del are Cut vnoremap <C-X> x @@ -67,7 +70,7 @@ endif " Uses the paste.vim autoload script. " Use CTRL-G u to have CTRL-Z only undo the paste. -if has("clipboard_working") +if has("clipboard") exe 'inoremap <script> <C-V> <C-G>u' . paste#paste_cmd['i'] exe 'vnoremap <script> <C-V> ' . paste#paste_cmd['v'] endif diff --git a/runtime/nvim.appdata.xml b/runtime/nvim.appdata.xml index bff8bc4bff..517b8b20fe 100644 --- a/runtime/nvim.appdata.xml +++ b/runtime/nvim.appdata.xml @@ -26,6 +26,11 @@ </screenshots> <releases> + <release date="2024-05-16" version="0.10.0"/> + <release date="2023-12-30" version="0.9.5"/> + <release date="2023-10-09" version="0.9.4"/> + <release date="2023-09-07" version="0.9.2"/> + <release date="2023-05-29" version="0.9.1"/> <release date="2023-04-07" version="0.9.0"/> <release date="2023-02-02" version="0.8.3"/> <release date="2022-12-29" version="0.8.2"/> diff --git a/runtime/optwin.vim b/runtime/optwin.vim index fc60f70335..5b5b33e4ad 100644 --- a/runtime/optwin.vim +++ b/runtime/optwin.vim @@ -444,6 +444,7 @@ if has("statusline") call <SID>AddOption("statusline", gettext("alternate format to be used for a status line")) call <SID>OptionG("stl", &stl) endif +call append("$", "\t" .. s:local_to_window) call <SID>AddOption("equalalways", gettext("make all windows the same size when adding/removing windows")) call <SID>BinOptionG("ea", &ea) call <SID>AddOption("eadirection", gettext("in which direction 'equalalways' works: \"ver\", \"hor\" or \"both\"")) @@ -452,6 +453,8 @@ call <SID>AddOption("winheight", gettext("minimal number of lines used for the c call append("$", " \tset wh=" . &wh) call <SID>AddOption("winminheight", gettext("minimal number of lines used for any window")) call append("$", " \tset wmh=" . &wmh) +call <SID>AddOption("winfixbuf", gettext("keep window focused on a single buffer")) +call <SID>OptionG("wfb", &wfb) call <SID>AddOption("winfixheight", gettext("keep the height of the window")) call append("$", "\t" .. s:local_to_window) call <SID>BinOptionL("wfh") diff --git a/runtime/pack/dist/opt/matchit/autoload/matchit.vim b/runtime/pack/dist/opt/matchit/autoload/matchit.vim index dc2aba696d..aa977488e5 100644 --- a/runtime/pack/dist/opt/matchit/autoload/matchit.vim +++ b/runtime/pack/dist/opt/matchit/autoload/matchit.vim @@ -1,6 +1,6 @@ " matchit.vim: (global plugin) Extended "%" matching " autload script of matchit plugin, see ../plugin/matchit.vim -" Last Change: Jan 24, 2022 +" Last Change: May 20, 2024 " Neovim does not support scriptversion if has("vimscript-4") @@ -87,9 +87,9 @@ function matchit#Match_wrapper(word, forward, mode) range let s:last_mps = &mps " quote the special chars in 'matchpairs', replace [,:] with \| and then " append the builtin pairs (/*, */, #if, #ifdef, #ifndef, #else, #elif, - " #endif) + " #elifdef, #elifndef, #endif) let default = escape(&mps, '[$^.*~\\/?]') .. (strlen(&mps) ? "," : "") .. - \ '\/\*:\*\/,#\s*if\%(n\=def\)\=:#\s*else\>:#\s*elif\>:#\s*endif\>' + \ '\/\*:\*\/,#\s*if\%(n\=def\)\=:#\s*else\>:#\s*elif\%(n\=def\)\=\>:#\s*endif\>' " s:all = pattern with all the keywords let match_words = match_words .. (strlen(match_words) ? "," : "") .. default let s:last_words = match_words @@ -101,6 +101,8 @@ function matchit#Match_wrapper(word, forward, mode) range let s:pat = s:ParseWords(match_words) endif let s:all = substitute(s:pat, s:notslash .. '\zs[,:]\+', '\\|', 'g') + " un-escape \, to , + let s:all = substitute(s:all, '\\,', ',', 'g') " Just in case there are too many '\(...)' groups inside the pattern, make " sure to use \%(...) groups, so that error E872 can be avoided let s:all = substitute(s:all, '\\(', '\\%(', 'g') @@ -112,6 +114,8 @@ function matchit#Match_wrapper(word, forward, mode) range let s:patBR = substitute(match_words .. ',', \ s:notslash .. '\zs[,:]*,[,:]*', ',', 'g') let s:patBR = substitute(s:patBR, s:notslash .. '\zs:\{2,}', ':', 'g') + " un-escape \, to , + let s:patBR = substitute(s:patBR, '\\,', ',', 'g') endif " Second step: set the following local variables: @@ -534,6 +538,8 @@ fun! s:Choose(patterns, string, comma, branch, prefix, suffix, ...) else let currpat = substitute(current, s:notslash .. a:branch, '\\|', 'g') endif + " un-escape \, to , + let currpat = substitute(currpat, '\\,', ',', 'g') while a:string !~ a:prefix .. currpat .. a:suffix let tail = strpart(tail, i) let i = matchend(tail, s:notslash .. a:comma) diff --git a/runtime/pack/dist/opt/matchit/doc/matchit.txt b/runtime/pack/dist/opt/matchit/doc/matchit.txt index 88d0c38e4d..8d56df6ddc 100644 --- a/runtime/pack/dist/opt/matchit/doc/matchit.txt +++ b/runtime/pack/dist/opt/matchit/doc/matchit.txt @@ -4,7 +4,7 @@ For instructions on installing this file, type `:help matchit-install` inside Vim. -For Vim version 9.0. Last change: 2023 June 28 +For Vim version 9.1. Last change: 2024 May 20 VIM REFERENCE MANUAL by Benji Fisher et al @@ -176,8 +176,8 @@ defined automatically. 2.1 Temporarily disable the matchit plugin *matchit-disable* *:MatchDisable* -To temporarily reset the plugins, that are setup you can run the following -command: > +To temporarily disable the matchit plugin, after it hat been loaded, +execute this command: > :MatchDisable This will delete all the defined key mappings to the Vim default. diff --git a/runtime/pack/dist/opt/matchit/plugin/matchit.vim b/runtime/pack/dist/opt/matchit/plugin/matchit.vim index d6c735d7b4..08fee09642 100644 --- a/runtime/pack/dist/opt/matchit/plugin/matchit.vim +++ b/runtime/pack/dist/opt/matchit/plugin/matchit.vim @@ -1,7 +1,7 @@ " matchit.vim: (global plugin) Extended "%" matching " Maintainer: Christian Brabandt -" Version: 1.19 -" Last Change: 2023, June 28th +" Version: 1.20 +" Last Change: 2024 May 20 " Repository: https://github.com/chrisbra/matchit " Previous URL:http://www.vim.org/script.php?script_id=39 " Previous Maintainer: Benji Fisher PhD <benji@member.AMS.org> diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim index a253acc63f..f78a082cb7 100644 --- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim +++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim @@ -427,7 +427,17 @@ func s:StartDebug_prompt(dict) let s:promptbuf = bufnr('') call prompt_setprompt(s:promptbuf, 'gdb> ') set buftype=prompt - file gdb + + if empty(glob('gdb')) + file gdb + elseif empty(glob('Termdebug-gdb-console')) + file Termdebug-gdb-console + else + call s:Echoerr("You have a file/folder named 'gdb' + \ or 'Termdebug-gdb-console'. + \ Please exit and rename them because Termdebug may not work as expected.") + endif + call prompt_setcallback(s:promptbuf, function('s:PromptCallback')) call prompt_setinterrupt(s:promptbuf, function('s:PromptInterrupt')) @@ -1481,9 +1491,12 @@ func s:GotoAsmwinOrCreateIt() if s:asmbuf > 0 && bufexists(s:asmbuf) exe 'buffer' . s:asmbuf - else + elseif empty(glob('Termdebug-asm-listing')) silent file Termdebug-asm-listing let s:asmbuf = bufnr('Termdebug-asm-listing') + else + call s:Echoerr("You have a file/folder named 'Termdebug-asm-listing'. + \ Please exit and rename it because Termdebug may not work as expected.") endif if mdf != 'vert' && s:GetDisasmWindowHeight() > 0 @@ -1550,9 +1563,12 @@ func s:GotoVariableswinOrCreateIt() if s:varbuf > 0 && bufexists(s:varbuf) exe 'buffer' . s:varbuf - else + elseif empty(glob('Termdebug-variables-listing')) silent file Termdebug-variables-listing let s:varbuf = bufnr('Termdebug-variables-listing') + else + call s:Echoerr("You have a file/folder named 'Termdebug-variables-listing'. + \ Please exit and rename it because Termdebug may not work as expected.") endif if mdf != 'vert' && s:GetVariablesWindowHeight() > 0 @@ -1679,7 +1695,7 @@ func s:CreateBreakpoint(id, subid, enabled) endif endif call sign_define('debugBreakpoint' .. nr, - \ #{text: strpart(label, 0, 2), + \ #{text: slice(label, 0, 2), \ texthl: hiName}) endif endfunc diff --git a/runtime/plugin/matchparen.vim b/runtime/plugin/matchparen.vim index 4235a0d39b..6c061c9fb8 100644 --- a/runtime/plugin/matchparen.vim +++ b/runtime/plugin/matchparen.vim @@ -1,6 +1,6 @@ " Vim plugin for showing matching parens " Maintainer: The Vim Project <https://github.com/vim/vim> -" Last Change: 2023 Oct 20 +" Last Change: 2024 May 18 " Former Maintainer: Bram Moolenaar <Bram@vim.org> " Exit quickly when: @@ -22,7 +22,8 @@ let s:has_matchaddpos = exists('*matchaddpos') augroup matchparen " Replace all matchparen autocommands - autocmd! CursorMoved,CursorMovedI,WinEnter,BufWinEnter,WinScrolled * call s:Highlight_Matching_Pair() + autocmd! CursorMoved,CursorMovedI,WinEnter,WinScrolled * call s:Highlight_Matching_Pair() + autocmd! BufWinEnter * autocmd SafeState * ++once call s:Highlight_Matching_Pair() autocmd! WinLeave,BufLeave * call s:Remove_Matches() if exists('##TextChanged') autocmd! TextChanged,TextChangedI * call s:Highlight_Matching_Pair() @@ -217,7 +218,7 @@ command NoMatchParen call s:NoMatchParen() func s:NoMatchParen() let w = winnr() - noau windo silent! call matchdelete(3) + noau windo call s:Remove_Matches() unlet! g:loaded_matchparen exe "noau ". w . "wincmd w" au! matchparen diff --git a/runtime/plugin/netrwPlugin.vim b/runtime/plugin/netrwPlugin.vim index ed6f7dc008..c70e6518ff 100644 --- a/runtime/plugin/netrwPlugin.vim +++ b/runtime/plugin/netrwPlugin.vim @@ -2,6 +2,8 @@ " PLUGIN SECTION " Maintainer: This runtime file is looking for a new maintainer. " Date: Feb 09, 2021 +" Last Change: +" 2024 May 08 by Vim Project: cleanup legacy Win9X checks " Former Maintainer: Charles E Campbell " GetLatestVimScripts: 1075 1 :AutoInstall: netrw.vim " Copyright: Copyright (C) 1999-2021 Charles E. Campbell {{{1 @@ -35,7 +37,7 @@ augroup FileExplorer au BufLeave * if &ft != "netrw"|let w:netrw_prvfile= expand("%:p")|endif au BufEnter * sil call s:LocalBrowse(expand("<amatch>")) au VimEnter * sil call s:VimEnter(expand("<amatch>")) - if has("win32") || has("win95") || has("win64") || has("win16") + if has("win32") au BufEnter .* sil call s:LocalBrowse(expand("<amatch>")) endif augroup END diff --git a/runtime/plugin/nvim.lua b/runtime/plugin/nvim.lua deleted file mode 100644 index 743d3044b6..0000000000 --- a/runtime/plugin/nvim.lua +++ /dev/null @@ -1,24 +0,0 @@ -vim.api.nvim_create_user_command('Inspect', function(cmd) - if cmd.bang then - vim.print(vim.inspect_pos()) - else - vim.show_pos() - end -end, { desc = 'Inspect highlights and extmarks at the cursor', bang = true }) - -vim.api.nvim_create_user_command('InspectTree', function(cmd) - if cmd.mods ~= '' or cmd.count ~= 0 then - local count = cmd.count ~= 0 and cmd.count or '' - local new = cmd.mods ~= '' and 'new' or 'vnew' - - vim.treesitter.inspect_tree({ - command = ('%s %s%s'):format(cmd.mods, count, new), - }) - else - vim.treesitter.inspect_tree() - end -end, { desc = 'Inspect treesitter language tree for buffer', count = true }) - -vim.api.nvim_create_user_command('EditQuery', function(cmd) - vim.treesitter.query.edit(cmd.fargs[1]) -end, { desc = 'Edit treesitter query', nargs = '?' }) diff --git a/runtime/queries/bash/highlights.scm b/runtime/queries/bash/highlights.scm index b4360ce7e1..feb0e038ea 100644 --- a/runtime/queries/bash/highlights.scm +++ b/runtime/queries/bash/highlights.scm @@ -68,10 +68,6 @@ argument: "$" @string) ; bare dollar (concatenation - [ - (simple_expansion) - (expansion) - ] (word) @string) [ @@ -110,7 +106,15 @@ ; trap -l ((word) @constant.builtin - (#match? @constant.builtin "^SIG(HUP|INT|QUIT|ILL|TRAP|ABRT|BUS|FPE|KILL|USR[12]|SEGV|PIPE|ALRM|TERM|STKFLT|CHLD|CONT|STOP|TSTP|TT(IN|OU)|URG|XCPU|XFSZ|VTALRM|PROF|WINCH|IO|PWR|SYS|RTMIN([+]([1-9]|1[0-5]))?|RTMAX(-([1-9]|1[0-4]))?)$")) + (#any-of? @constant.builtin + "SIGHUP" "SIGINT" "SIGQUIT" "SIGILL" "SIGTRAP" "SIGABRT" "SIGBUS" "SIGFPE" "SIGKILL" "SIGUSR1" + "SIGSEGV" "SIGUSR2" "SIGPIPE" "SIGALRM" "SIGTERM" "SIGSTKFLT" "SIGCHLD" "SIGCONT" "SIGSTOP" + "SIGTSTP" "SIGTTIN" "SIGTTOU" "SIGURG" "SIGXCPU" "SIGXFSZ" "SIGVTALRM" "SIGPROF" "SIGWINCH" + "SIGIO" "SIGPWR" "SIGSYS" "SIGRTMIN" "SIGRTMIN+1" "SIGRTMIN+2" "SIGRTMIN+3" "SIGRTMIN+4" + "SIGRTMIN+5" "SIGRTMIN+6" "SIGRTMIN+7" "SIGRTMIN+8" "SIGRTMIN+9" "SIGRTMIN+10" "SIGRTMIN+11" + "SIGRTMIN+12" "SIGRTMIN+13" "SIGRTMIN+14" "SIGRTMIN+15" "SIGRTMAX-14" "SIGRTMAX-13" + "SIGRTMAX-12" "SIGRTMAX-11" "SIGRTMAX-10" "SIGRTMAX-9" "SIGRTMAX-8" "SIGRTMAX-7" "SIGRTMAX-6" + "SIGRTMAX-5" "SIGRTMAX-4" "SIGRTMAX-3" "SIGRTMAX-2" "SIGRTMAX-1" "SIGRTMAX")) ((word) @boolean (#any-of? @boolean "true" "false")) @@ -120,10 +124,15 @@ (test_operator) @operator (command_substitution - "$(" @punctuation.bracket) + "$(" @punctuation.special + ")" @punctuation.special) (process_substitution - "<(" @punctuation.bracket) + [ + "<(" + ">(" + ] @punctuation.special + ")" @punctuation.special) (arithmetic_expansion [ @@ -156,27 +165,21 @@ (command_name (word) @function.call) -((command_name - (word) @function.builtin) - ; format-ignore +(command_name + (word) @function.builtin (#any-of? @function.builtin - "alias" "bg" "bind" "break" "builtin" "caller" "cd" - "command" "compgen" "complete" "compopt" "continue" - "coproc" "dirs" "disown" "echo" "enable" "eval" - "exec" "exit" "fc" "fg" "getopts" "hash" "help" - "history" "jobs" "kill" "let" "logout" "mapfile" - "popd" "printf" "pushd" "pwd" "read" "readarray" - "return" "set" "shift" "shopt" "source" "suspend" - "test" "time" "times" "trap" "type" "typeset" - "ulimit" "umask" "unalias" "wait")) + "alias" "bg" "bind" "break" "builtin" "caller" "cd" "command" "compgen" "complete" "compopt" + "continue" "coproc" "dirs" "disown" "echo" "enable" "eval" "exec" "exit" "fc" "fg" "getopts" + "hash" "help" "history" "jobs" "kill" "let" "logout" "mapfile" "popd" "printf" "pushd" "pwd" + "read" "readarray" "return" "set" "shift" "shopt" "source" "suspend" "test" "time" "times" + "trap" "type" "typeset" "ulimit" "umask" "unalias" "wait")) (command - argument: - [ - (word) @variable.parameter - (concatenation - (word) @variable.parameter) - ]) + argument: [ + (word) @variable.parameter + (concatenation + (word) @variable.parameter) + ]) (number) @number @@ -225,5 +228,5 @@ ((program . - (comment) @keyword.directive) + (comment) @keyword.directive @nospell) (#lua-match? @keyword.directive "^#!/")) diff --git a/runtime/queries/bash/injections.scm b/runtime/queries/bash/injections.scm new file mode 100644 index 0000000000..427b414958 --- /dev/null +++ b/runtime/queries/bash/injections.scm @@ -0,0 +1,3 @@ +(heredoc_redirect + (heredoc_body) @injection.content + (heredoc_end) @injection.language) diff --git a/runtime/queries/c/folds.scm b/runtime/queries/c/folds.scm index 2e2a6b4d0c..bb26a62eb5 100644 --- a/runtime/queries/c/folds.scm +++ b/runtime/queries/c/folds.scm @@ -16,6 +16,7 @@ (preproc_function_def) (initializer_list) (gnu_asm_expression) + (preproc_include)+ ] @fold (compound_statement diff --git a/runtime/queries/c/highlights.scm b/runtime/queries/c/highlights.scm index c848f68dca..170937c8f8 100644 --- a/runtime/queries/c/highlights.scm +++ b/runtime/queries/c/highlights.scm @@ -7,16 +7,19 @@ [ "default" - "enum" - "struct" - "typedef" - "union" "goto" "asm" "__asm__" ] @keyword [ + "enum" + "struct" + "union" + "typedef" +] @keyword.type + +[ "sizeof" "offsetof" ] @keyword.operator @@ -142,9 +145,6 @@ (char_literal) @character -((preproc_arg) @function.macro - (#set! "priority" 90)) - (preproc_defined) @function.macro ((field_expression @@ -159,21 +159,26 @@ (statement_identifier) @label +(declaration + type: (type_identifier) @_type + declarator: (identifier) @label + (#eq? @_type "__label__")) + [ (type_identifier) (type_descriptor) ] @type -(storage_class_specifier) @keyword.storage +(storage_class_specifier) @keyword.modifier [ (type_qualifier) (gnu_asm_qualifier) "__extension__" -] @type.qualifier +] @keyword.modifier (linkage_specification - "extern" @keyword.storage) + "extern" @keyword.modifier) (type_definition declarator: (type_identifier) @type.definition) @@ -232,10 +237,10 @@ (argument_list (identifier) @variable.builtin)) -((attribute_specifier +(attribute_specifier (argument_list (call_expression - function: (identifier) @variable.builtin)))) + function: (identifier) @variable.builtin))) ((call_expression function: (identifier) @function.builtin) @@ -258,18 +263,16 @@ function: (identifier) @function.call) (call_expression - function: - (field_expression - field: (field_identifier) @function.call)) + function: (field_expression + field: (field_identifier) @function.call)) (function_declarator declarator: (identifier) @function) (function_declarator - declarator: - (parenthesized_declarator - (pointer_declarator - declarator: (field_identifier) @function))) + declarator: (parenthesized_declarator + (pointer_declarator + declarator: (field_identifier) @function))) (preproc_function_def name: (identifier) @function.macro) diff --git a/runtime/queries/lua/highlights.scm b/runtime/queries/lua/highlights.scm index 0b0bf35a8b..0c8f07f290 100644 --- a/runtime/queries/lua/highlights.scm +++ b/runtime/queries/lua/highlights.scm @@ -180,27 +180,24 @@ (vararg_expression) @variable.parameter.builtin (function_declaration - name: - [ - (identifier) @function - (dot_index_expression - field: (identifier) @function) - ]) + name: [ + (identifier) @function + (dot_index_expression + field: (identifier) @function) + ]) (function_declaration - name: - (method_index_expression - method: (identifier) @function.method)) + name: (method_index_expression + method: (identifier) @function.method)) (assignment_statement (variable_list . - name: - [ - (identifier) @function - (dot_index_expression - field: (identifier) @function) - ]) + name: [ + (identifier) @function + (dot_index_expression + field: (identifier) @function) + ]) (expression_list . value: (function_definition))) @@ -211,27 +208,24 @@ value: (function_definition))) (function_call - name: - [ - (identifier) @function.call - (dot_index_expression - field: (identifier) @function.call) - (method_index_expression - method: (identifier) @function.method.call) - ]) + name: [ + (identifier) @function.call + (dot_index_expression + field: (identifier) @function.call) + (method_index_expression + method: (identifier) @function.method.call) + ]) (function_call (identifier) @function.builtin - ; format-ignore (#any-of? @function.builtin ; built-in functions in Lua 5.1 - "assert" "collectgarbage" "dofile" "error" "getfenv" "getmetatable" "ipairs" - "load" "loadfile" "loadstring" "module" "next" "pairs" "pcall" "print" - "rawequal" "rawget" "rawlen" "rawset" "require" "select" "setfenv" "setmetatable" - "tonumber" "tostring" "type" "unpack" "xpcall" - "__add" "__band" "__bnot" "__bor" "__bxor" "__call" "__concat" "__div" "__eq" "__gc" - "__idiv" "__index" "__le" "__len" "__lt" "__metatable" "__mod" "__mul" "__name" "__newindex" - "__pairs" "__pow" "__shl" "__shr" "__sub" "__tostring" "__unm")) + "assert" "collectgarbage" "dofile" "error" "getfenv" "getmetatable" "ipairs" "load" "loadfile" + "loadstring" "module" "next" "pairs" "pcall" "print" "rawequal" "rawget" "rawlen" "rawset" + "require" "select" "setfenv" "setmetatable" "tonumber" "tostring" "type" "unpack" "xpcall" + "__add" "__band" "__bnot" "__bor" "__bxor" "__call" "__concat" "__div" "__eq" "__gc" "__idiv" + "__index" "__le" "__len" "__lt" "__metatable" "__mod" "__mul" "__name" "__newindex" "__pairs" + "__pow" "__shl" "__shr" "__sub" "__tostring" "__unm")) ; Others (comment) @comment @spell @@ -255,21 +249,19 @@ (dot_index_expression field: (identifier) @_method (#any-of? @_method "find" "match" "gmatch" "gsub")) - arguments: - (arguments - . - (_) - . - (string - content: (string_content) @string.regexp))) + arguments: (arguments + . + (_) + . + (string + content: (string_content) @string.regexp))) ;("123"):match("%d+") (function_call (method_index_expression method: (identifier) @_method (#any-of? @_method "find" "match" "gmatch" "gsub")) - arguments: - (arguments - . - (string - content: (string_content) @string.regexp))) + arguments: (arguments + . + (string + content: (string_content) @string.regexp))) diff --git a/runtime/queries/lua/injections.scm b/runtime/queries/lua/injections.scm index c8a1843c84..4345c71ce8 100644 --- a/runtime/queries/lua/injections.scm +++ b/runtime/queries/lua/injections.scm @@ -1,66 +1,69 @@ ((function_call - name: - [ - (identifier) @_cdef_identifier - (_ - _ - (identifier) @_cdef_identifier) - ] - arguments: - (arguments - (string - content: _ @injection.content))) + name: [ + (identifier) @_cdef_identifier + (_ + _ + (identifier) @_cdef_identifier) + ] + arguments: (arguments + (string + content: _ @injection.content))) (#set! injection.language "c") (#eq? @_cdef_identifier "cdef")) ((function_call name: (_) @_vimcmd_identifier - arguments: - (arguments - (string - content: _ @injection.content))) + arguments: (arguments + (string + content: _ @injection.content))) (#set! injection.language "vim") - (#any-of? @_vimcmd_identifier "vim.cmd" "vim.api.nvim_command" "vim.api.nvim_command" "vim.api.nvim_exec2")) + (#any-of? @_vimcmd_identifier + "vim.cmd" "vim.api.nvim_command" "vim.api.nvim_command" "vim.api.nvim_exec2")) ((function_call name: (_) @_vimcmd_identifier - arguments: - (arguments - (string - content: _ @injection.content) .)) + arguments: (arguments + (string + content: _ @injection.content) .)) (#set! injection.language "query") (#any-of? @_vimcmd_identifier "vim.treesitter.query.set" "vim.treesitter.query.parse")) ((function_call name: (_) @_vimcmd_identifier - arguments: - (arguments - . - (_) - . - (string - content: _ @_method) - . - (string - content: _ @injection.content))) + arguments: (arguments + . + (_) + . + (string + content: _ @_method) + . + (string + content: _ @injection.content))) (#any-of? @_vimcmd_identifier "vim.rpcrequest" "vim.rpcnotify") (#eq? @_method "nvim_exec_lua") (#set! injection.language "lua")) +; exec_lua [[ ... ]] in functionaltests +((function_call + name: (identifier) @_function + arguments: (arguments + (string + content: (string_content) @injection.content))) + (#eq? @_function "exec_lua") + (#set! injection.language "lua")) + ; vim.api.nvim_create_autocmd("FileType", { command = "injected here" }) (function_call name: (_) @_vimcmd_identifier - arguments: - (arguments - . - (_) - . - (table_constructor - (field - name: (identifier) @_command - value: - (string - content: (_) @injection.content))) .) + arguments: (arguments + . + (_) + . + (table_constructor + (field + name: (identifier) @_command + value: (string + content: (_) @injection.content))) .) ; limit so only 2-argument functions gets matched before pred handle (#eq? @_vimcmd_identifier "vim.api.nvim_create_autocmd") (#eq? @_command "command") @@ -68,31 +71,29 @@ (function_call name: (_) @_user_cmd - arguments: - (arguments - . - (_) - . - (string - content: (_) @injection.content) - . - (_) .) + arguments: (arguments + . + (_) + . + (string + content: (_) @injection.content) + . + (_) .) (#eq? @_user_cmd "vim.api.nvim_create_user_command") (#set! injection.language "vim")) (function_call name: (_) @_user_cmd - arguments: - (arguments - . - (_) - . - (_) - . - (string - content: (_) @injection.content) - . - (_) .) + arguments: (arguments + . + (_) + . + (_) + . + (string + content: (_) @injection.content) + . + (_) .) ; Limiting predicate handling to only functions with 4 arguments (#eq? @_user_cmd "vim.api.nvim_buf_create_user_command") (#set! injection.language "vim")) diff --git a/runtime/queries/markdown/highlights.scm b/runtime/queries/markdown/highlights.scm index 7c26fd710c..4b445e02f3 100644 --- a/runtime/queries/markdown/highlights.scm +++ b/runtime/queries/markdown/highlights.scm @@ -1,34 +1,34 @@ ;From MDeiml/tree-sitter-markdown & Helix (setext_heading (paragraph) @markup.heading.1 - (setext_h1_underline) @markup.heading.1.marker) + (setext_h1_underline) @markup.heading.1) (setext_heading (paragraph) @markup.heading.2 - (setext_h2_underline) @markup.heading.2.marker) + (setext_h2_underline) @markup.heading.2) (atx_heading - (atx_h1_marker) @markup.heading.1.marker + (atx_h1_marker) @markup.heading.1 (inline) @markup.heading.1) (atx_heading - (atx_h2_marker) @markup.heading.2.marker + (atx_h2_marker) @markup.heading.2 (inline) @markup.heading.2) (atx_heading - (atx_h3_marker) @markup.heading.3.marker + (atx_h3_marker) @markup.heading.3 (inline) @markup.heading.3) (atx_heading - (atx_h4_marker) @markup.heading.4.marker + (atx_h4_marker) @markup.heading.4 (inline) @markup.heading.4) (atx_heading - (atx_h5_marker) @markup.heading.5.marker + (atx_h5_marker) @markup.heading.5 (inline) @markup.heading.5) (atx_heading - (atx_h6_marker) @markup.heading.6.marker + (atx_h6_marker) @markup.heading.6 (inline) @markup.heading.6) (info_string) @label @@ -54,12 +54,12 @@ (#set! "priority" 90)) (fenced_code_block - (fenced_code_block_delimiter) @markup.raw.delimiter + (fenced_code_block_delimiter) @markup.raw.block (#set! conceal "")) (fenced_code_block (info_string - (language) @conceal + (language) @label (#set! conceal ""))) (link_destination) @markup.link.url @@ -69,6 +69,10 @@ (link_label) ] @markup.link.label +((link_label) + . + ":" @punctuation.delimiter) + [ (list_marker_plus) (list_marker_minus) @@ -79,7 +83,7 @@ ; NOTE: The following has been commented out due to issues with spaces in the ; list marker nodes generated by the parser. If those spaces ever get captured -; by a different node (e.g. block_continuation) we can safely readd these +; by a different node (e.g. block_continuation) we can safely re-add these ; conceals. ; ;; Conceal bullet points ; ([(list_marker_plus) (list_marker_star)] @@ -107,6 +111,12 @@ ((block_quote) @markup.quote (#set! "priority" 90)) +([ + (plus_metadata) + (minus_metadata) +] @keyword.directive + (#set! "priority" 90)) + [ (block_continuation) (block_quote_marker) diff --git a/runtime/queries/markdown_inline/highlights.scm b/runtime/queries/markdown_inline/highlights.scm index e9b41c31d5..233ab411cd 100644 --- a/runtime/queries/markdown_inline/highlights.scm +++ b/runtime/queries/markdown_inline/highlights.scm @@ -16,10 +16,10 @@ ] @string.escape ; Conceal codeblock and text style markers -((code_span_delimiter) @markup.raw.delimiter - (#set! conceal "")) - -((emphasis_delimiter) @conceal +([ + (code_span_delimiter) + (emphasis_delimiter) +] @conceal (#set! conceal "")) ; Conceal inline links @@ -33,6 +33,18 @@ ] @markup.link (#set! conceal "")) +[ + (link_label) + (link_text) + (link_title) + (image_description) +] @markup.link.label + +(inline_link + (link_text) @_label + (link_destination) @_url + (#set! @_label "url" @_url)) + ; Conceal image links (image [ @@ -75,13 +87,6 @@ (uri_autolink) ] @markup.link.url @nospell -[ - (link_label) - (link_text) - (link_title) - (image_description) -] @markup.link.label - ; Replace common HTML entities. ((entity_reference) @character.special (#eq? @character.special " ") diff --git a/runtime/queries/python/folds.scm b/runtime/queries/python/folds.scm index 7c547db38f..ecb9352d78 100644 --- a/runtime/queries/python/folds.scm +++ b/runtime/queries/python/folds.scm @@ -21,3 +21,8 @@ (dictionary) (string) ] @fold + +[ + (import_statement) + (import_from_statement) +]+ @fold diff --git a/runtime/queries/python/highlights.scm b/runtime/queries/python/highlights.scm index 764521c7be..5e5a2a88de 100644 --- a/runtime/queries/python/highlights.scm +++ b/runtime/queries/python/highlights.scm @@ -17,11 +17,9 @@ (#lua-match? @constant.builtin "^__[a-zA-Z0-9_]*__$")) ((identifier) @constant.builtin - ; format-ignore - (#any-of? @constant.builtin + (#any-of? @constant.builtin ; https://docs.python.org/3/library/constants.html - "NotImplemented" "Ellipsis" - "quit" "exit" "copyright" "credits" "license")) + "NotImplemented" "Ellipsis" "quit" "exit" "copyright" "credits" "license")) "_" @constant.builtin ; match wildcard @@ -37,9 +35,8 @@ ((assignment left: (identifier) @type.definition - right: - (call - function: (identifier) @_func)) + right: (call + function: (identifier) @_func)) (#any-of? @_func "TypeVar" "NewType")) ; Function calls @@ -47,18 +44,16 @@ function: (identifier) @function.call) (call - function: - (attribute - attribute: (identifier) @function.method.call)) + function: (attribute + attribute: (identifier) @function.method.call)) ((call function: (identifier) @constructor) (#lua-match? @constructor "^%u")) ((call - function: - (attribute - attribute: (identifier) @constructor)) + function: (attribute + attribute: (identifier) @constructor)) (#lua-match? @constructor "^%u")) ; Decorators @@ -84,12 +79,19 @@ ((decorator (identifier) @attribute.builtin) - (#any-of? @attribute.builtin "classmethod" "property")) + (#any-of? @attribute.builtin "classmethod" "property" "staticmethod")) ; Builtin functions ((call function: (identifier) @function.builtin) - (#any-of? @function.builtin "abs" "all" "any" "ascii" "bin" "bool" "breakpoint" "bytearray" "bytes" "callable" "chr" "classmethod" "compile" "complex" "delattr" "dict" "dir" "divmod" "enumerate" "eval" "exec" "filter" "float" "format" "frozenset" "getattr" "globals" "hasattr" "hash" "help" "hex" "id" "input" "int" "isinstance" "issubclass" "iter" "len" "list" "locals" "map" "max" "memoryview" "min" "next" "object" "oct" "open" "ord" "pow" "print" "property" "range" "repr" "reversed" "round" "set" "setattr" "slice" "sorted" "staticmethod" "str" "sum" "super" "tuple" "type" "vars" "zip" "__import__")) + (#any-of? @function.builtin + "abs" "all" "any" "ascii" "bin" "bool" "breakpoint" "bytearray" "bytes" "callable" "chr" + "classmethod" "compile" "complex" "delattr" "dict" "dir" "divmod" "enumerate" "eval" "exec" + "filter" "float" "format" "frozenset" "getattr" "globals" "hasattr" "hash" "help" "hex" "id" + "input" "int" "isinstance" "issubclass" "iter" "len" "list" "locals" "map" "max" "memoryview" + "min" "next" "object" "oct" "open" "ord" "pow" "print" "property" "range" "repr" "reversed" + "round" "set" "setattr" "slice" "sorted" "staticmethod" "str" "sum" "super" "tuple" "type" + "vars" "zip" "__import__")) ; Function definitions (function_definition @@ -104,10 +106,9 @@ ((call function: (identifier) @_isinstance - arguments: - (argument_list - (_) - (identifier) @type)) + arguments: (argument_list + (_) + (identifier) @type)) (#eq? @_isinstance "isinstance")) ; Normal parameters @@ -187,7 +188,7 @@ ((module . - (comment) @keyword.directive) + (comment) @keyword.directive @nospell) (#lua-match? @keyword.directive "^#!/")) (string) @string @@ -200,22 +201,44 @@ ; doc-strings (module . + (comment)* + . (expression_statement - (string) @string.documentation @spell)) + (string) @string.documentation)) (class_definition - body: - (block - . - (expression_statement - (string) @string.documentation @spell))) + body: (block + . + (expression_statement + (string) @string.documentation))) (function_definition - body: - (block - . - (expression_statement - (string) @string.documentation @spell))) + body: (block + . + (expression_statement + (string) @string.documentation))) + +(module + . + (comment)* + . + (expression_statement + (string + (string_content) @spell))) + +(class_definition + body: (block + . + (expression_statement + (string + (string_content) @spell)))) + +(function_definition + body: (block + . + (expression_statement + (string + (string_content) @spell)))) ; Tokens [ @@ -277,7 +300,6 @@ [ "assert" - "class" "exec" "global" "nonlocal" @@ -285,10 +307,14 @@ "print" "with" "as" - "type" ] @keyword [ + "type" + "class" +] @keyword.type + +[ "async" "await" ] @keyword.coroutine @@ -371,33 +397,28 @@ name: (identifier) @type) (class_definition - body: - (block - (function_definition - name: (identifier) @function.method))) + body: (block + (function_definition + name: (identifier) @function.method))) (class_definition - superclasses: - (argument_list - (identifier) @type)) + superclasses: (argument_list + (identifier) @type)) ((class_definition - body: - (block - (expression_statement - (assignment - left: (identifier) @variable.member)))) - (#lua-match? @variable.member "^%l.*$")) + body: (block + (expression_statement + (assignment + left: (identifier) @variable.member)))) + (#lua-match? @variable.member "^[%l_].*$")) ((class_definition - body: - (block - (expression_statement - (assignment - left: - (_ - (identifier) @variable.member))))) - (#lua-match? @variable.member "^%l.*$")) + body: (block + (expression_statement + (assignment + left: (_ + (identifier) @variable.member))))) + (#lua-match? @variable.member "^[%l_].*$")) ((class_definition (block @@ -406,32 +427,31 @@ (#any-of? @constructor "__new__" "__init__")) ((identifier) @type.builtin - ; format-ignore (#any-of? @type.builtin ; https://docs.python.org/3/library/exceptions.html - "BaseException" "Exception" "ArithmeticError" "BufferError" "LookupError" "AssertionError" "AttributeError" - "EOFError" "FloatingPointError" "GeneratorExit" "ImportError" "ModuleNotFoundError" "IndexError" "KeyError" - "KeyboardInterrupt" "MemoryError" "NameError" "NotImplementedError" "OSError" "OverflowError" "RecursionError" - "ReferenceError" "RuntimeError" "StopIteration" "StopAsyncIteration" "SyntaxError" "IndentationError" "TabError" - "SystemError" "SystemExit" "TypeError" "UnboundLocalError" "UnicodeError" "UnicodeEncodeError" "UnicodeDecodeError" - "UnicodeTranslateError" "ValueError" "ZeroDivisionError" "EnvironmentError" "IOError" "WindowsError" - "BlockingIOError" "ChildProcessError" "ConnectionError" "BrokenPipeError" "ConnectionAbortedError" - "ConnectionRefusedError" "ConnectionResetError" "FileExistsError" "FileNotFoundError" "InterruptedError" - "IsADirectoryError" "NotADirectoryError" "PermissionError" "ProcessLookupError" "TimeoutError" "Warning" + "BaseException" "Exception" "ArithmeticError" "BufferError" "LookupError" "AssertionError" + "AttributeError" "EOFError" "FloatingPointError" "GeneratorExit" "ImportError" + "ModuleNotFoundError" "IndexError" "KeyError" "KeyboardInterrupt" "MemoryError" "NameError" + "NotImplementedError" "OSError" "OverflowError" "RecursionError" "ReferenceError" "RuntimeError" + "StopIteration" "StopAsyncIteration" "SyntaxError" "IndentationError" "TabError" "SystemError" + "SystemExit" "TypeError" "UnboundLocalError" "UnicodeError" "UnicodeEncodeError" + "UnicodeDecodeError" "UnicodeTranslateError" "ValueError" "ZeroDivisionError" "EnvironmentError" + "IOError" "WindowsError" "BlockingIOError" "ChildProcessError" "ConnectionError" + "BrokenPipeError" "ConnectionAbortedError" "ConnectionRefusedError" "ConnectionResetError" + "FileExistsError" "FileNotFoundError" "InterruptedError" "IsADirectoryError" + "NotADirectoryError" "PermissionError" "ProcessLookupError" "TimeoutError" "Warning" "UserWarning" "DeprecationWarning" "PendingDeprecationWarning" "SyntaxWarning" "RuntimeWarning" "FutureWarning" "ImportWarning" "UnicodeWarning" "BytesWarning" "ResourceWarning" ; https://docs.python.org/3/library/stdtypes.html - "bool" "int" "float" "complex" "list" "tuple" "range" "str" - "bytes" "bytearray" "memoryview" "set" "frozenset" "dict" "type" "object")) + "bool" "int" "float" "complex" "list" "tuple" "range" "str" "bytes" "bytearray" "memoryview" + "set" "frozenset" "dict" "type" "object")) ; Regex from the `re` module (call - function: - (attribute - object: (identifier) @_re) - arguments: - (argument_list - . - (string - (string_content) @string.regexp)) + function: (attribute + object: (identifier) @_re) + arguments: (argument_list + . + (string + (string_content) @string.regexp)) (#eq? @_re "re")) diff --git a/runtime/queries/query/highlights.scm b/runtime/queries/query/highlights.scm index cdedb23e29..210d03dc33 100644 --- a/runtime/queries/query/highlights.scm +++ b/runtime/queries/query/highlights.scm @@ -53,35 +53,33 @@ . (comment)* . - (comment) @keyword.import) + (comment) @keyword.import @nospell) (#lua-match? @keyword.import "^;+ *inherits *:")) ((program . (comment)* . - (comment) @keyword.directive) + (comment) @keyword.directive @nospell) (#lua-match? @keyword.directive "^;+ *extends *$")) -((comment) @keyword.directive +((comment) @keyword.directive @nospell (#lua-match? @keyword.directive "^;+%s*format%-ignore%s*$")) ((predicate name: (identifier) @_name - parameters: - (parameters - (string - "\"" @string - "\"" @string) @string.regexp)) + parameters: (parameters + (string + "\"" @string + "\"" @string) @string.regexp)) (#any-of? @_name "match" "not-match" "vim-match" "not-vim-match" "lua-match" "not-lua-match")) ((predicate name: (identifier) @_name - parameters: - (parameters - (string - "\"" @string - "\"" @string) @string.regexp - . - (string) .)) + parameters: (parameters + (string + "\"" @string + "\"" @string) @string.regexp + . + (string) .)) (#any-of? @_name "gsub" "not-gsub")) diff --git a/runtime/queries/vim/highlights.scm b/runtime/queries/vim/highlights.scm index 54832ffa56..14e5a8128f 100644 --- a/runtime/queries/vim/highlights.scm +++ b/runtime/queries/vim/highlights.scm @@ -42,9 +42,8 @@ function: (identifier) @function.call) (call_expression - function: - (scoped_identifier - (identifier) @function.call)) + function: (scoped_identifier + (identifier) @function.call)) (parameters (identifier) @variable.parameter) @@ -127,11 +126,14 @@ "view" "eval" "sign" + "abort" ] @keyword (map_statement cmd: _ @keyword) +(keycode) @character.special + (command_name) @function.macro ; Filetype command @@ -204,10 +206,9 @@ (command_attribute name: _ @property - val: - (behavior - name: _ @constant - val: (identifier)? @function)?) + val: (behavior + name: _ @constant + val: (identifier)? @function)?) ; Edit command (plus_plus_opt @@ -277,8 +278,6 @@ "/" "%" ".." - "is" - "isnot" "==" "!=" ">" @@ -297,9 +296,15 @@ "..=" "<<" "=<<" + "->" (match_case) ] @operator +[ + "is" + "isnot" +] @keyword.operator + ; Some characters have different meanings based on the context (unary_operation "!" @operator) diff --git a/runtime/queries/vim/injections.scm b/runtime/queries/vim/injections.scm index 16ec57ca99..5feb832ec4 100644 --- a/runtime/queries/vim/injections.scm +++ b/runtime/queries/vim/injections.scm @@ -28,5 +28,7 @@ ((set_item option: (option_name) @_option value: (set_value) @injection.content) - (#any-of? @_option "includeexpr" "inex" "printexpr" "pexpr" "formatexpr" "fex" "indentexpr" "inde" "foldtext" "fdt" "foldexpr" "fde" "diffexpr" "dex" "patchexpr" "pex" "charconvert" "ccv") + (#any-of? @_option + "includeexpr" "inex" "printexpr" "pexpr" "formatexpr" "fex" "indentexpr" "inde" "foldtext" "fdt" + "foldexpr" "fde" "diffexpr" "dex" "patchexpr" "pex" "charconvert" "ccv") (#set! injection.language "vim")) diff --git a/runtime/queries/vimdoc/highlights.scm b/runtime/queries/vimdoc/highlights.scm index 294fa94f10..70a3a2f206 100644 --- a/runtime/queries/vimdoc/highlights.scm +++ b/runtime/queries/vimdoc/highlights.scm @@ -7,39 +7,46 @@ (column_heading) @markup.heading.4 (column_heading - "~" @markup.heading.4.marker + "~" @markup.heading.4 + (#set! conceal "")) + +(tag + "*" @label (#set! conceal "")) (tag - "*" @markup.heading.5.marker - (#set! conceal "") text: (_) @label) (taglink "|" @markup.link - (#set! conceal "") + (#set! conceal "")) + +(taglink text: (_) @markup.link) (optionlink text: (_) @markup.link) (codespan - "`" @markup.raw.delimiter - (#set! conceal "") + "`" @markup.raw + (#set! conceal "")) + +(codespan text: (_) @markup.raw) ((codeblock) @markup.raw.block (#set! "priority" 90)) (codeblock - [ - ">" - (language) - ] @markup.raw.delimiter + ">" @markup.raw + (#set! conceal "")) + +(codeblock + (language) @label (#set! conceal "")) (block - "<" @markup.raw.delimiter + "<" @markup.raw (#set! conceal "")) (argument) @variable.parameter @@ -48,6 +55,8 @@ (url) @string.special.url +(modeline) @keyword.directive + ((note) @comment.note (#any-of? @comment.note "Note:" "NOTE:" "Notes:")) diff --git a/runtime/syntax/astro.vim b/runtime/syntax/astro.vim new file mode 100644 index 0000000000..0816051ada --- /dev/null +++ b/runtime/syntax/astro.vim @@ -0,0 +1,190 @@ +" Vim syntax file. +" Language: Astro +" Author: Wuelner Martínez <wuelner.martinez@outlook.com> +" Maintainer: Wuelner Martínez <wuelner.martinez@outlook.com> +" URL: https://github.com/wuelnerdotexe/vim-astro +" Last Change: 2022 Aug 22 +" Based On: Evan Lecklider's vim-svelte +" Changes: See https://github.com/evanleck/vim-svelte +" Credits: See vim-svelte on github + +" Quit when a (custom) syntax file was already loaded. +if !exists('main_syntax') + if exists('b:current_syntax') + finish + endif + let main_syntax = 'astro' +elseif exists('b:current_syntax') && b:current_syntax == 'astro' + finish +endif + +" Astro syntax variables are initialized. +let g:astro_typescript = get(g:, 'astro_typescript', 'disable') +let g:astro_stylus = get(g:, 'astro_stylus', 'disable') + +let s:cpoptions_save = &cpoptions +set cpoptions&vim + +" Embedded HTML syntax. +runtime! syntax/html.vim + +" htmlTagName: expand HTML tag names to include mixed case and periods. +syntax match htmlTagName contained "\<[a-zA-Z\.]*\>" + +" astroDirectives: add Astro Directives to HTML arguments. +syntax match astroDirectives contained '\<[a-z]\+:[a-z|]*\>' containedin=htmlTag + +unlet b:current_syntax + +if g:astro_typescript == 'enable' + " Embedded TypeScript syntax. + syntax include @astroJavaScript syntax/typescript.vim + + " javaScriptExpression: a javascript expression is used as an arg value. + syntax clear javaScriptExpression + syntax region javaScriptExpression + \ contained start=+&{+ + \ keepend end=+};+ + \ contains=@astroJavaScript,@htmlPreproc + + " javaScript: add TypeScript support to HTML script tag. + syntax clear javaScript + syntax region javaScript + \ start=+<script\_[^>]*>+ + \ keepend + \ end=+</script\_[^>]*>+me=s-1 + \ contains=htmlScriptTag,@astroJavaScript,@htmlPreproc,htmlCssStyleComment +else + " Embedded JavaScript syntax. + syntax include @astroJavaScript syntax/javascript.vim +endif + +" astroFence: detect the Astro fence. +syntax match astroFence contained +^---$+ + +" astrojavaScript: add TypeScript support to Astro code fence. +syntax region astroJavaScript + \ start=+^---$+ + \ keepend + \ end=+^---$+ + \ contains=htmlTag,@astroJavaScript,@htmlPreproc,htmlCssStyleComment,htmlEndTag,astroFence + \ fold + +unlet b:current_syntax + +if g:astro_typescript == 'enable' + " Embedded TypeScript React (TSX) syntax. + syntax include @astroJavaScriptReact syntax/typescriptreact.vim +else + " Embedded JavaScript React (JSX) syntax. + syntax include @astroJavaScriptReact syntax/javascriptreact.vim +endif + +" astroJavaScriptExpression: add {JSX or TSX} support to Astro expresions. +execute 'syntax region astroJavaScriptExpression start=+{+ keepend end=+}+ ' . + \ 'contains=@astroJavaScriptReact, @htmlPreproc containedin=' . join([ + \ 'htmlArg', 'htmlBold', 'htmlBoldItalic', 'htmlBoldItalicUnderline', + \ 'htmlBoldUnderline', 'htmlBoldUnderlineItalic', 'htmlH1', 'htmlH2', + \ 'htmlH3', 'htmlH4', 'htmlH5', 'htmlH6', 'htmlHead', 'htmlItalic', + \ 'htmlItalicBold', 'htmlItalicBoldUnderline', 'htmlItalicUnderline', + \ 'htmlItalicUnderlineBold', 'htmlLeadingSpace', 'htmlLink', + \ 'htmlStrike', 'htmlString', 'htmlTag', 'htmlTitle', 'htmlUnderline', + \ 'htmlUnderlineBold', 'htmlUnderlineBoldItalic', + \ 'htmlUnderlineItalic', 'htmlUnderlineItalicBold', 'htmlValue' + \ ], ',') + +" cssStyle: add CSS style tags support in TypeScript React. +syntax region cssStyle + \ start=+<style\_[^>]*>+ + \ keepend + \ end=+</style\_[^>]*>+me=s-1 + \ contains=htmlTag,@htmlCss,htmlCssStyleComment,@htmlPreproc,htmlEndTag + \ containedin=@astroJavaScriptReact + +unlet b:current_syntax + +" Embedded SCSS syntax. +syntax include @astroScss syntax/scss.vim + +" cssStyle: add SCSS style tags support in Astro. +syntax region scssStyle + \ start=/<style\>\_[^>]*\(lang\)=\("\|''\)[^\2]*scss[^\2]*\2\_[^>]*>/ + \ keepend + \ end=+</style>+me=s-1 + \ contains=@astroScss,astroSurroundingTag + \ fold + +unlet b:current_syntax + +" Embedded SASS syntax. +syntax include @astroSass syntax/sass.vim + +" cssStyle: add SASS style tags support in Astro. +syntax region sassStyle + \ start=/<style\>\_[^>]*\(lang\)=\("\|''\)[^\2]*sass[^\2]*\2\_[^>]*>/ + \ keepend + \ end=+</style>+me=s-1 + \ contains=@astroSass,astroSurroundingTag + \ fold + +unlet b:current_syntax + +" Embedded LESS syntax. +syntax include @astroLess syntax/less.vim + +" cssStyle: add LESS style tags support in Astro. +syntax region lessStyle + \ start=/<style\>\_[^>]*\(lang\)=\("\|''\)[^\2]*less[^\2]*\2\_[^>]*>/ + \ keepend + \ end=+</style>+me=s-1 + \ contains=@astroLess,astroSurroundingTag + \ fold + +unlet b:current_syntax + +" Embedded Stylus syntax. +" NOTE: Vim does not provide stylus support by default, but you can install +" this plugin to support it: https://github.com/wavded/vim-stylus +if g:astro_stylus == 'enable' + try + " Embedded Stylus syntax. + syntax include @astroStylus syntax/stylus.vim + + " stylusStyle: add Stylus style tags support in Astro. + syntax region stylusStyle + \ start=/<style\>\_[^>]*\(lang\)=\("\|''\)[^\2]*stylus[^\2]*\2\_[^>]*>/ + \ keepend + \ end=+</style>+me=s-1 + \ contains=@astroStylus,astroSurroundingTag + \ fold + + unlet b:current_syntax + catch + echomsg "you need install a external plugin for support stylus in .astro files" + endtry +endif + +" astroSurroundingTag: add surround HTML tag to script and style. +syntax region astroSurroundingTag + \ start=+<\(script\|style\)+ + \ end=+>+ + \ contains=htmlTagError,htmlTagN,htmlArg,htmlValue,htmlEvent,htmlString + \ contained + \ fold + +" Define the default highlighting. +" Only used when an item doesn't have highlighting yet. +highlight default link astroDirectives Special +highlight default link astroFence Comment + +let b:current_syntax = 'astro' +if main_syntax == 'astro' + unlet main_syntax +endif + +" Sync from start because of the wacky nesting. +syntax sync fromstart + +let &cpoptions = s:cpoptions_save +unlet s:cpoptions_save +" vim: ts=8 diff --git a/runtime/syntax/cgdbrc.vim b/runtime/syntax/cgdbrc.vim new file mode 100644 index 0000000000..1ace370d8c --- /dev/null +++ b/runtime/syntax/cgdbrc.vim @@ -0,0 +1,16 @@ +" Vim syntax file +" Language: cgdbrc +" Maintainer: Wu, Zhenyu <wuzhenyu@ustc.edu> +" Documentation: https://cgdb.github.io/docs/Configuring-CGDB.html +" Latest Revision: 2024-04-09 + +if exists('b:current_syntax') + finish +endif +let b:current_syntax = 'cgdbrc' + +runtime! syntax/vim.vim + +syn region cgdbComment start="^\s*\#" skip="\\$" end="$" contains=@Spell + +highlight default link cgdbComment Comment diff --git a/runtime/syntax/cmakecache.vim b/runtime/syntax/cmakecache.vim new file mode 100644 index 0000000000..f07c719811 --- /dev/null +++ b/runtime/syntax/cmakecache.vim @@ -0,0 +1,60 @@ +" Vim syntax file +" Language: cmakecache - CMakeCache.txt files generated by CMake +" Author: bfrg <https://github.com/bfrg> +" Upstream: https://github.com/bfrg/vim-cmakecache-syntax +" Last Change: Nov 28, 2019 +" License: Same as Vim itself (see :h license) + +if exists('b:current_syntax') + finish +endif + +let s:cpo_save = &cpoptions +set cpoptions&vim + +" Comments start with # or // +syntax region CMakeCacheComment start="#\|//" end="$" + +" Match 'key' in key:type=value +syntax match CMakeCacheKey "^\s*\w\+\(-ADVANCED\)\=:"me=e-1 + +" Highlight 'str' in key:STRING=str (many thanks to Nickspoons in #vim!) +syntax region CMakeCacheStringVar matchgroup=CMakeCacheType start=":STRING="ms=s+1,rs=e-1 end="$" contains=CMakeCacheString keepend +syntax region CMakeCacheString start="="ms=s+1 end="$" contained + +" Highlight boolean 'value' in key:BOOL=value +syntax region CMakeCacheBoolVar matchgroup=CMakeCacheType start=":BOOL="ms=s+1,rs=e-1 end="$" contains=CMakeCacheBool keepend +syntax region CMakeCacheBool start="="ms=s+1 end="$" contained + +" Highlight 'path' in key:PATH=path +syntax region CMakeCachePathVar matchgroup=CMakeCacheType start=":PATH="ms=s+1,rs=e-1 end="$" contains=CMakeCachePath keepend +syntax region CMakeCachePath start="="ms=s+1 end="$" contained + +" Highlight 'file' in key:FILEPATH=file +syntax region CMakeCacheFilePathVar matchgroup=CMakeCacheType start=":FILEPATH="ms=s+1,rs=e-1 end="$" contains=CMakeCacheFilePath keepend +syntax region CMakeCacheFilePath start="="ms=s+1 end="$" contained + +" Highlight 'value' in key:STATIC=value +syntax region CMakeCacheStaticVar matchgroup=CMakeCacheType start=":STATIC="ms=s+1,rs=e-1 end="$" contains=CMakeCacheStatic keepend +syntax region CMakeCacheStatic start="="ms=s+1 end="$" contained + +" Highlight 'value' in key:Internal=value +syntax region CMakeCacheInternalVar matchgroup=CMakeCacheType start=":INTERNAL="ms=s+1,rs=e-1 end="$" contains=CMakeCacheInternal keepend +syntax region CMakeCacheInternal start="="ms=s+1 end="$" contained + +hi def link CMakeCacheComment Comment +hi def link CMakeCacheKey Identifier +hi def link CMakeCacheString String +hi def link CMakeCacheBool Constant +hi def link CMakeCachePath Directory +hi def link CMakeCacheFilePath Normal +hi def link CMakeCacheStatic Normal +hi def link CMakeCacheInternal Normal + +" Highlight 'type' in key:type=value +hi def link CMakeCacheType Type + +let b:current_syntax = 'cmakecache' + +let &cpoptions = s:cpo_save +unlet s:cpo_save diff --git a/runtime/syntax/cpp.vim b/runtime/syntax/cpp.vim index 8daf90a33c..ff1226b7b0 100644 --- a/runtime/syntax/cpp.vim +++ b/runtime/syntax/cpp.vim @@ -2,7 +2,8 @@ " Language: C++ " Current Maintainer: vim-jp (https://github.com/vim-jp/vim-cpp) " Previous Maintainer: Ken Shan <ccshan@post.harvard.edu> -" Last Change: 2023 Dec 08 +" Last Change: 2024 May 04 +" 2024 May 04 by Vim Project (fix digit separator in octals and floats) " quit when a syntax file was already loaded if exists("b:current_syntax") @@ -55,11 +56,11 @@ if !exists("cpp_no_cpp14") syn match cppNumbers display transparent "\<\d\|\.\d" contains=cppNumber,cppFloat syn match cppNumber display contained "\<0\([Uu]\=\([Ll]\|LL\|ll\)\|\([Ll]\|LL\|ll\)\=[Uu]\|i[fl]\=\|h\|min\|s\|ms\|us\|ns\|_\i*\)\=\>" syn match cppNumber display contained "\<[1-9]\('\=\d\+\)*\([Uu]\=\([Ll]\|LL\|ll\)\|\([Ll]\|LL\|ll\)\=[Uu]\|i[fl]\=\|h\|min\|s\|ms\|us\|ns\|_\i*\)\=\>" - syn match cppNumber display contained "\<0\o\+\([Uu]\=\([Ll]\|LL\|ll\)\|\([Ll]\|LL\|ll\)\=[Uu]\|i[fl]\=\|h\|min\|s\|ms\|us\|ns\|_\i*\)\=\>" + syn match cppNumber display contained "\<0\('\=\o\+\)\+\([Uu]\=\([Ll]\|LL\|ll\)\|\([Ll]\|LL\|ll\)\=[Uu]\|i[fl]\=\|h\|min\|s\|ms\|us\|ns\|_\i*\)\=\>" syn match cppNumber display contained "\<0b[01]\('\=[01]\+\)*\([Uu]\=\([Ll]\|LL\|ll\)\|\([Ll]\|LL\|ll\)\=[Uu]\|i[fl]\=\|h\|min\|s\|ms\|us\|ns\|_\i*\)\=\>" syn match cppNumber display contained "\<0x\x\('\=\x\+\)*\([Uu]\=\([Ll]\|LL\|ll\)\|\([Ll]\|LL\|ll\)\=[Uu]\|i[fl]\=\|h\|min\|s\|ms\|us\|ns\|_\i*\)\=\>" - syn match cppFloat display contained "\<\d\+\.\d*\(e[-+]\=\d\+\)\=\([FfLl]\|i[fl]\=\|h\|min\|s\|ms\|us\|ns\|_\i*\)\=\>" - syn match cppFloat display contained "\<\.\d\+\(e[-+]\=\d\+\)\=\([FfLl]\|i[fl]\=\|h\|min\|s\|ms\|us\|ns\|_\i*\)\=\>" + syn match cppFloat display contained "\<\d\('\=\d\+\)*\.\(\d\('\=\d\+\)*\)\=\(e[-+]\=\d\+\)\=\([FfLl]\|i[fl]\=\|h\|min\|s\|ms\|us\|ns\|_\i*\)\=\>" + syn match cppFloat display contained "\.\d\('\=\d\+\)*\(e[-+]\=\d\+\)\=\([FfLl]\|i[fl]\=\|h\|min\|s\|ms\|us\|ns\|_\i*\)\=\>" syn match cppFloat display contained "\<\d\+e[-+]\=\d\+\([FfLl]\|i[fl]\=\|h\|min\|s\|ms\|us\|ns\|_\i*\)\=\>" syn region cppString start=+\(L\|u\|u8\|U\)\="+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"\(sv\|s\|_\i*\)\=+ end='$' contains=cSpecial,cFormat,@Spell endif diff --git a/runtime/syntax/cuda.vim b/runtime/syntax/cuda.vim index 13d70e343a..8306d096a0 100644 --- a/runtime/syntax/cuda.vim +++ b/runtime/syntax/cuda.vim @@ -1,7 +1,8 @@ " Vim syntax file " Language: CUDA (NVIDIA Compute Unified Device Architecture) " Maintainer: Timothy B. Terriberry <tterribe@users.sourceforge.net> -" Last Change: 2018 Feb 06 +" Last Change: 2024 Apr 04 +" Contributor: jiangyinzuo " quit when a syntax file was already loaded if exists("b:current_syntax") @@ -11,12 +12,13 @@ endif " Read the C++ syntax to start with runtime! syntax/cpp.vim -" CUDA extentions -syn keyword cudaStorageClass __device__ __global__ __host__ -syn keyword cudaStorageClass __constant__ __shared__ -syn keyword cudaStorageClass __inline__ __align__ __thread__ +" CUDA extentions. +" Reference: https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#c-language-extensions +syn keyword cudaStorageClass __device__ __global__ __host__ __managed__ +syn keyword cudaStorageClass __constant__ __grid_constant__ __shared__ +syn keyword cudaStorageClass __inline__ __noinline__ __forceinline__ __inline_hint__ +syn keyword cudaStorageClass __align__ __thread__ __restrict__ "syn keyword cudaStorageClass __import__ __export__ __location__ -syn keyword cudaStructure template syn keyword cudaType char1 char2 char3 char4 syn keyword cudaType uchar1 uchar2 uchar3 uchar4 syn keyword cudaType short1 short2 short3 short4 @@ -25,37 +27,23 @@ syn keyword cudaType int1 int2 int3 int4 syn keyword cudaType uint1 uint2 uint3 uint4 syn keyword cudaType long1 long2 long3 long4 syn keyword cudaType ulong1 ulong2 ulong3 ulong4 +syn keyword cudaType longlong1 longlong2 longlong3 longlong4 +syn keyword cudaType ulonglong1 ulonglong2 ulonglong3 ulonglong4 syn keyword cudaType float1 float2 float3 float4 -syn keyword cudaType ufloat1 ufloat2 ufloat3 ufloat4 +syn keyword cudaType double1 double2 double3 double4 syn keyword cudaType dim3 texture textureReference syn keyword cudaType cudaError_t cudaDeviceProp cudaMemcpyKind syn keyword cudaType cudaArray cudaChannelFormatKind syn keyword cudaType cudaChannelFormatDesc cudaTextureAddressMode syn keyword cudaType cudaTextureFilterMode cudaTextureReadMode -syn keyword cudaVariable gridDim blockIdx blockDim threadIdx +syn keyword cudaVariable gridDim blockIdx blockDim threadIdx warpSize +syn keyword cudaConstant __CUDA_ARCH__ syn keyword cudaConstant __DEVICE_EMULATION__ +" There are too many CUDA enumeration constants. We only define a subset of commonly used constants. +" Reference: https://docs.nvidia.com/cuda/cuda-runtime-api/group__CUDART__TYPES.html syn keyword cudaConstant cudaSuccess -" Many more errors are defined, but only these are listed in the maunal -syn keyword cudaConstant cudaErrorMemoryAllocation -syn keyword cudaConstant cudaErrorInvalidDevicePointer -syn keyword cudaConstant cudaErrorInvalidSymbol -syn keyword cudaConstant cudaErrorMixedDeviceExecution -syn keyword cudaConstant cudaMemcpyHostToHost -syn keyword cudaConstant cudaMemcpyHostToDevice -syn keyword cudaConstant cudaMemcpyDeviceToHost -syn keyword cudaConstant cudaMemcpyDeviceToDevice -syn keyword cudaConstant cudaReadModeElementType -syn keyword cudaConstant cudaReadModeNormalizedFloat -syn keyword cudaConstant cudaFilterModePoint -syn keyword cudaConstant cudaFilterModeLinear -syn keyword cudaConstant cudaAddressModeClamp -syn keyword cudaConstant cudaAddressModeWrap -syn keyword cudaConstant cudaChannelFormatKindSigned -syn keyword cudaConstant cudaChannelFormatKindUnsigned -syn keyword cudaConstant cudaChannelFormatKindFloat hi def link cudaStorageClass StorageClass -hi def link cudaStructure Structure hi def link cudaType Type hi def link cudaVariable Identifier hi def link cudaConstant Constant diff --git a/runtime/syntax/debcontrol.vim b/runtime/syntax/debcontrol.vim index b173a7b3f7..ea82d85b03 100644 --- a/runtime/syntax/debcontrol.vim +++ b/runtime/syntax/debcontrol.vim @@ -3,7 +3,7 @@ " Maintainer: Debian Vim Maintainers " Former Maintainers: Gerfried Fuchs <alfie@ist.org> " Wichert Akkerman <wakkerma@debian.org> -" Last Change: 2023 Dec 22 +" Last Change: 2024 Mar 26 " URL: https://salsa.debian.org/vim-team/vim-debian/blob/main/syntax/debcontrol.vim " Standard syntax initialization @@ -93,7 +93,7 @@ syn case ignore " Catch-all for the legal fields syn region debcontrolField matchgroup=debcontrolKey start="^\%(\%(XSBC-Original-\)\=Maintainer\|Standards-Version\|Bugs\|Origin\|X[SB]-Python-Version\|\%(XS-\)\=Vcs-Mtn\|\%(XS-\)\=Testsuite\%(-Triggers\)\=\|Build-Profiles\|Tag\|Subarchitecture\|Kernel-Version\|Installer-Menu-Item\): " end="$" contains=debcontrolVariable,debcontrolEmail oneline -syn region debcontrolMultiField matchgroup=debcontrolKey start="^\%(Build-\%(Conflicts\|Depends\)\%(-Arch\|-Indep\)\=\|\%(Pre-\)\=Depends\|Recommends\|Suggests\|Breaks\|Enhances\|Replaces\|Conflicts\|Provides\|Built-Using\|Uploaders\|X[SBC]\{0,3\}\%(Private-\)\=-[-a-zA-Z0-9]\+\): *" skip="^[ \t]" end="^$"me=s-1 end="^[^ \t#]"me=s-1 contains=debcontrolEmail,debcontrolVariable,debcontrolComment +syn region debcontrolMultiField matchgroup=debcontrolKey start="^\%(Build-\%(Conflicts\|Depends\)\%(-Arch\|-Indep\)\=\|\%(Pre-\)\=Depends\|Recommends\|Suggests\|Breaks\|Enhances\|Replaces\|Conflicts\|Provides\|Built-Using\|Static-Built-Using\|Uploaders\|X[SBC]\{0,3\}\%(Private-\)\=-[-a-zA-Z0-9]\+\): *" skip="^[ \t]" end="^$"me=s-1 end="^[^ \t#]"me=s-1 contains=debcontrolEmail,debcontrolVariable,debcontrolComment syn region debcontrolMultiFieldSpell matchgroup=debcontrolKey start="^Description: *" skip="^[ \t]" end="^$"me=s-1 end="^[^ \t#]"me=s-1 contains=debcontrolEmail,debcontrolVariable,debcontrolComment,@Spell " Fields for which we do strict syntax checking diff --git a/runtime/syntax/go.vim b/runtime/syntax/go.vim index ba776f949c..feed9646fb 100644 --- a/runtime/syntax/go.vim +++ b/runtime/syntax/go.vim @@ -5,7 +5,8 @@ " go.vim: Vim syntax file for Go. " Language: Go " Maintainer: Billie Cleek <bhcleek@gmail.com> -" Latest Revision: 2024-01-21 +" Latest Revision: 2024-04-13 +" 2024-03-17: - fix goPackageComment highlight (by Vim Project) " License: BSD-style. See LICENSE file in source repository. " Repository: https://github.com/fatih/vim-go @@ -190,7 +191,7 @@ else syn region goRawString start=+`+ end=+`+ endif -syn match goImportString /^\%(\s\+\|import \)\(\h\w* \)\?\zs"[^"]\+"$/ contained containedin=goImport +syn match goImportString /^\%(\s\+\|import \)\(\h\w* \)\?\zs"[^"]\+"/ contained containedin=goImport if s:HighlightFormatStrings() " [n] notation is valid for specifying explicit argument indexes @@ -531,12 +532,12 @@ if s:HighlightBuildConstraints() || s:FoldEnable('package_comment') " matched as comments to avoid looking like working build constraints. " The he, me, and re options let the "package" itself be highlighted by " the usual rules. - exe 'syn region goPackageComment start=/\v(\/\/.*\n)+\s*package/' - \ . ' end=/\v\n\s*package/he=e-7,me=e-7,re=e-7' + exe 'syn region goPackageComment start=/\v(\/\/.*\n)+\s*package\s/' + \ . ' end=/\v\n\s*package\s/he=e-8,me=e-8,re=e-8' \ . ' contains=@goCommentGroup,@Spell' \ . (s:FoldEnable('package_comment') ? ' fold' : '') - exe 'syn region goPackageComment start=/\v^\s*\/\*.*\n(.*\n)*\s*\*\/\npackage/' - \ . ' end=/\v\*\/\n\s*package/he=e-7,me=e-7,re=e-7' + exe 'syn region goPackageComment start=/\v^\s*\/\*.*\n(.*\n)*\s*\*\/\npackage\s/' + \ . ' end=/\v\*\/\n\s*package\s/he=e-8,me=e-8,re=e-8' \ . ' contains=@goCommentGroup,@Spell' \ . (s:FoldEnable('package_comment') ? ' fold' : '') hi def link goPackageComment Comment diff --git a/runtime/syntax/haskell.vim b/runtime/syntax/haskell.vim index b48b278084..509aa25122 100644 --- a/runtime/syntax/haskell.vim +++ b/runtime/syntax/haskell.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: Haskell " Maintainer: Haskell Cafe mailinglist <haskell-cafe@haskell.org> -" Last Change: 2020 Oct 4 by Marcin Szamotulski <profunctor@pm.me> +" Last Change: 2024 Mar 28 by Enrico Maria De Angelis <enricomaria.dean6elis@gmail.com> " Original Author: John Williams <jrw@pobox.com> " " Thanks to Ryan Crumley for suggestions and John Meacham for @@ -104,8 +104,8 @@ endif " Comments -syn match hsLineComment "---*\([^-!#$%&\*\+./<=>\?@\\^|~].*\)\?$" contains=@Spell -syn region hsBlockComment start="{-" end="-}" contains=hsBlockComment,@Spell +syn match hsLineComment "---*\([^-!#$%&\*\+./<=>\?@\\^|~].*\)\?$" contains=hsTodo,@Spell +syn region hsBlockComment start="{-" end="-}" contains=hsBlockComment,hsTodo,@Spell syn region hsPragma start="{-#" end="#-}" syn keyword hsTodo contained FIXME TODO XXX NOTE @@ -164,6 +164,7 @@ hi def link hsLiterateComment hsComment hi def link hsBlockComment hsComment hi def link hsLineComment hsComment hi def link hsComment Comment +hi def link hsTodo Todo hi def link hsPragma SpecialComment hi def link hsBoolean Boolean hi def link hsType Type diff --git a/runtime/syntax/i3config.vim b/runtime/syntax/i3config.vim index 8131639a11..f4d789e418 100644 --- a/runtime/syntax/i3config.vim +++ b/runtime/syntax/i3config.vim @@ -2,8 +2,8 @@ " Language: i3 config file " Original Author: Josef Litos (JosefLitos/i3config.vim) " Maintainer: Quentin Hibon (github user hiqua) -" Version: 1.0.2 -" Last Change: 2023-12-28 +" Version: 1.2.3 +" Last Change: 2024-05-23 " References: " http://i3wm.org/docs/userguide.html#configuring @@ -27,225 +27,246 @@ syn keyword i3ConfigTodo TODO FIXME XXX contained syn match i3ConfigSeparator /[,;\\]/ contained syn match i3ConfigParen /[{}]/ contained syn keyword i3ConfigBoolean yes no enabled disabled on off true false contained -syn region i3ConfigString start=/\W\@<="/ skip=/\\\("\|$\)/ end=/"\|$/ contained contains=i3ConfigShCommand,i3ConfigShDelim,i3ConfigShOper,i3ConfigShParam,i3ConfigNumber,i3ConfigVariable,i3ConfigExecAction keepend extend -syn region i3ConfigString start=/\W\@<='/ skip=/\\$/ end=/'\|$/ contained contains=i3ConfigShCommand,i3ConfigShDelim,i3ConfigShOper,i3ConfigShParam,i3ConfigNumber,i3ConfigVariable,i3ConfigExecAction keepend extend +" String in simpler (matchable end) and more robust (includes `extend` keyword) forms +syn cluster i3ConfigStrIn contains=i3ConfigShCommand,i3ConfigShDelim,i3ConfigShOper,i3ConfigShParam,@i3ConfigNumVar,i3ConfigExecAction +syn match i3ConfigString /\(["']\)[^\\"')\]}]*\1/ contained contains=@i3ConfigStrIn +syn region i3ConfigString start=/"[^\\"')\]}]*[\\')\]}]/ skip=/\\\@<=\("\|$\)/ end=/"\|$/ contained contains=@i3ConfigStrIn keepend extend +syn region i3ConfigString start=/'[^\\"')\]}]*[\\")\]}]/ skip=/\\\@<=$/ end=/'\|$/ contained contains=@i3ConfigStrIn keepend extend syn match i3ConfigColor /#[0-9A-Fa-f]\{3,8}/ contained syn match i3ConfigNumber /[0-9A-Za-z_$-]\@<!-\?\d\+\w\@!/ contained +" Grouping of common usages +syn cluster i3ConfigStrVar contains=i3ConfigString,i3ConfigVariable +syn cluster i3ConfigNumVar contains=i3ConfigNumber,i3ConfigVariable +syn cluster i3ConfigColVar contains=i3ConfigColor,i3ConfigVariable +syn cluster i3ConfigIdent contains=i3ConfigString,i3ConfigNumber,i3ConfigVariable +syn cluster i3ConfigValue contains=@i3ConfigIdent,i3ConfigBoolean " 4.1 Include directive -syn keyword i3ConfigIncludeKeyword include contained -syn match i3ConfigIncludeCommand /`[^`]*`/ contained contains=i3ConfigShDelim,i3ConfigShParam,i3ConfigShOper,i3ConfigShCommand,i3ConfigString -syn match i3ConfigParamLine /^include .*$/ contains=i3ConfigIncludeKeyword,i3ConfigString,i3ConfigVariable,i3ConfigIncludeCommand,i3ConfigShOper +syn match i3ConfigIncludeCommand /`[^`]*`/ contained contains=@i3ConfigSh +syn region i3ConfigParamLine matchgroup=i3ConfigKeyword start=/include / end=/$/ contained contains=@i3ConfigStrVar,i3ConfigIncludeCommand,i3ConfigShOper keepend " 4.2 Comments -syn match i3ConfigComment /^\s*#.*$/ contains=i3ConfigTodo +syn match i3ConfigComment /#.*$/ contained contains=i3ConfigTodo " 4.3 Fonts -syn keyword i3ConfigFontKeyword font contained +syn match i3ConfigFontSize / \d\+\(px\)\?$/ contained syn match i3ConfigColonOperator /:/ contained -syn match i3ConfigFontNamespace /\w\+:/ contained contains=i3ConfigColonOperator -syn match i3ConfigFontSize / \d\+\(px\)\?\s\?$/ contained -syn region i3ConfigFont start=/^\s*font / skip=/\\$/ end=/$/ contains=i3ConfigFontKeyword,i3ConfigFontNamespace,i3ConfigFontSize,i3ConfigSeparator keepend +syn match i3ConfigFontNamespace /pango:/ contained contains=i3ConfigColonOperator +syn region i3ConfigParamLine matchgroup=i3ConfigKeyword start=/font / skip=/\\$/ end=/$/ contained contains=i3ConfigFontNamespace,i3ConfigFontSize,i3ConfigSeparator keepend containedin=i3ConfigBarBlock " 4.4-4.5 Keyboard/Mouse bindings -syn keyword i3ConfigBindKeyword bindsym bindcode contained -syn match i3ConfigBindArgument /--\(release\|border\|whole-window\|exclude-titlebar\)/ contained +syn match i3ConfigBindArgument /--\(release\|border\|whole-window\|exclude-titlebar\) / contained nextgroup=i3ConfigBindArgument,i3ConfigBindCombo syn match i3ConfigBindModifier /+/ contained syn keyword i3ConfigBindModkey Ctrl Shift Mod1 Mod2 Mod3 Mod4 Mod5 contained -syn match i3ConfigBindCombo /[$0-9A-Za-z_+]\+ / contained contains=i3ConfigBindModifier,i3ConfigVariable,i3ConfigBindModkey -syn match i3ConfigBindComboLine /bind\(sym\|code\)\( --[a-z-]\+\)* [$0-9A-Za-z_+]\+ / contained contains=i3ConfigBindKeyword,i3ConfigBindArgument,i3ConfigBindCombo -syn region i3ConfigBind start=/^\s*bind\(sym\|code\) / skip=/\\$/ end=/$/ contains=i3ConfigBindComboLine,i3ConfigCriteria,i3ConfigAction,i3ConfigSeparator,i3ConfigActionKeyword,i3ConfigOption,i3ConfigString,i3ConfigNumber,i3ConfigVariable,i3ConfigBoolean keepend +syn match i3ConfigBindCombo /[$0-9A-Za-z_+]\+/ contained contains=i3ConfigBindModifier,i3ConfigVariable,i3ConfigBindModkey nextgroup=i3ConfigBind +syn cluster i3ConfigBinder contains=i3ConfigCriteria,@i3ConfigCommand,i3ConfigSeparator +syn region i3ConfigBind start=/\zs/ skip=/\\$/ end=/$/ contained contains=@i3ConfigBinder keepend +syn keyword i3ConfigBindKeyword bindsym bindcode contained skipwhite nextgroup=i3ConfigBindArgument,i3ConfigBindCombo " 4.6 Binding modes -syn region i3ConfigKeyword start=/^mode\( --pango_markup\)\? \([^'" {]\+\|'[^']\+'\|".\+"\)\s\+{$/ end=/^\s*}$/ contains=i3ConfigShParam,i3ConfigString,i3ConfigBind,i3ConfigComment,i3ConfigNumber,i3ConfigParen,i3ConfigVariable fold keepend extend +syn region i3ConfigModeBlock matchgroup=i3ConfigKeyword start=/mode\ze\( --pango_markup\)\? \([^'" {]\+\|'[^']\+'\|".\+"\)\s\+{$/ end=/^}\zs$/ contained contains=i3ConfigShParam,@i3ConfigStrVar,i3ConfigBindKeyword,i3ConfigComment,i3ConfigParen fold keepend extend " 4.7 Floating modifier syn match i3ConfigKeyword /^floating_modifier [$0-9A-Za-z]*$/ contains=i3ConfigVariable,i3ConfigBindModkey " 4.8 Floating window size syn keyword i3ConfigSizeSpecial x contained -syn match i3ConfigSize / -\?\d\+ x -\?\d\+/ contained contains=i3ConfigSizeSpecial,i3ConfigNumber -syn match i3ConfigKeyword /^floating_\(maximum\|minimum\)_size .*$/ contains=i3ConfigSize +syn match i3ConfigSize /-\?\d\+ x -\?\d\+/ contained contains=i3ConfigSizeSpecial,i3ConfigNumber +syn keyword i3ConfigKeyword floating_maximum_size floating_minimum_size contained skipwhite nextgroup=i3ConfigSize " 4.9 Orientation syn keyword i3ConfigOrientationOpts vertical horizontal auto contained -syn match i3ConfigKeyword /^default_orientation \w*$/ contains=i3ConfigOrientationOpts +syn keyword i3ConfigKeyword default_orientation contained skipwhite nextgroup=i3ConfigOrientationOpts " 4.10 Layout mode syn keyword i3ConfigWorkspaceLayoutOpts default stacking tabbed contained -syn match i3ConfigKeyword /^workspace_layout \w*$/ contains=i3ConfigWorkspaceLayoutOpts +syn keyword i3ConfigKeyword workspace_layout contained skipwhite nextgroup=i3ConfigWorkspaceLayoutOpts " 4.11 Title alignment syn keyword i3ConfigTitleAlignOpts left center right contained -syn match i3ConfigKeyword /^title_align .*$/ contains=i3ConfigTitleAlignOpts +syn keyword i3ConfigKeyword title_align contained skipwhite nextgroup=i3ConfigTitleAlignOpts -" 4.12 Border style -syn keyword i3ConfigBorderOpts none normal pixel contained -syn match i3ConfigKeyword /^default\(_floating\)\?_border .*$/ contains=i3ConfigBorderOpts,i3ConfigNumber,i3ConfigVariable +" 4.12 Border size +syn keyword i3ConfigBorderOpts none normal pixel contained skipwhite nextgroup=@i3ConfigNumVar +syn keyword i3ConfigKeyword default_floating_border default_border contained skipwhite nextgroup=i3ConfigBorderOpts " 4.13 Hide edge borders syn keyword i3ConfigEdgeOpts none vertical horizontal both smart smart_no_gaps contained -syn match i3ConfigKeyword /^hide_edge_borders \w*$/ contains=i3ConfigEdgeOpts +syn keyword i3ConfigKeyword hide_edge_borders contained skipwhite nextgroup=i3ConfigEdgeOpts " 4.14 Smart Borders syn keyword i3ConfigSmartBorderOpts no_gaps contained -syn match i3ConfigKeyword /^smart_borders \(on\|off\|no_gaps\)$/ contains=i3ConfigSmartBorderOpts,i3ConfigBoolean +syn keyword i3ConfigKeyword smart_borders contained skipwhite nextgroup=i3ConfigSmartBorderOpts,i3ConfigBoolean " 4.15 Arbitrary commands -syn region i3ConfigKeyword start=/^for_window / end=/$/ contains=i3ConfigForWindowKeyword,i3ConfigCriteria keepend +syn keyword i3ConfigKeyword for_window contained skipwhite nextgroup=i3ConfigCriteria " 4.16 No opening focus -syn match i3ConfigKeyword /^no_focus .*$/ contains=i3ConfigCondition +syn keyword i3ConfigKeyword no_focus contained skipwhite nextgroup=i3ConfigCondition " 4.17 Variables syn match i3ConfigVariable /\$[0-9A-Za-z_:|[\]-]\+/ -syn keyword i3ConfigSetKeyword set contained -syn match i3ConfigSet /^set \$.*$/ contains=i3ConfigSetKeyword,i3ConfigVariable,i3ConfigColor,i3ConfigString,i3ConfigNumber,i3ConfigShCommand,i3ConfigShDelim,i3ConfigShParam,i3ConfigShOper,i3ConfigBindModkey +syn region i3ConfigSet start=/\$/ skip=/\\$/ end=/$/ contained contains=@i3ConfigSh,@i3ConfigValue,i3ConfigColor,i3ConfigBindModkey keepend +syn keyword i3ConfigKeyword set contained skipwhite nextgroup=i3ConfigSet " 4.18 X resources -syn keyword i3ConfigResourceKeyword set_from_resource contained -syn match i3ConfigParamLine /^set_from_resource\s\+.*$/ contains=i3ConfigResourceKeyword,i3ConfigCondition,i3ConfigColor,i3ConfigVariable,i3ConfigString,i3ConfigNumber +syn region i3ConfigParamLine matchgroup=i3ConfigKeyword start=/set_from_resource\ze \$/ end=/$/ contained contains=@i3ConfigColVar,i3ConfigDotOperator " 4.19 Assign clients to workspaces -syn keyword i3ConfigAssignKeyword assign contained syn match i3ConfigAssignSpecial /→\|number/ contained -syn match i3ConfigAssign /^assign .*$/ contains=i3ConfigAssignKeyword,i3ConfigAssignSpecial,i3ConfigCondition,i3ConfigVariable,i3ConfigString,i3ConfigNumber +syn region i3ConfigKeyword start=/assign / end=/$/ contained contains=i3ConfigAssignSpecial,i3ConfigCondition,@i3ConfigIdent keepend " 4.20 Executing shell commands -syn keyword i3ConfigExecKeyword exec contained -syn keyword i3ConfigExecAlwaysKeyword exec_always contained -syn match i3ConfigShCmdDelim /\$(/ contained -syn region i3ConfigShCommand start=/\$(/ end=/)/ contained contains=i3ConfigShCmdDelim,i3ConfigExecAction,i3ConfigShCommand,i3ConfigShDelim,i3ConfigShOper,i3ConfigShParam,i3ConfigString,i3ConfigNumber,i3ConfigVariable keepend extend +syn region i3ConfigShCommand matchgroup=i3ConfigShDelim start=/\$(/ end=/)/ contained contains=i3ConfigExecAction,i3ConfigShCommand,i3ConfigShDelim,i3ConfigShOper,i3ConfigShParam,i3ConfigString,i3ConfigNumber,i3ConfigVariable extend syn match i3ConfigShDelim /[[\]{}();`]\+/ contained syn match i3ConfigShOper /[<>&|+=~^*!.?]\+/ contained -syn match i3ConfigShParam /\<-[0-9A-Za-z_-]\+\>/ contained containedin=i3ConfigVar -syn region i3ConfigExec start=/^\s*exec\(_always\)\?\( --no-startup-id\)\? [^{]/ skip=/\\$/ end=/$/ contains=i3ConfigExecKeyword,i3ConfigExecAlwaysKeyword,i3ConfigShCommand,i3ConfigShDelim,i3ConfigShOper,i3ConfigShParam,i3ConfigNumber,i3ConfigString,i3ConfigVariable,i3ConfigExecAction keepend +syn match i3ConfigShParam /\<-[A-Za-z-][0-9A-Za-z_-]*\>/ contained +syn cluster i3ConfigSh contains=@i3ConfigIdent,i3ConfigShOper,i3ConfigShDelim,i3ConfigShParam,i3ConfigShCommand +syn region i3ConfigExec start=/ \ze[^{]/ skip=/\\$/ end=/$/ contained contains=i3ConfigExecAction,@i3ConfigSh keepend +syn keyword i3ConfigKeyword exec_always exec contained nextgroup=i3ConfigExec " 4.21 Workspaces per output -syn keyword i3ConfigWorkspaceKeyword workspace contained -syn keyword i3ConfigWorkspaceOutput output contained -syn keyword i3ConfigWorkspaceDir prev next back_and_forth number contained -syn region i3ConfigWorkspaceLine start=/^workspace / skip=/\\$/ end=/$/ contains=i3ConfigWorkspaceKeyword,i3ConfigNumber,i3ConfigString,i3ConfigGaps,i3ConfigWorkspaceOutput,i3ConfigVariable,i3ConfigBoolean,i3ConfigSeparator keepend +syn match i3ConfigOutputIdent /[^'",; ]\+/ contained contains=@i3ConfigIdent,i3ConfigColonOperator skipwhite nextgroup=i3ConfigOutputIdent +syn region i3ConfigOutputIdent start=/['"]/ end=/\ze/ contained contains=@i3ConfigIdent skipwhite nextgroup=i3ConfigOutputIdent +syn keyword i3ConfigOutput output contained skipwhite nextgroup=i3ConfigOutputIdent +syn match i3ConfigWorkspaceIdent /[^'",; ]\+/ contained contains=@i3ConfigIdent skipwhite nextgroup=i3ConfigGaps,i3ConfigOutput +syn region i3ConfigWorkspaceIdent start=/['"]/ end=/\ze/ contained contains=@i3ConfigIdent skipwhite nextgroup=i3ConfigGaps,i3ConfigOutput +syn keyword i3ConfigKeyword workspace contained skipwhite nextgroup=i3ConfigWorkspaceIdent " 4.22 Changing colors -syn match i3ConfigDotOperator /\./ contained -syn keyword i3ConfigClientOpts focused focused_inactive unfocused urgent placeholder background contained -syn match i3ConfigKeyword /^client\..*$/ contains=i3ConfigDotOperator,i3ConfigClientOpts,i3ConfigColor,i3ConfigVariable +syn keyword i3ConfigClientOpts focused focused_inactive focused_tab_title unfocused urgent placeholder background contained skipwhite nextgroup=i3ConfigColorSeq +syn match i3ConfigDotOperator /\./ contained nextgroup=i3ConfigClientOpts +syn keyword i3ConfigKeyword client contained nextgroup=i3ConfigDotOperator " 4.23 Interprocess communication -syn match i3ConfigIpcKeyword /ipc-socket/ contained -syn match i3ConfigParamLine /^ipc-socket .*$/ contains=i3ConfigIpcKeyword +syn region i3ConfigParamLine matchgroup=i3ConfigKeyword start=/ipc-socket / end=/$/ contained contains=i3ConfigNumber,i3ConfigShOper " 4.24 Focus follows mouse -syn match i3ConfigKeyword /^focus_follows_mouse \(yes\|no\)$/ contains=i3ConfigBoolean +syn keyword i3ConfigFocusFollowsMouseOpts always contained +syn keyword i3ConfigKeyword focus_follows_mouse contained skipwhite nextgroup=i3ConfigBoolean,i3ConfigFocusFollowsMouseOpts " 4.25 Mouse warping syn keyword i3ConfigMouseWarpingOpts output container none contained -syn match i3ConfigKeyword /^mouse_warping \w*$/ contains=i3ConfigMouseWarpingOpts +syn keyword i3ConfigKeyword mouse_warping contained skipwhite nextgroup=i3ConfigMouseWarpingOpts " 4.26 Popups while fullscreen syn keyword i3ConfigPopupFullscreenOpts smart ignore leave_fullscreen contained -syn match i3ConfigKeyword /^popup_during_fullscreen \w*$/ contains=i3ConfigPopupFullscreenOpts +syn keyword i3ConfigKeyword popup_during_fullscreen contained skipwhite nextgroup=i3ConfigPopupFullscreenOpts " 4.27 Focus wrapping syn keyword i3ConfigFocusWrappingOpts force workspace contained -syn match i3ConfigKeyword /^focus_wrapping \(yes\|no\|force\|workspace\)$/ contains=i3ConfigBoolean,i3ConfigFocusWrappingOpts +syn keyword i3ConfigKeyword focus_wrapping contained skipwhite nextgroup=i3ConfigBoolean,i3ConfigFocusWrappingOpts " 4.28 Forcing Xinerama -syn match i3ConfigKeyword /^force_xinerama \(yes\|no\)$/ contains=i3ConfigBoolean - " 4.29 Automatic workspace back-and-forth -syn match i3ConfigKeyword /^workspace_auto_back_and_forth \(yes\|no\)$/ contains=i3ConfigBoolean +" 4.32 Show marks in title +syn keyword i3ConfigKeyword force_xinerama workspace_auto_back_and_forth show_marks contained skipwhite nextgroup=i3ConfigBoolean " 4.30 Delay urgency hint -syn keyword i3ConfigTimeUnit ms contained -syn match i3ConfigKeyword /^force_display_urgency_hint \d\+\( ms\)\?$/ contains=i3ConfigNumber,i3ConfigTimeUnit +syn match i3ConfigTimeUnit / \d\+\( ms\)\?$/ contained contains=i3ConfigNumber +syn keyword i3ConfigKeyword force_display_urgency_hint contained nextgroup=i3ConfigTimeUnit " 4.31 Focus on window activation syn keyword i3ConfigFocusOnActivationOpts smart urgent focus none contained -syn match i3ConfigKeyword /^focus_on_window_activation \w*$/ contains=i3ConfigFocusOnActivationOpts - -" 4.32 Show marks in title -syn match i3ConfigShowMarks /^show_marks \(yes\|no\)$/ contains=i3ConfigBoolean +syn keyword i3ConfigKeyword focus_on_window_activation contained skipwhite nextgroup=i3ConfigFocusOnActivationOpts " 4.34 Tiling drag -syn keyword i3ConfigTilingDragOpts modifier titlebar contained -syn match i3ConfigKeyword /^tiling_drag\( off\|\( modifier\| titlebar\)\{1,2\}\)$/ contains=i3ConfigTilingDragOpts,i3ConfigBoolean +syn keyword i3ConfigTilingDragOpts modifier titlebar contained skipwhite nextgroup=i3ConfigTilingDragOpts +syn keyword i3ConfigKeyword tiling_drag contained skipwhite nextgroup=i3ConfigTilingDragOpts,i3ConfigBoolean + +" 4.35 Gaps (+6.24) +syn keyword i3ConfigGapsWhich inner outer horizontal vertical left right top bottom contained skipwhite nextgroup=i3ConfigGapsWhere,@i3ConfigNumVar +syn keyword i3ConfigGapsWhere current all contained skipwhite nextgroup=i3ConfigGapsOper +syn keyword i3ConfigGapsOper set plus minus toggle contained skipwhite nextgroup=@i3ConfigNumVar +syn match i3ConfigGaps /gaps/ contained contains=i3ConfigCommand skipwhite nextgroup=i3ConfigGapsWhich +syn keyword i3ConfigCommand gaps contained skipwhite nextgroup=i3ConfigGapsWhich -" 4.35 Gaps -syn keyword i3ConfigGapsOpts inner outer horizontal vertical left right top bottom current all set plus minus toggle contained -syn region i3ConfigGaps start=/gaps/ skip=/\\$/ end=/[,;]\|$/ contained contains=i3ConfigGapsOpts,i3ConfigNumber,i3ConfigVariable,i3ConfigSeparator keepend -syn match i3ConfigGapsLine /^gaps .*$/ contains=i3ConfigGaps -syn keyword i3ConfigSmartGapOpts inverse_outer contained -syn match i3ConfigKeyword /^smart_gaps \(on\|off\|inverse_outer\)$/ contains=i3ConfigSmartGapOpts,i3ConfigBoolean +syn keyword i3ConfigSmartGapOpts inverse_outer toggle contained +syn keyword i3ConfigKeyword smart_gaps contained skipwhite nextgroup=i3ConfigSmartGapOpts,i3ConfigBoolean " 5 Configuring bar -syn match i3ConfigBarModifier /^\s\+modifier \S\+$/ contained contains=i3ConfigBindModifier,i3ConfigVariable,i3ConfigBindModkey,i3ConfigBarOptVals -syn keyword i3ConfigBarOpts bar i3bar_command status_command workspace_command mode hidden_state id position output tray_output tray_padding separator_symbol workspace_buttons workspace_min_width strip_workspace_numbers strip_workspace_name binding_mode_indicator padding contained +syn keyword i3ConfigBarOpts modifier contained skipwhite nextgroup=i3ConfigBindCombo,i3ConfigBarOptVals +syn keyword i3ConfigBarOpts i3bar_command status_command workspace_command contained skipwhite nextgroup=@i3ConfigSh +syn keyword i3ConfigBarOpts mode hidden_state id position output tray_output tray_padding separator_symbol workspace_buttons workspace_min_width strip_workspace_numbers strip_workspace_name binding_mode_indicator padding contained skipwhite nextgroup=i3ConfigBarOptVals,@i3ConfigValue,i3ConfigShOper syn keyword i3ConfigBarOptVals dock hide invisible show none top bottom primary nonprimary contained -syn region i3ConfigBarBlock start=/^bar {$/ end=/^}$/ contains=i3ConfigBarOpts,i3ConfigBarOptVals,i3ConfigBarModifier,i3ConfigBind,i3ConfigString,i3ConfigComment,i3ConfigFont,i3ConfigBoolean,i3ConfigNumber,i3ConfigParen,i3ConfigColor,i3ConfigVariable,i3ConfigColorsBlock,i3ConfigShOper,i3ConfigShCommand fold keepend extend +syn region i3ConfigBarBlock matchgroup=i3ConfigKeyword start=/bar\ze {$/ end=/^\s*}\zs$/ contained contains=i3ConfigBarOpts,i3ConfigComment,i3ConfigParen,i3ConfigBindKeyword,i3ConfigColorsBlock fold keepend extend " 5.16 Color block -syn keyword i3ConfigColorsKeyword colors contained -syn match i3ConfigColorsOpts /\(focused_\)\?\(background\|statusline\|separator\)\|\(focused\|active\|inactive\|urgent\)_workspace\|binding_mode/ contained -syn region i3ConfigColorsBlock start=/^\s\+colors {$/ end=/^\s\+}$/ contained contains=i3ConfigColorsKeyword,i3ConfigColorsOpts,i3ConfigColor,i3ConfigVariable,i3ConfigComment,i3ConfigParen fold keepend extend +syn match i3ConfigColorSeq /#[0-9A-Fa-f]\{3,8}\|\$[0-9A-Za-z_:|[\]-]\+/ contained contains=@i3ConfigColVar skipwhite nextgroup=i3ConfigColorSeq +syn keyword i3ConfigColorsOpts background statusline separator contained skipwhite nextgroup=@i3ConfigColVar +syn match i3ConfigColorsOpts /focused_\(background\|statusline\|separator\)\|\(focused\|active\|inactive\|urgent\)_workspace\|binding_mode/ contained skipwhite nextgroup=i3ConfigColorSeq +syn region i3ConfigColorsBlock matchgroup=i3ConfigKeyword start=/^\s\+colors \ze{$/ end=/^\s\+}\zs$/ contained contains=i3ConfigColorsOpts,i3ConfigComment,i3ConfigParen fold keepend extend " 6.0 Command criteria syn keyword i3ConfigConditionProp class instance window_role window_type machine id title urgent workspace con_mark con_id floating_from tiling_from contained syn keyword i3ConfigConditionSpecial __focused__ all floating tiling contained -syn region i3ConfigCondition start=/\[/ end=/\]/ contained contains=i3ConfigShDelim,i3ConfigConditionProp,i3ConfigShOper,i3ConfigConditionSpecial,i3ConfigNumber,i3ConfigString keepend extend -syn region i3ConfigCriteria start=/\[/ skip=/\\$/ end=/\(;\|$\)/ contained contains=i3ConfigCondition,i3ConfigAction,i3ConfigActionKeyword,i3ConfigOption,i3ConfigBoolean,i3ConfigNumber,i3ConfigVariable,i3ConfigSeparator keepend transparent +syn region i3ConfigCondition matchgroup=i3ConfigShDelim start=/\[/ end=/\]/ contained contains=i3ConfigConditionProp,i3ConfigShOper,i3ConfigConditionSpecial,@i3ConfigIdent keepend extend +syn region i3ConfigCriteria start=/\[/ skip=/\\$/ end=/\(;\|$\)/ contained contains=i3ConfigCondition,@i3ConfigCommand,i3ConfigSeparator keepend transparent " 6.1 Actions through shell syn match i3ConfigExecActionKeyword /i3-msg/ contained -syn region i3ConfigExecAction start=/[a-z3-]\+msg "/ skip=/ "\|\\$/ end=/"\|$/ contained contains=i3ConfigExecActionKeyword,i3ConfigShCommand,i3ConfigNumber,i3ConfigShOper,i3ConfigCriteria,i3ConfigAction,i3ConfigActionKeyword,i3ConfigOption,i3ConfigVariable keepend extend -syn region i3ConfigExecAction start=/[a-z3-]\+msg '/ skip=/ '\|\\$/ end=/'\|$/ contained contains=i3ConfigExecActionKeyword,i3ConfigShCommand,i3ConfigNumber,i3ConfigShOper,i3ConfigCriteria,i3ConfigAction,i3ConfigActionKeyword,i3ConfigOption,i3ConfigVariable keepend extend -syn region i3ConfigExecAction start=/[a-z3-]\+msg ['"-]\@!/ skip=/\\$/ end=/[&|;})'"]\@=\|$/ contained contains=i3ConfigExecActionKeyword,i3ConfigShCommand,i3ConfigNumber,i3ConfigShOper,i3ConfigCriteria,i3ConfigAction,i3ConfigActionKeyword,i3ConfigOption,i3ConfigVariable keepend extend +syn cluster i3ConfigExecActionVal contains=i3ConfigExecActionKeyword,i3ConfigCriteria,i3ConfigAction,i3ConfigActionKeyword,i3ConfigOption,@i3ConfigNumVar +syn region i3ConfigExecAction start=/[a-z3-]\+msg "/ skip=/ "\|\\$/ end=/"\|$/ contained contains=i3ConfigExecActionKeyword,@i3ConfigExecActionVal keepend extend +syn region i3ConfigExecAction start=/[a-z3-]\+msg '/ skip=/ '\|\\$/ end=/'\|$/ contained contains=i3ConfigExecActionKeyword,@i3ConfigExecActionVal keepend extend +syn region i3ConfigExecAction start=/[a-z3-]\+msg ['"-]\@!/ skip=/\\$/ end=/[&|;})'"]\@=\|$/ contained contains=i3ConfigExecActionKeyword,@i3ConfigExecActionVal keepend extend " 6.1 Executing applications (4.20) -syn region i3ConfigAction start=/exec/ skip=/\\$/ end=/[,;]\|$/ contained contains=i3ConfigExecKeyword,i3ConfigExecAction,i3ConfigShCommand,i3ConfigShDelim,i3ConfigShOper,i3ConfigShParam,i3ConfigNumber,i3ConfigString,i3ConfigVariable,i3ConfigSeparator keepend +syn region i3ConfigAction matchgroup=i3ConfigCommand start=/exec / skip=/\\$/ end=/\ze[,;]\|$/ contained contains=i3ConfigExecAction,@i3ConfigSh keepend " 6.3 Manipulating layout -syn keyword i3ConfigLayoutKeyword layout contained syn keyword i3ConfigLayoutOpts default tabbed stacking splitv splith toggle split all contained -syn region i3ConfigAction start=/layout/ skip=/\\$/ end=/[,;]\|$/ contained contains=i3ConfigLayoutKeyword,i3ConfigLayoutOpts,i3ConfigSeparator keepend transparent +syn region i3ConfigAction matchgroup=i3ConfigCommand start=/layout / skip=/\\$/ end=/\ze[,;]\|$/ contained contains=i3ConfigLayoutOpts keepend transparent " 6.4 Focusing containers -syn keyword i3ConfigFocusKeyword focus contained -syn keyword i3ConfigFocusOpts left right up down workspace parent child next prev sibling floating tiling mode_toggle contained -syn keyword i3ConfigFocusOutputOpts left right down up current primary nonprimary next prev contained -syn region i3ConfigFocusOutput start=/ output / skip=/\\$/ end=/[,;]\|$/ contained contains=i3ConfigWorkspaceOutput,i3ConfigFocusOutputOpts,i3ConfigString,i3ConfigNumber,i3ConfigSeparator keepend -syn match i3ConfigFocusOutputLine /^focus output .*$/ contains=i3ConfigFocusKeyword,i3ConfigFocusOutput -syn region i3ConfigAction start=/focus/ skip=/\\$/ end=/[,;]\|$/ contained contains=i3ConfigFocusKeyword,i3ConfigFocusOpts,i3ConfigFocusOutput,i3ConfigString,i3ConfigSeparator keepend transparent +syn keyword i3ConfigFocusOpts left right up down parent child next prev sibling floating tiling mode_toggle contained +syn keyword i3ConfigOutputDir left right down up current primary nonprimary next prev contained skipwhite +syn keyword i3ConfigFocusOutput output contained skipwhite nextgroup=i3ConfigOutputIdent,i3ConfigOutputDir +syn keyword i3ConfigActionKeyword focus contained skipwhite nextgroup=i3ConfigFocusOpts,i3ConfigFocusOutput +syn keyword i3ConfigKeyword focus skipwhite contained nextgroup=i3ConfigFocusOutput " 6.8 Focusing workspaces (4.21) -syn region i3ConfigAction start=/workspace / skip=/\\$/ end=/[,;]\|$/ contained contains=i3ConfigWorkspaceKeyword,i3ConfigWorkspaceDir,i3ConfigNumber,i3ConfigString,i3ConfigGaps,i3ConfigWorkspaceOutput,i3ConfigVariable,i3ConfigBoolean,i3ConfigSeparator keepend transparent +syn keyword i3ConfigWorkspaceDir prev next back_and_forth contained +syn keyword i3ConfigWorkspaceDir number contained skipwhite nextgroup=i3ConfigWorkspaceIdent +syn keyword i3ConfigActionKeyword workspace contained skipwhite nextgroup=i3ConfigWorkspaceDir,i3ConfigWorkspaceIdent " 6.8.2 Renaming workspaces -syn keyword i3ConfigRenameKeyword rename contained -syn region i3ConfigAction start=/rename workspace/ end=/[,;]\|$/ contained contains=i3ConfigRenameKeyword,i3ConfigMoveDir,i3ConfigMoveType,i3ConfigNumber,i3ConfigVariable,i3ConfigString keepend transparent +syn region i3ConfigWorkspaceFromTo start=/workspace\( .*\)\? to/ end=/\ze[,;]\|$/ contained contains=i3ConfigMoveType,@i3ConfigWorkspaceIdent keepend transparent +syn keyword i3ConfigActionKeyword rename contained skipwhite nextgroup=i3ConfigWorkspaceFromTo " 6.5,6.9-6.11 Moving containers -syn keyword i3ConfigMoveKeyword move contained -syn keyword i3ConfigMoveDir left right down up position absolute center to current contained -syn keyword i3ConfigMoveType window container workspace output mark mouse scratchpad contained -syn match i3ConfigUnit / px\| ppt/ contained -syn region i3ConfigAction start=/move/ skip=/\\$/ end=/[,;]\|$/ contained contains=i3ConfigMoveKeyword,i3ConfigMoveDir,i3ConfigMoveType,i3ConfigWorkspaceDir,i3ConfigUnit,i3ConfigNumber,i3ConfigVariable,i3ConfigString,i3ConfigSeparator,i3ConfigShParam keepend transparent +syn match i3ConfigUnit /-\?\d\+\( px\| ppt\)\?/ contained contains=i3ConfigNumber skipwhite nextgroup=i3ConfigUnit,i3ConfigResizeExtra +syn keyword i3ConfigMoveDir left right down up position contained skipwhite nextgroup=i3ConfigUnit +syn match i3ConfigMoveDir /position \(mouse\|center\)/ contained +syn keyword i3ConfigMoveDir absolute contained skipwhite nextgroup=i3ConfigMoveDir +syn keyword i3ConfigMoveDir absolute contained + +syn keyword i3ConfigMoveType mark contained skipwhite nextgroup=i3ConfigOutputIdent +syn keyword i3ConfigMoveType scratchpad contained +syn keyword i3ConfigMoveType output contained skipwhite nextgroup=i3ConfigOutputIdent,i3ConfigOutputDir +syn keyword i3ConfigMoveType workspace contained skipwhite nextgroup=i3ConfigMoveType,i3ConfigWorkspaceIdent,i3ConfigWorkspaceDir +syn keyword i3ConfigMoveType window container contained skipwhite nextgroup=i3ConfigMoveType +syn keyword i3ConfigMoveTo to contained +syn match i3ConfigMoveType /to/ contained contains=i3ConfigMoveTo skipwhite nextgroup=i3ConfigMoveType +syn match i3ConfigActionKeyword /move\( --no-auto-back-and-forth\)\?/ contained contains=i3ConfigShParam skipwhite nextgroup=i3ConfigMoveType,i3ConfigMoveDir " 6.12 Resizing containers/windows -syn keyword i3ConfigResizeKeyword resize contained -syn keyword i3ConfigResizeOpts grow shrink up down left right set width height or contained -syn region i3ConfigAction start=/resize/ skip=/\\$/ end=/[,;]\|$/ contained contains=i3ConfigResizeKeyword,i3ConfigResizeOpts,i3ConfigNumber,i3ConfigUnit,i3ConfigSeparator keepend transparent +syn keyword i3ConfigResizeExtra or height contained skipwhite nextgroup=i3ConfigUnit +syn keyword i3ConfigResizeDir up down left right width height contained skipwhite nextgroup=i3ConfigUnit +syn keyword i3ConfigResizeType grow shrink contained skipwhite nextgroup=i3ConfigResizeDir +syn keyword i3ConfigResizeType set contained skipwhite nextgroup=i3ConfigResizeDir,i3ConfigUnit +syn keyword i3ConfigActionKeyword resize contained skipwhite nextgroup=i3ConfigResizeType " 6.14 VIM-like marks -syn match i3ConfigMark /mark\( --\(add\|replace\)\( --toggle\)\?\)\?/ contained contains=i3ConfigShParam -syn region i3ConfigAction start=/\<mark/ skip=/\\$/ end=/[,;]\|$/ contained contains=i3ConfigMark,i3ConfigNumber,i3ConfigString,i3ConfigSeparator keepend transparent +syn match i3ConfigMarkOpt /--\(add\|replace\)\( --toggle\)\?/ contained contains=i3ConfigShParam skipwhite nextgroup=i3ConfigOutputIdent +syn keyword i3ConfigActionKeyword mark contained skipwhite nextgroup=i3ConfigMarkOpt,i3ConfigOutputIdent -" 6.24 Changing gaps (4.35) -syn region i3ConfigAction start=/gaps/ skip=/\\$/ end=/[,;]\|$/ contained contains=i3ConfigGaps keepend transparent +" Commands usable for direct config calls - for enforcing start of line for Commands +syn match i3ConfigTopLevelDirective /^\s*/ nextgroup=i3ConfigComment,i3ConfigKeyword,i3ConfigCommand,i3ConfigBindKeyword,i3ConfigParamLine,i3ConfigModeBlock,i3ConfigBarBlock,i3ConfigError " Commands useable in keybinds -syn keyword i3ConfigActionKeyword mode append_layout kill open fullscreen sticky split floating swap unmark show_marks title_window_icon title_format border restart reload exit scratchpad nop bar contained -syn keyword i3ConfigOption default enable disable toggle key restore current horizontal vertical auto none normal pixel show container with id con_id padding hidden_state hide dock invisible contained +syn keyword i3ConfigActionKeyword mode append_layout kill open fullscreen sticky split floating swap unmark title_window_icon title_format border restart reload exit scratchpad nop bar contained skipwhite nextgroup=i3ConfigOption,@i3ConfigValue +syn keyword i3ConfigOption default enable disable toggle key restore current horizontal vertical auto none normal pixel show container with id con_id padding hidden_state hide dock invisible contained skipwhite nextgroup=i3ConfigOption,@i3ConfigValue +" Commands usable at runtime (outside loading config) +syn cluster i3ConfigCommand contains=i3ConfigCommand,i3ConfigAction,i3ConfigActionKeyword,@i3ConfigValue,i3ConfigColor " Define the highlighting. hi def link i3ConfigError Error @@ -260,18 +281,15 @@ hi def link i3ConfigBoolean Boolean hi def link i3ConfigString String hi def link i3ConfigColor Constant hi def link i3ConfigNumber Number -hi def link i3ConfigIncludeKeyword i3ConfigKeyword hi def link i3ConfigComment Comment -hi def link i3ConfigFontKeyword i3ConfigKeyword hi def link i3ConfigColonOperator i3ConfigOperator hi def link i3ConfigFontNamespace i3ConfigOption hi def link i3ConfigFontSize i3ConfigNumber -hi def link i3ConfigFont i3ConfigString -hi def link i3ConfigBindKeyword i3ConfigKeyword hi def link i3ConfigBindArgument i3ConfigShParam hi def link i3ConfigBindModifier i3ConfigOperator hi def link i3ConfigBindModkey Special hi def link i3ConfigBindCombo SpecialChar +hi def link i3ConfigBindKeyword i3ConfigKeyword hi def link i3ConfigSizeSpecial i3ConfigOperator hi def link i3ConfigOrientationOpts i3ConfigOption hi def link i3ConfigWorkspaceLayoutOpts i3ConfigOption @@ -280,54 +298,47 @@ hi def link i3ConfigBorderOpts i3ConfigOption hi def link i3ConfigEdgeOpts i3ConfigOption hi def link i3ConfigSmartBorderOpts i3ConfigOption hi def link i3ConfigVariable Variable -hi def link i3ConfigSetKeyword i3ConfigKeyword -hi def link i3ConfigResourceKeyword i3ConfigKeyword -hi def link i3ConfigAssignKeyword i3ConfigKeyword hi def link i3ConfigAssignSpecial i3ConfigOption -hi def link i3ConfigExecKeyword i3ConfigCommand -hi def link i3ConfigExecAlwaysKeyword i3ConfigKeyword hi def link i3ConfigShParam PreProc hi def link i3ConfigShDelim Delimiter hi def link i3ConfigShOper Operator -hi def link i3ConfigShCmdDelim i3ConfigShDelim hi def link i3ConfigShCommand Normal -hi def link i3ConfigWorkspaceKeyword i3ConfigCommand -hi def link i3ConfigWorkspaceOutput i3ConfigMoveType -hi def link i3ConfigWorkspaceDir i3ConfigOption +hi def link i3ConfigOutputIdent i3ConfigParamLine +hi def link i3ConfigOutput i3ConfigMoveType +hi def link i3ConfigWorkspaceIdent i3ConfigParamLine hi def link i3ConfigDotOperator i3ConfigOperator hi def link i3ConfigClientOpts i3ConfigOption -hi def link i3ConfigIpcKeyword i3ConfigKeyword +hi def link i3ConfigFocusFollowsMouseOpts i3ConfigOption hi def link i3ConfigMouseWarpingOpts i3ConfigOption hi def link i3ConfigPopupFullscreenOpts i3ConfigOption hi def link i3ConfigFocusWrappingOpts i3ConfigOption hi def link i3ConfigTimeUnit i3ConfigNumber hi def link i3ConfigFocusOnActivationOpts i3ConfigOption -hi def link i3ConfigShowMarks i3ConfigCommand hi def link i3ConfigTilingDragOpts i3ConfigOption -hi def link i3ConfigGapsOpts i3ConfigOption -hi def link i3ConfigGaps i3ConfigCommand +hi def link i3ConfigGapsWhich i3ConfigOption +hi def link i3ConfigGapsWhere i3ConfigOption +hi def link i3ConfigGapsOper i3ConfigOption hi def link i3ConfigSmartGapOpts i3ConfigOption hi def link i3ConfigBarModifier i3ConfigKeyword hi def link i3ConfigBarOpts i3ConfigKeyword hi def link i3ConfigBarOptVals i3ConfigOption -hi def link i3ConfigColorsKeyword i3ConfigKeyword hi def link i3ConfigColorsOpts i3ConfigOption hi def link i3ConfigConditionProp i3ConfigShParam hi def link i3ConfigConditionSpecial Constant hi def link i3ConfigExecActionKeyword i3ConfigShCommand hi def link i3ConfigExecAction i3ConfigString -hi def link i3ConfigLayoutKeyword i3ConfigCommand hi def link i3ConfigLayoutOpts i3ConfigOption -hi def link i3ConfigFocusKeyword i3ConfigCommand hi def link i3ConfigFocusOpts i3ConfigOption -hi def link i3ConfigFocusOutputOpts i3ConfigOption -hi def link i3ConfigRenameKeyword i3ConfigCommand -hi def link i3ConfigMoveKeyword i3ConfigCommand +hi def link i3ConfigOutputDir i3ConfigOption +hi def link i3ConfigFocusOutput i3ConfigOutput +hi def link i3ConfigWorkspaceDir i3ConfigOption hi def link i3ConfigMoveDir i3ConfigOption hi def link i3ConfigMoveType Constant +hi def link i3ConfigMoveTo i3ConfigOption hi def link i3ConfigUnit i3ConfigNumber -hi def link i3ConfigResizeKeyword i3ConfigCommand -hi def link i3ConfigResizeOpts i3ConfigOption +hi def link i3ConfigResizeExtra i3ConfigOption +hi def link i3ConfigResizeDir i3ConfigOption +hi def link i3ConfigResizeType i3ConfigOption hi def link i3ConfigMark i3ConfigCommand hi def link i3ConfigActionKeyword i3ConfigCommand hi def link i3ConfigOption Type diff --git a/runtime/syntax/java.vim b/runtime/syntax/java.vim index f6d2660277..9867b147c2 100644 --- a/runtime/syntax/java.vim +++ b/runtime/syntax/java.vim @@ -1,8 +1,9 @@ " Vim syntax file -" Language: Java -" Maintainer: Claudio Fleiner <claudio@fleiner.com> -" URL: https://github.com/fleiner/vim/blob/master/runtime/syntax/java.vim -" Last Change: 2024 Mar 02 +" Language: Java +" 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 May 10 " Please check :help java.vim for comments on some of the options available. @@ -19,6 +20,34 @@ endif let s:cpo_save = &cpo set cpo&vim +"""" STRIVE TO REMAIN COMPATIBLE FOR AT LEAST VIM 7.0. +let s:ff = {} + +function! s:ff.LeftConstant(x, y) abort + return a:x +endfunction + +function! s:ff.RightConstant(x, y) abort + return a:y +endfunction + +if !exists("*s:ReportOnce") + function s:ReportOnce(message) abort + echomsg 'syntax/java.vim: ' . a:message + endfunction +else + function! s:ReportOnce(dummy) + endfunction +endif + +" Admit the ASCII dollar sign to keyword characters (JLS-17, §3.8): +try + exec 'syntax iskeyword ' . &l:iskeyword . ',$' +catch /\<E410:/ + call s:ReportOnce(v:exception) + setlocal iskeyword+=$ +endtry + " some characters that cannot be in a java program (outside a string) syn match javaError "[\\@`]" syn match javaError "<<<\|\.\.\|=>\|||=\|&&=\|\*\/" @@ -27,16 +56,18 @@ syn match javaError "<<<\|\.\.\|=>\|||=\|&&=\|\*\/" syn match javaError2 "#\|=<" hi def link javaError2 javaError -" keyword definitions +" Keywords (JLS-17, §3.9): syn keyword javaExternal native package -syn match javaExternal "\<import\>\(\s\+static\>\)\?" +syn match javaExternal "\<import\>\%(\s\+static\>\)\=" syn keyword javaError goto const syn keyword javaConditional if else switch syn keyword javaRepeat while for do syn keyword javaBoolean true false syn keyword javaConstant null syn keyword javaTypedef this super -syn keyword javaOperator var new instanceof +syn keyword javaOperator new instanceof +syn match javaOperator "\<var\>\%(\s*(\)\@!" + " Since the yield statement, which could take a parenthesised operand, " and _qualified_ yield methods get along within the switch block " (JLS-17, §3.8), it seems futile to make a region definition for this @@ -44,38 +75,63 @@ syn keyword javaOperator var new instanceof " backtrack (arbitrarily) 80 bytes, at most, on the matched line and, " if necessary, on the line before that (h: \@<=), trying to match " neither a method reference nor a qualified method invocation. -syn match javaOperator "\%(\%(::\|\.\)[[:space:]\n]*\)\@80<!\<yield\>" +try + syn match javaOperator "\%(\%(::\|\.\)[[:space:]\n]*\)\@80<!\<yield\>" + let s:ff.Peek = s:ff.LeftConstant +catch /\<E59:/ + call s:ReportOnce(v:exception) + syn match javaOperator "\%(\%(::\|\.\)[[:space:]\n]*\)\@<!\<yield\>" + let s:ff.Peek = s:ff.RightConstant +endtry + syn keyword javaType boolean char byte short int long float double syn keyword javaType void syn keyword javaStatement return -syn keyword javaStorageClass static synchronized transient volatile final strictfp serializable +syn keyword javaStorageClass static synchronized transient volatile strictfp serializable syn keyword javaExceptions throw try catch finally syn keyword javaAssert assert -syn keyword javaMethodDecl synchronized throws -syn keyword javaClassDecl extends implements interface -" to differentiate the keyword class from MyClass.class we use a match here +syn keyword javaMethodDecl throws +" Differentiate a "MyClass.class" literal from the keyword "class". syn match javaTypedef "\.\s*\<class\>"ms=s+1 -syn keyword javaClassDecl enum +syn keyword javaClassDecl enum extends implements interface +syn match javaClassDecl "\<permits\>\%(\s*(\)\@!" +syn match javaClassDecl "\<record\>\%(\s*(\)\@!" syn match javaClassDecl "^class\>" syn match javaClassDecl "[^.]\s*\<class\>"ms=s+1 -syn match javaAnnotation "@\([_$a-zA-Z][_$a-zA-Z0-9]*\.\)*[_$a-zA-Z][_$a-zA-Z0-9]*\>" contains=javaString +syn match javaAnnotation "@\%(\K\k*\.\)*\K\k*\>" syn match javaClassDecl "@interface\>" syn keyword javaBranch break continue nextgroup=javaUserLabelRef skipwhite syn match javaUserLabelRef "\k\+" contained syn match javaVarArg "\.\.\." -syn keyword javaScopeDecl public protected private abstract +syn keyword javaScopeDecl public protected private +syn keyword javaConceptKind abstract final +syn match javaConceptKind "\<non-sealed\>" +syn match javaConceptKind "\<sealed\>\%(\s*(\)\@!" syn match javaConceptKind "\<default\>\%(\s*\%(:\|->\)\)\@!" -function s:isModuleInfoDeclarationCurrentBuffer() abort - return fnamemodify(bufname("%"), ":t") =~ '^module-info\%(\.class\>\)\@!' -endfunction +" Note that a "module-info" file will be recognised with an arbitrary +" file extension (or no extension at all) so that more than one such +" declaration for the same Java module can be maintained for modular +" testing in a project without attendant confusion for IDEs, with the +" ".java\=" extension used for a production version and an arbitrary +" extension used for a testing version. +let s:module_info_cur_buf = fnamemodify(bufname("%"), ":t") =~ '^module-info\%(\.class\>\)\@!' +lockvar s:module_info_cur_buf + +if !(v:version < 704) + " Request the new regexp engine for [:upper:] and [:lower:]. + let [s:ff.Engine, s:ff.UpperCase, s:ff.LowerCase] = repeat([s:ff.LeftConstant], 3) +else + " XXX: \C\<[^a-z0-9]\k*\> rejects "type", but matches "τύπος". + " XXX: \C\<[^A-Z0-9]\k*\> rejects "Method", but matches "Μέθοδος". + let [s:ff.Engine, s:ff.UpperCase, s:ff.LowerCase] = repeat([s:ff.RightConstant], 3) +endif -" Java Modules(Since Java 9, for "module-info.java" file) -if s:isModuleInfoDeclarationCurrentBuffer() - syn keyword javaModuleStorageClass module transitive - syn keyword javaModuleStmt open requires exports opens uses provides - syn keyword javaModuleExternal to with - syn cluster javaTop add=javaModuleStorageClass,javaModuleStmt,javaModuleExternal +" Java modules (since Java 9, for "module-info.java" file). +if s:module_info_cur_buf + syn keyword javaModuleStorageClass module transitive + syn keyword javaModuleStmt open requires exports opens uses provides + syn keyword javaModuleExternal to with endif if exists("java_highlight_java_lang_ids") @@ -91,35 +147,33 @@ if exists("java_highlight_all") || exists("java_highlight_java") || exists("ja " keywords can be pre-sorted and appended without disturbing " the current keyword placement. The below _match_es follow suit. - syn keyword javaR_JavaLang ArithmeticException ArrayIndexOutOfBoundsException ArrayStoreException ClassCastException IllegalArgumentException IllegalMonitorStateException IllegalThreadStateException IndexOutOfBoundsException NegativeArraySizeException NullPointerException NumberFormatException RuntimeException SecurityException StringIndexOutOfBoundsException IllegalStateException UnsupportedOperationException EnumConstantNotPresentException TypeNotPresentException IllegalCallerException LayerInstantiationException - syn cluster javaTop add=javaR_JavaLang + syn keyword javaR_JavaLang ArithmeticException ArrayIndexOutOfBoundsException ArrayStoreException ClassCastException IllegalArgumentException IllegalMonitorStateException IllegalThreadStateException IndexOutOfBoundsException NegativeArraySizeException NullPointerException NumberFormatException RuntimeException SecurityException StringIndexOutOfBoundsException IllegalStateException UnsupportedOperationException EnumConstantNotPresentException TypeNotPresentException IllegalCallerException LayerInstantiationException WrongThreadException MatchException syn cluster javaClasses add=javaR_JavaLang hi def link javaR_JavaLang javaR_Java " Member enumerations: - syn match javaC_JavaLang "\%(\<Thread\.\)\@<=\<State\>" - syn match javaC_JavaLang "\%(\<Character\.\)\@<=\<UnicodeScript\>" - syn match javaC_JavaLang "\%(\<ProcessBuilder\.Redirect\.\)\@<=\<Type\>" - syn match javaC_JavaLang "\%(\<StackWalker\.\)\@<=\<Option\>" - syn match javaC_JavaLang "\%(\<System\.Logger\.\)\@<=\<Level\>" + exec 'syn match javaC_JavaLang "\%(\<Thread\.\)\@' . s:ff.Peek('7', '') . '<=\<State\>"' + exec 'syn match javaC_JavaLang "\%(\<Character\.\)\@' . s:ff.Peek('10', '') . '<=\<UnicodeScript\>"' + exec 'syn match javaC_JavaLang "\%(\<ProcessBuilder\.Redirect\.\)\@' . s:ff.Peek('24', '') . '<=\<Type\>"' + exec 'syn match javaC_JavaLang "\%(\<StackWalker\.\)\@' . s:ff.Peek('12', '') . '<=\<Option\>"' + exec 'syn match javaC_JavaLang "\%(\<System\.Logger\.\)\@' . s:ff.Peek('14', '') . '<=\<Level\>"' " Member classes: - syn match javaC_JavaLang "\%(\<Character\.\)\@<=\<Subset\>" - syn match javaC_JavaLang "\%(\<Character\.\)\@<=\<UnicodeBlock\>" - syn match javaC_JavaLang "\%(\<ProcessBuilder\.\)\@<=\<Redirect\>" - syn match javaC_JavaLang "\%(\<ModuleLayer\.\)\@<=\<Controller\>" - syn match javaC_JavaLang "\%(\<Runtime\.\)\@<=\<Version\>" - syn match javaC_JavaLang "\%(\<System\.\)\@<=\<LoggerFinder\>" - syn match javaC_JavaLang "\%(\<Enum\.\)\@<=\<EnumDesc\>" + exec 'syn match javaC_JavaLang "\%(\<Character\.\)\@' . s:ff.Peek('10', '') . '<=\<Subset\>"' + exec 'syn match javaC_JavaLang "\%(\<Character\.\)\@' . s:ff.Peek('10', '') . '<=\<UnicodeBlock\>"' + exec 'syn match javaC_JavaLang "\%(\<ProcessBuilder\.\)\@' . s:ff.Peek('15', '') . '<=\<Redirect\>"' + exec 'syn match javaC_JavaLang "\%(\<ModuleLayer\.\)\@' . s:ff.Peek('12', '') . '<=\<Controller\>"' + exec 'syn match javaC_JavaLang "\%(\<Runtime\.\)\@' . s:ff.Peek('8', '') . '<=\<Version\>"' + exec 'syn match javaC_JavaLang "\%(\<System\.\)\@' . s:ff.Peek('7', '') . '<=\<LoggerFinder\>"' + exec 'syn match javaC_JavaLang "\%(\<Enum\.\)\@' . s:ff.Peek('5', '') . '<=\<EnumDesc\>"' syn keyword javaC_JavaLang Boolean Character Class ClassLoader Compiler Double Float Integer Long Math Number Object Process Runtime SecurityManager String StringBuffer Thread ThreadGroup Byte Short Void InheritableThreadLocal Package RuntimePermission ThreadLocal StrictMath StackTraceElement Enum ProcessBuilder StringBuilder ClassValue Module ModuleLayer StackWalker Record syn match javaC_JavaLang "\<System\>" " See javaDebug. - syn cluster javaTop add=javaC_JavaLang + " As of JDK 21, java.lang.Compiler is no more (deprecated in JDK 9). + syn keyword javaLangDeprecated Compiler syn cluster javaClasses add=javaC_JavaLang hi def link javaC_JavaLang javaC_Java syn keyword javaE_JavaLang AbstractMethodError ClassCircularityError ClassFormatError Error IllegalAccessError IncompatibleClassChangeError InstantiationError InternalError LinkageError NoClassDefFoundError NoSuchFieldError NoSuchMethodError OutOfMemoryError StackOverflowError ThreadDeath UnknownError UnsatisfiedLinkError VerifyError VirtualMachineError ExceptionInInitializerError UnsupportedClassVersionError AssertionError BootstrapMethodError - syn cluster javaTop add=javaE_JavaLang syn cluster javaClasses add=javaE_JavaLang hi def link javaE_JavaLang javaE_Java syn keyword javaX_JavaLang ClassNotFoundException CloneNotSupportedException Exception IllegalAccessException InstantiationException InterruptedException NoSuchMethodException Throwable NoSuchFieldException ReflectiveOperationException - syn cluster javaTop add=javaX_JavaLang syn cluster javaClasses add=javaX_JavaLang hi def link javaX_JavaLang javaX_Java @@ -135,10 +189,9 @@ if exists("java_highlight_all") || exists("java_highlight_java") || exists("ja syn keyword javaLangObject clone equals finalize getClass hashCode syn keyword javaLangObject notify notifyAll toString wait hi def link javaLangObject javaConstant - syn cluster javaTop add=javaLangObject endif -if filereadable(expand("<sfile>:p:h")."/javaid.vim") +if filereadable(expand("<sfile>:p:h") . "/javaid.vim") source <sfile>:p:h/javaid.vim endif @@ -151,7 +204,7 @@ if exists("java_space_errors") endif endif -syn match javaUserLabel "^\s*\<\K\k*\>\%(\<default\>\)\@<!\s*:"he=e-1 +exec 'syn match javaUserLabel "^\s*\<\K\k*\>\%(\<default\>\)\@' . s:ff.Peek('7', '') . '<!\s*:"he=e-1' syn region javaLabelRegion transparent matchgroup=javaLabel start="\<case\>" matchgroup=NONE end=":\|->" contains=javaLabelCastType,javaLabelNumber,javaCharacter,javaString,javaConstant,@javaClasses,javaLabelDefault,javaLabelVarType,javaLabelWhenClause syn region javaLabelRegion transparent matchgroup=javaLabel start="\<default\>\%(\s*\%(:\|->\)\)\@=" matchgroup=NONE end=":\|->" oneline " Consider grouped _default_ _case_ labels, i.e. @@ -170,13 +223,6 @@ hi def link javaLabelVarType javaOperator hi def link javaLabelNumber javaNumber hi def link javaLabelCastType javaType -" highlighting C++ keywords as errors removed, too many people find it -" annoying. Was: if !exists("java_allow_cpp_keywords") - -" The following cluster contains all java groups except the contained ones -syn cluster javaTop add=javaExternal,javaError,javaBranch,javaLabelRegion,javaConditional,javaRepeat,javaBoolean,javaConstant,javaTypedef,javaOperator,javaType,javaStatement,javaStorageClass,javaAssert,javaExceptions,javaMethodDecl,javaClassDecl,javaScopeDecl,javaConceptKind,javaError2,javaUserLabel,javaLangObject,javaAnnotation,javaVarArg - - " Comments syn keyword javaTodo contained TODO FIXME XXX @@ -187,39 +233,56 @@ if exists("java_comment_strings") syn match javaCommentCharacter contained "'\\[^']\{1,6\}'" contains=javaSpecialChar syn match javaCommentCharacter contained "'\\''" contains=javaSpecialChar syn match javaCommentCharacter contained "'[^\\]'" - syn cluster javaCommentSpecial add=javaCommentString,javaCommentCharacter,javaNumber - syn cluster javaCommentSpecial2 add=javaComment2String,javaCommentCharacter,javaNumber + syn cluster javaCommentSpecial add=javaCommentString,javaCommentCharacter,javaNumber,javaStrTempl + syn cluster javaCommentSpecial2 add=javaComment2String,javaCommentCharacter,javaNumber,javaStrTempl endif -syn region javaComment start="/\*" end="\*/" contains=@javaCommentSpecial,javaTodo,@Spell +syn region javaComment matchgroup=javaCommentStart start="/\*" end="\*/" contains=@javaCommentSpecial,javaTodo,javaCommentError,javaSpaceError,@Spell syn match javaCommentStar contained "^\s*\*[^/]"me=e-1 syn match javaCommentStar contained "^\s*\*$" -syn match javaLineComment "//.*" contains=@javaCommentSpecial2,javaTodo,@Spell +syn match javaLineComment "//.*" contains=@javaCommentSpecial2,javaTodo,javaCommentMarkupTag,javaSpaceError,@Spell +syn match javaCommentMarkupTag contained "@\%(end\|highlight\|link\|replace\|start\)\>" nextgroup=javaCommentMarkupTagAttr,javaSpaceError skipwhite +syn match javaCommentMarkupTagAttr contained "\<region\>" nextgroup=javaCommentMarkupTagAttr,javaSpaceError skipwhite +exec 'syn region javaCommentMarkupTagAttr contained transparent matchgroup=htmlArg start=/\<\%(re\%(gex\|gion\|placement\)\|substring\|t\%(arget\|ype\)\)\%(\s*=\)\@=/ matchgroup=htmlString end=/\%(=\s*\)\@' . s:ff.Peek('80', '') . '<=\%("[^"]\+"\|' . "\x27[^\x27]\\+\x27" . '\|\%([.-]\|\k\)\+\)/ nextgroup=javaCommentMarkupTagAttr,javaSpaceError skipwhite oneline' +hi def link javaCommentMarkupTagAttr htmlArg hi def link javaCommentString javaString hi def link javaComment2String javaString hi def link javaCommentCharacter javaCharacter - -syn cluster javaTop add=javaComment,javaLineComment +syn match javaCommentError contained "/\*"me=e-1 display +hi def link javaCommentError javaError +hi def link javaCommentStart javaComment if !exists("java_ignore_javadoc") && main_syntax != 'jsp' syntax case ignore - " syntax coloring for javadoc comments (HTML) + + " Include HTML syntax coloring for Javadoc comments. syntax include @javaHtml syntax/html.vim unlet b:current_syntax - " HTML enables spell checking for all text that is not in a syntax item. This - " is wrong for Java (all identifiers would be spell-checked), so it's undone - " here. - syntax spell default - - syn region javaDocComment start="/\*\*" end="\*/" keepend contains=javaCommentTitle,@javaHtml,javaDocTags,javaDocSeeTag,javaTodo,@Spell - syn region javaCommentTitle contained matchgroup=javaDocComment start="/\*\*" matchgroup=javaCommentTitle keepend end="\.$" end="\.[ \t\r<&]"me=e-1 end="[^{]@"me=s-2,he=s-1 end="\*/"me=s-1,he=s-1 contains=@javaHtml,javaCommentStar,javaTodo,@Spell,javaDocTags,javaDocSeeTag - - syn region javaDocTags contained start="{@\(code\|link\|linkplain\|inherit[Dd]oc\|doc[rR]oot\|value\)" end="}" - syn match javaDocTags contained "@\(param\|exception\|throws\|since\)\s\+\S\+" contains=javaDocParam - syn match javaDocParam contained "\s\S\+" - syn match javaDocTags contained "@\(version\|author\|return\|deprecated\|serial\|serialField\|serialData\)\>" - syn region javaDocSeeTag contained matchgroup=javaDocTags start="@see\s\+" matchgroup=NONE end="\_."re=e-1 contains=javaDocSeeTagParam - syn match javaDocSeeTagParam contained @"\_[^"]\+"\|<a\s\+\_.\{-}</a>\|\(\k\|\.\)*\(#\k\+\((\_[^)]\+)\)\=\)\=@ extend + + " HTML enables spell checking for all text that is not in a syntax + " item (:syntax spell toplevel); instead, limit spell checking to + " items matchable with syntax groups containing the @Spell cluster. + try + syntax spell default + catch /\<E390:/ + call s:ReportOnce(v:exception) + endtry + + syn region javaDocComment start="/\*\*" end="\*/" keepend contains=javaCommentTitle,@javaHtml,javaDocTags,javaDocSeeTag,javaDocCodeTag,javaDocSnippetTag,javaTodo,javaCommentError,javaSpaceError,@Spell + exec 'syn region javaCommentTitle contained matchgroup=javaDocComment start="/\*\*" matchgroup=javaCommentTitle end="\.$" end="\.[ \t\r]\@=" end="\%(^\s*\**\s*\)\@' . s:ff.Peek('80', '') . '<=@"me=s-2,he=s-1 end="\*/"me=s-1,he=s-1 contains=@javaHtml,javaCommentStar,javaTodo,javaCommentError,javaSpaceError,@Spell,javaDocTags,javaDocSeeTag,javaDocCodeTag,javaDocSnippetTag' + syn region javaCommentTitle contained matchgroup=javaDocComment start="/\*\*\s*\r\=\n\=\s*\**\s*\%({@return\>\)\@=" matchgroup=javaCommentTitle end="}\%(\s*\.*\)*" contains=@javaHtml,javaCommentStar,javaTodo,javaCommentError,javaSpaceError,@Spell,javaDocTags,javaDocSeeTag,javaDocCodeTag,javaDocSnippetTag + syn region javaDocTags contained start="{@\%(li\%(teral\|nk\%(plain\)\=\)\|inherit[Dd]oc\|doc[rR]oot\|value\)\>" end="}" + syn match javaDocTags contained "@\%(param\|exception\|throws\|since\)\s\+\S\+" contains=javaDocParam + syn match javaDocParam contained "\s\S\+" + syn match javaDocTags contained "@\%(version\|author\|return\|deprecated\|serial\%(Field\|Data\)\=\)\>" + syn region javaDocSeeTag contained matchgroup=javaDocTags start="@see\s\+" matchgroup=NONE end="\_."re=e-1 contains=javaDocSeeTagParam + syn match javaDocSeeTagParam contained @"\_[^"]\+"\|<a\s\+\_.\{-}</a>\|\%(\k\|\.\)*\%(#\k\+\%((\_[^)]*)\)\=\)\=@ contains=@javaHtml extend + syn region javaCodeSkipBlock contained transparent start="{\%(@code\>\)\@!" end="}" contains=javaCodeSkipBlock,javaDocCodeTag + syn region javaDocCodeTag contained start="{@code\>" end="}" contains=javaDocCodeTag,javaCodeSkipBlock + exec 'syn region javaDocSnippetTagAttr contained transparent matchgroup=htmlArg start=/\<\%(class\|file\|id\|lang\|region\)\%(\s*=\)\@=/ matchgroup=htmlString end=/:$/ end=/\%(=\s*\)\@' . s:ff.Peek('80', '') . '<=\%("[^"]\+"\|' . "\x27[^\x27]\\+\x27" . '\|\%([.\\/-]\|\k\)\+\)/ nextgroup=javaDocSnippetTagAttr skipwhite skipnl' + syn region javaSnippetSkipBlock contained transparent start="{\%(@snippet\>\)\@!" end="}" contains=javaSnippetSkipBlock,javaDocSnippetTag,javaCommentMarkupTag + syn region javaDocSnippetTag contained start="{@snippet\>" end="}" contains=javaDocSnippetTag,javaSnippetSkipBlock,javaDocSnippetTagAttr,javaCommentMarkupTag + syntax case match endif @@ -234,8 +297,9 @@ syn match javaSpecialChar contained "\\\%(u\x\x\x\x\|[0-3]\o\o\|\o\o\=\|[bstn syn region javaString start=+"+ end=+"+ end=+$+ contains=javaSpecialChar,javaSpecialError,@Spell syn region javaString start=+"""[ \t\x0c\r]*$+hs=e+1 end=+"""+he=s-1 contains=javaSpecialChar,javaSpecialError,javaTextBlockError,@Spell syn match javaTextBlockError +"""\s*"""+ -" The next line is commented out, it can cause a crash for a long line -"syn match javaStringError +"\%([^"\\]\|\\.\)*$+ +syn region javaStrTemplEmbExp contained matchgroup=javaStrTempl start="\\{" end="}" contains=TOP +exec 'syn region javaStrTempl start=+\%(\.[[:space:]\n]*\)\@' . s:ff.Peek('80', '') . '<="+ end=+"+ contains=javaStrTemplEmbExp,javaSpecialChar,javaSpecialError,@Spell' +exec 'syn region javaStrTempl start=+\%(\.[[:space:]\n]*\)\@' . s:ff.Peek('80', '') . '<="""[ \t\x0c\r]*$+hs=e+1 end=+"""+he=s-1 contains=javaStrTemplEmbExp,javaSpecialChar,javaSpecialError,javaTextBlockError,@Spell' syn match javaCharacter "'[^']*'" contains=javaSpecialChar,javaSpecialCharError syn match javaCharacter "'\\''" contains=javaSpecialChar syn match javaCharacter "'[^\\]'" @@ -254,25 +318,38 @@ syn match javaNumber "\<0[xX]\%(\x\%(_*\x\)*\.\=\|\%(\x\%(_*\x\)*\)\=\.\x\%( " Unicode characters syn match javaSpecial "\\u\x\x\x\x" -syn cluster javaTop add=javaString,javaCharacter,javaNumber,javaSpecial,javaStringError,javaTextBlockError - +" Method declarations (JLS-17, §8.4.3, §8.4.4, §9.4). if exists("java_highlight_functions") - if java_highlight_functions == "indent" - syn match javaFuncDef "^\(\t\| \{8\}\)[_$a-zA-Z][_$a-zA-Z0-9_. \[\]<>]*([^-+*/]*)" contains=javaScopeDecl,javaType,javaStorageClass,@javaClasses,javaAnnotation - syn region javaFuncDef start=+^\(\t\| \{8\}\)[$_a-zA-Z][$_a-zA-Z0-9_. \[\]<>]*([^-+*/]*,\s*+ end=+)+ contains=javaScopeDecl,javaType,javaStorageClass,@javaClasses,javaAnnotation - syn match javaFuncDef "^ [$_a-zA-Z][$_a-zA-Z0-9_. \[\]<>]*([^-+*/]*)" contains=javaScopeDecl,javaType,javaStorageClass,@javaClasses,javaAnnotation - syn region javaFuncDef start=+^ [$_a-zA-Z][$_a-zA-Z0-9_. \[\]<>]*([^-+*/]*,\s*+ end=+)+ contains=javaScopeDecl,javaType,javaStorageClass,@javaClasses,javaAnnotation + syn cluster javaFuncParams contains=javaAnnotation,@javaClasses,javaType,javaVarArg,javaComment,javaLineComment + + if java_highlight_functions =~# '^indent[1-8]\=$' + let s:last = java_highlight_functions[-1 :] + let s:indent = s:last != 't' ? repeat("\x20", s:last) : "\t" + syn cluster javaFuncParams add=javaScopeDecl,javaConceptKind,javaStorageClass,javaExternal + " Try to not match other type members, initialiser blocks, enum + " constants (JLS-17, §8.9.1), and constructors (JLS-17, §8.1.7): + " at any _conventional_ indentation, skip over all fields with + " "[^=]*", all records with "\<record\s", and let the "*Skip*" + " definitions take care of constructor declarations and enum + " constants (with no support for @Foo(value = "bar")). + exec 'syn region javaFuncDef start=+^' . s:indent . '\%(<[^>]\+>\+\s\+\|\%(\%(@\%(\K\k*\.\)*\K\k*\>\)\s\+\)\+\)\=\%(\<\K\k*\>\.\)*\K\k*\>[^=]*\%(\<record\)\@' . s:ff.Peek('6', '') . '<!\s\K\k*\s*(+ end=+)+ contains=@javaFuncParams' + " As long as package-private constructors cannot be matched with + " javaFuncDef, do not look with javaConstructorSkipDeclarator for + " them. + exec 'syn match javaConstructorSkipDeclarator transparent +^' . s:indent . '\%(\%(@\%(\K\k*\.\)*\K\k*\>\)\s\+\)*p\%(ublic\|rotected\|rivate\)\s\+\%(<[^>]\+>\+\s\+\)\=\K\k*\s*\ze(+ contains=javaAnnotation,javaScopeDecl' + exec 'syn match javaEnumSkipArgumentativeConstant transparent +^' . s:indent . '\%(\%(@\%(\K\k*\.\)*\K\k*\>\)\s\+\)*\K\k*\s*\ze(+ contains=javaAnnotation' + unlet s:indent s:last else - " This line catches method declarations at any indentation>0, but it assumes - " two things: - " 1. class names are always capitalized (ie: Button) - " 2. method names are never capitalized (except constructors, of course) - "syn region javaFuncDef start=+^\s\+\(\(public\|protected\|private\|static\|abstract\|final\|native\|synchronized\)\s\+\)*\(\(void\|boolean\|char\|byte\|short\|int\|long\|float\|double\|\([A-Za-z_][A-Za-z0-9_$]*\.\)*[A-Z][A-Za-z0-9_$]*\)\(<[^>]*>\)\=\(\[\]\)*\s\+[a-z][A-Za-z0-9_$]*\|[A-Z][A-Za-z0-9_$]*\)\s*([^0-9]+ end=+)+ contains=javaScopeDecl,javaType,javaStorageClass,javaComment,javaLineComment,@javaClasses - syn region javaFuncDef start=+^\s\+\%(\%(public\|protected\|private\|static\|\%(abstract\|default\)\|final\|native\|synchronized\)\s\+\)*\%(<.*>\s\+\)\?\%(\%(void\|boolean\|char\|byte\|short\|int\|long\|float\|double\|\%([A-Za-z_][A-Za-z0-9_$]*\.\)*[A-Z][A-Za-z0-9_$]*\)\%(<[^(){}]*>\)\=\%(\[\]\)*\s\+[a-z][A-Za-z0-9_$]*\|[A-Z][A-Za-z0-9_$]*\)\s*(+ end=+)+ contains=javaScopeDecl,javaType,javaStorageClass,javaComment,javaLineComment,@javaClasses,javaAnnotation + " This is the "style" variant (:help ft-java-syntax). + syn cluster javaFuncParams add=javaScopeDecl,javaConceptKind,javaStorageClass,javaExternal + + " Match arbitrarily indented camelCasedName method declarations. + " Match: [@ɐ] [abstract] [<α, β>] Τʬ[<γ>][[][]] μʭʭ(/* ... */); + exec 'syn region javaFuncDef start=/' . s:ff.Engine('\%#=2', '') . '^\s\+\%(\%(@\%(\K\k*\.\)*\K\k*\>\)\s\+\)*\%(p\%(ublic\|rotected\|rivate\)\s\+\)\=\%(\%(abstract\|default\)\s\+\|\%(\%(final\|\%(native\|strictfp\)\|s\%(tatic\|ynchronized\)\)\s\+\)*\)\=\%(<.*[[:space:]-]\@' . s:ff.Peek('1', '') . '<!>\s\+\)\=\%(void\|\%(b\%(oolean\|yte\)\|char\|short\|int\|long\|float\|double\|\%(\<\K\k*\>\.\)*\<' . s:ff.UpperCase('[$_[:upper:]]', '[^a-z0-9]') . '\k*\>\%(<[^(){}]*[[:space:]-]\@' . s:ff.Peek('1', '') . '<!>\)\=\)\%(\[\]\)*\)\s\+\<' . s:ff.LowerCase('[$_[:lower:]]', '[^A-Z0-9]') . '\k*\>\s*(/ end=/)/ skip=/\/\*.\{-}\*\/\|\/\/.*$/ contains=@javaFuncParams' endif - syn match javaLambdaDef "\<\K\k*\>\%(\<default\>\)\@<!\s*->" - syn match javaBraces "[{}]" - syn cluster javaTop add=javaFuncDef,javaBraces,javaLambdaDef + + exec 'syn match javaLambdaDef "\<\K\k*\>\%(\<default\>\)\@' . s:ff.Peek('7', '') . '<!\s*->"' + syn match javaBraces "[{}]" endif if exists("java_highlight_debug") @@ -280,8 +357,11 @@ if exists("java_highlight_debug") syn match javaDebugSpecial contained "\\\%(u\x\x\x\x\|[0-3]\o\o\|\o\o\=\|[bstnfr"'\\]\)" syn region javaDebugString contained start=+"+ end=+"+ contains=javaDebugSpecial syn region javaDebugString contained start=+"""[ \t\x0c\r]*$+hs=e+1 end=+"""+he=s-1 contains=javaDebugSpecial,javaDebugTextBlockError -" The next line is commented out, it can cause a crash for a long line -" syn match javaDebugStringError contained +"\%([^"\\]\|\\.\)*$+ + " The highlight groups of java{StrTempl,Debug{,Paren,StrTempl}}\, + " share one colour by default. Do not conflate unrelated parens. + syn region javaDebugStrTemplEmbExp contained matchgroup=javaDebugStrTempl start="\\{" end="}" contains=javaComment,javaLineComment,javaDebug\%(Paren\)\@!.* + exec 'syn region javaDebugStrTempl contained start=+\%(\.[[:space:]\n]*\)\@' . s:ff.Peek('80', '') . '<="+ end=+"+ contains=javaDebugStrTemplEmbExp,javaDebugSpecial' + exec 'syn region javaDebugStrTempl contained start=+\%(\.[[:space:]\n]*\)\@' . s:ff.Peek('80', '') . '<="""[ \t\x0c\r]*$+hs=e+1 end=+"""+he=s-1 contains=javaDebugStrTemplEmbExp,javaDebugSpecial,javaDebugTextBlockError' syn match javaDebugTextBlockError contained +"""\s*"""+ syn match javaDebugCharacter contained "'[^\\]'" syn match javaDebugSpecialCharacter contained "'\\.'" @@ -297,18 +377,18 @@ if exists("java_highlight_debug") syn keyword javaDebugType contained null this super syn region javaDebugParen start=+(+ end=+)+ contained contains=javaDebug.*,javaDebugParen - " to make this work you must define the highlighting for these groups - syn match javaDebug "\<System\.\(out\|err\)\.print\(ln\)*\s*("me=e-1 contains=javaDebug.* nextgroup=javaDebugParen - syn match javaDebug "\<p\s*("me=e-1 contains=javaDebug.* nextgroup=javaDebugParen - syn match javaDebug "[A-Za-z][a-zA-Z0-9_]*\.printStackTrace\s*("me=e-1 contains=javaDebug.* nextgroup=javaDebugParen - syn match javaDebug "\<trace[SL]\=\s*("me=e-1 contains=javaDebug.* nextgroup=javaDebugParen - - syn cluster javaTop add=javaDebug + " To make this work, define the highlighting for these groups. + syn match javaDebug "\<System\.\%(out\|err\)\.print\%(ln\)\=\s*("me=e-1 contains=javaDebug.* nextgroup=javaDebugParen +" FIXME: What API does "p" belong to? +" syn match javaDebug "\<p\s*("me=e-1 contains=javaDebug.* nextgroup=javaDebugParen + syn match javaDebug "\<\K\k*\.printStackTrace\s*("me=e-1 contains=javaDebug.* nextgroup=javaDebugParen +" FIXME: What API do "trace*" belong to? +" syn match javaDebug "\<trace[SL]\=\s*("me=e-1 contains=javaDebug.* nextgroup=javaDebugParen hi def link javaDebug Debug hi def link javaDebugString DebugString - hi def link javaDebugStringError javaError - hi def link javaDebugTextBlockError javaDebugStringError + hi def link javaDebugStrTempl Macro + hi def link javaDebugTextBlockError Error hi def link javaDebugType DebugType hi def link javaDebugBoolean DebugBoolean hi def link javaDebugNumber Debug @@ -326,7 +406,6 @@ endif if exists("java_mark_braces_in_parens_as_errors") syn match javaInParen contained "[{}]" hi def link javaInParen javaError - syn cluster javaTop add=javaInParen endif " catch errors caused by wrong parenthesis @@ -343,13 +422,24 @@ syn match javaParenError "\]" hi def link javaParenError javaError if exists("java_highlight_functions") - syn match javaLambdaDef "([a-zA-Z0-9_<>\[\], \t]*)\s*->" - " needs to be defined after the parenthesis error catcher to work + " Make ()-matching definitions after the parenthesis error catcher. + exec 'syn match javaLambdaDef "\k\@' . s:ff.Peek('4', '') . '<!(\%(\k\|[[:space:]<>?\[\]@,.]\)*)\s*->"' endif +" The @javaTop cluster comprises non-contained Java syntax groups. +" Note that the syntax file "aidl.vim" relies on its availability. +syn cluster javaTop contains=TOP,javaDocComment,javaFold,javaParenError,javaParenT + if !exists("java_minlines") let java_minlines = 10 endif + +" Note that variations of a /*/ balanced comment, e.g., /*/*/, /*//*/, +" /* /*/, /* /*/, etc., may have their rightmost /*/ part accepted +" as a comment start by ':syntax sync ccomment'; consider alternatives +" to make synchronisation start further towards file's beginning by +" bumping up g:java_minlines or issuing ':syntax sync fromstart' or +" preferring &foldmethod set to 'syntax'. exec "syn sync ccomment javaComment minlines=" . java_minlines " The default highlighting. @@ -376,12 +466,12 @@ hi def link javaSpecial Special hi def link javaSpecialError Error hi def link javaSpecialCharError Error hi def link javaString String +hi def link javaStrTempl Macro hi def link javaCharacter Character hi def link javaSpecialChar SpecialChar hi def link javaNumber Number hi def link javaError Error -hi def link javaStringError Error -hi def link javaTextBlockError javaStringError +hi def link javaTextBlockError Error hi def link javaStatement Statement hi def link javaOperator Operator hi def link javaComment Comment @@ -394,6 +484,8 @@ hi def link javaAnnotation PreProc hi def link javaCommentTitle SpecialComment hi def link javaDocTags Special +hi def link javaDocCodeTag Special +hi def link javaDocSnippetTag Special hi def link javaDocParam Function hi def link javaDocSeeTagParam Function hi def link javaCommentStar javaComment @@ -403,12 +495,14 @@ hi def link javaExternal Include hi def link htmlComment Special hi def link htmlCommentPart Special +hi def link htmlArg Type +hi def link htmlString String hi def link javaSpaceError Error -if s:isModuleInfoDeclarationCurrentBuffer() - hi def link javaModuleStorageClass StorageClass - hi def link javaModuleStmt Statement - hi def link javaModuleExternal Include +if s:module_info_cur_buf + hi def link javaModuleStorageClass StorageClass + hi def link javaModuleStmt Statement + hi def link javaModuleExternal Include endif let b:current_syntax = "java" @@ -417,9 +511,8 @@ if main_syntax == 'java' unlet main_syntax endif -delfunction! s:isModuleInfoDeclarationCurrentBuffer -let b:spell_options="contained" +let b:spell_options = "contained" let &cpo = s:cpo_save -unlet s:cpo_save +unlet s:module_info_cur_buf s:ff s:cpo_save -" vim: ts=8 +" vim: sw=2 ts=8 noet sta diff --git a/runtime/syntax/jj.vim b/runtime/syntax/jj.vim new file mode 100644 index 0000000000..a2911a0268 --- /dev/null +++ b/runtime/syntax/jj.vim @@ -0,0 +1,20 @@ +" Vim syntax file +" Language: jj description +" Maintainer: Gregory Anders <greg@gpanders.com> +" Last Change: 2024 May 8 + +if exists('b:current_syntax') + finish +endif +let b:current_syntax = 'jj' + +syn match jjAdded "A .*" contained +syn match jjRemoved "D .*" contained +syn match jjChanged "M .*" contained + +syn region jjComment start="^JJ: " end="$" contains=jjAdded,jjRemoved,jjChanged + +hi def link jjComment Comment +hi def link jjAdded Added +hi def link jjRemoved Removed +hi def link jjChanged Changed diff --git a/runtime/syntax/jq.vim b/runtime/syntax/jq.vim new file mode 100644 index 0000000000..272dcb4ebe --- /dev/null +++ b/runtime/syntax/jq.vim @@ -0,0 +1,130 @@ +" Vim compiler file +" Language: jq +" Maintainer: Vito <vito.blog@gmail.com> +" Last Change: 2024 Apr 17 +" Upstream: https://github.com/vito-c/jq.vim +" +" Quit when a (custom) syntax file was already loaded +if exists('b:current_syntax') + finish +endif + +" syn include @jqHtml syntax/html.vim " Doc comment HTML + +" jqTodo +syntax keyword jqTodo contained TODO FIXME NOTE XXX + +" jqKeywords +syntax keyword jqKeywords and or not empty +syntax keyword jqKeywords try catch +syntax keyword jqKeywords reduce as label break foreach +syntax keyword jqKeywords import include module modulemeta +syntax keyword jqKeywords env nth has in while error stderr debug + +" jqConditional +syntax keyword jqConditional if then elif else end + +" jqConditions +syntax keyword jqCondtions true false null + +" jqSpecials +syntax keyword jqType type +syntax match jqType /[\|;]/ " not really a type I did this for coloring reasons though :help group-name +syntax region jqParentheses start=+(+ end=+)+ fold transparent + +" jq Functions +syntax keyword jqFunction add all any arrays ascii_downcase floor +syntax keyword jqFunction ascii_upcase booleans bsearch builtins capture combinations +syntax keyword jqFunction \contains del delpaths endswith explode +syntax keyword jqFunction finites first flatten format from_entries +syntax keyword jqFunction fromdate fromdateiso8601 fromjson fromstream get_jq_origin +syntax keyword jqFunction get_prog_origin get_search_list getpath gmtime group_by +syntax keyword jqFunction gsub halt halt_error implode index indices infinite +syntax keyword jqFunction input input_filename input_line_number inputs inside +syntax keyword jqFunction isempty isfinite isinfinite isnan isnormal iterables +syntax keyword jqFunction join keys keys_unsorted last leaf_paths +syntax keyword jqFunction length limit localtime ltrimstr map map_values +syntax keyword jqFunction match max max_by min min_by +syntax keyword jqFunction mktime nan normals now +syntax keyword jqFunction nulls numbers objects path paths range +syntax keyword jqFunction recurse recurse_down repeat reverse rindex +syntax keyword jqFunction rtrimstr scalars scalars_or_empty scan select +syntax keyword jqFunction setpath sort sort_by split splits with_entries +syntax keyword jqFunction startswith strflocaltime strftime strings strptime sub +syntax keyword jqFunction test to_entries todate todateiso8601 tojson __loc__ +syntax keyword jqFunction tonumber tostream tostring transpose truncate_stream +syntax keyword jqFunction unique unique_by until utf8bytelength values walk +" TODO: $__loc__ is going to be a pain + +" jq Math Functions +syntax keyword jqFunction acos acosh asin asinh atan atanh cbrt ceil cos cosh +syntax keyword jqFunction erf erfc exp exp10 exp2 expm1 fabs floor gamma j0 j1 +syntax keyword jqFunction lgamma lgamma_r log log10 log1p log2 logb nearbyint +syntax keyword jqFunction pow10 rint round significand sin sinh sqrt tan tanh +syntax keyword jqFunction tgamma trunc y0 y1 +syntax keyword jqFunction atan2 copysign drem fdim fmax fmin fmod frexp hypot +syntax keyword jqFunction jn ldexp modf nextafter nexttoward pow remainder +syntax keyword jqFunction scalb scalbln yn +syntax keyword jqFunction fma + +" jq SQL-style Operators +syntax keyword jqFunction INDEX JOIN IN + +" Macro +syntax match jqMacro "@\%(text\|json\|html\|uri\|[ct]sv\|sh\|base64d\?\)\>" + +" Comments +syntax match jqComment "#.*" contains=jqTodo + +" Variables +syn match jqVariables /$[_A-Za-z0-9]\+/ + +" Definition +syntax keyword jqKeywords def nextgroup=jqNameDefinition skipwhite +syn match jqNameDefinition /\<[_A-Za-z0-9]\+\>/ contained nextgroup=jqPostNameDefinition +syn match jqNameDefinition /`[^`]\+`/ contained nextgroup=jqPostNameDefinition + +" Strings +syn region jqError start=+'+ end=+'\|$\|[;)]\@=+ +syn region jqString matchgroup=jqQuote + \ start=+"+ skip=+\\[\\"]+ end=+"+ + \ contains=@Spell,jqInterpolation +syn region jqInterpolation matchgroup=jqInterpolationDelimiter + \ start=+\%([^\\]\%(\\\\\)*\\\)\@<!\\(+ end=+)+ + \ contained contains=TOP + +" Operators +syn match jqOperator /:\|\([-+*/%<>=]\|\/\/\)=\?\|[!|]=\|?\/\// +"syn region jqRange matchgroup=jqSquareBracket start=+\[+ skip=+:+ end=+\]+ + +" Errors +syn keyword jqError _assign _flatten _modify _nwise _plus _negate _minus _multiply +syn keyword jqError _divide _mod _strindices _equal _notequal _less _greater _lesseq +syn keyword jqError _greatereq _sort_by_impl _group_by_impl _min_by_impl _max_by_impl _match_impl _input +" TODO: these errors should show up when doing def _flatten: as well + +" Numbers +syn match jqNumber /\<0[dDfFlL]\?\>/ " Just a bare 0 +syn match jqNumber /\<[1-9]\d*[dDfFlL]\?\>/ " A multi-digit number - octal numbers with leading 0's are deprecated in Scala + +if !exists('jq_quote_highlight') + highlight def link jqQuote String +else + highlight def link jqQuote Type +endif + +hi def link jqCondtions Boolean +hi def link jqVariables Identifier +hi def link jqNameDefinition Function +hi def link jqTodo Todo +hi def link jqComment Comment +hi def link jqKeywords Keyword +hi def link jqType Type +hi def link jqOperator Operator +hi def link jqFunction Function +hi def link jqMacro Macro +hi def link jqError Error +hi def link jqString String +hi def link jqInterpolationDelimiter Delimiter +hi def link jqConditional Conditional +hi def link jqNumber Number diff --git a/runtime/syntax/json.vim b/runtime/syntax/json.vim index 3f49b0c5ea..f61a17e120 100644 --- a/runtime/syntax/json.vim +++ b/runtime/syntax/json.vim @@ -1,6 +1,6 @@ " Vim syntax file " Language: JSON -" Maintainer: vacancy +" Maintainer: Vito <vito.blog@gmail.com> " Previous Maintainer: Eli Parra <eli@elzr.com> " Last Change: 2019 Sep 17 " Version: 0.12 diff --git a/runtime/syntax/ondir.vim b/runtime/syntax/ondir.vim new file mode 100644 index 0000000000..4aeb014e1b --- /dev/null +++ b/runtime/syntax/ondir.vim @@ -0,0 +1,35 @@ +" Vim syntax file +" Language: ondir <https://github.com/alecthomas/ondir> +" Maintainer: Jon Parise <jon@indelible.org> + +if exists('b:current_syntax') + finish +endif + +let s:cpo_save = &cpoptions +set cpoptions&vim + +syn case match + +syn match ondirComment "#.*" contains=@Spell +syn keyword ondirKeyword final contained skipwhite nextgroup=ondirKeyword +syn keyword ondirKeyword enter leave contained skipwhite nextgroup=ondirPath +syn match ondirPath "[^:]\+" contained display +syn match ondirColon ":" contained display + +syn include @ondirShell syntax/sh.vim +syn region ondirContent start="^\s\+" end="^\ze\S.*$" keepend contained contains=@ondirShell + +syn region ondirSection start="^\(final\|enter\|leave\)" end="^\ze\S.*$" fold contains=ondirKeyword,ondirPath,ondirColon,ondirContent + +hi def link ondirComment Comment +hi def link ondirKeyword Keyword +hi def link ondirPath Special +hi def link ondirColon Operator + +let b:current_syntax = 'ondir' + +let &cpoptions = s:cpo_save +unlet s:cpo_save + +" vim: et ts=4 sw=2 sts=2: diff --git a/runtime/syntax/pamconf.vim b/runtime/syntax/pamconf.vim index 29132848a9..1b5f901348 100644 --- a/runtime/syntax/pamconf.vim +++ b/runtime/syntax/pamconf.vim @@ -1,9 +1,9 @@ " Vim syntax file " Language: pam(8) configuration file " Previous Maintainer: Nikolai Weibull <now@bitwi.se> -" Latest Revision: 2020/08/04 +" Latest Change: 2024/03/31 " Changes By: Haochen Tong - +" Vim Project for the @include syntax if exists("b:current_syntax") finish @@ -23,6 +23,13 @@ syn match pamconfType '-\?[[:alpha:]]\+' syn keyword pamconfTypeKeyword contained account auth password session +" The @include syntax is Debian specific +syn match pamconfInclude '^@include' + \ nextgroup=pamconfIncludeFile + \ skipwhite + +syn match pamconfIncludeFile '\f\+$' + if s:has_service_field syn match pamconfService '^[[:graph:]]\+' \ nextgroup=pamconfType, @@ -124,6 +131,8 @@ hi def link pamconfMPath String hi def link pamconfMPathLineCont pamconfServiceLineCont hi def link pamconfArgs Normal hi def link pamconfArgsLineCont pamconfServiceLineCont +hi def link pamconfInclude Include +hi def link pamconfIncludeFile Include let b:current_syntax = "pamconf" diff --git a/runtime/syntax/pandoc.vim b/runtime/syntax/pandoc.vim new file mode 100644 index 0000000000..7928cc665d --- /dev/null +++ b/runtime/syntax/pandoc.vim @@ -0,0 +1,709 @@ +scriptencoding utf-8 +" +" Language: Pandoc (superset of Markdown) +" Maintainer: Felipe Morales <hel.sheep@gmail.com> +" Maintainer: Caleb Maclennan <caleb@alerque.com> +" Upstream: https://github.com/vim-pandoc/vim-pandoc-syntax +" +" Contributor: David Sanson <dsanson@gmail.com> +" Jorge Israel Peña <jorge.israel.p@gmail.com> +" Original Author: Jeremy Schultz <taozhyn@gmail.com> +" Version: 5.0 +" Last Change: 2024 Apr 08 + +let s:cpo_save = &cpo +set cpo&vim + +" Configuration: {{{1 +" +" use conceal? {{{2 +if !exists('g:pandoc#syntax#conceal#use') + let g:pandoc#syntax#conceal#use = 1 +endif +"}}}2 + +" what groups not to use conceal in. works as a blacklist {{{2 +if !exists('g:pandoc#syntax#conceal#blacklist') + let g:pandoc#syntax#conceal#blacklist = [] +endif +" }}}2 + +" cchars used in conceal rules {{{2 +" utf-8 defaults (preferred) +if &encoding ==# 'utf-8' + let s:cchars = { + \'newline': '↵', + \'image': '▨', + \'super': 'ⁿ', + \'sub': 'ₙ', + \'strike': 'x̶', + \'atx': '§', + \'codelang': 'λ', + \'codeend': '—', + \'abbrev': '→', + \'footnote': '†', + \'definition': ' ', + \'li': '•', + \'html_c_s': '‹', + \'html_c_e': '›', + \'quote_s': '“', + \'quote_e': '”'} +else + " ascii defaults + let s:cchars = { + \'newline': ' ', + \'image': 'i', + \'super': '^', + \'sub': '_', + \'strike': '~', + \'atx': '#', + \'codelang': 'l', + \'codeend': '-', + \'abbrev': 'a', + \'footnote': 'f', + \'definition': ' ', + \'li': '*', + \'html_c_s': '+', + \'html_c_e': '+'} +endif +" }}}2 + +" if the user has a dictionary with replacements for the default cchars, use those {{{2 +if exists('g:pandoc#syntax#conceal#cchar_overrides') + let s:cchars = extend(s:cchars, g:pandoc#syntax#conceal#cchar_overrides) +endif +" }}}2 + +"should the urls in links be concealed? {{{2 +if !exists('g:pandoc#syntax#conceal#urls') + let g:pandoc#syntax#conceal#urls = 0 +endif +" should backslashes in escapes be concealed? {{{2 +if !exists('g:pandoc#syntax#conceal#backslash') + let g:pandoc#syntax#conceal#backslash = 0 +endif +" }}}2 + +" leave specified codeblocks as Normal (i.e. 'unhighlighted') {{{2 +if !exists('g:pandoc#syntax#codeblocks#ignore') + let g:pandoc#syntax#codeblocks#ignore = [] +endif +" }}}2 + +" use embedded highlighting for delimited codeblocks where a language is specifed. {{{2 +if !exists('g:pandoc#syntax#codeblocks#embeds#use') + let g:pandoc#syntax#codeblocks#embeds#use = 1 +endif +" }}}2 + +" for what languages and using what vim syntax files highlight those embeds. {{{2 +" defaults to None. +if !exists('g:pandoc#syntax#codeblocks#embeds#langs') + let g:pandoc#syntax#codeblocks#embeds#langs = [] +endif +" }}}2 + +" use italics ? {{{2 +if !exists('g:pandoc#syntax#style#emphases') + let g:pandoc#syntax#style#emphases = 1 +endif +" if 0, we don't conceal the emphasis marks, otherwise there wouldn't be a way +" to tell where the styles apply. +if g:pandoc#syntax#style#emphases == 0 + call add(g:pandoc#syntax#conceal#blacklist, 'block') +endif +" }}}2 + +" underline subscript, superscript and strikeout? {{{2 +if !exists('g:pandoc#syntax#style#underline_special') + let g:pandoc#syntax#style#underline_special = 1 +endif +" }}}2 + +" protect code blocks? {{{2 +if !exists('g:pandoc#syntax#protect#codeblocks') + let g:pandoc#syntax#protect#codeblocks = 1 +endif +" }}}2 + +" use color column? {{{2 +if !exists('g:pandoc#syntax#colorcolumn') + let g:pandoc#syntax#colorcolumn = 0 +endif +" }}}2 + +" highlight new lines? {{{2 +if !exists('g:pandoc#syntax#newlines') + let g:pandoc#syntax#newlines = 1 +endif +" }}} + +" detect roman-numeral list items? {{{2 +if !exists('g:pandoc#syntax#roman_lists') + let g:pandoc#syntax#roman_lists = 0 +endif +" }}}2 + +" disable syntax highlighting for definition lists? (better performances) {{{2 +if !exists('g:pandoc#syntax#use_definition_lists') + let g:pandoc#syntax#use_definition_lists = 1 +endif +" }}}2 + +" }}}1 + +" Functions: {{{1 +" EnableEmbedsforCodeblocksWithLang {{{2 +function! EnableEmbedsforCodeblocksWithLang(entry) + " prevent embedded language syntaxes from changing 'foldmethod' + if has('folding') + let s:foldmethod = &l:foldmethod + let s:foldtext = &l:foldtext + endif + + try + let s:langname = matchstr(a:entry, '^[^=]*') + let s:langsyntaxfile = matchstr(a:entry, '[^=]*$') + unlet! b:current_syntax + exe 'syn include @'.toupper(s:langname).' syntax/'.s:langsyntaxfile.'.vim' + " We might have just turned off spellchecking by including the file, + " so we turn it back on here. + exe 'syntax spell toplevel' + exe 'syn region pandocDelimitedCodeBlock_' . s:langname . ' start=/\(\_^\( \+\|\t\)\=\(`\{3,}`*\|\~\{3,}\~*\)\s*\%({[^.]*\.\)\=' . s:langname . '\>.*\n\)\@<=\_^/' . + \' end=/\_$\n\(\( \+\|\t\)\=\(`\{3,}`*\|\~\{3,}\~*\)\_$\n\_$\)\@=/ contained containedin=pandocDelimitedCodeBlock' . + \' contains=@' . toupper(s:langname) + exe 'syn region pandocDelimitedCodeBlockinBlockQuote_' . s:langname . ' start=/>\s\(`\{3,}`*\|\~\{3,}\~*\)\s*\%({[^.]*\.\)\=' . s:langname . '\>/' . + \ ' end=/\(`\{3,}`*\|\~\{3,}\~*\)/ contained containedin=pandocDelimitedCodeBlock' . + \' contains=@' . toupper(s:langname) . + \',pandocDelimitedCodeBlockStart,pandocDelimitedCodeBlockEnd,pandodDelimitedCodeblockLang,pandocBlockQuoteinDelimitedCodeBlock' + catch /E484/ + echo "No syntax file found for '" . s:langsyntaxfile . "'" + endtry + + if exists('s:foldmethod') && s:foldmethod !=# &l:foldmethod + let &l:foldmethod = s:foldmethod + endif + if exists('s:foldtext') && s:foldtext !=# &l:foldtext + let &l:foldtext = s:foldtext + endif +endfunction +" }}}2 + +" DisableEmbedsforCodeblocksWithLang {{{2 +function! DisableEmbedsforCodeblocksWithLang(langname) + try + exe 'syn clear pandocDelimitedCodeBlock_'.a:langname + exe 'syn clear pandocDelimitedCodeBlockinBlockQuote_'.a:langname + catch /E28/ + echo "No existing highlight definitions found for '" . a:langname . "'" + endtry +endfunction +" }}}2 + +" WithConceal {{{2 +function! s:WithConceal(rule_group, rule, conceal_rule) + let l:rule_tail = '' + if g:pandoc#syntax#conceal#use != 0 + if index(g:pandoc#syntax#conceal#blacklist, a:rule_group) == -1 + let l:rule_tail = ' ' . a:conceal_rule + endif + endif + execute a:rule . l:rule_tail +endfunction +" }}}2 + +" }}}1 + +" Commands: {{{1 +command! -buffer -nargs=1 -complete=syntax PandocHighlight call EnableEmbedsforCodeblocksWithLang(<f-args>) +command! -buffer -nargs=1 -complete=syntax PandocUnhighlight call DisableEmbedsforCodeblocksWithLang(<f-args>) +" }}}1 + +" BASE: +syntax clear +syntax spell toplevel +" }}}1 + +" Syntax Rules: {{{1 + +" Embeds: {{{2 + +" prevent embedded language syntaxes from changing 'foldmethod' +if has('folding') + let s:foldmethod = &l:foldmethod +endif + +" HTML: {{{3 +" Set embedded HTML highlighting +syn include @HTML syntax/html.vim +syn match pandocHTML /<\/\?\a\_.\{-}>/ contains=@HTML +" Support HTML multi line comments +syn region pandocHTMLComment start=/<!--\s\=/ end=/\s\=-->/ keepend contains=pandocHTMLCommentStart,pandocHTMLCommentEnd +call s:WithConceal('html_c_s', 'syn match pandocHTMLCommentStart /<!--/ contained', 'conceal cchar='.s:cchars['html_c_s']) +call s:WithConceal('html_c_e', 'syn match pandocHTMLCommentEnd /-->/ contained', 'conceal cchar='.s:cchars['html_c_e']) +" }}}3 + +" LaTeX: {{{3 +" Set embedded LaTex (pandoc extension) highlighting +" Unset current_syntax so the 2nd include will work +unlet b:current_syntax +syn include @LATEX syntax/tex.vim +if index(g:pandoc#syntax#conceal#blacklist, 'inlinemath') == -1 + " Can't use WithConceal here because it will mess up all other conceals + " when dollar signs are used normally. It must be skipped entirely if + " inlinemath is blacklisted + syn region pandocLaTeXInlineMath start=/\v\\@<!\$\S@=/ end=/\v\\@<!\$\d@!/ keepend contains=@LATEX + syn region pandocLaTeXInlineMath start=/\\\@<!\\(/ end=/\\\@<!\\)/ keepend contains=@LATEX +endif +syn match pandocEscapedDollar /\\\$/ conceal cchar=$ +syn match pandocProtectedFromInlineLaTeX /\\\@<!\${.*}\(\(\s\|[[:punct:]]\)\([^$]*\|.*\(\\\$.*\)\{2}\)\n\n\|$\)\@=/ display +" contains=@LATEX +syn region pandocLaTeXMathBlock start=/\$\$/ end=/\$\$/ keepend contains=@LATEX +syn region pandocLaTeXMathBlock start=/\\\@<!\\\[/ end=/\\\@<!\\\]/ keepend contains=@LATEX +syn match pandocLaTeXCommand /\\[[:alpha:]]\+\(\({.\{-}}\)\=\(\[.\{-}\]\)\=\)*/ contains=@LATEX +syn region pandocLaTeXRegion start=/\\begin{\z(.\{-}\)}/ end=/\\end{\z1}/ keepend contains=@LATEX +" we rehighlight sectioning commands, because otherwise tex.vim captures all text until EOF or a new sectioning command +syn region pandocLaTexSection start=/\\\(part\|chapter\|\(sub\)\{,2}section\|\(sub\)\=paragraph\)\*\=\(\[.*\]\)\={/ end=/\}/ keepend +syn match pandocLaTexSectionCmd /\\\(part\|chapter\|\(sub\)\{,2}section\|\(sub\)\=paragraph\)/ contained containedin=pandocLaTexSection +syn match pandocLaTeXDelimiter /[[\]{}]/ contained containedin=pandocLaTexSection +" }}}3 + +if exists('s:foldmethod') && s:foldmethod !=# &l:foldmethod + let &l:foldmethod = s:foldmethod +endif + +" }}}2 + +" Titleblock: {{{2 +syn region pandocTitleBlock start=/\%^%/ end=/\n\n/ contains=pandocReferenceLabel,pandocReferenceURL,pandocNewLine +call s:WithConceal('titleblock', 'syn match pandocTitleBlockMark /%\ / contained containedin=pandocTitleBlock,pandocTitleBlockTitle', 'conceal') +syn match pandocTitleBlockTitle /\%^%.*\n/ contained containedin=pandocTitleBlock +" }}}2 + +" Blockquotes: {{{2 +syn match pandocBlockQuote /^\s\{,3}>.*\n\(.*\n\@1<!\n\)*/ contains=@Spell,pandocEmphasis,pandocStrong,pandocPCite,pandocSuperscript,pandocSubscript,pandocStrikeout,pandocUListItem,pandocNoFormatted,pandocAmpersandEscape,pandocLaTeXInlineMath,pandocEscapedDollar,pandocLaTeXCommand,pandocLaTeXMathBlock,pandocLaTeXRegion skipnl +syn match pandocBlockQuoteMark /\_^\s\{,3}>/ contained containedin=pandocEmphasis,pandocStrong,pandocPCite,pandocSuperscript,pandocSubscript,pandocStrikeout,pandocUListItem,pandocNoFormatted +" }}}2 + +" Code Blocks: {{{2 +if g:pandoc#syntax#protect#codeblocks == 1 + syn match pandocCodeblock /\([ ]\{4}\|\t\).*$/ +endif +syn region pandocCodeBlockInsideIndent start=/\(\(\d\|\a\|*\).*\n\)\@<!\(^\(\s\{8,}\|\t\+\)\).*\n/ end=/.\(\n^\s*\n\)\@=/ contained +" }}}2 + +" Links: {{{2 + +" Base: {{{3 +syn region pandocReferenceLabel matchgroup=pandocOperator start=/!\{,1}\\\@<!\^\@<!\[/ skip=/\(\\\@<!\]\]\@=\|`.*\\\@<!].*`\)/ end=/\\\@<!\]/ keepend display +if g:pandoc#syntax#conceal#urls == 1 + syn region pandocReferenceURL matchgroup=pandocOperator start=/\]\@1<=(/ end=/)/ keepend conceal +else + syn region pandocReferenceURL matchgroup=pandocOperator start=/\]\@1<=(/ end=/)/ keepend +endif +" let's not consider "a [label] a" as a label, remove formatting - Note: breaks implicit links +syn match pandocNoLabel /\]\@1<!\(\s\{,3}\|^\)\[[^\[\]]\{-}\]\(\s\+\|$\)[\[(]\@!/ contains=pandocPCite +syn match pandocLinkTip /\s*".\{-}"/ contained containedin=pandocReferenceURL contains=@Spell,pandocAmpersandEscape display +call s:WithConceal('image', 'syn match pandocImageIcon /!\[\@=/ display', 'conceal cchar='. s:cchars['image']) +" }}}3 + +" Definitions: {{{3 +syn region pandocReferenceDefinition start=/\[.\{-}\]:/ end=/\(\n\s*".*"$\|$\)/ keepend +syn match pandocReferenceDefinitionLabel /\[\zs.\{-}\ze\]:/ contained containedin=pandocReferenceDefinition display +syn match pandocReferenceDefinitionAddress /:\s*\zs.*/ contained containedin=pandocReferenceDefinition +syn match pandocReferenceDefinitionTip /\s*".\{-}"/ contained containedin=pandocReferenceDefinition,pandocReferenceDefinitionAddress contains=@Spell,pandocAmpersandEscape +" }}}3 + +" Automatic_links: {{{3 +syn match pandocAutomaticLink /<\(https\{0,1}.\{-}\|[A-Za-z0-9!#$%&'*+\-/=?^_`{|}~.]\{-}@[A-Za-z0-9\-]\{-}\.\w\{-}\)>/ contains=NONE +" }}}3 + +" }}}2 + +" Citations: {{{2 +" parenthetical citations +syn match pandocPCite "\^\@<!\[[^\[\]]\{-}-\{0,1}@[[:alnum:]_][[:digit:][:lower:][:upper:]_:.#$%&\-+?<>~/]*.\{-}\]" contains=pandocEmphasis,pandocStrong,pandocLatex,pandocCiteKey,@Spell,pandocAmpersandEscape display +" in-text citations with location +syn match pandocICite "@[[:alnum:]_][[:digit:][:lower:][:upper:]_:.#$%&\-+?<>~/]*\s\[.\{-1,}\]" contains=pandocCiteKey,@Spell display +" cite keys +syn match pandocCiteKey /\(-\=@[[:alnum:]_][[:digit:][:lower:][:upper:]_:.#$%&\-+?<>~/]*\)/ containedin=pandocPCite,pandocICite contains=@NoSpell display +syn match pandocCiteAnchor /[-@]/ contained containedin=pandocCiteKey display +syn match pandocCiteLocator /[\[\]]/ contained containedin=pandocPCite,pandocICite +" }}}2 + +" Text Styles: {{{2 + +" Emphasis: {{{3 +call s:WithConceal('block', 'syn region pandocEmphasis matchgroup=pandocOperator start=/\\\@1<!\(\_^\|\s\|[[:punct:]]\)\@<=\*\S\@=/ skip=/\(\*\*\|__\)/ end=/\*\([[:punct:]]\|\s\|\_$\)\@=/ contains=@Spell,pandocNoFormattedInEmphasis,pandocLatexInlineMath,pandocAmpersandEscape', 'concealends') +call s:WithConceal('block', 'syn region pandocEmphasis matchgroup=pandocOperator start=/\\\@1<!\(\_^\|\s\|[[:punct:]]\)\@<=_\S\@=/ skip=/\(\*\*\|__\)/ end=/\S\@1<=_\([[:punct:]]\|\s\|\_$\)\@=/ contains=@Spell,pandocNoFormattedInEmphasis,pandocLatexInlineMath,pandocAmpersandEscape', 'concealends') +" }}}3 + +" Strong: {{{3 +call s:WithConceal('block', 'syn region pandocStrong matchgroup=pandocOperator start=/\(\\\@<!\*\)\{2}/ end=/\(\\\@<!\*\)\{2}/ contains=@Spell,pandocNoFormattedInStrong,pandocLatexInlineMath,pandocAmpersandEscape', 'concealends') +call s:WithConceal('block', 'syn region pandocStrong matchgroup=pandocOperator start=/__/ end=/__/ contains=@Spell,pandocNoFormattedInStrong,pandocLatexInlineMath,pandocAmpersandEscape', 'concealends') +" }}}3 + +" Strong Emphasis: {{{3 +call s:WithConceal('block', 'syn region pandocStrongEmphasis matchgroup=pandocOperator start=/\*\{3}\(\S[^*]*\(\*\S\|\n[^*]*\*\S\)\)\@=/ end=/\S\@<=\*\{3}/ contains=@Spell,pandocAmpersandEscape', 'concealends') +call s:WithConceal('block', 'syn region pandocStrongEmphasis matchgroup=pandocOperator start=/\(___\)\S\@=/ end=/\S\@<=___/ contains=@Spell,pandocAmpersandEscape', 'concealends') +" }}}3 + +" Mixed: {{{3 +call s:WithConceal('block', 'syn region pandocStrongInEmphasis matchgroup=pandocOperator start=/\*\*/ end=/\*\*/ contained containedin=pandocEmphasis contains=@Spell,pandocAmpersandEscape', 'concealends') +call s:WithConceal('block', 'syn region pandocStrongInEmphasis matchgroup=pandocOperator start=/__/ end=/__/ contained containedin=pandocEmphasis contains=@Spell,pandocAmpersandEscape', 'concealends') +call s:WithConceal('block', 'syn region pandocEmphasisInStrong matchgroup=pandocOperator start=/\\\@1<!\(\_^\|\s\|[[:punct:]]\)\@<=\*\S\@=/ skip=/\(\*\*\|__\)/ end=/\S\@<=\*\([[:punct:]]\|\s\|\_$\)\@=/ contained containedin=pandocStrong contains=@Spell,pandocAmpersandEscape', 'concealends') +call s:WithConceal('block', 'syn region pandocEmphasisInStrong matchgroup=pandocOperator start=/\\\@<!\(\_^\|\s\|[[:punct:]]\)\@<=_\S\@=/ skip=/\(\*\*\|__\)/ end=/\S\@<=_\([[:punct:]]\|\s\|\_$\)\@=/ contained containedin=pandocStrong contains=@Spell,pandocAmpersandEscape', 'concealends') +" }}}3 + +" Inline Code: {{{3 +" Using single back ticks +call s:WithConceal('inlinecode', 'syn region pandocNoFormatted matchgroup=pandocOperator start=/\\\@<!`/ end=/\\\@<!`/ nextgroup=pandocNoFormattedAttrs', 'concealends') +call s:WithConceal('inlinecode', 'syn region pandocNoFormattedInEmphasis matchgroup=pandocOperator start=/\\\@<!`/ end=/\\\@<!`/ nextgroup=pandocNoFormattedAttrs contained', 'concealends') +call s:WithConceal('inlinecode', 'syn region pandocNoFormattedInStrong matchgroup=pandocOperator start=/\\\@<!`/ end=/\\\@<!`/ nextgroup=pandocNoFormattedAttrs contained', 'concealends') +" Using double back ticks +call s:WithConceal('inlinecode', 'syn region pandocNoFormatted matchgroup=pandocOperator start=/\\\@<!``/ end=/\\\@<!``/ nextgroup=pandocNoFormattedAttrs', 'concealends') +call s:WithConceal('inlinecode', 'syn region pandocNoFormattedInEmphasis matchgroup=pandocOperator start=/\\\@<!``/ end=/\\\@<!``/ nextgroup=pandocNoFormattedAttrs contained', 'concealends') +call s:WithConceal('inlinecode', 'syn region pandocNoFormattedInStrong matchgroup=pandocOperator start=/\\\@<!``/ end=/\\\@<!``/ nextgroup=pandocNoFormattedAttrs contained', 'concealends') +syn match pandocNoFormattedAttrs /{.\{-}}/ contained +" }}}3 + +" Subscripts: {{{3 +syn region pandocSubscript start=/\~\(\([[:graph:]]\(\\ \)\=\)\{-}\~\)\@=/ end=/\~/ keepend +call s:WithConceal('subscript', 'syn match pandocSubscriptMark /\~/ contained containedin=pandocSubscript', 'conceal cchar='.s:cchars['sub']) +" }}}3 + +" Superscript: {{{3 +syn region pandocSuperscript start=/\^\(\([[:graph:]]\(\\ \)\=\)\{-}\^\)\@=/ skip=/\\ / end=/\^/ keepend +call s:WithConceal('superscript', 'syn match pandocSuperscriptMark /\^/ contained containedin=pandocSuperscript', 'conceal cchar='.s:cchars['super']) +" }}}3 + +" Strikeout: {{{3 +syn region pandocStrikeout start=/\~\~/ end=/\~\~/ contains=@Spell,pandocAmpersandEscape keepend +call s:WithConceal('strikeout', 'syn match pandocStrikeoutMark /\~\~/ contained containedin=pandocStrikeout', 'conceal cchar='.s:cchars['strike']) +" }}}3 + +" }}}2 + +" Headers: {{{2 +syn match pandocAtxHeader /\(\%^\|<.\+>.*\n\|^\s*\n\)\@<=#\{1,6}.*\n/ contains=pandocEmphasis,pandocStrong,pandocNoFormatted,pandocLaTeXInlineMath,pandocEscapedDollar,@Spell,pandocAmpersandEscape,pandocReferenceLabel,pandocReferenceURL display +syn match pandocAtxHeaderMark /\(^#\{1,6}\|\\\@<!#\+\(\s*.*$\)\@=\)/ contained containedin=pandocAtxHeader +call s:WithConceal('atx', 'syn match pandocAtxStart /#/ contained containedin=pandocAtxHeaderMark', 'conceal cchar='.s:cchars['atx']) +syn match pandocSetexHeader /^.\+\n[=]\+$/ contains=pandocEmphasis,pandocStrong,pandocNoFormatted,pandocLaTeXInlineMath,pandocEscapedDollar,@Spell,pandocAmpersandEscape +syn match pandocSetexHeader /^.\+\n[-]\+$/ contains=pandocEmphasis,pandocStrong,pandocNoFormatted,pandocLaTeXInlineMath,pandocEscapedDollar,@Spell,pandocAmpersandEscape +syn match pandocHeaderAttr /{.*}/ contained containedin=pandocAtxHeader,pandocSetexHeader +syn match pandocHeaderID /#[-_:.[:lower:][:upper:]]*/ contained containedin=pandocHeaderAttr +" }}}2 + +" Line Blocks: {{{2 +syn region pandocLineBlock start=/^|/ end=/\(^|\(.*\n|\@!\)\@=.*\)\@<=\n/ transparent +syn match pandocLineBlockDelimiter /^|/ contained containedin=pandocLineBlock +" }}}2 + +" Tables: {{{2 + +" Simple: {{{3 +syn region pandocSimpleTable start=/\%#=2\(^.*[[:graph:]].*\n\)\@<!\(^.*[[:graph:]].*\n\)\(-\{2,}\s*\)\+\n\n\@!/ end=/\n\n/ containedin=ALLBUT,pandocDelimitedCodeBlock,pandocDelimitedCodeBlockStart,pandocYAMLHeader keepend +syn match pandocSimpleTableDelims /\-/ contained containedin=pandocSimpleTable +syn match pandocSimpleTableHeader /\%#=2\(^.*[[:graph:]].*\n\)\@<!\(^.*[[:graph:]].*\n\)/ contained containedin=pandocSimpleTable + +syn region pandocTable start=/\%#=2^\(-\{2,}\s*\)\+\n\n\@!/ end=/\%#=2^\(-\{2,}\s*\)\+\n\n/ containedin=ALLBUT,pandocDelimitedCodeBlock,pandocYAMLHeader keepend +syn match pandocTableDelims /\-/ contained containedin=pandocTable +syn region pandocTableMultilineHeader start=/\%#=2\(^-\{2,}\n\)\@<=./ end=/\%#=2\n-\@=/ contained containedin=pandocTable +" }}}3 + +" Grid: {{{3 +syn region pandocGridTable start=/\%#=2\n\@1<=+-/ end=/+\n\n/ containedin=ALLBUT,pandocDelimitedCodeBlock,pandocYAMLHeader keepend +syn match pandocGridTableDelims /[\|=]/ contained containedin=pandocGridTable +syn match pandocGridTableDelims /\%#=2\([\-+][\-+=]\@=\|[\-+=]\@1<=[\-+]\)/ contained containedin=pandocGridTable +syn match pandocGridTableHeader /\%#=2\(^.*\n\)\(+=.*\)\@=/ contained containedin=pandocGridTable +" }}}3 + +" Pipe: {{{3 +" with beginning and end pipes +syn region pandocPipeTable start=/\%#=2\([+|]\n\)\@<!\n\@1<=|\(.*|\)\@=/ end=/|.*\n\(\n\|{\)/ containedin=ALLBUT,pandocDelimitedCodeBlock,pandocYAMLHeader keepend +" without beginning and end pipes +syn region pandocPipeTable start=/\%#=2^.*\n-.\{-}|/ end=/|.*\n\n/ keepend +syn match pandocPipeTableDelims /[\|\-:+]/ contained containedin=pandocPipeTable +syn match pandocPipeTableHeader /\(^.*\n\)\(|-\)\@=/ contained containedin=pandocPipeTable +syn match pandocPipeTableHeader /\(^.*\n\)\(-\)\@=/ contained containedin=pandocPipeTable +" }}}3 + +syn match pandocTableHeaderWord /\<.\{-}\>/ contained containedin=pandocGridTableHeader,pandocPipeTableHeader contains=@Spell +" }}}2 + +" Delimited Code Blocks: {{{2 +" this is here because we can override strikeouts and subscripts +syn region pandocDelimitedCodeBlock start=/^\(>\s\)\?\z(\([ ]\+\|\t\)\=\~\{3,}\~*\)/ end=/^\z1\~*/ skipnl contains=pandocDelimitedCodeBlockStart,pandocDelimitedCodeBlockEnd keepend +syn region pandocDelimitedCodeBlock start=/^\(>\s\)\?\z(\([ ]\+\|\t\)\=`\{3,}`*\)/ end=/^\z1`*/ skipnl contains=pandocDelimitedCodeBlockStart,pandocDelimitedCodeBlockEnd keepend +call s:WithConceal('codeblock_start', 'syn match pandocDelimitedCodeBlockStart /\(\(\_^\n\_^\|\%^\)\(>\s\)\?\( \+\|\t\)\=\)\@<=\(\~\{3,}\~*\|`\{3,}`*\)/ contained containedin=pandocDelimitedCodeBlock nextgroup=pandocDelimitedCodeBlockLanguage', 'conceal cchar='.s:cchars['codelang']) +syn match pandocDelimitedCodeBlockLanguage /\(\s\?\)\@<=.\+\(\_$\)\@=/ contained +call s:WithConceal('codeblock_delim', 'syn match pandocDelimitedCodeBlockEnd /\(`\{3,}`*\|\~\{3,}\~*\)\(\_$\n\(>\s\)\?\_$\)\@=/ contained containedin=pandocDelimitedCodeBlock', 'conceal cchar='.s:cchars['codeend']) +syn match pandocBlockQuoteinDelimitedCodeBlock '^>' contained containedin=pandocDelimitedCodeBlock +syn match pandocCodePre /<pre>.\{-}<\/pre>/ skipnl +syn match pandocCodePre /<code>.\{-}<\/code>/ skipnl + +" enable highlighting for embedded region in codeblocks if there exists a +" g:pandoc#syntax#codeblocks#embeds#langs *list*. +" +" entries in this list are the language code interpreted by pandoc, +" if this differs from the name of the vim syntax file, append =vimname +" e.g. let g:pandoc#syntax#codeblocks#embeds#langs = ["haskell", "literatehaskell=lhaskell"] +" +if g:pandoc#syntax#codeblocks#embeds#use != 0 + for l in g:pandoc#syntax#codeblocks#embeds#langs + call EnableEmbedsforCodeblocksWithLang(l) + endfor +endif +" }}}2 + +" Abbreviations: {{{2 +syn region pandocAbbreviationDefinition start=/^\*\[.\{-}\]:\s*/ end='$' contains=pandocNoFormatted,@Spell,pandocAmpersandEscape +call s:WithConceal('abbrev', 'syn match pandocAbbreviationSeparator /:/ contained containedin=pandocAbbreviationDefinition', 'conceal cchar='.s:cchars['abbrev']) +syn match pandocAbbreviation /\*\[.\{-}\]/ contained containedin=pandocAbbreviationDefinition +call s:WithConceal('abbrev', 'syn match pandocAbbreviationHead /\*\[/ contained containedin=pandocAbbreviation', 'conceal') +call s:WithConceal('abbrev', 'syn match pandocAbbreviationTail /\]/ contained containedin=pandocAbbreviation', 'conceal') +" }}}2 + +" Footnotes: {{{2 +" we put these here not to interfere with superscripts. +syn match pandocFootnoteID /\[\^[^\]]\+\]/ nextgroup=pandocFootnoteDef + +" Inline footnotes +syn region pandocFootnoteDef start=/\^\[/ skip=/\[.\{-}]/ end=/\]/ contains=pandocReferenceLabel,pandocReferenceURL,pandocLatex,pandocPCite,pandocCiteKey,pandocStrong,pandocEmphasis,pandocStrongEmphasis,pandocNoFormatted,pandocSuperscript,pandocSubscript,pandocStrikeout,pandocEnDash,pandocEmDash,pandocEllipses,pandocBeginQuote,pandocEndQuote,@Spell,pandocAmpersandEscape skipnl keepend +call s:WithConceal('footnote', 'syn match pandocFootnoteDefHead /\^\[/ contained containedin=pandocFootnoteDef', 'conceal cchar='.s:cchars['footnote']) +call s:WithConceal('footnote', 'syn match pandocFootnoteDefTail /\]/ contained containedin=pandocFootnoteDef', 'conceal') + +" regular footnotes +syn region pandocFootnoteBlock start=/\[\^.\{-}\]:\s*\n*/ end=/^\n^\s\@!/ contains=pandocReferenceLabel,pandocReferenceURL,pandocLatex,pandocPCite,pandocCiteKey,pandocStrong,pandocEmphasis,pandocNoFormatted,pandocSuperscript,pandocSubscript,pandocStrikeout,pandocEnDash,pandocEmDash,pandocNewLine,pandocStrongEmphasis,pandocEllipses,pandocBeginQuote,pandocEndQuote,pandocLaTeXInlineMath,pandocEscapedDollar,pandocLaTeXCommand,pandocLaTeXMathBlock,pandocLaTeXRegion,pandocAmpersandEscape,@Spell skipnl +syn match pandocFootnoteBlockSeparator /:/ contained containedin=pandocFootnoteBlock +syn match pandocFootnoteID /\[\^.\{-}\]/ contained containedin=pandocFootnoteBlock +call s:WithConceal('footnote', 'syn match pandocFootnoteIDHead /\[\^/ contained containedin=pandocFootnoteID', 'conceal cchar='.s:cchars['footnote']) +call s:WithConceal('footnote', 'syn match pandocFootnoteIDTail /\]/ contained containedin=pandocFootnoteID', 'conceal') +" }}}2 + +" List Items: {{{2 +" Unordered lists +syn match pandocUListItem /^>\=\s*[*+-]\s\+-\@!.*$/ nextgroup=pandocUListItem,pandocLaTeXMathBlock,pandocLaTeXInlineMath,pandocEscapedDollar,pandocDelimitedCodeBlock,pandocListItemContinuation contains=@Spell,pandocEmphasis,pandocStrong,pandocNoFormatted,pandocStrikeout,pandocSubscript,pandocSuperscript,pandocStrongEmphasis,pandocStrongEmphasis,pandocPCite,pandocICite,pandocCiteKey,pandocReferenceLabel,pandocLaTeXCommand,pandocLaTeXMathBlock,pandocLaTeXInlineMath,pandocEscapedDollar,pandocReferenceURL,pandocAutomaticLink,pandocFootnoteDef,pandocFootnoteBlock,pandocFootnoteID,pandocAmpersandEscape skipempty display +call s:WithConceal('list', 'syn match pandocUListItemBullet /^>\=\s*\zs[*+-]/ contained containedin=pandocUListItem', 'conceal cchar='.s:cchars['li']) + +" Ordered lists +syn match pandocListItem /^\s*(\?\(\d\+\|\l\|\#\|@\)[.)].*$/ nextgroup=pandocListItem,pandocLaTeXMathBlock,pandocLaTeXInlineMath,pandocEscapedDollar,pandocDelimitedCodeBlock,pandocListItemContinuation contains=@Spell,pandocEmphasis,pandocStrong,pandocNoFormatted,pandocStrikeout,pandocSubscript,pandocSuperscript,pandocStrongEmphasis,pandocStrongEmphasis,pandocPCite,pandocICite,pandocCiteKey,pandocReferenceLabel,pandocLaTeXCommand,pandocLaTeXMathBlock,pandocLaTeXInlineMath,pandocEscapedDollar,pandocAutomaticLink,pandocFootnoteDef,pandocFootnoteBlock,pandocFootnoteID,pandocAmpersandEscape skipempty display + +" support for roman numerals up to 'c' +if g:pandoc#syntax#roman_lists != 0 + syn match pandocListItem /^\s*(\?x\=l\=\(i\{,3}[vx]\=\)\{,3}c\{,3}[.)].*$/ nextgroup=pandocListItem,pandocMathBlock,pandocLaTeXInlineMath,pandocEscapedDollar,pandocDelimitedCodeBlock,pandocListItemContinuation,pandocAutomaticLink skipempty display +endif +syn match pandocListItemBullet /^(\?.\{-}[.)]/ contained containedin=pandocListItem +syn match pandocListItemBulletId /\(\d\+\|\l\|\#\|@.\{-}\|x\=l\=\(i\{,3}[vx]\=\)\{,3}c\{,3}\)/ contained containedin=pandocListItemBullet + +syn match pandocListItemContinuation /^\s\+\([-+*]\s\+\|(\?.\+[).]\)\@<!\([[:upper:][:lower:]_"[]\|\*\S\)\@=.*$/ nextgroup=pandocLaTeXMathBlock,pandocLaTeXInlineMath,pandocEscapedDollar,pandocDelimitedCodeBlock,pandocListItemContinuation,pandocListItem contains=@Spell,pandocEmphasis,pandocStrong,pandocNoFormatted,pandocStrikeout,pandocSubscript,pandocSuperscript,pandocStrongEmphasis,pandocStrongEmphasis,pandocPCite,pandocICite,pandocCiteKey,pandocReferenceLabel,pandocReferenceURL,pandocLaTeXCommand,pandocLaTeXMathBlock,pandocLaTeXInlineMath,pandocEscapedDollar,pandocAutomaticLink,pandocFootnoteDef,pandocFootnoteBlock,pandocFootnoteID,pandocAmpersandEscape contained skipempty display +" }}}2 + +" Definitions: {{{2 +if g:pandoc#syntax#use_definition_lists == 1 + syn region pandocDefinitionBlock start=/^\%(\_^\s*\([`~]\)\1\{2,}\)\@!.*\n\(^\s*\n\)\=\s\{0,2}\([:~]\)\(\3\{2,}\3*\)\@!/ skip=/\n\n\zs\s/ end=/\n\n/ contains=pandocDefinitionBlockMark,pandocDefinitionBlockTerm,pandocCodeBlockInsideIndent,pandocEmphasis,pandocStrong,pandocStrongEmphasis,pandocNoFormatted,pandocStrikeout,pandocSubscript,pandocSuperscript,pandocFootnoteID,pandocReferenceURL,pandocReferenceLabel,pandocLaTeXMathBlock,pandocLaTeXInlineMath,pandocEscapedDollar,pandocAutomaticLink,pandocEmDash,pandocEnDash,pandocFootnoteDef,pandocFootnoteBlock,pandocFootnoteID + syn match pandocDefinitionBlockTerm /^.*\n\(^\s*\n\)\=\(\s*[:~]\)\@=/ contained contains=pandocNoFormatted,pandocEmphasis,pandocStrong,pandocLaTeXInlineMath,pandocEscapedDollar,pandocFootnoteDef,pandocFootnoteBlock,pandocFootnoteID nextgroup=pandocDefinitionBlockMark + call s:WithConceal('definition', 'syn match pandocDefinitionBlockMark /^\s*[:~]/ contained', 'conceal cchar='.s:cchars['definition']) +endif +" }}}2 + +" Special: {{{2 + +" New_lines: {{{3 +if g:pandoc#syntax#newlines == 1 + call s:WithConceal('newline', 'syn match pandocNewLine /\%(\%(\S\)\@<= \{2,}\|\\\)$/ display containedin=pandocEmphasis,pandocStrong,pandocStrongEmphasis,pandocStrongInEmphasis,pandocEmphasisInStrong', 'conceal cchar='.s:cchars['newline']) +endif +" }}}3 + +" Emdashes: {{{3 +if &encoding ==# 'utf-8' + call s:WithConceal('emdashes', 'syn match pandocEllipses /\([^-]\)\@<=---\([^-]\)\@=/ display', 'conceal cchar=—') +endif +" }}}3 + +" Endashes: {{{3 +if &encoding ==# 'utf-8' + call s:WithConceal('endashes', 'syn match pandocEllipses /\([^-]\)\@<=--\([^-]\)\@=/ display', 'conceal cchar=–') +endif +" }}}3 + +" Ellipses: {{{3 +if &encoding ==# 'utf-8' + call s:WithConceal('ellipses', 'syn match pandocEllipses /\.\.\./ display', 'conceal cchar=…') +endif +" }}}3 + +" Quotes: {{{3 +if &encoding ==# 'utf-8' + call s:WithConceal('quotes', 'syn match pandocBeginQuote /"\</ containedin=pandocEmphasis,pandocStrong,pandocListItem,pandocListItemContinuation,pandocUListItem display', 'conceal cchar='.s:cchars['quote_s']) + call s:WithConceal('quotes', 'syn match pandocEndQuote /\(\>[[:punct:]]*\)\@<="[[:blank:][:punct:]\n]\@=/ containedin=pandocEmphasis,pandocStrong,pandocUListItem,pandocListItem,pandocListItemContinuation display', 'conceal cchar='.s:cchars['quote_e']) +endif +" }}}3 + +" Hrule: {{{3 +syn match pandocHRule /^\s*\([*\-_]\)\s*\%(\1\s*\)\{2,}$/ display +" }}}3 + +" Backslashes: {{{3 +if g:pandoc#syntax#conceal#backslash == 1 + syn match pandocBackslash /\v\\@<!\\((re)?newcommand)@!/ containedin=ALLBUT,pandocCodeblock,pandocCodeBlockInsideIndent,pandocNoFormatted,pandocNoFormattedInEmphasis,pandocNoFormattedInStrong,pandocDelimitedCodeBlock,pandocLineBlock,pandocYAMLHeader conceal +endif +" }}}3 + +" &-escaped Special Characters: {{{3 +syn match pandocAmpersandEscape /\v\&(#\d+|#x\x+|[[:alnum:]]+)\;/ contains=NoSpell +" }}}3 + +" YAML: {{{2 +try + unlet! b:current_syntax + syn include @YAML syntax/yaml.vim +catch /E484/ +endtry +syn region pandocYAMLHeader start=/\%(\%^\|\_^\s*\n\)\@<=\_^-\{3}\ze\n.\+/ end=/^\([-.]\)\1\{2}$/ keepend contains=@YAML containedin=TOP +" }}}2 + +" }}}1 + +" Styling: {{{1 +function! s:SetupPandocHighlights() + + hi def link pandocOperator Operator + + " override this for consistency + hi pandocTitleBlock term=italic gui=italic + hi def link pandocTitleBlockTitle Directory + hi def link pandocAtxHeader Title + hi def link pandocAtxStart Operator + hi def link pandocSetexHeader Title + hi def link pandocHeaderAttr Comment + hi def link pandocHeaderID Identifier + + hi def link pandocLaTexSectionCmd texSection + hi def link pandocLaTeXDelimiter texDelimiter + + hi def link pandocHTMLComment Comment + hi def link pandocHTMLCommentStart Delimiter + hi def link pandocHTMLCommentEnd Delimiter + hi def link pandocBlockQuote Comment + hi def link pandocBlockQuoteMark Comment + hi def link pandocAmpersandEscape Special + + " if the user sets g:pandoc#syntax#codeblocks#ignore to contain + " a codeblock type, don't highlight it so that it remains Normal + if index(g:pandoc#syntax#codeblocks#ignore, 'definition') == -1 + hi def link pandocCodeBlockInsideIndent String + endif + + if index(g:pandoc#syntax#codeblocks#ignore, 'delimited') == -1 + hi def link pandocDelimitedCodeBlock Special + endif + + hi def link pandocDelimitedCodeBlockStart Delimiter + hi def link pandocDelimitedCodeBlockEnd Delimiter + hi def link pandocDelimitedCodeBlockLanguage Comment + hi def link pandocBlockQuoteinDelimitedCodeBlock pandocBlockQuote + hi def link pandocCodePre String + + hi def link pandocLineBlockDelimiter Delimiter + + hi def link pandocListItemBullet Operator + hi def link pandocUListItemBullet Operator + hi def link pandocListItemBulletId Identifier + + hi def link pandocReferenceLabel Label + hi def link pandocReferenceURL Underlined + hi def link pandocLinkTip Identifier + hi def link pandocImageIcon Operator + + hi def link pandocReferenceDefinition Operator + hi def link pandocReferenceDefinitionLabel Label + hi def link pandocReferenceDefinitionAddress Underlined + hi def link pandocReferenceDefinitionTip Identifier + + hi def link pandocAutomaticLink Underlined + + hi def link pandocDefinitionBlockTerm Identifier + hi def link pandocDefinitionBlockMark Operator + + hi def link pandocSimpleTableDelims Delimiter + hi def link pandocSimpleTableHeader pandocStrong + hi def link pandocTableMultilineHeader pandocStrong + hi def link pandocTableDelims Delimiter + hi def link pandocGridTableDelims Delimiter + hi def link pandocGridTableHeader Delimiter + hi def link pandocPipeTableDelims Delimiter + hi def link pandocPipeTableHeader Delimiter + hi def link pandocTableHeaderWord pandocStrong + + hi def link pandocAbbreviationHead Type + hi def link pandocAbbreviation Label + hi def link pandocAbbreviationTail Type + hi def link pandocAbbreviationSeparator Identifier + hi def link pandocAbbreviationDefinition Comment + + hi def link pandocFootnoteID Label + hi def link pandocFootnoteIDHead Type + hi def link pandocFootnoteIDTail Type + hi def link pandocFootnoteDef Comment + hi def link pandocFootnoteDefHead Type + hi def link pandocFootnoteDefTail Type + hi def link pandocFootnoteBlock Comment + hi def link pandocFootnoteBlockSeparator Operator + + hi def link pandocPCite Operator + hi def link pandocICite Operator + hi def link pandocCiteKey Label + hi def link pandocCiteAnchor Operator + hi def link pandocCiteLocator Operator + + if g:pandoc#syntax#style#emphases == 1 + hi pandocEmphasis gui=italic cterm=italic + hi pandocStrong gui=bold cterm=bold + hi pandocStrongEmphasis gui=bold,italic cterm=bold,italic + hi pandocStrongInEmphasis gui=bold,italic cterm=bold,italic + hi pandocEmphasisInStrong gui=bold,italic cterm=bold,italic + if !exists('s:hi_tail') + let s:fg = '' " Vint can't figure ou these get set dynamically + let s:bg = '' " so initialize them manually first + for s:i in ['fg', 'bg'] + let s:tmp_val = synIDattr(synIDtrans(hlID('String')), s:i) + let s:tmp_ui = has('gui_running') || (has('termguicolors') && &termguicolors) ? 'gui' : 'cterm' + if !empty(s:tmp_val) && s:tmp_val != -1 + exe 'let s:'.s:i . ' = "'.s:tmp_ui.s:i.'='.s:tmp_val.'"' + else + exe 'let s:'.s:i . ' = ""' + endif + endfor + let s:hi_tail = ' '.s:fg.' '.s:bg + endif + exe 'hi pandocNoFormattedInEmphasis gui=italic cterm=italic'.s:hi_tail + exe 'hi pandocNoFormattedInStrong gui=bold cterm=bold'.s:hi_tail + endif + hi def link pandocNoFormatted String + hi def link pandocNoFormattedAttrs Comment + hi def link pandocSubscriptMark Operator + hi def link pandocSuperscriptMark Operator + hi def link pandocStrikeoutMark Operator + if g:pandoc#syntax#style#underline_special == 1 + hi pandocSubscript gui=underline cterm=underline + hi pandocSuperscript gui=underline cterm=underline + hi pandocStrikeout gui=underline cterm=underline + endif + hi def link pandocNewLine Error + hi def link pandocHRule Delimiter +endfunction + +call s:SetupPandocHighlights() + +" }}}1 + +let b:current_syntax = 'pandoc' + +syntax sync clear +syntax sync minlines=1000 + +let &cpo = s:cpo_save +unlet s:cpo_save + +" vim: set fdm=marker foldlevel=0: diff --git a/runtime/syntax/requirements.vim b/runtime/syntax/requirements.vim new file mode 100644 index 0000000000..a87d1e9a39 --- /dev/null +++ b/runtime/syntax/requirements.vim @@ -0,0 +1,67 @@ +" the Requirements File Format syntax support for Vim +" Version: 1.8.0 +" Author: raimon <raimon49@hotmail.com> +" Upstream: https://github.com/raimon49/requirements.txt.vim +" License: MIT LICENSE +" The MIT License (MIT) +" +" Copyright (c) 2015 raimon +" +" Permission is hereby granted, free of charge, to any person obtaining a copy +" of this software and associated documentation files (the "Software"), to deal +" in the Software without restriction, including without limitation the rights +" to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +" copies of the Software, and to permit persons to whom the Software is +" furnished to do so, subject to the following conditions: +" +" The above copyright notice and this permission notice shall be included in all +" copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +" OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +" SOFTWARE. + +if exists("b:current_syntax") && b:current_syntax == "requirements" + finish +endif + +syn case match + +" https://pip.pypa.io/en/stable/reference/requirements-file-format/ +" https://pip.pypa.io/en/stable/reference/inspect-report/#example +syn keyword requirementsKeyword implementation_name implementation_version os_name platform_machine platform_release platform_system platform_version python_full_version platform_python_implementation python_version sys_platform contained +syn region requirementsSubst matchgroup=requirementsSubstDelim start="\V${" end="\V}" +syn region requirementsString matchgroup=requirementsStringDelim start=`'` skip=`\\'` end=`'` +syn region requirementsString matchgroup=requirementsStringDelim start=`"` skip=`\\"` end=`"` +syn match requirementsVersion "\v\d+[a-zA-Z0-9\.\-\*]*" +syn region requirementsComment start="[ \t]*#" end="$" +syn match requirementsCommandOption "\v^\[?--?[a-zA-Z\-]*\]?" +syn match requirementsVersionSpecifiers "\v(\=\=\=?|\<\=?|\>\=?|\~\=|\!\=)" +syn match requirementsPackageName "\v^([a-zA-Z0-9][a-zA-Z0-9\-_\.]*[a-zA-Z0-9])" +syn match requirementsExtras "\v\[\S+\]" +syn match requirementsVersionControls "\v(git\+?|hg\+|svn\+|bzr\+).*://.\S+" +syn match requirementsURLs "\v(\@\s)?(https?|ftp|gopher)://?[^\s/$.?#].\S*" +syn match requirementsEnvironmentMarkers "\v;\s[^#]+" contains=requirementsKeyword,requirementsVersionSpecifiers,requirementsString + +hi def link requirementsKeyword Keyword +hi def link requirementsSubstDelim Delimiter +hi def link requirementsSubst PreProc +hi def link requirementsStringDelim Delimiter +hi def link requirementsString String +hi def link requirementsVersion Number +hi def link requirementsComment Comment +hi def link requirementsCommandOption Special +hi def link requirementsVersionSpecifiers Boolean +hi def link requirementsPackageName Identifier +hi def link requirementsExtras Type +hi def link requirementsVersionControls Underlined +hi def link requirementsURLs Underlined +hi def link requirementsEnvironmentMarkers Macro + +let b:current_syntax = "requirements" + +" vim: et sw=4 ts=4 sts=4: diff --git a/runtime/syntax/shared/debversions.vim b/runtime/syntax/shared/debversions.vim index 4aec246e27..e18eca96b1 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 Jan 25 +" Last Change: 2024 Apr 27 " 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', \ - \ 'trusty', 'xenial', 'bionic', 'focal', 'jammy', 'mantic', 'noble', + \ 'trusty', 'xenial', 'bionic', 'focal', 'jammy', 'mantic', 'noble', 'oracular', \ 'devel' \ ] let g:debSharedUnsupportedVersions = [ diff --git a/runtime/syntax/spec.vim b/runtime/syntax/spec.vim index 12ce8d5ac1..4cb3a343eb 100644 --- a/runtime/syntax/spec.vim +++ b/runtime/syntax/spec.vim @@ -111,7 +111,7 @@ syn region specDescriptionArea matchgroup=specSection start='^%description' end= syn region specPackageArea matchgroup=specSection start='^%package' end='^%'me=e-1 contains=specPackageOpts,specPreAmble,specComment "%% Scripts Section %% -syn region specScriptArea matchgroup=specSection start='^%\(prep\|build\|install\|clean\|check\|pre\|postun\|preun\|post\|posttrans\)\>' skip='^%{\|^%\(define\|patch\d*\|configure\|GNUconfigure\|setup\|autosetup\|autopatch\|find_lang\|make_build\|makeinstall\|make_install\)\>' end='^%'me=e-1 contains=specSpecialVariables,specVariables,@specCommands,specVariables,shDo,shFor,shCaseEsac,specNoNumberHilite,specCommandOpts,shComment,shIf,specSpecialChar,specMacroIdentifier,specSectionMacroArea,specSectionMacroBracketArea,shOperator,shQuote1,shQuote2 +syn region specScriptArea matchgroup=specSection start='^%\(prep\|generate_buildrequires\|conf\|build\|install\|clean\|check\|pre\|postun\|preun\|post\|posttrans\)\>' skip='^%{\|^%\(define\|patch\d*\|configure\|GNUconfigure\|setup\|autosetup\|autopatch\|find_lang\|make_build\|makeinstall\|make_install\)\>' end='^%'me=e-1 contains=specSpecialVariables,specVariables,@specCommands,specVariables,shDo,shFor,shCaseEsac,specNoNumberHilite,specCommandOpts,shComment,shIf,specSpecialChar,specMacroIdentifier,specSectionMacroArea,specSectionMacroBracketArea,shOperator,shQuote1,shQuote2 "%% Changelog Section %% syn region specChangelogArea matchgroup=specSection start='^%changelog' end='^%'me=e-1 contains=specEmail,specURL,specWeekday,specMonth,specNumber,specComment,specLicense diff --git a/runtime/syntax/ssa.vim b/runtime/syntax/ssa.vim index a5dbf37c30..3cfae816ff 100644 --- a/runtime/syntax/ssa.vim +++ b/runtime/syntax/ssa.vim @@ -2,7 +2,7 @@ " Language: SubStation Alpha " Maintainer: ObserverOfTime <chronobserver@disroot.org> " Filenames: *.ass,*.ssa -" Last Change: 2022 Oct 10 +" Last Change: 2024 Apr 28 if exists('b:current_syntax') finish @@ -20,16 +20,20 @@ syn match ssaSection /^\[[a-zA-Z0-9+ ]\+\]$/ syn match ssaHeader /^[^;!:]\+:/ skipwhite nextgroup=ssaField " Fields -syn match ssaField /[^,]*/ contained skipwhite nextgroup=ssaDelimiter +syn match ssaField /[^,]*\(,\|$\)/ contained skipwhite contains=ssaDelimiter,ssaTime nextgroup=ssaField " Time -syn match ssaTime /\d:\d\d:\d\d\.\d\d/ contained skipwhite nextgroup=ssaDelimiter +syn match ssaTime /\d:\d\d:\d\d\.\d\d/ contained " Delimiter -syn match ssaDelimiter /,/ contained skipwhite nextgroup=ssaField,ssaTime,ssaText +syn match ssaDelimiter /,/ contained + +" Dialogue +syn match ssaDialogue /^Dialogue:/ transparent skipwhite nextgroup=ssaDialogueFields +syn match ssaDialogueFields /\([^,]*,\)\{9\}/ contained transparent skipwhite contains=ssaField,ssaDelimiter nextgroup=ssaText " Text -syn match ssaText /\(^Dialogue:\(.*,\)\{9}\)\@<=.*$/ contained contains=@ssaTags,@Spell +syn match ssaText /.*$/ contained contains=@ssaTags,@Spell syn cluster ssaTags contains=ssaOverrideTag,ssaEscapeChar,ssaTextComment,ssaItalics,ssaBold,ssaUnderline,ssaStrikeout " Override tags @@ -60,4 +64,4 @@ hi ssaItalics cterm=italic gui=italic hi ssaStrikeout cterm=strikethrough gui=strikethrough hi ssaUnderline cterm=underline gui=underline -let b:current_syntax = 'srt' +let b:current_syntax = 'ssa' diff --git a/runtime/syntax/sshconfig.vim b/runtime/syntax/sshconfig.vim index 750289d83e..99e10fd1ee 100644 --- a/runtime/syntax/sshconfig.vim +++ b/runtime/syntax/sshconfig.vim @@ -63,8 +63,7 @@ syn keyword sshconfigMAC hmac-sha2-256 syn keyword sshconfigMAC hmac-sha2-512 syn keyword sshconfigMAC hmac-md5 syn keyword sshconfigMAC hmac-md5-96 -syn keyword sshconfigMAC hmac-ripemd160 -syn match sshconfigMAC "\<hmac-ripemd160@openssh\.com\>" +syn match sshconfigMAC "\<hmac-ripemd160\%(@openssh\.com\)\?\>" syn match sshconfigMAC "\<umac-64@openssh\.com\>" syn match sshconfigMAC "\<umac-128@openssh\.com\>" syn match sshconfigMAC "\<hmac-sha1-etm@openssh\.com\>" @@ -107,33 +106,35 @@ syn keyword sshconfigSysLogFacility DAEMON USER AUTH AUTHPRIV LOCAL0 LOCAL1 syn keyword sshconfigSysLogFacility LOCAL2 LOCAL3 LOCAL4 LOCAL5 LOCAL6 LOCAL7 syn keyword sshconfigAddressFamily inet inet6 -syn match sshconfigIPQoS "af1[123]" -syn match sshconfigIPQoS "af2[123]" -syn match sshconfigIPQoS "af3[123]" -syn match sshconfigIPQoS "af4[123]" -syn match sshconfigIPQoS "cs[0-7]" -syn keyword sshconfigIPQoS ef lowdelay throughput reliability +syn match sshconfigIPQoS "\<af[1-4][1-3]\>" +syn match sshconfigIPQoS "\<cs[0-7]\>" +syn keyword sshconfigIPQoS ef le lowdelay throughput reliability syn keyword sshconfigKbdInteractive bsdauth pam skey syn keyword sshconfigKexAlgo diffie-hellman-group1-sha1 syn keyword sshconfigKexAlgo diffie-hellman-group14-sha1 syn keyword sshconfigKexAlgo diffie-hellman-group-exchange-sha1 syn keyword sshconfigKexAlgo diffie-hellman-group-exchange-sha256 +syn keyword sshconfigKexAlgo diffie-hellman-group16-sha512 +syn keyword sshconfigKexAlgo diffie-hellman-group18-sha512 +syn keyword sshconfigKexAlgo diffie-hellman-group14-sha256 syn keyword sshconfigKexAlgo ecdh-sha2-nistp256 syn keyword sshconfigKexAlgo ecdh-sha2-nistp384 syn keyword sshconfigKexAlgo ecdh-sha2-nistp521 -syn match sshconfigKexAlgo "\<curve25519-sha256@libssh\.org\>" +syn match sshconfigKexAlgo "\<curve25519-sha256\%(@libssh\.org\)\?\>" +syn match sshconfigKexAlgo "\<sntrup761x25519-sha512@openssh\.com\>" syn keyword sshconfigTunnel point-to-point ethernet -syn match sshconfigVar "%[rhplLdun]\>" +syn match sshconfigVar "%[CdfHhIijKkLlnprTtu]\>" +syn match sshconfigVar "%%" syn match sshconfigSpecial "[*?]" -syn match sshconfigNumber "\d\+" +syn match sshconfigNumber "\<\d\+\>" syn match sshconfigHostPort "\<\(\d\{1,3}\.\)\{3}\d\{1,3}\(:\d\+\)\?\>" syn match sshconfigHostPort "\<\([-a-zA-Z0-9]\+\.\)\+[-a-zA-Z0-9]\{2,}\(:\d\+\)\?\>" syn match sshconfigHostPort "\<\(\x\{,4}:\)\+\x\{,4}[:/]\d\+\>" -syn match sshconfigHostPort "\(Host \)\@<=.\+" -syn match sshconfigHostPort "\(HostName \)\@<=.\+" +syn match sshconfigHostPort "\<\c\(Host \+\)\@<=.\+" +syn match sshconfigHostPort "\<\c\(Hostname \+\)\@<=.\+" " case off syn case ignore @@ -142,10 +143,10 @@ syn case ignore " Keywords syn keyword sshconfigHostSect Host -syn keyword sshconfigMatch canonical final exec host originalhost user localuser all +syn keyword sshconfigMatch canonical final exec localnetwork host originalhost tagged user localuser all -syn keyword sshconfigKeyword AddressFamily syn keyword sshconfigKeyword AddKeysToAgent +syn keyword sshconfigKeyword AddressFamily syn keyword sshconfigKeyword BatchMode syn keyword sshconfigKeyword BindAddress syn keyword sshconfigKeyword BindInterface @@ -157,16 +158,18 @@ syn keyword sshconfigKeyword CanonicalizePermittedCNAMEs syn keyword sshconfigKeyword CASignatureAlgorithms syn keyword sshconfigKeyword CertificateFile syn keyword sshconfigKeyword ChallengeResponseAuthentication +syn keyword sshconfigKeyword ChannelTimeout syn keyword sshconfigKeyword CheckHostIP syn keyword sshconfigKeyword Ciphers syn keyword sshconfigKeyword ClearAllForwardings syn keyword sshconfigKeyword Compression -syn keyword sshconfigKeyword ConnectTimeout syn keyword sshconfigKeyword ConnectionAttempts +syn keyword sshconfigKeyword ConnectTimeout syn keyword sshconfigKeyword ControlMaster syn keyword sshconfigKeyword ControlPath syn keyword sshconfigKeyword ControlPersist syn keyword sshconfigKeyword DynamicForward +syn keyword sshconfigKeyword EnableEscapeCommandline syn keyword sshconfigKeyword EnableSSHKeysign syn keyword sshconfigKeyword EscapeChar syn keyword sshconfigKeyword ExitOnForwardFailure @@ -176,18 +179,17 @@ syn keyword sshconfigKeyword ForwardAgent syn keyword sshconfigKeyword ForwardX11 syn keyword sshconfigKeyword ForwardX11Timeout syn keyword sshconfigKeyword ForwardX11Trusted -syn keyword sshconfigKeyword GSSAPIAuthentication -syn keyword sshconfigKeyword GSSAPIDelegateCredentials syn keyword sshconfigKeyword GatewayPorts syn keyword sshconfigKeyword GlobalKnownHostsFile +syn keyword sshconfigKeyword GSSAPIAuthentication +syn keyword sshconfigKeyword GSSAPIDelegateCredentials syn keyword sshconfigKeyword HashKnownHosts -syn keyword sshconfigKeyword HostKeyAlgorithms -syn keyword sshconfigKeyword HostKeyAlias -syn keyword sshconfigKeyword HostName -syn keyword sshconfigKeyword HostbasedAuthentication syn keyword sshconfigKeyword HostbasedAcceptedAlgorithms +syn keyword sshconfigKeyword HostbasedAuthentication syn keyword sshconfigKeyword HostbasedKeyTypes -syn keyword sshconfigKeyword IPQoS +syn keyword sshconfigKeyword HostKeyAlgorithms +syn keyword sshconfigKeyword HostKeyAlias +syn keyword sshconfigKeyword Hostname syn keyword sshconfigKeyword IdentitiesOnly syn keyword sshconfigKeyword IdentityAgent syn keyword sshconfigKeyword IdentityFile @@ -206,15 +208,16 @@ syn keyword sshconfigKeyword MACs syn keyword sshconfigKeyword Match syn keyword sshconfigKeyword NoHostAuthenticationForLocalhost syn keyword sshconfigKeyword NumberOfPasswordPrompts -syn keyword sshconfigKeyword PKCS11Provider +syn keyword sshconfigKeyword ObscureKeystrokeTiming syn keyword sshconfigKeyword PasswordAuthentication syn keyword sshconfigKeyword PermitLocalCommand syn keyword sshconfigKeyword PermitRemoteOpen +syn keyword sshconfigKeyword PKCS11Provider syn keyword sshconfigKeyword Port syn keyword sshconfigKeyword PreferredAuthentications syn keyword sshconfigKeyword ProxyCommand syn keyword sshconfigKeyword ProxyJump -syn keyword sshconfigKeyword ProxyUseFDPass +syn keyword sshconfigKeyword ProxyUseFdpass syn keyword sshconfigKeyword PubkeyAcceptedAlgorithms syn keyword sshconfigKeyword PubkeyAcceptedKeyTypes syn keyword sshconfigKeyword PubkeyAuthentication @@ -229,18 +232,19 @@ syn keyword sshconfigKeyword SendEnv syn keyword sshconfigKeyword ServerAliveCountMax syn keyword sshconfigKeyword ServerAliveInterval syn keyword sshconfigKeyword SessionType -syn keyword sshconfigKeyword SmartcardDevice syn keyword sshconfigKeyword SetEnv +syn keyword sshconfigKeyword SmartcardDevice syn keyword sshconfigKeyword StdinNull syn keyword sshconfigKeyword StreamLocalBindMask syn keyword sshconfigKeyword StreamLocalBindUnlink syn keyword sshconfigKeyword StrictHostKeyChecking syn keyword sshconfigKeyword SyslogFacility +syn keyword sshconfigKeyword Tag syn keyword sshconfigKeyword TCPKeepAlive syn keyword sshconfigKeyword Tunnel syn keyword sshconfigKeyword TunnelDevice -syn keyword sshconfigKeyword UseBlacklistedKeys syn keyword sshconfigKeyword UpdateHostKeys +syn keyword sshconfigKeyword UseBlacklistedKeys syn keyword sshconfigKeyword User syn keyword sshconfigKeyword UserKnownHostsFile syn keyword sshconfigKeyword VerifyHostKeyDNS @@ -268,9 +272,9 @@ syn keyword sshconfigDeprecated UsePrivilegedPort hi def link sshconfigComment Comment hi def link sshconfigTodo Todo hi def link sshconfigHostPort sshconfigConstant -hi def link sshconfigNumber sshconfigConstant +hi def link sshconfigNumber Number hi def link sshconfigConstant Constant -hi def link sshconfigYesNo sshconfigEnum +hi def link sshconfigYesNo Boolean hi def link sshconfigCipher sshconfigDeprecated hi def link sshconfigCiphers sshconfigEnum hi def link sshconfigMAC sshconfigEnum diff --git a/runtime/syntax/sshdconfig.vim b/runtime/syntax/sshdconfig.vim index c0d9c3f598..8b539d907b 100644 --- a/runtime/syntax/sshdconfig.vim +++ b/runtime/syntax/sshdconfig.vim @@ -64,8 +64,7 @@ syn keyword sshdconfigMAC hmac-sha2-256 syn keyword sshdconfigMAC hmac-sha2-512 syn keyword sshdconfigMAC hmac-md5 syn keyword sshdconfigMAC hmac-md5-96 -syn keyword sshdconfigMAC hmac-ripemd160 -syn match sshdconfigMAC "\<hmac-ripemd160@openssh\.com\>" +syn match sshdconfigMAC "\<hmac-ripemd160\%(@openssh\.com\)\?\>" syn match sshdconfigMAC "\<umac-64@openssh\.com\>" syn match sshdconfigMAC "\<umac-128@openssh\.com\>" syn match sshdconfigMAC "\<hmac-sha1-etm@openssh\.com\>" @@ -108,12 +107,9 @@ syn keyword sshdconfigSysLogFacility LOCAL2 LOCAL3 LOCAL4 LOCAL5 LOCAL6 LOCAL7 syn keyword sshdconfigCompression delayed -syn match sshdconfigIPQoS "af1[123]" -syn match sshdconfigIPQoS "af2[123]" -syn match sshdconfigIPQoS "af3[123]" -syn match sshdconfigIPQoS "af4[123]" -syn match sshdconfigIPQoS "cs[0-7]" -syn keyword sshdconfigIPQoS ef lowdelay throughput reliability +syn match sshdconfigIPQoS "\<af[1-4][1-3]\>" +syn match sshdconfigIPQoS "\<cs[0-7]\>" +syn keyword sshdconfigIPQoS ef le lowdelay throughput reliability syn keyword sshdconfigKexAlgo diffie-hellman-group1-sha1 syn keyword sshdconfigKexAlgo diffie-hellman-group14-sha1 @@ -125,20 +121,20 @@ syn keyword sshdconfigKexAlgo diffie-hellman-group-exchange-sha256 syn keyword sshdconfigKexAlgo ecdh-sha2-nistp256 syn keyword sshdconfigKexAlgo ecdh-sha2-nistp384 syn keyword sshdconfigKexAlgo ecdh-sha2-nistp521 -syn keyword sshdconfigKexAlgo curve25519-sha256 -syn match sshdconfigKexAlgo "\<curve25519-sha256@libssh\.org\>" +syn match sshdconfigKexAlgo "\<curve25519-sha256\%(@libssh\.org\)\?\>" syn match sshdconfigKexAlgo "\<sntrup4591761x25519-sha512@tinyssh\.org\>" +syn match sshdconfigKexAlgo "\<sntrup761x25519-sha512@openssh\.com\>" syn keyword sshdconfigTunnel point-to-point ethernet syn keyword sshdconfigSubsystem internal-sftp -syn match sshdconfigVar "%[hu]\>" +syn match sshdconfigVar "%[CDFfhiKksTtUu]\>" syn match sshdconfigVar "%%" syn match sshdconfigSpecial "[*?]" -syn match sshdconfigNumber "\d\+" +syn match sshdconfigNumber "\<\d\+\>" syn match sshdconfigHostPort "\<\(\d\{1,3}\.\)\{3}\d\{1,3}\(:\d\+\)\?\>" syn match sshdconfigHostPort "\<\([-a-zA-Z0-9]\+\.\)\+[-a-zA-Z0-9]\{2,}\(:\d\+\)\?\>" " FIXME: this matches quite a few things which are NOT valid IPv6 addresses @@ -162,15 +158,16 @@ syn keyword sshdconfigKeyword AllowStreamLocalForwarding syn keyword sshdconfigKeyword AllowTcpForwarding syn keyword sshdconfigKeyword AllowUsers syn keyword sshdconfigKeyword AuthenticationMethods -syn keyword sshdconfigKeyword AuthorizedKeysFile syn keyword sshdconfigKeyword AuthorizedKeysCommand syn keyword sshdconfigKeyword AuthorizedKeysCommandUser +syn keyword sshdconfigKeyword AuthorizedKeysFile syn keyword sshdconfigKeyword AuthorizedPrincipalsCommand syn keyword sshdconfigKeyword AuthorizedPrincipalsCommandUser syn keyword sshdconfigKeyword AuthorizedPrincipalsFile syn keyword sshdconfigKeyword Banner syn keyword sshdconfigKeyword CASignatureAlgorithms syn keyword sshdconfigKeyword ChallengeResponseAuthentication +syn keyword sshdconfigKeyword ChannelTimeout syn keyword sshdconfigKeyword ChrootDirectory syn keyword sshdconfigKeyword Ciphers syn keyword sshdconfigKeyword ClientAliveCountMax @@ -187,22 +184,22 @@ syn keyword sshdconfigKeyword GatewayPorts syn keyword sshdconfigKeyword GSSAPIAuthentication syn keyword sshdconfigKeyword GSSAPICleanupCredentials syn keyword sshdconfigKeyword GSSAPIEnablek5users -syn keyword sshdconfigKeyword GSSAPIKeyExchange syn keyword sshdconfigKeyword GSSAPIKexAlgorithms +syn keyword sshdconfigKeyword GSSAPIKeyExchange syn keyword sshdconfigKeyword GSSAPIStoreCredentialsOnRekey syn keyword sshdconfigKeyword GSSAPIStrictAcceptorCheck -syn keyword sshdconfigKeyword HostCertificate -syn keyword sshdconfigKeyword HostKey -syn keyword sshdconfigKeyword HostKeyAgent -syn keyword sshdconfigKeyword HostKeyAlgorithms syn keyword sshdconfigKeyword HostbasedAcceptedAlgorithms syn keyword sshdconfigKeyword HostbasedAcceptedKeyTypes syn keyword sshdconfigKeyword HostbasedAuthentication syn keyword sshdconfigKeyword HostbasedUsesNameFromPacketOnly -syn keyword sshdconfigKeyword IPQoS +syn keyword sshdconfigKeyword HostCertificate +syn keyword sshdconfigKeyword HostKey +syn keyword sshdconfigKeyword HostKeyAgent +syn keyword sshdconfigKeyword HostKeyAlgorithms syn keyword sshdconfigKeyword IgnoreRhosts syn keyword sshdconfigKeyword IgnoreUserKnownHosts syn keyword sshdconfigKeyword Include +syn keyword sshdconfigKeyword IPQoS syn keyword sshdconfigKeyword KbdInteractiveAuthentication syn keyword sshdconfigKeyword KerberosAuthentication syn keyword sshdconfigKeyword KerberosGetAFSToken @@ -213,9 +210,9 @@ syn keyword sshdconfigKeyword KerberosUseKuserok syn keyword sshdconfigKeyword KexAlgorithms syn keyword sshdconfigKeyword KeyRegenerationInterval syn keyword sshdconfigKeyword ListenAddress +syn keyword sshdconfigKeyword LoginGraceTime syn keyword sshdconfigKeyword LogLevel syn keyword sshdconfigKeyword LogVerbose -syn keyword sshdconfigKeyword LoginGraceTime syn keyword sshdconfigKeyword MACs syn keyword sshdconfigKeyword Match syn keyword sshdconfigKeyword MaxAuthTries @@ -223,8 +220,6 @@ syn keyword sshdconfigKeyword MaxSessions syn keyword sshdconfigKeyword MaxStartups syn keyword sshdconfigKeyword ModuliFile syn keyword sshdconfigKeyword PasswordAuthentication -syn keyword sshdconfigKeyword PerSourceMaxStartups -syn keyword sshdconfigKeyword PerSourceNetBlockSize syn keyword sshdconfigKeyword PermitBlacklistedKeys syn keyword sshdconfigKeyword PermitEmptyPasswords syn keyword sshdconfigKeyword PermitListen @@ -234,6 +229,8 @@ syn keyword sshdconfigKeyword PermitTTY syn keyword sshdconfigKeyword PermitTunnel syn keyword sshdconfigKeyword PermitUserEnvironment syn keyword sshdconfigKeyword PermitUserRC +syn keyword sshdconfigKeyword PerSourceMaxStartups +syn keyword sshdconfigKeyword PerSourceNetBlockSize syn keyword sshdconfigKeyword PidFile syn keyword sshdconfigKeyword Port syn keyword sshdconfigKeyword PrintLastLog @@ -243,23 +240,24 @@ syn keyword sshdconfigKeyword PubkeyAcceptedAlgorithms syn keyword sshdconfigKeyword PubkeyAcceptedKeyTypes syn keyword sshdconfigKeyword PubkeyAuthentication syn keyword sshdconfigKeyword PubkeyAuthOptions -syn keyword sshdconfigKeyword RSAAuthentication +syn keyword sshdconfigKeyword RDomain syn keyword sshdconfigKeyword RekeyLimit syn keyword sshdconfigKeyword RequiredRSASize syn keyword sshdconfigKeyword RevokedKeys -syn keyword sshdconfigKeyword RDomain syn keyword sshdconfigKeyword RhostsRSAAuthentication +syn keyword sshdconfigKeyword RSAAuthentication syn keyword sshdconfigKeyword SecurityKeyProvider syn keyword sshdconfigKeyword ServerKeyBits syn keyword sshdconfigKeyword SetEnv syn keyword sshdconfigKeyword ShowPatchLevel -syn keyword sshdconfigKeyword StrictModes syn keyword sshdconfigKeyword StreamLocalBindMask syn keyword sshdconfigKeyword StreamLocalBindUnlink +syn keyword sshdconfigKeyword StrictModes syn keyword sshdconfigKeyword Subsystem syn keyword sshdconfigKeyword SyslogFacility syn keyword sshdconfigKeyword TCPKeepAlive syn keyword sshdconfigKeyword TrustedUserCAKeys +syn keyword sshdconfigKeyword UnusedConnectionTimeout syn keyword sshdconfigKeyword UseBlacklist syn keyword sshdconfigKeyword UseBlocklist syn keyword sshdconfigKeyword UseDNS @@ -278,14 +276,13 @@ syn keyword sshdconfigKeyword XAuthLocation hi def link sshdconfigComment Comment hi def link sshdconfigTodo Todo hi def link sshdconfigHostPort sshdconfigConstant -hi def link sshdconfigTime sshdconfigConstant -hi def link sshdconfigNumber sshdconfigConstant +hi def link sshdconfigTime Number +hi def link sshdconfigNumber Number hi def link sshdconfigConstant Constant -hi def link sshdconfigYesNo sshdconfigEnum +hi def link sshdconfigYesNo Boolean hi def link sshdconfigAddressFamily sshdconfigEnum hi def link sshdconfigPrivilegeSeparation sshdconfigEnum hi def link sshdconfigTcpForwarding sshdconfigEnum -hi def link sshdconfigRootLogin sshdconfigEnum hi def link sshdconfigCiphers sshdconfigEnum hi def link sshdconfigMAC sshdconfigEnum hi def link sshdconfigHostKeyAlgo sshdconfigEnum diff --git a/runtime/syntax/stylus.vim b/runtime/syntax/stylus.vim new file mode 100644 index 0000000000..fd0f33b65a --- /dev/null +++ b/runtime/syntax/stylus.vim @@ -0,0 +1,61 @@ +" Vim syntax file +" Language: Stylus +" Maintainer: Hsiaoming Yang <lepture@me.com>, Marc Harter +" Filenames: *.styl, *.stylus +" Based On: Tim Pope (sass.vim) +" Created: Dec 14, 2011 +" Modified: Apr 29, 2024 + +if main_syntax == "css" + syn sync minlines=10 +endif + +" let b:current_syntax = "css" +" +if main_syntax == 'css' + unlet main_syntax +endif + +syn case ignore + +syn cluster stylusCssSelectors contains=cssTagName,cssSelector,cssPseudo +syn cluster stylusCssValues contains=cssValueLength,cssValueInteger,cssValueNumber,cssValueAngle,cssValueTime,cssValueFrequency,cssColorVal,cssCommonVal,cssFontVal,cssListVal,cssTextVal,cssVisualVal,cssBorderVal,cssBackgroundVal,cssFuncVal,cssAdvancedVal +syn cluster stylusCssProperties contains=cssProp,cssBackgroundProp,cssTableProp,cssBorderProp,cssFontProp,cssColorProp,cssBoxProp,cssTextProp,cssListProp,cssVisualProp,cssAdvancedProp,cssCommonProp,cssSpecialProp + +syn match stylusVariable "$\?[[:alnum:]_-]\+" +syn match stylusVariableAssignment "\%([[:alnum:]_-]\+\s*\)\@<==" nextgroup=stylusCssAttribute,stylusVariable skipwhite + +syn match stylusProperty "\%([{};]\s*\|^\)\@<=\%([[:alnum:]-]\|#{[^{}]*}\)\+:" contains=@stylusCssProperties,@stylusCssSelectors skipwhite nextgroup=stylusCssAttribute contained containedin=cssDefineBlock +syn match stylusProperty "^\s*\zs\s\%(\%([[:alnum:]-]\|#{[^{}]*}\)\+[ :]\|:[[:alnum:]-]\+\)"hs=s+1 contains=@stylusCssProperties,@stylusCssSelectors skipwhite nextgroup=stylusCssAttribute +syn match stylusProperty "^\s*\zs\s\%(:\=[[:alnum:]-]\+\s*=\)"hs=s+1 contains=@stylusCssProperties,@stylusCssSelectors skipwhite nextgroup=stylusCssAttribute + +syn match stylusCssAttribute +\%("\%([^"]\|\\"\)*"\|'\%([^']\|\\'\)*'\|#{[^{}]*}\|[^{};]\)*+ contained contains=@stylusCssValues,cssImportant,stylusFunction,stylusVariable,stylusControl,stylusUserFunction,stylusInterpolation,cssString,stylusComment,cssComment + +syn match stylusInterpolation %{[[:alnum:]_-]\+}% + +syn match stylusFunction "\<\%(red\|green\|blue\|alpha\|dark\|light\)\>(\@=" contained +syn match stylusFunction "\<\%(hue\|saturation\|lightness\|push\|unshift\|typeof\|unit\|match\)\>(\@=" contained +syn match stylusFunction "\<\%(hsla\|hsl\|rgba\|rgb\|lighten\|darken\)\>(\@=" contained +syn match stylusFunction "\<\%(abs\|ceil\|floor\|round\|min\|max\|even\|odd\|sum\|avg\|sin\|cos\|join\)\>(\@=" contained +syn match stylusFunction "\<\%(desaturate\|saturate\|invert\|unquote\|quote\|s\)\>(\@=" contained +syn match stylusFunction "\<\%(operate\|length\|warn\|error\|last\|p\|\)\>(\@=" contained +syn match stylusFunction "\<\%(opposite-position\|image-size\|add-property\)\>(\@=" contained + +syn keyword stylusVariable null true false arguments +syn keyword stylusControl if else unless for in return + +syn match stylusImport "@\%(import\|require\)" nextgroup=stylusImportList +syn match stylusImportList "[^;]\+" contained contains=cssString.*,cssMediaType,cssURL + +syn match stylusAmpersand "&" +syn match stylusClass "[[:alnum:]_-]\+" contained +syn match stylusClassChar "\.[[:alnum:]_-]\@=" nextgroup=stylusClass +syn match stylusEscape "^\s*\zs\\" +syn match stylusId "[[:alnum:]_-]\+" contained +syn match stylusIdChar "#[[:alnum:]_-]\@=" nextgroup=stylusId + +syn region stylusComment start="//" end="$" contains=cssTodo,@Spell fold + +let b:current_syntax = "stylus" + +" vim:set sw=2: diff --git a/runtime/syntax/swayconfig.vim b/runtime/syntax/swayconfig.vim index 69fe26d370..401412adfd 100644 --- a/runtime/syntax/swayconfig.vim +++ b/runtime/syntax/swayconfig.vim @@ -2,8 +2,8 @@ " Language: sway config file " Original Author: Josef Litos (JosefLitos/i3config.vim) " Maintainer: James Eapen <james.eapen@vai.org> -" Version: 1.0.2 -" Last Change: 2023-12-28 +" Version: 1.2.3 +" Last Change: 2024-05-23 " References: " http://i3wm.org/docs/userguide.html#configuring @@ -16,42 +16,37 @@ if exists("b:current_syntax") finish endif +" before i3 load to give i3ConfigKeyword lower priority +syn cluster i3ConfigCommand contains=i3ConfigCommand,i3ConfigAction,i3ConfigActionKeyword,@i3ConfigValue,i3ConfigColor,i3ConfigKeyword + runtime! syntax/i3config.vim -" i3 extensions -syn keyword i3ConfigActionKeyword opacity urgent shortcuts_inhibitor splitv splith splitt contained -syn keyword i3ConfigOption set plus minus allow deny csd v h t contained +" Sway extensions to i3 +syn keyword i3ConfigActionKeyword opacity urgent shortcuts_inhibitor splitv splith splitt contained contained skipwhite nextgroup=i3ConfigOption +syn keyword i3ConfigOption set plus minus allow deny csd v h t contained contained skipwhite nextgroup=i3ConfigOption,@i3ConfigValue syn keyword i3ConfigConditionProp app_id pid shell contained syn keyword i3ConfigWorkspaceDir prev_on_output next_on_output contained -syn keyword swayConfigBindKeyword bindswitch bindgesture contained -syn match i3ConfigBindArgument /--\(locked\|to-code\|no-repeat\|input-device=[:0-9a-zA-Z_/-]\+\|no-warn\)/ contained -syn region i3ConfigBind start=/^\s*bind\(switch\|gesture\) / skip=/\\$/ end=/$/ contains=swayConfigBindKeyword,swayConfigBindswitch,swayConfigBindswitchArgument,swayConfigBindgesture,swayConfigBindgestureArgument,i3ConfigCriteria,i3ConfigAction,i3ConfigSeparator,i3ConfigActionKeyword,i3ConfigOption,i3ConfigString,i3ConfigNumber,i3ConfigVariable,i3ConfigBoolean keepend - -syn match swayConfigBindBlockHeader /^\s*bind\(sym\|code\) .*{$/ contained contains=i3ConfigBindKeyword,i3ConfigBindArgument,i3ConfigParen -syn match swayConfigBindBlockCombo /^\s\+\(--[a-z-]\+ \)*[$a-zA-Z0-9_+]\+ [a-z[]\@=/ contained contains=i3ConfigBindArgument,i3ConfigBindCombo -syn region i3ConfigBind start=/^\s*bind\(sym\|code\) .*{$/ end=/^\s*}$/ contains=swayConfigBindBlockHeader,swayConfigBindBlockCombo,i3ConfigCriteria,i3ConfigAction,i3ConfigSeparator,i3ConfigActionKeyword,i3ConfigOption,i3ConfigString,i3ConfigNumber,i3ConfigVariable,i3ConfigBoolean,i3ConfigComment,i3ConfigParen fold keepend extend -" fix for extra long bindsym blocks that would be parsed incorrectly when scrolling up -syn region i3ConfigBlockOrphan start=/^\s\+\S/ skip=/^\s\|^$/ end=/^}\?/ contains=swayConfigBindBlockCombo,i3ConfigCriteria,i3ConfigAction,i3ConfigSeparator,i3ConfigActionKeyword,i3ConfigOption,i3ConfigString,i3ConfigNumber,i3ConfigVariable,i3ConfigBoolean,i3ConfigComment,i3ConfigParen keepend extend - -syn keyword i3ConfigClientOpts focused_tab_title contained +syn match i3ConfigBindArgument /--\(locked\|to-code\|no-repeat\|input-device=[^ '"]*\|no-warn\) / 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 swayConfigExecBlock start=/exec\(_always\)\? {/ end=/^}$/ contains=i3ConfigExecKeyword,i3ConfigExecAlwaysKeyword,i3ConfigShCommand,i3ConfigShDelim,i3ConfigShOper,i3ConfigShParam,i3ConfigNumber,i3ConfigString,i3ConfigVariable,i3ConfigComment fold keepend extend +syn region i3ConfigBindCombo matchgroup=i3ConfigParen start=/{$/ end=/^\s*}$/ contained contains=i3ConfigBindArgument,i3ConfigBindCombo,i3ConfigComment fold keepend extend +" hack for blocks with start outside parsing range +syn region swayConfigBlockOrphan start=/^\s\+\(--[a-z-]\+ \)*\([A-Z$][$a-zA-Z0-9_+]\+\|[a-z]\) [a-z[]/ skip=/\\$\|$\n^\s*}$/ end=/$/ contains=i3ConfigBindArgument,i3ConfigBindCombo,i3ConfigParen keepend extend -syn keyword swayConfigFloatingModifierOpts normal inverse contained -syn match i3ConfigKeyword /^floating_modifier [$a-zA-Z0-9+]\+ \(normal\|inverse\)$/ contains=i3ConfigVariable,i3ConfigBindModkey,swayConfigFloatingModifierOpts +syn region i3ConfigExec start=/ {$/ end=/^\s*}$/ contained contains=i3ConfigExecAction,@i3ConfigSh,i3ConfigComment fold keepend extend -syn keyword swayConfigSmartGapsOpts toggle contained -syn match i3ConfigKeyword /^smart_gaps toggle$/ contains=i3ConfigSmartGapOpts,i3ConfigBoolean,swayConfigSmartGapsOpts +syn keyword swayConfigFloatingModifierOpts normal inverse none contained +syn match i3ConfigKeyword /floating_modifier \(none\|[$a-zA-Z0-9+]\+ \(normal\|inverse\)\)$/ contained contains=i3ConfigVariable,i3ConfigBindModkey,swayConfigFloatingModifierOpts -syn keyword swayConfigFocusFollowsMouseOpts always contained -syn match i3ConfigKeyword /^focus_follows_mouse always$/ contains=i3ConfigBoolean,swayConfigFocusFollowsMouseOpts +syn match swayConfigI3Param /--i3/ contains=i3ConfigShParam skipwhite nextgroup=i3ConfigEdgeOpts +syn keyword i3ConfigKeyword hide_edge_borders contained skipwhite nextgroup=swayConfigI3Param,i3ConfigEdgeOpts -syn match i3ConfigKeyword /^hide_edge_borders --i3 \w*$/ contains=i3ConfigEdgeKeyword,i3ConfigShParam - -syn keyword i3ConfigBarOpts swaybar_command gaps height pango_markup status_edge_padding status_padding wrap_scroll tray_bindcode tray_bindsym icon_theme contained +syn keyword i3ConfigBarOpts swaybar_command contained skipwhite nextgroup=@i3ConfigSh +syn region i3ConfigBarOpts matchgroup=i3ConfigBarOpts start=/gaps/ end=/$/ contained contains=@i3ConfigNumVar +syn keyword i3ConfigBarOpts height pango_markup status_edge_padding status_padding wrap_scroll tray_bindcode tray_bindsym icon_theme contained skipwhite nextgroup=i3ConfigBarOptVals,@i3ConfigValue,i3ConfigShOper syn keyword i3ConfigBarOptVals overlay contained syn keyword i3ConfigExecActionKeyword swaymsg contained @@ -59,77 +54,88 @@ syn keyword i3ConfigExecActionKeyword swaymsg contained " Sway-only options " Xwayland syn keyword swayConfigXOpt enable disable force contained -syn match i3ConfigKeyword /^xwayland \w*$/ contains=swayConfigXOpt +syn keyword i3ConfigKeyword xwayland contained skipwhite nextgroup=swayConfigXOpt " Inhibit idle -syn keyword swayConfigInhibitKeyword inhibit_idle contained syn keyword swayConfigInhibitOpts focus fullscreen open none visible contained -syn match i3ConfigAction /inhibit_idle \w*/ contained contains=swayConfigInhibitKeyword,swayConfigInhibitOpts +syn keyword i3ConfigActionKeyword inhibit_idle contained skipwhite nextgroup=swayConfigInhibitOpts " Bindswitch -syn match swayConfigBindswitchArgument /--\(locked\|no-warn\|reload\)/ contained -syn keyword swayConfigBindswitchType lid tablet contained +syn match swayConfigBindswitchArgument /--\(locked\|no-warn\|reload\) / contained nextgroup=swayConfigBindswitchArgument,swayConfigBindswitchType +syn keyword swayConfigBindswitchType lid tablet contained nextgroup=swayConfigBindswitchCombo syn keyword swayConfigBindswitchState toggle contained -syn match swayConfigBindswitch /\(lid\|tablet\):\(on\|off\|toggle\) / contained contains=swayConfigBindswitchType,i3ConfigColonOperator,swayConfigBindswitchState,i3ConfigBoolean -syn region i3ConfigBind start=/^\s*bindswitch\s\+.*{$/ end=/^\s*}$/ contains=swayConfigBindKeyword,swayConfigBindswitch,swayConfigBindswitchArgument,i3ConfigNumber,i3ConfigVariable,i3ConfigAction,i3ConfigActionKeyword,i3ConfigOption,i3ConfigSeparator,i3ConfigString,i3ConfigCriteria,swayConfigOutputCommand,i3ConfigBoolean,i3ConfigComment,i3ConfigParen fold keepend extend +syn match swayConfigBindswitchCombo /:\(on\|off\|toggle\) / contained contains=i3ConfigColonOperator,swayConfigBindswitchState,i3ConfigBoolean nextgroup=i3ConfigBind +syn region swayConfigBindswitchType matchgroup=i3ConfigParen start=/{$/ end=/^\s*}$/ contained contains=swayConfigBindswitchArgument,swayConfigBindswitchType,i3ConfigComment fold keepend extend +syn keyword i3ConfigBindKeyword bindswitch contained skipwhite nextgroup=swayConfigBindswitchArgument,swayConfigBindswitchType +" hack for blocks with start outside parsing range +syn region swayConfigBlockOrphan start=/^\s\+\(lid\|tablet\):/ skip=/\\$\|$\n^\s*}$/ end=/$/ contains=swayConfigBindswitchArgument,swayConfigBindswitchType,i3ConfigParen keepend extend " Bindgesture -syn match swayConfigBindgestureArgument /--\(exact\|input-device=[:0-9a-zA-Z_/-]\+\|no-warn\)/ contained +syn match swayConfigBindgestureArgument /--\(exact\|input-device=[:0-9a-zA-Z_/-]\+\|no-warn\) / contained nextgroup=swayConfigBindgestureArgument,swayConfigBindgestureCombo syn keyword swayConfigBindgestureType hold swipe pinch contained syn keyword swayConfigBindgestureDir up down left right inward outward clockwise counterclockwise contained -syn match swayConfigBindgesture /\(hold\(:[1-5]\)\?\|swipe\(:[3-5]\)\?\(:up\|:down\|:left\|:right\)\?\|pinch\(:[2-5]\)\?:\(+\?\(inward\|outward\|clockwise\|counterclockwise\|up\|down\|left\|right\)\)\+\) / contained contains=i3ConfigNumber,swayConfigBindgestureType,i3ConfigColonOperator,swayConfigBindgestureDir,i3ConfigBindModifier -syn region i3ConfigBind start=/^\s*bindgesture\s\+.*{$/ end=/^\s*}$/ contains=swayConfigBindKeyword,swayConfigBindgesture,swayConfigBindgestureArgument,i3ConfigCriteria,i3ConfigAction,i3ConfigSeparator,i3ConfigActionKeyword,i3ConfigOption,i3ConfigString,i3ConfigNumber,i3ConfigVariable,i3ConfigBoolean,i3ConfigParen fold keepend extend +syn match swayConfigBindgestureCombo /\(hold\(:[1-5]\)\?\|swipe\(:[3-5]\)\?\(:up\|:down\|:left\|:right\)\?\|pinch\(:[2-5]\)\?:\(+\?\(inward\|outward\|clockwise\|counterclockwise\|up\|down\|left\|right\)\)\+\) / contained contains=i3ConfigNumber,swayConfigBindgestureType,i3ConfigColonOperator,swayConfigBindgestureDir,i3ConfigBindModifier nextgroup=swayConfigBindgestureCombo,i3ConfigBind +syn region swayConfigBindgestureCombo matchgroup=i3ConfigParen start=/{$/ end=/^\s*}$/ contained contains=swayConfigBindgestureArgument,swayConfigBindgestureCombo,i3ConfigComment fold keepend extend +syn keyword i3ConfigBindKeyword bindgesture contained skipwhite nextgroup=swayConfigBindgestureArgument,swayConfigBindgestureCombo +" hack for blocks with start outside parsing range +syn region swayConfigBlockOrphan start=/^\s\+\(--[a-z-]\+ \)*\(hold\|swipe\|pinch\):/ skip=/\\$\|$\n^\s*}$/ end=/$/ contains=swayConfigBindgestureArgument,swayConfigBindgestureCombo,i3ConfigParen keepend extend " Tiling drag threshold -syn match i3ConfigKeyword /^tiling_drag_threshold \d\+$/ contains=i3ConfigNumber - " Titlebar commands -syn match i3ConfigKeyword /^titlebar_border_thickness \(\d\+\|\$\S\+\)$/ contains=i3ConfigNumber,i3ConfigVariable -syn match i3ConfigKeyword /^titlebar_padding \(\d\+\|\$\S\+\)\( \d\+\)\?$/ contains=i3ConfigNumber,i3ConfigVariable +syn keyword i3ConfigKeyword tiling_drag_threshold titlebar_border_thickness contained skipwhite nextgroup=@i3ConfigNumVar +syn match i3ConfigKeyword /titlebar_padding \(\d\+\|\$\S\+\)\( \d\+\)\?$/ contained contains=@i3ConfigNumVar -syn match swayConfigDeviceOps /[*,:;]/ contained +syn match swayConfigDeviceOper /[*:;!]/ contained " Input devices -syn keyword swayConfigInputKeyword input contained -syn keyword swayConfigInputType touchpad pointer keyboard touch tablet_tool tablet_pad switch contained -syn match swayConfigInputTypePair /\<type:\w\+\>/ contained contains=i3ConfigColonOperator,swayConfigInputType -syn region swayConfigInputStart start=/^input / end=/\s/ contained contains=swayConfigInputKeyword,swayConfigInputTypePair,i3ConfigString keepend extend -syn keyword swayConfigInputOpts xkb_layout xkb_variant xkb_rules xkb_switch_layout xkb_numlock xkb_file xkb_capslock xkb_model repeat_delay repeat_rate map_to_output map_to_region map_from_region tool_mode accel_profile dwt dwtp drag_lock drag click_method middle_emulation tap events calibration_matrix natural_scroll left_handed pointer_accel scroll_button scroll_factor scroll_method tap_button_map contained -syn keyword swayConfigInputOptVals absolute relative adaptive flat none button_areas clickfinger toggle two_finger edge on_button_down lrm lmr next prev pen eraser brush pencil airbrush disabled_on_external_mouse disable contained -syn match swayConfigXkbOptsPairVal /:[0-9a-z_-]\+/ contained contains=i3ConfigColonOperator -syn match swayConfigXkbOptsPair /[a-z]\+:[0-9a-z_-]\+/ contained contains=swayConfigXkbOptsPairVal -syn match swayConfigInputXkbOpts /xkb_options \([a-z]\+:[0-9a-z_-]\+,\?\)\+/ contained contains=swayConfigXkbOptsPair,swayConfigDeviceOps -syn region i3ConfigAction start=/input/ skip=/\\$/ end=/\([,;]\|$\)/ contained contains=swayConfigInputStart,swayConfigInputXkbOpts,swayConfigInputOpts,swayConfigInputOptVals,i3ConfigVariable,i3ConfigNumber,i3ConfigBoolean,swayConfigDeviceOps keepend transparent -syn region i3ConfigInput start=/^input/ skip=/\\$/ end=/$/ contains=swayConfigInputStart,swayConfigInputXkbOpts,swayConfigInputOpts,swayConfigInputOptVals,i3ConfigVariable,i3ConfigNumber,i3ConfigBoolean,swayConfigDeviceOps keepend -syn region i3ConfigInput start=/^input .* {/ end=/}$/ contains=swayConfigInputStart,swayConfigInputXkbOpts,swayConfigInputOpts,swayConfigInputOptVals,i3ConfigVariable,i3ConfigNumber,i3ConfigBoolean,swayConfigDeviceOps,i3ConfigParen keepend extend +syn keyword swayConfigInputOpts xkb_variant xkb_rules xkb_switch_layout xkb_numlock xkb_file xkb_capslock xkb_model repeat_delay repeat_rate map_to_output map_to_region map_from_region tool_mode accel_profile dwt dwtp drag_lock drag click_method middle_emulation tap events calibration_matrix natural_scroll left_handed pointer_accel scroll_button scroll_factor scroll_method tap_button_map contained skipwhite nextgroup=swayConfigInputOptVals,@i3ConfigValue +syn keyword swayConfigInputOptVals absolute relative adaptive flat none button_areas clickfinger toggle two_finger edge on_button_down lrm lmr next prev pen eraser brush pencil airbrush disabled_on_external_mouse disable enable contained skipwhite nextgroup=swayConfigInputOpts,@i3ConfigValue,swayConfigDeviceOper +syn match swayConfigDeviceOper /,/ contained nextgroup=swayConfigXkbOptsPair,swayConfigXkbLayout +syn match swayConfigXkbLayout /[a-z]\+/ contained nextgroup=swayConfigDeviceOper +syn keyword swayConfigInputOpts xkb_layout contained skipwhite nextgroup=swayConfigXkbLayout +syn match swayConfigXkbOptsPairVal /[0-9a-z_-]\+/ contained contains=i3ConfigNumber skipwhite nextgroup=swayConfigDeviceOper,swayConfigInputOpts +syn match swayConfigXkbOptsPair /[a-z]\+:/ contained contains=i3ConfigColonOperator nextgroup=swayConfigXkbOptsPairVal +syn keyword swayConfigInputOpts xkb_options contained skipwhite nextgroup=swayConfigXkbOptsPair + +syn region swayConfigInput start=/\s/ skip=/\\$/ end=/\ze[,;]\|$/ contained contains=swayConfigInputOpts,@i3ConfigValue keepend +syn region swayConfigInput matchgroup=i3ConfigParen start=/ {$/ end=/^\s*}$/ contained contains=swayConfigInputOpts,@i3ConfigValue,i3ConfigComment keepend extend +syn keyword swayConfigInputType touchpad pointer keyboard touch tablet_tool tablet_pad switch contained nextgroup=swayConfigInput +syn match swayConfigInputIdent /type:!\?/ contained contains=swayConfigDeviceOper nextgroup=swayConfigInputType +syn match swayConfigInputIdent /[^t '"]\S*/ contained contains=i3ConfigOutputIdent nextgroup=swayConfigInput +syn region swayConfigInputIdent start=/['"]/ end=/\ze/ contained contains=i3ConfigOutputIdent nextgroup=swayConfigInput +syn keyword i3ConfigKeyword input contained skipwhite nextgroup=swayConfigInputIdent " Seat -syn keyword swayConfigSeatKeyword seat contained -syn keyword swayConfigSeatOpts attach cursor fallback hide_cursor idle_inhibit idle_wake keyboard_grouping shortcuts_inhibitor pointer_constraint xcursor_theme contained -syn match swayConfigSeatOptVals /when-typing/ contained -syn keyword swayConfigSeatOptVals move set press release none smart activate deactivate toggle escape enable disable contained -syn region i3ConfigAction start=/seat/ skip=/\\$/ end=/\([,;]\|$\)/ contained contains=swayConfigSeatKeyword,i3ConfigString,i3ConfigNumber,i3ConfigBoolean,swayConfigSeatOptVals,swayConfigSeatOpts,swayConfigDeviceOps,swayConfigInputType keepend transparent -syn region swayConfigSeat start=/seat/ skip=/\\$/ end=/$/ contains=swayConfigSeatKeyword,i3ConfigString,i3ConfigNumber,i3ConfigBoolean,swayConfigSeatOptVals,swayConfigSeatOpts,swayConfigDeviceOps,swayConfigInputType keepend -syn region swayConfigSeat start=/seat .* {$/ end=/}$/ contains=swayConfigSeatKeyword,i3ConfigString,i3ConfigNumber,i3ConfigBoolean,swayConfigSeatOptVals,swayConfigSeatOpts,swayConfigDeviceOps,i3ConfigParen,swayConfigInputType keepend extend +syn keyword swayConfigSeatOpts cursor fallback hide_cursor keyboard_grouping shortcuts_inhibitor pointer_constraint xcursor_theme contained skipwhite nextgroup=swayConfigSeatOptVals,@i3ConfigValue +syn match swayConfigInputTypeSeq / \w\+/ contained contains=swayConfigInputType nextgroup=swayConfigInputTypeSeq,swayConfigSeatOpts +syn keyword swayConfigSeatOpts idle_inhibit idle_wake contained nextgroup=swayConfigInputTypeSeq +syn keyword swayConfigSeatOpts attach contained skipwhite nextgroup=swayConfigSeatIdent +syn match swayConfigSeatOptVals /when-typing/ contained skipwhite nextgroup=swayConfigSeatOptVals +syn keyword swayConfigSeatOptVals move set press release none smart activate deactivate toggle escape enable disable contained skipwhite nextgroup=swayConfigSeatOpts +syn region swayConfigSeat start=/\s/ skip=/\\$/ end=/\ze[,;]\|$/ contained contains=swayConfigSeatOpts,@i3ConfigValue keepend +syn region swayConfigSeat matchgroup=i3ConfigParen start=/ {$/ end=/^\s*}$/ contained contains=swayConfigSeatOpts,@i3ConfigValue,i3ConfigComment keepend extend +syn match swayConfigSeatIdent /[^ ]\+/ contained contains=i3ConfigOutputIdent skipwhite nextgroup=swayConfigSeat +syn keyword i3ConfigKeyword seat contained skipwhite nextgroup=swayConfigSeatIdent " Output monitors -syn keyword swayConfigOutputKeyword output contained -syn keyword swayConfigOutputOpts mode resolution res modeline position pos scale scale_filter subpixel background bg transform disable enable power dpms max_render_time adaptive_sync render_bit_depth contained -syn keyword swayConfigOutputOptVals linear nearest smart rgb bgr vrgb vbgr none normal flipped fill stretch fit center tile solid_color clockwise anticlockwise toggle contained -syn match swayConfigOutputOptVals /--custom\|flipped-\(90\|180\|270\)/ contained -syn match swayConfigOutputFPS /@[0-9.]\+Hz/ contained -syn match swayConfigOutputMode / [0-9]\+x[0-9]\+\(@[0-9.]\+Hz\)\?/ contained contains=swayConfigOutputFPS -syn region i3ConfigAction start=/output/ skip=/\\$/ end=/\([,;]\|$\)/ contained contains=swayConfigOutputKeyword,swayConfigOutputMode,swayConfigOutputOpts,swayConfigOutputOptVals,i3ConfigVariable,i3ConfigNumber,i3ConfigString,i3ConfigColor,i3ConfigBoolean,swayConfigDeviceOps keepend transparent -syn region swayConfigOutput start=/^output/ skip=/\\$/ end=/$/ contains=swayConfigOutputKeyword,swayConfigOutputMode,swayConfigOutputOpts,swayConfigOutputOptVals,i3ConfigVariable,i3ConfigNumber,i3ConfigString,i3ConfigColor,i3ConfigBoolean,swayConfigDeviceOps keepend -syn region swayConfigOutput start=/^output .* {$/ end=/}$/ contains=swayConfigOutputKeyword,swayConfigOutputMode,swayConfigOutputOpts,swayConfigOutputOptVals,i3ConfigVariable,i3ConfigNumber,i3ConfigString,i3ConfigColor,i3ConfigBoolean,swayConfigDeviceOps,i3ConfigParen keepend extend +syn keyword swayConfigOutputOpts mode resolution res modeline position pos scale scale_filter subpixel transform disable enable power dpms max_render_time adaptive_sync render_bit_depth contained skipwhite nextgroup=swayConfigOutputOptVals,@i3ConfigValue,swayConfigOutputMode +syn keyword swayConfigOutputOptVals linear nearest smart rgb bgr vrgb vbgr none clockwise anticlockwise toggle contained skipwhite nextgroup=swayConfigOutputOptVals,@i3ConfigValue +syn keyword swayConfigOutputBgVals solid_color fill stretch fit center tile contained skipwhite nextgroup=@i3ConfigColVar +syn match swayConfigOutputBg /[#$]\S\+ solid_color/ contained contains=@i3ConfigColVar,swayConfigOutputBgVals +syn match swayConfigOutputBg /[^b# '"]\S*/ contained contains=i3ConfigShOper skipwhite nextgroup=swayConfigOutputBgVals +syn region swayConfigOutputBg start=/['"]/ end=/\ze/ contained contains=@i3ConfigIdent skipwhite nextgroup=swayConfigOutputBgVals +syn keyword swayConfigOutputOpts bg background contained skipwhite nextgroup=swayConfigOutputBg +syn match swayConfigOutputFPS /@[0-9.]\+Hz/ contained skipwhite nextgroup=swayConfigOutputOpts +syn match swayConfigOutputMode /\(--custom \)\?[0-9]\+x[0-9]\+/ contained contains=i3ConfigShParam skipwhite nextgroup=swayConfigOutputFPS,swayConfigOutputOpts +syn match swayConfigOutputOptVals /\(flipped-\)\?\(90\|180\|270\)\|flipped\|normal/ contained contains=i3ConfigNumber skipwhite nextgroup=swayConfigOutputOptsVals +syn region swayConfigOutput start=/\s/ skip=/\\$/ end=/\ze[,;]\|$/ contained contains=swayConfigOutputOpts,@i3ConfigValue keepend +syn region swayConfigOutput matchgroup=i3ConfigParen start=/ {$/ end=/^\s*}$/ contained contains=swayConfigOutputOpts,@i3ConfigValue,i3ConfigComment keepend extend +syn match swayConfigOutputIdent /[^ ]\+/ contained contains=i3ConfigOutputIdent skipwhite nextgroup=swayConfigOutput +syn keyword i3ConfigKeyword output contained skipwhite nextgroup=swayConfigOutputIdent " Define the highlighting. -hi def link swayConfigSmartGapsOpts i3ConfigOption hi def link swayConfigFloatingModifierOpts i3ConfigOption -hi def link swayConfigFocusFollowsMouseOpts i3ConfigOption -hi def link swayConfigBindKeyword i3ConfigBindKeyword hi def link swayConfigXOpt i3ConfigOption -hi def link swayConfigInhibitKeyword i3ConfigCommand hi def link swayConfigInhibitOpts i3ConfigOption hi def link swayConfigBindswitchArgument i3ConfigBindArgument hi def link swayConfigBindswitchType i3ConfigMoveType @@ -137,20 +143,18 @@ hi def link swayConfigBindswitchState i3ConfigMoveDir hi def link swayConfigBindgestureArgument i3ConfigBindArgument hi def link swayConfigBindgestureType i3ConfigMoveType hi def link swayConfigBindgestureDir i3ConfigMoveDir -hi def link swayConfigDeviceOps i3ConfigOperator -hi def link swayConfigInputKeyword i3ConfigCommand +hi def link swayConfigDeviceOper i3ConfigOperator hi def link swayConfigInputType i3ConfigMoveType -hi def link swayConfigInputTypePair i3ConfigMoveDir +hi def link swayConfigInputIdent i3ConfigMoveDir hi def link swayConfigInputOptVals i3ConfigShParam hi def link swayConfigInputOpts i3ConfigOption -hi def link swayConfigXkbOptsPairVal i3ConfigString +hi def link swayConfigXkbOptsPairVal i3ConfigParamLine hi def link swayConfigXkbOptsPair i3ConfigShParam -hi def link swayConfigInputXkbOpts i3ConfigOption -hi def link swayConfigSeatKeyword i3ConfigCommand +hi def link swayConfigXkbLayout i3ConfigParamLine hi def link swayConfigSeatOptVals swayConfigInputOptVals hi def link swayConfigSeatOpts swayConfigInputOpts -hi def link swayConfigOutputKeyword i3ConfigCommand hi def link swayConfigOutputOptVals swayConfigInputOptVals +hi def link swayConfigOutputBgVals swayConfigInputOptVals hi def link swayConfigOutputOpts swayConfigInputOpts hi def link swayConfigOutputFPS Constant hi def link swayConfigOutputMode i3ConfigNumber diff --git a/runtime/syntax/tutor.vim b/runtime/syntax/tutor.vim index 83ca547fdd..399026790a 100644 --- a/runtime/syntax/tutor.vim +++ b/runtime/syntax/tutor.vim @@ -8,6 +8,8 @@ syn include @TUTORSHELL syntax/sh.vim unlet b:current_syntax syn include @VIMNORMAL syntax/vimnormal.vim +syn iskeyword @,-,_,48-57 + syn match tutorLink /\[.\{-}\](.\{-})/ contains=tutorInlineNormal syn match tutorLinkBands /\[\|\]\|(\|)/ contained containedin=tutorLink,tutorLinkAnchor conceal syn match tutorLinkAnchor /(.\{-})/ contained containedin=tutorLink conceal diff --git a/runtime/syntax/uci.vim b/runtime/syntax/uci.vim new file mode 100644 index 0000000000..fdf5bfd9b3 --- /dev/null +++ b/runtime/syntax/uci.vim @@ -0,0 +1,33 @@ +" Vim syntax file +" Language: OpenWrt Unified Configuration Interface +" Maintainer: Colin Caine <complaints@cmcaine.co.uk> +" Upstream: https://github.com/cmcaine/vim-uci +" Last Change: 2021 Sep 19 +" +" For more information on uci, see https://openwrt.org/docs/guide-user/base-system/uci + +if exists("b:current_syntax") + finish +endif + +" Fancy zero-width non-capturing look-behind to see what the last word was. +" Would be really nice if there was some less obscure or more efficient way to +" do this. +syntax match uciOptionName '\%(\%(option\|list\)\s\+\)\@<=\S*' +syntax match uciConfigName '\%(\%(package\|config\)\s\+\)\@<=\S*' +syntax keyword uciConfigDec package config nextgroup=uciConfigName skipwhite +syntax keyword uciOptionType option list nextgroup=uciOptionName skipwhite + +" Standard matches. +syntax match uciComment "#.*$" +syntax region uciString start=+"+ end=+"+ skip=+\\"+ +syntax region uciString start=+'+ end=+'+ skip=+\\'+ + +highlight default link uciConfigName Identifier +highlight default link uciOptionName Constant +highlight default link uciConfigDec Statement +highlight default link uciOptionType Type +highlight default link uciComment Comment +highlight default link uciString Normal + +let b:current_syntax = "uci" diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim index 2857146949..4fc640bab1 100644 --- a/runtime/syntax/vim.vim +++ b/runtime/syntax/vim.vim @@ -15,6 +15,8 @@ endif let s:keepcpo = &cpo set cpo&vim +let s:vim9script = "\n" .. getline(1, 32)->join("\n") =~# '\n\s*vim9\%[script]\>' + " vimTodo: contains common special-notices for comments {{{2 " Use the vimCommentGroup cluster to add your own. syn keyword vimTodo contained COMBAK FIXME TODO XXX @@ -67,7 +69,7 @@ syn case match " Special Vim Highlighting (not automatic) {{{1 " Set up folding commands for this syntax highlighting file {{{2 -if exists("g:vimsyn_folding") && g:vimsyn_folding =~# '[afhlmpPrt]' +if exists("g:vimsyn_folding") && g:vimsyn_folding =~# '[afhHlmpPrt]' if g:vimsyn_folding =~# 'a' com! -nargs=* VimFolda <args> fold else @@ -83,6 +85,11 @@ if exists("g:vimsyn_folding") && g:vimsyn_folding =~# '[afhlmpPrt]' else com! -nargs=* VimFoldh <args> endif + if g:vimsyn_folding =~# 'H' + com! -nargs=* VimFoldH <args> fold + else + com! -nargs=* VimFoldH <args> + endif if g:vimsyn_folding =~# 'l' com! -nargs=* VimFoldl <args> fold else @@ -117,6 +124,7 @@ else com! -nargs=* VimFolda <args> com! -nargs=* VimFoldf <args> com! -nargs=* VimFoldh <args> + com! -nargs=* VimFoldH <args> com! -nargs=* VimFoldl <args> com! -nargs=* VimFoldm <args> com! -nargs=* VimFoldp <args> @@ -145,16 +153,18 @@ endif " Numbers {{{2 " ======= -syn match vimNumber '\<\d\+\%(\.\d\+\%([eE][+-]\=\d\+\)\=\)\=' skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment -syn match vimNumber '-\d\+\%(\.\d\+\%([eE][+-]\=\d\+\)\=\)\=' skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment -syn match vimNumber '\<0[xX]\x\+' skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment -syn match vimNumber '\%(^\|\A\)\zs#\x\{6}' skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment -syn match vimNumber '\<0[zZ][a-zA-Z0-9.]\+' skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment -syn match vimNumber '0[0-7]\+' skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment -syn match vimNumber '0[bB][01]\+' skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment +syn case ignore +syn match vimNumber '\<\d\+\%(\.\d\+\%(e[+-]\=\d\+\)\=\)\=' skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,@vimComment +syn match vimNumber '\<0b[01]\+' skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,@vimComment +syn match vimNumber '\<0o\=\o\+' skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,@vimComment +syn match vimNumber '\<0x\x\+' skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,@vimComment +syn match vimNumber '\<0z\>' skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,@vimComment +syn match vimNumber '\<0z\%(\x\x\)\+\%(\.\%(\x\x\)\+\)*' skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,@vimComment +syn match vimNumber '\%(^\|\A\)\zs#\x\{6}' skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,@vimComment +syn case match " All vimCommands are contained by vimIsCommand. {{{2 -syn cluster vimCmdList contains=vimAbb,vimAddress,vimAutoCmd,vimAugroup,vimBehave,vimEcho,vimEchoHL,vimExecute,vimIsCommand,vimExtCmd,vimFunction,vimGlobal,vimHighlight,vimLet,vimMap,vimMark,vimNotFunc,vimNorm,vimSet,vimSyntax,vimUnlet,vimUnmap,vimUserCmd +syn cluster vimCmdList contains=vimAbb,vimAddress,vimAutoCmd,vimAugroup,vimBehave,vimDef,@vimEcho,vimEnddef,vimEndfunction,vimExecute,vimIsCommand,vimExtCmd,vimFor,vimFunction,vimGlobal,vimHighlight,vimLet,vimMap,vimMark,vimNotFunc,vimNorm,vimSet,vimSyntax,vimUnlet,vimUnmap,vimUserCmd,vimMenu,vimMenutranslate syn match vimCmdSep "[:|]\+" skipwhite nextgroup=@vimCmdList,vimSubst1 syn match vimIsCommand "\<\%(\h\w*\|[23]mat\%[ch]\)\>" contains=vimCommand syn match vimVar contained "\<\h[a-zA-Z0-9#_]*\>" @@ -171,9 +181,9 @@ syn cluster vimExprList contains=vimEnvvar,vimFunc,vimFuncVar,vimNumber,vimOper, " (buftype != nofile test avoids having append, change, insert show up in the command window) " ======================= if &buftype != 'nofile' - syn region vimInsert matchgroup=vimCommand start="^[: \t]*\(\d\+\(,\d\+\)\=\)\=a\%[ppend]$" matchgroup=vimCommand end="^\.$"" - syn region vimInsert matchgroup=vimCommand start="^[: \t]*\(\d\+\(,\d\+\)\=\)\=c\%[hange]$" matchgroup=vimCommand end="^\.$"" - syn region vimInsert matchgroup=vimCommand start="^[: \t]*\(\d\+\(,\d\+\)\=\)\=i\%[nsert]$" matchgroup=vimCommand end="^\.$"" + syn region vimInsert matchgroup=vimCommand start="^[: \t]*\(\d\+\(,\d\+\)\=\)\=a\%[ppend]$" matchgroup=vimCommand end="^\.$" extend + syn region vimInsert matchgroup=vimCommand start="^[: \t]*\(\d\+\(,\d\+\)\=\)\=c\%[hange]$" matchgroup=vimCommand end="^\.$" extend + syn region vimInsert matchgroup=vimCommand start="^[: \t]*\(\d\+\(,\d\+\)\=\)\=i\%[nsert]$" matchgroup=vimCommand end="^\.$" extend endif " Behave! {{{2 @@ -196,7 +206,7 @@ syn keyword vimFTOption contained detect indent off on plugin " Augroup : vimAugroupError removed because long augroups caused sync'ing problems. {{{2 " ======= : Trade-off: Increasing synclines with slower editing vs augroup END error checking. -syn cluster vimAugroupList contains=@vimCmdList,vimFilter,vimFunc,vimLineComment,vimSpecFile,vimOper,vimNumber,vimOperParen,vimComment,vim9Comment,vimString,vimSubst,vimRegister,vimCmplxRepeat,vimRegion,vimNotation,vimCtrlChar,vimFuncVar,vimContinue +syn cluster vimAugroupList contains=@vimCmdList,vimFilter,vimFunc,vimLineComment,vimSpecFile,vimOper,vimNumber,vimOperParen,@vimComment,vimString,vimSubst,vimRegister,vimCmplxRepeat,vimNotation,vimCtrlChar,vimFuncVar,vimContinue syn match vimAugroup "\<aug\%[roup]\>" contains=vimAugroupKey,vimAugroupBang skipwhite nextgroup=vimAugroupBang,vimAutoCmdGroup if exists("g:vimsyn_folding") && g:vimsyn_folding =~# 'a' syn region vimAugroup fold start="\<aug\%[roup]\>\ze\s\+\%([eE][nN][dD]\)\@!\S\+" matchgroup=vimAugroupKey end="\<aug\%[roup]\>\ze\s\+[eE][nN][dD]\>" contains=vimAutoCmd,@vimAugroupList,vimAugroupkey skipwhite nextgroup=vimAugroupEnd @@ -214,48 +224,95 @@ syn keyword vimAugroupKey contained aug[roup] skipwhite nextgroup=vimAugroupBan " Operators: {{{2 " ========= -syn cluster vimOperGroup contains=vimEnvvar,vimFunc,vimFuncVar,vimOper,vimOperParen,vimNumber,vimString,vimType,vimRegister,@vimContinue,vim9Comment,vimVar +syn cluster vimOperGroup contains=vimEnvvar,vimFunc,vimFuncVar,vimOper,vimOperParen,vimNumber,vimString,vimRegister,@vimContinue,vim9Comment,vimVar syn match vimOper "||\|&&\|[-+*/%.!]" skipwhite nextgroup=vimString,vimSpecFile syn match vimOper "\%#=1\(==\|!=\|>=\|<=\|=\~\|!\~\|>\|<\|=\|!\~#\)[?#]\{0,2}" skipwhite nextgroup=vimString,vimSpecFile syn match vimOper "\(\<is\|\<isnot\)[?#]\{0,2}\>" skipwhite nextgroup=vimString,vimSpecFile -syn region vimOperParen matchgroup=vimParenSep start="(" end=")" contains=vimoperStar,@vimOperGroup +syn region vimOperParen matchgroup=vimParenSep start="(" end=")" contains=@vimOperGroup syn region vimOperParen matchgroup=vimSep start="#\={" end="}" contains=@vimOperGroup nextgroup=vimVar,vimFuncVar if !exists("g:vimsyn_noerror") && !exists("g:vimsyn_noopererror") syn match vimOperError ")" endif -" Functions : Tag is provided for those who wish to highlight tagged functions {{{2 +" Functions: Tag is provided for those who wish to highlight tagged functions {{{2 " ========= -syn cluster vimFuncList contains=vimCommand,vimFunctionError,vimFuncKey,Tag,vimFuncSID -syn cluster vimFuncBodyList contains=@vimCmdList,vimCmplxRepeat,vimComment,vim9Comment,vimContinue,vimCtrlChar,vimEnvvar,vimFBVar,vimFunc,vimFunction,vimFuncVar,vimLetHereDoc,vimLineComment,vimNotation,vimNotFunc,vimNumber,vimOper,vimOperParen,vimRegion,vimRegister,vimSearch,vimSpecFile,vimString,vimSubst -syn match vimFunction "\<\(fu\%[nction]\)!\=\s\+\%(<[sS][iI][dD]>\|[sSgGbBwWtTlL]:\)\=\%(\i\|[#.]\|{.\{-1,}}\)*\ze\s*(" contains=@vimFuncList nextgroup=vimFuncBody -syn match vimFunction "\<def!\=\ze\s*(" contains=@vimFuncList nextgroup=vimFuncBody +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 vimFuncBodyList contains=@vimFuncBodyCommon,vimComment,vimLineComment,vimFuncVar,vimInsert +syn cluster vimDefBodyList contains=@vimFuncBodyCommon,vim9Comment,vim9LineComment + +syn region vimFuncPattern contained matchgroup=vimOper start="/" end="$" contains=@vimSubstList +syn match vimFunction "\<fu\%[nction]\>" skipwhite nextgroup=vimCmdSep,vimComment,vimFuncPattern contains=vimFuncKey +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 skipnl nextgroup=vimFuncBody,vimEndfunction +syn match vimDefComment contained "#.*" skipwhite skipnl nextgroup=vimDefBody,vimEnddef + +syn match vimFuncBang contained "!" +syn match vimFuncSID contained "\c<sid>" +syn match vimFuncSID contained "\<[sg]:" +syn keyword vimFuncKey contained fu[nction] +syn keyword vimDefKey contained def + +syn region vimFuncParams contained matchgroup=Delimiter start="(" skip=+\n\s*\\\|\n\s*"\\ + end=")" skipwhite skipnl nextgroup=vimFuncBody,vimFuncComment,vimEndfunction,vimFuncMod contains=vimFuncParam,@vimContinue +syn region vimDefParams contained matchgroup=Delimiter start="(" end=")" skipwhite skipnl nextgroup=vimDefBody,vimDefComment,vimEnddef,vimReturnType contains=vimDefParam,vim9Comment +syn match vimFuncParam contained "\<\h\w*\>\|\.\.\." skipwhite nextgroup=vimFuncParamEquals +syn match vimDefParam contained "\<\h\w*\>" skipwhite nextgroup=vimParamType,vimFuncParamEquals + +syn match vimFuncParamEquals contained "=" skipwhite nextgroup=@vimExprList +syn match vimFuncMod contained "\<\%(abort\|closure\|dict\|range\)\>" skipwhite skipnl nextgroup=vimFuncBody,vimFuncComment,vimEndfunction,vimFuncMod + +syn region vimFuncBody contained start="^" matchgroup=vimCommand end="\<endfu\%[nction]\>" contains=@vimFuncBodyList +syn region vimDefBody contained start="^" matchgroup=vimCommand end="\<enddef\>" contains=@vimDefBodyList + +syn match vimEndfunction "\<endf\%[unction]\>" +syn match vimEnddef "\<enddef\>" if exists("g:vimsyn_folding") && g:vimsyn_folding =~# 'f' - syn region vimFuncBody contained fold start="\ze\s*(" matchgroup=vimCommand end="\<\(endf\>\|endfu\%[nction]\>\|enddef\>\)" contains=@vimFuncBodyList -else - syn region vimFuncBody contained start="\ze\s*(" matchgroup=vimCommand end="\<\(endf\>\|endfu\%[nction]\>\|enddef\>\)" contains=@vimFuncBodyList + syn region vimFuncFold start="^\s*:\=\s*fu\%[nction]\>!\=\s*\%(<[sS][iI][dD]>\|[sg]:\)\=\%(\i\|[#.]\|{.\{-1,}}\)\+\s*(" end="^\s*:\=\s*endf\%[unction]\>" contains=vimFunction fold keepend extend transparent + syn region vimFuncFold start="^\s*:\=\s*def\>!\=\s*\%(<[sS][iI][dD]>\|[sg]:\)\=\%(\i\|[#.]\)\+(" end="^\s*:\=\s*enddef\>" contains=vimDef fold keepend extend transparent + syn region vimFuncFold start="^\s*:\=\s*def\s\+new\i\+(" end="^\s*:\=\s*enddef\>" contains=vimDef fold keepend extend transparent endif -syn match vimFuncVar contained "a:\(\K\k*\|\d\+\)" -syn match vimFuncSID contained "\c<sid>\|\<s:" -syn keyword vimFuncKey contained fu[nction] -syn match vimFuncBlank contained "\s\+" -syn keyword vimPattern contained start skip end +syn match vimFuncVar contained "a:\%(\K\k*\|\d\+\)\>" +syn match vimFuncBlank contained "\s\+" +" Types: {{{2 +" ===== " vimTypes : new for vim9 -syn match vimType ":\s*\zs\<\(bool\|number\|float\|string\|blob\|list<\|dict<\|job\|channel\|func\)\>" +syn region vimReturnType contained start=":\s" end="$" matchgroup=vim9Comment end="\ze#" skipwhite skipnl nextgroup=vimDefBody,vimDefComment,vimEnddef contains=vimTypeSep transparent +syn match vimParamType contained ":\s\+\a" skipwhite skipnl nextgroup=vimFuncParamEquals contains=vimTypeSep,@vimType + +syn match vimTypeSep contained ":\s\@=" skipwhite nextgroup=@vimType +syn keyword vimType contained any blob bool channel float job number string void +syn match vimType contained "\<func\>" +syn region vimCompoundType contained matchgroup=vimType start="\<func(" end=")" nextgroup=vimTypeSep contains=@vimType oneline transparent +syn region vimCompoundType contained matchgroup=vimType start="\<\%(list\|dict\)<" end=">" contains=@vimType oneline transparent +syn match vimUserType contained "\<\u\w*\>" -" Keymaps: (Vim Project Addition) {{{2 +syn cluster vimType contains=vimType,vimCompoundType,vimUserType + +" Keymaps: {{{2 " ======= -" TODO: autogenerated vimCommand keyword list does not handle all abbreviations -" : handle Vim9 script comments when something like #13104 is merged -syn match vimKeymapStart "^" contained skipwhite nextgroup=vimKeymapLhs,vimKeymapLineComment +syn match vimKeymapStart "^" contained skipwhite nextgroup=vimKeymapLhs,@vimKeymapLineComment syn match vimKeymapLhs "\S\+" contained skipwhite nextgroup=vimKeymapRhs contains=vimNotation syn match vimKeymapRhs "\S\+" contained skipwhite nextgroup=vimKeymapTailComment contains=vimNotation syn match vimKeymapTailComment "\S.*" contained -syn match vimKeymapLineComment +".*+ contained contains=@vimCommentGroup,vimCommentString,vimCommentTitle + +" TODO: remove when :" comment is matched in parts as "ex-colon comment" --djk +if s:vim9script + syn match vim9KeymapLineComment "#.*" contained contains=@vimCommentGroup,vimCommentString,vim9CommentTitle +else + syn match vimKeymapLineComment +".*+ contained contains=@vimCommentGroup,vimCommentString,vimCommentTitle +endif +syn cluster vimKeymapLineComment contains=vim9\=KeymapLineComment syn region vimKeymap matchgroup=vimCommand start="\<loadk\%[eymap]\>" end="\%$" contains=vimKeymapStart @@ -271,9 +328,10 @@ syn match vimSpecFileMod "\(:[phtre]\)\+" contained " User-Specified Commands: {{{2 " ======================= -syn cluster vimUserCmdList contains=@vimCmdList,vimCmplxRepeat,vimComment,vim9Comment,vimCtrlChar,vimEscapeBrace,vimFunc,vimNotation,vimNumber,vimOper,vimRegion,vimRegister,vimSpecFile,vimString,vimSubst,vimSubstRep,vimSubstRange +syn cluster vimUserCmdList contains=@vimCmdList,vimCmplxRepeat,@vimComment,vimCtrlChar,vimEscapeBrace,vimFunc,vimNotation,vimNumber,vimOper,vimRegister,vimSpecFile,vimString,vimSubst,vimSubstRep,vimSubstRange syn keyword vimUserCommand contained com[mand] -syn match vimUserCmd "\<com\%[mand]!\=\>.*$" contains=vimUserAttrb,vimUserAttrbError,vimUserCommand,@vimUserCmdList,vimComFilter +syn match vimUserCmdName contained "\<\u\w*\>" nextgroup=vimUserCmdBlock skipwhite +syn match vimUserCmd "\<com\%[mand]!\=\>.*$" contains=vimUserAttrb,vimUserAttrbError,vimUserCommand,@vimUserCmdList,vimComFilter,vimCmdBlock,vimUserCmdName syn match vimUserAttrbError contained "-\a\+\ze\s" syn match vimUserAttrb contained "-nargs=[01*?+]" contains=vimUserAttrbKey,vimOper syn match vimUserAttrb contained "-complete=" contains=vimUserAttrbKey,vimOper nextgroup=vimUserAttrbCmplt,vimUserCmdError @@ -296,20 +354,41 @@ syn match vimUserAttrbCmpltFunc contained ",\%([sS]:\|<[sS][iI][dD]>\)\=\%(\h\w* syn case match syn match vimUserAttrbCmplt contained "custom,\u\w*" +syn region vimUserCmdBlock contained matchgroup=vimSep start="{" end="}" contains=@vimDefBodyList + " Lower Priority Comments: after some vim commands... {{{2 " ======================= -syn match vimComment excludenl +\s"[^\-:.%#=*].*$+lc=1 contains=@vimCommentGroup,vimCommentString -syn match vimComment +\<endif\s\+".*$+lc=5 contains=@vimCommentGroup,vimCommentString -syn match vimComment +\<else\s\+".*$+lc=4 contains=@vimCommentGroup,vimCommentString -syn region vimCommentString contained oneline start='\S\s\+"'ms=e end='"' -" Vim9 comments - TODO: might be highlighted while they don't work -syn match vim9Comment excludenl +\s#[^{].*$+lc=1 contains=@vimCommentGroup,vimCommentString -syn match vim9Comment +\<endif\s\+#[^{].*$+lc=5 contains=@vimCommentGroup,vimCommentString -syn match vim9Comment +\<else\s\+#[^{].*$+lc=4 contains=@vimCommentGroup,vimCommentString -" Vim9 comment inside expression -syn match vim9Comment +\s\zs#[^{].*$+ms=s+1 contains=@vimCommentGroup,vimCommentString -syn match vim9Comment +^\s*#[^{].*$+ contains=@vimCommentGroup,vimCommentString -syn match vim9Comment +^\s*#$+ contains=@vimCommentGroup,vimCommentString +syn region vimCommentString contained oneline start='\S\s\+"'ms=e end='"' + +if s:vim9script + syn match vimComment excludenl +\s"[^\-:.%#=*].*$+lc=1 contains=@vimCommentGroup,vimCommentString contained + syn match vimComment +\<endif\s\+".*$+lc=5 contains=@vimCommentGroup,vimCommentString contained + syn match vimComment +\<else\s\+".*$+lc=4 contains=@vimCommentGroup,vimCommentString contained + " Vim9 comments - TODO: might be highlighted while they don't work + syn match vim9Comment excludenl +\s#[^{].*$+lc=1 contains=@vimCommentGroup,vimCommentString + syn match vim9Comment +\<endif\s\+#[^{].*$+lc=5 contains=@vimCommentGroup,vimCommentString + syn match vim9Comment +\<else\s\+#[^{].*$+lc=4 contains=@vimCommentGroup,vimCommentString + " Vim9 comment inside expression + " syn match vim9Comment +\s\zs#[^{].*$+ms=s+1 contains=@vimCommentGroup,vimCommentString + " syn match vim9Comment +^\s*#[^{].*$+ contains=@vimCommentGroup,vimCommentString + " syn match vim9Comment +^\s*#$+ contains=@vimCommentGroup,vimCommentString + + syn cluster vimComment contains=vim9Comment +else + syn match vimComment excludenl +\s"[^\-:.%#=*].*$+lc=1 contains=@vimCommentGroup,vimCommentString + syn match vimComment +\<endif\s\+".*$+lc=5 contains=@vimCommentGroup,vimCommentString + syn match vimComment +\<else\s\+".*$+lc=4 contains=@vimCommentGroup,vimCommentString + " Vim9 comments - TODO: might be highlighted while they don't work + syn match vim9Comment excludenl +\s#[^{].*$+lc=1 contains=@vimCommentGroup,vimCommentString contained + syn match vim9Comment +\<endif\s\+#[^{].*$+lc=5 contains=@vimCommentGroup,vimCommentString contained + syn match vim9Comment +\<else\s\+#[^{].*$+lc=4 contains=@vimCommentGroup,vimCommentString contained + " Vim9 comment inside expression + syn match vim9Comment +\s\zs#[^{].*$+ms=s+1 contains=@vimCommentGroup,vimCommentString contained + syn match vim9Comment +^\s*#[^{].*$+ contains=@vimCommentGroup,vimCommentString contained + syn match vim9Comment +^\s*#$+ contains=@vimCommentGroup,vimCommentString contained + + syn cluster vimComment contains=vimComment +endif " Environment Variables: {{{2 " ===================== @@ -399,7 +478,7 @@ syn match vimCmplxRepeat '[^a-zA-Z_/\\()]q[0-9a-zA-Z"]\>'lc=1 syn match vimCmplxRepeat '@[0-9a-z".=@:]\ze\($\|[^a-zA-Z]\>\)' " Set command and associated set-options (vimOptions) with comment {{{2 -syn region vimSet matchgroup=vimCommand start="\<\%(setl\%[ocal]\|setg\%[lobal]\|se\%[t]\)\>" skip="\%(\\\\\)*\\.\n\@!" end="$" end="|" matchgroup=vimNotation end="<[cC][rR]>" keepend contains=vimSetEqual,vimOption,vimErrSetting,vimComment,vim9Comment,vimSetString,vimSetMod +syn region vimSet matchgroup=vimCommand start="\<\%(setl\%[ocal]\|setg\%[lobal]\|se\%[t]\)\>" skip="\%(\\\\\)*\\.\n\@!" end="$" end="|" matchgroup=vimNotation end="<[cC][rR]>" keepend contains=vimSetEqual,vimOption,vimErrSetting,@vimComment,vimSetString,vimSetMod syn region vimSetEqual contained start="[=:]\|[-+^]=" skip="\\\\\|\\\s" end="[| \t]"me=e-1 end="$" contains=vimCtrlChar,vimSetSep,vimNotation,vimEnvvar syn region vimSetString contained start=+="+hs=s+1 skip=+\\\\\|\\"+ end=+"+ contains=vimCtrlChar syn match vimSetSep contained "[,:]" @@ -415,36 +494,52 @@ syn keyword vimUnlet unl[et] skipwhite nextgroup=vimUnletBang,vimUnletVars syn match vimUnletBang contained "!" skipwhite nextgroup=vimUnletVars syn region vimUnletVars contained start="$\I\|\h" skip="\n\s*\\" end="$" end="|" contains=vimVar,vimEnvvar,vimContinue,vimString,vimNumber -VimFoldh syn region vimLetHereDoc matchgroup=vimLetHereDocStart start='=<<\s*\%(trim\s\+\%(eval\s\+\)\=\|eval\s\+\%(trim\s\+\)\=\)\=\z(\L\S*\)' matchgroup=vimLetHereDocStop end='^\s*\z1\s*$' +VimFoldh syn region vimLetHereDoc matchgroup=vimLetHereDocStart start='=<<\s*\%(trim\s\+\%(eval\s\+\)\=\|eval\s\+\%(trim\s\+\)\=\)\=\z(\L\S*\)' matchgroup=vimLetHereDocStop end='^\s*\z1\s*$' extend +syn keyword vimLet var skipwhite nextgroup=vimVar,vimFuncVar,vimLetHereDoc " For: {{{2 " === syn keyword vimFor for skipwhite nextgroup=vimVar,vimVarList + " Abbreviations: {{{2 " ============= " GEN_SYN_VIM: vimCommand abbrev, START_STR='syn keyword vimAbb', END_STR='skipwhite nextgroup=vimMapMod,vimMapLhs' syn keyword vimAbb ab[breviate] ca[bbrev] cnorea[bbrev] cuna[bbrev] ia[bbrev] inorea[bbrev] iuna[bbrev] norea[bbrev] una[bbreviate] skipwhite nextgroup=vimMapMod,vimMapLhs +" GEN_SYN_VIM: vimCommand abclear, START_STR='syn keyword vimAbb', END_STR='skipwhite nextgroup=vimMapMod' +syn keyword vimAbb abc[lear] cabc[lear] iabc[lear] skipwhite nextgroup=vimMapMod " Autocmd: {{{2 " ======= syn match vimAutoEventList contained "\(!\s\+\)\=\(\a\+,\)*\a\+" contains=vimAutoEvent,nvimAutoEvent nextgroup=vimAutoCmdSpace syn match vimAutoCmdSpace contained "\s\+" nextgroup=vimAutoCmdSfxList -syn match vimAutoCmdSfxList contained "\S*" skipwhite nextgroup=vimAutoCmdMod +syn match vimAutoCmdSfxList contained "\S*" skipwhite nextgroup=vimAutoCmdMod,vimAutoCmdBlock syn keyword vimAutoCmd au[tocmd] do[autocmd] doautoa[ll] skipwhite nextgroup=vimAutoEventList -syn match vimAutoCmdMod "\(++\)\=\(once\|nested\)" +syn match vimAutoCmdMod "\(++\)\=\(once\|nested\)" skipwhite nextgroup=vimAutoCmdBlock +syn region vimAutoCmdBlock contained matchgroup=vimSep start="{" end="}" contains=@vimDefBodyList " Echo And Execute: -- prefer strings! {{{2 " ================ -" GEN_SYN_VIM: vimCommand echo, START_STR='syn keyword vimEcho', END_STR='skipwhite nextgroup=vimEchoExpr' -syn keyword vimEcho ec[ho] echoe[rr] echom[sg] echoc[onsole] echon echow[indow] skipwhite nextgroup=vimEchoExpr -syn region vimEchoExpr contained start="[^[:space:]|]" skip=+\\\\\|\\|\|\n\s*\\\|\n\s*"\\ + matchgroup=vimCmdSep end="|" end="$" contains=@vimContinue,@vimExprList - -syn match vimEchoHL "\<echohl\=\>" skipwhite nextgroup=vimGroup,vimHLGroup,vimEchoHLNone,vimOnlyHLGroup,nvimHLGroup +" NOTE: No trailing comments + +syn region vimEcho + \ matchgroup=vimCommand + \ start="\<ec\%[ho]\>" + \ start="\<echoe\%[rr]\>" + \ start="\<echom\%[sg]\>" + \ start="\<echoc\%[onsole]\>" + \ start="\<echon\>" + \ start="\<echow\%[indow]\>" + \ skip=+\\|\|\n\s*\\\|\n\s*"\\ + + \ matchgroup=vimCmdSep end="|" excludenl end="$" contains=@vimContinue,@vimExprList transparent + +syn match vimEchohl "\<echohl\=\>" skipwhite nextgroup=vimGroup,vimHLGroup,vimEchohlNone,vimOnlyHLGroup,nvimHLGroup syn case ignore -syn keyword vimEchoHLNone none +syn keyword vimEchohlNone contained none syn case match -syn region vimExecute oneline excludenl matchgroup=vimCommand start="\<exe\%[cute]\>" skip="\(\\\\\)*\\|" end="$\||\|<[cC][rR]>" contains=vimFuncVar,vimIsCommand,vimOper,vimNotation,vimOperParen,vimString,vimVar +syn cluster vimEcho contains=vimEcho,vimEchohl + +syn region vimExecute matchgroup=vimCommand start="\<exe\%[cute]\>" skip=+\\|\|\n\s*\\\|\n\s*"\\ + matchgroup=vimCmdSep end="|" excludenl end="$" contains=@vimContinue,@vimExprList transparent " Maps: {{{2 " ==== @@ -457,27 +552,41 @@ syn keyword vimMap cmapc[lear] imapc[lear] lmapc[lear] nmapc[lear] omapc[lear] s syn keyword vimMap mapc[lear] skipwhite nextgroup=vimMapBang,vimMapMod " GEN_SYN_VIM: vimCommand unmap, START_STR='syn keyword vimUnmap', END_STR='skipwhite nextgroup=vimMapBang,vimMapMod,vimMapLhs' syn keyword vimUnmap cu[nmap] iu[nmap] lu[nmap] nun[map] ou[nmap] sunm[ap] tunma[p] unm[ap] vu[nmap] xu[nmap] skipwhite nextgroup=vimMapBang,vimMapMod,vimMapLhs -syn match vimMapLhs contained "\S\+" contains=vimNotation,vimCtrlChar skipwhite nextgroup=vimMapRhs -syn match vimMapBang contained "\a\@1<=!" skipwhite nextgroup=vimMapMod,vimMapLhs +syn match vimMapLhs contained "\%(.\|\S\)\+" contains=vimCtrlChar,vimNotation skipwhite nextgroup=vimMapRhs +syn match vimMapLhs contained "\%(.\|\S\)\+\ze\s*$" contains=vimCtrlChar,vimNotation skipwhite skipnl nextgroup=vimMapRhsContinue +syn match vimMapBang contained "\a\@1<=!" skipwhite nextgroup=vimMapMod,vimMapLhs syn match vimMapMod contained "\%#=1\c<\(buffer\|expr\|\(local\)\=leader\|nowait\|plug\|script\|sid\|unique\|silent\)\+>" contains=vimMapModKey,vimMapModErr skipwhite nextgroup=vimMapMod,vimMapLhs -syn match vimMapRhs contained ".*" contains=vimNotation,vimCtrlChar skipnl nextgroup=vimMapRhsExtend -syn match vimMapRhsExtend contained "^\s*\\.*$" contains=vimContinue +syn region vimMapRhs contained start="\S" skip=+\\|\|\@1<=|\|\n\s*\\\|\n\s*"\\ + end="|" end="$" contains=@vimContinue,vimCtrlChar,vimNotation skipnl nextgroup=vimMapRhsContinue +" assume a continuation comment introduces the RHS +syn region vimMapRhsContinue contained start=+^\s*\%(\\\|"\\ \)+ skip=+\\|\|\@1<=|\|\n\s*\\\|\n\s*"\\ + end="|" end="$" contains=@vimContinue,vimCtrlChar,vimNotation syn case ignore syn keyword vimMapModKey contained buffer expr leader localleader nowait plug script sid silent unique syn case match " Menus: {{{2 " ===== -syn cluster vimMenuList contains=vimMenuBang,vimMenuPriority,vimMenuName,vimMenuMod -" GEN_SYN_VIM: vimCommand menu, START_STR='syn keyword vimCommand', END_STR='skipwhite nextgroup=@vimMenuList' -syn keyword vimCommand am[enu] an[oremenu] aun[menu] cme[nu] cnoreme[nu] cunme[nu] ime[nu] inoreme[nu] iunme[nu] me[nu] nme[nu] nnoreme[nu] noreme[nu] nunme[nu] ome[nu] onoreme[nu] ounme[nu] sme[nu] snoreme[nu] sunme[nu] tlm[enu] tln[oremenu] tlu[nmenu] unme[nu] vme[nu] vnoreme[nu] vunme[nu] xme[nu] xnoreme[nu] xunme[nu] skipwhite nextgroup=@vimMenuList -syn match vimMenuName "[^ \t\\<]\+" contained nextgroup=vimMenuNameMore,vimMenuMap -syn match vimMenuPriority "\d\+\(\.\d\+\)*" contained skipwhite nextgroup=vimMenuName -syn match vimMenuNameMore "\c\\\s\|<tab>\|\\\." contained nextgroup=vimMenuName,vimMenuNameMore contains=vimNotation -syn match vimMenuMod contained "\c<\(script\|silent\)\+>" skipwhite contains=vimMapModKey,vimMapModErr nextgroup=@vimMenuList -syn match vimMenuMap "\s" contained skipwhite nextgroup=vimMenuRhs -syn match vimMenuRhs ".*$" contained contains=vimString,vimComment,vim9Comment,vimIsCommand -syn match vimMenuBang "!" contained skipwhite nextgroup=@vimMenuList +" NOTE: tail comments disallowed +" GEN_SYN_VIM: vimCommand menu, START_STR='syn keyword vimMenu', END_STR='skipwhite nextgroup=vimMenuBang,vimMenuMod,vimMenuName,vimMenuPriority,vimMenuStatus' +syn keyword vimMenu am[enu] an[oremenu] aun[menu] cme[nu] cnoreme[nu] cunme[nu] ime[nu] inoreme[nu] iunme[nu] me[nu] nme[nu] nnoreme[nu] noreme[nu] nunme[nu] ome[nu] onoreme[nu] ounme[nu] sme[nu] snoreme[nu] sunme[nu] tlm[enu] tln[oremenu] tlu[nmenu] tm[enu] tu[nmenu] unme[nu] vme[nu] vnoreme[nu] vunme[nu] xme[nu] xnoreme[nu] xunme[nu] skipwhite nextgroup=vimMenuBang,vimMenuMod,vimMenuName,vimMenuPriority,vimMenuStatus +syn keyword vimMenu popu[p] skipwhite nextgroup=vimMenuBang,vimMenuName +syn region vimMenuRhs contained contains=@vimContinue,vimNotation start="|\@!\S" skip=+\\\\\|\\|\|\n\s*\\\|\n\s*"\\ + end="$" matchgroup=vimSep end="|" +syn region vimMenuRhsContinue contained contains=@vimContinue,vimNotation start=+^\s*\%(\\\|"\\ \)+ skip=+\\\\\|\\|\|\n\s*\\\|\n\s*"\\ + end="$" matchgroup=vimSep end="|" +syn match vimMenuName "\.\@!\%(\\\s\|\S\)\+" contained contains=vimMenuNotation,vimNotation skipwhite nextgroup=vimCmdSep,vimMenuRhs +syn match vimMenuName "\.\@!\%(\\\s\|\S\)\+\ze\s*$" contained contains=vimMenuNotation,vimNotation skipwhite skipnl nextgroup=vimCmdSep,vimMenuRhsContinue +syn match vimMenuNotation "&\a\|&&\|\\\s\|\\\." contained +syn match vimMenuPriority "\<\d\+\%(\.\d\+\)*\>" contained skipwhite nextgroup=vimMenuName +syn match vimMenuMod "\c<\%(script\|silent\|special\)>" contained skipwhite nextgroup=vimMenuName,vimMenuPriority,vimMenuMod contains=vimMapModKey,vimMapModErr +syn keyword vimMenuStatus enable disable nextgroup=vimMenuName skipwhite +syn match vimMenuBang "\a\@1<=!" contained skipwhite nextgroup=vimMenuName,vimMenuMod + +syn region vimMenutranslate + \ matchgroup=vimCommand start="\<menut\%[ranslate]\>" + \ skip=+\\\\\|\\|\|\n\s*\\\|\n\s*"\\ + + \ end="$" matchgroup=vimCmdSep end="|" matchgroup=vimMenuClear end="\<clear\ze\s*\%(["#|]\|$\)" + \ contains=@vimContinue,vimMenutranslateName keepend transparent +" oneline is sufficient to match the current formatting in runtime/lang/*.vim +syn match vimMenutranslateName "\%(\\\s\|\S\)\+" contained contains=vimMenuNotation,vimNotation +syn match vimMenutranslateComment +".*+ contained containedin=vimMenutranslate " Angle-Bracket Notation: (tnx to Michael Geddes) {{{2 " ====================== @@ -505,9 +614,9 @@ syn case match " User Function Highlighting: {{{2 " (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 keyword vimFuncEcho contained ec ech echo +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 keyword vimFuncEcho contained ec ech echo " User Command Highlighting: {{{2 syn match vimUsrCmd '^\s*\zs\u\%(\w*\)\@>\%([(#[]\|\s\+\%([-+*/%]\=\|\.\.\)=\)\@!' @@ -547,8 +656,7 @@ if has("conceal") syn match vimSynCcharValue contained "\S" endif -syn match vimSyntax "\<sy\%[ntax]\>" contains=vimCommand skipwhite nextgroup=vimSynType,vimComment,vim9Comment -syn match vimAuSyntax contained "\s+sy\%[ntax]" contains=vimCommand skipwhite nextgroup=vimSynType,vimComment,vim9Comment +syn match vimSyntax "\<sy\%[ntax]\>" contains=vimCommand skipwhite nextgroup=vimSynType,@vimComment syn cluster vimFuncBodyList add=vimSyntax " Syntax: case {{{2 @@ -637,12 +745,12 @@ syn match vimIsCommand "<Bar>\s*\a\+" transparent contains=vimCommand,vimNotatio " Highlighting: {{{2 " ============ -syn cluster vimHighlightCluster contains=vimHiLink,vimHiClear,vimHiKeyList,vimComment,vim9Comment +syn cluster vimHighlightCluster contains=vimHiLink,vimHiClear,vimHiKeyList,@vimComment if !exists("g:vimsyn_noerror") && !exists("g:vimsyn_novimhictermerror") syn match vimHiCtermError contained "\D\i*" endif syn match vimHighlight "\<hi\%[ghlight]\>" skipwhite nextgroup=vimHiBang,@vimHighlightCluster -syn match vimHiBang contained "!" skipwhite nextgroup=@vimHighlightCluster +syn match vimHiBang contained "\a\@1<=!" skipwhite nextgroup=@vimHighlightCluster syn match vimHiGroup contained "\i\+" syn case ignore @@ -661,16 +769,17 @@ syn match vimHiGuiFontname contained "'[a-zA-Z\-* ]\+'" syn match vimHiGuiRgb contained "#\x\{6}" " Highlighting: hi group key=arg ... {{{2 -syn cluster vimHiCluster contains=vimGroup,vimHiBlend,vimHiGroup,vimHiTerm,vimHiCTerm,vimHiStartStop,vimHiCtermFgBg,vimHiCtermul,vimHiGui,vimHiGuiFont,vimHiGuiFgBg,vimHiKeyError,vimNotation,vimComment,vim9comment -syn region vimHiKeyList contained oneline start="\i\+" skip="\\\\\|\\|" end="$\||" contains=@vimHiCluster +syn cluster vimHiCluster contains=vimGroup,vimHiBlend,vimHiGroup,vimHiTerm,vimHiCTerm,vimHiStartStop,vimHiCtermFgBg,vimHiCtermul,vimHiCtermfont,vimHiGui,vimHiGuiFont,vimHiGuiFgBg,vimHiKeyError,vimNotation,vimComment,vim9comment +syn region vimHiKeyList contained start="\i\+" skip=+\\\\\|\\|\|\n\s*\\\|\n\s*"\\ + matchgroup=vimCmdSep end="|" excludenl end="$" contains=@vimContinue,@vimHiCluster if !exists("g:vimsyn_noerror") && !exists("g:vimsyn_vimhikeyerror") syn match vimHiKeyError contained "\i\+="he=e-1 endif syn match vimHiTerm contained "\cterm="he=e-1 nextgroup=vimHiAttribList -syn match vimHiStartStop contained "\c\(start\|stop\)="he=e-1 nextgroup=vimHiTermcap,vimOption +syn match vimHiStartStop contained "\c\%(start\|stop\)="he=e-1 nextgroup=vimHiTermcap,vimOption syn match vimHiCTerm contained "\ccterm="he=e-1 nextgroup=vimHiAttribList syn match vimHiCtermFgBg contained "\ccterm[fb]g="he=e-1 nextgroup=vimHiNmbr,vimHiCtermColor,vimFgBgAttrib,vimHiCtermError syn match vimHiCtermul contained "\cctermul="he=e-1 nextgroup=vimHiNmbr,vimHiCtermColor,vimFgBgAttrib,vimHiCtermError +syn match vimHiCtermfont contained "\cctermfont="he=e-1 nextgroup=vimHiNmbr,vimHiCtermColor,vimFgBgAttrib,vimHiCtermError syn match vimHiGui contained "\cgui="he=e-1 nextgroup=vimHiAttribList syn match vimHiGuiFont contained "\cfont="he=e-1 nextgroup=vimHiFontname syn match vimHiGuiFgBg contained "\cgui\%([fb]g\|sp\)="he=e-1 nextgroup=vimHiGroup,vimHiGuiFontname,vimHiGuiRgb,vimFgBgAttrib @@ -679,12 +788,13 @@ syn match vimHiBlend contained "\cblend="he=e-1 nextgroup=vimHiNmbr syn match vimHiNmbr contained '\d\+' " Highlight: clear {{{2 -syn keyword vimHiClear contained clear nextgroup=vimHiGroup +syn keyword vimHiClear contained clear skipwhite nextgroup=vimGroup,vimHiGroup " Highlight: link {{{2 " see tst24 (hi def vs hi) (Jul 06, 2018) "syn region vimHiLink contained oneline matchgroup=vimCommand start="\(\<hi\%[ghlight]\s\+\)\@<=\(\(def\%[ault]\s\+\)\=link\>\|\<def\>\)" end="$" contains=vimHiGroup,vimGroup,vimHLGroup,vimNotation -syn region vimHiLink contained oneline matchgroup=vimCommand start="\(\<hi\%[ghlight]\s\+\)\@<=\(\(def\%[ault]\s\+\)\=link\>\|\<def\>\)" end="$" contains=@vimHiCluster +" TODO: simplify and allow line continuations --djk +syn region vimHiLink contained matchgroup=Type start="\%(\<hi\%[ghlight]!\=\s\+\)\@<=\%(\%(def\%[ault]\s\+\)\=link\>\|\<def\%[ault]\>\)" skip=+\\\\\|\\|\|\n\s*\\\|\n\s*"\\ + matchgroup=vimCmdSep end="|" excludenl end="$" contains=@vimContinue,@vimHiCluster " Control Characters: {{{2 " ================== @@ -692,16 +802,21 @@ syn match vimCtrlChar "[--]" " Beginners - Patterns that involve ^ {{{2 " ========= -syn match vimLineComment +^[ \t:]*".*$+ contains=@vimCommentGroup,vimCommentString,vimCommentTitle,vimComment -syn match vimLineComment +^[ \t:]*"\("[^"]*"\|[^"]\)*$+ contains=@vimCommentGroup,vimCommentString,vimCommentTitle -syn match vim9LineComment +^[ \t:]\+#.*$+ contains=@vimCommentGroup,vimCommentString,vimCommentTitle +if s:vim9script + syn match vimLineComment +^[ \t:]*".*$+ contains=@vimCommentGroup,vimCommentString,vimCommentTitle contained + syn match vim9LineComment +^[ \t:]*#.*$+ contains=@vimCommentGroup,vimCommentString,vim9CommentTitle +else + syn match vimLineComment +^[ \t:]*".*$+ contains=@vimCommentGroup,vimCommentString,vimCommentTitle + syn match vim9LineComment +^[ \t:]*#.*$+ contains=@vimCommentGroup,vimCommentString,vim9CommentTitle contained +endif syn match vimCommentTitle '"\s*\%([sS]:\|\h\w*#\)\=\u\w*\(\s\+\u\w*\)*:'hs=s+1 contained contains=vimCommentTitleLeader,vimTodo,@vimCommentGroup -" Note: Look-behind to work around nextgroup skipnl consuming leading whitespace and preventing a match +syn match vim9CommentTitle '#\s*\%([sS]:\|\h\w*#\)\=\u\w*\(\s\+\u\w*\)*:'hs=s+1 contained contains=vim9CommentTitleLeader,vimTodo,@vimCommentGroup syn match vimContinue "^\s*\zs\\" syn match vimContinueComment '^\s*\zs["#]\\ .*' contained syn cluster vimContinue contains=vimContinue,vimContinueComment 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 " Searches And Globals: {{{2 " ==================== @@ -710,6 +825,17 @@ syn match vimSearchDelim '^\s*\zs[/?]\|[/?]$' contained syn region vimGlobal matchgroup=Statement start='\<g\%[lobal]!\=/' skip='\\.' end='/' skipwhite nextgroup=vimSubst1 syn region vimGlobal matchgroup=Statement start='\<v\%[global]!\=/' skip='\\.' end='/' skipwhite nextgroup=vimSubst1 +" Vim9 Script Regions: {{{2 +" ================== + +if s:vim9script + syn cluster vimLegacyTop contains=TOP,vim9LegacyHeader,vim9Comment,vim9LineComment + VimFoldH syn region vim9LegacyHeader start="\%^" end="^\ze\s*vim9s\%[cript]\>" contains=@vimLegacyTop,vimComment,vimLineComment + + syn keyword vim9Vim9ScriptArg noclear contained + syn keyword vim9Vim9Script vim9s[cript] nextgroup=vim9Vim9ScriptArg skipwhite +endif + " Embedded Scripts: {{{2 " ================ " perl,ruby : Benoit Cerrina @@ -895,6 +1021,7 @@ if exists("g:vimsyn_minlines") endif exe "syn sync maxlines=".s:vimsyn_maxlines syn sync linecont "^\s\+\\" +syn sync linebreaks=1 syn sync match vimAugroupSyncA groupthere NONE "\<aug\%[roup]\>\s\+[eE][nN][dD]" " ==================== @@ -913,7 +1040,6 @@ if !exists("skip_vim_syntax_inits") hi def link vimHiAttribList vimError hi def link vimHiCtermError vimError hi def link vimHiKeyError vimError - hi def link vimKeyCodeError vimError hi def link vimMapModErr vimError hi def link vimSubstFlagErr vimError hi def link vimSynCaseError vimError @@ -921,17 +1047,15 @@ if !exists("skip_vim_syntax_inits") hi def link vimBufnrWarn vimWarn endif + hi def link vim9Vim9ScriptArg Special hi def link vimAbb vimCommand hi def link vimAddress vimMark hi def link vimAugroupBang vimBang hi def link vimAugroupError vimError hi def link vimAugroupKey vimCommand - hi def link vimAuHighlight vimHighlight - hi def link vimAutoCmdOpt vimOption hi def link vimAutoCmd vimCommand hi def link vimAutoEvent Type hi def link vimAutoCmdMod Special - hi def link vimAutoSet vimCommand hi def link vimBang vimOper hi def link vimBehaveBang vimBang hi def link vimBehaveModel vimBehave @@ -943,29 +1067,37 @@ if !exists("skip_vim_syntax_inits") hi def link vim9Comment Comment hi def link vimCommentString vimString hi def link vimCommentTitle PreProc + hi def link vim9CommentTitle PreProc hi def link vimCondHL vimCommand hi def link vimConst vimCommand hi def link vimContinue Special hi def link vimContinueComment vimComment hi def link vimCtrlChar SpecialChar + hi def link vimDefComment vimComment + hi def link vimDefKey vimCommand + hi def link vimDefParam vimVar hi def link vimEcho vimCommand - hi def link vimEchoHLNone vimGroup - hi def link vimEchoHL vimCommand + hi def link vimEchohlNone vimGroup + hi def link vimEchohl vimCommand hi def link vimElseIfErr Error - hi def link vimElseif vimCondHL + hi def link vimEndfunction vimCommand + hi def link vimEnddef vimCommand hi def link vimEnvvar PreProc hi def link vimError Error hi def link vimEscape Special hi def link vimFBVar vimVar hi def link vimFgBgAttrib vimHiAttrib hi def link vimFuncEcho vimCommand - hi def link vimHiCtermul vimHiTerm - hi def link vimFold Folded hi def link vimFor vimCommand hi def link vimFTCmd vimCommand hi def link vimFTOption vimSynType + hi def link vimFuncBang vimBang + hi def link vimFuncComment vimComment hi def link vimFuncKey vimCommand hi def link vimFuncName Function + hi def link vimFuncMod Special + hi def link vimFuncParam vimVar + hi def link vimFuncParamEquals vimOper hi def link vimFuncSID Special hi def link vimFuncVar Identifier hi def link vimGroupAdd vimSynOption @@ -976,8 +1108,11 @@ if !exists("skip_vim_syntax_inits") hi def link vimHiAttrib PreProc hi def link vimHiBang vimBang hi def link vimHiBlend vimHiTerm - hi def link vimHiClear vimHighlight + hi def link vimHiClear Type + hi def link vimHiCtermColor Constant hi def link vimHiCtermFgBg vimHiTerm + hi def link vimHiCtermfont vimHiTerm + hi def link vimHiCtermul vimHiTerm hi def link vimHiCTerm vimHiTerm hi def link vimHighlight vimCommand hi def link vimHiGroup vimGroupName @@ -989,13 +1124,11 @@ if !exists("skip_vim_syntax_inits") hi def link vimHiStartStop vimHiTerm hi def link vimHiTerm Type hi def link vimHLGroup vimGroup - hi def link vimHLMod PreProc hi def link vimInsert vimString hi def link vimIskSep Delimiter - hi def link vimKeyCode vimSpecFile + hi def link vim9KeymapLineComment vimKeymapLineComment hi def link vimKeymapLineComment vimComment hi def link vimKeymapTailComment vimComment - hi def link vimKeyword Statement hi def link vimLet vimCommand hi def link vimLetHereDoc vimString hi def link vimLetHereDocStart Special @@ -1010,9 +1143,14 @@ if !exists("skip_vim_syntax_inits") hi def link vimMark Number hi def link vimMarkNumber vimNumber hi def link vimMenuBang vimBang + hi def link vimMenuClear Special hi def link vimMenuMod vimMapMod - hi def link vimMenuNameMore vimMenuName hi def link vimMenuName PreProc + hi def link vimMenu vimCommand + hi def link vimMenuNotation vimNotation + hi def link vimMenuPriority Number + hi def link vimMenuStatus Special + hi def link vimMenutranslateComment vimComment hi def link vimMtchComment vimComment hi def link vimNorm vimCommand hi def link vimNotation Special @@ -1021,7 +1159,6 @@ if !exists("skip_vim_syntax_inits") hi def link vimNumber Number hi def link vimOperError Error hi def link vimOper Operator - hi def link vimOperStar vimOper hi def link vimOption PreProc hi def link vimParenSep Delimiter hi def link vimPatSepErr vimError @@ -1040,10 +1177,10 @@ if !exists("skip_vim_syntax_inits") hi def link vimSetMod vimOption hi def link vimSetSep Statement hi def link vimSetString vimString + hi def link vim9Vim9Script vimCommand hi def link vimSpecFile Identifier hi def link vimSpecFileMod vimSpecFile hi def link vimSpecial Type - hi def link vimStatement Statement hi def link vimStringCont vimString hi def link vimString String hi def link vimStringEnd vimString @@ -1108,6 +1245,8 @@ let b:current_syntax = "vim" " Cleanup: {{{1 delc VimFolda delc VimFoldf +delc VimFoldh +delc VimFoldH delc VimFoldl delc VimFoldm delc VimFoldp @@ -1115,5 +1254,5 @@ delc VimFoldP delc VimFoldr delc VimFoldt let &cpo = s:keepcpo -unlet s:keepcpo -" vim:ts=18 fdm=marker +unlet s:keepcpo s:vim9script +" vim:ts=18 fdm=marker ft=vim diff --git a/runtime/syntax/yaml.vim b/runtime/syntax/yaml.vim index 49f7d049a7..6ec806a4cb 100644 --- a/runtime/syntax/yaml.vim +++ b/runtime/syntax/yaml.vim @@ -2,8 +2,7 @@ " Language: YAML (YAML Ain't Markup Language) 1.2 " Maintainer: Nikolai Pavlov <zyx.vim@gmail.com> " First author: Nikolai Weibull <now@bitwi.se> -" Latest Revision: 2015-03-28 -" removed duplicate yamlKeyValueDelimiter (pull #4799) +" Latest Revision: 2024-04-01 if exists('b:current_syntax') finish @@ -15,21 +14,21 @@ set cpo&vim " Choose the schema to use " TODO: Validate schema if !exists('b:yaml_schema') - if exists('g:yaml_schema') - let b:yaml_schema = g:yaml_schema - else - let b:yaml_schema = 'core' - endif + if exists('g:yaml_schema') + let b:yaml_schema = g:yaml_schema + else + let b:yaml_schema = 'core' + endif endif let s:ns_char = '\%([\n\r\uFEFF \t]\@!\p\)' let s:ns_word_char = '[[:alnum:]_\-]' let s:ns_uri_char = '\%(%\x\x\|'.s:ns_word_char.'\|[#/;?:@&=+$,.!~*''()[\]]\)' let s:ns_tag_char = '\%(%\x\x\|'.s:ns_word_char.'\|[#/;?:@&=+$.~*''()]\)' -let s:c_ns_anchor_char = '\%([\n\r\uFEFF \t,[\]{}]\@!\p\)' let s:c_indicator = '[\-?:,[\]{}#&*!|>''"%@`]' let s:c_flow_indicator = '[,[\]{}]' +let s:ns_anchor_char = substitute(s:ns_char, '\v\C[\zs', '\=s:c_flow_indicator[1:-2]', '') let s:ns_char_without_c_indicator = substitute(s:ns_char, '\v\C[\zs', '\=s:c_indicator[1:-2]', '') let s:_collection = '[^\@!\(\%(\\\.\|\[^\\\]]\)\+\)]' @@ -38,8 +37,8 @@ function s:SimplifyToAssumeAllPrintable(p) return substitute(a:p, '\V\C\\%('.s:_collection.'\\@!\\p\\)', '[^\1]', '') endfunction let s:ns_char = s:SimplifyToAssumeAllPrintable(s:ns_char) +let s:ns_anchor_char = s:SimplifyToAssumeAllPrintable(s:ns_anchor_char) let s:ns_char_without_c_indicator = s:SimplifyToAssumeAllPrintable(s:ns_char_without_c_indicator) -let s:c_ns_anchor_char = s:SimplifyToAssumeAllPrintable(s:c_ns_anchor_char) function s:SimplifyAdjacentCollections(p) return substitute(a:p, '\V\C'.s:_collection.'\\|'.s:_collection, '[\1\2]', 'g') @@ -60,9 +59,10 @@ let s:c_ns_tag_property = s:c_verbatim_tag. \ '\|'.s:c_ns_shorthand_tag. \ '\|'.s:c_non_specific_tag -let s:c_ns_anchor_name = s:c_ns_anchor_char.'\+' +let s:c_ns_anchor_name = s:ns_anchor_char.'\+' let s:c_ns_anchor_property = '&'.s:c_ns_anchor_name let s:c_ns_alias_node = '\*'.s:c_ns_anchor_name +let s:c_ns_properties = '\%(\%('.s:c_ns_tag_property.'\|'.s:c_ns_anchor_property.'\)\s\+\)\+' let s:ns_directive_name = s:ns_char.'\+' @@ -100,57 +100,71 @@ execute 'syn region yamlDirective oneline start='.string('^\ze%'.s:ns_directive_ \ 'yamlReservedDirective '. \ 'keepend' -syn match yamlTAGDirective '%TAG\s\+' contained nextgroup=yamlTagHandle -execute 'syn match yamlTagHandle contained nextgroup=yamlTagPrefix '.string(s:c_tag_handle.'\s\+') -execute 'syn match yamlTagPrefix contained nextgroup=yamlComment ' . string(s:ns_tag_prefix) +syn match yamlTAGDirective /%TAG\ze\s/ contained nextgroup=yamlTagHandle skipwhite +execute 'syn match yamlTagHandle' string(s:c_tag_handle) 'contained nextgroup=yamlTagPrefix skipwhite' +execute 'syn match yamlTagPrefix' string(s:ns_tag_prefix) 'contained nextgroup=yamlComment skipwhite' -syn match yamlYAMLDirective '%YAML\s\+' contained nextgroup=yamlYAMLVersion -syn match yamlYAMLVersion '\d\+\.\d\+' contained nextgroup=yamlComment +syn match yamlYAMLDirective /%YAML\ze\s/ contained nextgroup=yamlYAMLVersion skipwhite +syn match yamlYAMLVersion /\d\+\.\d\+/ contained nextgroup=yamlComment skipwhite execute 'syn match yamlReservedDirective contained nextgroup=yamlComment '. \string('%\%(\%(TAG\|YAML\)\s\)\@!'.s:ns_directive_name) syn region yamlFlowString matchgroup=yamlFlowStringDelimiter start='"' skip='\\"' end='"' - \ contains=yamlEscape - \ nextgroup=yamlKeyValueDelimiter + \ contains=yamlEscape contained nextgroup=yamlFlowMappingDelimiter,yamlComment skipwhite syn region yamlFlowString matchgroup=yamlFlowStringDelimiter start="'" skip="''" end="'" - \ contains=yamlSingleEscape - \ nextgroup=yamlKeyValueDelimiter + \ contains=yamlSingleEscape contained nextgroup=yamlFlowMappingDelimiter,yamlComment skipwhite syn match yamlEscape contained '\\\%([\\"abefnrtv\^0_ NLP\n]\|x\x\x\|u\x\{4}\|U\x\{8}\)' syn match yamlSingleEscape contained "''" -syn match yamlBlockScalarHeader contained '\s\+\zs[|>]\%([+-]\=[1-9]\|[1-9]\=[+-]\)\=' - syn cluster yamlConstant contains=yamlBool,yamlNull -syn cluster yamlFlow contains=yamlFlowString,yamlFlowMapping,yamlFlowCollection -syn cluster yamlFlow add=yamlFlowMappingKey,yamlFlowMappingMerge -syn cluster yamlFlow add=@yamlConstant,yamlPlainScalar,yamlFloat -syn cluster yamlFlow add=yamlTimestamp,yamlInteger,yamlMappingKeyStart -syn cluster yamlFlow add=yamlComment -syn region yamlFlowMapping matchgroup=yamlFlowIndicator start='{' end='}' contains=@yamlFlow -syn region yamlFlowCollection matchgroup=yamlFlowIndicator start='\[' end='\]' contains=@yamlFlow +syn cluster yamlFlowNode contains=yamlFlowString,yamlFlowMapping,yamlFlowCollection +syn cluster yamlFlowNode add=yamlFlowMappingKey,yamlFlowMappingKeyStart,yamlFlowMappingMerge +syn cluster yamlFlowNode add=@yamlConstant,yamlPlainScalar,yamlFloat,yamlComment +syn cluster yamlFlowNode add=yamlTimestamp,yamlInteger,yamlAlias,yamlFlowNodeProperties +syn region yamlFlowMapping matchgroup=yamlFlowIndicator start='{\@<!{{\@!' end='}' contains=@yamlFlowNode +syn region yamlFlowCollection matchgroup=yamlFlowIndicator start='\[' end='\]' contains=@yamlFlowNode execute 'syn match yamlPlainScalar /'.s:ns_plain_out.'/' execute 'syn match yamlPlainScalar contained /'.s:ns_plain_in.'/' -syn match yamlMappingKeyStart '?\ze\s' -syn match yamlMappingKeyStart '?' contained - -execute 'syn match yamlFlowMappingKey /\%#=1'.s:ns_plain_in.'\%(\s\+'.s:ns_plain_in.'\)*\ze\s*:/ contained '. - \'nextgroup=yamlKeyValueDelimiter' -syn match yamlFlowMappingMerge /<<\ze\s*:/ contained nextgroup=yamlKeyValueDelimiter - -syn match yamlBlockCollectionItemStart '^\s*\zs-\%(\s\+-\)*\s' nextgroup=yamlBlockMappingKey,yamlBlockMappingMerge -" Use the old regexp engine, the NFA engine doesn't like all the \@ items. -execute 'syn match yamlBlockMappingKey /\%#=1^\s*\zs'.s:ns_plain_out.'\%(\s\+'.s:ns_plain_out.'\)*\ze\s*:\%(\s\|$\)/ '. - \'nextgroup=yamlKeyValueDelimiter' -execute 'syn match yamlBlockMappingKey /\%#=1\s*\zs'.s:ns_plain_out.'\%(\s\+'.s:ns_plain_out.'\)*\ze\s*:\%(\s\|$\)/ contained '. - \'nextgroup=yamlKeyValueDelimiter' -syn match yamlBlockMappingMerge /^\s*\zs<<\ze:\%(\s\|$\)/ nextgroup=yamlKeyValueDelimiter -syn match yamlBlockMappingMerge /<<\ze\s*:\%(\s\|$\)/ nextgroup=yamlKeyValueDelimiter contained - -syn match yamlKeyValueDelimiter /\s*:/ contained +execute 'syn match yamlFlowMappingKey /'.s:ns_plain_in.'\%(\s\+'.s:ns_plain_in.'\)*\ze\s*:/ contained '. + \'nextgroup=yamlFlowMappingDelimiter skipwhite' +syn match yamlFlowMappingKeyStart /?/ contained nextgroup=@yamlFlowNode skipwhite +syn match yamlFlowMappingMerge /<<\ze\s*:/ contained nextgroup=yamlFlowMappingDelimiter skipwhite +syn match yamlFlowMappingDelimiter /:/ contained nextgroup=@yamlFlowNode skipwhite +execute 'syn match yamlFlowNodeProperties' string(s:c_ns_properties) + \ 'contained contains=yamlNodeTag,yamlAnchor nextgroup=@yamlFlowNode skipwhite' + +execute 'syn match yamlBlockMappingKey /^\s*\zs'.s:ns_plain_out.'\%(\s\+'.s:ns_plain_out.'\)*\ze\s*:\%(\s\|$\)/ '. + \'nextgroup=yamlBlockMappingDelimiter skipwhite' +execute 'syn match yamlBlockMappingKey /'.s:ns_plain_out.'\%(\s\+'.s:ns_plain_out.'\)*\ze\s*:\%(\s\|$\)/ contained '. + \'nextgroup=yamlBlockMappingDelimiter skipwhite' +syn match yamlBlockMappingKeyString /^\s*\zs\%("\%([^"]\|\\"\)*"\|'\%([^']\|''\)*'\)\ze\s*:\%(\s\|$\)/ + \ contains=yamlFlowString nextgroup=yamlBlockMappingDelimiter skipwhite +syn match yamlBlockMappingKeyString /\%("\%([^"]\|\\"\)*"\|'\%([^']\|''\)*'\)\ze\s*:\%(\s\|$\)/ contained + \ contains=yamlFlowString nextgroup=yamlBlockMappingDelimiter skipwhite +syn match yamlBlockMappingMerge /^\s*\zs<<\ze\s*:\%(\s\|$\)/ nextgroup=yamlBlockMappingDelimiter skipwhite +syn match yamlBlockMappingMerge /<<\ze\s*:\%(\s\|$\)/ contained nextgroup=yamlBlockMappingDelimiter skipwhite + +syn match yamlBlockMappingDelimiter /^\s*\zs:\ze\%(\s\|$\)/ nextgroup=@yamlBlockNode skipwhite +syn match yamlBlockMappingDelimiter /:\ze\%(\s\|$\)/ contained nextgroup=@yamlBlockNode skipwhite +syn match yamlBlockMappingKeyStart /^\s*\zs?\ze\%(\s\|$\)/ nextgroup=@yamlBlockNode skipwhite +syn match yamlBlockMappingKeyStart /?\ze\%(\s\|$\)/ contained nextgroup=@yamlBlockNode skipwhite + +syn match yamlBlockCollectionItemStart /^\s*\zs-\ze\%(\s\|$\)/ nextgroup=@yamlBlockNode skipwhite +syn match yamlBlockCollectionItemStart /-\ze\%(\s\|$\)/ contained nextgroup=@yamlBlockNode skipwhite + +execute 'syn match yamlBlockNodeProperties' string(s:c_ns_properties) + \ 'contained contains=yamlNodeTag,yamlAnchor nextgroup=@yamlFlowNode,yamlBlockScalarHeader skipwhite' +syn match yamlBlockScalarHeader '[|>]\%([1-9][+-]\|[+-]\?[1-9]\?\)\%(\s\+#.*\)\?$' contained + \ contains=yamlComment nextgroup=yamlBlockString skipnl +syn region yamlBlockString start=/^\z(\s\+\)/ skip=/^$/ end=/^\%(\z1\)\@!/ contained + +syn cluster yamlBlockNode contains=@yamlFlowNode,yamlBlockMappingKey,yamlBlockMappingKeyString, + \yamlBlockMappingMerge,yamlBlockMappingKeyStart,yamlBlockCollectionItemStart, + \yamlBlockNodeProperties,yamlBlockScalarHeader syn cluster yamlScalarWithSpecials contains=yamlPlainScalar,yamlBlockMappingKey,yamlFlowMappingKey @@ -164,8 +178,8 @@ elseif b:yaml_schema is# 'core' syn keyword yamlNull null Null NULL contained containedin=@yamlScalarWithSpecials syn keyword yamlBool true True TRUE false False FALSE contained containedin=@yamlScalarWithSpecials exe 'syn match yamlNull /'.s:_bounder.'\@1<!\~'.s:_bounder.'\@!/ contained containedin=@yamlScalarWithSpecials' - exe 'syn match yamlInteger /'.s:_bounder.'\@1<!\%([+-]\=\%(0\%(b[0-1_]\+\|[0-7_]\+\|x[0-9a-fA-F_]\+\)\=\|\%([1-9][0-9_]*\%(:[0-5]\=\d\)\+\)\)\|[1-9][0-9_]*\)'.s:_bounder.'\@!/ contained containedin=@yamlScalarWithSpecials' - exe 'syn match yamlFloat /'.s:_bounder.'\@1<!\%([+-]\=\%(\%(\d[0-9_]*\)\.[0-9_]*\%([eE][+-]\=\d\+\)\=\|\.[0-9_]\+\%([eE][-+]\=[0-9]\+\)\=\|\d[0-9_]*\%(:[0-5]\=\d\)\+\.[0-9_]*\|\.\%(inf\|Inf\|INF\)\)\|\%(\.\%(nan\|NaN\|NAN\)\)\)'.s:_bounder.'\@!/ contained containedin=@yamlScalarWithSpecials' + exe 'syn match yamlInteger /'.s:_bounder.'\@1<!\%([-+]\=\%(\%(0\%(b[0-1_]\+\|o\?[0-7_]\+\|x[0-9a-fA-F_]\+\)\=\|\%([1-9][0-9_]*\%(:[0-5]\=\d\)\+\)\)\|[1-9][0-9_]*\)\)'.s:_bounder.'\@!/ contained containedin=@yamlScalarWithSpecials' + exe 'syn match yamlFloat /'.s:_bounder.'\@1<!\%([-+]\=\%(\%(\d[0-9_]*\)\.[0-9_]*\%([eE][-+]\=\d\+\)\=\|\.[0-9_]\+\%([eE][-+]\=[0-9]\+\)\=\|\d[0-9_]*\%(:[0-5]\=\d\)\+\.[0-9_]*\|\.\%(inf\|Inf\|INF\)\)\|\%(\.\%(nan\|NaN\|NAN\)\)\)'.s:_bounder.'\@!/ contained containedin=@yamlScalarWithSpecials' elseif b:yaml_schema is# 'pyyaml' syn keyword yamlNull null Null NULL contained containedin=@yamlScalarWithSpecials syn keyword yamlBool true True TRUE false False FALSE yes Yes YES no No NO on On ON off Off OFF contained containedin=@yamlScalarWithSpecials @@ -208,17 +222,27 @@ hi def link yamlFlowStringDelimiter yamlString hi def link yamlEscape SpecialChar hi def link yamlSingleEscape SpecialChar -hi def link yamlBlockCollectionItemStart Label -hi def link yamlBlockMappingKey Identifier -hi def link yamlBlockMappingMerge Special - -hi def link yamlFlowMappingKey Identifier -hi def link yamlFlowMappingMerge Special - +hi def link yamlMappingKey Identifier hi def link yamlMappingKeyStart Special -hi def link yamlFlowIndicator Special +hi def link yamlMappingMerge Special hi def link yamlKeyValueDelimiter Special +hi def link yamlFlowIndicator Special +hi def link yamlFlowMappingKey yamlMappingKey +hi def link yamlFlowMappingKeyStart yamlMappingKeyStart +hi def link yamlFlowMappingMerge yamlMappingMerge +hi def link yamlFlowMappingDelimiter yamlKeyValueDelimiter + +hi def link yamlBlockMappingKey yamlMappingKey +hi def link yamlBlockMappingKeyStart yamlMappingKeyStart +hi def link yamlBlockMappingMerge yamlMappingMerge +hi def link yamlBlockMappingDelimiter yamlKeyValueDelimiter +hi def link yamlBlockCollectionItemStart Label +hi def link yamlBlockScalarHeader Special +" We do not link yamlBlockString to yamlString, because yamlPlainScalar is +" not highlighted as string neighter, and also due to historical reasons. +" hi def link yamlBlockString yamlString + hi def link yamlConstant Constant hi def link yamlNull yamlConstant @@ -234,10 +258,18 @@ hi def link yamlTimestamp Number let b:current_syntax = "yaml" -unlet s:ns_word_char s:ns_uri_char s:c_verbatim_tag s:c_named_tag_handle s:c_secondary_tag_handle s:c_primary_tag_handle s:c_tag_handle s:ns_tag_char s:c_ns_shorthand_tag s:c_non_specific_tag s:c_ns_tag_property s:c_ns_anchor_char s:c_ns_anchor_name s:c_ns_anchor_property s:c_ns_alias_node s:ns_char s:ns_directive_name s:ns_local_tag_prefix s:ns_global_tag_prefix s:ns_tag_prefix s:c_indicator s:ns_plain_safe_out s:c_flow_indicator s:ns_plain_safe_in s:ns_plain_first_in s:ns_plain_first_out s:ns_plain_char_in s:ns_plain_char_out s:ns_plain_out s:ns_plain_in s:ns_char_without_c_indicator s:ns_plain_safe_in_without_colhash s:ns_plain_safe_out_without_colhash -unlet s:_collection s:_neg_collection +unlet s:ns_char s:ns_word_char s:ns_uri_char s:ns_tag_char s:c_indicator s:c_flow_indicator + \ s:ns_anchor_char s:ns_char_without_c_indicator s:_collection s:_neg_collection + \ s:c_verbatim_tag s:c_named_tag_handle s:c_secondary_tag_handle s:c_primary_tag_handle + \ s:c_tag_handle s:c_ns_shorthand_tag s:c_non_specific_tag s:c_ns_tag_property + \ s:c_ns_anchor_name s:c_ns_anchor_property s:c_ns_alias_node s:c_ns_properties + \ s:ns_directive_name s:ns_local_tag_prefix s:ns_global_tag_prefix s:ns_tag_prefix + \ s:ns_plain_safe_out s:ns_plain_safe_in s:ns_plain_safe_in_without_colhash s:ns_plain_safe_out_without_colhash + \ s:ns_plain_first_in s:ns_plain_first_out s:ns_plain_char_in s:ns_plain_char_out s:ns_plain_out s:ns_plain_in delfunction s:SimplifyAdjacentCollections delfunction s:SimplifyToAssumeAllPrintable let &cpo = s:cpo_save unlet s:cpo_save + +" vim: set et sw=4 sts=4 ts=8: diff --git a/runtime/syntax/zathurarc.vim b/runtime/syntax/zathurarc.vim new file mode 100644 index 0000000000..5e0526d02a --- /dev/null +++ b/runtime/syntax/zathurarc.vim @@ -0,0 +1,37 @@ +" Vim syntax file +" Language: Zathurarc +" Maintainer: Wu, Zhenyu <wuzhenyu@ustc.edu> +" Documentation: https://pwmt.org/projects/zathura/documentation/ +" Upstream: https://github.com/Freed-Wu/zathurarc.vim +" Latest Revision: 2024-04-02 + +if exists('b:current_syntax') + finish +endif +let b:current_syntax = 'zathurarc' + +syntax case match +syntax iskeyword @,48-57,_,192-255,- + +syntax region zathurarcComment start="\%([ \t]*\&\([^\\]\zs\|^\)\)#" end="$" +syntax match zathurarcBracket /[<>]/ contained +syntax match zathurarcNotation `<[A-Z][a-z0-9]\+>` contains=zathurarcBracket +syntax match zathurarcNumber `\<[0-9.]\>` +syntax region zathurarcString start=`"` skip=`\\"` end=`"` +syntax region zathurarcString start=`'` skip=`\\'` end=`'` +syntax keyword zathurarcMode normal fullscreen presentation index +syntax keyword zathurarcBoolean true false +syntax keyword zathurarcCommand include map set unmap +syntax keyword zathurarcOption abort-clear-search adjust-open advance-pages-per-row completion-bg completion-fg completion-group-bg completion-group-fg completion-highlight-bg completion-highlight-fg continuous-hist-save database dbus-raise-window dbus-service default-bg default-fg exec-command filemonitor first-page-column font guioptions highlight-active-color highlight-color highlight-fg highlight-transparency incremental-search index-active-bg index-active-fg index-bg index-fg inputbar-bg inputbar-fg link-hadjust link-zoom n-completion-items notification-bg notification-error-bg notification-error-fg notification-fg notification-warning-bg notification-warning-fg page-cache-size page-padding page-right-to-left page-thumbnail-size pages-per-row recolor recolor-darkcolor recolor-keephue recolor-lightcolor recolor-reverse-video render-loading render-loading-bg render-loading-fg sandbox scroll-full-overlap scroll-hstep scroll-page-aware scroll-step scroll-wrap search-hadjust selection-clipboard selection-notification show-directories show-hidden show-recent statusbar-basename statusbar-bg statusbar-fg statusbar-h-padding statusbar-home-tilde statusbar-page-percent statusbar-v-padding synctex synctex-editor-command vertical-center window-height window-icon window-icon-document window-title-basename window-title-home-tilde window-title-page window-width zoom-center zoom-max zoom-min zoom-step + +highlight default link zathurarcComment Comment +highlight default link zathurarcNumber Number +highlight default link zathurarcMode Macro +highlight default link zathurarcString String +highlight default link zathurarcBoolean Boolean +" same as vim +highlight default link zathurarcBracket Delimiter +highlight default link zathurarcNotation Special +highlight default link zathurarcCommand Statement +highlight default link zathurarcOption PreProc +" ex: nowrap diff --git a/runtime/tutor/en/vim-01-beginner.tutor b/runtime/tutor/en/vim-01-beginner.tutor index c3decdef11..622eb7cc06 100644 --- a/runtime/tutor/en/vim-01-beginner.tutor +++ b/runtime/tutor/en/vim-01-beginner.tutor @@ -39,7 +39,7 @@ instead of text to type. Now, move to the next lesson (use the `j`{normal} key to scroll down). -## Lesson 1.1: MOVING THE CURSOR +# Lesson 1.1: MOVING THE CURSOR ** To move the cursor, press the `h`, `j`, `k`, `l` keys as indicated. ** @@ -87,7 +87,7 @@ NOTE: [:q!](:q) `<Enter>`{normal} discards any changes you made. In a few lesson 5. Move the cursor down to Lesson 1.3. -## Lesson 1.3: TEXT EDITING - DELETION +# Lesson 1.3: TEXT EDITING: DELETION ** Press `x`{normal} to delete the character under the cursor. ** @@ -251,8 +251,8 @@ The format for a delete command with the [d](d) delete operator is as follows: Thus typing `de`{normal} will delete from the cursor to the end of the word. -NOTE: Pressing just the motion while in Normal mode without an operator - will move the cursor as specified. +NOTE: Pressing just the motion while in Normal mode without an operator + will move the cursor as specified. # Lesson 2.4: USING A COUNT FOR A MOTION @@ -360,7 +360,7 @@ Fiix the errors oon thhis line and reeplace them witth undo. 7. To undo previous actions, type: `u`{normal} (lowercase u) To undo all the changes on a line, type: `U`{normal} (capital U) - To undo the undo's, type: `<C-r>`{normal} + To undo the undos, type: `<C-r>`{normal} # Lesson 3.1: THE PUT COMMAND @@ -381,7 +381,7 @@ b) Violets are blue, c) Intelligence is learned, a) Roses are red, -NOTE: You can also put the text before the cursor with `P`{normal} (capital P) +NOTE: You can also put the text before the cursor with `P`{normal} (capital P). # Lesson 3.2: THE REPLACE COMMAND @@ -508,7 +508,7 @@ NOTE: When the search reaches the end of the file it will continue at the # Lesson 4.3: MATCHING PARENTHESES SEARCH -** Type `%`{normal} to find a matching ),], or }. ** +** Type `%`{normal} to find a matching ), ], or }. ** 1. Place the cursor on any (, [, or { in the line below marked ✓. @@ -518,9 +518,9 @@ NOTE: When the search reaches the end of the file it will continue at the 4. Type `%`{normal} to move the cursor to the other matching bracket. - 5. Move the cursor to another (,),[,],{ or } and see what `%`{normal} does. + 5. Move the cursor to another (, ), [, ], {, or } and see what `%`{normal} does. -This ( is a test line with ('s, ['s ] and {'s } in it. )) +This ( is a test line with ('s, ['s, ] and {'s } in it. )) NOTE: This is very useful in debugging a program with unmatched parentheses! @@ -534,7 +534,7 @@ NOTE: This is very useful in debugging a program with unmatched parentheses! ~~~ cmd :s/thee/the/ ~~~ - NOTE: the [:s](:s) command only changed the first match of "thee" in the line. + NOTE: The [:s](:s) command only changed the first match of "thee" in the line. 3. Now type ~~~ cmd @@ -565,14 +565,14 @@ Usually thee best time to see thee flowers is in thee spring. to find every occurrence in the whole file, with a prompt whether to substitute or not. -NOTE: You can also select the lines you want to substitute first using visual-mode. +NOTE: You can also select the lines you want to substitute first using Visual mode. This will be explained more in a future lesson. # Lesson 4 SUMMARY 1. `<C-g>`{normal} displays your location and the file status. `G`{normal} moves to the end of the file. - number `G`{normal} moves to that line number. + number `G`{normal} moves to that line number. `gg`{normal} moves to the first line. 2. Typing `/`{normal} followed by a phrase searches FORWARD for the phrase. @@ -582,14 +582,14 @@ NOTE: You can also select the lines you want to substitute first using visual-mo `<C-o>`{normal} takes you back to older positions, `<C-i>`{normal} to newer positions. - 3. Typing `%`{normal} while the cursor is on a (,),[,],{, or } goes to its + 3. Typing `%`{normal} while the cursor is on a (, ), [, ], {, or } goes to its match. 4. To substitute new for the first old in a line type ~~~ cmd :s/old/new ~~~ - To substitute new for all 'old's on a line type + To substitute new for all olds on a line type ~~~ cmd :s/old/new/g ~~~ @@ -638,7 +638,7 @@ NOTE: All `:`{vim} commands are executed when you press `<Enter>`{normal}. ~~~ cmd :w TEST ~~~ - (where TEST is the filename you chose.) + (where TEST is the filename you chose.) 4. This saves the current file under the name TEST. To verify this, type `:!{unix:(ls),win:(dir)}`{vim} again to see your directory. @@ -667,7 +667,7 @@ NOTE: If you were to exit Neovim and start it again with `nvim TEST`, the file 4. Type - `:w TEST`{vim} + `w TEST`{vim} where TEST is a filename that does not exist yet. Verify that you see @@ -688,8 +688,8 @@ 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. +NOTE: After executing Step 2 you will see text from Lesson 5.3. Then move + DOWN to see this lesson again. 2. Now retrieve your TEST file using the command @@ -762,7 +762,7 @@ Open up a line above this by typing O while the cursor is on this line. This li will allow you to pract appendi text to a line. This line will allow you to practice appending text to a line. -NOTE: [a](a), [i](i) and [A](A) all go to the same Insert mode, the only +NOTE: [a](a), [i](i), and [A](A) all go to the same Insert mode, the only difference is where the characters are inserted. # Lesson 6.3: ANOTHER WAY TO REPLACE @@ -810,9 +810,9 @@ NOTE: Replace mode is like Insert mode, but every typed character a) This is the first item. b) -NOTE: you can use `y`{normal} as an operator: `yw`{normal} yanks one word. +NOTE: You can use `y`{normal} as an operator: `yw`{normal} yanks one word. -NOTE: you can use `P`{normal} to put before the cursor, rather than after. +NOTE: You can use `P`{normal} to put before the cursor, rather than after. # Lesson 6.5: SET OPTION @@ -864,7 +864,7 @@ NOTE: If you want to ignore case for just one search command, use [\c](/\c) 4. The `y`{normal} operator copies text, `p`{normal} pastes it. 5. Typing a capital `R`{normal} enters Replace mode until `<Esc>`{normal} is - pressed. + pressed. 6. Typing "[:set](:set) xxx" sets the option "xxx". Some options are: @@ -872,7 +872,7 @@ NOTE: If you want to ignore case for just one search command, use [\c](/\c) 'is' 'incsearch' show partial matches for a search phrase 'hls' 'hlsearch' highlight all matching phrases - You can either use the long or the short option name. + You can either use the long or the short option name. 7. Prepend "no" to switch an option off: ~~~ cmd @@ -921,8 +921,8 @@ To start using more features create an "init.vim" file. `:w`{vim} - You can add all your preferred settings to this "init.vim" file. - For more information type `:help init.vim`{vim}. +You can add all your preferred settings to this "init.vim" file. +For more information type `:help init.vim`{vim}. # Lesson 7.3: COMPLETION diff --git a/runtime/tutor/ja/vim-01-beginner.tutor b/runtime/tutor/ja/vim-01-beginner.tutor index 411ebc04f8..82d56bd745 100644 --- a/runtime/tutor/ja/vim-01-beginner.tutor +++ b/runtime/tutor/ja/vim-01-beginner.tutor @@ -1,32 +1,32 @@ # Neovimのチュートリアルへようこそ - -Neovim は、このチュートリアルで説明するには多すぎる程のコマンドを備えた非常に -強力なエディターです。このチュートリアルは、あなたが Neovim を万能エディターとして + Neovim は、このチュートリアルで説明するには多すぎる程のコマンドを備えた非常に強 +力なエディターです。このチュートリアルは、あなたが Neovim を万能エディターとして 使いこなせるようになるのに十分なコマンドについて説明をするようになっています。 -このチュートリアルが、体を使うことで覚えられる仕組みになっていることを、 -心しておかなければなりません。正しく学習するには実際にやってなければならない -のです。テキストをただ読むだけでは、何がが重要だったか忘れてしまうでしょう! +このチュートリアルが、体を使うことで覚えられる仕組みになっていることを、心してお +かなければなりません。正しく学習するには実際にやってなければならないのです。 +テキストをただ読むだけでは、何がが重要だったか忘れてしまうでしょう! -それでは、CapsLockキーが押されていないことを確認した後、画面にレッスン 0が -全部表示されるところまで、`j`{normal} キーを押してカーソルを移動しましょう。 +それでは、CapsLock キーが押されていないことを確認した後、画面にレッスン 0が全部 +表示されるところまで、`j`{normal} キーを押してカーソルを移動しましょう。 # レッスン 0 -NOTE: 以下の練習用コマンドにはこの文章を変更するものもありますが、それらの -変更は保存されません。失敗を恐れる必要はありません、 [<Esc>](<Esc>) キーを押した後、 - [u](u) キーを押すことで最後の操作を元に戻せる事を覚えておいてください。 +NOTE: 以下の練習用コマンドにはこの文章を変更するものもありますが、それらの変更は +保存されません。失敗を恐れる必要はありません、 [<Esc>](<Esc>) キーを押した後、 [u](u) キーを押 +すことで最後の操作を元に戻せる事を覚えておいてください。 -このチュートリアルはインタラクティブな設計になっており、 -あなたが知っておくべきことがいくつかあります。 --[このようなリンク](holy-grail )の上で [<Enter>](<Enter>) キーを押すことで、リンクされたヘルプを開くことができます。 +このチュートリアルはインタラクティブな設計になっており、あなたが知っておくべきこ +とがいくつかあります。 +-[このようなリンク](holy-grail )の上で [<Enter>](<Enter>) キーを押すことで、リンクされたヘルプを開くこと + ができます。 -もしくは、ドキュメントで検索したい単語の上で [K](K) キー(大文字)を押してみましょう。 -(注: 現在、日本語の単語には対応していません。) + (注: 日本語の単語には対応していません。) -ヘルプウィンドウは `:q`{vim} `<Enter>`{normal} で閉じることができます。 -画面の左端に ✗ が表示されている場合、その行のテキストを編集しなければなりません。 -正しいテキストに書き換えることで、左端の ✗ は ✓ に変わります。 -Neovim がいかに優れているか、おわかりいただけるでしょうか? +画面の左端に ✗ が表示されている場合、その行にあるテキストを編集しなければなりま +せん。正しいテキストに書き換えることで、左端の ✗ は ✓ に変わります。 + Neovim がいかに優れているか、おわかりいただけるでしょうか? また、次のようにコマンドを実行するよう求められることや、(後で詳しく説明します。) @@ -36,8 +36,8 @@ Neovim がいかに優れているか、おわかりいただけるでしょう ~~~ normal <Esc>0f<Space>d3wP$P ~~~ -< と > の間に囲まれたテキスト(例えば `<Enter>`{normal})は、 -そのテキストをタイプするのではなく、そのキーを押すことを表しています。 +< と > の間に囲まれたテキスト(例えば `<Enter>`{normal})は、そのテキストをタイプするのでは +なく、そのキーを押すことを表しています。 では、次のレッスンに向かいましょう。( `j`{normal} キーでスクロールダウンします。) @@ -58,11 +58,11 @@ Neovim がいかに優れているか、おわかりいただけるでしょう 3. 下へのキーを使って、レッスン1.2 に移動しましょう。 -NOTE: 何をタイプしているか判らなくなったら、`<Esc>`{normal} を押してノーマルモードにします。 +NOTE: 何を入力しているか判らなくなったら、`<Esc>`{normal} を押してノーマルモードにします。 それから入力しようとしていたコマンドを再入力しましょう。 -NOTE: カーソルキーでも移動できます。しかし hjkl に一度慣れてしまえば、 - はるかに速く移動することができるでしょう。 +NOTE: カーソルキーでも移動できます。しかし hjkl に一度慣れてしまえば、はるかに速 + く移動することができるでしょう。 # レッスン 1.2: NEOVIM の起動と終了 @@ -76,13 +76,13 @@ NOTE: カーソルキーでも移動できます。しかし hjkl に一度慣 これにより編集した内容を保存せずにエディタが終了します。 - 3. Neovim を開いて、このチュートリアルを始める為のコマンドを実行し、 - ここに戻ってきます。そのコマンドは: + 3. Neovim を開いて、このチュートリアルを始める為のコマンドを実行し、ここに戻っ + てきます。そのコマンドは: `:Tutor`{vim} `<Enter>`{normal} - 4. これまでのステップを覚え自信がついたならば、ステップ 1 から 3 までを実際に試して、 - エディタを1度終了してから再び起動しましょう。 + 4. これまでのステップを覚え自信がついたならば、ステップ 1 から 3 までを実際に試 + して、エディタを1度終了してから再び起動しましょう。 NOTE: [:q!](:q) `<Enter>`{normal} は全ての変更を破棄します。 後に変更をファイルに保存する方法についても勉強していきましょう。 @@ -115,13 +115,13 @@ NOTE: 全てのレッスンを通じて、頭で覚えようとしないでく 1. 以下の ✗ と示された最初の行にカーソルを移動しましょう。 - 2. 1行目を2行目と同じ様にするために、テキストを挿入しなければ - ならない位置の次の文字にカーソルを移動します。 + 2. 1行目を2行目と同じ様にするために、テキストを挿入しなければならない位置の次の + 文字にカーソルを移動します。 3. `i`{normal} キーを押してから、追加が必要な文字をタイプしましょう。 - 4. 間違いを修正したら `<Esc>`{normal} を押してノーマルモードに戻り、 - 正しい文になる様にステップ 2 から 4 を繰り返しましょう。 + 4. 間違いを修正したら `<Esc>`{normal} を押してノーマルモードに戻り、正しい文になる様にス + テップ 2 から 4 を繰り返しましょう。 この には 足り テキスト が 。 この 行 には 幾つか 足りない テキスト が ある。 @@ -139,8 +139,8 @@ NOTE: 全てのレッスンを通じて、頭で覚えようとしないでく 3. テキストを追加し終えたら、 `<Esc>`{normal} を押してノーマルモードに戻りましょう。 - 4. 2行目の ✗ と示された場所へ移動し、ステップ 2 から 3 を繰り返して - 文法を修正しましょう。 + 4. 2行目の ✗ と示された場所へ移動し、ステップ 2 から 3 を繰り返して文法を修正し + ましょう。 この 行 には 間違った テキスト が あり この 行 には 間違った テキスト が あります。 @@ -156,15 +156,15 @@ NOTE: 全てのレッスンを通じて、頭で覚えようとしないでく !! NOTE: 以下のあらゆるステップを行う前に、このレッスンを全部読みましょう!! - 1. レッスン 1.2 でやったように `:q!`{vim} をタイプして、このチュートリアルを終了します。 - もしくは、別のターミナルにアクセスできる場合、そこで以下の内容を行ってください。 + 1. レッスン 1.2 でやったように `:q!`{vim} を入力して、このチュートリアルを終了します。 + もしくは、別のターミナルにアクセスできる場合、そこで以下の内容を行います。 2. シェルプロンプトでこのコマンドをタイプします: ~~~ sh $ nvim tutor ~~~ - 'nvim' が Nvim エディタを起動するコマンド、'tutor' は編集したい - ファイルの名前です。変更できるファイルの名前を使いましょう。 + 'nvim' が Nvim エディタを起動するコマンド、'tutor' は編集したいファイルの名 + 前です。変更できるファイルの名前を使いましょう。 3. 前のレッスンで学んだように、テキストを挿入、削除します。 @@ -174,8 +174,8 @@ NOTE: 全てのレッスンを通じて、頭で覚えようとしないでく ~~~ コマンドを実行するには `<Enter>`{normal} を押さなければなりません。 - 5. ステップ 1 でこのチュートリアルを終了した場合は - 再度起動した後、以下の要約へ進みましょう。 + 5. ステップ 1 でこのチュートリアルを終了した場合は再度起動した後、以下の要約へ + 進みましょう。 6. 以上のステップを読んで理解した上でこれを実行しましょう。 @@ -197,8 +197,8 @@ NOTE: 全てのレッスンを通じて、頭で覚えようとしないでく `i`{normal} テキストのタイプ `<Esc>`{normal} カーソル位置に追加 `A`{normal} テキストの追加 `<Esc>`{normal} 行末に追加 -NOTE: `<Esc>`{normal} キーを押すとノーマルモードに移行します。 - その際間違ったり、入力途中のコマンドを取り消すことができます。 +NOTE: `<Esc>`{normal} キーを押すとノーマルモードに移行します。その際間違ったり、入力途中の + コマンドを取り消すことができます。 さて、続けてレッスン 2 を始めましょう。 @@ -252,12 +252,12 @@ NOTE: `<Esc>`{normal} キーを押すとノーマルモードに移行します つまり `de`{normal} とタイプすると、カーソル位置から単語の終わりまでを削除します。 -NOTE: 冒険したい人は、ノーマルモードにてオペレータなしにモーションを押してみましょう。 - カーソルが目的語一覧で示される位置に移動するはずです。 +NOTE: 冒険したい人は、ノーマルモードにてオペレータなしにモーションを押してみまし + ょう。カーソルが目的語一覧で示される位置に移動するはずです。 # レッスン 2.4: モーションにカウントを使用する -** 何回も繰り返し行いたいのモーションの前にその回数をタイプします。 ** +** 何回も繰り返し行いたいモーションの前にその回数をタイプします。 ** 1. 以下の ✓ と示された行の先頭にカーソルを移動します。 @@ -277,16 +277,16 @@ This is just a line with words you can move around in. ** オペレータとカウントをタイプすると、その操作が複数回繰り返されます。 ** -既述の削除のオペレータとモーションの組み合わせにカウントを追加することで、 -より多くの削除が行えます: +既述の削除のオペレータとモーションの組み合わせにカウントを追加することで、より多 +くの削除が行えます: d 数値 モーション 1. ✗ と示された行の最初の大文字の単語にカーソルを移動しましょう。 2. 大文字の単語2つを `d2w`{normal} とタイプして削除します。 - 3. 連続した大文字の単語を、異なるカウントを指定した1つのコマンドで削除し、 - ステップ 1 と 2 を繰り返します。 + 3. 連続した大文字の単語を、異なるカウントを指定した1つのコマンドで削除し、ステ + ップ 1 と 2 を繰り返します。 このABC DE行のFGHI JK LMN OP単語はQ RS TUV綺麗になった。 @@ -294,8 +294,8 @@ This is just a line with words you can move around in. ** 行全体を削除するには `dd`{normal} とタイプします。 ** -行全体を削除する頻度が多いので、Viのデザイナーは行の -削除を d の2回タイプという簡単なものに決めました。 +行全体を削除する頻度が多いので、Viのデザイナーは行の削除を d の2回タイプという簡 +単なものに決めました。 1. 以下の詩の2行目にカーソルを移動します。 @@ -315,9 +315,9 @@ This is just a line with words you can move around in. # Lesson 2.7: THE UNDO COMMAND -** 最後のコマンドを取り消す(Undo)には `u`{normal} を押します。`U`{normal} は行全体の取り消しです。 ** +** 最後のコマンドを取り消す(Undo)には `u`{normal} を押します。`U`{normal} は行全体の取り消しです。** - 1. 以下の ✗ と示された行にカーソルを移動し、最初の間違いにカーソルを移動しましょう。 + 1. 以下の ✗ と示された行にある、最初の間違いにカーソルを移動しましょう。 2. `x`{normal} をタイプして最初のいらない文字を削除しましょう。 @@ -329,8 +329,8 @@ This is just a line with words you can move around in. 6. `u`{normal} をタイプして直前の `U`{normal} コマンドを取り消しましょう。 - 7. ではコマンドを再実行するのに `<C-r>`{normal} (Ctrl + R)を数回 - タイプしてみましょう(取り消しの取り消し)。 + 7. ではコマンドを再実行するのに `<C-r>`{normal} (Ctrl + R)を数回タイプしてみましょう(取り + 消しの取り消し)。 このの行のの間違いを修正々し、後でそれらの修正をを取り消しまますす。 @@ -372,7 +372,7 @@ This is just a line with words you can move around in. 2. `dd`{normal} とタイプして行を削除し、Neovim のレジスタに格納しましょう。 - 3. 削除した行が本来あるべき位置の上の行である c) 行まで、カーソルを移動させましょう。 + 3. 削除した行が本来あるべき位置の上の行である c) 行にカーソルを移動しましょう。 4. `p`{normal} をタイプして格納した行をカーソルの下に戻します。 @@ -447,15 +447,15 @@ NOTE: タイプ中の間違いはバックスペースキーを使って直す # レッスン 3 要約 1. 既に削除されたテキストを再配置するには、[p](p) をタイプします。 - これは削除されたテキストをカーソルの後に挿入します(行単位で削除されたのならば、 - カーソルのある次の行に挿入されます)。 + これは削除されたテキストをカーソルの後に挿入します(行単位で削除されたのなら + ば、カーソルのある次の行に挿入されます)。 - 2. カーソルの下の文字を置き換えるには、[r](r) をタイプした後、 - それを置き換える文字をタイプします。 + 2. カーソルの下の文字を置き換えるには、[r](r) をタイプした後、それを置き換える + 文字をタイプします。 - 3. [変更オペレータ](c)ではカーソル位置から特定のモーションで指定される終端までを - 変更することが可能です。例えば `ce`{normal} ならばカーソル位置から単語の - 終わりまで、`c$`{normal} ならば行の終わりまでを変更します。 + 3. [変更オペレータ](c)ではカーソル位置から特定のモーションで指定される終端までを変更 + することが可能です。例えば `ce`{normal} ならばカーソル位置から単語の終わりまで、`c$`{normal} な + らば行の終わりまでを変更します。 4. 変更コマンドの形式は @@ -465,16 +465,16 @@ NOTE: タイプ中の間違いはバックスペースキーを使って直す # レッスン 4.1: 位置とファイルの情報 -** ファイル内での位置とファイルの状態を表示するには `<C-g>`{normal} をタイプします。 - ファイル内のある行に移動するには `G`{normal} をタイプします。 ** +** ファイル内での位置とファイルの状態を表示するには `<C-g>`{normal} をタイプします。ファイ + ル内のある行に移動するには `G`{normal} をタイプします。 ** NOTE: ステップを実行する前に、このレッスン全てに目を通しましょう!! 1. `<Ctrl>`{normal} を押したまま `g`{normal} を押しましょう。この操作を `<C-g>`{normal} と呼んでいます。 - ページの一番下にファイル名と行番号が表示されるはずです。 - ステップ 3のために行番号を覚えておきましょう。 + ページの一番下にファイル名と行番号が表示されるはずです。 ステップ 3のために + 行番号を覚えておきましょう。 -NOTE: 画面の右下隅にカーソルの位置が表示されているかもしれません。 +NOTE: 画面の右下隅にカーソルの座標が既に表示されているかもしれません。 これは ['ruler']('ruler') オプションを設定することで表示されます。 2. ファイルの最下行に移動するために [G](G) をタイプしましょう。 @@ -489,8 +489,8 @@ NOTE: 画面の右下隅にカーソルの位置が表示されているかも ** 語句を検索するには `/`{normal} と、前方検索する語句をタイプします。 ** - 1. ノーマルモードで `/`{normal} という文字をタイプします。画面一番下に `:`{normal} コマンドと - 同じ様に カーソルが現れることに気づくでしょう。 + 1. ノーマルモードで `/`{normal} という文字をタイプします。画面一番下に `:`{normal} コマンドと同じ様 + にカーソルが現れることに気づくでしょう。 2. では、'errroor' `<Enter>`{normal} とタイプしましょう。これが検索したい単語です。 @@ -499,13 +499,13 @@ NOTE: 画面の右下隅にカーソルの位置が表示されているかも 4. 逆方向に語句を検索する場合は、`/`{normal} の代わりに [?](?) コマンドを使用します。 - 5. 元の場所に戻るには `<C-o>`{normal} (`<Ctrl>`{normal} を押し続けながら `o`{normal} をタイプ)を - タイプします。さらに戻るにはこれを繰り返します。`<C-i>`{normal} は前方向です。 + 5. 元の場所に戻るには `<C-o>`{normal} (`<Ctrl>`{normal} を押し続けながら `o`{normal} をタイプ)を入力します。 + さらに戻るにはこれを繰り返します。`<C-i>`{normal} は前方向です。 "errroor" は error とスペルが違います; errroor はいわゆる error です。 -NOTE: 検索がファイルの終わりに達すると、オプション ['wrapscan']('wrapscan') が設定されている場合は、 - ファイルの先頭から検索を続行します。 +NOTE: 検索がファイルの終わりに達すると、オプション ['wrapscan']('wrapscan') が設定されている場 + 合は、ファイルの先頭から検索を続行します。 # レッスン 4.3: 対応する括弧を検索 @@ -523,7 +523,7 @@ NOTE: 検索がファイルの終わりに達すると、オプション ['wraps This ( is a test line with ('s, ['s ] and {'s } in it. )) -NOTE: この機能は括弧が一致していないプログラムをデバッグするのにとても役立ちます! +NOTE: この機能は括弧が一致していないプログラムのデバッグにとても役立ちます! # レッスン 4.4: 代替コマンド @@ -535,8 +535,8 @@ NOTE: この機能は括弧が一致していないプログラムをデバッ ~~~ cmd :s/thee/the/ ~~~ - NOTE: [:s](:s) コマンドはその行で最初に見つかったものにだけ - 行われることに気をつけましょう。 + NOTE: [:s](:s) コマンドはその行で最初に見つかったものにだけ行われることに気をつけ + ましょう。 3. さらに、次のようにタイプします ~~~ cmd @@ -578,8 +578,8 @@ NOTE: 置き換えたいテキストをビジュアルモードで選択する 検索の後の `n`{normal} は同じ方向の次の検索を、`N`{normal} は逆方向の検索をします。 `<C-o>`{normal} は場所を前に移し、`<C-i>`{normal} は場所を次に移動します。 - 3. (,),[,],{, もしくは } 上にカーソルがある状態で `%`{normal} をタイプすると - 対になる文字へ移動します。 + 3. (,),[,],{, もしくは } の上にカーソルがある状態で `%`{normal} をタイプすると対になる文 + 字へ移動します。 4. 現在行の最初の old を new に置換する。 ~~~ cmd @@ -647,7 +647,7 @@ NOTE: ここで Neovim を終了し、`nvim TEST` で起動すると、保存し ~~~ # レッスン 5.3: 選択した書き込み -** ファイルの一部を保存するには、`v`{normal} モーションと `:w ファイル名`{vim} をタイプします。 ** +** ファイルの一部を保存するには `v`{normal} モーションと `:w ファイル名`{vim} をタイプします。 ** 1. この行にカーソルを移動します。 @@ -675,8 +675,8 @@ NOTE: ここで Neovim を終了し、`nvim TEST` で起動すると、保存し それは削除しないでおいて下さい。次のレッスンで使用します。 NOTE: [v](v) を押すと、ビジュアル(Visual)選択が始まります。カーソルを動かすことで、 - 選択範囲を大きくも小さくもできます。さらに、その選択範囲に対して - オペレータを適用できます。例えば `d`{normal} はテキストを削除します。 + 選択範囲を大きくも小さくもできます。さらに、その選択範囲に対してオペレータ + を適用できます。例えば `d`{normal} はテキストを削除します。 # レッスン 5.4: ファイルの取込と合併 @@ -694,10 +694,9 @@ NOTE: ステップ 2 の実行後、レッスン 5.3 のテキストが現れま ここでいう TEST は使うファイルの名前のことです。 読み込まれたファイルは、カーソル行の下にあります。 - 3. 取り込んだファイルを確認してみましょう。カーソルを戻すと、レッスン5.3 の - オリジナルとファイルによるものの2つがあることがわかります。 + 3. 取り込んだファイルを確認してみましょう。カーソルを戻すと、レッスン5.3 のオリ + ジナルとファイルによるものの2つがあることがわかります。 - 4. 残りのチュートリアルの為に、`u`{normal} を押して最後のコマンドを取り消します。 NOTE: 外部コマンドの出力を読み込むこともできます。例えば、 @@ -711,11 +710,13 @@ NOTE: 外部コマンドの出力を読み込むこともできます。例え よく使う例: `:!{unix:(ls ),win:(dir)}`{vim} - ディレクトリ内の一覧を見る。 - `:!{unix:(rm ),win:(del)} ファイル名`{vim} - ファイルを削除する。 + `:!{unix:(rm ),win:(del)} ファイル名`{vim} - ファイルを削除する。 - 2. [:w](:w) ファイル名 ファイル名 によってファイル名というファイルがディスクに書き込まれる。 + 2. [:w](:w) ファイル名 ファイル名 によってファイル名というファイルがディスクに書 + き込まれる。 - 3. [v](v) モーション で :w ファイル名 とすると、ビジュアル選択行がファイルに保存される。 + 3. [v](v) モーション で :w ファイル名 とすると、ビジュアル選択行がファイルに保存 + される。 4. [:r](:r) ファイル名 によりファイル名というファイルがディスクより取り込まれ、 カーソル位置の下に挿入される。 @@ -731,13 +732,12 @@ NOTE: 外部コマンドの出力を読み込むこともできます。例え 2. `o`{normal} (小文字) をタイプして、カーソルの下の行を[開き](o)、挿入モードに入ります。 - 3. いくつか文字をタイプしてから、挿入モードを終了する為に `<Esc>`{normal} を - タイプします。 + 3. いくつか文字をタイプしてから、挿入モードを終了する為に `<Esc>`{normal} を入力します。 `o`{normal} をタイプするとカーソルは開いた行へ移動し挿入モードに入ります。 - 4. カーソルの上の行に挿入するには、小文字の `o`{normal} ではなく、 - 単純に[大文字の O](O)をタイプします。次の行で試してみましょう。 + 4. カーソルの上の行に挿入するには、小文字の `o`{normal} ではなく、単純に[大文字の O](O)をタイ + プします。次の行で試してみましょう。 この行の上へ挿入するには、この行へカーソルを置いて `O`{normal} をタイプします。 @@ -751,33 +751,33 @@ NOTE: 外部コマンドの出力を読み込むこともできます。例え 3. カーソルの後ろにテキストを[追加](a)するために `a`{normal} (小文字) をタイプします。 - 4. その下の行のような単語に完成させます。挿入モードを抜ける為に `<Esc>`{normal} を押します。 + 4. 下の行のように単語を完成させます。挿入モードを抜ける為に `<Esc>`{normal} を押します。 5. `e`{normal} を使って次の不完全な単語へ移動し、ステップ 3 と 4 を繰り返します。 This li will allow you to pract appendi text to a line. This line will allow you to practice appending text to a line. -NOTE: [a](a), [i](i) と [A](A) は同じ挿入モードへ移りますが、文字が挿入される位置だけが異なります。 +NOTE: [a](a), [i](i) と [A](A) は同じ挿入モードへ移りますが、文字が挿入される位置は異なります。 # レッスン 6.3: その他の置換方法 ** 1文字以上を置き換える(Replace)には大文字の `R`{normal} とタイプしましょう。 ** - 1. 以下の ✗ と示された行にカーソルを移動します。最初の "xxx" の先頭に移動します。 + 1. 以下の ✗ と示された行にある、最初の "xxx" の先頭にカーソルを移動します。 2. `R`{normal} ([大文字 R](R)) を押して、2行目の数値をタイプすることで、"xxx" が置換されます。 - 3. 置換モードを抜けるには `<Esc>`{normal} を押します。行の残りが変更されていないままに - なることに注意してください。 + 3. 置換モードを抜けるには `<Esc>`{normal} を押します。行の残りが変更されていないままにな + ることに注意してください。 4. 残った "xxx" をステップを繰り返して置換しましょう。 Adding 123 to xxx gives you xxx. Adding 123 to 456 gives you 579. -NOTE: 置換モードは挿入モードに似ていますが、全てのタイプされた文字は - 既存の文字を削除します。 +NOTE: 置換モードは挿入モードに似ていますが、全てのタイプされた文字は既存の文字を + 削除します。 # レッスン 6.4: テキストのコピーとペースト @@ -793,11 +793,11 @@ NOTE: 置換モードは挿入モードに似ていますが、全てのタイ 5. `p`{normal} を押して貼り付け([put](put))てから、次をタイプします: a second <ESC> - 6. `a`{normal} を押してから、 "second" とタイプします。その後、`<Esc>`{normal}を - 押して挿入モードを終了します。 + 6. `a`{normal} を押してから、 "second" とタイプします。その後、`<Esc>`{normal} を押して挿入モードを + 終了します。 - 7. ビジュアルモードで " item." を選択し、`y`{normal} で yank、次の行の行末まで `j$`{normal} で - 移動し、 `p`{normal} でテキストをそこに put します。 + 7. ビジュアルモードで " item." を選択し、`y`{normal} で yank、次の行の行末まで `j$`{normal} で移動 + し、 `p`{normal} でテキストをそこに put します。 a) This is the first item. b) @@ -840,8 +840,8 @@ NOTE: マッチの強調表示をやめるには次の様に入力します: ~~~ cmd :nohlsearch ~~~ -NOTE: 1つの検索コマンドだけ大文字小文字の区別をやめたいならば、 - 語句内で [\c](/\c) を使用します: /ignore\c <Enter> +NOTE: 1つの検索コマンドだけ大文字小文字の区別をやめたいならば、語句内で [\c](/\c) を使 + 用します: /ignore\c <Enter> # レッスン 6 要約 @@ -887,8 +887,8 @@ Neovim には広範にわたるオンラインヘルプシステムがありま `<C-w><C-w>`{normal} とタイプすると ヘルプウィンドウへジャンプします。 `:q`{vim} とタイプすると ヘルプウィンドウを閉じられます。 -":help" コマンドに引数を与えることにより、あらゆる題名のヘルプを見つけること -ができます。これらを試してみましょう(`<Enter>`{normal} をタイプし忘れないように): +":help" コマンドに引数を与えることにより、あらゆる題名のヘルプを見つけることがで +きます。これらを試してみましょう(`<Enter>`{normal} をタイプし忘れないように): ~~~ cmd :help w :help c_CTRL-D @@ -900,16 +900,15 @@ Neovim には広範にわたるオンラインヘルプシステムがありま ** Neovim の特徴を発揮する ** -Neovim はとても自由度の高いエディタです。あなたの好きなように -カスタマイズすることができます。より多くの機能を使いはじめるには -"init.vim" ファイルを作成します。 +Neovim はとても自由度の高いエディタです。あなたの好きなようにカスタマイズするこ +とができます。より多くの機能を使いはじめるには "init.vim" ファイルを作成します。 1. "init.vim" ファイルの編集を開始します。 `:call mkdir(stdpath('config'),'p')`{vim} `:exe 'edit' stdpath('config').'/init.vim'`{vim} - 3. 以下のようにファイルへ書き込みます。 + 2. 以下のようにしてファイルを保存します。 `:w`{vim} @@ -951,11 +950,11 @@ NOTE: 補完は多くのコマンドで動作します。特に `:help`{vim} の # おわりに -これにて Neovim のチュートリアルを終わります。エディタを簡単に、しかも充分に -使うことができるようにと、Neovim の持つ概念の要点のみを伝えようとしました。 -Neovim にはさらに多くのコマンドがあり、ここで全てを説明することはできません。 -ヘルプを沢山活用してください。オンライン上にも数多の教材や動画を -見つけることができます。ここにいくつか紹介します: +これにて Neovim のチュートリアルを終わります。エディタを簡単に、しかも充分に使う +ことができるようにと、Neovim の持つ概念の要点のみを伝えようとしました。Neovim に +はさらに多くのコマンドがあり、ここで全てを説明することはできません。ヘルプを沢山 +活用してください。オンライン上にも数多の教材や動画を見つけることができます。 +ここにいくつか紹介します: - *Learn Vim Progressively*: https://yannesposito.com/Scratch/en/blog/Learn-Vim-Progressively/ @@ -975,11 +974,12 @@ Neovim にはさらに多くのコマンドがあり、ここで全てを説明 https://vim-jp.org/vimdoc-ja/ もしあなたが本が好きならば、*Practical Vim* by Drew Neil をお勧めします。 +本書は翻訳版も出版されています。(邦題: *実践Vim 思考のスピードで編集しよう!*) (続編である *Modern Vim* には Neovimについての内容も含まれています。) -このチュートリアルは Colorado State University の Charles Smith のアイデア -を基に、Colorado School of Mines の Michael C. Pierce と Robert K. Ware の -両名によって書かれました。 E-mail: bware@mines.colorado.edu. +このチュートリアルは Colorado State University の Charles Smith のアイデアを基に +Colorado School of Mines の Michael C. Pierce と Robert K. Ware の両名によって書 +かれました。 E-mail: bware@mines.colorado.edu. Modified for Vim by Bram Moolenaar. Modified for vim-tutor-mode by Felipe Morales. diff --git a/runtime/tutor/ja/vim-01-beginner.tutor.json b/runtime/tutor/ja/vim-01-beginner.tutor.json index 5af4d5da94..6452a27db4 100644 --- a/runtime/tutor/ja/vim-01-beginner.tutor.json +++ b/runtime/tutor/ja/vim-01-beginner.tutor.json @@ -18,7 +18,7 @@ "312": -1, "313": -1, "314": -1, - "335": "この行の間違いを修正し、後でそれらの修正をを取り消します。", + "335": "この行の間違いを修正し、後でそれらの修正を取り消します。", "381": -1, "382": -1, "383": -1, |