mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
refactor(tui): use nvim_echo() for verbose terminfo
This is needed for #18375 for the obvious reasons. note: verbose_terminfo_event is only temporarily needed until the full TUI process refactor is merged.
This commit is contained in:
parent
f04087d8ba
commit
b42d8a43b9
@ -717,7 +717,7 @@ nvim_del_var({name}) *nvim_del_var()*
|
||||
Parameters: ~
|
||||
• {name} Variable name
|
||||
|
||||
nvim_echo({chunks}, {history}, {opts}) *nvim_echo()*
|
||||
nvim_echo({chunks}, {history}, {*opts}) *nvim_echo()*
|
||||
Echo a message.
|
||||
|
||||
Parameters: ~
|
||||
@ -725,7 +725,11 @@ nvim_echo({chunks}, {history}, {opts}) *nvim_echo()*
|
||||
chunk with specified highlight. `hl_group` element can be
|
||||
omitted for no highlight.
|
||||
• {history} if true, add to |message-history|.
|
||||
• {opts} Optional parameters. Reserved for future use.
|
||||
• {opts} Optional parameters.
|
||||
• verbose: Message was printed as a result of 'verbose'
|
||||
option if Nvim was invoked with -V3log_file, the message
|
||||
will be redirected to the log_file and surpressed from
|
||||
direct output.
|
||||
|
||||
nvim_err_write({str}) *nvim_err_write()*
|
||||
Writes a message to the Vim error buffer. Does not append "\n", the
|
||||
|
@ -219,5 +219,8 @@ return {
|
||||
cmd_opts = {
|
||||
"output";
|
||||
};
|
||||
echo_opts = {
|
||||
"verbose";
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -726,8 +726,11 @@ void nvim_set_vvar(String name, Object value, Error *err)
|
||||
/// text chunk with specified highlight. `hl_group` element
|
||||
/// can be omitted for no highlight.
|
||||
/// @param history if true, add to |message-history|.
|
||||
/// @param opts Optional parameters. Reserved for future use.
|
||||
void nvim_echo(Array chunks, Boolean history, Dictionary opts, Error *err)
|
||||
/// @param opts Optional parameters.
|
||||
/// - verbose: Message was printed as a result of 'verbose' option
|
||||
/// if Nvim was invoked with -V3log_file, the message will be
|
||||
/// redirected to the log_file and surpressed from direct output.
|
||||
void nvim_echo(Array chunks, Boolean history, Dict(echo_opts) *opts, Error *err)
|
||||
FUNC_API_SINCE(7)
|
||||
{
|
||||
HlMessage hl_msg = parse_hl_msg(chunks, err);
|
||||
@ -735,13 +738,19 @@ void nvim_echo(Array chunks, Boolean history, Dictionary opts, Error *err)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (opts.size > 0) {
|
||||
api_set_error(err, kErrorTypeValidation, "opts dict isn't empty");
|
||||
goto error;
|
||||
bool verbose = api_object_to_bool(opts->verbose, "verbose", false, err);
|
||||
|
||||
if (verbose) {
|
||||
verbose_enter();
|
||||
}
|
||||
|
||||
msg_multiattr(hl_msg, history ? "echomsg" : "echo", history);
|
||||
|
||||
if (verbose) {
|
||||
verbose_leave();
|
||||
verbose_stop(); // flush now
|
||||
}
|
||||
|
||||
if (history) {
|
||||
// history takes ownership
|
||||
return;
|
||||
|
@ -418,6 +418,22 @@ char *transstr(const char *const s, bool untab)
|
||||
return buf;
|
||||
}
|
||||
|
||||
size_t kv_transstr(StringBuilder *str, const char *const s, bool untab)
|
||||
FUNC_ATTR_NONNULL_ARG(1)
|
||||
{
|
||||
if (!s) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Compute the length of the result, taking account of unprintable
|
||||
// multi-byte characters.
|
||||
const size_t len = transstr_len(s, untab);
|
||||
kv_ensure_space(*str, len + 1);
|
||||
transstr_buf(s, str->items + str->size, len + 1, untab);
|
||||
str->size += len; // do not include NUL byte
|
||||
return len;
|
||||
}
|
||||
|
||||
/// Convert the string "str[orglen]" to do ignore-case comparing.
|
||||
/// Use the current locale.
|
||||
///
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/option_defs.h"
|
||||
#include "nvim/pos.h"
|
||||
#include "nvim/strings.h"
|
||||
#include "nvim/types.h"
|
||||
|
||||
/// Return the folded-case equivalent of the given character
|
||||
|
@ -2690,7 +2690,7 @@ return {
|
||||
full_name='verbose', abbreviation='vbs',
|
||||
short_desc=N_("give informative messages"),
|
||||
type='number', scope={'global'},
|
||||
varname='p_verbose',
|
||||
varname='p_verbose', redraw={'ui_option'},
|
||||
defaults={if_true=0}
|
||||
},
|
||||
{
|
||||
|
@ -7,10 +7,13 @@
|
||||
#include <string.h>
|
||||
#include <unibilium.h>
|
||||
|
||||
#include "nvim/api/private/helpers.h"
|
||||
#include "nvim/charset.h"
|
||||
#include "nvim/globals.h"
|
||||
#include "nvim/memory.h"
|
||||
#include "nvim/message.h"
|
||||
#include "nvim/option.h"
|
||||
#include "nvim/strings.h"
|
||||
#include "nvim/tui/terminfo.h"
|
||||
#include "nvim/tui/terminfo_defs.h"
|
||||
|
||||
@ -147,82 +150,80 @@ unibi_term *terminfo_from_builtin(const char *term, char **termname)
|
||||
/// Serves a similar purpose as Vim `:set termcap` (removed in Nvim).
|
||||
///
|
||||
/// @note adapted from unibilium unibi-dump.c
|
||||
void terminfo_info_msg(const unibi_term *const ut)
|
||||
/// @return allocated string
|
||||
String terminfo_info_msg(const unibi_term *ut, const char *termname)
|
||||
{
|
||||
if (exiting) {
|
||||
return;
|
||||
}
|
||||
msg_puts_title("\n\n--- Terminal info --- {{{\n");
|
||||
StringBuilder data = KV_INITIAL_VALUE;
|
||||
|
||||
char *term;
|
||||
get_tty_option("term", &term);
|
||||
msg_printf_attr(0, "&term: %s\n", term);
|
||||
msg_printf_attr(0, "Description: %s\n", unibi_get_name(ut));
|
||||
kv_printf(data, "&term: %s\n", termname);
|
||||
kv_printf(data, "Description: %s\n", unibi_get_name(ut));
|
||||
const char **a = unibi_get_aliases(ut);
|
||||
if (*a) {
|
||||
msg_puts("Aliases: ");
|
||||
kv_printf(data, "Aliases: ");
|
||||
do {
|
||||
msg_printf_attr(0, "%s%s\n", *a, a[1] ? " | " : "");
|
||||
kv_printf(data, "%s%s\n", *a, a[1] ? " | " : "");
|
||||
a++;
|
||||
} while (*a);
|
||||
}
|
||||
|
||||
msg_puts("Boolean capabilities:\n");
|
||||
kv_printf(data, "Boolean capabilities:\n");
|
||||
for (enum unibi_boolean i = unibi_boolean_begin_ + 1;
|
||||
i < unibi_boolean_end_; i++) {
|
||||
msg_printf_attr(0, " %-25s %-10s = %s\n", unibi_name_bool(i),
|
||||
unibi_short_name_bool(i),
|
||||
unibi_get_bool(ut, i) ? "true" : "false");
|
||||
kv_printf(data, " %-25s %-10s = %s\n", unibi_name_bool(i),
|
||||
unibi_short_name_bool(i),
|
||||
unibi_get_bool(ut, i) ? "true" : "false");
|
||||
}
|
||||
|
||||
msg_puts("Numeric capabilities:\n");
|
||||
kv_printf(data, "Numeric capabilities:\n");
|
||||
for (enum unibi_numeric i = unibi_numeric_begin_ + 1;
|
||||
i < unibi_numeric_end_; i++) {
|
||||
int n = unibi_get_num(ut, i); // -1 means "empty"
|
||||
msg_printf_attr(0, " %-25s %-10s = %d\n", unibi_name_num(i),
|
||||
unibi_short_name_num(i), n);
|
||||
kv_printf(data, " %-25s %-10s = %d\n", unibi_name_num(i),
|
||||
unibi_short_name_num(i), n);
|
||||
}
|
||||
|
||||
msg_puts("String capabilities:\n");
|
||||
kv_printf(data, "String capabilities:\n");
|
||||
for (enum unibi_string i = unibi_string_begin_ + 1;
|
||||
i < unibi_string_end_; i++) {
|
||||
const char *s = unibi_get_str(ut, i);
|
||||
if (s) {
|
||||
msg_printf_attr(0, " %-25s %-10s = ", unibi_name_str(i),
|
||||
unibi_short_name_str(i));
|
||||
kv_printf(data, " %-25s %-10s = ", unibi_name_str(i),
|
||||
unibi_short_name_str(i));
|
||||
// Most of these strings will contain escape sequences.
|
||||
msg_outtrans_special(s, false, 0);
|
||||
msg_putchar('\n');
|
||||
kv_transstr(&data, s, false);
|
||||
kv_push(data, '\n');
|
||||
}
|
||||
}
|
||||
|
||||
if (unibi_count_ext_bool(ut)) {
|
||||
msg_puts("Extended boolean capabilities:\n");
|
||||
kv_printf(data, "Extended boolean capabilities:\n");
|
||||
for (size_t i = 0; i < unibi_count_ext_bool(ut); i++) {
|
||||
msg_printf_attr(0, " %-25s = %s\n",
|
||||
unibi_get_ext_bool_name(ut, i),
|
||||
unibi_get_ext_bool(ut, i) ? "true" : "false");
|
||||
kv_printf(data, " %-25s = %s\n",
|
||||
unibi_get_ext_bool_name(ut, i),
|
||||
unibi_get_ext_bool(ut, i) ? "true" : "false");
|
||||
}
|
||||
}
|
||||
|
||||
if (unibi_count_ext_num(ut)) {
|
||||
msg_puts("Extended numeric capabilities:\n");
|
||||
kv_printf(data, "Extended numeric capabilities:\n");
|
||||
for (size_t i = 0; i < unibi_count_ext_num(ut); i++) {
|
||||
msg_printf_attr(0, " %-25s = %d\n",
|
||||
unibi_get_ext_num_name(ut, i),
|
||||
unibi_get_ext_num(ut, i));
|
||||
kv_printf(data, " %-25s = %d\n",
|
||||
unibi_get_ext_num_name(ut, i),
|
||||
unibi_get_ext_num(ut, i));
|
||||
}
|
||||
}
|
||||
|
||||
if (unibi_count_ext_str(ut)) {
|
||||
msg_puts("Extended string capabilities:\n");
|
||||
kv_printf(data, "Extended string capabilities:\n");
|
||||
for (size_t i = 0; i < unibi_count_ext_str(ut); i++) {
|
||||
msg_printf_attr(0, " %-25s = ", unibi_get_ext_str_name(ut, i));
|
||||
msg_outtrans_special(unibi_get_ext_str(ut, i), false, 0);
|
||||
msg_putchar('\n');
|
||||
kv_printf(data, " %-25s = ", unibi_get_ext_str_name(ut, i));
|
||||
// NOTE: unibi_get_ext_str(ut, i) might be NULL, as termcap
|
||||
// might include junk data on mac os. kv_transstr will handle this.
|
||||
kv_transstr(&data, unibi_get_ext_str(ut, i), false);
|
||||
kv_push(data, '\n');
|
||||
}
|
||||
}
|
||||
kv_push(data, NUL);
|
||||
|
||||
msg_puts("}}}\n");
|
||||
xfree(term);
|
||||
return cbuf_as_string(data.items, data.size - 1);
|
||||
}
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
#include <unibilium.h>
|
||||
|
||||
#include "nvim/api/private/defs.h"
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "tui/terminfo.h.generated.h"
|
||||
#endif
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include "auto/config.h"
|
||||
#include "klib/kvec.h"
|
||||
#include "nvim/api/private/defs.h"
|
||||
#include "nvim/api/private/helpers.h"
|
||||
#include "nvim/api/vim.h"
|
||||
#include "nvim/ascii.h"
|
||||
#include "nvim/event/defs.h"
|
||||
#include "nvim/event/loop.h"
|
||||
@ -25,10 +27,12 @@
|
||||
#include "nvim/grid_defs.h"
|
||||
#include "nvim/highlight_defs.h"
|
||||
#include "nvim/log.h"
|
||||
#include "nvim/macros.h"
|
||||
#include "nvim/main.h"
|
||||
#include "nvim/mbyte.h"
|
||||
#include "nvim/memory.h"
|
||||
#include "nvim/message.h"
|
||||
#include "nvim/msgpack_rpc/channel.h"
|
||||
#include "nvim/option.h"
|
||||
#include "nvim/os/input.h"
|
||||
#include "nvim/os/os.h"
|
||||
@ -98,6 +102,7 @@ struct TUIData {
|
||||
TermInput input;
|
||||
uv_loop_t write_loop;
|
||||
unibi_term *ut;
|
||||
char *term; // value of $TERM
|
||||
union {
|
||||
uv_tty_t tty;
|
||||
uv_pipe_t pipe;
|
||||
@ -132,6 +137,7 @@ struct TUIData {
|
||||
bool default_attr;
|
||||
bool can_clear_attr;
|
||||
ModeShape showing_mode;
|
||||
Integer verbose;
|
||||
struct {
|
||||
int enable_mouse, disable_mouse;
|
||||
int enable_mouse_move, disable_mouse_move;
|
||||
@ -295,6 +301,7 @@ static void terminfo_start(UI *ui)
|
||||
os_env_var_unlock();
|
||||
if (data->ut) {
|
||||
termname = xstrdup(term);
|
||||
data->term = xstrdup(term);
|
||||
}
|
||||
}
|
||||
if (!data->ut) {
|
||||
@ -509,9 +516,6 @@ static void tui_main(UIBridgeData *bridge, UI *ui)
|
||||
// Allow main thread to continue, we are ready to handle UI callbacks.
|
||||
CONTINUE(bridge);
|
||||
|
||||
loop_schedule_deferred(&main_loop,
|
||||
event_create(show_termcap_event, 1, data->ut));
|
||||
|
||||
// "Active" loop: first ~100 ms of startup.
|
||||
for (size_t ms = 0; ms < 100 && !tui_is_stopped(ui);) {
|
||||
ms += (loop_poll_events(&tui_loop, 20) ? 20 : 1);
|
||||
@ -533,6 +537,7 @@ static void tui_main(UIBridgeData *bridge, UI *ui)
|
||||
kv_destroy(data->invalid_regions);
|
||||
kv_destroy(data->attrs);
|
||||
xfree(data->space_buf);
|
||||
xfree(data->term);
|
||||
xfree(data);
|
||||
}
|
||||
|
||||
@ -1246,6 +1251,11 @@ static void tui_mode_change(UI *ui, String mode, Integer mode_idx)
|
||||
}
|
||||
#endif
|
||||
tui_set_mode(ui, (ModeShape)mode_idx);
|
||||
if (data->is_starting) {
|
||||
if (data->verbose >= 3) {
|
||||
show_verbose_terminfo(data);
|
||||
}
|
||||
}
|
||||
data->is_starting = false; // mode entered, no longer starting
|
||||
data->showing_mode = (ModeShape)mode_idx;
|
||||
}
|
||||
@ -1390,21 +1400,53 @@ static void tui_flush(UI *ui)
|
||||
}
|
||||
|
||||
/// Dumps termcap info to the messages area, if 'verbose' >= 3.
|
||||
static void show_termcap_event(void **argv)
|
||||
static void show_verbose_terminfo(TUIData *data)
|
||||
{
|
||||
if (p_verbose < 3) {
|
||||
return;
|
||||
}
|
||||
const unibi_term *const ut = argv[0];
|
||||
const unibi_term *const ut = data->ut;
|
||||
if (!ut) {
|
||||
abort();
|
||||
}
|
||||
verbose_enter();
|
||||
// XXX: (future) if unibi_term is modified (e.g. after a terminal
|
||||
// query-response) this is a race condition.
|
||||
terminfo_info_msg(ut);
|
||||
verbose_leave();
|
||||
verbose_stop(); // flush now
|
||||
|
||||
Array chunks = ARRAY_DICT_INIT;
|
||||
Array title = ARRAY_DICT_INIT;
|
||||
ADD(title, STRING_OBJ(cstr_to_string("\n\n--- Terminal info --- {{{\n")));
|
||||
ADD(title, STRING_OBJ(cstr_to_string("Title")));
|
||||
ADD(chunks, ARRAY_OBJ(title));
|
||||
Array info = ARRAY_DICT_INIT;
|
||||
String str = terminfo_info_msg(ut, data->term);
|
||||
ADD(info, STRING_OBJ(str));
|
||||
ADD(chunks, ARRAY_OBJ(info));
|
||||
Array end_fold = ARRAY_DICT_INIT;
|
||||
ADD(end_fold, STRING_OBJ(cstr_to_string("}}}\n")));
|
||||
ADD(end_fold, STRING_OBJ(cstr_to_string("Title")));
|
||||
ADD(chunks, ARRAY_OBJ(end_fold));
|
||||
|
||||
if (ui_client_channel_id) {
|
||||
Array args = ARRAY_DICT_INIT;
|
||||
ADD(args, ARRAY_OBJ(chunks));
|
||||
ADD(args, BOOLEAN_OBJ(true)); // history
|
||||
Dictionary opts = ARRAY_DICT_INIT;
|
||||
PUT(opts, "verbose", BOOLEAN_OBJ(true));
|
||||
ADD(args, DICTIONARY_OBJ(opts));
|
||||
rpc_send_event(ui_client_channel_id, "nvim_echo", args);
|
||||
} else {
|
||||
loop_schedule_deferred(&main_loop, event_create(verbose_terminfo_event, 2,
|
||||
chunks.items, chunks.size));
|
||||
}
|
||||
}
|
||||
|
||||
static void verbose_terminfo_event(void **argv)
|
||||
{
|
||||
Array chunks = { .items = argv[0], .size = (size_t)argv[1] };
|
||||
Dict(echo_opts) opts = { .verbose = BOOLEAN_OBJ(true) };
|
||||
Error err = ERROR_INIT;
|
||||
nvim_echo(chunks, true, &opts, &err);
|
||||
api_free_array(chunks);
|
||||
if (ERROR_SET(&err)) {
|
||||
fprintf(stderr, "TUI bought the farm: %s\n", err.msg);
|
||||
exit(1);
|
||||
}
|
||||
api_clear_error(&err);
|
||||
}
|
||||
|
||||
#ifdef UNIX
|
||||
@ -1509,6 +1551,8 @@ static void tui_option_set(UI *ui, String name, Object value)
|
||||
data->input.ttimeout = value.data.boolean;
|
||||
} else if (strequal(name.data, "ttimeoutlen")) {
|
||||
data->input.ttimeoutlen = (long)value.data.integer;
|
||||
} else if (strequal(name.data, "verbose")) {
|
||||
data->verbose = value.data.integer;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ describe('UI receives option updates', function()
|
||||
termguicolors=false,
|
||||
ttimeout=true,
|
||||
ttimeoutlen=50,
|
||||
verbose=0,
|
||||
ext_cmdline=false,
|
||||
ext_popupmenu=false,
|
||||
ext_tabline=false,
|
||||
|
Loading…
Reference in New Issue
Block a user