Compare commits

..

5 Commits

Author SHA1 Message Date
Justin M. Keyes
b84a741f1b
Merge 4f042ad3bc into deac7df80a 2024-09-12 18:58:28 +02:00
Justin M. Keyes
4f042ad3bc feat(ui): detach UI via [count]ctrl-z
how to get server-side channel-id from client:

    diff --git a/src/nvim/main.c b/src/nvim/main.c
    index f699d4484fe2..421277a396f1 100644
    --- a/src/nvim/main.c
    +++ b/src/nvim/main.c
    @@ -656,7 +656,6 @@ int main(int argc, char **argv)

       TIME_MSG("before starting main loop");
       ILOG("starting main loop");
    -  ELOG("xxx %" PRId64, ui_client_channel_id);

       // Main loop: never returns.
       normal_enter(false, false);
    @@ -917,26 +916,6 @@ static uint64_t server_connect(char *server_addr, const char **errmsg)
         *errmsg = error;
         return 0;
       }
    -
    -  Error err = ERROR_INIT;
    -  Arena arena = ARENA_EMPTY;
    -
    -  Array args = arena_array(&arena, (size_t)1);
    -  ADD(args, INTEGER_OBJ(0));
    -  ArenaMem res_mem = NULL;
    -  Object result = rpc_send_call(chan, "nvim_get_chan_info", args, &res_mem, &err);
    -  if (!ERROR_SET(&err)) {
    -    arena_mem_free(res_mem);
    -    ui_server_chan = result.data.dictionary.items[0].value.data.integer;
    -    assert(ui_server_chan > 0);
    -  }
    -  arena_mem_free(arena_finish(&arena));
    -
    -  if (ERROR_SET(&err)) {
    -    ELOG("nvim_get_chan_info failed: %s", err.msg);
    -    api_clear_error(&err);
    -  }
    -
       return chan;
     }

    @@ -966,7 +945,6 @@ static void remote_request(mparm_T *params, int remote_args, char *server_addr,
         }

         ui_client_channel_id = chan;
    -    ELOG("xxx main:remote_request ui_channel=%" PRId64, ui_client_channel_id);
         return;
       }

    diff --git a/src/nvim/ui_client.h b/src/nvim/ui_client.h
    index b59972022613..928bd4c0a525 100644
    --- a/src/nvim/ui_client.h
    +++ b/src/nvim/ui_client.h
    @@ -16,8 +16,6 @@ EXTERN sattr_T *grid_line_buf_attr INIT( = NULL);

     // 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);
    -// UI client server-side channel id.
    -EXTERN int64_t ui_server_chan INIT( = 0);

     // exit status from embedded nvim process
     EXTERN int ui_client_exit_status INIT( = 0);
2024-09-12 17:05:42 +02:00
Justin M. Keyes
5799ee2c60 tests: get stdout from clear() XXX 2024-09-12 17:05:42 +02:00
Justin M. Keyes
1d9a003616 feat(tui): built UI sets client info 2024-09-12 17:05:42 +02:00
Justin M. Keyes
2258679314 refactor(stream.c): unused params in stream_close 2024-09-12 17:05:42 +02:00
82 changed files with 575 additions and 654 deletions

View File

@ -26,21 +26,3 @@ 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 }}

View File

@ -5,7 +5,7 @@ on:
workflow_call:
jobs:
request-reviewer:
if: github.event.pull_request.state == 'open' && github.event.pull_request.draft == false && !endsWith(github.actor, '[bot]')
if: github.event.pull_request.state == 'open' && github.event.pull_request.draft == false
runs-on: ubuntu-latest
permissions:
pull-requests: write

View File

@ -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/v2.1.2.tar.gz
UNIBILIUM_SHA256 370ecb07fbbc20d91d1b350c55f1c806b06bf86797e164081ccc977fc9b3af7a
UNIBILIUM_URL https://github.com/neovim/unibilium/archive/ab28a2ddb86a144194a798bcf1fef1ab4f981ab7.tar.gz
UNIBILIUM_SHA256 7c0386fc48452632868e0dcb8e7ed140d67a3da79e39ceee54c1ba7a495ad625
LUV_URL https://github.com/luvit/luv/releases/download/1.48.0-2/luv-1.48.0-2.tar.gz
LUV_SHA256 2c3a1ddfebb4f6550293a40ee789f7122e97647eede51511f57203de48c03b7a

View File

@ -23,7 +23,6 @@
" 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
@ -11276,7 +11275,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
@ -11305,7 +11304,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
@ -11352,12 +11351,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
@ -11373,13 +11372,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

View File

@ -2559,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}, {opt}) *vim.ui.open()*
vim.ui.open({path}) *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.
@ -2570,8 +2570,6 @@ vim.ui.open({path}, {opt}) *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
@ -2581,8 +2579,6 @@ vim.ui.open({path}, {opt}) *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.

View File

@ -194,10 +194,7 @@ TUI
UI
• |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()|.
• TODO
==============================================================================
CHANGED FEATURES *news-changed*

View File

@ -1683,12 +1683,6 @@ 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: >

View File

@ -9,8 +9,8 @@
local function get_commentstring(ref_position)
local buf_cs = vim.bo.commentstring
local ts_parser = vim.treesitter._get_parser()
if not ts_parser then
local has_ts_parser, ts_parser = pcall(vim.treesitter.get_parser)
if not has_ts_parser then
return buf_cs
end

View File

@ -213,25 +213,23 @@ end
--- Default menus
do
--- Right click popup menu
vim.cmd([[
anoremenu PopUp.Go\ to\ definition <Cmd>lua vim.lsp.buf.definition()<CR>
amenu PopUp.Open\ in\ web\ browser gx
anoremenu PopUp.Inspect <Cmd>Inspect<CR>
anoremenu PopUp.-1- <Nop>
vnoremenu PopUp.Cut "+x
vnoremenu PopUp.Copy "+y
anoremenu PopUp.Paste "+gP
vnoremenu PopUp.Paste "+P
vnoremenu PopUp.Delete "_x
nnoremenu PopUp.Select\ All ggVG
vnoremenu PopUp.Select\ All gg0oG$
inoremenu PopUp.Select\ All <C-Home><C-O>VG
anoremenu PopUp.-2- <Nop>
anoremenu PopUp.How-to\ disable\ mouse <Cmd>help disable-mouse<CR>
]])
local function enable_ctx_menu(ctx)
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
anoremenu PopUp.Inspect <Cmd>Inspect<CR>
anoremenu PopUp.-1- <Nop>
vnoremenu PopUp.Cut "+x
vnoremenu PopUp.Copy "+y
anoremenu PopUp.Paste "+gP
vnoremenu PopUp.Paste "+P
vnoremenu PopUp.Delete "_x
nnoremenu PopUp.Select\ All ggVG
vnoremenu PopUp.Select\ All gg0oG$
inoremenu PopUp.Select\ All <C-Home><C-O>VG
anoremenu PopUp.-2- <Nop>
anoremenu PopUp.How-to\ disable\ mouse <Cmd>help disable-mouse<CR>
amenu disable PopUp.Go\ to\ definition
amenu disable PopUp.Open\ in\ web\ browser
]])
@ -242,6 +240,7 @@ 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', {
@ -253,7 +252,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)
enable_ctx_menu(ctx)
def_menu(ctx)
end,
})
end

View File

@ -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 integer|string
--- @param buf any
--- @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 integer|string
--- @param expr string|function
--- @param buf any
--- @param expr any
--- @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 integer|string
--- @param expr string|function
--- @param buf any
--- @param expr any
--- @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 integer|string
--- @param text string
--- @param buf any
--- @param text any
--- @return any
function vim.fn.prompt_setprompt(buf, text) end

View File

@ -280,7 +280,12 @@ 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',
@ -365,7 +370,12 @@ 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,
@ -648,7 +658,12 @@ 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',
@ -684,7 +699,12 @@ 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',
@ -753,7 +773,12 @@ 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',
@ -923,7 +948,12 @@ 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',
@ -1103,7 +1133,12 @@ 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',
@ -1133,7 +1168,12 @@ local extension = {
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',

View File

@ -447,9 +447,11 @@ function M.document_symbol(opts)
request_with_opts(ms.textDocument_documentSymbol, params, opts)
end
--- @param call_hierarchy_items lsp.CallHierarchyItem[]
--- @return lsp.CallHierarchyItem?
--- @param call_hierarchy_items 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
@ -474,7 +476,7 @@ local function call_hierarchy(method)
vim.notify(err.message, vim.log.levels.WARN)
return
end
if not result or vim.tbl_isempty(result) then
if not result then
vim.notify('No item resolved', vim.log.levels.WARN)
return
end

View File

@ -154,7 +154,7 @@ 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
local len = vim.fn.strlen(line)
if index > len then
-- LSP spec: if character > line length, default to the line length.
-- https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#position
@ -167,7 +167,7 @@ function M._str_byteindex_enc(line, index, encoding)
if index then
return index
else
return len
return #line
end
elseif encoding == 'utf-16' then
return vim.str_byteindex(line, index, true)

View File

@ -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 no parser can be found or created, returns `nil`.
--- 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, or `nil` if not found
function M._get_parser(bufnr, lang, opts)
---@return vim.treesitter.LanguageTree object to use for parsing
function M.get_parser(bufnr, lang, opts)
opts = opts or {}
if bufnr == nil or bufnr == 0 then
@ -94,14 +94,18 @@ function M._get_parser(bufnr, lang, opts)
if not valid_lang(lang) then
if not parsers[bufnr] then
return nil
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
)
)
end
elseif parsers[bufnr] == nil or parsers[bufnr]:lang() ~= lang then
local parser = vim.F.npcall(M._create_parser, bufnr, lang, opts)
if not parser then
return nil
end
parsers[bufnr] = parser
assert(lang, 'lang should be valid')
parsers[bufnr] = M._create_parser(bufnr, lang, opts)
end
parsers[bufnr]:register_cbs(opts.buf_attach_cbs)
@ -109,29 +113,6 @@ 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
@ -405,7 +386,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
@ -438,11 +419,7 @@ 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)
if not parser then
vim.notify('No parser for the given buffer.', vim.log.levels.WARN)
return
end
local parser = M.get_parser(bufnr, lang)
M.highlighter.new(parser)
end

View File

@ -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 = assert(ts._get_parser(bufnr))
local parser = 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 = ts._get_parser(bufnr)
local parser = vim.F.npcall(ts.get_parser, bufnr)
if not parser then
return '0'
end

View File

