refactor(lua): use vim.system #34707

This commit is contained in:
Yochem van Rosmalen
2025-07-24 05:03:30 +02:00
committed by GitHub
parent 54b8c99e51
commit 35af766de6
9 changed files with 77 additions and 61 deletions

View File

@@ -277,7 +277,7 @@ add_glob_target(
TOUCH_STRATEGY PER_DIR)
add_custom_target(lintcommit
COMMAND $<TARGET_FILE:nvim_bin> -u NONE -l ${PROJECT_SOURCE_DIR}/scripts/lintcommit.lua main)
COMMAND $<TARGET_FILE:nvim_bin> --clean -l ${PROJECT_SOURCE_DIR}/scripts/lintcommit.lua main)
add_dependencies(lintcommit nvim_bin)
add_custom_target(lint)

View File

@@ -3895,7 +3895,7 @@ conforming to the https://semver.org spec. Plugins, and plugin managers, can
use this to check available tools and dependencies on the current system.
Example: >lua
local v = vim.version.parse(vim.fn.system({'tmux', '-V'}), {strict=false})
local v = vim.version.parse(vim.system({'tmux', '-V'}):wait().stdout, {strict=false})
if vim.version.gt(v, {3, 2, 0}) then
-- ...
end

View File

@@ -76,7 +76,7 @@ vim.api.nvim_create_autocmd('TextYankPost', {
vim.api.nvim_create_user_command('GitBlameLine', function()
local line_number = vim.fn.line('.') -- Get the current line number. See `:h line()`
local filename = vim.api.nvim_buf_get_name(0)
print(vim.fn.system({ 'git', 'blame', '-L', line_number .. ',+1', filename }))
print(vim.system({ 'git', 'blame', '-L', line_number .. ',+1', filename }):wait().stdout)
end, { desc = 'Print the git blame for the current line' })
-- [[ Add optional packages ]]

View File

@@ -1,8 +1,13 @@
local M = {}
local health = require('vim.health')
local shell_error = function()
return vim.v.shell_error ~= 0
---Run a system command and return ok and its stdout and stderr combined.
---@param cmd string[]
---@return boolean
---@return string
local function system(cmd)
local result = vim.system(cmd, { text = true }):wait()
return result.code == 0, vim.trim(('%s\n%s'):format(result.stdout, result.stderr))
end
local suggest_faq = 'https://github.com/neovim/neovim/blob/master/BUILD.md#building'
@@ -168,10 +173,10 @@ local function check_performance()
end
-- check for slow shell invocation
local slow_cmd_time = 1.5
local start_time = vim.fn.reltime()
vim.fn.system('echo')
local elapsed_time = vim.fn.reltimefloat(vim.fn.reltime(start_time))
local slow_cmd_time = 1.5e9
local start_time = vim.uv.hrtime()
system({ 'echo' })
local elapsed_time = vim.uv.hrtime() - start_time
if elapsed_time > slow_cmd_time then
health.warn(
'Slow shell invocation (took ' .. vim.fn.printf('%.2f', elapsed_time) .. ' seconds).'
@@ -252,17 +257,17 @@ local function check_tmux()
---@param option string
local get_tmux_option = function(option)
local cmd = 'tmux show-option -qvg ' .. option -- try global scope
local out = vim.fn.system(vim.fn.split(cmd))
local cmd = { 'tmux', 'show-option', '-qvg', option } -- try global scope
local ok, out = system(cmd)
local val = vim.fn.substitute(out, [[\v(\s|\r|\n)]], '', 'g')
if shell_error() then
if not ok then
health.error('command failed: ' .. cmd .. '\n' .. out)
return 'error'
elseif val == '' then
cmd = 'tmux show-option -qvgs ' .. option -- try session scope
out = vim.fn.system(vim.fn.split(cmd))
cmd = { 'tmux', 'show-option', '-qvgs', option } -- try session scope
ok, out = system(cmd)
val = vim.fn.substitute(out, [[\v(\s|\r|\n)]], '', 'g')
if shell_error() then
if not ok then
health.error('command failed: ' .. cmd .. '\n' .. out)
return 'error'
end
@@ -301,16 +306,16 @@ local function check_tmux()
-- check default-terminal and $TERM
health.info('$TERM: ' .. vim.env.TERM)
local cmd = 'tmux show-option -qvg default-terminal'
local out = vim.fn.system(vim.fn.split(cmd))
local cmd = { 'tmux', 'show-option', '-qvg', 'default-terminal' }
local ok, out = system(cmd)
local tmux_default_term = vim.fn.substitute(out, [[\v(\s|\r|\n)]], '', 'g')
if tmux_default_term == '' then
cmd = 'tmux show-option -qvgs default-terminal'
out = vim.fn.system(vim.fn.split(cmd))
cmd = { 'tmux', 'show-option', '-qvgs', 'default-terminal' }
ok, out = system(cmd)
tmux_default_term = vim.fn.substitute(out, [[\v(\s|\r|\n)]], '', 'g')
end
if shell_error() then
if not ok then
health.error('command failed: ' .. cmd .. '\n' .. out)
elseif tmux_default_term ~= vim.env.TERM then
health.info('default-terminal: ' .. tmux_default_term)
@@ -329,7 +334,7 @@ local function check_tmux()
end
-- check for RGB capabilities
local info = vim.fn.system({ 'tmux', 'show-messages', '-T' })
local _, info = system({ 'tmux', 'show-messages', '-T' })
local has_setrgbb = vim.fn.stridx(info, ' setrgbb: (string)') ~= -1
local has_setrgbf = vim.fn.stridx(info, ' setrgbf: (string)') ~= -1
if not has_setrgbb or not has_setrgbf then
@@ -349,13 +354,13 @@ local function check_terminal()
end
health.start('terminal')
local cmd = 'infocmp -L'
local out = vim.fn.system(vim.fn.split(cmd))
local cmd = { 'infocmp', '-L' }
local ok, out = system(cmd)
local kbs_entry = vim.fn.matchstr(out, 'key_backspace=[^,[:space:]]*')
local kdch1_entry = vim.fn.matchstr(out, 'key_dc=[^,[:space:]]*')
if
shell_error()
not ok
and (
vim.fn.has('win32') == 0
or vim.fn.matchstr(

View File

@@ -4,8 +4,13 @@ local iswin = vim.fn.has('win32') == 1
local M = {}
local function cmd_ok(cmd)
local out = vim.fn.system(cmd)
return vim.v.shell_error == 0, out
local result = vim.system(cmd, { text = true }):wait()
return result.code == 0, result.stdout
end
local function cli_version(cmd)
local ok, out = cmd_ok(cmd)
return ok, vim.version.parse(out, { strict = false })
end
-- Attempts to construct a shell command from an args list.
@@ -127,14 +132,14 @@ local function clipboard()
os.getenv('TMUX')
and vim.fn.executable('tmux') == 1
and vim.fn.executable('pbpaste') == 1
and not cmd_ok('pbpaste')
and not cmd_ok({ 'pbpaste' })
then
local tmux_version = string.match(vim.fn.system('tmux -V'), '%d+%.%d+')
local _, tmux_version = cli_version({ 'tmux', '-V' })
local advice = {
'Install tmux 2.6+. https://superuser.com/q/231130',
'or use tmux with reattach-to-user-namespace. https://superuser.com/a/413233',
}
health.error('pbcopy does not work with tmux version: ' .. tmux_version, advice)
health.error('pbcopy does not work with tmux version: ' .. tostring(tmux_version), advice)
end
local clipboard_tool = vim.fn['provider#clipboard#Executable']() ---@type string
@@ -178,9 +183,8 @@ local function node()
return
end
-- local node_v = vim.fn.split(system({'node', '-v'}), "\n")[1] or ''
local ok, node_v = cmd_ok({ 'node', '-v' })
health.info('Node.js: ' .. node_v)
local ok, node_v = cli_version({ 'node', '-v' })
health.info('Node.js: ' .. tostring(node_v))
if not ok or vim.version.lt(node_v, '6.0.0') then
health.warn('Nvim node.js host does not support Node ' .. node_v)
-- Skip further checks, they are nonsense if nodejs is too old.
@@ -213,13 +217,14 @@ local function node()
end
local latest_npm_cmd = (
iswin and 'cmd /c ' .. manager .. ' info neovim --json' or manager .. ' info neovim --json'
iswin and { 'cmd', '/c', manager, 'info', 'neovim', '--json' }
or { manager, 'info', 'neovim', '--json' }
)
local latest_npm
ok, latest_npm = cmd_ok(vim.split(latest_npm_cmd, ' '))
ok, latest_npm = cmd_ok(latest_npm_cmd)
if not ok or latest_npm:find('^%s$') then
health.error(
'Failed to run: ' .. latest_npm_cmd,
'Failed to run: ' .. shellify(latest_npm_cmd),
{ "Make sure you're connected to the internet.", 'Are you behind a firewall or proxy?' }
)
return
@@ -237,8 +242,8 @@ local function node()
ok, current_npm = cmd_ok(current_npm_cmd)
if not ok then
health.error(
'Failed to run: ' .. table.concat(current_npm_cmd, ' '),
{ 'Report this issue with the output of: ', table.concat(current_npm_cmd, ' ') }
'Failed to run: ' .. shellify(current_npm_cmd),
{ 'Report this issue with the output of: ', shellify(current_npm_cmd) }
)
return
end
@@ -298,7 +303,7 @@ local function perl()
ok, latest_cpan = cmd_ok(latest_cpan_cmd)
if not ok or latest_cpan:find('^%s*$') then
health.error(
'Failed to run: ' .. table.concat(latest_cpan_cmd, ' '),
'Failed to run: ' .. shellify(latest_cpan_cmd),
{ "Make sure you're connected to the internet.", 'Are you behind a firewall or proxy?' }
)
return
@@ -329,8 +334,8 @@ local function perl()
ok, current_cpan = cmd_ok(current_cpan_cmd)
if not ok then
health.error(
'Failed to run: ' .. table.concat(current_cpan_cmd, ' '),
{ 'Report this issue with the output of: ', table.concat(current_cpan_cmd, ' ') }
'Failed to run: ' .. shellify(current_cpan_cmd),
{ 'Report this issue with the output of: ', shellify(current_cpan_cmd) }
)
return
end
@@ -426,12 +431,15 @@ end
--- @param url string
local function download(url)
local has_curl = vim.fn.executable('curl') == 1
if has_curl and vim.fn.system({ 'curl', '-V' }):find('Protocols:.*https') then
local out, rc = system({ 'curl', '-sL', url }, { stderr = true, ignore_error = true })
if rc ~= 0 then
return 'curl error with ' .. url .. ': ' .. rc
else
return out
if has_curl then
local ok, out = cmd_ok({ 'curl', '-V' })
if ok and out:find('Protocols:.*https') then
local content, rc = system({ 'curl', '-sL', url }, { stderr = true, ignore_error = true })
if rc ~= 0 then
return 'curl error with ' .. url .. ': ' .. rc
else
return content
end
end
elseif vim.fn.executable('python') == 1 then
local script = ([[
@@ -872,7 +880,8 @@ local function ruby()
)
return
end
health.info('Ruby: ' .. system({ 'ruby', '-v' }))
local _, ruby_v = cli_version({ 'ruby', '-v' })
health.info('Ruby: ' .. tostring(ruby_v))
local host, _ = vim.provider.ruby.detect()
if (not host) or host:find('^%s*$') then
@@ -887,11 +896,14 @@ local function ruby()
end
health.info('Host: ' .. host)
local latest_gem_cmd = (iswin and 'cmd /c gem list -ra "^^neovim$"' or 'gem list -ra ^neovim$')
local ok, latest_gem = cmd_ok(vim.split(latest_gem_cmd, ' '))
local latest_gem_cmd = (
iswin and { 'cmd', '/c', 'gem', 'list', '-ra', '"^^neovim$"' }
or { 'gem', 'list', '-ra', '^neovim$' }
)
local ok, latest_gem = cmd_ok(latest_gem_cmd)
if not ok or latest_gem:find('^%s*$') then
health.error(
'Failed to run: ' .. latest_gem_cmd,
'Failed to run: ' .. shellify(latest_gem_cmd),
{ "Make sure you're connected to the internet.", 'Are you behind a firewall or proxy?' }
)
return
@@ -904,8 +916,8 @@ local function ruby()
ok, current_gem = cmd_ok(current_gem_cmd)
if not ok then
health.error(
'Failed to run: ' .. table.concat(current_gem_cmd, ' '),
{ 'Report this issue with the output of: ', table.concat(current_gem_cmd, ' ') }
'Failed to run: ' .. shellify(current_gem_cmd),
{ 'Report this issue with the output of: ', shellify(current_gem_cmd) }
)
return
end

View File

@@ -25,14 +25,12 @@ function M.detect()
end
-- if perl is available, make sure we have 5.22+
vim.fn.system({ prog, '-e', 'use v5.22' })
if vim.v.shell_error ~= 0 then
if vim.system({ prog, '-e', 'use v5.22' }):wait().code ~= 0 then
return nil, 'Perl version is too old, 5.22+ required'
end
-- if perl is available, make sure the required module is available
vim.fn.system({ prog, '-W', '-MNeovim::Ext', '-e', '' })
if vim.v.shell_error ~= 0 then
if vim.system({ prog, '-W', '-MNeovim::Ext', '-e', '' }):wait().code ~= 0 then
return nil, '"Neovim::Ext" cpan module is not installed'
end
return prog, nil

View File

@@ -45,8 +45,8 @@ function M.detect()
prog = ''
else
-- neovim-ruby-host could be an rbenv shim for another Ruby version.
vim.fn.system(p)
prog = vim.v.shell_error ~= 0 and '' or p
local result = vim.system({ p }):wait()
prog = result.code ~= 0 and '' or p
end
end
local err = prog == '' and 'missing ruby or ruby-host' or ''

View File

@@ -6,7 +6,7 @@
--- Example:
---
--- ```lua
--- local v = vim.version.parse(vim.fn.system({'tmux', '-V'}), {strict=false})
--- local v = vim.version.parse(vim.system({'tmux', '-V'}):wait().stdout, {strict=false})
--- if vim.version.gt(v, {3, 2, 0}) then
--- -- ...
--- end

View File

@@ -27,8 +27,9 @@ local function run(cmd, or_die)
if _trace then
p('run: ' .. vim.inspect(cmd))
end
local rv = vim.trim(vim.fn.system(cmd)) or ''
if vim.v.shell_error ~= 0 then
local res = vim.system(cmd):wait()
local rv = vim.trim(res.stdout)
if res.code ~= 0 then
if or_die then
p(rv)
os.exit(1)