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
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 • Attempting to set an invalid keycode option (e.g. `set t_foo=123`) no longer
gives an error. 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* REMOVED FEATURES *news-removed*

View File

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

View File

@@ -266,29 +266,22 @@ M._complete = function()
return vim.tbl_keys(unique) return vim.tbl_keys(unique)
end end
-- Runs the specified healthchecks. --- Runs the specified healthchecks.
-- Runs all discovered healthchecks if plugin_names is empty. --- 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) --- @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 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 emptybuf = vim.fn.bufnr('$') == 1 and vim.fn.getline(1) == '' and 1 == vim.fn.line('$')
local mod = function()
if splitmod == 'vertical' then -- When no command modifiers are used:
return 'vertical sbuffer' -- - If the current buffer is empty, open healthcheck directly.
elseif splitmod == 'horizontal' then -- - If not specified otherwise open healthcheck in a tab.
return 'horizontal sbuffer' local buf_cmd = #mods > 0 and (mods .. ' sbuffer') or emptybuf and 'buffer' or 'tab 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
local bufnr = vim.api.nvim_create_buf(true, true) 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 if vim.fn.bufexists('health://') == 1 then
vim.cmd.bwipe('health://') 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) void invoke_prompt_callback(void)
{ {
typval_T rettv; typval_T rettv;

View File

@@ -7386,6 +7386,44 @@ void set_pressedreturn(bool val)
ex_pressedreturn = 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) static void ex_terminal(exarg_T *eap)
{ {
char ex_cmd[1024]; char ex_cmd[1024];
@@ -7393,10 +7431,8 @@ static void ex_terminal(exarg_T *eap)
if (cmdmod.cmod_tab > 0 || cmdmod.cmod_split != 0) { if (cmdmod.cmod_tab > 0 || cmdmod.cmod_split != 0) {
bool multi_mods = false; bool multi_mods = false;
// ex_cmd must be a null-terminated string before passing to add_win_cmd_modifiers
// ex_cmd must be a null terminated string before passing to add_win_cmd_modifiers ex_cmd[0] = NUL;
ex_cmd[0] = '\0';
len = add_win_cmd_modifiers(ex_cmd, &cmdmod, &multi_mods); len = add_win_cmd_modifiers(ex_cmd, &cmdmod, &multi_mods);
assert(len < sizeof(ex_cmd)); assert(len < sizeof(ex_cmd));
int result = snprintf(ex_cmd + len, sizeof(ex_cmd) - len, " new"); 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 command = helpers.command
local eq, neq, matches = helpers.eq, helpers.neq, helpers.matches local eq, neq, matches = helpers.eq, helpers.neq, helpers.matches
local getcompletion = helpers.funcs.getcompletion local getcompletion = helpers.funcs.getcompletion
local feed = helpers.feed local insert = helpers.insert
local source = helpers.source local source = helpers.source
local exec_lua = helpers.exec_lua local exec_lua = helpers.exec_lua
@@ -237,16 +237,19 @@ describe(':checkhealth window', function()
]]} ]]}
end) 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) local screen = Screen.new(50, 20)
screen:attach({ext_multigrid=true}) screen:attach({ext_multigrid=true})
command("vertical checkhealth success1") if not emptybuf then
screen:expect{grid=[[ insert('hello')
end
command(mods .. ' checkhealth success1')
screen:expect(([[
## grid 1 ## grid 1
[4:-------------------------]│[2:------------------------]|*19 %s
[3:--------------------------------------------------]| [3:--------------------------------------------------]|
## grid 2 ## grid 2
| %s |
~ |*18 ~ |*18
## grid 3 ## grid 3
| |
@@ -265,21 +268,44 @@ describe(':checkhealth window', function()
- OK nothing to see here | - OK nothing to see here |
| |
~ |*4 ~ |*4
]]} ]]):format(left
end) 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) local screen = Screen.new(50, 25)
screen:attach({ext_multigrid=true}) screen:attach({ext_multigrid=true})
command("horizontal checkhealth success1") if not emptybuf then
screen:expect{grid=[[ insert('hello')
end
command(mods .. ' checkhealth success1')
screen:expect(([[
## grid 1 ## grid 1
[4:--------------------------------------------------]|*12 %s
health:// |
[2:--------------------------------------------------]|*11
[3:--------------------------------------------------]| [3:--------------------------------------------------]|
## grid 2 ## grid 2
| %s |
~ |*10 ~ |*10
## grid 3 ## grid 3
| |
@@ -296,74 +322,37 @@ describe(':checkhealth window', function()
report 2 | report 2 |
- OK nothing to see here | - OK nothing to see here |
| |
]]} ]]):format(top
end) and [[
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
[4:--------------------------------------------------]|*12 [4:--------------------------------------------------]|*12
health:// | health:// |
[2:--------------------------------------------------]|*11]]
or ([[
[2:--------------------------------------------------]|*11 [2:--------------------------------------------------]|*11
[3:--------------------------------------------------]| [No Name] %s |
## grid 2 [4:--------------------------------------------------]|*12]]
hello | ):format(emptybuf and ' ' or '[+]'),
~ |*10 emptybuf and ' ' or 'hello')
## grid 3 )
| end
## 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)
it("opens in vsplit window", function() for _, mods in ipairs({ 'horizontal', 'leftabove', 'topleft' }) do
local screen = Screen.new(50, 25) it(('opens in top split window with :%s and no buffer created'):format(mods), function()
screen:attach({ext_multigrid=true}) test_health_split(true, true, mods)
feed('ihello') end)
feed('<esc>') it(('opens in top split window with :%s and non-empty buffer'):format(mods), function()
command("vertical checkhealth success1") test_health_split(true, false, mods)
screen:expect{grid=[[ end)
## grid 1 end
[4:-------------------------]│[2:------------------------]|*24
[3:--------------------------------------------------]| for _, mods in ipairs({ 'rightbelow', 'botright' }) do
## grid 2 it(('opens in bottom split window with :%s and no buffer created'):format(mods), function()
hello | test_health_split(false, true, mods)
~ |*23 end)
## grid 3 it(('opens in bottom split window with :%s and non-empty buffer'):format(mods), function()
| test_health_split(false, false, mods)
## grid 4 end)
^ | end
─────────────────────────|*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)
it("opens in tab", function() it("opens in tab", function()
-- create an empty buffer called "my_buff" -- create an empty buffer called "my_buff"