diff options
39 files changed, 499 insertions, 298 deletions
diff --git a/runtime/autoload/dist/ft.vim b/runtime/autoload/dist/ft.vim index 0d6841a35b..69712046a5 100644 --- a/runtime/autoload/dist/ft.vim +++ b/runtime/autoload/dist/ft.vim @@ -67,13 +67,29 @@ func dist#ft#FTasmsyntax() endif endfunc -" Check if one of the first five lines contains "VB_Name". In that case it is -" probably a Visual Basic file. Otherwise it's assumed to be "alt" filetype. -func dist#ft#FTVB(alt) - if getline(1).getline(2).getline(3).getline(4).getline(5) =~? 'VB_Name\|Begin VB\.\(Form\|MDIForm\|UserControl\)' +func dist#ft#FTbas() + if exists("g:filetype_bas") + exe "setf " . g:filetype_bas + return + endif + + " most frequent FreeBASIC-specific keywords in distro files + let fb_keywords = '\c^\s*\%(extern\|var\|enum\|private\|scope\|union\|byref\|operator\|constructor\|delete\|namespace\|public\|property\|with\|destructor\|using\)\>\%(\s*[:=(]\)\@!' + let fb_preproc = '\c^\s*\%(#\a\+\|option\s\+\%(byval\|dynamic\|escape\|\%(no\)\=gosub\|nokeyword\|private\|static\)\>\)' + let fb_comment = "^\\s*/'" + " OPTION EXPLICIT, without the leading underscore, is common to many dialects + let qb64_preproc = '\c^\s*\%($\a\+\|option\s\+\%(_explicit\|_\=explicitarray\)\>\)' + + let lines = getline(1, min([line("$"), 100])) + + if match(lines, fb_preproc) > -1 || match(lines, fb_comment) > -1 || match(lines, fb_keywords) > -1 + setf freebasic + elseif match(lines, qb64_preproc) > -1 + setf qb64 + elseif match(lines, '\cVB_Name\|Begin VB\.\(Form\|MDIForm\|UserControl\)') > -1 setf vb else - exe "setf " . a:alt + setf basic endif endfunc diff --git a/runtime/doc/diff.txt b/runtime/doc/diff.txt index 6115a5d235..abe99102ee 100644 --- a/runtime/doc/diff.txt +++ b/runtime/doc/diff.txt @@ -324,8 +324,9 @@ After setting this variable, reload the syntax script: > FINDING THE DIFFERENCES *diff-diffexpr* -The 'diffexpr' option can be set to use something else than the standard -"diff" program to compare two files and find the differences. *E959* +The 'diffexpr' option can be set to use something else than the internal diff +support or the standard "diff" program to compare two files and find the +differences. When 'diffexpr' is empty, Vim uses this command to find the differences between file1 and file2: > @@ -358,7 +359,7 @@ format mentioned. These variables are set to the file names used: v:fname_in original file v:fname_new new version of the same file - v:fname_out resulting diff file + v:fname_out where to write the resulting diff file Additionally, 'diffexpr' should take care of "icase" and "iwhite" in the 'diffopt' option. 'diffexpr' cannot change the value of 'lines' and diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt index b5a7a193a5..44987f3b7b 100644 --- a/runtime/doc/editing.txt +++ b/runtime/doc/editing.txt @@ -845,7 +845,7 @@ Note: When the 'write' option is off, you are not able to write any file. *:w* *:write* *E502* *E503* *E504* *E505* - *E512* *E514* *E667* *E796* *E949* + *E512* *E514* *E667* *E949* :w[rite] [++opt] Write the whole buffer to the current file. This is the normal way to save changes to a file. It fails when the 'readonly' option is set or when there is diff --git a/runtime/doc/filetype.txt b/runtime/doc/filetype.txt index fdd9c8c12e..5486c87af9 100644 --- a/runtime/doc/filetype.txt +++ b/runtime/doc/filetype.txt @@ -131,14 +131,15 @@ shell script: "#!/bin/csh". argument was used. *filetype-overrule* -When the same extension is used for two filetypes, Vim tries to guess what -kind of file it is. This doesn't always work. A number of global variables -can be used to overrule the filetype used for certain extensions: +When the same extension is used for multiple filetypes, Vim tries to guess +what kind of file it is. This doesn't always work. A number of global +variables can be used to overrule the filetype used for certain extensions: file name variable ~ *.asa g:filetype_asa |ft-aspvbs-syntax| |ft-aspperl-syntax| *.asm g:asmsyntax |ft-asm-syntax| *.asp g:filetype_asp |ft-aspvbs-syntax| |ft-aspperl-syntax| + *.bas g:filetype_bas |ft-basic-syntax| *.fs g:filetype_fs |ft-forth-syntax| *.i g:filetype_i |ft-progress-syntax| *.inc g:filetype_inc diff --git a/runtime/doc/fold.txt b/runtime/doc/fold.txt index 80c934d13b..8bc47a3b10 100644 --- a/runtime/doc/fold.txt +++ b/runtime/doc/fold.txt @@ -501,7 +501,9 @@ Note the use of backslashes to avoid some characters to be interpreted by the :endfunction Evaluating 'foldtext' is done in the |sandbox|. The current window is set to -the window that displays the line. Errors are ignored. +the window that displays the line. + +Errors are ignored. For debugging set the 'debug' option to "throw". The default value is |foldtext()|. This returns a reasonable text for most types of folding. If you don't like it, you can specify your own 'foldtext' diff --git a/runtime/doc/intro.txt b/runtime/doc/intro.txt index 0e0156ac6b..54999fa163 100644 --- a/runtime/doc/intro.txt +++ b/runtime/doc/intro.txt @@ -322,7 +322,6 @@ notation meaning equivalent decimal value(s) ~ <Bar> vertical bar | 124 *<Bar>* <Del> delete 127 <CSI> command sequence intro ALT-Esc 155 *<CSI>* -<xCSI> CSI when typed in the GUI *<xCSI>* <EOL> end-of-line (can be <CR>, <NL> or <CR><NL>, depends on system and 'fileformat') *<EOL>* diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index 1787fb0fe6..9244638788 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -1217,7 +1217,7 @@ scripts. *:command-verbose* When 'verbose' is non-zero, listing a command will also display where it was -last defined. Example: > +last defined and any completion argument. Example: > :verbose command TOhtml < Name Args Range Complete Definition ~ @@ -1332,6 +1332,8 @@ completion can be enabled: -complete=custom,{func} custom completion, defined via {func} -complete=customlist,{func} custom completion, defined via {func} +If you specify completion while there is nothing to complete (-nargs=0, the +default) then you get error *E1208* . Note: That some completion methods might expand environment variables. diff --git a/runtime/doc/nvim_terminal_emulator.txt b/runtime/doc/nvim_terminal_emulator.txt index bfacbe19f5..f322764ecf 100644 --- a/runtime/doc/nvim_terminal_emulator.txt +++ b/runtime/doc/nvim_terminal_emulator.txt @@ -162,12 +162,11 @@ command name, for example: > This opens two windows: gdb window A terminal window in which "gdb vim" is executed. Here you - can directly interact with gdb. The buffer name is "!gdb". + can directly interact with gdb. program window A terminal window for the executed program. When "run" is used in gdb the program I/O will happen in this window, so - that it does not interfere with controlling gdb. The buffer - name is "gdb program". + that it does not interfere with controlling gdb. The current window is used to show the source code. When gdb pauses the source file location will be displayed, if possible. A sign is used to diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt index 8e5b834088..978142a1e0 100644 --- a/runtime/doc/starting.txt +++ b/runtime/doc/starting.txt @@ -188,7 +188,7 @@ argument. changes and writing. -e *-e* *-E* --E Start Nvim in Ex mode |gQ|. +-E Start Nvim in Ex mode |gQ|, see |Ex-mode|. If stdin is not a TTY: -e reads/executes stdin as Ex commands. diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index 2c5531411d..be1586ab41 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -920,12 +920,16 @@ in .../after/syntax/baan.vim (see |after-directory|). Eg: > BASIC *basic.vim* *vb.vim* *ft-basic-syntax* *ft-vb-syntax* -Both Visual Basic and "normal" basic use the extension ".bas". To detect +Both Visual Basic and "normal" BASIC use the extension ".bas". To detect which one should be used, Vim checks for the string "VB_Name" in the first five lines of the file. If it is not found, filetype will be "basic", otherwise "vb". Files with the ".frm" extension will always be seen as Visual Basic. +If the automatic detection doesn't work for you or you only edit, for +example, FreeBASIC files, use this in your startup vimrc: > + :let filetype_bas = "freebasic" + C *c.vim* *ft-c-syntax* diff --git a/runtime/filetype.vim b/runtime/filetype.vim index 73237437dc..f58658a73b 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -1,7 +1,7 @@ " Vim support file to detect file types " " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last Change: 2022 Jan 13 +" Last Change: 2022 Jan 23 " Listen very carefully, I will say this only once if exists("did_load_filetypes") @@ -189,7 +189,8 @@ au BufNewFile,BufRead *.awk,*.gawk setf awk au BufNewFile,BufRead *.mch,*.ref,*.imp setf b " BASIC or Visual Basic -au BufNewFile,BufRead *.bas call dist#ft#FTVB("basic") +au BufNewFile,BufRead *.bas call dist#ft#FTbas() +au BufNewFile,BufRead *.bi,*.bm call dist#ft#FTbas() " Visual Basic Script (close to Visual Basic) or Visual Basic .NET au BufNewFile,BufRead *.vb,*.vbs,*.dsm,*.ctl setf vb @@ -198,7 +199,7 @@ au BufNewFile,BufRead *.vb,*.vbs,*.dsm,*.ctl setf vb au BufNewFile,BufRead *.iba,*.ibi setf ibasic " FreeBasic file (similar to QBasic) -au BufNewFile,BufRead *.fb,*.bi setf freebasic +au BufNewFile,BufRead *.fb setf freebasic " Batch file for MSDOS. au BufNewFile,BufRead *.bat,*.sys setf dosbatch @@ -673,8 +674,10 @@ autocmd BufRead,BufNewFile *.gift setf gift " Git au BufNewFile,BufRead COMMIT_EDITMSG,MERGE_MSG,TAG_EDITMSG setf gitcommit au BufNewFile,BufRead NOTES_EDITMSG,EDIT_DESCRIPTION setf gitcommit -au BufNewFile,BufRead *.git/config,.gitconfig,/etc/gitconfig setf gitconfig +au BufNewFile,BufRead *.git/config,.gitconfig,*/etc/gitconfig setf gitconfig au BufNewFile,BufRead */.config/git/config setf gitconfig +au BufNewFile,BufRead *.git/config.worktree setf gitconfig +au BufNewFile,BufRead *.git/worktrees/*/config.worktree setf gitconfig au BufNewFile,BufRead .gitmodules,*.git/modules/*/config setf gitconfig if !empty($XDG_CONFIG_HOME) au BufNewFile,BufRead $XDG_CONFIG_HOME/git/config setf gitconfig @@ -709,7 +712,7 @@ au BufNewFile,BufRead gitolite.conf setf gitolite au BufNewFile,BufRead {,.}gitolite.rc,example.gitolite.rc setf perl " Gnuplot scripts -au BufNewFile,BufRead *.gpi setf gnuplot +au BufNewFile,BufRead *.gpi,.gnuplot setf gnuplot " Go (Google) au BufNewFile,BufRead *.go setf go @@ -881,6 +884,9 @@ au BufNewFile,BufRead *.jov,*.j73,*.jovial setf jovial " JSON au BufNewFile,BufRead *.json,*.jsonp,*.webmanifest setf json +" JSON5 +au BufNewFile,BufRead *.json5 setf json5 + " JSON Patch (RFC 6902) au BufNewFile,BufRead *.json-patch setf json diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index 819587bb3e..736ecc1ff7 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -220,7 +220,6 @@ local extension = { ["f08"] = "fortran", fpc = "fpcmake", fsl = "framescript", - bi = "freebasic", fb = "freebasic", fsi = "fsharp", fsx = "fsharp", @@ -231,6 +230,7 @@ local extension = { gemini = "gemtext", gift = "gift", gpi = "gnuplot", + gnuplot = "gnuplot", go = "go", gp = "gp", gs = "grads", @@ -293,6 +293,7 @@ local extension = { webmanifest = "json", ipynb = "json", ["json-patch"] = "json", + json5 = "json5", jsonc = "jsonc", jsp = "jsp", jl = "julia", @@ -738,7 +739,9 @@ local extension = { PL = function() vim.fn["dist#ft#FTpl"]() end, R = function() vim.fn["dist#ft#FTr"]() end, asm = function() vim.fn["dist#ft#FTasm"]() end, - bas = function() vim.fn["dist#ft#FTVB"]("basic") end, + bas = function() vim.fn["dist#ft#FTbas"]() end, + bi = function() vim.fn["dist#ft#FTbas"]() end, + bm = function() vim.fn["dist#ft#FTbas"]() end, bash = function() vim.fn["dist#ft#SetFileTypeSH"]("bash") end, btm = function() vim.fn["dist#ft#FTbtm"]() end, c = function() vim.fn["dist#ft#FTlpc"]() end, @@ -890,8 +893,6 @@ local filename = { ["EDIT_DESCRIPTION"] = "gitcommit", [".gitconfig"] = "gitconfig", [".gitmodules"] = "gitconfig", - ["/.config/git/config"] = "gitconfig", - ["/etc/gitconfig"] = "gitconfig", ["gitolite.conf"] = "gitolite", ["git-rebase-todo"] = "gitrebase", gkrellmrc = "gkrellmrc", @@ -1146,7 +1147,10 @@ local pattern = { [".*Eterm/.*%.cfg"] = "eterm", [".*%.git/modules/.*/config"] = "gitconfig", [".*%.git/config"] = "gitconfig", + [".*/etc/gitconfig"] = "gitconfig", [".*/%.config/git/config"] = "gitconfig", + [".*%.git/config%.worktree"] = "gitconfig", + [".*%.git/worktrees/.*/config%.worktree"] = "gitconfig", ["%.gitsendemail%.msg%......."] = "gitsendemail", ["gkrellmrc_."] = "gkrellmrc", [".*/usr/.*/gnupg/options%.skel"] = "gpg", diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim index 829e41001b..49d9389773 100644 --- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim +++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim @@ -2,7 +2,7 @@ " " Author: Bram Moolenaar " Copyright: Vim license applies, see ":help license" -" Last Change: 2022 Jan 13 +" Last Change: 2022 Jan 17 " " WORK IN PROGRESS - Only the basics work " Note: On MS-Windows you need a recent version of gdb. The one included with @@ -1344,6 +1344,7 @@ func s:HandleCursor(msg) if lnum =~ '^[0-9]*$' call s:GotoSourcewinOrCreateIt() if expand('%:p') != fnamemodify(fname, ':p') + echomsg 'different fname: "' .. expand('%:p') .. '" vs "' .. fnamemodify(fname, ':p') .. '"' augroup Termdebug " Always open a file read-only instead of showing the ATTENTION " prompt, since we are unlikely to want to edit the file. diff --git a/runtime/syntax/rc.vim b/runtime/syntax/rc.vim index 4c6856bc83..d69edd00fd 100644 --- a/runtime/syntax/rc.vim +++ b/runtime/syntax/rc.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: M$ Resource files (*.rc) " Maintainer: Christian Brabandt -" Last Change: 2015-05-29 +" Last Change: 20220116 " Repository: https://github.com/chrisbra/vim-rc-syntax " License: Vim (see :h license) " Previous Maintainer: Heiko Erhardt <Heiko.Erhardt@munich.netsurf.de> @@ -173,16 +173,17 @@ hi def link rcAttribute rcCommonAttribute hi def link rcStdId rcStatement hi def link rcStatement Statement -" Default color overrides -hi def rcLanguage term=reverse ctermbg=Red ctermfg=Yellow guibg=Red guifg=Yellow -hi def rcMainObject term=underline ctermfg=Blue guifg=Blue -hi def rcSubObject ctermfg=Green guifg=Green -hi def rcCaptionParam term=underline ctermfg=DarkGreen guifg=Green -hi def rcParam ctermfg=DarkGreen guifg=DarkGreen -hi def rcStatement ctermfg=DarkGreen guifg=DarkGreen -hi def rcCommonAttribute ctermfg=Brown guifg=Brown +hi def link rcLanguage Constant +hi def link rcCaptionParam Constant +hi def link rcCommonAttribute Constant + +hi def link rcMainObject Identifier +hi def link rcSubObject Define +hi def link rcParam Constant +hi def link rcStatement Statement +" +"hi def link rcIdentifier Identifier -"hi def link rcIdentifier Identifier let b:current_syntax = "rc" diff --git a/runtime/syntax/scala.vim b/runtime/syntax/scala.vim index 16e114778d..c08e60e55a 100644 --- a/runtime/syntax/scala.vim +++ b/runtime/syntax/scala.vim @@ -3,7 +3,7 @@ " Maintainer: Derek Wyatt " URL: https://github.com/derekwyatt/vim-scala " License: Same as Vim -" Last Change: 23 August 2021 +" Last Change: 23 January 2022 " ---------------------------------------------------------------------------- if !exists('main_syntax') @@ -43,55 +43,55 @@ syn keyword scalaKeyword class trait object extends with nextgroup=scalaInstance syn keyword scalaKeyword case nextgroup=scalaKeyword,scalaCaseFollowing skipwhite syn keyword scalaKeyword val nextgroup=scalaNameDefinition,scalaQuasiQuotes skipwhite syn keyword scalaKeyword def var nextgroup=scalaNameDefinition skipwhite -hi link scalaKeyword Keyword +hi def link scalaKeyword Keyword exe 'syn region scalaBlock start=/{/ end=/}/ contains=' . s:ContainedGroup() . ' fold' syn keyword scalaAkkaSpecialWord when goto using startWith initialize onTransition stay become unbecome -hi link scalaAkkaSpecialWord PreProc +hi def link scalaAkkaSpecialWord PreProc syn keyword scalatestSpecialWord shouldBe syn match scalatestShouldDSLA /^\s\+\zsit should/ syn match scalatestShouldDSLB /\<should\>/ -hi link scalatestSpecialWord PreProc -hi link scalatestShouldDSLA PreProc -hi link scalatestShouldDSLB PreProc +hi def link scalatestSpecialWord PreProc +hi def link scalatestShouldDSLA PreProc +hi def link scalatestShouldDSLB PreProc syn match scalaSymbol /'[_A-Za-z0-9$]\+/ -hi link scalaSymbol Number +hi def link scalaSymbol Number syn match scalaChar /'.'/ syn match scalaChar /'\\[\\"'ntbrf]'/ contains=scalaEscapedChar syn match scalaChar /'\\u[A-Fa-f0-9]\{4}'/ contains=scalaUnicodeChar syn match scalaEscapedChar /\\[\\"'ntbrf]/ syn match scalaUnicodeChar /\\u[A-Fa-f0-9]\{4}/ -hi link scalaChar Character -hi link scalaEscapedChar Special -hi link scalaUnicodeChar Special +hi def link scalaChar Character +hi def link scalaEscapedChar Special +hi def link scalaUnicodeChar Special syn match scalaOperator "||" syn match scalaOperator "&&" syn match scalaOperator "|" syn match scalaOperator "&" -hi link scalaOperator Special +hi def link scalaOperator Special syn match scalaNameDefinition /\<[_A-Za-z0-9$]\+\>/ contained nextgroup=scalaPostNameDefinition,scalaVariableDeclarationList syn match scalaNameDefinition /`[^`]\+`/ contained nextgroup=scalaPostNameDefinition syn match scalaVariableDeclarationList /\s*,\s*/ contained nextgroup=scalaNameDefinition syn match scalaPostNameDefinition /\_s*:\_s*/ contained nextgroup=scalaTypeDeclaration -hi link scalaNameDefinition Function +hi def link scalaNameDefinition Function syn match scalaInstanceDeclaration /\<[_\.A-Za-z0-9$]\+\>/ contained nextgroup=scalaInstanceHash syn match scalaInstanceDeclaration /`[^`]\+`/ contained syn match scalaInstanceHash /#/ contained nextgroup=scalaInstanceDeclaration -hi link scalaInstanceDeclaration Special -hi link scalaInstanceHash Type +hi def link scalaInstanceDeclaration Special +hi def link scalaInstanceHash Type syn match scalaUnimplemented /???/ -hi link scalaUnimplemented ERROR +hi def link scalaUnimplemented ERROR syn match scalaCapitalWord /\<[A-Z][A-Za-z0-9$]*\>/ -hi link scalaCapitalWord Special +hi def link scalaCapitalWord Special " Handle type declarations specially syn region scalaTypeStatement matchgroup=Keyword start=/\<type\_s\+\ze/ end=/$/ contains=scalaTypeTypeDeclaration,scalaSquareBrackets,scalaTypeTypeEquals,scalaTypeStatement @@ -105,18 +105,18 @@ syn match scalaTypeTypeEquals /=\ze[^>]/ contained nextgroup=scalaTypeTypePostDe syn match scalaTypeTypeExtension /)\?\_s*\zs\%(⇒\|=>\|<:\|:>\|=:=\|::\|#\)/ contained contains=scalaTypeOperator nextgroup=scalaTypeTypeDeclaration skipwhite syn match scalaTypeTypePostDeclaration /\<[_\.A-Za-z0-9$]\+\>/ contained nextgroup=scalaTypeTypePostExtension skipwhite syn match scalaTypeTypePostExtension /\%(⇒\|=>\|<:\|:>\|=:=\|::\)/ contained contains=scalaTypeOperator nextgroup=scalaTypeTypePostDeclaration skipwhite -hi link scalaTypeTypeDeclaration Type -hi link scalaTypeTypeExtension Keyword -hi link scalaTypeTypePostDeclaration Special -hi link scalaTypeTypePostExtension Keyword +hi def link scalaTypeTypeDeclaration Type +hi def link scalaTypeTypeExtension Keyword +hi def link scalaTypeTypePostDeclaration Special +hi def link scalaTypeTypePostExtension Keyword syn match scalaTypeDeclaration /(/ contained nextgroup=scalaTypeExtension contains=scalaRoundBrackets skipwhite syn match scalaTypeDeclaration /\%(⇒\|=>\)\ze/ contained nextgroup=scalaTypeDeclaration contains=scalaTypeExtension skipwhite syn match scalaTypeDeclaration /\<[_\.A-Za-z0-9$]\+\>/ contained nextgroup=scalaTypeExtension skipwhite syn match scalaTypeExtension /)\?\_s*\zs\%(⇒\|=>\|<:\|:>\|=:=\|::\|#\)/ contained contains=scalaTypeOperator nextgroup=scalaTypeDeclaration skipwhite -hi link scalaTypeDeclaration Type -hi link scalaTypeExtension Keyword -hi link scalaTypePostExtension Keyword +hi def link scalaTypeDeclaration Type +hi def link scalaTypeExtension Keyword +hi def link scalaTypePostExtension Keyword syn match scalaTypeAnnotation /\%([_a-zA-Z0-9$\s]:\_s*\)\ze[_=(\.A-Za-z0-9$]\+/ skipwhite nextgroup=scalaTypeDeclaration contains=scalaRoundBrackets syn match scalaTypeAnnotation /)\_s*:\_s*\ze[_=(\.A-Za-z0-9$]\+/ skipwhite nextgroup=scalaTypeDeclaration @@ -124,51 +124,51 @@ hi clear scalaTypeAnnotation syn match scalaCaseFollowing /\<[_\.A-Za-z0-9$]\+\>/ contained contains=scalaCapitalWord syn match scalaCaseFollowing /`[^`]\+`/ contained contains=scalaCapitalWord -hi link scalaCaseFollowing Special +hi def link scalaCaseFollowing Special syn keyword scalaKeywordModifier abstract override final lazy implicit private protected sealed null super syn keyword scalaSpecialFunction implicitly require -hi link scalaKeywordModifier Function -hi link scalaSpecialFunction Function +hi def link scalaKeywordModifier Function +hi def link scalaSpecialFunction Function syn keyword scalaSpecial this true false ne eq syn keyword scalaSpecial new nextgroup=scalaInstanceDeclaration skipwhite syn match scalaSpecial "\%(=>\|⇒\|<-\|←\|->\|→\)" syn match scalaSpecial /`[^`]\+`/ " Backtick literals -hi link scalaSpecial PreProc +hi def link scalaSpecial PreProc syn keyword scalaExternal package import -hi link scalaExternal Include +hi def link scalaExternal Include syn match scalaStringEmbeddedQuote /\\"/ contained syn region scalaString start=/"/ end=/"/ contains=scalaStringEmbeddedQuote,scalaEscapedChar,scalaUnicodeChar -hi link scalaString String -hi link scalaStringEmbeddedQuote String +hi def link scalaString String +hi def link scalaStringEmbeddedQuote String syn region scalaIString matchgroup=scalaInterpolationBrackets start=/\<[a-zA-Z][a-zA-Z0-9_]*"/ skip=/\\"/ end=/"/ contains=scalaInterpolation,scalaInterpolationB,scalaEscapedChar,scalaUnicodeChar syn region scalaTripleIString matchgroup=scalaInterpolationBrackets start=/\<[a-zA-Z][a-zA-Z0-9_]*"""/ end=/"""\ze\%([^"]\|$\)/ contains=scalaInterpolation,scalaInterpolationB,scalaEscapedChar,scalaUnicodeChar -hi link scalaIString String -hi link scalaTripleIString String +hi def link scalaIString String +hi def link scalaTripleIString String syn match scalaInterpolation /\$[a-zA-Z0-9_$]\+/ contained exe 'syn region scalaInterpolationB matchgroup=scalaInterpolationBoundary start=/\${/ end=/}/ contained contains=' . s:ContainedGroup() -hi link scalaInterpolation Function +hi def link scalaInterpolation Function hi clear scalaInterpolationB syn region scalaFString matchgroup=scalaInterpolationBrackets start=/f"/ skip=/\\"/ end=/"/ contains=scalaFInterpolation,scalaFInterpolationB,scalaEscapedChar,scalaUnicodeChar syn match scalaFInterpolation /\$[a-zA-Z0-9_$]\+\(%[-A-Za-z0-9\.]\+\)\?/ contained exe 'syn region scalaFInterpolationB matchgroup=scalaInterpolationBoundary start=/${/ end=/}\(%[-A-Za-z0-9\.]\+\)\?/ contained contains=' . s:ContainedGroup() -hi link scalaFString String -hi link scalaFInterpolation Function +hi def link scalaFString String +hi def link scalaFInterpolation Function hi clear scalaFInterpolationB syn region scalaTripleString start=/"""/ end=/"""\%([^"]\|$\)/ contains=scalaEscapedChar,scalaUnicodeChar syn region scalaTripleFString matchgroup=scalaInterpolationBrackets start=/f"""/ end=/"""\%([^"]\|$\)/ contains=scalaFInterpolation,scalaFInterpolationB,scalaEscapedChar,scalaUnicodeChar -hi link scalaTripleString String -hi link scalaTripleFString String +hi def link scalaTripleString String +hi def link scalaTripleFString String -hi link scalaInterpolationBrackets Special -hi link scalaInterpolationBoundary Function +hi def link scalaInterpolationBrackets Special +hi def link scalaInterpolationBoundary Function syn match scalaNumber /\<0[dDfFlL]\?\>/ " Just a bare 0 syn match scalaNumber /\<[1-9]\d*[dDfFlL]\?\>/ " A multi-digit number - octal numbers with leading 0's are deprecated in Scala @@ -176,16 +176,16 @@ syn match scalaNumber /\<0[xX][0-9a-fA-F]\+[dDfFlL]\?\>/ " Hex number syn match scalaNumber /\%(\<\d\+\.\d*\|\.\d\+\)\%([eE][-+]\=\d\+\)\=[fFdD]\=/ " exponential notation 1 syn match scalaNumber /\<\d\+[eE][-+]\=\d\+[fFdD]\=\>/ " exponential notation 2 syn match scalaNumber /\<\d\+\%([eE][-+]\=\d\+\)\=[fFdD]\>/ " exponential notation 3 -hi link scalaNumber Number +hi def link scalaNumber Number syn region scalaRoundBrackets start="(" end=")" skipwhite contained contains=scalaTypeDeclaration,scalaSquareBrackets,scalaRoundBrackets syn region scalaSquareBrackets matchgroup=scalaSquareBracketsBrackets start="\[" end="\]" skipwhite nextgroup=scalaTypeExtension contains=scalaTypeDeclaration,scalaSquareBrackets,scalaTypeOperator,scalaTypeAnnotationParameter syn match scalaTypeOperator /[-+=:<>]\+/ contained syn match scalaTypeAnnotationParameter /@\<[`_A-Za-z0-9$]\+\>/ contained -hi link scalaSquareBracketsBrackets Type -hi link scalaTypeOperator Keyword -hi link scalaTypeAnnotationParameter Function +hi def link scalaSquareBracketsBrackets Type +hi def link scalaTypeOperator Keyword +hi def link scalaTypeAnnotationParameter Function syn match scalaShebang "\%^#!.*" display syn region scalaMultilineComment start="/\*" end="\*/" contains=scalaMultilineComment,scalaDocLinks,scalaParameterAnnotation,scalaCommentAnnotation,scalaTodo,scalaCommentCodeBlock,@Spell keepend fold @@ -195,20 +195,20 @@ syn match scalaParamAnnotationValue /[.`_A-Za-z0-9$]\+/ contained syn region scalaDocLinks start="\[\[" end="\]\]" contained syn region scalaCommentCodeBlock matchgroup=Keyword start="{{{" end="}}}" contained syn match scalaTodo "\vTODO|FIXME|XXX" contained -hi link scalaShebang Comment -hi link scalaMultilineComment Comment -hi link scalaDocLinks Function -hi link scalaParameterAnnotation Function -hi link scalaParamAnnotationValue Keyword -hi link scalaCommentAnnotation Function -hi link scalaCommentCodeBlock String -hi link scalaTodo Todo +hi def link scalaShebang Comment +hi def link scalaMultilineComment Comment +hi def link scalaDocLinks Function +hi def link scalaParameterAnnotation Function +hi def link scalaParamAnnotationValue Keyword +hi def link scalaCommentAnnotation Function +hi def link scalaCommentCodeBlock String +hi def link scalaTodo Todo syn match scalaAnnotation /@\<[`_A-Za-z0-9$]\+\>/ -hi link scalaAnnotation PreProc +hi def link scalaAnnotation PreProc syn match scalaTrailingComment "//.*$" contains=scalaTodo,@Spell -hi link scalaTrailingComment Comment +hi def link scalaTrailingComment Comment syn match scalaAkkaFSM /goto([^)]*)\_s\+\<using\>/ contains=scalaAkkaFSMGotoUsing syn match scalaAkkaFSM /stay\_s\+using/ @@ -221,8 +221,8 @@ syn match scalaAkkaFSM /onTermination/ syn match scalaAkkaFSM /whenUnhandled/ syn match scalaAkkaFSMGotoUsing /\<using\>/ syn match scalaAkkaFSMGotoUsing /\<goto\>/ -hi link scalaAkkaFSM PreProc -hi link scalaAkkaFSMGotoUsing PreProc +hi def link scalaAkkaFSM PreProc +hi def link scalaAkkaFSMGotoUsing PreProc let b:current_syntax = 'scala' diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index 370f7fb47e..80bd88c4ee 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -115,7 +115,12 @@ static Array extmark_to_array(ExtmarkInfo extmark, bool id, bool add_dict) if (decor->hl_id) { String name = cstr_to_string((const char *)syn_id2name(decor->hl_id)); PUT(dict, "hl_group", STRING_OBJ(name)); + PUT(dict, "hl_eol", BOOLEAN_OBJ(decor->hl_eol)); } + if (decor->hl_mode) { + PUT(dict, "hl_mode", STRING_OBJ(cstr_to_string(hl_mode_str[decor->hl_mode]))); + } + if (kv_size(decor->virt_text)) { Array chunks = ARRAY_DICT_INIT; for (size_t i = 0; i < decor->virt_text.size; i++) { @@ -129,6 +134,36 @@ static Array extmark_to_array(ExtmarkInfo extmark, bool id, bool add_dict) ADD(chunks, ARRAY_OBJ(chunk)); } PUT(dict, "virt_text", ARRAY_OBJ(chunks)); + PUT(dict, "virt_text_hide", BOOLEAN_OBJ(decor->virt_text_hide)); + if (decor->virt_text_pos == kVTWinCol) { + PUT(dict, "virt_text_win_col", INTEGER_OBJ(decor->col)); + } + PUT(dict, "virt_text_pos", + STRING_OBJ(cstr_to_string(virt_text_pos_str[decor->virt_text_pos]))); + } + + if (kv_size(decor->virt_lines)) { + Array all_chunks = ARRAY_DICT_INIT; + bool virt_lines_leftcol = false; + for (size_t i = 0; i < decor->virt_lines.size; i++) { + Array chunks = ARRAY_DICT_INIT; + VirtText *vt = &decor->virt_lines.items[i].line; + virt_lines_leftcol = decor->virt_lines.items[i].left_col; + for (size_t j = 0; j < vt->size; j++) { + Array chunk = ARRAY_DICT_INIT; + VirtTextChunk *vtc = &vt->items[j]; + ADD(chunk, STRING_OBJ(cstr_to_string(vtc->text))); + if (vtc->hl_id > 0) { + ADD(chunk, + STRING_OBJ(cstr_to_string((const char *)syn_id2name(vtc->hl_id)))); + } + ADD(chunks, ARRAY_OBJ(chunk)); + } + ADD(all_chunks, ARRAY_OBJ(chunks)); + } + PUT(dict, "virt_lines", ARRAY_OBJ(all_chunks)); + PUT(dict, "virt_lines_above", BOOLEAN_OBJ(decor->virt_lines_above)); + PUT(dict, "virt_lines_leftcol", BOOLEAN_OBJ(virt_lines_leftcol)); } if (decor->hl_id || kv_size(decor->virt_text)) { diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 59db12f2c0..cc622a00dc 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -187,21 +187,23 @@ static void on_redraw_event(void **argv) /// On execution error: does not fail, but updates v:errmsg. /// /// To input sequences like <C-o> use |nvim_replace_termcodes()| (typically -/// with escape_csi=true) to replace |keycodes|, then pass the result to +/// with escape_ks=false) to replace |keycodes|, then pass the result to /// nvim_feedkeys(). /// /// Example: /// <pre> /// :let key = nvim_replace_termcodes("<C-o>", v:true, v:false, v:true) -/// :call nvim_feedkeys(key, 'n', v:true) +/// :call nvim_feedkeys(key, 'n', v:false) /// </pre> /// /// @param keys to be typed /// @param mode behavior flags, see |feedkeys()| -/// @param escape_csi If true, escape K_SPECIAL/CSI bytes in `keys` +/// @param escape_ks If true, escape K_SPECIAL bytes in `keys` +/// This should be false if you already used +/// |nvim_replace_termcodes()|, and true otherwise. /// @see feedkeys() -/// @see vim_strsave_escape_csi -void nvim_feedkeys(String keys, String mode, Boolean escape_csi) +/// @see vim_strsave_escape_ks +void nvim_feedkeys(String keys, String mode, Boolean escape_ks) FUNC_API_SINCE(1) { bool remap = true; @@ -232,10 +234,10 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_csi) } char *keys_esc; - if (escape_csi) { - // Need to escape K_SPECIAL and CSI before putting the string in the + if (escape_ks) { + // Need to escape K_SPECIAL before putting the string in the // typeahead buffer. - keys_esc = (char *)vim_strsave_escape_csi((char_u *)keys.data); + keys_esc = (char *)vim_strsave_escape_ks((char_u *)keys.data); } else { keys_esc = keys.data; } @@ -245,7 +247,7 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_csi) typebuf_was_filled = true; } - if (escape_csi) { + if (escape_ks) { xfree(keys_esc); } diff --git a/src/nvim/decoration.h b/src/nvim/decoration.h index 209e2176f2..02472d09e4 100644 --- a/src/nvim/decoration.h +++ b/src/nvim/decoration.h @@ -17,6 +17,8 @@ typedef enum { kVTRightAlign, } VirtTextPos; +EXTERN const char *const virt_text_pos_str[] INIT(= { "eol", "overlay", "win_col", "right_align" }); + typedef enum { kHlModeUnknown, kHlModeReplace, @@ -24,6 +26,8 @@ typedef enum { kHlModeBlend, } HlMode; +EXTERN const char *const hl_mode_str[] INIT(= { "", "replace", "combine", "blend" }); + typedef kvec_t(VirtTextChunk) VirtText; #define VIRTTEXT_EMPTY ((VirtText)KV_INITIAL_VALUE) diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 9efe5a27c4..a9c606ec13 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -260,7 +260,7 @@ static colnr_T Insstart_blank_vcol; // vcol for first inserted blank static bool update_Insstart_orig = true; // set Insstart_orig to Insstart static char_u *last_insert = NULL; // the text of the previous insert, - // K_SPECIAL and CSI are escaped + // K_SPECIAL is escaped static int last_insert_skip; // nr of chars in front of previous insert static int new_insert_skip; // nr of chars in front of current insert static int did_restart_edit; // "restart_edit" when calling edit() @@ -6817,7 +6817,7 @@ void free_last_insert(void) /// Add character "c" to buffer "s" /// -/// Escapes the special meaning of K_SPECIAL and CSI, handles multi-byte +/// Escapes the special meaning of K_SPECIAL, handles multi-byte /// characters. /// /// @param[in] c Character to add. @@ -6831,7 +6831,7 @@ char_u *add_char2buf(int c, char_u *s) const int len = utf_char2bytes(c, temp); for (int i = 0; i < len; i++) { c = temp[i]; - // Need to escape K_SPECIAL and CSI like in the typeahead buffer. + // Need to escape K_SPECIAL like in the typeahead buffer. if (c == K_SPECIAL) { *s++ = K_SPECIAL; *s++ = KS_SPECIAL; diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 625e0ea1d5..a4b43e598d 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -6206,7 +6206,6 @@ static void do_ucmd(exarg_T *eap) // K_SPECIAL has been put in the buffer as K_SPECIAL // KS_SPECIAL KE_FILLER, like for mappings, but // do_cmdline() doesn't handle that, so convert it back. - // Also change K_SPECIAL KS_EXTRA KE_CSI into CSI. len = ksp - p; if (len > 0) { memmove(q, p, len); @@ -8633,7 +8632,7 @@ static void ex_normal(exarg_T *eap) return; } - // vgetc() expects a CSI and K_SPECIAL to have been escaped. Don't do + // vgetc() expects K_SPECIAL to have been escaped. Don't do // this for the K_SPECIAL leading byte, otherwise special keys will not // work. { @@ -8642,8 +8641,7 @@ static void ex_normal(exarg_T *eap) // Count the number of characters to be escaped. for (p = eap->arg; *p != NUL; p++) { for (l = utfc_ptr2len(p) - 1; l > 0; l--) { - if (*++p == K_SPECIAL // trailbyte K_SPECIAL or CSI - ) { + if (*++p == K_SPECIAL) { // trailbyte K_SPECIAL len += 2; } } diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 5565e17597..ef590adb3a 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -59,25 +59,18 @@ static int curscript = 0; FileDescriptor *scriptin[NSCRIPT] = { NULL }; -/* - * These buffers are used for storing: - * - stuffed characters: A command that is translated into another command. - * - redo characters: will redo the last change. - * - recorded characters: for the "q" command. - * - * The bytes are stored like in the typeahead buffer: - * - K_SPECIAL introduces a special key (two more bytes follow). A literal - * K_SPECIAL is stored as K_SPECIAL KS_SPECIAL KE_FILLER. - * - CSI introduces a GUI termcap code (also when gui.in_use is FALSE, - * otherwise switching the GUI on would make mappings invalid). - * A literal CSI is stored as CSI KS_EXTRA KE_CSI. - * These translations are also done on multi-byte characters! - * - * Escaping CSI bytes is done by the system-specific input functions, called - * by ui_inchar(). - * Escaping K_SPECIAL is done by inchar(). - * Un-escaping is done by vgetc(). - */ +// These buffers are used for storing: +// - stuffed characters: A command that is translated into another command. +// - redo characters: will redo the last change. +// - recorded characters: for the "q" command. +// +// The bytes are stored like in the typeahead buffer: +// - K_SPECIAL introduces a special key (two more bytes follow). A literal +// K_SPECIAL is stored as K_SPECIAL KS_SPECIAL KE_FILLER. +// These translations are also done on multi-byte characters! +// +// Escaping K_SPECIAL is done by inchar(). +// Un-escaping is done by vgetc(). #define MINIMAL_SIZE 20 // minimal size for b_str @@ -173,7 +166,7 @@ void free_buff(buffheader_T *buf) } /// Return the contents of a buffer as a single string. -/// K_SPECIAL and CSI in the returned string are escaped. +/// K_SPECIAL in the returned string is escaped. /// /// @param dozero count == zero is not an error static char_u *get_buffcont(buffheader_T *buffer, int dozero) @@ -202,11 +195,9 @@ static char_u *get_buffcont(buffheader_T *buffer, int dozero) return p; } -/* - * Return the contents of the record buffer as a single string - * and clear the record buffer. - * K_SPECIAL and CSI in the returned string are escaped. - */ +/// Return the contents of the record buffer as a single string +/// and clear the record buffer. +/// K_SPECIAL in the returned string is escaped. char_u *get_recorded(void) { char_u *p; @@ -236,10 +227,8 @@ char_u *get_recorded(void) return p; } -/* - * Return the contents of the redo buffer as a single string. - * K_SPECIAL and CSI in the returned string are escaped. - */ +/// Return the contents of the redo buffer as a single string. +/// K_SPECIAL in the returned string is escaped. char_u *get_inserted(void) { return get_buffcont(&redobuff, FALSE); @@ -247,7 +236,7 @@ char_u *get_inserted(void) /// Add string after the current block of the given buffer /// -/// K_SPECIAL and CSI should have been escaped already. +/// K_SPECIAL should have been escaped already. /// /// @param[out] buf Buffer to add to. /// @param[in] s String to add. @@ -305,10 +294,8 @@ static void add_num_buff(buffheader_T *buf, long n) add_buff(buf, number, -1L); } -/* - * Add character 'c' to buffer "buf". - * Translates special keys, NUL, CSI, K_SPECIAL and multibyte characters. - */ +/// Add character 'c' to buffer "buf". +/// Translates special keys, NUL, K_SPECIAL and multibyte characters. static void add_char_buff(buffheader_T *buf, int c) { uint8_t bytes[MB_MAXBYTES + 1]; @@ -340,12 +327,10 @@ static void add_char_buff(buffheader_T *buf, int c) } } -/* - * Get one byte from the read buffers. Use readbuf1 one first, use readbuf2 - * if that one is empty. - * If advance == TRUE go to the next char. - * No translation is done K_SPECIAL and CSI are escaped. - */ +/// Get one byte from the read buffers. Use readbuf1 one first, use readbuf2 +/// if that one is empty. +/// If advance == TRUE go to the next char. +/// No translation is done K_SPECIAL is escaped. static int read_readbuffers(int advance) { int c; @@ -524,10 +509,8 @@ void restoreRedobuff(save_redo_T *save_redo) old_redobuff = save_redo->sr_old_redobuff; } -/* - * Append "s" to the redo buffer. - * K_SPECIAL and CSI should already have been escaped. - */ +/// Append "s" to the redo buffer. +/// K_SPECIAL should already have been escaped. void AppendToRedobuff(const char *s) { if (!block_redo) { @@ -536,7 +519,7 @@ void AppendToRedobuff(const char *s) } /// Append to Redo buffer literally, escaping special characters with CTRL-V. -/// K_SPECIAL and CSI are escaped as well. +/// K_SPECIAL is escaped as well. /// /// @param str String to append /// @param len Length of `str` or -1 for up to the NUL. @@ -584,10 +567,8 @@ void AppendToRedobuffLit(const char_u *str, int len) } } -/* - * Append a character to the redo buffer. - * Translates special keys, NUL, CSI, K_SPECIAL and multibyte characters. - */ +/// Append a character to the redo buffer. +/// Translates special keys, NUL, K_SPECIAL and multibyte characters. void AppendCharToRedobuff(int c) { if (!block_redo) { @@ -605,17 +586,15 @@ void AppendNumberToRedobuff(long n) } } -/* - * Append string "s" to the stuff buffer. - * CSI and K_SPECIAL must already have been escaped. - */ +/// Append string "s" to the stuff buffer. +/// K_SPECIAL must already have been escaped. void stuffReadbuff(const char *s) { add_buff(&readbuf1, s, -1L); } /// Append string "s" to the redo stuff buffer. -/// @remark CSI and K_SPECIAL must already have been escaped. +/// @remark K_SPECIAL must already have been escaped. void stuffRedoReadbuff(const char *s) { add_buff(&readbuf2, s, -1L); @@ -626,11 +605,9 @@ void stuffReadbuffLen(const char *s, long len) add_buff(&readbuf1, s, len); } -/* - * Stuff "s" into the stuff buffer, leaving special key codes unmodified and - * escaping other K_SPECIAL and CSI bytes. - * Change CR, LF and ESC into a space. - */ +/// Stuff "s" into the stuff buffer, leaving special key codes unmodified and +/// escaping other K_SPECIAL bytes. +/// Change CR, LF and ESC into a space. void stuffReadbuffSpec(const char *s) { while (*s != NUL) { @@ -648,10 +625,8 @@ void stuffReadbuffSpec(const char *s) } } -/* - * Append a character to the stuff buffer. - * Translates special keys, NUL, CSI, K_SPECIAL and multibyte characters. - */ +/// Append a character to the stuff buffer. +/// Translates special keys, NUL, K_SPECIAL and multibyte characters. void stuffcharReadbuff(int c) { add_char_buff(&readbuf1, c); @@ -665,12 +640,12 @@ void stuffnumReadbuff(long n) add_num_buff(&readbuf1, n); } -// Read a character from the redo buffer. Translates K_SPECIAL, CSI and -// multibyte characters. -// The redo buffer is left as it is. -// If init is true, prepare for redo, return FAIL if nothing to redo, OK -// otherwise. -// If old_redo is true, use old_redobuff instead of redobuff. +/// Read a character from the redo buffer. Translates K_SPECIAL and +/// multibyte characters. +/// The redo buffer is left as it is. +/// If init is true, prepare for redo, return FAIL if nothing to redo, OK +/// otherwise. +/// If old_redo is true, use old_redobuff instead of redobuff. static int read_redo(bool init, bool old_redo) { static buffblock_T *bp; @@ -724,9 +699,9 @@ static int read_redo(bool init, bool old_redo) return c; } -// Copy the rest of the redo buffer into the stuff buffer (in a slow way). -// If old_redo is true, use old_redobuff instead of redobuff. -// The escaped K_SPECIAL and CSI are copied without translation. +/// Copy the rest of the redo buffer into the stuff buffer (in a slow way). +/// If old_redo is true, use old_redobuff instead of redobuff. +/// The escaped K_SPECIAL is copied without translation. static void copy_redo(bool old_redo) { int c; @@ -998,28 +973,35 @@ int ins_typebuf(char_u *str, int noremap, int offset, bool nottyped, bool silent * Uses cmd_silent, KeyTyped and KeyNoremap to restore the flags belonging to * the char. */ -void ins_char_typebuf(int c) +void ins_char_typebuf(int c, int modifier) { - char_u buf[MB_MAXBYTES + 1]; - if (IS_SPECIAL(c)) { + char_u buf[MB_MAXBYTES + 4]; + int idx = 0; + if (modifier != 0) { buf[0] = K_SPECIAL; - buf[1] = (char_u)K_SECOND(c); - buf[2] = (char_u)K_THIRD(c); + buf[1] = KS_MODIFIER; + buf[2] = (char_u)modifier; buf[3] = NUL; + idx = 3; + } + if (IS_SPECIAL(c)) { + buf[idx] = K_SPECIAL; + buf[idx + 1] = (char_u)K_SECOND(c); + buf[idx + 2] = (char_u)K_THIRD(c); + buf[idx + 3] = NUL; } else { - buf[utf_char2bytes(c, buf)] = NUL; - char_u *p = buf; - while (*p) { - if ((uint8_t)(*p) == CSI || (uint8_t)(*p) == K_SPECIAL) { - bool is_csi = (uint8_t)(*p) == CSI; - memmove(p + 3, p + 1, STRLEN(p + 1) + 1); + char_u *p = buf + idx; + int char_len = utf_char2bytes(c, p); + // If the character contains K_SPECIAL bytes they need escaping. + for (int i = char_len; --i >= 0; p++) { + if ((uint8_t)(*p) == K_SPECIAL) { + memmove(p + 3, p + 1, (size_t)i); *p++ = K_SPECIAL; - *p++ = is_csi ? KS_EXTRA : KS_SPECIAL; - *p++ = is_csi ? KE_CSI : KE_FILLER; - } else { - p++; + *p++ = KS_SPECIAL; + *p = KE_FILLER; } } + *p = NUL; } (void)ins_typebuf(buf, KeyNoremap, 0, !KeyTyped, cmd_silent); } @@ -1427,15 +1409,13 @@ static void updatescript(int c) } } -/* - * Get the next input character. - * Can return a special key or a multi-byte character. - * Can return NUL when called recursively, use safe_vgetc() if that's not - * wanted. - * This translates escaped K_SPECIAL and CSI bytes to a K_SPECIAL or CSI byte. - * Collects the bytes of a multibyte character into the whole character. - * Returns the modifiers in the global "mod_mask". - */ +/// Get the next input character. +/// Can return a special key or a multi-byte character. +/// Can return NUL when called recursively, use safe_vgetc() if that's not +/// wanted. +/// This translates escaped K_SPECIAL bytes to a K_SPECIAL byte. +/// Collects the bytes of a multibyte character into the whole character. +/// Returns the modifiers in the global "mod_mask". int vgetc(void) { int c, c2; @@ -1461,8 +1441,9 @@ int vgetc(void) mouse_row = old_mouse_row; mouse_col = old_mouse_col; } else { - mod_mask = 0x0; + mod_mask = 0; last_recorded_len = 0; + for (;;) { // this is done twice if there are modifiers bool did_inc = false; if (mod_mask) { // no mapping after modifier has been read @@ -1572,14 +1553,9 @@ int vgetc(void) buf[i] = (char_u)vgetorpeek(true); if (buf[i] == K_SPECIAL) { // Must be a K_SPECIAL - KS_SPECIAL - KE_FILLER sequence, - // which represents a K_SPECIAL (0x80), - // or a CSI - KS_EXTRA - KE_CSI sequence, which represents - // a CSI (0x9B), - // of a K_SPECIAL - KS_EXTRA - KE_CSI, which is CSI too. - c = vgetorpeek(true); - if (vgetorpeek(true) == KE_CSI && c == KS_EXTRA) { - buf[i] = CSI; - } + // which represents a K_SPECIAL (0x80). + (void)vgetorpeek(true); // skip KS_SPECIAL + (void)vgetorpeek(true); // skip KE_FILLER } } no_mapping--; @@ -1593,8 +1569,8 @@ int vgetc(void) if (!no_mapping && KeyTyped && !(State & TERM_FOCUS) && (mod_mask == MOD_MASK_ALT || mod_mask == MOD_MASK_META)) { mod_mask = 0; - ins_char_typebuf(c); - ins_char_typebuf(ESC); + ins_char_typebuf(c, 0); + ins_char_typebuf(ESC, 0); continue; } @@ -2043,7 +2019,7 @@ void vungetc(int c) /// /// When `no_mapping` (global) is zero, checks for mappings in the current mode. /// Only returns one byte (of a multi-byte character). -/// K_SPECIAL and CSI may be escaped, need to get two more bytes then. +/// K_SPECIAL may be escaped, need to get two more bytes then. static int vgetorpeek(bool advance) { int c, c1; @@ -2573,7 +2549,7 @@ int fix_input_buffer(char_u *buf, int len) FUNC_ATTR_NONNULL_ALL { if (!using_script()) { - // Should not escape K_SPECIAL/CSI reading input from the user because vim + // Should not escape K_SPECIAL reading input from the user because vim // key codes keys are processed in input.c/input_enqueue. buf[len] = NUL; return len; @@ -2584,9 +2560,8 @@ int fix_input_buffer(char_u *buf, int len) char_u *p = buf; // Two characters are special: NUL and K_SPECIAL. - // Replace NUL by K_SPECIAL KS_ZERO KE_FILLER + // Replace NUL by K_SPECIAL KS_ZERO KE_FILLER // Replace K_SPECIAL by K_SPECIAL KS_SPECIAL KE_FILLER - // Replace CSI by K_SPECIAL KS_EXTRA KE_CSI for (i = len; --i >= 0; ++p) { if (p[0] == NUL || (p[0] == K_SPECIAL @@ -3477,10 +3452,10 @@ static void showmap(mapblock_T *mp, bool local) } else if (mp->m_str == NULL) { msg_puts_attr("<Nop>", HL_ATTR(HLF_8)); } else { - // Remove escaping of CSI, because "m_str" is in a format to be used + // Remove escaping of K_SPECIAL, because "m_str" is in a format to be used // as typeahead. char_u *s = vim_strsave(mp->m_str); - vim_unescape_csi(s); + vim_unescape_ks(s); msg_outtrans_special(s, false, 0); xfree(s); } @@ -3860,9 +3835,9 @@ bool check_abbr(int c, char_u *ptr, int col, int mincol) int match; if (strchr((const char *)mp->m_keys, K_SPECIAL) != NULL) { - // Might have CSI escaped mp->m_keys. + // Might have K_SPECIAL escaped mp->m_keys. q = vim_strsave(mp->m_keys); - vim_unescape_csi(q); + vim_unescape_ks(q); qlen = (int)STRLEN(q); } // find entries with right mode and keys @@ -3908,7 +3883,7 @@ bool check_abbr(int c, char_u *ptr, int col, int mincol) int newlen = utf_char2bytes(c, tb + j); tb[j + newlen] = NUL; // Need to escape K_SPECIAL. - char_u *escaped = vim_strsave_escape_csi(tb + j); + char_u *escaped = vim_strsave_escape_ks(tb + j); if (escaped != NULL) { newlen = (int)STRLEN(escaped); memmove(tb + j, escaped, (size_t)newlen); @@ -3961,11 +3936,11 @@ static char_u *eval_map_expr(mapblock_T *mp, int c) int save_msg_col; int save_msg_row; - /* Remove escaping of CSI, because "str" is in a format to be used as - * typeahead. */ + // Remove escaping of K_SPECIAL, because "str" is in a format to be used as + // typeahead. if (mp->m_luaref == LUA_NOREF) { expr = vim_strsave(mp->m_str); - vim_unescape_csi(expr); + vim_unescape_ks(expr); } save_cmd = save_cmdline_alloc(); @@ -4005,18 +3980,16 @@ static char_u *eval_map_expr(mapblock_T *mp, int c) if (p == NULL) { return NULL; } - // Escape CSI in the result to be able to use the string as typeahead. - res = vim_strsave_escape_csi(p); + // Escape K_SPECIAL in the result to be able to use the string as typeahead. + res = vim_strsave_escape_ks(p); xfree(p); return res; } -/* - * Copy "p" to allocated memory, escaping K_SPECIAL and CSI so that the result - * can be put in the typeahead buffer. - */ -char_u *vim_strsave_escape_csi(char_u *p) +/// Copy "p" to allocated memory, escaping K_SPECIAL so that the result +/// can be put in the typeahead buffer. +char_u *vim_strsave_escape_ks(char_u *p) { // Need a buffer to hold up to three times as much. Four in case of an // illegal utf-8 byte: @@ -4031,7 +4004,7 @@ char_u *vim_strsave_escape_csi(char_u *p) *d++ = *s++; } else { // Add character, possibly multi-byte to destination, escaping - // CSI and K_SPECIAL. Be careful, it can be an illegal byte! + // K_SPECIAL. Be careful, it can be an illegal byte! d = add_char2buf(utf_ptr2char(s), d); s += utf_ptr2len(s); } @@ -4041,11 +4014,9 @@ char_u *vim_strsave_escape_csi(char_u *p) return res; } -/* - * Remove escaping from CSI and K_SPECIAL characters. Reverse of - * vim_strsave_escape_csi(). Works in-place. - */ -void vim_unescape_csi(char_u *p) +/// Remove escaping from K_SPECIAL characters. Reverse of +/// vim_strsave_escape_ks(). Works in-place. +void vim_unescape_ks(char_u *p) { char_u *s = p, *d = p; @@ -4053,10 +4024,6 @@ void vim_unescape_csi(char_u *p) if (s[0] == K_SPECIAL && s[1] == KS_SPECIAL && s[2] == KE_FILLER) { *d++ = K_SPECIAL; s += 3; - } else if ((s[0] == K_SPECIAL || s[0] == CSI) - && s[1] == KS_EXTRA && s[2] == (int)KE_CSI) { - *d++ = CSI; - s += 3; } else { *d++ = *s++; } @@ -4299,7 +4266,7 @@ int put_escstr(FILE *fd, char_u *strstart, int what) for (; *str != NUL; str++) { // Check for a multi-byte character, which may contain escaped - // K_SPECIAL and CSI bytes. + // K_SPECIAL bytes. const char *p = mb_unescape((const char **)&str); if (p != NULL) { while (*p != NUL) { diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 40c61d01b5..31a09b3969 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -127,7 +127,7 @@ typedef off_t off_T; // When vgetc() is called, it sets mod_mask to the set of modifiers that are // held down based on the MOD_MASK_* symbols that are read first. -EXTERN int mod_mask INIT(= 0x0); // current key modifiers +EXTERN int mod_mask INIT(= 0); // current key modifiers // Cmdline_row is the row where the command line starts, just below the diff --git a/src/nvim/input.c b/src/nvim/input.c index 2f7c5c2c16..5fa9b8b343 100644 --- a/src/nvim/input.c +++ b/src/nvim/input.c @@ -105,7 +105,7 @@ int get_keystroke(MultiQueue *events) // terminal code to complete. n = os_inchar(buf + len, maxlen, len == 0 ? -1L : 100L, 0, events); if (n > 0) { - // Replace zero and CSI by a special key code. + // Replace zero and K_SPECIAL by a special key code. n = fix_input_buffer(buf + len, n); len += n; waited = 0; diff --git a/src/nvim/keymap.c b/src/nvim/keymap.c index abf016b832..32f2158d7b 100644 --- a/src/nvim/keymap.c +++ b/src/nvim/keymap.c @@ -158,7 +158,6 @@ static const struct key_name_entry { { ESC, "Esc" }, { ESC, "Escape" }, // Alternative name { CSI, "CSI" }, - { K_CSI, "xCSI" }, { '|', "Bar" }, { '\\', "Bslash" }, { K_DEL, "Del" }, @@ -964,7 +963,6 @@ char_u *replace_termcodes(const char_u *from, const size_t from_len, char_u **bu for (i = utfc_ptr2len_len(src, (int)(end - src) + 1); i > 0; i--) { // If the character is K_SPECIAL, replace it with K_SPECIAL // KS_SPECIAL KE_FILLER. - // If compiled with the GUI replace CSI with K_CSI. if (*src == K_SPECIAL) { result[dlen++] = K_SPECIAL; result[dlen++] = KS_SPECIAL; diff --git a/src/nvim/keymap.h b/src/nvim/keymap.h index 5a74d1dc00..42cae0c35e 100644 --- a/src/nvim/keymap.h +++ b/src/nvim/keymap.h @@ -220,7 +220,7 @@ enum key_extra { KE_KINS = 79, // keypad Insert key KE_KDEL = 80, // keypad Delete key - KE_CSI = 81, // CSI typed directly + // KE_CSI = 81, // Nvim doesn't need escaping CSI KE_SNR = 82, // <SNR> KE_PLUG = 83, // <Plug> KE_CMDWIN = 84, // open command-line window from Command-line Mode @@ -435,7 +435,6 @@ enum key_extra { #define K_MOUSELEFT TERMCAP2KEY(KS_EXTRA, KE_MOUSELEFT) #define K_MOUSERIGHT TERMCAP2KEY(KS_EXTRA, KE_MOUSERIGHT) -#define K_CSI TERMCAP2KEY(KS_EXTRA, KE_CSI) #define K_SNR TERMCAP2KEY(KS_EXTRA, KE_SNR) #define K_PLUG TERMCAP2KEY(KS_EXTRA, KE_PLUG) #define K_CMDWIN TERMCAP2KEY(KS_EXTRA, KE_CMDWIN) diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c index 5eb209a6f6..1d1cd5e271 100644 --- a/src/nvim/mbyte.c +++ b/src/nvim/mbyte.c @@ -2089,8 +2089,7 @@ const char *mb_unescape(const char **const pp) size_t buf_idx = 0; uint8_t *str = (uint8_t *)(*pp); - // Must translate K_SPECIAL KS_SPECIAL KE_FILLER to K_SPECIAL and CSI - // KS_EXTRA KE_CSI to CSI. + // Must translate K_SPECIAL KS_SPECIAL KE_FILLER to K_SPECIAL. // Maximum length of a utf-8 character is 4 bytes. for (size_t str_idx = 0; str[str_idx] != NUL && buf_idx < 4; str_idx++) { if (str[str_idx] == K_SPECIAL @@ -2098,11 +2097,6 @@ const char *mb_unescape(const char **const pp) && str[str_idx + 2] == KE_FILLER) { buf[buf_idx++] = (char)K_SPECIAL; str_idx += 2; - } else if ((str[str_idx] == K_SPECIAL) - && str[str_idx + 1] == KS_EXTRA - && str[str_idx + 2] == KE_CSI) { - buf[buf_idx++] = (char)CSI; - str_idx += 2; } else if (str[str_idx] == K_SPECIAL) { break; // A special key can't be a multibyte char. } else { diff --git a/src/nvim/message.c b/src/nvim/message.c index 39b023132e..17ccef37f1 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -1215,7 +1215,7 @@ void wait_return(int redraw) } else if (vim_strchr((char_u *)"\r\n ", c) == NULL && c != Ctrl_C) { // Put the character back in the typeahead buffer. Don't use the // stuff buffer, because lmaps wouldn't work. - ins_char_typebuf(c); + ins_char_typebuf(c, mod_mask); do_redraw = true; // need a redraw even though there is // typeahead } @@ -3497,7 +3497,7 @@ int do_dialog(int type, char_u *title, char_u *message, char_u *buttons, int dfl } if (c == ':' && ex_cmd) { retval = dfltbutton; - ins_char_typebuf(':'); + ins_char_typebuf(':', 0); break; } diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 2b5b47c0b3..c3b7e81d17 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -1010,7 +1010,7 @@ static int normal_execute(VimState *state, int key) // restart automatically. // Insert the typed character in the typeahead buffer, so that it can // be mapped in Insert mode. Required for ":lmap" to work. - ins_char_typebuf(s->c); + ins_char_typebuf(s->c, mod_mask); if (restart_edit != 0) { s->c = 'd'; } else { diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 1a12cb636a..2bc92ce295 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -922,8 +922,8 @@ int do_record(int c) // The recorded text contents. p = get_recorded(); if (p != NULL) { - // Remove escaping for CSI and K_SPECIAL in multi-byte chars. - vim_unescape_csi(p); + // Remove escaping for K_SPECIAL in multi-byte chars. + vim_unescape_ks(p); (void)tv_dict_add_str(dict, S_LEN("regcontents"), (const char *)p); } @@ -933,7 +933,7 @@ int do_record(int c) buf[1] = NUL; (void)tv_dict_add_str(dict, S_LEN("regname"), buf); - // Get the recorded key hits. K_SPECIAL and CSI will be escaped, this + // Get the recorded key hits. K_SPECIAL will be escaped, this // needs to be removed again to put it in a register. exec_reg then // adds the escaping back later. apply_autocmds(EVENT_RECORDINGLEAVE, NULL, NULL, false, curbuf); @@ -1099,7 +1099,7 @@ int do_execreg(int regname, int colon, int addcr, int silent) return FAIL; } } - escaped = vim_strsave_escape_csi(reg->y_array[i]); + escaped = vim_strsave_escape_ks(reg->y_array[i]); retval = ins_typebuf(escaped, remap, 0, true, silent); xfree(escaped); if (retval == FAIL) { @@ -1141,7 +1141,7 @@ static void put_reedit_in_typebuf(int silent) /// Insert register contents "s" into the typeahead buffer, so that it will be /// executed again. /// -/// @param esc when true then it is to be taken literally: Escape CSI +/// @param esc when true then it is to be taken literally: Escape K_SPECIAL /// characters and no remapping. /// @param colon add ':' before the line static int put_in_typebuf(char_u *s, bool esc, bool colon, int silent) @@ -1156,7 +1156,7 @@ static int put_in_typebuf(char_u *s, bool esc, bool colon, int silent) char_u *p; if (esc) { - p = vim_strsave_escape_csi(s); + p = vim_strsave_escape_ks(s); } else { p = s; } diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c index 3790eba212..54cfaee80a 100644 --- a/src/nvim/os/input.c +++ b/src/nvim/os/input.c @@ -234,9 +234,9 @@ size_t input_enqueue(String keys) while (rbuffer_space(input_buffer) >= 19 && ptr < end) { // A "<x>" form occupies at least 1 characters, and produces up // to 19 characters (1 + 5 * 3 for the char and 3 for a modifier). - // In the case of K_SPECIAL(0x80) or CSI(0x9B), 3 bytes are escaped and - // needed, but since the keys are UTF-8, so the first byte cannot be - // K_SPECIAL(0x80) or CSI(0x9B). + // In the case of K_SPECIAL(0x80), 3 bytes are escaped and needed, + // but since the keys are UTF-8, so the first byte cannot be + // K_SPECIAL(0x80). uint8_t buf[19] = { 0 }; unsigned int new_size = trans_special((const uint8_t **)&ptr, (size_t)(end - ptr), buf, true, @@ -263,12 +263,8 @@ size_t input_enqueue(String keys) continue; } - // copy the character, escaping CSI and K_SPECIAL - if ((uint8_t)*ptr == CSI) { - rbuffer_write(input_buffer, (char *)&(uint8_t){ K_SPECIAL }, 1); - rbuffer_write(input_buffer, (char *)&(uint8_t){ KS_EXTRA }, 1); - rbuffer_write(input_buffer, (char *)&(uint8_t){ KE_CSI }, 1); - } else if ((uint8_t)*ptr == K_SPECIAL) { + // copy the character, escaping K_SPECIAL + if ((uint8_t)(*ptr) == K_SPECIAL) { rbuffer_write(input_buffer, (char *)&(uint8_t){ K_SPECIAL }, 1); rbuffer_write(input_buffer, (char *)&(uint8_t){ KS_SPECIAL }, 1); rbuffer_write(input_buffer, (char *)&(uint8_t){ KE_FILLER }, 1); diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index 70a5c7aa08..a2d855244c 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -1299,7 +1299,7 @@ static bool send_mouse_event(Terminal *term, int c) } end: - ins_char_typebuf(c); + ins_char_typebuf(c, mod_mask); return true; } diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index 7db05e34d5..8930d62fd3 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -76,6 +76,7 @@ let s:filename_checks = { \ 'ave': ['file.ave'], \ 'awk': ['file.awk', 'file.gawk'], \ 'b': ['file.mch', 'file.ref', 'file.imp'], + \ 'basic': ['file.bas', 'file.bi', 'file.bm'], \ 'bzl': ['file.bazel', 'file.bzl', 'WORKSPACE'], \ 'bc': ['file.bc'], \ 'bdf': ['file.bdf'], @@ -186,7 +187,7 @@ let s:filename_checks = { \ 'fortran': ['file.f', 'file.for', 'file.fortran', 'file.fpp', 'file.ftn', 'file.f77', 'file.f90', 'file.f95', 'file.f03', 'file.f08'], \ 'fpcmake': ['file.fpc'], \ 'framescript': ['file.fsl'], - \ 'freebasic': ['file.fb', 'file.bi'], + \ 'freebasic': ['file.fb'], \ 'fsharp': ['file.fs', 'file.fsi', 'file.fsx'], \ 'fstab': ['fstab', 'mtab'], \ 'fvwm': ['/.fvwm/file', 'any/.fvwm/file'], @@ -196,13 +197,13 @@ let s:filename_checks = { \ 'gemtext': ['file.gmi', 'file.gemini'], \ 'gift': ['file.gift'], \ 'gitcommit': ['COMMIT_EDITMSG', 'MERGE_MSG', 'TAG_EDITMSG', 'NOTES_EDITMSG', 'EDIT_DESCRIPTION'], - \ 'gitconfig': ['file.git/config', '.gitconfig', '.gitmodules', 'file.git/modules//config', '/.config/git/config', '/etc/gitconfig', '/etc/gitconfig.d/file', '/.gitconfig.d/file', 'any/.config/git/config', 'any/.gitconfig.d/file', 'some.git/config', 'some.git/modules/any/config'], + \ 'gitconfig': ['file.git/config', 'file.git/config.worktree', 'file.git/worktrees/x/config.worktree', '.gitconfig', '.gitmodules', 'file.git/modules//config', '/.config/git/config', '/etc/gitconfig', '/usr/local/etc/gitconfig', '/etc/gitconfig.d/file', '/.gitconfig.d/file', 'any/.config/git/config', 'any/.gitconfig.d/file', 'some.git/config', 'some.git/modules/any/config'], \ 'gitolite': ['gitolite.conf', '/gitolite-admin/conf/file', 'any/gitolite-admin/conf/file'], \ 'gitrebase': ['git-rebase-todo'], \ 'gitsendemail': ['.gitsendemail.msg.xxxxxx'], \ 'gkrellmrc': ['gkrellmrc', 'gkrellmrc_x'], \ 'gnash': ['gnashrc', '.gnashrc', 'gnashpluginrc', '.gnashpluginrc'], - \ 'gnuplot': ['file.gpi'], + \ 'gnuplot': ['file.gpi', '.gnuplot'], \ 'go': ['file.go'], \ 'gomod': ['go.mod'], \ 'gp': ['file.gp', '.gprc'], @@ -264,6 +265,7 @@ let s:filename_checks = { \ 'jovial': ['file.jov', 'file.j73', 'file.jovial'], \ 'jproperties': ['file.properties', 'file.properties_xx', 'file.properties_xx_xx', 'some.properties_xx_xx_file'], \ 'json': ['file.json', 'file.jsonp', 'file.json-patch', 'file.webmanifest', 'Pipfile.lock', 'file.ipynb', '.babelrc', '.eslintrc', '.prettierrc', '.firebaserc', 'file.slnf'], + \ 'json5': ['file.json5'], \ 'jsonc': ['file.jsonc'], \ 'jsp': ['file.jsp'], \ 'julia': ['file.jl'], @@ -1146,4 +1148,65 @@ func Test_foam_file() filetype off endfunc +func Test_bas_file() + filetype on + + call writefile(['looks like BASIC'], 'Xfile.bas') + split Xfile.bas + call assert_equal('basic', &filetype) + bwipe! + + " Test dist#ft#FTbas() + + let g:filetype_bas = 'freebasic' + split Xfile.bas + call assert_equal('freebasic', &filetype) + bwipe! + unlet g:filetype_bas + + " FreeBASIC + + call writefile(["/' FreeBASIC multiline comment '/"], 'Xfile.bas') + split Xfile.bas + call assert_equal('freebasic', &filetype) + bwipe! + + call writefile(['#define TESTING'], 'Xfile.bas') + split Xfile.bas + call assert_equal('freebasic', &filetype) + bwipe! + + call writefile(['option byval'], 'Xfile.bas') + split Xfile.bas + call assert_equal('freebasic', &filetype) + bwipe! + + call writefile(['extern "C"'], 'Xfile.bas') + split Xfile.bas + call assert_equal('freebasic', &filetype) + bwipe! + + " QB64 + + call writefile(['$LET TESTING = 1'], 'Xfile.bas') + split Xfile.bas + call assert_equal('qb64', &filetype) + bwipe! + + call writefile(['OPTION _EXPLICIT'], 'Xfile.bas') + split Xfile.bas + call assert_equal('qb64', &filetype) + bwipe! + + " Visual Basic + + call writefile(['Attribute VB_NAME = "Testing"'], 'Xfile.bas') + split Xfile.bas + call assert_equal('vb', &filetype) + bwipe! + + call delete('Xfile.bas') + filetype off +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/functional/api/extmark_spec.lua b/test/functional/api/extmark_spec.lua index c027cfb5eb..3f79515949 100644 --- a/test/functional/api/extmark_spec.lua +++ b/test/functional/api/extmark_spec.lua @@ -1448,6 +1448,49 @@ describe('API/extmarks', function() }) eq({ {1, 0, 0, { end_col = 0, end_row = 1 }} }, get_extmarks(ns, 0, -1, {details=true})) end) + + it('can get details', function() + set_extmark(ns, marks[1], 0, 0, { + end_col = 0, + end_row = 1, + priority = 0, + hl_eol = true, + hl_mode = "blend", + hl_group = "String", + virt_text = { { "text", "Statement" } }, + virt_text_pos = "right_align", + virt_text_hide = true, + virt_lines = { { { "lines", "Statement" } }}, + virt_lines_above = true, + virt_lines_leftcol = true, + }) + set_extmark(ns, marks[2], 0, 0, { + priority = 0, + virt_text = { { "text", "Statement" } }, + virt_text_win_col = 1, + }) + eq({0, 0, { + end_col = 0, + end_row = 1, + priority = 0, + hl_eol = true, + hl_mode = "blend", + hl_group = "String", + virt_text = { { "text", "Statement" } }, + virt_text_pos = "right_align", + virt_text_hide = true, + virt_lines = { { { "lines", "Statement" } }}, + virt_lines_above = true, + virt_lines_leftcol = true, + } }, get_extmark_by_id(ns, marks[1], { details = true })) + eq({0, 0, { + priority = 0, + virt_text = { { "text", "Statement" } }, + virt_text_hide = false, + virt_text_pos = "win_col", + virt_text_win_col = 1, + } }, get_extmark_by_id(ns, marks[2], { details = true })) + end) end) describe('Extmarks buffer api with many marks', function() diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 22201e21a2..201ba45803 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1367,18 +1367,18 @@ describe('API', function() end) describe('nvim_feedkeys', function() - it('CSI escaping', function() + it('K_SPECIAL escaping', function() local function on_setup() -- notice the special char(…) \xe2\80\xa6 nvim('feedkeys', ':let x1="…"\n', '', true) -- Both nvim_replace_termcodes and nvim_feedkeys escape \x80 local inp = helpers.nvim('replace_termcodes', ':let x2="…"<CR>', true, true, true) - nvim('feedkeys', inp, '', true) -- escape_csi=true + nvim('feedkeys', inp, '', true) -- escape_ks=true - -- nvim_feedkeys with CSI escaping disabled + -- nvim_feedkeys with K_SPECIAL escaping disabled inp = helpers.nvim('replace_termcodes', ':let x3="…"<CR>', true, true, true) - nvim('feedkeys', inp, '', false) -- escape_csi=false + nvim('feedkeys', inp, '', false) -- escape_ks=false helpers.stop() end diff --git a/test/functional/editor/meta_key_spec.lua b/test/functional/editor/meta_key_spec.lua index 2280f5bb24..f811b8ae8d 100644 --- a/test/functional/editor/meta_key_spec.lua +++ b/test/functional/editor/meta_key_spec.lua @@ -27,6 +27,14 @@ describe('meta-keys #8226 #13042', function() command('nnoremap <A-j> Aalt-j<Esc>') feed('<A-j><M-l>') expect('llo<ESC>;<ESC>;alt-jmeta-l') + -- Unmapped ALT-chord with characters containing K_SPECIAL bytes + command('nnoremap … A…<Esc>') + feed('<A-…><M-…>') + expect('llo<ESC>;<ESC>;alt-jmeta-l<ESC>…<ESC>…') + command("execute 'nnoremap' nr2char(0x40000000) 'AMAX<Esc>'") + command("call nvim_input('<A-'.nr2char(0x40000000).'>')") + command("call nvim_input('<M-'.nr2char(0x40000000).'>')") + expect('llo<ESC>;<ESC>;alt-jmeta-l<ESC>…<ESC>…<ESC>MAX<ESC>MAX') end) it('ALT/META, visual-mode', function() @@ -36,13 +44,20 @@ describe('meta-keys #8226 #13042', function() expect('peach') -- Unmapped ALT-chord resolves isolated (non-ALT) ESC mapping. #13086 #15869 command('vnoremap <ESC> A<lt>ESC>') - feed('viw<A-;><ESC>viw<M-;><ESC>') + feed('viw<A-;><Esc>viw<M-;><Esc>') expect('peach<ESC>;<ESC>;') -- Mapped ALT-chord behaves as mapped. command('vnoremap <M-l> Ameta-l<Esc>') command('vnoremap <A-j> Aalt-j<Esc>') feed('viw<A-j>viw<M-l>') expect('peach<ESC>;<ESC>;alt-jmeta-l') + -- Unmapped ALT-chord with characters containing K_SPECIAL bytes + feed('viw<A-…><Esc>viw<M-…><Esc>') + expect('peach<ESC>;<ESC>;alt-jmeta-l<ESC>…<ESC>…') + command("execute 'inoremap' nr2char(0x40000000) 'MAX'") + command("call nvim_input('viw<A-'.nr2char(0x40000000).'><Esc>')") + command("call nvim_input('viw<M-'.nr2char(0x40000000).'><Esc>')") + expect('peach<ESC>;<ESC>;alt-jmeta-l<ESC>…<ESC>…<ESC>MAX<ESC>MAX') end) it('ALT/META insert-mode', function() diff --git a/test/functional/terminal/mouse_spec.lua b/test/functional/terminal/mouse_spec.lua index 780a0b9b5a..6e2c851df7 100644 --- a/test/functional/terminal/mouse_spec.lua +++ b/test/functional/terminal/mouse_spec.lua @@ -1,7 +1,7 @@ local helpers = require('test.functional.helpers')(after_each) local thelpers = require('test.functional.terminal.helpers') local clear, eq, eval = helpers.clear, helpers.eq, helpers.eval -local feed, nvim = helpers.feed, helpers.nvim +local feed, nvim, command = helpers.feed, helpers.nvim, helpers.command local feed_data = thelpers.feed_data describe(':terminal mouse', function() @@ -10,9 +10,9 @@ describe(':terminal mouse', function() before_each(function() clear() nvim('set_option', 'statusline', '==========') - nvim('command', 'highlight StatusLine cterm=NONE') - nvim('command', 'highlight StatusLineNC cterm=NONE') - nvim('command', 'highlight VertSplit cterm=NONE') + command('highlight StatusLine cterm=NONE') + command('highlight StatusLineNC cterm=NONE') + command('highlight VertSplit cterm=NONE') screen = thelpers.screen_setup() local lines = {} for i = 1, 30 do @@ -38,6 +38,26 @@ describe(':terminal mouse', function() eq('nt', eval('mode(1)')) end) + it('will exit focus and trigger Normal mode mapping on mouse click', function() + command('let g:got_leftmouse = 0') + command('nnoremap <LeftMouse> <Cmd>let g:got_leftmouse = 1<CR>') + eq('t', eval('mode(1)')) + eq(0, eval('g:got_leftmouse')) + feed('<LeftMouse>') + eq('nt', eval('mode(1)')) + eq(1, eval('g:got_leftmouse')) + end) + + it('will exit focus and trigger Normal mode mapping on mouse click with modifier', function() + command('let g:got_ctrl_leftmouse = 0') + command('nnoremap <C-LeftMouse> <Cmd>let g:got_ctrl_leftmouse = 1<CR>') + eq('t', eval('mode(1)')) + eq(0, eval('g:got_ctrl_leftmouse')) + feed('<C-LeftMouse>') + eq('nt', eval('mode(1)')) + eq(1, eval('g:got_ctrl_leftmouse')) + end) + it('will exit focus on <C-\\> + mouse-scroll', function() eq('t', eval('mode(1)')) feed('<C-\\>') @@ -180,7 +200,7 @@ describe(':terminal mouse', function() it('will forward mouse clicks to the program with the correct even if set nu', function() if helpers.pending_win32(pending) then return end - nvim('command', 'set number') + command('set number') -- When the display area such as a number is clicked, it returns to the -- normal mode. feed('<LeftMouse><3,0>') diff --git a/test/functional/ui/bufhl_spec.lua b/test/functional/ui/bufhl_spec.lua index 16ed3b9486..7716414e87 100644 --- a/test/functional/ui/bufhl_spec.lua +++ b/test/functional/ui/bufhl_spec.lua @@ -755,12 +755,24 @@ describe('Buffer highlighting', function() -- TODO: only a virtual text from the same ns curretly overrides -- an existing virtual text. We might add a prioritation system. set_virtual_text(id1, 0, s1, {}) - eq({{1, 0, 0, { priority = 0, virt_text = s1}}}, get_extmarks(id1, {0,0}, {0, -1}, {details=true})) + eq({{1, 0, 0, { + priority = 0, + virt_text = s1, + -- other details + virt_text_pos = 'eol', + virt_text_hide = false, + }}}, get_extmarks(id1, {0,0}, {0, -1}, {details=true})) -- TODO: is this really valid? shouldn't the max be line_count()-1? local lastline = line_count() set_virtual_text(id1, line_count(), s2, {}) - eq({{3, lastline, 0, { priority = 0, virt_text = s2}}}, get_extmarks(id1, {lastline,0}, {lastline, -1}, {details=true})) + eq({{3, lastline, 0, { + priority = 0, + virt_text = s2, + -- other details + virt_text_pos = 'eol', + virt_text_hide = false, + }}}, get_extmarks(id1, {lastline,0}, {lastline, -1}, {details=true})) eq({}, get_extmarks(id1, {lastline+9000,0}, {lastline+9000, -1}, {})) end) diff --git a/test/functional/ui/input_spec.lua b/test/functional/ui/input_spec.lua index ea8968a653..11718a6e18 100644 --- a/test/functional/ui/input_spec.lua +++ b/test/functional/ui/input_spec.lua @@ -114,11 +114,30 @@ describe('mappings', function() end) end) -describe('input utf sequences that contain CSI/K_SPECIAL', function() +describe('input utf sequences that contain K_SPECIAL (0x80)', function() it('ok', function() feed('i…<esc>') expect('…') end) + + it('can be mapped', function() + command('inoremap … E280A6') + feed('i…<esc>') + expect('E280A6') + end) +end) + +describe('input utf sequences that contain CSI (0x9B)', function() + it('ok', function() + feed('iě<esc>') + expect('ě') + end) + + it('can be mapped', function() + command('inoremap ě C49B') + feed('iě<esc>') + expect('C49B') + end) end) describe('input non-printable chars', function() diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt index 1a8d7701a8..cdca7c7b9c 100644 --- a/third-party/CMakeLists.txt +++ b/third-party/CMakeLists.txt @@ -203,8 +203,8 @@ set(LIBICONV_SHA256 ccf536620a45458d26ba83887a983b96827001e92a13847b45e4925cc891 set(TREESITTER_C_URL https://github.com/tree-sitter/tree-sitter-c/archive/v0.20.1.tar.gz) set(TREESITTER_C_SHA256 ffcc2ef0eded59ad1acec9aec4f9b0c7dd209fc1a85d85f8b0e81298e3dddcc2) -set(TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/2346570901ef01517dad3e4a944a36d7b7237e4f.tar.gz) -set(TREESITTER_SHA256 d4df622491f3689f71d77ab4dcd26c85ad44a40bbd1ebe831e34658ba48cdc9f) +set(TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/v0.20.3.tar.gz) +set(TREESITTER_SHA256 ab52fe93e0c658cff656b9d10d67cdd29084247052964eba13ed6f0e9fa3bd36) if(USE_BUNDLED_UNIBILIUM) include(BuildUnibilium) |