mirror of
https://github.com/neovim/neovim.git
synced 2024-09-17 20:58:20 -04:00
Compare commits
68 Commits
a584fe9290
...
ef5662544a
Author | SHA1 | Date | |
---|---|---|---|
|
ef5662544a | ||
|
d9b4d321d0 | ||
|
a0d8c2b86e | ||
|
549c00c791 | ||
|
23dcd7cd73 | ||
|
3f15e57b26 | ||
|
a9031cc4a6 | ||
|
5e7933693b | ||
|
f408603f4f | ||
|
78b8510933 | ||
|
057d27a9d6 | ||
|
5792546777 | ||
|
3b54adc6c6 | ||
|
325d349f9d | ||
|
5191a11d66 | ||
|
90585e47fe | ||
|
f2173b1aa2 | ||
|
67d6b6f27e | ||
|
8512f669f0 | ||
|
755512ed60 | ||
|
4c23b83456 | ||
|
5284a2a793 | ||
|
b9b408a56c | ||
|
8654a97006 | ||
|
057314345a | ||
|
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 | ||
|
b40ec083ae | ||
|
d338ec9cb2 |
18
.github/workflows/backport.yml
vendored
18
.github/workflows/backport.yml
vendored
@ -26,3 +26,21 @@ jobs:
|
||||
pull_title: "${pull_title}"
|
||||
label_pattern: "^ci:backport ([^ ]+)$"
|
||||
github_token: ${{ steps.app-token.outputs.token }}
|
||||
|
||||
- name: Create failed backport label
|
||||
if: ${{ steps.backport.outputs.was_successful == 'false' }}
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
github.rest.issues.addLabels({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
labels: ['needs:backport']
|
||||
})
|
||||
|
||||
- name: Enable automerge
|
||||
if: ${{ steps.backport.outputs.was_successful == 'true' }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: gh pr merge --rebase --auto ${{ steps.backport.outputs.created_pull_numbers }}
|
||||
|
2
.github/workflows/reviewers_add.yml
vendored
2
.github/workflows/reviewers_add.yml
vendored
@ -5,7 +5,7 @@ on:
|
||||
workflow_call:
|
||||
jobs:
|
||||
request-reviewer:
|
||||
if: github.event.pull_request.state == 'open' && github.event.pull_request.draft == false
|
||||
if: github.event.pull_request.state == 'open' && github.event.pull_request.draft == false && !endsWith(github.actor, '[bot]')
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
@ -7,8 +7,8 @@ LUAJIT_SHA256 2b5514bd6a6573cb6111b43d013e952cbaf46762d14ebe26c872ddb80b5a84e0
|
||||
LUA_URL https://www.lua.org/ftp/lua-5.1.5.tar.gz
|
||||
LUA_SHA256 2640fc56a795f29d28ef15e13c34a47e223960b0240e8cb0a82d9b0738695333
|
||||
|
||||
UNIBILIUM_URL https://github.com/neovim/unibilium/archive/d72c3598e7ac5d1ebf86ee268b8b4ed95c0fa628.tar.gz
|
||||
UNIBILIUM_SHA256 9c4747c862ab5e3076dcf8fa8f0ea7a6b50f20ec5905618b9536655596797487
|
||||
UNIBILIUM_URL https://github.com/neovim/unibilium/archive/v2.1.2.tar.gz
|
||||
UNIBILIUM_SHA256 370ecb07fbbc20d91d1b350c55f1c806b06bf86797e164081ccc977fc9b3af7a
|
||||
|
||||
LUV_URL https://github.com/luvit/luv/releases/download/1.48.0-2/luv-1.48.0-2.tar.gz
|
||||
LUV_SHA256 2c3a1ddfebb4f6550293a40ee789f7122e97647eede51511f57203de48c03b7a
|
||||
@ -38,18 +38,18 @@ LIBICONV_SHA256 8f74213b56238c85a50a5329f77e06198771e70dd9a739779f4c02f65d971313
|
||||
UTF8PROC_URL https://github.com/JuliaStrings/utf8proc/archive/3de4596fbe28956855df2ecb3c11c0bbc3535838.tar.gz
|
||||
UTF8PROC_SHA256 fb4a16bb659b58afb7f921fcc8928d0b3c1fcab135366c8a4f9ca7de1b1cfada
|
||||
|
||||
TREESITTER_C_URL https://github.com/tree-sitter/tree-sitter-c/archive/v0.21.3.tar.gz
|
||||
TREESITTER_C_SHA256 75a3780df6114cd37496761c4a7c9fd900c78bee3a2707f590d78c0ca3a24368
|
||||
TREESITTER_LUA_URL https://github.com/tree-sitter-grammars/tree-sitter-lua/archive/v0.1.0.tar.gz
|
||||
TREESITTER_LUA_SHA256 230cfcbfa74ed1f7b8149e9a1f34c2efc4c589a71fe0f5dc8560622f8020d722
|
||||
TREESITTER_C_URL https://github.com/tree-sitter/tree-sitter-c/archive/v0.23.0.tar.gz
|
||||
TREESITTER_C_SHA256 ee58c925e2e507c23d735aad46bf7fb0af31ca06d6f4f41bc008216d9232b0cb
|
||||
TREESITTER_LUA_URL https://github.com/tree-sitter-grammars/tree-sitter-lua/archive/v0.2.0.tar.gz
|
||||
TREESITTER_LUA_SHA256 6c41227cd0a59047b19d31f0031d4d901f08bfd78d6fc7f55c89e5b8374c794e
|
||||
TREESITTER_VIM_URL https://github.com/neovim/tree-sitter-vim/archive/v0.4.0.tar.gz
|
||||
TREESITTER_VIM_SHA256 9f856f8b4a10ab43348550fa2d3cb2846ae3d8e60f45887200549c051c66f9d5
|
||||
TREESITTER_VIMDOC_URL https://github.com/neovim/tree-sitter-vimdoc/archive/v3.0.0.tar.gz
|
||||
TREESITTER_VIMDOC_SHA256 a639bf92bf57bfa1cdc90ca16af27bfaf26a9779064776dd4be34c1ef1453f6c
|
||||
TREESITTER_QUERY_URL https://github.com/tree-sitter-grammars/tree-sitter-query/archive/v0.4.0.tar.gz
|
||||
TREESITTER_QUERY_SHA256 d3a423ab66dc62b2969625e280116678a8a22582b5ff087795222108db2f6a6e
|
||||
TREESITTER_MARKDOWN_URL https://github.com/MDeiml/tree-sitter-markdown/archive/v0.2.3.tar.gz
|
||||
TREESITTER_MARKDOWN_SHA256 4909d6023643f1afc3ab219585d4035b7403f3a17849782ab803c5f73c8a31d5
|
||||
TREESITTER_MARKDOWN_URL https://github.com/tree-sitter-grammars/tree-sitter-markdown/archive/v0.3.2.tar.gz
|
||||
TREESITTER_MARKDOWN_SHA256 5dac48a6d971eb545aab665d59a18180d21963afc781bbf40f9077c06cb82ae5
|
||||
TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/v0.23.0.tar.gz
|
||||
TREESITTER_SHA256 6403b361b0014999e96f61b9c84d6950d42f0c7d6e806be79382e0232e48a11b
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
" 2024 Aug 15 by Vim Project: style changes, prevent E121 (#15501)
|
||||
" 2024 Aug 22 by Vim Project: fix mf-selection highlight (#15551)
|
||||
" 2024 Aug 22 by Vim Project: adjust echo output of mx command (#15550)
|
||||
" 2024 Sep 15 by Vim Project: more strict confirmation dialog (#15680)
|
||||
" }}}
|
||||
" Former Maintainer: Charles E Campbell
|
||||
" GetLatestVimScripts: 1075 1 :AutoInstall: netrw.vim
|
||||
@ -11275,7 +11276,7 @@ fun! s:NetrwLocalRm(path) range
|
||||
let ok= s:NetrwLocalRmFile(a:path,fname,all)
|
||||
if ok =~# 'q\%[uit]' || ok == "no"
|
||||
break
|
||||
elseif ok =~# 'a\%[ll]'
|
||||
elseif ok =~# '^a\%[ll]$'
|
||||
let all= 1
|
||||
endif
|
||||
endfor
|
||||
@ -11304,7 +11305,7 @@ fun! s:NetrwLocalRm(path) range
|
||||
let ok= s:NetrwLocalRmFile(a:path,curword,all)
|
||||
if ok =~# 'q\%[uit]' || ok == "no"
|
||||
break
|
||||
elseif ok =~# 'a\%[ll]'
|
||||
elseif ok =~# '^a\%[ll]$'
|
||||
let all= 1
|
||||
endif
|
||||
let ctr= ctr + 1
|
||||
@ -11351,12 +11352,12 @@ fun! s:NetrwLocalRmFile(path,fname,all)
|
||||
" call Decho("response: ok<".ok.">",'~'.expand("<slnum>"))
|
||||
let ok= substitute(ok,'\[{y(es)},n(o),a(ll),q(uit)]\s*','','e')
|
||||
" call Decho("response: ok<".ok."> (after sub)",'~'.expand("<slnum>"))
|
||||
if ok =~# 'a\%[ll]'
|
||||
if ok =~# '^a\%[ll]$'
|
||||
let all= 1
|
||||
endif
|
||||
endif
|
||||
|
||||
if all || ok =~# 'y\%[es]' || ok == ""
|
||||
if all || ok =~# '^y\%[es]$' || ok == ""
|
||||
let ret= s:NetrwDelete(rmfile)
|
||||
" call Decho("errcode=".v:shell_error." ret=".ret,'~'.expand("<slnum>"))
|
||||
endif
|
||||
@ -11372,13 +11373,13 @@ fun! s:NetrwLocalRmFile(path,fname,all)
|
||||
if ok == ""
|
||||
let ok="no"
|
||||
endif
|
||||
if ok =~# 'a\%[ll]'
|
||||
if ok =~# '^a\%[ll]$'
|
||||
let all= 1
|
||||
endif
|
||||
endif
|
||||
let rmfile= substitute(rmfile,'[\/]$','','e')
|
||||
|
||||
if all || ok =~# 'y\%[es]' || ok == ""
|
||||
if all || ok =~# '^y\%[es]$' || ok == ""
|
||||
if delete(rmfile,"rf")
|
||||
call netrw#ErrorMsg(s:ERROR,"unable to delete directory <".rmfile.">!",103)
|
||||
endif
|
||||
|
@ -4,6 +4,8 @@ They are used with the ":compiler" command.
|
||||
These scripts usually set options, for example 'errorformat'.
|
||||
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
|
||||
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
|
||||
" Compiler: Pandoc
|
||||
" Maintainer: Konfekt
|
||||
" Last Change: 2024 Aug 20
|
||||
" Last Change: 2024 Sep 8
|
||||
"
|
||||
" Expects output file extension, say `:make html` or `:make pdf`.
|
||||
" 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")
|
||||
finish
|
||||
@ -40,17 +42,20 @@ silent! function s:PandocFiletype(filetype) abort
|
||||
endif
|
||||
endfunction
|
||||
|
||||
let b:pandoc_compiler_from = get(b:, 'pandoc_compiler_from', s:PandocFiletype(&filetype))
|
||||
let b:pandoc_compiler_lang = get(b:, 'pandoc_compiler_lang', &spell ? matchstr(&spelllang, '^\a\a') : '')
|
||||
silent! function s:PandocLang()
|
||||
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(
|
||||
\ ' --standalone' .
|
||||
\ (b:pandoc_compiler_from ==# 'markdown' && (getline(1) =~# '^%\s\+\S\+' || (search('^title:\s+\S+', 'cnw') > 0)) ?
|
||||
\ '' : ' --metadata title=%:t:r:S') .
|
||||
\ (empty(b:pandoc_compiler_lang) ?
|
||||
\ '' : ' --metadata lang='..b:pandoc_compiler_lang) .
|
||||
\ ' --from='..b:pandoc_compiler_from .
|
||||
\ ' '..get(b:, 'pandoc_compiler_args', get(g:, 'pandoc_compiler_args', '')) .
|
||||
\ ' --standalone'..
|
||||
\ (s:PandocFiletype(&filetype) ==# 'markdown' && (getline(1) =~# '^%\s\+\S\+' || (search('^title:\s+\S+', 'cnw') > 0)) ?
|
||||
\ '' : ' --metadata title=%:t:r:S')..
|
||||
\ ' '..s:PandocLang()..
|
||||
\ ' --from='..s:PandocFiletype(&filetype)..
|
||||
\ ' '..get(b:, 'pandoc_compiler_args', get(g:, 'pandoc_compiler_args', ''))..
|
||||
\ ' --output %:r:S.$* -- %:S', ' ')
|
||||
CompilerSet errorformat=\"%f\",\ line\ %l:\ %m
|
||||
|
||||
|
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
|
||||
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
|
||||
cursor positioned on the start of a match. If it evaluates to
|
||||
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()*
|
||||
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: ~
|
||||
• {behavior} (`'error'|'keep'|'force'`) Decides what to do if a key is
|
||||
found in more than one map:
|
||||
@ -2553,7 +2559,7 @@ vim.ui.input({opts}, {on_confirm}) *vim.ui.input()*
|
||||
typed (it might be an empty string if nothing was
|
||||
entered), or `nil` if the user aborted the dialog.
|
||||
|
||||
vim.ui.open({path}) *vim.ui.open()*
|
||||
vim.ui.open({path}, {opt}) *vim.ui.open()*
|
||||
Opens `path` with the system default handler (macOS `open`, Windows
|
||||
`explorer.exe`, Linux `xdg-open`, …), or returns (but does not show) an
|
||||
error message on failure.
|
||||
@ -2564,6 +2570,8 @@ vim.ui.open({path}) *vim.ui.open()*
|
||||
-- Asynchronous.
|
||||
vim.ui.open("https://neovim.io/")
|
||||
vim.ui.open("~/path/to/file")
|
||||
-- Use the "osurl" command to handle the path or URL.
|
||||
vim.ui.open("gh#neovim/neovim!29490", { cmd = { 'osurl' } })
|
||||
-- Synchronous (wait until the process exits).
|
||||
local cmd, err = vim.ui.open("$VIMRUNTIME")
|
||||
if cmd then
|
||||
@ -2573,6 +2581,8 @@ vim.ui.open({path}) *vim.ui.open()*
|
||||
|
||||
Parameters: ~
|
||||
• {path} (`string`) Path or URL to open
|
||||
• {opt} (`{ cmd?: string[] }?`) Options
|
||||
• cmd string[]|nil Command used to open the path or URL.
|
||||
|
||||
Return (multiple): ~
|
||||
(`vim.SystemObj?`) Command object, or nil if not found.
|
||||
|
@ -189,11 +189,15 @@ TREESITTER
|
||||
|
||||
TUI
|
||||
|
||||
• TODO
|
||||
• |log| messages written by the builtin UI client (TUI, |--remote-ui|) are
|
||||
now prefixed with "ui" instead of "?".
|
||||
|
||||
UI
|
||||
|
||||
• TODO
|
||||
• |vim.ui.open()| (by default bound to |gx|) accepts an `opt.cmd` parameter
|
||||
which controls the tool used to open the given path or URL. If you want to
|
||||
globally set this, you can override vim.ui.open using the same approach
|
||||
described at |vim.paste()|.
|
||||
|
||||
==============================================================================
|
||||
CHANGED FEATURES *news-changed*
|
||||
@ -214,9 +218,6 @@ These existing features changed their behavior.
|
||||
more emoji characters than before, including those encoded with multiple
|
||||
emoji codepoints combined with ZWJ (zero width joiner) codepoints.
|
||||
|
||||
• |vim.tbl_deep_extend()| no longer ignores any values for which |vim.isarray()|
|
||||
returns `true`.
|
||||
|
||||
==============================================================================
|
||||
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
|
||||
When on, the title of the window will be set to the value of
|
||||
'titlestring' (if it is not empty), or to:
|
||||
filename [+=-] (path) - NVIM
|
||||
filename [+=-] (path) - Nvim
|
||||
Where:
|
||||
filename the name of the file being edited
|
||||
- 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 and modified
|
||||
(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' 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|.
|
||||
|
||||
Use the |compiler-make| plugin to undo the effect of a compiler plugin.
|
||||
|
||||
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
|
||||
compiler dotnet
|
||||
<
|
||||
|
||||
GCC *quickfix-gcc* *compiler-gcc*
|
||||
|
||||
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: >
|
||||
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*
|
||||
|
||||
@ -1307,8 +1325,7 @@ Additional arguments can be passed to pandoc:
|
||||
|
||||
The `--from` argument is an educated guess using the buffer file type;
|
||||
it can be overridden by setting `b:pandoc_compiler_from`.
|
||||
Likewise the `--metadata lang` argument is set using `&spelllang`;
|
||||
it can be overridden by setting `b:pandoc_compiler_lang`.
|
||||
The `--metadata lang` argument is set using 'spelllang';
|
||||
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.
|
||||
|
||||
|
@ -1683,6 +1683,12 @@ In order to highlight nested parens with different colors, define colors for
|
||||
or >
|
||||
:hi javaParen ctermfg=blue guifg=#0000ff
|
||||
|
||||
Certain modifiers are incompatible with each other, e.g. `abstract` and
|
||||
`final`: >
|
||||
:syn list javaConceptKind
|
||||
and can be differently highlighted as a group than other modifiers with >
|
||||
:hi link javaConceptKind NonText
|
||||
|
||||
If you notice highlighting errors while scrolling backwards, which are fixed
|
||||
when redrawing with CTRL-L, try setting the "g:java_minlines" variable to
|
||||
a larger number: >
|
||||
|
@ -53,11 +53,17 @@ active yes yes 'a'
|
||||
hidden no yes 'h'
|
||||
inactive no no ' '
|
||||
|
||||
Note: All CTRL-W commands can also be executed with |:wincmd|, for those
|
||||
places where a Normal mode command can't be used or is inconvenient.
|
||||
*buffer-reuse*
|
||||
Each buffer has a unique number and the number will not change within a Vim
|
||||
session. The |bufnr()| and |bufname()| functions can be used to convert
|
||||
between a buffer name and the buffer number. There is one exception: if a new
|
||||
empty buffer is created and it is not modified, the buffer will be re-used
|
||||
when loading another file into that buffer. This also means the buffer number
|
||||
will not change.
|
||||
|
||||
The main Vim window can hold several split windows. There are also tab pages
|
||||
|tab-page|, each of which can hold multiple windows.
|
||||
|
||||
*window-ID* *winid* *windowid*
|
||||
Each window has a unique identifier called the window ID. This identifier
|
||||
will not change within a Vim session. The |win_getid()| and |win_id2tabwin()|
|
||||
@ -69,9 +75,6 @@ across tabs. For most functions that take a window ID or a window number, the
|
||||
window number only applies to the current tab, while the window ID can refer
|
||||
to a window in any tab.
|
||||
|
||||
Each buffer has a unique number and the number will not change within a Vim
|
||||
session. The |bufnr()| and |bufname()| functions can be used to convert
|
||||
between a buffer name and the buffer number.
|
||||
|
||||
==============================================================================
|
||||
2. Starting Vim *windows-starting*
|
||||
@ -468,6 +471,10 @@ These commands can also be executed with ":wincmd":
|
||||
:exe nr .. "wincmd w"
|
||||
< This goes to window "nr".
|
||||
|
||||
Note: All CTRL-W commands can also be executed with |:wincmd|, for those
|
||||
places where a Normal mode command can't be used or is inconvenient (e.g.
|
||||
in a browser-based terminal).
|
||||
|
||||
==============================================================================
|
||||
5. Moving windows around *window-moving*
|
||||
|
||||
|
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
|
||||
" Maintainer: Igor Gnatenko i.gnatenko.brain@gmail.com
|
||||
" 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
|
||||
" 2024 Sep 10 by Vim Project: add epoch support for spec changelog, #15537
|
||||
|
||||
if exists("b:did_ftplugin")
|
||||
finish
|
||||
@ -66,9 +67,11 @@ if !exists("*s:SpecChangelog")
|
||||
endif
|
||||
let line = 0
|
||||
let name = ""
|
||||
let epoch = ""
|
||||
let ver = ""
|
||||
let rel = ""
|
||||
let nameline = -1
|
||||
let epochline = -1
|
||||
let verline = -1
|
||||
let relline = -1
|
||||
let chgline = -1
|
||||
@ -77,6 +80,9 @@ if !exists("*s:SpecChangelog")
|
||||
if name == "" && linestr =~? '^Name:'
|
||||
let nameline = line
|
||||
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:'
|
||||
let verline = line
|
||||
let ver = substitute(strpart(linestr,8), '^[ ]*\([^ ]\+\)[ ]*$','\1','')
|
||||
@ -93,6 +99,7 @@ if !exists("*s:SpecChangelog")
|
||||
if nameline != -1 && verline != -1 && relline != -1
|
||||
let include_release_info = exists("g:spec_chglog_release_info")
|
||||
let name = s:ParseRpmVars(name, nameline)
|
||||
let epoch = s:ParseRpmVars(epoch, epochline)
|
||||
let ver = s:ParseRpmVars(ver, verline)
|
||||
let rel = s:ParseRpmVars(rel, relline)
|
||||
else
|
||||
@ -117,6 +124,9 @@ if !exists("*s:SpecChangelog")
|
||||
if chgline != -1
|
||||
let tmptime = v:lc_time
|
||||
language time C
|
||||
if strlen(epoch)
|
||||
let ver = epoch.":".ver
|
||||
endif
|
||||
let parsed_format = "* ".strftime(format)." - ".ver."-".rel
|
||||
execute "language time" tmptime
|
||||
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 = {}
|
||||
if opt.font then
|
||||
fonts = type(opt.font) == 'string' and { opt.font } or opt.font --[[@as (string[])]]
|
||||
elseif vim.o.guifont:match('^[^:]+') then
|
||||
table.insert(fonts, vim.o.guifont:match('^[^:]+'))
|
||||
for i, v in pairs(fonts) do
|
||||
fonts[i] = ('"%s"'):format(v)
|
||||
end
|
||||
elseif vim.o.guifont:match('^[^:]+') then
|
||||
-- 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
|
||||
-- Generic family names (monospace here) must not be quoted
|
||||
-- because the browser recognizes them as font families.
|
||||
table.insert(fonts, 'monospace')
|
||||
--- @type vim.tohtml.state.global
|
||||
local state = {
|
||||
|
@ -9,8 +9,8 @@
|
||||
local function get_commentstring(ref_position)
|
||||
local buf_cs = vim.bo.commentstring
|
||||
|
||||
local has_ts_parser, ts_parser = pcall(vim.treesitter.get_parser)
|
||||
if not has_ts_parser then
|
||||
local ts_parser = vim.treesitter._get_parser()
|
||||
if not ts_parser then
|
||||
return buf_cs
|
||||
end
|
||||
|
||||
|
@ -97,37 +97,13 @@ do
|
||||
|
||||
--- Map |gx| to call |vim.ui.open| on the <cfile> at cursor.
|
||||
do
|
||||
local function do_open(uri)
|
||||
local cmd, err = vim.ui.open(uri)
|
||||
local rv = cmd and cmd:wait(1000) or nil
|
||||
if cmd and rv and rv.code ~= 0 then
|
||||
err = ('vim.ui.open: command %s (%d): %s'):format(
|
||||
(rv.code == 124 and 'timeout' or 'failed'),
|
||||
rv.code,
|
||||
vim.inspect(cmd.cmd)
|
||||
)
|
||||
end
|
||||
return err
|
||||
end
|
||||
|
||||
local gx_desc =
|
||||
'Opens filepath or URI under cursor with the system handler (file explorer, web browser, …)'
|
||||
vim.keymap.set({ 'n' }, 'gx', function()
|
||||
for _, url in ipairs(require('vim.ui')._get_urls()) do
|
||||
local err = do_open(url)
|
||||
if err then
|
||||
vim.notify(err, vim.log.levels.ERROR)
|
||||
end
|
||||
end
|
||||
vim.ui.open()
|
||||
end, { desc = gx_desc })
|
||||
vim.keymap.set({ 'x' }, 'gx', function()
|
||||
local lines =
|
||||
vim.fn.getregion(vim.fn.getpos('.'), vim.fn.getpos('v'), { type = vim.fn.mode() })
|
||||
-- Trim whitespace on each line and concatenate.
|
||||
local err = do_open(table.concat(vim.iter(lines):map(vim.trim):totable()))
|
||||
if err then
|
||||
vim.notify(err, vim.log.levels.ERROR)
|
||||
end
|
||||
vim.ui.open()
|
||||
end, { desc = gx_desc })
|
||||
end
|
||||
|
||||
@ -213,7 +189,6 @@ end
|
||||
--- Default menus
|
||||
do
|
||||
--- Right click popup menu
|
||||
local function def_menu(ctx)
|
||||
vim.cmd([[
|
||||
anoremenu PopUp.Go\ to\ definition <Cmd>lua vim.lsp.buf.definition()<CR>
|
||||
amenu PopUp.Open\ in\ web\ browser gx
|
||||
@ -229,7 +204,10 @@ do
|
||||
inoremenu PopUp.Select\ All <C-Home><C-O>VG
|
||||
anoremenu PopUp.-2- <Nop>
|
||||
anoremenu PopUp.How-to\ disable\ mouse <Cmd>help disable-mouse<CR>
|
||||
]])
|
||||
|
||||
local function enable_ctx_menu(ctx)
|
||||
vim.cmd([[
|
||||
amenu disable PopUp.Go\ to\ definition
|
||||
amenu disable PopUp.Open\ in\ web\ browser
|
||||
]])
|
||||
@ -240,7 +218,6 @@ do
|
||||
vim.cmd([[anoremenu enable PopUp.Go\ to\ definition]])
|
||||
end
|
||||
end
|
||||
def_menu()
|
||||
|
||||
local nvim_popupmenu_augroup = vim.api.nvim_create_augroup('nvim_popupmenu', {})
|
||||
vim.api.nvim_create_autocmd('MenuPopup', {
|
||||
@ -252,7 +229,7 @@ do
|
||||
local urls = require('vim.ui')._get_urls()
|
||||
local url = vim.startswith(urls[1], 'http')
|
||||
local ctx = url and 'url' or (vim.lsp.get_clients({ bufnr = 0 })[1] and 'lsp' or nil)
|
||||
def_menu(ctx)
|
||||
enable_ctx_menu(ctx)
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
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
|
||||
--- 'titlestring' (if it is not empty), or to:
|
||||
--- filename [+=-] (path) - NVIM
|
||||
--- filename [+=-] (path) - Nvim
|
||||
--- Where:
|
||||
--- filename the name of the file being edited
|
||||
--- - 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 and modified
|
||||
--- (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
|
||||
vim.o.title = false
|
||||
|
17
runtime/lua/vim/_meta/vimfn.lua
generated
17
runtime/lua/vim/_meta/vimfn.lua
generated
@ -6703,7 +6703,7 @@ function vim.fn.printf(fmt, expr1) end
|
||||
--- If the buffer doesn't exist or isn't a prompt buffer, an empty
|
||||
--- string is returned.
|
||||
---
|
||||
--- @param buf any
|
||||
--- @param buf integer|string
|
||||
--- @return any
|
||||
function vim.fn.prompt_getprompt(buf) end
|
||||
|
||||
@ -6738,8 +6738,8 @@ function vim.fn.prompt_getprompt(buf) end
|
||||
--- endfunc
|
||||
--- call prompt_setcallback(bufnr(), function('s:TextEntered'))
|
||||
---
|
||||
--- @param buf any
|
||||
--- @param expr any
|
||||
--- @param buf integer|string
|
||||
--- @param expr string|function
|
||||
--- @return any
|
||||
function vim.fn.prompt_setcallback(buf, expr) end
|
||||
|
||||
@ -6751,8 +6751,8 @@ function vim.fn.prompt_setcallback(buf, expr) end
|
||||
--- mode. Without setting a callback Vim will exit Insert mode,
|
||||
--- as in any buffer.
|
||||
---
|
||||
--- @param buf any
|
||||
--- @param expr any
|
||||
--- @param buf integer|string
|
||||
--- @param expr string|function
|
||||
--- @return any
|
||||
function vim.fn.prompt_setinterrupt(buf, expr) end
|
||||
|
||||
@ -6763,8 +6763,8 @@ function vim.fn.prompt_setinterrupt(buf, expr) end
|
||||
--- call prompt_setprompt(bufnr(''), 'command: ')
|
||||
--- <
|
||||
---
|
||||
--- @param buf any
|
||||
--- @param text any
|
||||
--- @param buf integer|string
|
||||
--- @param text string
|
||||
--- @return any
|
||||
function vim.fn.prompt_setprompt(buf, text) end
|
||||
|
||||
@ -7421,6 +7421,9 @@ function vim.fn.screenstring(row, col) end
|
||||
--- The value must not be negative. A zero value is like not
|
||||
--- 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
|
||||
--- cursor positioned on the start of a match. If it evaluates to
|
||||
--- non-zero this match is skipped. This can be used, for
|
||||
|
@ -280,12 +280,7 @@ local extension = {
|
||||
cfi = 'cf',
|
||||
hgrc = 'cfg',
|
||||
cfg = detect.cfg,
|
||||
cfG = detect.cfg,
|
||||
cFg = detect.cfg,
|
||||
cFG = detect.cfg,
|
||||
Cfg = detect.cfg,
|
||||
CfG = detect.cfg,
|
||||
CFg = detect.cfg,
|
||||
CFG = detect.cfg,
|
||||
chf = 'ch',
|
||||
chai = 'chaiscript',
|
||||
@ -370,12 +365,7 @@ local extension = {
|
||||
drt = 'dart',
|
||||
ds = 'datascript',
|
||||
dat = detect.dat,
|
||||
daT = detect.dat,
|
||||
dAt = detect.dat,
|
||||
dAT = detect.dat,
|
||||
Dat = detect.dat,
|
||||
DaT = detect.dat,
|
||||
DAt = detect.dat,
|
||||
DAT = detect.dat,
|
||||
dcd = 'dcd',
|
||||
decl = detect.decl,
|
||||
@ -658,12 +648,7 @@ local extension = {
|
||||
kt = 'kotlin',
|
||||
ktm = 'kotlin',
|
||||
sub = 'krl',
|
||||
suB = 'krl',
|
||||
sUb = 'krl',
|
||||
sUB = 'krl',
|
||||
Sub = 'krl',
|
||||
SuB = 'krl',
|
||||
SUb = 'krl',
|
||||
SUB = 'krl',
|
||||
ks = 'kscript',
|
||||
k = 'kwt',
|
||||
@ -699,12 +684,7 @@ local extension = {
|
||||
lite = 'lite',
|
||||
livemd = 'livebook',
|
||||
log = detect.log,
|
||||
loG = detect.log,
|
||||
lOg = detect.log,
|
||||
lOG = detect.log,
|
||||
Log = detect.log,
|
||||
LoG = detect.log,
|
||||
LOg = detect.log,
|
||||
LOG = detect.log,
|
||||
lgt = 'logtalk',
|
||||
lotos = 'lotos',
|
||||
@ -773,12 +753,7 @@ local extension = {
|
||||
mmp = 'mmp',
|
||||
mms = detect.mms,
|
||||
mod = detect.mod,
|
||||
moD = detect.mod,
|
||||
mOd = detect.mod,
|
||||
mOD = detect.mod,
|
||||
Mod = detect.mod,
|
||||
MoD = detect.mod,
|
||||
MOd = detect.mod,
|
||||
MOD = detect.mod,
|
||||
DEF = 'modula2',
|
||||
m3 = 'modula3',
|
||||
@ -948,12 +923,7 @@ local extension = {
|
||||
ih = 'ppwiz',
|
||||
action = 'privoxy',
|
||||
prg = detect.prg,
|
||||
prG = detect.prg,
|
||||
pRg = detect.prg,
|
||||
pRG = detect.prg,
|
||||
Prg = detect.prg,
|
||||
PrG = detect.prg,
|
||||
PRg = detect.prg,
|
||||
PRG = detect.prg,
|
||||
pc = 'proc',
|
||||
pdb = 'prolog',
|
||||
@ -1133,12 +1103,7 @@ local extension = {
|
||||
sqr = 'sqr',
|
||||
nut = 'squirrel',
|
||||
src = detect.src,
|
||||
srC = detect.src,
|
||||
sRc = detect.src,
|
||||
sRC = detect.src,
|
||||
Src = detect.src,
|
||||
SrC = detect.src,
|
||||
SRc = detect.src,
|
||||
SRC = detect.src,
|
||||
s28 = 'srec',
|
||||
s37 = 'srec',
|
||||
@ -1164,15 +1129,11 @@ local extension = {
|
||||
svelte = 'svelte',
|
||||
svg = 'svg',
|
||||
swift = 'swift',
|
||||
swiftinterface = 'swift',
|
||||
swig = 'swig',
|
||||
swg = 'swig',
|
||||
sys = detect.sys,
|
||||
syS = detect.sys,
|
||||
sYs = detect.sys,
|
||||
sYS = detect.sys,
|
||||
Sys = detect.sys,
|
||||
SyS = detect.sys,
|
||||
SYs = detect.sys,
|
||||
SYS = detect.sys,
|
||||
svh = 'systemverilog',
|
||||
sv = 'systemverilog',
|
||||
|
@ -285,8 +285,8 @@ local path2name = function(path)
|
||||
-- Remove everything up to the last /lua/ folder
|
||||
path = path:gsub('^.*/lua/', '')
|
||||
|
||||
-- Remove the filename (health.lua)
|
||||
path = vim.fs.dirname(path)
|
||||
-- Remove the filename (health.lua) or (health/init.lua)
|
||||
path = vim.fs.dirname(path:gsub('/init%.lua$', ''))
|
||||
|
||||
-- Change slashes to dots
|
||||
path = path:gsub('/', '.')
|
||||
|
@ -447,11 +447,9 @@ function M.document_symbol(opts)
|
||||
request_with_opts(ms.textDocument_documentSymbol, params, opts)
|
||||
end
|
||||
|
||||
--- @param call_hierarchy_items lsp.CallHierarchyItem[]?
|
||||
--- @param call_hierarchy_items lsp.CallHierarchyItem[]
|
||||
--- @return lsp.CallHierarchyItem?
|
||||
local function pick_call_hierarchy_item(call_hierarchy_items)
|
||||
if not call_hierarchy_items then
|
||||
return
|
||||
end
|
||||
if #call_hierarchy_items == 1 then
|
||||
return call_hierarchy_items[1]
|
||||
end
|
||||
@ -476,7 +474,7 @@ local function call_hierarchy(method)
|
||||
vim.notify(err.message, vim.log.levels.WARN)
|
||||
return
|
||||
end
|
||||
if not result then
|
||||
if not result or vim.tbl_isempty(result) then
|
||||
vim.notify('No item resolved', vim.log.levels.WARN)
|
||||
return
|
||||
end
|
||||
|
@ -43,17 +43,16 @@ function M.on_inlayhint(err, result, ctx, _)
|
||||
return
|
||||
end
|
||||
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
|
||||
end
|
||||
local client_id = ctx.client_id
|
||||
if not result then
|
||||
return
|
||||
end
|
||||
local bufstate = bufstates[bufnr]
|
||||
if not bufstate.enabled then
|
||||
return
|
||||
end
|
||||
if not (bufstate.client_hints and bufstate.version) then
|
||||
bufstate.client_hints = vim.defaulttable()
|
||||
bufstate.version = ctx.version
|
||||
@ -77,12 +76,7 @@ function M.on_inlayhint(err, result, ctx, _)
|
||||
local col = position.character
|
||||
if col > 0 then
|
||||
local line = lines[position.line + 1] or ''
|
||||
local ok, convert_result
|
||||
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)
|
||||
return util._str_byteindex_enc(line, col, client.offset_encoding)
|
||||
end
|
||||
return col
|
||||
end
|
||||
|
@ -140,12 +140,7 @@ local function tokens_to_ranges(data, bufnr, client, request)
|
||||
local function _get_byte_pos(col)
|
||||
if col > 0 then
|
||||
local buf_line = lines[line + 1] or ''
|
||||
local ok, result
|
||||
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)
|
||||
return util._str_byteindex_enc(buf_line, col, client.offset_encoding)
|
||||
end
|
||||
return col
|
||||
end
|
||||
|
@ -119,6 +119,7 @@ end
|
||||
---@param encoding string|nil utf-8|utf-16|utf-32|nil defaults to utf-16
|
||||
---@return integer `encoding` index of `index` in `line`
|
||||
function M._str_utfindex_enc(line, index, encoding)
|
||||
local len32, len16 = vim.str_utfindex(line)
|
||||
if not encoding then
|
||||
encoding = 'utf-16'
|
||||
end
|
||||
@ -129,9 +130,15 @@ function M._str_utfindex_enc(line, index, encoding)
|
||||
return #line
|
||||
end
|
||||
elseif encoding == 'utf-16' then
|
||||
if not index or index > len16 then
|
||||
return len16
|
||||
end
|
||||
local _, col16 = vim.str_utfindex(line, index)
|
||||
return col16
|
||||
elseif encoding == 'utf-32' then
|
||||
if not index or index > len32 then
|
||||
return len32
|
||||
end
|
||||
local col32, _ = vim.str_utfindex(line, index)
|
||||
return col32
|
||||
else
|
||||
@ -147,6 +154,12 @@ end
|
||||
---@param encoding string utf-8|utf-16|utf-32| defaults to utf-16
|
||||
---@return integer byte (utf-8) index of `encoding` index `index` in `line`
|
||||
function M._str_byteindex_enc(line, index, encoding)
|
||||
local len = #line
|
||||
if index > len then
|
||||
-- LSP spec: if character > line length, default to the line length.
|
||||
-- https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#position
|
||||
return len
|
||||
end
|
||||
if not encoding then
|
||||
encoding = 'utf-16'
|
||||
end
|
||||
@ -154,7 +167,7 @@ function M._str_byteindex_enc(line, index, encoding)
|
||||
if index then
|
||||
return index
|
||||
else
|
||||
return #line
|
||||
return len
|
||||
end
|
||||
elseif encoding == 'utf-16' then
|
||||
return vim.str_byteindex(line, index, true)
|
||||
@ -165,9 +178,6 @@ function M._str_byteindex_enc(line, index, encoding)
|
||||
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.
|
||||
---
|
||||
--- CAUTION: Changes in-place!
|
||||
@ -334,12 +344,7 @@ local function get_line_byte_from_position(bufnr, position, offset_encoding)
|
||||
-- character
|
||||
if col > 0 then
|
||||
local line = get_line(bufnr, position.line) or ''
|
||||
local ok, result
|
||||
ok, result = pcall(_str_byteindex_enc, line, col, offset_encoding)
|
||||
if ok then
|
||||
return result
|
||||
end
|
||||
return math.min(#line, col)
|
||||
return M._str_byteindex_enc(line, col, offset_encoding or 'utf-16')
|
||||
end
|
||||
return col
|
||||
end
|
||||
@ -436,14 +441,15 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding)
|
||||
e.end_col = last_line_len
|
||||
has_eol_text_edit = true
|
||||
else
|
||||
-- If the replacement is over the end of a line (i.e. e.end_col is 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
|
||||
-- to be meant to replace the newline with another newline and we need to make sure this
|
||||
-- doesn't add an extra empty line. E.g. when the last line to be replaced contains a '\r'
|
||||
-- in the file some servers (clangd on windows) will include that character in the line
|
||||
-- while nvim_buf_set_text doesn't count it as part of the line.
|
||||
if
|
||||
e.end_col > last_line_len
|
||||
e.end_col >= last_line_len
|
||||
and text_edit.range['end'].character > e.end_col
|
||||
and #text_edit.newText > 0
|
||||
and string.sub(text_edit.newText, -1) == '\n'
|
||||
then
|
||||
@ -1795,17 +1801,9 @@ function M.locations_to_items(locations, offset_encoding)
|
||||
local row = pos.line
|
||||
local end_row = end_pos.line
|
||||
local line = lines[row] or ''
|
||||
local line_len = vim.fn.strcharlen(line)
|
||||
local end_line = lines[end_row] or ''
|
||||
local end_line_len = vim.fn.strcharlen(end_line)
|
||||
-- LSP spec: if character > line length, default to the line length.
|
||||
-- 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
|
||||
local col = M._str_byteindex_enc(line, pos.character, offset_encoding)
|
||||
local end_col = M._str_byteindex_enc(end_line, end_pos.character, offset_encoding)
|
||||
|
||||
table.insert(items, {
|
||||
filename = filename,
|
||||
@ -1935,7 +1933,7 @@ local function make_position_param(window, offset_encoding)
|
||||
return { line = 0, character = 0 }
|
||||
end
|
||||
|
||||
col = _str_utfindex_enc(line, col, offset_encoding)
|
||||
col = M._str_utfindex_enc(line, col, offset_encoding)
|
||||
|
||||
return { line = row, character = col }
|
||||
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
|
||||
end
|
||||
-- If the col is past the EOL, use the line length.
|
||||
if col > #line then
|
||||
return _str_utfindex_enc(line, nil, offset_encoding)
|
||||
end
|
||||
return _str_utfindex_enc(line, col, offset_encoding)
|
||||
return M._str_utfindex_enc(line, col, offset_encoding)
|
||||
end
|
||||
|
||||
--- Helper function to return nested values in language server settings
|
||||
|
@ -354,6 +354,12 @@ function vim.tbl_isempty(t)
|
||||
return next(t) == nil
|
||||
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
|
||||
--- @param behavior 'error'|'keep'|'force'
|
||||
--- @param deep_extend boolean
|
||||
@ -368,7 +374,7 @@ local function tbl_extend_rec(behavior, deep_extend, ...)
|
||||
local tbl = select(i, ...) --[[@as table<any,any>]]
|
||||
if tbl then
|
||||
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)
|
||||
elseif behavior ~= 'force' and ret[k] ~= nil then
|
||||
if behavior == 'error' then
|
||||
@ -421,6 +427,11 @@ end
|
||||
|
||||
--- 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()|
|
||||
---
|
||||
---@generic T1: table
|
||||
|
@ -74,14 +74,14 @@ end
|
||||
|
||||
--- Returns the parser for a specific buffer and attaches it to the buffer
|
||||
---
|
||||
--- If needed, this will create the parser.
|
||||
--- If needed, this will create the parser. If no parser can be found or created, returns `nil`.
|
||||
---
|
||||
---@param bufnr (integer|nil) Buffer the parser should be tied to (default: current buffer)
|
||||
---@param lang (string|nil) Language of this parser (default: from buffer filetype)
|
||||
---@param opts (table|nil) Options to pass to the created language tree
|
||||
---
|
||||
---@return vim.treesitter.LanguageTree object to use for parsing
|
||||
function M.get_parser(bufnr, lang, opts)
|
||||
---@return vim.treesitter.LanguageTree? object to use for parsing, or `nil` if not found
|
||||
function M._get_parser(bufnr, lang, opts)
|
||||
opts = opts or {}
|
||||
|
||||
if bufnr == nil or bufnr == 0 then
|
||||
@ -94,18 +94,14 @@ function M.get_parser(bufnr, lang, opts)
|
||||
|
||||
if not valid_lang(lang) then
|
||||
if not parsers[bufnr] then
|
||||
error(
|
||||
string.format(
|
||||
'There is no parser available for buffer %d and one could not be'
|
||||
.. ' created because lang could not be determined. Either pass lang'
|
||||
.. ' or set the buffer filetype',
|
||||
bufnr
|
||||
)
|
||||
)
|
||||
return nil
|
||||
end
|
||||
elseif parsers[bufnr] == nil or parsers[bufnr]:lang() ~= lang then
|
||||
assert(lang, 'lang should be valid')
|
||||
parsers[bufnr] = M._create_parser(bufnr, lang, opts)
|
||||
local parser = vim.F.npcall(M._create_parser, bufnr, lang, opts)
|
||||
if not parser then
|
||||
return nil
|
||||
end
|
||||
parsers[bufnr] = parser
|
||||
end
|
||||
|
||||
parsers[bufnr]:register_cbs(opts.buf_attach_cbs)
|
||||
@ -113,6 +109,29 @@ function M.get_parser(bufnr, lang, opts)
|
||||
return parsers[bufnr]
|
||||
end
|
||||
|
||||
--- Returns the parser for a specific buffer and attaches it to the buffer
|
||||
---
|
||||
--- If needed, this will create the parser.
|
||||
---
|
||||
---@param bufnr (integer|nil) Buffer the parser should be tied to (default: current buffer)
|
||||
---@param lang (string|nil) Language of this parser (default: from buffer filetype)
|
||||
---@param opts (table|nil) Options to pass to the created language tree
|
||||
---
|
||||
---@return vim.treesitter.LanguageTree object to use for parsing
|
||||
function M.get_parser(bufnr, lang, opts)
|
||||
-- TODO(ribru17): Remove _get_parser and move that logic back here once the breaking function
|
||||
-- signature change is acceptable.
|
||||
local parser = M._get_parser(bufnr, lang, opts)
|
||||
if not parser then
|
||||
vim.notify_once(
|
||||
'WARNING: vim.treesitter.get_parser will return nil instead of raising an error in Neovim 0.12',
|
||||
vim.log.levels.WARN
|
||||
)
|
||||
error('Parser not found.')
|
||||
end
|
||||
return parser
|
||||
end
|
||||
|
||||
--- Returns a string parser
|
||||
---
|
||||
---@param str string Text to parse
|
||||
@ -386,7 +405,7 @@ function M.get_node(opts)
|
||||
|
||||
local ts_range = { row, col, row, col }
|
||||
|
||||
local root_lang_tree = M.get_parser(bufnr, opts.lang)
|
||||
local root_lang_tree = M._get_parser(bufnr, opts.lang)
|
||||
if not root_lang_tree then
|
||||
return
|
||||
end
|
||||
@ -419,7 +438,11 @@ end
|
||||
---@param lang (string|nil) Language of the parser (default: from buffer filetype)
|
||||
function M.start(bufnr, lang)
|
||||
bufnr = bufnr or api.nvim_get_current_buf()
|
||||
local parser = M.get_parser(bufnr, lang)
|
||||
local parser = M._get_parser(bufnr, lang)
|
||||
if not parser then
|
||||
vim.notify('No parser for the given buffer.', vim.log.levels.WARN)
|
||||
return
|
||||
end
|
||||
M.highlighter.new(parser)
|
||||
end
|
||||
|
||||
|
@ -114,7 +114,7 @@ local function compute_folds_levels(bufnr, info, srow, erow, parse_injections)
|
||||
srow = srow or 0
|
||||
erow = erow or api.nvim_buf_line_count(bufnr)
|
||||
|
||||
local parser = ts.get_parser(bufnr)
|
||||
local parser = assert(ts._get_parser(bufnr))
|
||||
|
||||
parser:parse(parse_injections and { srow, erow } or nil)
|
||||
|
||||
@ -392,7 +392,7 @@ function M.foldexpr(lnum)
|
||||
lnum = lnum or vim.v.lnum
|
||||
local bufnr = api.nvim_get_current_buf()
|
||||
|
||||
local parser = vim.F.npcall(ts.get_parser, bufnr)
|
||||
local parser = ts._get_parser(bufnr)
|
||||
if not parser then
|
||||
return '0'
|
||||
end
|
||||
|
@ -172,7 +172,7 @@ function M.lint(buf, opts)
|
||||
--- @type (table|nil)
|
||||
local parser_info = vim.F.npcall(vim.treesitter.language.inspect, lang)
|
||||
|
||||
local parser = vim.treesitter.get_parser(buf)
|
||||
local parser = assert(vim.treesitter._get_parser(buf), 'query parser not found.')
|
||||
parser:parse()
|
||||
parser:for_each_tree(function(tree, ltree)
|
||||
if ltree:lang() == 'query' then
|
||||
|
@ -76,10 +76,9 @@ end
|
||||
---
|
||||
---@package
|
||||
function TSTreeView:new(bufnr, lang)
|
||||
local ok, parser = pcall(vim.treesitter.get_parser, bufnr or 0, lang)
|
||||
if not ok then
|
||||
local err = parser --[[ @as string ]]
|
||||
return nil, 'No parser available for the given buffer:\n' .. err
|
||||
local parser = vim.treesitter._get_parser(bufnr or 0, lang)
|
||||
if not parser then
|
||||
return nil, 'No parser available for the given buffer.'
|
||||
end
|
||||
|
||||
-- For each child tree (injected language), find the root of the tree and locate the node within
|
||||
@ -539,7 +538,7 @@ local edit_ns = api.nvim_create_namespace('treesitter/dev-edit')
|
||||
local function update_editor_highlights(query_win, base_win, lang)
|
||||
local base_buf = api.nvim_win_get_buf(base_win)
|
||||
local query_buf = api.nvim_win_get_buf(query_win)
|
||||
local parser = vim.treesitter.get_parser(base_buf, lang)
|
||||
local parser = assert(vim.treesitter._get_parser(base_buf, lang))
|
||||
api.nvim_buf_clear_namespace(base_buf, edit_ns, 0, -1)
|
||||
local query_content = table.concat(api.nvim_buf_get_lines(query_buf, 0, -1, false), '\n')
|
||||
|
||||
@ -596,8 +595,8 @@ function M.edit_query(lang)
|
||||
end
|
||||
vim.cmd(cmd)
|
||||
|
||||
local ok, parser = pcall(vim.treesitter.get_parser, buf, lang)
|
||||
if not ok then
|
||||
local parser = vim.treesitter._get_parser(buf, lang)
|
||||
if not parser then
|
||||
return nil, 'No parser available for the given buffer'
|
||||
end
|
||||
lang = parser:lang()
|
||||
|
@ -117,6 +117,8 @@ end
|
||||
--- -- Asynchronous.
|
||||
--- vim.ui.open("https://neovim.io/")
|
||||
--- vim.ui.open("~/path/to/file")
|
||||
--- -- Use the "osurl" command to handle the path or URL.
|
||||
--- vim.ui.open("gh#neovim/neovim!29490", { cmd = { 'osurl' } })
|
||||
--- -- Synchronous (wait until the process exits).
|
||||
--- local cmd, err = vim.ui.open("$VIMRUNTIME")
|
||||
--- if cmd then
|
||||
@ -124,47 +126,89 @@ end
|
||||
--- end
|
||||
--- ```
|
||||
---
|
||||
---@param path string Path or URL to open
|
||||
---@param path? string Path or URL to open, or `nil` to get path or URL at cursor.
|
||||
---@param opt? { cmd?: string[] } Options
|
||||
--- - cmd string[]|nil Command used to open the path or URL.
|
||||
---
|
||||
---@return vim.SystemObj|nil # Command object, or nil if not found.
|
||||
---@return nil|string # Error message on failure, or nil on success.
|
||||
---
|
||||
---@see |vim.system()|
|
||||
function M.open(path)
|
||||
function M.open(path, opt)
|
||||
vim.validate({
|
||||
path = { path, 'string' },
|
||||
path = { path, 'string', true },
|
||||
})
|
||||
local is_uri = path:match('%w+:')
|
||||
if not is_uri then
|
||||
path = vim.fs.normalize(path)
|
||||
end
|
||||
|
||||
opt = opt or {}
|
||||
local function do_open(uri)
|
||||
local cmd ---@type string[]
|
||||
local opts --- @type vim.SystemOpts
|
||||
local job_opt = { text = true, detach = true } --- @type vim.SystemOpts
|
||||
|
||||
opts = { text = true, detach = true }
|
||||
|
||||
if vim.fn.has('mac') == 1 then
|
||||
cmd = { 'open', path }
|
||||
if opt.cmd then
|
||||
cmd = vim.list_extend(opt.cmd --[[@as string[] ]], { uri })
|
||||
elseif vim.fn.has('mac') == 1 then
|
||||
cmd = { 'open', uri }
|
||||
elseif vim.fn.has('win32') == 1 then
|
||||
if vim.fn.executable('rundll32') == 1 then
|
||||
cmd = { 'rundll32', 'url.dll,FileProtocolHandler', path }
|
||||
cmd = { 'rundll32', 'url.dll,FileProtocolHandler', uri }
|
||||
else
|
||||
return nil, 'vim.ui.open: rundll32 not found'
|
||||
end
|
||||
elseif vim.fn.executable('wslview') == 1 then
|
||||
cmd = { 'wslview', path }
|
||||
elseif vim.fn.executable('explorer.exe') == 1 then
|
||||
cmd = { 'explorer.exe', path }
|
||||
elseif vim.fn.executable('xdg-open') == 1 then
|
||||
cmd = { 'xdg-open', path }
|
||||
opts.stdout = false
|
||||
opts.stderr = false
|
||||
cmd = { 'xdg-open', uri }
|
||||
job_opt.stdout = false
|
||||
job_opt.stderr = false
|
||||
elseif vim.fn.executable('wslview') == 1 then
|
||||
cmd = { 'wslview', uri }
|
||||
elseif vim.fn.executable('explorer.exe') == 1 then
|
||||
cmd = { 'explorer.exe', uri }
|
||||
else
|
||||
return nil, 'vim.ui.open: no handler found (tried: wslview, explorer.exe, xdg-open)'
|
||||
end
|
||||
|
||||
return vim.system(cmd, opts), nil
|
||||
return vim.system(cmd, job_opt), nil
|
||||
end
|
||||
|
||||
local function do_open2(uri)
|
||||
local cmd, err = do_open(uri)
|
||||
-- wait() terminates the process if necessary (avoids stale processes), and allows us to show an
|
||||
-- error message if needed.
|
||||
local rv = cmd and cmd:wait(1000) or nil
|
||||
if cmd and rv and rv.code ~= 0 then
|
||||
err = ('vim.ui.open: command %s (%d): %s'):format(
|
||||
(rv.code == 124 and 'timeout' or 'failed'),
|
||||
rv.code,
|
||||
vim.inspect(cmd.cmd)
|
||||
)
|
||||
end
|
||||
return err
|
||||
end
|
||||
|
||||
if path then
|
||||
local is_uri = path:match('%w+:')
|
||||
if not is_uri then
|
||||
path = vim.fs.normalize(path)
|
||||
end
|
||||
return do_open(path)
|
||||
else -- DWIM mode: get the URL or path from the cursor position, and show error.
|
||||
local visual = not not vim.fn.mode():match('[vV\22]')
|
||||
if visual then
|
||||
local lines =
|
||||
vim.fn.getregion(vim.fn.getpos('.'), vim.fn.getpos('v'), { type = vim.fn.mode() })
|
||||
-- Trim whitespace on each line and concatenate.
|
||||
local err = do_open2(table.concat(vim.iter(lines):map(vim.trim):totable()))
|
||||
if err then
|
||||
vim.notify(err, vim.log.levels.ERROR)
|
||||
end
|
||||
else
|
||||
for _, url in ipairs(M._get_urls()) do
|
||||
local err = do_open2(url)
|
||||
if err then
|
||||
vim.notify(err, vim.log.levels.ERROR)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Returns all URLs at cursor, if any.
|
||||
|
@ -33,7 +33,7 @@ end
|
||||
--- Show a table of contents for the help buffer in a loclist
|
||||
function M.show_toc()
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
local parser = vim.treesitter.get_parser(bufnr, 'vimdoc')
|
||||
local parser = assert(vim.treesitter._get_parser(bufnr, 'vimdoc'), 'vimdoc parser not found.')
|
||||
local query = vim.treesitter.query.parse(
|
||||
parser:lang(),
|
||||
[[
|
||||
|
@ -45,6 +45,11 @@
|
||||
(link_destination) @_url
|
||||
(#set! @_label url @_url))
|
||||
|
||||
(image
|
||||
(image_description) @_label
|
||||
(link_destination) @_url
|
||||
(#set! @_label url @_url))
|
||||
|
||||
; Conceal image links
|
||||
(image
|
||||
[
|
||||
|
@ -33,7 +33,10 @@
|
||||
")"
|
||||
] @punctuation.bracket
|
||||
|
||||
":" @punctuation.delimiter
|
||||
[
|
||||
":"
|
||||
"/"
|
||||
] @punctuation.delimiter
|
||||
|
||||
[
|
||||
"@"
|
||||
|
@ -1,12 +1,12 @@
|
||||
" Vim syntax file
|
||||
" Language: Configuration File (ini file) for MSDOS/MS Windows
|
||||
" Version: 2.3
|
||||
" Version: 2.4
|
||||
" Original Author: Sean M. McKee <mckee@misslink.net>
|
||||
" Previous Maintainer: Nima Talebi <nima@it.net.au>
|
||||
" Current Maintainer: Hong Xu <hong@topbug.net>
|
||||
" Homepage: http://www.vim.org/scripts/script.php?script_id=3747
|
||||
" 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
|
||||
@ -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\+e[+-]\=\d\+\s*$"
|
||||
syn region dosiniHeader start="^\s*\[" end="\]"
|
||||
syn match dosiniComment "^[#;].*$"
|
||||
syn match dosiniComment "^[#;].*$" contains=@Spell
|
||||
syn region dosiniSection start="\s*\[.*\]" end="\ze\s*\[.*\]" fold
|
||||
\ contains=dosiniLabel,dosiniValue,dosiniNumber,dosiniHeader,dosiniComment
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
" Interactive Data Language syntax file (IDL, too [:-)]
|
||||
" 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
|
||||
" 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 compile_opt forward_function goto
|
||||
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 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 CHISQR_CVF CHISQR_PDF CHOLDC CHOLSOL CINDGEN
|
||||
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 COMPUTE_MESH_NORMALS COND CONGRID CONJ
|
||||
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 DCINDGEN DCOMPLEX DCOMPLEXARR DEFINE_KEY DEFROI
|
||||
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_PRINTJOB DIALOG_READ_IMAGE
|
||||
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 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 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 PLOTERR PLOTS PNT_LINE POINT_LUN POLAR_CONTOUR
|
||||
syn keyword idlangRoutine POLAR_SURFACE POLY POLY_2D POLY_AREA POLY_FIT
|
||||
|
@ -3,7 +3,7 @@
|
||||
" Maintainer: Aliaksei Budavei <0x000c70 AT gmail DOT com>
|
||||
" Former Maintainer: Claudio Fleiner <claudio@fleiner.com>
|
||||
" Repository: https://github.com/zzzyxwvut/java-vim.git
|
||||
" Last Change: 2024 Aug 26
|
||||
" Last Change: 2024 Sep 11
|
||||
|
||||
" 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
|
||||
" ".java\=" extension used for a production version and an arbitrary
|
||||
" 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 javaModuleStmt open requires exports opens uses provides
|
||||
syn keyword javaModuleExternal to with
|
||||
hi def link javaModuleStorageClass StorageClass
|
||||
hi def link javaModuleStmt Statement
|
||||
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
|
||||
|
||||
" 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)
|
||||
endtry
|
||||
|
||||
syn region javaDocComment start="/\*\*" end="\*/" keepend contains=javaCommentTitle,@javaHtml,javaDocTags,javaDocSeeTag,javaDocCodeTag,javaDocSnippetTag,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'
|
||||
syn region javaCommentTitle contained matchgroup=javaDocComment start="/\*\*\s*\r\=\n\=\s*\**\s*\%({@return\>\)\@=" matchgroup=javaCommentTitle end="}\%(\s*\.*\)*" contains=@javaHtml,javaCommentStar,javaTodo,javaCommentError,javaSpaceError,@Spell,javaDocTags,javaDocSeeTag,javaDocCodeTag,javaDocSnippetTag
|
||||
syn region javaDocTags contained start="{@\%(li\%(teral\|nk\%(plain\)\=\)\|inherit[Dd]oc\|doc[rR]oot\|value\)\>" end="}"
|
||||
syn match javaDocTags contained "@\%(param\|exception\|throws\|since\)\s\+\S\+" contains=javaDocParam
|
||||
syn match javaDocParam contained "\s\S\+"
|
||||
syn match javaDocTags contained "@\%(version\|author\|return\|deprecated\|serial\%(Field\|Data\)\=\)\>"
|
||||
syn region javaDocSeeTag contained matchgroup=javaDocTags start="@see\s\+" matchgroup=NONE end="\_."re=e-1 contains=javaDocSeeTagParam
|
||||
syn match javaDocSeeTagParam contained @"\_[^"]\+"\|<a\s\+\_.\{-}</a>\|\%(\k\|\.\)*\%(#\k\+\%((\_[^)]*)\)\=\)\=@ contains=@javaHtml extend
|
||||
syn region 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'
|
||||
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 javaCommentTitle contained matchgroup=javaDocComment start="/\*\*\s*\r\=\n\=\s*\**\s*\%({@summary\>\)\@=" matchgroup=javaCommentTitle end="}" contains=@javaHtml,javaCommentStar,javaTodo,javaCommentError,javaSpaceError,@Spell,@javaDocTags,javaTitleSkipBlock
|
||||
" The members of javaDocTags are sub-grouped according to the Java
|
||||
" version of their introduction, and sub-group members in turn are
|
||||
" arranged in alphabetical order, so that future newer members can
|
||||
" be pre-sorted and appended without disturbing the current member
|
||||
" 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 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'
|
||||
syn region javaSnippetSkipBlock contained transparent start="{\%(@snippet\>\)\@!" end="}" contains=javaSnippetSkipBlock,javaDocSnippetTag,javaCommentMarkupTag
|
||||
syn region javaDocSnippetTag contained start="{@snippet\>" end="}" contains=javaDocSnippetTag,javaSnippetSkipBlock,javaDocSnippetTagAttr,javaCommentMarkupTag
|
||||
|
||||
syntax case match
|
||||
hi def link javaDocComment Comment
|
||||
hi def link javaDocSeeTagStar javaDocComment
|
||||
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 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
|
||||
|
||||
" match the special comment /**/
|
||||
@ -586,7 +663,7 @@ hi def link javaStorageClass StorageClass
|
||||
hi def link javaMethodDecl javaStorageClass
|
||||
hi def link javaClassDecl javaStorageClass
|
||||
hi def link javaScopeDecl javaStorageClass
|
||||
hi def link javaConceptKind NonText
|
||||
hi def link javaConceptKind javaStorageClass
|
||||
|
||||
hi def link javaBoolean Boolean
|
||||
hi def link javaSpecial Special
|
||||
|
@ -4,6 +4,7 @@
|
||||
" Maintainer: Igor Gnatenko i.gnatenko.brain@gmail.com
|
||||
" Former Maintainer: Donovan Rebbechi elflord@panix.com (until March 2014)
|
||||
" Last Change: 2020 May 25
|
||||
" 2024 Sep 10 by Vim Project: add file triggers support, #15569
|
||||
|
||||
" quit when a syntax file was already loaded
|
||||
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
|
||||
|
||||
"%% 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 %%
|
||||
syn region specChangelogArea matchgroup=specSection start='^%changelog' end='^%'me=e-1 contains=specEmail,specURL,specWeekday,specMonth,specNumber,specComment,specLicense
|
||||
|
@ -685,7 +685,7 @@ if !exists("g:vimsyn_noerror") && !exists("g:vimsyn_novimfunctionerror")
|
||||
syn match vimBufnrWarn /\<bufnr\s*(\s*["']\.['"]\s*)/
|
||||
endif
|
||||
|
||||
syn match vimNotFunc "\<if\>\|\<el\%[seif]\>\|\<retu\%[rn]\>\|\<while\>" skipwhite nextgroup=vimOper,vimOperParen,vimVar,vimFunc,vimNotation
|
||||
syn match vimNotFunc "\<if\>\|\<el\%[seif]\>\|\<retu\%[rn]\>\|\<while\>" skipwhite nextgroup=@vimExprList,vimNotation
|
||||
|
||||
" Match: {{{2
|
||||
" =====
|
||||
|
@ -81,6 +81,14 @@ local function get_dependency(dependency_name)
|
||||
repo = 'luvit/luv',
|
||||
symbol = 'LUV',
|
||||
},
|
||||
['unibilium'] = {
|
||||
repo = 'neovim/unibilium',
|
||||
symbol = 'UNIBILIUM',
|
||||
},
|
||||
['utf8proc'] = {
|
||||
repo = 'JuliaStrings/utf8proc',
|
||||
symbol = 'UTF8PROC',
|
||||
},
|
||||
['tree-sitter'] = {
|
||||
repo = 'tree-sitter/tree-sitter',
|
||||
symbol = 'TREESITTER',
|
||||
@ -90,11 +98,11 @@ local function get_dependency(dependency_name)
|
||||
symbol = 'TREESITTER_C',
|
||||
},
|
||||
['tree-sitter-lua'] = {
|
||||
repo = 'MunifTanjim/tree-sitter-lua',
|
||||
repo = 'tree-sitter-grammars/tree-sitter-lua',
|
||||
symbol = 'TREESITTER_LUA',
|
||||
},
|
||||
['tree-sitter-vim'] = {
|
||||
repo = 'neovim/tree-sitter-vim',
|
||||
repo = 'tree-sitter-grammars/tree-sitter-vim',
|
||||
symbol = 'TREESITTER_VIM',
|
||||
},
|
||||
['tree-sitter-vimdoc'] = {
|
||||
@ -102,9 +110,21 @@ local function get_dependency(dependency_name)
|
||||
symbol = 'TREESITTER_VIMDOC',
|
||||
},
|
||||
['tree-sitter-query'] = {
|
||||
repo = 'nvim-treesitter/tree-sitter-query',
|
||||
repo = 'tree-sitter-grammars/tree-sitter-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]
|
||||
if dependency == nil then
|
||||
|
@ -786,7 +786,7 @@ local function parse_buf(fname, parser_path)
|
||||
if parser_path then
|
||||
vim.treesitter.language.add('vimdoc', { path = parser_path })
|
||||
end
|
||||
local lang_tree = vim.treesitter.get_parser(buf)
|
||||
local lang_tree = assert(vim.treesitter._get_parser(buf), 'vimdoc parser not found.')
|
||||
return lang_tree, buf
|
||||
end
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
fun:uv_spawn
|
||||
fun:libuv_process_spawn
|
||||
fun:process_spawn
|
||||
fun:libuv_proc_spawn
|
||||
fun:proc_spawn
|
||||
fun:job_start
|
||||
}
|
||||
|
@ -848,7 +848,7 @@ def CheckIncludes(filename, lines, error):
|
||||
or filename.endswith('.in.h')
|
||||
or FileInfo(filename).RelativePath() in {
|
||||
'func_attr.h',
|
||||
'os/pty_process.h',
|
||||
'os/pty_proc.h',
|
||||
}):
|
||||
return
|
||||
|
||||
@ -869,7 +869,7 @@ def CheckIncludes(filename, lines, error):
|
||||
"src/nvim/msgpack_rpc/unpacker.h",
|
||||
"src/nvim/option.h",
|
||||
"src/nvim/os/pty_conpty_win.h",
|
||||
"src/nvim/os/pty_process_win.h",
|
||||
"src/nvim/os/pty_proc_win.h",
|
||||
]
|
||||
|
||||
skip_headers = [
|
||||
|
@ -417,10 +417,10 @@ list(SORT NVIM_HEADERS)
|
||||
|
||||
foreach(sfile ${NVIM_SOURCES})
|
||||
get_filename_component(f ${sfile} NAME)
|
||||
if(WIN32 AND ${f} MATCHES "^(pty_process_unix.c)$")
|
||||
if(WIN32 AND ${f} MATCHES "^(pty_proc_unix.c)$")
|
||||
list(REMOVE_ITEM NVIM_SOURCES ${sfile})
|
||||
endif()
|
||||
if(NOT WIN32 AND ${f} MATCHES "^(pty_process_win.c)$")
|
||||
if(NOT WIN32 AND ${f} MATCHES "^(pty_proc_win.c)$")
|
||||
list(REMOVE_ITEM NVIM_SOURCES ${sfile})
|
||||
endif()
|
||||
if(NOT WIN32 AND ${f} MATCHES "^(pty_conpty_win.c)$")
|
||||
@ -436,7 +436,7 @@ foreach(hfile ${NVIM_HEADERS})
|
||||
if(WIN32 AND ${f} MATCHES "^(unix_defs.h)$")
|
||||
list(REMOVE_ITEM NVIM_HEADERS ${hfile})
|
||||
endif()
|
||||
if(WIN32 AND ${f} MATCHES "^(pty_process_unix.h)$")
|
||||
if(WIN32 AND ${f} MATCHES "^(pty_proc_unix.h)$")
|
||||
list(REMOVE_ITEM NVIM_HEADERS ${hfile})
|
||||
endif()
|
||||
if(NOT WIN32 AND ${f} MATCHES "^(win_defs.h)$")
|
||||
@ -832,12 +832,12 @@ find_program(CLANG_TIDY_PRG clang-tidy)
|
||||
set(EXCLUDE_CLANG_TIDY typval_encode.c.h ui_events.in.h)
|
||||
if(WIN32)
|
||||
list(APPEND EXCLUDE_CLANG_TIDY
|
||||
os/pty_process_unix.h
|
||||
os/pty_proc_unix.h
|
||||
os/unix_defs.h)
|
||||
else()
|
||||
list(APPEND EXCLUDE_CLANG_TIDY
|
||||
os/win_defs.h
|
||||
os/pty_process_win.h
|
||||
os/pty_proc_win.h
|
||||
os/pty_conpty_win.h
|
||||
os/os_win_console.h)
|
||||
endif()
|
||||
|
@ -70,7 +70,7 @@
|
||||
#include "nvim/optionstr.h"
|
||||
#include "nvim/os/input.h"
|
||||
#include "nvim/os/os_defs.h"
|
||||
#include "nvim/os/process.h"
|
||||
#include "nvim/os/proc.h"
|
||||
#include "nvim/popupmenu.h"
|
||||
#include "nvim/pos_defs.h"
|
||||
#include "nvim/runtime.h"
|
||||
|
@ -3338,7 +3338,7 @@ void maketitle(void)
|
||||
|
||||
#define SPACE_FOR_FNAME (sizeof(buf) - 100)
|
||||
#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;
|
||||
if (curbuf->b_fname == NULL) {
|
||||
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)));
|
||||
|
||||
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) {
|
||||
// Make it shorter by removing a bit in the middle.
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/event/loop.h"
|
||||
#include "nvim/event/multiqueue.h"
|
||||
#include "nvim/event/process.h"
|
||||
#include "nvim/event/proc.h"
|
||||
#include "nvim/event/rstream.h"
|
||||
#include "nvim/event/socket.h"
|
||||
#include "nvim/event/stream.h"
|
||||
@ -88,7 +88,7 @@ void channel_free_all_mem(void)
|
||||
bool channel_close(uint64_t id, ChannelPart part, const char **error)
|
||||
{
|
||||
Channel *chan;
|
||||
Process *proc;
|
||||
Proc *proc;
|
||||
|
||||
const char *dummy;
|
||||
if (!error) {
|
||||
@ -139,8 +139,8 @@ bool channel_close(uint64_t id, ChannelPart part, const char **error)
|
||||
if (part == kChannelPartStderr || part == kChannelPartAll) {
|
||||
rstream_may_close(&proc->err);
|
||||
}
|
||||
if (proc->type == kProcessTypePty && part == kChannelPartAll) {
|
||||
pty_process_close_master(&chan->stream.pty);
|
||||
if (proc->type == kProcTypePty && part == kChannelPartAll) {
|
||||
pty_proc_close_master(&chan->stream.pty);
|
||||
}
|
||||
|
||||
break;
|
||||
@ -289,7 +289,7 @@ static void channel_destroy(Channel *chan)
|
||||
}
|
||||
|
||||
if (chan->streamtype == kChannelStreamProc) {
|
||||
process_free(&chan->stream.proc);
|
||||
proc_free(&chan->stream.proc);
|
||||
}
|
||||
|
||||
callback_reader_free(&chan->on_data);
|
||||
@ -376,7 +376,7 @@ Channel *channel_job_start(char **argv, const char *exepath, CallbackReader on_s
|
||||
*status_out = 0;
|
||||
return NULL;
|
||||
}
|
||||
chan->stream.pty = pty_process_init(&main_loop, chan);
|
||||
chan->stream.pty = pty_proc_init(&main_loop, chan);
|
||||
if (pty_width > 0) {
|
||||
chan->stream.pty.width = pty_width;
|
||||
}
|
||||
@ -384,22 +384,22 @@ Channel *channel_job_start(char **argv, const char *exepath, CallbackReader on_s
|
||||
chan->stream.pty.height = pty_height;
|
||||
}
|
||||
} else {
|
||||
chan->stream.uv = libuv_process_init(&main_loop, chan);
|
||||
chan->stream.uv = libuv_proc_init(&main_loop, chan);
|
||||
}
|
||||
|
||||
Process *proc = &chan->stream.proc;
|
||||
Proc *proc = &chan->stream.proc;
|
||||
proc->argv = argv;
|
||||
proc->exepath = exepath;
|
||||
proc->cb = channel_process_exit_cb;
|
||||
proc->cb = channel_proc_exit_cb;
|
||||
proc->events = chan->events;
|
||||
proc->detach = detach;
|
||||
proc->cwd = cwd;
|
||||
proc->env = env;
|
||||
proc->overlapped = overlapped;
|
||||
|
||||
char *cmd = xstrdup(process_get_exepath(proc));
|
||||
char *cmd = xstrdup(proc_get_exepath(proc));
|
||||
bool has_out, has_err;
|
||||
if (proc->type == kProcessTypePty) {
|
||||
if (proc->type == kProcTypePty) {
|
||||
has_out = true;
|
||||
has_err = false;
|
||||
} else {
|
||||
@ -410,7 +410,7 @@ Channel *channel_job_start(char **argv, const char *exepath, CallbackReader on_s
|
||||
|
||||
bool has_in = stdin_mode == kChannelStdinPipe;
|
||||
|
||||
int status = process_spawn(proc, has_in, has_out, has_err);
|
||||
int status = proc_spawn(proc, has_in, has_out, has_err);
|
||||
if (status) {
|
||||
semsg(_(e_jobspawn), os_strerror(status), cmd);
|
||||
xfree(cmd);
|
||||
@ -760,7 +760,7 @@ void channel_reader_callbacks(Channel *chan, CallbackReader *reader)
|
||||
}
|
||||
}
|
||||
|
||||
static void channel_process_exit_cb(Process *proc, int status, void *data)
|
||||
static void channel_proc_exit_cb(Proc *proc, int status, void *data)
|
||||
{
|
||||
Channel *chan = data;
|
||||
if (chan->term) {
|
||||
@ -847,7 +847,7 @@ static void term_write(const char *buf, size_t size, void *data)
|
||||
static void term_resize(uint16_t width, uint16_t height, void *data)
|
||||
{
|
||||
Channel *chan = data;
|
||||
pty_process_resize(&chan->stream.pty, width, height);
|
||||
pty_proc_resize(&chan->stream.pty, width, height);
|
||||
}
|
||||
|
||||
static inline void term_delayed_free(void **argv)
|
||||
@ -867,7 +867,7 @@ static inline void term_delayed_free(void **argv)
|
||||
static void term_close(void *data)
|
||||
{
|
||||
Channel *chan = data;
|
||||
process_stop(&chan->stream.proc);
|
||||
proc_stop(&chan->stream.proc);
|
||||
multiqueue_put(chan->events, term_delayed_free, data);
|
||||
}
|
||||
|
||||
@ -907,7 +907,7 @@ bool channel_job_running(uint64_t id)
|
||||
Channel *chan = find_channel(id);
|
||||
return (chan
|
||||
&& chan->streamtype == kChannelStreamProc
|
||||
&& !process_is_stopped(&chan->stream.proc));
|
||||
&& !proc_is_stopped(&chan->stream.proc));
|
||||
}
|
||||
|
||||
Dictionary channel_info(uint64_t id, Arena *arena)
|
||||
@ -924,8 +924,8 @@ Dictionary channel_info(uint64_t id, Arena *arena)
|
||||
switch (chan->streamtype) {
|
||||
case kChannelStreamProc: {
|
||||
stream_desc = "job";
|
||||
if (chan->stream.proc.type == kProcessTypePty) {
|
||||
const char *name = pty_process_tty_name(&chan->stream.pty);
|
||||
if (chan->stream.proc.type == kProcTypePty) {
|
||||
const char *name = pty_proc_tty_name(&chan->stream.pty);
|
||||
PUT_C(info, "pty", CSTR_TO_ARENA_OBJ(arena, name));
|
||||
}
|
||||
|
||||
|
@ -7,11 +7,11 @@
|
||||
#include "nvim/channel_defs.h" // IWYU pragma: keep
|
||||
#include "nvim/eval/typval_defs.h"
|
||||
#include "nvim/event/defs.h"
|
||||
#include "nvim/event/libuv_process.h"
|
||||
#include "nvim/event/libuv_proc.h"
|
||||
#include "nvim/macros_defs.h"
|
||||
#include "nvim/map_defs.h"
|
||||
#include "nvim/msgpack_rpc/channel_defs.h"
|
||||
#include "nvim/os/pty_process.h"
|
||||
#include "nvim/os/pty_proc.h"
|
||||
#include "nvim/types_defs.h"
|
||||
|
||||
struct Channel {
|
||||
@ -21,9 +21,9 @@ struct Channel {
|
||||
|
||||
ChannelStreamType streamtype;
|
||||
union {
|
||||
Process proc;
|
||||
LibuvProcess uv;
|
||||
PtyProcess pty;
|
||||
Proc proc;
|
||||
LibuvProc uv;
|
||||
PtyProc pty;
|
||||
RStream socket;
|
||||
StdioPair stdio;
|
||||
StderrState err;
|
||||
|
@ -170,28 +170,26 @@ static void margin_columns_win(win_T *wp, int *left_col, int *right_col)
|
||||
// cache previous calculations depending on w_virtcol
|
||||
static int saved_w_virtcol;
|
||||
static win_T *prev_wp;
|
||||
static int prev_width1;
|
||||
static int prev_width2;
|
||||
static int prev_left_col;
|
||||
static int prev_right_col;
|
||||
static int prev_col_off;
|
||||
|
||||
int cur_col_off = win_col_off(wp);
|
||||
int width1;
|
||||
int width2;
|
||||
int width1 = wp->w_width_inner - cur_col_off;
|
||||
int width2 = width1 + win_col_off2(wp);
|
||||
|
||||
if (saved_w_virtcol == wp->w_virtcol && prev_wp == wp
|
||||
&& prev_col_off == cur_col_off) {
|
||||
&& prev_width1 == width1 && prev_width2 == width2) {
|
||||
*right_col = prev_right_col;
|
||||
*left_col = prev_left_col;
|
||||
return;
|
||||
}
|
||||
|
||||
width1 = wp->w_width_inner - cur_col_off;
|
||||
width2 = width1 + win_col_off2(wp);
|
||||
|
||||
*left_col = 0;
|
||||
*right_col = width1;
|
||||
|
||||
if (wp->w_virtcol >= (colnr_T)width1) {
|
||||
if (wp->w_virtcol >= (colnr_T)width1 && width2 > 0) {
|
||||
*right_col = width1 + ((wp->w_virtcol - width1) / width2 + 1) * width2;
|
||||
}
|
||||
if (wp->w_virtcol >= (colnr_T)width1 && width2 > 0) {
|
||||
@ -202,8 +200,9 @@ static void margin_columns_win(win_T *wp, int *left_col, int *right_col)
|
||||
prev_left_col = *left_col;
|
||||
prev_right_col = *right_col;
|
||||
prev_wp = wp;
|
||||
prev_width1 = width1;
|
||||
prev_width2 = width2;
|
||||
saved_w_virtcol = wp->w_virtcol;
|
||||
prev_col_off = cur_col_off;
|
||||
}
|
||||
|
||||
/// Put a single char from an UTF-8 buffer into a line buffer.
|
||||
|
@ -32,7 +32,7 @@
|
||||
#include "nvim/eval/vars.h"
|
||||
#include "nvim/event/loop.h"
|
||||
#include "nvim/event/multiqueue.h"
|
||||
#include "nvim/event/process.h"
|
||||
#include "nvim/event/proc.h"
|
||||
#include "nvim/event/time.h"
|
||||
#include "nvim/ex_cmds.h"
|
||||
#include "nvim/ex_docmd.h"
|
||||
@ -8506,7 +8506,7 @@ Channel *find_job(uint64_t id, bool show_error)
|
||||
{
|
||||
Channel *data = find_channel(id);
|
||||
if (!data || data->streamtype != kChannelStreamProc
|
||||
|| process_is_stopped(&data->stream.proc)) {
|
||||
|| proc_is_stopped(&data->stream.proc)) {
|
||||
if (show_error) {
|
||||
if (data && data->streamtype != kChannelStreamProc) {
|
||||
emsg(_(e_invchanjob));
|
||||
|
@ -8044,7 +8044,7 @@ M.funcs = {
|
||||
|
||||
]=],
|
||||
name = 'prompt_getprompt',
|
||||
params = { { 'buf', 'any' } },
|
||||
params = { { 'buf', 'integer|string' } },
|
||||
signature = 'prompt_getprompt({buf})',
|
||||
},
|
||||
prompt_setcallback = {
|
||||
@ -8084,7 +8084,7 @@ M.funcs = {
|
||||
|
||||
]=],
|
||||
name = 'prompt_setcallback',
|
||||
params = { { 'buf', 'any' }, { 'expr', 'any' } },
|
||||
params = { { 'buf', 'integer|string' }, { 'expr', 'string|function' } },
|
||||
signature = 'prompt_setcallback({buf}, {expr})',
|
||||
},
|
||||
prompt_setinterrupt = {
|
||||
@ -8101,7 +8101,7 @@ M.funcs = {
|
||||
|
||||
]=],
|
||||
name = 'prompt_setinterrupt',
|
||||
params = { { 'buf', 'any' }, { 'expr', 'any' } },
|
||||
params = { { 'buf', 'integer|string' }, { 'expr', 'string|function' } },
|
||||
signature = 'prompt_setinterrupt({buf}, {expr})',
|
||||
},
|
||||
prompt_setprompt = {
|
||||
@ -8116,7 +8116,7 @@ M.funcs = {
|
||||
<
|
||||
]=],
|
||||
name = 'prompt_setprompt',
|
||||
params = { { 'buf', 'any' }, { 'text', 'any' } },
|
||||
params = { { 'buf', 'integer|string' }, { 'text', 'string' } },
|
||||
signature = 'prompt_setprompt({buf}, {text})',
|
||||
},
|
||||
pum_getpos = {
|
||||
@ -8927,6 +8927,9 @@ M.funcs = {
|
||||
The value must not be negative. A zero value is like not
|
||||
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
|
||||
cursor positioned on the start of a match. If it evaluates to
|
||||
non-zero this match is skipped. This can be used, for
|
||||
|
@ -49,7 +49,7 @@
|
||||
#include "nvim/event/defs.h"
|
||||
#include "nvim/event/loop.h"
|
||||
#include "nvim/event/multiqueue.h"
|
||||
#include "nvim/event/process.h"
|
||||
#include "nvim/event/proc.h"
|
||||
#include "nvim/event/time.h"
|
||||
#include "nvim/ex_cmds.h"
|
||||
#include "nvim/ex_cmds_defs.h"
|
||||
@ -101,7 +101,7 @@
|
||||
#include "nvim/os/fs.h"
|
||||
#include "nvim/os/os.h"
|
||||
#include "nvim/os/os_defs.h"
|
||||
#include "nvim/os/pty_process.h"
|
||||
#include "nvim/os/pty_proc.h"
|
||||
#include "nvim/os/shell.h"
|
||||
#include "nvim/os/stdpaths_defs.h"
|
||||
#include "nvim/os/time.h"
|
||||
@ -3770,7 +3770,7 @@ static void f_jobpid(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
return;
|
||||
}
|
||||
|
||||
Process *proc = &data->stream.proc;
|
||||
Proc *proc = &data->stream.proc;
|
||||
rettv->vval.v_number = proc->pid;
|
||||
}
|
||||
|
||||
@ -3796,12 +3796,12 @@ static void f_jobresize(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
return;
|
||||
}
|
||||
|
||||
if (data->stream.proc.type != kProcessTypePty) {
|
||||
if (data->stream.proc.type != kProcTypePty) {
|
||||
emsg(_(e_channotpty));
|
||||
return;
|
||||
}
|
||||
|
||||
pty_process_resize(&data->stream.pty, (uint16_t)argvars[1].vval.v_number,
|
||||
pty_proc_resize(&data->stream.pty, (uint16_t)argvars[1].vval.v_number,
|
||||
(uint16_t)argvars[2].vval.v_number);
|
||||
rettv->vval.v_number = 1;
|
||||
}
|
||||
@ -4077,7 +4077,7 @@ static void f_jobstop(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
// Ignore return code, but show error later.
|
||||
channel_close(data->id, kChannelPartRpc, &error);
|
||||
}
|
||||
process_stop(&data->stream.proc);
|
||||
proc_stop(&data->stream.proc);
|
||||
rettv->vval.v_number = 1;
|
||||
if (error) {
|
||||
emsg(error);
|
||||
@ -4113,10 +4113,10 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
|| !(chan = find_channel((uint64_t)TV_LIST_ITEM_TV(arg)->vval.v_number))
|
||||
|| chan->streamtype != kChannelStreamProc) {
|
||||
jobs[i] = NULL; // Invalid job.
|
||||
} else if (process_is_stopped(&chan->stream.proc)) {
|
||||
} else if (proc_is_stopped(&chan->stream.proc)) {
|
||||
// Job is stopped but not fully destroyed.
|
||||
// Ensure all callbacks on its event queue are executed. #15402
|
||||
process_wait(&chan->stream.proc, -1, NULL);
|
||||
proc_wait(&chan->stream.proc, -1, NULL);
|
||||
jobs[i] = NULL; // Invalid job.
|
||||
} else {
|
||||
jobs[i] = chan;
|
||||
@ -4144,7 +4144,7 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
if (jobs[i] == NULL) {
|
||||
continue; // Invalid job, will assign status=-3 below.
|
||||
}
|
||||
int status = process_wait(&jobs[i]->stream.proc, remaining,
|
||||
int status = proc_wait(&jobs[i]->stream.proc, remaining,
|
||||
waiting_jobs);
|
||||
if (status < 0) {
|
||||
break; // Interrupted (CTRL-C) or timeout, skip remaining jobs.
|
||||
@ -7641,7 +7641,7 @@ static void get_xdg_var_list(const XDGVarType xdg, typval_T *rettv)
|
||||
return;
|
||||
}
|
||||
const void *iter = NULL;
|
||||
const char *appname = get_appname();
|
||||
const char *appname = get_appname(false);
|
||||
do {
|
||||
size_t dir_len;
|
||||
const char *dir;
|
||||
@ -8207,7 +8207,7 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
return;
|
||||
}
|
||||
|
||||
int pid = chan->stream.pty.process.pid;
|
||||
int pid = chan->stream.pty.proc.pid;
|
||||
|
||||
// "./…" => "/home/foo/…"
|
||||
vim_FullName(cwd, NameBuff, sizeof(NameBuff), false);
|
||||
|
@ -142,30 +142,31 @@ struct socket_watcher {
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
kProcessTypeUv,
|
||||
kProcessTypePty,
|
||||
} ProcessType;
|
||||
kProcTypeUv,
|
||||
kProcTypePty,
|
||||
} ProcType;
|
||||
|
||||
typedef struct process Process;
|
||||
typedef void (*process_exit_cb)(Process *proc, int status, void *data);
|
||||
typedef void (*internal_process_cb)(Process *proc);
|
||||
/// OS process
|
||||
typedef struct proc Proc;
|
||||
typedef void (*proc_exit_cb)(Proc *proc, int status, void *data);
|
||||
typedef void (*internal_proc_cb)(Proc *proc);
|
||||
|
||||
struct process {
|
||||
ProcessType type;
|
||||
struct proc {
|
||||
ProcType type;
|
||||
Loop *loop;
|
||||
void *data;
|
||||
int pid, status, refcount;
|
||||
uint8_t exit_signal; // Signal used when killing (on Windows).
|
||||
uint64_t stopped_time; // process_stop() timestamp
|
||||
uint64_t stopped_time; // proc_stop() timestamp
|
||||
const char *cwd;
|
||||
char **argv;
|
||||
const char *exepath;
|
||||
dict_T *env;
|
||||
Stream in;
|
||||
RStream out, err;
|
||||
/// Exit handler. If set, user must call process_free().
|
||||
process_exit_cb cb;
|
||||
internal_process_cb internal_exit_cb, internal_close_cb;
|
||||
/// Exit handler. If set, user must call proc_free().
|
||||
proc_exit_cb cb;
|
||||
internal_proc_cb internal_exit_cb, internal_close_cb;
|
||||
bool closed, detach, overlapped, fwd_err;
|
||||
MultiQueue *events;
|
||||
};
|
||||
|
@ -5,9 +5,9 @@
|
||||
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/event/defs.h"
|
||||
#include "nvim/event/libuv_process.h"
|
||||
#include "nvim/event/libuv_proc.h"
|
||||
#include "nvim/event/loop.h"
|
||||
#include "nvim/event/process.h"
|
||||
#include "nvim/event/proc.h"
|
||||
#include "nvim/log.h"
|
||||
#include "nvim/os/os.h"
|
||||
#include "nvim/os/os_defs.h"
|
||||
@ -15,15 +15,15 @@
|
||||
#include "nvim/ui_client.h"
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "event/libuv_process.c.generated.h"
|
||||
# include "event/libuv_proc.c.generated.h"
|
||||
#endif
|
||||
|
||||
/// @returns zero on success, or negative error code
|
||||
int libuv_process_spawn(LibuvProcess *uvproc)
|
||||
int libuv_proc_spawn(LibuvProc *uvproc)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
Process *proc = (Process *)uvproc;
|
||||
uvproc->uvopts.file = process_get_exepath(proc);
|
||||
Proc *proc = (Proc *)uvproc;
|
||||
uvproc->uvopts.file = proc_get_exepath(proc);
|
||||
uvproc->uvopts.args = proc->argv;
|
||||
uvproc->uvopts.flags = UV_PROCESS_WINDOWS_HIDE;
|
||||
#ifdef MSWIN
|
||||
@ -101,7 +101,7 @@ int libuv_process_spawn(LibuvProcess *uvproc)
|
||||
return status;
|
||||
}
|
||||
|
||||
void libuv_process_close(LibuvProcess *uvproc)
|
||||
void libuv_proc_close(LibuvProc *uvproc)
|
||||
FUNC_ATTR_NONNULL_ARG(1)
|
||||
{
|
||||
uv_close((uv_handle_t *)&uvproc->uv, close_cb);
|
||||
@ -109,11 +109,11 @@ void libuv_process_close(LibuvProcess *uvproc)
|
||||
|
||||
static void close_cb(uv_handle_t *handle)
|
||||
{
|
||||
Process *proc = handle->data;
|
||||
Proc *proc = handle->data;
|
||||
if (proc->internal_close_cb) {
|
||||
proc->internal_close_cb(proc);
|
||||
}
|
||||
LibuvProcess *uvproc = (LibuvProcess *)proc;
|
||||
LibuvProc *uvproc = (LibuvProc *)proc;
|
||||
if (uvproc->uvopts.env) {
|
||||
os_free_fullenv(uvproc->uvopts.env);
|
||||
}
|
||||
@ -121,7 +121,7 @@ static void close_cb(uv_handle_t *handle)
|
||||
|
||||
static void exit_cb(uv_process_t *handle, int64_t status, int term_signal)
|
||||
{
|
||||
Process *proc = handle->data;
|
||||
Proc *proc = handle->data;
|
||||
#if defined(MSWIN)
|
||||
// Use stored/expected signal.
|
||||
term_signal = proc->exit_signal;
|
||||
@ -130,10 +130,10 @@ static void exit_cb(uv_process_t *handle, int64_t status, int term_signal)
|
||||
proc->internal_exit_cb(proc);
|
||||
}
|
||||
|
||||
LibuvProcess libuv_process_init(Loop *loop, void *data)
|
||||
LibuvProc libuv_proc_init(Loop *loop, void *data)
|
||||
{
|
||||
LibuvProcess rv = {
|
||||
.process = process_init(loop, kProcessTypeUv, data)
|
||||
LibuvProc rv = {
|
||||
.proc = proc_init(loop, kProcTypeUv, data)
|
||||
};
|
||||
return rv;
|
||||
}
|
@ -5,12 +5,12 @@
|
||||
#include "nvim/event/defs.h"
|
||||
|
||||
typedef struct {
|
||||
Process process;
|
||||
Proc proc;
|
||||
uv_process_t uv;
|
||||
uv_process_options_t uvopts;
|
||||
uv_stdio_container_t uvstdio[4];
|
||||
} LibuvProcess;
|
||||
} LibuvProc;
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "event/libuv_process.h.generated.h"
|
||||
# include "event/libuv_proc.h.generated.h"
|
||||
#endif
|
@ -16,15 +16,14 @@ struct loop {
|
||||
uv_loop_t uv;
|
||||
MultiQueue *events;
|
||||
MultiQueue *thread_events;
|
||||
// Immediate events:
|
||||
// "Processed after exiting uv_run() (to avoid recursion), but before
|
||||
// returning from loop_poll_events()." 502aee690c98
|
||||
// Practical consequence (for main_loop): these events are processed by
|
||||
// state_enter()..os_inchar()
|
||||
// whereas "regular" events (main_loop.events) are processed by
|
||||
// state_enter()..VimState.execute()
|
||||
// But state_enter()..os_inchar() can be "too early" if you want the event
|
||||
// to trigger UI updates and other user-activity-related side-effects.
|
||||
// Immediate events.
|
||||
// - "Processed after exiting `uv_run()` (to avoid recursion), but before returning from
|
||||
// `loop_poll_events()`." 502aee690c98
|
||||
// - Practical consequence (for `main_loop`):
|
||||
// - these are processed by `state_enter()..input_get()` whereas "regular" events
|
||||
// (`main_loop.events`) are processed by `state_enter()..VimState.execute()`
|
||||
// - `state_enter()..input_get()` can be "too early" if you want the event to trigger UI
|
||||
// updates and other user-activity-related side-effects.
|
||||
MultiQueue *fast_events;
|
||||
|
||||
// used by process/job-control subsystem
|
||||
|
@ -4,24 +4,24 @@
|
||||
#include <uv.h>
|
||||
|
||||
#include "klib/klist.h"
|
||||
#include "nvim/event/libuv_process.h"
|
||||
#include "nvim/event/libuv_proc.h"
|
||||
#include "nvim/event/loop.h"
|
||||
#include "nvim/event/multiqueue.h"
|
||||
#include "nvim/event/process.h"
|
||||
#include "nvim/event/proc.h"
|
||||
#include "nvim/event/rstream.h"
|
||||
#include "nvim/event/stream.h"
|
||||
#include "nvim/event/wstream.h"
|
||||
#include "nvim/globals.h"
|
||||
#include "nvim/log.h"
|
||||
#include "nvim/main.h"
|
||||
#include "nvim/os/process.h"
|
||||
#include "nvim/os/pty_process.h"
|
||||
#include "nvim/os/proc.h"
|
||||
#include "nvim/os/pty_proc.h"
|
||||
#include "nvim/os/shell.h"
|
||||
#include "nvim/os/time.h"
|
||||
#include "nvim/ui_client.h"
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "event/process.c.generated.h"
|
||||
# include "event/proc.c.generated.h"
|
||||
#endif
|
||||
|
||||
// Time for a process to exit cleanly before we send KILL.
|
||||
@ -33,13 +33,13 @@
|
||||
void __gcov_flush(void);
|
||||
#endif
|
||||
|
||||
static bool process_is_tearing_down = false;
|
||||
static bool proc_is_tearing_down = false;
|
||||
|
||||
// Delay exit until handles are closed, to avoid deadlocks
|
||||
static int exit_need_delay = 0;
|
||||
|
||||
/// @returns zero on success, or negative error code
|
||||
int process_spawn(Process *proc, bool in, bool out, bool err)
|
||||
int proc_spawn(Proc *proc, bool in, bool out, bool err)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
// forwarding stderr contradicts with processing it internally
|
||||
@ -70,11 +70,11 @@ int process_spawn(Process *proc, bool in, bool out, bool err)
|
||||
|
||||
int status;
|
||||
switch (proc->type) {
|
||||
case kProcessTypeUv:
|
||||
status = libuv_process_spawn((LibuvProcess *)proc);
|
||||
case kProcTypeUv:
|
||||
status = libuv_proc_spawn((LibuvProc *)proc);
|
||||
break;
|
||||
case kProcessTypePty:
|
||||
status = pty_process_spawn((PtyProcess *)proc);
|
||||
case kProcTypePty:
|
||||
status = pty_proc_spawn((PtyProc *)proc);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -89,12 +89,12 @@ int process_spawn(Process *proc, bool in, bool out, bool err)
|
||||
uv_close((uv_handle_t *)&proc->err.s.uv.pipe, NULL);
|
||||
}
|
||||
|
||||
if (proc->type == kProcessTypeUv) {
|
||||
uv_close((uv_handle_t *)&(((LibuvProcess *)proc)->uv), NULL);
|
||||
if (proc->type == kProcTypeUv) {
|
||||
uv_close((uv_handle_t *)&(((LibuvProc *)proc)->uv), NULL);
|
||||
} else {
|
||||
process_close(proc);
|
||||
proc_close(proc);
|
||||
}
|
||||
process_free(proc);
|
||||
proc_free(proc);
|
||||
proc->status = -1;
|
||||
return status;
|
||||
}
|
||||
@ -102,52 +102,52 @@ int process_spawn(Process *proc, bool in, bool out, bool err)
|
||||
if (in) {
|
||||
stream_init(NULL, &proc->in, -1, (uv_stream_t *)&proc->in.uv.pipe);
|
||||
proc->in.internal_data = proc;
|
||||
proc->in.internal_close_cb = on_process_stream_close;
|
||||
proc->in.internal_close_cb = on_proc_stream_close;
|
||||
proc->refcount++;
|
||||
}
|
||||
|
||||
if (out) {
|
||||
stream_init(NULL, &proc->out.s, -1, (uv_stream_t *)&proc->out.s.uv.pipe);
|
||||
proc->out.s.internal_data = proc;
|
||||
proc->out.s.internal_close_cb = on_process_stream_close;
|
||||
proc->out.s.internal_close_cb = on_proc_stream_close;
|
||||
proc->refcount++;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
stream_init(NULL, &proc->err.s, -1, (uv_stream_t *)&proc->err.s.uv.pipe);
|
||||
proc->err.s.internal_data = proc;
|
||||
proc->err.s.internal_close_cb = on_process_stream_close;
|
||||
proc->err.s.internal_close_cb = on_proc_stream_close;
|
||||
proc->refcount++;
|
||||
}
|
||||
|
||||
proc->internal_exit_cb = on_process_exit;
|
||||
proc->internal_exit_cb = on_proc_exit;
|
||||
proc->internal_close_cb = decref;
|
||||
proc->refcount++;
|
||||
kl_push(WatcherPtr, proc->loop->children, proc);
|
||||
DLOG("new: pid=%d exepath=[%s]", proc->pid, process_get_exepath(proc));
|
||||
DLOG("new: pid=%d exepath=[%s]", proc->pid, proc_get_exepath(proc));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void process_teardown(Loop *loop) FUNC_ATTR_NONNULL_ALL
|
||||
void proc_teardown(Loop *loop) FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
process_is_tearing_down = true;
|
||||
proc_is_tearing_down = true;
|
||||
kl_iter(WatcherPtr, loop->children, current) {
|
||||
Process *proc = (*current)->data;
|
||||
if (proc->detach || proc->type == kProcessTypePty) {
|
||||
Proc *proc = (*current)->data;
|
||||
if (proc->detach || proc->type == kProcTypePty) {
|
||||
// Close handles to process without killing it.
|
||||
CREATE_EVENT(loop->events, process_close_handles, proc);
|
||||
CREATE_EVENT(loop->events, proc_close_handles, proc);
|
||||
} else {
|
||||
process_stop(proc);
|
||||
proc_stop(proc);
|
||||
}
|
||||
}
|
||||
|
||||
// Wait until all children exit and all close events are processed.
|
||||
LOOP_PROCESS_EVENTS_UNTIL(loop, loop->events, -1,
|
||||
kl_empty(loop->children) && multiqueue_empty(loop->events));
|
||||
pty_process_teardown(loop);
|
||||
pty_proc_teardown(loop);
|
||||
}
|
||||
|
||||
void process_close_streams(Process *proc) FUNC_ATTR_NONNULL_ALL
|
||||
void proc_close_streams(Proc *proc) FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
wstream_may_close(&proc->in);
|
||||
rstream_may_close(&proc->out);
|
||||
@ -162,7 +162,7 @@ void process_close_streams(Process *proc) FUNC_ATTR_NONNULL_ALL
|
||||
/// @return Exit code of the process. proc->status will have the same value.
|
||||
/// -1 if the timeout expired while the process is still running.
|
||||
/// -2 if the user interrupted the wait.
|
||||
int process_wait(Process *proc, int ms, MultiQueue *events)
|
||||
int proc_wait(Proc *proc, int ms, MultiQueue *events)
|
||||
FUNC_ATTR_NONNULL_ARG(1)
|
||||
{
|
||||
if (!proc->refcount) {
|
||||
@ -186,7 +186,7 @@ int process_wait(Process *proc, int ms, MultiQueue *events)
|
||||
// Assume that a user hitting CTRL-C does not like the current job. Kill it.
|
||||
if (got_int) {
|
||||
got_int = false;
|
||||
process_stop(proc);
|
||||
proc_stop(proc);
|
||||
if (ms == -1) {
|
||||
// We can only return if all streams/handles are closed and the job
|
||||
// exited.
|
||||
@ -214,7 +214,7 @@ int process_wait(Process *proc, int ms, MultiQueue *events)
|
||||
}
|
||||
|
||||
/// Ask a process to terminate and eventually kill if it doesn't respond
|
||||
void process_stop(Process *proc) FUNC_ATTR_NONNULL_ALL
|
||||
void proc_stop(Proc *proc) FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
bool exited = (proc->status >= 0);
|
||||
if (exited || proc->stopped_time) {
|
||||
@ -224,13 +224,13 @@ void process_stop(Process *proc) FUNC_ATTR_NONNULL_ALL
|
||||
proc->exit_signal = SIGTERM;
|
||||
|
||||
switch (proc->type) {
|
||||
case kProcessTypeUv:
|
||||
case kProcTypeUv:
|
||||
os_proc_tree_kill(proc->pid, SIGTERM);
|
||||
break;
|
||||
case kProcessTypePty:
|
||||
case kProcTypePty:
|
||||
// close all streams for pty processes to send SIGHUP to the process
|
||||
process_close_streams(proc);
|
||||
pty_process_close_master((PtyProcess *)proc);
|
||||
proc_close_streams(proc);
|
||||
pty_proc_close_master((PtyProc *)proc);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -240,7 +240,7 @@ void process_stop(Process *proc) FUNC_ATTR_NONNULL_ALL
|
||||
}
|
||||
|
||||
/// Frees process-owned resources.
|
||||
void process_free(Process *proc) FUNC_ATTR_NONNULL_ALL
|
||||
void proc_free(Proc *proc) FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
if (proc->argv != NULL) {
|
||||
shell_free_argv(proc->argv);
|
||||
@ -249,19 +249,19 @@ void process_free(Process *proc) FUNC_ATTR_NONNULL_ALL
|
||||
}
|
||||
|
||||
/// Sends SIGKILL (or SIGTERM..SIGKILL for PTY jobs) to processes that did
|
||||
/// not terminate after process_stop().
|
||||
/// not terminate after proc_stop().
|
||||
static void children_kill_cb(uv_timer_t *handle)
|
||||
{
|
||||
Loop *loop = handle->loop->data;
|
||||
|
||||
kl_iter(WatcherPtr, loop->children, current) {
|
||||
Process *proc = (*current)->data;
|
||||
Proc *proc = (*current)->data;
|
||||
bool exited = (proc->status >= 0);
|
||||
if (exited || !proc->stopped_time) {
|
||||
continue;
|
||||
}
|
||||
uint64_t term_sent = UINT64_MAX == proc->stopped_time;
|
||||
if (kProcessTypePty != proc->type || term_sent) {
|
||||
if (kProcTypePty != proc->type || term_sent) {
|
||||
proc->exit_signal = SIGKILL;
|
||||
os_proc_tree_kill(proc->pid, SIGKILL);
|
||||
} else {
|
||||
@ -275,19 +275,19 @@ static void children_kill_cb(uv_timer_t *handle)
|
||||
}
|
||||
}
|
||||
|
||||
static void process_close_event(void **argv)
|
||||
static void proc_close_event(void **argv)
|
||||
{
|
||||
Process *proc = argv[0];
|
||||
Proc *proc = argv[0];
|
||||
if (proc->cb) {
|
||||
// User (hint: channel_job_start) is responsible for calling
|
||||
// process_free().
|
||||
// proc_free().
|
||||
proc->cb(proc, proc->status, proc->data);
|
||||
} else {
|
||||
process_free(proc);
|
||||
proc_free(proc);
|
||||
}
|
||||
}
|
||||
|
||||
static void decref(Process *proc)
|
||||
static void decref(Proc *proc)
|
||||
{
|
||||
if (--proc->refcount != 0) {
|
||||
return;
|
||||
@ -303,13 +303,13 @@ static void decref(Process *proc)
|
||||
}
|
||||
assert(node);
|
||||
kl_shift_at(WatcherPtr, loop->children, node);
|
||||
CREATE_EVENT(proc->events, process_close_event, proc);
|
||||
CREATE_EVENT(proc->events, proc_close_event, proc);
|
||||
}
|
||||
|
||||
static void process_close(Process *proc)
|
||||
static void proc_close(Proc *proc)
|
||||
FUNC_ATTR_NONNULL_ARG(1)
|
||||
{
|
||||
if (process_is_tearing_down && (proc->detach || proc->type == kProcessTypePty)
|
||||
if (proc_is_tearing_down && (proc->detach || proc->type == kProcTypePty)
|
||||
&& proc->closed) {
|
||||
// If a detached/pty process dies while tearing down it might get closed
|
||||
// twice.
|
||||
@ -319,17 +319,17 @@ static void process_close(Process *proc)
|
||||
proc->closed = true;
|
||||
|
||||
if (proc->detach) {
|
||||
if (proc->type == kProcessTypeUv) {
|
||||
uv_unref((uv_handle_t *)&(((LibuvProcess *)proc)->uv));
|
||||
if (proc->type == kProcTypeUv) {
|
||||
uv_unref((uv_handle_t *)&(((LibuvProc *)proc)->uv));
|
||||
}
|
||||
}
|
||||
|
||||
switch (proc->type) {
|
||||
case kProcessTypeUv:
|
||||
libuv_process_close((LibuvProcess *)proc);
|
||||
case kProcTypeUv:
|
||||
libuv_proc_close((LibuvProc *)proc);
|
||||
break;
|
||||
case kProcessTypePty:
|
||||
pty_process_close((PtyProcess *)proc);
|
||||
case kProcTypePty:
|
||||
pty_proc_close((PtyProc *)proc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -338,7 +338,7 @@ static void process_close(Process *proc)
|
||||
///
|
||||
/// @param proc Process, for which an output stream should be flushed.
|
||||
/// @param stream Stream to flush.
|
||||
static void flush_stream(Process *proc, RStream *stream)
|
||||
static void flush_stream(Proc *proc, RStream *stream)
|
||||
FUNC_ATTR_NONNULL_ARG(1)
|
||||
{
|
||||
if (!stream || stream->s.closed) {
|
||||
@ -382,16 +382,16 @@ static void flush_stream(Process *proc, RStream *stream)
|
||||
}
|
||||
}
|
||||
|
||||
static void process_close_handles(void **argv)
|
||||
static void proc_close_handles(void **argv)
|
||||
{
|
||||
Process *proc = argv[0];
|
||||
Proc *proc = argv[0];
|
||||
|
||||
exit_need_delay++;
|
||||
flush_stream(proc, &proc->out);
|
||||
flush_stream(proc, &proc->err);
|
||||
|
||||
process_close_streams(proc);
|
||||
process_close(proc);
|
||||
proc_close_streams(proc);
|
||||
proc_close(proc);
|
||||
exit_need_delay--;
|
||||
}
|
||||
|
||||
@ -426,7 +426,7 @@ void exit_from_channel(int status)
|
||||
multiqueue_put(main_loop.fast_events, exit_event, (void *)(intptr_t)status);
|
||||
}
|
||||
|
||||
static void on_process_exit(Process *proc)
|
||||
static void on_proc_exit(Proc *proc)
|
||||
{
|
||||
Loop *loop = proc->loop;
|
||||
ILOG("exited: pid=%d status=%d stoptime=%" PRIu64, proc->pid, proc->status,
|
||||
@ -439,13 +439,13 @@ static void on_process_exit(Process *proc)
|
||||
// Process has terminated, but there could still be data to be read from the
|
||||
// OS. We are still in the libuv loop, so we cannot call code that polls for
|
||||
// more data directly. Instead delay the reading after the libuv loop by
|
||||
// queueing process_close_handles() as an event.
|
||||
// queueing proc_close_handles() as an event.
|
||||
MultiQueue *queue = proc->events ? proc->events : loop->events;
|
||||
CREATE_EVENT(queue, process_close_handles, proc);
|
||||
CREATE_EVENT(queue, proc_close_handles, proc);
|
||||
}
|
||||
|
||||
static void on_process_stream_close(Stream *stream, void *data)
|
||||
static void on_proc_stream_close(Stream *stream, void *data)
|
||||
{
|
||||
Process *proc = data;
|
||||
Proc *proc = data;
|
||||
decref(proc);
|
||||
}
|
@ -6,9 +6,9 @@
|
||||
#include "nvim/event/defs.h" // IWYU pragma: keep
|
||||
#include "nvim/types_defs.h"
|
||||
|
||||
static inline Process process_init(Loop *loop, ProcessType type, void *data)
|
||||
static inline Proc proc_init(Loop *loop, ProcType type, void *data)
|
||||
{
|
||||
return (Process) {
|
||||
return (Proc) {
|
||||
.type = type,
|
||||
.data = data,
|
||||
.loop = loop,
|
||||
@ -33,17 +33,17 @@ static inline Process process_init(Loop *loop, ProcessType type, void *data)
|
||||
}
|
||||
|
||||
/// Get the path to the executable of the process.
|
||||
static inline const char *process_get_exepath(Process *proc)
|
||||
static inline const char *proc_get_exepath(Proc *proc)
|
||||
{
|
||||
return proc->exepath != NULL ? proc->exepath : proc->argv[0];
|
||||
}
|
||||
|
||||
static inline bool process_is_stopped(Process *proc)
|
||||
static inline bool proc_is_stopped(Proc *proc)
|
||||
{
|
||||
bool exited = (proc->status >= 0);
|
||||
return exited || (proc->stopped_time != 0);
|
||||
}
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "event/process.h.generated.h"
|
||||
# include "event/proc.h.generated.h"
|
||||
#endif
|
@ -94,14 +94,17 @@ void stream_init(Loop *loop, Stream *stream, int fd, uv_stream_t *uvstream)
|
||||
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)
|
||||
{
|
||||
if (stream->closed) {
|
||||
return;
|
||||
}
|
||||
assert(!stream->closed);
|
||||
DLOG("closing Stream: %p", (void *)stream);
|
||||
stream->closed = true;
|
||||
stream->close_cb = on_stream_close;
|
||||
stream->close_cb_data = data;
|
||||
stream->close_cb = NULL;
|
||||
stream->close_cb_data = NULL;
|
||||
|
||||
#ifdef MSWIN
|
||||
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)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
|
@ -3264,18 +3264,12 @@ static void vim_mktempdir(void)
|
||||
char tmp[TEMP_FILE_PATH_MAXLEN];
|
||||
char path[TEMP_FILE_PATH_MAXLEN];
|
||||
char user[40] = { 0 };
|
||||
char appname[40] = { 0 };
|
||||
|
||||
os_get_username(user, sizeof(user));
|
||||
// Usernames may contain slashes! #19240
|
||||
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.
|
||||
// "repl" has been reported to use "0177".
|
||||
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_env((char *)temp_dirs[i], tmp, TEMP_FILE_PATH_MAXLEN - 64);
|
||||
if (!os_isdir(tmp)) {
|
||||
if (strequal("$TMPDIR", temp_dirs[i])) {
|
||||
WLOG("$TMPDIR tempdir not a directory (or does not exist): %s", tmp);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// "/tmp/" exists, now try to create "/tmp/nvim.<user>/".
|
||||
add_pathsep(tmp);
|
||||
|
||||
xstrlcat(tmp, appname, sizeof(tmp));
|
||||
xstrlcat(tmp, ".", sizeof(tmp));
|
||||
xstrlcat(tmp, "nvim.", sizeof(tmp));
|
||||
xstrlcat(tmp, user, sizeof(tmp));
|
||||
os_mkdir(tmp, 0700); // Always create, to avoid a race.
|
||||
bool owned = os_file_owned(tmp);
|
||||
|
@ -1858,7 +1858,7 @@ static void getchar_common(typval_T *argvars, typval_T *rettv)
|
||||
if (!char_avail()) {
|
||||
// Flush screen updates before blocking.
|
||||
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)) {
|
||||
state_handle_k_event();
|
||||
continue;
|
||||
@ -2981,7 +2981,7 @@ int inchar(uint8_t *buf, int maxlen, long wait_time)
|
||||
uint8_t dum[DUM_LEN + 1];
|
||||
|
||||
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)) {
|
||||
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
|
||||
// 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
|
||||
|
@ -370,12 +370,15 @@ void update_window_hl(win_T *wp, bool invalid)
|
||||
|
||||
// determine window specific background set in 'winhighlight'
|
||||
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];
|
||||
} else if (hl_def[HLF_COUNT] > 0) {
|
||||
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 {
|
||||
wp->w_hl_attr_normal = float_win ? HL_ATTR(HLF_NFLOAT) : 0;
|
||||
wp->w_hl_attr_normal = 0;
|
||||
}
|
||||
|
||||
if (wp->w_floating) {
|
||||
|
@ -37,7 +37,7 @@
|
||||
/// @param[in] str Prompt: question to ask user. Is always followed by
|
||||
/// " (y/n)?".
|
||||
/// @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
|
||||
/// 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
|
||||
// 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) {
|
||||
// Replace zero and K_SPECIAL by a special key code.
|
||||
n = fix_input_buffer(buf + len, n);
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "nvim/os/stdpaths_defs.h"
|
||||
#include "nvim/os/time.h"
|
||||
#include "nvim/path.h"
|
||||
#include "nvim/ui_client.h"
|
||||
|
||||
/// Cached location of the expanded log file path decided by log_path_init().
|
||||
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;
|
||||
}
|
||||
|
||||
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.
|
||||
// TODO(justinmk): expose this as v:name ?
|
||||
if (name[0] == NUL) {
|
||||
// Parent servername.
|
||||
if (regen) {
|
||||
// Parent servername ($NVIM).
|
||||
const char *parent = path_tail(os_getenv(ENV_NVIM));
|
||||
// Servername. Empty until starting=false.
|
||||
const char *serv = path_tail(get_vim_var_str(VV_SEND_SERVER));
|
||||
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) {
|
||||
snprintf(name, sizeof(name), "%s", serv);
|
||||
snprintf(name, sizeof(name), ui ? "ui/%s" : "%s", serv);
|
||||
} else {
|
||||
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,
|
||||
(context == NULL ? "" : context),
|
||||
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) {
|
||||
return false;
|
||||
|
@ -43,7 +43,7 @@
|
||||
#include "nvim/eval/userfunc.h"
|
||||
#include "nvim/event/loop.h"
|
||||
#include "nvim/event/multiqueue.h"
|
||||
#include "nvim/event/process.h"
|
||||
#include "nvim/event/proc.h"
|
||||
#include "nvim/event/stream.h"
|
||||
#include "nvim/ex_cmds.h"
|
||||
#include "nvim/ex_docmd.h"
|
||||
@ -174,7 +174,7 @@ bool event_teardown(void)
|
||||
loop_poll_events(&main_loop, 0); // Drain thread_events, fast_events.
|
||||
input_stop();
|
||||
channel_teardown();
|
||||
process_teardown(&main_loop);
|
||||
proc_teardown(&main_loop);
|
||||
timer_teardown();
|
||||
server_teardown();
|
||||
signal_teardown();
|
||||
@ -266,7 +266,7 @@ int main(int argc, char **argv)
|
||||
|
||||
if (argc > 1 && STRICMP(argv[1], "-ll") == 0) {
|
||||
if (argc == 2) {
|
||||
print_mainerr(err_arg_missing, argv[1]);
|
||||
print_mainerr(err_arg_missing, argv[1], NULL);
|
||||
exit(1);
|
||||
}
|
||||
nlua_run_script(argv, argc, 3);
|
||||
@ -357,10 +357,8 @@ int main(int argc, char **argv)
|
||||
assert(!ui_client_channel_id && !use_builtin_ui);
|
||||
// Nvim server...
|
||||
|
||||
int listen_rv = server_init(params.listen_addr);
|
||||
if (listen_rv != 0) {
|
||||
mainerr("Failed to --listen", listen_rv < 0
|
||||
? os_strerror(listen_rv) : (listen_rv == 1 ? "empty address" : NULL));
|
||||
if (!server_init(params.listen_addr)) {
|
||||
mainerr(IObuff, NULL, NULL);
|
||||
}
|
||||
|
||||
TIME_MSG("expanding arguments");
|
||||
@ -1053,7 +1051,7 @@ static void command_line_scan(mparm_T *parmp)
|
||||
// "+" or "+{number}" or "+/{pat}" or "+{command}" argument.
|
||||
if (argv[0][0] == '+' && !had_minmin) {
|
||||
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
|
||||
if (argv[0][1] == NUL) {
|
||||
@ -1074,7 +1072,7 @@ static void command_line_scan(mparm_T *parmp)
|
||||
parmp->no_swap_file = true;
|
||||
} else {
|
||||
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->edit_type = EDIT_STDIN;
|
||||
@ -1137,7 +1135,7 @@ static void command_line_scan(mparm_T *parmp)
|
||||
nlua_disable_preload = true;
|
||||
} else {
|
||||
if (argv[0][argv_idx]) {
|
||||
mainerr(err_opt_unknown, argv[0]);
|
||||
mainerr(err_opt_unknown, argv[0], NULL);
|
||||
}
|
||||
had_minmin = true;
|
||||
}
|
||||
@ -1211,7 +1209,7 @@ static void command_line_scan(mparm_T *parmp)
|
||||
break;
|
||||
case 'q': // "-q" QuickFix mode
|
||||
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;
|
||||
if (argv[0][argv_idx]) { // "-q{errorfile}"
|
||||
@ -1240,7 +1238,7 @@ static void command_line_scan(mparm_T *parmp)
|
||||
break;
|
||||
case 't': // "-t {tag}" or "-t{tag}" jump to tag
|
||||
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;
|
||||
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
|
||||
if (argv[0][argv_idx] != NUL) {
|
||||
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;
|
||||
argv_idx = -1;
|
||||
@ -1291,19 +1289,19 @@ static void command_line_scan(mparm_T *parmp)
|
||||
break;
|
||||
|
||||
default:
|
||||
mainerr(err_opt_unknown, argv[0]);
|
||||
mainerr(err_opt_unknown, argv[0], NULL);
|
||||
}
|
||||
|
||||
// Handle option arguments with argument.
|
||||
if (want_argument) {
|
||||
// Check for garbage immediately after the option letter.
|
||||
if (argv[0][argv_idx] != NUL) {
|
||||
mainerr(err_opt_garbage, argv[0]);
|
||||
mainerr(err_opt_garbage, argv[0], NULL);
|
||||
}
|
||||
|
||||
argc--;
|
||||
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_idx = -1;
|
||||
@ -1312,7 +1310,7 @@ static void command_line_scan(mparm_T *parmp)
|
||||
case 'c': // "-c {command}" execute command
|
||||
case 'S': // "-S {file}" execute Vim script
|
||||
if (parmp->n_commands >= MAX_ARG_CMDS) {
|
||||
mainerr(err_extra_cmd, NULL);
|
||||
mainerr(err_extra_cmd, NULL, NULL);
|
||||
}
|
||||
if (c == 'S') {
|
||||
char *a;
|
||||
@ -1343,7 +1341,7 @@ static void command_line_scan(mparm_T *parmp)
|
||||
if (strequal(argv[-1], "--cmd")) {
|
||||
// "--cmd {command}" execute command
|
||||
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];
|
||||
} else if (strequal(argv[-1], "--listen")) {
|
||||
@ -1425,7 +1423,7 @@ scripterror:
|
||||
|
||||
// Check for only one type of editing.
|
||||
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;
|
||||
|
||||
@ -1472,7 +1470,7 @@ scripterror:
|
||||
}
|
||||
|
||||
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.
|
||||
@ -2135,28 +2133,30 @@ static int execute_env(char *env)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/// Prints the following then exits:
|
||||
/// - An error message `errstr`
|
||||
/// - A string `str` if not null
|
||||
/// Prints a message of the form "{msg1}: {msg2}: {msg3}", then exits with code 1.
|
||||
///
|
||||
/// @param errstr string containing an error message
|
||||
/// @param str string to append to the primary error message, or NULL
|
||||
static void mainerr(const char *errstr, const char *str)
|
||||
/// @param msg1 error message
|
||||
/// @param msg2 extra message, or NULL
|
||||
/// @param msg3 extra message, or NULL
|
||||
static void mainerr(const char *msg1, const char *msg2, const char *msg3)
|
||||
FUNC_ATTR_NORETURN
|
||||
{
|
||||
print_mainerr(errstr, str);
|
||||
print_mainerr(msg1, msg2, msg3);
|
||||
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);
|
||||
|
||||
signal_stop(); // kill us with CTRL-C here, if you like
|
||||
|
||||
fprintf(stderr, "%s: %s", prgname, _(errstr));
|
||||
if (str != NULL) {
|
||||
fprintf(stderr, ": \"%s\"", str);
|
||||
fprintf(stderr, "%s: %s", prgname, _(msg1));
|
||||
if (msg2 != NULL) {
|
||||
fprintf(stderr, ": \"%s\"", msg2);
|
||||
}
|
||||
if (msg3 != NULL) {
|
||||
fprintf(stderr, ": \"%s\"", msg3);
|
||||
}
|
||||
fprintf(stderr, _("\nMore info with \""));
|
||||
fprintf(stderr, "%s -h\"\n", prgname);
|
||||
@ -2207,7 +2207,7 @@ static void usage(void)
|
||||
printf(_(" --headless Don't start a user interface\n"));
|
||||
printf(_(" --listen <address> Serve RPC API from this address\n"));
|
||||
printf(_(" --remote[-subcommand] Execute commands remotely on a server\n"));
|
||||
printf(_(" --server <address> Specify RPC server to send commands to\n"));
|
||||
printf(_(" --server <address> Connect to this Nvim server\n"));
|
||||
printf(_(" --startuptime <file> Write startup timing messages to <file>\n"));
|
||||
printf(_("\nSee \":help startup-options\" for all options.\n"));
|
||||
}
|
||||
|
@ -84,7 +84,7 @@
|
||||
#include "nvim/os/input.h"
|
||||
#include "nvim/os/os.h"
|
||||
#include "nvim/os/os_defs.h"
|
||||
#include "nvim/os/process.h"
|
||||
#include "nvim/os/proc.h"
|
||||
#include "nvim/os/time.h"
|
||||
#include "nvim/os/time_defs.h"
|
||||
#include "nvim/path.h"
|
||||
@ -743,7 +743,7 @@ static void add_b0_fenc(ZeroBlock *b0p, buf_T *buf)
|
||||
/// @param swap_fname Name of the swapfile. If it's from before a reboot, the result is 0.
|
||||
///
|
||||
/// @return PID, or 0 if process is not running or the swapfile is from before a reboot.
|
||||
static int swapfile_process_running(const ZeroBlock *b0p, const char *swap_fname)
|
||||
static int swapfile_proc_running(const ZeroBlock *b0p, const char *swap_fname)
|
||||
{
|
||||
FileInfo st;
|
||||
double uptime;
|
||||
@ -1214,7 +1214,7 @@ void ml_recover(bool checkext)
|
||||
msg(_("Recovery completed. Buffer contents equals file contents."), 0);
|
||||
}
|
||||
msg_puts(_("\nYou may want to delete the .swp file now."));
|
||||
if (swapfile_process_running(b0p, fname_used)) {
|
||||
if (swapfile_proc_running(b0p, fname_used)) {
|
||||
// Warn there could be an active Vim on the same file, the user may
|
||||
// want to kill it.
|
||||
msg_puts(_("\nNote: process STILL RUNNING: "));
|
||||
@ -1462,7 +1462,7 @@ char *make_percent_swname(char *dir, char *dir_end, const char *name)
|
||||
}
|
||||
|
||||
// PID of swapfile owner, or zero if not running.
|
||||
static int process_running;
|
||||
static int proc_running;
|
||||
|
||||
/// For Vimscript "swapinfo()".
|
||||
///
|
||||
@ -1488,7 +1488,7 @@ void swapfile_dict(const char *fname, dict_T *d)
|
||||
tv_dict_add_str_len(d, S_LEN("fname"), b0.b0_fname,
|
||||
B0_FNAME_SIZE_ORG);
|
||||
|
||||
tv_dict_add_nr(d, S_LEN("pid"), swapfile_process_running(&b0, fname));
|
||||
tv_dict_add_nr(d, S_LEN("pid"), swapfile_proc_running(&b0, fname));
|
||||
tv_dict_add_nr(d, S_LEN("mtime"), char_to_long(b0.b0_mtime));
|
||||
tv_dict_add_nr(d, S_LEN("dirty"), b0.b0_dirty ? 1 : 0);
|
||||
tv_dict_add_nr(d, S_LEN("inode"), char_to_long(b0.b0_ino));
|
||||
@ -1572,7 +1572,7 @@ static time_t swapfile_info(char *fname)
|
||||
if (char_to_long(b0.b0_pid) != 0) {
|
||||
msg_puts(_("\n process ID: "));
|
||||
msg_outnum((int)char_to_long(b0.b0_pid));
|
||||
if ((process_running = swapfile_process_running(&b0, fname))) {
|
||||
if ((proc_running = swapfile_proc_running(&b0, fname))) {
|
||||
msg_puts(_(" (STILL RUNNING)"));
|
||||
}
|
||||
}
|
||||
@ -1640,7 +1640,7 @@ static bool swapfile_unchanged(char *fname)
|
||||
}
|
||||
|
||||
// process must be known and not running.
|
||||
if (char_to_long(b0.b0_pid) == 0 || swapfile_process_running(&b0, fname)) {
|
||||
if (char_to_long(b0.b0_pid) == 0 || swapfile_proc_running(&b0, fname)) {
|
||||
ret = false;
|
||||
}
|
||||
|
||||
@ -3399,7 +3399,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
|
||||
fd = os_open(fname, O_RDONLY, 0);
|
||||
if (fd >= 0) {
|
||||
if (read_eintr(fd, &b0, sizeof(b0)) == sizeof(b0)) {
|
||||
process_running = swapfile_process_running(&b0, fname);
|
||||
proc_running = swapfile_proc_running(&b0, fname);
|
||||
|
||||
// If the swapfile has the same directory as the
|
||||
// buffer don't compare the directory names, they can
|
||||
@ -3459,7 +3459,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
|
||||
choice = SEA_CHOICE_READONLY;
|
||||
}
|
||||
|
||||
process_running = 0; // Set by attention_message..swapfile_info.
|
||||
proc_running = 0; // Set by attention_message..swapfile_info.
|
||||
if (choice == SEA_CHOICE_NONE) {
|
||||
// Show info about the existing swapfile.
|
||||
attention_message(buf, fname);
|
||||
@ -3491,12 +3491,12 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
|
||||
= do_dialog(VIM_WARNING,
|
||||
_("VIM - ATTENTION"),
|
||||
name,
|
||||
process_running
|
||||
proc_running
|
||||
? _("&Open Read-Only\n&Edit anyway\n&Recover\n&Quit\n&Abort")
|
||||
: _("&Open Read-Only\n&Edit anyway\n&Recover\n&Delete it\n&Quit\n&Abort"),
|
||||
1, NULL, false);
|
||||
|
||||
if (process_running && dialog_result >= 4) {
|
||||
if (proc_running && dialog_result >= 4) {
|
||||
// compensate for missing "Delete it" button
|
||||
dialog_result++;
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
#include "nvim/event/defs.h"
|
||||
#include "nvim/event/loop.h"
|
||||
#include "nvim/event/multiqueue.h"
|
||||
#include "nvim/event/process.h"
|
||||
#include "nvim/event/proc.h"
|
||||
#include "nvim/event/rstream.h"
|
||||
#include "nvim/event/wstream.h"
|
||||
#include "nvim/globals.h"
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
/// 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
|
||||
/// 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);
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
|
@ -11,12 +11,14 @@
|
||||
#include "nvim/event/socket.h"
|
||||
#include "nvim/garray.h"
|
||||
#include "nvim/garray_defs.h"
|
||||
#include "nvim/globals.h"
|
||||
#include "nvim/log.h"
|
||||
#include "nvim/main.h"
|
||||
#include "nvim/memory.h"
|
||||
#include "nvim/msgpack_rpc/server.h"
|
||||
#include "nvim/os/os.h"
|
||||
#include "nvim/os/stdpaths_defs.h"
|
||||
#include "nvim/types_defs.h"
|
||||
|
||||
#define MAX_CONNECTIONS 32
|
||||
#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"
|
||||
#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.
|
||||
int server_init(const char *listen_addr)
|
||||
/// @returns true on success, false on fatal error (message stored in IObuff)
|
||||
bool server_init(const char *listen_addr)
|
||||
{
|
||||
bool ok = true;
|
||||
bool must_free = false;
|
||||
TriState user_arg = kTrue; // User-provided --listen arg.
|
||||
ga_init(&watchers, sizeof(SocketWatcher *), 1);
|
||||
|
||||
// $NVIM_LISTEN_ADDRESS (deprecated)
|
||||
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);
|
||||
}
|
||||
|
||||
if (!listen_addr || listen_addr[0] == '\0') {
|
||||
user_arg = kNone; // Autogenerated server address.
|
||||
listen_addr = server_address_new(NULL);
|
||||
must_free = true;
|
||||
}
|
||||
|
||||
if (!listen_addr) {
|
||||
abort(); // Cannot happen.
|
||||
}
|
||||
|
||||
int rv = server_start(listen_addr);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// TODO(justinmk): this is for logging_spec. Can remove this after nvim_log #7062 is merged.
|
||||
// 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");
|
||||
}
|
||||
@ -66,7 +62,28 @@ int server_init(const 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
|
||||
@ -97,17 +114,19 @@ void server_teardown(void)
|
||||
/// - Windows: "\\.\pipe\<name>.<pid>.<counter>"
|
||||
/// - Other: "/tmp/nvim.user/xxx/<name>.<pid>.<counter>"
|
||||
char *server_address_new(const char *name)
|
||||
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_RET
|
||||
{
|
||||
static uint32_t count = 0;
|
||||
char fmt[ADDRESS_MAX_SIZE];
|
||||
const char *appname = get_appname();
|
||||
#ifdef MSWIN
|
||||
(void)get_appname(true);
|
||||
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
|
||||
char *dir = stdpaths_get_xdg_var(kXDGRuntimeDir);
|
||||
(void)get_appname(true);
|
||||
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);
|
||||
#endif
|
||||
if ((size_t)r >= sizeof(fmt)) {
|
||||
|
@ -6597,11 +6597,11 @@ static void nv_open(cmdarg_T *cap)
|
||||
static void nv_event(cmdarg_T *cap)
|
||||
{
|
||||
// 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
|
||||
// `os_inchar` branch was not executed (!multiqueue_empty(loop.events), which
|
||||
// the `input_get` in `state_enter`, but we also disable it here in case the
|
||||
// `input_get` branch was not executed (!multiqueue_empty(loop.events), which
|
||||
// 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
|
||||
// not safe to perform garbage collection because there could be unreferenced
|
||||
// lists or dicts being used.
|
||||
|
@ -210,39 +210,53 @@ static void set_init_default_backupskip(void)
|
||||
OptIndex opt_idx = kOptBackupskip;
|
||||
|
||||
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;
|
||||
char *p;
|
||||
size_t plen;
|
||||
#ifdef UNIX
|
||||
if (*names[n] == NUL) {
|
||||
if (*names[i] == NUL) {
|
||||
# ifdef __APPLE__
|
||||
p = "/private/tmp";
|
||||
plen = STRLEN_LITERAL("/private/tmp");
|
||||
# else
|
||||
p = "/tmp";
|
||||
plen = STRLEN_LITERAL("/tmp");
|
||||
# endif
|
||||
mustfree = false;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
p = vim_getenv(names[n]);
|
||||
p = vim_getenv(names[i]);
|
||||
plen = 0; // will be calcuated below
|
||||
}
|
||||
if (p != NULL && *p != NUL) {
|
||||
// First time count the NUL, otherwise count the ','.
|
||||
const size_t len = strlen(p) + 3;
|
||||
char *item = xmalloc(len);
|
||||
xstrlcpy(item, p, len);
|
||||
add_pathsep(item);
|
||||
xstrlcat(item, "*", len);
|
||||
if (find_dup_item(ga.ga_data, item, options[opt_idx].flags)
|
||||
== NULL) {
|
||||
ga_grow(&ga, (int)len);
|
||||
if (!GA_EMPTY(&ga)) {
|
||||
strcat(ga.ga_data, ",");
|
||||
bool has_trailing_path_sep = false;
|
||||
|
||||
if (plen == 0) {
|
||||
// the value was retrieved from the environment
|
||||
plen = strlen(p);
|
||||
// does the value include a trailing path separator?
|
||||
if (after_pathsep(p, p + plen)) {
|
||||
has_trailing_path_sep = true;
|
||||
}
|
||||
strcat(ga.ga_data, p);
|
||||
add_pathsep(ga.ga_data);
|
||||
strcat(ga.ga_data, "*");
|
||||
ga.ga_len += (int)len;
|
||||
}
|
||||
|
||||
// item size needs to be large enough to include "/*" and a trailing NUL
|
||||
// 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);
|
||||
}
|
||||
@ -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
|
||||
/// "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)
|
||||
{
|
||||
if (origval == NULL) {
|
||||
@ -535,11 +550,10 @@ static char *find_dup_item(char *origval, const char *newval, uint32_t flags)
|
||||
|
||||
int bs = 0;
|
||||
|
||||
const size_t newlen = strlen(newval);
|
||||
for (char *s = origval; *s != NUL; s++) {
|
||||
if ((!(flags & P_COMMA) || s == origval || (s[-1] == ',' && !(bs & 1)))
|
||||
&& strncmp(s, newval, newlen) == 0
|
||||
&& (!(flags & P_COMMA) || s[newlen] == ',' || s[newlen] == NUL)) {
|
||||
&& strncmp(s, newval, newvallen) == 0
|
||||
&& (!(flags & P_COMMA) || s[newvallen] == ',' || s[newvallen] == NUL)) {
|
||||
return s;
|
||||
}
|
||||
// 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);
|
||||
// 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[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"
|
||||
p_hlg[0] = 'e';
|
||||
p_hlg[1] = 'n';
|
||||
@ -950,7 +964,7 @@ static char *stropt_get_newval(int nextchar, OptIndex opt_idx, char **argp, void
|
||||
int len = 0;
|
||||
if (op == OP_REMOVING || (flags & P_NODUP)) {
|
||||
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
|
||||
if ((op == OP_ADDING || op == OP_PREPENDING) && s != NULL) {
|
||||
@ -1464,11 +1478,10 @@ int do_set(char *arg, int opt_flags)
|
||||
}
|
||||
|
||||
if (errmsg != NULL) {
|
||||
xstrlcpy(IObuff, _(errmsg), IOSIZE);
|
||||
int i = (int)strlen(IObuff) + 2;
|
||||
int i = vim_snprintf((char *)IObuff, IOSIZE, "%s", _(errmsg)) + 2;
|
||||
if (i + (arg - startarg) < IOSIZE) {
|
||||
// append the argument with the error
|
||||
xstrlcat(IObuff, ": ", IOSIZE);
|
||||
xstrlcpy(IObuff + i - 2, ": ", (size_t)(IOSIZE - i + 2));
|
||||
assert(arg >= startarg);
|
||||
memmove(IObuff + i, startarg, (size_t)(arg - startarg));
|
||||
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;
|
||||
return;
|
||||
}
|
||||
char *p = arg + strlen(arg) - 1;
|
||||
char *const argend = arg + strlen(arg);
|
||||
char *p = argend - 1;
|
||||
if (*p == ' ' && *(p - 1) != '\\') {
|
||||
xp->xp_pattern = p + 1;
|
||||
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
|
||||
// delimited by space.
|
||||
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 ','
|
||||
if (*p == ' ' || *p == ',' || (*p == ':' && (flags & P_COLON))) {
|
||||
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
|
||||
// at the end as we don't complete words.
|
||||
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
|
||||
@ -5952,7 +5966,7 @@ int ExpandSettingSubtract(expand_T *xp, regmatch_T *regmatch, int *numMatches, c
|
||||
|
||||
int count = 0;
|
||||
|
||||
(*matches)[count++] = xstrdup(option_val);
|
||||
(*matches)[count++] = xmemdupz(option_val, num_flags);
|
||||
|
||||
if (num_flags > 1) {
|
||||
// If more than one flags, split the flags up and expose each
|
||||
|
@ -9047,7 +9047,7 @@ return {
|
||||
desc = [=[
|
||||
When on, the title of the window will be set to the value of
|
||||
'titlestring' (if it is not empty), or to:
|
||||
filename [+=-] (path) - NVIM
|
||||
filename [+=-] (path) - Nvim
|
||||
Where:
|
||||
filename the name of the file being edited
|
||||
- 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 and modified
|
||||
(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',
|
||||
scope = { 'global' },
|
||||
short_desc = N_('Vim set the title of the window'),
|
||||
short_desc = N_('set the title of the window'),
|
||||
type = 'boolean',
|
||||
varname = 'p_title',
|
||||
},
|
||||
|
@ -344,7 +344,7 @@ char *os_getenvname_at_index(size_t index)
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Get the process ID of the Neovim process.
|
||||
/// Get the process ID of the Nvim process.
|
||||
///
|
||||
/// @return the process ID.
|
||||
int64_t os_get_pid(void)
|
||||
|
@ -33,12 +33,6 @@
|
||||
#define READ_BUFFER_SIZE 0xfff
|
||||
#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 char input_buffer[INPUT_BUFFER_SIZE];
|
||||
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)
|
||||
{
|
||||
// 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
|
||||
// `state_check` callback for the states where it can be triggered.
|
||||
assert(!events_enabled || multiqueue_empty(main_loop.events));
|
||||
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_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
|
||||
/// until `events` is non-empty.
|
||||
int os_inchar(uint8_t *buf, int maxlen, int ms, int tb_change_cnt, MultiQueue *events)
|
||||
/// - Consumes available input received from the OS.
|
||||
/// - Consumes pending 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.
|
||||
if (tb_change_cnt != cursorhold_tb_change_cnt) {
|
||||
restart_cursorhold_wait(tb_change_cnt);
|
||||
reset_cursorhold_wait(tb_change_cnt);
|
||||
}
|
||||
|
||||
if (maxlen && input_available()) {
|
||||
restart_cursorhold_wait(tb_change_cnt);
|
||||
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;
|
||||
}
|
||||
#define TRY_READ() \
|
||||
do { \
|
||||
if (maxlen && input_available()) { \
|
||||
reset_cursorhold_wait(tb_change_cnt); \
|
||||
assert(maxlen >= 0); \
|
||||
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.
|
||||
if ((mapped_ctrl_c | curbuf->b_mapped_ctrl_c) & get_real_state()) {
|
||||
ctrl_c_interrupts = false;
|
||||
}
|
||||
|
||||
InbufPollResult result;
|
||||
TriState result; ///< inbuf_poll result.
|
||||
if (ms >= 0) {
|
||||
if ((result = inbuf_poll(ms, events)) == kInputNone) {
|
||||
if ((result = inbuf_poll(ms, events)) == kFalse) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
uint64_t wait_start = os_hrtime();
|
||||
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) {
|
||||
// Drained eventloop & initial input; exit silent/batch-mode (-es/-Es).
|
||||
read_error_exit();
|
||||
}
|
||||
restart_cursorhold_wait(tb_change_cnt);
|
||||
reset_cursorhold_wait(tb_change_cnt);
|
||||
if (trigger_cursorhold() && !typebuf_changed(tb_change_cnt)) {
|
||||
create_cursorhold_event(events == main_loop.events);
|
||||
} else {
|
||||
@ -153,32 +166,26 @@ int os_inchar(uint8_t *buf, int maxlen, int ms, int tb_change_cnt, MultiQueue *e
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (maxlen && input_available()) {
|
||||
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;
|
||||
}
|
||||
TRY_READ();
|
||||
|
||||
// If there are events, return the keys directly
|
||||
if (maxlen && pending_events(events)) {
|
||||
return push_event_key(buf, maxlen);
|
||||
}
|
||||
|
||||
if (result == kInputEof) {
|
||||
if (result == kNone) {
|
||||
read_error_exit();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
#undef TRY_READ
|
||||
}
|
||||
|
||||
// Check if a character is available for reading
|
||||
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.
|
||||
@ -463,15 +470,22 @@ bool input_blocking(void)
|
||||
return blocking;
|
||||
}
|
||||
|
||||
// This is a replacement for the old `WaitForChar` function in os_unix.c
|
||||
static InbufPollResult inbuf_poll(int ms, MultiQueue *events)
|
||||
/// Checks for (but does not read) available input, and consumes `main_loop.events` while waiting.
|
||||
///
|
||||
/// @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)) {
|
||||
return kInputAvail;
|
||||
return kTrue;
|
||||
}
|
||||
|
||||
if (do_profiling == PROF_YES && ms) {
|
||||
prof_inchar_enter();
|
||||
prof_input_start();
|
||||
}
|
||||
|
||||
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;
|
||||
multiqueue_process_events(ch_before_blocking_events);
|
||||
}
|
||||
DLOG("blocking... events_enabled=%d events_pending=%d", events != NULL,
|
||||
events && !multiqueue_empty(events));
|
||||
LOOP_PROCESS_EVENTS_UNTIL(&main_loop, NULL, ms,
|
||||
os_input_ready(events) || input_eof);
|
||||
DLOG("blocking... events=%s", !!events ? "true" : "false");
|
||||
LOOP_PROCESS_EVENTS_UNTIL(&main_loop, NULL, ms, os_input_ready(events) || input_eof);
|
||||
blocking = false;
|
||||
|
||||
if (do_profiling == PROF_YES && ms) {
|
||||
prof_inchar_exit();
|
||||
prof_input_end();
|
||||
}
|
||||
|
||||
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)
|
||||
@ -533,8 +545,8 @@ static void process_ctrl_c(void)
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function used to push bytes from the 'event' key sequence partially
|
||||
// between calls to os_inchar when maxlen < 3
|
||||
/// Pushes bytes from the "event" key sequence (KE_EVENT) partially between calls to input_get when
|
||||
/// `maxlen < 3`.
|
||||
static int push_event_key(uint8_t *buf, int maxlen)
|
||||
{
|
||||
static const uint8_t key[3] = { K_SPECIAL, KS_EXTRA, KE_EVENT };
|
||||
|
@ -37,24 +37,24 @@
|
||||
|
||||
#include "nvim/log.h"
|
||||
#include "nvim/memory.h"
|
||||
#include "nvim/os/process.h"
|
||||
#include "nvim/os/proc.h"
|
||||
|
||||
#ifdef MSWIN
|
||||
# include "nvim/api/private/helpers.h"
|
||||
#endif
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "os/process.c.generated.h"
|
||||
# include "os/proc.c.generated.h"
|
||||
#endif
|
||||
|
||||
#ifdef MSWIN
|
||||
static bool os_proc_tree_kill_rec(HANDLE process, int sig)
|
||||
static bool os_proc_tree_kill_rec(HANDLE proc, int sig)
|
||||
{
|
||||
if (process == NULL) {
|
||||
if (proc == NULL) {
|
||||
return false;
|
||||
}
|
||||
PROCESSENTRY32 pe;
|
||||
DWORD pid = GetProcessId(process);
|
||||
DWORD pid = GetProcessId(proc);
|
||||
|
||||
if (pid != 0) {
|
||||
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
@ -77,7 +77,7 @@ static bool os_proc_tree_kill_rec(HANDLE process, int sig)
|
||||
}
|
||||
|
||||
theend:
|
||||
return (bool)TerminateProcess(process, (unsigned)sig);
|
||||
return (bool)TerminateProcess(proc, (unsigned)sig);
|
||||
}
|
||||
/// Kills process `pid` and its descendants recursively.
|
||||
bool os_proc_tree_kill(int pid, int sig)
|
@ -7,5 +7,5 @@
|
||||
#endif
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "os/process.h.generated.h"
|
||||
# include "os/proc.h.generated.h"
|
||||
#endif
|
@ -143,7 +143,7 @@ finished:
|
||||
return conpty_object;
|
||||
}
|
||||
|
||||
bool os_conpty_spawn(conpty_t *conpty_object, HANDLE *process_handle, wchar_t *name,
|
||||
bool os_conpty_spawn(conpty_t *conpty_object, HANDLE *proc_handle, wchar_t *name,
|
||||
wchar_t *cmd_line, wchar_t *cwd, wchar_t *env)
|
||||
{
|
||||
PROCESS_INFORMATION pi = { 0 };
|
||||
@ -159,7 +159,7 @@ bool os_conpty_spawn(conpty_t *conpty_object, HANDLE *process_handle, wchar_t *n
|
||||
&pi)) {
|
||||
return false;
|
||||
}
|
||||
*process_handle = pi.hProcess;
|
||||
*proc_handle = pi.hProcess;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
7
src/nvim/os/pty_proc.h
Normal file
7
src/nvim/os/pty_proc.h
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef MSWIN
|
||||
# include "nvim/os/pty_proc_win.h"
|
||||
#else
|
||||
# include "nvim/os/pty_proc_unix.h"
|
||||
#endif
|
@ -34,16 +34,16 @@
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/event/defs.h"
|
||||
#include "nvim/event/loop.h"
|
||||
#include "nvim/event/process.h"
|
||||
#include "nvim/event/proc.h"
|
||||
#include "nvim/log.h"
|
||||
#include "nvim/os/fs.h"
|
||||
#include "nvim/os/os_defs.h"
|
||||
#include "nvim/os/pty_process.h"
|
||||
#include "nvim/os/pty_process_unix.h"
|
||||
#include "nvim/os/pty_proc.h"
|
||||
#include "nvim/os/pty_proc_unix.h"
|
||||
#include "nvim/types_defs.h"
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "os/pty_process_unix.c.generated.h"
|
||||
# include "os/pty_proc_unix.c.generated.h"
|
||||
#endif
|
||||
|
||||
#if defined(__sun) && !defined(HAVE_FORKPTY)
|
||||
@ -158,7 +158,7 @@ static pid_t forkpty(int *amaster, char *name, struct termios *termp, struct win
|
||||
#endif
|
||||
|
||||
/// @returns zero on success, or negative error code
|
||||
int pty_process_spawn(PtyProcess *ptyproc)
|
||||
int pty_proc_spawn(PtyProc *ptyproc)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
// termios initialized at first use
|
||||
@ -168,7 +168,7 @@ int pty_process_spawn(PtyProcess *ptyproc)
|
||||
}
|
||||
|
||||
int status = 0; // zero or negative error code (libuv convention)
|
||||
Process *proc = (Process *)ptyproc;
|
||||
Proc *proc = (Proc *)ptyproc;
|
||||
assert(proc->err.s.closed);
|
||||
uv_signal_start(&proc->loop->children_watcher, chld_handler, SIGCHLD);
|
||||
ptyproc->winsize = (struct winsize){ ptyproc->height, ptyproc->width, 0, 0 };
|
||||
@ -224,29 +224,29 @@ error:
|
||||
return status;
|
||||
}
|
||||
|
||||
const char *pty_process_tty_name(PtyProcess *ptyproc)
|
||||
const char *pty_proc_tty_name(PtyProc *ptyproc)
|
||||
{
|
||||
return ptsname(ptyproc->tty_fd);
|
||||
}
|
||||
|
||||
void pty_process_resize(PtyProcess *ptyproc, uint16_t width, uint16_t height)
|
||||
void pty_proc_resize(PtyProc *ptyproc, uint16_t width, uint16_t height)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
ptyproc->winsize = (struct winsize){ height, width, 0, 0 };
|
||||
ioctl(ptyproc->tty_fd, TIOCSWINSZ, &ptyproc->winsize);
|
||||
}
|
||||
|
||||
void pty_process_close(PtyProcess *ptyproc)
|
||||
void pty_proc_close(PtyProc *ptyproc)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
pty_process_close_master(ptyproc);
|
||||
Process *proc = (Process *)ptyproc;
|
||||
pty_proc_close_master(ptyproc);
|
||||
Proc *proc = (Proc *)ptyproc;
|
||||
if (proc->internal_close_cb) {
|
||||
proc->internal_close_cb(proc);
|
||||
}
|
||||
}
|
||||
|
||||
void pty_process_close_master(PtyProcess *ptyproc) FUNC_ATTR_NONNULL_ALL
|
||||
void pty_proc_close_master(PtyProc *ptyproc) FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
if (ptyproc->tty_fd >= 0) {
|
||||
close(ptyproc->tty_fd);
|
||||
@ -254,12 +254,12 @@ void pty_process_close_master(PtyProcess *ptyproc) FUNC_ATTR_NONNULL_ALL
|
||||
}
|
||||
}
|
||||
|
||||
void pty_process_teardown(Loop *loop)
|
||||
void pty_proc_teardown(Loop *loop)
|
||||
{
|
||||
uv_signal_stop(&loop->children_watcher);
|
||||
}
|
||||
|
||||
static void init_child(PtyProcess *ptyproc)
|
||||
static void init_child(PtyProc *ptyproc)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
#if defined(HAVE__NSGETENVIRON)
|
||||
@ -277,13 +277,13 @@ static void init_child(PtyProcess *ptyproc)
|
||||
signal(SIGTERM, SIG_DFL);
|
||||
signal(SIGALRM, SIG_DFL);
|
||||
|
||||
Process *proc = (Process *)ptyproc;
|
||||
Proc *proc = (Proc *)ptyproc;
|
||||
if (proc->cwd && os_chdir(proc->cwd) != 0) {
|
||||
ELOG("chdir(%s) failed: %s", proc->cwd, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
const char *prog = process_get_exepath(proc);
|
||||
const char *prog = proc_get_exepath(proc);
|
||||
|
||||
assert(proc->env);
|
||||
environ = tv_dict_to_env(proc->env);
|
||||
@ -388,7 +388,7 @@ static void chld_handler(uv_signal_t *handle, int signum)
|
||||
Loop *loop = handle->loop->data;
|
||||
|
||||
kl_iter(WatcherPtr, loop->children, current) {
|
||||
Process *proc = (*current)->data;
|
||||
Proc *proc = (*current)->data;
|
||||
do {
|
||||
pid = waitpid(proc->pid, &stat, WNOHANG);
|
||||
} while (pid < 0 && errno == EINTR);
|
||||
@ -406,10 +406,10 @@ static void chld_handler(uv_signal_t *handle, int signum)
|
||||
}
|
||||
}
|
||||
|
||||
PtyProcess pty_process_init(Loop *loop, void *data)
|
||||
PtyProc pty_proc_init(Loop *loop, void *data)
|
||||
{
|
||||
PtyProcess rv;
|
||||
rv.process = process_init(loop, kProcessTypePty, data);
|
||||
PtyProc rv;
|
||||
rv.proc = proc_init(loop, kProcTypePty, data);
|
||||
rv.width = 80;
|
||||
rv.height = 24;
|
||||
rv.tty_fd = -1;
|
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
// IWYU pragma: private, include "nvim/os/pty_process.h"
|
||||
// IWYU pragma: private, include "nvim/os/pty_proc.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/ioctl.h>
|
||||
@ -7,12 +7,12 @@
|
||||
#include "nvim/event/defs.h"
|
||||
|
||||
typedef struct {
|
||||
Process process;
|
||||
Proc proc;
|
||||
uint16_t width, height;
|
||||
struct winsize winsize;
|
||||
int tty_fd;
|
||||
} PtyProcess;
|
||||
} PtyProc;
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "os/pty_process_unix.h.generated.h"
|
||||
# include "os/pty_proc_unix.h.generated.h"
|
||||
#endif
|
@ -10,20 +10,20 @@
|
||||
#include "nvim/memory.h"
|
||||
#include "nvim/os/os.h"
|
||||
#include "nvim/os/pty_conpty_win.h"
|
||||
#include "nvim/os/pty_process_win.h"
|
||||
#include "nvim/os/pty_proc_win.h"
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "os/pty_process_win.c.generated.h"
|
||||
# include "os/pty_proc_win.c.generated.h"
|
||||
#endif
|
||||
|
||||
static void CALLBACK pty_process_finish1(void *context, BOOLEAN unused)
|
||||
static void CALLBACK pty_proc_finish1(void *context, BOOLEAN unused)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
PtyProcess *ptyproc = (PtyProcess *)context;
|
||||
Process *proc = (Process *)ptyproc;
|
||||
PtyProc *ptyproc = (PtyProc *)context;
|
||||
Proc *proc = (Proc *)ptyproc;
|
||||
|
||||
os_conpty_free(ptyproc->conpty);
|
||||
// NB: pty_process_finish1() is called on a separate thread,
|
||||
// NB: pty_proc_finish1() is called on a separate thread,
|
||||
// but the timer only works properly if it's started by the main thread.
|
||||
loop_schedule_fast(proc->loop, event_create(start_wait_eof_timer, ptyproc));
|
||||
}
|
||||
@ -31,7 +31,7 @@ static void CALLBACK pty_process_finish1(void *context, BOOLEAN unused)
|
||||
static void start_wait_eof_timer(void **argv)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
PtyProcess *ptyproc = (PtyProcess *)argv[0];
|
||||
PtyProc *ptyproc = (PtyProc *)argv[0];
|
||||
|
||||
if (ptyproc->finish_wait != NULL) {
|
||||
uv_timer_start(&ptyproc->wait_eof_timer, wait_eof_timer_cb, 200, 200);
|
||||
@ -39,15 +39,15 @@ static void start_wait_eof_timer(void **argv)
|
||||
}
|
||||
|
||||
/// @returns zero on success, or negative error code.
|
||||
int pty_process_spawn(PtyProcess *ptyproc)
|
||||
int pty_proc_spawn(PtyProc *ptyproc)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
Process *proc = (Process *)ptyproc;
|
||||
Proc *proc = (Proc *)ptyproc;
|
||||
int status = 0;
|
||||
conpty_t *conpty_object = NULL;
|
||||
char *in_name = NULL;
|
||||
char *out_name = NULL;
|
||||
HANDLE process_handle = NULL;
|
||||
HANDLE proc_handle = NULL;
|
||||
uv_connect_t *in_req = NULL;
|
||||
uv_connect_t *out_req = NULL;
|
||||
wchar_t *cmd_line = NULL;
|
||||
@ -69,7 +69,7 @@ int pty_process_spawn(PtyProcess *ptyproc)
|
||||
uv_pipe_connect(in_req,
|
||||
&proc->in.uv.pipe,
|
||||
in_name,
|
||||
pty_process_connect_cb);
|
||||
pty_proc_connect_cb);
|
||||
}
|
||||
|
||||
if (!proc->out.s.closed) {
|
||||
@ -77,7 +77,7 @@ int pty_process_spawn(PtyProcess *ptyproc)
|
||||
uv_pipe_connect(out_req,
|
||||
&proc->out.s.uv.pipe,
|
||||
out_name,
|
||||
pty_process_connect_cb);
|
||||
pty_proc_connect_cb);
|
||||
}
|
||||
|
||||
if (proc->cwd != NULL) {
|
||||
@ -105,7 +105,7 @@ int pty_process_spawn(PtyProcess *ptyproc)
|
||||
}
|
||||
|
||||
if (!os_conpty_spawn(conpty_object,
|
||||
&process_handle,
|
||||
&proc_handle,
|
||||
NULL,
|
||||
cmd_line,
|
||||
cwd,
|
||||
@ -114,42 +114,42 @@ int pty_process_spawn(PtyProcess *ptyproc)
|
||||
status = (int)GetLastError();
|
||||
goto cleanup;
|
||||
}
|
||||
proc->pid = (int)GetProcessId(process_handle);
|
||||
proc->pid = (int)GetProcessId(proc_handle);
|
||||
|
||||
uv_timer_init(&proc->loop->uv, &ptyproc->wait_eof_timer);
|
||||
ptyproc->wait_eof_timer.data = (void *)ptyproc;
|
||||
if (!RegisterWaitForSingleObject(&ptyproc->finish_wait,
|
||||
process_handle,
|
||||
pty_process_finish1,
|
||||
proc_handle,
|
||||
pty_proc_finish1,
|
||||
ptyproc,
|
||||
INFINITE,
|
||||
WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE)) {
|
||||
abort();
|
||||
}
|
||||
|
||||
// Wait until pty_process_connect_cb is called.
|
||||
// Wait until pty_proc_connect_cb is called.
|
||||
while ((in_req != NULL && in_req->handle != NULL)
|
||||
|| (out_req != NULL && out_req->handle != NULL)) {
|
||||
uv_run(&proc->loop->uv, UV_RUN_ONCE);
|
||||
}
|
||||
|
||||
ptyproc->conpty = conpty_object;
|
||||
ptyproc->process_handle = process_handle;
|
||||
ptyproc->proc_handle = proc_handle;
|
||||
conpty_object = NULL;
|
||||
process_handle = NULL;
|
||||
proc_handle = NULL;
|
||||
|
||||
cleanup:
|
||||
if (status) {
|
||||
// In the case of an error of MultiByteToWideChar or CreateProcessW.
|
||||
ELOG("pty_process_spawn(%s): %s: error code: %d",
|
||||
ELOG("pty_proc_spawn(%s): %s: error code: %d",
|
||||
proc->argv[0], emsg, status);
|
||||
status = os_translate_sys_error(status);
|
||||
}
|
||||
os_conpty_free(conpty_object);
|
||||
xfree(in_name);
|
||||
xfree(out_name);
|
||||
if (process_handle != NULL) {
|
||||
CloseHandle(process_handle);
|
||||
if (proc_handle != NULL) {
|
||||
CloseHandle(proc_handle);
|
||||
}
|
||||
xfree(in_req);
|
||||
xfree(out_req);
|
||||
@ -159,32 +159,32 @@ cleanup:
|
||||
return status;
|
||||
}
|
||||
|
||||
const char *pty_process_tty_name(PtyProcess *ptyproc)
|
||||
const char *pty_proc_tty_name(PtyProc *ptyproc)
|
||||
{
|
||||
return "?";
|
||||
}
|
||||
|
||||
void pty_process_resize(PtyProcess *ptyproc, uint16_t width, uint16_t height)
|
||||
void pty_proc_resize(PtyProc *ptyproc, uint16_t width, uint16_t height)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
os_conpty_set_size(ptyproc->conpty, width, height);
|
||||
}
|
||||
|
||||
void pty_process_close(PtyProcess *ptyproc)
|
||||
void pty_proc_close(PtyProc *ptyproc)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
Process *proc = (Process *)ptyproc;
|
||||
Proc *proc = (Proc *)ptyproc;
|
||||
|
||||
pty_process_close_master(ptyproc);
|
||||
pty_proc_close_master(ptyproc);
|
||||
|
||||
if (ptyproc->finish_wait != NULL) {
|
||||
UnregisterWaitEx(ptyproc->finish_wait, NULL);
|
||||
ptyproc->finish_wait = NULL;
|
||||
uv_close((uv_handle_t *)&ptyproc->wait_eof_timer, NULL);
|
||||
}
|
||||
if (ptyproc->process_handle != NULL) {
|
||||
CloseHandle(ptyproc->process_handle);
|
||||
ptyproc->process_handle = NULL;
|
||||
if (ptyproc->proc_handle != NULL) {
|
||||
CloseHandle(ptyproc->proc_handle);
|
||||
ptyproc->proc_handle = NULL;
|
||||
}
|
||||
|
||||
if (proc->internal_close_cb) {
|
||||
@ -192,17 +192,17 @@ void pty_process_close(PtyProcess *ptyproc)
|
||||
}
|
||||
}
|
||||
|
||||
void pty_process_close_master(PtyProcess *ptyproc)
|
||||
void pty_proc_close_master(PtyProc *ptyproc)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
}
|
||||
|
||||
void pty_process_teardown(Loop *loop)
|
||||
void pty_proc_teardown(Loop *loop)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
}
|
||||
|
||||
static void pty_process_connect_cb(uv_connect_t *req, int status)
|
||||
static void pty_proc_connect_cb(uv_connect_t *req, int status)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
assert(status == 0);
|
||||
@ -212,23 +212,23 @@ static void pty_process_connect_cb(uv_connect_t *req, int status)
|
||||
static void wait_eof_timer_cb(uv_timer_t *wait_eof_timer)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
PtyProcess *ptyproc = wait_eof_timer->data;
|
||||
Process *proc = (Process *)ptyproc;
|
||||
PtyProc *ptyproc = wait_eof_timer->data;
|
||||
Proc *proc = (Proc *)ptyproc;
|
||||
|
||||
assert(ptyproc->finish_wait != NULL);
|
||||
if (proc->out.s.closed || proc->out.did_eof || !uv_is_readable(proc->out.s.uvstream)) {
|
||||
uv_timer_stop(&ptyproc->wait_eof_timer);
|
||||
pty_process_finish2(ptyproc);
|
||||
pty_proc_finish2(ptyproc);
|
||||
}
|
||||
}
|
||||
|
||||
static void pty_process_finish2(PtyProcess *ptyproc)
|
||||
static void pty_proc_finish2(PtyProc *ptyproc)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
Process *proc = (Process *)ptyproc;
|
||||
Proc *proc = (Proc *)ptyproc;
|
||||
|
||||
DWORD exit_code = 0;
|
||||
GetExitCodeProcess(ptyproc->process_handle, &exit_code);
|
||||
GetExitCodeProcess(ptyproc->proc_handle, &exit_code);
|
||||
proc->status = proc->exit_signal ? 128 + proc->exit_signal : (int)exit_code;
|
||||
|
||||
proc->internal_exit_cb(proc);
|
||||
@ -427,14 +427,14 @@ cleanup:
|
||||
return rc;
|
||||
}
|
||||
|
||||
PtyProcess pty_process_init(Loop *loop, void *data)
|
||||
PtyProc pty_proc_init(Loop *loop, void *data)
|
||||
{
|
||||
PtyProcess rv;
|
||||
rv.process = process_init(loop, kProcessTypePty, data);
|
||||
PtyProc rv;
|
||||
rv.proc = proc_init(loop, kProcTypePty, data);
|
||||
rv.width = 80;
|
||||
rv.height = 24;
|
||||
rv.conpty = NULL;
|
||||
rv.finish_wait = NULL;
|
||||
rv.process_handle = NULL;
|
||||
rv.proc_handle = NULL;
|
||||
return rv;
|
||||
}
|
@ -1,20 +1,20 @@
|
||||
#pragma once
|
||||
// IWYU pragma: private, include "nvim/os/pty_process.h"
|
||||
// IWYU pragma: private, include "nvim/os/pty_proc.h"
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
#include "nvim/event/process.h"
|
||||
#include "nvim/event/proc.h"
|
||||
#include "nvim/lib/queue_defs.h"
|
||||
#include "nvim/os/pty_conpty_win.h"
|
||||
|
||||
typedef struct pty_process {
|
||||
Process process;
|
||||
Proc proc;
|
||||
uint16_t width, height;
|
||||
conpty_t *conpty;
|
||||
HANDLE finish_wait;
|
||||
HANDLE process_handle;
|
||||
HANDLE proc_handle;
|
||||
uv_timer_t wait_eof_timer;
|
||||
} PtyProcess;
|
||||
} PtyProc;
|
||||
|
||||
// Structure used by build_cmd_line()
|
||||
typedef struct arg_node {
|
||||
@ -23,5 +23,5 @@ typedef struct arg_node {
|
||||
} ArgNode;
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "os/pty_process_win.h.generated.h"
|
||||
# include "os/pty_proc_win.h.generated.h"
|
||||
#endif
|
@ -1,7 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef MSWIN
|
||||
# include "nvim/os/pty_process_win.h"
|
||||
#else
|
||||
# include "nvim/os/pty_process_unix.h"
|
||||
#endif
|
@ -14,10 +14,10 @@
|
||||
#include "nvim/eval.h"
|
||||
#include "nvim/eval/typval_defs.h"
|
||||
#include "nvim/event/defs.h"
|
||||
#include "nvim/event/libuv_process.h"
|
||||
#include "nvim/event/libuv_proc.h"
|
||||
#include "nvim/event/loop.h"
|
||||
#include "nvim/event/multiqueue.h"
|
||||
#include "nvim/event/process.h"
|
||||
#include "nvim/event/proc.h"
|
||||
#include "nvim/event/rstream.h"
|
||||
#include "nvim/event/stream.h"
|
||||
#include "nvim/event/wstream.h"
|
||||
@ -872,12 +872,12 @@ static int do_os_system(char **argv, const char *input, size_t len, char **outpu
|
||||
char prog[MAXPATHL];
|
||||
xstrlcpy(prog, argv[0], MAXPATHL);
|
||||
|
||||
LibuvProcess uvproc = libuv_process_init(&main_loop, &buf);
|
||||
Process *proc = &uvproc.process;
|
||||
LibuvProc uvproc = libuv_proc_init(&main_loop, &buf);
|
||||
Proc *proc = &uvproc.proc;
|
||||
MultiQueue *events = multiqueue_new_child(main_loop.events);
|
||||
proc->events = events;
|
||||
proc->argv = argv;
|
||||
int status = process_spawn(proc, has_input, true, true);
|
||||
int status = proc_spawn(proc, has_input, true, true);
|
||||
if (status) {
|
||||
loop_poll_events(&main_loop, 0);
|
||||
// Failed, probably 'shell' is not executable.
|
||||
@ -910,7 +910,7 @@ static int do_os_system(char **argv, const char *input, size_t len, char **outpu
|
||||
|
||||
if (!wstream_write(&proc->in, input_buffer)) {
|
||||
// couldn't write, stop the process and tell the user about it
|
||||
process_stop(proc);
|
||||
proc_stop(proc);
|
||||
return -1;
|
||||
}
|
||||
// close the input stream after everything is written
|
||||
@ -927,7 +927,7 @@ static int do_os_system(char **argv, const char *input, size_t len, char **outpu
|
||||
msg_no_more = true;
|
||||
lines_left = -1;
|
||||
}
|
||||
int exitcode = process_wait(proc, -1, NULL);
|
||||
int exitcode = proc_wait(proc, -1, NULL);
|
||||
if (!got_int && out_data_decide_throttle(0)) {
|
||||
// Last chunk of output was skipped; display it now.
|
||||
out_data_ring(NULL, SIZE_MAX);
|
||||
@ -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"),
|
||||
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.
|
||||
|
@ -63,22 +63,32 @@ static const char *const xdg_defaults[] = {
|
||||
#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
|
||||
const char *get_appname(void)
|
||||
const char *get_appname(bool namelike)
|
||||
{
|
||||
const char *env_val = os_getenv("NVIM_APPNAME");
|
||||
if (env_val == NULL || *env_val == NUL) {
|
||||
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;
|
||||
}
|
||||
|
||||
/// Ensure that APPNAME is valid. Must be a name or relative path.
|
||||
bool appname_is_valid(void)
|
||||
{
|
||||
const char *appname = get_appname();
|
||||
const char *appname = get_appname(false);
|
||||
if (path_is_absolute(appname)
|
||||
// TODO(justinmk): on Windows, path_is_absolute says "/" is NOT absolute. Should it?
|
||||
|| strequal(appname, "/")
|
||||
@ -193,7 +203,7 @@ char *get_xdg_home(const XDGVarType idx)
|
||||
FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
char *dir = stdpaths_get_xdg_var(idx);
|
||||
const char *appname = get_appname();
|
||||
const char *appname = get_appname(false);
|
||||
size_t appname_len = strlen(appname);
|
||||
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;
|
||||
}
|
||||
|
||||
static proftime_T inchar_time;
|
||||
static proftime_T wait_time;
|
||||
|
||||
/// 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.
|
||||
void prof_inchar_exit(void)
|
||||
void prof_input_end(void)
|
||||
{
|
||||
inchar_time = profile_end(inchar_time);
|
||||
profile_set_wait(profile_add(profile_get_wait(), inchar_time));
|
||||
wait_time = profile_end(wait_time);
|
||||
profile_set_wait(profile_add(profile_get_wait(), wait_time));
|
||||
}
|
||||
|
||||
/// @return true when a function defined in the current script should be
|
||||
@ -950,8 +950,8 @@ void time_msg(const char *mesg, const proftime_T *start)
|
||||
/// Initializes the `time_fd` stream for the --startuptime report.
|
||||
///
|
||||
/// @param fname startuptime report file path
|
||||
/// @param process_name name of the current Nvim process to write in the report.
|
||||
void time_init(const char *fname, const char *process_name)
|
||||
/// @param proc_name name of the current Nvim process to write in the report.
|
||||
void time_init(const char *fname, const char *proc_name)
|
||||
{
|
||||
const size_t bufsize = 8192; // Big enough for the entire --startuptime report.
|
||||
time_fd = fopen(fname, "a");
|
||||
@ -972,7 +972,7 @@ void time_init(const char *fname, const char *process_name)
|
||||
semsg("time_init: setvbuf failed: %d %s", r, uv_err_name(r));
|
||||
return;
|
||||
}
|
||||
fprintf(time_fd, "--- Startup times for process: %s ---\n", process_name);
|
||||
fprintf(time_fd, "--- Startup times for process: %s ---\n", proc_name);
|
||||
}
|
||||
|
||||
/// Flushes the startuptimes to disk for the current process
|
||||
|
@ -6875,7 +6875,8 @@ bool set_ref_in_quickfix(int copyID)
|
||||
// In a location list window and none of the other windows is
|
||||
// referring to this location list. Mark the location list
|
||||
// context as still in use.
|
||||
if (mark_quickfix_ctx(win->w_llist_ref, copyID)) {
|
||||
if (mark_quickfix_ctx(win->w_llist_ref, copyID)
|
||||
|| mark_quickfix_user_data(win->w_llist_ref, copyID)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1559,7 +1559,7 @@ static inline char *add_env_sep_dirs(char *dest, const char *const val, const ch
|
||||
return dest;
|
||||
}
|
||||
const void *iter = NULL;
|
||||
const char *appname = get_appname();
|
||||
const char *appname = get_appname(false);
|
||||
const size_t appname_len = strlen(appname);
|
||||
do {
|
||||
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)) {
|
||||
*dest++ = PATHSEP;
|
||||
}
|
||||
const char *appname = get_appname();
|
||||
const char *appname = get_appname(false);
|
||||
size_t appname_len = strlen(appname);
|
||||
assert(appname_len < (IOSIZE - sizeof("-data")));
|
||||
xmemcpyz(IObuff, appname, appname_len);
|
||||
@ -1697,7 +1697,7 @@ char *runtimepath_default(bool clean_arg)
|
||||
size_t config_len = 0;
|
||||
size_t vimruntime_len = 0;
|
||||
size_t libdir_len = 0;
|
||||
const char *appname = get_appname();
|
||||
const char *appname = get_appname(false);
|
||||
size_t appname_len = strlen(appname);
|
||||
if (data_home != NULL) {
|
||||
data_len = strlen(data_home);
|
||||
|
@ -74,10 +74,9 @@ getkey:
|
||||
}
|
||||
// Flush screen updates before blocking.
|
||||
ui_flush();
|
||||
// Call `os_inchar` directly to block for events or user input without
|
||||
// consuming anything from `input_buffer`(os/input.c) or calling the
|
||||
// mapping engine.
|
||||
os_inchar(NULL, 0, -1, typebuf.tb_change_cnt, main_loop.events);
|
||||
// Call `input_get` directly to block for events or user input without consuming anything from
|
||||
// `os/input.c:input_buffer` or calling the mapping engine.
|
||||
input_get(NULL, 0, -1, typebuf.tb_change_cnt, main_loop.events);
|
||||
// If an event was put into the queue, we send K_EVENT directly.
|
||||
if (!input_available() && !multiqueue_empty(main_loop.events)) {
|
||||
key = K_EVENT;
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "nvim/memory_defs.h"
|
||||
#include "nvim/msgpack_rpc/channel.h"
|
||||
#include "nvim/msgpack_rpc/channel_defs.h"
|
||||
#include "nvim/os/os.h"
|
||||
#include "nvim/os/os_defs.h"
|
||||
#include "nvim/tui/tui.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);
|
||||
|
||||
// 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
|
||||
while (true) {
|
||||
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 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);
|
||||
|
||||
// exit status from embedded nvim process
|
||||
|
@ -103,7 +103,7 @@ Debugging tests
|
||||
DBG 2022-06-15T18:37:45.227 T57.58016.0/c UI: stop
|
||||
INF 2022-06-15T18:37:45.227 T57.58016.0/c os_exit:595: Nvim exit: 0
|
||||
DBG 2022-06-15T18:37:45.229 T57.58016.0 read_cb:118: closing Stream (0x7fd5d700ea18): EOF (end of file)
|
||||
INF 2022-06-15T18:37:45.229 T57.58016.0 on_process_exit:400: exited: pid=58017 status=0 stoptime=0
|
||||
INF 2022-06-15T18:37:45.229 T57.58016.0 on_proc_exit:400: exited: pid=58017 status=0 stoptime=0
|
||||
```
|
||||
- You can set `$GDB` to [run functional tests under gdbserver](https://github.com/neovim/neovim/pull/1527):
|
||||
|
||||
|
@ -114,6 +114,7 @@ function Session:request(method, ...)
|
||||
return true, result
|
||||
end
|
||||
|
||||
--- Runs the event loop.
|
||||
function Session:run(request_cb, notification_cb, setup_cb, timeout)
|
||||
local function on_request(method, args, response)
|
||||
coroutine_exec(request_cb, method, args, function(status, result, flag)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user