mirror of
https://github.com/neovim/neovim.git
synced 2024-09-17 20:58:20 -04:00
Compare commits
43 Commits
4085b9035a
...
8ded22a5a7
Author | SHA1 | Date | |
---|---|---|---|
|
8ded22a5a7 | ||
|
deac7df80a | ||
|
ae917dbd06 | ||
|
c65153893a | ||
|
f6cc0394ae | ||
|
f347c292d1 | ||
|
48c14d3544 | ||
|
5931f780e0 | ||
|
98ba65b8be | ||
|
f9bf64d746 | ||
|
a30afeeb85 | ||
|
7b680e0ca9 | ||
|
8501fe621a | ||
|
a5bd6665b0 | ||
|
4ac733f6ef | ||
|
c1a4b8680b | ||
|
f6579a4db1 | ||
|
608ef83fc6 | ||
|
57db94235c | ||
|
cdab8c8ebb | ||
|
830cf054bc | ||
|
def6111118 | ||
|
237d2aef4d | ||
|
15bfdf73ea | ||
|
f289161c3c | ||
|
4b98d38870 | ||
|
4c5bce9cb4 | ||
|
5d7853f229 | ||
|
f279d1ae33 | ||
|
9ddfcb64bf | ||
|
8e81212e15 | ||
|
648d6426c8 | ||
|
f0334c2c71 | ||
|
c8e3618e0e | ||
|
ed832b9ddf | ||
|
8a2aec9974 | ||
|
3a88113246 | ||
|
08153ddd1c | ||
|
003b8a251d | ||
|
0cfbc6eaff | ||
|
95b65a7554 | ||
|
e37404f7fe | ||
|
46401030b7 |
@ -7,8 +7,8 @@ LUAJIT_SHA256 2b5514bd6a6573cb6111b43d013e952cbaf46762d14ebe26c872ddb80b5a84e0
|
|||||||
LUA_URL https://www.lua.org/ftp/lua-5.1.5.tar.gz
|
LUA_URL https://www.lua.org/ftp/lua-5.1.5.tar.gz
|
||||||
LUA_SHA256 2640fc56a795f29d28ef15e13c34a47e223960b0240e8cb0a82d9b0738695333
|
LUA_SHA256 2640fc56a795f29d28ef15e13c34a47e223960b0240e8cb0a82d9b0738695333
|
||||||
|
|
||||||
UNIBILIUM_URL https://github.com/neovim/unibilium/archive/d72c3598e7ac5d1ebf86ee268b8b4ed95c0fa628.tar.gz
|
UNIBILIUM_URL https://github.com/neovim/unibilium/archive/ab28a2ddb86a144194a798bcf1fef1ab4f981ab7.tar.gz
|
||||||
UNIBILIUM_SHA256 9c4747c862ab5e3076dcf8fa8f0ea7a6b50f20ec5905618b9536655596797487
|
UNIBILIUM_SHA256 7c0386fc48452632868e0dcb8e7ed140d67a3da79e39ceee54c1ba7a495ad625
|
||||||
|
|
||||||
LUV_URL https://github.com/luvit/luv/releases/download/1.48.0-2/luv-1.48.0-2.tar.gz
|
LUV_URL https://github.com/luvit/luv/releases/download/1.48.0-2/luv-1.48.0-2.tar.gz
|
||||||
LUV_SHA256 2c3a1ddfebb4f6550293a40ee789f7122e97647eede51511f57203de48c03b7a
|
LUV_SHA256 2c3a1ddfebb4f6550293a40ee789f7122e97647eede51511f57203de48c03b7a
|
||||||
@ -38,18 +38,18 @@ LIBICONV_SHA256 8f74213b56238c85a50a5329f77e06198771e70dd9a739779f4c02f65d971313
|
|||||||
UTF8PROC_URL https://github.com/JuliaStrings/utf8proc/archive/3de4596fbe28956855df2ecb3c11c0bbc3535838.tar.gz
|
UTF8PROC_URL https://github.com/JuliaStrings/utf8proc/archive/3de4596fbe28956855df2ecb3c11c0bbc3535838.tar.gz
|
||||||
UTF8PROC_SHA256 fb4a16bb659b58afb7f921fcc8928d0b3c1fcab135366c8a4f9ca7de1b1cfada
|
UTF8PROC_SHA256 fb4a16bb659b58afb7f921fcc8928d0b3c1fcab135366c8a4f9ca7de1b1cfada
|
||||||
|
|
||||||
TREESITTER_C_URL https://github.com/tree-sitter/tree-sitter-c/archive/v0.21.3.tar.gz
|
TREESITTER_C_URL https://github.com/tree-sitter/tree-sitter-c/archive/v0.23.0.tar.gz
|
||||||
TREESITTER_C_SHA256 75a3780df6114cd37496761c4a7c9fd900c78bee3a2707f590d78c0ca3a24368
|
TREESITTER_C_SHA256 ee58c925e2e507c23d735aad46bf7fb0af31ca06d6f4f41bc008216d9232b0cb
|
||||||
TREESITTER_LUA_URL https://github.com/tree-sitter-grammars/tree-sitter-lua/archive/v0.1.0.tar.gz
|
TREESITTER_LUA_URL https://github.com/tree-sitter-grammars/tree-sitter-lua/archive/v0.2.0.tar.gz
|
||||||
TREESITTER_LUA_SHA256 230cfcbfa74ed1f7b8149e9a1f34c2efc4c589a71fe0f5dc8560622f8020d722
|
TREESITTER_LUA_SHA256 6c41227cd0a59047b19d31f0031d4d901f08bfd78d6fc7f55c89e5b8374c794e
|
||||||
TREESITTER_VIM_URL https://github.com/neovim/tree-sitter-vim/archive/v0.4.0.tar.gz
|
TREESITTER_VIM_URL https://github.com/neovim/tree-sitter-vim/archive/v0.4.0.tar.gz
|
||||||
TREESITTER_VIM_SHA256 9f856f8b4a10ab43348550fa2d3cb2846ae3d8e60f45887200549c051c66f9d5
|
TREESITTER_VIM_SHA256 9f856f8b4a10ab43348550fa2d3cb2846ae3d8e60f45887200549c051c66f9d5
|
||||||
TREESITTER_VIMDOC_URL https://github.com/neovim/tree-sitter-vimdoc/archive/v3.0.0.tar.gz
|
TREESITTER_VIMDOC_URL https://github.com/neovim/tree-sitter-vimdoc/archive/v3.0.0.tar.gz
|
||||||
TREESITTER_VIMDOC_SHA256 a639bf92bf57bfa1cdc90ca16af27bfaf26a9779064776dd4be34c1ef1453f6c
|
TREESITTER_VIMDOC_SHA256 a639bf92bf57bfa1cdc90ca16af27bfaf26a9779064776dd4be34c1ef1453f6c
|
||||||
TREESITTER_QUERY_URL https://github.com/tree-sitter-grammars/tree-sitter-query/archive/v0.4.0.tar.gz
|
TREESITTER_QUERY_URL https://github.com/tree-sitter-grammars/tree-sitter-query/archive/v0.4.0.tar.gz
|
||||||
TREESITTER_QUERY_SHA256 d3a423ab66dc62b2969625e280116678a8a22582b5ff087795222108db2f6a6e
|
TREESITTER_QUERY_SHA256 d3a423ab66dc62b2969625e280116678a8a22582b5ff087795222108db2f6a6e
|
||||||
TREESITTER_MARKDOWN_URL https://github.com/MDeiml/tree-sitter-markdown/archive/v0.2.3.tar.gz
|
TREESITTER_MARKDOWN_URL https://github.com/tree-sitter-grammars/tree-sitter-markdown/archive/v0.3.2.tar.gz
|
||||||
TREESITTER_MARKDOWN_SHA256 4909d6023643f1afc3ab219585d4035b7403f3a17849782ab803c5f73c8a31d5
|
TREESITTER_MARKDOWN_SHA256 5dac48a6d971eb545aab665d59a18180d21963afc781bbf40f9077c06cb82ae5
|
||||||
TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/v0.23.0.tar.gz
|
TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/v0.23.0.tar.gz
|
||||||
TREESITTER_SHA256 6403b361b0014999e96f61b9c84d6950d42f0c7d6e806be79382e0232e48a11b
|
TREESITTER_SHA256 6403b361b0014999e96f61b9c84d6950d42f0c7d6e806be79382e0232e48a11b
|
||||||
|
|
||||||
|
@ -4,6 +4,8 @@ They are used with the ":compiler" command.
|
|||||||
These scripts usually set options, for example 'errorformat'.
|
These scripts usually set options, for example 'errorformat'.
|
||||||
See ":help write-compiler-plugin".
|
See ":help write-compiler-plugin".
|
||||||
|
|
||||||
|
To undo the effect of a compiler plugin, use the make compiler plugin.
|
||||||
|
|
||||||
If you want to write your own compiler plugin, have a look at the other files
|
If you want to write your own compiler plugin, have a look at the other files
|
||||||
for how to do it, the format is simple.
|
for how to do it, the format is simple.
|
||||||
|
|
||||||
|
45
runtime/compiler/groff.vim
Normal file
45
runtime/compiler/groff.vim
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
" Vim compiler file
|
||||||
|
" Compiler: Groff
|
||||||
|
" Maintainer: Konfekt
|
||||||
|
" Last Change: 2024 Sep 8
|
||||||
|
"
|
||||||
|
" Expects output file extension, say `:make html` or `:make pdf`.
|
||||||
|
" Supported devices as of Sept 2024 are: (x)html, pdf, ps, dvi, lj4, lbp ...
|
||||||
|
" Adjust command-line flags, language, encoding by buffer-local/global variables
|
||||||
|
" groff_compiler_args, groff_compiler_lang, and groff_compiler_encoding,
|
||||||
|
" which default to '', &spelllang and 'utf8'.
|
||||||
|
|
||||||
|
if exists("current_compiler")
|
||||||
|
finish
|
||||||
|
endif
|
||||||
|
|
||||||
|
let s:keepcpo = &cpo
|
||||||
|
set cpo&vim
|
||||||
|
|
||||||
|
let current_compiler = 'groff'
|
||||||
|
|
||||||
|
silent! function s:groff_compiler_lang()
|
||||||
|
let lang = get(b:, 'groff_compiler_lang',
|
||||||
|
\ &spell ? matchstr(&spelllang, '^\a\a') : '')
|
||||||
|
if lang ==# 'en' | let lang = '' | endif
|
||||||
|
return empty(lang) ? '' : '-m'..lang
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Requires output format (= device) to be set by user after :make.
|
||||||
|
execute 'CompilerSet makeprg=groff'..escape(
|
||||||
|
\ ' '..s:groff_compiler_lang()..
|
||||||
|
\ ' -K'..get(b:, 'groff_compiler_encoding', get(g:, 'groff_compiler_encoding', 'utf8'))..
|
||||||
|
\ ' '..get(b:, 'groff_compiler_args', get(g:, 'groff_compiler_args', ''))..
|
||||||
|
\ ' -mom -T$* -- %:S > %:r:S.$*', ' ')
|
||||||
|
" From Gavin Freeborn's https://github.com/Gavinok/vim-troff under Vim License
|
||||||
|
" https://github.com/Gavinok/vim-troff/blob/91017b1423caa80aba541c997909a4f810edd275/compiler/troff.vim#L39
|
||||||
|
CompilerSet errorformat=%o:<standard\ input>\ (%f):%l:%m,
|
||||||
|
\%o:\ <standard\ input>\ (%f):%l:%m,
|
||||||
|
\%o:%f:%l:%m,
|
||||||
|
\%o:\ %f:%l:%m,
|
||||||
|
\%f:%l:\ macro\ %trror:%m,
|
||||||
|
\%f:%l:%m,
|
||||||
|
\%W%tarning:\ file\ '%f'\\,\ around\ line\ %l:,%Z%m
|
||||||
|
|
||||||
|
let &cpo = s:keepcpo
|
||||||
|
unlet s:keepcpo
|
13
runtime/compiler/make.vim
Normal file
13
runtime/compiler/make.vim
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
" Vim compiler plugin
|
||||||
|
"
|
||||||
|
" Maintainer: The Vim Project <https://github.com/vim/vim>
|
||||||
|
" Last Change: 2024 Sep 10
|
||||||
|
" Original Author: Konfekt
|
||||||
|
"
|
||||||
|
" This compiler plugin is used to reset previously set compiler options.
|
||||||
|
|
||||||
|
if exists("g:current_compiler") | unlet g:current_compiler | endif
|
||||||
|
if exists("b:current_compiler") | unlet b:current_compiler | endif
|
||||||
|
|
||||||
|
CompilerSet makeprg&
|
||||||
|
CompilerSet errorformat&
|
@ -1,10 +1,12 @@
|
|||||||
" Vim compiler file
|
" Vim compiler file
|
||||||
" Compiler: Pandoc
|
" Compiler: Pandoc
|
||||||
" Maintainer: Konfekt
|
" Maintainer: Konfekt
|
||||||
" Last Change: 2024 Aug 20
|
" Last Change: 2024 Sep 8
|
||||||
"
|
"
|
||||||
" Expects output file extension, say `:make html` or `:make pdf`.
|
" Expects output file extension, say `:make html` or `:make pdf`.
|
||||||
" Passes additional arguments to pandoc, say `:make html --self-contained`.
|
" Passes additional arguments to pandoc, say `:make html --self-contained`.
|
||||||
|
" Adjust command-line flags by buffer-local/global variable
|
||||||
|
" b/g:pandoc_compiler_args which defaults to empty.
|
||||||
|
|
||||||
if exists("current_compiler")
|
if exists("current_compiler")
|
||||||
finish
|
finish
|
||||||
@ -40,18 +42,21 @@ silent! function s:PandocFiletype(filetype) abort
|
|||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
let b:pandoc_compiler_from = get(b:, 'pandoc_compiler_from', s:PandocFiletype(&filetype))
|
silent! function s:PandocLang()
|
||||||
let b:pandoc_compiler_lang = get(b:, 'pandoc_compiler_lang', &spell ? matchstr(&spelllang, '^\a\a') : '')
|
let lang = get(b:, 'pandoc_compiler_lang',
|
||||||
|
\ &spell ? matchstr(&spelllang, '^\a\a') : '')
|
||||||
|
if lang ==# 'en' | let lang = '' | endif
|
||||||
|
return empty(lang) ? '' : '--metadata lang='..lang
|
||||||
|
endfunction
|
||||||
|
|
||||||
execute 'CompilerSet makeprg=pandoc'..escape(
|
execute 'CompilerSet makeprg=pandoc'..escape(
|
||||||
\ ' --standalone' .
|
\ ' --standalone'..
|
||||||
\ (b:pandoc_compiler_from ==# 'markdown' && (getline(1) =~# '^%\s\+\S\+' || (search('^title:\s+\S+', 'cnw') > 0)) ?
|
\ (s:PandocFiletype(&filetype) ==# 'markdown' && (getline(1) =~# '^%\s\+\S\+' || (search('^title:\s+\S+', 'cnw') > 0)) ?
|
||||||
\ '' : ' --metadata title=%:t:r:S') .
|
\ '' : ' --metadata title=%:t:r:S')..
|
||||||
\ (empty(b:pandoc_compiler_lang) ?
|
\ ' '..s:PandocLang()..
|
||||||
\ '' : ' --metadata lang='..b:pandoc_compiler_lang) .
|
\ ' --from='..s:PandocFiletype(&filetype)..
|
||||||
\ ' --from='..b:pandoc_compiler_from .
|
\ ' '..get(b:, 'pandoc_compiler_args', get(g:, 'pandoc_compiler_args', ''))..
|
||||||
\ ' '..get(b:, 'pandoc_compiler_args', get(g:, 'pandoc_compiler_args', '')) .
|
\ ' --output %:r:S.$* -- %:S', ' ')
|
||||||
\ ' --output %:r:S.$* -- %:S', ' ')
|
|
||||||
CompilerSet errorformat=\"%f\",\ line\ %l:\ %m
|
CompilerSet errorformat=\"%f\",\ line\ %l:\ %m
|
||||||
|
|
||||||
let &cpo = s:keepcpo
|
let &cpo = s:keepcpo
|
||||||
|
3
runtime/doc/builtin.txt
generated
3
runtime/doc/builtin.txt
generated
@ -6201,6 +6201,9 @@ search({pattern} [, {flags} [, {stopline} [, {timeout} [, {skip}]]]]) *search()*
|
|||||||
The value must not be negative. A zero value is like not
|
The value must not be negative. A zero value is like not
|
||||||
giving the argument.
|
giving the argument.
|
||||||
|
|
||||||
|
Note: the timeout is only considered when searching, not
|
||||||
|
while evaluating the {skip} expression.
|
||||||
|
|
||||||
If the {skip} expression is given it is evaluated with the
|
If the {skip} expression is given it is evaluated with the
|
||||||
cursor positioned on the start of a match. If it evaluates to
|
cursor positioned on the start of a match. If it evaluates to
|
||||||
non-zero this match is skipped. This can be used, for
|
non-zero this match is skipped. This can be used, for
|
||||||
|
@ -2230,6 +2230,12 @@ vim.tbl_count({t}) *vim.tbl_count()*
|
|||||||
vim.tbl_deep_extend({behavior}, {...}) *vim.tbl_deep_extend()*
|
vim.tbl_deep_extend({behavior}, {...}) *vim.tbl_deep_extend()*
|
||||||
Merges recursively two or more tables.
|
Merges recursively two or more tables.
|
||||||
|
|
||||||
|
Only values that are empty tables or tables that are not |lua-list|s
|
||||||
|
(indexed by consecutive integers starting from 1) are merged recursively.
|
||||||
|
This is useful for merging nested tables like default and user
|
||||||
|
configurations where lists should be treated as literals (i.e., are
|
||||||
|
overwritten instead of merged).
|
||||||
|
|
||||||
Parameters: ~
|
Parameters: ~
|
||||||
• {behavior} (`'error'|'keep'|'force'`) Decides what to do if a key is
|
• {behavior} (`'error'|'keep'|'force'`) Decides what to do if a key is
|
||||||
found in more than one map:
|
found in more than one map:
|
||||||
|
@ -189,7 +189,8 @@ TREESITTER
|
|||||||
|
|
||||||
TUI
|
TUI
|
||||||
|
|
||||||
• TODO
|
• |log| messages written by the builtin UI client (TUI, |--remote-ui|) are
|
||||||
|
now prefixed with "ui" instead of "?".
|
||||||
|
|
||||||
UI
|
UI
|
||||||
|
|
||||||
@ -214,9 +215,6 @@ These existing features changed their behavior.
|
|||||||
more emoji characters than before, including those encoded with multiple
|
more emoji characters than before, including those encoded with multiple
|
||||||
emoji codepoints combined with ZWJ (zero width joiner) codepoints.
|
emoji codepoints combined with ZWJ (zero width joiner) codepoints.
|
||||||
|
|
||||||
• |vim.tbl_deep_extend()| no longer ignores any values for which |vim.isarray()|
|
|
||||||
returns `true`.
|
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
REMOVED FEATURES *news-removed*
|
REMOVED FEATURES *news-removed*
|
||||||
|
|
||||||
|
@ -6713,7 +6713,7 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
global
|
global
|
||||||
When on, the title of the window will be set to the value of
|
When on, the title of the window will be set to the value of
|
||||||
'titlestring' (if it is not empty), or to:
|
'titlestring' (if it is not empty), or to:
|
||||||
filename [+=-] (path) - NVIM
|
filename [+=-] (path) - Nvim
|
||||||
Where:
|
Where:
|
||||||
filename the name of the file being edited
|
filename the name of the file being edited
|
||||||
- indicates the file cannot be modified, 'ma' off
|
- indicates the file cannot be modified, 'ma' off
|
||||||
@ -6721,7 +6721,7 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
= indicates the file is read-only
|
= indicates the file is read-only
|
||||||
=+ indicates the file is read-only and modified
|
=+ indicates the file is read-only and modified
|
||||||
(path) is the path of the file being edited
|
(path) is the path of the file being edited
|
||||||
- NVIM the server name |v:servername| or "NVIM"
|
- Nvim the server name |v:servername| or "Nvim"
|
||||||
|
|
||||||
*'titlelen'*
|
*'titlelen'*
|
||||||
'titlelen' number (default 85)
|
'titlelen' number (default 85)
|
||||||
|
@ -1262,6 +1262,7 @@ not "b:current_compiler". What the command actually does is the following:
|
|||||||
|
|
||||||
For writing a compiler plugin, see |write-compiler-plugin|.
|
For writing a compiler plugin, see |write-compiler-plugin|.
|
||||||
|
|
||||||
|
Use the |compiler-make| plugin to undo the effect of a compiler plugin.
|
||||||
|
|
||||||
DOTNET *compiler-dotnet*
|
DOTNET *compiler-dotnet*
|
||||||
|
|
||||||
@ -1277,7 +1278,6 @@ Example: limit output to only display errors, and suppress the project name: >
|
|||||||
let dotnet_show_project_file = v:false
|
let dotnet_show_project_file = v:false
|
||||||
compiler dotnet
|
compiler dotnet
|
||||||
<
|
<
|
||||||
|
|
||||||
GCC *quickfix-gcc* *compiler-gcc*
|
GCC *quickfix-gcc* *compiler-gcc*
|
||||||
|
|
||||||
There's one variable you can set for the GCC compiler:
|
There's one variable you can set for the GCC compiler:
|
||||||
@ -1294,6 +1294,24 @@ Commonly used compiler options can be added to 'makeprg' by setting the
|
|||||||
g:javac_makeprg_params variable. For example: >
|
g:javac_makeprg_params variable. For example: >
|
||||||
let g:javac_makeprg_params = "-Xlint:all -encoding utf-8"
|
let g:javac_makeprg_params = "-Xlint:all -encoding utf-8"
|
||||||
<
|
<
|
||||||
|
GNU MAKE *compiler-make*
|
||||||
|
|
||||||
|
Since the default make program is "make", the compiler plugin for make,
|
||||||
|
:compiler make, will reset the 'makeprg' and 'errorformat' option to
|
||||||
|
the default values and unlet any variables that may have been set by a
|
||||||
|
previous compiler plugin.
|
||||||
|
|
||||||
|
GROFF *quickfix-groff* *compiler-groff*
|
||||||
|
|
||||||
|
The GROFF compiler plugin uses the mom macro set (documented in the groff_mom
|
||||||
|
manpage) as input and expects that the output file type extension is passed to
|
||||||
|
make, say :make html or :make pdf.
|
||||||
|
|
||||||
|
Additional arguments can be passed to groff by setting them in
|
||||||
|
`b:groff_compiler_args` or `g:groff_compiler_args`. The `language` argument
|
||||||
|
passed to groff is set using 'spelllang'; it can be overridden by setting
|
||||||
|
`b:groff_compiler_lang`. The default enconding is `UTF-8` and can be changed
|
||||||
|
by setting `b:groff_compiler_encoding` or `g:groff_compiler_encoding`.
|
||||||
|
|
||||||
PANDOC *quickfix-pandoc* *compiler-pandoc*
|
PANDOC *quickfix-pandoc* *compiler-pandoc*
|
||||||
|
|
||||||
@ -1307,8 +1325,7 @@ Additional arguments can be passed to pandoc:
|
|||||||
|
|
||||||
The `--from` argument is an educated guess using the buffer file type;
|
The `--from` argument is an educated guess using the buffer file type;
|
||||||
it can be overridden by setting `b:pandoc_compiler_from`.
|
it can be overridden by setting `b:pandoc_compiler_from`.
|
||||||
Likewise the `--metadata lang` argument is set using `&spelllang`;
|
The `--metadata lang` argument is set using 'spelllang';
|
||||||
it can be overridden by setting `b:pandoc_compiler_lang`.
|
|
||||||
If `--from=markdown` is assumed and no title set in a title header or
|
If `--from=markdown` is assumed and no title set in a title header or
|
||||||
YAML block, then the filename (without extension) is used as the title.
|
YAML block, then the filename (without extension) is used as the title.
|
||||||
|
|
||||||
|
3
runtime/ftplugin/dot.lua
Normal file
3
runtime/ftplugin/dot.lua
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
vim.bo.commentstring = '// %s'
|
||||||
|
|
||||||
|
vim.b.undo_ftplugin = (vim.b.undo_ftplugin or '') .. '\n setl commentstring<'
|
3
runtime/ftplugin/faust.lua
Normal file
3
runtime/ftplugin/faust.lua
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
vim.bo.commentstring = '// %s'
|
||||||
|
|
||||||
|
vim.b.undo_ftplugin = (vim.b.undo_ftplugin or '') .. '\n setl commentstring<'
|
@ -2,8 +2,9 @@
|
|||||||
" Filename: spec.vim
|
" Filename: spec.vim
|
||||||
" Maintainer: Igor Gnatenko i.gnatenko.brain@gmail.com
|
" Maintainer: Igor Gnatenko i.gnatenko.brain@gmail.com
|
||||||
" Former Maintainer: Gustavo Niemeyer <niemeyer@conectiva.com> (until March 2014)
|
" Former Maintainer: Gustavo Niemeyer <niemeyer@conectiva.com> (until March 2014)
|
||||||
" Last Change: Mon Jun 01 21:15 MSK 2015 Igor Gnatenko
|
" Last Change: 2015 Jun 01
|
||||||
" Update by Zdenek Dohnal, 2022 May 17
|
" Update by Zdenek Dohnal, 2022 May 17
|
||||||
|
" 2024 Sep 10 by Vim Project: add epoch support for spec changelog, #15537
|
||||||
|
|
||||||
if exists("b:did_ftplugin")
|
if exists("b:did_ftplugin")
|
||||||
finish
|
finish
|
||||||
@ -66,9 +67,11 @@ if !exists("*s:SpecChangelog")
|
|||||||
endif
|
endif
|
||||||
let line = 0
|
let line = 0
|
||||||
let name = ""
|
let name = ""
|
||||||
|
let epoch = ""
|
||||||
let ver = ""
|
let ver = ""
|
||||||
let rel = ""
|
let rel = ""
|
||||||
let nameline = -1
|
let nameline = -1
|
||||||
|
let epochline = -1
|
||||||
let verline = -1
|
let verline = -1
|
||||||
let relline = -1
|
let relline = -1
|
||||||
let chgline = -1
|
let chgline = -1
|
||||||
@ -77,6 +80,9 @@ if !exists("*s:SpecChangelog")
|
|||||||
if name == "" && linestr =~? '^Name:'
|
if name == "" && linestr =~? '^Name:'
|
||||||
let nameline = line
|
let nameline = line
|
||||||
let name = substitute(strpart(linestr,5), '^[ ]*\([^ ]\+\)[ ]*$','\1','')
|
let name = substitute(strpart(linestr,5), '^[ ]*\([^ ]\+\)[ ]*$','\1','')
|
||||||
|
elseif epoch == "" && linestr =~? '^Epoch:'
|
||||||
|
let epochline = line
|
||||||
|
let epoch = substitute(strpart(linestr,6), '^[ ]*\([^ ]\+\)[ ]*$','\1','')
|
||||||
elseif ver == "" && linestr =~? '^Version:'
|
elseif ver == "" && linestr =~? '^Version:'
|
||||||
let verline = line
|
let verline = line
|
||||||
let ver = substitute(strpart(linestr,8), '^[ ]*\([^ ]\+\)[ ]*$','\1','')
|
let ver = substitute(strpart(linestr,8), '^[ ]*\([^ ]\+\)[ ]*$','\1','')
|
||||||
@ -93,6 +99,7 @@ if !exists("*s:SpecChangelog")
|
|||||||
if nameline != -1 && verline != -1 && relline != -1
|
if nameline != -1 && verline != -1 && relline != -1
|
||||||
let include_release_info = exists("g:spec_chglog_release_info")
|
let include_release_info = exists("g:spec_chglog_release_info")
|
||||||
let name = s:ParseRpmVars(name, nameline)
|
let name = s:ParseRpmVars(name, nameline)
|
||||||
|
let epoch = s:ParseRpmVars(epoch, epochline)
|
||||||
let ver = s:ParseRpmVars(ver, verline)
|
let ver = s:ParseRpmVars(ver, verline)
|
||||||
let rel = s:ParseRpmVars(rel, relline)
|
let rel = s:ParseRpmVars(rel, relline)
|
||||||
else
|
else
|
||||||
@ -117,6 +124,9 @@ if !exists("*s:SpecChangelog")
|
|||||||
if chgline != -1
|
if chgline != -1
|
||||||
let tmptime = v:lc_time
|
let tmptime = v:lc_time
|
||||||
language time C
|
language time C
|
||||||
|
if strlen(epoch)
|
||||||
|
let ver = epoch.":".ver
|
||||||
|
endif
|
||||||
let parsed_format = "* ".strftime(format)." - ".ver."-".rel
|
let parsed_format = "* ".strftime(format)." - ".ver."-".rel
|
||||||
execute "language time" tmptime
|
execute "language time" tmptime
|
||||||
let release_info = "+ ".name."-".ver."-".rel
|
let release_info = "+ ".name."-".ver."-".rel
|
||||||
|
3
runtime/ftplugin/stata.lua
Normal file
3
runtime/ftplugin/stata.lua
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
vim.bo.commentstring = '// %s'
|
||||||
|
|
||||||
|
vim.b.undo_ftplugin = (vim.b.undo_ftplugin or '') .. '\n setl commentstring<'
|
3
runtime/ftplugin/supercollider.lua
Normal file
3
runtime/ftplugin/supercollider.lua
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
vim.bo.commentstring = '// %s'
|
||||||
|
|
||||||
|
vim.b.undo_ftplugin = (vim.b.undo_ftplugin or '') .. '\n setl commentstring<'
|
3
runtime/ftplugin/swift.lua
Normal file
3
runtime/ftplugin/swift.lua
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
vim.bo.commentstring = '// %s'
|
||||||
|
|
||||||
|
vim.b.undo_ftplugin = vim.b.undo_ftplugin .. ' | setl commentstring<'
|
@ -1293,9 +1293,25 @@ local function opt_to_global_state(opt, title)
|
|||||||
local fonts = {}
|
local fonts = {}
|
||||||
if opt.font then
|
if opt.font then
|
||||||
fonts = type(opt.font) == 'string' and { opt.font } or opt.font --[[@as (string[])]]
|
fonts = type(opt.font) == 'string' and { opt.font } or opt.font --[[@as (string[])]]
|
||||||
|
for i, v in pairs(fonts) do
|
||||||
|
fonts[i] = ('"%s"'):format(v)
|
||||||
|
end
|
||||||
elseif vim.o.guifont:match('^[^:]+') then
|
elseif vim.o.guifont:match('^[^:]+') then
|
||||||
table.insert(fonts, vim.o.guifont:match('^[^:]+'))
|
-- Example:
|
||||||
|
-- Input: "Font,Escape\,comma, Ignore space after comma"
|
||||||
|
-- Output: { "Font","Escape,comma","Ignore space after comma" }
|
||||||
|
local prev = ''
|
||||||
|
for name in vim.gsplit(vim.o.guifont:match('^[^:]+'), ',', { trimempty = true }) do
|
||||||
|
if vim.endswith(name, '\\') then
|
||||||
|
prev = prev .. vim.trim(name:sub(1, -2) .. ',')
|
||||||
|
elseif vim.trim(name) ~= '' then
|
||||||
|
table.insert(fonts, ('"%s%s"'):format(prev, vim.trim(name)))
|
||||||
|
prev = ''
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
-- Generic family names (monospace here) must not be quoted
|
||||||
|
-- because the browser recognizes them as font families.
|
||||||
table.insert(fonts, 'monospace')
|
table.insert(fonts, 'monospace')
|
||||||
--- @type vim.tohtml.state.global
|
--- @type vim.tohtml.state.global
|
||||||
local state = {
|
local state = {
|
||||||
|
4
runtime/lua/vim/_meta/options.lua
generated
4
runtime/lua/vim/_meta/options.lua
generated
@ -7255,7 +7255,7 @@ vim.go.tm = vim.go.timeoutlen
|
|||||||
|
|
||||||
--- When on, the title of the window will be set to the value of
|
--- When on, the title of the window will be set to the value of
|
||||||
--- 'titlestring' (if it is not empty), or to:
|
--- 'titlestring' (if it is not empty), or to:
|
||||||
--- filename [+=-] (path) - NVIM
|
--- filename [+=-] (path) - Nvim
|
||||||
--- Where:
|
--- Where:
|
||||||
--- filename the name of the file being edited
|
--- filename the name of the file being edited
|
||||||
--- - indicates the file cannot be modified, 'ma' off
|
--- - indicates the file cannot be modified, 'ma' off
|
||||||
@ -7263,7 +7263,7 @@ vim.go.tm = vim.go.timeoutlen
|
|||||||
--- = indicates the file is read-only
|
--- = indicates the file is read-only
|
||||||
--- =+ indicates the file is read-only and modified
|
--- =+ indicates the file is read-only and modified
|
||||||
--- (path) is the path of the file being edited
|
--- (path) is the path of the file being edited
|
||||||
--- - NVIM the server name `v:servername` or "NVIM"
|
--- - Nvim the server name `v:servername` or "Nvim"
|
||||||
---
|
---
|
||||||
--- @type boolean
|
--- @type boolean
|
||||||
vim.o.title = false
|
vim.o.title = false
|
||||||
|
3
runtime/lua/vim/_meta/vimfn.lua
generated
3
runtime/lua/vim/_meta/vimfn.lua
generated
@ -7421,6 +7421,9 @@ function vim.fn.screenstring(row, col) end
|
|||||||
--- The value must not be negative. A zero value is like not
|
--- The value must not be negative. A zero value is like not
|
||||||
--- giving the argument.
|
--- giving the argument.
|
||||||
---
|
---
|
||||||
|
--- Note: the timeout is only considered when searching, not
|
||||||
|
--- while evaluating the {skip} expression.
|
||||||
|
---
|
||||||
--- If the {skip} expression is given it is evaluated with the
|
--- If the {skip} expression is given it is evaluated with the
|
||||||
--- cursor positioned on the start of a match. If it evaluates to
|
--- cursor positioned on the start of a match. If it evaluates to
|
||||||
--- non-zero this match is skipped. This can be used, for
|
--- non-zero this match is skipped. This can be used, for
|
||||||
|
@ -1164,6 +1164,7 @@ local extension = {
|
|||||||
svelte = 'svelte',
|
svelte = 'svelte',
|
||||||
svg = 'svg',
|
svg = 'svg',
|
||||||
swift = 'swift',
|
swift = 'swift',
|
||||||
|
swiftinterface = 'swift',
|
||||||
swig = 'swig',
|
swig = 'swig',
|
||||||
swg = 'swig',
|
swg = 'swig',
|
||||||
sys = detect.sys,
|
sys = detect.sys,
|
||||||
|
@ -285,8 +285,8 @@ local path2name = function(path)
|
|||||||
-- Remove everything up to the last /lua/ folder
|
-- Remove everything up to the last /lua/ folder
|
||||||
path = path:gsub('^.*/lua/', '')
|
path = path:gsub('^.*/lua/', '')
|
||||||
|
|
||||||
-- Remove the filename (health.lua)
|
-- Remove the filename (health.lua) or (health/init.lua)
|
||||||
path = vim.fs.dirname(path)
|
path = vim.fs.dirname(path:gsub('/init%.lua$', ''))
|
||||||
|
|
||||||
-- Change slashes to dots
|
-- Change slashes to dots
|
||||||
path = path:gsub('/', '.')
|
path = path:gsub('/', '.')
|
||||||
|
@ -43,17 +43,16 @@ function M.on_inlayhint(err, result, ctx, _)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
local bufnr = assert(ctx.bufnr)
|
local bufnr = assert(ctx.bufnr)
|
||||||
if util.buf_versions[bufnr] ~= ctx.version then
|
if
|
||||||
|
util.buf_versions[bufnr] ~= ctx.version
|
||||||
|
or not result
|
||||||
|
or not api.nvim_buf_is_loaded(bufnr)
|
||||||
|
or not bufstates[bufnr].enabled
|
||||||
|
then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local client_id = ctx.client_id
|
local client_id = ctx.client_id
|
||||||
if not result then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local bufstate = bufstates[bufnr]
|
local bufstate = bufstates[bufnr]
|
||||||
if not bufstate.enabled then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if not (bufstate.client_hints and bufstate.version) then
|
if not (bufstate.client_hints and bufstate.version) then
|
||||||
bufstate.client_hints = vim.defaulttable()
|
bufstate.client_hints = vim.defaulttable()
|
||||||
bufstate.version = ctx.version
|
bufstate.version = ctx.version
|
||||||
@ -77,12 +76,7 @@ function M.on_inlayhint(err, result, ctx, _)
|
|||||||
local col = position.character
|
local col = position.character
|
||||||
if col > 0 then
|
if col > 0 then
|
||||||
local line = lines[position.line + 1] or ''
|
local line = lines[position.line + 1] or ''
|
||||||
local ok, convert_result
|
return util._str_byteindex_enc(line, col, client.offset_encoding)
|
||||||
ok, convert_result = pcall(util._str_byteindex_enc, line, col, client.offset_encoding)
|
|
||||||
if ok then
|
|
||||||
return convert_result
|
|
||||||
end
|
|
||||||
return math.min(#line, col)
|
|
||||||
end
|
end
|
||||||
return col
|
return col
|
||||||
end
|
end
|
||||||
|
@ -140,12 +140,7 @@ local function tokens_to_ranges(data, bufnr, client, request)
|
|||||||
local function _get_byte_pos(col)
|
local function _get_byte_pos(col)
|
||||||
if col > 0 then
|
if col > 0 then
|
||||||
local buf_line = lines[line + 1] or ''
|
local buf_line = lines[line + 1] or ''
|
||||||
local ok, result
|
return util._str_byteindex_enc(buf_line, col, client.offset_encoding)
|
||||||
ok, result = pcall(util._str_byteindex_enc, buf_line, col, client.offset_encoding)
|
|
||||||
if ok then
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
return math.min(#buf_line, col)
|
|
||||||
end
|
end
|
||||||
return col
|
return col
|
||||||
end
|
end
|
||||||
|
@ -119,6 +119,7 @@ end
|
|||||||
---@param encoding string|nil utf-8|utf-16|utf-32|nil defaults to utf-16
|
---@param encoding string|nil utf-8|utf-16|utf-32|nil defaults to utf-16
|
||||||
---@return integer `encoding` index of `index` in `line`
|
---@return integer `encoding` index of `index` in `line`
|
||||||
function M._str_utfindex_enc(line, index, encoding)
|
function M._str_utfindex_enc(line, index, encoding)
|
||||||
|
local len32, len16 = vim.str_utfindex(line)
|
||||||
if not encoding then
|
if not encoding then
|
||||||
encoding = 'utf-16'
|
encoding = 'utf-16'
|
||||||
end
|
end
|
||||||
@ -129,9 +130,15 @@ function M._str_utfindex_enc(line, index, encoding)
|
|||||||
return #line
|
return #line
|
||||||
end
|
end
|
||||||
elseif encoding == 'utf-16' then
|
elseif encoding == 'utf-16' then
|
||||||
|
if not index or index > len16 then
|
||||||
|
return len16
|
||||||
|
end
|
||||||
local _, col16 = vim.str_utfindex(line, index)
|
local _, col16 = vim.str_utfindex(line, index)
|
||||||
return col16
|
return col16
|
||||||
elseif encoding == 'utf-32' then
|
elseif encoding == 'utf-32' then
|
||||||
|
if not index or index > len32 then
|
||||||
|
return len32
|
||||||
|
end
|
||||||
local col32, _ = vim.str_utfindex(line, index)
|
local col32, _ = vim.str_utfindex(line, index)
|
||||||
return col32
|
return col32
|
||||||
else
|
else
|
||||||
@ -147,6 +154,12 @@ end
|
|||||||
---@param encoding string utf-8|utf-16|utf-32| defaults to utf-16
|
---@param encoding string utf-8|utf-16|utf-32| defaults to utf-16
|
||||||
---@return integer byte (utf-8) index of `encoding` index `index` in `line`
|
---@return integer byte (utf-8) index of `encoding` index `index` in `line`
|
||||||
function M._str_byteindex_enc(line, index, encoding)
|
function M._str_byteindex_enc(line, index, encoding)
|
||||||
|
local len = vim.fn.strlen(line)
|
||||||
|
if index > len then
|
||||||
|
-- LSP spec: if character > line length, default to the line length.
|
||||||
|
-- https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#position
|
||||||
|
return len
|
||||||
|
end
|
||||||
if not encoding then
|
if not encoding then
|
||||||
encoding = 'utf-16'
|
encoding = 'utf-16'
|
||||||
end
|
end
|
||||||
@ -165,9 +178,6 @@ function M._str_byteindex_enc(line, index, encoding)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local _str_utfindex_enc = M._str_utfindex_enc
|
|
||||||
local _str_byteindex_enc = M._str_byteindex_enc
|
|
||||||
|
|
||||||
--- Replaces text in a range with new text.
|
--- Replaces text in a range with new text.
|
||||||
---
|
---
|
||||||
--- CAUTION: Changes in-place!
|
--- CAUTION: Changes in-place!
|
||||||
@ -334,12 +344,7 @@ local function get_line_byte_from_position(bufnr, position, offset_encoding)
|
|||||||
-- character
|
-- character
|
||||||
if col > 0 then
|
if col > 0 then
|
||||||
local line = get_line(bufnr, position.line) or ''
|
local line = get_line(bufnr, position.line) or ''
|
||||||
local ok, result
|
return M._str_byteindex_enc(line, col, offset_encoding or 'utf-16')
|
||||||
ok, result = pcall(_str_byteindex_enc, line, col, offset_encoding)
|
|
||||||
if ok then
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
return math.min(#line, col)
|
|
||||||
end
|
end
|
||||||
return col
|
return col
|
||||||
end
|
end
|
||||||
@ -436,14 +441,15 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding)
|
|||||||
e.end_col = last_line_len
|
e.end_col = last_line_len
|
||||||
has_eol_text_edit = true
|
has_eol_text_edit = true
|
||||||
else
|
else
|
||||||
-- If the replacement is over the end of a line (i.e. e.end_col is out of bounds and the
|
-- If the replacement is over the end of a line (i.e. e.end_col is equal to the line length and the
|
||||||
-- replacement text ends with a newline We can likely assume that the replacement is assumed
|
-- replacement text ends with a newline We can likely assume that the replacement is assumed
|
||||||
-- to be meant to replace the newline with another newline and we need to make sure this
|
-- to be meant to replace the newline with another newline and we need to make sure this
|
||||||
-- doesn't add an extra empty line. E.g. when the last line to be replaced contains a '\r'
|
-- doesn't add an extra empty line. E.g. when the last line to be replaced contains a '\r'
|
||||||
-- in the file some servers (clangd on windows) will include that character in the line
|
-- in the file some servers (clangd on windows) will include that character in the line
|
||||||
-- while nvim_buf_set_text doesn't count it as part of the line.
|
-- while nvim_buf_set_text doesn't count it as part of the line.
|
||||||
if
|
if
|
||||||
e.end_col > last_line_len
|
e.end_col >= last_line_len
|
||||||
|
and text_edit.range['end'].character > e.end_col
|
||||||
and #text_edit.newText > 0
|
and #text_edit.newText > 0
|
||||||
and string.sub(text_edit.newText, -1) == '\n'
|
and string.sub(text_edit.newText, -1) == '\n'
|
||||||
then
|
then
|
||||||
@ -1795,17 +1801,9 @@ function M.locations_to_items(locations, offset_encoding)
|
|||||||
local row = pos.line
|
local row = pos.line
|
||||||
local end_row = end_pos.line
|
local end_row = end_pos.line
|
||||||
local line = lines[row] or ''
|
local line = lines[row] or ''
|
||||||
local line_len = vim.fn.strcharlen(line)
|
|
||||||
local end_line = lines[end_row] or ''
|
local end_line = lines[end_row] or ''
|
||||||
local end_line_len = vim.fn.strcharlen(end_line)
|
local col = M._str_byteindex_enc(line, pos.character, offset_encoding)
|
||||||
-- LSP spec: if character > line length, default to the line length.
|
local end_col = M._str_byteindex_enc(end_line, end_pos.character, offset_encoding)
|
||||||
-- https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#position
|
|
||||||
local col = pos.character <= line_len
|
|
||||||
and M._str_byteindex_enc(line, pos.character, offset_encoding)
|
|
||||||
or line_len
|
|
||||||
local end_col = end_pos.character <= end_line_len
|
|
||||||
and M._str_byteindex_enc(end_line, end_pos.character, offset_encoding)
|
|
||||||
or end_line_len
|
|
||||||
|
|
||||||
table.insert(items, {
|
table.insert(items, {
|
||||||
filename = filename,
|
filename = filename,
|
||||||
@ -1935,7 +1933,7 @@ local function make_position_param(window, offset_encoding)
|
|||||||
return { line = 0, character = 0 }
|
return { line = 0, character = 0 }
|
||||||
end
|
end
|
||||||
|
|
||||||
col = _str_utfindex_enc(line, col, offset_encoding)
|
col = M._str_utfindex_enc(line, col, offset_encoding)
|
||||||
|
|
||||||
return { line = row, character = col }
|
return { line = row, character = col }
|
||||||
end
|
end
|
||||||
@ -2117,11 +2115,7 @@ function M.character_offset(buf, row, col, offset_encoding)
|
|||||||
)
|
)
|
||||||
offset_encoding = vim.lsp.get_clients({ bufnr = buf })[1].offset_encoding
|
offset_encoding = vim.lsp.get_clients({ bufnr = buf })[1].offset_encoding
|
||||||
end
|
end
|
||||||
-- If the col is past the EOL, use the line length.
|
return M._str_utfindex_enc(line, col, offset_encoding)
|
||||||
if col > #line then
|
|
||||||
return _str_utfindex_enc(line, nil, offset_encoding)
|
|
||||||
end
|
|
||||||
return _str_utfindex_enc(line, col, offset_encoding)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Helper function to return nested values in language server settings
|
--- Helper function to return nested values in language server settings
|
||||||
|
@ -354,6 +354,12 @@ function vim.tbl_isempty(t)
|
|||||||
return next(t) == nil
|
return next(t) == nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- We only merge empty tables or tables that are not list-like (indexed by consecutive integers
|
||||||
|
--- starting from 1)
|
||||||
|
local function can_merge(v)
|
||||||
|
return type(v) == 'table' and (vim.tbl_isempty(v) or not vim.islist(v))
|
||||||
|
end
|
||||||
|
|
||||||
--- Recursive worker for tbl_extend
|
--- Recursive worker for tbl_extend
|
||||||
--- @param behavior 'error'|'keep'|'force'
|
--- @param behavior 'error'|'keep'|'force'
|
||||||
--- @param deep_extend boolean
|
--- @param deep_extend boolean
|
||||||
@ -368,7 +374,7 @@ local function tbl_extend_rec(behavior, deep_extend, ...)
|
|||||||
local tbl = select(i, ...) --[[@as table<any,any>]]
|
local tbl = select(i, ...) --[[@as table<any,any>]]
|
||||||
if tbl then
|
if tbl then
|
||||||
for k, v in pairs(tbl) do
|
for k, v in pairs(tbl) do
|
||||||
if deep_extend and type(v) == 'table' and type(ret[k]) == 'table' then
|
if deep_extend and can_merge(v) and can_merge(ret[k]) then
|
||||||
ret[k] = tbl_extend_rec(behavior, true, ret[k], v)
|
ret[k] = tbl_extend_rec(behavior, true, ret[k], v)
|
||||||
elseif behavior ~= 'force' and ret[k] ~= nil then
|
elseif behavior ~= 'force' and ret[k] ~= nil then
|
||||||
if behavior == 'error' then
|
if behavior == 'error' then
|
||||||
@ -421,6 +427,11 @@ end
|
|||||||
|
|
||||||
--- Merges recursively two or more tables.
|
--- Merges recursively two or more tables.
|
||||||
---
|
---
|
||||||
|
--- Only values that are empty tables or tables that are not |lua-list|s (indexed by consecutive
|
||||||
|
--- integers starting from 1) are merged recursively. This is useful for merging nested tables
|
||||||
|
--- like default and user configurations where lists should be treated as literals (i.e., are
|
||||||
|
--- overwritten instead of merged).
|
||||||
|
---
|
||||||
---@see |vim.tbl_extend()|
|
---@see |vim.tbl_extend()|
|
||||||
---
|
---
|
||||||
---@generic T1: table
|
---@generic T1: table
|
||||||
|
@ -45,6 +45,11 @@
|
|||||||
(link_destination) @_url
|
(link_destination) @_url
|
||||||
(#set! @_label url @_url))
|
(#set! @_label url @_url))
|
||||||
|
|
||||||
|
(image
|
||||||
|
(image_description) @_label
|
||||||
|
(link_destination) @_url
|
||||||
|
(#set! @_label url @_url))
|
||||||
|
|
||||||
; Conceal image links
|
; Conceal image links
|
||||||
(image
|
(image
|
||||||
[
|
[
|
||||||
|
@ -33,7 +33,10 @@
|
|||||||
")"
|
")"
|
||||||
] @punctuation.bracket
|
] @punctuation.bracket
|
||||||
|
|
||||||
":" @punctuation.delimiter
|
[
|
||||||
|
":"
|
||||||
|
"/"
|
||||||
|
] @punctuation.delimiter
|
||||||
|
|
||||||
[
|
[
|
||||||
"@"
|
"@"
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
" Vim syntax file
|
" Vim syntax file
|
||||||
" Language: Configuration File (ini file) for MSDOS/MS Windows
|
" Language: Configuration File (ini file) for MSDOS/MS Windows
|
||||||
" Version: 2.3
|
" Version: 2.4
|
||||||
" Original Author: Sean M. McKee <mckee@misslink.net>
|
" Original Author: Sean M. McKee <mckee@misslink.net>
|
||||||
" Previous Maintainer: Nima Talebi <nima@it.net.au>
|
" Previous Maintainer: Nima Talebi <nima@it.net.au>
|
||||||
" Current Maintainer: Hong Xu <hong@topbug.net>
|
" Current Maintainer: Hong Xu <hong@topbug.net>
|
||||||
" Homepage: http://www.vim.org/scripts/script.php?script_id=3747
|
" Homepage: http://www.vim.org/scripts/script.php?script_id=3747
|
||||||
" Repository: https://github.com/xuhdev/syntax-dosini.vim
|
" Repository: https://github.com/xuhdev/syntax-dosini.vim
|
||||||
" Last Change: 2023 Aug 20
|
" Last Change: 2024 Sept 08
|
||||||
|
|
||||||
|
|
||||||
" quit when a syntax file was already loaded
|
" quit when a syntax file was already loaded
|
||||||
@ -27,7 +27,7 @@ syn match dosiniNumber "=\zs\s*\d\+\s*$"
|
|||||||
syn match dosiniNumber "=\zs\s*\d*\.\d\+\s*$"
|
syn match dosiniNumber "=\zs\s*\d*\.\d\+\s*$"
|
||||||
syn match dosiniNumber "=\zs\s*\d\+e[+-]\=\d\+\s*$"
|
syn match dosiniNumber "=\zs\s*\d\+e[+-]\=\d\+\s*$"
|
||||||
syn region dosiniHeader start="^\s*\[" end="\]"
|
syn region dosiniHeader start="^\s*\[" end="\]"
|
||||||
syn match dosiniComment "^[#;].*$"
|
syn match dosiniComment "^[#;].*$" contains=@Spell
|
||||||
syn region dosiniSection start="\s*\[.*\]" end="\ze\s*\[.*\]" fold
|
syn region dosiniSection start="\s*\[.*\]" end="\ze\s*\[.*\]" fold
|
||||||
\ contains=dosiniLabel,dosiniValue,dosiniNumber,dosiniHeader,dosiniComment
|
\ contains=dosiniLabel,dosiniValue,dosiniNumber,dosiniHeader,dosiniComment
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
" Interactive Data Language syntax file (IDL, too [:-)]
|
" Interactive Data Language syntax file (IDL, too [:-)]
|
||||||
" Maintainer: Aleksandar Jelenak <ajelenak AT yahoo.com>
|
" Maintainer: Aleksandar Jelenak <ajelenak AT yahoo.com>
|
||||||
" Last change: 2011 Apr 11
|
" Created By: Hermann Rochholz <Hermann.Rochholz AT gmx.de>
|
||||||
" Created by: Hermann Rochholz <Hermann.Rochholz AT gmx.de>
|
" Last Change: 2011 Apr 11
|
||||||
|
" 2024 Sep 10 by Vim Project: update syntax script, #15419
|
||||||
|
|
||||||
" Remove any old syntax stuff hanging around
|
" Remove any old syntax stuff hanging around
|
||||||
" quit when a syntax file was already loaded
|
" quit when a syntax file was already loaded
|
||||||
@ -16,7 +17,7 @@ syn match idlangStatement "^\s*function\s"
|
|||||||
syn keyword idlangStatement return continue mod do break
|
syn keyword idlangStatement return continue mod do break
|
||||||
syn keyword idlangStatement compile_opt forward_function goto
|
syn keyword idlangStatement compile_opt forward_function goto
|
||||||
syn keyword idlangStatement begin common end of
|
syn keyword idlangStatement begin common end of
|
||||||
syn keyword idlangStatement inherits on_ioerror begin
|
syn keyword idlangStatement inherits on_error on_ioerror begin
|
||||||
|
|
||||||
syn keyword idlangConditional if else then for while case switch
|
syn keyword idlangConditional if else then for while case switch
|
||||||
syn keyword idlangConditional endcase endelse endfor endswitch
|
syn keyword idlangConditional endcase endelse endfor endswitch
|
||||||
@ -82,7 +83,7 @@ syn keyword idlangRoutine CALL_EXTERNAL CALL_FUNCTION CALL_METHOD
|
|||||||
syn keyword idlangRoutine CALL_PROCEDURE CATCH CD CEIL CHEBYSHEV CHECK_MATH
|
syn keyword idlangRoutine CALL_PROCEDURE CATCH CD CEIL CHEBYSHEV CHECK_MATH
|
||||||
syn keyword idlangRoutine CHISQR_CVF CHISQR_PDF CHOLDC CHOLSOL CINDGEN
|
syn keyword idlangRoutine CHISQR_CVF CHISQR_PDF CHOLDC CHOLSOL CINDGEN
|
||||||
syn keyword idlangRoutine CIR_3PNT CLOSE CLUST_WTS CLUSTER COLOR_CONVERT
|
syn keyword idlangRoutine CIR_3PNT CLOSE CLUST_WTS CLUSTER COLOR_CONVERT
|
||||||
syn keyword idlangRoutine COLOR_QUAN COLORMAP_APPLICABLE COMFIT COMMON
|
syn keyword idlangRoutine COLOR_QUAN COLORMAP_APPLICABLE COMFIT
|
||||||
syn keyword idlangRoutine COMPLEX COMPLEXARR COMPLEXROUND
|
syn keyword idlangRoutine COMPLEX COMPLEXARR COMPLEXROUND
|
||||||
syn keyword idlangRoutine COMPUTE_MESH_NORMALS COND CONGRID CONJ
|
syn keyword idlangRoutine COMPUTE_MESH_NORMALS COND CONGRID CONJ
|
||||||
syn keyword idlangRoutine CONSTRAINED_MIN CONTOUR CONVERT_COORD CONVOL
|
syn keyword idlangRoutine CONSTRAINED_MIN CONTOUR CONVERT_COORD CONVOL
|
||||||
@ -98,7 +99,7 @@ syn keyword idlangRoutine CW_PALETTE_EDITOR_GET CW_PALETTE_EDITOR_SET
|
|||||||
syn keyword idlangRoutine CW_PDMENU CW_RGBSLIDER CW_TMPL CW_ZOOM DBLARR
|
syn keyword idlangRoutine CW_PDMENU CW_RGBSLIDER CW_TMPL CW_ZOOM DBLARR
|
||||||
syn keyword idlangRoutine DCINDGEN DCOMPLEX DCOMPLEXARR DEFINE_KEY DEFROI
|
syn keyword idlangRoutine DCINDGEN DCOMPLEX DCOMPLEXARR DEFINE_KEY DEFROI
|
||||||
syn keyword idlangRoutine DEFSYSV DELETE_SYMBOL DELLOG DELVAR DERIV DERIVSIG
|
syn keyword idlangRoutine DEFSYSV DELETE_SYMBOL DELLOG DELVAR DERIV DERIVSIG
|
||||||
syn keyword idlangRoutine DETERM DEVICE DFPMIN DIALOG_MESSAGE
|
syn keyword idlangRoutine DETERM DEVICE DFPMIN DIAG_MATRIX DIALOG_MESSAGE
|
||||||
syn keyword idlangRoutine DIALOG_PICKFILE DIALOG_PRINTERSETUP
|
syn keyword idlangRoutine DIALOG_PICKFILE DIALOG_PRINTERSETUP
|
||||||
syn keyword idlangRoutine DIALOG_PRINTJOB DIALOG_READ_IMAGE
|
syn keyword idlangRoutine DIALOG_PRINTJOB DIALOG_READ_IMAGE
|
||||||
syn keyword idlangRoutine DIALOG_WRITE_IMAGE DIGITAL_FILTER DILATE DINDGEN
|
syn keyword idlangRoutine DIALOG_WRITE_IMAGE DIGITAL_FILTER DILATE DINDGEN
|
||||||
@ -155,7 +156,7 @@ syn keyword idlangRoutine MPEG_PUT MPEG_SAVE MSG_CAT_CLOSE MSG_CAT_COMPILE
|
|||||||
syn keyword idlangRoutine MSG_CAT_OPEN MULTI N_ELEMENTS N_PARAMS N_TAGS
|
syn keyword idlangRoutine MSG_CAT_OPEN MULTI N_ELEMENTS N_PARAMS N_TAGS
|
||||||
syn keyword idlangRoutine NEWTON NORM OBJ_CLASS OBJ_DESTROY OBJ_ISA OBJ_NEW
|
syn keyword idlangRoutine NEWTON NORM OBJ_CLASS OBJ_DESTROY OBJ_ISA OBJ_NEW
|
||||||
syn keyword idlangRoutine OBJ_VALID OBJARR ON_ERROR ON_IOERROR ONLINE_HELP
|
syn keyword idlangRoutine OBJ_VALID OBJARR ON_ERROR ON_IOERROR ONLINE_HELP
|
||||||
syn keyword idlangRoutine OPEN OPENR OPENW OPLOT OPLOTERR P_CORRELATE
|
syn keyword idlangRoutine OPEN OPENR OPENW OPENU OPLOT OPLOTERR P_CORRELATE
|
||||||
syn keyword idlangRoutine PARTICLE_TRACE PCOMP PLOT PLOT_3DBOX PLOT_FIELD
|
syn keyword idlangRoutine PARTICLE_TRACE PCOMP PLOT PLOT_3DBOX PLOT_FIELD
|
||||||
syn keyword idlangRoutine PLOTERR PLOTS PNT_LINE POINT_LUN POLAR_CONTOUR
|
syn keyword idlangRoutine PLOTERR PLOTS PNT_LINE POINT_LUN POLAR_CONTOUR
|
||||||
syn keyword idlangRoutine POLAR_SURFACE POLY POLY_2D POLY_AREA POLY_FIT
|
syn keyword idlangRoutine POLAR_SURFACE POLY POLY_2D POLY_AREA POLY_FIT
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
" Maintainer: Aliaksei Budavei <0x000c70 AT gmail DOT com>
|
" Maintainer: Aliaksei Budavei <0x000c70 AT gmail DOT com>
|
||||||
" Former Maintainer: Claudio Fleiner <claudio@fleiner.com>
|
" Former Maintainer: Claudio Fleiner <claudio@fleiner.com>
|
||||||
" Repository: https://github.com/zzzyxwvut/java-vim.git
|
" Repository: https://github.com/zzzyxwvut/java-vim.git
|
||||||
" Last Change: 2024 Aug 26
|
" Last Change: 2024 Sep 10
|
||||||
|
|
||||||
" Please check :help java.vim for comments on some of the options available.
|
" Please check :help java.vim for comments on some of the options available.
|
||||||
|
|
||||||
@ -157,13 +157,20 @@ endif
|
|||||||
" testing in a project without attendant confusion for IDEs, with the
|
" testing in a project without attendant confusion for IDEs, with the
|
||||||
" ".java\=" extension used for a production version and an arbitrary
|
" ".java\=" extension used for a production version and an arbitrary
|
||||||
" extension used for a testing version.
|
" extension used for a testing version.
|
||||||
if fnamemodify(bufname("%"), ":t") =~ '^module-info\%(\.class\>\)\@!'
|
if fnamemodify(bufname("%"), ":t") =~ '^module-info\>\%(\.class\>\)\@!'
|
||||||
syn keyword javaModuleStorageClass module transitive
|
syn keyword javaModuleStorageClass module transitive
|
||||||
syn keyword javaModuleStmt open requires exports opens uses provides
|
syn keyword javaModuleStmt open requires exports opens uses provides
|
||||||
syn keyword javaModuleExternal to with
|
syn keyword javaModuleExternal to with
|
||||||
hi def link javaModuleStorageClass StorageClass
|
hi def link javaModuleStorageClass StorageClass
|
||||||
hi def link javaModuleStmt Statement
|
hi def link javaModuleStmt Statement
|
||||||
hi def link javaModuleExternal Include
|
hi def link javaModuleExternal Include
|
||||||
|
|
||||||
|
if !exists("g:java_ignore_javadoc") && g:main_syntax != 'jsp'
|
||||||
|
syn match javaDocProvidesTag contained "@provides\_s\+\S\+" contains=javaDocParam
|
||||||
|
syn match javaDocUsesTag contained "@uses\_s\+\S\+" contains=javaDocParam
|
||||||
|
hi def link javaDocProvidesTag Special
|
||||||
|
hi def link javaDocUsesTag Special
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" Fancy parameterised types (JLS-17, §4.5).
|
" Fancy parameterised types (JLS-17, §4.5).
|
||||||
@ -335,29 +342,99 @@ if !exists("g:java_ignore_javadoc") && g:main_syntax != 'jsp'
|
|||||||
call s:ReportOnce(v:exception)
|
call s:ReportOnce(v:exception)
|
||||||
endtry
|
endtry
|
||||||
|
|
||||||
syn region javaDocComment start="/\*\*" end="\*/" keepend contains=javaCommentTitle,@javaHtml,javaDocTags,javaDocSeeTag,javaDocCodeTag,javaDocSnippetTag,javaTodo,javaCommentError,javaSpaceError,@Spell fold
|
syn region javaDocComment start="/\*\*" end="\*/" keepend contains=javaCommentTitle,@javaHtml,@javaDocTags,javaTodo,javaCommentError,javaSpaceError,@Spell fold
|
||||||
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'
|
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'
|
||||||
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 javaCommentTitle contained matchgroup=javaDocComment start="/\*\*\s*\r\=\n\=\s*\**\s*\%({@return\>\)\@=" matchgroup=javaCommentTitle end="}\%(\s*\.*\)*" contains=@javaHtml,javaCommentStar,javaTodo,javaCommentError,javaSpaceError,@Spell,@javaDocTags,javaTitleSkipBlock
|
||||||
syn region javaDocTags contained start="{@\%(li\%(teral\|nk\%(plain\)\=\)\|inherit[Dd]oc\|doc[rR]oot\|value\)\>" end="}"
|
syn region javaCommentTitle contained matchgroup=javaDocComment start="/\*\*\s*\r\=\n\=\s*\**\s*\%({@summary\>\)\@=" matchgroup=javaCommentTitle end="}" contains=@javaHtml,javaCommentStar,javaTodo,javaCommentError,javaSpaceError,@Spell,@javaDocTags,javaTitleSkipBlock
|
||||||
syn match javaDocTags contained "@\%(param\|exception\|throws\|since\)\s\+\S\+" contains=javaDocParam
|
" The members of javaDocTags are sub-grouped according to the Java
|
||||||
syn match javaDocParam contained "\s\S\+"
|
" version of their introduction, and sub-group members in turn are
|
||||||
syn match javaDocTags contained "@\%(version\|author\|return\|deprecated\|serial\%(Field\|Data\)\=\)\>"
|
" arranged in alphabetical order, so that future newer members can
|
||||||
syn region javaDocSeeTag contained matchgroup=javaDocTags start="@see\s\+" matchgroup=NONE end="\_."re=e-1 contains=javaDocSeeTagParam
|
" be pre-sorted and appended without disturbing the current member
|
||||||
syn match javaDocSeeTagParam contained @"\_[^"]\+"\|<a\s\+\_.\{-}</a>\|\%(\k\|\.\)*\%(#\k\+\%((\_[^)]*)\)\=\)\=@ contains=@javaHtml extend
|
" placement.
|
||||||
|
" Since they only have significance in javaCommentTitle, neither
|
||||||
|
" javaDocSummaryTag nor javaDocReturnTitleTag are defined.
|
||||||
|
syn cluster javaDocTags contains=javaDocAuthorTag,javaDocDeprecatedTag,javaDocExceptionTag,javaDocParamTag,javaDocReturnTag,javaDocSeeTag,javaDocVersionTag,javaDocSinceTag,javaDocLinkTag,javaDocSerialTag,javaDocSerialDataTag,javaDocSerialFieldTag,javaDocThrowsTag,javaDocDocRootTag,javaDocInheritDocTag,javaDocLinkplainTag,javaDocValueTag,javaDocCodeTag,javaDocLiteralTag,javaDocHiddenTag,javaDocIndexTag,javaDocProvidesTag,javaDocUsesTag,javaDocSystemPropertyTag,javaDocSnippetTag,javaDocSpecTag
|
||||||
|
|
||||||
|
" Anticipate non-standard inline tags in {@return} and {@summary}.
|
||||||
|
syn region javaTitleSkipBlock contained transparent start="{\%(@\%(return\|summary\)\>\)\@!" end="}"
|
||||||
|
syn match javaDocDocRootTag contained "{@docRoot}"
|
||||||
|
syn match javaDocInheritDocTag contained "{@inheritDoc}"
|
||||||
|
syn region javaIndexSkipBlock contained transparent start="{\%(@index\>\)\@!" end="}" contains=javaIndexSkipBlock,javaDocIndexTag
|
||||||
|
syn region javaDocIndexTag contained start="{@index\>" end="}" contains=javaDocIndexTag,javaIndexSkipBlock
|
||||||
|
syn region javaLinkSkipBlock contained transparent start="{\%(@link\>\)\@!" end="}" contains=javaLinkSkipBlock,javaDocLinkTag
|
||||||
|
syn region javaDocLinkTag contained start="{@link\>" end="}" contains=javaDocLinkTag,javaLinkSkipBlock
|
||||||
|
syn region javaLinkplainSkipBlock contained transparent start="{\%(@linkplain\>\)\@!" end="}" contains=javaLinkplainSkipBlock,javaDocLinkplainTag
|
||||||
|
syn region javaDocLinkplainTag contained start="{@linkplain\>" end="}" contains=javaDocLinkplainTag,javaLinkplainSkipBlock
|
||||||
|
syn region javaLiteralSkipBlock contained transparent start="{\%(@literal\>\)\@!" end="}" contains=javaLiteralSkipBlock,javaDocLiteralTag
|
||||||
|
syn region javaDocLiteralTag contained start="{@literal\>" end="}" contains=javaDocLiteralTag,javaLiteralSkipBlock
|
||||||
|
syn region javaSystemPropertySkipBlock contained transparent start="{\%(@systemProperty\>\)\@!" end="}" contains=javaSystemPropertySkipBlock,javaDocSystemPropertyTag
|
||||||
|
syn region javaDocSystemPropertyTag contained start="{@systemProperty\>" end="}" contains=javaDocSystemPropertyTag,javaSystemPropertySkipBlock
|
||||||
|
syn region javaValueSkipBlock contained transparent start="{\%(@value\>\)\@!" end="}" contains=javaValueSkipBlock,javaDocValueTag
|
||||||
|
syn region javaDocValueTag contained start="{@value\>" end="}" contains=javaDocValueTag,javaValueSkipBlock
|
||||||
|
|
||||||
|
syn match javaDocParam contained "\s\zs\S\+"
|
||||||
|
syn match javaDocExceptionTag contained "@exception\s\+\S\+" contains=javaDocParam
|
||||||
|
syn match javaDocParamTag contained "@param\s\+\S\+" contains=javaDocParam
|
||||||
|
syn match javaDocSinceTag contained "@since\s\+\S\+" contains=javaDocParam
|
||||||
|
syn match javaDocThrowsTag contained "@throws\s\+\S\+" contains=javaDocParam
|
||||||
|
syn match javaDocSpecTag contained "@spec\_s\+\S\+\ze\_s\+\S\+" contains=javaDocParam
|
||||||
|
|
||||||
|
syn match javaDocAuthorTag contained "@author\>"
|
||||||
|
syn match javaDocDeprecatedTag contained "@deprecated\>"
|
||||||
|
syn match javaDocHiddenTag contained "@hidden\>"
|
||||||
|
syn match javaDocReturnTag contained "@return\>"
|
||||||
|
syn match javaDocSerialTag contained "@serial\>"
|
||||||
|
syn match javaDocSerialDataTag contained "@serialData\>"
|
||||||
|
syn match javaDocSerialFieldTag contained "@serialField\>"
|
||||||
|
syn match javaDocVersionTag contained "@version\>"
|
||||||
|
|
||||||
|
syn match javaDocSeeTag contained "@see\>" nextgroup=javaDocSeeTag1,javaDocSeeTag2,javaDocSeeTag3,javaDocSeeTagStar skipwhite skipempty
|
||||||
|
syn match javaDocSeeTagStar contained "^\s*\*\+\%(\s*{\=@\|/\|$\)\@!" nextgroup=javaDocSeeTag1,javaDocSeeTag2,javaDocSeeTag3 skipwhite skipempty
|
||||||
|
syn match javaDocSeeTag1 contained @"\_[^"]\+"@
|
||||||
|
syn match javaDocSeeTag2 contained @<a\s\+\_.\{-}</a>@ contains=@javaHtml extend
|
||||||
|
syn match javaDocSeeTag3 contained @["< \t]\@!\%(\k\|[/.]\)*\%(##\=\k\+\%((\_[^)]*)\)\=\)\=@ nextgroup=javaDocSeeTag3Label skipwhite skipempty
|
||||||
|
syn match javaDocSeeTag3Label contained @\k\%(\k\+\s*\)*$@
|
||||||
|
|
||||||
syn region javaCodeSkipBlock contained transparent start="{\%(@code\>\)\@!" end="}" contains=javaCodeSkipBlock,javaDocCodeTag
|
syn region javaCodeSkipBlock contained transparent start="{\%(@code\>\)\@!" end="}" contains=javaCodeSkipBlock,javaDocCodeTag
|
||||||
syn region javaDocCodeTag contained start="{@code\>" end="}" contains=javaDocCodeTag,javaCodeSkipBlock
|
syn region javaDocCodeTag contained start="{@code\>" end="}" contains=javaDocCodeTag,javaCodeSkipBlock
|
||||||
|
|
||||||
exec 'syn region javaDocSnippetTagAttr contained transparent matchgroup=javaHtmlArg start=/\<\%(class\|file\|id\|lang\|region\)\%(\s*=\)\@=/ matchgroup=javaHtmlString end=/:$/ end=/\%(=\s*\)\@' . s:ff.Peek('80', '') . '<=\%("[^"]\+"\|' . "\x27[^\x27]\\+\x27" . '\|\%([.\\/-]\|\k\)\+\)/ nextgroup=javaDocSnippetTagAttr skipwhite skipnl'
|
exec 'syn region javaDocSnippetTagAttr contained transparent matchgroup=javaHtmlArg start=/\<\%(class\|file\|id\|lang\|region\)\%(\s*=\)\@=/ matchgroup=javaHtmlString 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 javaSnippetSkipBlock contained transparent start="{\%(@snippet\>\)\@!" end="}" contains=javaSnippetSkipBlock,javaDocSnippetTag,javaCommentMarkupTag
|
||||||
syn region javaDocSnippetTag contained start="{@snippet\>" end="}" contains=javaDocSnippetTag,javaSnippetSkipBlock,javaDocSnippetTagAttr,javaCommentMarkupTag
|
syn region javaDocSnippetTag contained start="{@snippet\>" end="}" contains=javaDocSnippetTag,javaSnippetSkipBlock,javaDocSnippetTagAttr,javaCommentMarkupTag
|
||||||
|
|
||||||
syntax case match
|
syntax case match
|
||||||
hi def link javaDocComment Comment
|
hi def link javaDocComment Comment
|
||||||
|
hi def link javaDocSeeTagStar javaDocComment
|
||||||
hi def link javaCommentTitle SpecialComment
|
hi def link javaCommentTitle SpecialComment
|
||||||
hi def link javaDocTags Special
|
|
||||||
hi def link javaDocCodeTag Special
|
|
||||||
hi def link javaDocSnippetTag Special
|
|
||||||
hi def link javaDocSeeTagParam Function
|
|
||||||
hi def link javaDocParam Function
|
hi def link javaDocParam Function
|
||||||
|
|
||||||
|
hi def link javaDocAuthorTag Special
|
||||||
|
hi def link javaDocCodeTag Special
|
||||||
|
hi def link javaDocDeprecatedTag Special
|
||||||
|
hi def link javaDocDocRootTag Special
|
||||||
|
hi def link javaDocExceptionTag Special
|
||||||
|
hi def link javaDocHiddenTag Special
|
||||||
|
hi def link javaDocIndexTag Special
|
||||||
|
hi def link javaDocInheritDocTag Special
|
||||||
|
hi def link javaDocLinkTag Special
|
||||||
|
hi def link javaDocLinkplainTag Special
|
||||||
|
hi def link javaDocLiteralTag Special
|
||||||
|
hi def link javaDocParamTag Special
|
||||||
|
hi def link javaDocReturnTag Special
|
||||||
|
hi def link javaDocSeeTag Special
|
||||||
|
hi def link javaDocSeeTag1 String
|
||||||
|
hi def link javaDocSeeTag2 Special
|
||||||
|
hi def link javaDocSeeTag3 Function
|
||||||
|
hi def link javaDocSerialTag Special
|
||||||
|
hi def link javaDocSerialDataTag Special
|
||||||
|
hi def link javaDocSerialFieldTag Special
|
||||||
|
hi def link javaDocSinceTag Special
|
||||||
|
hi def link javaDocSnippetTag Special
|
||||||
|
hi def link javaDocSpecTag Special
|
||||||
|
hi def link javaDocSystemPropertyTag Special
|
||||||
|
hi def link javaDocThrowsTag Special
|
||||||
|
hi def link javaDocValueTag Special
|
||||||
|
hi def link javaDocVersionTag Special
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" match the special comment /**/
|
" match the special comment /**/
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
" Maintainer: Igor Gnatenko i.gnatenko.brain@gmail.com
|
" Maintainer: Igor Gnatenko i.gnatenko.brain@gmail.com
|
||||||
" Former Maintainer: Donovan Rebbechi elflord@panix.com (until March 2014)
|
" Former Maintainer: Donovan Rebbechi elflord@panix.com (until March 2014)
|
||||||
" Last Change: 2020 May 25
|
" Last Change: 2020 May 25
|
||||||
|
" 2024 Sep 10 by Vim Project: add file triggers support, #15569
|
||||||
|
|
||||||
" quit when a syntax file was already loaded
|
" quit when a syntax file was already loaded
|
||||||
if exists("b:current_syntax")
|
if exists("b:current_syntax")
|
||||||
@ -111,7 +112,7 @@ syn region specDescriptionArea matchgroup=specSection start='^%description' end=
|
|||||||
syn region specPackageArea matchgroup=specSection start='^%package' end='^%'me=e-1 contains=specPackageOpts,specPreAmble,specComment
|
syn region specPackageArea matchgroup=specSection start='^%package' end='^%'me=e-1 contains=specPackageOpts,specPreAmble,specComment
|
||||||
|
|
||||||
"%% Scripts Section %%
|
"%% Scripts Section %%
|
||||||
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
|
syn region specScriptArea matchgroup=specSection start='^%\(prep\|generate_buildrequires\|conf\|build\|install\|clean\|check\|pre\|postun\|preun\|post\|posttrans\|filetriggerin\|filetriggerun\|filetriggerpostun\|transfiletriggerin\|transfiletriggerun\|transfiletriggerpostun\)\>' 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 %%
|
"%% Changelog Section %%
|
||||||
syn region specChangelogArea matchgroup=specSection start='^%changelog' end='^%'me=e-1 contains=specEmail,specURL,specWeekday,specMonth,specNumber,specComment,specLicense
|
syn region specChangelogArea matchgroup=specSection start='^%changelog' end='^%'me=e-1 contains=specEmail,specURL,specWeekday,specMonth,specNumber,specComment,specLicense
|
||||||
|
@ -81,6 +81,14 @@ local function get_dependency(dependency_name)
|
|||||||
repo = 'luvit/luv',
|
repo = 'luvit/luv',
|
||||||
symbol = 'LUV',
|
symbol = 'LUV',
|
||||||
},
|
},
|
||||||
|
['unibilium'] = {
|
||||||
|
repo = 'neovim/unibilium',
|
||||||
|
symbol = 'UNIBILIUM',
|
||||||
|
},
|
||||||
|
['utf8proc'] = {
|
||||||
|
repo = 'JuliaStrings/utf8proc',
|
||||||
|
symbol = 'UTF8PROC',
|
||||||
|
},
|
||||||
['tree-sitter'] = {
|
['tree-sitter'] = {
|
||||||
repo = 'tree-sitter/tree-sitter',
|
repo = 'tree-sitter/tree-sitter',
|
||||||
symbol = 'TREESITTER',
|
symbol = 'TREESITTER',
|
||||||
@ -90,11 +98,11 @@ local function get_dependency(dependency_name)
|
|||||||
symbol = 'TREESITTER_C',
|
symbol = 'TREESITTER_C',
|
||||||
},
|
},
|
||||||
['tree-sitter-lua'] = {
|
['tree-sitter-lua'] = {
|
||||||
repo = 'MunifTanjim/tree-sitter-lua',
|
repo = 'tree-sitter-grammars/tree-sitter-lua',
|
||||||
symbol = 'TREESITTER_LUA',
|
symbol = 'TREESITTER_LUA',
|
||||||
},
|
},
|
||||||
['tree-sitter-vim'] = {
|
['tree-sitter-vim'] = {
|
||||||
repo = 'neovim/tree-sitter-vim',
|
repo = 'tree-sitter-grammars/tree-sitter-vim',
|
||||||
symbol = 'TREESITTER_VIM',
|
symbol = 'TREESITTER_VIM',
|
||||||
},
|
},
|
||||||
['tree-sitter-vimdoc'] = {
|
['tree-sitter-vimdoc'] = {
|
||||||
@ -102,9 +110,21 @@ local function get_dependency(dependency_name)
|
|||||||
symbol = 'TREESITTER_VIMDOC',
|
symbol = 'TREESITTER_VIMDOC',
|
||||||
},
|
},
|
||||||
['tree-sitter-query'] = {
|
['tree-sitter-query'] = {
|
||||||
repo = 'nvim-treesitter/tree-sitter-query',
|
repo = 'tree-sitter-grammars/tree-sitter-query',
|
||||||
symbol = 'TREESITTER_QUERY',
|
symbol = 'TREESITTER_QUERY',
|
||||||
},
|
},
|
||||||
|
['tree-sitter-markdown'] = {
|
||||||
|
repo = 'tree-sitter-grammars/tree-sitter-markdown',
|
||||||
|
symbol = 'TREESITTER_MARKDOWN',
|
||||||
|
},
|
||||||
|
['wasmtime'] = {
|
||||||
|
repo = 'bytecodealliance/wasmtime',
|
||||||
|
symbol = 'WASMTIME',
|
||||||
|
},
|
||||||
|
['uncrustify'] = {
|
||||||
|
repo = 'uncrustify/uncrustify',
|
||||||
|
symbol = 'UNCRUSTIFY',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
local dependency = dependency_table[dependency_name]
|
local dependency = dependency_table[dependency_name]
|
||||||
if dependency == nil then
|
if dependency == nil then
|
||||||
|
@ -3338,7 +3338,7 @@ void maketitle(void)
|
|||||||
|
|
||||||
#define SPACE_FOR_FNAME (sizeof(buf) - 100)
|
#define SPACE_FOR_FNAME (sizeof(buf) - 100)
|
||||||
#define SPACE_FOR_DIR (sizeof(buf) - 20)
|
#define SPACE_FOR_DIR (sizeof(buf) - 20)
|
||||||
#define SPACE_FOR_ARGNR (sizeof(buf) - 10) // At least room for " - NVIM".
|
#define SPACE_FOR_ARGNR (sizeof(buf) - 10) // At least room for " - Nvim".
|
||||||
char *buf_p = buf;
|
char *buf_p = buf;
|
||||||
if (curbuf->b_fname == NULL) {
|
if (curbuf->b_fname == NULL) {
|
||||||
const size_t size = xstrlcpy(buf_p, _("[No Name]"),
|
const size_t size = xstrlcpy(buf_p, _("[No Name]"),
|
||||||
@ -3412,7 +3412,7 @@ void maketitle(void)
|
|||||||
|
|
||||||
append_arg_number(curwin, buf_p, (int)(SPACE_FOR_ARGNR - (size_t)(buf_p - buf)));
|
append_arg_number(curwin, buf_p, (int)(SPACE_FOR_ARGNR - (size_t)(buf_p - buf)));
|
||||||
|
|
||||||
xstrlcat(buf_p, " - NVIM", (sizeof(buf) - (size_t)(buf_p - buf)));
|
xstrlcat(buf_p, " - Nvim", (sizeof(buf) - (size_t)(buf_p - buf)));
|
||||||
|
|
||||||
if (maxlen > 0) {
|
if (maxlen > 0) {
|
||||||
// Make it shorter by removing a bit in the middle.
|
// Make it shorter by removing a bit in the middle.
|
||||||
|
@ -8927,6 +8927,9 @@ M.funcs = {
|
|||||||
The value must not be negative. A zero value is like not
|
The value must not be negative. A zero value is like not
|
||||||
giving the argument.
|
giving the argument.
|
||||||
|
|
||||||
|
Note: the timeout is only considered when searching, not
|
||||||
|
while evaluating the {skip} expression.
|
||||||
|
|
||||||
If the {skip} expression is given it is evaluated with the
|
If the {skip} expression is given it is evaluated with the
|
||||||
cursor positioned on the start of a match. If it evaluates to
|
cursor positioned on the start of a match. If it evaluates to
|
||||||
non-zero this match is skipped. This can be used, for
|
non-zero this match is skipped. This can be used, for
|
||||||
|
@ -7641,7 +7641,7 @@ static void get_xdg_var_list(const XDGVarType xdg, typval_T *rettv)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const void *iter = NULL;
|
const void *iter = NULL;
|
||||||
const char *appname = get_appname();
|
const char *appname = get_appname(false);
|
||||||
do {
|
do {
|
||||||
size_t dir_len;
|
size_t dir_len;
|
||||||
const char *dir;
|
const char *dir;
|
||||||
|
@ -16,15 +16,14 @@ struct loop {
|
|||||||
uv_loop_t uv;
|
uv_loop_t uv;
|
||||||
MultiQueue *events;
|
MultiQueue *events;
|
||||||
MultiQueue *thread_events;
|
MultiQueue *thread_events;
|
||||||
// Immediate events:
|
// Immediate events.
|
||||||
// "Processed after exiting uv_run() (to avoid recursion), but before
|
// - "Processed after exiting `uv_run()` (to avoid recursion), but before returning from
|
||||||
// returning from loop_poll_events()." 502aee690c98
|
// `loop_poll_events()`." 502aee690c98
|
||||||
// Practical consequence (for main_loop): these events are processed by
|
// - Practical consequence (for `main_loop`):
|
||||||
// state_enter()..os_inchar()
|
// - these are processed by `state_enter()..input_get()` whereas "regular" events
|
||||||
// whereas "regular" events (main_loop.events) are processed by
|
// (`main_loop.events`) are processed by `state_enter()..VimState.execute()`
|
||||||
// state_enter()..VimState.execute()
|
// - `state_enter()..input_get()` can be "too early" if you want the event to trigger UI
|
||||||
// But state_enter()..os_inchar() can be "too early" if you want the event
|
// updates and other user-activity-related side-effects.
|
||||||
// to trigger UI updates and other user-activity-related side-effects.
|
|
||||||
MultiQueue *fast_events;
|
MultiQueue *fast_events;
|
||||||
|
|
||||||
// used by process/job-control subsystem
|
// used by process/job-control subsystem
|
||||||
|
@ -94,14 +94,17 @@ void stream_init(Loop *loop, Stream *stream, int fd, uv_stream_t *uvstream)
|
|||||||
stream->events = NULL;
|
stream->events = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stream_close(Stream *stream, stream_close_cb on_stream_close, void *data, bool rstream)
|
void stream_may_close(Stream *stream, bool rstream)
|
||||||
FUNC_ATTR_NONNULL_ARG(1)
|
FUNC_ATTR_NONNULL_ARG(1)
|
||||||
{
|
{
|
||||||
|
if (stream->closed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
assert(!stream->closed);
|
assert(!stream->closed);
|
||||||
DLOG("closing Stream: %p", (void *)stream);
|
DLOG("closing Stream: %p", (void *)stream);
|
||||||
stream->closed = true;
|
stream->closed = true;
|
||||||
stream->close_cb = on_stream_close;
|
stream->close_cb = NULL;
|
||||||
stream->close_cb_data = data;
|
stream->close_cb_data = NULL;
|
||||||
|
|
||||||
#ifdef MSWIN
|
#ifdef MSWIN
|
||||||
if (UV_TTY == uv_guess_handle(stream->fd)) {
|
if (UV_TTY == uv_guess_handle(stream->fd)) {
|
||||||
@ -115,13 +118,6 @@ void stream_close(Stream *stream, stream_close_cb on_stream_close, void *data, b
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void stream_may_close(Stream *stream, bool rstream)
|
|
||||||
{
|
|
||||||
if (!stream->closed) {
|
|
||||||
stream_close(stream, NULL, NULL, rstream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void stream_close_handle(Stream *stream, bool rstream)
|
void stream_close_handle(Stream *stream, bool rstream)
|
||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
|
@ -3264,18 +3264,12 @@ static void vim_mktempdir(void)
|
|||||||
char tmp[TEMP_FILE_PATH_MAXLEN];
|
char tmp[TEMP_FILE_PATH_MAXLEN];
|
||||||
char path[TEMP_FILE_PATH_MAXLEN];
|
char path[TEMP_FILE_PATH_MAXLEN];
|
||||||
char user[40] = { 0 };
|
char user[40] = { 0 };
|
||||||
char appname[40] = { 0 };
|
|
||||||
|
|
||||||
os_get_username(user, sizeof(user));
|
os_get_username(user, sizeof(user));
|
||||||
// Usernames may contain slashes! #19240
|
// Usernames may contain slashes! #19240
|
||||||
memchrsub(user, '/', '_', sizeof(user));
|
memchrsub(user, '/', '_', sizeof(user));
|
||||||
memchrsub(user, '\\', '_', sizeof(user));
|
memchrsub(user, '\\', '_', sizeof(user));
|
||||||
|
|
||||||
// Appname may be a relative path, replace slashes to make it name-like.
|
|
||||||
xstrlcpy(appname, get_appname(), sizeof(appname));
|
|
||||||
memchrsub(appname, '/', '%', sizeof(appname));
|
|
||||||
memchrsub(appname, '\\', '%', sizeof(appname));
|
|
||||||
|
|
||||||
// Make sure the umask doesn't remove the executable bit.
|
// Make sure the umask doesn't remove the executable bit.
|
||||||
// "repl" has been reported to use "0177".
|
// "repl" has been reported to use "0177".
|
||||||
mode_t umask_save = umask(0077);
|
mode_t umask_save = umask(0077);
|
||||||
@ -3283,14 +3277,15 @@ static void vim_mktempdir(void)
|
|||||||
// Expand environment variables, leave room for "/tmp/nvim.<user>/XXXXXX/999999999".
|
// Expand environment variables, leave room for "/tmp/nvim.<user>/XXXXXX/999999999".
|
||||||
expand_env((char *)temp_dirs[i], tmp, TEMP_FILE_PATH_MAXLEN - 64);
|
expand_env((char *)temp_dirs[i], tmp, TEMP_FILE_PATH_MAXLEN - 64);
|
||||||
if (!os_isdir(tmp)) {
|
if (!os_isdir(tmp)) {
|
||||||
|
if (strequal("$TMPDIR", temp_dirs[i])) {
|
||||||
|
WLOG("$TMPDIR tempdir not a directory (or does not exist): %s", tmp);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// "/tmp/" exists, now try to create "/tmp/nvim.<user>/".
|
// "/tmp/" exists, now try to create "/tmp/nvim.<user>/".
|
||||||
add_pathsep(tmp);
|
add_pathsep(tmp);
|
||||||
|
xstrlcat(tmp, "nvim.", sizeof(tmp));
|
||||||
xstrlcat(tmp, appname, sizeof(tmp));
|
|
||||||
xstrlcat(tmp, ".", sizeof(tmp));
|
|
||||||
xstrlcat(tmp, user, sizeof(tmp));
|
xstrlcat(tmp, user, sizeof(tmp));
|
||||||
os_mkdir(tmp, 0700); // Always create, to avoid a race.
|
os_mkdir(tmp, 0700); // Always create, to avoid a race.
|
||||||
bool owned = os_file_owned(tmp);
|
bool owned = os_file_owned(tmp);
|
||||||
|
@ -1858,7 +1858,7 @@ static void getchar_common(typval_T *argvars, typval_T *rettv)
|
|||||||
if (!char_avail()) {
|
if (!char_avail()) {
|
||||||
// Flush screen updates before blocking.
|
// Flush screen updates before blocking.
|
||||||
ui_flush();
|
ui_flush();
|
||||||
os_inchar(NULL, 0, -1, typebuf.tb_change_cnt, main_loop.events);
|
input_get(NULL, 0, -1, typebuf.tb_change_cnt, main_loop.events);
|
||||||
if (!multiqueue_empty(main_loop.events)) {
|
if (!multiqueue_empty(main_loop.events)) {
|
||||||
state_handle_k_event();
|
state_handle_k_event();
|
||||||
continue;
|
continue;
|
||||||
@ -2981,7 +2981,7 @@ int inchar(uint8_t *buf, int maxlen, long wait_time)
|
|||||||
uint8_t dum[DUM_LEN + 1];
|
uint8_t dum[DUM_LEN + 1];
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
len = os_inchar(dum, DUM_LEN, 0, 0, NULL);
|
len = input_get(dum, DUM_LEN, 0, 0, NULL);
|
||||||
if (len == 0 || (len == 1 && dum[0] == Ctrl_C)) {
|
if (len == 0 || (len == 1 && dum[0] == Ctrl_C)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2997,7 +2997,7 @@ int inchar(uint8_t *buf, int maxlen, long wait_time)
|
|||||||
|
|
||||||
// Fill up to a third of the buffer, because each character may be
|
// Fill up to a third of the buffer, because each character may be
|
||||||
// tripled below.
|
// tripled below.
|
||||||
len = os_inchar(buf, maxlen / 3, (int)wait_time, tb_change_cnt, NULL);
|
len = input_get(buf, maxlen / 3, (int)wait_time, tb_change_cnt, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the typebuf was changed further down, it is like nothing was added by
|
// If the typebuf was changed further down, it is like nothing was added by
|
||||||
|
@ -370,12 +370,15 @@ void update_window_hl(win_T *wp, bool invalid)
|
|||||||
|
|
||||||
// determine window specific background set in 'winhighlight'
|
// determine window specific background set in 'winhighlight'
|
||||||
bool float_win = wp->w_floating && !wp->w_config.external;
|
bool float_win = wp->w_floating && !wp->w_config.external;
|
||||||
if (float_win && hl_def[HLF_NFLOAT] != 0) {
|
if (float_win && hl_def[HLF_NFLOAT] != 0 && ns_id > 0) {
|
||||||
wp->w_hl_attr_normal = hl_def[HLF_NFLOAT];
|
wp->w_hl_attr_normal = hl_def[HLF_NFLOAT];
|
||||||
} else if (hl_def[HLF_COUNT] > 0) {
|
} else if (hl_def[HLF_COUNT] > 0) {
|
||||||
wp->w_hl_attr_normal = hl_def[HLF_COUNT];
|
wp->w_hl_attr_normal = hl_def[HLF_COUNT];
|
||||||
|
} else if (float_win) {
|
||||||
|
wp->w_hl_attr_normal = HL_ATTR(HLF_NFLOAT) > 0
|
||||||
|
? HL_ATTR(HLF_NFLOAT) : highlight_attr[HLF_NFLOAT];
|
||||||
} else {
|
} else {
|
||||||
wp->w_hl_attr_normal = float_win ? HL_ATTR(HLF_NFLOAT) : 0;
|
wp->w_hl_attr_normal = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wp->w_floating) {
|
if (wp->w_floating) {
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
/// @param[in] str Prompt: question to ask user. Is always followed by
|
/// @param[in] str Prompt: question to ask user. Is always followed by
|
||||||
/// " (y/n)?".
|
/// " (y/n)?".
|
||||||
/// @param[in] direct Determines what function to use to get user input. If
|
/// @param[in] direct Determines what function to use to get user input. If
|
||||||
/// true then os_inchar() will be used, otherwise vgetc().
|
/// true then input_get() will be used, otherwise vgetc().
|
||||||
/// I.e. when direct is true then characters are obtained
|
/// I.e. when direct is true then characters are obtained
|
||||||
/// directly from the user without buffers involved.
|
/// directly from the user without buffers involved.
|
||||||
///
|
///
|
||||||
@ -111,7 +111,7 @@ int get_keystroke(MultiQueue *events)
|
|||||||
|
|
||||||
// First time: blocking wait. Second time: wait up to 100ms for a
|
// First time: blocking wait. Second time: wait up to 100ms for a
|
||||||
// terminal code to complete.
|
// terminal code to complete.
|
||||||
n = os_inchar(buf + len, maxlen, len == 0 ? -1 : 100, 0, events);
|
n = input_get(buf + len, maxlen, len == 0 ? -1 : 100, 0, events);
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
// Replace zero and K_SPECIAL by a special key code.
|
// Replace zero and K_SPECIAL by a special key code.
|
||||||
n = fix_input_buffer(buf + len, n);
|
n = fix_input_buffer(buf + len, n);
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "nvim/os/stdpaths_defs.h"
|
#include "nvim/os/stdpaths_defs.h"
|
||||||
#include "nvim/os/time.h"
|
#include "nvim/os/time.h"
|
||||||
#include "nvim/path.h"
|
#include "nvim/path.h"
|
||||||
|
#include "nvim/ui_client.h"
|
||||||
|
|
||||||
/// Cached location of the expanded log file path decided by log_path_init().
|
/// Cached location of the expanded log file path decided by log_path_init().
|
||||||
static char log_file_path[MAXPATHL + 1] = { 0 };
|
static char log_file_path[MAXPATHL + 1] = { 0 };
|
||||||
@ -322,20 +323,28 @@ static bool v_do_log_to_file(FILE *log_file, int log_level, const char *context,
|
|||||||
millis = (int)curtime.tv_usec / 1000;
|
millis = (int)curtime.tv_usec / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ui = !!ui_client_channel_id; // Running as a UI client (--remote-ui).
|
||||||
|
|
||||||
|
// Regenerate the name when:
|
||||||
|
// - UI client (to ensure "ui" is in the name)
|
||||||
|
// - not set yet
|
||||||
|
// - no v:servername yet
|
||||||
|
bool regen = ui || name[0] == NUL || name[0] == '?';
|
||||||
|
|
||||||
// Get a name for this Nvim instance.
|
// Get a name for this Nvim instance.
|
||||||
// TODO(justinmk): expose this as v:name ?
|
// TODO(justinmk): expose this as v:name ?
|
||||||
if (name[0] == NUL) {
|
if (regen) {
|
||||||
// Parent servername.
|
// Parent servername ($NVIM).
|
||||||
const char *parent = path_tail(os_getenv(ENV_NVIM));
|
const char *parent = path_tail(os_getenv(ENV_NVIM));
|
||||||
// Servername. Empty until starting=false.
|
// Servername. Empty until starting=false.
|
||||||
const char *serv = path_tail(get_vim_var_str(VV_SEND_SERVER));
|
const char *serv = path_tail(get_vim_var_str(VV_SEND_SERVER));
|
||||||
if (parent[0] != NUL) {
|
if (parent[0] != NUL) {
|
||||||
snprintf(name, sizeof(name), "%s/c", parent); // "/c" indicates child.
|
snprintf(name, sizeof(name), ui ? "ui/c/%s" : "c/%s", parent); // "c/" = child of $NVIM.
|
||||||
} else if (serv[0] != NUL) {
|
} else if (serv[0] != NUL) {
|
||||||
snprintf(name, sizeof(name), "%s", serv);
|
snprintf(name, sizeof(name), ui ? "ui/%s" : "%s", serv);
|
||||||
} else {
|
} else {
|
||||||
int64_t pid = os_get_pid();
|
int64_t pid = os_get_pid();
|
||||||
snprintf(name, sizeof(name), "?.%-5" PRId64, pid);
|
snprintf(name, sizeof(name), "%s.%-5" PRId64, ui ? "ui" : "?", pid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,10 +357,6 @@ static bool v_do_log_to_file(FILE *log_file, int log_level, const char *context,
|
|||||||
log_levels[log_level], date_time, millis, name,
|
log_levels[log_level], date_time, millis, name,
|
||||||
(context == NULL ? "" : context),
|
(context == NULL ? "" : context),
|
||||||
func_name, line_num);
|
func_name, line_num);
|
||||||
if (name[0] == '?') {
|
|
||||||
// No v:servername yet. Clear `name` so that the next log can try again.
|
|
||||||
name[0] = NUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -266,7 +266,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
if (argc > 1 && STRICMP(argv[1], "-ll") == 0) {
|
if (argc > 1 && STRICMP(argv[1], "-ll") == 0) {
|
||||||
if (argc == 2) {
|
if (argc == 2) {
|
||||||
print_mainerr(err_arg_missing, argv[1]);
|
print_mainerr(err_arg_missing, argv[1], NULL);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
nlua_run_script(argv, argc, 3);
|
nlua_run_script(argv, argc, 3);
|
||||||
@ -357,10 +357,8 @@ int main(int argc, char **argv)
|
|||||||
assert(!ui_client_channel_id && !use_builtin_ui);
|
assert(!ui_client_channel_id && !use_builtin_ui);
|
||||||
// Nvim server...
|
// Nvim server...
|
||||||
|
|
||||||
int listen_rv = server_init(params.listen_addr);
|
if (!server_init(params.listen_addr)) {
|
||||||
if (listen_rv != 0) {
|
mainerr(IObuff, NULL, NULL);
|
||||||
mainerr("Failed to --listen", listen_rv < 0
|
|
||||||
? os_strerror(listen_rv) : (listen_rv == 1 ? "empty address" : NULL));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TIME_MSG("expanding arguments");
|
TIME_MSG("expanding arguments");
|
||||||
@ -1053,7 +1051,7 @@ static void command_line_scan(mparm_T *parmp)
|
|||||||
// "+" or "+{number}" or "+/{pat}" or "+{command}" argument.
|
// "+" or "+{number}" or "+/{pat}" or "+{command}" argument.
|
||||||
if (argv[0][0] == '+' && !had_minmin) {
|
if (argv[0][0] == '+' && !had_minmin) {
|
||||||
if (parmp->n_commands >= MAX_ARG_CMDS) {
|
if (parmp->n_commands >= MAX_ARG_CMDS) {
|
||||||
mainerr(err_extra_cmd, NULL);
|
mainerr(err_extra_cmd, NULL, NULL);
|
||||||
}
|
}
|
||||||
argv_idx = -1; // skip to next argument
|
argv_idx = -1; // skip to next argument
|
||||||
if (argv[0][1] == NUL) {
|
if (argv[0][1] == NUL) {
|
||||||
@ -1074,7 +1072,7 @@ static void command_line_scan(mparm_T *parmp)
|
|||||||
parmp->no_swap_file = true;
|
parmp->no_swap_file = true;
|
||||||
} else {
|
} else {
|
||||||
if (parmp->edit_type > EDIT_STDIN) {
|
if (parmp->edit_type > EDIT_STDIN) {
|
||||||
mainerr(err_too_many_args, argv[0]);
|
mainerr(err_too_many_args, argv[0], NULL);
|
||||||
}
|
}
|
||||||
parmp->had_stdin_file = true;
|
parmp->had_stdin_file = true;
|
||||||
parmp->edit_type = EDIT_STDIN;
|
parmp->edit_type = EDIT_STDIN;
|
||||||
@ -1137,7 +1135,7 @@ static void command_line_scan(mparm_T *parmp)
|
|||||||
nlua_disable_preload = true;
|
nlua_disable_preload = true;
|
||||||
} else {
|
} else {
|
||||||
if (argv[0][argv_idx]) {
|
if (argv[0][argv_idx]) {
|
||||||
mainerr(err_opt_unknown, argv[0]);
|
mainerr(err_opt_unknown, argv[0], NULL);
|
||||||
}
|
}
|
||||||
had_minmin = true;
|
had_minmin = true;
|
||||||
}
|
}
|
||||||
@ -1211,7 +1209,7 @@ static void command_line_scan(mparm_T *parmp)
|
|||||||
break;
|
break;
|
||||||
case 'q': // "-q" QuickFix mode
|
case 'q': // "-q" QuickFix mode
|
||||||
if (parmp->edit_type != EDIT_NONE) {
|
if (parmp->edit_type != EDIT_NONE) {
|
||||||
mainerr(err_too_many_args, argv[0]);
|
mainerr(err_too_many_args, argv[0], NULL);
|
||||||
}
|
}
|
||||||
parmp->edit_type = EDIT_QF;
|
parmp->edit_type = EDIT_QF;
|
||||||
if (argv[0][argv_idx]) { // "-q{errorfile}"
|
if (argv[0][argv_idx]) { // "-q{errorfile}"
|
||||||
@ -1240,7 +1238,7 @@ static void command_line_scan(mparm_T *parmp)
|
|||||||
break;
|
break;
|
||||||
case 't': // "-t {tag}" or "-t{tag}" jump to tag
|
case 't': // "-t {tag}" or "-t{tag}" jump to tag
|
||||||
if (parmp->edit_type != EDIT_NONE) {
|
if (parmp->edit_type != EDIT_NONE) {
|
||||||
mainerr(err_too_many_args, argv[0]);
|
mainerr(err_too_many_args, argv[0], NULL);
|
||||||
}
|
}
|
||||||
parmp->edit_type = EDIT_TAG;
|
parmp->edit_type = EDIT_TAG;
|
||||||
if (argv[0][argv_idx]) { // "-t{tag}"
|
if (argv[0][argv_idx]) { // "-t{tag}"
|
||||||
@ -1274,7 +1272,7 @@ static void command_line_scan(mparm_T *parmp)
|
|||||||
case 'c': // "-c{command}" or "-c {command}" exec command
|
case 'c': // "-c{command}" or "-c {command}" exec command
|
||||||
if (argv[0][argv_idx] != NUL) {
|
if (argv[0][argv_idx] != NUL) {
|
||||||
if (parmp->n_commands >= MAX_ARG_CMDS) {
|
if (parmp->n_commands >= MAX_ARG_CMDS) {
|
||||||
mainerr(err_extra_cmd, NULL);
|
mainerr(err_extra_cmd, NULL, NULL);
|
||||||
}
|
}
|
||||||
parmp->commands[parmp->n_commands++] = argv[0] + argv_idx;
|
parmp->commands[parmp->n_commands++] = argv[0] + argv_idx;
|
||||||
argv_idx = -1;
|
argv_idx = -1;
|
||||||
@ -1291,19 +1289,19 @@ static void command_line_scan(mparm_T *parmp)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
mainerr(err_opt_unknown, argv[0]);
|
mainerr(err_opt_unknown, argv[0], NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle option arguments with argument.
|
// Handle option arguments with argument.
|
||||||
if (want_argument) {
|
if (want_argument) {
|
||||||
// Check for garbage immediately after the option letter.
|
// Check for garbage immediately after the option letter.
|
||||||
if (argv[0][argv_idx] != NUL) {
|
if (argv[0][argv_idx] != NUL) {
|
||||||
mainerr(err_opt_garbage, argv[0]);
|
mainerr(err_opt_garbage, argv[0], NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
argc--;
|
argc--;
|
||||||
if (argc < 1 && c != 'S') { // -S has an optional argument
|
if (argc < 1 && c != 'S') { // -S has an optional argument
|
||||||
mainerr(err_arg_missing, argv[0]);
|
mainerr(err_arg_missing, argv[0], NULL);
|
||||||
}
|
}
|
||||||
argv++;
|
argv++;
|
||||||
argv_idx = -1;
|
argv_idx = -1;
|
||||||
@ -1312,7 +1310,7 @@ static void command_line_scan(mparm_T *parmp)
|
|||||||
case 'c': // "-c {command}" execute command
|
case 'c': // "-c {command}" execute command
|
||||||
case 'S': // "-S {file}" execute Vim script
|
case 'S': // "-S {file}" execute Vim script
|
||||||
if (parmp->n_commands >= MAX_ARG_CMDS) {
|
if (parmp->n_commands >= MAX_ARG_CMDS) {
|
||||||
mainerr(err_extra_cmd, NULL);
|
mainerr(err_extra_cmd, NULL, NULL);
|
||||||
}
|
}
|
||||||
if (c == 'S') {
|
if (c == 'S') {
|
||||||
char *a;
|
char *a;
|
||||||
@ -1343,7 +1341,7 @@ static void command_line_scan(mparm_T *parmp)
|
|||||||
if (strequal(argv[-1], "--cmd")) {
|
if (strequal(argv[-1], "--cmd")) {
|
||||||
// "--cmd {command}" execute command
|
// "--cmd {command}" execute command
|
||||||
if (parmp->n_pre_commands >= MAX_ARG_CMDS) {
|
if (parmp->n_pre_commands >= MAX_ARG_CMDS) {
|
||||||
mainerr(err_extra_cmd, NULL);
|
mainerr(err_extra_cmd, NULL, NULL);
|
||||||
}
|
}
|
||||||
parmp->pre_commands[parmp->n_pre_commands++] = argv[0];
|
parmp->pre_commands[parmp->n_pre_commands++] = argv[0];
|
||||||
} else if (strequal(argv[-1], "--listen")) {
|
} else if (strequal(argv[-1], "--listen")) {
|
||||||
@ -1425,7 +1423,7 @@ scripterror:
|
|||||||
|
|
||||||
// Check for only one type of editing.
|
// Check for only one type of editing.
|
||||||
if (parmp->edit_type > EDIT_STDIN) {
|
if (parmp->edit_type > EDIT_STDIN) {
|
||||||
mainerr(err_too_many_args, argv[0]);
|
mainerr(err_too_many_args, argv[0], NULL);
|
||||||
}
|
}
|
||||||
parmp->edit_type = EDIT_FILE;
|
parmp->edit_type = EDIT_FILE;
|
||||||
|
|
||||||
@ -1472,7 +1470,7 @@ scripterror:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (embedded_mode && (silent_mode || parmp->luaf)) {
|
if (embedded_mode && (silent_mode || parmp->luaf)) {
|
||||||
mainerr(_("--embed conflicts with -es/-Es/-l"), NULL);
|
mainerr(_("--embed conflicts with -es/-Es/-l"), NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is a "+123" or "-c" command, set v:swapcommand to the first one.
|
// If there is a "+123" or "-c" command, set v:swapcommand to the first one.
|
||||||
@ -2135,28 +2133,30 @@ static int execute_env(char *env)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prints the following then exits:
|
/// Prints a message of the form "{msg1}: {msg2}: {msg3}", then exits with code 1.
|
||||||
/// - An error message `errstr`
|
|
||||||
/// - A string `str` if not null
|
|
||||||
///
|
///
|
||||||
/// @param errstr string containing an error message
|
/// @param msg1 error message
|
||||||
/// @param str string to append to the primary error message, or NULL
|
/// @param msg2 extra message, or NULL
|
||||||
static void mainerr(const char *errstr, const char *str)
|
/// @param msg3 extra message, or NULL
|
||||||
|
static void mainerr(const char *msg1, const char *msg2, const char *msg3)
|
||||||
FUNC_ATTR_NORETURN
|
FUNC_ATTR_NORETURN
|
||||||
{
|
{
|
||||||
print_mainerr(errstr, str);
|
print_mainerr(msg1, msg2, msg3);
|
||||||
os_exit(1);
|
os_exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_mainerr(const char *errstr, const char *str)
|
static void print_mainerr(const char *msg1, const char *msg2, const char *msg3)
|
||||||
{
|
{
|
||||||
char *prgname = path_tail(argv0);
|
char *prgname = path_tail(argv0);
|
||||||
|
|
||||||
signal_stop(); // kill us with CTRL-C here, if you like
|
signal_stop(); // kill us with CTRL-C here, if you like
|
||||||
|
|
||||||
fprintf(stderr, "%s: %s", prgname, _(errstr));
|
fprintf(stderr, "%s: %s", prgname, _(msg1));
|
||||||
if (str != NULL) {
|
if (msg2 != NULL) {
|
||||||
fprintf(stderr, ": \"%s\"", str);
|
fprintf(stderr, ": \"%s\"", msg2);
|
||||||
|
}
|
||||||
|
if (msg3 != NULL) {
|
||||||
|
fprintf(stderr, ": \"%s\"", msg3);
|
||||||
}
|
}
|
||||||
fprintf(stderr, _("\nMore info with \""));
|
fprintf(stderr, _("\nMore info with \""));
|
||||||
fprintf(stderr, "%s -h\"\n", prgname);
|
fprintf(stderr, "%s -h\"\n", prgname);
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
/// HACK: os/input.c drains this queue immediately before blocking for input.
|
/// HACK: os/input.c drains this queue immediately before blocking for input.
|
||||||
/// Events on this queue are async-safe, but they need the resolved state
|
/// Events on this queue are async-safe, but they need the resolved state
|
||||||
/// of os_inchar(), so they are processed "just-in-time".
|
/// of input_get(), so they are processed "just-in-time".
|
||||||
EXTERN MultiQueue *ch_before_blocking_events INIT( = NULL);
|
EXTERN MultiQueue *ch_before_blocking_events INIT( = NULL);
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
|
@ -11,12 +11,14 @@
|
|||||||
#include "nvim/event/socket.h"
|
#include "nvim/event/socket.h"
|
||||||
#include "nvim/garray.h"
|
#include "nvim/garray.h"
|
||||||
#include "nvim/garray_defs.h"
|
#include "nvim/garray_defs.h"
|
||||||
|
#include "nvim/globals.h"
|
||||||
#include "nvim/log.h"
|
#include "nvim/log.h"
|
||||||
#include "nvim/main.h"
|
#include "nvim/main.h"
|
||||||
#include "nvim/memory.h"
|
#include "nvim/memory.h"
|
||||||
#include "nvim/msgpack_rpc/server.h"
|
#include "nvim/msgpack_rpc/server.h"
|
||||||
#include "nvim/os/os.h"
|
#include "nvim/os/os.h"
|
||||||
#include "nvim/os/stdpaths_defs.h"
|
#include "nvim/os/stdpaths_defs.h"
|
||||||
|
#include "nvim/types_defs.h"
|
||||||
|
|
||||||
#define MAX_CONNECTIONS 32
|
#define MAX_CONNECTIONS 32
|
||||||
#define ENV_LISTEN "NVIM_LISTEN_ADDRESS" // deprecated
|
#define ENV_LISTEN "NVIM_LISTEN_ADDRESS" // deprecated
|
||||||
@ -27,37 +29,31 @@ static garray_T watchers = GA_EMPTY_INIT_VALUE;
|
|||||||
# include "msgpack_rpc/server.c.generated.h"
|
# include "msgpack_rpc/server.c.generated.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// Initializes the module
|
/// Initializes resources, handles `--listen`, starts the primary server at v:servername.
|
||||||
///
|
///
|
||||||
/// @returns 0: success, 1: validation error, 2: already listening, -errno: failed to bind/listen.
|
/// @returns true on success, false on fatal error (message stored in IObuff)
|
||||||
int server_init(const char *listen_addr)
|
bool server_init(const char *listen_addr)
|
||||||
{
|
{
|
||||||
|
bool ok = true;
|
||||||
bool must_free = false;
|
bool must_free = false;
|
||||||
|
TriState user_arg = kTrue; // User-provided --listen arg.
|
||||||
ga_init(&watchers, sizeof(SocketWatcher *), 1);
|
ga_init(&watchers, sizeof(SocketWatcher *), 1);
|
||||||
|
|
||||||
// $NVIM_LISTEN_ADDRESS (deprecated)
|
// $NVIM_LISTEN_ADDRESS (deprecated)
|
||||||
if ((!listen_addr || listen_addr[0] == '\0') && os_env_exists(ENV_LISTEN)) {
|
if ((!listen_addr || listen_addr[0] == '\0') && os_env_exists(ENV_LISTEN)) {
|
||||||
|
user_arg = kFalse; // User-provided env var.
|
||||||
listen_addr = os_getenv(ENV_LISTEN);
|
listen_addr = os_getenv(ENV_LISTEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!listen_addr || listen_addr[0] == '\0') {
|
if (!listen_addr || listen_addr[0] == '\0') {
|
||||||
|
user_arg = kNone; // Autogenerated server address.
|
||||||
listen_addr = server_address_new(NULL);
|
listen_addr = server_address_new(NULL);
|
||||||
must_free = true;
|
must_free = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!listen_addr) {
|
|
||||||
abort(); // Cannot happen.
|
|
||||||
}
|
|
||||||
|
|
||||||
int rv = server_start(listen_addr);
|
int rv = server_start(listen_addr);
|
||||||
|
|
||||||
if (os_env_exists(ENV_LISTEN)) {
|
// TODO(justinmk): this is for log_spec. Can remove this after nvim_log #7062 is merged.
|
||||||
// Unset $NVIM_LISTEN_ADDRESS, it's a liability hereafter. It is "input only", it must not be
|
|
||||||
// leaked to child jobs or :terminal.
|
|
||||||
os_unsetenv(ENV_LISTEN);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(justinmk): this is for logging_spec. Can remove this after nvim_log #7062 is merged.
|
|
||||||
if (os_env_exists("__NVIM_TEST_LOG")) {
|
if (os_env_exists("__NVIM_TEST_LOG")) {
|
||||||
ELOG("test log message");
|
ELOG("test log message");
|
||||||
}
|
}
|
||||||
@ -66,7 +62,28 @@ int server_init(const char *listen_addr)
|
|||||||
xfree((char *)listen_addr);
|
xfree((char *)listen_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
if (rv == 0 || user_arg == kNone) {
|
||||||
|
// The autogenerated servername can fail if the user has a broken $XDG_RUNTIME_DIR. #30282
|
||||||
|
// But that is not fatal (startup will continue, logged in $NVIM_LOGFILE, empty v:servername).
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)snprintf(IObuff, IOSIZE,
|
||||||
|
user_arg ==
|
||||||
|
kTrue ? "Failed to --listen: %s: \"%s\""
|
||||||
|
: "Failed $NVIM_LISTEN_ADDRESS: %s: \"%s\"",
|
||||||
|
rv < 0 ? os_strerror(rv) : (rv == 1 ? "empty address" : "?"),
|
||||||
|
listen_addr);
|
||||||
|
ok = false;
|
||||||
|
|
||||||
|
end:
|
||||||
|
if (os_env_exists(ENV_LISTEN)) {
|
||||||
|
// Unset $NVIM_LISTEN_ADDRESS, it's a liability hereafter. It is "input only", it must not be
|
||||||
|
// leaked to child jobs or :terminal.
|
||||||
|
os_unsetenv(ENV_LISTEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Teardown a single server
|
/// Teardown a single server
|
||||||
@ -97,17 +114,19 @@ void server_teardown(void)
|
|||||||
/// - Windows: "\\.\pipe\<name>.<pid>.<counter>"
|
/// - Windows: "\\.\pipe\<name>.<pid>.<counter>"
|
||||||
/// - Other: "/tmp/nvim.user/xxx/<name>.<pid>.<counter>"
|
/// - Other: "/tmp/nvim.user/xxx/<name>.<pid>.<counter>"
|
||||||
char *server_address_new(const char *name)
|
char *server_address_new(const char *name)
|
||||||
|
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_RET
|
||||||
{
|
{
|
||||||
static uint32_t count = 0;
|
static uint32_t count = 0;
|
||||||
char fmt[ADDRESS_MAX_SIZE];
|
char fmt[ADDRESS_MAX_SIZE];
|
||||||
const char *appname = get_appname();
|
|
||||||
#ifdef MSWIN
|
#ifdef MSWIN
|
||||||
|
(void)get_appname(true);
|
||||||
int r = snprintf(fmt, sizeof(fmt), "\\\\.\\pipe\\%s.%" PRIu64 ".%" PRIu32,
|
int r = snprintf(fmt, sizeof(fmt), "\\\\.\\pipe\\%s.%" PRIu64 ".%" PRIu32,
|
||||||
name ? name : appname, os_get_pid(), count++);
|
name ? name : NameBuff, os_get_pid(), count++);
|
||||||
#else
|
#else
|
||||||
char *dir = stdpaths_get_xdg_var(kXDGRuntimeDir);
|
char *dir = stdpaths_get_xdg_var(kXDGRuntimeDir);
|
||||||
|
(void)get_appname(true);
|
||||||
int r = snprintf(fmt, sizeof(fmt), "%s/%s.%" PRIu64 ".%" PRIu32,
|
int r = snprintf(fmt, sizeof(fmt), "%s/%s.%" PRIu64 ".%" PRIu32,
|
||||||
dir, name ? name : appname, os_get_pid(), count++);
|
dir, name ? name : NameBuff, os_get_pid(), count++);
|
||||||
xfree(dir);
|
xfree(dir);
|
||||||
#endif
|
#endif
|
||||||
if ((size_t)r >= sizeof(fmt)) {
|
if ((size_t)r >= sizeof(fmt)) {
|
||||||
|
@ -6597,11 +6597,11 @@ static void nv_open(cmdarg_T *cap)
|
|||||||
static void nv_event(cmdarg_T *cap)
|
static void nv_event(cmdarg_T *cap)
|
||||||
{
|
{
|
||||||
// Garbage collection should have been executed before blocking for events in
|
// Garbage collection should have been executed before blocking for events in
|
||||||
// the `os_inchar` in `state_enter`, but we also disable it here in case the
|
// the `input_get` in `state_enter`, but we also disable it here in case the
|
||||||
// `os_inchar` branch was not executed (!multiqueue_empty(loop.events), which
|
// `input_get` branch was not executed (!multiqueue_empty(loop.events), which
|
||||||
// could have `may_garbage_collect` set to true in `normal_check`).
|
// could have `may_garbage_collect` set to true in `normal_check`).
|
||||||
//
|
//
|
||||||
// That is because here we may run code that calls `os_inchar`
|
// That is because here we may run code that calls `input_get`
|
||||||
// later(`f_confirm` or `get_keystroke` for example), but in these cases it is
|
// later(`f_confirm` or `get_keystroke` for example), but in these cases it is
|
||||||
// not safe to perform garbage collection because there could be unreferenced
|
// not safe to perform garbage collection because there could be unreferenced
|
||||||
// lists or dicts being used.
|
// lists or dicts being used.
|
||||||
|
@ -210,39 +210,53 @@ static void set_init_default_backupskip(void)
|
|||||||
OptIndex opt_idx = kOptBackupskip;
|
OptIndex opt_idx = kOptBackupskip;
|
||||||
|
|
||||||
ga_init(&ga, 1, 100);
|
ga_init(&ga, 1, 100);
|
||||||
for (size_t n = 0; n < ARRAY_SIZE(names); n++) {
|
for (size_t i = 0; i < ARRAY_SIZE(names); i++) {
|
||||||
bool mustfree = true;
|
bool mustfree = true;
|
||||||
char *p;
|
char *p;
|
||||||
|
size_t plen;
|
||||||
#ifdef UNIX
|
#ifdef UNIX
|
||||||
if (*names[n] == NUL) {
|
if (*names[i] == NUL) {
|
||||||
# ifdef __APPLE__
|
# ifdef __APPLE__
|
||||||
p = "/private/tmp";
|
p = "/private/tmp";
|
||||||
|
plen = STRLEN_LITERAL("/private/tmp");
|
||||||
# else
|
# else
|
||||||
p = "/tmp";
|
p = "/tmp";
|
||||||
|
plen = STRLEN_LITERAL("/tmp");
|
||||||
# endif
|
# endif
|
||||||
mustfree = false;
|
mustfree = false;
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
p = vim_getenv(names[n]);
|
p = vim_getenv(names[i]);
|
||||||
|
plen = 0; // will be calcuated below
|
||||||
}
|
}
|
||||||
if (p != NULL && *p != NUL) {
|
if (p != NULL && *p != NUL) {
|
||||||
// First time count the NUL, otherwise count the ','.
|
bool has_trailing_path_sep = false;
|
||||||
const size_t len = strlen(p) + 3;
|
|
||||||
char *item = xmalloc(len);
|
if (plen == 0) {
|
||||||
xstrlcpy(item, p, len);
|
// the value was retrieved from the environment
|
||||||
add_pathsep(item);
|
plen = strlen(p);
|
||||||
xstrlcat(item, "*", len);
|
// does the value include a trailing path separator?
|
||||||
if (find_dup_item(ga.ga_data, item, options[opt_idx].flags)
|
if (after_pathsep(p, p + plen)) {
|
||||||
== NULL) {
|
has_trailing_path_sep = true;
|
||||||
ga_grow(&ga, (int)len);
|
|
||||||
if (!GA_EMPTY(&ga)) {
|
|
||||||
strcat(ga.ga_data, ",");
|
|
||||||
}
|
}
|
||||||
strcat(ga.ga_data, p);
|
}
|
||||||
add_pathsep(ga.ga_data);
|
|
||||||
strcat(ga.ga_data, "*");
|
// item size needs to be large enough to include "/*" and a trailing NUL
|
||||||
ga.ga_len += (int)len;
|
// note: the value (and therefore plen) may already include a path separator
|
||||||
|
size_t itemsize = plen + (has_trailing_path_sep ? 0 : 1) + 2;
|
||||||
|
char *item = xmalloc(itemsize);
|
||||||
|
// add a preceeding comma as a separator after the first item
|
||||||
|
size_t itemseplen = (ga.ga_len == 0) ? 0 : 1;
|
||||||
|
|
||||||
|
size_t itemlen = (size_t)vim_snprintf(item, itemsize, "%s%s*", p,
|
||||||
|
has_trailing_path_sep ? "" : PATHSEPSTR);
|
||||||
|
|
||||||
|
if (find_dup_item(ga.ga_data, item, itemlen, options[opt_idx].flags) == NULL) {
|
||||||
|
ga_grow(&ga, (int)(itemseplen + itemlen + 1));
|
||||||
|
ga.ga_len += vim_snprintf((char *)ga.ga_data + ga.ga_len,
|
||||||
|
itemseplen + itemlen + 1,
|
||||||
|
"%s%s", (itemseplen > 0) ? "," : "", item);
|
||||||
}
|
}
|
||||||
xfree(item);
|
xfree(item);
|
||||||
}
|
}
|
||||||
@ -526,7 +540,8 @@ static void set_string_default(OptIndex opt_idx, char *val, bool allocated)
|
|||||||
|
|
||||||
/// For an option value that contains comma separated items, find "newval" in
|
/// For an option value that contains comma separated items, find "newval" in
|
||||||
/// "origval". Return NULL if not found.
|
/// "origval". Return NULL if not found.
|
||||||
static char *find_dup_item(char *origval, const char *newval, uint32_t flags)
|
static char *find_dup_item(char *origval, const char *newval, const size_t newvallen,
|
||||||
|
uint32_t flags)
|
||||||
FUNC_ATTR_NONNULL_ARG(2)
|
FUNC_ATTR_NONNULL_ARG(2)
|
||||||
{
|
{
|
||||||
if (origval == NULL) {
|
if (origval == NULL) {
|
||||||
@ -535,11 +550,10 @@ static char *find_dup_item(char *origval, const char *newval, uint32_t flags)
|
|||||||
|
|
||||||
int bs = 0;
|
int bs = 0;
|
||||||
|
|
||||||
const size_t newlen = strlen(newval);
|
|
||||||
for (char *s = origval; *s != NUL; s++) {
|
for (char *s = origval; *s != NUL; s++) {
|
||||||
if ((!(flags & P_COMMA) || s == origval || (s[-1] == ',' && !(bs & 1)))
|
if ((!(flags & P_COMMA) || s == origval || (s[-1] == ',' && !(bs & 1)))
|
||||||
&& strncmp(s, newval, newlen) == 0
|
&& strncmp(s, newval, newvallen) == 0
|
||||||
&& (!(flags & P_COMMA) || s[newlen] == ',' || s[newlen] == NUL)) {
|
&& (!(flags & P_COMMA) || s[newvallen] == ',' || s[newvallen] == NUL)) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
// Count backslashes. Only a comma with an even number of backslashes
|
// Count backslashes. Only a comma with an even number of backslashes
|
||||||
@ -697,10 +711,10 @@ void set_helplang_default(const char *lang)
|
|||||||
}
|
}
|
||||||
p_hlg = xmemdupz(lang, lang_len);
|
p_hlg = xmemdupz(lang, lang_len);
|
||||||
// zh_CN becomes "cn", zh_TW becomes "tw".
|
// zh_CN becomes "cn", zh_TW becomes "tw".
|
||||||
if (STRNICMP(p_hlg, "zh_", 3) == 0 && strlen(p_hlg) >= 5) {
|
if (STRNICMP(p_hlg, "zh_", 3) == 0 && lang_len >= 5) {
|
||||||
p_hlg[0] = (char)TOLOWER_ASC(p_hlg[3]);
|
p_hlg[0] = (char)TOLOWER_ASC(p_hlg[3]);
|
||||||
p_hlg[1] = (char)TOLOWER_ASC(p_hlg[4]);
|
p_hlg[1] = (char)TOLOWER_ASC(p_hlg[4]);
|
||||||
} else if (strlen(p_hlg) >= 1 && *p_hlg == 'C') {
|
} else if (lang_len && *p_hlg == 'C') {
|
||||||
// any C like setting, such as C.UTF-8, becomes "en"
|
// any C like setting, such as C.UTF-8, becomes "en"
|
||||||
p_hlg[0] = 'e';
|
p_hlg[0] = 'e';
|
||||||
p_hlg[1] = 'n';
|
p_hlg[1] = 'n';
|
||||||
@ -950,7 +964,7 @@ static char *stropt_get_newval(int nextchar, OptIndex opt_idx, char **argp, void
|
|||||||
int len = 0;
|
int len = 0;
|
||||||
if (op == OP_REMOVING || (flags & P_NODUP)) {
|
if (op == OP_REMOVING || (flags & P_NODUP)) {
|
||||||
len = (int)strlen(newval);
|
len = (int)strlen(newval);
|
||||||
s = find_dup_item(origval, newval, flags);
|
s = find_dup_item(origval, newval, (size_t)len, flags);
|
||||||
|
|
||||||
// do not add if already there
|
// do not add if already there
|
||||||
if ((op == OP_ADDING || op == OP_PREPENDING) && s != NULL) {
|
if ((op == OP_ADDING || op == OP_PREPENDING) && s != NULL) {
|
||||||
@ -1464,11 +1478,10 @@ int do_set(char *arg, int opt_flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (errmsg != NULL) {
|
if (errmsg != NULL) {
|
||||||
xstrlcpy(IObuff, _(errmsg), IOSIZE);
|
int i = vim_snprintf((char *)IObuff, IOSIZE, "%s", _(errmsg)) + 2;
|
||||||
int i = (int)strlen(IObuff) + 2;
|
|
||||||
if (i + (arg - startarg) < IOSIZE) {
|
if (i + (arg - startarg) < IOSIZE) {
|
||||||
// append the argument with the error
|
// append the argument with the error
|
||||||
xstrlcat(IObuff, ": ", IOSIZE);
|
xstrlcpy(IObuff + i - 2, ": ", (size_t)(IOSIZE - i + 2));
|
||||||
assert(arg >= startarg);
|
assert(arg >= startarg);
|
||||||
memmove(IObuff + i, startarg, (size_t)(arg - startarg));
|
memmove(IObuff + i, startarg, (size_t)(arg - startarg));
|
||||||
IObuff[i + (arg - startarg)] = NUL;
|
IObuff[i + (arg - startarg)] = NUL;
|
||||||
@ -5431,7 +5444,8 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
|
|||||||
xp->xp_pattern = arg;
|
xp->xp_pattern = arg;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
char *p = arg + strlen(arg) - 1;
|
char *const argend = arg + strlen(arg);
|
||||||
|
char *p = argend - 1;
|
||||||
if (*p == ' ' && *(p - 1) != '\\') {
|
if (*p == ' ' && *(p - 1) != '\\') {
|
||||||
xp->xp_pattern = p + 1;
|
xp->xp_pattern = p + 1;
|
||||||
return;
|
return;
|
||||||
@ -5618,7 +5632,7 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
|
|||||||
// Triple-backslashed escaped file names (e.g. 'path') can also be
|
// Triple-backslashed escaped file names (e.g. 'path') can also be
|
||||||
// delimited by space.
|
// delimited by space.
|
||||||
if ((flags & P_EXPAND) || (flags & P_COMMA) || (flags & P_COLON)) {
|
if ((flags & P_EXPAND) || (flags & P_COMMA) || (flags & P_COLON)) {
|
||||||
for (p = arg + strlen(arg) - 1; p > xp->xp_pattern; p--) {
|
for (p = argend - 1; p > xp->xp_pattern; p--) {
|
||||||
// count number of backslashes before ' ' or ','
|
// count number of backslashes before ' ' or ','
|
||||||
if (*p == ' ' || *p == ',' || (*p == ':' && (flags & P_COLON))) {
|
if (*p == ' ' || *p == ',' || (*p == ':' && (flags & P_COLON))) {
|
||||||
char *s = p;
|
char *s = p;
|
||||||
@ -5642,7 +5656,7 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
|
|||||||
// An option that is a list of single-character flags should always start
|
// An option that is a list of single-character flags should always start
|
||||||
// at the end as we don't complete words.
|
// at the end as we don't complete words.
|
||||||
if (flags & P_FLAGLIST) {
|
if (flags & P_FLAGLIST) {
|
||||||
xp->xp_pattern = arg + strlen(arg);
|
xp->xp_pattern = argend;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some options can either be using file/dir expansions, or custom value
|
// Some options can either be using file/dir expansions, or custom value
|
||||||
@ -5952,7 +5966,7 @@ int ExpandSettingSubtract(expand_T *xp, regmatch_T *regmatch, int *numMatches, c
|
|||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
(*matches)[count++] = xstrdup(option_val);
|
(*matches)[count++] = xmemdupz(option_val, num_flags);
|
||||||
|
|
||||||
if (num_flags > 1) {
|
if (num_flags > 1) {
|
||||||
// If more than one flags, split the flags up and expose each
|
// If more than one flags, split the flags up and expose each
|
||||||
|
@ -9047,7 +9047,7 @@ return {
|
|||||||
desc = [=[
|
desc = [=[
|
||||||
When on, the title of the window will be set to the value of
|
When on, the title of the window will be set to the value of
|
||||||
'titlestring' (if it is not empty), or to:
|
'titlestring' (if it is not empty), or to:
|
||||||
filename [+=-] (path) - NVIM
|
filename [+=-] (path) - Nvim
|
||||||
Where:
|
Where:
|
||||||
filename the name of the file being edited
|
filename the name of the file being edited
|
||||||
- indicates the file cannot be modified, 'ma' off
|
- indicates the file cannot be modified, 'ma' off
|
||||||
@ -9055,11 +9055,11 @@ return {
|
|||||||
= indicates the file is read-only
|
= indicates the file is read-only
|
||||||
=+ indicates the file is read-only and modified
|
=+ indicates the file is read-only and modified
|
||||||
(path) is the path of the file being edited
|
(path) is the path of the file being edited
|
||||||
- NVIM the server name |v:servername| or "NVIM"
|
- Nvim the server name |v:servername| or "Nvim"
|
||||||
]=],
|
]=],
|
||||||
full_name = 'title',
|
full_name = 'title',
|
||||||
scope = { 'global' },
|
scope = { 'global' },
|
||||||
short_desc = N_('Vim set the title of the window'),
|
short_desc = N_('set the title of the window'),
|
||||||
type = 'boolean',
|
type = 'boolean',
|
||||||
varname = 'p_title',
|
varname = 'p_title',
|
||||||
},
|
},
|
||||||
|
@ -33,12 +33,6 @@
|
|||||||
#define READ_BUFFER_SIZE 0xfff
|
#define READ_BUFFER_SIZE 0xfff
|
||||||
#define INPUT_BUFFER_SIZE ((READ_BUFFER_SIZE * 4) + MAX_KEY_CODE_LEN)
|
#define INPUT_BUFFER_SIZE ((READ_BUFFER_SIZE * 4) + MAX_KEY_CODE_LEN)
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
kInputNone,
|
|
||||||
kInputAvail,
|
|
||||||
kInputEof,
|
|
||||||
} InbufPollResult;
|
|
||||||
|
|
||||||
static RStream read_stream = { .s.closed = true }; // Input before UI starts.
|
static RStream read_stream = { .s.closed = true }; // Input before UI starts.
|
||||||
static char input_buffer[INPUT_BUFFER_SIZE];
|
static char input_buffer[INPUT_BUFFER_SIZE];
|
||||||
static char *input_read_pos = input_buffer;
|
static char *input_read_pos = input_buffer;
|
||||||
@ -84,57 +78,76 @@ static void cursorhold_event(void **argv)
|
|||||||
static void create_cursorhold_event(bool events_enabled)
|
static void create_cursorhold_event(bool events_enabled)
|
||||||
{
|
{
|
||||||
// If events are enabled and the queue has any items, this function should not
|
// If events are enabled and the queue has any items, this function should not
|
||||||
// have been called (inbuf_poll would return kInputAvail).
|
// have been called (`inbuf_poll` would return `kTrue`).
|
||||||
// TODO(tarruda): Cursorhold should be implemented as a timer set during the
|
// TODO(tarruda): Cursorhold should be implemented as a timer set during the
|
||||||
// `state_check` callback for the states where it can be triggered.
|
// `state_check` callback for the states where it can be triggered.
|
||||||
assert(!events_enabled || multiqueue_empty(main_loop.events));
|
assert(!events_enabled || multiqueue_empty(main_loop.events));
|
||||||
multiqueue_put(main_loop.events, cursorhold_event, NULL);
|
multiqueue_put(main_loop.events, cursorhold_event, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void restart_cursorhold_wait(int tb_change_cnt)
|
static void reset_cursorhold_wait(int tb_change_cnt)
|
||||||
{
|
{
|
||||||
cursorhold_time = 0;
|
cursorhold_time = 0;
|
||||||
cursorhold_tb_change_cnt = tb_change_cnt;
|
cursorhold_tb_change_cnt = tb_change_cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Low level input function
|
/// Reads OS input into `buf`, and consumes pending events while waiting (if `ms != 0`).
|
||||||
///
|
///
|
||||||
/// Wait until either the input buffer is non-empty or, if `events` is not NULL
|
/// - Consumes available input received from the OS.
|
||||||
/// until `events` is non-empty.
|
/// - Consumes pending events.
|
||||||
int os_inchar(uint8_t *buf, int maxlen, int ms, int tb_change_cnt, MultiQueue *events)
|
/// - Manages CursorHold events.
|
||||||
|
/// - Handles EOF conditions.
|
||||||
|
///
|
||||||
|
/// Originally based on the Vim `mch_inchar` function.
|
||||||
|
///
|
||||||
|
/// @param buf Buffer to store consumed input.
|
||||||
|
/// @param maxlen Maximum bytes to read into `buf`, or 0 to skip reading.
|
||||||
|
/// @param ms Timeout in milliseconds. -1 for indefinite wait, 0 for no wait.
|
||||||
|
/// @param tb_change_cnt Used to detect when typeahead changes.
|
||||||
|
/// @param events (optional) Events to process.
|
||||||
|
/// @return Bytes read into buf, or 0 if no input was read
|
||||||
|
int input_get(uint8_t *buf, int maxlen, int ms, int tb_change_cnt, MultiQueue *events)
|
||||||
{
|
{
|
||||||
// This check is needed so that feeding typeahead from RPC can prevent CursorHold.
|
// This check is needed so that feeding typeahead from RPC can prevent CursorHold.
|
||||||
if (tb_change_cnt != cursorhold_tb_change_cnt) {
|
if (tb_change_cnt != cursorhold_tb_change_cnt) {
|
||||||
restart_cursorhold_wait(tb_change_cnt);
|
reset_cursorhold_wait(tb_change_cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maxlen && input_available()) {
|
#define TRY_READ() \
|
||||||
restart_cursorhold_wait(tb_change_cnt);
|
do { \
|
||||||
size_t to_read = MIN((size_t)maxlen, input_available());
|
if (maxlen && input_available()) { \
|
||||||
memcpy(buf, input_read_pos, to_read);
|
reset_cursorhold_wait(tb_change_cnt); \
|
||||||
input_read_pos += to_read;
|
assert(maxlen >= 0); \
|
||||||
return (int)to_read;
|
size_t to_read = MIN((size_t)maxlen, input_available()); \
|
||||||
}
|
memcpy(buf, input_read_pos, to_read); \
|
||||||
|
input_read_pos += to_read; \
|
||||||
|
/* This is safe because INPUT_BUFFER_SIZE fits in an int. */ \
|
||||||
|
assert(to_read <= INT_MAX); \
|
||||||
|
return (int)to_read; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
TRY_READ();
|
||||||
|
|
||||||
// No risk of a UI flood, so disable CTRL-C "interrupt" behavior if it's mapped.
|
// No risk of a UI flood, so disable CTRL-C "interrupt" behavior if it's mapped.
|
||||||
if ((mapped_ctrl_c | curbuf->b_mapped_ctrl_c) & get_real_state()) {
|
if ((mapped_ctrl_c | curbuf->b_mapped_ctrl_c) & get_real_state()) {
|
||||||
ctrl_c_interrupts = false;
|
ctrl_c_interrupts = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
InbufPollResult result;
|
TriState result; ///< inbuf_poll result.
|
||||||
if (ms >= 0) {
|
if (ms >= 0) {
|
||||||
if ((result = inbuf_poll(ms, events)) == kInputNone) {
|
if ((result = inbuf_poll(ms, events)) == kFalse) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
uint64_t wait_start = os_hrtime();
|
uint64_t wait_start = os_hrtime();
|
||||||
cursorhold_time = MIN(cursorhold_time, (int)p_ut);
|
cursorhold_time = MIN(cursorhold_time, (int)p_ut);
|
||||||
if ((result = inbuf_poll((int)p_ut - cursorhold_time, events)) == kInputNone) {
|
if ((result = inbuf_poll((int)p_ut - cursorhold_time, events)) == kFalse) {
|
||||||
if (read_stream.s.closed && silent_mode) {
|
if (read_stream.s.closed && silent_mode) {
|
||||||
// Drained eventloop & initial input; exit silent/batch-mode (-es/-Es).
|
// Drained eventloop & initial input; exit silent/batch-mode (-es/-Es).
|
||||||
read_error_exit();
|
read_error_exit();
|
||||||
}
|
}
|
||||||
restart_cursorhold_wait(tb_change_cnt);
|
reset_cursorhold_wait(tb_change_cnt);
|
||||||
if (trigger_cursorhold() && !typebuf_changed(tb_change_cnt)) {
|
if (trigger_cursorhold() && !typebuf_changed(tb_change_cnt)) {
|
||||||
create_cursorhold_event(events == main_loop.events);
|
create_cursorhold_event(events == main_loop.events);
|
||||||
} else {
|
} else {
|
||||||
@ -153,32 +166,26 @@ int os_inchar(uint8_t *buf, int maxlen, int ms, int tb_change_cnt, MultiQueue *e
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maxlen && input_available()) {
|
TRY_READ();
|
||||||
restart_cursorhold_wait(tb_change_cnt);
|
|
||||||
// Safe to convert `to_read` to int, it will never overflow since
|
|
||||||
// INPUT_BUFFER_SIZE fits in an int
|
|
||||||
size_t to_read = MIN((size_t)maxlen, input_available());
|
|
||||||
memcpy(buf, input_read_pos, to_read);
|
|
||||||
input_read_pos += to_read;
|
|
||||||
return (int)to_read;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there are events, return the keys directly
|
// If there are events, return the keys directly
|
||||||
if (maxlen && pending_events(events)) {
|
if (maxlen && pending_events(events)) {
|
||||||
return push_event_key(buf, maxlen);
|
return push_event_key(buf, maxlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == kInputEof) {
|
if (result == kNone) {
|
||||||
read_error_exit();
|
read_error_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
#undef TRY_READ
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if a character is available for reading
|
// Check if a character is available for reading
|
||||||
bool os_char_avail(void)
|
bool os_char_avail(void)
|
||||||
{
|
{
|
||||||
return inbuf_poll(0, NULL) == kInputAvail;
|
return inbuf_poll(0, NULL) == kTrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Poll for fast events. `got_int` will be set to `true` if CTRL-C was typed.
|
/// Poll for fast events. `got_int` will be set to `true` if CTRL-C was typed.
|
||||||
@ -463,15 +470,22 @@ bool input_blocking(void)
|
|||||||
return blocking;
|
return blocking;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a replacement for the old `WaitForChar` function in os_unix.c
|
/// Checks for (but does not read) available input, and consumes `main_loop.events` while waiting.
|
||||||
static InbufPollResult inbuf_poll(int ms, MultiQueue *events)
|
///
|
||||||
|
/// @param ms Timeout in milliseconds. -1 for indefinite wait, 0 for no wait.
|
||||||
|
/// @param events (optional) Queue to check for pending events.
|
||||||
|
/// @return TriState:
|
||||||
|
/// - kTrue: Input/events available
|
||||||
|
/// - kFalse: No input/events
|
||||||
|
/// - kNone: EOF reached on the input stream
|
||||||
|
static TriState inbuf_poll(int ms, MultiQueue *events)
|
||||||
{
|
{
|
||||||
if (os_input_ready(events)) {
|
if (os_input_ready(events)) {
|
||||||
return kInputAvail;
|
return kTrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_profiling == PROF_YES && ms) {
|
if (do_profiling == PROF_YES && ms) {
|
||||||
prof_inchar_enter();
|
prof_input_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ms == -1 || ms > 0) && events != main_loop.events && !input_eof) {
|
if ((ms == -1 || ms > 0) && events != main_loop.events && !input_eof) {
|
||||||
@ -479,20 +493,18 @@ static InbufPollResult inbuf_poll(int ms, MultiQueue *events)
|
|||||||
blocking = true;
|
blocking = true;
|
||||||
multiqueue_process_events(ch_before_blocking_events);
|
multiqueue_process_events(ch_before_blocking_events);
|
||||||
}
|
}
|
||||||
DLOG("blocking... events_enabled=%d events_pending=%d", events != NULL,
|
DLOG("blocking... events=%s", !!events ? "true" : "false");
|
||||||
events && !multiqueue_empty(events));
|
LOOP_PROCESS_EVENTS_UNTIL(&main_loop, NULL, ms, os_input_ready(events) || input_eof);
|
||||||
LOOP_PROCESS_EVENTS_UNTIL(&main_loop, NULL, ms,
|
|
||||||
os_input_ready(events) || input_eof);
|
|
||||||
blocking = false;
|
blocking = false;
|
||||||
|
|
||||||
if (do_profiling == PROF_YES && ms) {
|
if (do_profiling == PROF_YES && ms) {
|
||||||
prof_inchar_exit();
|
prof_input_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (os_input_ready(events)) {
|
if (os_input_ready(events)) {
|
||||||
return kInputAvail;
|
return kTrue;
|
||||||
}
|
}
|
||||||
return input_eof ? kInputEof : kInputNone;
|
return input_eof ? kNone : kFalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t input_read_cb(RStream *stream, const char *buf, size_t c, void *data, bool at_eof)
|
static size_t input_read_cb(RStream *stream, const char *buf, size_t c, void *data, bool at_eof)
|
||||||
@ -533,8 +545,8 @@ static void process_ctrl_c(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function used to push bytes from the 'event' key sequence partially
|
/// Pushes bytes from the "event" key sequence (KE_EVENT) partially between calls to input_get when
|
||||||
// between calls to os_inchar when maxlen < 3
|
/// `maxlen < 3`.
|
||||||
static int push_event_key(uint8_t *buf, int maxlen)
|
static int push_event_key(uint8_t *buf, int maxlen)
|
||||||
{
|
{
|
||||||
static const uint8_t key[3] = { K_SPECIAL, KS_EXTRA, KE_EVENT };
|
static const uint8_t key[3] = { K_SPECIAL, KS_EXTRA, KE_EVENT };
|
||||||
|
@ -1292,7 +1292,7 @@ static void shell_write_cb(Stream *stream, void *data, int status)
|
|||||||
msg_schedule_semsg(_("E5677: Error writing input to shell-command: %s"),
|
msg_schedule_semsg(_("E5677: Error writing input to shell-command: %s"),
|
||||||
uv_err_name(status));
|
uv_err_name(status));
|
||||||
}
|
}
|
||||||
stream_close(stream, NULL, NULL, false);
|
stream_may_close(stream, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Applies 'shellxescape' (p_sxe) and 'shellxquote' (p_sxq) to a command.
|
/// Applies 'shellxescape' (p_sxe) and 'shellxquote' (p_sxq) to a command.
|
||||||
|
@ -63,22 +63,32 @@ static const char *const xdg_defaults[] = {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Get the value of $NVIM_APPNAME or "nvim" if not set.
|
/// Gets the value of $NVIM_APPNAME, or "nvim" if not set.
|
||||||
|
///
|
||||||
|
/// @param namelike Write "name-like" value (no path separators) in `NameBuff`.
|
||||||
///
|
///
|
||||||
/// @return $NVIM_APPNAME value
|
/// @return $NVIM_APPNAME value
|
||||||
const char *get_appname(void)
|
const char *get_appname(bool namelike)
|
||||||
{
|
{
|
||||||
const char *env_val = os_getenv("NVIM_APPNAME");
|
const char *env_val = os_getenv("NVIM_APPNAME");
|
||||||
if (env_val == NULL || *env_val == NUL) {
|
if (env_val == NULL || *env_val == NUL) {
|
||||||
env_val = "nvim";
|
env_val = "nvim";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (namelike) {
|
||||||
|
// Appname may be a relative path, replace slashes to make it name-like.
|
||||||
|
xstrlcpy(NameBuff, env_val, sizeof(NameBuff));
|
||||||
|
memchrsub(NameBuff, '/', '-', sizeof(NameBuff));
|
||||||
|
memchrsub(NameBuff, '\\', '-', sizeof(NameBuff));
|
||||||
|
}
|
||||||
|
|
||||||
return env_val;
|
return env_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ensure that APPNAME is valid. Must be a name or relative path.
|
/// Ensure that APPNAME is valid. Must be a name or relative path.
|
||||||
bool appname_is_valid(void)
|
bool appname_is_valid(void)
|
||||||
{
|
{
|
||||||
const char *appname = get_appname();
|
const char *appname = get_appname(false);
|
||||||
if (path_is_absolute(appname)
|
if (path_is_absolute(appname)
|
||||||
// TODO(justinmk): on Windows, path_is_absolute says "/" is NOT absolute. Should it?
|
// TODO(justinmk): on Windows, path_is_absolute says "/" is NOT absolute. Should it?
|
||||||
|| strequal(appname, "/")
|
|| strequal(appname, "/")
|
||||||
@ -193,7 +203,7 @@ char *get_xdg_home(const XDGVarType idx)
|
|||||||
FUNC_ATTR_WARN_UNUSED_RESULT
|
FUNC_ATTR_WARN_UNUSED_RESULT
|
||||||
{
|
{
|
||||||
char *dir = stdpaths_get_xdg_var(idx);
|
char *dir = stdpaths_get_xdg_var(idx);
|
||||||
const char *appname = get_appname();
|
const char *appname = get_appname(false);
|
||||||
size_t appname_len = strlen(appname);
|
size_t appname_len = strlen(appname);
|
||||||
assert(appname_len < (IOSIZE - sizeof("-data")));
|
assert(appname_len < (IOSIZE - sizeof("-data")));
|
||||||
|
|
||||||
|
@ -383,19 +383,19 @@ void set_context_in_profile_cmd(expand_T *xp, const char *arg)
|
|||||||
xp->xp_context = EXPAND_NOTHING;
|
xp->xp_context = EXPAND_NOTHING;
|
||||||
}
|
}
|
||||||
|
|
||||||
static proftime_T inchar_time;
|
static proftime_T wait_time;
|
||||||
|
|
||||||
/// Called when starting to wait for the user to type a character.
|
/// Called when starting to wait for the user to type a character.
|
||||||
void prof_inchar_enter(void)
|
void prof_input_start(void)
|
||||||
{
|
{
|
||||||
inchar_time = profile_start();
|
wait_time = profile_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when finished waiting for the user to type a character.
|
/// Called when finished waiting for the user to type a character.
|
||||||
void prof_inchar_exit(void)
|
void prof_input_end(void)
|
||||||
{
|
{
|
||||||
inchar_time = profile_end(inchar_time);
|
wait_time = profile_end(wait_time);
|
||||||
profile_set_wait(profile_add(profile_get_wait(), inchar_time));
|
profile_set_wait(profile_add(profile_get_wait(), wait_time));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @return true when a function defined in the current script should be
|
/// @return true when a function defined in the current script should be
|
||||||
|
@ -1559,7 +1559,7 @@ static inline char *add_env_sep_dirs(char *dest, const char *const val, const ch
|
|||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
const void *iter = NULL;
|
const void *iter = NULL;
|
||||||
const char *appname = get_appname();
|
const char *appname = get_appname(false);
|
||||||
const size_t appname_len = strlen(appname);
|
const size_t appname_len = strlen(appname);
|
||||||
do {
|
do {
|
||||||
size_t dir_len;
|
size_t dir_len;
|
||||||
@ -1626,7 +1626,7 @@ static inline char *add_dir(char *dest, const char *const dir, const size_t dir_
|
|||||||
if (!after_pathsep(dest - 1, dest)) {
|
if (!after_pathsep(dest - 1, dest)) {
|
||||||
*dest++ = PATHSEP;
|
*dest++ = PATHSEP;
|
||||||
}
|
}
|
||||||
const char *appname = get_appname();
|
const char *appname = get_appname(false);
|
||||||
size_t appname_len = strlen(appname);
|
size_t appname_len = strlen(appname);
|
||||||
assert(appname_len < (IOSIZE - sizeof("-data")));
|
assert(appname_len < (IOSIZE - sizeof("-data")));
|
||||||
xmemcpyz(IObuff, appname, appname_len);
|
xmemcpyz(IObuff, appname, appname_len);
|
||||||
@ -1697,7 +1697,7 @@ char *runtimepath_default(bool clean_arg)
|
|||||||
size_t config_len = 0;
|
size_t config_len = 0;
|
||||||
size_t vimruntime_len = 0;
|
size_t vimruntime_len = 0;
|
||||||
size_t libdir_len = 0;
|
size_t libdir_len = 0;
|
||||||
const char *appname = get_appname();
|
const char *appname = get_appname(false);
|
||||||
size_t appname_len = strlen(appname);
|
size_t appname_len = strlen(appname);
|
||||||
if (data_home != NULL) {
|
if (data_home != NULL) {
|
||||||
data_len = strlen(data_home);
|
data_len = strlen(data_home);
|
||||||
|
@ -74,10 +74,9 @@ getkey:
|
|||||||
}
|
}
|
||||||
// Flush screen updates before blocking.
|
// Flush screen updates before blocking.
|
||||||
ui_flush();
|
ui_flush();
|
||||||
// Call `os_inchar` directly to block for events or user input without
|
// Call `input_get` directly to block for events or user input without consuming anything from
|
||||||
// consuming anything from `input_buffer`(os/input.c) or calling the
|
// `os/input.c:input_buffer` or calling the mapping engine.
|
||||||
// mapping engine.
|
input_get(NULL, 0, -1, typebuf.tb_change_cnt, main_loop.events);
|
||||||
os_inchar(NULL, 0, -1, typebuf.tb_change_cnt, main_loop.events);
|
|
||||||
// If an event was put into the queue, we send K_EVENT directly.
|
// If an event was put into the queue, we send K_EVENT directly.
|
||||||
if (!input_available() && !multiqueue_empty(main_loop.events)) {
|
if (!input_available() && !multiqueue_empty(main_loop.events)) {
|
||||||
key = K_EVENT;
|
key = K_EVENT;
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "nvim/memory_defs.h"
|
#include "nvim/memory_defs.h"
|
||||||
#include "nvim/msgpack_rpc/channel.h"
|
#include "nvim/msgpack_rpc/channel.h"
|
||||||
#include "nvim/msgpack_rpc/channel_defs.h"
|
#include "nvim/msgpack_rpc/channel_defs.h"
|
||||||
|
#include "nvim/os/os.h"
|
||||||
#include "nvim/os/os_defs.h"
|
#include "nvim/os/os_defs.h"
|
||||||
#include "nvim/tui/tui.h"
|
#include "nvim/tui/tui.h"
|
||||||
#include "nvim/tui/tui_defs.h"
|
#include "nvim/tui/tui_defs.h"
|
||||||
@ -126,6 +127,11 @@ void ui_client_run(bool remote_ui)
|
|||||||
|
|
||||||
ui_client_attach(width, height, term, rgb);
|
ui_client_attach(width, height, term, rgb);
|
||||||
|
|
||||||
|
// TODO(justinmk): this is for log_spec. Can remove this after nvim_log #7062 is merged.
|
||||||
|
if (os_env_exists("__NVIM_TEST_LOG")) {
|
||||||
|
ELOG("test log message");
|
||||||
|
}
|
||||||
|
|
||||||
// os_exit() will be invoked when the client channel detaches
|
// os_exit() will be invoked when the client channel detaches
|
||||||
while (true) {
|
while (true) {
|
||||||
LOOP_PROCESS_EVENTS(&main_loop, resize_events, -1);
|
LOOP_PROCESS_EVENTS(&main_loop, resize_events, -1);
|
||||||
|
@ -14,7 +14,7 @@ EXTERN size_t grid_line_buf_size INIT( = 0);
|
|||||||
EXTERN schar_T *grid_line_buf_char INIT( = NULL);
|
EXTERN schar_T *grid_line_buf_char INIT( = NULL);
|
||||||
EXTERN sattr_T *grid_line_buf_attr INIT( = NULL);
|
EXTERN sattr_T *grid_line_buf_attr INIT( = NULL);
|
||||||
|
|
||||||
// ID of the ui client channel. If zero, the client is not running.
|
// Client-side UI channel. Zero during early startup or if not a (--remote-ui) UI client.
|
||||||
EXTERN uint64_t ui_client_channel_id INIT( = 0);
|
EXTERN uint64_t ui_client_channel_id INIT( = 0);
|
||||||
|
|
||||||
// exit status from embedded nvim process
|
// exit status from embedded nvim process
|
||||||
|
@ -101,6 +101,23 @@ bool ui_comp_should_draw(void)
|
|||||||
return composed_uis != 0 && valid_screen;
|
return composed_uis != 0 && valid_screen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int compare_zindex(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
int za = (*(ScreenGrid **)a)->zindex;
|
||||||
|
int zb = (*(ScreenGrid **)b)->zindex;
|
||||||
|
size_t ia = (*(ScreenGrid **)a)->comp_index;
|
||||||
|
size_t ib = (*(ScreenGrid **)b)->comp_index;
|
||||||
|
return za == zb ? (ia == ib ? 0 : (ia < ib ? -1 : 1)) : (za < zb ? -1 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ui_sort_layers_by_zindex(void)
|
||||||
|
{
|
||||||
|
qsort(layers.items, layers.size, sizeof(ScreenGrid *), compare_zindex);
|
||||||
|
for (size_t i = 0; i < kv_size(layers); i++) {
|
||||||
|
kv_A(layers, i)->comp_index = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Places `grid` at (col,row) position with (width * height) size.
|
/// Places `grid` at (col,row) position with (width * height) size.
|
||||||
/// Adds `grid` as the top layer if it is a new layer.
|
/// Adds `grid` as the top layer if it is a new layer.
|
||||||
///
|
///
|
||||||
|
@ -839,7 +839,12 @@ void ui_ext_win_position(win_T *wp, bool validate)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool resort = wp->w_grid_alloc.comp_index != 0
|
||||||
|
&& wp->w_grid_alloc.zindex != wp->w_config.zindex;
|
||||||
wp->w_grid_alloc.zindex = wp->w_config.zindex;
|
wp->w_grid_alloc.zindex = wp->w_config.zindex;
|
||||||
|
if (resort) {
|
||||||
|
ui_sort_layers_by_zindex();
|
||||||
|
}
|
||||||
if (ui_has(kUIMultigrid)) {
|
if (ui_has(kUIMultigrid)) {
|
||||||
String anchor = cstr_as_string(float_anchor_str[c.anchor]);
|
String anchor = cstr_as_string(float_anchor_str[c.anchor]);
|
||||||
if (!c.hide) {
|
if (!c.hide) {
|
||||||
|
@ -3201,7 +3201,7 @@ describe('API', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
describe('nvim_get_runtime_file', function()
|
describe('nvim_get_runtime_file', function()
|
||||||
local p = n.alter_slashes
|
local p = t.fix_slashes
|
||||||
it('can find files', function()
|
it('can find files', function()
|
||||||
eq({}, api.nvim_get_runtime_file('bork.borkbork', false))
|
eq({}, api.nvim_get_runtime_file('bork.borkbork', false))
|
||||||
eq({}, api.nvim_get_runtime_file('bork.borkbork', true))
|
eq({}, api.nvim_get_runtime_file('bork.borkbork', true))
|
||||||
@ -3210,36 +3210,36 @@ describe('API', function()
|
|||||||
local val = api.nvim_get_runtime_file('autoload/remote/*.vim', true)
|
local val = api.nvim_get_runtime_file('autoload/remote/*.vim', true)
|
||||||
eq(2, #val)
|
eq(2, #val)
|
||||||
if endswith(val[1], 'define.vim') then
|
if endswith(val[1], 'define.vim') then
|
||||||
ok(endswith(val[1], p 'autoload/remote/define.vim'))
|
ok(endswith(p(val[1]), 'autoload/remote/define.vim'))
|
||||||
ok(endswith(val[2], p 'autoload/remote/host.vim'))
|
ok(endswith(p(val[2]), 'autoload/remote/host.vim'))
|
||||||
else
|
else
|
||||||
ok(endswith(val[1], p 'autoload/remote/host.vim'))
|
ok(endswith(p(val[1]), 'autoload/remote/host.vim'))
|
||||||
ok(endswith(val[2], p 'autoload/remote/define.vim'))
|
ok(endswith(p(val[2]), 'autoload/remote/define.vim'))
|
||||||
end
|
end
|
||||||
val = api.nvim_get_runtime_file('autoload/remote/*.vim', false)
|
val = api.nvim_get_runtime_file('autoload/remote/*.vim', false)
|
||||||
eq(1, #val)
|
eq(1, #val)
|
||||||
ok(
|
ok(
|
||||||
endswith(val[1], p 'autoload/remote/define.vim')
|
endswith(p(val[1]), 'autoload/remote/define.vim')
|
||||||
or endswith(val[1], p 'autoload/remote/host.vim')
|
or endswith(p(val[1]), 'autoload/remote/host.vim')
|
||||||
)
|
)
|
||||||
|
|
||||||
val = api.nvim_get_runtime_file('lua', true)
|
val = api.nvim_get_runtime_file('lua', true)
|
||||||
eq(1, #val)
|
eq(1, #val)
|
||||||
ok(endswith(val[1], p 'lua'))
|
ok(endswith(p(val[1]), 'lua'))
|
||||||
|
|
||||||
val = api.nvim_get_runtime_file('lua/vim', true)
|
val = api.nvim_get_runtime_file('lua/vim', true)
|
||||||
eq(1, #val)
|
eq(1, #val)
|
||||||
ok(endswith(val[1], p 'lua/vim'))
|
ok(endswith(p(val[1]), 'lua/vim'))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('can find directories', function()
|
it('can find directories', function()
|
||||||
local val = api.nvim_get_runtime_file('lua/', true)
|
local val = api.nvim_get_runtime_file('lua/', true)
|
||||||
eq(1, #val)
|
eq(1, #val)
|
||||||
ok(endswith(val[1], p 'lua/'))
|
ok(endswith(p(val[1]), 'lua/'))
|
||||||
|
|
||||||
val = api.nvim_get_runtime_file('lua/vim/', true)
|
val = api.nvim_get_runtime_file('lua/vim/', true)
|
||||||
eq(1, #val)
|
eq(1, #val)
|
||||||
ok(endswith(val[1], p 'lua/vim/'))
|
ok(endswith(p(val[1]), 'lua/vim/'))
|
||||||
|
|
||||||
eq({}, api.nvim_get_runtime_file('foobarlang/', true))
|
eq({}, api.nvim_get_runtime_file('foobarlang/', true))
|
||||||
end)
|
end)
|
||||||
|
@ -9,7 +9,7 @@ local request = n.request
|
|||||||
local is_os = t.is_os
|
local is_os = t.is_os
|
||||||
|
|
||||||
describe('autocmd DirChanged and DirChangedPre', function()
|
describe('autocmd DirChanged and DirChangedPre', function()
|
||||||
local curdir = vim.uv.cwd():gsub('\\', '/')
|
local curdir = t.fix_slashes(vim.uv.cwd())
|
||||||
local dirs = {
|
local dirs = {
|
||||||
curdir .. '/Xtest-functional-autocmd-dirchanged.dir1',
|
curdir .. '/Xtest-functional-autocmd-dirchanged.dir1',
|
||||||
curdir .. '/Xtest-functional-autocmd-dirchanged.dir2',
|
curdir .. '/Xtest-functional-autocmd-dirchanged.dir2',
|
||||||
|
@ -321,11 +321,11 @@ end)
|
|||||||
describe('tmpdir', function()
|
describe('tmpdir', function()
|
||||||
local tmproot_pat = [=[.*[/\\]nvim%.[^/\\]+]=]
|
local tmproot_pat = [=[.*[/\\]nvim%.[^/\\]+]=]
|
||||||
local testlog = 'Xtest_tmpdir_log'
|
local testlog = 'Xtest_tmpdir_log'
|
||||||
local os_tmpdir
|
local os_tmpdir ---@type string
|
||||||
|
|
||||||
before_each(function()
|
before_each(function()
|
||||||
-- Fake /tmp dir so that we can mess it up.
|
-- Fake /tmp dir so that we can mess it up.
|
||||||
os_tmpdir = vim.uv.fs_mkdtemp(vim.fs.dirname(t.tmpname(false)) .. '/nvim_XXXXXXXXXX')
|
os_tmpdir = assert(vim.uv.fs_mkdtemp(vim.fs.dirname(t.tmpname(false)) .. '/nvim_XXXXXXXXXX'))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
after_each(function()
|
after_each(function()
|
||||||
@ -414,15 +414,4 @@ describe('tmpdir', function()
|
|||||||
rm_tmpdir()
|
rm_tmpdir()
|
||||||
eq('E5431: tempdir disappeared (3 times)', api.nvim_get_vvar('errmsg'))
|
eq('E5431: tempdir disappeared (3 times)', api.nvim_get_vvar('errmsg'))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('$NVIM_APPNAME relative path', function()
|
|
||||||
clear({
|
|
||||||
env = {
|
|
||||||
NVIM_APPNAME = 'a/b',
|
|
||||||
NVIM_LOG_FILE = testlog,
|
|
||||||
TMPDIR = os_tmpdir,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
matches([=[.*[/\\]a%%b%.[^/\\]+]=], fn.tempname())
|
|
||||||
end)
|
|
||||||
end)
|
end)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
local t = require('test.testutil')
|
local t = require('test.testutil')
|
||||||
local n = require('test.functional.testnvim')()
|
local n = require('test.functional.testnvim')()
|
||||||
|
local tt = require('test.functional.terminal.testutil')
|
||||||
|
|
||||||
local assert_log = t.assert_log
|
local assert_log = t.assert_log
|
||||||
local clear = n.clear
|
local clear = n.clear
|
||||||
@ -29,10 +30,54 @@ describe('log', function()
|
|||||||
assert(request('nvim__stats').log_skip <= 13)
|
assert(request('nvim__stats').log_skip <= 13)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('messages are formatted with name or test id', function()
|
it('TUI client name is "ui"', function()
|
||||||
|
local function setup(env)
|
||||||
|
clear()
|
||||||
|
-- Start Nvim with builtin UI.
|
||||||
|
local screen = tt.setup_child_nvim({
|
||||||
|
'-u',
|
||||||
|
'NONE',
|
||||||
|
'-i',
|
||||||
|
'NONE',
|
||||||
|
'--cmd',
|
||||||
|
n.nvim_set,
|
||||||
|
}, {
|
||||||
|
env = env,
|
||||||
|
})
|
||||||
|
screen:expect([[
|
||||||
|
{1: } |
|
||||||
|
~ |*4
|
||||||
|
|
|
||||||
|
{3:-- TERMINAL --} |
|
||||||
|
]])
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Without $NVIM parent.
|
||||||
|
setup({
|
||||||
|
NVIM = '',
|
||||||
|
NVIM_LISTEN_ADDRESS = '',
|
||||||
|
NVIM_LOG_FILE = testlog,
|
||||||
|
__NVIM_TEST_LOG = '1',
|
||||||
|
})
|
||||||
|
-- Example:
|
||||||
|
-- ERR 2024-09-11T16:40:02.421 ui.47056 ui_client_run:165: test log message
|
||||||
|
assert_log(' ui%.%d+% +ui_client_run:%d+: test log message', testlog, 100)
|
||||||
|
|
||||||
|
-- With $NVIM parent.
|
||||||
|
setup({
|
||||||
|
NVIM_LOG_FILE = testlog,
|
||||||
|
__NVIM_TEST_LOG = '1',
|
||||||
|
})
|
||||||
|
-- Example:
|
||||||
|
-- ERR 2024-09-11T16:41:17.539 ui/c/T2.47826.0 ui_client_run:165: test log message
|
||||||
|
local tid = _G._nvim_test_id
|
||||||
|
assert_log(' ui/c/' .. tid .. '%.%d+%.%d +ui_client_run:%d+: test log message', testlog, 100)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('formats messages with session name or test id', function()
|
||||||
-- Examples:
|
-- Examples:
|
||||||
-- ERR 2022-05-29T12:30:03.800 T2 log_init:110: test log message
|
-- ERR 2024-09-11T16:44:33.794 T3.49429.0 server_init:58: test log message
|
||||||
-- ERR 2022-05-29T12:30:03.814 T2/child log_init:110: test log message
|
-- ERR 2024-09-11T16:44:33.823 c/T3.49429.0 server_init:58: test log message
|
||||||
|
|
||||||
clear({
|
clear({
|
||||||
env = {
|
env = {
|
||||||
@ -47,10 +92,10 @@ describe('log', function()
|
|||||||
|
|
||||||
exec_lua([[
|
exec_lua([[
|
||||||
local j1 = vim.fn.jobstart({ vim.v.progpath, '-es', '-V1', '+foochild', '+qa!' }, vim.empty_dict())
|
local j1 = vim.fn.jobstart({ vim.v.progpath, '-es', '-V1', '+foochild', '+qa!' }, vim.empty_dict())
|
||||||
vim.fn.jobwait({ j1 }, 10000)
|
vim.fn.jobwait({ j1 }, 5000)
|
||||||
]])
|
]])
|
||||||
|
|
||||||
-- Child Nvim spawned by jobstart() appends "/c" to parent name.
|
-- Child Nvim spawned by jobstart() prepends "c/" to parent name.
|
||||||
assert_log('%.%d+%.%d/c +server_init:%d+: test log message', testlog, 100)
|
assert_log('c/' .. tid .. '%.%d+%.%d +server_init:%d+: test log message', testlog, 100)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
@ -41,6 +41,21 @@ describe('server', function()
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('broken $XDG_RUNTIME_DIR is not fatal #30282', function()
|
||||||
|
clear {
|
||||||
|
args_rm = { '--listen' },
|
||||||
|
env = { NVIM_LOG_FILE = testlog, XDG_RUNTIME_DIR = '/non-existent-dir/subdir//' },
|
||||||
|
}
|
||||||
|
|
||||||
|
if is_os('win') then
|
||||||
|
-- Windows pipes have a special namespace and thus aren't decided by $XDG_RUNTIME_DIR.
|
||||||
|
matches('nvim', api.nvim_get_vvar('servername'))
|
||||||
|
else
|
||||||
|
eq('', api.nvim_get_vvar('servername'))
|
||||||
|
t.assert_log('Failed to start server%: no such file or directory', testlog, 100)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
it('serverstart(), serverstop() does not set $NVIM', function()
|
it('serverstart(), serverstop() does not set $NVIM', function()
|
||||||
clear()
|
clear()
|
||||||
local s = eval('serverstart()')
|
local s = eval('serverstart()')
|
||||||
@ -139,7 +154,7 @@ describe('server', function()
|
|||||||
clear_serverlist()
|
clear_serverlist()
|
||||||
|
|
||||||
-- Address without slashes is a "name" which is appended to a generated path. #8519
|
-- Address without slashes is a "name" which is appended to a generated path. #8519
|
||||||
matches([[.*[/\\]xtest1%.2%.3%.4[^/\\]*]], fn.serverstart('xtest1.2.3.4'))
|
matches([[[/\\]xtest1%.2%.3%.4[^/\\]*]], fn.serverstart('xtest1.2.3.4'))
|
||||||
clear_serverlist()
|
clear_serverlist()
|
||||||
|
|
||||||
eq('Vim:Failed to start server: invalid argument', pcall_err(fn.serverstart, '127.0.0.1:65536')) -- invalid port
|
eq('Vim:Failed to start server: invalid argument', pcall_err(fn.serverstart, '127.0.0.1:65536')) -- invalid port
|
||||||
@ -175,56 +190,79 @@ describe('server', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
describe('startup --listen', function()
|
describe('startup --listen', function()
|
||||||
|
-- Tests Nvim output when failing to start, with and without "--headless".
|
||||||
|
-- TODO(justinmk): clear() should have a way to get stdout if Nvim fails to start.
|
||||||
|
local function _test(args, env, expected)
|
||||||
|
local function run(cmd)
|
||||||
|
return n.exec_lua(function(cmd_, env_)
|
||||||
|
return vim
|
||||||
|
.system(cmd_, {
|
||||||
|
text = true,
|
||||||
|
env = vim.tbl_extend(
|
||||||
|
'force',
|
||||||
|
-- Avoid noise in the logs; we expect failures for these tests.
|
||||||
|
{ NVIM_LOG_FILE = testlog },
|
||||||
|
env_ or {}
|
||||||
|
),
|
||||||
|
})
|
||||||
|
:wait()
|
||||||
|
end, cmd, env) --[[@as vim.SystemCompleted]]
|
||||||
|
end
|
||||||
|
|
||||||
|
local cmd = vim.list_extend({ n.nvim_prog, '+qall!', '--headless' }, args)
|
||||||
|
local r = run(cmd)
|
||||||
|
eq(1, r.code)
|
||||||
|
matches(expected, (r.stderr .. r.stdout):gsub('\\n', ' '))
|
||||||
|
|
||||||
|
if is_os('win') then
|
||||||
|
return -- On Windows, output without --headless is garbage.
|
||||||
|
end
|
||||||
|
table.remove(cmd, 3) -- Remove '--headless'.
|
||||||
|
assert(not vim.tbl_contains(cmd, '--headless'))
|
||||||
|
r = run(cmd)
|
||||||
|
eq(1, r.code)
|
||||||
|
matches(expected, (r.stderr .. r.stdout):gsub('\\n', ' '))
|
||||||
|
end
|
||||||
|
|
||||||
it('validates', function()
|
it('validates', function()
|
||||||
clear { env = { NVIM_LOG_FILE = testlog } }
|
clear { env = { NVIM_LOG_FILE = testlog } }
|
||||||
|
local in_use = n.eval('v:servername') ---@type string Address already used by another server.
|
||||||
-- Tests args with and without "--headless".
|
|
||||||
local function _test(args, expected)
|
|
||||||
local function run(cmd)
|
|
||||||
return n.exec_lua(function(cmd_)
|
|
||||||
return vim
|
|
||||||
.system(cmd_, {
|
|
||||||
text = true,
|
|
||||||
env = {
|
|
||||||
-- Avoid noise in the logs; we expect failures for these tests.
|
|
||||||
NVIM_LOG_FILE = testlog,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
:wait()
|
|
||||||
end, cmd) --[[@as vim.SystemCompleted]]
|
|
||||||
end
|
|
||||||
|
|
||||||
local cmd = vim.list_extend({ n.nvim_prog, '+qall!', '--headless' }, args)
|
|
||||||
local r = run(cmd)
|
|
||||||
eq(1, r.code)
|
|
||||||
matches(expected, (r.stderr .. r.stdout):gsub('\\n', ' '))
|
|
||||||
|
|
||||||
if is_os('win') then
|
|
||||||
return -- On Windows, output without --headless is garbage.
|
|
||||||
end
|
|
||||||
table.remove(cmd, 3) -- Remove '--headless'.
|
|
||||||
assert(not vim.tbl_contains(cmd, '--headless'))
|
|
||||||
r = run(cmd)
|
|
||||||
eq(1, r.code)
|
|
||||||
matches(expected, (r.stderr .. r.stdout):gsub('\\n', ' '))
|
|
||||||
end
|
|
||||||
|
|
||||||
t.assert_nolog('Failed to start server', testlog, 100)
|
t.assert_nolog('Failed to start server', testlog, 100)
|
||||||
t.assert_nolog('Host lookup failed', testlog, 100)
|
t.assert_nolog('Host lookup failed', testlog, 100)
|
||||||
|
|
||||||
_test({ '--listen' }, 'nvim.*: Argument missing after: "%-%-listen"')
|
_test({ '--listen' }, nil, 'nvim.*: Argument missing after: "%-%-listen"')
|
||||||
_test({ '--listen2' }, 'nvim.*: Garbage after option argument: "%-%-listen2"')
|
_test({ '--listen2' }, nil, 'nvim.*: Garbage after option argument: "%-%-listen2"')
|
||||||
_test({ '--listen', n.eval('v:servername') }, 'nvim.*: Failed to %-%-listen: ".* already .*"')
|
_test(
|
||||||
_test({ '--listen', '/' }, 'nvim.*: Failed to %-%-listen: ".*"')
|
{ '--listen', in_use },
|
||||||
|
nil,
|
||||||
|
('nvim.*: Failed to %%-%%-listen: [^:]+ already [^:]+: "%s"'):format(vim.pesc(in_use))
|
||||||
|
)
|
||||||
|
_test({ '--listen', '/' }, nil, 'nvim.*: Failed to %-%-listen: [^:]+: "/"')
|
||||||
_test(
|
_test(
|
||||||
{ '--listen', 'https://example.com' },
|
{ '--listen', 'https://example.com' },
|
||||||
('nvim.*: Failed to %%-%%-listen: "%s"'):format(
|
nil,
|
||||||
|
('nvim.*: Failed to %%-%%-listen: %s: "https://example.com"'):format(
|
||||||
is_os('mac') and 'unknown node or service' or 'service not available for socket type'
|
is_os('mac') and 'unknown node or service' or 'service not available for socket type'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
t.assert_log('Failed to start server', testlog, 100)
|
t.assert_log('Failed to start server', testlog, 100)
|
||||||
t.assert_log('Host lookup failed', testlog, 100)
|
t.assert_log('Host lookup failed', testlog, 100)
|
||||||
|
|
||||||
|
_test(
|
||||||
|
{},
|
||||||
|
{ NVIM_LISTEN_ADDRESS = in_use },
|
||||||
|
('nvim.*: Failed $NVIM_LISTEN_ADDRESS: [^:]+ already [^:]+: "%s"'):format(vim.pesc(in_use))
|
||||||
|
)
|
||||||
|
_test({}, { NVIM_LISTEN_ADDRESS = '/' }, 'nvim.*: Failed $NVIM_LISTEN_ADDRESS: [^:]+: "/"')
|
||||||
|
_test(
|
||||||
|
{},
|
||||||
|
{ NVIM_LISTEN_ADDRESS = 'https://example.com' },
|
||||||
|
('nvim.*: Failed $NVIM_LISTEN_ADDRESS: %s: "https://example.com"'):format(
|
||||||
|
is_os('mac') and 'unknown node or service' or 'service not available for socket type'
|
||||||
|
)
|
||||||
|
)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('sets v:servername, overrides $NVIM_LISTEN_ADDRESS', function()
|
it('sets v:servername, overrides $NVIM_LISTEN_ADDRESS', function()
|
||||||
@ -235,6 +273,6 @@ describe('startup --listen', function()
|
|||||||
|
|
||||||
-- Address without slashes is a "name" which is appended to a generated path. #8519
|
-- Address without slashes is a "name" which is appended to a generated path. #8519
|
||||||
clear({ args = { '--listen', 'test-name' } })
|
clear({ args = { '--listen', 'test-name' } })
|
||||||
matches([[.*[/\\]test%-name[^/\\]*]], api.nvim_get_vvar('servername'))
|
matches([[[/\\]test%-name[^/\\]*]], api.nvim_get_vvar('servername'))
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
@ -27,7 +27,6 @@ local sleep = vim.uv.sleep
|
|||||||
local startswith = vim.startswith
|
local startswith = vim.startswith
|
||||||
local write_file = t.write_file
|
local write_file = t.write_file
|
||||||
local api = n.api
|
local api = n.api
|
||||||
local alter_slashes = n.alter_slashes
|
|
||||||
local is_os = t.is_os
|
local is_os = t.is_os
|
||||||
local dedent = t.dedent
|
local dedent = t.dedent
|
||||||
local tbl_map = vim.tbl_map
|
local tbl_map = vim.tbl_map
|
||||||
@ -40,22 +39,15 @@ local testlog = 'Xtest-startupspec-log'
|
|||||||
describe('startup', function()
|
describe('startup', function()
|
||||||
it('--clean', function()
|
it('--clean', function()
|
||||||
clear()
|
clear()
|
||||||
ok(
|
matches(
|
||||||
string.find(
|
vim.pesc(t.fix_slashes(fn.stdpath('config'))),
|
||||||
alter_slashes(api.nvim_get_option_value('runtimepath', {})),
|
t.fix_slashes(api.nvim_get_option_value('runtimepath', {}))
|
||||||
fn.stdpath('config'),
|
|
||||||
1,
|
|
||||||
true
|
|
||||||
) ~= nil
|
|
||||||
)
|
)
|
||||||
|
|
||||||
clear('--clean')
|
clear('--clean')
|
||||||
ok(
|
ok(
|
||||||
string.find(
|
not t.fix_slashes(api.nvim_get_option_value('runtimepath', {}))
|
||||||
alter_slashes(api.nvim_get_option_value('runtimepath', {})),
|
:match(vim.pesc(t.fix_slashes(fn.stdpath('config'))))
|
||||||
fn.stdpath('config'),
|
|
||||||
1,
|
|
||||||
true
|
|
||||||
) == nil
|
|
||||||
)
|
)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
@ -170,7 +170,7 @@ describe(':mksession', function()
|
|||||||
skip(is_os('win'), 'causes rmdir() to fail')
|
skip(is_os('win'), 'causes rmdir() to fail')
|
||||||
|
|
||||||
local cwd_dir = fn.fnamemodify('.', ':p:~'):gsub([[[\/]*$]], '')
|
local cwd_dir = fn.fnamemodify('.', ':p:~'):gsub([[[\/]*$]], '')
|
||||||
cwd_dir = cwd_dir:gsub([[\]], '/') -- :mksession always uses unix slashes.
|
cwd_dir = t.fix_slashes(cwd_dir) -- :mksession always uses unix slashes.
|
||||||
local session_path = cwd_dir .. '/' .. session_file
|
local session_path = cwd_dir .. '/' .. session_file
|
||||||
|
|
||||||
command('cd ' .. tab_dir)
|
command('cd ' .. tab_dir)
|
||||||
|
@ -217,7 +217,7 @@ describe('URI methods', function()
|
|||||||
]],
|
]],
|
||||||
file
|
file
|
||||||
)
|
)
|
||||||
local expected_uri = 'file:///' .. file:gsub('\\', '/')
|
local expected_uri = 'file:///' .. t.fix_slashes(file)
|
||||||
eq(expected_uri, exec_lua(test_case))
|
eq(expected_uri, exec_lua(test_case))
|
||||||
os.remove(file)
|
os.remove(file)
|
||||||
end)
|
end)
|
||||||
|
@ -1071,12 +1071,11 @@ describe('lua stdlib', function()
|
|||||||
]])
|
]])
|
||||||
)
|
)
|
||||||
|
|
||||||
-- Fix github issue #23654
|
|
||||||
ok(exec_lua([[
|
ok(exec_lua([[
|
||||||
local a = { sub = { [1] = 'a' } }
|
local a = { sub = { 'a', 'b' } }
|
||||||
local b = { sub = { b = 'a' } }
|
local b = { sub = { 'b', 'c' } }
|
||||||
local c = vim.tbl_deep_extend('force', a, b)
|
local c = vim.tbl_deep_extend('force', a, b)
|
||||||
return vim.deep_equal(c, { sub = { [1] = 'a', b = 'a' } })
|
return vim.deep_equal(c, { sub = { 'b', 'c' } })
|
||||||
]]))
|
]]))
|
||||||
|
|
||||||
matches('invalid "behavior": nil', pcall_err(exec_lua, [[return vim.tbl_deep_extend()]]))
|
matches('invalid "behavior": nil', pcall_err(exec_lua, [[return vim.tbl_deep_extend()]]))
|
||||||
|
@ -22,7 +22,7 @@ describe("'autochdir'", function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
it('is not overwritten by getwinvar() call #17609', function()
|
it('is not overwritten by getwinvar() call #17609', function()
|
||||||
local curdir = vim.uv.cwd():gsub('\\', '/')
|
local curdir = t.fix_slashes(vim.uv.cwd())
|
||||||
local dir_a = curdir .. '/Xtest-functional-options-autochdir.dir_a'
|
local dir_a = curdir .. '/Xtest-functional-options-autochdir.dir_a'
|
||||||
local dir_b = curdir .. '/Xtest-functional-options-autochdir.dir_b'
|
local dir_b = curdir .. '/Xtest-functional-options-autochdir.dir_b'
|
||||||
mkdir(dir_a)
|
mkdir(dir_a)
|
||||||
|
@ -23,7 +23,6 @@ local insert = n.insert
|
|||||||
local neq = t.neq
|
local neq = t.neq
|
||||||
local mkdir = t.mkdir
|
local mkdir = t.mkdir
|
||||||
local rmdir = n.rmdir
|
local rmdir = n.rmdir
|
||||||
local alter_slashes = n.alter_slashes
|
|
||||||
local tbl_contains = vim.tbl_contains
|
local tbl_contains = vim.tbl_contains
|
||||||
local expect_exit = n.expect_exit
|
local expect_exit = n.expect_exit
|
||||||
local check_close = n.check_close
|
local check_close = n.check_close
|
||||||
@ -262,7 +261,7 @@ describe('startup defaults', function()
|
|||||||
NVIM_LOG_FILE = '', -- Empty is invalid.
|
NVIM_LOG_FILE = '', -- Empty is invalid.
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
eq(xdgstatedir .. '/log', string.gsub(eval('$NVIM_LOG_FILE'), '\\', '/'))
|
eq(xdgstatedir .. '/log', t.fix_slashes(eval('$NVIM_LOG_FILE')))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('defaults to stdpath("log")/log if invalid', function()
|
it('defaults to stdpath("log")/log if invalid', function()
|
||||||
@ -273,7 +272,7 @@ describe('startup defaults', function()
|
|||||||
NVIM_LOG_FILE = '.', -- Any directory is invalid.
|
NVIM_LOG_FILE = '.', -- Any directory is invalid.
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
eq(xdgstatedir .. '/log', string.gsub(eval('$NVIM_LOG_FILE'), '\\', '/'))
|
eq(xdgstatedir .. '/log', t.fix_slashes(eval('$NVIM_LOG_FILE')))
|
||||||
-- Avoid "failed to open $NVIM_LOG_FILE" noise in test output.
|
-- Avoid "failed to open $NVIM_LOG_FILE" noise in test output.
|
||||||
expect_exit(command, 'qall!')
|
expect_exit(command, 'qall!')
|
||||||
end)
|
end)
|
||||||
@ -383,69 +382,69 @@ describe('XDG defaults', function()
|
|||||||
|
|
||||||
eq(
|
eq(
|
||||||
(
|
(
|
||||||
(
|
t.fix_slashes(
|
||||||
root_path
|
root_path
|
||||||
.. ('/x'):rep(4096)
|
.. ('/x'):rep(4096)
|
||||||
.. '/nvim'
|
.. '/nvim'
|
||||||
.. ','
|
.. ','
|
||||||
.. root_path
|
.. root_path
|
||||||
.. ('/a'):rep(2048)
|
.. ('/a'):rep(2048)
|
||||||
.. '/nvim'
|
.. '/nvim'
|
||||||
.. ','
|
.. ','
|
||||||
.. root_path
|
.. root_path
|
||||||
.. ('/b'):rep(2048)
|
.. ('/b'):rep(2048)
|
||||||
.. '/nvim'
|
.. '/nvim'
|
||||||
.. (',' .. root_path .. '/c/nvim')
|
.. (',' .. root_path .. '/c/nvim')
|
||||||
.. ','
|
.. ','
|
||||||
.. root_path
|
.. root_path
|
||||||
.. ('/X'):rep(4096)
|
.. ('/X'):rep(4096)
|
||||||
.. '/'
|
.. '/'
|
||||||
.. data_dir
|
.. data_dir
|
||||||
.. '/site'
|
.. '/site'
|
||||||
.. ','
|
.. ','
|
||||||
.. root_path
|
.. root_path
|
||||||
.. ('/A'):rep(2048)
|
.. ('/A'):rep(2048)
|
||||||
.. '/nvim/site'
|
.. '/nvim/site'
|
||||||
.. ','
|
.. ','
|
||||||
.. root_path
|
.. root_path
|
||||||
.. ('/B'):rep(2048)
|
.. ('/B'):rep(2048)
|
||||||
.. '/nvim/site'
|
.. '/nvim/site'
|
||||||
.. (',' .. root_path .. '/C/nvim/site')
|
.. (',' .. root_path .. '/C/nvim/site')
|
||||||
.. ','
|
.. ','
|
||||||
.. vimruntime
|
.. vimruntime
|
||||||
.. ','
|
.. ','
|
||||||
.. libdir
|
.. libdir
|
||||||
.. (',' .. root_path .. '/C/nvim/site/after')
|
.. (',' .. root_path .. '/C/nvim/site/after')
|
||||||
.. ','
|
.. ','
|
||||||
.. root_path
|
.. root_path
|
||||||
.. ('/B'):rep(2048)
|
.. ('/B'):rep(2048)
|
||||||
.. '/nvim/site/after'
|
.. '/nvim/site/after'
|
||||||
.. ','
|
.. ','
|
||||||
.. root_path
|
.. root_path
|
||||||
.. ('/A'):rep(2048)
|
.. ('/A'):rep(2048)
|
||||||
.. '/nvim/site/after'
|
.. '/nvim/site/after'
|
||||||
.. ','
|
.. ','
|
||||||
.. root_path
|
.. root_path
|
||||||
.. ('/X'):rep(4096)
|
.. ('/X'):rep(4096)
|
||||||
.. '/'
|
.. '/'
|
||||||
.. data_dir
|
.. data_dir
|
||||||
.. '/site/after'
|
.. '/site/after'
|
||||||
.. (',' .. root_path .. '/c/nvim/after')
|
.. (',' .. root_path .. '/c/nvim/after')
|
||||||
.. ','
|
.. ','
|
||||||
.. root_path
|
.. root_path
|
||||||
.. ('/b'):rep(2048)
|
.. ('/b'):rep(2048)
|
||||||
.. '/nvim/after'
|
.. '/nvim/after'
|
||||||
.. ','
|
.. ','
|
||||||
.. root_path
|
.. root_path
|
||||||
.. ('/a'):rep(2048)
|
.. ('/a'):rep(2048)
|
||||||
.. '/nvim/after'
|
.. '/nvim/after'
|
||||||
.. ','
|
.. ','
|
||||||
.. root_path
|
.. root_path
|
||||||
.. ('/x'):rep(4096)
|
.. ('/x'):rep(4096)
|
||||||
.. '/nvim/after'
|
.. '/nvim/after'
|
||||||
):gsub('\\', '/')
|
)
|
||||||
),
|
),
|
||||||
(api.nvim_get_option_value('runtimepath', {})):gsub('\\', '/')
|
t.fix_slashes(api.nvim_get_option_value('runtimepath', {}))
|
||||||
)
|
)
|
||||||
command('set runtimepath&')
|
command('set runtimepath&')
|
||||||
command('set backupdir&')
|
command('set backupdir&')
|
||||||
@ -454,85 +453,85 @@ describe('XDG defaults', function()
|
|||||||
command('set viewdir&')
|
command('set viewdir&')
|
||||||
eq(
|
eq(
|
||||||
(
|
(
|
||||||
(
|
t.fix_slashes(
|
||||||
root_path
|
root_path
|
||||||
.. ('/x'):rep(4096)
|
.. ('/x'):rep(4096)
|
||||||
.. '/nvim'
|
.. '/nvim'
|
||||||
.. ','
|
.. ','
|
||||||
.. root_path
|
.. root_path
|
||||||
.. ('/a'):rep(2048)
|
.. ('/a'):rep(2048)
|
||||||
.. '/nvim'
|
.. '/nvim'
|
||||||
.. ','
|
.. ','
|
||||||
.. root_path
|
.. root_path
|
||||||
.. ('/b'):rep(2048)
|
.. ('/b'):rep(2048)
|
||||||
.. '/nvim'
|
.. '/nvim'
|
||||||
.. (',' .. root_path .. '/c/nvim')
|
.. (',' .. root_path .. '/c/nvim')
|
||||||
.. ','
|
.. ','
|
||||||
.. root_path
|
.. root_path
|
||||||
.. ('/X'):rep(4096)
|
.. ('/X'):rep(4096)
|
||||||
.. '/'
|
.. '/'
|
||||||
.. data_dir
|
.. data_dir
|
||||||
.. '/site'
|
.. '/site'
|
||||||
.. ','
|
.. ','
|
||||||
.. root_path
|
.. root_path
|
||||||
.. ('/A'):rep(2048)
|
.. ('/A'):rep(2048)
|
||||||
.. '/nvim/site'
|
.. '/nvim/site'
|
||||||
.. ','
|
.. ','
|
||||||
.. root_path
|
.. root_path
|
||||||
.. ('/B'):rep(2048)
|
.. ('/B'):rep(2048)
|
||||||
.. '/nvim/site'
|
.. '/nvim/site'
|
||||||
.. (',' .. root_path .. '/C/nvim/site')
|
.. (',' .. root_path .. '/C/nvim/site')
|
||||||
.. ','
|
.. ','
|
||||||
.. vimruntime
|
.. vimruntime
|
||||||
.. ','
|
.. ','
|
||||||
.. libdir
|
.. libdir
|
||||||
.. (',' .. root_path .. '/C/nvim/site/after')
|
.. (',' .. root_path .. '/C/nvim/site/after')
|
||||||
.. ','
|
.. ','
|
||||||
.. root_path
|
.. root_path
|
||||||
.. ('/B'):rep(2048)
|
.. ('/B'):rep(2048)
|
||||||
.. '/nvim/site/after'
|
.. '/nvim/site/after'
|
||||||
.. ','
|
.. ','
|
||||||
.. root_path
|
.. root_path
|
||||||
.. ('/A'):rep(2048)
|
.. ('/A'):rep(2048)
|
||||||
.. '/nvim/site/after'
|
.. '/nvim/site/after'
|
||||||
.. ','
|
.. ','
|
||||||
.. root_path
|
.. root_path
|
||||||
.. ('/X'):rep(4096)
|
.. ('/X'):rep(4096)
|
||||||
.. '/'
|
.. '/'
|
||||||
.. data_dir
|
.. data_dir
|
||||||
.. '/site/after'
|
.. '/site/after'
|
||||||
.. (',' .. root_path .. '/c/nvim/after')
|
.. (',' .. root_path .. '/c/nvim/after')
|
||||||
.. ','
|
.. ','
|
||||||
.. root_path
|
.. root_path
|
||||||
.. ('/b'):rep(2048)
|
.. ('/b'):rep(2048)
|
||||||
.. '/nvim/after'
|
.. '/nvim/after'
|
||||||
.. ','
|
.. ','
|
||||||
.. root_path
|
.. root_path
|
||||||
.. ('/a'):rep(2048)
|
.. ('/a'):rep(2048)
|
||||||
.. '/nvim/after'
|
.. '/nvim/after'
|
||||||
.. ','
|
.. ','
|
||||||
.. root_path
|
.. root_path
|
||||||
.. ('/x'):rep(4096)
|
.. ('/x'):rep(4096)
|
||||||
.. '/nvim/after'
|
.. '/nvim/after'
|
||||||
):gsub('\\', '/')
|
)
|
||||||
),
|
),
|
||||||
(api.nvim_get_option_value('runtimepath', {})):gsub('\\', '/')
|
t.fix_slashes(api.nvim_get_option_value('runtimepath', {}))
|
||||||
)
|
)
|
||||||
eq(
|
eq(
|
||||||
'.,' .. root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/backup//',
|
'.,' .. root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/backup//',
|
||||||
(api.nvim_get_option_value('backupdir', {}):gsub('\\', '/'))
|
t.fix_slashes(api.nvim_get_option_value('backupdir', {}))
|
||||||
)
|
)
|
||||||
eq(
|
eq(
|
||||||
root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/swap//',
|
root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/swap//',
|
||||||
(api.nvim_get_option_value('directory', {})):gsub('\\', '/')
|
t.fix_slashes(api.nvim_get_option_value('directory', {}))
|
||||||
)
|
)
|
||||||
eq(
|
eq(
|
||||||
root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/undo//',
|
root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/undo//',
|
||||||
(api.nvim_get_option_value('undodir', {})):gsub('\\', '/')
|
t.fix_slashes(api.nvim_get_option_value('undodir', {}))
|
||||||
)
|
)
|
||||||
eq(
|
eq(
|
||||||
root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/view//',
|
root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/view//',
|
||||||
(api.nvim_get_option_value('viewdir', {})):gsub('\\', '/')
|
t.fix_slashes(api.nvim_get_option_value('viewdir', {}))
|
||||||
)
|
)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
@ -574,26 +573,26 @@ describe('XDG defaults', function()
|
|||||||
local vimruntime, libdir = vimruntime_and_libdir()
|
local vimruntime, libdir = vimruntime_and_libdir()
|
||||||
eq(
|
eq(
|
||||||
(
|
(
|
||||||
(
|
t.fix_slashes(
|
||||||
'$XDG_DATA_HOME/nvim'
|
'$XDG_DATA_HOME/nvim'
|
||||||
.. ',$XDG_DATA_DIRS/nvim'
|
.. ',$XDG_DATA_DIRS/nvim'
|
||||||
.. ',$XDG_CONFIG_HOME/'
|
.. ',$XDG_CONFIG_HOME/'
|
||||||
.. data_dir
|
.. data_dir
|
||||||
.. '/site'
|
.. '/site'
|
||||||
.. ',$XDG_CONFIG_DIRS/nvim/site'
|
.. ',$XDG_CONFIG_DIRS/nvim/site'
|
||||||
.. ','
|
.. ','
|
||||||
.. vimruntime
|
.. vimruntime
|
||||||
.. ','
|
.. ','
|
||||||
.. libdir
|
.. libdir
|
||||||
.. ',$XDG_CONFIG_DIRS/nvim/site/after'
|
.. ',$XDG_CONFIG_DIRS/nvim/site/after'
|
||||||
.. ',$XDG_CONFIG_HOME/'
|
.. ',$XDG_CONFIG_HOME/'
|
||||||
.. data_dir
|
.. data_dir
|
||||||
.. '/site/after'
|
.. '/site/after'
|
||||||
.. ',$XDG_DATA_DIRS/nvim/after'
|
.. ',$XDG_DATA_DIRS/nvim/after'
|
||||||
.. ',$XDG_DATA_HOME/nvim/after'
|
.. ',$XDG_DATA_HOME/nvim/after'
|
||||||
):gsub('\\', '/')
|
)
|
||||||
),
|
),
|
||||||
(api.nvim_get_option_value('runtimepath', {})):gsub('\\', '/')
|
t.fix_slashes(api.nvim_get_option_value('runtimepath', {}))
|
||||||
)
|
)
|
||||||
command('set runtimepath&')
|
command('set runtimepath&')
|
||||||
command('set backupdir&')
|
command('set backupdir&')
|
||||||
@ -602,8 +601,47 @@ describe('XDG defaults', function()
|
|||||||
command('set viewdir&')
|
command('set viewdir&')
|
||||||
eq(
|
eq(
|
||||||
(
|
(
|
||||||
(
|
t.fix_slashes(
|
||||||
'$XDG_DATA_HOME/nvim'
|
'$XDG_DATA_HOME/nvim'
|
||||||
|
.. ',$XDG_DATA_DIRS/nvim'
|
||||||
|
.. ',$XDG_CONFIG_HOME/'
|
||||||
|
.. data_dir
|
||||||
|
.. '/site'
|
||||||
|
.. ',$XDG_CONFIG_DIRS/nvim/site'
|
||||||
|
.. ','
|
||||||
|
.. vimruntime
|
||||||
|
.. ','
|
||||||
|
.. libdir
|
||||||
|
.. ',$XDG_CONFIG_DIRS/nvim/site/after'
|
||||||
|
.. ',$XDG_CONFIG_HOME/'
|
||||||
|
.. data_dir
|
||||||
|
.. '/site/after'
|
||||||
|
.. ',$XDG_DATA_DIRS/nvim/after'
|
||||||
|
.. ',$XDG_DATA_HOME/nvim/after'
|
||||||
|
)
|
||||||
|
),
|
||||||
|
t.fix_slashes(api.nvim_get_option_value('runtimepath', {}))
|
||||||
|
)
|
||||||
|
eq(
|
||||||
|
('.,$XDG_CONFIG_HOME/' .. state_dir .. '/backup//'),
|
||||||
|
t.fix_slashes(api.nvim_get_option_value('backupdir', {}))
|
||||||
|
)
|
||||||
|
eq(
|
||||||
|
('$XDG_CONFIG_HOME/' .. state_dir .. '/swap//'),
|
||||||
|
t.fix_slashes(api.nvim_get_option_value('directory', {}))
|
||||||
|
)
|
||||||
|
eq(
|
||||||
|
('$XDG_CONFIG_HOME/' .. state_dir .. '/undo//'),
|
||||||
|
t.fix_slashes(api.nvim_get_option_value('undodir', {}))
|
||||||
|
)
|
||||||
|
eq(
|
||||||
|
('$XDG_CONFIG_HOME/' .. state_dir .. '/view//'),
|
||||||
|
t.fix_slashes(api.nvim_get_option_value('viewdir', {}))
|
||||||
|
)
|
||||||
|
command('set all&')
|
||||||
|
eq(
|
||||||
|
t.fix_slashes(
|
||||||
|
'$XDG_DATA_HOME/nvim'
|
||||||
.. ',$XDG_DATA_DIRS/nvim'
|
.. ',$XDG_DATA_DIRS/nvim'
|
||||||
.. ',$XDG_CONFIG_HOME/'
|
.. ',$XDG_CONFIG_HOME/'
|
||||||
.. data_dir
|
.. data_dir
|
||||||
@ -619,63 +657,24 @@ describe('XDG defaults', function()
|
|||||||
.. '/site/after'
|
.. '/site/after'
|
||||||
.. ',$XDG_DATA_DIRS/nvim/after'
|
.. ',$XDG_DATA_DIRS/nvim/after'
|
||||||
.. ',$XDG_DATA_HOME/nvim/after'
|
.. ',$XDG_DATA_HOME/nvim/after'
|
||||||
):gsub('\\', '/')
|
|
||||||
),
|
),
|
||||||
(api.nvim_get_option_value('runtimepath', {})):gsub('\\', '/')
|
t.fix_slashes(api.nvim_get_option_value('runtimepath', {}))
|
||||||
)
|
)
|
||||||
eq(
|
eq(
|
||||||
('.,$XDG_CONFIG_HOME/' .. state_dir .. '/backup//'),
|
('.,$XDG_CONFIG_HOME/' .. state_dir .. '/backup//'),
|
||||||
api.nvim_get_option_value('backupdir', {}):gsub('\\', '/')
|
t.fix_slashes(api.nvim_get_option_value('backupdir', {}))
|
||||||
)
|
)
|
||||||
eq(
|
eq(
|
||||||
('$XDG_CONFIG_HOME/' .. state_dir .. '/swap//'),
|
('$XDG_CONFIG_HOME/' .. state_dir .. '/swap//'),
|
||||||
api.nvim_get_option_value('directory', {}):gsub('\\', '/')
|
t.fix_slashes(api.nvim_get_option_value('directory', {}))
|
||||||
)
|
)
|
||||||
eq(
|
eq(
|
||||||
('$XDG_CONFIG_HOME/' .. state_dir .. '/undo//'),
|
('$XDG_CONFIG_HOME/' .. state_dir .. '/undo//'),
|
||||||
api.nvim_get_option_value('undodir', {}):gsub('\\', '/')
|
t.fix_slashes(api.nvim_get_option_value('undodir', {}))
|
||||||
)
|
)
|
||||||
eq(
|
eq(
|
||||||
('$XDG_CONFIG_HOME/' .. state_dir .. '/view//'),
|
('$XDG_CONFIG_HOME/' .. state_dir .. '/view//'),
|
||||||
api.nvim_get_option_value('viewdir', {}):gsub('\\', '/')
|
t.fix_slashes(api.nvim_get_option_value('viewdir', {}))
|
||||||
)
|
|
||||||
command('set all&')
|
|
||||||
eq(
|
|
||||||
(
|
|
||||||
'$XDG_DATA_HOME/nvim'
|
|
||||||
.. ',$XDG_DATA_DIRS/nvim'
|
|
||||||
.. ',$XDG_CONFIG_HOME/'
|
|
||||||
.. data_dir
|
|
||||||
.. '/site'
|
|
||||||
.. ',$XDG_CONFIG_DIRS/nvim/site'
|
|
||||||
.. ','
|
|
||||||
.. vimruntime
|
|
||||||
.. ','
|
|
||||||
.. libdir
|
|
||||||
.. ',$XDG_CONFIG_DIRS/nvim/site/after'
|
|
||||||
.. ',$XDG_CONFIG_HOME/'
|
|
||||||
.. data_dir
|
|
||||||
.. '/site/after'
|
|
||||||
.. ',$XDG_DATA_DIRS/nvim/after'
|
|
||||||
.. ',$XDG_DATA_HOME/nvim/after'
|
|
||||||
):gsub('\\', '/'),
|
|
||||||
(api.nvim_get_option_value('runtimepath', {})):gsub('\\', '/')
|
|
||||||
)
|
|
||||||
eq(
|
|
||||||
('.,$XDG_CONFIG_HOME/' .. state_dir .. '/backup//'),
|
|
||||||
api.nvim_get_option_value('backupdir', {}):gsub('\\', '/')
|
|
||||||
)
|
|
||||||
eq(
|
|
||||||
('$XDG_CONFIG_HOME/' .. state_dir .. '/swap//'),
|
|
||||||
api.nvim_get_option_value('directory', {}):gsub('\\', '/')
|
|
||||||
)
|
|
||||||
eq(
|
|
||||||
('$XDG_CONFIG_HOME/' .. state_dir .. '/undo//'),
|
|
||||||
api.nvim_get_option_value('undodir', {}):gsub('\\', '/')
|
|
||||||
)
|
|
||||||
eq(
|
|
||||||
('$XDG_CONFIG_HOME/' .. state_dir .. '/view//'),
|
|
||||||
api.nvim_get_option_value('viewdir', {}):gsub('\\', '/')
|
|
||||||
)
|
)
|
||||||
eq(nil, (fn.tempname()):match('XDG_RUNTIME_DIR'))
|
eq(nil, (fn.tempname()):match('XDG_RUNTIME_DIR'))
|
||||||
end)
|
end)
|
||||||
@ -915,7 +914,7 @@ describe('stdpath()', function()
|
|||||||
assert_alive() -- Check for crash. #8393
|
assert_alive() -- Check for crash. #8393
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('supports $NVIM_APPNAME', function()
|
it('$NVIM_APPNAME', function()
|
||||||
local appname = 'NVIM_APPNAME_TEST' .. ('_'):rep(106)
|
local appname = 'NVIM_APPNAME_TEST' .. ('_'):rep(106)
|
||||||
clear({ env = { NVIM_APPNAME = appname, NVIM_LOG_FILE = testlog } })
|
clear({ env = { NVIM_APPNAME = appname, NVIM_LOG_FILE = testlog } })
|
||||||
eq(appname, fn.fnamemodify(fn.stdpath('config'), ':t'))
|
eq(appname, fn.fnamemodify(fn.stdpath('config'), ':t'))
|
||||||
@ -939,7 +938,7 @@ describe('stdpath()', function()
|
|||||||
local child = vim.fn.jobstart({ vim.v.progpath, '--clean', '--headless', '--listen', 'x', '+qall!' }, { env = { NVIM_APPNAME = %q } })
|
local child = vim.fn.jobstart({ vim.v.progpath, '--clean', '--headless', '--listen', 'x', '+qall!' }, { env = { NVIM_APPNAME = %q } })
|
||||||
return vim.fn.jobwait({ child }, %d)[1]
|
return vim.fn.jobwait({ child }, %d)[1]
|
||||||
]],
|
]],
|
||||||
alter_slashes(testAppname),
|
testAppname,
|
||||||
3000
|
3000
|
||||||
)
|
)
|
||||||
eq(expected_exitcode, exec_lua(lua_code))
|
eq(expected_exitcode, exec_lua(lua_code))
|
||||||
@ -957,24 +956,43 @@ describe('stdpath()', function()
|
|||||||
test_appname('a/b\\c', 0)
|
test_appname('a/b\\c', 0)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('$NVIM_APPNAME relative path', function()
|
||||||
|
local tmpdir = t.tmpname(false)
|
||||||
|
t.mkdir(tmpdir)
|
||||||
|
|
||||||
|
clear({
|
||||||
|
args_rm = { '--listen' },
|
||||||
|
env = {
|
||||||
|
NVIM_APPNAME = 'relative/appname',
|
||||||
|
NVIM_LOG_FILE = testlog,
|
||||||
|
TMPDIR = tmpdir,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
t.matches(vim.pesc(tmpdir), t.fix_slashes(fn.tempname()))
|
||||||
|
t.assert_nolog('tempdir', testlog, 100)
|
||||||
|
t.assert_nolog('TMPDIR', testlog, 100)
|
||||||
|
t.matches([=[[/\\]relative%-appname.[^/\\]+]=], api.nvim_get_vvar('servername'))
|
||||||
|
end)
|
||||||
|
|
||||||
describe('returns a String', function()
|
describe('returns a String', function()
|
||||||
describe('with "config"', function()
|
describe('with "config"', function()
|
||||||
it('knows XDG_CONFIG_HOME', function()
|
it('knows XDG_CONFIG_HOME', function()
|
||||||
clear({
|
clear({
|
||||||
env = {
|
env = {
|
||||||
XDG_CONFIG_HOME = alter_slashes('/home/docwhat/.config'),
|
XDG_CONFIG_HOME = '/home/docwhat/.config',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
eq(alter_slashes('/home/docwhat/.config/nvim'), fn.stdpath('config'))
|
eq('/home/docwhat/.config/nvim', t.fix_slashes(fn.stdpath('config')))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('handles changes during runtime', function()
|
it('handles changes during runtime', function()
|
||||||
clear({ env = {
|
clear({ env = {
|
||||||
XDG_CONFIG_HOME = alter_slashes('/home/original'),
|
XDG_CONFIG_HOME = '/home/original',
|
||||||
} })
|
} })
|
||||||
eq(alter_slashes('/home/original/nvim'), fn.stdpath('config'))
|
eq('/home/original/nvim', t.fix_slashes(fn.stdpath('config')))
|
||||||
command("let $XDG_CONFIG_HOME='" .. alter_slashes('/home/new') .. "'")
|
command("let $XDG_CONFIG_HOME='/home/new'")
|
||||||
eq(alter_slashes('/home/new/nvim'), fn.stdpath('config'))
|
eq('/home/new/nvim', t.fix_slashes(fn.stdpath('config')))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("doesn't expand $VARIABLES", function()
|
it("doesn't expand $VARIABLES", function()
|
||||||
@ -984,32 +1002,32 @@ describe('stdpath()', function()
|
|||||||
VARIABLES = 'this-should-not-happen',
|
VARIABLES = 'this-should-not-happen',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
eq(alter_slashes('$VARIABLES/nvim'), fn.stdpath('config'))
|
eq('$VARIABLES/nvim', t.fix_slashes(fn.stdpath('config')))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("doesn't expand ~/", function()
|
it("doesn't expand ~/", function()
|
||||||
clear({ env = {
|
clear({ env = {
|
||||||
XDG_CONFIG_HOME = alter_slashes('~/frobnitz'),
|
XDG_CONFIG_HOME = '~/frobnitz',
|
||||||
} })
|
} })
|
||||||
eq(alter_slashes('~/frobnitz/nvim'), fn.stdpath('config'))
|
eq('~/frobnitz/nvim', t.fix_slashes(fn.stdpath('config')))
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('with "data"', function()
|
describe('with "data"', function()
|
||||||
it('knows XDG_DATA_HOME', function()
|
it('knows XDG_DATA_HOME', function()
|
||||||
clear({ env = {
|
clear({ env = {
|
||||||
XDG_DATA_HOME = alter_slashes('/home/docwhat/.local'),
|
XDG_DATA_HOME = '/home/docwhat/.local',
|
||||||
} })
|
} })
|
||||||
eq(alter_slashes('/home/docwhat/.local/' .. datadir), fn.stdpath('data'))
|
eq('/home/docwhat/.local/' .. datadir, t.fix_slashes(fn.stdpath('data')))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('handles changes during runtime', function()
|
it('handles changes during runtime', function()
|
||||||
clear({ env = {
|
clear({ env = {
|
||||||
XDG_DATA_HOME = alter_slashes('/home/original'),
|
XDG_DATA_HOME = '/home/original',
|
||||||
} })
|
} })
|
||||||
eq(alter_slashes('/home/original/' .. datadir), fn.stdpath('data'))
|
eq('/home/original/' .. datadir, t.fix_slashes(fn.stdpath('data')))
|
||||||
command("let $XDG_DATA_HOME='" .. alter_slashes('/home/new') .. "'")
|
command("let $XDG_DATA_HOME='/home/new'")
|
||||||
eq(alter_slashes('/home/new/' .. datadir), fn.stdpath('data'))
|
eq('/home/new/' .. datadir, t.fix_slashes(fn.stdpath('data')))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("doesn't expand $VARIABLES", function()
|
it("doesn't expand $VARIABLES", function()
|
||||||
@ -1019,14 +1037,14 @@ describe('stdpath()', function()
|
|||||||
VARIABLES = 'this-should-not-happen',
|
VARIABLES = 'this-should-not-happen',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
eq(alter_slashes('$VARIABLES/' .. datadir), fn.stdpath('data'))
|
eq('$VARIABLES/' .. datadir, t.fix_slashes(fn.stdpath('data')))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("doesn't expand ~/", function()
|
it("doesn't expand ~/", function()
|
||||||
clear({ env = {
|
clear({ env = {
|
||||||
XDG_DATA_HOME = alter_slashes('~/frobnitz'),
|
XDG_DATA_HOME = '~/frobnitz',
|
||||||
} })
|
} })
|
||||||
eq(alter_slashes('~/frobnitz/' .. datadir), fn.stdpath('data'))
|
eq('~/frobnitz/' .. datadir, t.fix_slashes(fn.stdpath('data')))
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@ -1034,19 +1052,19 @@ describe('stdpath()', function()
|
|||||||
it('knows XDG_STATE_HOME', function()
|
it('knows XDG_STATE_HOME', function()
|
||||||
clear({
|
clear({
|
||||||
env = {
|
env = {
|
||||||
XDG_STATE_HOME = alter_slashes('/home/docwhat/.local'),
|
XDG_STATE_HOME = '/home/docwhat/.local',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
eq(alter_slashes('/home/docwhat/.local/' .. statedir), fn.stdpath('state'))
|
eq('/home/docwhat/.local/' .. statedir, t.fix_slashes(fn.stdpath('state')))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('handles changes during runtime', function()
|
it('handles changes during runtime', function()
|
||||||
clear({ env = {
|
clear({ env = {
|
||||||
XDG_STATE_HOME = alter_slashes('/home/original'),
|
XDG_STATE_HOME = '/home/original',
|
||||||
} })
|
} })
|
||||||
eq(alter_slashes('/home/original/' .. statedir), fn.stdpath('state'))
|
eq('/home/original/' .. statedir, t.fix_slashes(fn.stdpath('state')))
|
||||||
command("let $XDG_STATE_HOME='" .. alter_slashes('/home/new') .. "'")
|
command("let $XDG_STATE_HOME='" .. '/home/new' .. "'")
|
||||||
eq(alter_slashes('/home/new/' .. statedir), fn.stdpath('state'))
|
eq('/home/new/' .. statedir, t.fix_slashes(fn.stdpath('state')))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("doesn't expand $VARIABLES", function()
|
it("doesn't expand $VARIABLES", function()
|
||||||
@ -1056,14 +1074,14 @@ describe('stdpath()', function()
|
|||||||
VARIABLES = 'this-should-not-happen',
|
VARIABLES = 'this-should-not-happen',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
eq(alter_slashes('$VARIABLES/' .. statedir), fn.stdpath('state'))
|
eq('$VARIABLES/' .. statedir, t.fix_slashes(fn.stdpath('state')))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("doesn't expand ~/", function()
|
it("doesn't expand ~/", function()
|
||||||
clear({ env = {
|
clear({ env = {
|
||||||
XDG_STATE_HOME = alter_slashes('~/frobnitz'),
|
XDG_STATE_HOME = '~/frobnitz',
|
||||||
} })
|
} })
|
||||||
eq(alter_slashes('~/frobnitz/' .. statedir), fn.stdpath('state'))
|
eq('~/frobnitz/' .. statedir, t.fix_slashes(fn.stdpath('state')))
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@ -1071,19 +1089,19 @@ describe('stdpath()', function()
|
|||||||
it('knows XDG_CACHE_HOME', function()
|
it('knows XDG_CACHE_HOME', function()
|
||||||
clear({
|
clear({
|
||||||
env = {
|
env = {
|
||||||
XDG_CACHE_HOME = alter_slashes('/home/docwhat/.cache'),
|
XDG_CACHE_HOME = '/home/docwhat/.cache',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
eq(alter_slashes('/home/docwhat/.cache/nvim'), fn.stdpath('cache'))
|
eq('/home/docwhat/.cache/nvim', t.fix_slashes(fn.stdpath('cache')))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('handles changes during runtime', function()
|
it('handles changes during runtime', function()
|
||||||
clear({ env = {
|
clear({ env = {
|
||||||
XDG_CACHE_HOME = alter_slashes('/home/original'),
|
XDG_CACHE_HOME = '/home/original',
|
||||||
} })
|
} })
|
||||||
eq(alter_slashes('/home/original/nvim'), fn.stdpath('cache'))
|
eq('/home/original/nvim', t.fix_slashes(fn.stdpath('cache')))
|
||||||
command("let $XDG_CACHE_HOME='" .. alter_slashes('/home/new') .. "'")
|
command("let $XDG_CACHE_HOME='" .. '/home/new' .. "'")
|
||||||
eq(alter_slashes('/home/new/nvim'), fn.stdpath('cache'))
|
eq('/home/new/nvim', t.fix_slashes(fn.stdpath('cache')))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("doesn't expand $VARIABLES", function()
|
it("doesn't expand $VARIABLES", function()
|
||||||
@ -1093,14 +1111,14 @@ describe('stdpath()', function()
|
|||||||
VARIABLES = 'this-should-not-happen',
|
VARIABLES = 'this-should-not-happen',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
eq(alter_slashes('$VARIABLES/nvim'), fn.stdpath('cache'))
|
eq('$VARIABLES/nvim', t.fix_slashes(fn.stdpath('cache')))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("doesn't expand ~/", function()
|
it("doesn't expand ~/", function()
|
||||||
clear({ env = {
|
clear({ env = {
|
||||||
XDG_CACHE_HOME = alter_slashes('~/frobnitz'),
|
XDG_CACHE_HOME = '~/frobnitz',
|
||||||
} })
|
} })
|
||||||
eq(alter_slashes('~/frobnitz/nvim'), fn.stdpath('cache'))
|
eq('~/frobnitz/nvim', t.fix_slashes(fn.stdpath('cache')))
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
@ -1114,6 +1132,7 @@ describe('stdpath()', function()
|
|||||||
HOMEDRIVE = 'C:',
|
HOMEDRIVE = 'C:',
|
||||||
HOMEPATH = '\\Users\\docwhat',
|
HOMEPATH = '\\Users\\docwhat',
|
||||||
LOCALAPPDATA = 'C:\\Users\\docwhat\\AppData\\Local',
|
LOCALAPPDATA = 'C:\\Users\\docwhat\\AppData\\Local',
|
||||||
|
NVIM_LOG_FILE = testlog,
|
||||||
TEMP = 'C:\\Users\\docwhat\\AppData\\Local\\Temp',
|
TEMP = 'C:\\Users\\docwhat\\AppData\\Local\\Temp',
|
||||||
TMPDIR = 'C:\\Users\\docwhat\\AppData\\Local\\Temp',
|
TMPDIR = 'C:\\Users\\docwhat\\AppData\\Local\\Temp',
|
||||||
TMP = 'C:\\Users\\docwhat\\AppData\\Local\\Temp',
|
TMP = 'C:\\Users\\docwhat\\AppData\\Local\\Temp',
|
||||||
@ -1124,6 +1143,7 @@ describe('stdpath()', function()
|
|||||||
HOMEDRIVE = 'HOMEDRIVE-should-be-ignored',
|
HOMEDRIVE = 'HOMEDRIVE-should-be-ignored',
|
||||||
HOMEPATH = 'HOMEPATH-should-be-ignored',
|
HOMEPATH = 'HOMEPATH-should-be-ignored',
|
||||||
LOCALAPPDATA = 'LOCALAPPDATA-should-be-ignored',
|
LOCALAPPDATA = 'LOCALAPPDATA-should-be-ignored',
|
||||||
|
NVIM_LOG_FILE = testlog,
|
||||||
TEMP = 'TEMP-should-be-ignored',
|
TEMP = 'TEMP-should-be-ignored',
|
||||||
TMPDIR = 'TMPDIR-should-be-ignored',
|
TMPDIR = 'TMPDIR-should-be-ignored',
|
||||||
TMP = 'TMP-should-be-ignored',
|
TMP = 'TMP-should-be-ignored',
|
||||||
@ -1147,12 +1167,18 @@ describe('stdpath()', function()
|
|||||||
describe(msg, function()
|
describe(msg, function()
|
||||||
it('set via system', function()
|
it('set via system', function()
|
||||||
set_paths_via_system(env_var_name, paths)
|
set_paths_via_system(env_var_name, paths)
|
||||||
eq(expected_paths, fn.stdpath(stdpath_arg))
|
eq(expected_paths, t.fix_slashes(fn.stdpath(stdpath_arg)))
|
||||||
|
if not is_os('win') then
|
||||||
|
assert_log('$TMPDIR tempdir not a directory.*TMPDIR%-should%-be%-ignored', testlog, 100)
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('set at runtime', function()
|
it('set at runtime', function()
|
||||||
set_paths_at_runtime(env_var_name, paths)
|
set_paths_at_runtime(env_var_name, paths)
|
||||||
eq(expected_paths, fn.stdpath(stdpath_arg))
|
eq(expected_paths, t.fix_slashes(fn.stdpath(stdpath_arg)))
|
||||||
|
if not is_os('win') then
|
||||||
|
assert_log('$TMPDIR tempdir not a directory.*TMPDIR%-should%-be%-ignored', testlog, 100)
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@ -1163,10 +1189,10 @@ describe('stdpath()', function()
|
|||||||
'config_dirs',
|
'config_dirs',
|
||||||
'XDG_CONFIG_DIRS',
|
'XDG_CONFIG_DIRS',
|
||||||
{
|
{
|
||||||
alter_slashes('/home/docwhat/.config'),
|
t.fix_slashes('/home/docwhat/.config'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
alter_slashes('/home/docwhat/.config/nvim'),
|
t.fix_slashes('/home/docwhat/.config/nvim'),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1175,12 +1201,12 @@ describe('stdpath()', function()
|
|||||||
'config_dirs',
|
'config_dirs',
|
||||||
'XDG_CONFIG_DIRS',
|
'XDG_CONFIG_DIRS',
|
||||||
{
|
{
|
||||||
alter_slashes('/home/docwhat/.config'),
|
t.fix_slashes('/home/docwhat/.config'),
|
||||||
alter_slashes('/etc/config'),
|
t.fix_slashes('/etc/config'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
alter_slashes('/home/docwhat/.config/nvim'),
|
t.fix_slashes('/home/docwhat/.config/nvim'),
|
||||||
alter_slashes('/etc/config/nvim'),
|
t.fix_slashes('/etc/config/nvim'),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1190,25 +1216,25 @@ describe('stdpath()', function()
|
|||||||
'XDG_CONFIG_DIRS',
|
'XDG_CONFIG_DIRS',
|
||||||
{ '$HOME', '$TMP' },
|
{ '$HOME', '$TMP' },
|
||||||
{
|
{
|
||||||
alter_slashes('$HOME/nvim'),
|
t.fix_slashes('$HOME/nvim'),
|
||||||
alter_slashes('$TMP/nvim'),
|
t.fix_slashes('$TMP/nvim'),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
behaves_like_dir_list_env("doesn't expand ~/", 'config_dirs', 'XDG_CONFIG_DIRS', {
|
behaves_like_dir_list_env("doesn't expand ~/", 'config_dirs', 'XDG_CONFIG_DIRS', {
|
||||||
alter_slashes('~/.oldconfig'),
|
t.fix_slashes('~/.oldconfig'),
|
||||||
alter_slashes('~/.olderconfig'),
|
t.fix_slashes('~/.olderconfig'),
|
||||||
}, {
|
}, {
|
||||||
alter_slashes('~/.oldconfig/nvim'),
|
t.fix_slashes('~/.oldconfig/nvim'),
|
||||||
alter_slashes('~/.olderconfig/nvim'),
|
t.fix_slashes('~/.olderconfig/nvim'),
|
||||||
})
|
})
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('with "data_dirs"', function()
|
describe('with "data_dirs"', function()
|
||||||
behaves_like_dir_list_env('knows XDG_DATA_DIRS with one path', 'data_dirs', 'XDG_DATA_DIRS', {
|
behaves_like_dir_list_env('knows XDG_DATA_DIRS with one path', 'data_dirs', 'XDG_DATA_DIRS', {
|
||||||
alter_slashes('/home/docwhat/.data'),
|
t.fix_slashes('/home/docwhat/.data'),
|
||||||
}, {
|
}, {
|
||||||
alter_slashes('/home/docwhat/.data/nvim'),
|
t.fix_slashes('/home/docwhat/.data/nvim'),
|
||||||
})
|
})
|
||||||
|
|
||||||
behaves_like_dir_list_env(
|
behaves_like_dir_list_env(
|
||||||
@ -1216,12 +1242,12 @@ describe('stdpath()', function()
|
|||||||
'data_dirs',
|
'data_dirs',
|
||||||
'XDG_DATA_DIRS',
|
'XDG_DATA_DIRS',
|
||||||
{
|
{
|
||||||
alter_slashes('/home/docwhat/.data'),
|
t.fix_slashes('/home/docwhat/.data'),
|
||||||
alter_slashes('/etc/local'),
|
t.fix_slashes('/etc/local'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
alter_slashes('/home/docwhat/.data/nvim'),
|
t.fix_slashes('/home/docwhat/.data/nvim'),
|
||||||
alter_slashes('/etc/local/nvim'),
|
t.fix_slashes('/etc/local/nvim'),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1231,17 +1257,17 @@ describe('stdpath()', function()
|
|||||||
'XDG_DATA_DIRS',
|
'XDG_DATA_DIRS',
|
||||||
{ '$HOME', '$TMP' },
|
{ '$HOME', '$TMP' },
|
||||||
{
|
{
|
||||||
alter_slashes('$HOME/nvim'),
|
t.fix_slashes('$HOME/nvim'),
|
||||||
alter_slashes('$TMP/nvim'),
|
t.fix_slashes('$TMP/nvim'),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
behaves_like_dir_list_env("doesn't expand ~/", 'data_dirs', 'XDG_DATA_DIRS', {
|
behaves_like_dir_list_env("doesn't expand ~/", 'data_dirs', 'XDG_DATA_DIRS', {
|
||||||
alter_slashes('~/.oldconfig'),
|
t.fix_slashes('~/.oldconfig'),
|
||||||
alter_slashes('~/.olderconfig'),
|
t.fix_slashes('~/.olderconfig'),
|
||||||
}, {
|
}, {
|
||||||
alter_slashes('~/.oldconfig/nvim'),
|
t.fix_slashes('~/.oldconfig/nvim'),
|
||||||
alter_slashes('~/.olderconfig/nvim'),
|
t.fix_slashes('~/.olderconfig/nvim'),
|
||||||
})
|
})
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
@ -40,11 +40,22 @@ describe(':checkhealth', function()
|
|||||||
matches('ERROR $VIM .* zub', curbuf_contents())
|
matches('ERROR $VIM .* zub', curbuf_contents())
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('completions can be listed via getcompletion()', function()
|
it('getcompletion()', function()
|
||||||
clear()
|
clear { args = { '-u', 'NORC', '+set runtimepath+=test/functional/fixtures' } }
|
||||||
|
|
||||||
eq('vim.deprecated', getcompletion('vim', 'checkhealth')[1])
|
eq('vim.deprecated', getcompletion('vim', 'checkhealth')[1])
|
||||||
eq('vim.provider', getcompletion('vim.prov', 'checkhealth')[1])
|
eq('vim.provider', getcompletion('vim.prov', 'checkhealth')[1])
|
||||||
eq('vim.lsp', getcompletion('vim.ls', 'checkhealth')[1])
|
eq('vim.lsp', getcompletion('vim.ls', 'checkhealth')[1])
|
||||||
|
|
||||||
|
-- "test_plug/health/init.lua" should complete as "test_plug", not "test_plug.health". #30342
|
||||||
|
eq({
|
||||||
|
'test_plug',
|
||||||
|
'test_plug.full_render',
|
||||||
|
'test_plug.submodule',
|
||||||
|
'test_plug.submodule_empty',
|
||||||
|
'test_plug.success1',
|
||||||
|
'test_plug.success2',
|
||||||
|
}, getcompletion('test_plug', 'checkhealth'))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('completion checks for vim.health._complete() return type #28456', function()
|
it('completion checks for vim.health._complete() return type #28456', function()
|
||||||
@ -57,11 +68,9 @@ describe(':checkhealth', function()
|
|||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('health.vim', function()
|
describe('vim.health', function()
|
||||||
before_each(function()
|
before_each(function()
|
||||||
clear { args = { '-u', 'NORC' } }
|
clear { args = { '-u', 'NORC', '+set runtimepath+=test/functional/fixtures' } }
|
||||||
-- Provides healthcheck functions
|
|
||||||
command('set runtimepath+=test/functional/fixtures')
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe(':checkhealth', function()
|
describe(':checkhealth', function()
|
||||||
@ -207,9 +216,7 @@ end)
|
|||||||
|
|
||||||
describe(':checkhealth window', function()
|
describe(':checkhealth window', function()
|
||||||
before_each(function()
|
before_each(function()
|
||||||
clear { args = { '-u', 'NORC' } }
|
clear { args = { '-u', 'NORC', '+set runtimepath+=test/functional/fixtures' } }
|
||||||
-- Provides healthcheck functions
|
|
||||||
command('set runtimepath+=test/functional/fixtures')
|
|
||||||
command('set nofoldenable nowrap laststatus=0')
|
command('set nofoldenable nowrap laststatus=0')
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
@ -3607,21 +3607,21 @@ describe('LSP', function()
|
|||||||
range = {
|
range = {
|
||||||
['end'] = {
|
['end'] = {
|
||||||
character = 8,
|
character = 8,
|
||||||
line = 9,
|
line = 3,
|
||||||
},
|
},
|
||||||
start = {
|
start = {
|
||||||
character = 6,
|
character = 6,
|
||||||
line = 9,
|
line = 3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
selectionRange = {
|
selectionRange = {
|
||||||
['end'] = {
|
['end'] = {
|
||||||
character = 8,
|
character = 8,
|
||||||
line = 9,
|
line = 3,
|
||||||
},
|
},
|
||||||
start = {
|
start = {
|
||||||
character = 6,
|
character = 6,
|
||||||
line = 9,
|
line = 3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
uri = 'file:///home/jiangyinzuo/hello.cpp',
|
uri = 'file:///home/jiangyinzuo/hello.cpp',
|
||||||
@ -3651,21 +3651,21 @@ describe('LSP', function()
|
|||||||
range = {
|
range = {
|
||||||
['end'] = {
|
['end'] = {
|
||||||
character = 8,
|
character = 8,
|
||||||
line = 8,
|
line = 2,
|
||||||
},
|
},
|
||||||
start = {
|
start = {
|
||||||
character = 6,
|
character = 6,
|
||||||
line = 8,
|
line = 2,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
selectionRange = {
|
selectionRange = {
|
||||||
['end'] = {
|
['end'] = {
|
||||||
character = 8,
|
character = 8,
|
||||||
line = 8,
|
line = 2,
|
||||||
},
|
},
|
||||||
start = {
|
start = {
|
||||||
character = 6,
|
character = 6,
|
||||||
line = 8,
|
line = 2,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
uri = 'file:///home/jiangyinzuo/hello.cpp',
|
uri = 'file:///home/jiangyinzuo/hello.cpp',
|
||||||
@ -3679,7 +3679,15 @@ describe('LSP', function()
|
|||||||
})
|
})
|
||||||
local client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
|
local client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
|
||||||
local handler = require 'vim.lsp.handlers'['typeHierarchy/subtypes']
|
local handler = require 'vim.lsp.handlers'['typeHierarchy/subtypes']
|
||||||
handler(nil, clangd_response, { client_id = client_id, bufnr = 1 })
|
local bufnr = vim.api.nvim_get_current_buf()
|
||||||
|
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {
|
||||||
|
'class B : public A{};',
|
||||||
|
'class C : public B{};',
|
||||||
|
'class D1 : public C{};',
|
||||||
|
'class D2 : public C{};',
|
||||||
|
'class E : public D1, D2 {};',
|
||||||
|
})
|
||||||
|
handler(nil, clangd_response, { client_id = client_id, bufnr = bufnr })
|
||||||
return vim.fn.getqflist()
|
return vim.fn.getqflist()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@ -3689,7 +3697,7 @@ describe('LSP', function()
|
|||||||
col = 7,
|
col = 7,
|
||||||
end_col = 0,
|
end_col = 0,
|
||||||
end_lnum = 0,
|
end_lnum = 0,
|
||||||
lnum = 10,
|
lnum = 4,
|
||||||
module = '',
|
module = '',
|
||||||
nr = 0,
|
nr = 0,
|
||||||
pattern = '',
|
pattern = '',
|
||||||
@ -3703,7 +3711,7 @@ describe('LSP', function()
|
|||||||
col = 7,
|
col = 7,
|
||||||
end_col = 0,
|
end_col = 0,
|
||||||
end_lnum = 0,
|
end_lnum = 0,
|
||||||
lnum = 9,
|
lnum = 3,
|
||||||
module = '',
|
module = '',
|
||||||
nr = 0,
|
nr = 0,
|
||||||
pattern = '',
|
pattern = '',
|
||||||
@ -3763,7 +3771,15 @@ describe('LSP', function()
|
|||||||
})
|
})
|
||||||
local client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
|
local client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
|
||||||
local handler = require 'vim.lsp.handlers'['typeHierarchy/subtypes']
|
local handler = require 'vim.lsp.handlers'['typeHierarchy/subtypes']
|
||||||
handler(nil, jdtls_response, { client_id = client_id, bufnr = 1 })
|
local bufnr = vim.api.nvim_get_current_buf()
|
||||||
|
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {
|
||||||
|
'package mylist;',
|
||||||
|
'',
|
||||||
|
'public class MyList {',
|
||||||
|
' static class Inner extends MyList{}',
|
||||||
|
'~}',
|
||||||
|
})
|
||||||
|
handler(nil, jdtls_response, { client_id = client_id, bufnr = bufnr })
|
||||||
return vim.fn.getqflist()
|
return vim.fn.getqflist()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@ -3840,21 +3856,21 @@ describe('LSP', function()
|
|||||||
range = {
|
range = {
|
||||||
['end'] = {
|
['end'] = {
|
||||||
character = 8,
|
character = 8,
|
||||||
line = 9,
|
line = 3,
|
||||||
},
|
},
|
||||||
start = {
|
start = {
|
||||||
character = 6,
|
character = 6,
|
||||||
line = 9,
|
line = 3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
selectionRange = {
|
selectionRange = {
|
||||||
['end'] = {
|
['end'] = {
|
||||||
character = 8,
|
character = 8,
|
||||||
line = 9,
|
line = 3,
|
||||||
},
|
},
|
||||||
start = {
|
start = {
|
||||||
character = 6,
|
character = 6,
|
||||||
line = 9,
|
line = 3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
uri = 'file:///home/jiangyinzuo/hello.cpp',
|
uri = 'file:///home/jiangyinzuo/hello.cpp',
|
||||||
@ -3884,21 +3900,21 @@ describe('LSP', function()
|
|||||||
range = {
|
range = {
|
||||||
['end'] = {
|
['end'] = {
|
||||||
character = 8,
|
character = 8,
|
||||||
line = 8,
|
line = 2,
|
||||||
},
|
},
|
||||||
start = {
|
start = {
|
||||||
character = 6,
|
character = 6,
|
||||||
line = 8,
|
line = 2,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
selectionRange = {
|
selectionRange = {
|
||||||
['end'] = {
|
['end'] = {
|
||||||
character = 8,
|
character = 8,
|
||||||
line = 8,
|
line = 2,
|
||||||
},
|
},
|
||||||
start = {
|
start = {
|
||||||
character = 6,
|
character = 6,
|
||||||
line = 8,
|
line = 2,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
uri = 'file:///home/jiangyinzuo/hello.cpp',
|
uri = 'file:///home/jiangyinzuo/hello.cpp',
|
||||||
@ -3912,7 +3928,16 @@ describe('LSP', function()
|
|||||||
})
|
})
|
||||||
local client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
|
local client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
|
||||||
local handler = require 'vim.lsp.handlers'['typeHierarchy/supertypes']
|
local handler = require 'vim.lsp.handlers'['typeHierarchy/supertypes']
|
||||||
handler(nil, clangd_response, { client_id = client_id, bufnr = 1 })
|
local bufnr = vim.api.nvim_get_current_buf()
|
||||||
|
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {
|
||||||
|
'class B : public A{};',
|
||||||
|
'class C : public B{};',
|
||||||
|
'class D1 : public C{};',
|
||||||
|
'class D2 : public C{};',
|
||||||
|
'class E : public D1, D2 {};',
|
||||||
|
})
|
||||||
|
|
||||||
|
handler(nil, clangd_response, { client_id = client_id, bufnr = bufnr })
|
||||||
return vim.fn.getqflist()
|
return vim.fn.getqflist()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@ -3922,7 +3947,7 @@ describe('LSP', function()
|
|||||||
col = 7,
|
col = 7,
|
||||||
end_col = 0,
|
end_col = 0,
|
||||||
end_lnum = 0,
|
end_lnum = 0,
|
||||||
lnum = 10,
|
lnum = 4,
|
||||||
module = '',
|
module = '',
|
||||||
nr = 0,
|
nr = 0,
|
||||||
pattern = '',
|
pattern = '',
|
||||||
@ -3936,7 +3961,7 @@ describe('LSP', function()
|
|||||||
col = 7,
|
col = 7,
|
||||||
end_col = 0,
|
end_col = 0,
|
||||||
end_lnum = 0,
|
end_lnum = 0,
|
||||||
lnum = 9,
|
lnum = 3,
|
||||||
module = '',
|
module = '',
|
||||||
nr = 0,
|
nr = 0,
|
||||||
pattern = '',
|
pattern = '',
|
||||||
@ -3996,7 +4021,15 @@ describe('LSP', function()
|
|||||||
})
|
})
|
||||||
local client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
|
local client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
|
||||||
local handler = require 'vim.lsp.handlers'['typeHierarchy/supertypes']
|
local handler = require 'vim.lsp.handlers'['typeHierarchy/supertypes']
|
||||||
handler(nil, jdtls_response, { client_id = client_id, bufnr = 1 })
|
local bufnr = vim.api.nvim_get_current_buf()
|
||||||
|
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {
|
||||||
|
'package mylist;',
|
||||||
|
'',
|
||||||
|
'public class MyList {',
|
||||||
|
' static class Inner extends MyList{}',
|
||||||
|
'~}',
|
||||||
|
})
|
||||||
|
handler(nil, jdtls_response, { client_id = client_id, bufnr = bufnr })
|
||||||
return vim.fn.getqflist()
|
return vim.fn.getqflist()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
@ -136,6 +136,50 @@ local function run_tohtml_and_assert(screen, func)
|
|||||||
screen:expect({ grid = expected.grid, attr_ids = expected.attr_ids })
|
screen:expect({ grid = expected.grid, attr_ids = expected.attr_ids })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param guifont boolean
|
||||||
|
local function test_generates_html(guifont, expect_font)
|
||||||
|
insert([[line]])
|
||||||
|
exec('set termguicolors')
|
||||||
|
local bg = fn.synIDattr(fn.hlID('Normal'), 'bg#', 'gui')
|
||||||
|
local fg = fn.synIDattr(fn.hlID('Normal'), 'fg#', 'gui')
|
||||||
|
local tmpfile = t.tmpname()
|
||||||
|
|
||||||
|
exec_lua(
|
||||||
|
[[
|
||||||
|
local guifont, outfile = ...
|
||||||
|
local html = (guifont
|
||||||
|
and require('tohtml').tohtml(0,{title="title"})
|
||||||
|
or require('tohtml').tohtml(0,{title="title",font={ "dumyfont","anotherfont" }}))
|
||||||
|
vim.fn.writefile(html, outfile)
|
||||||
|
vim.cmd.split(outfile)
|
||||||
|
]],
|
||||||
|
guifont,
|
||||||
|
tmpfile
|
||||||
|
)
|
||||||
|
|
||||||
|
local out_file = api.nvim_buf_get_name(api.nvim_get_current_buf())
|
||||||
|
eq({
|
||||||
|
'<!DOCTYPE html>',
|
||||||
|
'<html>',
|
||||||
|
'<head>',
|
||||||
|
'<meta charset="UTF-8">',
|
||||||
|
'<title>title</title>',
|
||||||
|
('<meta name="colorscheme" content="%s"></meta>'):format(api.nvim_get_var('colors_name')),
|
||||||
|
'<style>',
|
||||||
|
('* {font-family: %s,monospace}'):format(expect_font),
|
||||||
|
('body {background-color: %s; color: %s}'):format(bg, fg),
|
||||||
|
'</style>',
|
||||||
|
'</head>',
|
||||||
|
'<body style="display: flex">',
|
||||||
|
'<pre>',
|
||||||
|
'line',
|
||||||
|
'',
|
||||||
|
'</pre>',
|
||||||
|
'</body>',
|
||||||
|
'</html>',
|
||||||
|
}, fn.readfile(out_file))
|
||||||
|
end
|
||||||
|
|
||||||
describe(':TOhtml', function()
|
describe(':TOhtml', function()
|
||||||
--- @type test.functional.ui.screen
|
--- @type test.functional.ui.screen
|
||||||
local screen
|
local screen
|
||||||
@ -146,41 +190,16 @@ describe(':TOhtml', function()
|
|||||||
exec('colorscheme default')
|
exec('colorscheme default')
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('expected internal html generated', function()
|
it('generates html with given font', function()
|
||||||
insert([[line]])
|
test_generates_html(false, '"dumyfont","anotherfont"')
|
||||||
exec('set termguicolors')
|
|
||||||
local bg = fn.synIDattr(fn.hlID('Normal'), 'bg#', 'gui')
|
|
||||||
local fg = fn.synIDattr(fn.hlID('Normal'), 'fg#', 'gui')
|
|
||||||
exec_lua [[
|
|
||||||
local outfile = vim.fn.tempname() .. '.html'
|
|
||||||
local html = require('tohtml').tohtml(0,{title="title",font="dumyfont"})
|
|
||||||
vim.fn.writefile(html, outfile)
|
|
||||||
vim.cmd.split(outfile)
|
|
||||||
]]
|
|
||||||
local out_file = api.nvim_buf_get_name(api.nvim_get_current_buf())
|
|
||||||
eq({
|
|
||||||
'<!DOCTYPE html>',
|
|
||||||
'<html>',
|
|
||||||
'<head>',
|
|
||||||
'<meta charset="UTF-8">',
|
|
||||||
'<title>title</title>',
|
|
||||||
('<meta name="colorscheme" content="%s"></meta>'):format(api.nvim_get_var('colors_name')),
|
|
||||||
'<style>',
|
|
||||||
'* {font-family: dumyfont,monospace}',
|
|
||||||
('body {background-color: %s; color: %s}'):format(bg, fg),
|
|
||||||
'</style>',
|
|
||||||
'</head>',
|
|
||||||
'<body style="display: flex">',
|
|
||||||
'<pre>',
|
|
||||||
'line',
|
|
||||||
'',
|
|
||||||
'</pre>',
|
|
||||||
'</body>',
|
|
||||||
'</html>',
|
|
||||||
}, fn.readfile(out_file))
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('expected internal html generated from range', function()
|
it("generates html, respects 'guifont'", function()
|
||||||
|
exec_lua [[vim.o.guifont='Font,Escape\\,comma, Ignore space after comma']]
|
||||||
|
test_generates_html(true, '"Font","Escape,comma","Ignore space after comma"')
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('generates html from range', function()
|
||||||
insert([[
|
insert([[
|
||||||
line1
|
line1
|
||||||
line2
|
line2
|
||||||
@ -218,7 +237,7 @@ describe(':TOhtml', function()
|
|||||||
}, fn.readfile(out_file))
|
}, fn.readfile(out_file))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('highlight attributes generated', function()
|
it('generates highlight attributes', function()
|
||||||
--Make sure to uncomment the attribute in `html_syntax_match()`
|
--Make sure to uncomment the attribute in `html_syntax_match()`
|
||||||
exec('hi LINE guisp=#00ff00 gui=' .. table.concat({
|
exec('hi LINE guisp=#00ff00 gui=' .. table.concat({
|
||||||
'bold',
|
'bold',
|
||||||
|
@ -342,7 +342,7 @@ describe(':terminal buffer', function()
|
|||||||
command('wincmd p')
|
command('wincmd p')
|
||||||
|
|
||||||
-- cwd will be inserted in a file URI, which cannot contain backs
|
-- cwd will be inserted in a file URI, which cannot contain backs
|
||||||
local cwd = fn.getcwd():gsub('\\', '/')
|
local cwd = t.fix_slashes(fn.getcwd())
|
||||||
local parent = cwd:match('^(.+/)')
|
local parent = cwd:match('^(.+/)')
|
||||||
local expected = '\027]7;file://host' .. parent
|
local expected = '\027]7;file://host' .. parent
|
||||||
api.nvim_chan_send(term, string.format('%s\027\\', expected))
|
api.nvim_chan_send(term, string.format('%s\027\\', expected))
|
||||||
|
@ -14,8 +14,7 @@ local is_os = t.is_os
|
|||||||
local ok = t.ok
|
local ok = t.ok
|
||||||
local sleep = uv.sleep
|
local sleep = uv.sleep
|
||||||
|
|
||||||
--- This module uses functions from the context of the test session, i.e. in the context of the
|
--- Functions executing in the current nvim session/process being tested.
|
||||||
--- nvim being tests.
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
local runtime_set = 'set runtimepath^=./build/lib/nvim/'
|
local runtime_set = 'set runtimepath^=./build/lib/nvim/'
|
||||||
@ -903,26 +902,6 @@ function M.missing_provider(provider)
|
|||||||
assert(false, 'Unknown provider: ' .. provider)
|
assert(false, 'Unknown provider: ' .. provider)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param obj string|table
|
|
||||||
--- @return any
|
|
||||||
function M.alter_slashes(obj)
|
|
||||||
if not is_os('win') then
|
|
||||||
return obj
|
|
||||||
end
|
|
||||||
if type(obj) == 'string' then
|
|
||||||
local ret = obj:gsub('/', '\\')
|
|
||||||
return ret
|
|
||||||
elseif type(obj) == 'table' then
|
|
||||||
--- @cast obj table<any,any>
|
|
||||||
local ret = {} --- @type table<any,any>
|
|
||||||
for k, v in pairs(obj) do
|
|
||||||
ret[k] = M.alter_slashes(v)
|
|
||||||
end
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
assert(false, 'expected string or table of strings, got ' .. type(obj))
|
|
||||||
end
|
|
||||||
|
|
||||||
local load_factor = 1
|
local load_factor = 1
|
||||||
if t.is_ci() then
|
if t.is_ci() then
|
||||||
-- Compute load factor only once (but outside of any tests).
|
-- Compute load factor only once (but outside of any tests).
|
||||||
|
@ -1344,6 +1344,53 @@ describe('float window', function()
|
|||||||
|
|
|
|
||||||
]])
|
]])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- floating windows inherit NormalFloat from global-ns.
|
||||||
|
--
|
||||||
|
command('fclose')
|
||||||
|
command('hi NormalFloat guibg=LightRed')
|
||||||
|
api.nvim_open_win(0, false, { relative = 'win', row = 3, col = 3, width = 12, height = 3, style = 'minimal' })
|
||||||
|
api.nvim_set_hl_ns(api.nvim_create_namespace('test1'))
|
||||||
|
if multigrid then
|
||||||
|
screen:expect({
|
||||||
|
grid = [[
|
||||||
|
## grid 1
|
||||||
|
[2:----------------------------------------]|*6
|
||||||
|
[3:----------------------------------------]|
|
||||||
|
## grid 2
|
||||||
|
{14: 1 }^x |
|
||||||
|
{14: 2 }y |
|
||||||
|
{14: 3 } |
|
||||||
|
{0:~ }|*3
|
||||||
|
## grid 3
|
||||||
|
|
|
||||||
|
## grid 5
|
||||||
|
{22:x }|
|
||||||
|
{22:y }|
|
||||||
|
{22: }|
|
||||||
|
]], float_pos={
|
||||||
|
[5] = {1002, "NW", 2, 3, 3, true, 50};
|
||||||
|
}, win_viewport={
|
||||||
|
[2] = {win = 1000, topline = 0, botline = 4, curline = 0, curcol = 0, linecount = 3, sum_scroll_delta = 0};
|
||||||
|
[5] = {win = 1002, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3, sum_scroll_delta = 0};
|
||||||
|
}, win_viewport_margins={
|
||||||
|
[2] = { bottom = 0, left = 0, right = 0, top = 0, win = 1000 },
|
||||||
|
[5] = { bottom = 0, left = 0, right = 0, top = 0, win = 1002 }
|
||||||
|
}})
|
||||||
|
else
|
||||||
|
screen:expect({
|
||||||
|
grid = [[
|
||||||
|
{14: 1 }^x |
|
||||||
|
{14: 2 }y |
|
||||||
|
{14: 3 } |
|
||||||
|
{0:~ }{22:x }{0: }|
|
||||||
|
{0:~ }{22:y }{0: }|
|
||||||
|
{0:~ }{22: }{0: }|
|
||||||
|
|
|
||||||
|
]]
|
||||||
|
})
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("can use 'minimal' style", function()
|
it("can use 'minimal' style", function()
|
||||||
@ -8434,6 +8481,107 @@ describe('float window', function()
|
|||||||
|
|
|
|
||||||
]]}
|
]]}
|
||||||
end
|
end
|
||||||
|
command('fclose')
|
||||||
|
exec_lua([[
|
||||||
|
local win1, win3 = ...
|
||||||
|
vim.api.nvim_win_set_config(win1, { zindex = 400, title = 'win_400', title_pos = 'center', border = 'double' })
|
||||||
|
vim.api.nvim_win_set_config(win3, { zindex = 300, title = 'win_300', title_pos = 'center', border = 'single' })
|
||||||
|
]], win1, win3)
|
||||||
|
if multigrid then
|
||||||
|
screen:expect({
|
||||||
|
grid = [[
|
||||||
|
## grid 1
|
||||||
|
[2:----------------------------------------]|*6
|
||||||
|
[3:----------------------------------------]|
|
||||||
|
## grid 2
|
||||||
|
^ |
|
||||||
|
{0:~ }|*5
|
||||||
|
## grid 3
|
||||||
|
|
|
||||||
|
## grid 4
|
||||||
|
{5:╔══════}{11:win_400}{5:═══════╗}|
|
||||||
|
{5:║}{7: }{5:║}|
|
||||||
|
{5:║}{7:~ }{5:║}|*2
|
||||||
|
{5:╚════════════════════╝}|
|
||||||
|
## grid 6
|
||||||
|
{5:┌──────}{11:win_300}{5:───────┐}|
|
||||||
|
{5:│}{8: }{5:│}|
|
||||||
|
{5:│}{8:~ }{5:│}|*2
|
||||||
|
{5:└────────────────────┘}|
|
||||||
|
]], float_pos={
|
||||||
|
[4] = {1001, "NW", 1, 1, 5, true, 400};
|
||||||
|
[6] = {1003, "NW", 1, 3, 7, true, 300};
|
||||||
|
}, win_viewport={
|
||||||
|
[2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
|
||||||
|
[4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
|
||||||
|
[6] = {win = 1003, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
|
||||||
|
}, win_viewport_margins={
|
||||||
|
[2] = { bottom = 0, left = 0, right = 0, top = 0, win = 1000 },
|
||||||
|
[4] = { bottom = 1, left = 1, right = 1, top = 1, win = 1001 },
|
||||||
|
[6] = { bottom = 1, left = 1, right = 1, top = 1, win = 1003 }
|
||||||
|
}})
|
||||||
|
else
|
||||||
|
screen:expect({
|
||||||
|
grid = [[
|
||||||
|
^ |
|
||||||
|
{0:~ }{5:╔══════}{11:win_400}{5:═══════╗}{0: }|
|
||||||
|
{0:~ }{5:║}{7: }{5:║─┐}{0: }|
|
||||||
|
{0:~ }{5:║}{7:~ }{5:║}{8: }{5:│}{0: }|*2
|
||||||
|
{0:~ }{5:╚════════════════════╝}{8: }{5:│}{0: }|
|
||||||
|
{5:└────────────────────┘} |
|
||||||
|
]]
|
||||||
|
})
|
||||||
|
end
|
||||||
|
exec_lua([[
|
||||||
|
local win1, win3 = ...
|
||||||
|
vim.api.nvim_win_set_config(win1, { zindex = 100, title='win_100' })
|
||||||
|
vim.api.nvim_win_set_config(win3, { zindex = 150, title='win_150' })
|
||||||
|
]], win1, win3)
|
||||||
|
if multigrid then
|
||||||
|
screen:expect({
|
||||||
|
grid = [[
|
||||||
|
## grid 1
|
||||||
|
[2:----------------------------------------]|*6
|
||||||
|
[3:----------------------------------------]|
|
||||||
|
## grid 2
|
||||||
|
^ |
|
||||||
|
{0:~ }|*5
|
||||||
|
## grid 3
|
||||||
|
|
|
||||||
|
## grid 4
|
||||||
|
{5:╔}{11:win_100}{5:═════════════╗}|
|
||||||
|
{5:║}{7: }{5:║}|
|
||||||
|
{5:║}{7:~ }{5:║}|*2
|
||||||
|
{5:╚════════════════════╝}|
|
||||||
|
## grid 6
|
||||||
|
{5:┌}{11:win_150}{5:─────────────┐}|
|
||||||
|
{5:│}{8: }{5:│}|
|
||||||
|
{5:│}{8:~ }{5:│}|*2
|
||||||
|
{5:└────────────────────┘}|
|
||||||
|
]], float_pos={
|
||||||
|
[4] = {1001, "NW", 1, 1, 5, true, 100};
|
||||||
|
[6] = {1003, "NW", 1, 3, 7, true, 150};
|
||||||
|
}, win_viewport={
|
||||||
|
[2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
|
||||||
|
[4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
|
||||||
|
[6] = {win = 1003, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
|
||||||
|
}, win_viewport_margins={
|
||||||
|
[2] = { bottom = 0, left = 0, right = 0, top = 0, win = 1000 },
|
||||||
|
[4] = { bottom = 1, left = 1, right = 1, top = 1, win = 1001 },
|
||||||
|
[6] = { bottom = 1, left = 1, right = 1, top = 1, win = 1003 }
|
||||||
|
}})
|
||||||
|
else
|
||||||
|
screen:expect({
|
||||||
|
grid = [[
|
||||||
|
^ |
|
||||||
|
{0:~ }{5:╔}{11:w}{5:┌}{11:win_150}{5:─────────────┐}{0: }|
|
||||||
|
{0:~ }{5:║}{7: }{5:│}{8: }{5:│}{0: }|
|
||||||
|
{0:~ }{5:║}{7:~}{5:│}{8:~ }{5:│}{0: }|*2
|
||||||
|
{0:~ }{5:╚═└────────────────────┘}{0: }|
|
||||||
|
|
|
||||||
|
]]
|
||||||
|
})
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('can use winbar', function()
|
it('can use winbar', function()
|
||||||
|
@ -22,7 +22,7 @@ describe('title', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
it('has correct default title with unnamed file', function()
|
it('has correct default title with unnamed file', function()
|
||||||
local expected = '[No Name] - NVIM'
|
local expected = '[No Name] - Nvim'
|
||||||
command('set title')
|
command('set title')
|
||||||
screen:expect(function()
|
screen:expect(function()
|
||||||
eq(expected, screen.title)
|
eq(expected, screen.title)
|
||||||
@ -30,7 +30,7 @@ describe('title', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
it('has correct default title with named file', function()
|
it('has correct default title with named file', function()
|
||||||
local expected = (is_os('win') and 'myfile (C:\\mydir) - NVIM' or 'myfile (/mydir) - NVIM')
|
local expected = (is_os('win') and 'myfile (C:\\mydir) - Nvim' or 'myfile (/mydir) - Nvim')
|
||||||
command('set title')
|
command('set title')
|
||||||
command(is_os('win') and 'file C:\\mydir\\myfile' or 'file /mydir/myfile')
|
command(is_os('win') and 'file C:\\mydir\\myfile' or 'file /mydir/myfile')
|
||||||
screen:expect(function()
|
screen:expect(function()
|
||||||
@ -41,7 +41,7 @@ describe('title', function()
|
|||||||
describe('is not changed by', function()
|
describe('is not changed by', function()
|
||||||
local file1 = is_os('win') and 'C:\\mydir\\myfile1' or '/mydir/myfile1'
|
local file1 = is_os('win') and 'C:\\mydir\\myfile1' or '/mydir/myfile1'
|
||||||
local file2 = is_os('win') and 'C:\\mydir\\myfile2' or '/mydir/myfile2'
|
local file2 = is_os('win') and 'C:\\mydir\\myfile2' or '/mydir/myfile2'
|
||||||
local expected = (is_os('win') and 'myfile1 (C:\\mydir) - NVIM' or 'myfile1 (/mydir) - NVIM')
|
local expected = (is_os('win') and 'myfile1 (C:\\mydir) - Nvim' or 'myfile1 (/mydir) - Nvim')
|
||||||
local buf2
|
local buf2
|
||||||
|
|
||||||
before_each(function()
|
before_each(function()
|
||||||
|
@ -7,11 +7,10 @@ local fnamemodify = n.fn.fnamemodify
|
|||||||
local getcwd = n.fn.getcwd
|
local getcwd = n.fn.getcwd
|
||||||
local command = n.command
|
local command = n.command
|
||||||
local write_file = t.write_file
|
local write_file = t.write_file
|
||||||
local alter_slashes = n.alter_slashes
|
|
||||||
local is_os = t.is_os
|
local is_os = t.is_os
|
||||||
|
|
||||||
local function eq_slashconvert(expected, got)
|
local function eq_slashconvert(expected, got)
|
||||||
eq(alter_slashes(expected), alter_slashes(got))
|
eq(t.fix_slashes(expected), t.fix_slashes(got))
|
||||||
end
|
end
|
||||||
|
|
||||||
describe('fnamemodify()', function()
|
describe('fnamemodify()', function()
|
||||||
|
@ -710,7 +710,7 @@ func s:GetFilenameChecks() abort
|
|||||||
\ 'svg': ['file.svg'],
|
\ 'svg': ['file.svg'],
|
||||||
\ 'svn': ['svn-commitfile.tmp', 'svn-commit-file.tmp', 'svn-commit.tmp'],
|
\ 'svn': ['svn-commitfile.tmp', 'svn-commit-file.tmp', 'svn-commit.tmp'],
|
||||||
\ 'swayconfig': ['/home/user/.sway/config', '/home/user/.config/sway/config', '/etc/sway/config', '/etc/xdg/sway/config'],
|
\ 'swayconfig': ['/home/user/.sway/config', '/home/user/.config/sway/config', '/etc/sway/config', '/etc/xdg/sway/config'],
|
||||||
\ 'swift': ['file.swift'],
|
\ 'swift': ['file.swift', 'file.swiftinterface'],
|
||||||
\ 'swiftgyb': ['file.swift.gyb'],
|
\ 'swiftgyb': ['file.swift.gyb'],
|
||||||
\ 'swig': ['file.swg', 'file.swig'],
|
\ 'swig': ['file.swg', 'file.swig'],
|
||||||
\ 'sysctl': ['/etc/sysctl.conf', '/etc/sysctl.d/file.conf', 'any/etc/sysctl.conf', 'any/etc/sysctl.d/file.conf'],
|
\ 'sysctl': ['/etc/sysctl.conf', '/etc/sysctl.d/file.conf', 'any/etc/sysctl.conf', 'any/etc/sysctl.d/file.conf'],
|
||||||
|
@ -16,7 +16,7 @@ local function shell_quote(str)
|
|||||||
return str
|
return str
|
||||||
end
|
end
|
||||||
|
|
||||||
--- This module uses functions from the context of the test runner.
|
--- Functions executing in the context of the test runner (not the current nvim test session).
|
||||||
--- @class test.testutil
|
--- @class test.testutil
|
||||||
local M = {
|
local M = {
|
||||||
paths = Paths,
|
paths = Paths,
|
||||||
@ -42,6 +42,29 @@ function M.isdir(path)
|
|||||||
return stat.type == 'directory'
|
return stat.type == 'directory'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- (Only on Windows) Replaces yucky "\\" slashes with delicious "/" slashes in a string, or all
|
||||||
|
--- string values in a table (recursively).
|
||||||
|
---
|
||||||
|
--- @param obj string|table
|
||||||
|
--- @return any
|
||||||
|
function M.fix_slashes(obj)
|
||||||
|
if not M.is_os('win') then
|
||||||
|
return obj
|
||||||
|
end
|
||||||
|
if type(obj) == 'string' then
|
||||||
|
local ret = obj:gsub('\\', '/')
|
||||||
|
return ret
|
||||||
|
elseif type(obj) == 'table' then
|
||||||
|
--- @cast obj table<any,any>
|
||||||
|
local ret = {} --- @type table<any,any>
|
||||||
|
for k, v in pairs(obj) do
|
||||||
|
ret[k] = M.fix_slashes(v)
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
assert(false, 'expected string or table of strings, got ' .. type(obj))
|
||||||
|
end
|
||||||
|
|
||||||
--- @param ... string|string[]
|
--- @param ... string|string[]
|
||||||
--- @return string
|
--- @return string
|
||||||
function M.argss_to_cmd(...)
|
function M.argss_to_cmd(...)
|
||||||
|
975
test/unit/termkey_spec.lua
Normal file
975
test/unit/termkey_spec.lua
Normal file
@ -0,0 +1,975 @@
|
|||||||
|
local t = require('test.unit.testutil')
|
||||||
|
local itp = t.gen_itp(it)
|
||||||
|
local bit = require('bit')
|
||||||
|
|
||||||
|
--- @alias TermKeyKey {utf8: string, type: integer, modifiers: integer, code: {codepoint: integer, sym: any, number: integer}}
|
||||||
|
|
||||||
|
--- @class termkey
|
||||||
|
--- @field TERMKEY_CANON_SPACESYMBOL integer
|
||||||
|
--- @field TERMKEY_FLAG_SPACESYMBOL integer
|
||||||
|
--- @field TERMKEY_FLAG_UTF8 integer
|
||||||
|
--- @field TERMKEY_FORMAT_ALTISMETA integer
|
||||||
|
--- @field TERMKEY_FORMAT_CARETCTRL integer
|
||||||
|
--- @field TERMKEY_FORMAT_LONGMOD integer
|
||||||
|
--- @field TERMKEY_FORMAT_LOWERMOD integer
|
||||||
|
--- @field TERMKEY_FORMAT_LOWERSPACE integer
|
||||||
|
--- @field TERMKEY_FORMAT_MOUSE_POS integer
|
||||||
|
--- @field TERMKEY_FORMAT_SPACEMOD integer
|
||||||
|
--- @field TERMKEY_FORMAT_WRAPBRACKET integer
|
||||||
|
--- @field TERMKEY_KEYMOD_ALT integer
|
||||||
|
--- @field TERMKEY_KEYMOD_CTRL integer
|
||||||
|
--- @field TERMKEY_MOUSE_DRAG integer
|
||||||
|
--- @field TERMKEY_MOUSE_PRESS integer
|
||||||
|
--- @field TERMKEY_MOUSE_RELEASE integer
|
||||||
|
--- @field TERMKEY_RES_AGAIN integer
|
||||||
|
--- @field TERMKEY_RES_KEY integer
|
||||||
|
--- @field TERMKEY_RES_NONE integer
|
||||||
|
--- @field TERMKEY_SYM_DOWN integer
|
||||||
|
--- @field TERMKEY_SYM_PAGEUP integer
|
||||||
|
--- @field TERMKEY_SYM_SPACE integer
|
||||||
|
--- @field TERMKEY_SYM_UNKNOWN integer
|
||||||
|
--- @field TERMKEY_SYM_UP integer
|
||||||
|
--- @field TERMKEY_TYPE_DCS integer
|
||||||
|
--- @field TERMKEY_TYPE_FUNCTION integer
|
||||||
|
--- @field TERMKEY_TYPE_KEYSYM integer
|
||||||
|
--- @field TERMKEY_TYPE_MODEREPORT integer
|
||||||
|
--- @field TERMKEY_TYPE_MOUSE integer
|
||||||
|
--- @field TERMKEY_TYPE_OSC integer
|
||||||
|
--- @field TERMKEY_TYPE_POSITION integer
|
||||||
|
--- @field TERMKEY_TYPE_UNICODE integer
|
||||||
|
--- @field TERMKEY_TYPE_UNKNOWN_CSI integer
|
||||||
|
--- @field termkey_canonicalise fun(any, any):any
|
||||||
|
--- @field termkey_destroy fun(any)
|
||||||
|
--- @field termkey_get_buffer_remaining fun(any):integer
|
||||||
|
--- @field termkey_get_buffer_size fun(any):integer
|
||||||
|
--- @field termkey_get_canonflags fun(any):any
|
||||||
|
--- @field termkey_get_keyname fun(any, any):any
|
||||||
|
--- @field termkey_getkey fun(any, any):any
|
||||||
|
--- @field termkey_getkey_force fun(any, any):any
|
||||||
|
--- @field termkey_interpret_csi fun(any, any, any, any, any):any
|
||||||
|
--- @field termkey_interpret_modereport fun(any, any, any, any, any):any
|
||||||
|
--- @field termkey_interpret_mouse fun(any, any, TermKeyKey, integer, integer, integer):any
|
||||||
|
--- @field termkey_interpret_position fun(any, any, any, any):any
|
||||||
|
--- @field termkey_interpret_string fun(any, TermKeyKey, any):any
|
||||||
|
--- @field termkey_lookup_keyname fun(any, any, any):any
|
||||||
|
--- @field termkey_new_abstract fun(string, integer):any
|
||||||
|
--- @field termkey_push_bytes fun(any, string, integer):integer
|
||||||
|
--- @field termkey_set_buffer_size fun(any, integer):integer
|
||||||
|
--- @field termkey_set_canonflags fun(any, any):any
|
||||||
|
--- @field termkey_set_flags fun(any, integer)
|
||||||
|
--- @field termkey_start fun(any):integer
|
||||||
|
--- @field termkey_stop fun(any):integer
|
||||||
|
--- @field termkey_strfkey fun(any, string, integer, any, any):integer
|
||||||
|
local termkey = t.cimport(
|
||||||
|
'./src/nvim/tui/termkey/termkey.h',
|
||||||
|
'./src/nvim/tui/termkey/termkey-internal.h',
|
||||||
|
'./src/nvim/tui/termkey/termkey_defs.h',
|
||||||
|
'./src/nvim/tui/termkey/driver-csi.h'
|
||||||
|
)
|
||||||
|
|
||||||
|
describe('termkey', function()
|
||||||
|
itp('01base', function()
|
||||||
|
local tk = termkey.termkey_new_abstract('vt100', 0)
|
||||||
|
t.neq(tk, nil)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_get_buffer_size(tk), 256)
|
||||||
|
t.eq(tk.is_started, 1) -- tk->is_started true after construction
|
||||||
|
|
||||||
|
termkey.termkey_stop(tk)
|
||||||
|
t.neq(tk.is_started, 1) -- tk->is_started false after termkey_stop()
|
||||||
|
|
||||||
|
termkey.termkey_start(tk)
|
||||||
|
t.eq(tk.is_started, 1) -- tk->is_started true after termkey_start()
|
||||||
|
|
||||||
|
termkey.termkey_destroy(tk)
|
||||||
|
end)
|
||||||
|
|
||||||
|
itp('02getkey', function()
|
||||||
|
local tk = termkey.termkey_new_abstract('vt100', 0)
|
||||||
|
local key = t.ffi.new('TermKeyKey') ---@type TermKeyKey
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_get_buffer_remaining(tk), 256) -- buffer free initially 256
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_NONE) -- getkey yields RES_NONE when empty
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_push_bytes(tk, 'h', 1), 1) -- push_bytes returns 1
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_get_buffer_remaining(tk), 255) -- buffer free 255 after push_bytes
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY after h
|
||||||
|
|
||||||
|
t.eq(key.type, termkey.TERMKEY_TYPE_UNICODE) -- key.type after h
|
||||||
|
t.eq(key.code.codepoint, string.byte('h')) -- key.code.codepoint after h
|
||||||
|
t.eq(key.modifiers, 0) -- key.modifiers after h
|
||||||
|
t.eq(t.ffi.string(key.utf8), 'h') -- key.utf8 after h
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_get_buffer_remaining(tk), 256) -- buffer free 256 after getkey
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_NONE) -- getkey yields RES_NONE a second time
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\x01', 1)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY after C-a
|
||||||
|
|
||||||
|
t.eq(key.type, termkey.TERMKEY_TYPE_UNICODE) -- key.type after C-a
|
||||||
|
t.eq(key.code.codepoint, string.byte('a')) -- key.code.codepoint after C-a
|
||||||
|
t.eq(key.modifiers, termkey.TERMKEY_KEYMOD_CTRL) -- key.modifiers after C-a
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\033OA', 3)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY after Up
|
||||||
|
|
||||||
|
-- is_int(key.type, TERMKEY_TYPE_KEYSYM, "key.type after Up");
|
||||||
|
-- is_int(key.code.sym, TERMKEY_SYM_UP, "key.code.sym after Up");
|
||||||
|
t.eq(key.modifiers, 0) -- key.modifiers after Up
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_push_bytes(tk, '\033O', 2), 2) -- push_bytes returns 2
|
||||||
|
|
||||||
|
-- is_int(termkey_get_buffer_remaining(tk), 254, "buffer free 254 after partial write");
|
||||||
|
|
||||||
|
-- is_int(termkey_getkey(tk, &key), TERMKEY_RES_AGAIN, "getkey yields RES_AGAIN after partial write");
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, 'C', 1)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY after Right completion
|
||||||
|
|
||||||
|
-- is_int(key.type, TERMKEY_TYPE_KEYSYM, "key.type after Right");
|
||||||
|
-- is_int(key.code.sym, TERMKEY_SYM_RIGHT, "key.code.sym after Right");
|
||||||
|
-- is_int(key.modifiers, 0, "key.modifiers after Right");
|
||||||
|
|
||||||
|
-- is_int(termkey_get_buffer_remaining(tk), 256, "buffer free 256 after completion");
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\033[27;5u', 7)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY after Ctrl-Escape
|
||||||
|
|
||||||
|
-- is_int(key.type, TERMKEY_TYPE_KEYSYM, "key.type after Ctrl-Escape");
|
||||||
|
-- is_int(key.code.sym, TERMKEY_SYM_ESCAPE, "key.code.sym after Ctrl-Escape");
|
||||||
|
-- is_int(key.modifiers, TERMKEY_KEYMOD_CTRL, "key.modifiers after Ctrl-Escape");
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\0', 1)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY after Ctrl-Space
|
||||||
|
|
||||||
|
t.eq(key.type, termkey.TERMKEY_TYPE_UNICODE) -- key.type after Ctrl-Space
|
||||||
|
-- t.eq(key.code.codepoint, string.byte(' ')) -- key.code.codepoint after Ctrl-Space
|
||||||
|
-- is_int(key.modifiers, TERMKEY_KEYMOD_CTRL, "key.modifiers after Ctrl-Space");
|
||||||
|
|
||||||
|
termkey.termkey_destroy(tk)
|
||||||
|
end)
|
||||||
|
|
||||||
|
itp('03utf8', function()
|
||||||
|
local tk = termkey.termkey_new_abstract('vt100', termkey.TERMKEY_FLAG_UTF8)
|
||||||
|
local key = t.ffi.new('TermKeyKey') ---@type TermKeyKey
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, 'a', 1)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY low ASCII
|
||||||
|
t.eq(key.type, termkey.TERMKEY_TYPE_UNICODE) -- key.type low ASCII
|
||||||
|
t.eq(key.code.codepoint, string.byte('a')) -- key.code.codepoint low ASCII
|
||||||
|
|
||||||
|
-- 2-byte UTF-8 range is U+0080 to U+07FF (0xDF 0xBF)
|
||||||
|
-- However, we'd best avoid the C1 range, so we'll start at U+00A0 (0xC2 0xA0)
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\xC2\xA0', 2)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY UTF-8 2 low
|
||||||
|
t.eq(key.type, termkey.TERMKEY_TYPE_UNICODE) -- key.type UTF-8 2 low
|
||||||
|
t.eq(key.code.codepoint, 0x00A0) -- key.code.codepoint UTF-8 2 low
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\xDF\xBF', 2)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY UTF-8 2 high
|
||||||
|
t.eq(key.type, termkey.TERMKEY_TYPE_UNICODE) -- key.type UTF-8 2 high
|
||||||
|
t.eq(key.code.codepoint, 0x07FF) -- key.code.codepoint UTF-8 2 high
|
||||||
|
|
||||||
|
-- 3-byte UTF-8 range is U+0800 (0xE0 0xA0 0x80) to U+FFFD (0xEF 0xBF 0xBD)
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\xE0\xA0\x80', 3)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY UTF-8 3 low
|
||||||
|
t.eq(key.type, termkey.TERMKEY_TYPE_UNICODE) -- key.type UTF-8 3 low
|
||||||
|
t.eq(key.code.codepoint, 0x0800) -- key.code.codepoint UTF-8 3 low
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\xEF\xBF\xBD', 3)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY UTF-8 3 high
|
||||||
|
t.eq(key.type, termkey.TERMKEY_TYPE_UNICODE) -- key.type UTF-8 3 high
|
||||||
|
t.eq(key.code.codepoint, 0xFFFD) -- key.code.codepoint UTF-8 3 high
|
||||||
|
|
||||||
|
-- 4-byte UTF-8 range is U+10000 (0xF0 0x90 0x80 0x80) to U+10FFFF (0xF4 0x8F 0xBF 0xBF)
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\xF0\x90\x80\x80', 4)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY UTF-8 4 low
|
||||||
|
t.eq(key.type, termkey.TERMKEY_TYPE_UNICODE) -- key.type UTF-8 4 low
|
||||||
|
t.eq(key.code.codepoint, 0x10000) -- key.code.codepoint UTF-8 4 low
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\xF4\x8F\xBF\xBF', 4)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY UTF-8 4 high
|
||||||
|
t.eq(key.type, termkey.TERMKEY_TYPE_UNICODE) -- key.type UTF-8 4 high
|
||||||
|
t.eq(key.code.codepoint, 0x10FFFF) -- key.code.codepoint UTF-8 4 high
|
||||||
|
|
||||||
|
-- Invalid continuations
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\xC2!', 2)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY UTF-8 2 invalid cont
|
||||||
|
t.eq(key.code.codepoint, 0xFFFD) -- key.code.codepoint UTF-8 2 invalid cont
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY UTF-8 2 invalid after
|
||||||
|
t.eq(key.code.codepoint, string.byte('!')) -- key.code.codepoint UTF-8 2 invalid after
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\xE0!', 2)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY UTF-8 3 invalid cont
|
||||||
|
t.eq(key.code.codepoint, 0xFFFD) -- key.code.codepoint UTF-8 3 invalid cont
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY UTF-8 3 invalid after
|
||||||
|
t.eq(key.code.codepoint, string.byte('!')) -- key.code.codepoint UTF-8 3 invalid after
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\xE0\xA0!', 3)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY UTF-8 3 invalid cont 2
|
||||||
|
t.eq(key.code.codepoint, 0xFFFD) -- key.code.codepoint UTF-8 3 invalid cont 2
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY UTF-8 3 invalid after
|
||||||
|
t.eq(key.code.codepoint, string.byte('!')) -- key.code.codepoint UTF-8 3 invalid after
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\xF0!', 2)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY UTF-8 4 invalid cont
|
||||||
|
t.eq(key.code.codepoint, 0xFFFD) -- key.code.codepoint UTF-8 4 invalid cont
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY UTF-8 4 invalid after
|
||||||
|
t.eq(key.code.codepoint, string.byte('!')) -- key.code.codepoint UTF-8 4 invalid after
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\xF0\x90!', 3)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY UTF-8 4 invalid cont 2
|
||||||
|
t.eq(key.code.codepoint, 0xFFFD) -- key.code.codepoint UTF-8 4 invalid cont 2
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY UTF-8 4 invalid after
|
||||||
|
t.eq(key.code.codepoint, string.byte('!')) -- key.code.codepoint UTF-8 4 invalid after
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\xF0\x90\x80!', 4)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY UTF-8 4 invalid cont 3
|
||||||
|
t.eq(key.code.codepoint, 0xFFFD) -- key.code.codepoint UTF-8 4 invalid cont 3
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY UTF-8 4 invalid after
|
||||||
|
t.eq(key.code.codepoint, string.byte('!')) -- key.code.codepoint UTF-8 4 invalid after
|
||||||
|
|
||||||
|
-- Partials
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\xC2', 1)
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_AGAIN) -- getkey yields RES_AGAIN UTF-8 2 partial
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\xA0', 1)
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY UTF-8 2 partial
|
||||||
|
t.eq(key.code.codepoint, 0x00A0) -- key.code.codepoint UTF-8 2 partial
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\xE0', 1)
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_AGAIN) -- getkey yields RES_AGAIN UTF-8 3 partial
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\xA0', 1)
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_AGAIN) -- getkey yields RES_AGAIN UTF-8 3 partial
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\x80', 1)
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY UTF-8 3 partial
|
||||||
|
t.eq(key.code.codepoint, 0x0800) -- key.code.codepoint UTF-8 3 partial
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\xF0', 1)
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_AGAIN) -- getkey yields RES_AGAIN UTF-8 4 partial
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\x90', 1)
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_AGAIN) -- getkey yields RES_AGAIN UTF-8 4 partial
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\x80', 1)
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_AGAIN) -- getkey yields RES_AGAIN UTF-8 4 partial
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\x80', 1)
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY UTF-8 4 partial
|
||||||
|
t.eq(key.code.codepoint, 0x10000) -- key.code.codepoint UTF-8 4 partial
|
||||||
|
|
||||||
|
termkey.termkey_destroy(tk)
|
||||||
|
end)
|
||||||
|
|
||||||
|
itp('04flags', function()
|
||||||
|
local tk = termkey.termkey_new_abstract('vt100', 0)
|
||||||
|
local key = t.ffi.new('TermKeyKey') ---@type TermKeyKey
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, ' ', 1)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY after space
|
||||||
|
|
||||||
|
t.eq(key.type, termkey.TERMKEY_TYPE_UNICODE) -- key.type after space
|
||||||
|
t.eq(key.code.codepoint, string.byte(' ')) -- key.code.codepoint after space
|
||||||
|
t.eq(key.modifiers, 0) -- key.modifiers after space
|
||||||
|
|
||||||
|
termkey.termkey_set_flags(tk, termkey.TERMKEY_FLAG_SPACESYMBOL)
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, ' ', 1)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY after space
|
||||||
|
|
||||||
|
t.eq(key.type, termkey.TERMKEY_TYPE_KEYSYM) -- key.type after space with FLAG_SPACESYMBOL
|
||||||
|
t.eq(key.code.sym, termkey.TERMKEY_SYM_SPACE) -- key.code.sym after space with FLAG_SPACESYMBOL
|
||||||
|
t.eq(key.modifiers, 0) -- key.modifiers after space with FLAG_SPACESYMBOL
|
||||||
|
|
||||||
|
termkey.termkey_destroy(tk)
|
||||||
|
end)
|
||||||
|
|
||||||
|
itp('06buffer', function()
|
||||||
|
local tk = termkey.termkey_new_abstract('vt100', 0)
|
||||||
|
local key = t.ffi.new('TermKeyKey') ---@type TermKeyKey
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_get_buffer_remaining(tk), 256) -- buffer free initially 256
|
||||||
|
t.eq(termkey.termkey_get_buffer_size(tk), 256) -- buffer size initially 256
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_push_bytes(tk, 'h', 1), 1) -- push_bytes returns 1
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_get_buffer_remaining(tk), 255) -- buffer free 255 after push_bytes
|
||||||
|
t.eq(termkey.termkey_get_buffer_size(tk), 256) -- buffer size 256 after push_bytes
|
||||||
|
|
||||||
|
t.eq(not not termkey.termkey_set_buffer_size(tk, 512), true) -- buffer set size OK
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_get_buffer_remaining(tk), 511) -- buffer free 511 after push_bytes
|
||||||
|
t.eq(termkey.termkey_get_buffer_size(tk), 512) -- buffer size 512 after push_bytes
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- buffered key still useable after resize
|
||||||
|
|
||||||
|
termkey.termkey_destroy(tk)
|
||||||
|
end)
|
||||||
|
|
||||||
|
local function termkey_keyname2sym(tk, keyname)
|
||||||
|
local sym = t.ffi.new('TermKeySym[1]')
|
||||||
|
local endp = termkey.termkey_lookup_keyname(tk, keyname, sym)
|
||||||
|
if endp == nil then
|
||||||
|
return termkey.TERMKEY_SYM_UNKNOWN
|
||||||
|
end
|
||||||
|
return sym
|
||||||
|
end
|
||||||
|
|
||||||
|
itp('10keyname', function()
|
||||||
|
local tk = termkey.termkey_new_abstract('vt100', 0)
|
||||||
|
|
||||||
|
local sym = termkey_keyname2sym(tk, 'SomeUnknownKey')
|
||||||
|
t.eq(sym, termkey.TERMKEY_SYM_UNKNOWN) -- keyname2sym SomeUnknownKey
|
||||||
|
|
||||||
|
sym = termkey_keyname2sym(tk, 'Space')
|
||||||
|
t.eq(sym[0], termkey.TERMKEY_SYM_SPACE) -- keyname2sym Space
|
||||||
|
|
||||||
|
local _end = termkey.termkey_lookup_keyname(tk, 'Up', sym)
|
||||||
|
t.neq(_end, nil) -- termkey_get_keyname Up returns non-NULL
|
||||||
|
t.eq(t.ffi.string(_end), '') -- termkey_get_keyname Up return points at endofstring
|
||||||
|
t.eq(sym[0], termkey.TERMKEY_SYM_UP) -- termkey_get_keyname Up yields Up symbol
|
||||||
|
|
||||||
|
_end = termkey.termkey_lookup_keyname(tk, 'DownMore', sym)
|
||||||
|
t.neq(_end, nil) -- termkey_get_keyname DownMore returns non-NULL
|
||||||
|
t.eq(t.ffi.string(_end), 'More') -- termkey_get_keyname DownMore return points at More
|
||||||
|
t.eq(sym[0], termkey.TERMKEY_SYM_DOWN) -- termkey_get_keyname DownMore yields Down symbol
|
||||||
|
|
||||||
|
_end = termkey.termkey_lookup_keyname(tk, 'SomeUnknownKey', sym)
|
||||||
|
t.eq(_end, nil) -- termkey_get_keyname SomeUnknownKey returns NULL
|
||||||
|
|
||||||
|
t.eq(t.ffi.string(termkey.termkey_get_keyname(tk, termkey.TERMKEY_SYM_SPACE)), 'Space') -- "get_keyname SPACE");
|
||||||
|
|
||||||
|
termkey.termkey_destroy(tk)
|
||||||
|
end)
|
||||||
|
|
||||||
|
itp('11strfkey', function()
|
||||||
|
local tk = termkey.termkey_new_abstract('vt100', 0)
|
||||||
|
---@type TermKeyKey
|
||||||
|
local key = t.ffi.new(
|
||||||
|
'TermKeyKey',
|
||||||
|
{ type = termkey.TERMKEY_TYPE_UNICODE, code = { codepoint = string.byte('A') } }
|
||||||
|
)
|
||||||
|
local buffer = t.ffi.new('char[16]')
|
||||||
|
|
||||||
|
local len = termkey.termkey_strfkey(tk, buffer, t.ffi.sizeof(buffer), key, 0)
|
||||||
|
t.eq(len, 1) -- length for unicode/A/0
|
||||||
|
t.eq(t.ffi.string(buffer), 'A') -- buffer for unicode/A/0
|
||||||
|
|
||||||
|
len = termkey.termkey_strfkey(
|
||||||
|
tk,
|
||||||
|
buffer,
|
||||||
|
t.ffi.sizeof(buffer),
|
||||||
|
key,
|
||||||
|
termkey.TERMKEY_FORMAT_WRAPBRACKET
|
||||||
|
)
|
||||||
|
t.eq(len, 1) -- length for unicode/A/0 wrapbracket
|
||||||
|
t.eq(t.ffi.string(buffer), 'A') -- buffer for unicode/A/0 wrapbracket
|
||||||
|
|
||||||
|
---@type TermKeyKey
|
||||||
|
key = t.ffi.new('TermKeyKey', {
|
||||||
|
type = termkey.TERMKEY_TYPE_UNICODE,
|
||||||
|
code = { codepoint = string.byte('b') },
|
||||||
|
modifiers = termkey.TERMKEY_KEYMOD_CTRL,
|
||||||
|
})
|
||||||
|
|
||||||
|
len = termkey.termkey_strfkey(tk, buffer, t.ffi.sizeof(buffer), key, 0)
|
||||||
|
t.eq(len, 3) -- length for unicode/b/CTRL
|
||||||
|
t.eq(t.ffi.string(buffer), 'C-b') -- buffer for unicode/b/CTRL
|
||||||
|
|
||||||
|
len =
|
||||||
|
termkey.termkey_strfkey(tk, buffer, t.ffi.sizeof(buffer), key, termkey.TERMKEY_FORMAT_LONGMOD)
|
||||||
|
t.eq(len, 6) -- length for unicode/b/CTRL longmod
|
||||||
|
t.eq(t.ffi.string(buffer), 'Ctrl-b') -- buffer for unicode/b/CTRL longmod
|
||||||
|
|
||||||
|
len = termkey.termkey_strfkey(
|
||||||
|
tk,
|
||||||
|
buffer,
|
||||||
|
t.ffi.sizeof(buffer),
|
||||||
|
key,
|
||||||
|
bit.bor(termkey.TERMKEY_FORMAT_LONGMOD, termkey.TERMKEY_FORMAT_SPACEMOD)
|
||||||
|
)
|
||||||
|
t.eq(len, 6) -- length for unicode/b/CTRL longmod|spacemod
|
||||||
|
t.eq(t.ffi.string(buffer), 'Ctrl b') -- buffer for unicode/b/CTRL longmod|spacemod
|
||||||
|
|
||||||
|
len = termkey.termkey_strfkey(
|
||||||
|
tk,
|
||||||
|
buffer,
|
||||||
|
t.ffi.sizeof(buffer),
|
||||||
|
key,
|
||||||
|
bit.bor(termkey.TERMKEY_FORMAT_LONGMOD, termkey.TERMKEY_FORMAT_LOWERMOD)
|
||||||
|
)
|
||||||
|
t.eq(len, 6) -- length for unicode/b/CTRL longmod|lowermod
|
||||||
|
t.eq(t.ffi.string(buffer), 'ctrl-b') -- buffer for unicode/b/CTRL longmod|lowermod
|
||||||
|
|
||||||
|
len = termkey.termkey_strfkey(
|
||||||
|
tk,
|
||||||
|
buffer,
|
||||||
|
t.ffi.sizeof(buffer),
|
||||||
|
key,
|
||||||
|
bit.bor(
|
||||||
|
termkey.TERMKEY_FORMAT_LONGMOD,
|
||||||
|
termkey.TERMKEY_FORMAT_SPACEMOD,
|
||||||
|
termkey.TERMKEY_FORMAT_LOWERMOD
|
||||||
|
)
|
||||||
|
)
|
||||||
|
t.eq(len, 6) -- length for unicode/b/CTRL longmod|spacemod|lowermode
|
||||||
|
t.eq(t.ffi.string(buffer), 'ctrl b') -- buffer for unicode/b/CTRL longmod|spacemod|lowermode
|
||||||
|
|
||||||
|
len = termkey.termkey_strfkey(
|
||||||
|
tk,
|
||||||
|
buffer,
|
||||||
|
t.ffi.sizeof(buffer),
|
||||||
|
key,
|
||||||
|
termkey.TERMKEY_FORMAT_CARETCTRL
|
||||||
|
)
|
||||||
|
t.eq(len, 2) -- length for unicode/b/CTRL caretctrl
|
||||||
|
t.eq(t.ffi.string(buffer), '^B') -- buffer for unicode/b/CTRL caretctrl
|
||||||
|
|
||||||
|
len = termkey.termkey_strfkey(
|
||||||
|
tk,
|
||||||
|
buffer,
|
||||||
|
t.ffi.sizeof(buffer),
|
||||||
|
key,
|
||||||
|
termkey.TERMKEY_FORMAT_WRAPBRACKET
|
||||||
|
)
|
||||||
|
t.eq(len, 5) -- length for unicode/b/CTRL wrapbracket
|
||||||
|
t.eq(t.ffi.string(buffer), '<C-b>') -- buffer for unicode/b/CTRL wrapbracket
|
||||||
|
|
||||||
|
---@type TermKeyKey
|
||||||
|
key = t.ffi.new('TermKeyKey', {
|
||||||
|
type = termkey.TERMKEY_TYPE_UNICODE,
|
||||||
|
code = { codepoint = string.byte('c') },
|
||||||
|
modifiers = termkey.TERMKEY_KEYMOD_ALT,
|
||||||
|
})
|
||||||
|
|
||||||
|
len = termkey.termkey_strfkey(tk, buffer, t.ffi.sizeof(buffer), key, 0)
|
||||||
|
t.eq(len, 3) -- length for unicode/c/ALT
|
||||||
|
t.eq(t.ffi.string(buffer), 'A-c') -- buffer for unicode/c/ALT
|
||||||
|
|
||||||
|
len =
|
||||||
|
termkey.termkey_strfkey(tk, buffer, t.ffi.sizeof(buffer), key, termkey.TERMKEY_FORMAT_LONGMOD)
|
||||||
|
t.eq(len, 5) -- length for unicode/c/ALT longmod
|
||||||
|
t.eq(t.ffi.string(buffer), 'Alt-c') -- buffer for unicode/c/ALT longmod
|
||||||
|
|
||||||
|
len = termkey.termkey_strfkey(
|
||||||
|
tk,
|
||||||
|
buffer,
|
||||||
|
t.ffi.sizeof(buffer),
|
||||||
|
key,
|
||||||
|
termkey.TERMKEY_FORMAT_ALTISMETA
|
||||||
|
)
|
||||||
|
t.eq(len, 3) -- length for unicode/c/ALT altismeta
|
||||||
|
t.eq(t.ffi.string(buffer), 'M-c') -- buffer for unicode/c/ALT altismeta
|
||||||
|
|
||||||
|
len = termkey.termkey_strfkey(
|
||||||
|
tk,
|
||||||
|
buffer,
|
||||||
|
t.ffi.sizeof(buffer),
|
||||||
|
key,
|
||||||
|
bit.bor(termkey.TERMKEY_FORMAT_LONGMOD, termkey.TERMKEY_FORMAT_ALTISMETA)
|
||||||
|
)
|
||||||
|
t.eq(len, 6) -- length for unicode/c/ALT longmod|altismeta
|
||||||
|
t.eq(t.ffi.string(buffer), 'Meta-c') -- buffer for unicode/c/ALT longmod|altismeta
|
||||||
|
|
||||||
|
---@type TermKeyKey
|
||||||
|
key = t.ffi.new(
|
||||||
|
'TermKeyKey',
|
||||||
|
{ type = termkey.TERMKEY_TYPE_KEYSYM, code = { sym = termkey.TERMKEY_SYM_UP } }
|
||||||
|
)
|
||||||
|
|
||||||
|
len = termkey.termkey_strfkey(tk, buffer, t.ffi.sizeof(buffer), key, 0)
|
||||||
|
t.eq(len, 2) -- length for sym/Up/0
|
||||||
|
t.eq(t.ffi.string(buffer), 'Up') -- buffer for sym/Up/0
|
||||||
|
|
||||||
|
len = termkey.termkey_strfkey(
|
||||||
|
tk,
|
||||||
|
buffer,
|
||||||
|
t.ffi.sizeof(buffer),
|
||||||
|
key,
|
||||||
|
termkey.TERMKEY_FORMAT_WRAPBRACKET
|
||||||
|
)
|
||||||
|
t.eq(len, 4) -- length for sym/Up/0 wrapbracket
|
||||||
|
t.eq(t.ffi.string(buffer), '<Up>') -- buffer for sym/Up/0 wrapbracket
|
||||||
|
|
||||||
|
---@type TermKeyKey
|
||||||
|
key = t.ffi.new(
|
||||||
|
'TermKeyKey',
|
||||||
|
{ type = termkey.TERMKEY_TYPE_KEYSYM, code = { sym = termkey.TERMKEY_SYM_PAGEUP } }
|
||||||
|
)
|
||||||
|
|
||||||
|
len = termkey.termkey_strfkey(tk, buffer, t.ffi.sizeof(buffer), key, 0)
|
||||||
|
t.eq(len, 6) -- length for sym/PageUp/0
|
||||||
|
t.eq(t.ffi.string(buffer), 'PageUp') -- buffer for sym/PageUp/0
|
||||||
|
|
||||||
|
len = termkey.termkey_strfkey(
|
||||||
|
tk,
|
||||||
|
buffer,
|
||||||
|
t.ffi.sizeof(buffer),
|
||||||
|
key,
|
||||||
|
termkey.TERMKEY_FORMAT_LOWERSPACE
|
||||||
|
)
|
||||||
|
t.eq(len, 7) -- length for sym/PageUp/0 lowerspace
|
||||||
|
t.eq(t.ffi.string(buffer), 'page up') -- buffer for sym/PageUp/0 lowerspace
|
||||||
|
|
||||||
|
-- If size of buffer is too small, strfkey should return something consistent
|
||||||
|
len = termkey.termkey_strfkey(tk, buffer, 4, key, 0)
|
||||||
|
t.eq(len, 6) -- length for sym/PageUp/0
|
||||||
|
t.eq(t.ffi.string(buffer), 'Pag') -- buffer of len 4 for sym/PageUp/0
|
||||||
|
|
||||||
|
len = termkey.termkey_strfkey(tk, buffer, 4, key, termkey.TERMKEY_FORMAT_LOWERSPACE)
|
||||||
|
t.eq(len, 7) -- length for sym/PageUp/0 lowerspace
|
||||||
|
t.eq(t.ffi.string(buffer), 'pag') -- buffer of len 4 for sym/PageUp/0 lowerspace
|
||||||
|
|
||||||
|
key = t.ffi.new('TermKeyKey', { type = termkey.TERMKEY_TYPE_FUNCTION, code = { number = 5 } }) ---@type TermKeyKey
|
||||||
|
|
||||||
|
len = termkey.termkey_strfkey(tk, buffer, t.ffi.sizeof(buffer), key, 0)
|
||||||
|
t.eq(len, 2) -- length for func/5/0
|
||||||
|
t.eq(t.ffi.string(buffer), 'F5') -- buffer for func/5/0
|
||||||
|
|
||||||
|
len = termkey.termkey_strfkey(
|
||||||
|
tk,
|
||||||
|
buffer,
|
||||||
|
t.ffi.sizeof(buffer),
|
||||||
|
key,
|
||||||
|
termkey.TERMKEY_FORMAT_WRAPBRACKET
|
||||||
|
)
|
||||||
|
t.eq(len, 4) -- length for func/5/0 wrapbracket
|
||||||
|
t.eq(t.ffi.string(buffer), '<F5>') -- buffer for func/5/0 wrapbracket
|
||||||
|
|
||||||
|
len = termkey.termkey_strfkey(
|
||||||
|
tk,
|
||||||
|
buffer,
|
||||||
|
t.ffi.sizeof(buffer),
|
||||||
|
key,
|
||||||
|
termkey.TERMKEY_FORMAT_LOWERSPACE
|
||||||
|
)
|
||||||
|
t.eq(len, 2) -- length for func/5/0 lowerspace
|
||||||
|
t.eq(t.ffi.string(buffer), 'f5') -- buffer for func/5/0 lowerspace
|
||||||
|
|
||||||
|
termkey.termkey_destroy(tk)
|
||||||
|
end)
|
||||||
|
|
||||||
|
itp('13cmpkey', function()
|
||||||
|
local function termkey_keycmp(tk, key1, key2)
|
||||||
|
termkey.termkey_canonicalise(tk, key1)
|
||||||
|
termkey.termkey_canonicalise(tk, key2)
|
||||||
|
|
||||||
|
if key1.type ~= key2.type then
|
||||||
|
return key1.type - key2.type
|
||||||
|
end
|
||||||
|
|
||||||
|
if key1.type == termkey.TERMKEY_TYPE_UNICODE then
|
||||||
|
if key1.code.codepoint ~= key2.code.codepoint then
|
||||||
|
return key1.code.codepoint - key2.code.codepoint
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return key1.modifiers - key2.modifiers
|
||||||
|
end
|
||||||
|
|
||||||
|
local tk = termkey.termkey_new_abstract('vt100', 0)
|
||||||
|
---@type TermKeyKey
|
||||||
|
local key1 = t.ffi.new('TermKeyKey', {
|
||||||
|
type = termkey.TERMKEY_TYPE_UNICODE,
|
||||||
|
code = { codepoint = string.byte('A') },
|
||||||
|
modifiers = 0,
|
||||||
|
})
|
||||||
|
---@type TermKeyKey
|
||||||
|
local key2 = t.ffi.new('TermKeyKey', {
|
||||||
|
type = termkey.TERMKEY_TYPE_UNICODE,
|
||||||
|
code = { codepoint = string.byte('A') },
|
||||||
|
modifiers = 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
t.eq(termkey_keycmp(tk, key1, key1), 0) -- cmpkey same structure
|
||||||
|
t.eq(termkey_keycmp(tk, key1, key2), 0) -- cmpkey identical structure
|
||||||
|
|
||||||
|
key2.modifiers = termkey.TERMKEY_KEYMOD_CTRL
|
||||||
|
|
||||||
|
t.eq(termkey_keycmp(tk, key1, key2) < 0, true) -- cmpkey orders CTRL after nomod
|
||||||
|
t.eq(termkey_keycmp(tk, key2, key1) > 0, true) -- cmpkey orders nomod before CTRL
|
||||||
|
|
||||||
|
key2.code.codepoint = string.byte('B')
|
||||||
|
key2.modifiers = 0
|
||||||
|
|
||||||
|
t.eq(termkey_keycmp(tk, key1, key2) < 0, true) -- cmpkey orders 'B' after 'A'
|
||||||
|
t.eq(termkey_keycmp(tk, key2, key1) > 0, true) -- cmpkey orders 'A' before 'B'
|
||||||
|
|
||||||
|
key1.modifiers = termkey.TERMKEY_KEYMOD_CTRL
|
||||||
|
|
||||||
|
t.eq(termkey_keycmp(tk, key1, key2) < 0, true) -- cmpkey orders nomod 'B' after CTRL 'A'
|
||||||
|
t.eq(termkey_keycmp(tk, key2, key1) > 0, true) -- cmpkey orders CTRL 'A' before nomod 'B'
|
||||||
|
|
||||||
|
key2.type = termkey.TERMKEY_TYPE_KEYSYM
|
||||||
|
key2.code.sym = termkey.TERMKEY_SYM_UP
|
||||||
|
|
||||||
|
t.eq(termkey_keycmp(tk, key1, key2) < 0, true) -- cmpkey orders KEYSYM after UNICODE
|
||||||
|
t.eq(termkey_keycmp(tk, key2, key1) > 0, true) -- cmpkey orders UNICODE before KEYSYM
|
||||||
|
|
||||||
|
key1.type = termkey.TERMKEY_TYPE_KEYSYM
|
||||||
|
key1.code.sym = termkey.TERMKEY_SYM_SPACE
|
||||||
|
key1.modifiers = 0
|
||||||
|
key2.type = termkey.TERMKEY_TYPE_UNICODE
|
||||||
|
key2.code.codepoint = string.byte(' ')
|
||||||
|
key2.modifiers = 0
|
||||||
|
|
||||||
|
t.eq(termkey_keycmp(tk, key1, key2), 0) -- cmpkey considers KEYSYM/SPACE and UNICODE/SP identical
|
||||||
|
|
||||||
|
termkey.termkey_set_canonflags(
|
||||||
|
tk,
|
||||||
|
bit.bor(termkey.termkey_get_canonflags(tk), termkey.TERMKEY_CANON_SPACESYMBOL)
|
||||||
|
)
|
||||||
|
t.eq(termkey_keycmp(tk, key1, key2), 0) -- "cmpkey considers KEYSYM/SPACE and UNICODE/SP identical under SPACESYMBOL");
|
||||||
|
|
||||||
|
termkey.termkey_destroy(tk)
|
||||||
|
end)
|
||||||
|
|
||||||
|
itp('30mouse', function()
|
||||||
|
local tk = termkey.termkey_new_abstract('vt100', 0)
|
||||||
|
local key = t.ffi.new('TermKeyKey', { type = -1 }) ---@type TermKeyKey
|
||||||
|
local ev = t.ffi.new('TermKeyMouseEvent[1]')
|
||||||
|
local button = t.ffi.new('int[1]')
|
||||||
|
local line = t.ffi.new('int[1]')
|
||||||
|
local col = t.ffi.new('int[1]')
|
||||||
|
local buffer = t.ffi.new('char[32]')
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\x1b[M !!', 6)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY for mouse press
|
||||||
|
|
||||||
|
t.eq(key.type, termkey.TERMKEY_TYPE_MOUSE) -- key.type for mouse press
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_interpret_mouse(tk, key, ev, button, line, col), termkey.TERMKEY_RES_KEY) -- interpret_mouse yields RES_KEY
|
||||||
|
|
||||||
|
t.eq(ev[0], termkey.TERMKEY_MOUSE_PRESS) -- mouse event for press
|
||||||
|
t.eq(button[0], 1) -- mouse button for press
|
||||||
|
t.eq(line[0], 1) -- mouse line for press
|
||||||
|
t.eq(col[0], 1) -- mouse column for press
|
||||||
|
t.eq(key.modifiers, 0) -- modifiers for press
|
||||||
|
|
||||||
|
local len = termkey.termkey_strfkey(tk, buffer, t.ffi.sizeof(buffer), key, 0)
|
||||||
|
t.eq(len, 13) -- string length for press
|
||||||
|
t.eq(t.ffi.string(buffer), 'MousePress(1)') -- string buffer for press
|
||||||
|
|
||||||
|
len = termkey.termkey_strfkey(
|
||||||
|
tk,
|
||||||
|
buffer,
|
||||||
|
t.ffi.sizeof(buffer),
|
||||||
|
key,
|
||||||
|
termkey.TERMKEY_FORMAT_MOUSE_POS
|
||||||
|
)
|
||||||
|
t.eq(len, 21) -- string length for press
|
||||||
|
t.eq(t.ffi.string(buffer), 'MousePress(1) @ (1,1)') -- string buffer for press
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\x1b[M@"!', 6)
|
||||||
|
|
||||||
|
termkey.termkey_getkey(tk, key)
|
||||||
|
t.eq(termkey.termkey_interpret_mouse(tk, key, ev, button, line, col), termkey.TERMKEY_RES_KEY) -- interpret_mouse yields RES_KEY
|
||||||
|
|
||||||
|
t.eq(ev[0], termkey.TERMKEY_MOUSE_DRAG) -- mouse event for drag
|
||||||
|
t.eq(button[0], 1) -- mouse button for drag
|
||||||
|
t.eq(line[0], 1) -- mouse line for drag
|
||||||
|
t.eq(col[0], 2) -- mouse column for drag
|
||||||
|
t.eq(key.modifiers, 0) -- modifiers for press
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\x1b[M##!', 6)
|
||||||
|
|
||||||
|
termkey.termkey_getkey(tk, key)
|
||||||
|
t.eq(termkey.termkey_interpret_mouse(tk, key, ev, button, line, col), termkey.TERMKEY_RES_KEY) -- interpret_mouse yields RES_KEY
|
||||||
|
|
||||||
|
t.eq(ev[0], termkey.TERMKEY_MOUSE_RELEASE) -- mouse event for release
|
||||||
|
t.eq(line[0], 1) -- mouse line for release
|
||||||
|
t.eq(col[0], 3) -- mouse column for release
|
||||||
|
t.eq(key.modifiers, 0) -- modifiers for press
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\x1b[M0++', 6)
|
||||||
|
|
||||||
|
termkey.termkey_getkey(tk, key)
|
||||||
|
t.eq(termkey.termkey_interpret_mouse(tk, key, ev, button, line, col), termkey.TERMKEY_RES_KEY) -- interpret_mouse yields RES_KEY
|
||||||
|
|
||||||
|
t.eq(ev[0], termkey.TERMKEY_MOUSE_PRESS) -- mouse event for Ctrl-press
|
||||||
|
t.eq(button[0], 1) -- mouse button for Ctrl-press
|
||||||
|
t.eq(line[0], 11) -- mouse line for Ctrl-press
|
||||||
|
t.eq(col[0], 11) -- mouse column for Ctrl-press
|
||||||
|
t.eq(key.modifiers, termkey.TERMKEY_KEYMOD_CTRL) -- modifiers for Ctrl-press
|
||||||
|
|
||||||
|
len = termkey.termkey_strfkey(tk, buffer, t.ffi.sizeof(buffer), key, 0)
|
||||||
|
t.eq(len, 15) -- string length for Ctrl-press
|
||||||
|
t.eq(t.ffi.string(buffer), 'C-MousePress(1)') -- string buffer for Ctrl-press
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\x1b[M`!!', 6)
|
||||||
|
|
||||||
|
termkey.termkey_getkey(tk, key)
|
||||||
|
t.eq(termkey.termkey_interpret_mouse(tk, key, ev, button, line, col), termkey.TERMKEY_RES_KEY) -- interpret_mouse yields RES_KEY
|
||||||
|
|
||||||
|
t.eq(ev[0], termkey.TERMKEY_MOUSE_PRESS) -- mouse event for wheel down
|
||||||
|
t.eq(button[0], 4) -- mouse button for wheel down
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\x1b[Mb!!', 6)
|
||||||
|
|
||||||
|
termkey.termkey_getkey(tk, key)
|
||||||
|
t.eq(termkey.termkey_interpret_mouse(tk, key, ev, button, line, col), termkey.TERMKEY_RES_KEY) -- interpret_mouse yields RES_KEY
|
||||||
|
|
||||||
|
t.eq(ev[0], termkey.TERMKEY_MOUSE_PRESS) -- mouse event for wheel left
|
||||||
|
t.eq(button[0], 6) -- mouse button for wheel left
|
||||||
|
|
||||||
|
-- rxvt protocol
|
||||||
|
termkey.termkey_push_bytes(tk, '\x1b[0;20;20M', 10)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY for mouse press rxvt protocol
|
||||||
|
|
||||||
|
t.eq(key.type, termkey.TERMKEY_TYPE_MOUSE) -- key.type for mouse press rxvt protocol
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_interpret_mouse(tk, key, ev, button, line, col), termkey.TERMKEY_RES_KEY) -- interpret_mouse yields RES_KEY
|
||||||
|
|
||||||
|
t.eq(ev[0], termkey.TERMKEY_MOUSE_PRESS) -- mouse event for press rxvt protocol
|
||||||
|
t.eq(button[0], 1) -- mouse button for press rxvt protocol
|
||||||
|
t.eq(line[0], 20) -- mouse line for press rxvt protocol
|
||||||
|
t.eq(col[0], 20) -- mouse column for press rxvt protocol
|
||||||
|
t.eq(key.modifiers, 0) -- modifiers for press rxvt protocol
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\x1b[3;20;20M', 10)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY for mouse release rxvt protocol
|
||||||
|
|
||||||
|
t.eq(key.type, termkey.TERMKEY_TYPE_MOUSE) -- key.type for mouse release rxvt protocol
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_interpret_mouse(tk, key, ev, button, line, col), termkey.TERMKEY_RES_KEY) -- interpret_mouse yields RES_KEY
|
||||||
|
|
||||||
|
t.eq(ev[0], termkey.TERMKEY_MOUSE_RELEASE) -- mouse event for release rxvt protocol
|
||||||
|
t.eq(line[0], 20) -- mouse line for release rxvt protocol
|
||||||
|
t.eq(col[0], 20) -- mouse column for release rxvt protocol
|
||||||
|
t.eq(key.modifiers, 0) -- modifiers for release rxvt protocol
|
||||||
|
|
||||||
|
-- SGR protocol
|
||||||
|
termkey.termkey_push_bytes(tk, '\x1b[<0;30;30M', 11)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY for mouse press SGR encoding
|
||||||
|
|
||||||
|
t.eq(key.type, termkey.TERMKEY_TYPE_MOUSE) -- key.type for mouse press SGR encoding
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_interpret_mouse(tk, key, ev, button, line, col), termkey.TERMKEY_RES_KEY) -- interpret_mouse yields RES_KEY
|
||||||
|
|
||||||
|
t.eq(ev[0], termkey.TERMKEY_MOUSE_PRESS) -- mouse event for press SGR
|
||||||
|
t.eq(button[0], 1) -- mouse button for press SGR
|
||||||
|
t.eq(line[0], 30) -- mouse line for press SGR
|
||||||
|
t.eq(col[0], 30) -- mouse column for press SGR
|
||||||
|
t.eq(key.modifiers, 0) -- modifiers for press SGR
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\x1b[<0;30;30m', 11)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY for mouse release SGR encoding
|
||||||
|
|
||||||
|
t.eq(key.type, termkey.TERMKEY_TYPE_MOUSE) -- key.type for mouse release SGR encoding
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_interpret_mouse(tk, key, ev, button, line, col), termkey.TERMKEY_RES_KEY) -- interpret_mouse yields RES_KEY
|
||||||
|
|
||||||
|
t.eq(ev[0], termkey.TERMKEY_MOUSE_RELEASE) -- mouse event for release SGR
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\x1b[<0;500;300M', 13)
|
||||||
|
|
||||||
|
termkey.termkey_getkey(tk, key)
|
||||||
|
termkey.termkey_interpret_mouse(tk, key, ev, button, line, col)
|
||||||
|
|
||||||
|
t.eq(line[0], 300) -- mouse line for press SGR wide
|
||||||
|
t.eq(col[0], 500) -- mouse column for press SGR wide
|
||||||
|
|
||||||
|
termkey.termkey_destroy(tk)
|
||||||
|
end)
|
||||||
|
|
||||||
|
itp('31position', function()
|
||||||
|
local tk = termkey.termkey_new_abstract('vt100', 0)
|
||||||
|
local key = t.ffi.new('TermKeyKey') ---@type TermKeyKey
|
||||||
|
local line = t.ffi.new('int[1]')
|
||||||
|
local col = t.ffi.new('int[1]')
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\x1b[?15;7R', 8)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY for position report
|
||||||
|
|
||||||
|
t.eq(key.type, termkey.TERMKEY_TYPE_POSITION) -- key.type for position report
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_interpret_position(tk, key, line, col), termkey.TERMKEY_RES_KEY) -- interpret_position yields RES_KEY
|
||||||
|
|
||||||
|
t.eq(line[0], 15) -- line for position report
|
||||||
|
t.eq(col[0], 7) -- column for position report
|
||||||
|
|
||||||
|
-- A plain CSI R is likely to be <F3> though.
|
||||||
|
-- This is tricky :/
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\x1b[R', 3)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY for <F3>
|
||||||
|
|
||||||
|
t.eq(key.type, termkey.TERMKEY_TYPE_FUNCTION) -- key.type for <F3>
|
||||||
|
t.eq(key.code.number, 3) -- key.code.number for <F3>
|
||||||
|
|
||||||
|
termkey.termkey_destroy(tk)
|
||||||
|
end)
|
||||||
|
|
||||||
|
itp('32modereport', function()
|
||||||
|
local tk = termkey.termkey_new_abstract('vt100', 0)
|
||||||
|
local key = t.ffi.new('TermKeyKey') ---@type TermKeyKey
|
||||||
|
local initial = t.ffi.new('int[1]')
|
||||||
|
local mode = t.ffi.new('int[1]')
|
||||||
|
local value = t.ffi.new('int[1]')
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\x1b[?1;2$y', 8)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY for mode report
|
||||||
|
|
||||||
|
t.eq(key.type, termkey.TERMKEY_TYPE_MODEREPORT) -- key.type for mode report
|
||||||
|
|
||||||
|
t.eq(
|
||||||
|
termkey.termkey_interpret_modereport(tk, key, initial, mode, value),
|
||||||
|
termkey.TERMKEY_RES_KEY
|
||||||
|
) -- interpret_modereoprt yields RES_KEY
|
||||||
|
|
||||||
|
t.eq(initial[0], 63) -- initial indicator from mode report
|
||||||
|
t.eq(mode[0], 1) -- mode number from mode report
|
||||||
|
t.eq(value[0], 2) -- mode value from mode report
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\x1b[4;1$y', 7)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY for mode report
|
||||||
|
|
||||||
|
t.eq(key.type, termkey.TERMKEY_TYPE_MODEREPORT) -- key.type for mode report
|
||||||
|
|
||||||
|
t.eq(
|
||||||
|
termkey.termkey_interpret_modereport(tk, key, initial, mode, value),
|
||||||
|
termkey.TERMKEY_RES_KEY
|
||||||
|
) -- interpret_modereoprt yields RES_KEY
|
||||||
|
|
||||||
|
t.eq(initial[0], 0) -- initial indicator from mode report
|
||||||
|
t.eq(mode[0], 4) -- mode number from mode report
|
||||||
|
t.eq(value[0], 1) -- mode value from mode report
|
||||||
|
|
||||||
|
termkey.termkey_destroy(tk)
|
||||||
|
end)
|
||||||
|
|
||||||
|
itp('38csi', function()
|
||||||
|
local tk = termkey.termkey_new_abstract('vt100', 0)
|
||||||
|
local key = t.ffi.new('TermKeyKey') ---@type TermKeyKey
|
||||||
|
local args = t.ffi.new('TermKeyCsiParam[16]')
|
||||||
|
local nargs = t.ffi.new('size_t[1]')
|
||||||
|
local command = t.ffi.new('unsigned[1]')
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\x1b[5;25v', 7)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY for CSI v
|
||||||
|
|
||||||
|
t.eq(key.type, termkey.TERMKEY_TYPE_UNKNOWN_CSI) -- key.type for unknown CSI
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_interpret_csi(tk, key, args, nargs, command), termkey.TERMKEY_RES_KEY) -- interpret_csi yields RES_KEY
|
||||||
|
|
||||||
|
t.eq(nargs[0], 2) -- nargs for unknown CSI
|
||||||
|
-- t.eq(args[0], 5) -- args[0] for unknown CSI
|
||||||
|
-- t.eq(args[1], 25) -- args[1] for unknown CSI
|
||||||
|
t.eq(command[0], 118) -- command for unknown CSI
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\x1b[?w', 4)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY for CSI ? w
|
||||||
|
t.eq(key.type, termkey.TERMKEY_TYPE_UNKNOWN_CSI) -- key.type for unknown CSI
|
||||||
|
t.eq(termkey.termkey_interpret_csi(tk, key, args, nargs, command), termkey.TERMKEY_RES_KEY) -- interpret_csi yields RES_KEY
|
||||||
|
t.eq(command[0], bit.bor(bit.lshift(63, 8), 119)) -- command for unknown CSI
|
||||||
|
|
||||||
|
termkey.termkey_push_bytes(tk, '\x1b[?$x', 5)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY for CSI ? $x
|
||||||
|
t.eq(key.type, termkey.TERMKEY_TYPE_UNKNOWN_CSI) -- key.type for unknown CSI
|
||||||
|
t.eq(termkey.termkey_interpret_csi(tk, key, args, nargs, command), termkey.TERMKEY_RES_KEY) -- interpret_csi yields RES_KEY
|
||||||
|
t.eq(command[0], bit.bor(bit.lshift(36, 16), bit.lshift(63, 8), 120)) -- command for unknown CSI
|
||||||
|
|
||||||
|
termkey.termkey_destroy(tk)
|
||||||
|
end)
|
||||||
|
|
||||||
|
itp('39dcs', function()
|
||||||
|
local tk = termkey.termkey_new_abstract('xterm', 0)
|
||||||
|
local key = t.ffi.new('TermKeyKey') ---@type TermKeyKey
|
||||||
|
|
||||||
|
-- 7bit DCS
|
||||||
|
termkey.termkey_push_bytes(tk, '\x1bP1$r1 q\x1b\\', 10)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY for DCS
|
||||||
|
|
||||||
|
t.eq(key.type, termkey.TERMKEY_TYPE_DCS) -- key.type for DCS
|
||||||
|
t.eq(key.modifiers, 0) -- key.modifiers for DCS
|
||||||
|
|
||||||
|
local str = t.ffi.new('const char*[1]')
|
||||||
|
t.eq(termkey.termkey_interpret_string(tk, key, str), termkey.TERMKEY_RES_KEY) -- termkey_interpret_string() gives string
|
||||||
|
t.eq(t.ffi.string(str[0]), '1$r1 q') -- termkey_interpret_string() yields correct string
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_NONE) -- getkey again yields RES_NONE
|
||||||
|
|
||||||
|
-- 8bit DCS
|
||||||
|
termkey.termkey_push_bytes(tk, '\x901$r2 q\x9c', 8)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY for DCS
|
||||||
|
|
||||||
|
t.eq(key.type, termkey.TERMKEY_TYPE_DCS) -- key.type for DCS
|
||||||
|
t.eq(key.modifiers, 0) -- key.modifiers for DCS
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_interpret_string(tk, key, str), termkey.TERMKEY_RES_KEY) -- "termkey_interpret_string() gives string");
|
||||||
|
t.eq(t.ffi.string(str[0]), '1$r2 q') -- "termkey_interpret_string() yields correct string");
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_NONE) -- "getkey again yields RES_NONE");
|
||||||
|
|
||||||
|
-- 7bit OSC
|
||||||
|
termkey.termkey_push_bytes(tk, '\x1b]15;abc\x1b\\', 10)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_KEY) -- getkey yields RES_KEY for OSC
|
||||||
|
|
||||||
|
t.eq(key.type, termkey.TERMKEY_TYPE_OSC) -- key.type for OSC
|
||||||
|
t.eq(key.modifiers, 0) -- key.modifiers for OSC
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_interpret_string(tk, key, str), termkey.TERMKEY_RES_KEY) -- "termkey_interpret_string() gives string");
|
||||||
|
t.eq(t.ffi.string(str[0]), '15;abc') -- "termkey_interpret_string() yields correct string");
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_NONE) -- getkey again yields RES_NONE
|
||||||
|
|
||||||
|
-- False alarm
|
||||||
|
termkey.termkey_push_bytes(tk, '\x1bP', 2)
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey(tk, key), termkey.TERMKEY_RES_AGAIN) -- getkey yields RES_AGAIN for false alarm
|
||||||
|
|
||||||
|
t.eq(termkey.termkey_getkey_force(tk, key), termkey.TERMKEY_RES_KEY) -- getkey_force yields RES_KEY for false alarm
|
||||||
|
|
||||||
|
t.eq(key.type, termkey.TERMKEY_TYPE_UNICODE) -- key.type for false alarm
|
||||||
|
t.eq(key.code.codepoint, string.byte('P')) -- key.code.codepoint for false alarm
|
||||||
|
t.eq(key.modifiers, termkey.TERMKEY_KEYMOD_ALT) -- key.modifiers for false alarm
|
||||||
|
|
||||||
|
termkey.termkey_destroy(tk)
|
||||||
|
end)
|
||||||
|
end)
|
Loading…
Reference in New Issue
Block a user