@ -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 = assert(vim.treesitter._get_parser(buf), 'query parser not found.')
local parser = vim.treesitter.get_parser(buf)
parser:parse()
parser:for_each_tree(function(tree, ltree)
if ltree:lang() == 'query' then

View File

@ -76,9 +76,10 @@ end
---
---@package
function TSTreeView:new(bufnr, lang)
local parser = vim.treesitter._get_parser(bufnr or 0, lang)
if not parser then
return nil, 'No parser available for the given buffer.'
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
end
-- For each child tree (injected language), find the root of the tree and locate the node within
@ -538,7 +539,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 = assert(vim.treesitter._get_parser(base_buf, lang))
local parser = 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')
@ -595,8 +596,8 @@ function M.edit_query(lang)
end
vim.cmd(cmd)
local parser = vim.treesitter._get_parser(buf, lang)
if not parser then
local ok, parser = pcall(vim.treesitter.get_parser, buf, lang)
if not ok then
return nil, 'No parser available for the given buffer'
end
lang = parser:lang()

View File

@ -117,8 +117,6 @@ 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
@ -127,14 +125,12 @@ end
--- ```
---
---@param path string Path or URL to open
---@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, opt)
function M.open(path)
vim.validate({
path = { path, 'string' },
})
@ -143,13 +139,12 @@ function M.open(path, opt)
path = vim.fs.normalize(path)
end
opt = opt or {}
local cmd ---@type string[]
local job_opt = { text = true, detach = true } --- @type vim.SystemOpts
local cmd --- @type string[]
local opts --- @type vim.SystemOpts
if opt.cmd then
cmd = vim.list_extend(opt.cmd --[[@as string[] ]], { path })
elseif vim.fn.has('mac') == 1 then
opts = { text = true, detach = true }
if vim.fn.has('mac') == 1 then
cmd = { 'open', path }
elseif vim.fn.has('win32') == 1 then
if vim.fn.executable('rundll32') == 1 then
@ -159,8 +154,8 @@ function M.open(path, opt)
end
elseif vim.fn.executable('xdg-open') == 1 then
cmd = { 'xdg-open', path }
job_opt.stdout = false
job_opt.stderr = false
opts.stdout = false
opts.stderr = false
elseif vim.fn.executable('wslview') == 1 then
cmd = { 'wslview', path }
elseif vim.fn.executable('explorer.exe') == 1 then
@ -169,7 +164,7 @@ function M.open(path, opt)
return nil, 'vim.ui.open: no handler found (tried: wslview, explorer.exe, xdg-open)'
end
return vim.system(cmd, job_opt), nil
return vim.system(cmd, opts), nil
end
--- Returns all URLs at cursor, if any.

View File

@ -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 = assert(vim.treesitter._get_parser(bufnr, 'vimdoc'), 'vimdoc parser not found.')
local parser = vim.treesitter.get_parser(bufnr, 'vimdoc')
local query = vim.treesitter.query.parse(
parser:lang(),
[[

View File

@ -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 Sep 11
" Last Change: 2024 Sep 10
" Please check :help java.vim for comments on some of the options available.
@ -663,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 javaStorageClass
hi def link javaConceptKind NonText
hi def link javaBoolean Boolean
hi def link javaSpecial Special

View File

@ -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=@vimExprList,vimNotation
syn match vimNotFunc "\<if\>\|\<el\%[seif]\>\|\<retu\%[rn]\>\|\<while\>" skipwhite nextgroup=vimOper,vimOperParen,vimVar,vimFunc,vimNotation
" Match: {{{2
" =====

View File

@ -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 = assert(vim.treesitter._get_parser(buf), 'vimdoc parser not found.')
local lang_tree = vim.treesitter.get_parser(buf)
return lang_tree, buf
end

View File

@ -10,7 +10,7 @@
Memcheck:Leak
fun:malloc
fun:uv_spawn
fun:libuv_proc_spawn
fun:proc_spawn
fun:libuv_process_spawn
fun:process_spawn
fun:job_start
}

View File

@ -848,7 +848,7 @@ def CheckIncludes(filename, lines, error):
or filename.endswith('.in.h')
or FileInfo(filename).RelativePath() in {
'func_attr.h',
'os/pty_proc.h',
'os/pty_process.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_proc_win.h",
"src/nvim/os/pty_process_win.h",
]
skip_headers = [

View File

@ -417,10 +417,10 @@ list(SORT NVIM_HEADERS)
foreach(sfile ${NVIM_SOURCES})
get_filename_component(f ${sfile} NAME)
if(WIN32 AND ${f} MATCHES "^(pty_proc_unix.c)$")
if(WIN32 AND ${f} MATCHES "^(pty_process_unix.c)$")
list(REMOVE_ITEM NVIM_SOURCES ${sfile})
endif()
if(NOT WIN32 AND ${f} MATCHES "^(pty_proc_win.c)$")
if(NOT WIN32 AND ${f} MATCHES "^(pty_process_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_proc_unix.h)$")
if(WIN32 AND ${f} MATCHES "^(pty_process_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_proc_unix.h
os/pty_process_unix.h
os/unix_defs.h)
else()
list(APPEND EXCLUDE_CLANG_TIDY
os/win_defs.h
os/pty_proc_win.h
os/pty_process_win.h
os/pty_conpty_win.h
os/os_win_console.h)
endif()

View File

@ -70,7 +70,7 @@
#include "nvim/optionstr.h"
#include "nvim/os/input.h"
#include "nvim/os/os_defs.h"
#include "nvim/os/proc.h"
#include "nvim/os/process.h"
#include "nvim/popupmenu.h"
#include "nvim/pos_defs.h"
#include "nvim/runtime.h"

View File

@ -19,7 +19,7 @@
#include "nvim/eval/typval.h"
#include "nvim/event/loop.h"
#include "nvim/event/multiqueue.h"
#include "nvim/event/proc.h"
#include "nvim/event/process.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;
Proc *proc;
Process *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 == kProcTypePty && part == kChannelPartAll) {
pty_proc_close_master(&chan->stream.pty);
if (proc->type == kProcessTypePty && part == kChannelPartAll) {
pty_process_close_master(&chan->stream.pty);
}
break;
@ -289,7 +289,7 @@ static void channel_destroy(Channel *chan)
}
if (chan->streamtype == kChannelStreamProc) {
proc_free(&chan->stream.proc);
process_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_proc_init(&main_loop, chan);
chan->stream.pty = pty_process_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_proc_init(&main_loop, chan);
chan->stream.uv = libuv_process_init(&main_loop, chan);
}
Proc *proc = &chan->stream.proc;
Process *proc = &chan->stream.proc;
proc->argv = argv;
proc->exepath = exepath;
proc->cb = channel_proc_exit_cb;
proc->cb = channel_process_exit_cb;
proc->events = chan->events;
proc->detach = detach;
proc->cwd = cwd;
proc->env = env;
proc->overlapped = overlapped;
char *cmd = xstrdup(proc_get_exepath(proc));
char *cmd = xstrdup(process_get_exepath(proc));
bool has_out, has_err;
if (proc->type == kProcTypePty) {
if (proc->type == kProcessTypePty) {
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 = proc_spawn(proc, has_in, has_out, has_err);
int status = process_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_proc_exit_cb(Proc *proc, int status, void *data)
static void channel_process_exit_cb(Process *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_proc_resize(&chan->stream.pty, width, height);
pty_process_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;
proc_stop(&chan->stream.proc);
process_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
&& !proc_is_stopped(&chan->stream.proc));
&& !process_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 == kProcTypePty) {
const char *name = pty_proc_tty_name(&chan->stream.pty);
if (chan->stream.proc.type == kProcessTypePty) {
const char *name = pty_process_tty_name(&chan->stream.pty);
PUT_C(info, "pty", CSTR_TO_ARENA_OBJ(arena, name));
}

View File

@ -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_proc.h"
#include "nvim/event/libuv_process.h"
#include "nvim/macros_defs.h"
#include "nvim/map_defs.h"
#include "nvim/msgpack_rpc/channel_defs.h"
#include "nvim/os/pty_proc.h"
#include "nvim/os/pty_process.h"
#include "nvim/types_defs.h"
struct Channel {
@ -21,9 +21,9 @@ struct Channel {
ChannelStreamType streamtype;
union {
Proc proc;
LibuvProc uv;
PtyProc pty;
Process proc;
LibuvProcess uv;
PtyProcess pty;
RStream socket;
StdioPair stdio;
StderrState err;

View File

@ -170,26 +170,28 @@ 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 = wp->w_width_inner - cur_col_off;
int width2 = width1 + win_col_off2(wp);
int width1;
int width2;
if (saved_w_virtcol == wp->w_virtcol && prev_wp == wp
&& prev_width1 == width1 && prev_width2 == width2) {
&& prev_col_off == cur_col_off) {
*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 && width2 > 0) {
if (wp->w_virtcol >= (colnr_T)width1) {
*right_col = width1 + ((wp->w_virtcol - width1) / width2 + 1) * width2;
}
if (wp->w_virtcol >= (colnr_T)width1 && width2 > 0) {
@ -200,9 +202,8 @@ 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.

View File

@ -32,7 +32,7 @@
#include "nvim/eval/vars.h"
#include "nvim/event/loop.h"
#include "nvim/event/multiqueue.h"
#include "nvim/event/proc.h"
#include "nvim/event/process.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
|| proc_is_stopped(&data->stream.proc)) {
|| process_is_stopped(&data->stream.proc)) {
if (show_error) {
if (data && data->streamtype != kChannelStreamProc) {
emsg(_(e_invchanjob));

View File

@ -8044,7 +8044,7 @@ M.funcs = {
]=],
name = 'prompt_getprompt',
params = { { 'buf', 'integer|string' } },
params = { { 'buf', 'any' } },
signature = 'prompt_getprompt({buf})',
},
prompt_setcallback = {
@ -8084,7 +8084,7 @@ M.funcs = {
]=],
name = 'prompt_setcallback',
params = { { 'buf', 'integer|string' }, { 'expr', 'string|function' } },
params = { { 'buf', 'any' }, { 'expr', 'any' } },
signature = 'prompt_setcallback({buf}, {expr})',
},
prompt_setinterrupt = {
@ -8101,7 +8101,7 @@ M.funcs = {
]=],
name = 'prompt_setinterrupt',
params = { { 'buf', 'integer|string' }, { 'expr', 'string|function' } },
params = { { 'buf', 'any' }, { 'expr', 'any' } },
signature = 'prompt_setinterrupt({buf}, {expr})',
},
prompt_setprompt = {
@ -8116,7 +8116,7 @@ M.funcs = {
<
]=],
name = 'prompt_setprompt',
params = { { 'buf', 'integer|string' }, { 'text', 'string' } },
params = { { 'buf', 'any' }, { 'text', 'any' } },
signature = 'prompt_setprompt({buf}, {text})',
},
pum_getpos = {

View File

@ -49,7 +49,7 @@
#include "nvim/event/defs.h"
#include "nvim/event/loop.h"
#include "nvim/event/multiqueue.h"
#include "nvim/event/proc.h"
#include "nvim/event/process.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_proc.h"
#include "nvim/os/pty_process.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;
}
Proc *proc = &data->stream.proc;
Process *proc = &data->stream.proc;
rettv->vval.v_number = proc->pid;
}
@ -3796,13 +3796,13 @@ static void f_jobresize(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
return;
}
if (data->stream.proc.type != kProcTypePty) {
if (data->stream.proc.type != kProcessTypePty) {
emsg(_(e_channotpty));
return;
}
pty_proc_resize(&data->stream.pty, (uint16_t)argvars[1].vval.v_number,
(uint16_t)argvars[2].vval.v_number);
pty_process_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);
}
proc_stop(&data->stream.proc);
process_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 (proc_is_stopped(&chan->stream.proc)) {
} else if (process_is_stopped(&chan->stream.proc)) {
// Job is stopped but not fully destroyed.
// Ensure all callbacks on its event queue are executed. #15402
proc_wait(&chan->stream.proc, -1, NULL);
process_wait(&chan->stream.proc, -1, NULL);
jobs[i] = NULL; // Invalid job.
} else {
jobs[i] = chan;
@ -4144,8 +4144,8 @@ 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 = proc_wait(&jobs[i]->stream.proc, remaining,
waiting_jobs);
int status = process_wait(&jobs[i]->stream.proc, remaining,
waiting_jobs);
if (status < 0) {
break; // Interrupted (CTRL-C) or timeout, skip remaining jobs.
}
@ -8207,7 +8207,7 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
return;
}
int pid = chan->stream.pty.proc.pid;
int pid = chan->stream.pty.process.pid;
// "./…" => "/home/foo/…"
vim_FullName(cwd, NameBuff, sizeof(NameBuff), false);

View File

@ -142,31 +142,30 @@ struct socket_watcher {
};
typedef enum {
kProcTypeUv,
kProcTypePty,
} ProcType;
kProcessTypeUv,
kProcessTypePty,
} ProcessType;
/// OS process
typedef struct proc Proc;
typedef void (*proc_exit_cb)(Proc *proc, int status, void *data);
typedef void (*internal_proc_cb)(Proc *proc);
typedef struct process Process;
typedef void (*process_exit_cb)(Process *proc, int status, void *data);
typedef void (*internal_process_cb)(Process *proc);
struct proc {
ProcType type;
struct process {
ProcessType type;
Loop *loop;
void *data;
int pid, status, refcount;
uint8_t exit_signal; // Signal used when killing (on Windows).
uint64_t stopped_time; // proc_stop() timestamp
uint64_t stopped_time; // process_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 proc_free().
proc_exit_cb cb;
internal_proc_cb internal_exit_cb, internal_close_cb;
/// Exit handler. If set, user must call process_free().
process_exit_cb cb;
internal_process_cb internal_exit_cb, internal_close_cb;
bool closed, detach, overlapped, fwd_err;
MultiQueue *events;
};

View File

@ -5,9 +5,9 @@
#include "nvim/eval/typval.h"
#include "nvim/event/defs.h"
#include "nvim/event/libuv_proc.h"
#include "nvim/event/libuv_process.h"
#include "nvim/event/loop.h"
#include "nvim/event/proc.h"
#include "nvim/event/process.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_proc.c.generated.h"
# include "event/libuv_process.c.generated.h"
#endif
/// @returns zero on success, or negative error code
int libuv_proc_spawn(LibuvProc *uvproc)
int libuv_process_spawn(LibuvProcess *uvproc)
FUNC_ATTR_NONNULL_ALL
{
Proc *proc = (Proc *)uvproc;
uvproc->uvopts.file = proc_get_exepath(proc);
Process *proc = (Process *)uvproc;
uvproc->uvopts.file = process_get_exepath(proc);
uvproc->uvopts.args = proc->argv;
uvproc->uvopts.flags = UV_PROCESS_WINDOWS_HIDE;
#ifdef MSWIN
@ -101,7 +101,7 @@ int libuv_proc_spawn(LibuvProc *uvproc)
return status;
}
void libuv_proc_close(LibuvProc *uvproc)
void libuv_process_close(LibuvProcess *uvproc)
FUNC_ATTR_NONNULL_ARG(1)
{
uv_close((uv_handle_t *)&uvproc->uv, close_cb);
@ -109,11 +109,11 @@ void libuv_proc_close(LibuvProc *uvproc)
static void close_cb(uv_handle_t *handle)
{
Proc *proc = handle->data;
Process *proc = handle->data;
if (proc->internal_close_cb) {
proc->internal_close_cb(proc);
}
LibuvProc *uvproc = (LibuvProc *)proc;
LibuvProcess *uvproc = (LibuvProcess *)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)
{
Proc *proc = handle->data;
Process *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);
}
LibuvProc libuv_proc_init(Loop *loop, void *data)
LibuvProcess libuv_process_init(Loop *loop, void *data)
{
LibuvProc rv = {
.proc = proc_init(loop, kProcTypeUv, data)
LibuvProcess rv = {
.process = process_init(loop, kProcessTypeUv, data)
};
return rv;
}

View File

@ -5,12 +5,12 @@
#include "nvim/event/defs.h"
typedef struct {
Proc proc;
Process process;
uv_process_t uv;
uv_process_options_t uvopts;
uv_stdio_container_t uvstdio[4];
} LibuvProc;
} LibuvProcess;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/libuv_proc.h.generated.h"
# include "event/libuv_process.h.generated.h"
#endif

View File

@ -4,24 +4,24 @@
#include <uv.h>
#include "klib/klist.h"
#include "nvim/event/libuv_proc.h"
#include "nvim/event/libuv_process.h"
#include "nvim/event/loop.h"
#include "nvim/event/multiqueue.h"
#include "nvim/event/proc.h"
#include "nvim/event/process.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/proc.h"
#include "nvim/os/pty_proc.h"
#include "nvim/os/process.h"
#include "nvim/os/pty_process.h"
#include "nvim/os/shell.h"
#include "nvim/os/time.h"
#include "nvim/ui_client.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/proc.c.generated.h"
# include "event/process.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 proc_is_tearing_down = false;
static bool process_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 proc_spawn(Proc *proc, bool in, bool out, bool err)
int process_spawn(Process *proc, bool in, bool out, bool err)
FUNC_ATTR_NONNULL_ALL
{
// forwarding stderr contradicts with processing it internally
@ -70,11 +70,11 @@ int proc_spawn(Proc *proc, bool in, bool out, bool err)
int status;
switch (proc->type) {
case kProcTypeUv:
status = libuv_proc_spawn((LibuvProc *)proc);
case kProcessTypeUv:
status = libuv_process_spawn((LibuvProcess *)proc);
break;
case kProcTypePty:
status = pty_proc_spawn((PtyProc *)proc);
case kProcessTypePty:
status = pty_process_spawn((PtyProcess *)proc);
break;
}
@ -89,12 +89,12 @@ int proc_spawn(Proc *proc, bool in, bool out, bool err)
uv_close((uv_handle_t *)&proc->err.s.uv.pipe, NULL);
}
if (proc->type == kProcTypeUv) {
uv_close((uv_handle_t *)&(((LibuvProc *)proc)->uv), NULL);
if (proc->type == kProcessTypeUv) {
uv_close((uv_handle_t *)&(((LibuvProcess *)proc)->uv), NULL);
} else {
proc_close(proc);
process_close(proc);
}
proc_free(proc);
process_free(proc);
proc->status = -1;
return status;
}
@ -102,52 +102,52 @@ int proc_spawn(Proc *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_proc_stream_close;
proc->in.internal_close_cb = on_process_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_proc_stream_close;
proc->out.s.internal_close_cb = on_process_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_proc_stream_close;
proc->err.s.internal_close_cb = on_process_stream_close;
proc->refcount++;
}
proc->internal_exit_cb = on_proc_exit;
proc->internal_exit_cb = on_process_exit;
proc->internal_close_cb = decref;
proc->refcount++;
kl_push(WatcherPtr, proc->loop->children, proc);
DLOG("new: pid=%d exepath=[%s]", proc->pid, proc_get_exepath(proc));
DLOG("new: pid=%d exepath=[%s]", proc->pid, process_get_exepath(proc));
return 0;
}
void proc_teardown(Loop *loop) FUNC_ATTR_NONNULL_ALL
void process_teardown(Loop *loop) FUNC_ATTR_NONNULL_ALL
{
proc_is_tearing_down = true;
process_is_tearing_down = true;
kl_iter(WatcherPtr, loop->children, current) {
Proc *proc = (*current)->data;
if (proc->detach || proc->type == kProcTypePty) {
Process *proc = (*current)->data;
if (proc->detach || proc->type == kProcessTypePty) {
// Close handles to process without killing it.
CREATE_EVENT(loop->events, proc_close_handles, proc);
CREATE_EVENT(loop->events, process_close_handles, proc);
} else {
proc_stop(proc);
process_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_proc_teardown(loop);
pty_process_teardown(loop);
}
void proc_close_streams(Proc *proc) FUNC_ATTR_NONNULL_ALL
void process_close_streams(Process *proc) FUNC_ATTR_NONNULL_ALL
{
wstream_may_close(&proc->in);
rstream_may_close(&proc->out);
@ -162,7 +162,7 @@ void proc_close_streams(Proc *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 proc_wait(Proc *proc, int ms, MultiQueue *events)
int process_wait(Process *proc, int ms, MultiQueue *events)
FUNC_ATTR_NONNULL_ARG(1)
{
if (!proc->refcount) {
@ -186,7 +186,7 @@ int proc_wait(Proc *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;
proc_stop(proc);
process_stop(proc);
if (ms == -1) {
// We can only return if all streams/handles are closed and the job
// exited.
@ -214,7 +214,7 @@ int proc_wait(Proc *proc, int ms, MultiQueue *events)
}
/// Ask a process to terminate and eventually kill if it doesn't respond
void proc_stop(Proc *proc) FUNC_ATTR_NONNULL_ALL
void process_stop(Process *proc) FUNC_ATTR_NONNULL_ALL
{
bool exited = (proc->status >= 0);
if (exited || proc->stopped_time) {
@ -224,13 +224,13 @@ void proc_stop(Proc *proc) FUNC_ATTR_NONNULL_ALL
proc->exit_signal = SIGTERM;
switch (proc->type) {
case kProcTypeUv:
case kProcessTypeUv:
os_proc_tree_kill(proc->pid, SIGTERM);
break;
case kProcTypePty:
case kProcessTypePty:
// close all streams for pty processes to send SIGHUP to the process
proc_close_streams(proc);
pty_proc_close_master((PtyProc *)proc);
process_close_streams(proc);
pty_process_close_master((PtyProcess *)proc);
break;
}
@ -240,7 +240,7 @@ void proc_stop(Proc *proc) FUNC_ATTR_NONNULL_ALL
}
/// Frees process-owned resources.
void proc_free(Proc *proc) FUNC_ATTR_NONNULL_ALL
void process_free(Process *proc) FUNC_ATTR_NONNULL_ALL
{
if (proc->argv != NULL) {
shell_free_argv(proc->argv);
@ -249,19 +249,19 @@ void proc_free(Proc *proc) FUNC_ATTR_NONNULL_ALL
}
/// Sends SIGKILL (or SIGTERM..SIGKILL for PTY jobs) to processes that did
/// not terminate after proc_stop().
/// not terminate after process_stop().
static void children_kill_cb(uv_timer_t *handle)
{
Loop *loop = handle->loop->data;
kl_iter(WatcherPtr, loop->children, current) {
Proc *proc = (*current)->data;
Process *proc = (*current)->data;
bool exited = (proc->status >= 0);
if (exited || !proc->stopped_time) {
continue;
}
uint64_t term_sent = UINT64_MAX == proc->stopped_time;
if (kProcTypePty != proc->type || term_sent) {
if (kProcessTypePty != 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 proc_close_event(void **argv)
static void process_close_event(void **argv)
{
Proc *proc = argv[0];
Process *proc = argv[0];
if (proc->cb) {
// User (hint: channel_job_start) is responsible for calling
// proc_free().
// process_free().
proc->cb(proc, proc->status, proc->data);
} else {
proc_free(proc);
process_free(proc);
}
}
static void decref(Proc *proc)
static void decref(Process *proc)
{
if (--proc->refcount != 0) {
return;
@ -303,13 +303,13 @@ static void decref(Proc *proc)
}
assert(node);
kl_shift_at(WatcherPtr, loop->children, node);
CREATE_EVENT(proc->events, proc_close_event, proc);
CREATE_EVENT(proc->events, process_close_event, proc);
}
static void proc_close(Proc *proc)
static void process_close(Process *proc)
FUNC_ATTR_NONNULL_ARG(1)
{
if (proc_is_tearing_down && (proc->detach || proc->type == kProcTypePty)
if (process_is_tearing_down && (proc->detach || proc->type == kProcessTypePty)
&& proc->closed) {
// If a detached/pty process dies while tearing down it might get closed
// twice.
@ -319,17 +319,17 @@ static void proc_close(Proc *proc)
proc->closed = true;
if (proc->detach) {
if (proc->type == kProcTypeUv) {
uv_unref((uv_handle_t *)&(((LibuvProc *)proc)->uv));
if (proc->type == kProcessTypeUv) {
uv_unref((uv_handle_t *)&(((LibuvProcess *)proc)->uv));
}
}
switch (proc->type) {
case kProcTypeUv:
libuv_proc_close((LibuvProc *)proc);
case kProcessTypeUv:
libuv_process_close((LibuvProcess *)proc);
break;
case kProcTypePty:
pty_proc_close((PtyProc *)proc);
case kProcessTypePty:
pty_process_close((PtyProcess *)proc);
break;
}
}
@ -338,7 +338,7 @@ static void proc_close(Proc *proc)
///
/// @param proc Process, for which an output stream should be flushed.
/// @param stream Stream to flush.
static void flush_stream(Proc *proc, RStream *stream)
static void flush_stream(Process *proc, RStream *stream)
FUNC_ATTR_NONNULL_ARG(1)
{
if (!stream || stream->s.closed) {
@ -382,16 +382,16 @@ static void flush_stream(Proc *proc, RStream *stream)
}
}
static void proc_close_handles(void **argv)
static void process_close_handles(void **argv)
{
Proc *proc = argv[0];
Process *proc = argv[0];
exit_need_delay++;
flush_stream(proc, &proc->out);
flush_stream(proc, &proc->err);
proc_close_streams(proc);
proc_close(proc);
process_close_streams(proc);
process_close(proc);
exit_need_delay--;
}
@ -416,10 +416,6 @@ static void exit_event(void **argv)
os_exit(status);
} else {
assert(status == 0); // Called from rpc_close(), which passes 0 as status.
// TODO(justinmk):
// - make this optional ("nvim --nohup")?
// - dynamic: can be set on the channel at any time
// - TUI sets this on SIGUP
// preserve_exit(NULL);
}
}
@ -432,7 +428,7 @@ void exit_from_channel(int status)
multiqueue_put(main_loop.fast_events, exit_event, (void *)(intptr_t)status);
}
static void on_proc_exit(Proc *proc)
static void on_process_exit(Process *proc)
{
Loop *loop = proc->loop;
ILOG("exited: pid=%d status=%d stoptime=%" PRIu64, proc->pid, proc->status,
@ -445,13 +441,13 @@ static void on_proc_exit(Proc *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 proc_close_handles() as an event.
// queueing process_close_handles() as an event.
MultiQueue *queue = proc->events ? proc->events : loop->events;
CREATE_EVENT(queue, proc_close_handles, proc);
CREATE_EVENT(queue, process_close_handles, proc);
}
static void on_proc_stream_close(Stream *stream, void *data)
static void on_process_stream_close(Stream *stream, void *data)
{
Proc *proc = data;
Process *proc = data;
decref(proc);
}

View File

@ -6,9 +6,9 @@
#include "nvim/event/defs.h" // IWYU pragma: keep
#include "nvim/types_defs.h"
static inline Proc proc_init(Loop *loop, ProcType type, void *data)
static inline Process process_init(Loop *loop, ProcessType type, void *data)
{
return (Proc) {
return (Process) {
.type = type,
.data = data,
.loop = loop,
@ -33,17 +33,17 @@ static inline Proc proc_init(Loop *loop, ProcType type, void *data)
}
/// Get the path to the executable of the process.
static inline const char *proc_get_exepath(Proc *proc)
static inline const char *process_get_exepath(Process *proc)
{
return proc->exepath != NULL ? proc->exepath : proc->argv[0];
}
static inline bool proc_is_stopped(Proc *proc)
static inline bool process_is_stopped(Process *proc)
{
bool exited = (proc->status >= 0);
return exited || (proc->stopped_time != 0);
}
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/proc.h.generated.h"
# include "event/process.h.generated.h"
#endif

View File

@ -43,7 +43,7 @@
#include "nvim/eval/userfunc.h"
#include "nvim/event/loop.h"
#include "nvim/event/multiqueue.h"
#include "nvim/event/proc.h"
#include "nvim/event/process.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();
proc_teardown(&main_loop);
process_teardown(&main_loop);
timer_teardown();
server_teardown();
signal_teardown();

View File

@ -84,7 +84,7 @@
#include "nvim/os/input.h"
#include "nvim/os/os.h"
#include "nvim/os/os_defs.h"
#include "nvim/os/proc.h"
#include "nvim/os/process.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_proc_running(const ZeroBlock *b0p, const char *swap_fname)
static int swapfile_process_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_proc_running(b0p, fname_used)) {
if (swapfile_process_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 proc_running;
static int process_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_proc_running(&b0, fname));
tv_dict_add_nr(d, S_LEN("pid"), swapfile_process_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 ((proc_running = swapfile_proc_running(&b0, fname))) {
if ((process_running = swapfile_process_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_proc_running(&b0, fname)) {
if (char_to_long(b0.b0_pid) == 0 || swapfile_process_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)) {
proc_running = swapfile_proc_running(&b0, fname);
process_running = swapfile_process_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;
}
proc_running = 0; // Set by attention_message..swapfile_info.
process_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,
proc_running
process_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 (proc_running && dialog_result >= 4) {
if (process_running && dialog_result >= 4) {
// compensate for missing "Delete it" button
dialog_result++;
}

View File

@ -14,7 +14,7 @@
#include "nvim/event/defs.h"
#include "nvim/event/loop.h"
#include "nvim/event/multiqueue.h"
#include "nvim/event/proc.h"
#include "nvim/event/process.h"
#include "nvim/event/rstream.h"
#include "nvim/event/wstream.h"
#include "nvim/globals.h"

View File

@ -344,7 +344,7 @@ char *os_getenvname_at_index(size_t index)
#endif
}
/// Get the process ID of the Nvim process.
/// Get the process ID of the Neovim process.
///
/// @return the process ID.
int64_t os_get_pid(void)

View File

@ -37,24 +37,24 @@
#include "nvim/log.h"
#include "nvim/memory.h"
#include "nvim/os/proc.h"
#include "nvim/os/process.h"
#ifdef MSWIN
# include "nvim/api/private/helpers.h"
#endif
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/proc.c.generated.h"
# include "os/process.c.generated.h"
#endif
#ifdef MSWIN
static bool os_proc_tree_kill_rec(HANDLE proc, int sig)
static bool os_proc_tree_kill_rec(HANDLE process, int sig)
{
if (proc == NULL) {
if (process == NULL) {
return false;
}
PROCESSENTRY32 pe;
DWORD pid = GetProcessId(proc);
DWORD pid = GetProcessId(process);
if (pid != 0) {
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
@ -77,7 +77,7 @@ static bool os_proc_tree_kill_rec(HANDLE proc, int sig)
}
theend:
return (bool)TerminateProcess(proc, (unsigned)sig);
return (bool)TerminateProcess(process, (unsigned)sig);
}
/// Kills process `pid` and its descendants recursively.
bool os_proc_tree_kill(int pid, int sig)

View File

@ -7,5 +7,5 @@
#endif
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/proc.h.generated.h"
# include "os/process.h.generated.h"
#endif

View File

@ -143,7 +143,7 @@ finished:
return conpty_object;
}
bool os_conpty_spawn(conpty_t *conpty_object, HANDLE *proc_handle, wchar_t *name,
bool os_conpty_spawn(conpty_t *conpty_object, HANDLE *process_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 *proc_handle, wchar_t *name
&pi)) {
return false;
}
*proc_handle = pi.hProcess;
*process_handle = pi.hProcess;
return true;
}

View File

@ -1,7 +0,0 @@
#pragma once
#ifdef MSWIN
# include "nvim/os/pty_proc_win.h"
#else
# include "nvim/os/pty_proc_unix.h"
#endif

View File

@ -0,0 +1,7 @@
#pragma once
#ifdef MSWIN
# include "nvim/os/pty_process_win.h"
#else
# include "nvim/os/pty_process_unix.h"
#endif

View File

@ -34,16 +34,16 @@
#include "nvim/eval/typval.h"
#include "nvim/event/defs.h"
#include "nvim/event/loop.h"
#include "nvim/event/proc.h"
#include "nvim/event/process.h"
#include "nvim/log.h"
#include "nvim/os/fs.h"
#include "nvim/os/os_defs.h"
#include "nvim/os/pty_proc.h"
#include "nvim/os/pty_proc_unix.h"
#include "nvim/os/pty_process.h"
#include "nvim/os/pty_process_unix.h"
#include "nvim/types_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/pty_proc_unix.c.generated.h"
# include "os/pty_process_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_proc_spawn(PtyProc *ptyproc)
int pty_process_spawn(PtyProcess *ptyproc)
FUNC_ATTR_NONNULL_ALL
{
// termios initialized at first use
@ -168,7 +168,7 @@ int pty_proc_spawn(PtyProc *ptyproc)
}
int status = 0; // zero or negative error code (libuv convention)
Proc *proc = (Proc *)ptyproc;
Process *proc = (Process *)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_proc_tty_name(PtyProc *ptyproc)
const char *pty_process_tty_name(PtyProcess *ptyproc)
{
return ptsname(ptyproc->tty_fd);
}
void pty_proc_resize(PtyProc *ptyproc, uint16_t width, uint16_t height)
void pty_process_resize(PtyProcess *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_proc_close(PtyProc *ptyproc)
void pty_process_close(PtyProcess *ptyproc)
FUNC_ATTR_NONNULL_ALL
{
pty_proc_close_master(ptyproc);
Proc *proc = (Proc *)ptyproc;
pty_process_close_master(ptyproc);
Process *proc = (Process *)ptyproc;
if (proc->internal_close_cb) {
proc->internal_close_cb(proc);
}
}
void pty_proc_close_master(PtyProc *ptyproc) FUNC_ATTR_NONNULL_ALL
void pty_process_close_master(PtyProcess *ptyproc) FUNC_ATTR_NONNULL_ALL
{
if (ptyproc->tty_fd >= 0) {
close(ptyproc->tty_fd);
@ -254,12 +254,12 @@ void pty_proc_close_master(PtyProc *ptyproc) FUNC_ATTR_NONNULL_ALL
}
}
void pty_proc_teardown(Loop *loop)
void pty_process_teardown(Loop *loop)
{
uv_signal_stop(&loop->children_watcher);
}
static void init_child(PtyProc *ptyproc)
static void init_child(PtyProcess *ptyproc)
FUNC_ATTR_NONNULL_ALL
{
#if defined(HAVE__NSGETENVIRON)
@ -277,13 +277,13 @@ static void init_child(PtyProc *ptyproc)
signal(SIGTERM, SIG_DFL);
signal(SIGALRM, SIG_DFL);
Proc *proc = (Proc *)ptyproc;
Process *proc = (Process *)ptyproc;
if (proc->cwd && os_chdir(proc->cwd) != 0) {
ELOG("chdir(%s) failed: %s", proc->cwd, strerror(errno));
return;
}
const char *prog = proc_get_exepath(proc);
const char *prog = process_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) {
Proc *proc = (*current)->data;
Process *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)
}
}
PtyProc pty_proc_init(Loop *loop, void *data)
PtyProcess pty_process_init(Loop *loop, void *data)
{
PtyProc rv;
rv.proc = proc_init(loop, kProcTypePty, data);
PtyProcess rv;
rv.process = process_init(loop, kProcessTypePty, data);
rv.width = 80;
rv.height = 24;
rv.tty_fd = -1;

View File

@ -1,5 +1,5 @@
#pragma once
// IWYU pragma: private, include "nvim/os/pty_proc.h"
// IWYU pragma: private, include "nvim/os/pty_process.h"
#include <stdint.h>
#include <sys/ioctl.h>
@ -7,12 +7,12 @@
#include "nvim/event/defs.h"
typedef struct {
Proc proc;
Process process;
uint16_t width, height;
struct winsize winsize;
int tty_fd;
} PtyProc;
} PtyProcess;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/pty_proc_unix.h.generated.h"
# include "os/pty_process_unix.h.generated.h"
#endif

View File

@ -10,20 +10,20 @@
#include "nvim/memory.h"
#include "nvim/os/os.h"
#include "nvim/os/pty_conpty_win.h"
#include "nvim/os/pty_proc_win.h"
#include "nvim/os/pty_process_win.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/pty_proc_win.c.generated.h"
# include "os/pty_process_win.c.generated.h"
#endif
static void CALLBACK pty_proc_finish1(void *context, BOOLEAN unused)
static void CALLBACK pty_process_finish1(void *context, BOOLEAN unused)
FUNC_ATTR_NONNULL_ALL
{
PtyProc *ptyproc = (PtyProc *)context;
Proc *proc = (Proc *)ptyproc;
PtyProcess *ptyproc = (PtyProcess *)context;
Process *proc = (Process *)ptyproc;
os_conpty_free(ptyproc->conpty);
// NB: pty_proc_finish1() is called on a separate thread,
// NB: pty_process_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_proc_finish1(void *context, BOOLEAN unused)
static void start_wait_eof_timer(void **argv)
FUNC_ATTR_NONNULL_ALL
{
PtyProc *ptyproc = (PtyProc *)argv[0];
PtyProcess *ptyproc = (PtyProcess *)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_proc_spawn(PtyProc *ptyproc)
int pty_process_spawn(PtyProcess *ptyproc)
FUNC_ATTR_NONNULL_ALL
{
Proc *proc = (Proc *)ptyproc;
Process *proc = (Process *)ptyproc;
int status = 0;
conpty_t *conpty_object = NULL;
char *in_name = NULL;
char *out_name = NULL;
HANDLE proc_handle = NULL;
HANDLE process_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_proc_spawn(PtyProc *ptyproc)
uv_pipe_connect(in_req,
&proc->in.uv.pipe,
in_name,
pty_proc_connect_cb);
pty_process_connect_cb);
}
if (!proc->out.s.closed) {
@ -77,7 +77,7 @@ int pty_proc_spawn(PtyProc *ptyproc)
uv_pipe_connect(out_req,
&proc->out.s.uv.pipe,
out_name,
pty_proc_connect_cb);
pty_process_connect_cb);
}
if (proc->cwd != NULL) {
@ -105,7 +105,7 @@ int pty_proc_spawn(PtyProc *ptyproc)
}
if (!os_conpty_spawn(conpty_object,
&proc_handle,
&process_handle,
NULL,
cmd_line,
cwd,
@ -114,42 +114,42 @@ int pty_proc_spawn(PtyProc *ptyproc)
status = (int)GetLastError();
goto cleanup;
}
proc->pid = (int)GetProcessId(proc_handle);
proc->pid = (int)GetProcessId(process_handle);
uv_timer_init(&proc->loop->uv, &ptyproc->wait_eof_timer);
ptyproc->wait_eof_timer.data = (void *)ptyproc;
if (!RegisterWaitForSingleObject(&ptyproc->finish_wait,
proc_handle,
pty_proc_finish1,
process_handle,
pty_process_finish1,
ptyproc,
INFINITE,
WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE)) {
abort();
}
// Wait until pty_proc_connect_cb is called.
// Wait until pty_process_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->proc_handle = proc_handle;
ptyproc->process_handle = process_handle;
conpty_object = NULL;
proc_handle = NULL;
process_handle = NULL;
cleanup:
if (status) {
// In the case of an error of MultiByteToWideChar or CreateProcessW.
ELOG("pty_proc_spawn(%s): %s: error code: %d",
ELOG("pty_process_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 (proc_handle != NULL) {
CloseHandle(proc_handle);
if (process_handle != NULL) {
CloseHandle(process_handle);
}
xfree(in_req);
xfree(out_req);
@ -159,32 +159,32 @@ cleanup:
return status;
}
const char *pty_proc_tty_name(PtyProc *ptyproc)
const char *pty_process_tty_name(PtyProcess *ptyproc)
{
return "?";
}
void pty_proc_resize(PtyProc *ptyproc, uint16_t width, uint16_t height)
void pty_process_resize(PtyProcess *ptyproc, uint16_t width, uint16_t height)
FUNC_ATTR_NONNULL_ALL
{
os_conpty_set_size(ptyproc->conpty, width, height);
}
void pty_proc_close(PtyProc *ptyproc)
void pty_process_close(PtyProcess *ptyproc)
FUNC_ATTR_NONNULL_ALL
{
Proc *proc = (Proc *)ptyproc;
Process *proc = (Process *)ptyproc;
pty_proc_close_master(ptyproc);
pty_process_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->proc_handle != NULL) {
CloseHandle(ptyproc->proc_handle);
ptyproc->proc_handle = NULL;
if (ptyproc->process_handle != NULL) {
CloseHandle(ptyproc->process_handle);
ptyproc->process_handle = NULL;
}
if (proc->internal_close_cb) {
@ -192,17 +192,17 @@ void pty_proc_close(PtyProc *ptyproc)
}
}
void pty_proc_close_master(PtyProc *ptyproc)
void pty_process_close_master(PtyProcess *ptyproc)
FUNC_ATTR_NONNULL_ALL
{
}
void pty_proc_teardown(Loop *loop)
void pty_process_teardown(Loop *loop)
FUNC_ATTR_NONNULL_ALL
{
}
static void pty_proc_connect_cb(uv_connect_t *req, int status)
static void pty_process_connect_cb(uv_connect_t *req, int status)
FUNC_ATTR_NONNULL_ALL
{
assert(status == 0);
@ -212,23 +212,23 @@ static void pty_proc_connect_cb(uv_connect_t *req, int status)
static void wait_eof_timer_cb(uv_timer_t *wait_eof_timer)
FUNC_ATTR_NONNULL_ALL
{
PtyProc *ptyproc = wait_eof_timer->data;
Proc *proc = (Proc *)ptyproc;
PtyProcess *ptyproc = wait_eof_timer->data;
Process *proc = (Process *)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_proc_finish2(ptyproc);
pty_process_finish2(ptyproc);
}
}
static void pty_proc_finish2(PtyProc *ptyproc)
static void pty_process_finish2(PtyProcess *ptyproc)
FUNC_ATTR_NONNULL_ALL
{
Proc *proc = (Proc *)ptyproc;
Process *proc = (Process *)ptyproc;
DWORD exit_code = 0;
GetExitCodeProcess(ptyproc->proc_handle, &exit_code);
GetExitCodeProcess(ptyproc->process_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;
}
PtyProc pty_proc_init(Loop *loop, void *data)
PtyProcess pty_process_init(Loop *loop, void *data)
{
PtyProc rv;
rv.proc = proc_init(loop, kProcTypePty, data);
PtyProcess rv;
rv.process = process_init(loop, kProcessTypePty, data);
rv.width = 80;
rv.height = 24;
rv.conpty = NULL;
rv.finish_wait = NULL;
rv.proc_handle = NULL;
rv.process_handle = NULL;
return rv;
}

View File

@ -1,20 +1,20 @@
#pragma once
// IWYU pragma: private, include "nvim/os/pty_proc.h"
// IWYU pragma: private, include "nvim/os/pty_process.h"
#include <uv.h>
#include "nvim/event/proc.h"
#include "nvim/event/process.h"
#include "nvim/lib/queue_defs.h"
#include "nvim/os/pty_conpty_win.h"
typedef struct pty_process {
Proc proc;
Process process;
uint16_t width, height;
conpty_t *conpty;
HANDLE finish_wait;
HANDLE proc_handle;
HANDLE process_handle;
uv_timer_t wait_eof_timer;
} PtyProc;
} PtyProcess;
// 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_proc_win.h.generated.h"
# include "os/pty_process_win.h.generated.h"
#endif

View File

@ -14,10 +14,10 @@
#include "nvim/eval.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/event/defs.h"
#include "nvim/event/libuv_proc.h"
#include "nvim/event/libuv_process.h"
#include "nvim/event/loop.h"
#include "nvim/event/multiqueue.h"
#include "nvim/event/proc.h"
#include "nvim/event/process.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);
LibuvProc uvproc = libuv_proc_init(&main_loop, &buf);
Proc *proc = &uvproc.proc;
LibuvProcess uvproc = libuv_process_init(&main_loop, &buf);
Process *proc = &uvproc.process;
MultiQueue *events = multiqueue_new_child(main_loop.events);
proc->events = events;
proc->argv = argv;
int status = proc_spawn(proc, has_input, true, true);
int status = process_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
proc_stop(proc);
process_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 = proc_wait(proc, -1, NULL);
int exitcode = process_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);

View File

@ -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 proc_name name of the current Nvim process to write in the report.
void time_init(const char *fname, const char *proc_name)
/// @param process_name name of the current Nvim process to write in the report.
void time_init(const char *fname, const char *process_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 *proc_name)
semsg("time_init: setvbuf failed: %d %s", r, uv_err_name(r));
return;
}
fprintf(time_fd, "--- Startup times for process: %s ---\n", proc_name);
fprintf(time_fd, "--- Startup times for process: %s ---\n", process_name);
}
/// Flushes the startuptimes to disk for the current process

View File

@ -6875,8 +6875,7 @@ 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)
|| mark_quickfix_user_data(win->w_llist_ref, copyID)) {
if (mark_quickfix_ctx(win->w_llist_ref, copyID)) {
return true;
}
}

View File

@ -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_proc_exit:400: exited: pid=58017 status=0 stoptime=0
INF 2022-06-15T18:37:45.229 T57.58016.0 on_process_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):

View File

@ -1,12 +1,16 @@
local uv = vim.uv
local MsgpackRpcStream = require('test.client.msgpack_rpc_stream')
--- Nvim msgpack RPC session.
---
--- @class test.Session
--- @field private _pending_messages string[]
--- @field private _msgpack_rpc_stream test.MsgpackRpcStream
--- @field private _prepare uv.uv_prepare_t
--- @field private _timer uv.uv_timer_t
--- @field private _is_running boolean
--- @field private _stdout_buffer string[] Stores stdout chunks
--- @field public stdout string Full stdout after the process exits
local Session = {}
Session.__index = Session
if package.loaded['jit'] then
@ -50,6 +54,7 @@ local function coroutine_exec(func, ...)
end))
end
--- Creates a new msgpack RPC session.
function Session.new(stream)
return setmetatable({
_msgpack_rpc_stream = MsgpackRpcStream.new(stream),
@ -114,7 +119,6 @@ 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)
@ -203,8 +207,8 @@ function Session:_run(request_cb, notification_cb, timeout)
end)
end
self._msgpack_rpc_stream:read_start(request_cb, notification_cb, function()
uv.stop()
self.eof_err = { 1, 'EOF was received from Nvim. Likely the Nvim process crashed.' }
uv.stop()
self.eof_err = { 1, 'EOF was received from Nvim. Likely the Nvim process crashed.' }
end)
uv.run()
self._prepare:stop()
@ -212,4 +216,5 @@ function Session:_run(request_cb, notification_cb, timeout)
self._msgpack_rpc_stream:read_stop()
end
--- Nvim msgpack RPC session.
return Session

View File

@ -119,6 +119,36 @@ end
local ChildProcessStream = {}
ChildProcessStream.__index = ChildProcessStream
function ChildProcessStream:get_stdout_sync()
local output_buffer = {}
local done = false
local error_message = nil
self._child_stdout:read_start(function(err, chunk)
if err then
error_message = err
done = true
elseif chunk then
table.insert(output_buffer, chunk)
else
-- End of stdout
self._child_stdout:read_stop()
done = true
end
end)
-- Run the libuv event loop until we're done reading
while not done do
uv.run("once")
end
if error_message then
error(error_message)
end
return table.concat(output_buffer)
end
--- @param argv string[]
--- @param env string[]?
--- @param io_extra uv.uv_pipe_t?

View File

@ -1,6 +1,6 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local tt = require('test.functional.testterm')
local tt = require('test.functional.terminal.testutil')
local clear = n.clear
local feed_command = n.feed_command

View File

@ -1,6 +1,6 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local tt = require('test.functional.testterm')
local tt = require('test.functional.terminal.testutil')
local uv = vim.uv
local clear, command, testprg = n.clear, n.command, n.testprg
@ -199,7 +199,7 @@ end)
describe('autocmd TextChangedT', function()
clear()
local screen = tt.setup_screen()
local screen = tt.screen_setup()
it('works', function()
command('autocmd TextChangedT * ++once let g:called = 1')

View File

@ -1,7 +1,7 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
local tt = require('test.functional.testterm')
local tt = require('test.functional.terminal.testutil')
local clear = n.clear
local eq = t.eq

View File

@ -1,6 +1,6 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local tt = require('test.functional.testterm')
local tt = require('test.functional.terminal.testutil')
local assert_log = t.assert_log
local clear = n.clear

View File

@ -38,6 +38,12 @@ local testlog = 'Xtest-startupspec-log'
describe('startup', function()
it('--clean', function()
local s = clear({
args = { '--listen' },
args_rm = { '--embed' },
})
eq('x', s)
clear()
matches(
vim.pesc(t.fix_slashes(fn.stdpath('config'))),

View File

@ -157,28 +157,5 @@ describe('vim.ui', function()
exec_lua [[local _, err = vim.ui.open('foo') ; return err]]
)
end)
it('opt.cmd #29490', function()
t.matches(
'ENOENT: no such file or directory',
t.pcall_err(exec_lua, function()
vim.ui.open('foo', { cmd = { 'non-existent-tool' } })
end)
)
eq(
{
code = 0,
signal = 0,
stderr = '',
stdout = 'arg1=arg1;arg2=https://example.com;',
},
exec_lua(function(cmd_)
local cmd, err = vim.ui.open('https://example.com', { cmd = cmd_ })
assert(cmd and not err)
return cmd:wait()
end, { n.testprg('printargs-test'), 'arg1' })
)
end)
end)
end)

View File

@ -1,7 +1,7 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local tt = require('test.functional.testterm')
local tt = require('test.functional.terminal.testutil')
local clear, eq, api = n.clear, t.eq, n.api
local feed = n.feed
local feed_data = tt.feed_data
@ -17,7 +17,7 @@ describe(':terminal altscreen', function()
before_each(function()
clear()
screen = tt.setup_screen()
screen = tt.screen_setup()
feed_data({
'line1',
'line2',

View File

@ -1,7 +1,7 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local tt = require('test.functional.testterm')
local tt = require('test.functional.terminal.testutil')
local ok = t.ok
if t.skip(t.is_os('win')) then

View File

@ -1,7 +1,7 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
local tt = require('test.functional.testterm')
local tt = require('test.functional.terminal.testutil')
local assert_alive = n.assert_alive
local feed, clear = n.feed, n.clear
@ -29,7 +29,7 @@ describe(':terminal buffer', function()
before_each(function()
clear()
command('set modifiable swapfile undolevels=20')
screen = tt.setup_screen()
screen = tt.screen_setup()
end)
it('terminal-mode forces various options', function()
@ -574,7 +574,7 @@ if is_os('win') then
feed_command('set modifiable swapfile undolevels=20')
poke_eventloop()
local cmd = { 'cmd.exe', '/K', 'PROMPT=$g$s' }
screen = tt.setup_screen(nil, cmd)
screen = tt.screen_setup(nil, cmd)
end)
it('"put" operator sends data normally', function()

View File

@ -1,7 +1,7 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
local tt = require('test.functional.testterm')
local tt = require('test.functional.terminal.testutil')
local feed, clear = n.feed, n.clear
local testprg, command = n.testprg, n.command
@ -18,7 +18,7 @@ describe(':terminal cursor', function()
before_each(function()
clear()
screen = tt.setup_screen()
screen = tt.screen_setup()
end)
it('moves the screen cursor when focused', function()

View File

@ -1,7 +1,7 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
local tt = require('test.functional.testterm')
local tt = require('test.functional.terminal.testutil')
local feed, clear = n.feed, n.clear
local api = n.api

View File

@ -1,7 +1,7 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local tt = require('test.functional.testterm')
local tt = require('test.functional.terminal.testutil')
local clear, eq, eval = n.clear, t.eq, n.eval
local feed, api, command = n.feed, n.api, n.command
local feed_data = tt.feed_data
@ -14,7 +14,7 @@ describe(':terminal mouse', function()
before_each(function()
clear()
api.nvim_set_option_value('statusline', '==========', {})
screen = tt.setup_screen()
screen = tt.screen_setup()
command('highlight StatusLine NONE')
command('highlight StatusLineNC NONE')
command('highlight StatusLineTerm NONE')

View File

@ -1,7 +1,7 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
local tt = require('test.functional.testterm')
local tt = require('test.functional.terminal.testutil')
local clear, eq = n.clear, t.eq
local feed, testprg = n.feed, n.testprg
@ -22,7 +22,7 @@ describe(':terminal scrollback', function()
before_each(function()
clear()
screen = tt.setup_screen(nil, nil, 30)
screen = tt.screen_setup(nil, nil, 30)
end)
describe('when the limit is exceeded', function()
@ -399,9 +399,9 @@ describe("'scrollback' option", function()
it('set to 0 behaves as 1', function()
local screen
if is_os('win') then
screen = tt.setup_screen(nil, { 'cmd.exe' }, 30)
screen = tt.screen_setup(nil, { 'cmd.exe' }, 30)
else
screen = tt.setup_screen(nil, { 'sh' }, 30)
screen = tt.screen_setup(nil, { 'sh' }, 30)
end
api.nvim_set_option_value('scrollback', 0, {})
@ -416,10 +416,10 @@ describe("'scrollback' option", function()
local screen
if is_os('win') then
command([[let $PROMPT='$$']])
screen = tt.setup_screen(nil, { 'cmd.exe' }, 30)
screen = tt.screen_setup(nil, { 'cmd.exe' }, 30)
else
command('let $PS1 = "$"')
screen = tt.setup_screen(nil, { 'sh' }, 30)
screen = tt.screen_setup(nil, { 'sh' }, 30)
end
api.nvim_set_option_value('scrollback', 200, {})
@ -480,8 +480,8 @@ describe("'scrollback' option", function()
end)
it('deletes extra lines immediately', function()
-- Scrollback is 10 on setup_screen
local screen = tt.setup_screen(nil, nil, 30)
-- Scrollback is 10 on screen_setup
local screen = tt.screen_setup(nil, nil, 30)
local lines = {}
for i = 1, 30 do
table.insert(lines, 'line' .. tostring(i))

View File

@ -1,13 +1,6 @@
-- Functions to test :terminal and the Nvim TUI.
-- Starts a child process in a `:terminal` and sends bytes to the child via nvim_chan_send().
-- Note: the global functional/testutil.lua test-session is _host_ session, _not_
-- the child session.
--
-- - Use `setup_screen()` to test `:terminal` behavior with an arbitrary command.
-- - Use `setup_child_nvim()` to test the Nvim TUI.
-- - NOTE: Only use this if your test actually needs the full lifecycle/capabilities of the
-- builtin Nvim TUI. Most tests should just use `Screen.new()` directly, or plain old API calls.
-- To test tui/input.c, this module spawns `nvim` inside :terminal and sends
-- bytes via jobsend(). Note: the functional/testutil.lua test-session methods
-- operate on the _host_ session, _not_ the child session.
local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
@ -16,20 +9,18 @@ local exec_lua = n.exec_lua
local api = n.api
local nvim_prog = n.nvim_prog
local M = {}
function M.feed_data(data)
local function feed_data(data)
if type(data) == 'table' then
data = table.concat(data, '\n')
end
exec_lua('vim.api.nvim_chan_send(vim.b.terminal_job_id, ...)', data)
end
function M.feed_termcode(data)
M.feed_data('\027' .. data)
local function feed_termcode(data)
feed_data('\027' .. data)
end
function M.make_lua_executor(session)
local function make_lua_executor(session)
return function(code, ...)
local status, rv = session:request('nvim_exec_lua', code, { ... })
if not status then
@ -43,68 +34,60 @@ end
-- some t for controlling the terminal. the codes were taken from
-- infocmp xterm-256color which is less what libvterm understands
-- civis/cnorm
function M.hide_cursor()
M.feed_termcode('[?25l')
local function hide_cursor()
feed_termcode('[?25l')
end
function M.show_cursor()
M.feed_termcode('[?25h')
local function show_cursor()
feed_termcode('[?25h')
end
-- smcup/rmcup
function M.enter_altscreen()
M.feed_termcode('[?1049h')
local function enter_altscreen()
feed_termcode('[?1049h')
end
function M.exit_altscreen()
M.feed_termcode('[?1049l')
local function exit_altscreen()
feed_termcode('[?1049l')
end
-- character attributes
function M.set_fg(num)
M.feed_termcode('[38;5;' .. num .. 'm')
local function set_fg(num)
feed_termcode('[38;5;' .. num .. 'm')
end
function M.set_bg(num)
M.feed_termcode('[48;5;' .. num .. 'm')
local function set_bg(num)
feed_termcode('[48;5;' .. num .. 'm')
end
function M.set_bold()
M.feed_termcode('[1m')
local function set_bold()
feed_termcode('[1m')
end
function M.set_italic()
M.feed_termcode('[3m')
local function set_italic()
feed_termcode('[3m')
end
function M.set_underline()
M.feed_termcode('[4m')
local function set_underline()
feed_termcode('[4m')
end
function M.set_underdouble()
M.feed_termcode('[4:2m')
local function set_underdouble()
feed_termcode('[4:2m')
end
function M.set_undercurl()
M.feed_termcode('[4:3m')
local function set_undercurl()
feed_termcode('[4:3m')
end
function M.set_strikethrough()
M.feed_termcode('[9m')
local function set_strikethrough()
feed_termcode('[9m')
end
function M.clear_attrs()
M.feed_termcode('[0;10m')
local function clear_attrs()
feed_termcode('[0;10m')
end
-- mouse
function M.enable_mouse()
M.feed_termcode('[?1002h')
local function enable_mouse()
feed_termcode('[?1002h')
end
function M.disable_mouse()
M.feed_termcode('[?1002l')
local function disable_mouse()
feed_termcode('[?1002l')
end
local default_command = { testprg('tty-test') }
--- Runs `cmd` in a :terminal, and returns a `Screen` object.
---
---@param extra_rows? integer Extra rows to add to the default screen.
---@param cmd? string|string[] Command to run in the terminal (default: `{ 'tty-test' }`)
---@param cols? integer Create screen with this many columns (default: 50)
---@param env? table Environment set on the `cmd` job.
---@param screen_opts? table Options for `Screen.new()`.
---@return test.functional.ui.screen # Screen attached to the global (not child) Nvim session.
function M.setup_screen(extra_rows, cmd, cols, env, screen_opts)
local function screen_setup(extra_rows, command, cols, env, screen_opts)
extra_rows = extra_rows and extra_rows or 0
cmd = cmd and cmd or default_command
command = command and command or default_command
cols = cols and cols or 50
api.nvim_command('highlight TermCursor cterm=reverse')
@ -137,7 +120,7 @@ function M.setup_screen(extra_rows, cmd, cols, env, screen_opts)
screen:attach(screen_opts or { rgb = false })
api.nvim_command('enew')
api.nvim_call_function('termopen', { cmd, env and { env = env } or nil })
api.nvim_call_function('termopen', { command, env and { env = env } or nil })
api.nvim_input('<CR>')
local vim_errmsg = api.nvim_eval('v:errmsg')
if vim_errmsg and '' ~= vim_errmsg then
@ -150,7 +133,7 @@ function M.setup_screen(extra_rows, cmd, cols, env, screen_opts)
-- tty-test puts the terminal into raw mode and echoes input. Tests work by
-- feeding termcodes to control the display and asserting by screen:expect.
if cmd == default_command and screen_opts == nil then
if command == default_command and screen_opts == nil then
-- Wait for "tty ready" to be printed before each test or the terminal may
-- still be in canonical mode (will echo characters for example).
local empty_line = (' '):rep(cols)
@ -177,24 +160,37 @@ function M.setup_screen(extra_rows, cmd, cols, env, screen_opts)
return screen
end
--- Spawns Nvim with `args` in a :terminal, and returns a `Screen` object.
---
--- @note Only use this if you actually need the full lifecycle/capabilities of the builtin Nvim
--- TUI. Most tests should just use `Screen.new()` directly, or plain old API calls.
---
---@param args? string[] Args passed to child Nvim.
---@param opts? table Options
---@return test.functional.ui.screen # Screen attached to the global (not child) Nvim session.
function M.setup_child_nvim(args, opts)
local function setup_child_nvim(args, opts)
opts = opts or {}
local argv = { nvim_prog, unpack(args or {}) }
local argv = { nvim_prog, unpack(args) }
local env = opts.env or {}
if not env.VIMRUNTIME then
env.VIMRUNTIME = os.getenv('VIMRUNTIME')
end
return M.setup_screen(opts.extra_rows, argv, opts.cols, env)
return screen_setup(opts.extra_rows, argv, opts.cols, env)
end
return M
return {
feed_data = feed_data,
feed_termcode = feed_termcode,
make_lua_executor = make_lua_executor,
hide_cursor = hide_cursor,
show_cursor = show_cursor,
enter_altscreen = enter_altscreen,
exit_altscreen = exit_altscreen,
set_fg = set_fg,
set_bg = set_bg,
set_bold = set_bold,
set_italic = set_italic,
set_underline = set_underline,
set_underdouble = set_underdouble,
set_undercurl = set_undercurl,
set_strikethrough = set_strikethrough,
clear_attrs = clear_attrs,
enable_mouse = enable_mouse,
disable_mouse = disable_mouse,
screen_setup = screen_setup,
setup_child_nvim = setup_child_nvim,
}

View File

@ -7,7 +7,7 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
local tt = require('test.functional.testterm')
local tt = require('test.functional.terminal.testutil')
local eq = t.eq
local feed_data = tt.feed_data
@ -2111,7 +2111,7 @@ describe('TUI', function()
finally(function()
os.remove('testF')
end)
local screen = tt.setup_screen(
local screen = tt.screen_setup(
0,
('"%s" -u NONE -i NONE --cmd "set noswapfile noshowcmd noruler" --cmd "normal iabc" > /dev/null 2>&1 && cat testF && rm testF'):format(
nvim_prog

View File

@ -1,7 +1,7 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local tt = require('test.functional.testterm')
local tt = require('test.functional.terminal.testutil')
local feed_data = tt.feed_data
local feed, clear = n.feed, n.clear
local poke_eventloop = n.poke_eventloop
@ -37,7 +37,7 @@ describe(':terminal window', function()
before_each(function()
clear()
screen = tt.setup_screen()
screen = tt.screen_setup()
end)
it('sets topline correctly #8556', function()
@ -198,7 +198,7 @@ describe(':terminal with multigrid', function()
before_each(function()
clear()
screen = tt.setup_screen(0, nil, 50, nil, { ext_multigrid = true })
screen = tt.screen_setup(0, nil, 50, nil, { ext_multigrid = true })
end)
it('resizes to requested size', function()

View File

@ -1,7 +1,7 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local tt = require('test.functional.testterm')
local tt = require('test.functional.terminal.testutil')
local assert_alive = n.assert_alive
local clear = n.clear
local feed = n.feed
@ -22,7 +22,7 @@ describe(':terminal', function()
-- set the statusline to a constant value because of variables like pid
-- and current directory and to improve visibility of splits
api.nvim_set_option_value('statusline', '==========', {})
screen = tt.setup_screen(3)
screen = tt.screen_setup(3)
command('highlight StatusLine NONE')
command('highlight StatusLineNC NONE')
command('highlight StatusLineTerm NONE')

View File

@ -250,8 +250,6 @@ function M.set_method_error(err)
method_error = err
end
--- Runs the event loop of the given session.
---
--- @param lsession test.Session
--- @param request_cb function?
--- @param notification_cb function?
@ -298,7 +296,6 @@ function M.run_session(lsession, request_cb, notification_cb, setup_cb, timeout)
return lsession.eof_err
end
--- Runs the event loop of the current global session.
function M.run(request_cb, notification_cb, setup_cb, timeout)
assert(session)
return M.run_session(session, request_cb, notification_cb, setup_cb, timeout)
@ -458,7 +455,7 @@ end
--- @param argv string[]
--- @param merge boolean?
--- @param env string[]?
--- @param keep boolean
--- @param keep boolean Don't close the current global session.
--- @param io_extra uv.uv_pipe_t? used for stdin_fd, see :help ui-option
--- @return test.Session
function M.spawn(argv, merge, env, keep, io_extra)
@ -468,7 +465,17 @@ function M.spawn(argv, merge, env, keep, io_extra)
local child_stream =
ChildProcessStream.spawn(merge and M.merge_args(prepend_argv, argv) or argv, env, io_extra)
return Session.new(child_stream)
-- local session = Session.new(child_stream)
--
-- -- Run the session (synchronously waits for the process to complete)
-- session:run(function(method, args) end, function(method, args) end)
--
-- -- Access the stdout after the process completes
-- print("Process stdout: " .. (session.stdout or ""))
-- return session
return child_stream:get_stdout_sync()
end
-- Creates a new Session connected by domain socket (named pipe) or TCP.
@ -481,6 +488,8 @@ end
-- Starts (and returns) a new global Nvim session.
--
-- Use `spawn_argv()` to get a new session without replacing the current global session.
--
-- Parameters are interpreted as startup args, OR a map with these keys:
-- args: List: Args appended to the default `nvim_argv` set.
-- args_rm: List: Args removed from the default set. All cases are
@ -496,8 +505,10 @@ function M.clear(...)
return M.get_session()
end
--- same params as clear, but does returns the session instead
--- of replacing the default session
--- Same as clear(), but only returns the session instead of replacing the current global session.
---
--- @param keep boolean Don't close the current global session.
---
--- @return test.Session
function M.spawn_argv(keep, ...)
local argv, env, io_extra = M.new_argv(...)

View File

@ -8,7 +8,6 @@ local exec_lua = n.exec_lua
local pcall_err = t.pcall_err
local matches = t.matches
local insert = n.insert
local NIL = vim.NIL
before_each(clear)
@ -16,12 +15,10 @@ describe('treesitter language API', function()
-- error tests not requiring a parser library
it('handles missing language', function()
eq(
'.../treesitter.lua:0: Parser not found.',
".../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers",
pcall_err(exec_lua, "parser = vim.treesitter.get_parser(0, 'borklang')")
)
eq(NIL, exec_lua("return vim.treesitter._get_parser(0, 'borklang')"))
-- actual message depends on platform
matches(
"Failed to load parser for language 'borklang': uv_dlopen: .+",
@ -108,10 +105,9 @@ describe('treesitter language API', function()
command('set filetype=borklang')
-- Should throw an error when filetype changes to borklang
eq(
'.../treesitter.lua:0: Parser not found.',
".../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers",
pcall_err(exec_lua, "new_parser = vim.treesitter.get_parser(0, 'borklang')")
)
eq(NIL, exec_lua("return vim.treesitter._get_parser(0, 'borklang')"))
end
)

View File

@ -135,7 +135,9 @@ void ui_refresh(void)
insert(test_text)
eq(
'.../treesitter.lua:0: Parser not found.',
'.../treesitter.lua:0: There is no parser available for buffer 1 and one'
.. ' could not be created because lang could not be determined. Either'
.. ' pass lang or set the buffer filetype',
pcall_err(exec_lua, 'vim.treesitter.get_parser(0)')
)

View File

@ -1078,44 +1078,6 @@ describe('CursorLine and CursorLineNr highlights', function()
]])
end)
-- oldtest: Test_cursorline_screenline_resize()
it("'cursorlineopt' screenline is updated on window resize", function()
local screen = Screen.new(75, 8)
screen:attach()
exec([[
50vnew
call setline(1, repeat('xyz ', 30))
setlocal number cursorline cursorlineopt=screenline
normal! $
]])
screen:expect([[
{8: 1 }xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xy |
{8: }z xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz {1:~ }|
{8: }{21:xyz xyz xyz xyz xyz xyz xyz^ }{1:~ }|
{1:~ }{1:~ }|*3
{3:[No Name] [+] }{2:[No Name] }|
|
]])
command('vertical resize -4')
screen:expect([[
{8: 1 }xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xy |
{8: }z xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz {1:~ }|
{8: }{21:xyz xyz xyz xyz xyz xyz xyz xyz xyz^ }{1:~ }|
{1:~ }{1:~ }|*3
{3:[No Name] [+] }{2:[No Name] }|
|
]])
command('set cpoptions+=n')
screen:expect([[
{8: 1 }xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xy |
z xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz {1:~ }|
{21:xyz xyz xyz xyz xyz xyz xyz xyz^ }{1:~ }|
{1:~ }{1:~ }|*3
{3:[No Name] [+] }{2:[No Name] }|
|
]])
end)
-- oldtest: Test_cursorline_after_yank()
it('always updated. vim-patch:8.1.0849', function()
local screen = Screen.new(50, 5)

View File

@ -1,7 +1,7 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
local tt = require('test.functional.testterm')
local tt = require('test.functional.terminal.testutil')
local clear, insert = n.clear, n.insert
local command = n.command

View File

@ -1,7 +1,7 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
local tt = require('test.functional.testterm')
local tt = require('test.functional.terminal.testutil')
local assert_alive = n.assert_alive
local mkdir, write_file, rmdir = t.mkdir, t.write_file, n.rmdir

View File

@ -262,34 +262,14 @@ func Test_cursorline_callback()
call timer_start(300, 'Func')
END
call writefile(lines, 'Xcul_timer', 'D')
call writefile(lines, 'Xcul_timer')
let buf = RunVimInTerminal('-S Xcul_timer', #{rows: 8})
call TermWait(buf, 310)
call VerifyScreenDump(buf, 'Test_cursorline_callback_1', {})
call StopVimInTerminal(buf)
endfunc
func Test_cursorline_screenline_resize()
CheckScreendump
let lines =<< trim END
50vnew
call setline(1, repeat('xyz ', 30))
setlocal number cursorline cursorlineopt=screenline
normal! $
END
call writefile(lines, 'Xcul_screenline_resize', 'D')
let buf = RunVimInTerminal('-S Xcul_screenline_resize', #{rows: 8})
call VerifyScreenDump(buf, 'Test_cursorline_screenline_resize_1', {})
call term_sendkeys(buf, ":vertical resize -4\<CR>")
call VerifyScreenDump(buf, 'Test_cursorline_screenline_resize_2', {})
call term_sendkeys(buf, ":set cpoptions+=n\<CR>")
call VerifyScreenDump(buf, 'Test_cursorline_screenline_resize_3', {})
call StopVimInTerminal(buf)
call delete('Xcul_timer')
endfunc
func Test_cursorline_screenline_update()
@ -300,7 +280,7 @@ func Test_cursorline_screenline_update()
set cursorline cursorlineopt=screenline
inoremap <F2> <Cmd>call cursor(1, 1)<CR>
END
call writefile(lines, 'Xcul_screenline', 'D')
call writefile(lines, 'Xcul_screenline')
let buf = RunVimInTerminal('-S Xcul_screenline', #{rows: 8})
call term_sendkeys(buf, "A")
@ -310,17 +290,7 @@ func Test_cursorline_screenline_update()
call term_sendkeys(buf, "\<Esc>")
call StopVimInTerminal(buf)
endfunc
func Test_cursorline_screenline_zero_width()
CheckOption foldcolumn
set cursorline culopt=screenline winminwidth=1 foldcolumn=1
" This used to crash Vim
1vnew | redraw
bwipe!
set cursorline& culopt& winminwidth& foldcolumn&
call delete('Xcul_screenline')
endfunc
func Test_cursorline_cursorbind_horizontal_scroll()

View File

@ -1150,14 +1150,15 @@ func Test_cfg_file()
unlet g:filetype_cfg
" RAPID cfg
let ext = 'cfg'
for i in ['EIO', 'MMC', 'MOC', 'PROC', 'SIO', 'SYS']
for ext in ['cfg', 'Cfg', 'CFG']
call writefile([i .. ':CFG'], 'cfgfile.' .. ext)
execute "split cfgfile." .. ext
call assert_equal('rapid', &filetype)
bwipe!
call delete('cfgfile.' .. ext)
endfor
call writefile([i .. ':CFG'], 'cfgfile.' .. ext)
execute "split cfgfile." .. ext
call assert_equal('rapid', &filetype)
bwipe!
call delete('cfgfile.' .. ext)
" check different case of file extension
let ext = substitute(ext, '\(\l\)', '\u\1', '')
endfor
" clean up

View File

@ -4071,23 +4071,11 @@ func Test_ll_window_ctx()
enew | only
endfunc
" Similar to the problem above, but for user data.
func Test_ll_window_user_data()
call setloclist(0, [#{bufnr: bufnr(), user_data: {}}])
lopen
wincmd t
close
call test_garbagecollect_now()
call feedkeys("\<CR>", 'tx')
call test_garbagecollect_now()
%bwipe!
endfunc
" The following test used to crash vim
func Test_lfile_crash()
sp Xtest
au QuickFixCmdPre * bw
call assert_fails('lfile', 'E40:')
call assert_fails('lfile', 'E40')
au! QuickFixCmdPre
endfunc