feat(health): make :checkhealth support more split modifiers (#26731)

This commit is contained in:
zeertzjq 2023-12-25 10:21:13 +08:00 committed by GitHub
parent 2ff2785c39
commit 2877672d70
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 125 additions and 138 deletions

View File

@ -366,7 +366,8 @@ The following changes to existing APIs or features add new behavior.
• Attempting to set an invalid keycode option (e.g. `set t_foo=123`) no longer
gives an error.
• |:checkhealth| buffer can now be opened in a split window using |:vertical| or |:horizontal|.
• |:checkhealth| buffer can now be opened in a split window using modifiers like
|:vertical|, |:horizontal| and |:botright|.
==============================================================================
REMOVED FEATURES *news-removed*

View File

@ -242,9 +242,10 @@ and 'winminwidth' are relevant.
*:hor* *:horizontal*
:hor[izontal] {cmd}
Execute {cmd}. Currently only makes a difference for
`horizontal wincmd =`, which will equalize windows only
horizontally, and |:terminal|, which will open a |terminal|
buffer in a split window.
the following commands:
- `:wincmd =`: equalize windows only horizontally.
- |:terminal|: open a |terminal| buffer in a split window.
- |:checkhealth|: open a healthcheck buffer in a split window.
:lefta[bove] {cmd} *:lefta* *:leftabove*
:abo[veleft] {cmd} *:abo* *:aboveleft*

View File

@ -266,29 +266,22 @@ M._complete = function()
return vim.tbl_keys(unique)
end
-- Runs the specified healthchecks.
-- Runs all discovered healthchecks if plugin_names is empty.
-- splitmod controls how the healthcheck window opens: "vertical", "horizontal" or "tab"
function M._check(splitmod, plugin_names)
--- Runs the specified healthchecks.
--- Runs all discovered healthchecks if plugin_names is empty.
---
--- @param mods string command modifiers that affect splitting a window.
function M._check(mods, plugin_names)
local healthchecks = plugin_names == '' and get_healthcheck('*') or get_healthcheck(plugin_names)
local emptybuf = vim.fn.bufnr('$') == 1 and vim.fn.getline(1) == '' and 1 == vim.fn.line('$')
local mod = function()
if splitmod == 'vertical' then
return 'vertical sbuffer'
elseif splitmod == 'horizontal' then
return 'horizontal sbuffer'
elseif emptybuf then
-- if this is the default buffer when Nvim starts, open healthcheck directly
return 'buffer'
else
-- if not specified otherwise open healthcheck in a tab
return 'tab sbuffer'
end
end
-- When no command modifiers are used:
-- - If the current buffer is empty, open healthcheck directly.
-- - If not specified otherwise open healthcheck in a tab.
local buf_cmd = #mods > 0 and (mods .. ' sbuffer') or emptybuf and 'buffer' or 'tab sbuffer'
local bufnr = vim.api.nvim_create_buf(true, true)
vim.cmd(mod() .. ' ' .. bufnr)
vim.cmd(buf_cmd .. ' ' .. bufnr)
if vim.fn.bufexists('health://') == 1 then
vim.cmd.bwipe('health://')

View File

@ -8810,39 +8810,6 @@ void eval_fmt_source_name_line(char *buf, size_t bufsize)
}
}
/// ":checkhealth [plugins]"
void ex_checkhealth(exarg_T *eap)
{
Error err = ERROR_INIT;
MAXSIZE_TEMP_ARRAY(args, 2);
if (cmdmod.cmod_split & WSP_VERT) {
ADD_C(args, CSTR_AS_OBJ("vertical"));
} else if (cmdmod.cmod_split & WSP_HOR) {
ADD_C(args, CSTR_AS_OBJ("horizontal"));
} else {
ADD_C(args, CSTR_AS_OBJ("tab"));
}
ADD_C(args, CSTR_AS_OBJ(eap->arg));
NLUA_EXEC_STATIC("return vim.health._check(...)", args, &err);
if (!ERROR_SET(&err)) {
return;
}
const char *vimruntime_env = os_getenv("VIMRUNTIME");
if (vimruntime_env == NULL) {
emsg(_("E5009: $VIMRUNTIME is empty or unset"));
} else {
bool rtp_ok = NULL != strstr(p_rtp, vimruntime_env);
if (rtp_ok) {
semsg(_("E5009: Invalid $VIMRUNTIME: %s"), vimruntime_env);
} else {
emsg(_("E5009: Invalid 'runtimepath'"));
}
}
semsg_multiline(err.msg);
api_clear_error(&err);
}
void invoke_prompt_callback(void)
{
typval_T rettv;

View File

@ -7386,6 +7386,44 @@ void set_pressedreturn(bool val)
ex_pressedreturn = val;
}
/// ":checkhealth [plugins]"
static void ex_checkhealth(exarg_T *eap)
{
Error err = ERROR_INIT;
MAXSIZE_TEMP_ARRAY(args, 2);
char mods[1024];
size_t mods_len = 0;
mods[0] = NUL;
if (cmdmod.cmod_tab > 0 || cmdmod.cmod_split != 0) {
bool multi_mods = false;
mods_len = add_win_cmd_modifiers(mods, &cmdmod, &multi_mods);
assert(mods_len < sizeof(mods));
}
ADD_C(args, STRING_OBJ(((String){ .data = mods, .size = mods_len })));
ADD_C(args, CSTR_AS_OBJ(eap->arg));
NLUA_EXEC_STATIC("return vim.health._check(...)", args, &err);
if (!ERROR_SET(&err)) {
return;
}
const char *vimruntime_env = os_getenv("VIMRUNTIME");
if (vimruntime_env == NULL) {
emsg(_("E5009: $VIMRUNTIME is empty or unset"));
} else {
bool rtp_ok = NULL != strstr(p_rtp, vimruntime_env);
if (rtp_ok) {
semsg(_("E5009: Invalid $VIMRUNTIME: %s"), vimruntime_env);
} else {
emsg(_("E5009: Invalid 'runtimepath'"));
}
}
semsg_multiline(err.msg);
api_clear_error(&err);
}
static void ex_terminal(exarg_T *eap)
{
char ex_cmd[1024];
@ -7393,10 +7431,8 @@ static void ex_terminal(exarg_T *eap)
if (cmdmod.cmod_tab > 0 || cmdmod.cmod_split != 0) {
bool multi_mods = false;
// ex_cmd must be a null terminated string before passing to add_win_cmd_modifiers
ex_cmd[0] = '\0';
// ex_cmd must be a null-terminated string before passing to add_win_cmd_modifiers
ex_cmd[0] = NUL;
len = add_win_cmd_modifiers(ex_cmd, &cmdmod, &multi_mods);
assert(len < sizeof(ex_cmd));
int result = snprintf(ex_cmd + len, sizeof(ex_cmd) - len, " new");

View File

@ -6,7 +6,7 @@ local curbuf_contents = helpers.curbuf_contents
local command = helpers.command
local eq, neq, matches = helpers.eq, helpers.neq, helpers.matches
local getcompletion = helpers.funcs.getcompletion
local feed = helpers.feed
local insert = helpers.insert
local source = helpers.source
local exec_lua = helpers.exec_lua
@ -237,16 +237,19 @@ describe(':checkhealth window', function()
]]}
end)
it("opens in vsplit window when no buffer created", function()
local function test_health_vsplit(left, emptybuf, mods)
local screen = Screen.new(50, 20)
screen:attach({ext_multigrid=true})
command("vertical checkhealth success1")
screen:expect{grid=[[
if not emptybuf then
insert('hello')
end
command(mods .. ' checkhealth success1')
screen:expect(([[
## grid 1
[4:-------------------------]│[2:------------------------]|*19
%s
[3:--------------------------------------------------]|
## grid 2
|
%s |
~ |*18
## grid 3
|
@ -265,21 +268,44 @@ describe(':checkhealth window', function()
- OK nothing to see here |
|
~ |*4
]]}
end)
]]):format(left
and '[4:-------------------------]│[2:------------------------]|*19'
or '[2:------------------------]│[4:-------------------------]|*19',
emptybuf and ' ' or 'hello')
)
end
it("opens in split window when no buffer created", function()
for _, mods in ipairs({ 'vertical', 'leftabove vertical', 'topleft vertical' }) do
it(('opens in left vsplit window with :%s and no buffer created'):format(mods), function()
test_health_vsplit(true, true, mods)
end)
it(('opens in left vsplit window with :%s and non-empty buffer'):format(mods), function()
test_health_vsplit(true, false, mods)
end)
end
for _, mods in ipairs({ 'rightbelow vertical', 'botright vertical' }) do
it(('opens in right vsplit window with :%s and no buffer created'):format(mods), function()
test_health_vsplit(false, true, mods)
end)
it(('opens in right vsplit window with :%s and non-empty buffer'):format(mods), function()
test_health_vsplit(false, false, mods)
end)
end
local function test_health_split(top, emptybuf, mods)
local screen = Screen.new(50, 25)
screen:attach({ext_multigrid=true})
command("horizontal checkhealth success1")
screen:expect{grid=[[
if not emptybuf then
insert('hello')
end
command(mods .. ' checkhealth success1')
screen:expect(([[
## grid 1
[4:--------------------------------------------------]|*12
health:// |
[2:--------------------------------------------------]|*11
%s
[3:--------------------------------------------------]|
## grid 2
|
%s |
~ |*10
## grid 3
|
@ -296,74 +322,37 @@ describe(':checkhealth window', function()
report 2 |
- OK nothing to see here |
|
]]}
end)
it("opens in split window", function()
local screen = Screen.new(50, 25)
screen:attach({ext_multigrid=true})
feed('ihello')
feed('<esc>')
command("horizontal checkhealth success1")
screen:expect{grid=[[
## grid 1
]]):format(top
and [[
[4:--------------------------------------------------]|*12
health:// |
[2:--------------------------------------------------]|*11]]
or ([[
[2:--------------------------------------------------]|*11
[3:--------------------------------------------------]|
## grid 2
hello |
~ |*10
## grid 3
|
## grid 4
^ |
|
|
test_plug.success1: require("test_plug.success1. |
health").check() |
|
report 1 |
- OK everything is fine |
|
report 2 |
- OK nothing to see here |
|
]]}
end)
[No Name] %s |
[4:--------------------------------------------------]|*12]]
):format(emptybuf and ' ' or '[+]'),
emptybuf and ' ' or 'hello')
)
end
it("opens in vsplit window", function()
local screen = Screen.new(50, 25)
screen:attach({ext_multigrid=true})
feed('ihello')
feed('<esc>')
command("vertical checkhealth success1")
screen:expect{grid=[[
## grid 1
[4:-------------------------]│[2:------------------------]|*24
[3:--------------------------------------------------]|
## grid 2
hello |
~ |*23
## grid 3
|
## grid 4
^ |
|*3
|
test_plug.success1: |
require("test_plug. |
success1.health").check()|
|
report 1 |
- OK everything is fine |
|
report 2 |
- OK nothing to see here |
|
~ |*9
]]}
end)
for _, mods in ipairs({ 'horizontal', 'leftabove', 'topleft' }) do
it(('opens in top split window with :%s and no buffer created'):format(mods), function()
test_health_split(true, true, mods)
end)
it(('opens in top split window with :%s and non-empty buffer'):format(mods), function()
test_health_split(true, false, mods)
end)
end
for _, mods in ipairs({ 'rightbelow', 'botright' }) do
it(('opens in bottom split window with :%s and no buffer created'):format(mods), function()
test_health_split(false, true, mods)
end)
it(('opens in bottom split window with :%s and non-empty buffer'):format(mods), function()
test_health_split(false, false, mods)
end)
end
it("opens in tab", function()
-- create an empty buffer called "my_buff"